curses_putmixed() initial attempt
The curses interface was using genl_putmixed() which doesn't
preserve the symbol actually used for a glyph on the display.
This is a first-attempt at implementing curses_putmixed().
On Linux you'll need to distribute the Makefiles again
sh sys/unix/setup.sh sys/unix/hints/linux.370
On macOS, you'll need to distribute the Makefiles again
sh sys/unix/setup.sh sys/unix/hints/macOS.370
This commit is contained in:
@@ -3119,6 +3119,7 @@ extern int hide_privileges(boolean);
|
||||
#ifdef ENHANCED_SYMBOLS
|
||||
extern int glyphrep(const char *);
|
||||
extern char *mixed_to_utf8(char *buf, size_t bufsz, const char *str, int *);
|
||||
extern const char *mixed_to_glyphinfo(const char *str, glyph_info *gip);
|
||||
extern int match_glyph(char *);
|
||||
extern void dump_all_glyphids(FILE *fp);
|
||||
extern void fill_glyphid_cache(void);
|
||||
|
||||
@@ -79,6 +79,7 @@ extern void curses_display_nhwindow(winid wid, boolean block);
|
||||
extern void curses_destroy_nhwindow(winid wid);
|
||||
extern void curses_curs(winid wid, int x, int y);
|
||||
extern void curses_putstr(winid wid, int attr, const char *text);
|
||||
extern void curses_putmixed(winid window, int attr, const char *str);
|
||||
extern void curses_display_file(const char *filename, boolean must_exist);
|
||||
extern void curses_start_menu(winid wid, unsigned long);
|
||||
extern void curses_add_menu(winid wid, const glyph_info *,
|
||||
|
||||
@@ -542,6 +542,33 @@ mixed_to_utf8(char *buf, size_t bufsz, const char *str, int *retflags)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper routine if a window port wants to extract the unicode
|
||||
* representation from a glyph representation in the string;
|
||||
* the returned string is the remainder of the string after
|
||||
* extracting the \GNNNNNNNN information.
|
||||
*/
|
||||
const char *
|
||||
mixed_to_glyphinfo(const char *str, glyph_info *gip)
|
||||
{
|
||||
int dcount, ggv;
|
||||
|
||||
if (!str || !gip)
|
||||
return " ";
|
||||
|
||||
*gip = nul_glyphinfo;
|
||||
if (*str == '\\' && *(str + 1) == 'G') {
|
||||
if ((dcount = decode_glyph(str + 2, &ggv))) {
|
||||
map_glyphinfo(0, 0, ggv, 0, gip);
|
||||
/* 'str' is ready for the next loop iteration and
|
||||
'*str' should not be copied at the end of this
|
||||
iteration */
|
||||
str += (dcount + 2);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
dump_all_glyphids(FILE *fp)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ WINCFLAGS += -DNOTTYGRAPHICS
|
||||
endif
|
||||
|
||||
ifdef WANT_WIN_CURSES
|
||||
WINCFLAGS += -DCURSES_GRAPHICS
|
||||
WINCFLAGS += -DCURSES_GRAPHICS -D_XOPEN_SOURCE_EXTENDED=1
|
||||
WINSRC += $(WINCURSESSRC)
|
||||
WINOBJ0 += $(WINCURSESOBJ)
|
||||
endif
|
||||
|
||||
@@ -22,6 +22,8 @@ extern char erase_char, kill_char;
|
||||
|
||||
extern long curs_mesg_suppress_seq; /* from cursmesg.c */
|
||||
extern boolean curs_mesg_no_suppress; /* ditto */
|
||||
extern int mesg_mixed;
|
||||
extern glyph_info mesg_gi;
|
||||
|
||||
/* stubs for curses_procs{} */
|
||||
#ifdef POSITIONBAR
|
||||
@@ -70,7 +72,7 @@ struct window_procs curses_procs = {
|
||||
curses_destroy_nhwindow,
|
||||
curses_curs,
|
||||
curses_putstr,
|
||||
genl_putmixed,
|
||||
curses_putmixed,
|
||||
curses_display_file,
|
||||
curses_start_menu,
|
||||
curses_add_menu,
|
||||
@@ -561,6 +563,19 @@ curses_putstr(winid wid, int attr, const char *text)
|
||||
curs_mesg_no_suppress = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
curses_putmixed(winid window, int attr, const char *str)
|
||||
{
|
||||
if (window == WIN_MESSAGE) {
|
||||
str = mixed_to_glyphinfo(str, &mesg_gi);
|
||||
mesg_mixed = 1;
|
||||
}
|
||||
/* now send it to the normal putstr */
|
||||
curses_putstr(window, attr, str);
|
||||
if (window == WIN_MESSAGE)
|
||||
mesg_mixed = 0;
|
||||
}
|
||||
|
||||
/* Display the file named str. Complain about missing files
|
||||
iff complain is TRUE.
|
||||
*/
|
||||
|
||||
@@ -26,10 +26,13 @@ long curs_mesg_suppress_seq = -1L;
|
||||
message triggers More>> for the previous message and the player responds
|
||||
with ESC; we need to avoid initiating suppression in that situation */
|
||||
boolean curs_mesg_no_suppress = FALSE;
|
||||
/* curses_putmixed() will place information in these next two */
|
||||
int mesg_mixed = 0;
|
||||
glyph_info mesg_gi;
|
||||
|
||||
/* Message window routines for curses interface */
|
||||
|
||||
/* Private declatations */
|
||||
/* Private declarations */
|
||||
|
||||
typedef struct nhpm {
|
||||
char *str; /* Message text */
|
||||
@@ -43,6 +46,7 @@ static void unscroll_window(winid wid);
|
||||
static void directional_scroll(winid wid, int nlines);
|
||||
static void mesg_add_line(const char *mline);
|
||||
static nhprev_mesg *get_msg_line(boolean reverse, int mindex);
|
||||
static int curscolor(int nhcolor, boolean *boldon);
|
||||
|
||||
static int turn_lines = 0;
|
||||
static int mx = 0;
|
||||
@@ -61,8 +65,10 @@ curses_message_win_puts(const char *message, boolean recursed)
|
||||
int height, width, border_space, linespace;
|
||||
char *tmpstr;
|
||||
WINDOW *win = curses_get_nhwin(MESSAGE_WIN);
|
||||
boolean bold, border = curses_window_has_border(MESSAGE_WIN);
|
||||
boolean bold, border = curses_window_has_border(MESSAGE_WIN),
|
||||
have_mixed_leadin = FALSE, adjustbold = FALSE;
|
||||
int message_length = (int) strlen(message);
|
||||
cchar_t mixed_leadin_cchar[2];
|
||||
|
||||
#if 0
|
||||
/*
|
||||
@@ -110,6 +116,36 @@ curses_message_win_puts(const char *message, boolean recursed)
|
||||
/* -2: for leading " " (if combining this message with preceding one) */
|
||||
if (mx > border_space)
|
||||
linespace -= 2;
|
||||
bold = (height > 1 && !last_messages);
|
||||
|
||||
if (mesg_mixed) {
|
||||
wchar_t w[2];
|
||||
int leadin_color;
|
||||
|
||||
leadin_color = curscolor(mesg_gi.gm.sym.color, &adjustbold);
|
||||
/*
|
||||
* curses_putmixed() skipped past the \GNNNNNNNN encoding
|
||||
* in the string, and filled in the mesg_gi glyphinfo. It
|
||||
* flagged that to us by setting mesg_mixed.
|
||||
*/
|
||||
|
||||
w[0] = (wchar_t) mesg_gi.ttychar;
|
||||
#ifdef ENHANCED_SYMBOLS
|
||||
if ((windowprocs.wincap2 & WC2_U_UTF8STR) && SYMHANDLING(H_UTF8)
|
||||
&& mesg_gi.gm.u) {
|
||||
/* FIXME: this won't work with all unicode values (32 bits -> 16
|
||||
* bits on Windows) */
|
||||
w[0] = (wchar_t) mesg_gi.gm.u->utf32ch;
|
||||
}
|
||||
#endif
|
||||
w[1] = L'\0';
|
||||
if (setcchar(mixed_leadin_cchar, w,
|
||||
(bold || adjustbold) ? A_BOLD : A_NORMAL,
|
||||
leadin_color, 0) == OK) {
|
||||
have_mixed_leadin = TRUE;
|
||||
message_length++; /* account for that additional column */
|
||||
}
|
||||
}
|
||||
|
||||
if (linespace < message_length) {
|
||||
if (my - border_space >= height - 1) {
|
||||
@@ -143,35 +179,76 @@ curses_message_win_puts(const char *message, boolean recursed)
|
||||
}
|
||||
}
|
||||
|
||||
bold = (height > 1 && !last_messages);
|
||||
if (bold)
|
||||
if (bold || adjustbold)
|
||||
curses_toggle_color_attr(win, NONE, A_BOLD, ON);
|
||||
|
||||
/* will this message fit as-is or do we need to split it? */
|
||||
if (mx == border_space && message_length > width - 3) {
|
||||
/* split needed */
|
||||
tmpstr = curses_break_str(message, (width - 3), 1);
|
||||
if (have_mixed_leadin) {
|
||||
mvwadd_wch(win, my, mx, mixed_leadin_cchar);
|
||||
++mx;
|
||||
message_length--;
|
||||
have_mixed_leadin = FALSE;
|
||||
mesg_mixed = 0;
|
||||
}
|
||||
mvwprintw(win, my, mx, "%s", tmpstr), mx += (int) strlen(tmpstr);
|
||||
/* one space to separate first part of message from rest [is this
|
||||
actually useful?] */
|
||||
if (mx < width)
|
||||
++mx;
|
||||
free(tmpstr);
|
||||
if (bold)
|
||||
if (bold || adjustbold)
|
||||
curses_toggle_color_attr(win, NONE, A_BOLD, OFF);
|
||||
tmpstr = curses_str_remainder(message, (width - 3), 1);
|
||||
curses_message_win_puts(tmpstr, TRUE);
|
||||
free(tmpstr);
|
||||
} else {
|
||||
if (have_mixed_leadin) {
|
||||
mvwadd_wch(win, my, mx, mixed_leadin_cchar);
|
||||
++mx;
|
||||
message_length--;
|
||||
have_mixed_leadin = FALSE;
|
||||
mesg_mixed = 0;
|
||||
}
|
||||
mvwprintw(win, my, mx, "%s", message), mx += message_length;
|
||||
if (bold)
|
||||
if (bold || adjustbold)
|
||||
curses_toggle_color_attr(win, NONE, A_BOLD, OFF);
|
||||
}
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
void
|
||||
curses_got_input(void)
|
||||
|
||||
static int
|
||||
curscolor(int nhcolor, boolean *boldon)
|
||||
{
|
||||
int curses_color;
|
||||
|
||||
*boldon = FALSE;
|
||||
if (nhcolor == 0) { /* make black fg visible */
|
||||
#ifdef USE_DARKGRAY
|
||||
if (iflags.wc2_darkgray) {
|
||||
if (COLORS > 16) {
|
||||
/* colorpair for black is already darkgray */
|
||||
} else { /* Use bold for a bright black */
|
||||
*boldon = TRUE;
|
||||
}
|
||||
} else
|
||||
#endif /* USE_DARKGRAY */
|
||||
nhcolor = CLR_BLUE;
|
||||
}
|
||||
curses_color = nhcolor + 1;
|
||||
if (COLORS < 16) {
|
||||
if (curses_color > 8 && curses_color < 17)
|
||||
curses_color -= 8;
|
||||
else if (curses_color > (17 + 16))
|
||||
curses_color -= 16;
|
||||
}
|
||||
return curses_color;
|
||||
}
|
||||
|
||||
void curses_got_input(void)
|
||||
{
|
||||
/* if messages are being suppressed, reenable them */
|
||||
curs_mesg_suppress_seq = -1L;
|
||||
|
||||
Reference in New Issue
Block a user