From: PatR Date: Tue, 26 Feb 2019 23:16:42 +0000 (-0800) Subject: curses run-time options X-Git-Tag: NetHack-3.6.2_Released~47^2^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1a028d11975e7099a95e47ac0ef9235c0d881c24;p=nethack curses run-time options This started out as an attempt to document the curses options in the Guidebook, but I didn't actually get that far. Instead, integrate the curses options better via more consistent WC/WC2 usage. This prevents 'guicolor' from showing up as a boolean option for non-curses interface in curses+other binary. For curses itself, let 'petattr' be set/reset via 'O'. Also, accept 'Dim' as a possible pet highlight attribute since it already handles all the other ordinary attributes. I'm not sure what leftline and rightline highlighting are supposed to do. They were missing for ncurses (or maybe they're misspelled for PDcurses?) but adding them didn't produce any visible effect (using TERM=xterm-256color on OSX with default font/character set). Not addressed: 1) general confusion about compile-time vs run-time option filtering; 2) curses pet highlighting only works if 'color' option is enabled. --- diff --git a/include/wincurs.h b/include/wincurs.h index cb43f3729..ddf026483 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -45,6 +45,12 @@ extern WINDOW *mapwin, *statuswin, *messagewin; /* Main windows */ # endif #endif +#if !defined(A_LEFTLINE) && defined(A_LEFT) +#define A_LEFTLINE A_LEFT +#endif +#if !defined(A_RIGHTLINE) && defined(A_RIGHT) +#define A_RIGHTLINE A_RIGHT +#endif typedef enum orient_type { @@ -158,6 +164,7 @@ extern void curses_rtrim(char *str); extern int curses_get_count(int first_digit); extern int curses_convert_attr(int attr); extern int curses_read_attrs(char *attrs); +extern char *curses_fmt_attrs(char *); extern int curses_convert_keys(int key); extern int curses_get_mouse(int *mousex, int *mousey, int *mod); diff --git a/src/options.c b/src/options.c index 64d8d9dea..2c5e463ef 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1551138503 2019/02/25 23:48:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.355 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1551222973 2019/02/26 23:16:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.356 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -29,6 +29,7 @@ NEARDATA struct instance_flags iflags; /* provide linkage */ #ifdef CURSES_GRAPHICS extern int curses_read_attrs(char *attrs); +extern char *curses_fmt_attrs(char *); #endif enum window_option_types { @@ -131,9 +132,9 @@ static struct Bool_Opt { { "flush", (boolean *) 0, FALSE, SET_IN_FILE }, #endif { "force_invmenu", &iflags.force_invmenu, FALSE, SET_IN_GAME }, - { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE }, + { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE }, /*WC2*/ { "goldX", &iflags.goldX, FALSE, SET_IN_GAME }, - { "guicolor", &iflags.wc2_guicolor, TRUE, SET_IN_GAME}, + { "guicolor", &iflags.wc2_guicolor, TRUE, SET_IN_GAME}, /*WC2*/ { "help", &flags.help, TRUE, SET_IN_GAME }, { "herecmd_menu", &iflags.herecmd_menu, FALSE, SET_IN_GAME }, { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/ @@ -209,7 +210,7 @@ static struct Bool_Opt { { "showscore", (boolean *) 0, FALSE, SET_IN_FILE }, #endif { "silent", &flags.silent, TRUE, SET_IN_GAME }, - { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE }, + { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE }, /*WC2*/ { "sortpack", &flags.sortpack, TRUE, SET_IN_GAME }, { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME }, { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/ @@ -228,7 +229,7 @@ static struct Bool_Opt { #ifdef DEBUG { "travel_debug", &iflags.trav_debug, FALSE, SET_IN_WIZGAME }, /*hack.c*/ #endif - { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE }, + { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE }, /*WC2*/ #ifdef WIN32 { "use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME }, /*WC*/ #else @@ -243,7 +244,7 @@ static struct Bool_Opt { { "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME }, { "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME }, { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME }, - { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME }, + { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME }, /*WC2*/ #ifdef ZEROCOMP { "zerocomp", &iflags.zerocomp, #if defined(COMPRESS) || defined(ZLIB_COMP) @@ -344,19 +345,18 @@ static struct Comp_Opt { #ifdef CHANGE_COLOR { "palette", #ifndef WIN32 - "palette (00c/880/-fff is blue/yellow/reverse white)", 15, - SET_IN_GAME }, + "palette (00c/880/-fff is blue/yellow/reverse white)", 15, SET_IN_GAME #else - "palette (adjust an RGB color in palette (color-R-G-B)", 15, - SET_IN_FILE }, + "palette (adjust an RGB color in palette (color-R-G-B)", 15, SET_IN_FILE #endif + }, #if defined(MAC) { "hicolor", "same as palette, only order is reversed", 15, SET_IN_FILE }, #endif #endif { "paranoid_confirmation", "extra prompting in certain situations", 28, SET_IN_GAME }, - { "petattr", "attributes for highlighting pets", 12, SET_IN_FILE }, + { "petattr", "attributes for highlighting pets", 88, SET_IN_GAME }, { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME }, { "pickup_burden", "maximum burden picked up before prompt", 20, SET_IN_GAME }, @@ -409,6 +409,9 @@ static struct Comp_Opt { #endif { "suppress_alert", "suppress alerts about version-specific features", 8, SET_IN_GAME }, + /* term_cols,term_rows -> WC2_TERM_SIZE (6: room to format 1..32767) */ + { "term_cols", "number of columns", 6, SET_IN_FILE }, /*WC2*/ + { "term_rows", "number of rows", 6, SET_IN_FILE }, /*WC2*/ { "tile_width", "width of tiles", 20, DISP_IN_GAME }, /*WC*/ { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/ { "tile_file", "name of tile file", 70, DISP_IN_GAME }, /*WC*/ @@ -430,6 +433,7 @@ static struct Comp_Opt { { "whatis_filter", "filter coordinate locations when targeting next or previous", 1, SET_IN_GAME }, + { "windowborders", "1 (on), 2 (off), 3 (auto)", 9, DISP_IN_GAME }, /*WC2*/ { "windowcolors", "the foreground/background colors of windows", /*WC*/ 80, DISP_IN_GAME }, { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, @@ -3325,6 +3329,7 @@ boolean tinitial, tfrom_file; return retval; } #endif /* VIDEOSHADES */ + #ifdef MSDOS #ifdef NO_TERMS /* video:string -- must be after longer tests */ @@ -3447,8 +3452,8 @@ boolean tinitial, tfrom_file; if (negated) { bad_negation(fullname, FALSE); return FALSE; - } else { #if defined(WIN32) + } else { op = string_for_opt(opts, 0); if (!op) return FALSE; @@ -3593,29 +3598,34 @@ boolean tinitial, tfrom_file; } return retval; } + #ifdef CURSES_GRAPHICS /* WINCAP2 - * term_cols:amount */ + * term_cols:amount or term_rows:amount */ fullname = "term_cols"; - if (match_optname(opts, fullname, sizeof "term_cols" - 1, TRUE)) { - op = string_for_opt(opts, negated); - iflags.wc2_term_cols = atoi(op); - if (negated) { - bad_negation(fullname, FALSE); - return FALSE; - } - return retval; - } + if (match_optname(opts, fullname, 8, TRUE) + /* alternate spelling */ + || match_optname(opts, "term_columns", 9, TRUE) + /* different option but identical handlng */ + || (fullname = "term_rows", match_optname(opts, fullname, 8, TRUE))) { + long ltmp; - /* WINCAP2 - * term_rows:amount */ - fullname = "term_rows"; - if (match_optname(opts, fullname, sizeof "term_rows" - 1, TRUE)) { op = string_for_opt(opts, negated); - iflags.wc2_term_rows = atoi(op); + ltmp = atol(op); if (negated) { bad_negation(fullname, FALSE); - return FALSE; + retval = FALSE; + + /* this just checks atol() sanity, not logical window size sanity */ + } else if (ltmp <= 0L || ltmp >= (long) LARGEST_INT) { + config_error_add("Invalid %s: %ld", fullname, ltmp); + retval = FALSE; + + } else { + if (!strcmp(fullname, "term_rows")) + iflags.wc2_term_rows = (int) ltmp; + else /* !strcmp(fullname, "term_cols") */ + iflags.wc2_term_cols = (int) ltmp; } return retval; } @@ -3625,22 +3635,31 @@ boolean tinitial, tfrom_file; fullname = "petattr"; if (match_optname(opts, fullname, sizeof "petattr" - 1, TRUE)) { op = string_for_opt(opts, negated); - if (op && !negated) { + if (op && negated) { + bad_negation(fullname, TRUE); + retval = FALSE; + } else if (op) { #ifdef CURSES_GRAPHICS - iflags.wc2_petattr = curses_read_attrs(op); - if (!curses_read_attrs(op)) { + int itmp = curses_read_attrs(op); + + if (itmp == -1) { config_error_add("Unknown %s parameter '%s'", fullname, opts); - return FALSE; - } + retval = FALSE; + } else + iflags.wc2_petattr = itmp; #else /* non-curses windowports will not use this flag anyway * but the above will not compile if we don't have curses. * Just set it to a sensible default: */ - iflags.wc2_petattr = ATR_INVERSE + iflags.wc2_petattr = ATR_INVERSE; #endif } else if (negated) { - bad_negation(fullname, TRUE); - return FALSE; + iflags.wc2_petattr = ATR_NONE; + } + if (retval) { + iflags.hilite_pet = (iflags.wc2_petattr != ATR_NONE); + if (!initial) + need_redraw = TRUE; } return retval; } @@ -3648,28 +3667,31 @@ boolean tinitial, tfrom_file; /* WINCAP2 * windowborders:n */ fullname = "windowborders"; - if (match_optname(opts, fullname, sizeof "windowborders" - 1, TRUE)) { + if (match_optname(opts, fullname, 10, TRUE)) { op = string_for_opt(opts, negated); if (negated && op) { bad_negation(fullname, TRUE); - return FALSE; + retval = FALSE; } else { + int itmp; + if (negated) - iflags.wc2_windowborders = 2; /* Off */ + itmp = 2; /* Off */ else if (!op) - iflags.wc2_windowborders = 1; /* On */ - else /* Value supplied */ - iflags.wc2_windowborders = atoi(op); - if ((iflags.wc2_windowborders > 3) - || (iflags.wc2_windowborders < 1)) { - iflags.wc2_windowborders = 0; - config_error_add("Badoption - windowborders %s.", opts); - return FALSE; + itmp = 1; /* On */ + else /* Value supplied; expect 1 (on), 2 (off), or 3 (auto) */ + itmp = atoi(op); + + if (itmp < 1 || itmp > 3) { + config_error_add("Invalid %s: %s.", fullname, opts); + retval = FALSE; + } else { + iflags.wc2_windowborders = itmp; } } return retval; } -#endif +#endif /* CURSES_GRAPHICS */ /* menustyle:traditional or combination or full or partial */ fullname = "menustyle"; @@ -5592,6 +5614,18 @@ char *buf; if (flags.paranoia_bits & paranoia[i].flagmask) Sprintf(eos(tmpbuf), " %s", paranoia[i].argname); Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none"); + } else if (!strcmp(optname, "petattr")) { +#ifdef CURSES_GRAPHICS + if (WINDOWPORT("curses")) { + char tmpbuf[QBUFSZ]; + + Strcpy(buf, curses_fmt_attrs(tmpbuf)); + } else +#endif + if (iflags.wc2_petattr != 0) + Sprintf(buf, "0x%08x", iflags.wc2_petattr); + else + Strcpy(buf, defopt); } else if (!strcmp(optname, "pettype")) { Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" : (preferred_pet == 'd') ? "dog" @@ -5674,7 +5708,6 @@ char *buf; symset[PRIMARY].name ? symset[PRIMARY].name : "default"); if (currentgraphics == PRIMARY && symset[PRIMARY].name) Strcat(buf, ", active"); -#ifdef CURSES_GRAPHICS } else if (!strcmp(optname, "term_cols")) { if (iflags.wc2_term_cols) Sprintf(buf, "%d", iflags.wc2_term_cols); @@ -5682,10 +5715,9 @@ char *buf; Strcpy(buf, defopt); } else if (!strcmp(optname, "term_rows")) { if (iflags.wc2_term_rows) - Sprintf(buf, "%d",iflags.wc2_term_rows); + Sprintf(buf, "%d", iflags.wc2_term_rows); else Strcpy(buf, defopt); -#endif } else if (!strcmp(optname, "tile_file")) { Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt); @@ -6433,9 +6465,11 @@ static struct wc_Opt wc2_options[] = { { "status hilite rules", WC2_HILITE_STATUS }, /* statushilites doesn't have its own bit */ { "statushilites", WC2_HILITE_STATUS }, -#ifdef CURSES_GRAPHICS - {"windowborders", WC2_WINDOWBORDERS}, -#endif + { "term_cols", WC2_TERM_SIZE }, + { "term_rows", WC2_TERM_SIZE }, + { "petattr", WC2_PETATTR }, + { "guicolor", WC2_GUICOLOR }, + { "windowborders", WC2_WINDOWBORDERS }, { (char *) 0, 0L } }; diff --git a/win/curses/cursinit.c b/win/curses/cursinit.c index 5f53df4ed..1cdc62a18 100644 --- a/win/curses/cursinit.c +++ b/win/curses/cursinit.c @@ -835,11 +835,15 @@ curses_init_options() iflags.wc2_windowborders = 3; /* Set to auto if not specified */ } - if (!iflags.wc2_petattr) { - iflags.wc2_petattr = A_REVERSE; - } else { /* Pet attribute specified, so hilite_pet should be true */ - + /* fix up pet highlighting */ + if (iflags.wc2_petattr == -1) /* shouldn't happen */ + iflags.wc2_petattr = A_NORMAL; + if (iflags.wc2_petattr != A_NORMAL) { + /* Pet attribute specified, so hilite_pet should be true */ iflags.hilite_pet = TRUE; + } else if (iflags.hilite_pet) { + /* pet highlighting specified, so don't leave petattr at A_NORMAL */ + iflags.wc2_petattr = A_REVERSE; } #ifdef NCURSES_MOUSE_VERSION diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index b4b3764d7..63bf2e03d 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -47,7 +47,7 @@ curses_read_char() ch = curses_convert_keys(ch); if (ch == 0) { - ch = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */ + ch = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */ } #if defined(ALT_0) && defined(ALT_9) /* PDCurses, maybe others */ if ((ch >= ALT_0) && (ch <= ALT_9)) { @@ -66,11 +66,11 @@ curses_read_char() #ifdef KEY_RESIZE /* Handle resize events via get_nh_event, not this code */ if (ch == KEY_RESIZE) { - ch = '\033'; /* NetHack doesn't know what to do with KEY_RESIZE */ + ch = '\033'; /* NetHack doesn't know what to do with KEY_RESIZE */ } #endif - if (counting && !isdigit(ch)) { /* Dismiss count window if necissary */ + if (counting && !isdigit(ch)) { /* Dismiss count window if necissary */ curses_count_window(NULL); curses_refresh_nethack_windows(); } @@ -249,7 +249,7 @@ curses_num_lines(const char *str, int width) if (last_space == 0) { /* No spaces found */ last_space = count - 1; } - for (count = (last_space + 1); (size_t) count < strlen(substr); count++) { + for (count = (last_space + 1); count < (int) strlen(substr); count++) { tmpstr[count - (last_space + 1)] = substr[count]; } tmpstr[count - (last_space + 1)] = '\0'; @@ -389,7 +389,7 @@ curses_str_remainder(const char *str, int width, int line_num) if (substr[count] == '\0') { break; } - for (count = (last_space + 1); (size_t) count < strlen(substr); count++) { + for (count = (last_space + 1); count < (int) strlen(substr); count++) { tmpstr[count - (last_space + 1)] = substr[count]; } tmpstr[count - (last_space + 1)] = '\0'; @@ -682,44 +682,87 @@ curses_convert_attr(int attr) /* Map letter attributes from a string to bitmask. Return mask on -success, or 0 if not found */ + success (might be 0), or -1 if not found. */ int curses_read_attrs(char *attrs) { int retattr = 0; - if (strchr(attrs, 'b') || strchr(attrs, 'B')) { - retattr = retattr | A_BOLD; - } - if (strchr(attrs, 'i') || strchr(attrs, 'I')) { - retattr = retattr | A_REVERSE; - } - if (strchr(attrs, 'u') || strchr(attrs, 'U')) { - retattr = retattr | A_UNDERLINE; - } - if (strchr(attrs, 'k') || strchr(attrs, 'K')) { - retattr = retattr | A_BLINK; - } + if (!attrs || !*attrs) + return A_NORMAL; + + if (strchr(attrs, 'b') || strchr(attrs, 'B')) + retattr |= A_BOLD; + if (strchr(attrs, 'i') || strchr(attrs, 'I')) /* inverse */ + retattr |= A_REVERSE; + if (strchr(attrs, 'u') || strchr(attrs, 'U')) + retattr |= A_UNDERLINE; + if (strchr(attrs, 'k') || strchr(attrs, 'K')) + retattr |= A_BLINK; + if (strchr(attrs, 'd') || strchr(attrs, 'D')) + retattr |= A_DIM; #ifdef A_ITALIC - if (strchr(attrs, 't') || strchr(attrs, 'T')) { - retattr = retattr | A_ITALIC; - } + if (strchr(attrs, 't') || strchr(attrs, 'T')) + retattr |= A_ITALIC; +#endif +#ifdef A_LEFTLINE + if (strchr(attrs, 'l') || strchr(attrs, 'L')) + retattr |= A_LEFTLINE; #endif #ifdef A_RIGHTLINE - if (strchr(attrs, 'r') || strchr(attrs, 'R')) { - retattr = retattr | A_RIGHTLINE; - } + if (strchr(attrs, 'r') || strchr(attrs, 'R')) + retattr |= A_RIGHTLINE; #endif -#ifdef A_LEFTLINE - if (strchr(attrs, 'l') || strchr(attrs, 'L')) { - retattr = retattr | A_LEFTLINE; + if (retattr == 0) { + /* still default; check for none/normal */ + if (strchr(attrs, 'n') || strchr(attrs, 'N')) + retattr = A_NORMAL; + else + retattr = -1; /* error */ } -#endif - return retattr; } +/* format iflags.wc2_petattr into "+a+b..." for set bits a, b, ... + (used by core's 'O' command; return value points past leading '+') */ +char * +curses_fmt_attrs(outbuf) +char *outbuf; +{ + int attr = iflags.wc2_petattr; + + outbuf[0] = '\0'; + if (attr == A_NORMAL) { + Strcpy(outbuf, "+N(None)"); + } else { + if (attr & A_BOLD) + Strcat(outbuf, "+B(Bold)"); + if (attr & A_REVERSE) + Strcat(outbuf, "+I(Inverse)"); + if (attr & A_UNDERLINE) + Strcat(outbuf, "+U(Underline)"); + if (attr & A_BLINK) + Strcat(outbuf, "+K(blinK)"); + if (attr & A_DIM) + Strcat(outbuf, "+D(Dim)"); +#ifdef A_ITALIC + if (attr & A_ITALIC) + Strcat(outbuf, "+T(iTalic)"); +#endif +#ifdef A_LEFTLINE + if (attr & A_LEFTLINE) + Strcat(outbuf, "+L(Left line)"); +#endif +#ifdef A_RIGHTLINE + if (attr & A_RIGHTLINE) + Strcat(outbuf, "+R(Right line)"); +#endif + } + if (!*outbuf) + Sprintf(outbuf, "+unknown [%d]", attr); + return &outbuf[1]; +} /* Convert special keys into values that NetHack can understand. Currently this is limited to arrow keys, but this may be expanded. */ @@ -827,7 +870,7 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) #ifdef NCURSES_MOUSE_VERSION MEVENT event; - if (getmouse(&event) == OK) { /* When the user clicks left mouse button */ + if (getmouse(&event) == OK) { /* When the user clicks left mouse button */ if (event.bstate & BUTTON1_CLICKED) { /* See if coords are in map window & convert coords */ if (wmouse_trafo(mapwin, &event.y, &event.x, TRUE)) { diff --git a/win/curses/cursmisc.h b/win/curses/cursmisc.h index 364901267..392d67d11 100644 --- a/win/curses/cursmisc.h +++ b/win/curses/cursmisc.h @@ -27,6 +27,7 @@ void curses_rtrim(char *str); int curses_get_count(int first_digit); int curses_convert_attr(int attr); int curses_read_attrs(char *attrs); +char *curses_fmt_attrs(char *); int curses_convert_keys(int key); int curses_get_mouse(int *mousex, int *mousey, int *mod);