XFree86 3.1.2Cd - 1996/2/14 - T.Dickey (dickey@clark.net) I observed an occasional glitch in the xterm's color behavior; a clear to end of line would get a color that had been used in a program that supposedly reset colors. I traced this down to the way xterm was modifying colors of GC's on the fly; it didn't restore the original color of the GC, even though it would later be used in functions (such as ClearRight) that assumed (my error) that the GC would have the current foreground or background color. I fixed this by resetting the GC's colors with a new function 'resetXtermGC()', and direct calls on SGR_Foreground/SGR_Background, as appropriate and using a new function 'updatedXtermGC()' to encapsulate the logic that modifies the GC's color. (I also removed some commented-out code that was trying to do this -- the problem was a little more obscure). -------------------------------------------------------------------------------- charproc.c | 197 ++++----------------------!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! screen.c | 87 +++------!!!!!!!!!!!!!!!!!! util.c | 77 +++++++++++++++++++++++ xterm.h | 7 ++ 4 files changed, 109 insertions, 90 deletions, 169 modifications -------------------------------------------------------------------------------- Index: charproc.c *** /build/x11r6/XFree86-3.1.2Cd/xc/programs/xterm/charproc.c Mon Feb 12 12:35:46 1996 --- /build/x11r6/XFree86-current/xc/programs/xterm/charproc.c Wed Feb 14 20:01:18 1996 *************** *** 123,130 **** static int set_character_class PROTO((char *s)); static void DoSetSelectedFont PROTO_XT_SEL_CB_ARGS; static void FromAlternate PROTO((TScreen *screen)); ! static void SGR_Background PROTO((int color)); ! static void SGR_Foreground PROTO((int color)); static void SwitchBufs PROTO((TScreen *screen)); static void ToAlternate PROTO((TScreen *screen)); static void VTGraphicsOrNoExpose PROTO((XEvent *event)); --- 123,129 ---- static int set_character_class PROTO((char *s)); static void DoSetSelectedFont PROTO_XT_SEL_CB_ARGS; static void FromAlternate PROTO((TScreen *screen)); ! static void SGR_Save PROTO((void)); static void SwitchBufs PROTO((TScreen *screen)); static void ToAlternate PROTO((TScreen *screen)); static void VTGraphicsOrNoExpose PROTO((XEvent *event)); *************** *** 266,274 **** #define doinput() (bcnt-- > 0 ? *bptr++ : in_put()) - #define GET_FG(flags,color) ((flags&FG_COLOR) ? screen->colors[color] : screen->foreground) - #define GET_BG(flags,color) ((flags&BG_COLOR) ? screen->colors[color] : term->core.background_pixel) - static int nparam; static ANSI reply; static int param[NPARAM]; --- 265,270 ---- *************** *** 709,741 **** static Pixel original_fg; static Pixel original_bg; /* * The terminal's foreground and background colors are set via two mechanisms: * text (cur_foreground, cur_background values that are passed down to * XDrawImageString and XDrawString) * area (X11 graphics context used in XClearArea and XFillRectangle) */ ! static void SGR_Foreground(color) int color; { register TScreen *screen = &term->screen; Pixel fg; - static int initialized; ! if (!initialized) { ! original_fg = screen->foreground; ! original_bg = term->core.background_pixel; ! initialized = TRUE; ! } if (color >= 0) { fg = COLOR_VALUE(screen,color); term->flags |= FG_COLOR; - term->cur_foreground = color; } else { fg = original_fg; term->flags &= ~FG_COLOR; } XSetForeground(screen->display, screen->normalGC, fg); XSetBackground(screen->display, screen->reverseGC, fg); --- 705,742 ---- static Pixel original_fg; static Pixel original_bg; + static void SGR_Save() + { + static int initialized; + if (!initialized) { + original_fg = term->screen.foreground; + original_bg = term->core.background_pixel; + initialized = TRUE; + } + } + /* * The terminal's foreground and background colors are set via two mechanisms: * text (cur_foreground, cur_background values that are passed down to * XDrawImageString and XDrawString) * area (X11 graphics context used in XClearArea and XFillRectangle) */ ! void SGR_Foreground(color) int color; { register TScreen *screen = &term->screen; Pixel fg; ! SGR_Save(); if (color >= 0) { fg = COLOR_VALUE(screen,color); term->flags |= FG_COLOR; } else { fg = original_fg; term->flags &= ~FG_COLOR; } + term->cur_foreground = color; XSetForeground(screen->display, screen->normalGC, fg); XSetBackground(screen->display, screen->reverseGC, fg); *************** *** 743,769 **** XSetBackground(screen->display, screen->reverseboldGC, fg); } ! static void SGR_Background(color) int color; { register TScreen *screen = &term->screen; Pixel bg; - static int initialized; ! if (!initialized) { ! original_fg = screen->foreground; ! original_bg = term->core.background_pixel; ! initialized = TRUE; ! } if (color >= 0) { bg = COLOR_VALUE(screen,color); term->flags |= BG_COLOR; - term->cur_background = color; } else { bg = original_bg; term->flags &= ~BG_COLOR; } XSetBackground(screen->display, screen->normalGC, bg); XSetForeground(screen->display, screen->reverseGC, bg); --- 744,765 ---- XSetBackground(screen->display, screen->reverseboldGC, fg); } ! void SGR_Background(color) int color; { register TScreen *screen = &term->screen; Pixel bg; ! SGR_Save(); if (color >= 0) { bg = COLOR_VALUE(screen,color); term->flags |= BG_COLOR; } else { bg = original_bg; term->flags &= ~BG_COLOR; } + term->cur_background = color; XSetBackground(screen->display, screen->normalGC, bg); XSetForeground(screen->display, screen->reverseGC, bg); *************** *** 1827,1897 **** { register int cx, cy; register unsigned fgs = flags; - register Pixel fg_pix, bg_pix; GC currentGC; ! fg_pix = GET_FG(fgs,fg); ! bg_pix = GET_BG(fgs,bg); ! ! if(screen->cur_row - screen->topline <= screen->max_row) { ! /* ! if(screen->cur_row == screen->cursor_row && screen->cur_col <= ! screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1) ! screen->cursor_state = OFF; ! */ ! if(screen->cursor_state) ! HideCursor(); ! ! /* ! * make sure that the correct GC is current ! */ ! ! if (fgs & INVERSE) ! { ! if (fgs & BOLD) ! currentGC = screen->reverseboldGC; ! else currentGC = screen->reverseGC; ! XSetForeground(screen->display, currentGC, bg_pix); ! XSetBackground(screen->display, currentGC, fg_pix); ! } else { ! if (fgs & BOLD) ! currentGC = screen->normalboldGC; ! else /* not bold */ ! currentGC = screen->normalGC; ! XSetForeground(screen->display, currentGC, fg_pix); ! XSetBackground(screen->display, currentGC, bg_pix); } - - if (fgs & INSERT) - InsertChar(screen, len); - if (!(AddToRefresh(screen))) { - if(screen->scroll_amt) - FlushScroll(screen); - cx = CursorX(screen, screen->cur_col); - cy = CursorY(screen, screen->cur_row)+screen->fnt_norm->ascent; - XDrawImageString(screen->display, TextWindow(screen), currentGC, - cx, cy, str, len); - - if((fgs & BOLD) && screen->enbolden) - if (currentGC == screen->normalGC || screen->reverseGC) - XDrawString(screen->display, TextWindow(screen), - currentGC,cx + 1, cy, str, len); - - if((fgs & UNDERLINE) && screen->underline) - XDrawLine(screen->display, TextWindow(screen), currentGC, - cx, cy+1, - cx + len * FontWidth(screen), cy+1); - /* - * the following statements compile data to compute the average - * number of characters written on each call to XText. The data - * may be examined via the use of a "hidden" escape sequence. - */ - ctotal += len; - ++ntotal; - } - } ScreenWrite(screen, str, flags, fg, bg, len); CursorForward(screen, len); } --- 1823,1874 ---- { register int cx, cy; register unsigned fgs = flags; GC currentGC; ! if(screen->cur_row - screen->topline <= screen->max_row) { ! if(screen->cursor_state) ! HideCursor(); ! ! if (fgs & INSERT) ! InsertChar(screen, len); ! if (!(AddToRefresh(screen))) { ! /* make sure that the correct GC is current */ ! currentGC = updatedXtermGC(screen, flags, fg, bg, False); ! if(screen->scroll_amt) ! FlushScroll(screen); ! cx = CursorX(screen, screen->cur_col); ! cy = CursorY(screen, screen->cur_row)+screen->fnt_norm->ascent; ! XDrawImageString(screen->display, TextWindow(screen), ! currentGC, cx, cy, str, len); ! /* Fake boldface by drawing the characters one pixel ! * offset, if required. ! */ ! if ((fgs & BOLD) ! && screen->enbolden ! && (currentGC == screen->normalGC ! || screen->reverseGC)) ! XDrawString(screen->display, ! TextWindow(screen), ! currentGC, cx + 1, cy, str, len); ! ! if((fgs & UNDERLINE) && screen->underline) ! XDrawLine(screen->display, ! TextWindow(screen), currentGC, ! cx, cy+1, ! cx + len * FontWidth(screen), cy+1); ! /* ! * The following statements compile data to compute the ! * average number of characters written on each call to ! * XText. The data may be examined via the use of a ! * "hidden" escape sequence. ! */ ! ctotal += len; ! ++ntotal; ! resetXtermGC(screen, flags, False); ! } } ScreenWrite(screen, str, flags, fg, bg, len); CursorForward(screen, len); } *************** *** 3128,3153 **** } } } - #if 0 - /*RFB*/ - if ( flags & BG_COLOR ) - XSetForeground( screen->display, currentGC, - screen->colors[ term->cur_background ]); - if ( flags & FG_COLOR ) - XSetBackground( screen->display, currentGC, - screen->colors[ term->cur_foreground ]); - /**********************************************************/ - /* */ - /* we test "flags and background" before calling */ - /* XSetForeground; */ - /* */ - /* it looks funny, but we're in reverse video and the */ - /* color we're setting it to is the current background */ - /* color! */ - /* */ - /**********************************************************/ - /*RFB*/ - #endif } else { /* not selected */ if (( (flags & INVERSE) && !in_selection) || (!(flags & INVERSE) && in_selection)) { --- 3105,3110 ---- *************** *** 3156,3171 **** } else { /* normal video */ currentGC = screen->normalGC; } - #if 0 - /*RFB*/ - if ( flags & FG_COLOR ) - XSetForeground( screen->display, currentGC, - screen->colors[ term->cur_foreground ]); - if ( flags & BG_COLOR ) - XSetBackground( screen->display, currentGC, - screen->colors[ term->cur_background ]); - /*RFB*/ - #endif } x = CursorX (screen, screen->cur_col); --- 3113,3118 ---- *************** *** 3200,3206 **** register TScreen *screen = &term->screen; GC currentGC; register int x, y, flags, fg, bg; - register Pixel fg_pix, bg_pix; char c; Boolean in_selection; --- 3147,3152 ---- *************** *** 3212,3220 **** fg = SCRN_BUF_FORES(screen, screen->cursor_row)[screen->cursor_col]; bg = SCRN_BUF_BACKS(screen, screen->cursor_row)[screen->cursor_col]; - fg_pix = GET_FG(flags,fg); - bg_pix = GET_BG(flags,bg); - if (screen->cursor_row > screen->endHRow || (screen->cursor_row == screen->endHRow && screen->cursor_col >= screen->endHCol) || --- 3158,3163 ---- *************** *** 3225,3252 **** else in_selection = True; ! if (( (flags & INVERSE) && !in_selection) || ! (!(flags & INVERSE) && in_selection)) { ! if(flags & BOLD) { ! currentGC = screen->reverseboldGC; ! } else { ! currentGC = screen->reverseGC; ! } ! ! XSetForeground(screen->display, currentGC, bg_pix); ! XSetBackground(screen->display, currentGC, fg_pix); ! ! } else { ! if(flags & BOLD) { ! currentGC = screen->normalboldGC; ! } else { ! currentGC = screen->normalGC; ! } ! ! XSetForeground(screen->display, currentGC, fg_pix); ! XSetBackground(screen->display, currentGC, bg_pix); ! ! } if (c == 0) c = ' '; --- 3168,3174 ---- else in_selection = True; ! currentGC = updatedXtermGC(screen, flags, fg, bg, in_selection); if (c == 0) c = ' '; *************** *** 3263,3268 **** --- 3185,3191 ---- XDrawLine(screen->display, TextWindow(screen), currentGC, x, y+1, x + FontWidth(screen), y+1); screen->cursor_state = OFF; + resetXtermGC(screen, flags, in_selection); } void Index: screen.c *** /build/x11r6/XFree86-3.1.2Cd/xc/programs/xterm/screen.c Fri Jan 26 11:43:22 1996 --- /build/x11r6/XFree86-current/xc/programs/xterm/screen.c Wed Feb 14 20:01:22 1996 *************** *** 410,415 **** --- 410,416 ---- int maxrow = toprow + nrows - 1; int scrollamt = screen->scroll_amt; int max = screen->max_row; + int gc_changes = 0; if(screen->cursor_col >= leftcol && screen->cursor_col <= (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline && *************** *** 426,432 **** int fg, bg; int x, n; GC gc; - Pixel fg_pix, bg_pix; Boolean hilite; if (row < screen->top_marg || row > screen->bot_marg) --- 427,432 ---- *************** *** 479,514 **** flags = attrs[col]; fg = fgs[col]; bg = bgs[col]; ! ! fg_pix = (flags & FG_COLOR) ? screen->colors[fg] ! : screen->foreground; ! bg_pix = (flags & BG_COLOR) ? screen->colors[bg] ! : term->core.background_pixel; ! ! if ( (!hilite && (flags & INVERSE) != 0) || ! (hilite && (flags & INVERSE) == 0) ) { ! if (flags & BOLD) gc = screen->reverseboldGC; ! else gc = screen->reverseGC; ! ! XSetForeground(screen->display, gc, bg_pix); ! XSetBackground(screen->display, gc, fg_pix); ! ! } else { ! if (flags & BOLD) gc = screen->normalboldGC; ! else gc = screen->normalGC; ! ! XSetForeground(screen->display, gc, fg_pix); ! XSetBackground(screen->display, gc, bg_pix); ! } ! x = CursorX(screen, col); lastind = col; for (; col <= maxcol; col++) { ! if (attrs[col] != flags || ! (flags & FG_COLOR && fgs[col] != fg) || ! (flags & BG_COLOR && bgs[col] != bg)) { XDrawImageString(screen->display, TextWindow(screen), gc, x, y, (char *) &chars[lastind], n = col - lastind); --- 479,494 ---- flags = attrs[col]; fg = fgs[col]; bg = bgs[col]; ! gc = updatedXtermGC(screen, flags, fg, bg, hilite); ! gc_changes |= (flags & (FG_COLOR|BG_COLOR)); x = CursorX(screen, col); lastind = col; for (; col <= maxcol; col++) { ! if ((attrs[col] != flags) || ! ((flags & FG_COLOR) && (fgs[col] != fg)) || ! ((flags & BG_COLOR) && (bgs[col] != bg))) { XDrawImageString(screen->display, TextWindow(screen), gc, x, y, (char *) &chars[lastind], n = col - lastind); *************** *** 526,577 **** flags = attrs[col]; fg = fgs[col]; bg = bgs[col]; ! ! fg_pix = (flags & FG_COLOR) ? screen->colors[fg] ! : screen->foreground; ! bg_pix = (flags & BG_COLOR) ? screen->colors[bg] ! : term->core.background_pixel; ! ! if ( (!hilite && (flags & INVERSE) != 0) || ! (hilite && (flags & INVERSE) == 0) ) { ! if (flags & BOLD) gc = screen->reverseboldGC; ! else gc = screen->reverseGC; ! ! XSetForeground(screen->display, gc, bg_pix); ! XSetBackground(screen->display, gc, fg_pix); ! ! } else { ! if (flags & BOLD) gc = screen->normalboldGC; ! else gc = screen->normalGC; ! ! XSetForeground(screen->display, gc, fg_pix); ! XSetBackground(screen->display, gc, bg_pix); ! ! } } if(chars[col] == 0) chars[col] = ' '; } - - if ( (!hilite && (flags & INVERSE) != 0) || - (hilite && (flags & INVERSE) == 0) ) { - if (flags & BOLD) gc = screen->reverseboldGC; - else gc = screen->reverseGC; - - XSetForeground(screen->display, gc, bg_pix); - XSetBackground(screen->display, gc, fg_pix); - - } else { - if (flags & BOLD) gc = screen->normalboldGC; - else gc = screen->normalGC; - - XSetForeground(screen->display, gc, fg_pix); - XSetBackground(screen->display, gc, bg_pix); - - } - XDrawImageString(screen->display, TextWindow(screen), gc, x, y, (char *) &chars[lastind], n = col - lastind); if((flags & BOLD) && screen->enbolden) --- 506,519 ---- flags = attrs[col]; fg = fgs[col]; bg = bgs[col]; ! gc = updatedXtermGC(screen, flags, fg, bg, hilite); ! gc_changes |= (flags & (FG_COLOR|BG_COLOR)); } if(chars[col] == 0) chars[col] = ' '; } XDrawImageString(screen->display, TextWindow(screen), gc, x, y, (char *) &chars[lastind], n = col - lastind); if((flags & BOLD) && screen->enbolden) *************** *** 581,586 **** --- 523,538 ---- XDrawLine(screen->display, TextWindow(screen), gc, x, y+1, x + n * FontWidth(screen), y+1); } + + /* + * If we're in color mode, reset the various GC's to the current + * screen foreground and background so that other functions (e.g., + * ClearRight) will get the correct colors. + */ + if (gc_changes & FG_COLOR) + SGR_Foreground(term->cur_foreground); + if (gc_changes & BG_COLOR) + SGR_Background(term->cur_background); } void *************** *** 819,824 **** --- 771,777 ---- } return ret; } + Bool non_blank_line(sb, row, col, len) ScrnBuf sb; *************** *** 827,833 **** register int i; register Char *ptr = BUF_CHARS(sb, row); ! for (i = col; i < len; i++) { if (ptr[i]) return True; } --- 780,786 ---- register int i; register Char *ptr = BUF_CHARS(sb, row); ! for (i = col; i < len; i++) { if (ptr[i]) return True; } Index: util.c *** /build/x11r6/XFree86-3.1.2Cd/xc/programs/xterm/util.c Wed Jan 10 12:27:01 1996 --- /build/x11r6/XFree86-current/xc/programs/xterm/util.c Wed Feb 14 20:04:10 1996 *************** *** 726,734 **** --- 726,736 ---- if((top = -screen->topline) <= screen->max_row) { if(screen->scroll_amt) FlushScroll(screen); + #if 1 /* FIXME */ if(top == 0) XClearWindow(screen->display, TextWindow(screen)); else + #endif XClearArea(screen->display, TextWindow(screen), screen->border + screen->scrollbar, top * FontHeight(screen) + screen->border, *************** *** 1121,1124 **** --- 1123,1201 ---- colordefs, 2); XRecolorCursor (dpy, cursor, colordefs, colordefs+1); return; + } + + /* + * Returns a GC, selected according to the font (reverse/bold/normal) that is + * required for the current position (implied). The GC is updated with the + * current screen foreground and background colors. + */ + GC + updatedXtermGC(screen, flags, fg, bg, hilite) + register TScreen *screen; + int flags; + int fg; + int bg; + Bool hilite; + { + Pixel fg_pix = GET_FG(flags,fg); + Pixel bg_pix = GET_BG(flags,bg); + GC gc; + + if ( (!hilite && (flags & INVERSE) != 0) + || (hilite && (flags & INVERSE) == 0) ) { + if (flags & BOLD) + gc = screen->reverseboldGC; + else + gc = screen->reverseGC; + + XSetForeground(screen->display, gc, bg_pix); + XSetBackground(screen->display, gc, fg_pix); + + } else { + if (flags & BOLD) + gc = screen->normalboldGC; + else + gc = screen->normalGC; + + XSetForeground(screen->display, gc, fg_pix); + XSetBackground(screen->display, gc, bg_pix); + } + return gc; + } + + /* + * Resets the foreground/background of the GC returned by 'updatedXtermGC()' + * to the values that would be set in SGR_Foreground and SGR_Background. This + * duplicates some logic, but only modifies 1/4 as many GC's. + */ + void + resetXtermGC(screen, flags, hilite) + register TScreen *screen; + int flags; + Bool hilite; + { + Pixel fg_pix = GET_FG(flags,term->cur_foreground); + Pixel bg_pix = GET_BG(flags,term->cur_background); + GC gc; + + if ( (!hilite && (flags & INVERSE) != 0) + || (hilite && (flags & INVERSE) == 0) ) { + if (flags & BOLD) + gc = screen->reverseboldGC; + else + gc = screen->reverseGC; + + XSetForeground(screen->display, gc, bg_pix); + XSetBackground(screen->display, gc, fg_pix); + + } else { + if (flags & BOLD) + gc = screen->normalboldGC; + else + gc = screen->normalGC; + + XSetForeground(screen->display, gc, fg_pix); + XSetBackground(screen->display, gc, bg_pix); + } } Index: xterm.h *** /build/x11r6/XFree86-3.1.2Cd/xc/programs/xterm/xterm.h Tue Jan 16 15:43:01 1996 --- /build/x11r6/XFree86-current/xc/programs/xterm/xterm.h Wed Feb 14 20:47:00 1996 *************** *** 7,12 **** --- 7,15 ---- #include "proto.h" + #define GET_FG(flags,color) ((flags&FG_COLOR) ? screen->colors[color] : screen->foreground) + #define GET_BG(flags,color) ((flags&BG_COLOR) ? screen->colors[color] : term->core.background_pixel) + /* Tekproc.c */ extern int TekInit PROTO((void)); extern void ChangeTekColors PROTO((TScreen *screen, ScrnColors *pNew)); *************** *** 48,53 **** --- 51,58 ---- extern int v_write PROTO((int f, char *d, int len)); extern void FindFontSelection PROTO((char *atom_name, Bool justprobe)); extern void HideCursor PROTO((void)); + extern void SGR_Background PROTO((int color)); + extern void SGR_Foreground PROTO((int color)); extern void SetVTFont PROTO((int i, Bool doresize, char *name1, char *name2)); extern void ShowCursor PROTO((void)); extern void SwitchBufPtrs PROTO((TScreen *screen)); *************** *** 164,169 **** --- 169,175 ---- extern void TabZonk PROTO((Tabs tabs)); /* util.c */ + extern GC updatedXtermGC PROTO((TScreen *screen, int flags, int fg, int bg, Bool hilite)); extern int AddToRefresh PROTO((TScreen *screen)); extern int HandleExposure PROTO((TScreen *screen, XEvent *event)); extern void ChangeColors PROTO((XtermWidget tw, ScrnColors *pNew)); *************** *** 183,188 **** --- 189,195 ---- extern void ReverseVideo PROTO((XtermWidget termw)); extern void Scroll PROTO((TScreen *screen, int amount)); extern void recolor_cursor PROTO((Cursor cursor, unsigned long fg, unsigned long bg)); + extern void resetXtermGC PROTO((TScreen *screen, int flags, Bool hilite)); extern void scrolling_copy_area PROTO((TScreen *screen, int firstline, int nlines, int amount)); #endif /* included_xterm_h */