# ------------------------------------------------------------------------------
 #  charproc.c     |    8 +--
 #  doublechr.c    |   79 +++++++++++++++++++++++++++++++++++++-
 #  fontutils.c    |  112 ++++++++++++++++++++++++++++++++++++-------------------
 #  fontutils.h    |    4 +
 #  main.c         |   10 ++--
 #  ptyx.h         |   10 +++-
 #  resize.c       |    4 -
 #  util.c         |   54 +++++++++++++++++++++++---
 #  version.h      |    2 
 #  xterm.h        |    5 +-
 #  xterm.log.html |   32 +++++++++++++++
 #  xterm.man      |    4 +
 #  12 files changed, 257 insertions, 67 deletions
 # ------------------------------------------------------------------------------
 Index: charproc.c
--- xterm-88+/charproc.c        Sun Oct 25 13:31:39 1998
 +++ xterm-89/charproc.c Wed Nov 18 20:35:49 1998
 @@ -4419,7 +4419,7 @@
                 }
        }
 
-       TRACE(("%s @%d, calling drawXtermText\n", __FILE__, __LINE__))
 +       TRACE(("%s @%d, ShowCursor calling drawXtermText\n", __FILE__, __LINE__))
  
        drawXtermText(screen, flags, currentGC,
                x = CurCursorX(screen, screen->cur_row, screen->cur_col),
@@ -4485,11 +4485,11 @@
        if (c == 0)
                c = ' ';
 
-       TRACE(("%s @%d, calling drawXtermText\n", __FILE__, __LINE__))
 +       TRACE(("%s @%d, HideCursor calling drawXtermText\n", __FILE__, __LINE__))
         drawXtermText(screen, flags, currentGC,
-               CursorX(screen, screen->cursor_col),
 +               CurCursorX(screen, screen->cursor_row, screen->cursor_col),
                 CursorY(screen, screen->cursor_row),
-               curXtermChrSet(screen->cur_row),
 +               curXtermChrSet(screen->cursor_row),
                 &c, 1);
 
        screen->cursor_state = OFF;
Index: doublechr.c
--- xterm-88+/doublechr.c       Sun Oct 25 13:31:39 1998
 +++ xterm-89/doublechr.c        Fri Nov 20 06:22:59 1998
 @@ -36,6 +36,7 @@
  
 #include <xterm.h>
 #include <data.h>
+#include <fontutils.h>
 
 /*
  * The first column is all that matters for double-size characters (since the
@@ -50,10 +51,19 @@
 {
        register TScreen *screen = &term->screen;
        int curcol = screen->cur_col;
+       int currow = screen->cur_row;
         int len = screen->max_col + 1;
        int width = len;
+       unsigned oldChrSet = SCRN_BUF_CSETS(screen, currow)[0];
  
-       TRACE(("repaint_line(%2d,%2d) (%d)\n", screen->cur_row, screen->cur_col, newChrSet))
 +       /*
+        * Ignore repetition.
 +        */
+       if (oldChrSet == newChrSet)
 +               return;
 +
+       TRACE(("repaint_line(%2d,%2d) (%d)\n", currow, screen->cur_col, newChrSet))
 +       HideCursor();
  
        /* If switching from single-width, keep the cursor in the visible part
         * of the line.
@@ -64,11 +74,24 @@
                        curcol = width;
        }
 
+       /*
+        * ScrnRefresh won't paint blanks for us if we're switching between a
 +        * single-size and double-size font.
 +        */
+       if (CSET_DOUBLE(oldChrSet) != CSET_DOUBLE(newChrSet)) {
 +               ClearCurBackground(
 +                       screen,
 +                       CursorY (screen, currow),
 +                       CurCursorX (screen, currow, 0),
 +                       FontHeight(screen),
 +                       len * CurFontWidth(screen,currow));
 +       }
+
         /* FIXME: do VT220 softchars allow double-sizes? */
-       memset(SCRN_BUF_CSETS(screen, screen->cur_row), newChrSet, len);
 +       memset(SCRN_BUF_CSETS(screen, currow), newChrSet, len);
  
        screen->cur_col = 0;
-       ScrnRefresh (screen, screen->cur_row, 0, 1, len, True);
 +       ScrnRefresh (screen, currow, 0, 1, len, True);
         screen->cur_col = curcol;
 }
 #endif
@@ -106,3 +129,53 @@
        repaint_line(CSET_DWL);
 #endif
 }
+
+
+#if OPT_DEC_CHRSET
+/*
+ * Lookup/cache a GC for the double-size character display.  We save up to
 + * NUM_CHRSET values.
+ */
 +GC
+xterm_DoubleGC(unsigned chrset, unsigned flags, GC old_gc)
 +{
+       XGCValues gcv;
 +       register TScreen *screen = &term->screen;
 +       unsigned long mask = (GCForeground | GCBackground | GCFont);
 +       int n = (chrset % NUM_CHRSET);
 +       char *name = xtermSpecialFont(flags, chrset);
 +
+       if (name == 0)
 +               return 0;
 +
+       if (screen->double_fn[n] != 0) {
 +               if (!strcmp(screen->double_fn[n], name)) {
 +                       if (screen->double_fs[n] != 0) {
 +                               XCopyGC(screen->display, old_gc, ~GCFont, screen->double_gc[n]);
 +                               return screen->double_gc[n];
 +                       }
 +               }
 +       }
+       screen->double_fn[n] = name;
 +
+       if (screen->double_fs[n] != 0) {
 +               XFreeFont(screen->display, screen->double_fs[n]);
 +               screen->double_fs[n] = 0;
 +       }
+
 +       TRACE(("xterm_DoubleGC %s %d: %s\n", flags&BOLD ? "BOLD" : "NORM", chrset, name))
+
+       if ((screen->double_fs[n] = XLoadQueryFont (screen->display, name)) == 0)
 +               return 0;
 +       TRACE(("-> OK\n"))
 +
+       gcv.graphics_exposures = TRUE;  /* default */
 +       gcv.font       = screen->double_fs[n]->fid;
 +       gcv.foreground = screen->foreground;
 +       gcv.background = term->core.background_pixel;
 +
+       screen->double_gc[n] = XCreateGC (screen->display, TextWindow(screen), mask, &gcv);
 +       XCopyGC(screen->display, old_gc, ~GCFont, screen->double_gc[n]);
 +       return screen->double_gc[n];
 +}
+#endif
Index: fontutils.c
--- xterm-88+/fontutils.c       Sun Nov  1 14:10:30 1998
 +++ xterm-89/fontutils.c        Wed Nov 18 20:25:57 1998
 @@ -121,6 +121,7 @@
  get_font_name_props(Display *dpy, XFontStruct *fs)
 {
        static FontNameProperties props;
+       static char *last_name;
  
        register XFontProp *fp;
        register int i;
@@ -141,6 +142,13 @@
                return 0;
 
        /*
+        * XGetAtomName allocates memory - don't leak
 +        */
+       if (last_name != 0)
 +               XFree(last_name);
 +       last_name = name;
 +
+       /*
        * Now split it up into parts and put them in
        * their places. Since we are using parts of
        * the original string, we must not free the Atom Name
@@ -222,59 +230,86 @@
      return ret;
 }
 
-#if 0
 #ifdef OPT_DEC_CHRSET
 /*
  * Take the given font props and try to make a well formed font name specifying
- * the same base font but changed depending on the given attributes and lflags.
 + * the same base font but changed depending on the given attributes and chrset.
   *
  * For double width fonts, we just double the X-resolution, for double height
  * fonts we double the pixel-size and Y-resolution
  */
 char *
-special_font_name(FontNameProperties *props, unsigned char atts,
 -                 LineFlagsElem lflags)
 +xtermSpecialFont(unsigned atts, unsigned chrset)
  {
-     char tmp[MAX_FONTNAME];
 -     char *ret;
+#if OPT_TRACE
 +       static char old_spacing[80];
 +       static FontNameProperties old_props;
 +#endif
+       TScreen *screen = &term->screen;
 +       FontNameProperties *props;
 +       char tmp[MAX_FONTNAME];
 +       char *ret;
 +       char *width;
 +       int pixel_size;
 +       int res_x;
 +       int res_y;
 +
+       props = get_font_name_props(screen->display, screen->fnt_norm);
 +       if (props == 0)
 +               return 0;
 +
+       pixel_size = props->pixel_size;
 +       res_x = props->res_x;
 +       res_y = props->res_y;
 +       if (atts & BOLD)
 +               width = "bold";
 +       else
+               width = props->width;
 +
+       if (CSET_DOUBLE(chrset))
 +               res_x *= 2;
 +
+       if (chrset == CSET_DHL_TOP 
 +        || chrset == CSET_DHL_BOT) {
 +               res_y *= 2;
 +               pixel_size *= 2;
 +       }
 
-     char *width;
-     int pixel_size = props->pixel_size;
 -     int res_x = props->res_x;
 -     int res_y = props->res_y;
 -
-     if (atts & ATT_BOLD)
 -         width = "bold";
 -     else
-         width = props->width;
 -
-     if (lflags & LINE_D_WIDE)
 -         res_x *= 2;
 -
-     if (lflags & (LINE_D_UPPER | LINE_D_LOWER)) {
 -         res_x *= 2;
 -         res_y *= 2;
 -         pixel_size *= 2;
 -     }
+#if OPT_TRACE
+       if (old_props.res_x      != res_x
 +        || old_props.res_x      != res_y
 +        || old_props.pixel_size != pixel_size
 +        || strcmp(old_props.spacing, props->spacing)) {
 +               TRACE(("xtermSpecialFont(atts = %#x, chrset = %#x)\n", atts, chrset))
 +               TRACE(("res_x      = %d\n", res_x))
 +               TRACE(("res_y      = %d\n", res_y))
 +               TRACE(("point_size = %s\n", props->point_size))
 +               TRACE(("pixel_size = %d\n", pixel_size))
 +               TRACE(("spacing    = %s\n", props->spacing))
 +               old_props.res_x      = res_x;
 +               old_props.res_x      = res_y;
 +               old_props.pixel_size = pixel_size;
 +               old_props.spacing    = strcpy(old_spacing, props->spacing);
 +       }
+#endif
  
-     sprintf(tmp, "%s-%s-%s-%d-%s-%d-%d-%s-*-%s",
 -            props->beginning,
 -            width,
 -            props->middle,
 -            pixel_size,
 -            props->point_size,
 -            res_x,
 -            res_y,
 -            props->spacing,
 -            props->end);
 +       sprintf(tmp, "%s-%s-%s-%d-%s-%d-%d-%s-*-%s",
 +               props->beginning,
 +               width,
 +               props->middle,
 +               pixel_size,
 +               props->point_size,
 +               res_x,
 +               res_y,
 +               props->spacing,
 +               props->end);
  
-     ret = XtMalloc(strlen(tmp) + 1);
 -     strcpy(ret, tmp);
 +       ret = XtMalloc(strlen(tmp) + 1);
 +       strcpy(ret, tmp);
  
-     return ret;
+       return ret;
  }
 #endif /* OPT_DEC_CHRSET */
-#endif
 
 /*
  * Double-check the fontname that we asked for versus what the font server
@@ -330,6 +365,7 @@
        Bool doresize,
        int fontnum)
 {
+       /* FIXME: use XFreeFontInfo */
         FontNameProperties *fp;
        XFontStruct *nfs = NULL;
        XFontStruct *bfs = NULL;
Index: fontutils.h
--- xterm-88+/fontutils.h       Sun Oct 25 13:31:39 1998
 +++ xterm-89/fontutils.h        Tue Nov  3 21:40:32 1998
 @@ -43,4 +43,8 @@
  extern void xtermUpdateFontInfo (TScreen *screen, Bool doresize);
 extern void xtermSetCursorBox (TScreen *screen);
 
+#if OPT_DEC_CHRSET
+extern char *xtermSpecialFont(unsigned atts, unsigned chrset);
 +#endif
+
 #endif /* included_fontutils_h */
Index: main.c
--- xterm-88+/main.c    Sun Oct 25 13:31:39 1998
 +++ xterm-89/main.c     Fri Nov 20 06:23:47 1998
 @@ -3122,7 +3122,7 @@
                                sizeof(utmp.ut_name));
 
                utmp.ut_pid = getpid();
-#if defined(SVR4) || defined(SCO325) || (defined(linux) && __GLIBC__ >= 2)
 +#if defined(SVR4) || defined(SCO325) || (defined(linux) && __GLIBC__ >= 2 && !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0))
                 utmp.ut_session = getsid(0);
                utmp.ut_xtime = time ((time_t *) 0);
                utmp.ut_tv.tv_usec = 0;
@@ -3138,7 +3138,7 @@
                if (term->misc.login_shell)
                    updwtmpx(WTMPX_FILE, &utmp);
 #else
-#if defined(linux) && __GLIBC__ >= 2
 +#if defined(linux) && __GLIBC__ >= 2 && !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
                 if (term->misc.login_shell)
                    updwtmp(etc_wtmp, &utmp);
 #else
@@ -3899,7 +3899,7 @@
 #endif
        char* ptyname;
        char* ptynameptr = 0;
-#if defined(WTMP) && !defined(SVR4) && !(defined(linux) && __GLIBC__ >= 2)
 +#if defined(WTMP) && !defined(SVR4) && !(defined(linux) && __GLIBC__ >= 2 && !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0))
         int fd;                 /* for /etc/wtmp */
        int i;
 #endif
@@ -3931,7 +3931,7 @@
            /* write it out only if it exists, and the pid's match */
            if (utptr && (utptr->ut_pid == screen->pid)) {
                    utptr->ut_type = DEAD_PROCESS;
-#if defined(SVR4) || defined(SCO325) || (defined(linux) && __GLIBC__ >= 2)
 +#if defined(SVR4) || defined(SCO325) || (defined(linux) && __GLIBC__ >= 2 && !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0))
                     utptr->ut_session = getsid(0);
                    utptr->ut_xtime = time ((time_t *) 0);
                    utptr->ut_tv.tv_usec = 0;
@@ -3945,7 +3945,7 @@
                    if (term->misc.login_shell)
                        updwtmpx(WTMPX_FILE, utptr);
 #else
-#if defined(linux) && __GLIBC__ >= 2
 +#if defined(linux) && __GLIBC__ >= 2 && !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
                     strncpy (utmp.ut_line, utptr->ut_line, sizeof (utmp.ut_line));
                    if (term->misc.login_shell)
                        updwtmp(etc_wtmp, utptr);
Index: ptyx.h
--- xterm-88+/ptyx.h    Sun Oct 25 13:31:39 1998
 +++ xterm-89/ptyx.h     Fri Nov 20 06:20:11 1998
 @@ -421,15 +421,16 @@
  
 #if OPT_DEC_CHRSET
 #define if_OPT_DEC_CHRSET(code) code
-       /* Use 3 bits for encoding the double high/wide sense of characters */
 +       /* Use 2 bits for encoding the double high/wide sense of characters */
  #define CSET_SWL        0
 #define CSET_DHL_TOP    1
 #define CSET_DHL_BOT    2
-#define CSET_DWL        4
 +#define CSET_DWL        3
 +#define NUM_CHRSET      4
         /* Use remaining bits for encoding the other character-sets */
 #define CSET_NORMAL(code)  ((code) == CSET_SWL)
 #define CSET_DOUBLE(code)  (!CSET_NORMAL(code) && !CSET_EXTEND(code))
-#define CSET_EXTEND(code)  ((code) >= 8)
 +#define CSET_EXTEND(code)  ((code) > CSET_DWL)
  #define CurMaxCol(screen, row) \
        (CSET_DOUBLE(SCRN_BUF_CSETS(screen, row)[0]) \
        ? (screen->max_col / 2) \
@@ -627,6 +628,9 @@
 #endif
 #if OPT_DEC_CHRSET
        Char            chrset;         /* character-set index & code   */
+       XFontStruct *   double_fs[NUM_CHRSET];
 +       GC              double_gc[NUM_CHRSET];
 +       char *          double_fn[NUM_CHRSET];
  #endif
        int             border;         /* inner border                 */
        Cursor          arrow;          /* arrow cursor                 */
Index: resize.c
--- xterm-88+/resize.c  Sun Oct 25 13:31:39 1998
 +++ xterm-89/resize.c   Fri Nov 20 06:38:44 1998
 @@ -536,10 +536,8 @@
                          setname, termcap);
 #endif /* USE_TERMCAP */
 #ifdef USE_TERMINFO
-#ifndef SVR4
                printf ("%sCOLUMNS=%d;\nLINES=%d;\nexport COLUMNS LINES;\n",
                        setname, cols, rows);
-#endif /* !SVR4 */
 #endif /* USE_TERMINFO */
 
        } else {                /* not Bourne shell */
@@ -550,10 +548,8 @@
                         setname, termcap);
 #endif /* USE_TERMCAP */
 #ifdef USE_TERMINFO
-#ifndef SVR4
                printf ("set noglob;\n%ssetenv COLUMNS '%d';\nsetenv LINES '%d';\nunset noglob;\n",
                        setname, cols, rows);
-#endif /* !SVR4 */
 #endif /* USE_TERMINFO */
        }
        exit(0);
Index: util.c
--- xterm-88+/util.c    Sun Oct 25 13:31:39 1998
 +++ xterm-89/util.c     Tue Nov  3 21:40:32 1998
 @@ -1310,17 +1310,57 @@
  {
 #if OPT_DEC_CHRSET
        if (CSET_DOUBLE(chrset)) {
-               Char *temp = (Char *) malloc(2 * len);
 -               int n = 0;
 +               GC gc2 = xterm_DoubleGC(chrset, flags, gc);
 +
                TRACE(("DRAWTEXT%c[%4d,%4d] (%d) %d:%.*s\n",
                        screen->cursor_state == OFF ? ' ' : '*',
                        y, x, chrset, len, len, text))
-               while (len--) {
 -                       temp[n++] = *text++;
 -                       temp[n++] = ' ';
 +
+               if (gc2 != 0) { /* draw actual double-sized characters */
 +                       XRectangle rect, *rp = ▭
 +                       Cardinal nr = 1;
 +
+                       rect.x = 0;
 +                       rect.y = 0;
 +                       rect.width = 2 * len * FontWidth(screen);
 +                       rect.height = FontHeight(screen);
 +
+                       switch (chrset) {
 +                       case CSET_DHL_TOP:
 +                               rect.y = - (rect.height / 2);
 +                               y -= rect.y;
 +                               break;
 +                       case CSET_DHL_BOT:
 +                               rect.y = (rect.height / 2);
 +                               y -= rect.y;
 +                               break;
 +                       default:
 +                               nr = 0;
 +                               break;
 +                       }
 +
+                       if (nr)
 +                               XSetClipRectangles(screen->display, gc2,
 +                                       x, y, rp, nr, YXBanded);
 +                       else
 +                               XSetClipMask(screen->display, gc2, None);
 +
+                       x = drawXtermText(screen, flags, gc2,
 +                               x, y, 0, text, len);
 +                       x += len * FontWidth(screen);
 +
+                       TRACE(("drewtext [%4d,%4d]\n", y, x))
 +
+               } else {        /* simulate double-sized characters */
 +                       Char *temp = (Char *) malloc(2 * len);
 +                       int n = 0;
 +                       while (len--) {
 +                               temp[n++] = *text++;
 +                               temp[n++] = ' ';
 +                       }
 +                       x = drawXtermText(screen, flags, gc, x, y, 0, temp, n);
 +                       free(temp);
                 }
-               x = drawXtermText(screen, flags, gc, x, y, 0, temp, n);
 -               free(temp);
                 return x;
        }
 #endif
Index: version.h
--- xterm-88+/version.h Sun Nov  1 14:10:30 1998
 +++ xterm-89/version.h  Thu Nov 19 06:43:45 1998
 @@ -6,4 +6,4 @@
   * version of xterm has been built.  The number in parentheses is my patch
  * number (T.Dickey).
  */
-#define XTERM_VERSION "XFree86 3.9Nk(88)"
 +#define XTERM_VERSION "XFree86 3.9Nm(89)"
 Index: xterm.h
--- xterm-88+/xterm.h   Sun Oct 25 13:31:39 1998
 +++ xterm-89/xterm.h    Fri Nov 20 06:21:03 1998
 @@ -36,8 +36,8 @@
  
 #ifndef X_NOT_STDC_ENV
 #define HAVE_STDLIB_H 1
-#else
 #define DECL_ERRNO 1
+#else
 #define size_t int
 #define time_t long
 #endif
@@ -167,6 +167,9 @@
 extern void xterm_DECDHL (Bool top);
 extern void xterm_DECSWL (void);
 extern void xterm_DECDWL (void);
+#if OPT_DEC_CHRSET
+extern GC xterm_DoubleGC(unsigned chrset, unsigned flags, GC old_gc);
 +#endif
 
 /* input.c */
 extern void Input (TKeyboard *keyboard, TScreen *screen, XKeyEvent *event, Bool eightbit);
Index: xterm.log.html
--- xterm-88+/xterm.log.html    Sun Nov  1 14:10:30 1998
 +++ xterm-89/xterm.log.html     Fri Nov 20 06:48:21 1998
 @@ -41,6 +41,7 @@
  xc/programs/Xserver/hw/xfree86).
 
 <UL>
+<LI><A HREF="#xterm_89">Patch #89 - 1998/11/20 - XFree86 3.9Nm</A>
  <LI><A HREF="#xterm_88">Patch #88 - 1998/10/31 - XFree86 3.9Nk and 3.3.2h</A>
 <LI><A HREF="#xterm_87">Patch #87 - 1998/10/21 - XFree86 3.9Nj and 3.3.2f</A>
 <LI><A HREF="#xterm_86">Patch #86 - 1998/10/14 - XFree86 3.9Nj and 3.3.2e</A>
@@ -131,6 +132,37 @@
 <LI><A HREF="#xterm_02">Patch #2 - 1996/1/7</A>
 <LI><A HREF="#xterm_01">Patch #1 - 1996/1/6</A>
 </UL>
+
+<H1><A NAME="xterm_89">Patch #89 - 1998/11/20 - XFree86 3.9Nm</A></H1>
 +This patch completes the implementation of double-sized character support
 +for the VT100 emulation, and fixes a few minor bugs:
 +
+<ul>
+<li>corrected the cursor position in HideCursor, which did not multiply
 +the column by two when in doublesize mode.
 +This bug, which did not appear in normal use, 
 +dates back to my original <a href="#xterm_44">changes</a> to partly implement
 +double-sized characters.
+I noticed it when cat'ing a typescript from vttest's double-sized character
 +test.
+<li>ensure that the current line is repainted when switching between
 +single and double width characters.
 +<li>reduce the number of bits used for double-sized character coding
 +from 3 to 2, to make more room for soft-font codes.
 +<li>copy newer ifdef's from the XFree86 3.3.3 release's main.c,
 +which address details of glibc and powerpc.
 +<li>moved definition of DECL_ERRNO in xterm.h to match XFree86 3.3.3
 +<li>modify <em>resize</em> to remove the ifdef on SVr4 that suppressed
 +printing the script for $LINES and $COLUMNS.
 +Solaris' resize utility does this; suppressing the behavior is unnecessary.
 +</ul>
+I tested the double-sized characters using vttest and the xfsft patch.
 +These fonts worked reasonably well:
 +<pre>
+       -bitstream-courier-medium-r-normal--0-0-0-0-m-0-iso8859-1
 +       9x15
+</pre>
 +The iso8859 font does not include box characters, of course, but looks good.
  
 <H1><A NAME="xterm_88">Patch #88 - 1998/10/31 - XFree86 3.9Nk and 3.3.2h</A></H1>
 This refines my #85 patch by checking for a case where the font server
Index: xterm.man
--- xterm-88+/xterm.man Sun Oct 11 13:00:35 1998
 +++ xterm-89/xterm.man  Wed Nov 11 19:44:01 1998
 @@ -58,7 +58,9 @@
  .SH EMULATIONS
 The VT102 emulation is fairly complete, but does not support
 autorepeat.
-Double-size and blinking characters are partially implemented;
 +Double-size characters are displayed properly if your font server supports
 +scalable fonts.
+Blinking characters are partially implemented;
  the emulation is functional but does not have the appearance of a real VT102.
 The VT220 emulation does not support soft fonts, it is otherwise complete.
 .IR Termcap (5)