Hi,
if you happen to have a machine where the X server is running with a
default depth of 30 bits per pixel and a True Color Visual (10 bit/rgb
component), xterm wih TrueType fonts (using faceName X resource or the
-fa command-line option) will display as a black window...
This happens to be a 2 stage regression from xterm 366, which was ok
on these setups, to xterm 369 which started to get faded colors, to
xterm 370 which completely fails to display stuff.
The patch below backs out the changes between xterm v366 and v372 that
cause this regression. As far as I can tell the result is also still
ok on other displays.
ok ?
Index: misc.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/app/xterm/misc.c,v
retrieving revision 1.46
diff -u -r1.46 misc.c
--- misc.c 22 May 2022 13:50:19 -0000 1.46
+++ misc.c 2 Sep 2022 09:58:21 -0000
@@ -2599,7 +2599,7 @@
return result;
}
-XVisualInfo *
+int
getVisualInfo(XtermWidget xw)
{
#define MYFMT "getVisualInfo \
@@ -2640,9 +2640,7 @@
(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 @@
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 @@
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 @@
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 @@
* 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 @@
}
}
}
- 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 @@
#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 @@
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 @@
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 @@
return (result);
}
+#if OPT_COLOR_RES
Pixel
xtermGetColorRes(XtermWidget xw, ColorRes * res)
{
@@ -2970,6 +3095,7 @@
}
return result;
}
+#endif
static int
ChangeOneAnsiColor(XtermWidget xw, int color, const char *name)
@@ -3108,15 +3234,16 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
if (AllowColorOps(xw, ecGetColor)) {
XColor color;
+ Colormap cmap = xw->core.colormap;
char buffer[80];
/*
@@ -3611,7 +3709,7 @@
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 @@
(void) code;
TRACE(("ResetColorsRequest code=%d\n", code));
+
+#if OPT_COLOR_RES
if (GetOldColors(xw)) {
ScrnColors newColors;
const char *thisName;
@@ -3777,6 +3877,7 @@
}
result = True;
}
+#endif
return result;
}
@@ -6974,9 +7075,7 @@
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 @@
}
static int
-insertFontParams(XtermWidget xw, int *targetp, Bool first)
+insertFontParams(XtermWidget xw, int *targetp, Boolean first)
{
int changed = 0;
int n;
Index: ptyx.h
===================================================================
RCS file: /cvs/OpenBSD/xenocara/app/xterm/ptyx.h,v
retrieving revision 1.51
diff -u -r1.51 ptyx.h
--- ptyx.h 25 Apr 2022 19:20:37 -0000 1.51
+++ ptyx.h 2 Sep 2022 09:58:21 -0000
@@ -552,6 +552,10 @@
#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
Index: util.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/app/xterm/util.c,v
retrieving revision 1.41
diff -u -r1.41 util.c
--- util.c 25 Apr 2022 19:20:38 -0000 1.41
+++ util.c 2 Sep 2022 09:58:21 -0000
@@ -2953,7 +2953,7 @@
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 @@
&& ((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)) {
Index: xterm.h
===================================================================
RCS file: /cvs/OpenBSD/xenocara/app/xterm/xterm.h,v
retrieving revision 1.50
diff -u -r1.50 xterm.h
--- xterm.h 25 Apr 2022 19:20:38 -0000 1.50
+++ xterm.h 2 Sep 2022 09:58:21 -0000
@@ -1180,7 +1180,7 @@
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 */);
--
Matthieu Herrb