diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2022-09-03 06:51:47 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2022-09-03 06:51:47 +0000 |
commit | 6d094594ce46895fd45b62bb0c284575920eb91d (patch) | |
tree | 42f71556d6c1adeec641094f7e592926e4cf3bd3 /app/xterm | |
parent | c51805f95c9adb6ca062522e0083daae7dff9019 (diff) |
Revert parts of the changes in versions 368 and 369 that broke
support of 30bpp displays with TrueType fonts
Diffstat (limited to 'app/xterm')
-rw-r--r-- | app/xterm/misc.c | 351 | ||||
-rw-r--r-- | app/xterm/ptyx.h | 4 | ||||
-rw-r--r-- | app/xterm/util.c | 8 | ||||
-rw-r--r-- | app/xterm/xterm.h | 2 |
4 files changed, 234 insertions, 131 deletions
diff --git a/app/xterm/misc.c b/app/xterm/misc.c index 0369ff4a4..35f12489b 100644 --- a/app/xterm/misc.c +++ b/app/xterm/misc.c @@ -2599,7 +2599,7 @@ maskToWidth(unsigned long mask) return result; } -XVisualInfo * +int getVisualInfo(XtermWidget xw) { #define MYFMT "getVisualInfo \ @@ -2640,9 +2640,7 @@ rgb masks (%04lx/%04lx/%04lx)\n" (vi->blue_mask != 0) && ((vi->red_mask & vi->green_mask) == 0) && ((vi->green_mask & vi->blue_mask) == 0) && - ((vi->blue_mask & vi->red_mask) == 0) && - (vi->class == TrueColor - || vi->class == DirectColor)); + ((vi->blue_mask & vi->red_mask) == 0)); if (resource.reportColors) { printf(MYFMT, MYARG); @@ -2652,13 +2650,9 @@ rgb masks (%04lx/%04lx/%04lx)\n" xw->rgb_shifts[0], xw->rgb_shifts[1], xw->rgb_shifts[2])); - TRACE(("...widths %u/%u/%u\n", - xw->rgb_widths[0], - xw->rgb_widths[1], - xw->rgb_widths[2])); } } - return (xw->visInfo != 0) && (xw->numVisuals > 0) ? xw->visInfo : NULL; + return (xw->visInfo != 0) && (xw->numVisuals > 0); #undef MYFMT #undef MYARG } @@ -2671,11 +2665,12 @@ ReportAnsiColorRequest(XtermWidget xw, int opcode, int colornum, int final) if (AllowColorOps(xw, ecGetAnsiColor)) { XColor color; + Colormap cmap = xw->core.colormap; char buffer[80]; TRACE(("ReportAnsiColorRequest %d\n", colornum)); color.pixel = GET_COLOR_RES(xw, TScreenOf(xw)->Acolors[colornum]); - (void) QueryOneColor(xw, &color); + XQueryColor(TScreenOf(xw)->display, cmap, &color); sprintf(buffer, "%d;%d;rgb:%04x/%04x/%04x", opcode, (opcode == 5) ? (colornum - NUM_ANSI_COLORS) : colornum, @@ -2742,70 +2737,6 @@ loadColorTable(XtermWidget xw, unsigned length) return result; } -/***====================================================================***/ - -/* - * Call this function with def->{red,green,blue} initialized, to obtain a pixel - * value. - */ -Boolean -AllocOneColor(XtermWidget xw, XColor *def) -{ - TScreen *screen = TScreenOf(xw); - Boolean result = True; - -#define MaskIt(name,nn) \ - ((unsigned long) ((def->name >> (16 - xw->rgb_widths[nn])) \ - << xw->rgb_shifts[nn]) \ - & xw->visInfo->name ##_mask) - - if (getVisualInfo(xw) != NULL && xw->has_rgb) { - def->pixel = MaskIt(red, 0) | MaskIt(green, 1) | MaskIt(blue, 2); - } else { - Display *dpy = screen->display; - if (!XAllocColor(dpy, xw->core.colormap, def)) { - /* - * Decide between foreground and background by a grayscale - * approximation. - */ - int bright = def->red * 3 + def->green * 10 + def->blue; - int levels = 14 * 0x8000; - def->pixel = ((bright >= levels) - ? xw->dft_background - : xw->dft_foreground); - result = False; - } - } - return result; -} - -/***====================================================================***/ - -/* - * Call this function with def->pixel set to the color that we want to convert - * to separate red/green/blue. - */ -Boolean -QueryOneColor(XtermWidget xw, XColor *def) -{ - Boolean result = True; - -#define UnMaskIt(name,nn) \ - ((unsigned short)((def->pixel & xw->visInfo->name ##_mask) >> xw->rgb_shifts[nn])) -#define UnMaskIt2(name,nn) \ - (unsigned short)((((UnMaskIt(name,nn) << 8) \ - |UnMaskIt(name,nn))) << (8 - xw->rgb_widths[nn])) - - if (getVisualInfo(xw) != NULL && xw->has_rgb) { - /* *INDENT-EQLS* */ - def->red = UnMaskIt2(red, 0); - def->green = UnMaskIt2(green, 1); - def->blue = UnMaskIt2(blue, 2); - } else if (!XQueryColor(TScreenOf(xw)->display, xw->core.colormap, def)) { - result = False; - } - return result; -} /***====================================================================***/ @@ -2820,7 +2751,7 @@ QueryOneColor(XtermWidget xw, XColor *def) * Return False if not able to find or allocate a color. */ static Boolean -allocateClosestRGB(XtermWidget xw, XColor *def) +allocateClosestRGB(XtermWidget xw, Colormap cmap, XColor *def) { TScreen *screen = TScreenOf(xw); Boolean result = False; @@ -2874,7 +2805,8 @@ allocateClosestRGB(XtermWidget xw, XColor *def) } } } - if (AllocOneColor(xw, &screen->cmap_data[bestInx])) { + if (XAllocColor(screen->display, cmap, + &screen->cmap_data[bestInx]) != 0) { *def = screen->cmap_data[bestInx]; TRACE(("...closest %x/%x/%x\n", def->red, def->green, def->blue)); @@ -2899,6 +2831,193 @@ allocateClosestRGB(XtermWidget xw, XColor *def) #define ULONG_MAX (unsigned long)(~(0L)) #endif +#define CheckColor(result, value) \ + result = 0; \ + if (value.red) \ + result |= 1; \ + if (value.green) \ + result |= 2; \ + if (value.blue) \ + result |= 4 + +#define SelectColor(state, value, result) \ + switch (state) { \ + default: \ + case 1: \ + result = value.red; \ + break; \ + case 2: \ + result = value.green; \ + break; \ + case 4: \ + result = value.blue; \ + break; \ + } + +/* + * Check if the color map consists of values in exactly one of the red, green + * or blue columns. If it is not, we do not know how to use it for the exact + * match. + */ +static int +simpleColors(XColor *colortable, unsigned length) +{ + unsigned n; + int state = 0; + int check; + + for (n = 0; n < length; ++n) { + if (state > 0) { + CheckColor(check, colortable[n]); + if (check > 0 && check != state) { + state = 0; + break; + } + } else { + CheckColor(state, colortable[n]); + } + } + switch (state) { + case 1: + case 2: + case 4: + break; + default: + state = 0; + break; + } + return state; +} + +/* + * Shift the mask left or right to put its most significant bit at the 16-bit + * mark. + */ +static unsigned +normalizeMask(unsigned mask) +{ + while (mask < 0x8000) { + mask <<= 1; + } + while (mask >= 0x10000) { + mask >>= 1; + } + return mask; +} + +static unsigned +searchColors(XColor *colortable, unsigned mask, unsigned length, unsigned + color, int state) +{ + unsigned result = 0; + unsigned n; + unsigned long best = ULONG_MAX; + unsigned value; + + mask = normalizeMask(mask); + for (n = 0; n < length; ++n) { + unsigned long diff; + + SelectColor(state, colortable[n], value); + diff = ((color & mask) - (value & mask)); + diff *= diff; + if (diff < best) { +#if 0 + TRACE(("...%d:looking for %x, found %x/%x/%x (%lx)\n", + n, color, + colortable[n].red, + colortable[n].green, + colortable[n].blue, + diff)); +#endif + result = n; + best = diff; + } + } + SelectColor(state, colortable[result], value); + return value; +} + +/* + * This is a workaround for a longstanding defect in the X libraries. + * + * According to + * http://www.unix.com/man-page/all/3x/XAllocColoA/ + * + * XAllocColor() acts differently on static and dynamic visuals. On Pseu- + * doColor, DirectColor, and GrayScale visuals, XAllocColor() fails if + * there are no unallocated colorcells and no allocated read-only cell + * exactly matches the requested RGB values. On StaticColor, TrueColor, + * and StaticGray visuals, XAllocColor() returns the closest RGB values + * available in the colormap. The colorcell_in_out structure returns the + * actual RGB values allocated. + * + * That is, XAllocColor() should suffice unless the color map is full. In that + * case, allocateClosestRGB() is useful for the dynamic display classes such as + * PseudoColor. It is not useful for TrueColor, since XQueryColors() does not + * return regular RGB triples (unless a different scheme was used for + * specifying the pixel values); only the blue value is filled in. However, it + * is filled in with the colors that the server supports. + * + * Also (the reason for this function), XAllocColor() does not really work as + * described. For some TrueColor configurations it merely returns a close + * approximation, but not the closest. + */ +static Boolean +allocateExactRGB(XtermWidget xw, Colormap cmap, XColor *def) +{ + XColor save = *def; + TScreen *screen = TScreenOf(xw); + Boolean result = (Boolean) (XAllocColor(screen->display, cmap, def) != 0); + + /* + * If this is a statically allocated display with too many items to store + * in our array, i.e., TrueColor, see if we can improve on the result by + * using the color values actually supported by the server. + */ + if (result) { + unsigned cmap_type; + unsigned cmap_size; + + getColormapInfo(xw, &cmap_type, &cmap_size); + + if (cmap_type == TrueColor) { + XColor temp = *def; + int state; + + if (loadColorTable(xw, cmap_size) + && (state = simpleColors(screen->cmap_data, cmap_size)) > 0) { +#define SearchColors(which) \ + temp.which = (unsigned short) searchColors(screen->cmap_data, \ + (unsigned) xw->visInfo->which##_mask,\ + cmap_size, \ + save.which, \ + state) + SearchColors(red); + SearchColors(green); + SearchColors(blue); + if (XAllocColor(screen->display, cmap, &temp) != 0) { +#if OPT_TRACE + if (temp.red != save.red + || temp.green != save.green + || temp.blue != save.blue) { + TRACE(("...improved %x/%x/%x ->%x/%x/%x\n", + save.red, save.green, save.blue, + temp.red, temp.green, temp.blue)); + } else { + TRACE(("...no improvement for %x/%x/%x\n", + save.red, save.green, save.blue)); + } +#endif + *def = temp; + } + } + } + } + + return result; +} + /* * Allocate a color for the "ANSI" colors. That actually includes colors up * to 256. @@ -2917,8 +3036,11 @@ AllocateAnsiColor(XtermWidget xw, XColor def; if (xtermAllocColor(xw, &def, spec)) { - if (res->mode == True && - EQL_COLOR_RES(res, def.pixel)) { + if ( +#if OPT_COLOR_RES + res->mode == True && +#endif + EQL_COLOR_RES(res, def.pixel)) { result = 0; } else { result = 1; @@ -2932,9 +3054,11 @@ AllocateAnsiColor(XtermWidget xw, def.green, def.blue, def.pixel)); +#if OPT_COLOR_RES if (!res->mode) result = 0; res->mode = True; +#endif } } else { TRACE(("AllocateAnsiColor %s (failed)\n", spec)); @@ -2943,6 +3067,7 @@ AllocateAnsiColor(XtermWidget xw, return (result); } +#if OPT_COLOR_RES Pixel xtermGetColorRes(XtermWidget xw, ColorRes * res) { @@ -2970,6 +3095,7 @@ xtermGetColorRes(XtermWidget xw, ColorRes * res) } return result; } +#endif static int ChangeOneAnsiColor(XtermWidget xw, int color, const char *name) @@ -3108,15 +3234,16 @@ ResetAnsiColorRequest(XtermWidget xw, char *buf, int start) return repaint; } #else -#define allocateClosestRGB(xw, def) 0 +#define allocateClosestRGB(xw, cmap, def) 0 +#define allocateExactRGB(xw, cmap, def) XAllocColor(TScreenOf(xw)->display, cmap, def) #endif /* OPT_ISO_COLORS */ Boolean allocateBestRGB(XtermWidget xw, XColor *def) { - (void) xw; - (void) def; - return AllocOneColor(xw, def) || allocateClosestRGB(xw, def); + Colormap cmap = xw->core.colormap; + + return allocateExactRGB(xw, cmap, def) || allocateClosestRGB(xw, cmap, def); } static Boolean @@ -3129,7 +3256,7 @@ xtermAllocColor(XtermWidget xw, XColor *def, const char *spec) if (have == 0 || have > MAX_U_STRING) { if (resource.reportColors) { - printf("color (ignored, length %lu)\n", (unsigned long) have); + printf("color (ignored, length %lu)\n", have); } } else if (XParseColor(screen->display, cmap, spec, def)) { XColor save_def = *def; @@ -3166,7 +3293,7 @@ int xtermClosestColor(XtermWidget xw, int find_red, int find_green, int find_blue) { int result = -1; -#if OPT_ISO_COLORS +#if OPT_COLOR_RES && OPT_ISO_COLORS int n; int best_index = -1; unsigned long best_value = 0; @@ -3201,7 +3328,6 @@ xtermClosestColor(XtermWidget xw, int find_red, int find_green, int find_blue) } TRACE(("...best match at %d with diff %lx\n", best_index, best_value)); result = best_index; - #else (void) xw; (void) find_red; @@ -3215,48 +3341,19 @@ xtermClosestColor(XtermWidget xw, int find_red, int find_green, int find_blue) int getDirectColor(XtermWidget xw, int red, int green, int blue) { - Pixel result = 0; - -#define getRGB(name,shift) \ - do { \ - Pixel value = (Pixel) name & 0xff; \ - if (xw->rgb_widths[shift] < 8) { \ - value >>= (int) (8 - xw->rgb_widths[shift]); \ - } \ - value <<= xw->rgb_shifts[shift]; \ - value &= xw->visInfo->name ##_mask; \ - result |= value; \ - } while (0) - - getRGB(red, 0); - getRGB(green, 1); - getRGB(blue, 2); - -#undef getRGB - +#define nRGB(name,shift) \ + ((unsigned long)(name << xw->rgb_shifts[shift]) \ + & xw->visInfo->name ##_mask) + MyPixel result = (MyPixel) (nRGB(red, 0) | nRGB(green, 1) | nRGB(blue, 2)); return (int) result; } static void formatDirectColor(char *target, XtermWidget xw, unsigned value) { - Pixel result[3]; - -#define getRGB(name, shift) \ - do { \ - result[shift] = value & xw->visInfo->name ## _mask; \ - result[shift] >>= xw->rgb_shifts[shift]; \ - if (xw->rgb_widths[shift] < 8) \ - result[shift] <<= (int) (8 - xw->rgb_widths[shift]); \ - } while(0) - - getRGB(red, 0); - getRGB(green, 1); - getRGB(blue, 2); - -#undef getRGB - - sprintf(target, "%lu:%lu:%lu", result[0], result[1], result[2]); +#define fRGB(name, shift) \ + (value & xw->visInfo->name ## _mask) >> xw->rgb_shifts[shift] + sprintf(target, "%lu:%lu:%lu", fRGB(red, 0), fRGB(green, 1), fRGB(blue, 2)); } #endif /* OPT_DIRECT_COLOR */ @@ -3600,6 +3697,7 @@ ReportColorRequest(XtermWidget xw, int ndx, int final) if (AllowColorOps(xw, ecGetColor)) { XColor color; + Colormap cmap = xw->core.colormap; char buffer[80]; /* @@ -3611,7 +3709,7 @@ ReportColorRequest(XtermWidget xw, int ndx, int final) GetOldColors(xw); color.pixel = xw->work.oldColors->colors[ndx]; - (void) QueryOneColor(xw, &color); + XQueryColor(TScreenOf(xw)->display, cmap, &color); sprintf(buffer, "%d;rgb:%04x/%04x/%04x", i + 10, color.red, color.green, @@ -3752,6 +3850,8 @@ ResetColorsRequest(XtermWidget xw, (void) code; TRACE(("ResetColorsRequest code=%d\n", code)); + +#if OPT_COLOR_RES if (GetOldColors(xw)) { ScrnColors newColors; const char *thisName; @@ -3777,6 +3877,7 @@ ResetColorsRequest(XtermWidget xw, } result = True; } +#endif return result; } @@ -6974,9 +7075,7 @@ die_callback(Widget w GCC_UNUSED, XtPointer client_data GCC_UNUSED, XtPointer call_data GCC_UNUSED) { - TRACE(("die_callback client=%p, call=%p\n", - (void *) client_data, - (void *) call_data)); + TRACE(("die_callback %p\n", die_callback)); TRACE_SM_PROPS(); NormalExit(); } @@ -7186,7 +7285,7 @@ findFontParams(int argc, char **argv) } static int -insertFontParams(XtermWidget xw, int *targetp, Bool first) +insertFontParams(XtermWidget xw, int *targetp, Boolean first) { int changed = 0; int n; diff --git a/app/xterm/ptyx.h b/app/xterm/ptyx.h index 037f4ae55..e392dc9fa 100644 --- a/app/xterm/ptyx.h +++ b/app/xterm/ptyx.h @@ -552,6 +552,10 @@ typedef enum { #define OPT_COLOR_CLASS 1 /* true if xterm uses separate color-resource classes */ #endif +#ifndef OPT_COLOR_RES +#define OPT_COLOR_RES 1 /* true if xterm delays color-resource evaluation */ +#endif + #ifndef OPT_DABBREV #define OPT_DABBREV 0 /* dynamic abbreviations */ #endif diff --git a/app/xterm/util.c b/app/xterm/util.c index b5e43debd..eca80336f 100644 --- a/app/xterm/util.c +++ b/app/xterm/util.c @@ -2953,7 +2953,7 @@ getXftColor(XtermWidget xw, Pixel pixel) if (!found) { i = oldest; color.pixel = pixel; - (void) QueryOneColor(xw, &color); + XQueryColor(TScreenOf(xw)->display, xw->core.colormap, &color); cache[i].color.color.red = color.red; cache[i].color.color.green = color.green; cache[i].color.color.blue = color.blue; @@ -5075,10 +5075,10 @@ getXtermForeground(XtermWidget xw, unsigned attr_flags, int color) && ((color >= 0) || (result != (Pixel) color))) { XColor work; - last_in = result; work.pixel = result; - if (QueryOneColor(xw, &work)) { - DIM_IT(red); + last_in = result; + if (XQueryColor(TScreenOf(xw)->display, xw->core.colormap, &work)) { + DIM_IT(red); DIM_IT(green); DIM_IT(blue); if (allocateBestRGB(xw, &work)) { diff --git a/app/xterm/xterm.h b/app/xterm/xterm.h index 468294a99..a91b26a47 100644 --- a/app/xterm/xterm.h +++ b/app/xterm/xterm.h @@ -1180,7 +1180,7 @@ extern Window WMFrameWindow (XtermWidget /* xw */); extern XtInputMask xtermAppPending (void); extern XrmOptionDescRec * sortedOptDescs (XrmOptionDescRec *, Cardinal); extern XtermWidget getXtermWidget (Widget /* w */); -extern XVisualInfo *getVisualInfo (XtermWidget /* xw */); +extern int getVisualInfo (XtermWidget /* xw */); extern char *udk_lookup (XtermWidget /* xw */, int /* keycode */, int * /* len */); extern char *xtermEnvEncoding (void); extern char *xtermFindShell (char * /* leaf */, Bool /* warning */); |