Add support for tabbed menu columns
This commit is contained in:
committed by
Pasi Kallinen
parent
44b04064be
commit
ae8b4bf12a
@@ -531,8 +531,10 @@ extern void X11_update_label(Widget);
|
|||||||
extern void X11_set_attrs(Widget, unsigned);
|
extern void X11_set_attrs(Widget, unsigned);
|
||||||
extern void X11_set_highlight(Widget, boolean);
|
extern void X11_set_highlight(Widget, boolean);
|
||||||
extern void X11_set_percent(Widget, unsigned, Pixel);
|
extern void X11_set_percent(Widget, unsigned, Pixel);
|
||||||
|
extern void X11_set_column_widths(Widget, const int *, unsigned);
|
||||||
extern void X11_blink_labels(void);
|
extern void X11_blink_labels(void);
|
||||||
extern int X11_font_height(X11_Font *);
|
extern int X11_font_height(X11_Font *);
|
||||||
|
extern int X11_column_width(Display *, X11_Font *, const char *, size_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are for widgets that use the enhanced label services only for text
|
* These are for widgets that use the enhanced label services only for text
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ NetHack*text*borderWidth: 0
|
|||||||
! These correspond to the .nethackrc settings font_map, font_menu,
|
! These correspond to the .nethackrc settings font_map, font_menu,
|
||||||
! font_message, font_status and font_text
|
! font_message, font_status and font_text
|
||||||
NetHack.font_map: mono-10
|
NetHack.font_map: mono-10
|
||||||
NetHack.font_menu: mono-10
|
NetHack.font_menu: sans-10
|
||||||
NetHack.font_message: sans-10
|
NetHack.font_message: sans-10
|
||||||
NetHack.font_status: sans-10
|
NetHack.font_status: sans-10
|
||||||
NetHack.font_text: mono-10
|
NetHack.font_text: mono-10
|
||||||
|
|||||||
+4
-1
@@ -1571,7 +1571,7 @@ static XtResource resources[] = {
|
|||||||
{ nhStr("font_map"), nhStr("Font_map"), XtRString, sizeof(String),
|
{ nhStr("font_map"), nhStr("Font_map"), XtRString, sizeof(String),
|
||||||
XtOffset(AppResources *, font_map), XtRString, nhStr("mono-10") },
|
XtOffset(AppResources *, font_map), XtRString, nhStr("mono-10") },
|
||||||
{ nhStr("font_menu"), nhStr("Font_menu"), XtRString, sizeof(String),
|
{ nhStr("font_menu"), nhStr("Font_menu"), XtRString, sizeof(String),
|
||||||
XtOffset(AppResources *, font_menu), XtRString, nhStr("mono-10") },
|
XtOffset(AppResources *, font_menu), XtRString, nhStr("sans-10") },
|
||||||
{ nhStr("font_message"), nhStr("Font_message"), XtRString, sizeof(String),
|
{ nhStr("font_message"), nhStr("Font_message"), XtRString, sizeof(String),
|
||||||
XtOffset(AppResources *, font_message), XtRString, nhStr("sans-10") },
|
XtOffset(AppResources *, font_message), XtRString, nhStr("sans-10") },
|
||||||
{ nhStr("font_status"), nhStr("Font_status"), XtRString, sizeof(String),
|
{ nhStr("font_status"), nhStr("Font_status"), XtRString, sizeof(String),
|
||||||
@@ -1646,6 +1646,9 @@ X11_init_nhwindows(int *argcp, char **argv)
|
|||||||
Arg args[4];
|
Arg args[4];
|
||||||
uid_t savuid;
|
uid_t savuid;
|
||||||
|
|
||||||
|
/* Request tabbed menu columns */
|
||||||
|
iflags.menu_tab_sep = TRUE;
|
||||||
|
|
||||||
/* Init windows to nothing. */
|
/* Init windows to nothing. */
|
||||||
for (i = 0; i < MAX_WINDOWS; i++)
|
for (i = 0; i < MAX_WINDOWS; i++)
|
||||||
window_list[i].type = NHW_NONE;
|
window_list[i].type = NHW_NONE;
|
||||||
|
|||||||
+93
-12
@@ -19,7 +19,8 @@
|
|||||||
#include "winX.h"
|
#include "winX.h"
|
||||||
|
|
||||||
/* Declarations depending on Xft support or none */
|
/* Declarations depending on Xft support or none */
|
||||||
static int X11_text_width(Display *, X11_Font *, const char *, size_t);
|
static int X11_text_width(Display *, X11_Font *, const char *, size_t,
|
||||||
|
const int *, unsigned);
|
||||||
|
|
||||||
/* Data attached to a wrapped widget */
|
/* Data attached to a wrapped widget */
|
||||||
typedef struct WidgetData {
|
typedef struct WidgetData {
|
||||||
@@ -41,6 +42,10 @@ typedef struct WidgetData {
|
|||||||
/* Percentage bar */
|
/* Percentage bar */
|
||||||
unsigned percent;
|
unsigned percent;
|
||||||
Pixel bar_color;
|
Pixel bar_color;
|
||||||
|
|
||||||
|
/* Columns */
|
||||||
|
int *columns;
|
||||||
|
unsigned num_cols;
|
||||||
} WidgetData;
|
} WidgetData;
|
||||||
|
|
||||||
/* Bits for WidgetData::font */
|
/* Bits for WidgetData::font */
|
||||||
@@ -119,6 +124,7 @@ delete_callback(Widget w, XtPointer client_data, XtPointer call_data)
|
|||||||
XFreePixmap(display, data->pixmap);
|
XFreePixmap(display, data->pixmap);
|
||||||
}
|
}
|
||||||
free_fonts(w, data);
|
free_fonts(w, data);
|
||||||
|
free(data->columns);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +179,25 @@ X11_set_percent(Widget w, unsigned percent, Pixel color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
X11_set_column_widths(Widget w, const int *col_widths, unsigned num_cols)
|
||||||
|
{
|
||||||
|
WidgetData *data = get_widget_data(w);
|
||||||
|
if (data != NULL) {
|
||||||
|
int col_spacing = X11_font_height(data->font[0]) * 2;
|
||||||
|
free(data->columns);
|
||||||
|
data->columns = (int *) alloc(sizeof(data->columns[0]) * num_cols);
|
||||||
|
if (num_cols != 0) {
|
||||||
|
data->columns[0] = 0;
|
||||||
|
for (unsigned i = 1; i < num_cols; ++i) {
|
||||||
|
data->columns[i] = data->columns[i-1] + col_spacing + col_widths[i-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data->num_cols = num_cols;
|
||||||
|
update_label(w, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the label's pixmap */
|
/* Update the label's pixmap */
|
||||||
/* This is called from functions that have altered the data block, and already
|
/* This is called from functions that have altered the data block, and already
|
||||||
have a pointer to it */
|
have a pointer to it */
|
||||||
@@ -235,7 +260,8 @@ update_label(Widget w, WidgetData *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the width of the line */
|
/* Get the width of the line */
|
||||||
int lwidth = X11_text_width(display, font, label + i, line2);
|
int lwidth = X11_text_width(display, font, label + i, line2,
|
||||||
|
data->columns, data->num_cols);
|
||||||
|
|
||||||
/* Update pixmap dimensions */
|
/* Update pixmap dimensions */
|
||||||
width = max(lwidth, width);
|
width = max(lwidth, width);
|
||||||
@@ -301,6 +327,7 @@ update_label(Widget w, WidgetData *data)
|
|||||||
if ((attrs & HL_BLINK) && X11_blink) {
|
if ((attrs & HL_BLINK) && X11_blink) {
|
||||||
values.foreground = values.background;
|
values.foreground = values.background;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_XFT
|
#ifdef USE_XFT
|
||||||
Visual *visual = DefaultVisualOfScreen(screen);
|
Visual *visual = DefaultVisualOfScreen(screen);
|
||||||
Colormap cmap = DefaultColormapOfScreen(screen);
|
Colormap cmap = DefaultColormapOfScreen(screen);
|
||||||
@@ -357,7 +384,8 @@ update_label(Widget w, WidgetData *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the width of the line */
|
/* Get the width of the line */
|
||||||
int lwidth = X11_text_width(display, font, label + i, line2);
|
int lwidth = X11_text_width(display, font, label + i, line2,
|
||||||
|
data->columns, data->num_cols);
|
||||||
|
|
||||||
/* Place the line horizontally */
|
/* Place the line horizontally */
|
||||||
int x = 0;
|
int x = 0;
|
||||||
@@ -378,13 +406,38 @@ update_label(Widget w, WidgetData *data)
|
|||||||
/* Render the line */
|
/* Render the line */
|
||||||
#ifdef USE_XFT
|
#ifdef USE_XFT
|
||||||
XftDrawRect(draw, &bgcolor, x, y - font->ascent, lwidth, X11_font_height(font));
|
XftDrawRect(draw, &bgcolor, x, y - font->ascent, lwidth, X11_font_height(font));
|
||||||
XftDrawString8(draw, &fgcolor, font, x, y,
|
|
||||||
(const FcChar8 *) (label + i), line2);
|
|
||||||
#else
|
#else
|
||||||
XDrawImageString(display, new_pixmap, ggc,
|
XSetForeground(display, ggc, values.background);
|
||||||
x, y,
|
XFillRectangle(display, new_pixmap, ggc, x, y - font->ascent, lwidth, X11_font_height(font));
|
||||||
label + i, line2);
|
XSetForeground(display, ggc, values.foreground);
|
||||||
#endif
|
#endif
|
||||||
|
size_t j = 0;
|
||||||
|
unsigned col = 0;
|
||||||
|
while (j < line2) {
|
||||||
|
size_t line3;
|
||||||
|
int pos;
|
||||||
|
if (data->num_cols == 0) {
|
||||||
|
/* Columns not set */
|
||||||
|
line3 = line2;
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
line3 = min(strcspn(label + i + j, "\t\n"), line2);
|
||||||
|
pos = data->columns[min(col, data->num_cols-1)];
|
||||||
|
}
|
||||||
|
#ifdef USE_XFT
|
||||||
|
XftDrawString8(draw, &fgcolor, font, x + pos, y,
|
||||||
|
(const FcChar8 *) (label + i + j), line3);
|
||||||
|
#else
|
||||||
|
XDrawString(display, new_pixmap, ggc,
|
||||||
|
x + pos, y,
|
||||||
|
label + i + j, line3);
|
||||||
|
#endif
|
||||||
|
j += line3;
|
||||||
|
if (j < line2) {
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
++col;
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw the underline if requested */
|
/* Draw the underline if requested */
|
||||||
if (attrs & HL_ULINE) {
|
if (attrs & HL_ULINE) {
|
||||||
@@ -488,13 +541,41 @@ free_fonts(Widget w, WidgetData *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
X11_text_width(Display *display, X11_Font *font, const char *text, size_t length,
|
||||||
|
const int *columns, unsigned num_cols)
|
||||||
|
{
|
||||||
|
if (num_cols == 0) {
|
||||||
|
/* Columns have not been set */
|
||||||
|
return X11_column_width(display, font, text, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Width is the position of the last column, plus the width of the string
|
||||||
|
in the last column */
|
||||||
|
|
||||||
|
unsigned col = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
while (col < num_cols) {
|
||||||
|
size_t len = strcspn(text + i, "\t\n");
|
||||||
|
if (i+len >= length || text[i+len] != '\t') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++col;
|
||||||
|
i += len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = columns[col] + X11_column_width(display, font, text + i, length - i);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions that depend on the font rendering API //
|
// Functions that depend on the font rendering API //
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef USE_XFT
|
#ifdef USE_XFT
|
||||||
static int
|
int
|
||||||
X11_text_width(Display *display, X11_Font *font, const char *text, size_t length)
|
X11_column_width(Display *display, X11_Font *font, const char *text, size_t length)
|
||||||
{
|
{
|
||||||
XGlyphInfo extents;
|
XGlyphInfo extents;
|
||||||
XftTextExtents8(display, font, (const FcChar8*) text, length, &extents);
|
XftTextExtents8(display, font, (const FcChar8*) text, length, &extents);
|
||||||
@@ -507,8 +588,8 @@ X11_font_height(X11_Font *font)
|
|||||||
return max(font->height, font->ascent + font->descent);
|
return max(font->height, font->ascent + font->descent);
|
||||||
}
|
}
|
||||||
#else /* !USE_XFT */
|
#else /* !USE_XFT */
|
||||||
static int
|
int
|
||||||
X11_text_width(Display *display, X11_Font *font, const char *text, size_t length)
|
X11_column_width(Display *display, X11_Font *font, const char *text, size_t length)
|
||||||
{
|
{
|
||||||
nhUse(display);
|
nhUse(display);
|
||||||
return XTextWidth(font, text, length);
|
return XTextWidth(font, text, length);
|
||||||
|
|||||||
+77
-1
@@ -60,6 +60,7 @@ static unsigned menu_scrollmask(struct xwindow *);
|
|||||||
static void menu_unscroll(struct xwindow *);
|
static void menu_unscroll(struct xwindow *);
|
||||||
static Widget menu_create_buttons(struct xwindow *, Widget, Widget);
|
static Widget menu_create_buttons(struct xwindow *, Widget, Widget);
|
||||||
static void menu_create_entries(struct xwindow *, struct menu *);
|
static void menu_create_entries(struct xwindow *, struct menu *);
|
||||||
|
static unsigned get_col_widths(Widget, X11_Font *, const char *, int **);
|
||||||
static void destroy_menu_entry_widgets(struct xwindow *);
|
static void destroy_menu_entry_widgets(struct xwindow *);
|
||||||
static void create_menu_translation_tables(void);
|
static void create_menu_translation_tables(void);
|
||||||
|
|
||||||
@@ -1317,6 +1318,13 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
|
|||||||
Cardinal num_args;
|
Cardinal num_args;
|
||||||
Dimension cwidth, maxwidth = 0;
|
Dimension cwidth, maxwidth = 0;
|
||||||
|
|
||||||
|
int *col_widths = NULL;
|
||||||
|
unsigned num_cols = 0;
|
||||||
|
X11_Font *font;
|
||||||
|
#ifdef USE_XFT
|
||||||
|
font = X11_new_font(wp->w, 0, NHW_MENU);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (curr = curr_menu->base; curr; curr = curr->next) {
|
for (curr = curr_menu->base; curr; curr = curr->next) {
|
||||||
char tmpbuf[BUFSZ];
|
char tmpbuf[BUFSZ];
|
||||||
Widget linewidget;
|
Widget linewidget;
|
||||||
@@ -1376,13 +1384,42 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
|
|||||||
wp->w, args, num_args);
|
wp->w, args, num_args);
|
||||||
X11_wrap_widget(curr->w, NHW_MENU);
|
X11_wrap_widget(curr->w, NHW_MENU);
|
||||||
X11_set_attrs(curr->w, 0x1 << attr);
|
X11_set_attrs(curr->w, 0x1 << attr);
|
||||||
XtManageChild(curr->w);
|
|
||||||
|
|
||||||
if (canpick)
|
if (canpick)
|
||||||
XtAddCallback(linewidget, XtNcallback, menu_select,
|
XtAddCallback(linewidget, XtNcallback, menu_select,
|
||||||
(XtPointer) curr);
|
(XtPointer) curr);
|
||||||
prevlinewidget = linewidget;
|
prevlinewidget = linewidget;
|
||||||
|
|
||||||
|
#ifndef USE_XFT /* If Xft, the font is acquired at the start of the loop */
|
||||||
|
num_args = 0;
|
||||||
|
XtSetArg(args[num_args], XtNfont, &font); num_args++;
|
||||||
|
XtGetValues(curr->w, args, num_args);
|
||||||
|
#endif
|
||||||
|
/* Get column widths for this line */
|
||||||
|
if (strchr(str, '\t') != NULL) { /* Might be a header if no tab */
|
||||||
|
int *col_widths0;
|
||||||
|
unsigned num_cols0 = get_col_widths(curr->w, font, str, &col_widths0);
|
||||||
|
if (num_cols0 > num_cols) {
|
||||||
|
col_widths = (int *) re_alloc((long *) col_widths, num_cols0 * sizeof(col_widths[0]));
|
||||||
|
memset(col_widths + num_cols, 0, sizeof(col_widths[0]) * (num_cols0 - num_cols));
|
||||||
|
num_cols = num_cols0;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < num_cols0; ++i) {
|
||||||
|
col_widths[i] = max(col_widths[i], col_widths0[i]);
|
||||||
|
}
|
||||||
|
free(col_widths0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef USE_XFT
|
||||||
|
X11_release_font(wp->w, font);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set the column widths */
|
||||||
|
for (curr = curr_menu->base; curr; curr = curr->next) {
|
||||||
|
X11_set_column_widths(curr->w, col_widths, num_cols);
|
||||||
|
XtManageChild(curr->w);
|
||||||
|
|
||||||
|
boolean canpick = (how != PICK_NONE && curr->identifier.a_void);
|
||||||
if (canpick) {
|
if (canpick) {
|
||||||
/* get the current line width */
|
/* get the current line width */
|
||||||
XtSetArg(args[0], XtNwidth, &cwidth);
|
XtSetArg(args[0], XtNwidth, &cwidth);
|
||||||
@@ -1392,6 +1429,8 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(col_widths);
|
||||||
|
|
||||||
/* set all selectable menu entries to the maximum width */
|
/* set all selectable menu entries to the maximum width */
|
||||||
if (how != PICK_NONE) {
|
if (how != PICK_NONE) {
|
||||||
XtSetArg(args[0], XtNwidth, maxwidth);
|
XtSetArg(args[0], XtNwidth, maxwidth);
|
||||||
@@ -1401,6 +1440,43 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine widths of columns */
|
||||||
|
static unsigned
|
||||||
|
get_col_widths(Widget w, X11_Font *font, const char *str, int **col_widths)
|
||||||
|
{
|
||||||
|
/* Determine the number of columns */
|
||||||
|
unsigned num_cols = 1;
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0') {
|
||||||
|
size_t len = strcspn(str + i, "\t");
|
||||||
|
if (str[i+len] == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++num_cols;
|
||||||
|
i += len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate width array */
|
||||||
|
int *cwidths = (int *) alloc(sizeof(cwidths[0]) * num_cols);
|
||||||
|
memset(cwidths, 0, sizeof(cwidths[0]) * num_cols);
|
||||||
|
|
||||||
|
/* Get the widths of the columns */
|
||||||
|
unsigned col = 0;
|
||||||
|
i = 0;
|
||||||
|
while (str[i] != '\0') {
|
||||||
|
size_t len = strcspn(str + i, "\t");
|
||||||
|
cwidths[col++] = X11_column_width(XtDisplay(w), font, str + i, len);
|
||||||
|
i += len;
|
||||||
|
if (str[i] == '\t') {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return */
|
||||||
|
*col_widths = cwidths;
|
||||||
|
return num_cols;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_menu_entry_widgets(struct xwindow *wp)
|
destroy_menu_entry_widgets(struct xwindow *wp)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user