Merge branch 'X11-bug-fixes' of https://github.com/chasonr/NetHack into NetHack-5.0

This commit is contained in:
nhmall
2026-09-09 11:12:38 -04:00
5 changed files with 135 additions and 31 deletions
+20 -9
View File
@@ -1952,9 +1952,11 @@ wiz_custom(void)
win = create_nhwindow(NHW_MENU); win = create_nhwindow(NHW_MENU);
start_menu(win, MENU_BEHAVE_STANDARD); start_menu(win, MENU_BEHAVE_STANDARD);
add_menu_heading(win, const char *heading = iflags.menu_tab_sep
" glyph glyph identifier " ? "glyph\tglyph identifier\tsym\tclr\tcustomcolor\tunicode\tutf8"
" sym clr customcolor unicode utf8"); : " glyph glyph identifier "
" sym clr customcolor unicode utf8";
add_menu_heading(win, heading);
Sprintf(bufa, "%s: colorcount=%ld %s", wizcustom, Sprintf(bufa, "%s: colorcount=%ld %s", wizcustom,
(long) iflags.colorcount, (long) iflags.colorcount,
gs.symset[PRIMARYSET].name ? gs.symset[PRIMARYSET].name gs.symset[PRIMARYSET].name ? gs.symset[PRIMARYSET].name
@@ -2001,26 +2003,35 @@ wizcustom_callback(winid win, int glyphnum, char *id)
cgm->u || cgm->u ||
#endif #endif
cgm->customcolor != 0) { cgm->customcolor != 0) {
Sprintf(bufa, "[%04d] %-44s", glyphnum, id); if (iflags.menu_tab_sep) {
Sprintf(bufb, "'\\%03d' %02d", Sprintf(bufa, "[%04d]\t%s\t", glyphnum, id);
gs.showsyms[cgm->sym.symidx], cgm->sym.color); Sprintf(bufb, "'\\%03d'\t%02d\t",
Sprintf(bufc, "%011lx", (unsigned long) cgm->customcolor); gs.showsyms[cgm->sym.symidx], cgm->sym.color);
Sprintf(bufc, "%011lx\t", (unsigned long) cgm->customcolor);
} else {
Sprintf(bufa, "[%04d] %-45s", glyphnum, id);
Sprintf(bufb, "'\\%03d' %02d ",
gs.showsyms[cgm->sym.symidx], cgm->sym.color);
Sprintf(bufc, "%011lx ", (unsigned long) cgm->customcolor);
}
bufu[0] = '\0'; bufu[0] = '\0';
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
if (cgm->u && cgm->u->utf8str) { if (cgm->u && cgm->u->utf8str) {
uint8 *cp; uint8 *cp;
char sep = iflags.menu_tab_sep ? '\t' : ' ';
Sprintf(bufu, "U+%04lx", (unsigned long) cgm->u->utf32ch); Sprintf(bufu, "U+%04lx", (unsigned long) cgm->u->utf32ch);
cp = cgm->u->utf8str; cp = cgm->u->utf8str;
while (*cp) { while (*cp) {
char bufd[BUFSZ]; char bufd[BUFSZ];
Sprintf(bufd, " <%d>", (int) *cp); Sprintf(bufd, "%c<%d>", sep, (int) *cp);
Strcat(bufu, bufd); Strcat(bufu, bufd);
cp++; cp++;
sep = ' ';
} }
} }
#endif #endif
any.a_int = glyphnum + 1; /* avoid 0 */ any.a_int = glyphnum + 1; /* avoid 0 */
Snprintf(buf, sizeof buf, "%s %s %s %s", bufa, bufb, bufc, bufu); Snprintf(buf, sizeof buf, "%s%s%s%s", bufa, bufb, bufc, bufu);
add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr, buf, add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, clr, buf,
MENU_ITEMFLAGS_NONE); MENU_ITEMFLAGS_NONE);
} }
+76 -7
View File
@@ -54,6 +54,7 @@ enum { font_bold = 1, font_italic = 2 };
static boolean check_label(Widget); static boolean check_label(Widget);
static void delete_callback(Widget, XtPointer, XtPointer); static void delete_callback(Widget, XtPointer, XtPointer);
static void update_label(Widget, WidgetData *); static void update_label(Widget, WidgetData *);
static void set_tab_stops(Widget, WidgetData *, const char *);
static void allocate_font(Widget, WidgetData *, unsigned); static void allocate_font(Widget, WidgetData *, unsigned);
static void free_fonts(Widget, WidgetData *); static void free_fonts(Widget, WidgetData *);
@@ -242,6 +243,11 @@ update_label(Widget w, WidgetData *data)
attrs |= HL_DIM; attrs |= HL_DIM;
} }
/* Set the tab stops if needed */
if (data->columns == NULL && strchr(label, '\t') != NULL) {
set_tab_stops(w, data, label);
}
/* Dimensions of pixmap */ /* Dimensions of pixmap */
Dimension width; Dimension width;
Dimension height; Dimension height;
@@ -496,6 +502,66 @@ update_label(Widget w, WidgetData *data)
data->pixmap = new_pixmap; data->pixmap = new_pixmap;
} }
/* Set tab stops for text window */
static void
set_tab_stops(Widget w, WidgetData *data, const char *label)
{
/* Count columns */
unsigned col = 0;
unsigned num_cols = 0;
size_t i = 0;
while (label[i] != '\0') {
size_t len = strcspn(label + i, "\t\n");
++col;
i += len;
if (label[i] != '\t') {
/* The last column on its line */
num_cols = max(num_cols, col);
col = 0;
}
if (label[i] != '\0') {
++i;
}
}
int *columns = (int *) alloc(num_cols * sizeof(columns[0]));
memset(columns, 0, num_cols * sizeof(columns[0]));
/* Determine column sizes */
col = 0;
i = 0;
Display *display = XtDisplay(w);
while (label[i] != '\0') {
size_t len = strcspn(label + i, "\t\n");
if (label[i+len] == '\t') {
/* A column from label+i to label+i+len */
int width = X11_column_width(display, data->font[0], label + i, len);
columns[col] = max(columns[col], width);
++col;
} else {
/* Last column of the line */
/* This does not participate in sizing the column */
col = 0;
}
i += len;
if (label[i] != '\0') {
++i;
}
}
/* Convert to column positions */
int pos = 0;
for (unsigned j = 0; j < num_cols; ++j) {
int rpos = pos + columns[j];
columns[j] = pos;
pos = rpos;
}
free(data->columns);
data->columns = columns;
data->num_cols = num_cols;
}
/* Allocate a bold or italic font */ /* Allocate a bold or italic font */
static void static void
allocate_font(Widget w, WidgetData *data, unsigned font_idx) allocate_font(Widget w, WidgetData *data, unsigned font_idx)
@@ -610,9 +676,9 @@ typedef struct WidgetBucket {
WidgetData *data; WidgetData *data;
} WidgetBucket; } WidgetBucket;
#define MAX_WIDGETS 1024 static WidgetBucket *widget_table = NULL;
static WidgetBucket widget_table[MAX_WIDGETS]; static unsigned num_widgets = 0;
static unsigned num_widgets; static unsigned max_widgets = 0;
/* bsearch compare function to search widget-table */ /* bsearch compare function to search widget-table */
static int static int
@@ -653,9 +719,12 @@ get_widget_data(Widget w)
static WidgetData * static WidgetData *
add_widget(Widget w) add_widget(Widget w)
{ {
/* Panic rather than overflow the array */ /* If the array is full (or unallocated), add some new space to it */
if (num_widgets >= MAX_WIDGETS) { if (num_widgets >= max_widgets) {
panic("Widget table is full\n"); max_widgets = num_widgets + 1024;
widget_table = (WidgetBucket *) re_alloc(
(long *) widget_table,
max_widgets * sizeof(widget_table[0]));
} }
/* Insert the widget into the table, maintaining its order */ /* Insert the widget into the table, maintaining its order */
@@ -688,7 +757,7 @@ delete_widget(Widget w)
/* Remove the widget from the table */ /* Remove the widget from the table */
for (unsigned i = (unsigned)(bucket - widget_table); for (unsigned i = (unsigned)(bucket - widget_table);
i + 1 < MAX_WIDGETS; i + 1 < num_widgets;
++i) { ++i) {
widget_table[i] = widget_table[i+1]; widget_table[i] = widget_table[i+1];
} }
+5 -7
View File
@@ -1320,12 +1320,10 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
/* Does any line have a selector? */ /* Does any line have a selector? */
boolean any_canpick = FALSE; boolean any_canpick = FALSE;
if (how != PICK_NONE) { for (curr = curr_menu->base; curr; curr = curr->next) {
for (curr = curr_menu->base; curr; curr = curr->next) { if (curr->identifier.a_void != NULL) {
if (curr->identifier.a_void != NULL) { any_canpick = TRUE;
any_canpick = TRUE; break;
break;
}
} }
} }
@@ -1342,7 +1340,7 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
String str = (String) curr->str; String str = (String) curr->str;
int attr = ATR_NONE; int attr = ATR_NONE;
int color = NO_COLOR; int color = NO_COLOR;
boolean canpick = (how != PICK_NONE && curr->identifier.a_void); boolean canpick = curr->identifier.a_void != NULL;
/* Add tabs if needed to align non-selector lines with selector lines */ /* Add tabs if needed to align non-selector lines with selector lines */
if (any_canpick && !canpick) { if (any_canpick && !canpick) {
+32 -6
View File
@@ -520,16 +520,42 @@ redraw_message_window(struct xwindow *wp)
for (y_base = row = 0, curr = mesg_info->head; row < mesg_info->num_lines; for (y_base = row = 0, curr = mesg_info->head; row < mesg_info->num_lines;
row++, y_base += mesg_info->char_height, curr = curr->next) { row++, y_base += mesg_info->char_height, curr = curr->next) {
#ifdef USE_XFT if (curr->line == NULL) {
if (curr->line != NULL) { continue;
XftDrawString8(draw, &fgcolor, font,
mesg_info->char_lbearing, mesg_info->char_ascent + y_base,
(const FcChar8 *) curr->line, curr->str_length);
} }
/* Deal with any tabs in the output. These will just be single strings,
* not needing to align columns, so just convert to spaces */
const char *str = curr->line;
int str_length = curr->str_length;
char buf[BUFSZ];
if (memchr(str, '\t', str_length) != NULL) {
int i2 = 0;
for (int i1 = 0; i1 < str_length; ++i1) {
if (str[i1] == '\t') {
if (i2 + 4 > BUFSZ) {
break;
}
memcpy(buf + i2, " ", 4);
i2 += 4;
} else {
if (i2 >= BUFSZ) {
break;
}
buf[i2++] = str[i1];
}
}
/* buf does not need to be null terminated */
str = buf;
str_length = i2;
}
#ifdef USE_XFT
XftDrawString8(draw, &fgcolor, font,
mesg_info->char_lbearing, mesg_info->char_ascent + y_base,
(const FcChar8 *) str, str_length);
#else /* !USE_XFT */ #else /* !USE_XFT */
XDrawString(XtDisplay(wp->w), XtWindow(wp->w), mesg_info->gc, XDrawString(XtDisplay(wp->w), XtWindow(wp->w), mesg_info->gc,
mesg_info->char_lbearing, mesg_info->char_ascent + y_base, mesg_info->char_lbearing, mesg_info->char_ascent + y_base,
curr->line, curr->str_length); str, str_length);
#endif /* ?USE_XFT */ #endif /* ?USE_XFT */
/* /*
* This draws a line at the _top_ of the line of text pointed to by * This draws a line at the _top_ of the line of text pointed to by
+2 -2
View File
@@ -170,7 +170,7 @@ display_text_window(struct xwindow *wp, boolean blocking)
XtSetArg(args[num_args], XtNlabel, text_info->text.text); XtSetArg(args[num_args], XtNlabel, text_info->text.text);
num_args++; num_args++;
XtSetValues(wp->w, args, num_args); XtSetValues(wp->w, args, num_args);
X11_update_label_if_Xft(wp->w); X11_update_label(wp->w);
#ifdef TRANSIENT_TEXT #ifdef TRANSIENT_TEXT
XtRealizeWidget(wp->popup); XtRealizeWidget(wp->popup);
@@ -259,7 +259,7 @@ create_text_window(struct xwindow *wp)
form, /* parent widget */ form, /* parent widget */
args, /* set some values */ args, /* set some values */
num_args); /* number of values to set */ num_args); /* number of values to set */
X11_wrap_widget_if_Xft(wp->w, NHW_TEXT); X11_wrap_widget(wp->w, NHW_TEXT);
} }
void void