summaryrefslogtreecommitdiff
path: root/doublechr.c
diff options
context:
space:
mode:
Diffstat (limited to 'doublechr.c')
-rw-r--r--doublechr.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/doublechr.c b/doublechr.c
new file mode 100644
index 0000000..3c13ef0
--- /dev/null
+++ b/doublechr.c
@@ -0,0 +1,331 @@
+/* $XTermId: doublechr.c,v 1.81 2012/04/15 23:39:53 tom Exp $ */
+
+/*
+ * Copyright 1997-2011,2012 by Thomas E. Dickey
+ *
+ * All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+
+#include <xterm.h>
+#include <data.h>
+#include <fontutils.h>
+
+#include <assert.h>
+
+#define WhichCgsId(flag) (((flag) & BOLD) ? gcCBold : gcCNorm)
+
+/*
+ * The first column is all that matters for double-size characters (since the
+ * controls apply to a whole line). However, it's easier to maintain the
+ * information for special fonts by writing to all cells.
+ */
+#if OPT_DEC_CHRSET
+
+static void
+repaint_line(XtermWidget xw, unsigned newChrSet)
+{
+ TScreen *screen = TScreenOf(xw);
+ LineData *ld;
+ int curcol = screen->cur_col;
+ int currow = screen->cur_row;
+ int width = MaxCols(screen);
+ unsigned len = (unsigned) width;
+
+ assert(width > 0);
+
+ /*
+ * Ignore repetition.
+ */
+ if (!IsLeftRightMode(xw)
+ && (ld = getLineData(screen, currow)) != 0) {
+ unsigned oldChrSet = GetLineDblCS(ld);
+
+ if (oldChrSet != newChrSet) {
+ TRACE(("repaint_line(%2d,%2d) (%s -> %s)\n", currow, screen->cur_col,
+ visibleChrsetName(oldChrSet),
+ visibleChrsetName(newChrSet)));
+ HideCursor();
+
+ /* If switching from single-width, keep the cursor in the visible part
+ * of the line.
+ */
+ if (CSET_DOUBLE(newChrSet)) {
+ width /= 2;
+ if (curcol > width)
+ curcol = width;
+ }
+
+ /*
+ * ScrnRefresh won't paint blanks for us if we're switching between a
+ * single-size and double-size font. So we paint our own.
+ */
+ ClearCurBackground(xw,
+ currow,
+ 0,
+ 1,
+ len,
+ (unsigned) LineFontWidth(screen, ld));
+
+ SetLineDblCS(ld, newChrSet);
+
+ set_cur_col(screen, 0);
+ ScrnUpdate(xw, currow, 0, 1, (int) len, True);
+ set_cur_col(screen, curcol);
+ }
+ }
+}
+#endif
+
+/*
+ * Set the line to double-height characters. The 'top' flag denotes whether
+ * we'll be using it for the top (true) or bottom (false) of the line.
+ */
+void
+xterm_DECDHL(XtermWidget xw GCC_UNUSED, Bool top)
+{
+#if OPT_DEC_CHRSET
+ repaint_line(xw, (unsigned) (top ? CSET_DHL_TOP : CSET_DHL_BOT));
+#else
+ (void) top;
+#endif
+}
+
+/*
+ * Set the line to single-width characters (the normal state).
+ */
+void
+xterm_DECSWL(XtermWidget xw GCC_UNUSED)
+{
+#if OPT_DEC_CHRSET
+ repaint_line(xw, CSET_SWL);
+#endif
+}
+
+/*
+ * Set the line to double-width characters
+ */
+void
+xterm_DECDWL(XtermWidget xw GCC_UNUSED)
+{
+#if OPT_DEC_CHRSET
+ repaint_line(xw, CSET_DWL);
+#endif
+}
+
+/*
+ * Reset all lines on the screen to single-width/single-height.
+ */
+void
+xterm_ResetDouble(XtermWidget xw)
+{
+#if OPT_DEC_CHRSET
+ TScreen *screen = TScreenOf(xw);
+ Boolean changed = False;
+ LineData *ld;
+ unsigned code;
+ int row;
+
+ for (row = 0; row < screen->max_row; ++row) {
+ if ((ld = getLineData(screen, ROW2INX(screen, row))) != 0) {
+ code = GetLineDblCS(ld);
+ if (code != CSET_SWL) {
+ SetLineDblCS(ld, CSET_SWL);
+ changed = True;
+ }
+ }
+ }
+ if (changed) {
+ xtermRepaint(xw);
+ }
+#endif
+}
+
+#if OPT_DEC_CHRSET
+static void
+discard_font(XtermWidget xw, int n)
+{
+ TScreen *screen = TScreenOf(xw);
+ XTermFonts *data = &(screen->double_fonts[n]);
+
+ TRACE(("discard_font chrset=%d %s\n", data->chrset,
+ (data->fn != 0) ? data->fn : "<no-name>"));
+
+ data->chrset = 0;
+ data->flags = 0;
+ if (data->fn != 0) {
+ free(data->fn);
+ data->fn = 0;
+ }
+ (void) xtermCloseFont(xw, data);
+
+ screen->fonts_used -= 1;
+ while (n < screen->fonts_used) {
+ screen->double_fonts[n] = screen->double_fonts[n + 1];
+ ++n;
+ }
+}
+
+/* push back existing fonts and create a new entry */
+static XTermFonts *
+pushback_font(XtermWidget xw, XTermFonts * source)
+{
+ TScreen *screen = TScreenOf(xw);
+ XTermFonts *data = screen->double_fonts;
+ int n;
+
+ if (screen->fonts_used >= screen->cache_doublesize) {
+ TRACE(("pushback_font: discard oldest\n"));
+ discard_font(xw, screen->fonts_used - 1);
+ } else {
+ screen->fonts_used += 1;
+ }
+
+ for (n = screen->fonts_used; n > 0; n--)
+ data[n] = data[n - 1];
+ data[0] = *source;
+
+ TRACE(("pushback_font -> (NEW:%d)\n", screen->fonts_used));
+
+ return data;
+}
+
+int
+xterm_Double_index(XtermWidget xw, unsigned chrset, unsigned flags)
+{
+ int n;
+ int result = -1;
+ TScreen *screen = TScreenOf(xw);
+ XTermFonts *data = screen->double_fonts;
+
+ flags &= BOLD;
+ TRACE(("xterm_Double_index chrset=%#x, flags=%#x\n", chrset, flags));
+
+ for (n = 0; n < screen->fonts_used; n++) {
+ if (data[n].chrset == chrset
+ && data[n].flags == flags) {
+ if (n != 0) {
+ XTermFonts save;
+ TRACE(("...xterm_Double_index -> %d (OLD:%d)\n", n, screen->fonts_used));
+ save = data[n];
+ while (n > 0) {
+ data[n] = data[n - 1];
+ n--;
+ }
+ data[n] = save;
+ }
+ result = n;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Lookup/cache a GC for the double-size character display. We save up to
+ * NUM_CHRSET values.
+ */
+GC
+xterm_DoubleGC(XtermWidget xw,
+ unsigned chrset,
+ unsigned flags,
+ GC old_gc,
+ int *inxp)
+{
+ TScreen *screen = TScreenOf(xw);
+ VTwin *cgsWin = WhichVWin(screen);
+ int n;
+ char *name;
+ XTermFonts *data = 0;
+ GC result = 0;
+
+ if ((name = xtermSpecialFont(screen, flags, chrset)) != 0) {
+ CgsEnum cgsId = WhichCgsId(flags);
+ Boolean found = False;
+
+ if ((n = xterm_Double_index(xw, chrset, flags)) >= 0) {
+ data = &(screen->double_fonts[n]);
+ if (data->fn != 0) {
+ if (!strcmp(data->fn, name)
+ && data->fs != 0) {
+ found = True;
+ free(name);
+ } else {
+ discard_font(xw, n);
+ }
+ }
+ }
+
+ if (!found) {
+ XTermFonts temp;
+
+ TRACE(("xterm_DoubleGC %s %d: %s\n",
+ flags & BOLD ? "BOLD" : "NORM", n, name));
+
+ memset(&temp, 0, sizeof(temp));
+ temp.fn = name;
+ temp.chrset = chrset;
+ temp.flags = (flags & BOLD);
+
+ if (!xtermOpenFont(xw, name, &temp, fwAlways, False)) {
+ /* Retry with * in resolutions */
+ char *nname = xtermSpecialFont(screen, flags | NORESOLUTION, chrset);
+
+ if (nname != 0) {
+ found = (Boolean) xtermOpenFont(xw, nname, &temp,
+ fwAlways, False);
+ free(nname);
+ }
+ } else {
+ found = True;
+ }
+ free(name);
+
+ if (found) {
+ n = 0;
+ data = pushback_font(xw, &temp);
+ }
+
+ TRACE(("-> %s\n", found ? "OK" : "FAIL"));
+ }
+
+ if (found) {
+ setCgsCSet(xw, cgsWin, cgsId, chrset);
+ setCgsFont(xw, cgsWin, cgsId, data);
+ setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, old_gc));
+ setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, old_gc));
+ result = getCgsGC(xw, cgsWin, cgsId);
+ *inxp = n;
+ } else if (flags & BOLD) {
+ UIntClr(flags, BOLD);
+ result = xterm_DoubleGC(xw, chrset, flags, old_gc, inxp);
+ }
+ }
+
+ return result;
+}
+#endif