diff --git a/.gitignore b/.gitignore index 4f50d101..4fab1f25 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ dat/*.lev dat/data dat/dungeon dat/dungeon.pdf +dat/nhdat dat/options dat/oracles dat/quest.dat @@ -28,6 +29,7 @@ src/vis_tab.c util/dgn_comp util/dgn_lex.c util/dgn_yacc.c +util/dlb util/lev_comp util/lev_lex.c util/lev_yacc.c diff --git a/include/decl.h b/include/decl.h index 2cc539b5..c1286cdf 100644 --- a/include/decl.h +++ b/include/decl.h @@ -479,6 +479,7 @@ E struct _plinemsg *pline_msg; #define MSGTYP_NOREP 1 #define MSGTYP_NOSHOW 2 #define MSGTYP_STOP 3 +#define MSGTYP_ALERT 4 /* FIXME: These should be integrated into objclass and permonst structs, diff --git a/include/extern.h b/include/extern.h index e3c66040..6e0eeaac 100644 --- a/include/extern.h +++ b/include/extern.h @@ -616,6 +616,7 @@ E void FDECL(make_grave, (int,int,const char *)); /* ### exper.c ### */ +E long FDECL(newuexp, (int)); E int FDECL(experience, (struct monst *,int)); E void FDECL(more_experienced, (int,int)); E void FDECL(losexp, (const char *)); diff --git a/include/flag.h b/include/flag.h index 3819c84a..efb09173 100644 --- a/include/flag.h +++ b/include/flag.h @@ -157,7 +157,8 @@ struct flag { struct instance_flags { boolean cbreak; /* in cbreak mode, rogue format */ #ifdef CURSES_GRAPHICS - boolean cursesgraphics; /* Use portable curses extended characters */ + boolean classic_status; /* What kind of horizontal statusbar to use */ + boolean cursesgraphics; /* Use portable curses extended characters */ #endif boolean DECgraphics; /* use DEC VT-xxx extended character set */ boolean echo; /* 1 to echo characters */ @@ -342,6 +343,9 @@ struct instance_flags { #ifdef REALTIME_ON_BOTL boolean showrealtime; /* show actual elapsed time */ #endif + boolean msg_is_alert; /* suggest windowport should grab player's attention + * and request acknowlegement */ + }; /* diff --git a/include/unixconf.h b/include/unixconf.h index f7cdcf77..905d7bb8 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -102,8 +102,9 @@ * If you want the static parts of your playground on a read-only file * system, define VAR_PLAYGROUND to be where the variable parts are kept. */ +#ifndef VAR_PLAYGROUND #define VAR_PLAYGROUND "/nh343/var" - +#endif /* * Define DEF_PAGER as your default pager, e.g. "/bin/cat" or "/usr/ucb/more" diff --git a/include/wincurs.h b/include/wincurs.h index 3db6c5a2..edf44536 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -21,6 +21,7 @@ boolean counting; /* Count window is active */ #define NONE -1 #define KEY_ESC 0x1b #define DIALOG_BORDER_COLOR CLR_MAGENTA +#define ALERT_BORDER_COLOR CLR_RED #define SCROLLBAR_COLOR CLR_MAGENTA #define SCROLLBAR_BACK_COLOR CLR_BLACK #define HIGHLIGHT_COLOR CLR_WHITE @@ -30,7 +31,8 @@ boolean counting; /* Count window is active */ #define MESSAGE_WIN 1 #define STATUS_WIN 2 #define MAP_WIN 3 -#define NHWIN_MAX 4 +#define INV_WIN 4 +#define NHWIN_MAX 5 #define MESG_HISTORY_MAX 200 #if !defined(__APPLE__) || !defined(NCURSES_VERSION) # define USE_DARKGRAY /* Allow "bright" black; delete if not visible */ @@ -178,6 +180,10 @@ extern void curses_puts(winid wid, int attr, const char *text); extern void curses_clear_nhwin(winid wid); +extern void curses_alert_win_border(winid wid, boolean onoff); + +extern void curses_alert_main_borders(boolean onoff); + extern void curses_draw_map(int sx, int sy, int ex, int ey); extern boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, @@ -237,8 +243,10 @@ extern int curses_character_input_dialog(const char *prompt, const char *choices extern int curses_ext_cmd(void); extern void curses_create_nhmenu(winid wid); - -extern void curses_add_nhmenu_item(winid wid, const ANY_P *identifier, +#ifdef MENU_COLOR +extern boolean get_menu_coloring(char *, int *, int *); +#endif +extern void curses_add_nhmenu_item(winid wid, int glyph, const ANY_P *identifier, CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str, BOOLEAN_P presel); @@ -253,10 +261,14 @@ extern void curses_del_menu(winid wid); /* cursstat.c */ -extern void curses_update_stats(boolean redraw); - +extern attr_t curses_color_attr(int nh_color, int bg_color); +extern void curses_update_stats(void); extern void curses_decrement_highlight(void); +/* cursinvt.c */ + +extern void curses_update_inv(void); +extern void curses_add_inv(int, int, CHAR_P, attr_t, const char *); /* cursinit.c */ @@ -279,10 +291,14 @@ extern void curses_cleanup(void); extern void curses_message_win_puts(const char *message, boolean recursed); +extern int curses_block(boolean require_tab); /* for MSGTYPE=STOP */ + extern int curses_more(void); extern void curses_clear_unhighlight_message_window(void); +extern void curses_message_win_getline(const char *prompt, char *answer, int buffer); + extern void curses_last_messages(void); extern void curses_init_mesg_history(void); diff --git a/src/display.c b/src/display.c index f2bf94f8..66d17bde 100644 --- a/src/display.c +++ b/src/display.c @@ -1324,6 +1324,7 @@ row_refresh(start,stop,y) for (x = start; x <= stop; x++) if (gbuf[y][x].glyph != cmap_to_glyph(S_stone)) print_glyph(WIN_MAP,x,y,gbuf[y][x].glyph); + display_nhwindow(WIN_MAP,FALSE); } void diff --git a/src/end.c b/src/end.c index 80e0005c..2e51eaa5 100644 --- a/src/end.c +++ b/src/end.c @@ -169,14 +169,15 @@ dump_init () char new_dump_fn[512]; Sprintf(new_dump_fn, "%s", dump_format_str(dump_fn)); - dump_fp = fopen(new_dump_fn, "w"); -#ifdef UNIX - chmod(new_dump_fn, dumpmode); -#endif + dump_fp = fopen (new_dump_fn, "w"); if (!dump_fp) { pline("Can't open %s for output.", new_dump_fn); pline("Dump file not created."); + return; } +#if defined(UNIX) + chmod(new_dump_fn, dumpmode); +#endif } } @@ -861,19 +862,21 @@ int how; program_state.something_worth_saving = 0; #ifdef DUMP_LOG /* D: Grab screen dump right here */ - if (dump_fn[0]) { - dump_init(); - Sprintf(pbuf, "%s, %s %s %s %s", plname, - aligns[1 - u.ualign.type].adj, - genders[flags.female].adj, - urace.adj, - (flags.female && urole.name.f)? - urole.name.f : urole.name.m); - dump("", pbuf); - /* D: Add a line for clearance from the screen dump */ - dump("", ""); - dump_screen(0); - } + if (dump_fn[0]) { + dump_init(); + if (dump_fp) { + Sprintf(pbuf, "%s, %s %s %s %s", plname, + aligns[1 - u.ualign.type].adj, + genders[flags.female].adj, + urace.adj, + (flags.female && urole.name.f)? + urole.name.f : urole.name.m); + dump("", pbuf); + /* D: Add a line for clearance from the screen dump */ + dump("", ""); + dump_screen(0); + } + } #endif /* DUMP_LOG */ #ifdef WHEREIS_FILE diff --git a/src/exper.c b/src/exper.c index 649f1c68..d3b95a63 100644 --- a/src/exper.c +++ b/src/exper.c @@ -4,10 +4,9 @@ #include "hack.h" -STATIC_DCL long FDECL(newuexp, (int)); STATIC_DCL int FDECL(enermod, (int)); -STATIC_OVL long +long newuexp(lev) int lev; { diff --git a/src/files.c b/src/files.c index d0e356ec..8fed4eec 100644 --- a/src/files.c +++ b/src/files.c @@ -1998,6 +1998,8 @@ char *tmp_levels; else if (!strcasecmp("noshow", msgtype)) typ = MSGTYP_NOSHOW; else if (!strcasecmp("more", msgtype)) typ = MSGTYP_STOP; else if (!strcasecmp("stop", msgtype)) typ = MSGTYP_STOP; + /* 'alert' will fallback to 'stop' behaviour if windowport does not support it */ + else if (!strcasecmp("alert", msgtype)) typ = MSGTYP_ALERT; if ((typ != MSGTYP_NORMAL) || !strcasecmp("show", msgtype)) { msgpline_add(typ, pattern); } diff --git a/src/mthrowu.c b/src/mthrowu.c index 953e01d4..8582e9a2 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -421,21 +421,22 @@ m_throw(mon, x, y, dx, dy, range, obj) (void) drop_throw(singleobj, hitu, u.ux, u.uy); break; } - } else if (!range /* reached end of path */ - /* missile hits edge of screen */ - || !isok(bhitpos.x+dx,bhitpos.y+dy) - /* missile hits the wall */ - || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) - /* missile hit closed door */ - || closed_door(bhitpos.x+dx, bhitpos.y+dy) - /* missile might hit iron bars */ - || (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS && - hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0)) + } + if (!range /* reached end of path */ + /* missile hits edge of screen */ + || !isok(bhitpos.x+dx,bhitpos.y+dy) + /* missile hits the wall */ + || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) + /* missile hit closed door */ + || closed_door(bhitpos.x+dx, bhitpos.y+dy) + /* missile might hit iron bars */ + || (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS && + hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0)) #ifdef SINKS - /* Thrown objects "sink" */ - || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) + /* Thrown objects "sink" */ + || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) #endif - ) { + ) { if (singleobj) /* hits_bars might have destroyed it */ (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); break; diff --git a/src/options.c b/src/options.c index 57b81653..99c42a50 100644 --- a/src/options.c +++ b/src/options.c @@ -79,6 +79,9 @@ static struct Bool_Opt {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME}, #else {"checkspace", (boolean *)0, FALSE, SET_IN_FILE}, +#endif +#ifdef CURSES_GRAPHICS + {"classic_status", &iflags.classic_status, TRUE, SET_IN_FILE}, #endif {"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME}, # if defined(MICRO) || defined(WIN32) || defined(CURSES_GRAPHICS) @@ -637,6 +640,7 @@ initoptions() #ifdef SORTLOOT iflags.sortloot = 'n'; #endif + iflags.msg_is_alert = FALSE; /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */ (void)memcpy((genericptr_t)flags.inv_order, diff --git a/src/pline.c b/src/pline.c index a7b15645..283c4fe0 100644 --- a/src/pline.c +++ b/src/pline.c @@ -218,7 +218,15 @@ pline VA_DECL(const char *, line) putstr(WIN_MESSAGE, 0, line); strncpy(prevmsg, line, BUFSZ); - if (typ == MSGTYP_STOP) display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */ + switch (typ) { + case MSGTYP_ALERT: + iflags.msg_is_alert = TRUE; /* */ + /* FT */ + case MSGTYP_STOP: + display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */ + break; + } + iflags.msg_is_alert = FALSE; } /*VARARGS1*/ diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 49fb111c..fc5028a6 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -177,9 +177,9 @@ WINTTYOBJ = getline.o termcap.o topl.o wintty.o tile.o WINCURSESSRC = ../win/curses/cursmain.c ../win/curses/curswins.c \ ../win/curses/cursmisc.c ../win/curses/cursdial.c \ ../win/curses/cursstat.c ../win/curses/cursinit.c \ - ../win/curses/cursmesg.c + ../win/curses/cursmesg.c ../win/curses/cursinvt.c WINCURSESOBJ = cursmain.o curswins.o cursmisc.o cursdial.o cursstat.o \ - cursinit.o cursmesg.o + cursinit.o cursmesg.o cursinvt.o # # # files for an X11 port @@ -635,6 +635,9 @@ cursinit.o: ../win/curses/cursinit.c $(HACK_H) ../include/wincurs.h \ cursmesg.o: ../win/curses/cursmesg.c $(HACK_H) ../include/wincurs.h \ ../win/curses/cursmesg.h $(CC) $(CFLAGS) -c ../win/curses/cursmesg.c +cursinvt.o: ../win/curses/cursinvt.c $(HACK_H) ../include/wincurs.h \ + ../win/curses/cursinvt.h + $(CC) $(CFLAGS) -c ../win/curses/cursinvt.c Window.o: ../win/X11/Window.c ../include/xwindowp.h ../include/xwindow.h \ $(CONFIG_H) $(CC) $(CFLAGS) -c ../win/X11/Window.c diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index d155dd3b..329b122d 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" @@ -10,40 +12,38 @@ /* Private declarations */ -typedef struct nhmi -{ - winid wid; /* NetHack window id */ - anything identifier; /* Value returned if item selected */ - CHAR_P accelerator; /* Character used to select item from menu */ - CHAR_P group_accel; /* Group accelerator for menu item, if any */ - int attr; /* Text attributes for item */ - const char *str; /* Text of menu item */ - BOOLEAN_P presel; /* Whether menu item should be preselected */ - boolean selected; /* Whether item is currently selected */ - int page_num; /* Display page number for entry */ - int line_num; /* Line number on page where entry begins */ - int num_lines; /* Number of lines entry uses on page */ - int count; /* Count for selected item */ - struct nhmi *prev_item; /* Pointer to previous entry */ - struct nhmi *next_item; /* Pointer to next entry */ +typedef struct nhmi { + winid wid; /* NetHack window id */ + int glyph; /* Menu glyphs */ + anything identifier; /* Value returned if item selected */ + CHAR_P accelerator; /* Character used to select item from menu */ + CHAR_P group_accel; /* Group accelerator for menu item, if any */ + int attr; /* Text attributes for item */ + const char *str; /* Text of menu item */ + BOOLEAN_P presel; /* Whether menu item should be preselected */ + boolean selected; /* Whether item is currently selected */ + int page_num; /* Display page number for entry */ + int line_num; /* Line number on page where entry begins */ + int num_lines; /* Number of lines entry uses on page */ + int count; /* Count for selected item */ + struct nhmi *prev_item; /* Pointer to previous entry */ + struct nhmi *next_item; /* Pointer to next entry */ } nhmenu_item; -typedef struct nhm -{ - winid wid; /* NetHack window id */ - const char *prompt; /* Menu prompt text */ - nhmenu_item *entries; /* Menu entries */ - int num_entries; /* Number of menu entries */ - int num_pages; /* Number of display pages for entry */ - int height; /* Window height of menu */ - int width; /* Window width of menu */ - boolean reuse_accels; /* Non-unique accelerators per page */ - struct nhm *prev_menu; /* Pointer to previous entry */ - struct nhm *next_menu; /* Pointer to next entry */ +typedef struct nhm { + winid wid; /* NetHack window id */ + const char *prompt; /* Menu prompt text */ + nhmenu_item *entries; /* Menu entries */ + int num_entries; /* Number of menu entries */ + int num_pages; /* Number of display pages for entry */ + int height; /* Window height of menu */ + int width; /* Window width of menu */ + boolean reuse_accels; /* Non-unique accelerators per page */ + struct nhm *prev_menu; /* Pointer to previous entry */ + struct nhm *next_menu; /* Pointer to next entry */ } nhmenu; -typedef enum menu_op_type -{ +typedef enum menu_op_type { SELECT, DESELECT, INVERT @@ -54,28 +54,17 @@ extern struct menucoloring *menu_colorings; #endif static nhmenu *get_menu(winid wid); - static char menu_get_accel(boolean first); - static void menu_determine_pages(nhmenu *menu); - static boolean menu_is_multipage(nhmenu *menu, int width, int height); - static void menu_win_size(nhmenu *menu); - -static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num); - -static int menu_get_selections(WINDOW *win, nhmenu *menu, int how); - -static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operation); - -static int menu_operation(WINDOW *win, nhmenu *menu, menu_op operation, - int page_num); - +static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num); +static int menu_get_selections(WINDOW * win, nhmenu *menu, int how); +static void menu_select_deselect(WINDOW * win, nhmenu_item *item, + menu_op operation); +static int menu_operation(WINDOW * win, nhmenu *menu, menu_op operation, + int page_num); static void menu_clear_selections(nhmenu *menu); - -static boolean get_menu_coloring(char *str, int *color, int *attr); - static int menu_max_height(void); static nhmenu *nhmenus = NULL; /* NetHack menu array */ @@ -83,7 +72,8 @@ static nhmenu *nhmenus = NULL; /* NetHack menu array */ /* Get a line of text from the player, such as asking for a character name or a wish */ -void curses_line_input_dialog(const char *prompt, char *answer, int buffer) +void +curses_line_input_dialog(const char *prompt, char *answer, int buffer) { int map_height, map_width, maxwidth, remaining_buf, winx, winy, count; WINDOW *askwin, *bwin; @@ -95,61 +85,52 @@ void curses_line_input_dialog(const char *prompt, char *answer, int buffer) maxwidth = term_cols - 2; - if (iflags.window_inited) - { + if (iflags.window_inited) { + if (!iflags.wc_popup_dialog) + return curses_message_win_getline(prompt, answer, buffer); curses_get_window_size(MAP_WIN, &map_height, &map_width); if ((prompt_width + 2) > map_width) maxwidth = map_width - 2; } - - if (prompt_width > maxwidth) - { + + if (prompt_width > maxwidth) { prompt_height = curses_num_lines(prompt, maxwidth); height = prompt_height; prompt_width = maxwidth; tmpstr = curses_break_str(prompt, maxwidth, prompt_height); remaining_buf = buffer - (strlen(tmpstr) - 1); - if (remaining_buf > 0 ) - { + if (remaining_buf > 0) { height += (remaining_buf / prompt_width); - if ((remaining_buf % prompt_width) > 0) - { + if ((remaining_buf % prompt_width) > 0) { height++; } } } - - if (iflags.window_inited) - { + + if (iflags.window_inited) { bwin = curses_create_window(prompt_width, height, UP); wrefresh(bwin); getbegyx(bwin, winy, winx); askwin = newwin(height, prompt_width, winy + 1, winx + 1); - } - else - { + } else { bwin = curses_create_window(prompt_width, height, CENTER); wrefresh(bwin); getbegyx(bwin, winy, winx); askwin = newwin(height, prompt_width, winy + 1, winx + 1); } - for (count = 0; count < prompt_height; count++) - { + for (count = 0; count < prompt_height; count++) { tmpstr = curses_break_str(prompt, maxwidth, count + 1); - if (count == (prompt_height - 1)) /* Last line */ - { + if (count == (prompt_height - 1)) { /* Last line */ mvwprintw(askwin, count, 0, "%s ", tmpstr); - } - else - { + } else { mvwaddstr(askwin, count, 0, tmpstr); } free(tmpstr); } - + echo(); curs_set(1); - wgetnstr(askwin, input, buffer-1); + wgetnstr(askwin, input, buffer - 1); curs_set(0); strcpy(answer, input); werase(bwin); @@ -161,7 +142,9 @@ void curses_line_input_dialog(const char *prompt, char *answer, int buffer) /* Get a single character response from the player, such as a y/n prompt */ -int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def) +int +curses_character_input_dialog(const char *prompt, const char *choices, + CHAR_P def) { WINDOW *askwin = NULL; int answer, count, maxwidth, map_height, map_width; @@ -173,82 +156,65 @@ int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_ boolean any_choice = FALSE; boolean accept_count = FALSE; - if (invent || (moves > 1)) - { + if (invent || (moves > 1)) { curses_get_window_size(MAP_WIN, &map_height, &map_width); - } - else - { + } else { map_height = term_rows; map_width = term_cols; } - + maxwidth = map_width - 2; - - if (choices != NULL) - { - for (count = 0; choices[count] != '\0'; count++) - { - if (choices[count] == '#') /* Accept a count */ - { + + if (choices != NULL) { + for (count = 0; choices[count] != '\0'; count++) { + if (choices[count] == '#') { /* Accept a count */ accept_count = TRUE; } } choicestr[0] = ' '; choicestr[1] = '['; - for (count = 0; choices[count] != '\0'; count++) - { - if (choices[count] == DOESCAPE) /* Escape */ - { + for (count = 0; choices[count] != '\0'; count++) { + if (choices[count] == DOESCAPE) { /* Escape */ break; } choicestr[count + 2] = choices[count]; } choicestr[count + 2] = ']'; - if (((def >= 'A') && (def <= 'Z')) || ((def >= 'a') && (def <= 'z'))) - { + if (((def >= 'A') && (def <= 'Z')) || ((def >= 'a') && (def <= 'z'))) { choicestr[count + 3] = ' '; choicestr[count + 4] = '('; choicestr[count + 5] = def; choicestr[count + 6] = ')'; choicestr[count + 7] = '\0'; - } - else /* No usable default choice */ - { + } else { /* No usable default choice */ + choicestr[count + 3] = '\0'; - def = '\0'; /* Mark as no default */ + def = '\0'; /* Mark as no default */ } strcpy(askstr, prompt); strcat(askstr, choicestr); - } - else - { + } else { strcpy(askstr, prompt); any_choice = TRUE; } - + prompt_width = strlen(askstr); - - if ((prompt_width + 2) > maxwidth) - { + + if ((prompt_width + 2) > maxwidth) { prompt_height = curses_num_lines(askstr, maxwidth); prompt_width = map_width - 2; } - if (iflags.wc_popup_dialog || curses_stupid_hack) - { + if (iflags.wc_popup_dialog || curses_stupid_hack) { askwin = curses_create_window(prompt_width, prompt_height, UP); - for (count = 0; count < prompt_height; count++) - { + for (count = 0; count < prompt_height; count++) { linestr = curses_break_str(askstr, maxwidth, count + 1); mvwaddstr(askwin, count + 1, 1, linestr); free(linestr); } - + wrefresh(askwin); - } - else - { + } else { linestr = curses_copy_of(askstr); pline("%s", linestr); free(linestr); @@ -257,90 +223,69 @@ int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_ curses_stupid_hack = 0; - while (1) - { + while (1) { answer = getch(); - if (answer == ERR) { - answer = def; - break; - } + if (answer == ERR) { + answer = def; + break; + } answer = curses_convert_keys(answer); - if (answer==KEY_ESC) - { - if (choices == NULL) - { + if (answer == KEY_ESC) { + if (choices == NULL) { break; } answer = def; - for (count = 0; choices[count] != '\0'; count++) - { - if (choices[count] == 'q') /* q is preferred over n */ - { + for (count = 0; choices[count] != '\0'; count++) { + if (choices[count] == 'q') { /* q is preferred over n */ answer = 'q'; - } - else if ((choices[count] == 'n') && answer != 'q') - { + } else if ((choices[count] == 'n') && answer != 'q') { answer = 'n'; } } break; - } - else if ((answer == '\n') || (answer == '\r') || - (answer == ' ')) - { - if ((choices != NULL) && (def != '\0')) - { + } else if ((answer == '\n') || (answer == '\r') || (answer == ' ')) { + if ((choices != NULL) && (def != '\0')) { answer = def; } break; } - - if (digit(answer)) - { - if (accept_count) - { - if (answer != '0') - { + + if (digit(answer)) { + if (accept_count) { + if (answer != '0') { yn_number = curses_get_count(answer - '0'); touchwin(askwin); refresh(); } - + answer = '#'; break; } } - - if (any_choice) - { + + if (any_choice) { break; } - - if (choices != NULL) - { - for (count = 0; count < strlen(choices); count++) - { - if (choices[count] == answer) - { + + if (choices != NULL) { + for (count = 0; count < strlen(choices); count++) { + if (choices[count] == answer) { break; } } - if (choices[count] == answer) - { + if (choices[count] == answer) { break; } } } - if (iflags.wc_popup_dialog) - { + if (iflags.wc_popup_dialog) { /* Kludge to make prompt visible after window is dismissed - when inputting a number */ - if (digit(answer)) - { + when inputting a number */ + if (digit(answer)) { linestr = curses_copy_of(askstr); pline("%s", linestr); free(linestr); @@ -348,9 +293,7 @@ int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_ } curses_destroy_win(askwin); - } - else - { + } else { curses_clear_unhighlight_message_window(); curs_set(0); } @@ -361,160 +304,160 @@ int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_ /* Return an extended command from the user */ -int curses_ext_cmd() +int +curses_ext_cmd() { int count, letter, prompt_width, startx, starty, winx, winy; - int messageh, messagew; + int messageh, messagew, maxlen = BUFSZ - 1; int ret = -1; char cur_choice[BUFSZ]; int matches = 0; - WINDOW *extwin = NULL; + WINDOW *extwin = NULL, *extwin2 = NULL; - if (iflags.extmenu) - { + if (iflags.extmenu) { return extcmd_via_menu(); } - if (iflags.wc_popup_dialog) /* Prompt in popup window */ - { - startx = 1; - starty = 1; - extwin = curses_create_window(25, 1, UP); - } - else - { + startx = 0; + starty = 0; + if (iflags.wc_popup_dialog) { /* Prompt in popup window */ + int x0, y0, w, h; /* bounding coords of popup */ + extwin2 = curses_create_window(25, 1, UP); + wrefresh(extwin2); + /* create window inside window to prevent overwriting of border */ + getbegyx(extwin2,y0,x0); + getmaxyx(extwin2,h,w); + extwin = newwin(1, w-2, y0+1, x0+1); + if (w - 4 < maxlen) maxlen = w - 4; + } else { curses_get_window_xy(MESSAGE_WIN, &winx, &winy); curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); - - if (curses_window_has_border(MESSAGE_WIN)) - { + + if (curses_window_has_border(MESSAGE_WIN)) { winx++; winy++; } - + winy += messageh - 1; - extwin = newwin(1, 25, winy, winx); - startx = 0; - starty = 0; + extwin = newwin(1, messagew-2, winy, winx); + if (messagew - 4 < maxlen) maxlen = messagew - 4; pline("#"); } cur_choice[0] = '\0'; - while (1) - { + while (1) { wmove(extwin, starty, startx); waddstr(extwin, "# "); wmove(extwin, starty, startx + 2); - curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, ON); waddstr(extwin, cur_choice); - curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, OFF); wmove(extwin, starty, strlen(cur_choice) + startx + 2); - wprintw(extwin, " ", cur_choice); + wprintw(extwin, " "); - if (matches == 1) - { + /* if we have an autocomplete command, AND it matches uniquely */ + if (matches == 1) { + curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, ON); wmove(extwin, starty, strlen(cur_choice) + startx + 2); - wprintw(extwin, "%s ", extcmdlist[ret].ef_txt - + strlen(cur_choice)); + wprintw(extwin, "%s", extcmdlist[ret].ef_txt + strlen(cur_choice)); + curses_toggle_color_attr(extwin, NONE, A_UNDERLINE, OFF); + mvwprintw(extwin, starty, + strlen(extcmdlist[ret].ef_txt) + 2, " "); } wrefresh(extwin); letter = getch(); - prompt_width = strlen(cur_choice); + prompt_width = strlen(cur_choice); matches = 0; - if (letter == DOESCAPE || letter == ERR) - { + if (letter == DOESCAPE || letter == ERR) { ret = -1; break; } - if ((letter == '\r') || (letter == '\n')) - { + if ((letter == '\r') || (letter == '\n')) { + if (ret == -1) { + for (count = 0; extcmdlist[count].ef_txt; count++) { + if (!strcasecmp(cur_choice, extcmdlist[count].ef_txt)) { + ret = count; + break; + } + } + } break; } - if ((letter == '\b') || (letter == KEY_BACKSPACE)) - { - if (prompt_width == 0) - { + if ((letter == '\b') || (letter == KEY_BACKSPACE)) { + if (prompt_width == 0) { ret = -1; break; - } - else - { + } else { cur_choice[prompt_width - 1] = '\0'; letter = '*'; prompt_width--; } } - - for (count = 0; extcmdlist[count].ef_txt; count++) - { - if (!extcmdlist[count].autocomplete) continue; - if (strlen(extcmdlist[count].ef_txt) > prompt_width) - { + if (letter != '*' && prompt_width < maxlen) { + cur_choice[prompt_width] = letter; + cur_choice[prompt_width + 1] = '\0'; + ret = -1; + } + for (count = 0; extcmdlist[count].ef_txt; count++) { + if (!extcmdlist[count].autocomplete) + continue; + if (strlen(extcmdlist[count].ef_txt) > prompt_width) { if (strncasecmp(cur_choice, extcmdlist[count].ef_txt, - prompt_width) == 0) - { + prompt_width) == 0) { if ((extcmdlist[count].ef_txt[prompt_width] == - lowc(letter)) || letter == '*') - { - if ((matches == 0) && (letter != '*')) - { + lowc(letter)) || letter == '*') { + if (matches == 0) { ret = count; - cur_choice[prompt_width] = letter; - cur_choice[prompt_width + 1] = '\0'; } matches++; } } } - } - } - + } + } + curses_destroy_win(extwin); + if (extwin2) curses_destroy_win(extwin2); return ret; } /* Initialize a menu from given NetHack winid */ -void curses_create_nhmenu(winid wid) +void +curses_create_nhmenu(winid wid) { nhmenu *new_menu = NULL; nhmenu *menuptr = nhmenus; nhmenu_item *menu_item_ptr = NULL; nhmenu_item *tmp_menu_item = NULL; - + new_menu = get_menu(wid); - - if (new_menu != NULL) - { + + if (new_menu != NULL) { /* Reuse existing menu, clearing out current entries */ menu_item_ptr = new_menu->entries; - - if (menu_item_ptr != NULL) - { - while (menu_item_ptr->next_item != NULL) - { + + if (menu_item_ptr != NULL) { + while (menu_item_ptr->next_item != NULL) { tmp_menu_item = menu_item_ptr->next_item; free(menu_item_ptr); menu_item_ptr = tmp_menu_item; } - free(menu_item_ptr); /* Last entry */ + free(menu_item_ptr); /* Last entry */ new_menu->entries = NULL; } - if (new_menu->prompt != NULL) /* Reusing existing menu */ - { - free((char *)new_menu->prompt); - } + if (new_menu->prompt != NULL) { /* Reusing existing menu */ + free((char *) new_menu->prompt); + } return; } - - new_menu = malloc(sizeof(nhmenu)); + + new_menu = malloc(sizeof (nhmenu)); new_menu->wid = wid; new_menu->prompt = NULL; new_menu->entries = NULL; @@ -523,16 +466,12 @@ void curses_create_nhmenu(winid wid) new_menu->width = 0; new_menu->reuse_accels = FALSE; new_menu->next_menu = NULL; - - if (nhmenus == NULL) /* no menus in memory yet */ - { + + if (nhmenus == NULL) { /* no menus in memory yet */ new_menu->prev_menu = NULL; nhmenus = new_menu; - } - else - { - while (menuptr->next_menu != NULL) - { + } else { + while (menuptr->next_menu != NULL) { menuptr = menuptr->next_menu; } new_menu->prev_menu = menuptr; @@ -543,23 +482,30 @@ void curses_create_nhmenu(winid wid) /* Add a menu item to the given menu window */ -void curses_add_nhmenu_item(winid wid, const ANY_P *identifier, - CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str, - BOOLEAN_P presel) +void +curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier, + CHAR_P accelerator, CHAR_P group_accel, int attr, + const char *str, BOOLEAN_P presel) { char *new_str; nhmenu_item *new_item, *current_items, *menu_item_ptr; nhmenu *current_menu = get_menu(wid); - - if (str == NULL) - { + + if (current_menu == NULL) { + impossible + ("curses_add_nhmenu_item: attempt to add item to nonexistent menu"); + return; + } + + if (str == NULL) { return; } new_str = curses_copy_of(str); curses_rtrim((char *) new_str); - new_item = malloc(sizeof(nhmenu_item)); + new_item = malloc(sizeof (nhmenu_item)); new_item->wid = wid; + new_item->glyph = glyph; new_item->identifier = *identifier; new_item->accelerator = accelerator; new_item->group_accel = group_accel; @@ -572,24 +518,15 @@ void curses_add_nhmenu_item(winid wid, const ANY_P *identifier, new_item->num_lines = 0; new_item->count = -1; new_item->next_item = NULL; - - if (current_menu == NULL) - { - panic("curses_add_nhmenu_item: attempt to add item to nonexistant menu"); - } current_items = current_menu->entries; menu_item_ptr = current_items; - if (current_items == NULL) - { + if (current_items == NULL) { new_item->prev_item = NULL; current_menu->entries = new_item; - } - else - { - while (menu_item_ptr->next_item != NULL) - { + } else { + while (menu_item_ptr->next_item != NULL) { menu_item_ptr = menu_item_ptr->next_item; } new_item->prev_item = menu_item_ptr; @@ -601,19 +538,19 @@ void curses_add_nhmenu_item(winid wid, const ANY_P *identifier, /* No more entries are to be added to menu, so details of the menu can be finalized in memory */ -void curses_finalize_nhmenu(winid wid, const char *prompt) +void +curses_finalize_nhmenu(winid wid, const char *prompt) { int count = 0; nhmenu *current_menu = get_menu(wid); - nhmenu_item *menu_item_ptr = current_menu->entries; - if (current_menu == NULL) - { - panic("curses_finalize_nhmenu: attempt to finalize nonexistant menu"); + if (current_menu == NULL) { + impossible("curses_finalize_nhmenu: attempt to finalize nonexistent menu"); + return; } - while (menu_item_ptr != NULL) - { + nhmenu_item *menu_item_ptr = current_menu->entries; + while (menu_item_ptr != NULL) { menu_item_ptr = menu_item_ptr->next_item; count++; } @@ -626,7 +563,8 @@ void curses_finalize_nhmenu(winid wid, const char *prompt) /* Display a nethack menu, and return a selection, if applicable */ -int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected) +int +curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected) { nhmenu *current_menu = get_menu(wid); nhmenu_item *menu_item_ptr; @@ -634,116 +572,104 @@ int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected) WINDOW *win; MENU_ITEM_P *selected = NULL; - *_selected = NULL; - - if (current_menu == NULL) - { - panic("curses_display_nhmenu: attempt to display nonexistant menu"); + *_selected = NULL; + + if (current_menu == NULL) { + impossible("curses_display_nhmenu: attempt to display nonexistent menu"); + return '\033'; } - + menu_item_ptr = current_menu->entries; - - if (menu_item_ptr == NULL) - { - panic("curses_display_nhmenu: attempt to display empty menu"); + + if (menu_item_ptr == NULL) { + impossible("curses_display_nhmenu: attempt to display empty menu"); + return '\033'; } - + /* Reset items to unselected to clear out selections from previous - invocations of this menu, and preselect appropriate items */ - while (menu_item_ptr != NULL) - { + invocations of this menu, and preselect appropriate items */ + while (menu_item_ptr != NULL) { menu_item_ptr->selected = menu_item_ptr->presel; menu_item_ptr = menu_item_ptr->next_item; } menu_win_size(current_menu); menu_determine_pages(current_menu); - + /* Display pre and post-game menus centered */ - if (((moves <= 1) && !invent) || program_state.gameover) - { + if (((moves <= 1) && !invent) || program_state.gameover) { win = curses_create_window(current_menu->width, - current_menu->height, CENTER); - } - else /* Display during-game menus on the right out of the way */ - { + current_menu->height, CENTER); + } else { /* Display during-game menus on the right out of the way */ + win = curses_create_window(current_menu->width, - current_menu->height, RIGHT); + current_menu->height, RIGHT); } - + num_chosen = menu_get_selections(win, current_menu, how); curses_destroy_win(win); - - if (num_chosen > 0) - { - selected = (MENU_ITEM_P*) malloc(num_chosen * - sizeof(MENU_ITEM_P)); + + if (num_chosen > 0) { + selected = (MENU_ITEM_P *) malloc(num_chosen * sizeof (MENU_ITEM_P)); count = 0; - + menu_item_ptr = current_menu->entries; - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->selected) - { - if (count == num_chosen) - { - panic("curses_display_nhmenu: Selected items " - "exceeds expected number"); + while (menu_item_ptr != NULL) { + if (menu_item_ptr->selected) { + if (count == num_chosen) { + impossible("curses_display_nhmenu: Selected items " + "exceeds expected number"); + break; } selected[count].item = menu_item_ptr->identifier; selected[count].count = menu_item_ptr->count; - count++; + count++; } menu_item_ptr = menu_item_ptr->next_item; } - - if (count != num_chosen) - { - panic("curses_display_nhmenu: Selected items less than " - "expected number"); + + if (count != num_chosen) { + impossible("curses_display_nhmenu: Selected items less than " + "expected number"); } } *_selected = selected; - + return num_chosen; } -boolean curses_menu_exists(winid wid) +boolean +curses_menu_exists(winid wid) { - if (get_menu(wid) != NULL) - { + if (get_menu(wid) != NULL) { return TRUE; - } - else - { + } else { return FALSE; } } /* Delete the menu associated with the given NetHack winid from memory */ -void curses_del_menu(winid wid) +void +curses_del_menu(winid wid) { nhmenu_item *tmp_menu_item; nhmenu_item *menu_item_ptr; nhmenu *tmpmenu; nhmenu *current_menu = get_menu(wid); - - if (current_menu == NULL) - { - return; + + if (current_menu == NULL) { + return; } - + menu_item_ptr = current_menu->entries; - + /* First free entries associated with this menu from memory */ - if (menu_item_ptr != NULL) - { - while (menu_item_ptr->next_item != NULL) - { + if (menu_item_ptr != NULL) { + while (menu_item_ptr->next_item != NULL) { tmp_menu_item = menu_item_ptr->next_item; free(menu_item_ptr); menu_item_ptr = tmp_menu_item; @@ -751,116 +677,101 @@ void curses_del_menu(winid wid) free(menu_item_ptr); /* Last entry */ current_menu->entries = NULL; } - + /* Now unlink the menu from the list and free it as well */ - if (current_menu->prev_menu != NULL) - { + if (current_menu->prev_menu != NULL) { tmpmenu = current_menu->prev_menu; tmpmenu->next_menu = current_menu->next_menu; + } else { + nhmenus = current_menu->next_menu; /* New head mode or NULL */ } - else - { - nhmenus = current_menu->next_menu; /* New head mode or NULL */ - } - if (current_menu->next_menu != NULL) - { + if (current_menu->next_menu != NULL) { tmpmenu = current_menu->next_menu; tmpmenu->prev_menu = current_menu->prev_menu; } - + free(current_menu); - + curses_del_wid(wid); } /* return a pointer to the menu associated with the given NetHack winid */ -static nhmenu *get_menu(winid wid) +static nhmenu * +get_menu(winid wid) { nhmenu *menuptr = nhmenus; - while (menuptr != NULL) - { - if (menuptr->wid == wid) - { + while (menuptr != NULL) { + if (menuptr->wid == wid) { return menuptr; } menuptr = menuptr->next_menu; } - - return NULL; /* Not found */ + + return NULL; /* Not found */ } -static char menu_get_accel(boolean first) +static char +menu_get_accel(boolean first) { char ret; static char next_letter = 'a'; - - if (first) - { + + if (first) { next_letter = 'a'; } - + ret = next_letter; - + if (((next_letter < 'z') && (next_letter >= 'a')) || ((next_letter < 'Z') - && (next_letter >= 'A')) || ((next_letter < '9') && (next_letter >= '0'))) - { + && (next_letter >= + 'A')) || + ((next_letter < '9') && (next_letter >= '0'))) { next_letter++; - } - else if (next_letter == 'z') - { + } else if (next_letter == 'z') { next_letter = 'A'; - } - else if (next_letter == 'Z') - { + } else if (next_letter == 'Z') { next_letter = '0'; } - + return ret; } /* Determine if menu will require multiple pages to display */ -static boolean menu_is_multipage(nhmenu *menu, int width, int height) +static boolean +menu_is_multipage(nhmenu *menu, int width, int height) { int num_lines; int curline = 0; nhmenu_item *menu_item_ptr = menu->entries; - if (strlen(menu->prompt) > 0) - { + if (strlen(menu->prompt) > 0) { curline += curses_num_lines(menu->prompt, width) + 1; } - - if (menu->num_entries <= (height - curline)) - { - while (menu_item_ptr != NULL) - { + + if (menu->num_entries <= (height - curline)) { + while (menu_item_ptr != NULL) { menu_item_ptr->line_num = curline; - if (menu_item_ptr->identifier.a_void == NULL) - { + if (menu_item_ptr->identifier.a_void == NULL) { num_lines = curses_num_lines(menu_item_ptr->str, width); - } - else - { + } else { /* Add space for accelerator */ num_lines = curses_num_lines(menu_item_ptr->str, width - 4); } menu_item_ptr->num_lines = num_lines; curline += num_lines; menu_item_ptr = menu_item_ptr->next_item; - if ((curline > height) || ((curline > height -2) && - (height == menu_max_height()))) - { + if ((curline > height) || ((curline > height - 2) && + (height == menu_max_height()))) { break; } } - if (menu_item_ptr == NULL) - { + if (menu_item_ptr == NULL) { return FALSE; } } @@ -870,7 +781,8 @@ static boolean menu_is_multipage(nhmenu *menu, int width, int height) /* Determine which entries go on which page, and total number of pages */ -static void menu_determine_pages(nhmenu *menu) +static void +menu_determine_pages(nhmenu *menu) { int tmpline, num_lines; int curline = 0; @@ -879,40 +791,33 @@ static void menu_determine_pages(nhmenu *menu) int width = menu->width; int height = menu->height; int page_end = height; - - - if (strlen(menu->prompt) > 0) - { + + + if (strlen(menu->prompt) > 0) { curline += curses_num_lines(menu->prompt, width) + 1; } - + tmpline = curline; - - if (menu_is_multipage(menu, width, height)) - { - page_end -= 2; /* Room to display current page number */ + + if (menu_is_multipage(menu, width, height)) { + page_end -= 2; /* Room to display current page number */ } /* Determine what entries belong on which page */ menu_item_ptr = menu->entries; - - while (menu_item_ptr != NULL) - { + + while (menu_item_ptr != NULL) { menu_item_ptr->page_num = page_num; menu_item_ptr->line_num = curline; - if (menu_item_ptr->identifier.a_void == NULL) - { + if (menu_item_ptr->identifier.a_void == NULL) { num_lines = curses_num_lines(menu_item_ptr->str, width); - } - else - { + } else { /* Add space for accelerator */ num_lines = curses_num_lines(menu_item_ptr->str, width - 4); } menu_item_ptr->num_lines = num_lines; curline += num_lines; - if (curline > page_end) - { + if (curline > page_end) { page_num++; curline = tmpline; /* Move ptr back so entry will be reprocessed on new page */ @@ -920,91 +825,81 @@ static void menu_determine_pages(nhmenu *menu) } menu_item_ptr = menu_item_ptr->next_item; } - + menu->num_pages = page_num; } /* Determine dimensions of menu window based on term size and entries */ -static void menu_win_size(nhmenu *menu) +static void +menu_win_size(nhmenu *menu) { int width, height, maxwidth, maxheight, curentrywidth, lastline; int maxentrywidth = strlen(menu->prompt); int maxheaderwidth = 0; nhmenu_item *menu_item_ptr = menu->entries; - - maxwidth = 38; /* Reasonable minimum usable width */ - - if ((term_cols / 2) > maxwidth) - { - maxwidth = (term_cols / 2); /* Half the screen */ + + maxwidth = 38; /* Reasonable minimum usable width */ + + if ((term_cols / 2) > maxwidth) { + maxwidth = (term_cols / 2); /* Half the screen */ } - + maxheight = menu_max_height(); - + /* First, determine the width of the longest menu entry */ while (menu_item_ptr != NULL) - { - if (menu_item_ptr->identifier.a_void == NULL) - { - curentrywidth=strlen(menu_item_ptr->str); + if (menu_item_ptr->identifier.a_void == NULL) { + curentrywidth = strlen(menu_item_ptr->str); - if (curentrywidth > maxheaderwidth) - { + if (curentrywidth > maxheaderwidth) { maxheaderwidth = curentrywidth; } - } - else - { + } else { /* Add space for accelerator */ - curentrywidth=strlen(menu_item_ptr->str) + 4; + curentrywidth = strlen(menu_item_ptr->str) + 4; + if (menu_item_ptr->glyph != NO_GLYPH + && iflags.use_menu_glyphs) + curentrywidth += 2; } - if (curentrywidth > maxentrywidth) - { - maxentrywidth = curentrywidth; + if (curentrywidth > maxentrywidth) { + maxentrywidth = curentrywidth; } menu_item_ptr = menu_item_ptr->next_item; } - + /* If the widest entry is smaller than maxwidth, reduce maxwidth accordingly */ - if (maxentrywidth < maxwidth) - { + if (maxentrywidth < maxwidth) { maxwidth = maxentrywidth; } - + /* Try not to wrap headers/normal text lines if possible. We can - go wider than half the screen for this purpose if need be */ - - if ((maxheaderwidth > maxwidth) && (maxheaderwidth < (term_cols - 2))) - { + go wider than half the screen for this purpose if need be */ + + if ((maxheaderwidth > maxwidth) && (maxheaderwidth < (term_cols - 2))) { maxwidth = maxheaderwidth; } - + width = maxwidth; - - /* Possibly reduce height if only 1 page */ - if (!menu_is_multipage(menu, maxwidth, maxheight)) - { + + /* Possibly reduce height if only 1 page */ + if (!menu_is_multipage(menu, maxwidth, maxheight)) { menu_item_ptr = menu->entries; - - while (menu_item_ptr->next_item != NULL) - { + + while (menu_item_ptr->next_item != NULL) { menu_item_ptr = menu_item_ptr->next_item; } - + lastline = (menu_item_ptr->line_num) + menu_item_ptr->num_lines; - - if (lastline < maxheight) - { + + if (lastline < maxheight) { maxheight = lastline; } - } - else /* If multipage, make sure we have enough width for page footer */ - { - if (width < 20) - { + } else { /* If multipage, make sure we have enough width for page footer */ + + if (width < 20) { width = 20; } } @@ -1017,160 +912,147 @@ static void menu_win_size(nhmenu *menu) /* Displays menu selections in the given window */ -static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num) +static void +menu_display_page(nhmenu *menu, WINDOW * win, int page_num) { nhmenu_item *menu_item_ptr; int count, curletter, entry_cols, start_col, num_lines, footer_x; boolean first_accel = TRUE; + #ifdef MENU_COLOR int color = NO_COLOR; int attr = A_NORMAL; boolean menu_color = FALSE; #endif /* MENU_COLOR */ - + /* Cycle through entries until we are on the correct page */ menu_item_ptr = menu->entries; - - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->page_num == page_num) - { + + while (menu_item_ptr != NULL) { + if (menu_item_ptr->page_num == page_num) { break; } menu_item_ptr = menu_item_ptr->next_item; } - - if (menu_item_ptr == NULL) /* Page not found */ - { - panic("menu_display_page: attempt to display nonexistant page"); + + if (menu_item_ptr == NULL) { /* Page not found */ + impossible("menu_display_page: attempt to display nonexistent page"); + return; } werase(win); - if (strlen(menu->prompt) > 0) - { + if (strlen(menu->prompt) > 0) { num_lines = curses_num_lines(menu->prompt, menu->width); - - for (count = 0; count < num_lines; count++) - { + + for (count = 0; count < num_lines; count++) { mvwprintw(win, count + 1, 1, "%s", - curses_break_str(menu->prompt, menu->width, count + 1)); + curses_break_str(menu->prompt, menu->width, count + 1)); } } /* Display items for current page */ - - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->page_num != page_num) - { + + while (menu_item_ptr != NULL) { + if (menu_item_ptr->page_num != page_num) { break; } - if (menu_item_ptr->identifier.a_void != NULL) - { - if (menu_item_ptr->accelerator != 0) - { + if (menu_item_ptr->identifier.a_void != NULL) { + if (menu_item_ptr->accelerator != 0) { curletter = menu_item_ptr->accelerator; - } - else - { - if (first_accel) - { + } else { + if (first_accel) { curletter = menu_get_accel(TRUE); first_accel = FALSE; - if (!menu->reuse_accels && (menu->num_pages > 1)) - { + if (!menu->reuse_accels && (menu->num_pages > 1)) { menu->reuse_accels = TRUE; } - } - else - { + } else { curletter = menu_get_accel(FALSE); } menu_item_ptr->accelerator = curletter; } - if (menu_item_ptr->selected) - { + if (menu_item_ptr->selected) { curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, ON); mvwaddch(win, menu_item_ptr->line_num + 1, 1, '<'); mvwaddch(win, menu_item_ptr->line_num + 1, 2, curletter); mvwaddch(win, menu_item_ptr->line_num + 1, 3, '>'); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, OFF); - } - else - { + } else { curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON); mvwaddch(win, menu_item_ptr->line_num + 1, 2, curletter); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF); mvwprintw(win, menu_item_ptr->line_num + 1, 3, ") "); } } -#ifdef MENU_COLOR - if (iflags.use_menu_color && (menu_color = get_menu_coloring - ((char *)menu_item_ptr->str, &color, &attr))) - { - if (color != NO_COLOR) - { - curses_toggle_color_attr(win, color, NONE, ON); - } - if (attr != A_NORMAL) - { - menu_item_ptr->attr = menu_item_ptr->attr|attr; - } - } -#endif /* MENU_COLOR */ - curses_toggle_color_attr(win, NONE, menu_item_ptr->attr, ON); entry_cols = menu->width; start_col = 1; - if (menu_item_ptr->identifier.a_void != NULL) - { + if (menu_item_ptr->identifier.a_void != NULL) { entry_cols -= 4; start_col += 4; - } - + } + if (menu_item_ptr->glyph != NO_GLYPH && iflags.use_menu_glyphs) { + unsigned special; /*notused */ + + mapglyph(menu_item_ptr->glyph, &curletter, &color, &special, 0, 0); + curses_toggle_color_attr(win, color, NONE, ON); + mvwaddch(win, menu_item_ptr->line_num + 1, start_col, curletter); + curses_toggle_color_attr(win, color, NONE, OFF); + mvwaddch(win, menu_item_ptr->line_num + 1, start_col + 1, ' '); + entry_cols -= 2; + start_col += 2; + } +#ifdef MENU_COLOR + if (iflags.use_menu_color && (menu_color = get_menu_coloring + ((char *) menu_item_ptr->str, &color, + &attr))) { + if (color != NO_COLOR) { + curses_toggle_color_attr(win, color, NONE, ON); + } + if (attr != A_NORMAL) { + menu_item_ptr->attr = menu_item_ptr->attr | attr; + } + } +#endif /* MENU_COLOR */ + curses_toggle_color_attr(win, NONE, menu_item_ptr->attr, ON); + num_lines = curses_num_lines(menu_item_ptr->str, entry_cols); - - for (count = 0; count < num_lines; count++) - { - if (strlen(menu_item_ptr->str) > 0) - { + + for (count = 0; count < num_lines; count++) { + if (strlen(menu_item_ptr->str) > 0) { mvwprintw(win, menu_item_ptr->line_num + count + 1, - start_col, "%s", curses_break_str(menu_item_ptr->str, - entry_cols, count + 1)); - } + start_col, "%s", curses_break_str(menu_item_ptr->str, + entry_cols, + count + 1)); + } } #ifdef MENU_COLOR - if (menu_color && (color != NO_COLOR)) - { - curses_toggle_color_attr(win, color, NONE, OFF); - } + if (menu_color && (color != NO_COLOR)) { + curses_toggle_color_attr(win, color, NONE, OFF); + } #endif /* MENU_COLOR */ curses_toggle_color_attr(win, NONE, menu_item_ptr->attr, OFF); menu_item_ptr = menu_item_ptr->next_item; } - if (menu->num_pages > 1) - { + if (menu->num_pages > 1) { footer_x = menu->width - strlen("<- (Page X of Y) ->"); - if (menu->num_pages > 9) /* Unlikely */ - { + if (menu->num_pages > 9) { /* Unlikely */ footer_x -= 2; } mvwprintw(win, menu->height, footer_x + 3, "(Page %d of %d)", - page_num, menu->num_pages); - if (page_num != 1) - { + page_num, menu->num_pages); + if (page_num != 1) { curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON); mvwaddstr(win, menu->height, footer_x, "<="); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF); } - if (page_num != menu->num_pages) - { + if (page_num != menu->num_pages) { curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON); - mvwaddstr(win, menu->height, menu->width - 2, "=>"); + mvwaddstr(win, menu->height, menu->width - 2, "=>"); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF); } } @@ -1181,7 +1063,8 @@ static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num) } -static int menu_get_selections(WINDOW *win, nhmenu *menu, int how) +static int +menu_get_selections(WINDOW * win, nhmenu *menu, int how) { int curletter; int count = -1; @@ -1194,247 +1077,173 @@ static int menu_get_selections(WINDOW *win, nhmenu *menu, int how) menu_display_page(menu, win, 1); - while (!dismiss) - { + while (!dismiss) { curletter = getch(); - if (curletter == ERR) { - num_selected = -1; - dismiss = TRUE; - } - - if (curletter == DOESCAPE) - { + if (curletter == ERR) { + num_selected = -1; + dismiss = TRUE; + } + + if (curletter == DOESCAPE) { curletter = curses_convert_keys(curletter); } - - - - switch (how) - { - case PICK_NONE: - { - if (menu->num_pages == 1) - { - if (curletter == KEY_ESC) - { - num_selected = -1; - } - else - { - num_selected = 0; - - } - dismiss = TRUE; - break; + + switch (how) { + case PICK_NONE: + if (menu->num_pages == 1) { + if (curletter == KEY_ESC) { + num_selected = -1; + } else { + num_selected = 0; + } + dismiss = TRUE; break; } - case PICK_ANY: - { - switch (curletter) - { - case MENU_SELECT_PAGE: - { - (void) menu_operation(win, menu, SELECT, curpage); - break; - } - case MENU_SELECT_ALL: - { - curpage = menu_operation(win, menu, SELECT, 0); - break; - } - case MENU_UNSELECT_PAGE: - { - (void) menu_operation(win, menu, DESELECT, curpage); - break; - } - case MENU_UNSELECT_ALL: - { - curpage = menu_operation(win, menu, DESELECT, 0); - break; - } - case MENU_INVERT_PAGE: - { - (void) menu_operation(win, menu, INVERT, curpage); - break; - } - case MENU_INVERT_ALL: - { - curpage = menu_operation(win, menu, INVERT, 0); - break; - } - } + break; + case PICK_ANY: + switch (curletter) { + case MENU_SELECT_PAGE: + (void) menu_operation(win, menu, SELECT, curpage); + break; + case MENU_SELECT_ALL: + curpage = menu_operation(win, menu, SELECT, 0); + break; + case MENU_UNSELECT_PAGE: + (void) menu_operation(win, menu, DESELECT, curpage); + break; + case MENU_UNSELECT_ALL: + curpage = menu_operation(win, menu, DESELECT, 0); + break; + case MENU_INVERT_PAGE: + (void) menu_operation(win, menu, INVERT, curpage); + break; + case MENU_INVERT_ALL: + curpage = menu_operation(win, menu, INVERT, 0); + break; } - default: - { - if (isdigit(curletter)) - { - count = curses_get_count(curletter - '0'); - touchwin(win); - refresh(); - curletter = getch(); - if (count > 0) - { - count_letter = curletter; - } + default: + if (isdigit(curletter)) { + count = curses_get_count(curletter - '0'); + touchwin(win); + refresh(); + curletter = getch(); + if (count > 0) { + count_letter = curletter; } } } - - - - - switch (curletter) - { - case KEY_ESC: - { - num_selected = -1; - dismiss = TRUE; - break; - } - case '\n': - case '\r': - { + + switch (curletter) { + case KEY_ESC: + num_selected = -1; + dismiss = TRUE; + break; + case '\n': + case '\r': + dismiss = TRUE; + break; + case KEY_RIGHT: + case KEY_NPAGE: + case MENU_NEXT_PAGE: + case ' ': + if (curpage < menu->num_pages) { + curpage++; + menu_display_page(menu, win, curpage); + } else if (curletter == ' ') { dismiss = TRUE; break; } - case KEY_RIGHT: - case KEY_NPAGE: - case MENU_NEXT_PAGE: - case ' ': - { - if (curpage < menu->num_pages) - { - curpage++; - menu_display_page(menu, win, curpage); - } - else if (curletter == ' ') - { - dismiss = TRUE; - break; - } - break; + break; + case KEY_LEFT: + case KEY_PPAGE: + case MENU_PREVIOUS_PAGE: + if (curpage > 1) { + curpage--; + menu_display_page(menu, win, curpage); } - case KEY_LEFT: - case KEY_PPAGE: - case MENU_PREVIOUS_PAGE: - { - if (curpage > 1) - { - curpage--; - menu_display_page(menu, win, curpage); - } - break; + break; + case KEY_END: + case MENU_LAST_PAGE: + if (curpage != menu->num_pages) { + curpage = menu->num_pages; + menu_display_page(menu, win, curpage); } - case KEY_END: - case MENU_LAST_PAGE: - { - if (curpage != menu->num_pages) - { - curpage = menu->num_pages; - menu_display_page(menu, win, curpage); - } - break; + break; + case KEY_HOME: + case MENU_FIRST_PAGE: + if (curpage != 1) { + curpage = 1; + menu_display_page(menu, win, curpage); } - case KEY_HOME: - case MENU_FIRST_PAGE: - { - if (curpage != 1) - { - curpage = 1; - menu_display_page(menu, win, curpage); - } + break; + case MENU_SEARCH: + curses_line_input_dialog("Search for:", search_key, BUFSZ); + + refresh(); + touchwin(win); + wrefresh(win); + + if (strlen(search_key) == 0) { break; } - case MENU_SEARCH: - { - curses_line_input_dialog("Search for:", search_key, - BUFSZ); - - refresh(); - touchwin(win); - wrefresh(win); - - if (strlen(search_key) == 0) - { - break; - } - - menu_item_ptr = menu->entries; - - while (menu_item_ptr != NULL) - { - if ((menu_item_ptr->identifier.a_void != NULL) && - (strstri(menu_item_ptr->str, search_key))) - { - if (how == PICK_ONE) - { - menu_clear_selections(menu); - menu_select_deselect(win, menu_item_ptr, - SELECT); - num_selected = 1; - dismiss = TRUE; - break; - } - else - { - menu_select_deselect(win, menu_item_ptr, - INVERT); - } - } - menu_item_ptr = menu_item_ptr->next_item; + menu_item_ptr = menu->entries; + + while (menu_item_ptr != NULL) { + if ((menu_item_ptr->identifier.a_void != NULL) && + (strstri(menu_item_ptr->str, search_key))) { + if (how == PICK_ONE) { + menu_clear_selections(menu); + menu_select_deselect(win, menu_item_ptr, SELECT); + num_selected = 1; + dismiss = TRUE; + break; + } else { + menu_select_deselect(win, menu_item_ptr, INVERT); + } } - menu_item_ptr = menu->entries; - break; + menu_item_ptr = menu_item_ptr->next_item; } - default: - { - if (how==PICK_NONE) - { - num_selected = 0; - dismiss = TRUE; - break; - } + + menu_item_ptr = menu->entries; + break; + default: + if (how == PICK_NONE) { + num_selected = 0; + dismiss = TRUE; + break; } } - menu_item_ptr = menu->entries; - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->identifier.a_void != NULL) - { + while (menu_item_ptr != NULL) { + if (menu_item_ptr->identifier.a_void != NULL) { if (((curletter == menu_item_ptr->accelerator) && - ((curpage == menu_item_ptr->page_num) || - (!menu->reuse_accels))) || ((menu_item_ptr->group_accel) - && (curletter == menu_item_ptr->group_accel))) - { - if (curpage != menu_item_ptr->page_num) - { + ((curpage == menu_item_ptr->page_num) || + (!menu->reuse_accels))) || ((menu_item_ptr->group_accel) + && (curletter == + menu_item_ptr-> + group_accel))) { + if (curpage != menu_item_ptr->page_num) { curpage = menu_item_ptr->page_num; menu_display_page(menu, win, curpage); } - if (how == PICK_ONE) - { + if (how == PICK_ONE) { menu_clear_selections(menu); menu_select_deselect(win, menu_item_ptr, SELECT); num_selected = 1; dismiss = TRUE; break; - } - else if ((how == PICK_ANY) && (curletter == count_letter)) - { + } else if ((how == PICK_ANY) && (curletter == count_letter)) { menu_select_deselect(win, menu_item_ptr, SELECT); menu_item_ptr->count = count; count = 0; count_letter = '\0'; - } - else - { + } else { menu_select_deselect(win, menu_item_ptr, INVERT); } } @@ -1442,47 +1251,40 @@ static int menu_get_selections(WINDOW *win, nhmenu *menu, int how) menu_item_ptr = menu_item_ptr->next_item; } } - - if ((how == PICK_ANY) && (num_selected != -1)) - { + + if ((how == PICK_ANY) && (num_selected != -1)) { num_selected = 0; menu_item_ptr = menu->entries; - - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->identifier.a_void != NULL) - { - if (menu_item_ptr->selected) - { + + while (menu_item_ptr != NULL) { + if (menu_item_ptr->identifier.a_void != NULL) { + if (menu_item_ptr->selected) { num_selected++; } } menu_item_ptr = menu_item_ptr->next_item; } } - + return num_selected; } /* Select, deselect, or toggle selected for the given menu entry */ -static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operation) +static void +menu_select_deselect(WINDOW * win, nhmenu_item *item, menu_op operation) { int curletter = item->accelerator; - - if ((operation == DESELECT) || (item->selected && (operation == - INVERT))) - { + + if ((operation == DESELECT) || (item->selected && (operation == INVERT))) { item->selected = FALSE; mvwaddch(win, item->line_num + 1, 1, ' '); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON); mvwaddch(win, item->line_num + 1, 2, curletter); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF); mvwaddch(win, item->line_num + 1, 3, ')'); - } - else - { + } else { item->selected = TRUE; curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, ON); mvwaddch(win, item->line_num + 1, 1, '<'); @@ -1490,7 +1292,7 @@ static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operati mvwaddch(win, item->line_num + 1, 3, '>'); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, OFF); } - + wrefresh(win); } @@ -1499,79 +1301,70 @@ static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operati on the given menu page. If menu_page is 0, then perform opetation on all pages in menu. Returns last page displayed. */ -static int menu_operation(WINDOW *win, nhmenu *menu, menu_op - operation, int page_num) +static int +menu_operation(WINDOW * win, nhmenu *menu, menu_op + operation, int page_num) { int first_page, last_page, current_page; - nhmenu_item *menu_item_ptr = menu->entries; - - if (page_num == 0) /* Operation to occur on all pages */ - { + nhmenu_item *menu_item_ptr = menu->entries; + + if (page_num == 0) { /* Operation to occur on all pages */ first_page = 1; last_page = menu->num_pages; - } - else - { + } else { first_page = page_num; last_page = page_num; } /* Cycle through entries until we are on the correct page */ - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->page_num == first_page) - { + while (menu_item_ptr != NULL) { + if (menu_item_ptr->page_num == first_page) { break; } menu_item_ptr = menu_item_ptr->next_item; } - + current_page = first_page; - - if (page_num == 0) - { + + if (page_num == 0) { menu_display_page(menu, win, current_page); } - - if (menu_item_ptr == NULL) /* Page not found */ - { - panic("menu_display_page: attempt to display nonexistant page"); + + if (menu_item_ptr == NULL) { /* Page not found */ + impossible("menu_display_page: attempt to display nonexistent page"); + return 0; } - - while (menu_item_ptr != NULL) - { - if (menu_item_ptr->page_num != current_page) - { - if (menu_item_ptr->page_num > last_page) - { + + while (menu_item_ptr != NULL) { + if (menu_item_ptr->page_num != current_page) { + if (menu_item_ptr->page_num > last_page) { break; } current_page = menu_item_ptr->page_num; menu_display_page(menu, win, current_page); } - - if (menu_item_ptr->identifier.a_void != NULL) - { + + if (menu_item_ptr->identifier.a_void != NULL) { menu_select_deselect(win, menu_item_ptr, operation); } - + menu_item_ptr = menu_item_ptr->next_item; } - + return current_page; } /* Set all menu items to unselected in menu */ -static void menu_clear_selections(nhmenu *menu) +static void +menu_clear_selections(nhmenu *menu) { - nhmenu_item *menu_item_ptr = menu->entries; + nhmenu_item *menu_item_ptr = menu->entries; - while (menu_item_ptr != NULL) - { + while (menu_item_ptr != NULL) { menu_item_ptr->selected = FALSE; menu_item_ptr = menu_item_ptr->next_item; } @@ -1582,25 +1375,27 @@ static void menu_clear_selections(nhmenu *menu) applied */ #ifdef MENU_COLOR -static boolean get_menu_coloring(char *str, int *color, int *attr) +boolean +get_menu_coloring(char *str, int *color, int *attr) { struct menucoloring *tmpmc; + if (iflags.use_menu_color) - for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next) + for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next) # ifdef MENU_COLOR_REGEX # ifdef MENU_COLOR_REGEX_POSIX - if (regexec(&tmpmc->match, str, 0, NULL, 0) == 0) { + if (regexec(&tmpmc->match, str, 0, NULL, 0) == 0) { # else - if (re_search(&tmpmc->match, str, strlen(str), 0, 9999, 0) >= 0) { + if (re_search(&tmpmc->match, str, strlen(str), 0, 9999, 0) >= 0) { # endif # else - if (pmatch(tmpmc->match, str)) { + if (pmatch(tmpmc->match, str)) { # endif - *color = tmpmc->color; - *attr = curses_convert_attr(tmpmc->attr); - return TRUE; - } + *color = tmpmc->color; + *attr = curses_convert_attr(tmpmc->attr); + return TRUE; + } return FALSE; } #endif /* MENU_COLOR */ @@ -1608,7 +1403,8 @@ static boolean get_menu_coloring(char *str, int *color, int *attr) /* Get the maximum height for a menu */ -static int menu_max_height(void) +static int +menu_max_height(void) { return term_rows - 2; } diff --git a/win/curses/cursdial.h b/win/curses/cursdial.h index dccdbe80..8a7dcdb2 100644 --- a/win/curses/cursdial.h +++ b/win/curses/cursdial.h @@ -1,35 +1,33 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSDIAL_H -#define CURSDIAL_H +# define CURSDIAL_H -#ifdef MENU_COLOR -# ifdef MENU_COLOR_REGEX -# include +# ifdef MENU_COLOR +# ifdef MENU_COLOR_REGEX +# include +# endif # endif -#endif /* Global declarations */ void curses_line_input_dialog(const char *prompt, char *answer, int buffer); - -int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def); - +int curses_character_input_dialog(const char *prompt, const char *choices, + CHAR_P def); int curses_ext_cmd(void); - void curses_create_nhmenu(winid wid); - -void curses_add_nhmenu_item(winid wid, const ANY_P *identifier, - CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str, - BOOLEAN_P presel); - +void curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier, + CHAR_P accelerator, CHAR_P group_accel, int attr, + const char *str, BOOLEAN_P presel); +# ifdef MENU_COLOR +boolean get_menu_coloring(char *, int *, int *); +# endif void curses_finalize_nhmenu(winid wid, const char *prompt); - -int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected); - +int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected); boolean curses_menu_exists(winid wid); - void curses_del_menu(winid wid); -#endif /* CURSDIAL_H */ +#endif /* CURSDIAL_H */ diff --git a/win/curses/cursinit.c b/win/curses/cursinit.c index 4155a2df..4a64731e 100644 --- a/win/curses/cursinit.c +++ b/win/curses/cursinit.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" @@ -14,11 +16,16 @@ #define SLASHEM_CURSES 2 #define UNNETHACK_CURSES 3 #define SPORKHACK_CURSES 4 +#define GRUNTHACK_CURSES 5 +#define DNETHACK_CURSES 6 + +static void set_window_position(int *, int *, int *, int *, int, + int *, int *, int *, int *, int, + int, int); /* array to save initial terminal colors for later restoration */ -typedef struct nhrgb_type -{ +typedef struct nhrgb_type { short r; short g; short b; @@ -106,25 +113,86 @@ nhrgb orig_hiwhite; #define SPORKHACK_SPLASH_G \ " | | " #define SPORKHACK_SPLASH_H \ -" |_| " +" |_| " + +#define GRUNTHACK_SPLASH_A \ +" ______ _ _ _ _ " +#define GRUNTHACK_SPLASH_B \ +"/ ____) | | | | | | | | " +#define GRUNTHACK_SPLASH_C \ +"| / ___ _ __ _ _ _ __ | |_ | |__| | __ _ ___ | | _" +#define GRUNTHACK_SPLASH_D \ +"| | L \\| '__)| | | || '_ \\ | __)| __ | / _` | / __)| |/ /" +#define GRUNTHACK_SPLASH_E \ +"| l__) || | | |_| || | | || |_ | | | || (_| || (__ | < " +#define GRUNTHACK_SPLASH_F \ +"\\______/|_| \\___,_||_| |_| \\__)|_| |_| \\__,_| \\___)|_|\\_\\" + +#define DNETHACK_SPLASH_A \ +" _ _ _ _ _ _ _ " +#define DNETHACK_SPLASH_B \ +" | || \\ | | | | | | | | | | " +#define DNETHACK_SPLASH_C \ +" __| || \\| | ___ | |_ | |__| | __ _ ___ | | __" +#define DNETHACK_SPLASH_D \ +" / _` || . ` | / _ \\| __|| __ | / _` | / __|| |/ /" +#define DNETHACK_SPLASH_E \ +"| (_| || |\\ || __/| |_ | | | || (_| || (__ | < " +#define DNETHACK_SPLASH_F \ +" \\__,_||_| \\_| \\___| \\__||_| |_| \\__,_| \\___||_|\\_\\" + + +/* win* is size and placement of window to change, x/y/w/h is baseline which can + decrease depending on alignment of win* in orientation. + Negative minh/minw: as much as possible, but at least as much as specified. */ +static void +set_window_position(int *winx, int *winy, int *winw, int *winh, int orientation, + int *x, int *y, int *w, int *h, int border_space, + int minh, int minw) +{ + *winw = *w; + *winh = *h; + + /* Set window height/width */ + if (orientation == ALIGN_TOP || orientation == ALIGN_BOTTOM) { + if (minh < 0) { + *winh = (*h - ROWNO - border_space); + if (-minh > *winh) + *winh = -minh; + } else + *winh = minh; + *h -= (*winh + border_space); + } else { + if (minw < 0) { + *winw = (*w - COLNO - border_space); + if (-minw > *winw) + *winw = -minw; + } else + *winw = minw; + *w -= (*winw + border_space); + } + + *winx = *w + border_space + *x; + *winy = *h + border_space + *y; + /* Set window position */ + if (orientation != ALIGN_RIGHT) { + *winx = *x; + if (orientation == ALIGN_LEFT) + *x += *winw + border_space; + } + if (orientation != ALIGN_BOTTOM) { + *winy = *y; + if (orientation == ALIGN_TOP) + *y += *winh + border_space; + } +} /* Create the "main" nonvolitile windows used by nethack */ -void curses_create_main_windows() +void +curses_create_main_windows() { - int message_x = 0; - int message_y = 0; - int status_x = 0; - int status_y = 0; - int map_x = 0; - int map_y = 0; - int message_height = 0; - int message_width = 0; - int status_height = 0; - int status_width = 0; - int map_height = 0; - int map_width = 0; int min_message_height = 1; int message_orientation = 0; int status_orientation = 0; @@ -132,418 +200,171 @@ void curses_create_main_windows() int hspace = term_cols - 80; boolean borders = FALSE; - switch (iflags.wc2_windowborders) - { - case 1: /* On */ - { + switch (iflags.wc2_windowborders) { + case 1: /* On */ + borders = TRUE; + break; + case 2: /* Off */ + borders = FALSE; + break; + case 3: /* Auto */ + if ((term_cols > 81) && (term_rows > 25)) { borders = TRUE; - break; - } - case 2: /* Off */ - { - borders = FALSE; - break; - } - case 3: /* Auto */ - { - if ((term_cols > 81) && (term_rows > 25)) - { - borders = TRUE; - } - break; - } - default: - { - borders = FALSE; } + break; + default: + borders = FALSE; } - - if (borders) - { + + if (borders) { border_space = 2; hspace -= border_space; } - - if ((term_cols - border_space) < COLNO) - { + + if ((term_cols - border_space) < COLNO) { min_message_height++; } - - /* Determine status window orientation */ + + /* Determine status window orientation */ if (!iflags.wc_align_status || (iflags.wc_align_status == ALIGN_TOP) - || (iflags.wc_align_status == ALIGN_BOTTOM)) - { - if (!iflags.wc_align_status) - { + || (iflags.wc_align_status == ALIGN_BOTTOM)) { + if (!iflags.wc_align_status) { iflags.wc_align_status = ALIGN_BOTTOM; } status_orientation = iflags.wc_align_status; - } - else /* left or right alignment */ - { + } else { /* left or right alignment */ + /* Max space for player name and title horizontally */ - if ((hspace >= 26) && (term_rows >= 24)) - { + if ((hspace >= 26) && (term_rows >= 24)) { status_orientation = iflags.wc_align_status; hspace -= (26 + border_space); - } - else - { + } else { status_orientation = ALIGN_BOTTOM; } } - - /* Determine message window orientation */ + + /* Determine message window orientation */ if (!iflags.wc_align_message || (iflags.wc_align_message == ALIGN_TOP) - || (iflags.wc_align_message == ALIGN_BOTTOM)) - { - if (!iflags.wc_align_message) - { + || (iflags.wc_align_message == ALIGN_BOTTOM)) { + if (!iflags.wc_align_message) { iflags.wc_align_message = ALIGN_TOP; } message_orientation = iflags.wc_align_message; - } - else /* left or right alignment */ - { - if ((hspace - border_space) >= 25) /* Arbitrary */ - { + } else { /* left or right alignment */ + + if ((hspace - border_space) >= 25) { /* Arbitrary */ message_orientation = iflags.wc_align_message; - } - else - { + } else { message_orientation = ALIGN_TOP; } } - - /* Determine window placement and size - 16 possible combos - If anyone wants to try to generalize this, be my guest! */ - if ((status_orientation == ALIGN_TOP) && - (message_orientation == ALIGN_TOP)) - { - status_x = 0; - status_y = 0; - status_width = (term_cols - border_space); - status_height = 2; - message_x = 0; - message_y = status_y + (status_height + border_space); - message_width = (term_cols - border_space); - message_height = term_rows - (status_height + ROWNO + (border_space * 3)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_x = 0; - map_y = message_y + (message_height + border_space); - map_width = (term_cols - border_space); - map_height = term_rows - (status_height + message_height + (border_space * 3)); - } - else if ((status_orientation == ALIGN_TOP) && - (message_orientation == ALIGN_RIGHT)) - { - status_x = 0; - status_y = 0; - status_height = 2; - message_height = (term_rows - border_space); - message_width = term_cols - (COLNO + (border_space * 2)); - status_width = term_cols - (message_width + (border_space * 2)); - message_x = status_x + (status_width + border_space); - message_y = 0; - map_x = 0; - map_y = status_y + (status_height + border_space); - map_width = status_width; - map_height = term_rows - (status_height + (border_space * 2)); - } - else if ((status_orientation == ALIGN_TOP) && - (message_orientation == ALIGN_BOTTOM)) - { - status_x = 0; - status_y = 0; - status_width = (term_cols - border_space); - status_height = 2; - map_x = 0; - map_y = status_y + (status_height + border_space); - map_width = (term_cols - border_space); - message_height = term_rows - (status_height + ROWNO + (border_space * 3)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_height = term_rows - (status_height + message_height + (border_space * 3)); - message_x = 0; - message_y = map_y + (map_height + border_space); - message_width = (term_cols - border_space); - } - else if ((status_orientation == ALIGN_TOP) && - (message_orientation == ALIGN_LEFT)) - { - message_x = 0; - message_y = 0; - message_height = (term_rows - border_space); - message_width = term_cols - (COLNO + (border_space * 2)); - status_x = message_x + (message_width + border_space); - status_y = 0; - status_height = 2; - status_width = term_cols - (message_width + (border_space * 2)); - map_x = status_x; - map_y = status_y + (status_height + border_space); - map_height = term_rows - (status_height + (border_space * 2)); - map_width = status_width; - } - if ((status_orientation == ALIGN_RIGHT) && - (message_orientation == ALIGN_TOP)) - { - status_width = 26; - status_height = (term_rows - border_space); - status_x = term_cols - (status_width + border_space); - status_y = 0; - message_x = 0; - message_y = 0; - message_width = term_cols - (status_width + (border_space * 2)); - message_height = term_rows - (ROWNO + (border_space * 2)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_x = 0; - map_y = message_y + (message_height + border_space); - map_width = term_cols - (status_width + (border_space * 2)); - map_height = term_rows - (message_height + (border_space * 2)); - } - else if ((status_orientation == ALIGN_RIGHT) && - (message_orientation == ALIGN_RIGHT)) - { - map_x = 0; - map_y = 0; - map_height = (term_rows - border_space); - status_width = 26; - message_width = term_cols - (COLNO + status_width + (border_space * 3)); - map_width = term_cols - (status_width + message_width + (border_space * 3)); - message_x = map_x + (map_width + border_space); - message_y = 0; - message_height = (term_rows - border_space); - status_x = message_x + (message_width + border_space); - status_y = 0; - status_height = (term_rows - border_space); - } - else if ((status_orientation == ALIGN_RIGHT) && - (message_orientation == ALIGN_BOTTOM)) - { - map_x = 0; - map_y = 0; - status_width = 26; - map_width = term_cols - (status_width + (border_space * 2)); - message_height = term_rows - (ROWNO + (border_space * 2)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_height = term_rows - (message_height + (border_space * 2)); - message_x = 0; - message_y = map_y + (map_height + border_space); - message_width = map_width; - status_x = map_x + (map_width + border_space); - status_y = 0; - status_height = (term_rows - border_space); - } - else if ((status_orientation == ALIGN_RIGHT) && - (message_orientation == ALIGN_LEFT)) - { - status_x = 0; - status_y = 0; - status_height = (term_rows - border_space); - status_width = 26; - message_width = term_cols - (status_width + COLNO + (border_space * 3)); - map_x = status_x + (status_width + border_space); - map_y = 0; - map_height = (term_rows - border_space); - map_width = term_cols - (status_width + message_width + (border_space * 3)); - message_x = map_x + (map_width + border_space); - message_y = 0; - message_height = (term_rows - border_space); - } - if ((status_orientation == ALIGN_BOTTOM) && - (message_orientation == ALIGN_TOP)) - { - message_x = 0; - message_y = 0; - message_width = (term_cols - border_space); - status_height = 2; - message_height = term_rows - (status_height + ROWNO + (border_space * 3)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_x = 0; - map_y = message_y + (message_height + border_space); - map_width = (term_cols - border_space); - map_height = term_rows - (status_height + message_height + (border_space * 3)); - status_x = 0; - status_y = map_y + (map_height + border_space); - status_width = (term_cols - border_space); - } - else if ((status_orientation == ALIGN_BOTTOM) && - (message_orientation == ALIGN_RIGHT)) - { - map_x = 0; - map_y = 0; - status_height = 2; - map_height = term_rows - (status_height + (border_space * 2)); - message_width = term_cols - (COLNO + (border_space * 2)); - map_width = term_cols - (message_width + (border_space * 2)); - status_x = 0; - status_y = map_y + (map_height + border_space); - status_width = map_width; - message_x = map_x + (map_width + border_space); - message_y = 0; - message_height = (term_rows - border_space); - } - else if ((status_orientation == ALIGN_BOTTOM) && - (message_orientation == ALIGN_BOTTOM)) - { - map_x = 0; - map_y = 0; - message_x = 0; - status_x = 0; - message_width = (term_cols - border_space); - status_height = 2; - message_height = term_rows - (status_height + ROWNO + (border_space * 3)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_width = (term_cols - border_space); - map_height = term_rows - (status_height + message_height + (border_space * 3)); - message_y = map_y + (map_height + border_space); - status_y = message_y + (message_height + border_space); - status_width = (term_cols - border_space); - } - else if ((status_orientation == ALIGN_BOTTOM) && - (message_orientation == ALIGN_LEFT)) - { - message_x = 0; - message_y = 0; - message_height = (term_rows - border_space); - message_width = term_cols - (COLNO + (border_space * 2)); - status_height = 2; - map_x = message_x + (message_width + border_space); - map_y = 0; - map_height = term_rows - (status_height + (border_space * 2)); - map_width = term_cols - (message_width + (border_space * 2)); - status_x = map_x; - status_y = map_y + (map_height + border_space); - status_width = term_cols - (message_width + (border_space * 2)); - } - if ((status_orientation == ALIGN_LEFT) && - (message_orientation == ALIGN_TOP)) - { - status_x = 0; - status_y = 0; - status_height = (term_rows - border_space); - status_width = 26; - message_x = status_x + (status_width + border_space); - message_y = 0; - message_height = term_rows - (ROWNO + (border_space * 2)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - message_width = term_cols - (status_width + (border_space * 2)); - map_x = message_x; - map_y = message_y + (message_height + border_space); - map_height = term_rows - (message_height + (border_space * 2)); - map_width = term_cols - (status_width + (border_space * 2)); - } - else if ((status_orientation == ALIGN_LEFT) && - (message_orientation == ALIGN_RIGHT)) - { - message_x = 0; - message_y = 0; - message_height = (term_rows - border_space); - status_width = 26; - message_width = term_cols - (status_width + COLNO + (border_space * 3)); - map_x = message_x + (message_width + border_space); - map_y = 0; - map_height = (term_rows - border_space); - map_width = term_cols - (status_width + message_width + (border_space * 3)); - status_x = map_x + (map_width + border_space); - status_y = 0; - status_height = (term_rows - border_space); - } - else if ((status_orientation == ALIGN_LEFT) && - (message_orientation == ALIGN_BOTTOM)) - { - status_x = 0; - status_y = 0; - status_height = (term_rows - border_space); - status_width = 26; - map_x = status_x + (status_width + border_space); - map_y = 0; - message_height = term_rows - (ROWNO + (border_space * 2)); - if (message_height < min_message_height) - { - message_height = min_message_height; - } - map_height = term_rows - (message_height + (border_space * 2)); - map_width = term_cols - (status_width + (border_space * 2)); - message_x = status_x + (status_width + border_space); - message_y = map_y + (map_height + border_space); - message_width = map_width; - } - else if ((status_orientation == ALIGN_LEFT) && - (message_orientation == ALIGN_LEFT)) - { - status_x = 0; - status_y = 0; - status_height = (term_rows - border_space); - status_width = 26; - message_x = status_x + (status_width + border_space); - message_y = 0; - message_height = status_height; - message_width = term_cols - (COLNO + status_width + (border_space * 3)); - map_x = message_x + (message_width + border_space); - map_y = 0; - map_height = message_height; - map_width = term_cols - (status_width + message_width + (border_space * 3)); + + /* Figure out window positions and placements. Status and message area can be aligned + based on configuration. The priority alignment-wise is: status > msgarea > game. + Define everything as taking as much space as possible and shrink/move based on + alignment positions. */ + int message_x = 0; + int message_y = 0; + int status_x = 0; + int status_y = 0; + int inv_x = 0; + int inv_y = 0; + int map_x = 0; + int map_y = 0; + + int message_height = 0; + int message_width = 0; + int status_height = 0; + int status_width = 0; + int inv_height = 0; + int inv_width = 0; + int map_height = (term_rows - border_space); + int map_width = (term_cols - border_space); + + boolean status_vertical = FALSE; + boolean msg_vertical = FALSE; + if (status_orientation == ALIGN_LEFT || + status_orientation == ALIGN_RIGHT) + status_vertical = TRUE; + if (message_orientation == ALIGN_LEFT || + message_orientation == ALIGN_RIGHT) + msg_vertical = TRUE; + + int statusheight = 3; + if (iflags.classic_status) + statusheight = 2; + + /* Vertical windows have priority. Otherwise, priotity is: + status > inv > msg */ + if (status_vertical) + set_window_position(&status_x, &status_y, &status_width, &status_height, + status_orientation, &map_x, &map_y, &map_width, &map_height, + border_space, statusheight, 26); + + if (flags.perm_invent) { + /* Take up all width unless msgbar is also vertical. */ + int width = -25; + if (msg_vertical) + width = 25; + + set_window_position(&inv_x, &inv_y, &inv_width, &inv_height, + ALIGN_RIGHT, &map_x, &map_y, &map_width, &map_height, + border_space, -1, width); } - + + if (msg_vertical) + set_window_position(&message_x, &message_y, &message_width, &message_height, + message_orientation, &map_x, &map_y, &map_width, &map_height, + border_space, -1, -25); + + /* Now draw horizontal windows */ + if (!status_vertical) + set_window_position(&status_x, &status_y, &status_width, &status_height, + status_orientation, &map_x, &map_y, &map_width, &map_height, + border_space, statusheight, 26); + + if (!msg_vertical) + set_window_position(&message_x, &message_y, &message_width, &message_height, + message_orientation, &map_x, &map_y, &map_width, &map_height, + border_space, -1, -25); + if (map_width > COLNO) - { map_width = COLNO; - } - + if (map_height > ROWNO) - { map_height = ROWNO; - } - - if (curses_window_exists(STATUS_WIN)) - { + + if (curses_get_nhwin(STATUS_WIN)) { curses_del_nhwin(STATUS_WIN); curses_del_nhwin(MESSAGE_WIN); curses_del_nhwin(MAP_WIN); + curses_del_nhwin(INV_WIN); + clear(); } curses_add_nhwin(STATUS_WIN, status_height, status_width, status_y, - status_x, status_orientation, borders); + status_x, status_orientation, borders); curses_add_nhwin(MESSAGE_WIN, message_height, message_width, message_y, - message_x, message_orientation, borders); + message_x, message_orientation, borders); + + if (flags.perm_invent) + curses_add_nhwin(INV_WIN, inv_height, inv_width, inv_y, inv_x, + ALIGN_RIGHT, borders); - curses_add_nhwin(MAP_WIN, map_height, map_width, map_y, map_x, 0, - borders); + curses_add_nhwin(MAP_WIN, map_height, map_width, map_y, map_x, 0, borders); refresh(); - + curses_refresh_nethack_windows(); - if (iflags.window_inited) - { - curses_update_stats(TRUE); - } - else - { + if (iflags.window_inited) { + curses_update_stats(); + if (flags.perm_invent) + curses_update_inventory(); + } else { iflags.window_inited = TRUE; } } @@ -551,11 +372,11 @@ void curses_create_main_windows() /* Initialize curses colors to colors used by NetHack */ -void curses_init_nhcolors() +void +curses_init_nhcolors() { #ifdef TEXTCOLOR - if (has_colors()) - { + if (has_colors()) { use_default_colors(); init_pair(1, COLOR_BLACK, -1); init_pair(2, COLOR_RED, -1); @@ -566,23 +387,39 @@ void curses_init_nhcolors() init_pair(7, COLOR_CYAN, -1); init_pair(8, -1, -1); - { - int i; - for (i = 0; i < 16; i++) { - int clr_remap[16] = { - COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, - COLOR_MAGENTA, COLOR_CYAN, -1, COLOR_WHITE, - COLOR_RED+8, COLOR_GREEN+8, COLOR_YELLOW+8, COLOR_BLUE+8, - COLOR_MAGENTA+8, COLOR_CYAN+8, COLOR_WHITE+8 - }; - init_pair(17 + (i*2) + 0, clr_remap[i], COLOR_RED); - init_pair(17 + (i*2) + 1, clr_remap[i], COLOR_BLUE); - } - } - - - if (COLORS >= 16) { + int i; + + int clr_remap[16] = { + COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, + COLOR_BLUE, + COLOR_MAGENTA, COLOR_CYAN, -1, COLOR_WHITE, + COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8, + COLOR_BLUE + 8, + COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8 + }; + + for (i = 0; i < (COLORS >= 16 ? 16 : 8); i++) { + init_pair(17 + (i * 2) + 0, clr_remap[i], COLOR_RED); + init_pair(17 + (i * 2) + 1, clr_remap[i], COLOR_BLUE); + } + + boolean hicolor = FALSE; + if (COLORS >= 16) + hicolor = TRUE; + + /* Work around the crazy definitions above for more background colors... */ + for (i = 0; i < (COLORS >= 16 ? 16 : 8); i++) { + init_pair((hicolor ? 49 : 9) + i, clr_remap[i], COLOR_GREEN); + init_pair((hicolor ? 65 : 33) + i, clr_remap[i], COLOR_YELLOW); + init_pair((hicolor ? 81 : 41) + i, clr_remap[i], COLOR_MAGENTA); + init_pair((hicolor ? 97 : 49) + i, clr_remap[i], COLOR_CYAN); + init_pair((hicolor ? 113 : 57) + i, clr_remap[i], COLOR_WHITE); + } + } + + + if (COLORS >= 16) { init_pair(9, COLOR_WHITE, -1); init_pair(10, COLOR_RED + 8, -1); init_pair(11, COLOR_GREEN + 8, -1); @@ -593,35 +430,33 @@ void curses_init_nhcolors() init_pair(16, COLOR_WHITE + 8, -1); } - if (can_change_color()) - { + if (can_change_color()) { /* Preserve initial terminal colors */ color_content(COLOR_YELLOW, &orig_yellow.r, &orig_yellow.g, - &orig_yellow.b); + &orig_yellow.b); color_content(COLOR_WHITE, &orig_white.r, &orig_white.g, - &orig_white.b); - + &orig_white.b); + /* Set colors to appear as NetHack expects */ init_color(COLOR_YELLOW, 500, 300, 0); init_color(COLOR_WHITE, 600, 600, 600); - if (COLORS >= 16) - { + if (COLORS >= 16) { /* Preserve initial terminal colors */ color_content(COLOR_RED + 8, &orig_hired.r, - &orig_hired.g, &orig_hired.b); + &orig_hired.g, &orig_hired.b); color_content(COLOR_GREEN + 8, &orig_higreen.r, - &orig_higreen.g, &orig_higreen.b); + &orig_higreen.g, &orig_higreen.b); color_content(COLOR_YELLOW + 8, &orig_hiyellow.r, - &orig_hiyellow.g, &orig_hiyellow.b); + &orig_hiyellow.g, &orig_hiyellow.b); color_content(COLOR_BLUE + 8, &orig_hiblue.r, - &orig_hiblue.g, &orig_hiblue.b); + &orig_hiblue.g, &orig_hiblue.b); color_content(COLOR_MAGENTA + 8, &orig_himagenta.r, - &orig_himagenta.g, &orig_himagenta.b); + &orig_himagenta.g, &orig_himagenta.b); color_content(COLOR_CYAN + 8, &orig_hicyan.r, - &orig_hicyan.g, &orig_hicyan.b); + &orig_hicyan.g, &orig_hicyan.b); color_content(COLOR_WHITE + 8, &orig_hiwhite.r, - &orig_hiwhite.g, &orig_hiwhite.b); - + &orig_hiwhite.g, &orig_hiwhite.b); + /* Set colors to appear as NetHack expects */ init_color(COLOR_RED + 8, 1000, 500, 0); init_color(COLOR_GREEN + 8, 0, 1000, 0); @@ -630,15 +465,16 @@ void curses_init_nhcolors() init_color(COLOR_MAGENTA + 8, 1000, 0, 1000); init_color(COLOR_CYAN + 8, 0, 1000, 1000); init_color(COLOR_WHITE + 8, 1000, 1000, 1000); -#ifdef USE_DARKGRAY - if (COLORS > 16) - { +# ifdef USE_DARKGRAY + if (COLORS > 16) { + color_content(CURSES_DARK_GRAY, &orig_darkgray.r, + &orig_darkgray.g, &orig_darkgray.b); init_color(CURSES_DARK_GRAY, 300, 300, 300); + /* just override black colorpair entry here */ + init_pair(1, CURSES_DARK_GRAY, -1); } -#endif - } - else - { +# endif + } else { /* Set flag to use bold for bright colors */ } } @@ -650,195 +486,199 @@ void curses_init_nhcolors() /* Allow player to pick character's role, race, gender, and alignment. Borrowed from the Gnome window port. */ -void curses_choose_character() +void +curses_choose_character() { int n, i, sel, count_off, pick4u; int count = 0; int cur_character = 0; - const char** choices; - int* pickmap; + const char **choices; + int *pickmap; char *prompt; char pbuf[QBUFSZ]; char choice[QBUFSZ]; char tmpchoice[QBUFSZ]; + #ifdef TUTORIAL_MODE - winid win; - anything any; - menu_item *selected = 0; + winid win; + anything any; + menu_item *selected = 0; #endif - prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, - flags.initrace, flags.initgend, flags.initalign); + prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, + flags.initrace, flags.initgend, + flags.initalign); /* This part is irritating: we have to strip the choices off of - the string and put them in a separate string in order to use - curses_character_input_dialog for this prompt. */ + the string and put them in a separate string in order to use + curses_character_input_dialog for this prompt. */ - while (cur_character != '[') - { + while (cur_character != '[') { cur_character = prompt[count]; count++; } - + count_off = count; - - while (cur_character != ']') - { + + while (cur_character != ']') { tmpchoice[count - count_off] = prompt[count]; count++; cur_character = prompt[count]; } - + tmpchoice[count - count_off] = '\0'; lcase(tmpchoice); - - while (!isspace(prompt[count_off])) - { + + while (!isspace(prompt[count_off])) { count_off--; } - + prompt[count_off] = '\0'; sprintf(choice, "%s%c", tmpchoice, '\033'); - if(strchr(tmpchoice, 't')) /* Tutorial mode */ - { + if (strchr(tmpchoice, 't')) { /* Tutorial mode */ mvaddstr(0, 1, "New? Press t to enter a tutorial."); } - + /* Add capital letters as choices that aren't displayed */ - - for (count = 0; tmpchoice[count]; count++) - { + + for (count = 0; tmpchoice[count]; count++) { tmpchoice[count] = toupper(tmpchoice[count]); } - + sprintf(choice, "%s%s", choice, tmpchoice); /* prevent an unnecessary prompt */ - rigid_role_checks(); - - if (!flags.randomall && - (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || - flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) - { - pick4u = tolower(curses_character_input_dialog(prompt, choice, - 'y')); - } - else - { + rigid_role_checks(); + + if (!flags.randomall && + (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || + flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) { + pick4u = tolower(curses_character_input_dialog(prompt, choice, 'y')); + } else { pick4u = 'y'; } - - if (pick4u == 'q') /* Quit or cancelled */ - { - clearlocks(); - curses_bail(0); + + if (pick4u == 'q') { /* Quit or cancelled */ + clearlocks(); + curses_bail(0); } - - if (pick4u == 'y') - { + + if (pick4u == 'y') { flags.randomall = TRUE; } #ifdef TUTORIAL_MODE - else if (pick4u == 't') /* Tutorial mode in UnNetHack */ - { - clear(); + else if (pick4u == 't') { /* Tutorial mode in UnNetHack */ + clear(); mvaddstr(0, 1, "Choose a character"); refresh(); - win = curses_get_wid(NHW_MENU); + win = curses_get_wid(NHW_MENU); curses_create_nhmenu(win); - any.a_int = 1; - curses_add_menu(win, NO_GLYPH, &any, 'v', 0, ATR_NONE, - "lawful female dwarf Valkyrie (uses melee and thrown weapons)", - MENU_UNSELECTED); - any.a_int = 2; - curses_add_menu(win, NO_GLYPH, &any, 'w', 0, ATR_NONE, - "chaotic male elf Wizard (relies mostly on spells)", - MENU_UNSELECTED); - any.a_int = 3; - curses_add_menu(win, NO_GLYPH, &any, 'R', 0, ATR_NONE, - "neutral female human Ranger (good with ranged combat)", - MENU_UNSELECTED); - any.a_int = 4; - curses_add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, - "quit", MENU_UNSELECTED); - curses_end_menu(win, "What character do you want to try?"); - n = curses_select_menu(win, PICK_ONE, &selected); - destroy_nhwindow(win); - if (n != 1 || selected[0].item.a_int == 4) - { - clearlocks(); - curses_bail(0); - } - switch (selected[0].item.a_int) { - case 1: - flags.initrole = str2role("Valkyrie"); - flags.initrace = str2race("dwarf"); - flags.initgend = str2gend("female"); - flags.initalign = str2align("lawful"); - break; - case 2: - flags.initrole = str2role("Wizard"); - flags.initrace = str2race("elf"); - flags.initgend = str2gend("male"); - flags.initalign = str2align("chaotic"); - break; - case 3: - flags.initrole = str2role("Ranger"); - flags.initrace = str2race("human"); - flags.initgend = str2gend("female"); - flags.initalign = str2align("neutral"); - break; - default: panic("Impossible menu selection"); break; - } - free((genericptr_t) selected); - selected = 0; - flags.tutorial = 1; - } + any.a_int = 1; + curses_add_menu(win, NO_GLYPH, &any, 'v', 0, ATR_NONE, + "lawful female dwarf Valkyrie (uses melee and thrown weapons)", + MENU_UNSELECTED); + any.a_int = 2; + curses_add_menu(win, NO_GLYPH, &any, 'w', 0, ATR_NONE, + "chaotic male elf Wizard (relies mostly on spells)", + MENU_UNSELECTED); + any.a_int = 3; + curses_add_menu(win, NO_GLYPH, &any, 'R', 0, ATR_NONE, + "neutral female human Ranger (good with ranged combat)", + MENU_UNSELECTED); + any.a_int = 4; + curses_add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, + "quit", MENU_UNSELECTED); + curses_end_menu(win, "What character do you want to try?"); + n = curses_select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == 4) { + clearlocks(); + curses_bail(0); + } + switch (selected[0].item.a_int) { + case 1: + flags.initrole = str2role("Valkyrie"); + flags.initrace = str2race("dwarf"); + flags.initgend = str2gend("female"); + flags.initalign = str2align("lawful"); + break; + case 2: + flags.initrole = str2role("Wizard"); + flags.initrace = str2race("elf"); + flags.initgend = str2gend("male"); + flags.initalign = str2align("chaotic"); + break; + case 3: + flags.initrole = str2role("Ranger"); + flags.initrace = str2race("human"); + flags.initgend = str2gend("female"); + flags.initalign = str2align("neutral"); + break; + default: + panic("Impossible menu selection"); + break; + } + free((genericptr_t) selected); + selected = 0; + flags.tutorial = 1; + } #endif - + clear(); refresh(); if (!flags.randomall && flags.initrole < 0) { - /* select a role */ - for (n = 0; roles[n].name.m; n++) continue; - choices = (const char **)alloc(sizeof(char *) * (n+1)); - pickmap = (int*)alloc(sizeof(int) * (n+1)); - for (;;) { - for (n = 0, i = 0; roles[i].name.m; i++) { - if (ok_role(i, flags.initrace, - flags.initgend, flags.initalign)) { - if (flags.initgend >= 0 && flags.female && roles[i].name.f) - choices[n] = roles[i].name.f; - else - choices[n] = roles[i].name.m; - pickmap[n++] = i; - } - } - if (n > 0) break; - else if (flags.initalign >= 0) flags.initalign = -1; /* reset */ - else if (flags.initgend >= 0) flags.initgend = -1; - else if (flags.initrace >= 0) flags.initrace = -1; - else panic("no available ROLE+race+gender+alignment combinations"); - } - choices[n] = (const char *) 0; - if (n > 1) - sel = curses_character_dialog(choices, "Choose one of the following roles:"); - else sel = 0; - if (sel >= 0) sel = pickmap[sel]; - else if (sel == ROLE_NONE) { /* Quit */ - clearlocks(); - curses_bail(0); - } - free(choices); - free(pickmap); - } else if (flags.initrole < 0) sel = ROLE_RANDOM; - else sel = flags.initrole; - - if (sel == ROLE_RANDOM) { /* Random role */ - sel = pick_role(flags.initrace, flags.initgend, - flags.initalign, PICK_RANDOM); - if (sel < 0) sel = randrole(); + /* select a role */ + for (n = 0; roles[n].name.m; n++) + continue; + choices = (const char **) alloc(sizeof (char *) * (n + 1)); + pickmap = (int *) alloc(sizeof (int) * (n + 1)); + for (;;) { + for (n = 0, i = 0; roles[i].name.m; i++) { + if (ok_role(i, flags.initrace, flags.initgend, flags.initalign)) { + if (flags.initgend >= 0 && flags.female && roles[i].name.f) + choices[n] = roles[i].name.f; + else + choices[n] = roles[i].name.m; + pickmap[n++] = i; + } + } + if (n > 0) + break; + else if (flags.initalign >= 0) + flags.initalign = -1; /* reset */ + else if (flags.initgend >= 0) + flags.initgend = -1; + else if (flags.initrace >= 0) + flags.initrace = -1; + else + panic("no available ROLE+race+gender+alignment combinations"); + } + choices[n] = (const char *) 0; + if (n > 1) + sel = + curses_character_dialog(choices, + "Choose one of the following roles:"); + else + sel = 0; + if (sel >= 0) + sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + curses_bail(0); + } + free(choices); + free(pickmap); + } else if (flags.initrole < 0) + sel = ROLE_RANDOM; + else + sel = flags.initrole; + + if (sel == ROLE_RANDOM) { /* Random role */ + sel = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (sel < 0) + sel = randrole(); } flags.initrole = sel; @@ -847,165 +687,182 @@ void curses_choose_character() /* force compatibility with role, try for compatibility with * pre-selected gender/alignment */ if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { - if (flags.initrace == ROLE_RANDOM || flags.randomall) { - flags.initrace = pick_race(flags.initrole, flags.initgend, - flags.initalign, PICK_RANDOM); - if (flags.initrace < 0) flags.initrace = randrace(flags.initrole); - } else { - /* Count the number of valid races */ - n = 0; /* number valid */ - for (i = 0; races[i].noun; i++) { - if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) - n++; - } - if (n == 0) { - for (i = 0; races[i].noun; i++) { - if (validrace(flags.initrole, i)) n++; - } - } - - choices = (const char **)alloc(sizeof(char *) * (n+1)); - pickmap = (int*)alloc(sizeof(int) * (n + 1)); - for (n = 0, i = 0; races[i].noun; i++) { - if (ok_race(flags.initrole, i, flags.initgend, - flags.initalign)) { - choices[n] = races[i].noun; - pickmap[n++] = i; - } - } - choices[n] = (const char *) 0; - /* Permit the user to pick, if there is more than one */ - if (n > 1) - sel = curses_character_dialog(choices, "Choose one of the following races:"); - else sel = 0; - if (sel >= 0) sel = pickmap[sel]; - else if (sel == ROLE_NONE) { /* Quit */ - clearlocks(); - curses_bail(0); - } - flags.initrace = sel; - free(choices); - free(pickmap); - } - if (flags.initrace == ROLE_RANDOM) { /* Random role */ - sel = pick_race(flags.initrole, flags.initgend, - flags.initalign, PICK_RANDOM); - if (sel < 0) sel = randrace(flags.initrole); - flags.initrace = sel; - } + if (flags.initrace == ROLE_RANDOM || flags.randomall) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) + flags.initrace = randrace(flags.initrole); + } else { + /* Count the number of valid races */ + n = 0; /* number valid */ + for (i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) + n++; + } + if (n == 0) { + for (i = 0; races[i].noun; i++) { + if (validrace(flags.initrole, i)) + n++; + } + } + + choices = (const char **) alloc(sizeof (char *) * (n + 1)); + pickmap = (int *) alloc(sizeof (int) * (n + 1)); + for (n = 0, i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { + choices[n] = races[i].noun; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = + curses_character_dialog(choices, + "Choose one of the following races:"); + else + sel = 0; + if (sel >= 0) + sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + curses_bail(0); + } + flags.initrace = sel; + free(choices); + free(pickmap); + } + if (flags.initrace == ROLE_RANDOM) { /* Random role */ + sel = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (sel < 0) + sel = randrace(flags.initrole); + flags.initrace = sel; + } } /* Select a gender, if necessary */ /* force compatibility with role/race, try for compatibility with * pre-selected alignment */ if (flags.initgend < 0 || - !validgend(flags.initrole, flags.initrace, flags.initgend)) { - if (flags.initgend == ROLE_RANDOM || flags.randomall) { - flags.initgend = pick_gend(flags.initrole, flags.initrace, - flags.initalign, PICK_RANDOM); - if (flags.initgend < 0) - flags.initgend = randgend(flags.initrole, flags.initrace); - } else { - /* Count the number of valid genders */ - n = 0; /* number valid */ - for (i = 0; i < ROLE_GENDERS; i++) { - if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) - n++; - } - if (n == 0) { - for (i = 0; i < ROLE_GENDERS; i++) { - if (validgend(flags.initrole, flags.initrace, i)) n++; - } - } - - choices = (const char **)alloc(sizeof(char *) * (n+1)); - pickmap = (int*)alloc(sizeof(int) * (n + 1)); - for (n = 0, i = 0; i < ROLE_GENDERS; i++) { - if (ok_gend(flags.initrole, flags.initrace, i, - flags.initalign)) { - choices[n] = genders[i].adj; - pickmap[n++] = i; - } - } - choices[n] = (const char *) 0; - /* Permit the user to pick, if there is more than one */ - if (n > 1) - sel = curses_character_dialog(choices, "Choose one of the following genders:"); - else sel = 0; - if (sel >= 0) sel = pickmap[sel]; - else if (sel == ROLE_NONE) { /* Quit */ - clearlocks(); - curses_bail(0); - } - flags.initgend = sel; - free(choices); - free(pickmap); - } - if (flags.initgend == ROLE_RANDOM) { /* Random gender */ - sel = pick_gend(flags.initrole, flags.initrace, - flags.initalign, PICK_RANDOM); - if (sel < 0) sel = randgend(flags.initrole, flags.initrace); - flags.initgend = sel; - } + !validgend(flags.initrole, flags.initrace, flags.initgend)) { + if (flags.initgend == ROLE_RANDOM || flags.randomall) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) + flags.initgend = randgend(flags.initrole, flags.initrace); + } else { + /* Count the number of valid genders */ + n = 0; /* number valid */ + for (i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) + n++; + } + if (n == 0) { + for (i = 0; i < ROLE_GENDERS; i++) { + if (validgend(flags.initrole, flags.initrace, i)) + n++; + } + } + + choices = (const char **) alloc(sizeof (char *) * (n + 1)); + pickmap = (int *) alloc(sizeof (int) * (n + 1)); + for (n = 0, i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { + choices[n] = genders[i].adj; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = + curses_character_dialog(choices, + "Choose one of the following genders:"); + else + sel = 0; + if (sel >= 0) + sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + curses_bail(0); + } + flags.initgend = sel; + free(choices); + free(pickmap); + } + if (flags.initgend == ROLE_RANDOM) { /* Random gender */ + sel = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (sel < 0) + sel = randgend(flags.initrole, flags.initrace); + flags.initgend = sel; + } } /* Select an alignment, if necessary */ /* force compatibility with role/race/gender */ if (flags.initalign < 0 || - !validalign(flags.initrole, flags.initrace, flags.initalign)) { - if (flags.initalign == ROLE_RANDOM || flags.randomall) { - flags.initalign = pick_align(flags.initrole, flags.initrace, - flags.initgend, PICK_RANDOM); - if (flags.initalign < 0) - flags.initalign = randalign(flags.initrole, flags.initrace); - } else { - /* Count the number of valid alignments */ - n = 0; /* number valid */ - for (i = 0; i < ROLE_ALIGNS; i++) { - if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) - n++; - } - if (n == 0) { - for (i = 0; i < ROLE_ALIGNS; i++) - if (validalign(flags.initrole, flags.initrace, i)) n++; - } - - choices = (const char **)alloc(sizeof(char *) * (n+1)); - pickmap = (int*)alloc(sizeof(int) * (n + 1)); - for (n = 0, i = 0; i < ROLE_ALIGNS; i++) { - if (ok_align(flags.initrole, - flags.initrace, flags.initgend, i)) { - choices[n] = aligns[i].adj; - pickmap[n++] = i; - } - } - choices[n] = (const char *) 0; - /* Permit the user to pick, if there is more than one */ - if (n > 1) - sel = curses_character_dialog(choices, "Choose one of the following alignments:"); - else sel = 0; - if (sel >= 0) sel = pickmap[sel]; - else if (sel == ROLE_NONE) { /* Quit */ - clearlocks(); - curses_bail(0); - } - flags.initalign = sel; - free(choices); - free(pickmap); - } - if (flags.initalign == ROLE_RANDOM) { - sel = pick_align(flags.initrole, flags.initrace, - flags.initgend, PICK_RANDOM); - if (sel < 0) sel = randalign(flags.initrole, flags.initrace); - flags.initalign = sel; - } + !validalign(flags.initrole, flags.initrace, flags.initalign)) { + if (flags.initalign == ROLE_RANDOM || flags.randomall) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) + flags.initalign = randalign(flags.initrole, flags.initrace); + } else { + /* Count the number of valid alignments */ + n = 0; /* number valid */ + for (i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) + n++; + } + if (n == 0) { + for (i = 0; i < ROLE_ALIGNS; i++) + if (validalign(flags.initrole, flags.initrace, i)) + n++; + } + + choices = (const char **) alloc(sizeof (char *) * (n + 1)); + pickmap = (int *) alloc(sizeof (int) * (n + 1)); + for (n = 0, i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { + choices[n] = aligns[i].adj; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = + curses_character_dialog(choices, + "Choose one of the following alignments:"); + else + sel = 0; + if (sel >= 0) + sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + curses_bail(0); + } + flags.initalign = sel; + free(choices); + free(pickmap); + } + if (flags.initalign == ROLE_RANDOM) { + sel = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (sel < 0) + sel = randalign(flags.initrole, flags.initrace); + flags.initalign = sel; + } } } /* Prompt user for character race, role, alignment, or gender */ -int curses_character_dialog(const char** choices, const char *prompt) +int +curses_character_dialog(const char **choices, const char *prompt) { int count, count2, ret, curletter; char used_letters[52]; @@ -1016,48 +873,42 @@ int curses_character_dialog(const char** choices, const char *prompt) identifier.a_void = 0; curses_start_menu(wid); - for (count=0; choices[count]; count++) - { - curletter=tolower(choices[count][0]); - for (count2=0; count2item.a_int); - } - else /* Cancelled selection */ - { + } else { /* Cancelled selection */ + ret = ROLE_NONE; } - - if (ret > 0) - { + + if (ret > 0) { ret--; } - + free(selected); return ret; } @@ -1065,77 +916,67 @@ int curses_character_dialog(const char** choices, const char *prompt) /* Initialize and display options appropriately */ -void curses_init_options() +void +curses_init_options() { - set_wc_option_mod_status(WC_ALIGN_MESSAGE|WC_ALIGN_STATUS|WC_COLOR| - WC_HILITE_PET|WC_POPUP_DIALOG, SET_IN_GAME); + set_wc_option_mod_status(WC_ALIGN_MESSAGE | WC_ALIGN_STATUS | WC_COLOR | + WC_HILITE_PET | WC_POPUP_DIALOG, SET_IN_GAME); set_wc2_option_mod_status(WC2_GUICOLOR, SET_IN_GAME); /* Remove a few options that are irrelevant to this windowport */ set_option_mod_status("DECgraphics", SET_IN_FILE); - set_option_mod_status("perm_invent", SET_IN_FILE); set_option_mod_status("eight_bit_tty", SET_IN_FILE); + /* Add those that are */ + set_option_mod_status("classic_status", SET_IN_GAME); + /* Make sure that DECgraphics is not set to true via the config - file, as this will cause display issues. We can't disable it in - options.c in case the game is compiled with both tty and curses.*/ - if (iflags.DECgraphics) - { + file, as this will cause display issues. We can't disable it in + options.c in case the game is compiled with both tty and curses. */ + if (iflags.DECgraphics) { switch_graphics(CURS_GRAPHICS); } - #ifdef PDCURSES /* PDCurses for SDL, win32 and OS/2 has the ability to set the - terminal size programatically. If the user does not specify a - size in the config file, we will set it to a nice big 110x32 to - take advantage of some of the nice features of this windowport. */ - if (iflags.wc2_term_cols == 0) - { + terminal size programatically. If the user does not specify a + size in the config file, we will set it to a nice big 110x32 to + take advantage of some of the nice features of this windowport. */ + if (iflags.wc2_term_cols == 0) { iflags.wc2_term_cols = 110; } - - if (iflags.wc2_term_rows == 0) - { + + if (iflags.wc2_term_rows == 0) { iflags.wc2_term_rows = 32; } - + resize_term(iflags.wc2_term_rows, iflags.wc2_term_cols); getmaxyx(base_term, term_rows, term_cols); - + /* This is needed for an odd bug with PDCurses-SDL */ switch_graphics(ASCII_GRAPHICS); - if (iflags.IBMgraphics) - { + if (iflags.IBMgraphics) { switch_graphics(IBM_GRAPHICS); - } - else if (iflags.cursesgraphics) - { + } else if (iflags.cursesgraphics) { switch_graphics(CURS_GRAPHICS); - } - else - { + } else { switch_graphics(ASCII_GRAPHICS); } -#endif /* PDCURSES */ - if (!iflags.wc2_windowborders) - { - iflags.wc2_windowborders = 3; /* Set to auto if not specified */ +#endif /* PDCURSES */ + if (!iflags.wc2_windowborders) { + iflags.wc2_windowborders = 3; /* Set to auto if not specified */ } - - if (!iflags.wc2_petattr) - { + + if (!iflags.wc2_petattr) { iflags.wc2_petattr = A_REVERSE; - } - else /* Pet attribute specified, so hilite_pet should be true */ - { + } else { /* Pet attribute specified, so hilite_pet should be true */ + iflags.hilite_pet = TRUE; } #ifdef NCURSES_MOUSE_VERSION - if (iflags.wc_mouse_support) - { - mousemask(BUTTON1_CLICKED, NULL); + if (iflags.wc_mouse_support) { + mousemask(BUTTON1_CLICKED, NULL); } #endif } @@ -1143,91 +984,103 @@ void curses_init_options() /* Display an ASCII splash screen if the splash_screen option is set */ -void curses_display_splash_window() +void +curses_display_splash_window() { - int x_start = 1; - int y_start = 6; - int which_variant = NETHACK_CURSES; /* Default to NetHack */ + int x_start; + int y_start; + int which_variant = NETHACK_CURSES; /* Default to NetHack */ + curses_get_window_xy(MAP_WIN, &x_start, &y_start); - if ((term_cols < 70) || (term_rows < 20)) - { - iflags.wc_splash_screen = FALSE; /* No room for s.s. */ + if ((term_cols < 70) || (term_rows < 20)) { + iflags.wc_splash_screen = FALSE; /* No room for s.s. */ } - #ifdef DEF_GAME_NAME - if (strcmp(DEF_GAME_NAME, "SlashEM") == 0) - { + if (strcmp(DEF_GAME_NAME, "SlashEM") == 0) { which_variant = SLASHEM_CURSES; } #endif #ifdef GAME_SHORT_NAME - if (strcmp(GAME_SHORT_NAME, "UNH") == 0) - { + if (strcmp(GAME_SHORT_NAME, "UNH") == 0) { which_variant = UNNETHACK_CURSES; } #endif - if (strncmp("SporkHack", COPYRIGHT_BANNER_A, 9) == 0) - { + if (strncmp("SporkHack", COPYRIGHT_BANNER_A, 9) == 0) { which_variant = SPORKHACK_CURSES; } - curses_toggle_color_attr(stdscr, CLR_WHITE, A_NORMAL, ON); + if (strncmp("GruntHack", COPYRIGHT_BANNER_A, 9) == 0) { + which_variant = GRUNTHACK_CURSES; + } - if (iflags.wc_splash_screen) - { - switch (which_variant) - { - case NETHACK_CURSES: - { - mvaddstr(y_start, x_start, NETHACK_SPLASH_A); - mvaddstr(y_start + 1, x_start, NETHACK_SPLASH_B); - mvaddstr(y_start + 2, x_start, NETHACK_SPLASH_C); - mvaddstr(y_start + 3, x_start, NETHACK_SPLASH_D); - mvaddstr(y_start + 4, x_start, NETHACK_SPLASH_E); - mvaddstr(y_start + 5, x_start, NETHACK_SPLASH_F); - y_start += 7; - break; - } - case SLASHEM_CURSES: - { - mvaddstr(y_start, x_start, SLASHEM_SPLASH_A); - mvaddstr(y_start + 1, x_start, SLASHEM_SPLASH_B); - mvaddstr(y_start + 2, x_start, SLASHEM_SPLASH_C); - mvaddstr(y_start + 3, x_start, SLASHEM_SPLASH_D); - mvaddstr(y_start + 4, x_start, SLASHEM_SPLASH_E); - mvaddstr(y_start + 5, x_start, SLASHEM_SPLASH_F); - y_start += 7; - break; - } - case UNNETHACK_CURSES: - { - mvaddstr(y_start, x_start, UNNETHACK_SPLASH_A); - mvaddstr(y_start + 1, x_start, UNNETHACK_SPLASH_B); - mvaddstr(y_start + 2, x_start, UNNETHACK_SPLASH_C); - mvaddstr(y_start + 3, x_start, UNNETHACK_SPLASH_D); - mvaddstr(y_start + 4, x_start, UNNETHACK_SPLASH_E); - mvaddstr(y_start + 5, x_start, UNNETHACK_SPLASH_F); - y_start += 7; - break; - } - case SPORKHACK_CURSES: - mvaddstr(y_start, x_start, SPORKHACK_SPLASH_A); - mvaddstr(y_start + 1, x_start, SPORKHACK_SPLASH_B); - mvaddstr(y_start + 2, x_start, SPORKHACK_SPLASH_C); - mvaddstr(y_start + 3, x_start, SPORKHACK_SPLASH_D); - mvaddstr(y_start + 4, x_start, SPORKHACK_SPLASH_E); - mvaddstr(y_start + 5, x_start, SPORKHACK_SPLASH_F); - mvaddstr(y_start + 6, x_start, SPORKHACK_SPLASH_G); - mvaddstr(y_start + 7, x_start, SPORKHACK_SPLASH_H); - y_start += 9; - break; - default: - { - impossible("which_variant number %d out of range", - which_variant); - } + if (strncmp("dNethack", COPYRIGHT_BANNER_A, 8) == 0) { + which_variant = DNETHACK_CURSES; + } + + + curses_toggle_color_attr(stdscr, CLR_WHITE, A_NORMAL, ON); + if (iflags.wc_splash_screen) { + switch (which_variant) { + case NETHACK_CURSES: + mvaddstr(y_start, x_start, NETHACK_SPLASH_A); + mvaddstr(y_start + 1, x_start, NETHACK_SPLASH_B); + mvaddstr(y_start + 2, x_start, NETHACK_SPLASH_C); + mvaddstr(y_start + 3, x_start, NETHACK_SPLASH_D); + mvaddstr(y_start + 4, x_start, NETHACK_SPLASH_E); + mvaddstr(y_start + 5, x_start, NETHACK_SPLASH_F); + y_start += 7; + break; + case SLASHEM_CURSES: + mvaddstr(y_start, x_start, SLASHEM_SPLASH_A); + mvaddstr(y_start + 1, x_start, SLASHEM_SPLASH_B); + mvaddstr(y_start + 2, x_start, SLASHEM_SPLASH_C); + mvaddstr(y_start + 3, x_start, SLASHEM_SPLASH_D); + mvaddstr(y_start + 4, x_start, SLASHEM_SPLASH_E); + mvaddstr(y_start + 5, x_start, SLASHEM_SPLASH_F); + y_start += 7; + break; + case UNNETHACK_CURSES: + mvaddstr(y_start, x_start, UNNETHACK_SPLASH_A); + mvaddstr(y_start + 1, x_start, UNNETHACK_SPLASH_B); + mvaddstr(y_start + 2, x_start, UNNETHACK_SPLASH_C); + mvaddstr(y_start + 3, x_start, UNNETHACK_SPLASH_D); + mvaddstr(y_start + 4, x_start, UNNETHACK_SPLASH_E); + mvaddstr(y_start + 5, x_start, UNNETHACK_SPLASH_F); + y_start += 7; + break; + case SPORKHACK_CURSES: + mvaddstr(y_start, x_start, SPORKHACK_SPLASH_A); + mvaddstr(y_start + 1, x_start, SPORKHACK_SPLASH_B); + mvaddstr(y_start + 2, x_start, SPORKHACK_SPLASH_C); + mvaddstr(y_start + 3, x_start, SPORKHACK_SPLASH_D); + mvaddstr(y_start + 4, x_start, SPORKHACK_SPLASH_E); + mvaddstr(y_start + 5, x_start, SPORKHACK_SPLASH_F); + mvaddstr(y_start + 6, x_start, SPORKHACK_SPLASH_G); + mvaddstr(y_start + 7, x_start, SPORKHACK_SPLASH_H); + y_start += 9; + break; + case GRUNTHACK_CURSES: + mvaddstr(y_start, x_start, GRUNTHACK_SPLASH_A); + mvaddstr(y_start + 1, x_start, GRUNTHACK_SPLASH_B); + mvaddstr(y_start + 2, x_start, GRUNTHACK_SPLASH_C); + mvaddstr(y_start + 3, x_start, GRUNTHACK_SPLASH_D); + mvaddstr(y_start + 4, x_start, GRUNTHACK_SPLASH_E); + mvaddstr(y_start + 5, x_start, GRUNTHACK_SPLASH_F); + y_start += 7; + break; + case DNETHACK_CURSES: + mvaddstr(y_start, x_start, DNETHACK_SPLASH_A); + mvaddstr(y_start + 1, x_start, DNETHACK_SPLASH_B); + mvaddstr(y_start + 2, x_start, DNETHACK_SPLASH_C); + mvaddstr(y_start + 3, x_start, DNETHACK_SPLASH_D); + mvaddstr(y_start + 4, x_start, DNETHACK_SPLASH_E); + mvaddstr(y_start + 5, x_start, DNETHACK_SPLASH_F); + y_start += 7; + break; + default: + impossible("which_variant number %d out of range", which_variant); } } @@ -1248,7 +1101,7 @@ void curses_display_splash_window() y_start++; #endif -#ifdef COPYRIGHT_BANNER_D /* Just in case */ +#ifdef COPYRIGHT_BANNER_D /* Just in case */ mvaddstr(y_start, x_start, COPYRIGHT_BANNER_D); y_start++; #endif @@ -1258,41 +1111,35 @@ void curses_display_splash_window() /* Resore colors and cursor state before exiting */ -void curses_cleanup() +void +curses_cleanup() { #ifdef TEXTCOLOR - if (has_colors() && can_change_color()) - { - init_color(COLOR_YELLOW, orig_yellow.r, orig_yellow.g, - orig_yellow.b); - init_color(COLOR_WHITE, orig_white.r, orig_white.g, - orig_white.b); - - if (COLORS >= 16) - { - init_color(COLOR_RED + 8, orig_hired.r, orig_hired.g, - orig_hired.b); + if (has_colors() && can_change_color()) { + init_color(COLOR_YELLOW, orig_yellow.r, orig_yellow.g, orig_yellow.b); + init_color(COLOR_WHITE, orig_white.r, orig_white.g, orig_white.b); + + if (COLORS >= 16) { + init_color(COLOR_RED + 8, orig_hired.r, orig_hired.g, orig_hired.b); init_color(COLOR_GREEN + 8, orig_higreen.r, orig_higreen.g, - orig_higreen.b); + orig_higreen.b); init_color(COLOR_YELLOW + 8, orig_hiyellow.r, - orig_hiyellow.g, orig_hiyellow.b); + orig_hiyellow.g, orig_hiyellow.b); init_color(COLOR_BLUE + 8, orig_hiblue.r, orig_hiblue.g, - orig_hiblue.b); + orig_hiblue.b); init_color(COLOR_MAGENTA + 8, orig_himagenta.r, - orig_himagenta.g, orig_himagenta.b); + orig_himagenta.g, orig_himagenta.b); init_color(COLOR_CYAN + 8, orig_hicyan.r, orig_hicyan.g, - orig_hicyan.b); + orig_hicyan.b); init_color(COLOR_WHITE + 8, orig_hiwhite.r, orig_hiwhite.g, - orig_hiwhite.b); + orig_hiwhite.b); # ifdef USE_DARKGRAY - if (COLORS > 16) - { + if (COLORS > 16) { init_color(CURSES_DARK_GRAY, orig_darkgray.r, - orig_darkgray.g, orig_darkgray.b); + orig_darkgray.g, orig_darkgray.b); } # endif } } #endif } - diff --git a/win/curses/cursinit.h b/win/curses/cursinit.h index 94459622..c7f39004 100644 --- a/win/curses/cursinit.h +++ b/win/curses/cursinit.h @@ -1,21 +1,17 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSINIT_H -#define CURSINIT_H +# define CURSINIT_H /* Global declarations */ void curses_create_main_windows(void); - void curses_init_nhcolors(void); - void curses_choose_character(void); - -int curses_character_dialog(const char** choices, const char *prompt); - +int curses_character_dialog(const char **choices, const char *prompt); void curses_init_options(void); - void curses_display_splash_window(void); - void curses_cleanup(void); -#endif /* CURSINIT_H */ +#endif /* CURSINIT_H */ diff --git a/win/curses/cursinvt.c b/win/curses/cursinvt.c new file mode 100644 index 00000000..f1a022b2 --- /dev/null +++ b/win/curses/cursinvt.c @@ -0,0 +1,112 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + +#include "curses.h" +#include "hack.h" +#include "wincurs.h" +#include "cursinvt.h" + +/* Permanent inventory for curses interface */ + +/* Runs when the game indicates that the inventory has been updated */ +void +curses_update_inv(void) +{ + WINDOW *win = curses_get_nhwin(INV_WIN); + + /* Check if the inventory window is enabled in first place */ + if (!win) { + /* It's not. Re-initialize the main windows if the + option was enabled. */ + if (flags.perm_invent) { + curses_create_main_windows(); + curses_last_messages(); + doredraw(); + } + return; + } + + boolean border = curses_window_has_border(INV_WIN); + + /* Figure out drawing area */ + int x = 0; + int y = 0; + if (border) { + x++; + y++; + } + + /* Clear the window as it is at the moment. */ + werase(win); + + wmove(win, y, x); + attr_t attr = A_UNDERLINE; + wattron(win, attr); + wprintw(win, "Inventory:"); + wattroff(win, attr); + + /* The actual inventory will override this if we do carry stuff */ + wmove(win, y + 1, x); + wprintw(win, "Not carrying anything"); + + display_inventory(NULL, FALSE); + + if (border) + box(win, 0, 0); + + wnoutrefresh(win); +} + +/* Adds an inventory item. */ +void +curses_add_inv(int y, int glyph, CHAR_P accelerator, attr_t attr, + const char *str) +{ + WINDOW *win = curses_get_nhwin(INV_WIN); + + /* Figure out where to draw the line */ + int x = 0; + if (curses_window_has_border(INV_WIN)) { + x++; + y++; + } + + wmove(win, y, x); + if (accelerator) { + attr_t bold = A_BOLD; + wattron(win, bold); + waddch(win, accelerator); + wattroff(win, bold); + wprintw(win, ") "); + } + + if (accelerator && glyph != NO_GLYPH && iflags.use_menu_glyphs) { + unsigned dummy = 0; /* Not used */ + int color = 0; + int symbol = 0; + mapglyph(glyph, &symbol, &color, &dummy, + u.ux, u.uy); + attr_t glyphclr = curses_color_attr(color, 0); + wattron(win, glyphclr); + wprintw(win, "%c ", symbol); + wattroff(win, glyphclr); + } + +#ifdef MENU_COLOR + if (accelerator && /* Don't colorize categories */ + iflags.use_menu_color) { + int color = NO_COLOR; + boolean menu_color = FALSE; + char str_mutable[BUFSZ]; + Strcpy(str_mutable, str); + attr = 0; + get_menu_coloring(str_mutable, &color, &attr); + if (color != NO_COLOR) + attr |= curses_color_attr(color, 0); + } +#endif + + wattron(win, attr); + wprintw(win, "%s", str); + wattroff(win, attr); + wclrtoeol(win); +} diff --git a/win/curses/cursinvt.h b/win/curses/cursinvt.h new file mode 100644 index 00000000..99c90d27 --- /dev/null +++ b/win/curses/cursinvt.h @@ -0,0 +1,11 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + +#ifndef CURSINVT_H +# define CURSINVT_H + + +/* Global declarations */ + +void curses_update_inv(void); + +#endif /* CURSINVT_H */ diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index ff2a47c9..efcb585b 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "patchlevel.h" @@ -9,10 +11,10 @@ /* Interface definition, for windows.c */ struct window_procs curses_procs = { "curses", - WC_ALIGN_MESSAGE|WC_ALIGN_STATUS|WC_COLOR|WC_HILITE_PET| - WC_POPUP_DIALOG|WC_SPLASH_SCREEN, - WC2_TERM_COLS|WC2_TERM_ROWS|WC2_WINDOWBORDERS|WC2_PETATTR| - WC2_GUICOLOR, + WC_ALIGN_MESSAGE | WC_ALIGN_STATUS | WC_COLOR | WC_HILITE_PET | + WC_POPUP_DIALOG | WC_SPLASH_SCREEN, + WC2_TERM_COLS | WC2_TERM_ROWS | WC2_WINDOWBORDERS | WC2_PETATTR | + WC2_GUICOLOR, curses_init_nhwindows, curses_player_selection, curses_askname, @@ -53,7 +55,7 @@ struct window_procs curses_procs = { curses_get_ext_cmd, curses_number_pad, curses_delay_output, -#ifdef CHANGE_COLOR /* only a Mac option currently */ +#ifdef CHANGE_COLOR /* only a Mac option currently */ donull, donull, #endif @@ -63,6 +65,11 @@ struct window_procs curses_procs = { curses_preference_update, }; +/* Track if we're performing an update to the permanent window. + Needed since we aren't using the normal menu functions to handle + the inventory window. */ +static int inv_update = 0; + /* init_nhwindows(int* argcp, char** argv) -- Initialize the windows used by NetHack. This can also @@ -77,7 +84,8 @@ init_nhwindows(int* argcp, char** argv) ** Why not have init_nhwindows() create all of the "standard" ** windows? Or at least all but WIN_INFO? -dean */ -void curses_init_nhwindows(int* argcp, char** argv) +void +curses_init_nhwindows(int *argcp, char **argv) { #ifdef PDCURSES char window_title[BUFSZ]; @@ -89,23 +97,20 @@ void curses_init_nhwindows(int* argcp, char** argv) base_term = initscr(); #endif #ifdef TEXTCOLOR - if (has_colors()) - { + if (has_colors()) { start_color(); curses_init_nhcolors(); - } - else - { + } else { iflags.use_color = FALSE; set_option_mod_status("color", SET_IN_FILE); iflags.wc2_guicolor = FALSE; - set_wc2_option_mod_status(WC2_GUICOLOR, SET_IN_FILE); + set_wc2_option_mod_status(WC2_GUICOLOR, SET_IN_FILE); } #else iflags.use_color = FALSE; - set_option_mod_status("color", SET_IN_FILE); + set_option_mod_status("color", SET_IN_FILE); iflags.wc2_guicolor = FALSE; - set_wc2_option_mod_status(WC2_GUICOLOR, SET_IN_FILE); + set_wc2_option_mod_status(WC2_GUICOLOR, SET_IN_FILE); #endif noecho(); raw(); @@ -114,36 +119,37 @@ void curses_init_nhwindows(int* argcp, char** argv) keypad(stdscr, TRUE); #ifdef NCURSES_VERSION # ifdef __APPLE__ - ESCDELAY = 25; + ESCDELAY = 25; # else set_escdelay(25); -# endif /* __APPLE__ */ -#endif /* NCURSES_VERSION */ +# endif/* __APPLE__ */ +#endif /* NCURSES_VERSION */ #ifdef PDCURSES # ifdef DEF_GAME_NAME # ifdef VERSION_STRING sprintf(window_title, "%s %s", DEF_GAME_NAME, VERSION_STRING); # else sprintf(window_title, "%s", DEF_GAME_NAME); -# endif /* VERSION_STRING */ +# endif + /* VERSION_STRING */ # else # ifdef VERSION_STRING sprintf(window_title, "%s %s", "NetHack", VERSION_STRING); # else sprintf(window_title, "%s", "NetHack"); -# endif /* VERSION_STRING */ -# endif /* DEF_GAME_NAME */ +# endif + /* VERSION_STRING */ +# endif/* DEF_GAME_NAME */ PDC_set_title(window_title); - PDC_set_blink(TRUE); /* Only if the user asks for it! */ + PDC_set_blink(TRUE); /* Only if the user asks for it! */ timeout(1); - (void)getch(); + (void) getch(); timeout(-1); -#endif /* PDCURSES */ +#endif /* PDCURSES */ getmaxyx(base_term, term_rows, term_cols); counting = FALSE; curses_init_options(); - if ((term_rows < 15) || (term_cols < 40)) - { + if ((term_rows < 15) || (term_cols < 40)) { panic("Terminal too small. Must be minumum 40 width and 15 height"); } @@ -152,19 +158,20 @@ void curses_init_nhwindows(int* argcp, char** argv) curses_display_splash_window(); } - /* Do a window-port specific player type selection. If player_selection() offers a Quit option, it is its responsibility to clean up and terminate the process. You need to fill in pl_character[0]. */ -void curses_player_selection() +void +curses_player_selection() { curses_choose_character(); } /* Ask the user for a player name. */ -void curses_askname() +void +curses_askname() { curses_line_input_dialog("Who are you?", plname, PL_NSIZ); } @@ -173,11 +180,11 @@ void curses_askname() /* Does window event processing (e.g. exposure events). A noop for the tty and X window-ports. */ -void curses_get_nh_event() +void +curses_get_nh_event() { #ifdef PDCURSES - if (is_termresized()) - { + if (is_termresized()) { resize_term(0, 0); getmaxyx(base_term, term_rows, term_cols); curses_create_main_windows(); @@ -185,14 +192,12 @@ void curses_get_nh_event() doredraw(); } #endif -#ifdef NCURSES_VERSION /* Is there a better way to detect ncurses? */ - if (is_term_resized(term_rows, term_cols)) - { - if (!isendwin()) - { +#ifdef NCURSES_VERSION /* Is there a better way to detect ncurses? */ + if (is_term_resized(term_rows, term_cols)) { + if (!isendwin()) { endwin(); } - + refresh(); getmaxyx(base_term, term_rows, term_cols); curses_create_main_windows(); @@ -205,27 +210,29 @@ void curses_get_nh_event() /* Exits the window system. This should dismiss all windows, except the "window" used for raw_print(). str is printed if possible. */ -void curses_exit_nhwindows(const char *str) +void +curses_exit_nhwindows(const char *str) { curses_cleanup(); curs_set(orig_cursor); endwin(); iflags.window_inited = 0; - if (str != NULL) - { + if (str != NULL) { raw_print(str); } } /* Prepare the window to be suspended. */ -void curses_suspend_nhwindows(const char *str) +void +curses_suspend_nhwindows(const char *str) { endwin(); } /* Restore the windows after being suspended. */ -void curses_resume_nhwindows() +void +curses_resume_nhwindows() { curses_refresh_nethack_windows(); } @@ -237,25 +244,25 @@ void curses_resume_nhwindows() NHW_MENU (inventory or other "corner" windows) NHW_TEXT (help/text, full screen paged window) */ -winid curses_create_nhwindow(int type) +winid +curses_create_nhwindow(int type) { winid wid = curses_get_wid(type); - if (curses_is_menu(wid) || curses_is_text(wid)) - { + if (curses_is_menu(wid) || curses_is_text(wid)) { curses_start_menu(wid); curses_add_wid(wid); } - + return wid; } /* Clear the given window, when asked to. */ -void curses_clear_nhwindow(winid wid) +void +curses_clear_nhwindow(winid wid) { - if (wid != NHW_MESSAGE) - { + if (wid != NHW_MESSAGE) { curses_clear_nhwin(wid); } } @@ -269,29 +276,39 @@ void curses_clear_nhwindow(winid wid) -- Calling display_nhwindow(WIN_MESSAGE,???) will do a --more--, if necessary, in the tty window-port. */ -void curses_display_nhwindow(winid wid, BOOLEAN_P block) +void +curses_display_nhwindow(winid wid, BOOLEAN_P block) { menu_item *selected = NULL; - - if ((wid == MAP_WIN) && block) - { - (void) curses_more(); - } - - if (curses_is_menu(wid) || curses_is_text(wid)) - { + if (curses_is_menu(wid) || curses_is_text(wid)) { curses_end_menu(wid, ""); curses_select_menu(wid, PICK_NONE, &selected); return; } - + + /* actually display the window */ + wnoutrefresh(curses_get_nhwin(wid)); + /* flush pending writes from other windows too */ + doupdate(); + if ((wid == MAP_WIN) && block) { + (void) curses_more(); + } + + if ((wid == MESSAGE_WIN) && block) { + if (u.uhp != -1 && program_state.gameover != 1) + (void) curses_block(TRUE); + /* don't bug player with TAB prompt on "Saving..." or endgame */ + else + (void) curses_more(); + } } /* Destroy will dismiss the window if the window has not * already been dismissed. */ -void curses_destroy_nhwindow(winid wid) +void +curses_destroy_nhwindow(winid wid) { curses_del_nhwin(wid); } @@ -301,7 +318,8 @@ void curses_destroy_nhwindow(winid wid) 1 <= x < cols, 0 <= y < rows, where cols and rows are the size of window. */ -void curses_curs(winid wid, int x, int y) +void +curses_curs(winid wid, int x, int y) { curses_move_cursor(wid, x, y); } @@ -329,10 +347,11 @@ Attributes then the second. In the tty port, pline() achieves this by calling more() or displaying both on the same line. */ -void curses_putstr(winid wid, int attr, const char *text) +void +curses_putstr(winid wid, int attr, const char *text) { int curses_attr = curses_convert_attr(attr); - + /* We need to convert NetHack attributes to curses attributes */ curses_puts(wid, curses_attr, text); } @@ -340,7 +359,8 @@ void curses_putstr(winid wid, int attr, const char *text) /* Display the file named str. Complain about missing files iff complain is TRUE. */ -void curses_display_file(const char *filename,BOOLEAN_P must_exist) +void +curses_display_file(const char *filename, BOOLEAN_P must_exist) { curses_view_file(filename, must_exist); } @@ -350,8 +370,12 @@ void curses_display_file(const char *filename,BOOLEAN_P must_exist) putstr() to the window. Only windows of type NHW_MENU may be used for menus. */ -void curses_start_menu(winid wid) +void +curses_start_menu(winid wid) { + if (inv_update) + return; + curses_create_nhmenu(wid); } @@ -386,14 +410,21 @@ add_menu(winid wid, int glyph, const anything identifier, -- If you want this choice to be preselected when the menu is displayed, set preselected to TRUE. */ -void curses_add_menu(winid wid, int glyph, const ANY_P * identifier, - CHAR_P accelerator, CHAR_P group_accel, int attr, - const char *str, BOOLEAN_P presel) +void +curses_add_menu(winid wid, int glyph, const ANY_P * identifier, + CHAR_P accelerator, CHAR_P group_accel, int attr, + const char *str, BOOLEAN_P presel) { int curses_attr = curses_convert_attr(attr); - curses_add_nhmenu_item(wid, identifier, accelerator, group_accel, - curses_attr, str, presel); + if (inv_update) { + curses_add_inv(inv_update, glyph, accelerator, curses_attr, str); + inv_update++; + return; + } + + curses_add_nhmenu_item(wid, glyph, identifier, accelerator, group_accel, + curses_attr, str, presel); } /* @@ -405,8 +436,12 @@ end_menu(window, prompt) ** This probably shouldn't flush the window any more (if ** it ever did). That should be select_menu's job. -dean */ -void curses_end_menu(winid wid, const char *prompt) +void +curses_end_menu(winid wid, const char *prompt) { + if (inv_update) + return; + curses_finalize_nhmenu(wid, prompt); } @@ -435,18 +470,36 @@ int select_menu(winid window, int how, menu_item **selected) select_menu() will be called for the window at create_nhwindow() time. */ -int curses_select_menu(winid wid, int how, MENU_ITEM_P **selected) +int +curses_select_menu(winid wid, int how, MENU_ITEM_P ** selected) { + if (inv_update) + return 0; + return curses_display_nhmenu(wid, how, selected); } -/* - -- Indicate to the window port that the inventory has been changed. - -- Merely calls display_inventory() for window-ports that leave the - window up, otherwise empty. -*/ -void curses_update_inventory() +void +curses_update_inventory(void) { + /* Don't do anything if perm_invent is off unless we + changed the option. */ + if (!flags.perm_invent) { + if (curses_get_nhwin(INV_WIN)) { + curses_create_main_windows(); + curses_last_messages(); + doredraw(); + } + return; + } + + /* Update inventory sidebar. NetHack uses normal menu functions + when drawing the inventory, and we don't want to change the + underlying code. So instead, track if an inventory update is + being performed with a static variable. */ + inv_update = 1; + curses_update_inv(); + inv_update = 0; } /* @@ -454,7 +507,8 @@ mark_synch() -- Don't go beyond this point in I/O on any channel until all channels are caught up to here. Can be an empty call for the moment */ -void curses_mark_synch() +void +curses_mark_synch() { } @@ -464,7 +518,8 @@ wait_synch() -- Wait until all pending output is complete (*flush*() for -- May also deal with exposure events etc. so that the display is OK when return from wait_synch(). */ -void curses_wait_synch() +void +curses_wait_synch() { } @@ -473,13 +528,13 @@ cliparound(x, y)-- Make sure that the user is more-or-less centered on the screen if the playing area is larger than the screen. -- This function is only defined if CLIPPING is defined. */ -void curses_cliparound(int x, int y) +void +curses_cliparound(int x, int y) { int sx, sy, ex, ey; boolean redraw = curses_map_borders(&sx, &sy, &ex, &ey, x, y); - - if (redraw) - { + + if (redraw) { curses_draw_map(sx, sy, ex, ey); } } @@ -491,7 +546,8 @@ print_glyph(window, x, y, glyph) port wants (symbol, font, color, attributes, ...there's a 1-1 map between glyphs and distinct things on the map). */ -void curses_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph) +void +curses_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph) { glyph_t ch; int color; @@ -500,26 +556,23 @@ void curses_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph) /* map glyph to character and color */ mapglyph(glyph, &ch, &color, &special, x, y); - if ((special & MG_PET) && iflags.hilite_pet) - { + if ((special & MG_PET) && iflags.hilite_pet) { attr = iflags.wc2_petattr; } - if ((special & MG_DETECT) && iflags.use_inverse) - { - attr = A_REVERSE; - } - if (iflags.cursesgraphics) - { - ch = curses_convert_glyph(ch, glyph); - } - - if (wid == NHW_MAP) { - if ((special & MG_STAIRS) && iflags.hilite_hidden_stairs) { - color = 16 + (color*2); - } else if ((special & MG_OBJPILE) && iflags.hilite_obj_piles) { - color = 16 + (color*2) + 1; - } - } + if ((special & MG_DETECT) && iflags.use_inverse) { + attr = A_REVERSE; + } + if (iflags.cursesgraphics) { + ch = curses_convert_glyph(ch, glyph); + } + + if (wid == NHW_MAP) { + if ((special & MG_STAIRS) && iflags.hilite_hidden_stairs) { + color = 16 + (color * 2); + } else if ((special & MG_OBJPILE) && iflags.hilite_obj_piles) { + color = 16 + (color * 2) + 1; + } + } curses_putch(wid, x, y, ch, color, attr); } @@ -533,7 +586,8 @@ raw_print(str) -- Print directly to a screen, or otherwise guarantee that for error messages, and maybe other "msg" uses. E.g. updating status for micros (i.e, "saving"). */ -void curses_raw_print(const char *str) +void +curses_raw_print(const char *str) { puts(str); } @@ -542,7 +596,8 @@ void curses_raw_print(const char *str) raw_print_bold(str) -- Like raw_print(), but prints in bold/standout (if possible). */ -void curses_raw_print_bold(const char *str) +void +curses_raw_print_bold(const char *str) { curses_raw_print(str); } @@ -553,14 +608,15 @@ int nhgetch() -- Returns a single character input from the user. will be the routine the OS provides to read a character. Returned character _must_ be non-zero. */ -int curses_nhgetch() -{ +int +curses_nhgetch() +{ int ch; - + curses_prehousekeeping(); ch = curses_read_char(); curses_posthousekeeping(); - + return ch; } @@ -579,14 +635,14 @@ int nh_poskey(int *x, int *y, int *mod) hardware supports. If no mouse is supported, this routine always returns a non-zero character. */ -int curses_nh_poskey(int *x, int *y, int *mod) +int +curses_nh_poskey(int *x, int *y, int *mod) { int key = curses_nhgetch(); - + #ifdef NCURSES_MOUSE_VERSION /* Mouse event if mouse_support is true */ - if (key == KEY_MOUSE) - { + if (key == KEY_MOUSE) { key = curses_get_mouse(x, y, mod); } #endif @@ -598,7 +654,8 @@ int curses_nh_poskey(int *x, int *y, int *mod) nhbell() -- Beep at user. [This will exist at least until sounds are redone, since sounds aren't attributable to windows anyway.] */ -void curses_nhbell() +void +curses_nhbell() { beep(); } @@ -608,7 +665,8 @@ doprev_message() -- Display previous messages. Used by the ^P command. -- On the tty-port this scrolls WIN_MESSAGE back one line. */ -int curses_doprev_message() +int +curses_doprev_message() { curses_prev_mesg(); return 0; @@ -633,33 +691,36 @@ char yn_function(const char *ques, const char *choices, char default) -- This uses the top line in the tty window-port, other ports might use a popup. */ -char curses_yn_function(const char *question, const char *choices, CHAR_P def) +char +curses_yn_function(const char *question, const char *choices, CHAR_P def) { - return (char)curses_character_input_dialog(question, choices, def); + return (char) curses_character_input_dialog(question, choices, def); } /* getlin(const char *ques, char *input) - -- Prints ques as a prompt and reads a single line of text, - up to a newline. The string entered is returned without the - newline. ESC is used to cancel, in which case the string - "\033\000" is returned. - -- getlin() must call flush_screen(1) before doing anything. - -- This uses the top line in the tty window-port, other - ports might use a popup. + -- Prints ques as a prompt and reads a single line of text, + up to a newline. The string entered is returned without the + newline. ESC is used to cancel, in which case the string + "\033\000" is returned. + -- getlin() must call flush_screen(1) before doing anything. + -- This uses the top line in the tty window-port, other + ports might use a popup. */ -void curses_getlin(const char *question, char *input) +void +curses_getlin(const char *question, char *input) { curses_line_input_dialog(question, input, BUFSZ); } /* int get_ext_cmd(void) - -- Get an extended command in a window-port specific way. - An index into extcmdlist[] is returned on a successful - selection, -1 otherwise. + -- Get an extended command in a window-port specific way. + An index into extcmdlist[] is returned on a successful + selection, -1 otherwise. */ -int curses_get_ext_cmd() +int +curses_get_ext_cmd() { return curses_ext_cmd(); } @@ -667,65 +728,73 @@ int curses_get_ext_cmd() /* number_pad(state) - -- Initialize the number pad to the given state. + -- Initialize the number pad to the given state. */ -void curses_number_pad(int state) +void +curses_number_pad(int state) { } /* delay_output() -- Causes a visible delay of 50ms in the output. - Conceptually, this is similar to wait_synch() followed - by a nap(50ms), but allows asynchronous operation. + Conceptually, this is similar to wait_synch() followed + by a nap(50ms), but allows asynchronous operation. */ -void curses_delay_output() +void +curses_delay_output() { + /* refreshing the whole display is a waste of time, + * but that's why we're here */ + refresh(); napms(50); } /* start_screen() -- Only used on Unix tty ports, but must be declared for - completeness. Sets up the tty to work in full-screen - graphics mode. Look at win/tty/termcap.c for an - example. If your window-port does not need this function - just declare an empty function. + completeness. Sets up the tty to work in full-screen + graphics mode. Look at win/tty/termcap.c for an + example. If your window-port does not need this function + just declare an empty function. */ -void curses_start_screen() +void +curses_start_screen() { } /* end_screen() -- Only used on Unix tty ports, but must be declared for - completeness. The complement of start_screen(). + completeness. The complement of start_screen(). */ -void curses_end_screen() +void +curses_end_screen() { } /* outrip(winid, int) - -- The tombstone code. If you want the traditional code use - genl_outrip for the value and check the #if in rip.c. + -- The tombstone code. If you want the traditional code use + genl_outrip for the value and check the #if in rip.c. */ -void curses_outrip(winid wid, int how) +void +curses_outrip(winid wid, int how) { } /* preference_update(preference) - -- The player has just changed one of the wincap preference - settings, and the NetHack core is notifying your window - port of that change. If your window-port is capable of - dynamically adjusting to the change then it should do so. - Your window-port will only be notified of a particular - change if it indicated that it wants to be by setting the - corresponding bit in the wincap mask. + -- The player has just changed one of the wincap preference + settings, and the NetHack core is notifying your window + port of that change. If your window-port is capable of + dynamically adjusting to the change then it should do so. + Your window-port will only be notified of a particular + change if it indicated that it wants to be by setting the + corresponding bit in the wincap mask. */ -void curses_preference_update(const char *pref) +void +curses_preference_update(const char *pref) { if ((strcmp(pref, "align_status") == 0) || - (strcmp(pref, "align_message") == 0)) - { + (strcmp(pref, "align_message") == 0)) { curses_create_main_windows(); curses_last_messages(); doredraw(); diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index b64c568d..c51e4496 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -1,29 +1,32 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" #include "cursmesg.h" +#include + /* Message window routines for curses interface */ /* Private declatations */ -typedef struct nhpm -{ - char *str; /* Message text */ - long turn; /* Turn number for message */ - struct nhpm *prev_mesg; /* Pointer to previous message */ - struct nhpm *next_mesg; /* Pointer to next message */ +typedef struct nhpm { + char *str; /* Message text */ + long turn; /* Turn number for message */ + struct nhpm *prev_mesg; /* Pointer to previous message */ + struct nhpm *next_mesg; /* Pointer to next message */ } nhprev_mesg; static void scroll_window(winid wid); - +static void unscroll_window(winid wid); +static void directional_scroll(winid wid, int nlines); static void mesg_add_line(char *mline); - static nhprev_mesg *get_msg_line(boolean reverse, int mindex); static int turn_lines = 1; static int mx = 0; -static int my = 0; /* message window text location */ +static int my = 0; /* message window text location */ static nhprev_mesg *first_mesg = NULL; static nhprev_mesg *last_mesg = NULL; static int max_messages; @@ -33,7 +36,8 @@ static int num_messages = 0; /* Write a string to the message window. Attributes set by calling function. */ -void curses_message_win_puts(const char *message, boolean recursed) +void +curses_message_win_puts(const char *message, boolean recursed) { int height, width, linespace; char *tmpstr; @@ -43,108 +47,84 @@ void curses_message_win_puts(const char *message, boolean recursed) int border_space = 0; static long suppress_turn = -1; - if (strncmp("Count:", message, 6) == 0) - { + if (strncmp("Count:", message, 6) == 0) { curses_count_window(message); return; } - - if (suppress_turn == moves) - { + + if (suppress_turn == moves) { return; } - + curses_get_window_size(MESSAGE_WIN, &height, &width); - if (border) - { + if (border) { border_space = 1; - if (mx < 1) - { + if (mx < 1) { mx = 1; } - if (my < 1) - { + if (my < 1) { my = 1; } } - + linespace = ((width + border_space) - 3) - mx; - - if (strcmp(message, "#") == 0) /* Extended command or Count: */ - { - if ((strcmp(toplines, "#") != 0) && (my >= (height - 1 + - border_space)) && (height != 1)) /* Bottom of message window */ - { + + if (strcmp(message, "#") == 0) { /* Extended command or Count: */ + if ((strcmp(toplines, "#") != 0) && (my >= (height - 1 + border_space)) && (height != 1)) { /* Bottom of message window */ scroll_window(MESSAGE_WIN); mx = width; my--; strcpy(toplines, message); } - + return; } - if (!recursed) - { + if (!recursed) { strcpy(toplines, message); mesg_add_line((char *) message); } - - if (linespace < message_length) - { - if (my >= (height - 1 + border_space)) /* bottom of message win */ - { - if ((turn_lines > height) || (height == 1)) - { + + if (linespace < message_length) { + if (my >= (height - 1 + border_space)) { /* bottom of message win */ + if ((turn_lines > height) || (height == 1)) { /* Pause until key is hit - Esc suppresses any further - messages that turn */ - if (curses_more() == DOESCAPE) - { + messages that turn */ + if (curses_more() == DOESCAPE) { suppress_turn = moves; return; } - } - else - { + } else { scroll_window(MESSAGE_WIN); turn_lines++; } - } - else - { - if (mx != border_space) - { + } else { + if (mx != border_space) { my++; mx = border_space; } } } - if (height > 1) - { + if (height > 1) { curses_toggle_color_attr(win, NONE, A_BOLD, ON); } - - if ((mx == border_space) && ((message_length + 2) > width)) - { + + if ((mx == border_space) && ((message_length + 2) > width)) { tmpstr = curses_break_str(message, (width - 2), 1); mvwprintw(win, my, mx, "%s", tmpstr); mx += strlen(tmpstr); - if (strlen(tmpstr) < (width - 2)) - { + if (strlen(tmpstr) < (width - 2)) { mx++; } free(tmpstr); - if (height > 1) - { + if (height > 1) { curses_toggle_color_attr(win, NONE, A_BOLD, OFF); } - wrefresh(win); - curses_message_win_puts(curses_str_remainder(message, (width - 2), 1), - TRUE); - } - else - { + curses_message_win_puts(tmpstr = curses_str_remainder(message, (width - 2), 1), + TRUE); + free(tmpstr); + } else { mvwprintw(win, my, mx, "%s", message); curses_toggle_color_attr(win, NONE, A_BOLD, OFF); mx += message_length + 1; @@ -153,76 +133,85 @@ void curses_message_win_puts(const char *message, boolean recursed) } -int curses_more() +int +curses_block(boolean noscroll) +/* noscroll - blocking because of msgtype = stop/alert */ +/* else blocking because window is full, so need to scroll after */ { - int height, width, ret; + int height, width, ret = 0; WINDOW *win = curses_get_nhwin(MESSAGE_WIN); - + char *resp = " \n\033"; /* space, enter, esc */ + curses_get_window_size(MESSAGE_WIN, &height, &width); curses_toggle_color_attr(win, MORECOLOR, NONE, ON); - mvwprintw(win, my, mx, ">>"); + mvwprintw(win, my, mx, iflags.msg_is_alert ? "" : ">>"); curses_toggle_color_attr(win, MORECOLOR, NONE, OFF); + if (iflags.msg_is_alert) + curses_alert_main_borders(TRUE); wrefresh(win); - ret = wgetch(win); - if (height == 1) - { + while (iflags.msg_is_alert && (ret = wgetch(win) != '\t')); + /* msgtype=stop should require space/enter rather than + * just any key, as we want to prevent YASD from + * riding direction keys. */ + while (!iflags.msg_is_alert && (ret = wgetch(win)) && !index(resp,(char)ret)); + if (iflags.msg_is_alert) + curses_alert_main_borders(FALSE); + if (height == 1) { curses_clear_unhighlight_message_window(); + } else { + mvwprintw(win, my, mx, " "); + if (!noscroll) { + scroll_window(MESSAGE_WIN); + turn_lines = 1; + } } - else - { - mvwprintw(win, my, mx, " "); - scroll_window(MESSAGE_WIN); - turn_lines = 1; - } - + return ret; } +int +curses_more() +{ + return curses_block(FALSE); +} + /* Clear the message window if one line; otherwise unhighlight old messages */ -void curses_clear_unhighlight_message_window() +void +curses_clear_unhighlight_message_window() { int mh, mw, count; boolean border = curses_window_has_border(MESSAGE_WIN); WINDOW *win = curses_get_nhwin(MESSAGE_WIN); turn_lines = 1; - - curses_get_window_size(MESSAGE_WIN, &mh, &mw); - + + curses_get_window_size(MESSAGE_WIN, &mh, &mw); + mx = 0; - - if (border) - { + + if (border) { mx++; } - - if (mh == 1) - { + + if (mh == 1) { curses_clear_nhwin(MESSAGE_WIN); - } - else - { - mx += mw; /* Force new line on new turn */ - - if (border) - { + } else { + mx += mw; /* Force new line on new turn */ + + if (border) { - for (count = 0; count < mh; count++) - { - mvwchgat(win, count+1, 1, mw, COLOR_PAIR(8), A_NORMAL, NULL); + for (count = 0; count < mh; count++) { + mvwchgat(win, count + 1, 1, mw, COLOR_PAIR(8), A_NORMAL, NULL); } - } - else - { - for (count = 0; count < mh; count++) - { + } else { + for (count = 0; count < mh; count++) { mvwchgat(win, count, 0, mw, COLOR_PAIR(8), A_NORMAL, NULL); } } - wrefresh(win); + wnoutrefresh(win); } } @@ -230,38 +219,42 @@ void curses_clear_unhighlight_message_window() /* Reset message window cursor to starting position, and display most recent messages. */ -void curses_last_messages() +void +curses_last_messages() { boolean border = curses_window_has_border(MESSAGE_WIN); - if (border) - { + if (border) { mx = 1; my = 1; - } - else - { + } else { mx = 0; my = 0; } - - pline("%s", toplines); + + nhprev_mesg *mesg; + int i; + for (i = (num_messages - 1); i > 0; i--) { + mesg = get_msg_line(TRUE, i); + if (mesg && mesg->str && strcmp(mesg->str, "")) + curses_message_win_puts(mesg->str, TRUE); + } + curses_message_win_puts(toplines, TRUE); } /* Initialize list for message history */ -void curses_init_mesg_history() +void +curses_init_mesg_history() { max_messages = iflags.msg_history; - - if (max_messages < 1) - { + + if (max_messages < 1) { max_messages = 1; } - if (max_messages > MESG_HISTORY_MAX) - { + if (max_messages > MESG_HISTORY_MAX) { max_messages = MESG_HISTORY_MAX; } } @@ -269,7 +262,8 @@ void curses_init_mesg_history() /* Display previous message window messages in reverse chron order */ -void curses_prev_mesg() +void +curses_prev_mesg() { int count; winid wid; @@ -280,22 +274,20 @@ void curses_prev_mesg() wid = curses_get_wid(NHW_MENU); curses_create_nhmenu(wid); - identifier = malloc(sizeof(anything)); + identifier = malloc(sizeof (anything)); identifier->a_void = NULL; - - for (count = 0; count < num_messages; count++) - { + + for (count = 0; count < num_messages; count++) { mesg = get_msg_line(TRUE, count); - if ((turn != mesg->turn) && (count != 0)) - { + if ((turn != mesg->turn) && (count != 0)) { curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NORMAL, - "---", FALSE); + "---", FALSE); } curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NORMAL, - mesg->str, FALSE); + mesg->str, FALSE); turn = mesg->turn; } - + curses_end_menu(wid, ""); curses_select_menu(wid, PICK_NONE, &selected); } @@ -304,107 +296,264 @@ void curses_prev_mesg() /* Shows Count: in a separate window, or at the bottom of the message window, depending on the user's settings */ -void curses_count_window(const char *count_text) +void +curses_count_window(const char *count_text) { int startx, starty, winx, winy; int messageh, messagew; static WINDOW *countwin = NULL; - if ((count_text == NULL) && (countwin != NULL)) - { + if ((count_text == NULL) && (countwin != NULL)) { delwin(countwin); countwin = NULL; counting = FALSE; return; } - + counting = TRUE; - if (iflags.wc_popup_dialog) /* Display count in popup window */ - { + if (iflags.wc_popup_dialog) { /* Display count in popup window */ startx = 1; starty = 1; - - if (countwin == NULL) - { + + if (countwin == NULL) { countwin = curses_create_window(25, 1, UP); } - - } - else /* Display count at bottom of message window */ - { + + } else { /* Display count at bottom of message window */ + curses_get_window_xy(MESSAGE_WIN, &winx, &winy); curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); - - if (curses_window_has_border(MESSAGE_WIN)) - { + + if (curses_window_has_border(MESSAGE_WIN)) { winx++; winy++; } - + winy += messageh - 1; - - if (countwin == NULL) - { + + if (countwin == NULL) { pline("#"); #ifndef PDCURSES countwin = newwin(1, 25, winy, winx); -#endif /* !PDCURSES */ +#endif /* !PDCURSES */ } #ifdef PDCURSES - else - { + else { curses_destroy_win(countwin); } - + countwin = newwin(1, 25, winy, winx); -#endif /* PDCURSES */ +#endif /* PDCURSES */ startx = 0; starty = 0; } - + mvwprintw(countwin, starty, startx, "%s", count_text); wrefresh(countwin); } + /* Gets a "line" (buffer) of input. */ +void +curses_message_win_getline(const char *prompt, char *answer, int buffer) +{ + int height, width; /* of window */ + char *tmpbuf, *p_answer; /* combined prompt + answer */ + int nlines, maxlines, i; /* prompt + answer */ + int promptline; + int promptx; + char **linestarts; /* pointers to start of each line */ + char *tmpstr; /* for free() */ + int maxy, maxx; /* linewrap / scroll */ + int ch; + + WINDOW *win = curses_get_nhwin(MESSAGE_WIN); + int border_space = 0; + int len = 0; /* of answer string */ + boolean border = curses_window_has_border(MESSAGE_WIN); + int orig_cursor = curs_set(0); + + curses_get_window_size(MESSAGE_WIN, &height, &width); + if (border) { + border_space = 1; + if (mx < 1) mx = 1; + if (my < 1) my = 1; + } + maxy = height - 1 + border_space; + maxx = width - 1 + border_space; + + tmpbuf = (char *)malloc(strlen(prompt) + buffer + 2); + maxlines = buffer / width * 2; + strcpy(tmpbuf, prompt); + strcat(tmpbuf, " "); + nlines = curses_num_lines(tmpbuf,width); + maxlines += nlines * 2; + linestarts = (char **)malloc(sizeof(char*) * maxlines); + p_answer = tmpbuf + strlen(tmpbuf); + linestarts[0] = tmpbuf; + + if (mx > border_space) { /* newline */ + if (my >= maxy) scroll_window(MESSAGE_WIN); + else my++; + mx = border_space; + } + + curses_toggle_color_attr(win, NONE, A_BOLD, ON); + + for (i = 0; i < nlines-1; i++) { + tmpstr = curses_break_str(linestarts[i],width-1,1); + linestarts[i+1] = linestarts[i] + strlen(tmpstr); + if (*linestarts[i+1] == ' ') linestarts[i+1]++; + mvwaddstr(win,my,mx,tmpstr); + free(tmpstr); + if (++my >= maxy) { + scroll_window(MESSAGE_WIN); + my--; + } + } + mvwaddstr(win,my,mx,linestarts[nlines-1]); + mx = promptx = strlen(linestarts[nlines-1]) + border_space; + promptline = nlines - 1; + + while(1) { + mx = strlen(linestarts[nlines - 1]) + border_space; + if (mx > maxx) { + if (nlines < maxlines) { + tmpstr = curses_break_str(linestarts[nlines - 1], width - 1, 1); + mx = strlen(tmpstr) + border_space; + mvwprintw(win, my, mx, "%*c", maxx - mx + 1, ' '); + if (++my > maxy) { + scroll_window(MESSAGE_WIN); + my--; + } + mx = border_space; + linestarts[nlines] = linestarts[nlines - 1] + strlen(tmpstr); + if (*linestarts[nlines] == ' ') linestarts[nlines]++; + mvwaddstr(win, my, mx, linestarts[nlines]); + mx = strlen(linestarts[nlines]) + border_space; + nlines++; + free(tmpstr); + } else { + p_answer[--len] = '\0'; + mvwaddch(win, my, --mx, ' '); + } + } + wmove(win, my, mx); + curs_set(1); + wrefresh(win); + ch = getch(); + curs_set(0); + switch(ch) { + case '\033': /* DOESCAPE */ + /* blank the input but don't exit */ + while(nlines - 1 > promptline) { + if (nlines-- > height) { + unscroll_window(MESSAGE_WIN); + tmpstr = curses_break_str(linestarts[nlines - height], width - 1, 1); + mvwaddstr(win, border_space, border_space, tmpstr); + free(tmpstr); + } else { + mx = border_space; + mvwprintw(win, my, mx, "%*c", maxx - mx, ' '); + my--; + } + } + mx = promptx; + mvwprintw(win, my, mx, "%*c", maxx - mx, ' '); + *p_answer = '\0'; + len = 0; + break; + case ERR: /* should not happen */ + *answer = '\0'; + free(tmpbuf); + free(linestarts); + curs_set(orig_cursor); + curses_toggle_color_attr(win, NONE, A_BOLD, OFF); + return; + case '\r': + case '\n': + free(linestarts); + strncpy(answer, p_answer, buffer); + strcpy(toplines, tmpbuf); + mesg_add_line((char *) tmpbuf); + free(tmpbuf); + curs_set(orig_cursor); + curses_toggle_color_attr(win, NONE, A_BOLD, OFF); + return; + case '\b': + case KEY_BACKSPACE: + if (len < 1) { + len = 1; + mx = promptx; + } + p_answer[--len] = '\0'; + mvwaddch(win, my, --mx, ' '); + /* try to unwrap back to the previous line if there is one */ + if (nlines > 1 && strlen(linestarts[nlines - 2]) < width) { + mvwaddstr(win, my - 1, border_space, linestarts[nlines - 2]); + if (nlines-- > height) { + unscroll_window(MESSAGE_WIN); + tmpstr = curses_break_str(linestarts[nlines - height], width - 1, 1); + mvwaddstr(win, border_space, border_space, tmpstr); + free(tmpstr); + } else { + /* clean up the leftovers on the next line, if we didn't scroll it away */ + mvwprintw(win, my--, border_space, "%*c", strlen(linestarts[nlines]), ' '); + } + } + break; + default: + p_answer[len++] = ch; + if (len >= buffer) len = buffer-1; + else mvwaddch(win, my, mx, ch); + p_answer[len] = '\0'; + } + } +} /* Scroll lines upward in given window, or clear window if only one line. */ +static void +scroll_window(winid wid) +{ + directional_scroll(wid,1); +} + +static void +unscroll_window(winid wid) +{ + directional_scroll(wid,-1); +} -static void scroll_window(winid wid) +static void +directional_scroll(winid wid, int nlines) { int wh, ww, s_top, s_bottom; boolean border = curses_window_has_border(wid); WINDOW *win = curses_get_nhwin(wid); - + curses_get_window_size(wid, &wh, &ww); - if (wh == 1) - { + if (wh == 1) { curses_clear_nhwin(wid); return; } - if (border) - { + if (border) { s_top = 1; s_bottom = wh; - } - else - { + } else { s_top = 0; s_bottom = wh - 1; } scrollok(win, TRUE); wsetscrreg(win, s_top, s_bottom); - scroll(win); + wscrl(win, nlines); scrollok(win, FALSE); - if (wid == MESSAGE_WIN) - { + if (wid == MESSAGE_WIN) { if (border) mx = 1; else mx = 0; } - if (border) - { + if (border) { box(win, 0, 0); } wrefresh(win); @@ -413,34 +562,30 @@ static void scroll_window(winid wid) /* Add given line to message history */ -static void mesg_add_line(char *mline) +static void +mesg_add_line(char *mline) { nhprev_mesg *tmp_mesg = NULL; - nhprev_mesg *current_mesg = malloc(sizeof(nhprev_mesg)); + nhprev_mesg *current_mesg = malloc(sizeof (nhprev_mesg)); current_mesg->str = curses_copy_of(mline); current_mesg->turn = moves; current_mesg->next_mesg = NULL; - if (num_messages == 0) - { + if (num_messages == 0) { first_mesg = current_mesg; } - - if (last_mesg != NULL) - { + + if (last_mesg != NULL) { last_mesg->next_mesg = current_mesg; } current_mesg->prev_mesg = last_mesg; last_mesg = current_mesg; - if (num_messages < max_messages) - { + if (num_messages < max_messages) { num_messages++; - } - else - { + } else { tmp_mesg = first_mesg->next_mesg; free(first_mesg); first_mesg = tmp_mesg; @@ -450,31 +595,25 @@ static void mesg_add_line(char *mline) /* Returns specified line from message history, or NULL if out of bounds */ -static nhprev_mesg *get_msg_line(boolean reverse, int mindex) +static nhprev_mesg * +get_msg_line(boolean reverse, int mindex) { int count; nhprev_mesg *current_mesg; - if (reverse) - { + if (reverse) { current_mesg = last_mesg; - for (count = 0; count < mindex; count++) - { - if (current_mesg == NULL) - { + for (count = 0; count < mindex; count++) { + if (current_mesg == NULL) { return NULL; } current_mesg = current_mesg->prev_mesg; } return current_mesg; - } - else - { + } else { current_mesg = first_mesg; - for (count = 0; count < mindex; count++) - { - if (current_mesg == NULL) - { + for (count = 0; count < mindex; count++) { + if (current_mesg == NULL) { return NULL; } current_mesg = current_mesg->next_mesg; @@ -482,4 +621,3 @@ static nhprev_mesg *get_msg_line(boolean reverse, int mindex) return current_mesg; } } - diff --git a/win/curses/cursmesg.h b/win/curses/cursmesg.h index 344736cd..54af5f9b 100644 --- a/win/curses/cursmesg.h +++ b/win/curses/cursmesg.h @@ -1,21 +1,19 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSMESG_H -#define CURSMESG_H +# define CURSMESG_H /* Global declarations */ void curses_message_win_puts(const char *message, boolean recursed); - +int curses_block(boolean require_tab); int curses_more(void); - void curses_clear_unhighlight_message_window(void); - +void curses_message_win_getline(const char *prompt, char *answer, int buffer); void curses_last_messages(void); - void curses_init_mesg_history(void); - void curses_prev_mesg(void); - void curses_count_window(const char *count_text); -#endif /* CURSMESG_H */ +#endif /* CURSMESG_H */ diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index 9dd7fc0d..374d75b7 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" @@ -20,42 +22,39 @@ static int parse_escape_sequence(void); #ifndef M # ifndef NHSTDC -# define M(c) (0x80 | (c)) +# define M(c) (0x80 | (c)) # else -# define M(c) ((c) - 128) -# endif /* NHSTDC */ +# define M(c) ((c) - 128) +# endif/* NHSTDC */ #endif #ifndef C -#define C(c) (0x1f & (c)) +# define C(c) (0x1f & (c)) #endif /* Read a character of input from the user */ -int curses_read_char() +int +curses_read_char() { int ch, tmpch; - + ch = getch(); tmpch = ch; ch = curses_convert_keys(ch); - if (ch == 0) - { - ch = DOESCAPE; /* map NUL to ESC since nethack doesn't expect NUL */ + if (ch == 0) { + ch = DOESCAPE; /* 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)) - { +#if defined(ALT_0) && defined(ALT_9) /* PDCurses, maybe others */ + if ((ch >= ALT_0) && (ch <= ALT_9)) { tmpch = (ch - ALT_0) + '0'; ch = M(tmpch); } #endif -#if defined(ALT_A) && defined(ALT_Z) /* PDCurses, maybe others */ - if ((ch >= ALT_A) && (ch <= ALT_Z)) - { +#if defined(ALT_A) && defined(ALT_Z) /* PDCurses, maybe others */ + if ((ch >= ALT_A) && (ch <= ALT_Z)) { tmpch = (ch - ALT_A) + 'a'; ch = M(tmpch); } @@ -63,14 +62,12 @@ int curses_read_char() #ifdef KEY_RESIZE /* Handle resize events via get_nh_event, not this code */ - if (ch == KEY_RESIZE) - { - ch = DOESCAPE; /* NetHack doesn't know what to do with KEY_RESIZE */ + if (ch == KEY_RESIZE) { + ch = DOESCAPE; /* 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(); } @@ -80,98 +77,84 @@ int curses_read_char() /* Turn on or off the specified color and / or attribute */ -void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff) +void +curses_toggle_color_attr(WINDOW * win, int color, int attr, int onoff) { #ifdef TEXTCOLOR int curses_color; /* Map color disabled */ - if ((!iflags.wc_color) && (win == mapwin)) - { + if ((!iflags.wc_color) && (win == mapwin)) { return; } - + /* GUI color disabled */ - if ((!iflags.wc2_guicolor) && (win != mapwin)) - { + if ((!iflags.wc2_guicolor) && (win != mapwin)) { return; } - - if (color == 0) /* make black fg visible */ - { -#ifdef USE_DARKGRAY - if (can_change_color() && (COLORS > 16)) - { - color = CURSES_DARK_GRAY - 1; - } - else /* Use bold for a bright black */ - { - wattron(win, A_BOLD); - } -#else - color = CLR_BLUE; -#endif /* USE_DARKGRAY */ + + if (color == 0) { /* make black fg visible */ +# ifdef USE_DARKGRAY + if (iflags.wc2_darkgray) { + if (can_change_color() && (COLORS > 16)) { + /* colorpair for black is already darkgray */ + } else { /* Use bold for a bright black */ + + wattron(win, A_BOLD); + } + } else +# endif/* USE_DARKGRAY */ + color = CLR_BLUE; } curses_color = color + 1; - if (COLORS < 16) - { + if (COLORS < 16) { if (curses_color > 8 && curses_color < 17) curses_color -= 8; - else if (curses_color > (17+16)) + else if (curses_color > (17 + 16)) curses_color -= 16; } - if (onoff == ON) /* Turn on color/attributes */ - { - if (color != NONE) - { + if (onoff == ON) { /* Turn on color/attributes */ + if (color != NONE) { if ((((color > 7) && (color < 17)) || - (color > 17+17)) && (COLORS < 16)) - { + (color > 17 + 17)) && (COLORS < 16)) { wattron(win, A_BOLD); } wattron(win, COLOR_PAIR(curses_color)); } - - if (attr != NONE) - { + + if (attr != NONE) { wattron(win, attr); } - } - else /* Turn off color/attributes */ - { - if (color != NONE) - { - if ((color > 7) && (COLORS < 16)) - { + } else { /* Turn off color/attributes */ + + if (color != NONE) { + if ((color > 7) && (COLORS < 16)) { wattroff(win, A_BOLD); } -#ifdef USE_DARKGRAY - if ((color == 0) && (!can_change_color() || - (COLORS <= 16))) - { +# ifdef USE_DARKGRAY + if ((color == 0) && (!can_change_color() || (COLORS <= 16))) { wattroff(win, A_BOLD); } -#else - if (iflags.use_inverse) - { +# else + if (iflags.use_inverse) { wattroff(win, A_REVERSE); } -#endif /* DARKGRAY */ +# endif/* DARKGRAY */ wattroff(win, COLOR_PAIR(curses_color)); } - - if (attr != NONE) - { + + if (attr != NONE) { wattroff(win, attr); } } -#endif /* TEXTCOLOR */ +#endif /* TEXTCOLOR */ } /* clean up and quit - taken from tty port */ -void curses_bail(const char *mesg) +void +curses_bail(const char *mesg) { clearlocks(); curses_exit_nhwindows(mesg); @@ -181,65 +164,45 @@ void curses_bail(const char *mesg) /* Return a winid for a new window of the given type */ -winid curses_get_wid(int type) +winid +curses_get_wid(int type) { - winid ret; + winid ret; static winid menu_wid = 20; /* Always even */ static winid text_wid = 21; /* Always odd */ - switch (type) - { - case NHW_MESSAGE: - { - return MESSAGE_WIN; - break; - } - case NHW_MAP: - { - return MAP_WIN; - break; - } - case NHW_STATUS: - { - return STATUS_WIN; - break; - } - case NHW_MENU: - { - ret = menu_wid; - break; - } - case NHW_TEXT: - { - ret = text_wid; - break; - } - default: - { - panic("curses_get_wid: unsupported window type"); - ret = -1; /* Not reached */ - } - } - - while (curses_window_exists(ret)) - { - ret += 2; - if ((ret + 2) > 10000) /* Avoid "wid2k" problem */ - { - ret -= 9900; - } - } - - if (type == NHW_MENU) - { - menu_wid += 2; - } - else - { - text_wid += 2; - } - - return ret; + switch (type) { + case NHW_MESSAGE: + return MESSAGE_WIN; + case NHW_MAP: + return MAP_WIN; + case NHW_STATUS: + return STATUS_WIN; + case NHW_MENU: + ret = menu_wid; + break; + case NHW_TEXT: + ret = text_wid; + break; + default: + impossible("curses_get_wid: unsupported window type"); + ret = -1; + } + + while (curses_window_exists(ret)) { + ret += 2; + if ((ret + 2) > 10000) { /* Avoid "wid2k" problem */ + ret -= 9900; + } + } + + if (type == NHW_MENU) { + menu_wid += 2; + } else { + text_wid += 2; + } + + return ret; } @@ -250,9 +213,11 @@ winid curses_get_wid(int type) * This is taken from copy_of() in tty/wintty.c. */ -char *curses_copy_of(const char *s) +char * +curses_copy_of(const char *s) { - if (!s) s = ""; + if (!s) + s = ""; return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s); } @@ -260,38 +225,36 @@ char *curses_copy_of(const char *s) /* Determine the number of lines needed for a string for a dialog window of the given width */ -int curses_num_lines(const char *str, int width) +int +curses_num_lines(const char *str, int width) { int last_space, count; int curline = 1; char substr[BUFSZ]; char tmpstr[BUFSZ]; - - strcpy(substr, str); - - while (strlen(substr) > width) - { + + strncpy(substr, str, BUFSZ-1); + substr[BUFSZ-1] = '\0'; + + while (strlen(substr) > width) { last_space = 0; - - for (count = 0; count <= width; count++) - { + + for (count = 0; count <= width; count++) { if (substr[count] == ' ') - last_space = count; + last_space = count; } - if (last_space == 0) /* No spaces found */ - { + if (last_space == 0) { /* No spaces found */ last_space = count - 1; } - for (count = (last_space + 1); count < strlen(substr); count++) - { + for (count = (last_space + 1); count < strlen(substr); count++) { tmpstr[count - (last_space + 1)] = substr[count]; } tmpstr[count - (last_space + 1)] = '\0'; strcpy(substr, tmpstr); curline++; } - + return curline; } @@ -299,7 +262,8 @@ int curses_num_lines(const char *str, int width) /* Break string into smaller lines to fit into a dialog window of the given width */ -char *curses_break_str(const char *str, int width, int line_num) +char * +curses_break_str(const char *str, int width, int line_num) { int last_space, count; char *retstr; @@ -308,64 +272,54 @@ char *curses_break_str(const char *str, int width, int line_num) char substr[strsize]; char curstr[strsize]; char tmpstr[strsize]; - + strcpy(substr, str); - - while (curline < line_num) - { - if (strlen(substr) == 0 ) - { + + while (curline < line_num) { + if (strlen(substr) == 0) { break; } curline++; - last_space = 0; - for (count = 0; count <= width; count++) - { - if (substr[count] == ' ') - { + last_space = 0; + for (count = 0; count <= width; count++) { + if (substr[count] == ' ') { last_space = count; - } - else if (substr[count] == '\0') - { + } else if (substr[count] == '\0') { last_space = count; break; } } - if (last_space == 0) /* No spaces found */ - { + if (last_space == 0) { /* No spaces found */ last_space = count - 1; } - for (count = 0; count < last_space; count++) - { + for (count = 0; count < last_space; count++) { curstr[count] = substr[count]; } curstr[count] = '\0'; - if (substr[count] == '\0') - { + if (substr[count] == '\0') { break; } - for (count = (last_space + 1); count < strlen(substr); count++) - { + for (count = (last_space + 1); count < strlen(substr); count++) { tmpstr[count - (last_space + 1)] = substr[count]; } tmpstr[count - (last_space + 1)] = '\0'; strcpy(substr, tmpstr); } - - if (curline < line_num) - { + + if (curline < line_num) { return NULL; } - + retstr = curses_copy_of(curstr); - + return retstr; } /* Return the remaining portion of a string after hacking-off line_num lines */ -char *curses_str_remainder(const char *str, int width, int line_num) +char * +curses_str_remainder(const char *str, int width, int line_num) { int last_space, count; char *retstr; @@ -374,71 +328,58 @@ char *curses_str_remainder(const char *str, int width, int line_num) char substr[strsize]; char curstr[strsize]; char tmpstr[strsize]; - + strcpy(substr, str); - - while (curline < line_num) - { - if (strlen(substr) == 0 ) - { + + while (curline < line_num) { + if (strlen(substr) == 0) { break; } curline++; - last_space = 0; - for (count = 0; count <= width; count++) - { - if (substr[count] == ' ') - { + last_space = 0; + for (count = 0; count <= width; count++) { + if (substr[count] == ' ') { last_space = count; - } - else if (substr[count] == '\0') - { + } else if (substr[count] == '\0') { last_space = count; break; } } - if (last_space == 0) /* No spaces found */ - { + if (last_space == 0) { /* No spaces found */ last_space = count - 1; } - for (count = 0; count < last_space; count++) - { + for (count = 0; count < last_space; count++) { curstr[count] = substr[count]; } curstr[count] = '\0'; - if (substr[count] == '\0') - { + if (substr[count] == '\0') { break; } - for (count = (last_space + 1); count < strlen(substr); count++) - { + for (count = (last_space + 1); count < strlen(substr); count++) { tmpstr[count - (last_space + 1)] = substr[count]; } tmpstr[count - (last_space + 1)] = '\0'; strcpy(substr, tmpstr); } - - if (curline < line_num) - { + + if (curline < line_num) { return NULL; } - + retstr = curses_copy_of(substr); - + return retstr; } /* Determine if the given NetHack winid is a menu window */ -boolean curses_is_menu(winid wid) +boolean +curses_is_menu(winid wid) { - if ((wid > 19) && !(wid % 2)) /* Even number */ - { + if ((wid > 19) && !(wid % 2)) { /* Even number */ return TRUE; - } - else - { + } else { return FALSE; } } @@ -446,14 +387,12 @@ boolean curses_is_menu(winid wid) /* Determine if the given NetHack winid is a text window */ -boolean curses_is_text(winid wid) +boolean +curses_is_text(winid wid) { - if ((wid > 19) && (wid % 2)) /* Odd number */ - { + if ((wid > 19) && (wid % 2)) { /* Odd number */ return TRUE; - } - else - { + } else { return FALSE; } } @@ -462,72 +401,70 @@ boolean curses_is_text(winid wid) /* Replace certain characters with portable drawing characters if cursesgraphics option is enabled */ -int curses_convert_glyph(int ch, int glyph) +int +curses_convert_glyph(int ch, int glyph) { int symbol; - + #ifdef REINCARNATION - if (Is_rogue_level(&u.uz)) - { + if (Is_rogue_level(&u.uz)) { return ch; } #endif - + /* Save some processing time by returning if the glyph represents - an object that we don't have custom characters for */ - if (!glyph_is_cmap(glyph)) - { + an object that we don't have custom characters for */ + if (!glyph_is_cmap(glyph)) { return ch; } - + symbol = glyph_to_cmap(glyph); - + /* If user selected a custom character for this object, don't - override this. */ - if (((glyph_is_cmap(glyph)) && (ch != showsyms[symbol]))) - { + override this. */ + if (((glyph_is_cmap(glyph)) && (ch != showsyms[symbol]))) { return ch; } - switch (symbol) - { - case S_vwall: - return ACS_VLINE; - case S_hwall: - return ACS_HLINE; - case S_tlcorn: - return ACS_ULCORNER; - case S_trcorn: - return ACS_URCORNER; - case S_blcorn: - return ACS_LLCORNER; - case S_brcorn: - return ACS_LRCORNER; - case S_crwall: - return ACS_PLUS; - case S_tuwall: - return ACS_BTEE; - case S_tdwall: - return ACS_TTEE; - case S_tlwall: - return ACS_RTEE; - case S_trwall: - return ACS_LTEE; - case S_tree: - return ACS_PLMINUS; - case S_corr: - return ACS_CKBOARD; - case S_litcorr: - return ACS_CKBOARD; - } - - return ch; + switch (symbol) { + case S_vwall: + return ACS_VLINE; + case S_hwall: + return ACS_HLINE; + case S_tlcorn: + return ACS_ULCORNER; + case S_trcorn: + return ACS_URCORNER; + case S_blcorn: + return ACS_LLCORNER; + case S_brcorn: + return ACS_LRCORNER; + case S_crwall: + return ACS_PLUS; + case S_tuwall: + return ACS_BTEE; + case S_tdwall: + return ACS_TTEE; + case S_tlwall: + return ACS_RTEE; + case S_trwall: + return ACS_LTEE; + case S_tree: + return ACS_PLMINUS; + case S_corr: + return ACS_CKBOARD; + case S_litcorr: + return ACS_CKBOARD; + } + + return ch; } /* Move text cursor to specified coordinates in the given NetHack window */ -void curses_move_cursor(winid wid, int x, int y) +void +curses_move_cursor(winid wid, int x, int y) { int sx, sy, ex, ey; int xadj = 0; @@ -537,29 +474,24 @@ void curses_move_cursor(winid wid, int x, int y) WINDOW *win = curses_get_nhwin(MAP_WIN); #endif - if (wid != MAP_WIN) - { + if (wid != MAP_WIN) { return; } - #ifdef PDCURSES /* PDCurses seems to not handle wmove correctly, so we use move and - physical screen coordinates instead */ + physical screen coordinates instead */ curses_get_window_xy(wid, &xadj, &yadj); -#endif +#endif curs_x = x + xadj; curs_y = y + yadj; curses_map_borders(&sx, &sy, &ex, &ey, x, y); - - if (curses_window_has_border(wid)) - { + + if (curses_window_has_border(wid)) { curs_x++; curs_y++; } - - if ((x >= sx) && (x <= ex) && - (y >= sy) && (y <= ey)) - { + + if ((x >= sx) && (x <= ex) && (y >= sy) && (y <= ey)) { curs_x -= sx; curs_y -= sy; #ifdef PDCURSES @@ -573,22 +505,22 @@ void curses_move_cursor(winid wid, int x, int y) /* Perform actions that should be done every turn before nhgetch() */ -void curses_prehousekeeping() +void +curses_prehousekeeping() { #ifndef PDCURSES WINDOW *win = curses_get_nhwin(MAP_WIN); -#endif /* PDCURSES */ +#endif /* PDCURSES */ - if ((curs_x > -1) && (curs_y > -1)) - { + if ((curs_x > -1) && (curs_y > -1)) { curs_set(1); #ifdef PDCURSES /* PDCurses seems to not handle wmove correctly, so we use move - and physical screen coordinates instead */ + and physical screen coordinates instead */ move(curs_y, curs_x); #else wmove(win, curs_y, curs_x); -#endif /* PDCURSES */ +#endif /* PDCURSES */ curses_refresh_nhwin(MAP_WIN); } } @@ -596,89 +528,88 @@ void curses_prehousekeeping() /* Perform actions that should be done every turn after nhgetch() */ -void curses_posthousekeeping() +void +curses_posthousekeeping() { curs_set(0); - curses_decrement_highlight(); + curses_decrement_highlights(FALSE); curses_clear_unhighlight_message_window(); } -void curses_view_file(const char *filename, boolean must_exist) +void +curses_view_file(const char *filename, boolean must_exist) { winid wid; anything *identifier; char buf[BUFSZ]; menu_item *selected = NULL; dlb *fp = dlb_fopen(filename, "r"); - - if ((fp == NULL) && (must_exist)) - { + + if ((fp == NULL) && (must_exist)) { pline("Cannot open %s for reading!", filename); } - if (fp == NULL) - { + if (fp == NULL) { return; } - + wid = curses_get_wid(NHW_MENU); curses_create_nhmenu(wid); - identifier = malloc(sizeof(anything)); + identifier = malloc(sizeof (anything)); identifier->a_void = NULL; - - while (dlb_fgets(buf, BUFSZ, fp) != NULL) - { - curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NORMAL, buf, - FALSE); + + while (dlb_fgets(buf, BUFSZ, fp) != NULL) { + curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NORMAL, buf, FALSE); } - + dlb_fclose(fp); curses_end_menu(wid, ""); curses_select_menu(wid, PICK_NONE, &selected); } -void curses_rtrim(char *str) +void +curses_rtrim(char *str) { char *s; - for(s = str; *s != '\0'; ++s); - for(--s;isspace(*s) && s > str; --s); - if(s == str) *s = '\0'; - else *(++s) = '\0'; + for (s = str; *s != '\0'; ++s); + for (--s; isspace(*s) && s > str; --s); + if (s == str) + *s = '\0'; + else + *(++s) = '\0'; } /* Read numbers until non-digit is encountered, and return number in int form. */ -int curses_get_count(int first_digit) +int +curses_get_count(int first_digit) { long current_count = first_digit; int current_char; - + current_char = curses_read_char(); - - while (isdigit(current_char)) - { + + while (isdigit(current_char)) { current_count = (current_count * 10) + (current_char - '0'); - if (current_count > LARGEST_INT) - { + if (current_count > LARGEST_INT) { current_count = LARGEST_INT; } - + pline("Count: %ld", current_count); current_char = curses_read_char(); } - + ungetch(current_char); - - if (current_char == DOESCAPE) /* Cancelled with escape */ - { + + if (current_char == DOESCAPE) { /* Cancelled with escape */ current_count = -1; } - + return current_count; } @@ -686,43 +617,31 @@ int curses_get_count(int first_digit) /* Convert the given NetHack text attributes into the format curses understands, and return that format mask. */ -int curses_convert_attr(int attr) +int +curses_convert_attr(int attr) { int curses_attr; - - switch (attr) - { - case ATR_NONE: - { - curses_attr = A_NORMAL; - break; - } - case ATR_ULINE: - { - curses_attr = A_UNDERLINE; - break; - } - case ATR_BOLD: - { - curses_attr = A_BOLD; - break; - } - case ATR_BLINK: - { - curses_attr = A_BLINK; - break; - } - case ATR_INVERSE: - { - curses_attr = A_REVERSE; - break; - } - default: - { - curses_attr = A_NORMAL; - } + + switch (attr) { + case ATR_NONE: + curses_attr = A_NORMAL; + break; + case ATR_ULINE: + curses_attr = A_UNDERLINE; + break; + case ATR_BOLD: + curses_attr = A_BOLD; + break; + case ATR_BLINK: + curses_attr = A_BLINK; + break; + case ATR_INVERSE: + curses_attr = A_REVERSE; + break; + default: + curses_attr = A_NORMAL; } - + return curses_attr; } @@ -730,43 +649,36 @@ int curses_convert_attr(int attr) /* Map letter attributes from a string to bitmask. Return mask on success, or 0 if not found */ -int curses_read_attrs(char *attrs) +int +curses_read_attrs(char *attrs) { int retattr = 0; - if (strchr(attrs, 'b') || strchr(attrs, 'B')) - { - retattr = retattr|A_BOLD; + 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, 'i') || strchr(attrs, 'I')) { + retattr = retattr | A_REVERSE; } - if (strchr(attrs, 'u') || strchr(attrs, 'U')) - { - retattr = retattr|A_UNDERLINE; + if (strchr(attrs, 'u') || strchr(attrs, 'U')) { + retattr = retattr | A_UNDERLINE; } - if (strchr(attrs, 'k') || strchr(attrs, 'K')) - { - retattr = retattr|A_BLINK; + if (strchr(attrs, 'k') || strchr(attrs, 'K')) { + retattr = retattr | A_BLINK; } #ifdef A_ITALIC - if (strchr(attrs, 't') || strchr(attrs, 'T')) - { - retattr = retattr|A_ITALIC; + if (strchr(attrs, 't') || strchr(attrs, 'T')) { + retattr = retattr | A_ITALIC; } #endif #ifdef A_RIGHTLINE - if (strchr(attrs, 'r') || strchr(attrs, 'R')) - { - retattr = retattr|A_RIGHTLINE; + if (strchr(attrs, 'r') || strchr(attrs, 'R')) { + retattr = retattr | A_RIGHTLINE; } - #endif #ifdef A_LEFTLINE - if (strchr(attrs, 'l') || strchr(attrs, 'L')) - { - retattr = retattr|A_LEFTLINE; + if (strchr(attrs, 'l') || strchr(attrs, 'L')) { + retattr = retattr | A_LEFTLINE; } #endif @@ -777,136 +689,90 @@ int curses_read_attrs(char *attrs) /* Convert special keys into values that NetHack can understand. Currently this is limited to arrow keys, but this may be expanded. */ -int curses_convert_keys(int key) +int +curses_convert_keys(int key) { int ret = key; - - if (ret == '\033') - { + + if (ret == '\033') { ret = parse_escape_sequence(); } /* Handle arrow keys */ - switch (key) - { - case KEY_LEFT: - { - if (iflags.num_pad) - { - ret = '4'; - } - else - { - ret = 'h'; - } - break; - } - case KEY_RIGHT: - { - if (iflags.num_pad) - { - ret = '6'; - } - else - { - ret = 'l'; - } - break; - } - case KEY_UP: - { - if (iflags.num_pad) - { - ret = '8'; - } - else - { - ret = 'k'; - } - break; - } - case KEY_DOWN: - { - if (iflags.num_pad) - { - ret = '2'; - } - else - { - ret = 'j'; - } - break; - } + switch (key) { + case KEY_LEFT: + if (iflags.num_pad) { + ret = '4'; + } else { + ret = 'h'; + } + break; + case KEY_RIGHT: + if (iflags.num_pad) { + ret = '6'; + } else { + ret = 'l'; + } + break; + case KEY_UP: + if (iflags.num_pad) { + ret = '8'; + } else { + ret = 'k'; + } + break; + case KEY_DOWN: + if (iflags.num_pad) { + ret = '2'; + } else { + ret = 'j'; + } + break; #ifdef KEY_A1 - case KEY_A1: - { - if (iflags.num_pad) - { - ret = '7'; - } - else - { - ret = 'y'; - } - break; - } -#endif /* KEY_A1 */ + case KEY_A1: + if (iflags.num_pad) { + ret = '7'; + } else { + ret = 'y'; + } + break; +#endif /* KEY_A1 */ #ifdef KEY_A3 - case KEY_A3: - { - if (iflags.num_pad) - { - ret = '9'; - } - else - { - ret = 'u'; - } - break; - } -#endif /* KEY_A3 */ + case KEY_A3: + if (iflags.num_pad) { + ret = '9'; + } else { + ret = 'u'; + } + break; +#endif /* KEY_A3 */ #ifdef KEY_C1 - case KEY_C1: - { - if (iflags.num_pad) - { - ret = '1'; - } - else - { - ret = 'b'; - } - break; - } -#endif /* KEY_C1 */ + case KEY_C1: + if (iflags.num_pad) { + ret = '1'; + } else { + ret = 'b'; + } + break; +#endif /* KEY_C1 */ #ifdef KEY_C3 - case KEY_C3: - { - if (iflags.num_pad) - { - ret = '3'; - } - else - { - ret = 'n'; - } - break; - } -#endif /* KEY_C3 */ + case KEY_C3: + if (iflags.num_pad) { + ret = '3'; + } else { + ret = 'n'; + } + break; +#endif /* KEY_C3 */ #ifdef KEY_B2 - case KEY_B2: - { - if (iflags.num_pad) - { - ret = '5'; - } - else - { - ret = 'g'; - } - break; + case KEY_B2: + if (iflags.num_pad) { + ret = '5'; + } else { + ret = 'g'; } -#endif /* KEY_B2 */ + break; +#endif /* KEY_B2 */ } return ret; @@ -918,40 +784,39 @@ mouse movement events are available. Returns 0 for a mouse click event, or the first non-mouse key event in the case of mouse movement. */ -int curses_get_mouse(int *mousex, int *mousey, int *mod) +int +curses_get_mouse(int *mousex, int *mousey, int *mod) { int key = '\033'; + #ifdef NCURSES_MOUSE_VERSION - MEVENT event; + MEVENT event; - if (getmouse(&event) == OK) - { /* When the user clicks left mouse button */ - if(event.bstate & BUTTON1_CLICKED) - { + 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)) - { - key = 0; /* Flag mouse click */ + if (wmouse_trafo(mapwin, &event.y, &event.x, TRUE)) { + key = 0; /* Flag mouse click */ *mousex = event.x; *mousey = event.y; - - if (curses_window_has_border(MAP_WIN)) - { + + if (curses_window_has_border(MAP_WIN)) { (*mousex)--; (*mousey)--; } - + *mod = CLICK_1; } } } -#endif /* NCURSES_MOUSE_VERSION */ +#endif /* NCURSES_MOUSE_VERSION */ return key; } -static int parse_escape_sequence(void) +static int +parse_escape_sequence(void) { #ifndef PDCURSES int ret; @@ -960,29 +825,19 @@ static int parse_escape_sequence(void) ret = getch(); - if (ret != ERR) /* Likely an escape sequence */ - { - if (((ret >= 'a') && (ret <= 'z')) || - ((ret >= '0') && (ret <= '9'))) - { - ret |= 0x80; /* Meta key support for most terminals */ - } - else if (ret == 'O') /* Numeric keypad */ - { + if (ret != ERR) { /* Likely an escape sequence */ + if (((ret >= 'a') && (ret <= 'z')) || ((ret >= '0') && (ret <= '9'))) { + ret |= 0x80; /* Meta key support for most terminals */ + } else if (ret == 'O') { /* Numeric keypad */ ret = getch(); - if ((ret != ERR) && (ret >= 112) && (ret <= 121)) - { + if ((ret != ERR) && (ret >= 112) && (ret <= 121)) { ret = ret - 112 + '0'; /* Convert to number */ - } - else - { - ret = '\033'; /* Escape */ + } else { + ret = '\033'; /* Escape */ } } - } - else - { - ret = '\033'; /* Just an escape character */ + } else { + ret = '\033'; /* Just an escape character */ } timeout(-1); @@ -990,7 +845,7 @@ static int parse_escape_sequence(void) return ret; #else return '\033'; -#endif /* !PDCURSES */ +#endif /* !PDCURSES */ } @@ -999,8 +854,23 @@ functions, which causes a compiler error if TTY_GRAPHICS is not defined. Adding stub functions to avoid this. */ #if defined(STATUS_COLORS) && !defined(TTY_GRAPHICS) -extern void term_start_color(int color) {} -extern void term_start_attr(int attr) {} -extern void term_end_color() {} -extern void term_end_attr(int attr) {} -#endif /* STATUS_COLORS && !TTY_GRAPGICS */ +extern void +term_start_color(int color) +{ +} + +extern void +term_start_attr(int attr) +{ +} + +extern void +term_end_color() +{ +} + +extern void +term_end_attr(int attr) +{ +} +#endif /* STATUS_COLORS && !TTY_GRAPGICS */ diff --git a/win/curses/cursmisc.h b/win/curses/cursmisc.h index 0f03246a..50821c81 100644 --- a/win/curses/cursmisc.h +++ b/win/curses/cursmisc.h @@ -1,48 +1,30 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSMISC_H -#define CURSMISC_H +# define CURSMISC_H /* Global declarations */ int curses_read_char(void); - -void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff); - +void curses_toggle_color_attr(WINDOW * win, int color, int attr, int onoff); void curses_bail(const char *mesg); - winid curses_get_wid(int type); - char *curses_copy_of(const char *s); - int curses_num_lines(const char *str, int width); - char *curses_break_str(const char *str, int width, int line_num); - char *curses_str_remainder(const char *str, int width, int line_num); - boolean curses_is_menu(winid wid); - boolean curses_is_text(winid wid); - int curses_convert_glyph(int ch, int glyph); - void curses_move_cursor(winid wid, int x, int y); - void curses_prehousekeeping(void); - void curses_posthousekeeping(void); - void curses_view_file(const char *filename, boolean must_exist); - void curses_rtrim(char *str); - int curses_get_count(int first_digit); - int curses_convert_attr(int attr); - int curses_read_attrs(char *attrs); - int curses_convert_keys(int key); - int curses_get_mouse(int *mousex, int *mousey, int *mod); -#endif /* CURSMISC_H */ +#endif /* CURSMISC_H */ diff --git a/win/curses/cursstat.c b/win/curses/cursstat.c index f96c36bb..36127d74 100644 --- a/win/curses/cursstat.c +++ b/win/curses/cursstat.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" @@ -7,45 +9,42 @@ /* Private declarations */ -typedef struct nhs -{ +/* Used to track previous value of things, to highlight changes. */ +typedef struct nhs { long value; - char *txt; - aligntyp alignment; - boolean display; int highlight_turns; int highlight_color; - int stat_color; - int stat_attr; - int x; - int y; - char *label; - const char *id; } nhstat; -#ifdef STATUS_COLORS -extern const struct text_color_option *text_colors; -extern const struct percent_color_option *hp_colors; -extern const struct percent_color_option *pw_colors; +static attr_t get_trouble_color(const char *); +static void draw_trouble_str(const char *); +static void print_statdiff(const char *append, nhstat *, int, int); +static void get_playerrank(char *); +static int hpen_color(boolean, int, int); +static void draw_bar(boolean, int, int, const char *); +static void draw_horizontal(int, int, int, int); +static void draw_horizontal_new(int, int, int, int); +static void draw_vertical(int, int, int, int); +static void curses_add_statuses(WINDOW *, boolean, boolean, int *, int *); +static void curses_add_status(WINDOW *, boolean, boolean, int *, int *, + const char *, int); +static int decrement_highlight(nhstat *, boolean); +#ifdef STATUS_COLORS +static attr_t hpen_color_attr(boolean, int, int); extern struct color_option text_color_of(const char *text, - const struct text_color_option *color_options); - + const struct text_color_option *color_options); struct color_option percentage_color_of(int value, int max, - const struct percent_color_option *color_options); + const struct percent_color_option *color_options); -static boolean stat_colored(const char *id); +extern const struct text_color_option *text_colors; +extern const struct percent_color_option *hp_colors; +extern const struct percent_color_option *pw_colors; #endif -static void init_stats(void); - -static void set_labels(int label_width); - -static void set_stat_color(nhstat *stat); - -static void color_stat(nhstat stat, int onoff); - -static nhstat prevname; +/* Whether or not we have printed status window content at least once. + Used to ensure that prev* doesn't end up highlighted on game start. */ +static boolean first = TRUE; static nhstat prevdepth; static nhstat prevstr; static nhstat prevint; @@ -53,2675 +52,916 @@ static nhstat prevwis; static nhstat prevdex; static nhstat prevcon; static nhstat prevcha; -static nhstat prevalign; static nhstat prevau; -static nhstat prevhp; -static nhstat prevmhp; static nhstat prevlevel; -static nhstat prevpow; -static nhstat prevmpow; static nhstat prevac; static nhstat prevexp; static nhstat prevtime; + #ifdef SCORE_ON_BOTL static nhstat prevscore; #endif -static nhstat prevhunger; -static nhstat prevconf; -static nhstat prevblind; -static nhstat prevstun; -static nhstat prevhallu; -static nhstat prevsick; -static nhstat prevslime; -static nhstat prevencumb; - -#define COMPACT_LABELS 1 -#define NORMAL_LABELS 2 -#define WIDE_LABELS 3 - -extern const char *hu_stat[]; /* from eat.c */ -extern const char *enc_stat[]; /* from botl.c */ -/* Update the status win - this is called when NetHack would normally -write to the status window, so we know somwthing has changed. We -override the write and update what needs to be updated ourselves. */ - -void curses_update_stats(boolean redraw) +extern const char *hu_stat[]; /* from eat.c */ +extern const char *enc_stat[]; /* from botl.c */ + +/* If the statuscolors patch isn't enabled, have some default colors for status problems + anyway */ + +struct statcolor { + const char *txt; /* For status problems */ + int color; /* Default color assuming STATUS_COLORS isn't enabled */ +}; + +static const struct statcolor default_colors[] = { + {"Satiated", CLR_YELLOW}, + {"Hungry", CLR_YELLOW}, + {"Weak", CLR_ORANGE}, + {"Fainted", CLR_BRIGHT_MAGENTA}, + {"Fainting", CLR_BRIGHT_MAGENTA}, + {"Burdened", CLR_RED}, + {"Stressed", CLR_RED}, + {"Strained", CLR_ORANGE}, + {"Overtaxed", CLR_ORANGE}, + {"Overloaded", CLR_BRIGHT_MAGENTA}, + {"Conf", CLR_BRIGHT_BLUE}, + {"Blind", CLR_BRIGHT_BLUE}, + {"Stun", CLR_BRIGHT_BLUE}, + {"Hallu", CLR_BRIGHT_BLUE}, + {"Ill", CLR_BRIGHT_MAGENTA}, + {"FoodPois", CLR_BRIGHT_MAGENTA}, + {"Slime", CLR_BRIGHT_MAGENTA}, + {NULL, NULL, NO_COLOR}, +}; + +static attr_t +get_trouble_color(const char *stat) { - char buf[BUFSZ]; - int count, enc, orient, sx_start, hp, hpmax, labels, swidth, - sheight, sx_end, sy_end; - WINDOW *win = curses_get_nhwin(STATUS_WIN); - static int prev_labels = -1; - static boolean first = TRUE; - static boolean horiz; - int sx = 0; - int sy = 0; - boolean border = curses_window_has_border(STATUS_WIN); - - curses_get_window_size(STATUS_WIN, &sheight, &swidth); + attr_t res = curses_color_attr(CLR_GRAY, 0); + const struct statcolor *clr; + for (clr = default_colors; clr->txt; clr++) { + if (stat && !strcmp(clr->txt, stat)) { +#ifdef STATUS_COLORS + /* Check if we have a color enabled with statuscolors */ + if (!iflags.use_status_colors) + return curses_color_attr(CLR_GRAY, 0); /* no color configured */ - if (border) - { - sx++; - sy++; - swidth--; - sheight--; - } - - sx_end = swidth - 1; - sy_end = sheight - 1; - sx_start = sx; - - if (first) - { - init_stats(); - first = FALSE; - redraw = TRUE; - } + struct color_option stat_color; - if (redraw) - { - orient = curses_get_window_orientation(STATUS_WIN); + stat_color = text_color_of(clr->txt, text_colors); + if (stat_color.color == NO_COLOR && !stat_color.attr_bits) + return curses_color_attr(CLR_GRAY, 0); - if ((orient == ALIGN_RIGHT) || (orient == ALIGN_LEFT)) - { - horiz = FALSE; - } - else - { - horiz = TRUE; - } - } - - if (horiz) - { - if (term_cols >= 80) - { - labels = NORMAL_LABELS; - } - else - { - labels = COMPACT_LABELS; - } - } - else - { - labels = WIDE_LABELS; - } - - if (labels != prev_labels) - { - set_labels(labels); - prev_labels = labels; - } + if (stat_color.color != NO_COLOR) + res = curses_color_attr(stat_color.color, 0); - curses_clear_nhwin(STATUS_WIN); - - /* Line 1 */ - - /* Player name and title */ - strcpy(buf, plname); - if ('a' <= buf[0] && buf[0] <= 'z') buf[0] += 'A'-'a'; - strcat(buf, " the "); - if (u.mtimedone) { - char mname[BUFSZ]; - int k = 0; - strcpy(mname, mons[u.umonnum].mname); - while(mname[k] != 0) { - if ((k == 0 || (k > 0 && mname[k-1] == ' ')) - && 'a' <= mname[k] && mname[k] <= 'z') - { - mname[k] += 'A' - 'a'; + res = curses_color_attr(stat_color.color, 0); + int count; + for (count = 0; (1 << count) <= stat_color.attr_bits; count++) { + if (count != ATR_NONE && + (stat_color.attr_bits & (1 << count))) + res |= curses_convert_attr(count); } - k++; - } - strcat(buf, mname); - } else { - strcat(buf, rank_of(u.ulevel, pl_character[0], flags.female)); - } - - if (strcmp(buf, prevname.txt) != 0) /* Title changed */ - { - prevname.highlight_turns = 5; - prevname.highlight_color = HIGHLIGHT_COLOR; - free(prevname.txt); - prevname.txt = curses_copy_of(buf); - if ((labels == COMPACT_LABELS) && (u.ulevel > 1)) - { - curses_puts(MESSAGE_WIN, A_NORMAL, "You are now known as"); - curses_puts(MESSAGE_WIN, A_NORMAL, prevname.txt); - } - } - - if (prevname.label != NULL) - { - mvwaddstr(win, sy, sx, prevname.label); - sx += strlen(prevname.label); - } - - if (labels != COMPACT_LABELS) - { - color_stat(prevname, ON); - mvwaddstr(win, sy, sx, prevname.txt); - color_stat(prevname, OFF); - } - - if (horiz) - { - if (labels != COMPACT_LABELS) - { - sx += strlen(prevname.txt) + 1; - } - - - } - else - { - sx = sx_start; - sy++; - } - - /* Add dungeon name and level if status window is vertical */ - if (!horiz) - { - sprintf(buf, "%s", dungeons[u.uz.dnum].dname); - mvwaddstr(win, sy, sx, buf); - sy += 2; - } - /* Strength */ - if (ACURR(A_STR) != prevstr.value) /* Strength changed */ - { - - if (ACURR(A_STR) > prevstr.value) - { - prevstr.highlight_color = STAT_UP_COLOR; - } - else - { - prevstr.highlight_color = STAT_DOWN_COLOR; - } - prevstr.value = ACURR(A_STR); - if (ACURR(A_STR) > 118) - { - sprintf(buf, "%d", ACURR(A_STR) - 100); - } - else if (ACURR(A_STR)==118) - { - sprintf(buf, "18/**"); - } - else if(ACURR(A_STR) > 18) - { - sprintf(buf, "18/%02d", ACURR(A_STR) - 18); - } - else - { - sprintf(buf, "%d", ACURR(A_STR)); + return res; +#else + return curses_color_attr(clr->color, 0); +#endif } - free(prevstr.txt); - prevstr.txt = curses_copy_of(buf); - prevstr.highlight_turns = 5; - } - - if (prevstr.label != NULL) - { - mvwaddstr(win, sy, sx, prevstr.label); - sx += strlen(prevstr.label); - } - - color_stat(prevstr, ON); - mvwaddstr(win, sy, sx, prevstr.txt); - color_stat(prevstr, OFF); - - if (horiz) - { - sx += strlen(prevstr.txt) + 1; - } - else - { - sx = sx_start; - sy++; } - /* Intelligence */ - if (ACURR(A_INT) != prevint.value) /* Intelligence changed */ - { - - if (ACURR(A_INT) > prevint.value) - { - prevint.highlight_color = STAT_UP_COLOR; - } - else - { - prevint.highlight_color = STAT_DOWN_COLOR; - } - prevint.value = ACURR(A_INT); - sprintf(buf, "%d", ACURR(A_INT)); - free(prevint.txt); - prevint.txt = curses_copy_of(buf); - prevint.highlight_turns = 5; - } + return res; +} - if (prevint.label != NULL) - { - mvwaddstr(win, sy, sx, prevint.label); - sx += strlen(prevint.label); - } - - color_stat(prevint, ON); - mvwaddstr(win, sy, sx, prevint.txt); - color_stat(prevint, OFF); - - if (horiz) - { - sx += strlen(prevint.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } +/* TODO: This is in the wrong place. */ +void +get_playerrank(char *rank) +{ + char buf[BUFSZ]; + if (Upolyd) { + int k = 0; - /* Wisdom */ - if (ACURR(A_WIS) != prevwis.value) /* Wisdom changed */ - { - - if (ACURR(A_WIS) > prevwis.value) - { - prevwis.highlight_color = STAT_UP_COLOR; - } - else - { - prevwis.highlight_color = STAT_DOWN_COLOR; + Strcpy(buf, mons[u.umonnum].mname); + while(buf[k] != 0) { + if ((k == 0 || (k > 0 && buf[k-1] == ' ')) && + 'a' <= buf[k] && buf[k] <= 'z') + buf[k] += 'A' - 'a'; + k++; } - prevwis.value = ACURR(A_WIS); - sprintf(buf, "%d", ACURR(A_WIS)); - free(prevwis.txt); - prevwis.txt = curses_copy_of(buf); - prevwis.highlight_turns = 5; - } + Strcpy(rank, buf); + } else + Strcpy(rank, rank_of(u.ulevel, Role_switch, flags.female)); +} - if (prevwis.label != NULL) - { - mvwaddstr(win, sy, sx, prevwis.label); - sx += strlen(prevwis.label); - } - - color_stat(prevwis, ON); - mvwaddstr(win, sy, sx, prevwis.txt); - color_stat(prevwis, OFF); - - if (horiz) - { - sx += strlen(prevwis.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } +/* Handles numerical stat changes of various kinds. + type is generally STAT_OTHER (generic "do nothing special"), + but is used if the stat needs to be handled in a special way. */ +static void +print_statdiff(const char *append, nhstat *stat, int new, int type) +{ + char buf[BUFSZ]; + WINDOW *win = curses_get_nhwin(STATUS_WIN); - /* Dexterity */ - if (ACURR(A_DEX) != prevdex.value) /* Dexterity changed */ - { - - if (ACURR(A_DEX) > prevdex.value) - { - prevdex.highlight_color = STAT_UP_COLOR; - } + int color = CLR_GRAY; + + /* Turncount isn't highlighted, or it would be highlighted constantly. */ + if (type != STAT_TIME && new != stat->value) { + /* Less AC is better */ + if ((type == STAT_AC && new < stat->value) || + (type != STAT_AC && new > stat->value)) { + color = STAT_UP_COLOR; + if (type == STAT_GOLD) + color = HI_GOLD; + } else + color = STAT_DOWN_COLOR; + + stat->value = new; + stat->highlight_color = color; + stat->highlight_turns = 5; + } else if (stat->highlight_turns) + color = stat->highlight_color; + + attr_t attr = curses_color_attr(color, 0); + wattron(win, attr); + wprintw(win, "%s", append); + if (type == STAT_STR && new > 18) { + if (new > 118) + wprintw(win, "%d", new - 100); + else if (new == 118) + wprintw(win, "18/**"); else - { - prevdex.highlight_color = STAT_DOWN_COLOR; - } - prevdex.value = ACURR(A_DEX); - sprintf(buf, "%d", ACURR(A_DEX)); - free(prevdex.txt); - prevdex.txt = curses_copy_of(buf); - prevdex.highlight_turns = 5; - } - - if (prevdex.label != NULL) - { - mvwaddstr(win, sy, sx, prevdex.label); - sx += strlen(prevdex.label); - } - - color_stat(prevdex, ON); - mvwaddstr(win, sy, sx, prevdex.txt); - color_stat(prevdex, OFF); - - if (horiz) - { - sx += strlen(prevdex.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } + wprintw(win, "18/%02d", new - 18); + } else + wprintw(win, "%d", new); - /* Constitution */ - if (ACURR(A_CON) != prevcon.value) /* Constitution changed */ - { - - if (ACURR(A_CON) > prevcon.value) - { - prevcon.highlight_color = STAT_UP_COLOR; - } - else - { - prevcon.highlight_color = STAT_DOWN_COLOR; - } - prevcon.value = ACURR(A_CON); - sprintf(buf, "%d", ACURR(A_CON)); - free(prevcon.txt); - prevcon.txt = curses_copy_of(buf); - prevcon.highlight_turns = 5; - } + wattroff(win, attr); +} - if (prevcon.label != NULL) - { - mvwaddstr(win, sy, sx, prevcon.label); - sx += strlen(prevcon.label); - } - - color_stat(prevcon, ON); - mvwaddstr(win, sy, sx, prevcon.txt); - color_stat(prevcon, OFF); - - if (horiz) - { - sx += strlen(prevcon.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } +static void +draw_trouble_str(const char *str) +{ + WINDOW *win = curses_get_nhwin(STATUS_WIN); - /* Charisma */ - if (ACURR(A_CHA) != prevcha.value) /* Charisma changed */ - { - if (ACURR(A_CHA) > prevcha.value) - { - prevcha.highlight_color = STAT_UP_COLOR; - } - else - { - prevcha.highlight_color = STAT_DOWN_COLOR; - } - prevcha.value = ACURR(A_CHA); - sprintf(buf, "%d", ACURR(A_CHA)); - free(prevcha.txt); - prevcha.txt = curses_copy_of(buf); - prevcha.highlight_turns = 5; - } + attr_t attr = get_trouble_color(str); + wattron(win, attr); + wprintw(win, "%s", str); + wattroff(win, attr); +} - if (prevcha.label != NULL) - { - mvwaddstr(win, sy, sx, prevcha.label); - sx += strlen(prevcha.label); - } - - color_stat(prevcha, ON); - mvwaddstr(win, sy, sx, prevcha.txt); - color_stat(prevcha, OFF); - - if (horiz) - { - sx += strlen(prevcha.txt) + 1; - } - else - { - sx = sx_start; - sy ++; - } - - /* Alignment */ - if (prevalign.alignment != u.ualign.type) /* Alignment changed */ - { - prevalign.highlight_color = HIGHLIGHT_COLOR; - prevalign.highlight_turns = 10; /* This is a major change! */ - prevalign.alignment = u.ualign.type; - free(prevalign.txt); - switch (u.ualign.type) - { - case A_LAWFUL: - { - prevalign.txt = curses_copy_of("Lawful"); +/* Returns a ncurses attribute for foreground and background. + This should probably be in cursinit.c or something. */ +attr_t +curses_color_attr(int nh_color, int bg_color) +{ + int color = nh_color + 1; + attr_t cattr = A_NORMAL; + + if (!nh_color) { +#ifdef USE_DARKGRAY + if (iflags.wc2_darkgray) { + if (!can_change_color() || COLORS <= 16) + cattr |= A_BOLD; + } else +#endif + color = COLOR_BLUE; + } + + if (COLORS < 16 && color > 8) { + color -= 8; + cattr = A_BOLD; + } + + /* Can we do background colors? We can if we have more than + 16*7 colors (more than 8*7 for terminals with bold) */ + if (COLOR_PAIRS > (COLORS >= 16 ? 16 : 8) * 7) { + /* NH3 has a rather overcomplicated way of defining + its colors past the first 16: + Pair Foreground Background + 17 Black Red + 18 Black Blue + 19 Red Red + 20 Red Blue + 21 Green Red + ... + (Foreground order: Black, Red, Green, Yellow, Blue, + Magenta, Cyan, Gray/White) + + To work around these oddities, we define backgrounds + by the following pairs: + + 16 COLORS + 49-64: Green + 65-80: Yellow + 81-96: Magenta + 97-112: Cyan + 113-128: Gray/White + + 8 COLORS + 9-16: Green + 33-40: Yellow + 41-48: Magenta + 49-56: Cyan + 57-64: Gray/White */ + + if (bg_color == nh_color) + color = 1; /* Make foreground black if fg==bg */ + + if (bg_color == CLR_RED || bg_color == CLR_BLUE) { + /* already defined before extension */ + color *= 2; + color += 16; + if (bg_color == CLR_RED) + color--; + } else { + boolean hicolor = FALSE; + if (COLORS >= 16) + hicolor = TRUE; + + switch (bg_color) { + case CLR_GREEN: + color = (hicolor ? 48 : 8) + color; break; - } - case A_NEUTRAL: - { - prevalign.txt = curses_copy_of("Neutral"); + case CLR_BROWN: + color = (hicolor ? 64 : 32) + color; break; - } - case A_CHAOTIC: - { - prevalign.txt = curses_copy_of("Chaotic"); + case CLR_MAGENTA: + color = (hicolor ? 80 : 40) + color; + break; + case CLR_CYAN: + color = (hicolor ? 96 : 48) + color; + break; + case CLR_GRAY: + color = (hicolor ? 112 : 56) + color; + break; + default: break; } } } + cattr |= COLOR_PAIR(color); - if (prevalign.label != NULL) - { - mvwaddstr(win, sy, sx, prevalign.label); - sx += strlen(prevalign.label); - } - - color_stat(prevalign, ON); - mvwaddstr(win, sy, sx, prevalign.txt); - color_stat(prevalign, OFF); + return cattr; +} - /* Line 2 */ - - sx = sx_start; - sy++; - - /* Dungeon Level */ - if (depth(&u.uz) != prevdepth.value) /* Dungeon level changed */ - { - prevdepth.highlight_color = HIGHLIGHT_COLOR; - prevdepth.highlight_turns = 5; - prevdepth.value = depth(&u.uz); - free(prevdepth.txt); - if (In_endgame(&u.uz)) - { - strcpy(buf, (Is_astralevel(&u.uz) ? "Astral Plane":"End Game")); - } - else - { - sprintf(buf, "%d", depth(&u.uz)); - } - prevdepth.txt = curses_copy_of(buf); - } - - if (prevdepth.label != NULL) - { - mvwaddstr(win, sy, sx, prevdepth.label); - sx += strlen(prevdepth.label); - } - - color_stat(prevdepth, ON); - mvwaddstr(win, sy, sx, prevdepth.txt); - color_stat(prevdepth, OFF); - - if (horiz) - { - sx += strlen(prevdepth.txt) + 1; - } - else - { - sx = sx_start; - sy++; +/* Returns a complete curses attribute. Used to possibly bold/underline/etc HP/Pw. */ +#ifdef STATUS_COLORS +static attr_t +hpen_color_attr(boolean is_hp, int cur, int max) +{ + struct color_option stat_color; + int count; + attr_t attr = 0; + if (!iflags.use_status_colors) + return curses_color_attr(CLR_GRAY, 0); + + stat_color = percentage_color_of(cur, max, is_hp ? hp_colors : pw_colors); + + if (stat_color.color != NO_COLOR) + attr |= curses_color_attr(stat_color.color, 0); + + for (count = 0; (1 << count) <= stat_color.attr_bits; count++) { + if (count != ATR_NONE && (stat_color.attr_bits & (1 << count))) + attr |= curses_convert_attr(count); } - - /* Gold */ -#ifndef GOLDOBJ - if (prevau.value != u.ugold) /* Gold changed */ - { - if (u.ugold > prevau.value) - { -#else - if (prevau.value != money_cnt(invent)) /* Gold changed */ - { - if (money_cnt(invent) > prevau.value) - { + + return attr; +} #endif - prevau.highlight_color = HI_GOLD; - } + +/* Return color for the HP bar. + With status colors ON, this respect its configuration (defaulting to gray), but + only obeys the color (no weird attributes for the HP bar). + With status colors OFF, this returns reasonable defaults which are also used + for the HP/Pw text itself. */ +static int +hpen_color(boolean is_hp, int cur, int max) +{ +#ifdef STATUS_COLORS + if (iflags.use_status_colors) { + struct color_option stat_color; + stat_color = percentage_color_of(cur, max, is_hp ? hp_colors : pw_colors); + + if (stat_color.color == NO_COLOR) + return CLR_GRAY; else - { - prevau.highlight_color = STAT_DOWN_COLOR; - } -#ifndef GOLDOBJ - prevau.value = u.ugold; - sprintf(buf,"%ld", u.ugold); -#else - prevau.value = money_cnt(invent); - sprintf(buf,"%ld", money_cnt(invent)); + return stat_color.color; + } else + return CLR_GRAY; #endif - free(prevau.txt); - prevau.txt = curses_copy_of(buf); - prevau.highlight_turns = 5; - } - - if (prevau.label != NULL) - { - mvwaddstr(win, sy, sx, prevau.label); - sx += strlen(prevau.label); - } - - color_stat(prevau, ON); - mvwaddstr(win, sy, sx, prevau.txt); - color_stat(prevau, OFF); - - if (horiz) - { - sx += strlen(prevau.txt) + 1; - } + + int color = CLR_GRAY; + if (cur == max) + color = CLR_GRAY; + else if (cur * 3 > max * 2) /* >2/3 */ + color = is_hp ? CLR_GREEN : CLR_CYAN; + else if (cur * 3 > max) /* >1/3 */ + color = is_hp ? CLR_YELLOW : CLR_BLUE; + else if (cur * 7 > max) /* >1/7 */ + color = is_hp ? CLR_RED : CLR_MAGENTA; else - { - sx = sx_start; - sy++; - } + color = is_hp ? CLR_ORANGE : CLR_BRIGHT_MAGENTA; + return color; +} - /* Hit Points */ - - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - hp = u.mh; - hpmax = u.mhmax; - } - else /* Not polymorphed */ - { - hp = u.uhp; - hpmax = u.uhpmax; - } - - if (hp != prevhp.value) - { - if (hp > prevhp.value) - { - prevhp.highlight_color = STAT_UP_COLOR; - } - else - { - prevhp.highlight_color = STAT_DOWN_COLOR; - } - prevhp.value = hp; - if (prevhp.value < 0) - { - prevhp.value = 0; - } - sprintf(buf, "%ld", prevhp.value); - free(prevhp.txt); - prevhp.txt = curses_copy_of(buf); - prevhp.highlight_turns = 3; - } - - if (prevhp.label != NULL) - { - mvwaddstr(win, sy, sx, prevhp.label); - sx += strlen(prevhp.label); - } +/* Draws a bar + is_hp: TRUE if we're drawing HP, Pw otherwise (determines colors) + cur/max: Current/max HP/Pw + title: Not NULL if we are drawing as part of an existing title. + Otherwise, the format is as follows: [ 11 / 11 ] */ +static void +draw_bar(boolean is_hp, int cur, int max, const char *title) +{ + WINDOW *win = curses_get_nhwin(STATUS_WIN); - color_stat(prevhp, ON); - mvwaddstr(win, sy, sx, prevhp.txt); - color_stat(prevhp, OFF); - - sx += strlen(prevhp.txt); - - /* Max Hit Points */ - - if (hpmax != prevmhp.value) /* Not polymorphed */ - { - if (hpmax > prevmhp.value) - { - prevmhp.highlight_color = STAT_UP_COLOR; - } - else - { - prevmhp.highlight_color = STAT_DOWN_COLOR; - } - prevmhp.value = hpmax; - sprintf(buf, "%d", hpmax); - free(prevmhp.txt); - prevmhp.txt = curses_copy_of(buf); - prevmhp.highlight_turns = 3; - } - - if (prevmhp.label != NULL) - { - mvwaddstr(win, sy, sx, prevmhp.label); - sx += strlen(prevmhp.label); +#ifdef STATUS_COLORS + if (!iflags.hitpointbar) { + wprintw(win, "%s", !title ? "---" : title); + return; } +#endif - color_stat(prevmhp, ON); - mvwaddstr(win, sy, sx, prevmhp.txt); - color_stat(prevmhp, OFF); + char buf[BUFSZ]; + if (title) + Strcpy(buf, title); + else { + int len = 5; + sprintf(buf, "%*d / %-*d", len, cur, len, max); + } + + /* Colors */ + attr_t fillattr, attr; + int color = hpen_color(is_hp, cur, max); + int invcolor = color & 7; + + fillattr = curses_color_attr(color, invcolor); + attr = curses_color_attr(color, 0); + + /* Figure out how much of the bar to fill */ + int fill = 0; + int len = strlen(buf); + if (cur > 0 && max > 0) + fill = len * cur / max; + if (fill > len) + fill = len; + + waddch(win, '['); + wattron(win, fillattr); + wprintw(win, "%.*s", fill, buf); + wattroff(win, fillattr); + wattron(win, attr); + wprintw(win, "%.*s", len - fill, &buf[fill]); + wattroff(win, attr); + waddch(win, ']'); +} - if (horiz) - { - color_stat(prevmhp, ON); - sx += strlen(prevmhp.txt) + 1; - color_stat(prevmhp, OFF); - } - else - { - sx = sx_start; - sy++; - } +/* Update the status win - this is called when NetHack would normally + write to the status window, so we know somwthing has changed. We + override the write and update what needs to be updated ourselves. */ +void +curses_update_stats(void) +{ + WINDOW *win = curses_get_nhwin(STATUS_WIN); - /* Power */ - if (u.uen != prevpow.value) - { - if (u.uen > prevpow.value) - { - prevpow.highlight_color = STAT_UP_COLOR; - } - else - { - prevpow.highlight_color = STAT_DOWN_COLOR; - } - prevpow.value = u.uen; - sprintf(buf, "%d", u.uen); - free(prevpow.txt); - prevpow.txt = curses_copy_of(buf); - prevpow.highlight_turns = 3; - } - - if (prevpow.label != NULL) - { - mvwaddstr(win, sy, sx, prevpow.label); - sx += strlen(prevpow.label); - } + /* Clear the window */ + werase(win); - color_stat(prevpow, ON); - mvwaddstr(win, sy, sx, prevpow.txt); - color_stat(prevpow, OFF); - - sx += strlen(prevpow.txt); - - /* Max Power */ - if (u.uenmax != prevmpow.value) - { - if (u.uenmax > prevmpow.value) - { - prevmpow.highlight_color = STAT_UP_COLOR; - } - else - { - prevmpow.highlight_color = STAT_DOWN_COLOR; - } - prevmpow.value = u.uenmax; - sprintf(buf, "%d", u.uenmax); - free(prevmpow.txt); - prevmpow.txt = curses_copy_of(buf); - prevmpow.highlight_turns = 3; - } - - if (prevmpow.label != NULL) - { - mvwaddstr(win, sy, sx, prevmpow.label); - sx += strlen(prevmpow.label); - } + int orient = curses_get_window_orientation(STATUS_WIN); - color_stat(prevmpow, ON); - mvwaddstr(win, sy, sx, prevmpow.txt); - color_stat(prevmpow, OFF); - - if (horiz) - { - sx += strlen(prevmpow.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } + boolean horiz = FALSE; + if ((orient != ALIGN_RIGHT) && (orient != ALIGN_LEFT)) + horiz = TRUE; + boolean border = curses_window_has_border(STATUS_WIN); - /* Armor Class */ - if (u.uac != prevac.value) - { - if (u.uac > prevac.value) /* Lower is better for AC */ - { - prevac.highlight_color = STAT_DOWN_COLOR; - } - else - { - prevac.highlight_color = STAT_UP_COLOR; - } - prevac.value = u.uac; - sprintf(buf, "%d", u.uac); - free(prevac.txt); - prevac.txt = curses_copy_of(buf); - prevac.highlight_turns = 5; - } - - if (prevac.label != NULL) - { - mvwaddstr(win, sy, sx, prevac.label); - sx += strlen(prevac.label); - } + /* Figure out if we have proper window dimensions for horizontal statusbar. */ + if (horiz) { + /* correct y */ + int cy = 3; + if (iflags.classic_status) + cy = 2; - color_stat(prevac, ON); - mvwaddstr(win, sy, sx, prevac.txt); - color_stat(prevac, OFF); - - if (horiz) - { - sx += strlen(prevac.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } + /* actual y (and x) */ + int ax = 0; + int ay = 0; + getmaxyx(win, ay, ax); + if (border) + ay -= 2; - /* Experience */ -#ifdef EXP_ON_BOTL - if (prevexp.display != flags.showexp) /* Setting has changed */ - { - prevexp.display = flags.showexp; - free(prevlevel.label); - if (prevexp.display) - { - prevlevel.label = curses_copy_of("/"); - } - else - { - if (horiz) - { - if (labels == COMPACT_LABELS) - { - prevlevel.label = curses_copy_of("Lv:"); - } - else - { - prevlevel.label = curses_copy_of("Lvl:"); - } - } - else - { - prevlevel.label = curses_copy_of("Level: "); - } - } - } + if (cy != ay) { + curses_create_main_windows(); + curses_last_messages(); + doredraw(); - if (prevexp.display && !u.mtimedone) - { - if (u.uexp != prevexp.value) - { - if (u.uexp > prevexp.value) - { - prevexp.highlight_color = STAT_UP_COLOR; - } - else - { - prevexp.highlight_color = STAT_DOWN_COLOR; - } - sprintf(buf, "%ld", u.uexp); - free(prevexp.txt); - prevexp.txt = curses_copy_of(buf); - prevexp.highlight_turns = 3; - } - - if (prevexp.label != NULL) - { - mvwaddstr(win, sy, sx, prevexp.label); - sx += strlen(prevexp.label); + /* Reset XP highlight (since classic_status and new show different numbers) */ + prevexp.highlight_turns = 0; + curses_update_stats(); + return; } + } - color_stat(prevexp, ON); - mvwaddstr(win, sy, sx, prevexp.txt); - color_stat(prevexp, OFF); + /* Starting x/y. Passed to draw_horizontal/draw_vertical to keep track of + window positioning. */ + int x = 0; + int y = 0; - sx += strlen(prevexp.txt); - } - - prevexp.value = u.uexp; /* Track it even when it's not displayed */ -#endif /* EXP_ON_BOTL */ - - /* Level */ - if (u.mtimedone) /* Currently polymorphed - show monster HD */ - { - if ((strncmp(prevlevel.label, "HP:", 3) != 0) || - (strncmp(prevlevel.label, "Hit Points:", 11) != 0)) - { - free(prevlevel.label); - if (horiz) - { - prevlevel.label = curses_copy_of("HD:"); - } - else - { - prevlevel.label = curses_copy_of("Hit Dice: "); - } - } - if (mons[u.umonnum].mlevel != prevlevel.value) - { - if (mons[u.umonnum].mlevel > prevlevel.value) - { - prevlevel.highlight_color = STAT_UP_COLOR; - } - else - { - prevlevel.highlight_color = STAT_DOWN_COLOR; - } - prevlevel.highlight_turns = 5; - } - prevlevel.value = mons[u.umonnum].mlevel; - sprintf(buf, "%d", mons[u.umonnum].mlevel); - free(prevlevel.txt); - prevlevel.txt = curses_copy_of(buf); - } - else /* Not polymorphed */ - { - if ((strncmp(prevlevel.label, "HD:", 3) != 0) || - (strncmp(prevlevel.label, "Hit Dice:", 9) != 0)) - { - free(prevlevel.label); - if (prevexp.display) - { - prevlevel.label = curses_copy_of("/"); - } - else - { - if (horiz) - { - if (labels == COMPACT_LABELS) - { - prevlevel.label = curses_copy_of("Lv:"); - } - else - { - prevlevel.label = curses_copy_of("Lvl:"); - } - } - else - { - prevlevel.label = curses_copy_of("Level: "); - } - } - } - if (u.ulevel > prevlevel.value) - { - prevlevel.highlight_color = STAT_UP_COLOR; - prevlevel.highlight_turns = 5; - } - else if (u.ulevel < prevlevel.value) - { - prevlevel.highlight_color = STAT_DOWN_COLOR; - prevlevel.highlight_turns = 5; - } - prevlevel.value = u.ulevel; - sprintf(buf, "%d", u.ulevel); - free(prevlevel.txt); - prevlevel.txt = curses_copy_of(buf); + /* Don't start at border position if applicable */ + if (border) { + x++; + y++; } - if (prevlevel.label != NULL) - { - mvwaddstr(win, sy, sx, prevlevel.label); - sx += strlen(prevlevel.label); + /* Get HP values. */ + int hp = u.uhp; + int hpmax = u.uhpmax; + if (Upolyd) { + hp = u.mh; + hpmax = u.mhmax; } - color_stat(prevlevel, ON); - mvwaddstr(win, sy, sx, prevlevel.txt); - color_stat(prevlevel, OFF); - - if (horiz) - { - sx += strlen(prevlevel.txt) + 1; - } + if (orient != ALIGN_RIGHT && orient != ALIGN_LEFT) + draw_horizontal(x, y, hp, hpmax); else - { - sx = sx_start; - sy++; - } + draw_vertical(x, y, hp, hpmax); - /* Time */ - if (prevtime.display != flags.time) /* Setting has changed */ - { - prevtime.display = flags.time; - } - if (prevtime.display) - { - if (moves != prevtime.value) - { - sprintf(buf, "%ld", moves); - free(prevtime.txt); - prevtime.txt = curses_copy_of(buf); - } - - if (prevtime.label != NULL) - { - mvwaddstr(win, sy, sx, prevtime.label); - sx += strlen(prevtime.label); - } + if (border) + box(win, 0, 0); - color_stat(prevtime, ON); - mvwaddstr(win, sy, sx, prevtime.txt); - color_stat(prevtime, OFF); + wnoutrefresh(win); - if (horiz) - { - sx += strlen(prevtime.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } + if (first) { + first = FALSE; + + /* Zero highlight timers. This will call curses_update_status again if needed */ + curses_decrement_highlights(TRUE); } - - /* Score */ -#ifdef SCORE_ON_BOTL - if (prevscore.display != flags.showscore) /* Setting has changed */ - { - prevscore.display = flags.showscore; +} + +static void +draw_horizontal(int x, int y, int hp, int hpmax) +{ + if (!iflags.classic_status) { + /* Draw new-style statusbar */ + draw_horizontal_new(x, y, hp, hpmax); + return; } - if (prevscore.display) - { - if (botl_score() != prevscore.value) - { - if (botl_score() > prevscore.value) - { - prevscore.highlight_color = STAT_UP_COLOR; - } - else /* Not sure this is possible */ - { - prevscore.highlight_color = STAT_DOWN_COLOR; - } - sprintf(buf, "%ld", botl_score()); - free(prevscore.txt); - prevscore.txt = curses_copy_of(buf); - prevscore.highlight_turns = 3; - } - - if (prevscore.label != NULL) - { - mvwaddstr(win, sy, sx, prevscore.label); - sx += strlen(prevscore.label); - } + char buf[BUFSZ]; + char rank[BUFSZ]; + WINDOW *win = curses_get_nhwin(STATUS_WIN); - color_stat(prevscore, ON); - mvwaddstr(win, sy, sx, prevscore.txt); - color_stat(prevscore, OFF); + /* Line 1 */ + wmove(win, y, x); - if (horiz) - { - sx += strlen(prevscore.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } - - prevscore.value = botl_score(); /* Track it even when it's not displayed */ -#endif /* SCORE_ON_BOTL */ + get_playerrank(rank); + sprintf(buf, "%s the %s", plname, rank); - /* Hunger */ - if (u.uhs != prevhunger.value) - { - if ((u.uhs > prevhunger.value) || (u.uhs > 3)) - { - prevhunger.highlight_color = STAT_DOWN_COLOR; - } - else - { - prevhunger.highlight_color = STAT_UP_COLOR; - } - prevhunger.value = u.uhs; - for (count = 0; count < strlen(hu_stat[u.uhs]); count++) - { - if ((hu_stat[u.uhs][count]) == ' ') - { - break; - } - buf[count] = hu_stat[u.uhs][count]; - } + /* Use the title as HP bar (similar to hitpointbar) */ + draw_bar(TRUE, hp, hpmax, buf); - buf[count] = '\0'; - free(prevhunger.txt); - prevhunger.txt = curses_copy_of(buf); - prevhunger.highlight_turns = 5; - } + /* Attributes */ + print_statdiff(" St:", &prevstr, ACURR(A_STR), STAT_STR); + print_statdiff(" Dx:", &prevdex, ACURR(A_DEX), STAT_OTHER); + print_statdiff(" Co:", &prevcon, ACURR(A_CON), STAT_OTHER); + print_statdiff(" In:", &prevint, ACURR(A_INT), STAT_OTHER); + print_statdiff(" Wi:", &prevwis, ACURR(A_WIS), STAT_OTHER); + print_statdiff(" Ch:", &prevcha, ACURR(A_CHA), STAT_OTHER); - if (prevhunger.label != NULL) - { - mvwaddstr(win, sy, sx, prevhunger.label); - sx += strlen(prevhunger.label); - } + wprintw(win, (u.ualign.type == A_CHAOTIC ? " Chaotic" : + u.ualign.type == A_NEUTRAL ? " Neutral" : " Lawful")); - color_stat(prevhunger, ON); - mvwaddstr(win, sy, sx, prevhunger.txt); - color_stat(prevhunger, OFF); - - if (strlen(prevhunger.txt) > 0) - { - if (horiz) - { - sx += strlen(prevhunger.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } +#ifdef SCORE_ON_BOTL + if (flags.showscore) + print_statdiff(" S:", &prevscore, botl_score(), STAT_OTHER); +#endif /* SCORE_ON_BOTL */ - /* Confusion */ - if (Confusion != prevconf.value) - { - prevconf.highlight_color = STAT_DOWN_COLOR; - if (prevconf.txt != NULL) - { - free(prevconf.txt); - } - if (Confusion) - { - prevconf.txt = curses_copy_of("Conf"); - } - else - { - prevconf.txt = NULL; - } - if (prevconf.value == 0) - { - prevconf.highlight_turns = 5; - } - prevconf.value = Confusion; - } - - if (prevconf.label != NULL) - { - mvwaddstr(win, sy, sx, prevconf.label); - sx += strlen(prevconf.label); - } - if (prevconf.txt != NULL) - { - color_stat(prevconf, ON); - mvwaddstr(win, sy, sx, prevconf.txt); - color_stat(prevconf, OFF); - } + /* Line 2 */ + y++; + wmove(win, y, x); - if (prevconf.txt != NULL) - { - if (horiz) - { - sx += strlen(prevconf.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } + describe_level(buf); - /* Blindness */ - if (Blind != prevblind.value) - { - prevblind.highlight_color = STAT_DOWN_COLOR; - if (prevblind.txt != NULL) - { - free(prevblind.txt); - } - if (Blind) - { - prevblind.txt = curses_copy_of("Blind"); - } - else - { - prevblind.txt = NULL; - } - if (prevblind.value == 0) - { - prevblind.highlight_turns = 5; - } - prevblind.value = Blind; - } - - if (prevblind.label != NULL) - { - mvwaddstr(win, sy, sx, prevblind.label); - sx += strlen(prevblind.label); - } - - if (prevblind.txt != NULL) - { - color_stat(prevblind, ON); - mvwaddstr(win, sy, sx, prevblind.txt); - color_stat(prevblind, OFF); - } - - if (prevblind.txt != NULL) - { - if (horiz) - { - sx += strlen(prevblind.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } + wprintw(win, "%s", buf); - /* Stun */ - if (Stunned != prevstun.value) - { - prevstun.highlight_color = STAT_DOWN_COLOR; - if (prevstun.txt != NULL) - { - free(prevstun.txt); - } - if (Stunned) - { - prevstun.txt = curses_copy_of("Stun"); - } - else - { - prevstun.txt = NULL; - } - if (prevstun.value == 0) - { - prevstun.highlight_turns = 5; - } - prevstun.value = Stunned; - } - - if (prevstun.label != NULL) - { - mvwaddstr(win, sy, sx, prevstun.label); - sx += strlen(prevstun.label); - } - - if (prevstun.txt != NULL) - { - color_stat(prevstun, ON); - mvwaddstr(win, sy, sx, prevstun.txt); - color_stat(prevstun, OFF); - } - - if (prevstun.txt != NULL) - { - if (horiz) - { - sx += strlen(prevstun.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } - - /* Hallucination */ - if (Hallucination != prevhallu.value) - { - prevhallu.highlight_color = STAT_DOWN_COLOR; - if (prevhallu.txt != NULL) - { - free(prevhallu.txt); - } - if (Hallucination) - { - prevhallu.txt = curses_copy_of("Hallu"); - } - else - { - prevhallu.txt = NULL; - } - if (prevhallu.value == 0) - { - prevhallu.highlight_turns = 5; - } - prevhallu.value = Hallucination; - } - - if (prevhallu.label != NULL) - { - mvwaddstr(win, sy, sx, prevhallu.label); - sx += strlen(prevhallu.label); - } +#ifndef GOLDOBJ + print_statdiff("$", &prevau, u.ugold, STAT_GOLD); +#else + print_statdiff("$", &prevau, money_cnt(invent), STAT_GOLD); +#endif - if (prevhallu.txt != NULL) - { - color_stat(prevhallu, ON); - mvwaddstr(win, sy, sx, prevhallu.txt); - color_stat(prevhallu, OFF); - } + /* HP/Pw use special coloring rules */ + attr_t hpattr, pwattr; +#ifdef STATUS_COLORS + hpattr = hpen_color_attr(TRUE, hp, hpmax); + pwattr = hpen_color_attr(FALSE, u.uen, u.uenmax); +#else + int hpcolor, pwcolor; + hpcolor = hpen_color(TRUE, hp, hpmax); + pwcolor = hpen_color(FALSE, u.uen, u.uenmax); + hpattr = curses_color_attr(hpcolor, 0); + pwattr = curses_color_attr(pwcolor, 0); +#endif + wprintw(win, " HP:"); + wattron(win, hpattr); + wprintw(win, "%d(%d)", (hp < 0) ? 0 : hp, hpmax); + wattroff(win, hpattr); - if (prevhallu.txt != NULL) - { - if (horiz) - { - sx += strlen(prevhallu.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } + wprintw(win, " Pw:"); + wattron(win, pwattr); + wprintw(win, "%d(%d)", u.uen, u.uenmax); + wattroff(win, pwattr); - /* Sick */ - if (Sick != prevsick.value) - { - prevsick.highlight_color = STAT_DOWN_COLOR; - if (prevsick.txt != NULL) - { - free(prevsick.txt); - } - if (Sick) - { - if (u.usick_type & SICK_VOMITABLE) - { - prevsick.txt = curses_copy_of("FoodPois"); - } - else - { - prevsick.txt = curses_copy_of("Ill"); - } - } - else - { - prevsick.txt = NULL; - } - if (prevsick.value == 0) - { - prevsick.highlight_turns = 5; - } - prevsick.value = Sick; - } - - if (prevsick.label != NULL) - { - mvwaddstr(win, sy, sx, prevsick.label); - sx += strlen(prevsick.label); - } + print_statdiff(" AC:", &prevac, u.uac, STAT_AC); - if (prevsick.txt != NULL) - { - color_stat(prevsick, ON); - mvwaddstr(win, sy, sx, prevsick.txt); - color_stat(prevsick, OFF); + if (Upolyd) + print_statdiff(" HD:", &prevlevel, mons[u.umonnum].mlevel, STAT_OTHER); +#ifdef EXP_ON_BOTL + else if (flags.showexp) { + print_statdiff(" Xp:", &prevlevel, u.ulevel, STAT_OTHER); + /* use waddch, we don't want to highlight the '/' */ + waddch(win, '/'); + print_statdiff("", &prevexp, u.uexp, STAT_OTHER); } +#endif + else + print_statdiff(" Exp:", &prevlevel, u.ulevel, STAT_OTHER); - if (prevsick.txt != NULL) - { - if (horiz) - { - sx += strlen(prevsick.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } + if (flags.time) + print_statdiff(" T:", &prevtime, moves, STAT_TIME); - /* Slime */ - if (Slimed != prevslime.value) - { - prevslime.highlight_color = STAT_DOWN_COLOR; - if (prevslime.txt != NULL) - { - free(prevslime.txt); - } - if (Slimed) - { - prevslime.txt = curses_copy_of("Slime"); - } - else - { - prevslime.txt = NULL; - } - if (prevslime.value == 0) - { - prevslime.highlight_turns = 5; - } - prevslime.value = Slimed; - } - - if (prevslime.label != NULL) - { - mvwaddstr(win, sy, sx, prevslime.label); - sx += strlen(prevslime.label); - } + curses_add_statuses(win, FALSE, FALSE, NULL, NULL); +} - if (prevslime.txt != NULL) - { - color_stat(prevslime, ON); - mvwaddstr(win, sy, sx, prevslime.txt); - color_stat(prevslime, OFF); - } +static void +draw_horizontal_new(int x, int y, int hp, int hpmax) +{ + char buf[BUFSZ]; + char rank[BUFSZ]; + WINDOW *win = curses_get_nhwin(STATUS_WIN); - if (prevslime.txt != NULL) - { - if (horiz) - { - sx += strlen(prevslime.txt) + 1; - } - else - { - sx = sx_start; - sy++; - } - } + /* Line 1 */ + wmove(win, y, x); + + get_playerrank(rank); + char race[BUFSZ]; + Strcpy(race, urace.adj); + race[0] = highc(race[0]); + wprintw(win, "%s the %s %s%s%s", plname, + (u.ualign.type == A_CHAOTIC ? "Chaotic" : + u.ualign.type == A_NEUTRAL ? "Neutral" : "Lawful"), + Upolyd ? "" : race, Upolyd ? "" : " ", + rank); - /* Encumberance */ - enc = near_capacity(); - - if (enc != prevencumb.value) - { - if (enc < prevencumb.value) - { - prevencumb.highlight_color = STAT_UP_COLOR; - } - else - { - prevencumb.highlight_color = STAT_DOWN_COLOR; - } - if (prevencumb.txt != NULL) - { - free(prevencumb.txt); - } - if (enc > UNENCUMBERED) - { - sprintf(buf, "%s", enc_stat[enc]); - prevencumb.txt = curses_copy_of(buf); - prevencumb.highlight_turns = 5; - } - else - { - prevencumb.txt = NULL; + /* Line 2 */ + y++; + wmove(win, y, x); + wprintw(win, "HP:"); + draw_bar(TRUE, hp, hpmax, NULL); + print_statdiff(" AC:", &prevac, u.uac, STAT_AC); + if (Upolyd) + print_statdiff(" HD:", &prevlevel, mons[u.umonnum].mlevel, STAT_OTHER); +#ifdef EXP_ON_BOTL + else if (flags.showexp) { + /* Ensure that Xp have proper highlight on level change. */ + int levelchange = 0; + if (prevlevel.value != u.ulevel) { + if (prevlevel.value < u.ulevel) + levelchange = 1; + else + levelchange = 2; } - prevencumb.value = enc; - } - - if (prevencumb.label != NULL) - { - mvwaddstr(win, sy, sx, prevencumb.label); - sx += strlen(prevencumb.label); - } + print_statdiff(" Xp:", &prevlevel, u.ulevel, STAT_OTHER); + /* use waddch, we don't want to highlight the '/' */ + waddch(win, '('); - if (prevencumb.txt != NULL) - { - color_stat(prevencumb, ON); - mvwaddstr(win, sy, sx, prevencumb.txt); - color_stat(prevencumb, OFF); - } + /* Figure out amount of Xp needed to next level */ + int xp_left = 0; + if (u.ulevel < 30) + xp_left = (newuexp(u.ulevel) - u.uexp); - if (prevencumb.txt != NULL) - { - if (horiz) - { - sx += strlen(prevencumb.txt) + 1; - } - else - { - sx = sx_start; - sy++; + if (levelchange) { + prevexp.value = (xp_left + 1); + if (levelchange == 2) + prevexp.value = (xp_left - 1); } + print_statdiff("", &prevexp, xp_left, STAT_AC); + waddch(win, ')'); } +#endif + else + print_statdiff(" Exp:", &prevlevel, u.ulevel, STAT_OTHER); - wrefresh(win); -} + waddch(win, ' '); + describe_level(buf); + wprintw(win, "%s", buf); -/* Decrement the highlight_turns for all stats. Call curses_update_stats -if needed to unhighlight a stat */ + /* Line 3 */ + y++; + wmove(win, y, x); + wprintw(win, "Pw:"); + draw_bar(FALSE, u.uen, u.uenmax, NULL); -void curses_decrement_highlight() -{ - boolean unhighlight = FALSE; - - if (prevname.highlight_turns > 0) - { - prevname.highlight_turns--; - if (prevname.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevdepth.highlight_turns > 0) - { - prevdepth.highlight_turns--; - if (prevdepth.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevstr.highlight_turns > 0) - { - prevstr.highlight_turns--; - if (prevstr.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevint.highlight_turns > 0) - { - prevint.highlight_turns--; - if (prevint.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevwis.highlight_turns > 0) - { - prevwis.highlight_turns--; - if (prevwis.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevdex.highlight_turns > 0) - { - prevdex.highlight_turns--; - if (prevdex.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevcon.highlight_turns > 0) - { - prevcon.highlight_turns--; - if (prevcon.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevcha.highlight_turns > 0) - { - prevcha.highlight_turns--; - if (prevcha.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevalign.highlight_turns > 0) - { - prevalign.highlight_turns--; - if (prevalign.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevau.highlight_turns > 0) - { - prevau.highlight_turns--; - if (prevau.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevhp.highlight_turns > 0) - { - prevhp.highlight_turns--; - if (prevhp.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevmhp.highlight_turns > 0) - { - prevmhp.highlight_turns--; - if (prevmhp.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevlevel.highlight_turns > 0) - { - prevlevel.highlight_turns--; - if (prevlevel.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevpow.highlight_turns > 0) - { - prevpow.highlight_turns--; - if (prevpow.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevmpow.highlight_turns > 0) - { - prevmpow.highlight_turns--; - if (prevmpow.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevac.highlight_turns > 0) - { - prevac.highlight_turns--; - if (prevac.highlight_turns == 0) - { - unhighlight = TRUE; - } - } -#ifdef EXP_ON_BOTL - if (prevexp.highlight_turns > 0) - { - prevexp.highlight_turns--; - if (prevexp.highlight_turns == 0) - { - unhighlight = TRUE; - } - } +#ifndef GOLDOBJ + print_statdiff(" $", &prevau, u.ugold, STAT_GOLD); +#else + print_statdiff(" $", &prevau, money_cnt(invent), STAT_GOLD); #endif - if (prevtime.highlight_turns > 0) - { - prevtime.highlight_turns--; - if (prevtime.highlight_turns == 0) - { - unhighlight = TRUE; - } - } + #ifdef SCORE_ON_BOTL - if (prevscore.highlight_turns > 0) - { - prevscore.highlight_turns--; - if (prevscore.highlight_turns == 0) - { - unhighlight = TRUE; - } - } -#endif - if (prevhunger.highlight_turns > 0) - { - prevhunger.highlight_turns--; - if (prevhunger.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevconf.highlight_turns > 0) - { - prevconf.highlight_turns--; - if (prevconf.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevblind.highlight_turns > 0) - { - prevblind.highlight_turns--; - if (prevblind.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevstun.highlight_turns > 0) - { - prevstun.highlight_turns--; - if (prevstun.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevhallu.highlight_turns > 0) - { - prevhallu.highlight_turns--; - if (prevhallu.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevsick.highlight_turns > 0) - { - prevsick.highlight_turns--; - if (prevsick.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevslime.highlight_turns > 0) - { - prevslime.highlight_turns--; - if (prevslime.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - if (prevencumb.highlight_turns > 0) - { - prevencumb.highlight_turns--; - if (prevencumb.highlight_turns == 0) - { - unhighlight = TRUE; - } - } - - if (unhighlight) - { - curses_update_stats(FALSE); - } + if (flags.showscore) + print_statdiff(" S:", &prevscore, botl_score(), STAT_OTHER); +#endif /* SCORE_ON_BOTL */ + + if (flags.time) + print_statdiff(" T:", &prevtime, moves, STAT_TIME); + + curses_add_statuses(win, TRUE, FALSE, &x, &y); + + /* Right-aligned attributes */ + int stat_length = 6; /* " Dx:xx" */ + int str_length = 6; + if (ACURR(A_STR) > 18 && ACURR(A_STR) < 119) + str_length = 9; + + getmaxyx(win, y, x); + + /* We want to deal with top line of y. getmaxx would do what we want, but it only + exist for compatibility reasons and might not exist at all in some versions. */ + y = 0; + if (curses_window_has_border(STATUS_WIN)) { + x--; + y++; + } + + x -= stat_length; + int orig_x = x; + wmove(win, y, x); + print_statdiff(" Co:", &prevcon, ACURR(A_CON), STAT_OTHER); + x -= stat_length; + wmove(win, y, x); + print_statdiff(" Dx:", &prevdex, ACURR(A_DEX), STAT_OTHER); + x -= str_length; + wmove(win, y, x); + print_statdiff(" St:", &prevstr, ACURR(A_STR), STAT_STR); + + x = orig_x; + y++; + wmove(win, y, x); + print_statdiff(" Ch:", &prevcha, ACURR(A_CHA), STAT_OTHER); + x -= stat_length; + wmove(win, y, x); + print_statdiff(" Wi:", &prevwis, ACURR(A_WIS), STAT_OTHER); + x -= str_length; + wmove(win, y, x); + print_statdiff(" In:", &prevint, ACURR(A_INT), STAT_OTHER); } - -/* Initialize the stats with beginning values. */ - -static void init_stats() +/* Personally I never understood the point of a vertical status bar. But removing the + option would be silly, so keep the functionality. */ +static void +draw_vertical(int x, int y, int hp, int hpmax) { char buf[BUFSZ]; - int count; - - /* Player name and title */ - strcpy(buf, plname); - if ('a' <= buf[0] && buf[0] <= 'z') buf[0] += 'A'-'a'; - strcat(buf, " the "); - if (u.mtimedone) { - char mname[BUFSZ]; - int k = 0; + char rank[BUFSZ]; + WINDOW *win = curses_get_nhwin(STATUS_WIN); - strcpy(mname, mons[u.umonnum].mname); - while(mname[k] != 0) { - if ((k == 0 || (k > 0 && mname[k-1] == ' ')) - && 'a' <= mname[k] && mname[k] <= 'z') - { - mname[k] += 'A' - 'a'; - } - k++; - } - strcat(buf, mname); - } else { - strcat(buf, rank_of(u.ulevel, pl_character[0], flags.female)); - } + /* Print title and dungeon branch */ + wmove(win, y++, x); - prevname.txt = curses_copy_of(buf); - prevname.display = TRUE; - prevname.highlight_turns = 0; - prevname.label = NULL; - prevname.id = "name"; - set_stat_color(&prevname); - - /* Strength */ - if (ACURR(A_STR) > 118) - { - sprintf(buf, "%d", ACURR(A_STR) - 100); - } - else if (ACURR(A_STR)==118) - { - sprintf(buf, "18/**"); - } - else if(ACURR(A_STR) > 18) - { - sprintf(buf, "18/%02d", ACURR(A_STR) - 18); - } - else - { - sprintf(buf, "%d", ACURR(A_STR)); - } + get_playerrank(rank); + int ranklen = strlen(rank); + int namelen = strlen(plname); + int maxlen = 19; +#ifdef STATUS_COLORS + if (!iflags.hitpointbar) + maxlen += 2; /* With no hitpointbar, we can fit more since there's no "[]" */ +#endif - prevstr.value = ACURR(A_STR); - prevstr.txt = curses_copy_of(buf); - prevstr.display = TRUE; - prevstr.highlight_turns = 0; - prevstr.label = NULL; - prevstr.id = "str"; - set_stat_color(&prevstr); - - /* Intelligence */ - sprintf(buf, "%d", ACURR(A_INT)); - prevint.value = ACURR(A_INT); - prevint.txt = curses_copy_of(buf); - prevint.display = TRUE; - prevint.highlight_turns = 0; - prevint.label = NULL; - prevint.id = "int"; - set_stat_color(&prevint); - - /* Wisdom */ - sprintf(buf, "%d", ACURR(A_WIS)); - prevwis.value = ACURR(A_WIS); - prevwis.txt = curses_copy_of(buf); - prevwis.display = TRUE; - prevwis.highlight_turns = 0; - prevwis.label = NULL; - prevwis.id = "wis"; - set_stat_color(&prevwis); - - /* Dexterity */ - sprintf(buf, "%d", ACURR(A_DEX)); - prevdex.value = ACURR(A_DEX); - prevdex.txt = curses_copy_of(buf); - prevdex.display = TRUE; - prevdex.highlight_turns = 0; - prevdex.label = NULL; - prevdex.id = "dex"; - set_stat_color(&prevdex); - - /* Constitution */ - sprintf(buf, "%d", ACURR(A_CON)); - prevcon.value = ACURR(A_CON); - prevcon.txt = curses_copy_of(buf); - prevcon.display = TRUE; - prevcon.highlight_turns = 0; - prevcon.label = NULL; - prevcon.id = "con"; - set_stat_color(&prevcon); - - /* Charisma */ - sprintf(buf, "%d", ACURR(A_CHA)); - prevcha.value = ACURR(A_CHA); - prevcha.txt = curses_copy_of(buf); - prevcha.display = TRUE; - prevcha.highlight_turns = 0; - prevcha.label = NULL; - prevcha.id = "cha"; - set_stat_color(&prevcha); - - /* Alignment */ - switch (u.ualign.type) - { - case A_LAWFUL: - { - prevalign.txt = curses_copy_of("Lawful"); - break; - } - case A_NEUTRAL: - { - prevalign.txt = curses_copy_of("Neutral"); - break; - } - case A_CHAOTIC: - { - prevalign.txt = curses_copy_of("Chaotic"); - break; - } - } - - prevalign.alignment = u.ualign.type; - prevalign.display = TRUE; - prevalign.highlight_turns = 0; - prevalign.label = NULL; - prevalign.id = "align"; - set_stat_color(&prevalign); - - /* Dungeon level */ + if ((ranklen + namelen) > maxlen) { + /* The result doesn't fit. Strip name if >10 characters, then strip title */ + if (namelen > 10) { + while (namelen > 10 && (ranklen + namelen) > maxlen) + namelen--; + } + + while ((ranklen + namelen) > maxlen) + ranklen--; /* Still doesn't fit, strip rank */ + } + sprintf(buf, "%-*s the %-*s", namelen, plname, ranklen, rank); + draw_bar(TRUE, hp, hpmax, buf); + wmove(win, y++, x); + wprintw(win, "%s", dungeons[u.uz.dnum].dname); + + y++; /* Blank line inbetween */ + wmove(win, y++, x); + + /* Attributes. Old vertical order is preserved */ + print_statdiff("Strength: ", &prevstr, ACURR(A_STR), STAT_STR); + wmove(win, y++, x); + print_statdiff("Intelligence: ", &prevint, ACURR(A_INT), STAT_OTHER); + wmove(win, y++, x); + print_statdiff("Wisdom: ", &prevwis, ACURR(A_WIS), STAT_OTHER); + wmove(win, y++, x); + print_statdiff("Dexterity: ", &prevdex, ACURR(A_DEX), STAT_OTHER); + wmove(win, y++, x); + print_statdiff("Constitution: ", &prevcon, ACURR(A_CON), STAT_OTHER); + wmove(win, y++, x); + print_statdiff("Charisma: ", &prevcha, ACURR(A_CHA), STAT_OTHER); + wmove(win, y++, x); + wprintw(win, "Alignment: "); + wprintw(win, (u.ualign.type == A_CHAOTIC ? "Chaotic" : + u.ualign.type == A_NEUTRAL ? "Neutral" : "Lawful")); + wmove(win, y++, x); + wprintw(win, "Dungeon Level: "); + + /* Astral Plane doesn't fit */ if (In_endgame(&u.uz)) - { - strcpy(buf, (Is_astralevel(&u.uz) ? "Astral Plane":"End Game")); - } + wprintw(win, "%s", Is_astralevel(&u.uz) ? "Astral" : "End Game"); else - { - sprintf(buf, "%d", depth(&u.uz)); - } + wprintw(win, "%d", depth(&u.uz)); + wmove(win, y++, x); - prevdepth.value = depth(&u.uz); - prevdepth.txt = curses_copy_of(buf); - prevdepth.display = TRUE; - prevdepth.highlight_turns = 0; - prevdepth.label = NULL; - prevdepth.id = "dlvl"; - set_stat_color(&prevdepth); - - /* Gold */ #ifndef GOLDOBJ - sprintf(buf,"%ld", u.ugold); - prevau.value = u.ugold; + print_statdiff("Gold: ", &prevau, u.ugold, STAT_GOLD); #else - sprintf(buf,"%ld", money_cnt(invent)); - prevau.value = money_cnt(invent); -#endif - prevau.txt = curses_copy_of(buf); - prevau.display = TRUE; - prevau.highlight_turns = 0; - prevau.label = NULL; - prevau.id = "gold"; - set_stat_color(&prevau); - - /* Hit Points */ - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevhp.value = u.mh; - sprintf(buf, "%d", u.mh); - prevhp.txt = curses_copy_of(buf); - } - else if (u.uhp != prevhp.value) /* Not polymorphed */ - { - prevhp.value = u.uhp; - sprintf(buf, "%d", u.uhp); - prevhp.txt = curses_copy_of(buf); - } - prevhp.display = TRUE; - prevhp.highlight_turns = 0; - prevhp.label = NULL; - prevhp.id = "hp"; - set_stat_color(&prevhp); - - /* Max Hit Points */ - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevmhp.value = u.mhmax; - sprintf(buf, "%d", u.mhmax); - prevmhp.txt = curses_copy_of(buf); - } - else /* Not polymorphed */ - { - prevmhp.value = u.uhpmax; - sprintf(buf, "%d", u.uhpmax); - prevmhp.txt = curses_copy_of(buf); - } - prevmhp.display = TRUE; - prevmhp.highlight_turns = 0; - prevmhp.label = curses_copy_of("/"); - prevmhp.id = "mhp"; - set_stat_color(&prevmhp); - - /* Power */ - prevpow.value = u.uen; - sprintf(buf, "%d", u.uen); - prevpow.txt = curses_copy_of(buf); - prevpow.display = TRUE; - prevpow.highlight_turns = 0; - prevpow.label = NULL; - prevpow.id = "pw"; - set_stat_color(&prevpow); - - /* Max Power */ - prevmpow.value = u.uenmax; - sprintf(buf, "%d", u.uenmax); - prevmpow.txt = curses_copy_of(buf); - prevmpow.display = TRUE; - prevmpow.highlight_turns = 0; - prevmpow.label = curses_copy_of("/"); - prevmpow.id = "mpw"; - set_stat_color(&prevmpow); - - /* Armor Class */ - prevac.value = u.uac; - sprintf(buf, "%d", u.uac); - prevac.txt = curses_copy_of(buf); - prevac.display = TRUE; - prevac.highlight_turns = 0; - prevac.label = NULL; - prevac.id = "ac"; - set_stat_color(&prevac); - - /* Experience */ -#ifdef EXP_ON_BOTL - prevexp.value = u.uexp; - sprintf(buf, "%ld", u.uexp); - prevexp.txt = curses_copy_of(buf); - prevexp.display = flags.showexp; - prevexp.highlight_turns = 0; - prevexp.label = NULL; - prevexp.id = "xp"; - set_stat_color(&prevexp); + print_statdiff("Gold: ", &prevau, money_cnt(invent), STAT_GOLD); #endif + wmove(win, y++, x); - /* Level */ - prevlevel.label = NULL; - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevlevel.value = mons[u.umonnum].mlevel; - sprintf(buf, "%d", mons[u.umonnum].mlevel); - prevlevel.txt = curses_copy_of(buf); - } - else if (u.ulevel != prevlevel.value) /* Not polymorphed */ - { - prevlevel.value = u.ulevel; - sprintf(buf, "%d", u.ulevel); - prevlevel.txt = curses_copy_of(buf); - } - prevlevel.display = TRUE; - prevlevel.highlight_turns = 0; - prevlevel.id = "lvl"; - set_stat_color(&prevlevel); - - /* Time */ - prevtime.value = moves; - sprintf(buf, "%ld", moves); - prevtime.txt = curses_copy_of(buf); - prevtime.display = flags.time; - prevtime.highlight_turns = 0; - prevtime.label = NULL; - prevtime.id = "time"; - set_stat_color(&prevtime); - - /* Score */ -#ifdef SCORE_ON_BOTL - prevscore.value = botl_score(); - sprintf(buf, "%ld", botl_score()); - prevscore.txt = curses_copy_of(buf); - prevscore.display = flags.showscore; - prevscore.highlight_turns = 0; - prevscore.label = NULL; - prevscore.id = "score"; - set_stat_color(&prevscore); + /* HP/Pw use special coloring rules */ + attr_t hpattr, pwattr; +#ifdef STATUS_COLORS + hpattr = hpen_color_attr(TRUE, hp, hpmax); + pwattr = hpen_color_attr(FALSE, u.uen, u.uenmax); +#else + int hpcolor, pwcolor; + hpcolor = hpen_color(TRUE, hp, hpmax); + pwcolor = hpen_color(FALSE, u.uen, u.uenmax); + hpattr = curses_color_attr(hpcolor, 0); + pwattr = curses_color_attr(pwcolor, 0); #endif - /* Hunger */ - prevhunger.value = u.uhs; - for (count = 0; count < strlen(hu_stat[u.uhs]); count++) - { - if ((hu_stat[u.uhs][count]) == ' ') - { - break; - } - buf[count] = hu_stat[u.uhs][count]; - } + wprintw(win, "Hit Points: "); + wattron(win, hpattr); + wprintw(win, "%d/%d", (hp < 0) ? 0 : hp, hpmax); + wattroff(win, hpattr); + wmove(win, y++, x); - buf[count] = '\0'; - prevhunger.txt = curses_copy_of(buf); - prevhunger.display = TRUE; - prevhunger.highlight_turns = 0; - prevhunger.label = NULL; - prevhunger.id = "hunger"; - set_stat_color(&prevhunger); - - /* Confusion */ - prevconf.value = Confusion; - if (Confusion) - { - prevconf.txt = curses_copy_of("Conf"); - } - else - { - prevconf.txt = NULL; - } - prevconf.display = TRUE; - prevconf.highlight_turns = 0; - prevconf.label = NULL; - prevconf.id = "conf"; - set_stat_color(&prevconf); - - /* Blindness */ - prevblind.value = Blind; - if (Blind) - { - prevblind.txt = curses_copy_of("Blind"); - } - else - { - prevblind.txt = NULL; - } - prevblind.display = TRUE; - prevblind.highlight_turns = 0; - prevblind.label = NULL; - prevblind.id = "blind"; - set_stat_color(&prevblind); - - /* Stun */ - prevstun.value = Stunned; - if (Stunned) - { - prevstun.txt = curses_copy_of("Stun"); - } - else - { - prevstun.txt = NULL; - } - prevstun.display = TRUE; - prevstun.highlight_turns = 0; - prevstun.label = NULL; - prevstun.id = "stun"; - set_stat_color(&prevstun); - - /* Hallucination */ - prevhallu.value = Hallucination; - if (Hallucination) - { - prevhallu.txt = curses_copy_of("Hallu"); - } - else - { - prevhallu.txt = NULL; - } - prevhallu.display = TRUE; - prevhallu.highlight_turns = 0; - prevhallu.label = NULL; - prevhallu.id = "hallu"; - set_stat_color(&prevhallu); - - /* Sick */ - prevsick.value = Sick; - if (Sick) - { - if (u.usick_type & SICK_VOMITABLE) - { - prevsick.txt = curses_copy_of("FoodPois"); - } - else - { - prevsick.txt = curses_copy_of("Ill"); - } - } - else - { - prevsick.txt = NULL; - } - prevsick.display = TRUE; - prevsick.highlight_turns = 0; - prevsick.label = NULL; - prevsick.id = "sick"; - set_stat_color(&prevsick); - - /* Slimed */ - prevslime.value = Slimed; - if (Slimed) - { - prevslime.txt = curses_copy_of("Slime"); - } - else - { - prevslime.txt = NULL; - } - prevslime.display = TRUE; - prevslime.highlight_turns = 0; - prevslime.label = NULL; - prevslime.id = "slime"; - set_stat_color(&prevslime); - - /* Encumberance */ - prevencumb.value = near_capacity(); - if (prevencumb.value > UNENCUMBERED) - { - sprintf(buf, "%s", enc_stat[prevencumb.value]); - prevencumb.txt = curses_copy_of(buf); - } - else - { - prevencumb.txt = NULL; - } - prevencumb.display = TRUE; - prevencumb.highlight_turns = 0; - prevencumb.label = NULL; - prevencumb.id = "encumberance"; - set_stat_color(&prevencumb); -} + wprintw(win, "Magic Power: "); + wattron(win, pwattr); + wprintw(win, "%d/%d", u.uen, u.uenmax); + wattroff(win, pwattr); + wmove(win, y++, x); -/* Set labels based on orientation of status window. If horizontal, -we want to compress this info; otherwise we know we have a width of at -least 26 characters. */ + print_statdiff("Armor Class: ", &prevac, u.uac, STAT_AC); + wmove(win, y++, x); -static void set_labels(int label_width) -{ - char buf[BUFSZ]; - - switch (label_width) - { - case COMPACT_LABELS: - { - /* Strength */ - if (prevstr.label) - { - free (prevstr.label); - } - prevstr.label = curses_copy_of("S:"); - /* Intelligence */ - if (prevint.label) - { - free (prevint.label); - } - prevint.label = curses_copy_of("I:"); - - /* Wisdom */ - if (prevwis.label) - { - free (prevwis.label); - } - prevwis.label = curses_copy_of("W:"); - - /* Dexterity */ - if (prevdex.label) - { - free (prevdex.label); - } - prevdex.label = curses_copy_of("D:"); - - /* Constitution */ - if (prevcon.label) - { - free (prevcon.label); - } - prevcon.label = curses_copy_of("C:"); - - /* Charisma */ - if (prevcha.label) - { - free (prevcha.label); - } - prevcha.label = curses_copy_of("Ch:"); - - /* Alignment */ - if (prevalign.label) - { - free (prevalign.label); - } - prevalign.label = NULL; - - /* Dungeon level */ - if (prevdepth.label) - { - free (prevdepth.label); - } - prevdepth.label = curses_copy_of("Dl:"); - - /* Gold */ - if (prevau.label) - { - free (prevau.label); - } - sprintf(buf, "%c:", GOLD_SYM); - prevau.label = curses_copy_of(buf); - - /* Hit points */ - if (prevhp.label) - { - free (prevhp.label); - } - prevhp.label = curses_copy_of("HP:"); - - /* Power */ - if (prevpow.label) - { - free (prevpow.label); - } - prevpow.label = curses_copy_of("Pw:"); - - /* Armor Class */ - if (prevac.label) - { - free (prevac.label); - } - prevac.label = curses_copy_of("AC:"); - -#ifdef EXP_ON_BOTL - /* Experience */ - if (prevexp.label) - { - free (prevexp.label); - } - prevexp.label = curses_copy_of("XP:"); -#endif - - /* Level */ - if (prevlevel.label) - { - free (prevlevel.label); - prevlevel.label = NULL; - } - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevlevel.label = curses_copy_of("HD:"); - } - else /* Not polymorphed */ - { - if (prevexp.display) - { - prevlevel.label = curses_copy_of("/"); - } - else - { - prevlevel.label = curses_copy_of("Lv:"); - } - } - - /* Time */ - if (prevtime.label) - { - free (prevtime.label); - } - prevtime.label = curses_copy_of("T:"); - -#ifdef SCORE_ON_BOTL - /* Score */ - if (prevscore.label) - { - free (prevscore.label); - } - prevscore.label = curses_copy_of("S:"); + if (Upolyd) + print_statdiff("Hit Dice: ", &prevlevel, mons[u.umonnum].mlevel, STAT_OTHER); +#ifdef EXP_ON_BOTL + else if (flags.showexp) { + print_statdiff("Experience: ", &prevlevel, u.ulevel, STAT_OTHER); + /* use waddch, we don't want to highlight the '/' */ + waddch(win, '/'); + print_statdiff("", &prevexp, u.uexp, STAT_OTHER); + } #endif - break; - } - case NORMAL_LABELS: - { - /* Strength */ - if (prevstr.label) - { - free (prevstr.label); - } - prevstr.label = curses_copy_of("Str:"); - /* Intelligence */ - if (prevint.label) - { - free (prevint.label); - } - prevint.label = curses_copy_of("Int:"); + else + print_statdiff("Level: ", &prevlevel, u.ulevel, STAT_OTHER); + wmove(win, y++, x); - /* Wisdom */ - if (prevwis.label) - { - free (prevwis.label); - } - prevwis.label = curses_copy_of("Wis:"); - - /* Dexterity */ - if (prevdex.label) - { - free (prevdex.label); - } - prevdex.label = curses_copy_of("Dex:"); - - /* Constitution */ - if (prevcon.label) - { - free (prevcon.label); - } - prevcon.label = curses_copy_of("Con:"); - - /* Charisma */ - if (prevcha.label) - { - free (prevcha.label); - } - prevcha.label = curses_copy_of("Cha:"); - - /* Alignment */ - if (prevalign.label) - { - free (prevalign.label); - } - prevalign.label = NULL; - - /* Dungeon level */ - if (prevdepth.label) - { - free (prevdepth.label); - } - prevdepth.label = curses_copy_of("Dlvl:"); - - /* Gold */ - if (prevau.label) - { - free (prevau.label); - } - sprintf(buf, "%c:", GOLD_SYM); - prevau.label = curses_copy_of(buf); - - /* Hit points */ - if (prevhp.label) - { - free (prevhp.label); - } - prevhp.label = curses_copy_of("HP:"); - - /* Power */ - if (prevpow.label) - { - free (prevpow.label); - } - prevpow.label = curses_copy_of("Pw:"); - - /* Armor Class */ - if (prevac.label) - { - free (prevac.label); - } - prevac.label = curses_copy_of("AC:"); - -#ifdef EXP_ON_BOTL - /* Experience */ - if (prevexp.label) - { - free (prevexp.label); - } - prevexp.label = curses_copy_of("XP:"); -#endif - - /* Level */ - if (prevlevel.label) - { - free (prevlevel.label); - prevlevel.label = NULL; - } - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevlevel.label = curses_copy_of("HD:"); - } - else /* Not polymorphed */ - { - if (prevexp.display) - { - prevlevel.label = curses_copy_of("/"); - } - else - { - prevlevel.label = curses_copy_of("Lvl:"); - } - } - - /* Time */ - if (prevtime.label) - { - free (prevtime.label); - } - prevtime.label = curses_copy_of("T:"); - -#ifdef SCORE_ON_BOTL - /* Score */ - if (prevscore.label) - { - free (prevscore.label); - } - prevscore.label = curses_copy_of("S:"); -#endif - break; - } - case WIDE_LABELS: - { - /* Strength */ - if (prevstr.label) - { - free (prevstr.label); - } - prevstr.label = curses_copy_of("Strength: "); - - /* Intelligence */ - if (prevint.label) - { - free (prevint.label); - } - prevint.label = curses_copy_of("Intelligence: "); - - /* Wisdom */ - if (prevwis.label) - { - free (prevwis.label); - } - prevwis.label = curses_copy_of("Wisdom: "); - - /* Dexterity */ - if (prevdex.label) - { - free (prevdex.label); - } - prevdex.label = curses_copy_of("Dexterity: "); - - /* Constitution */ - if (prevcon.label) - { - free (prevcon.label); - } - prevcon.label = curses_copy_of("Constitution: "); - - /* Charisma */ - if (prevcha.label) - { - free (prevcha.label); - } - prevcha.label = curses_copy_of("Charisma: "); - - /* Alignment */ - if (prevalign.label) - { - free (prevalign.label); - } - prevalign.label = curses_copy_of("Alignment: "); - - /* Dungeon level */ - if (prevdepth.label) - { - free (prevdepth.label); - } - prevdepth.label = curses_copy_of("Dungeon Level: "); - - /* Gold */ - if (prevau.label) - { - free (prevau.label); - } - prevau.label = curses_copy_of("Gold: "); - - /* Hit points */ - if (prevhp.label) - { - free (prevhp.label); - } - prevhp.label = curses_copy_of("Hit Points: "); - - /* Power */ - if (prevpow.label) - { - free (prevpow.label); - } - prevpow.label = curses_copy_of("Magic Power: "); - - /* Armor Class */ - if (prevac.label) - { - free (prevac.label); - } - prevac.label = curses_copy_of("Armor Class: "); - -#ifdef EXP_ON_BOTL - /* Experience */ - if (prevexp.label) - { - free (prevexp.label); - } - prevexp.label = curses_copy_of("Experience: "); -#endif + if (flags.time) { + print_statdiff("Time: ", &prevtime, moves, STAT_TIME); + wmove(win, y++, x); + } - /* Level */ - if (prevlevel.label) - { - free (prevlevel.label); - } - if (u.mtimedone) /* Currently polymorphed - show monster HP */ - { - prevlevel.label = curses_copy_of("Hit Dice: "); - } - else /* Not polymorphed */ - { - if (prevexp.display) - { - prevlevel.label = curses_copy_of(" / "); - } - else - { - prevlevel.label = curses_copy_of("Level: "); - } - } - - /* Time */ - if (prevtime.label) - { - free (prevtime.label); - } - prevtime.label = curses_copy_of("Time: "); - #ifdef SCORE_ON_BOTL - /* Score */ - if (prevscore.label) - { - free (prevscore.label); - } - prevscore.label = curses_copy_of("Score: "); -#endif - break; - } - default: - { - panic( "set_labels(): Invalid label_width %d\n", - label_width ); - break; - } + if (flags.showscore) { + print_statdiff("Score: ", &prevscore, botl_score(), STAT_OTHER); + wmove(win, y++, x); } -} +#endif /* SCORE_ON_BOTL */ + curses_add_statuses(win, FALSE, TRUE, &x, &y); +} -/* Get the default (non-highlighted) color for a stat. For now, this -is NO_COLOR unless the statuscolors patch is in use. */ - -static void set_stat_color(nhstat *stat) +static void +curses_add_statuses(WINDOW *win, boolean align_right, + boolean vertical, int *x, int *y) { -#ifdef STATUS_COLORS - struct color_option stat_color; - int count; - int attr = A_NORMAL; - - if (iflags.use_status_colors && stat_colored(stat->id)) - { - stat_color = text_color_of(stat->id, text_colors); - - for (count = 0; (1 << count) <= stat_color.attr_bits; ++count) - { - if (count != ATR_NONE && stat_color.attr_bits & (1 << count)) - { - attr += curses_convert_attr(count); - } - } + if (align_right) { + /* Right-aligned statuses. Since add_status decrease one x more + (to separate them with spaces), add 1 to x unless we have borders + (which would offset what add_status does) */ + int mx = *x; + int my = *y; + getmaxyx(win, my, mx); + if (!curses_window_has_border(STATUS_WIN)) + mx++; - stat->stat_color = stat_color.color; - stat->stat_attr = attr; - } - else - { - stat->stat_color = NO_COLOR; - stat->stat_attr = A_NORMAL; + *x = mx; } -#else - stat->stat_color = NO_COLOR; - stat->stat_attr = A_NORMAL; -#endif /* STATUS_COLORS */ -} +#define statprob(str, trouble) \ + curses_add_status(win, align_right, vertical, x, y, str, trouble) -/* Set the color to the base color for the given stat, or highlight a - changed stat. */ + /* Hunger */ + statprob(hu_stat[u.uhs], u.uhs != 1); /* 1 is NOT_HUNGRY (not defined here) */ + + /* General troubles */ + statprob("Conf", Confusion); + statprob("Blind", Blind); + statprob("Stun", Stunned); + statprob("Hallu", Hallucination); + statprob("Ill", (u.usick_type & SICK_NONVOMITABLE)); + statprob("FoodPois", (u.usick_type & SICK_VOMITABLE)); + statprob("Slime", Slimed); + + /* Encumbrance */ + int enc = near_capacity(); + statprob(enc_stat[enc], enc > UNENCUMBERED); +#undef statprob +} -static void color_stat(nhstat stat, int onoff) +static void +curses_add_status(WINDOW *win, boolean align_right, boolean vertical, + int *x, int *y, const char *str, int trouble) { - WINDOW *win = curses_get_nhwin(STATUS_WIN); -#ifdef STATUS_COLORS - struct color_option stat_color; - int color, attr, hp, hpmax, count; - char buf[BUFSIZ]; - - stat_color.color = NO_COLOR; - stat_color.attr_bits = ATR_NONE; - - if (strcmp(stat.id, "hp") == 0) - { - hp = Upolyd ? u.mh : u.uhp; - hpmax = Upolyd ? u.mhmax : u.uhpmax; - stat_color = percentage_color_of(hp, hpmax, hp_colors); - } - - if (strcmp(stat.id, "pw") == 0) - { - stat_color = percentage_color_of(u.uen, u.uenmax, pw_colors); - } - - if (strcmp(stat.id, "hunger") == 0) - { - for (count = 0; count < strlen(hu_stat[u.uhs]); count++) - { - if ((hu_stat[u.uhs][count]) == ' ') - { - break; - } - buf[count] = hu_stat[u.uhs][count]; - } + /* If vertical is TRUE here with no x/y, that's an error. But handle + it gracefully since NH3 doesn't recover well in crashes. */ + if (!x || !y) + vertical = FALSE; - buf[count] = '\0'; - stat_color = text_color_of(buf, text_colors); - } - - if (strcmp(stat.id, "encumberance") == 0) - { - stat_color = text_color_of(enc_stat[prevencumb.value], - text_colors); - } - - if (strcmp(stat.id, "sick") == 0) - { - if (u.usick_type & SICK_VOMITABLE) - { - stat_color = text_color_of("foodpois", text_colors); - } - else - { - stat_color = text_color_of("ill", text_colors); - } - } + if (!trouble) + return; - if (strcmp(stat.id, "align") == 0) - { - switch (u.ualign.type) - { - case A_LAWFUL: - { - stat_color = text_color_of("lawful", text_colors); - break; - } - case A_NEUTRAL: - { - stat_color = text_color_of("neutral", text_colors); - break; - } - case A_CHAOTIC: - { - stat_color = text_color_of("chaotic", text_colors); - break; - } - } - } + if (!vertical && !align_right) + waddch(win, ' '); - color = stat_color.color; - attr = A_NORMAL; + /* For whatever reason, hunger states have trailing spaces. Get rid of them. */ + char buf[BUFSZ]; + Strcpy(buf, str); + int i; + for (i = 0; (buf[i] != ' ' && buf[i] != '\0'); i++) ; - for (count = 0; (1 << count) <= stat_color.attr_bits; ++count) - { - if (count != ATR_NONE && stat_color.attr_bits & (1 << count)) - { - attr += curses_convert_attr(count); - } + buf[i] = '\0'; + if (align_right) { + *x -= (strlen(buf) + 1); /* add spacing */ + wmove(win, *y, *x); } - stat.stat_color = color; - stat.stat_attr = attr; -#endif /* STATUS_COLORS */ - - if ((stat.stat_color == NO_COLOR) && (stat.stat_attr == A_NORMAL)) - { - if (stat.highlight_turns > 0) - { -#ifdef STATUS_COLORS - if (iflags.use_status_colors) -#endif - curses_toggle_color_attr(win, stat.highlight_color, - A_NORMAL, onoff); - } + draw_trouble_str(buf); - return; + if (vertical) { + wmove(win, *y, *x); + *y += 1; /* ++ advances the pointer addr */ } - -#ifdef STATUS_COLORS - if (iflags.use_status_colors) -#endif - curses_toggle_color_attr(win, stat.stat_color, stat.stat_attr, - onoff); } - -/* Determine if a stat is configured via statuscolors. */ - -#ifdef STATUS_COLORS -static boolean stat_colored(const char *id) +/* Decrement a single highlight, return 1 if decremented to zero. zero is TRUE if we're + zeroing the highlight. */ +static int +decrement_highlight(nhstat *stat, boolean zero) { - struct text_color_option *cur_option = - (struct text_color_option *)text_colors; - - while(cur_option != NULL) - { - if (strcmpi(cur_option->text, id) == 0) - { - return TRUE; + if (stat->highlight_turns > 0) { + if (zero) { + stat->highlight_turns = 0; + return 1; } - - cur_option = (struct text_color_option *)cur_option->next; + + stat->highlight_turns--; + if (stat->highlight_turns == 0) + return 1; } - - return FALSE; + return 0; } -#endif /* STATUS_COLORS */ +/* Decrement the highlight_turns for all stats. Call curses_update_stats + if needed to unhighlight a stat */ +void +curses_decrement_highlights(boolean zero) +{ + int unhighlight = 0; + + unhighlight |= decrement_highlight(&prevdepth, zero); + unhighlight |= decrement_highlight(&prevstr, zero); + unhighlight |= decrement_highlight(&prevdex, zero); + unhighlight |= decrement_highlight(&prevcon, zero); + unhighlight |= decrement_highlight(&prevint, zero); + unhighlight |= decrement_highlight(&prevwis, zero); + unhighlight |= decrement_highlight(&prevcha, zero); + unhighlight |= decrement_highlight(&prevau, zero); + unhighlight |= decrement_highlight(&prevlevel, zero); + unhighlight |= decrement_highlight(&prevac, zero); +#ifdef EXP_ON_BOTL + unhighlight |= decrement_highlight(&prevexp, zero); +#endif + unhighlight |= decrement_highlight(&prevtime, zero); +#ifdef SCORE_ON_BOTL + unhighlight |= decrement_highlight(&prevscore, zero); +#endif + + if (unhighlight) + curses_update_stats(); +} diff --git a/win/curses/cursstat.h b/win/curses/cursstat.h index cde3624e..7773d422 100644 --- a/win/curses/cursstat.h +++ b/win/curses/cursstat.h @@ -1,12 +1,21 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSSTAT_H -#define CURSSTAT_H +# define CURSSTAT_H +/* Used by handle_stat_change to handle some stats differently. Not an enum + because this is how NetHack code generally handles them. */ +# define STAT_OTHER 0 +# define STAT_STR 1 +# define STAT_GOLD 2 +# define STAT_AC 4 +# define STAT_TIME 5 +# define STAT_TROUBLE 6 /* Global declarations */ -void curses_update_stats(boolean redraw); - -void curses_decrement_highlight(void); - +void curses_update_stats(); +void curses_decrement_highlights(boolean); +attr_t curses_color_attr(int nh_color, int bg_color); -#endif /* CURSSTAT_H */ +#endif /* CURSSTAT_H */ diff --git a/win/curses/curswins.c b/win/curses/curswins.c index a4029dc8..961a99cd 100644 --- a/win/curses/curswins.c +++ b/win/curses/curswins.c @@ -1,3 +1,5 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #include "curses.h" #include "hack.h" #include "wincurs.h" @@ -7,49 +9,42 @@ /* Private declarations */ -typedef struct nhw -{ - winid nhwin; /* NetHack window id */ - WINDOW *curwin; /* Curses window pointer */ - int width; /* Usable width not counting border */ - int height; /* Usable height not counting border */ - int x; /* start of window on terminal (left) */ - int y; /* start of window on termial (top) */ - int orientation; /* Placement of window relative to map */ - boolean border; /* Whether window has a visible border */ +typedef struct nhw { + winid nhwin; /* NetHack window id */ + WINDOW *curwin; /* Curses window pointer */ + int width; /* Usable width not counting border */ + int height; /* Usable height not counting border */ + int x; /* start of window on terminal (left) */ + int y; /* start of window on termial (top) */ + int orientation; /* Placement of window relative to map */ + boolean border; /* Whether window has a visible border */ } nethack_window; -typedef struct nhwd -{ - winid nhwid; /* NetHack window id */ - struct nhwd *prev_wid; /* Pointer to previous entry */ - struct nhwd *next_wid; /* Pointer to next entry */ +typedef struct nhwd { + winid nhwid; /* NetHack window id */ + struct nhwd *prev_wid; /* Pointer to previous entry */ + struct nhwd *next_wid; /* Pointer to next entry */ } nethack_wid; -typedef struct nhchar -{ - int ch; /* character */ - int color; /* color info for character */ - int attr; /* attributes of character */ +typedef struct nhchar { + int ch; /* character */ + int color; /* color info for character */ + int attr; /* attributes of character */ } nethack_char; -static boolean map_clipped; /* Map window smaller than 80x21 */ - -static nethack_window nhwins[NHWIN_MAX]; /* NetHack window array */ - +static boolean map_clipped; /* Map window smaller than 80x21 */ +static nethack_window nhwins[NHWIN_MAX]; /* NetHack window array */ static nethack_char map[ROWNO][COLNO]; /* Map window contents */ - -static nethack_wid *nhwids = NULL; /* NetHack wid array */ +static nethack_wid *nhwids = NULL; /* NetHack wid array */ static boolean is_main_window(winid wid); - -static void write_char(WINDOW *win, int x, int y, nethack_char ch); - +static void write_char(WINDOW * win, int x, int y, nethack_char ch); static void clear_map(void); /* Create a window with the specified size and orientation */ -WINDOW *curses_create_window(int width, int height, orient orientation) +WINDOW * +curses_create_window(int width, int height, orient orientation) { int mapx, mapy, maph, mapw = 0; int startx = 0; @@ -57,18 +52,14 @@ WINDOW *curses_create_window(int width, int height, orient orientation) WINDOW *win; boolean map_border = FALSE; int mapb_offset = 0; - + if ((orientation == UP) || (orientation == DOWN) || - (orientation == LEFT) || (orientation == RIGHT)) - { - if (invent || (moves > 1)) - { + (orientation == LEFT) || (orientation == RIGHT)) { + if (invent || (moves > 1)) { map_border = curses_window_has_border(MAP_WIN); curses_get_window_xy(MAP_WIN, &mapx, &mapy); curses_get_window_size(MAP_WIN, &maph, &mapw); - } - else - { + } else { map_border = TRUE; mapx = 0; mapy = 0; @@ -76,92 +67,71 @@ WINDOW *curses_create_window(int width, int height, orient orientation) mapw = term_cols; } } - - if (map_border) - { + + if (map_border) { mapb_offset = 1; } - - width += 2; /* leave room for bounding box */ + + width += 2; /* leave room for bounding box */ height += 2; - - if ((width > term_cols) || (height > term_rows)) - panic("curses_create_window: Terminal too small for dialog window"); - switch (orientation) - { - case CENTER: - { - startx = (term_cols / 2) - (width / 2); - starty = (term_rows / 2) - (height / 2); - break; - } - case UP: - { - if (invent || (moves > 1)) - { - startx = (mapw / 2) - (width / 2) + mapx + mapb_offset; - } - else - { - startx = 0; - } - - starty = mapy + mapb_offset; - break; - } - case DOWN: - { - if (invent || (moves > 1)) - { - startx = (mapw / 2) - (width / 2) + mapx + mapb_offset; - } - else - { - startx = 0; - } - - starty = height - mapy - 1 - mapb_offset; - break; - } - case LEFT: - { - if (map_border && (width < term_cols)) - startx = 1; - else - startx = 0; - starty = term_rows - height; - break; + + if ((width > term_cols) || (height > term_rows)) { + impossible("curses_create_window: Terminal too small for dialog window"); + width = term_cols; + height = term_rows; + } + switch (orientation) { + default: + impossible("curses_create_window: Bad orientation"); + /* fall through to centre */ + case CENTER: + startx = (term_cols / 2) - (width / 2); + starty = (term_rows / 2) - (height / 2); + break; + case UP: + if (invent || (moves > 1)) { + startx = (mapw / 2) - (width / 2) + mapx + mapb_offset; + } else { + startx = 0; } - case RIGHT: - { - if (invent || (moves > 1)) - { - startx = (mapw + mapx + (mapb_offset * 2)) - width; - } - else - { - startx = term_cols - width; - } - - starty = 0; - break; + + starty = mapy + mapb_offset; + break; + case DOWN: + if (invent || (moves > 1)) { + startx = (mapw / 2) - (width / 2) + mapx + mapb_offset; + } else { + startx = 0; } - default: - { - panic("curses_create_window: Bad orientation"); + + starty = height - mapy - 1 - mapb_offset; + break; + case LEFT: + if (map_border && (width < term_cols)) + startx = 1; + else + startx = 0; + starty = term_rows - height; + break; + case RIGHT: + if (invent || (moves > 1)) { + startx = (mapw + mapx + (mapb_offset * 2)) - width; + } else { + startx = term_cols - width; } + + starty = 0; + break; } - - if (startx < 0) - { + + if (startx < 0) { startx = 0; } - - if (starty < 0) - { + + if (starty < 0) { starty = 0; } - + win = newwin(height, width, starty, startx); curses_toggle_color_attr(win, DIALOG_BORDER_COLOR, NONE, ON); box(win, 0, 0); @@ -172,7 +142,8 @@ WINDOW *curses_create_window(int width, int height, orient orientation) /* Erase and delete curses window, and refresh standard windows */ -void curses_destroy_win(WINDOW *win) +void +curses_destroy_win(WINDOW * win) { werase(win); wrefresh(win); @@ -183,28 +154,31 @@ void curses_destroy_win(WINDOW *win) /* Refresh nethack windows if they exist, or base window if not */ -void curses_refresh_nethack_windows() +void +curses_refresh_nethack_windows() { - WINDOW *status_window, *message_window, *map_window; - + WINDOW *status_window, *message_window, *map_window, *inv_window; + status_window = curses_get_nhwin(STATUS_WIN); message_window = curses_get_nhwin(MESSAGE_WIN); map_window = curses_get_nhwin(MAP_WIN); - - if ((moves <= 1) && !invent) - { + inv_window = curses_get_nhwin(INV_WIN); + + if ((moves <= 1) && !invent) { /* Main windows not yet displayed; refresh base window instead */ touchwin(stdscr); refresh(); - } - else - { + } else { touchwin(status_window); wnoutrefresh(status_window); touchwin(map_window); wnoutrefresh(map_window); touchwin(message_window); wnoutrefresh(message_window); + if (inv_window) { + touchwin(inv_window); + wnoutrefresh(inv_window); + } doupdate(); } } @@ -212,31 +186,33 @@ void curses_refresh_nethack_windows() /* Return curses window pointer for given NetHack winid */ -WINDOW *curses_get_nhwin(winid wid) +WINDOW * +curses_get_nhwin(winid wid) { - if (!is_main_window(wid)) - { - panic("curses_get_nhwin: wid out of range. Not a main window."); + if (!is_main_window(wid)) { + impossible("curses_get_nhwin: wid %d out of range. Not a main window.", wid); + return NULL; } - + return nhwins[wid].curwin; } /* Add curses window pointer and window info to list for given NetHack winid */ -void curses_add_nhwin(winid wid, int height, int width, int y, int x, - orient orientation, boolean border) +void +curses_add_nhwin(winid wid, int height, int width, int y, int x, + orient orientation, boolean border) { WINDOW *win; int real_width = width; int real_height = height; - - if (!is_main_window(wid)) - { - panic("curses_add_nhwin: wid out of range. Not a main window."); + + if (!is_main_window(wid)) { + impossible("curses_add_nhwin: wid %d out of range. Not a main window.", wid); + return; } - + nhwins[wid].nhwin = wid; nhwins[wid].border = border; nhwins[wid].width = width; @@ -244,74 +220,59 @@ void curses_add_nhwin(winid wid, int height, int width, int y, int x, nhwins[wid].x = x; nhwins[wid].y = y; nhwins[wid].orientation = orientation; - - if (border) - { - real_width += 2; /* leave room for bounding box */ + + if (border) { + real_width += 2; /* leave room for bounding box */ real_height += 2; } - + win = newwin(real_height, real_width, y, x); - - switch (wid) - { - case MESSAGE_WIN: - { - messagewin = win; - break; - } - case STATUS_WIN: - { - statuswin = win; - break; - } - case MAP_WIN: - { - mapwin = win; - - if ((width < COLNO) || (height < ROWNO)) - { - map_clipped = TRUE; - } - else - { - map_clipped = FALSE; - } - - break; + + switch (wid) { + case MESSAGE_WIN: + messagewin = win; + break; + case STATUS_WIN: + statuswin = win; + break; + case MAP_WIN: + mapwin = win; + + if ((width < COLNO) || (height < ROWNO)) { + map_clipped = TRUE; + } else { + map_clipped = FALSE; } + + break; } - - if (border) - { + + if (border) { box(win, 0, 0); } - + nhwins[wid].curwin = win; } /* Add wid to list of known window IDs */ -void curses_add_wid(winid wid) +void +curses_add_wid(winid wid) { nethack_wid *new_wid; nethack_wid *widptr = nhwids; - - new_wid = malloc(sizeof(nethack_wid)); + + new_wid = malloc(sizeof (nethack_wid)); new_wid->nhwid = wid; - + new_wid->next_wid = NULL; - - if (widptr == NULL) - { + + if (widptr == NULL) { new_wid->prev_wid = NULL; nhwids = new_wid; - } - else - { - while (widptr->next_wid != NULL) - { + } else { + while (widptr->next_wid != NULL) { widptr = widptr->next_wid; } new_wid->prev_wid = widptr; @@ -322,58 +283,55 @@ void curses_add_wid(winid wid) /* refresh a curses window via given nethack winid */ -void curses_refresh_nhwin(winid wid) +void +curses_refresh_nhwin(winid wid) { - wrefresh(curses_get_nhwin(wid)); + wnoutrefresh(curses_get_nhwin(wid)); + doupdate(); } /* Delete curses window via given NetHack winid and remove entry from list */ -void curses_del_nhwin(winid wid) +void +curses_del_nhwin(winid wid) { - if (curses_is_menu(wid) || curses_is_text(wid)) - { + if (curses_is_menu(wid) || curses_is_text(wid)) { curses_del_menu(wid); return; } - - if (!is_main_window(wid)) - { - panic("curses_del_nhwin: wid out of range. Not a main window."); + + if (!is_main_window(wid)) { + impossible("curses_del_nhwin: wid %d out of range. Not a main window.", wid); + return; } + nhwins[wid].curwin = NULL; nhwins[wid].nhwin = -1; } /* Delete wid from list of known window IDs */ -void curses_del_wid(winid wid) +void +curses_del_wid(winid wid) { nethack_wid *tmpwid; nethack_wid *widptr = nhwids; - - if (curses_is_menu(wid) || curses_is_text(wid)) - { + + if (curses_is_menu(wid) || curses_is_text(wid)) { curses_del_menu(wid); } - - while (widptr != NULL) - { - if (widptr->nhwid == wid) - { - if (widptr->prev_wid != NULL) - { + + while (widptr != NULL) { + if (widptr->nhwid == wid) { + if (widptr->prev_wid != NULL) { tmpwid = widptr->prev_wid; tmpwid->next_wid = widptr->next_wid; + } else { + nhwids = widptr->next_wid; /* New head mode, or NULL */ } - else - { - nhwids = widptr->next_wid; /* New head mode, or NULL */ - } - if (widptr->next_wid != NULL) - { + if (widptr->next_wid != NULL) { tmpwid = widptr->next_wid; tmpwid->prev_wid = widptr->prev_wid; } @@ -387,25 +345,23 @@ void curses_del_wid(winid wid) /* Print a single character in the given window at the given coordinates */ -void curses_putch(winid wid, int x, int y, int ch, int color, int attr) +void +curses_putch(winid wid, int x, int y, int ch, int color, int attr) { int sx, sy, ex, ey; boolean border = curses_window_has_border(wid); nethack_char nch; static boolean map_initted = FALSE; - if (wid == STATUS_WIN) - { - curses_update_stats(FALSE); + if (wid == STATUS_WIN) { + curses_update_stats(); } - if (wid != MAP_WIN) - { + if (wid != MAP_WIN) { return; } - if (!map_initted) - { + if (!map_initted) { clear_map(); map_initted = TRUE; } @@ -414,31 +370,33 @@ void curses_putch(winid wid, int x, int y, int ch, int color, int attr) map[y][x].color = color; map[y][x].attr = attr; nch = map[y][x]; - - (void)curses_map_borders(&sx, &sy, &ex, &ey, -1, -1); - - if ((x >= sx) && (x <= ex) && (y >= sy) && (y <= ey)) - { - if (border) - { + + (void) curses_map_borders(&sx, &sy, &ex, &ey, -1, -1); + + if ((x >= sx) && (x <= ex) && (y >= sy) && (y <= ey)) { + if (border) { x++; y++; } write_char(mapwin, x - sx, y - sy, nch); } - - wrefresh(mapwin); + /* refresh after every character? + * Fair go, mate! Some of us are playing from Australia! */ + /* wrefresh(mapwin); */ } /* Get x, y coordinates of curses window on the physical terminal window */ -void curses_get_window_xy(winid wid, int *x, int *y) +void +curses_get_window_xy(winid wid, int *x, int *y) { - if (!is_main_window(wid)) - { - panic("curses_get_window_xy: wid out of range. Not a main window."); + if (!is_main_window(wid)) { + impossible("curses_get_window_xy: wid %d out of range. Not a main window.", wid); + *x = 0; + *y = 0; + return; } *x = nhwins[wid].x; @@ -448,7 +406,8 @@ void curses_get_window_xy(winid wid, int *x, int *y) /* Get usable width and height curses window on the physical terminal window */ -void curses_get_window_size(winid wid, int *height, int *width) +void +curses_get_window_size(winid wid, int *height, int *width) { *height = nhwins[wid].height; *width = nhwins[wid].width; @@ -457,7 +416,8 @@ void curses_get_window_size(winid wid, int *height, int *width) /* Determine if given window has a visible border */ -boolean curses_window_has_border(winid wid) +boolean +curses_window_has_border(winid wid) { return nhwins[wid].border; } @@ -465,18 +425,17 @@ boolean curses_window_has_border(winid wid) /* Determine if window for given winid exists */ -boolean curses_window_exists(winid wid) +boolean +curses_window_exists(winid wid) { nethack_wid *widptr = nhwids; - - while (widptr != NULL) - { - if (widptr->nhwid == wid) - { + + while (widptr != NULL) { + if (widptr->nhwid == wid) { return TRUE; - } + } - widptr = widptr->next_wid; + widptr = widptr->next_wid; } return FALSE; @@ -485,94 +444,115 @@ boolean curses_window_exists(winid wid) /* Return the orientation of the specified window */ -int curses_get_window_orientation(winid wid) +int +curses_get_window_orientation(winid wid) { - if (!is_main_window(wid)) - { - panic("curses_get_window_orientation: wid out of range. Not a main window."); + if (!is_main_window(wid)) { + impossible + ("curses_get_window_orientation: wid %d out of range. Not a main window.", wid); + return CENTER; } - return nhwins[wid].orientation; + return nhwins[wid].orientation; } /* Output a line of text to specified NetHack window with given coordinates and text attributes */ -void curses_puts(winid wid, int attr, const char *text) +void +curses_puts(winid wid, int attr, const char *text) { anything *identifier; WINDOW *win = NULL; - - if (is_main_window(wid)) - { + + if (is_main_window(wid)) { win = curses_get_nhwin(wid); } - - if (wid == MESSAGE_WIN) - { + + if (wid == MESSAGE_WIN) { curses_message_win_puts(text, FALSE); return; } - - if (wid == STATUS_WIN) - { - curses_update_stats(FALSE); /* We will do the write ourselves */ + + if (wid == STATUS_WIN) { + curses_update_stats(); /* We will do the write ourselves */ + /* Inventory updating isn't performed on redraws, so + also update inventory here... */ + curses_update_inventory(); return; } - - if (curses_is_menu(wid) || curses_is_text(wid)) - { - if (!curses_menu_exists(wid)) - { - panic("curses_puts: Attempted write to nonexistant window!"); + + if (curses_is_menu(wid) || curses_is_text(wid)) { + if (!curses_menu_exists(wid)) { + impossible("curses_puts: Attempted write to nonexistant window %d!", wid); + return; } - identifier = malloc(sizeof(anything)); + identifier = malloc(sizeof (anything)); identifier->a_void = NULL; - curses_add_nhmenu_item(wid, identifier, 0, 0, attr, text, - FALSE); - } - else - { + curses_add_nhmenu_item(wid, NO_GLYPH, identifier, 0, 0, attr, text, + FALSE); + } else { waddstr(win, text); - wrefresh(win); + wnoutrefresh(win); } } /* Clear the contents of a window via the given NetHack winid */ -void curses_clear_nhwin(winid wid) +void +curses_clear_nhwin(winid wid) { WINDOW *win = curses_get_nhwin(wid); boolean border = curses_window_has_border(wid); - - if (wid == MAP_WIN) - { - clearok(win, TRUE); /* Redraw entire screen when refreshed */ + + if (wid == MAP_WIN) { + clearok(win, TRUE); /* Redraw entire screen when refreshed */ clear_map(); } - + werase(win); - if (border) - { + if (border) { box(win, 0, 0); } } +/* Change colour of window border to alert player to something */ +void +curses_alert_win_border(winid wid, boolean onoff) +{ + WINDOW *win = curses_get_nhwin(wid); + + if (!win || !curses_window_has_border(wid)) + return; + if (onoff) + curses_toggle_color_attr(win, ALERT_BORDER_COLOR, NONE, ON); + box(win, 0, 0); + if (onoff) + curses_toggle_color_attr(win, ALERT_BORDER_COLOR, NONE, OFF); + wnoutrefresh(win); +} + + +void +curses_alert_main_borders(boolean onoff) +{ + curses_alert_win_border(MAP_WIN, onoff); + curses_alert_win_border(MESSAGE_WIN, onoff); + curses_alert_win_border(STATUS_WIN, onoff); + curses_alert_win_border(INV_WIN, onoff); +} /* Return true if given wid is a main NetHack window */ -static boolean is_main_window(winid wid) +static boolean +is_main_window(winid wid) { - if ((wid == MESSAGE_WIN) || (wid == MAP_WIN) || - (wid == STATUS_WIN)) - { + if ((wid == MESSAGE_WIN) || (wid == MAP_WIN) || (wid == STATUS_WIN) || wid == INV_WIN) { return TRUE; - } - else - { + } else { return FALSE; } } @@ -581,7 +561,8 @@ static boolean is_main_window(winid wid) /* Unconditionally write a single character to a window at the given coordinates without a refresh. Currently only used for the map. */ -static void write_char(WINDOW *win, int x, int y, nethack_char nch) +static void +write_char(WINDOW * win, int x, int y, nethack_char nch) { curses_toggle_color_attr(win, nch.color, nch.attr, ON); #ifdef PDCURSES @@ -596,20 +577,20 @@ static void write_char(WINDOW *win, int x, int y, nethack_char nch) /* Draw the entire visible map onto the screen given the visible map boundaries */ -void curses_draw_map(int sx, int sy, int ex, int ey) +void +curses_draw_map(int sx, int sy, int ex, int ey) { int curx, cury; int bspace = 0; + #ifdef MAP_SCROLLBARS int sbsx, sbsy, sbex, sbey, count; nethack_char hsb_back, hsb_bar, vsb_back, vsb_bar; #endif - - if (curses_window_has_border(MAP_WIN)) - { + + if (curses_window_has_border(MAP_WIN)) { bspace++; } - #ifdef MAP_SCROLLBARS hsb_back.ch = '-'; hsb_back.color = SCROLLBAR_BACK_COLOR; @@ -625,62 +606,46 @@ void curses_draw_map(int sx, int sy, int ex, int ey) vsb_bar.attr = A_NORMAL; /* Horizontal scrollbar */ - if ((sx > 0) || (ex < (COLNO - 1))) - { - sbsx = (sx * ((float)(ex - sx + 1) / COLNO)); - sbex = (ex * ((float)(ex - sx + 1) / COLNO)); - - for (count = 0; count < sbsx; count++) - { - write_char(mapwin, count + bspace, - ey - sy + 1 + bspace, hsb_back); + if ((sx > 0) || (ex < (COLNO - 1))) { + sbsx = (sx * ((float) (ex - sx + 1) / COLNO)); + sbex = (ex * ((float) (ex - sx + 1) / COLNO)); + + for (count = 0; count < sbsx; count++) { + write_char(mapwin, count + bspace, ey - sy + 1 + bspace, hsb_back); } - - for (count = sbsx; count <= sbex; count++) - { - write_char(mapwin, count + bspace, - ey - sy + 1 + bspace, hsb_bar); + + for (count = sbsx; count <= sbex; count++) { + write_char(mapwin, count + bspace, ey - sy + 1 + bspace, hsb_bar); } - - for (count = sbex + 1; count <= (ex - sx); count++) - { - write_char(mapwin, count + bspace, - ey - sy + 1 + bspace, hsb_back); + + for (count = sbex + 1; count <= (ex - sx); count++) { + write_char(mapwin, count + bspace, ey - sy + 1 + bspace, hsb_back); } } - + /* Vertical scrollbar */ - if ((sy > 0) || (ey < (ROWNO - 1))) - { - sbsy = (sy * ((float)(ey - sy + 1) / ROWNO)); - sbey = (ey * ((float)(ey - sy + 1) / ROWNO)); - - for (count = 0; count < sbsy; count++) - { - write_char(mapwin, ex - sx + 1 + bspace, count + bspace, - vsb_back); + if ((sy > 0) || (ey < (ROWNO - 1))) { + sbsy = (sy * ((float) (ey - sy + 1) / ROWNO)); + sbey = (ey * ((float) (ey - sy + 1) / ROWNO)); + + for (count = 0; count < sbsy; count++) { + write_char(mapwin, ex - sx + 1 + bspace, count + bspace, vsb_back); } - - for (count = sbsy; count <= sbey; count++) - { - write_char(mapwin, ex - sx + 1 + bspace, count + bspace, - vsb_bar); + + for (count = sbsy; count <= sbey; count++) { + write_char(mapwin, ex - sx + 1 + bspace, count + bspace, vsb_bar); } - - for (count = sbey + 1; count <= (ey - sy); count++) - { - write_char(mapwin, ex - sx + 1 + bspace, count + bspace, - vsb_back); + + for (count = sbey + 1; count <= (ey - sy); count++) { + write_char(mapwin, ex - sx + 1 + bspace, count + bspace, vsb_back); } - } -#endif /* MAP_SCROLLBARS */ + } +#endif /* MAP_SCROLLBARS */ - for (curx = sx; curx <= ex; curx++) - { - for (cury = sy; cury <= ey; cury++) - { + for (curx = sx; curx <= ex; curx++) { + for (cury = sy; cury <= ey; cury++) { write_char(mapwin, curx - sx + bspace, cury - sy + bspace, - map[cury][curx]); + map[cury][curx]); } } } @@ -688,14 +653,13 @@ void curses_draw_map(int sx, int sy, int ex, int ey) /* Init map array to blanks */ -static void clear_map() +static void +clear_map() { int x, y; - - for (x = 0; x < COLNO; x++) - { - for (y = 0; y < ROWNO; y++) - { + + for (x = 0; x < COLNO; x++) { + for (y = 0; y < ROWNO; y++) { map[y][x].ch = ' '; map[y][x].color = NO_COLOR; map[y][x].attr = A_NORMAL; @@ -707,8 +671,8 @@ static void clear_map() /* Determine visible boundaries of map, and determine if it needs to be based on the location of the player. */ -boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, int ux, - int uy) +boolean +curses_map_borders(int *sx, int *sy, int *ex, int *ey, int ux, int uy) { static int width = 0; static int height = 0; @@ -718,103 +682,80 @@ boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, int ux, static int oey = 0; static int oux = -1; static int ouy = -1; - - if ((oux == -1) || (ouy == -1)) - { + + if ((oux == -1) || (ouy == -1)) { oux = u.ux; ouy = u.uy; } - - if (ux == -1) - { + + if (ux == -1) { ux = oux; - } - else - { + } else { oux = ux; } - if (uy == -1) - { + if (uy == -1) { uy = ouy; - } - else - { + } else { ouy = uy; } curses_get_window_size(MAP_WIN, &height, &width); - + #ifdef MAP_SCROLLBARS - if (width < COLNO) - { - height--; /* room for horizontal scrollbar */ + if (width < COLNO) { + height--; /* room for horizontal scrollbar */ } - if (height < ROWNO) - { - width--; /* room for vertical scrollbar */ + if (height < ROWNO) { + width--; /* room for vertical scrollbar */ - if (width == COLNO) - { + if (width == COLNO) { height--; } } -#endif /* MAP_SCROLLBARS */ +#endif /* MAP_SCROLLBARS */ - if (width >= COLNO) - { + if (width >= COLNO) { *sx = 0; *ex = COLNO - 1; - } - else - { + } else { *ex = (width / 2) + ux; *sx = *ex - (width - 1); - - if (*ex >= COLNO) - { + + if (*ex >= COLNO) { *sx = COLNO - width; *ex = COLNO - 1; - } - else if (*sx < 0) - { + } else if (*sx < 0) { *sx = 0; *ex = width - 1; } } - - if (height >= ROWNO) - { + + if (height >= ROWNO) { *sy = 0; *ey = ROWNO - 1; - } - else - { + } else { *ey = (height / 2) + uy; *sy = *ey - (height - 1); - - if (*ey >= ROWNO) - { + + if (*ey >= ROWNO) { *sy = ROWNO - height; *ey = ROWNO - 1; - } - else if (*sy < 0) - { + } else if (*sy < 0) { *sy = 0; *ey = height - 1; } } if ((*sx != osx) || (*sy != osy) || (*ex != oex) || (*ey != oey) || - map_clipped) - { + map_clipped) { osx = *sx; osy = *sy; oex = *ex; oey = *ey; return TRUE; } - + return FALSE; } diff --git a/win/curses/curswins.h b/win/curses/curswins.h index c41d4983..ce1935e0 100644 --- a/win/curses/curswins.h +++ b/win/curses/curswins.h @@ -1,46 +1,33 @@ +/* vim:set cin ft=c sw=4 sts=4 ts=8 et ai cino=Ls\:0t0(0 : -*- mode:c;fill-column:80;tab-width:8;c-basic-offset:4;indent-tabs-mode:nil;c-file-style:"k&r" -*-*/ + #ifndef CURSWIN_H -#define CURSWIN_H +# define CURSWIN_H /* Global declarations */ WINDOW *curses_create_window(int width, int height, orient orientation); -void curses_destroy_win(WINDOW *win); - +void curses_destroy_win(WINDOW * win); void curses_refresh_nethack_windows(void); - WINDOW *curses_get_nhwin(winid wid); - void curses_add_nhwin(winid wid, int height, int width, int y, int x, - orient orientation, boolean border); - + orient orientation, boolean border); void curses_add_wid(winid wid); - void curses_refresh_nhwin(winid wid); - void curses_del_nhwin(winid wid); - void curses_del_wid(winid wid); - void curses_putch(winid wid, int x, int y, int ch, int color, int attrs); - void curses_get_window_xy(winid wid, int *x, int *y); - boolean curses_window_has_border(winid wid); - boolean curses_window_exists(winid wid); - int curses_get_window_orientation(winid wid); - void curses_puts(winid wid, int attr, const char *text); - void curses_clear_nhwin(winid wid); - +void curses_alert_win_border(winid wid, boolean onoff); +void curses_alert_main_borders(boolean onoff); void curses_draw_map(int sx, int sy, int ex, int ey); - -boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, int ux, - int uy); +boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, int ux, int uy); -#endif /* CURSWIN_H */ +#endif /* CURSWIN_H */ diff --git a/win/tty/topl.c b/win/tty/topl.c index 46b05189..632660a8 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -188,11 +188,17 @@ more() if(flags.standout) standoutbeg(); - putsyms(defmorestr); - if(flags.standout) - standoutend(); - - xwaitforspace("\033 "); + if (iflags.msg_is_alert) { + term_start_color(CLR_ORANGE); + putsyms(""); + term_end_color(); + xwaitforspace("\t"); + } else { + putsyms(defmorestr); + xwaitforspace("\033 "); + } + if (flags.standout) + standoutend(); if(morc == '\033') cw->flags |= WIN_STOP; diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 71b3d4ec..58bfc798 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -2308,7 +2308,8 @@ tty_end_menu(window, prompt) } if (len > (int)ttyDisplay->cols) { - curr->str[ttyDisplay->cols-2] = 0; + /* reduce the string by the amount len exceeds cols */ + curr->str[strlen(curr->str) - (len - ttyDisplay->cols)] = 0; len = ttyDisplay->cols; } if (len > cw->cols) cw->cols = len;