static void dynamic_display(menu_type *m, int oid, bool cursor, int row, int col, int width) { struct menu_entry *entry; byte color = curs_attrs[CURS_KNOWN][0 != cursor]; for (entry = menu_priv(m); oid; oid--) { entry = entry->next; assert(entry); } /*if ((entry->text[0] == '$') && (entry->text[1] >= 'A') && (entry->text[1] < 'P')) {*/ /* if the entry starts with a custom color, use it */ /*Term_putstr(col, row, width, entry->text[1]-'A', entry->text+2);*/ if (entry->text[0] == '$') { if (entry->text[1] != '$') { color = curs_attrs[CURS_UNKNOWN][0 != cursor]; } Term_putstr(col, row, width, color, entry->text+1); } else { Term_putstr(col, row, width, color, entry->text); } }
void display_panel(const data_panel *panel, int count, bool left_adj, const region *bounds) { int i; char buffer[50]; int col = bounds->col; int row = bounds->row; int w = bounds->width; int offset = 0; if (left_adj) { for (i = 0; i < count; i++) { int len = panel[i].label ? strlen(panel[i].label) : 0; if (offset < len) offset = len; } offset += 2; } for (i = 0; i < count; i++, row++) { int len; if (!panel[i].label) continue; Term_putstr(col, row, strlen(panel[i].label), TERM_WHITE, panel[i].label); strnfmt(buffer, sizeof(buffer), panel[i].fmt, panel[i].value[0], panel[i].value[1]); len = strlen(buffer); len = len < w - offset ? len : w - offset - 1; if (left_adj) Term_putstr(col+offset, row, len, panel[i].color, buffer); else Term_putstr(col+w-len, row, len, panel[i].color, buffer); } }
/* * Get the Sex. */ static bool get_sex(void) { char query2; int loopagain = TRUE; // Set the default sex info to female if (p_ptr->psex == SEX_UNDEFINED) { p_ptr->psex = SEX_FEMALE; sp_ptr = &sex_info[SEX_FEMALE]; } while (loopagain == TRUE) { /* Display the player */ display_player(0); // Highlight the relevant feature c_put_str(TERM_YELLOW, sp_ptr->title, 3, 8); /* Prompt */ Term_putstr(QUESTION_COL, INSTRUCT_ROW + 1, -1, TERM_SLATE, "Enter accept sex"); Term_putstr(QUESTION_COL, INSTRUCT_ROW + 2, -1, TERM_SLATE, "Space change sex"); /* Hack - highlight the key names */ Term_putstr(QUESTION_COL, INSTRUCT_ROW + 1, - 1, TERM_L_WHITE, "Enter"); Term_putstr(QUESTION_COL, INSTRUCT_ROW + 2, - 1, TERM_L_WHITE, "Space"); /* Move the cursor */ Term_gotoxy(0, INSTRUCT_ROW + 1); /* Query */ query2 = inkey(); if ((query2 == '\r') || (query2 == '\n')) { /* got a sex*/ loopagain = FALSE; p_ptr->redraw |= (PR_MISC); } else if (query2 == ESCAPE) return (FALSE); else if (((query2 == 'Q') || (query2 == 'q')) && (turn == 0)) quit (NULL); else { if (p_ptr->psex == SEX_FEMALE) p_ptr->psex = SEX_MALE; else p_ptr->psex = SEX_FEMALE; sp_ptr = &sex_info[p_ptr->psex]; } } return (TRUE); }
/** * Get some input at the cursor location. * * The buffer is assumed to have been initialized to a default string. * Note that this string is often "empty" (see below). * * The default buffer is displayed in yellow until cleared, which happens * on the first keypress, unless that keypress is Return. * * Normal chars clear the default and append the char. * Backspace clears the default or deletes the final char. * Return accepts the current buffer contents and returns true. * Escape clears the buffer and the window and returns false. * * Note that 'len' refers to the size of the buffer. The maximum length * of the input is 'len-1'. * * 'keypress_h' is a pointer to a function to handle keypresses, altering * the input buffer, cursor position and suchlike as required. See * 'askfor_aux_keypress' (the default handler if you supply NULL for * 'keypress_h') for an example. */ bool askfor_aux(char *buf, size_t len, bool (*keypress_h)(char *, size_t, size_t *, size_t *, struct keypress, bool)) { int y, x; size_t k = 0; /* Cursor position */ size_t nul = 0; /* Position of the null byte in the string */ struct keypress ch = KEYPRESS_NULL; bool done = false; bool firsttime = true; if (keypress_h == NULL) keypress_h = askfor_aux_keypress; /* Locate the cursor */ Term_locate(&x, &y); /* Paranoia */ if ((x < 0) || (x >= 80)) x = 0; /* Restrict the length */ if (x + len > 80) len = 80 - x; /* Truncate the default entry */ buf[len-1] = '\0'; /* Get the position of the null byte */ nul = strlen(buf); /* Display the default answer */ Term_erase(x, y, (int)len); Term_putstr(x, y, -1, COLOUR_YELLOW, buf); /* Process input */ while (!done) { /* Place cursor */ Term_gotoxy(x + k, y); /* Get a key */ ch = inkey(); /* Let the keypress handler deal with the keypress */ done = keypress_h(buf, len, &k, &nul, ch, firsttime); /* Update the entry */ Term_erase(x, y, (int)len); Term_putstr(x, y, -1, COLOUR_WHITE, buf); /* Not the first time round anymore */ firsttime = false; } /* Done */ return (ch.code != ESCAPE); }
/* * Handle signal -- abort, kill, etc */ static void handle_signal_abort(int sig) { /* Disable handler */ (void)(*signal_aux)(sig, SIG_IGN); /* Nothing to save, just quit */ if (!character_generated || character_saved) quit(NULL); /* Clear the bottom line */ Term_erase(0, 23, 255); /* Give a warning */ Term_putstr(0, 23, -1, TERM_RED, "A gruesome software bug LEAPS out at you!"); /* Message */ Term_putstr(45, 23, -1, TERM_RED, "Panic save..."); /* Flush output */ Term_fresh(); /* Panic Save p_ptr->panic_save = 1; */ /* Panic save */ my_strcpy(p_ptr->died_from, "(panic save)", sizeof(p_ptr->died_from)); /* Forbid suspend */ signals_ignore_tstp(); /* Attempt to save */ if (old_save()) { Term_putstr(45, 23, -1, TERM_RED, "Panic save succeeded!"); } /* Save failed */ else { Term_putstr(45, 23, -1, TERM_RED, "Panic save failed!"); } /* Flush output */ Term_fresh(); /* Quit */ quit("software bug"); }
/** * Redraw the "monster mana bar" * * The "monster mana bar" provides visual feedback on the "mana" * of the monster currently being "tracked". It follows the lead of the * monster health bar for who to track. */ static void prt_mana(int row, int col) { byte attr = TERM_SLATE; /* Not tracking */ if (!p_ptr->health_who) { /* Erase the health bar */ Term_erase(col, row, 12); } /* Tracking an unseen, hallucinatory, or dead monster */ else if ((!m_list[p_ptr->health_who].ml) || /* Unseen */ (p_ptr->timed[TMD_IMAGE]) || /* Hallucination */ (m_list[p_ptr->health_who].hp < 0)) { /* Dead (?) */ /* The monster mana is "unknown" */ Term_putstr(col, row, 12, attr, "[----------]"); } /* Tracking a visible monster */ else { int pct, len; monster_type *m_ptr = &m_list[p_ptr->health_who]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; /* no mana, stop here */ if (!r_ptr->mana) { /* Erase the mana bar */ Term_erase(col, row, 12); return; } attr = monster_mana_attr(); /* Extract the "percent" of mana */ pct = 100L * m_ptr->mana / r_ptr->mana; /* Convert percent into "mana" */ len = (pct < 10) ? 1 : (pct < 90) ? (pct / 10 + 1) : 10; /* Default to "unknown" */ Term_putstr(col, row, 12, TERM_WHITE, "[----------]"); /* Dump the current "mana" (use '*' symbols) */ Term_putstr(col + 1, row, len, attr, "**********"); } }
/*! * @brief スナイパーの技能リストを表示する * @return なし */ void display_snipe_list(void) { int i; int y = 1; int x = 1; int plev = p_ptr->lev; snipe_power spell; char psi_desc[80]; /* Display a list of spells */ prt("", y, x); #ifdef JP put_str("名前", y, x + 5); put_str("Lv MP", y, x + 35); #else put_str("Name", y, x + 5); put_str("Lv Mana", y, x + 35); #endif /* Dump the spells */ for (i = 0; i < MAX_SNIPE_POWERS; i++) { /* Access the available spell */ spell = snipe_powers[i]; if (spell.min_lev > plev) continue; if (spell.mana_cost > (int)p_ptr->concent) continue; /* Dump the spell */ sprintf(psi_desc, " %c) %-30s%2d %4d", I2A(i), spell.name, spell.min_lev, spell.mana_cost); Term_putstr(x, y + i + 1, -1, TERM_WHITE, psi_desc); } return; }
/* Display an entry on a command menu */ static void cmd_sub_entry(menu_type *menu, int oid, bool cursor, int row, int col, int width) { byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE); const struct generic_command *commands = menu_priv(menu); (void)width; /* Write the description */ Term_putstr(col, row, -1, attr, commands[oid].desc); /* Include keypress */ Term_addch(attr, ' '); Term_addch(attr, '('); /* KTRL()ing a control character does not alter it at all */ if (KTRL(commands[oid].key) == commands[oid].key) { Term_addch(attr, '^'); Term_addch(attr, UN_KTRL(commands[oid].key)); } else { Term_addch(attr, commands[oid].key); } Term_addch(attr, ')'); }
/* ------------------------------------------------------------------------ * MN_STRINGS HELPER FUNCTIONS * * MN_STRINGS is the type of menu iterator that displays a simple list of * strings - no action is associated, as selection will just return the index. * ------------------------------------------------------------------------ */ static void display_string(menu_type *m, int oid, bool cursor, int row, int col, int width) { char **items = menu_priv(m); byte color = curs_attrs[CURS_KNOWN][0 != cursor]; Term_putstr(col, row, width, color, items[oid]); }
/* Modal display of menu */ static void display_menu_row(menu_type *menu, int pos, int top, bool cursor, int row, int col, int width) { int flags = menu->flags; char sel = 0; int oid = pos; if (menu->filter_list) oid = menu->filter_list[oid]; if (menu->row_funcs->valid_row && menu->row_funcs->valid_row(menu, oid) == 2) return; if (!(flags & MN_NO_TAGS)) { if (flags & MN_REL_TAGS) sel = menu->skin->get_tag(menu, pos); else if (menu->selections && !(flags & MN_PVT_TAGS)) sel = menu->selections[pos]; else if (menu->row_funcs->get_tag) sel = menu->row_funcs->get_tag(menu, oid); } if (sel) { /* TODO: CHECK FOR VALID */ byte color = curs_attrs[CURS_KNOWN][0 != (cursor)]; Term_putstr(col, row, 3, color, format("%c) ", sel)); col += 3; width -= 3; } menu->row_funcs->display_row(menu, oid, cursor, row, col, width); }
/** * Display an entry on a command menu */ static void show_display(menu_type * menu, int oid, bool cursor, int row, int col, int width) { byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE); /* Write the description */ Term_putstr(col + 4, row, -1, attr, comm_descr[oid]); }
/** * Redraw the "monster health bar" * * The "monster health bar" provides visual feedback on the "health" * of the monster currently being "tracked". There are several ways * to "track" a monster, including targetting it, attacking it, and * affecting it (and nobody else) with a ranged attack. When nothing * is being tracked, we clear the health bar. If the monster being * tracked is not currently visible, a special health bar is shown. */ static void prt_health(int row, int col) { byte attr = monster_health_attr(); /* Not tracking */ if (!p_ptr->health_who) { /* Erase the health bar */ Term_erase(col, row, 12); } /* Tracking an unseen, hallucinatory, or dead monster */ else if ((!m_list[p_ptr->health_who].ml) || /* Unseen */ (p_ptr->timed[TMD_IMAGE]) || /* Hallucination */ (m_list[p_ptr->health_who].hp < 0)) { /* Dead (?) */ /* The monster health is "unknown" */ Term_putstr(col, row, 12, attr, "[----------]"); } /* Tracking a visible monster */ else { int pct, len; monster_type *m_ptr = &m_list[p_ptr->health_who]; /* Extract the "percent" of health */ pct = 100L * m_ptr->hp / m_ptr->maxhp; /* Convert percent into "health" */ len = (pct < 10) ? 1 : (pct < 90) ? (pct / 10 + 1) : 10; /* Default to "unknown" */ Term_putstr(col, row, 12, TERM_WHITE, "[----------]"); /* Dump the current "health" (handle monster stunning, confusion) */ if (m_ptr->confused) Term_putstr(col + 1, row, len, attr, "cccccccccc"); else if (m_ptr->stunned) Term_putstr(col + 1, row, len, attr, "ssssssssss"); else Term_putstr(col + 1, row, len, attr, "**********"); } }
/* Display an event, with possible preference overrides */ static void display_action_aux(menu_action *act, byte color, int row, int col, int wid) { /* TODO: add preference support */ /* TODO: wizard mode should show more data */ Term_erase(col, row, wid); /*if (act->name) Term_putstr(col, row, wid, color, act->name);*/ if (act->text) Term_putstr(col, row, wid, color, act->text); }
static void display_panel(const struct panel *p, bool left_adj, const region *bounds) { size_t i; int col = bounds->col; int row = bounds->row; int w = bounds->width; int offset = 0; region_erase(bounds); if (left_adj) { for (i = 0; i < p->len; i++) { struct panel_line *pl = &p->lines[i]; int len = pl->label ? strlen(pl->label) : 0; if (offset < len) offset = len; } offset += 2; } for (i = 0; i < p->len; i++, row++) { int len; struct panel_line *pl = &p->lines[i]; if (!pl->label) continue; Term_putstr(col, row, strlen(pl->label), COLOUR_WHITE, pl->label); len = strlen(pl->value); len = len < w - offset ? len : w - offset - 1; if (left_adj) Term_putstr(col+offset, row, len, pl->attr, pl->value); else Term_putstr(col+w-len, row, len, pl->attr, pl->value); } }
/* * Hack -- flush */ static void msg_flush(int x) { byte a = TERM_L_BLUE; /* Pause for response */ Term_putstr(x, 0, -1, a, "-more-"); if (!OPT(auto_more)) anykey(); /* Clear the line */ Term_erase(0, 0, 255); }
/* * Display additional information about each house during the selection. */ static void house_aux_hook(birth_menu c_str) { int house_idx, i, adj; char s[128]; byte attr; /* Extract the proper house index from the string. */ for (house_idx = 0; house_idx < z_info->c_max; house_idx++) { if (!strcmp(c_str.name, c_name + c_info[house_idx].name)) break; } if (house_idx == z_info->c_max) return; /* Display relevant details. */ for (i = 0; i < A_MAX; i++) { /*dump potential total stats*/ strnfmt(s, sizeof(s), "%s", stat_names[i]); Term_putstr(TOTAL_AUX_COL, TABLE_ROW + i, -1, TERM_WHITE, s); adj = c_info[house_idx].h_adj[i] + rp_ptr->r_adj[i]; strnfmt(s, sizeof(s), "%+d", adj); if (adj < 0) attr = TERM_RED; else if (adj == 0) attr = TERM_L_DARK; else if (adj == 1) attr = TERM_GREEN; else if (adj == 2) attr = TERM_L_GREEN; else attr = TERM_L_BLUE; Term_putstr(TOTAL_AUX_COL + 4, TABLE_ROW + i, -1, attr, s); } /* Display the race flags */ Term_putstr(TOTAL_AUX_COL, TABLE_ROW + A_MAX + 1, -1, TERM_WHITE, " "); Term_putstr(TOTAL_AUX_COL, TABLE_ROW + A_MAX + 2, -1, TERM_WHITE, " "); Term_putstr(TOTAL_AUX_COL, TABLE_ROW + A_MAX + 3, -1, TERM_WHITE, " "); Term_putstr(TOTAL_AUX_COL, TABLE_ROW + A_MAX + 4, -1, TERM_WHITE, " "); Term_putstr(TOTAL_AUX_COL, TABLE_ROW + A_MAX + 5, -1, TERM_WHITE, " "); print_rh_flags(p_ptr->prace,house_idx,TOTAL_AUX_COL,TABLE_ROW + A_MAX + 1); }
/* Display an entry on a command menu */ static void cmd_sub_entry(menu_type *menu, int oid, bool cursor, int row, int col, int width) { byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE); const struct cmd_info *commands = menu_priv(menu); int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; struct keypress kp = { EVT_KBRD, commands[oid].key[mode] }; char buf[16]; /* Write the description */ Term_putstr(col, row, -1, attr, commands[oid].desc); /* Include keypress */ Term_addch(attr, ' '); Term_addch(attr, '('); /* Get readable version */ keypress_to_readable(buf, sizeof buf, kp); Term_addstr(-1, attr, buf); Term_addch(attr, ')'); }
void display_snipe_list(void) { int i; int y = 1; int x = 1; int plev = p_ptr->lev; snipe_power spell; char desc[80]; prt("", y, x); put_str("Name", y, x + 5); put_str("Lv Mana", y, x + 35); for (i = 0; i < MAX_SNIPE_POWERS; i++) { spell = snipe_powers[i]; if (spell.min_lev > plev) continue; if (spell.mana_cost > (int)p_ptr->concent) continue; sprintf(desc, " %c) %-30s%2d %4d", I2A(i), spell.name, spell.min_lev, spell.mana_cost); Term_putstr(x, y + i + 1, -1, TERM_WHITE, desc); } return; }
/* * Display additional information about each race during the selection. */ static void race_aux_hook(birth_menu r_str) { int race, i, adj; char s[50]; byte attr; /* Extract the proper race index from the string. */ for (race = 0; race < z_info->p_max; race++) { if (!strcmp(r_str.name, p_name + p_info[race].name)) break; } if (race == z_info->p_max) return; /* Display the stats */ for (i = 0; i < A_MAX; i++) { /*dump the stats*/ strnfmt(s, sizeof(s), "%s", stat_names[i]); Term_putstr(RACE_AUX_COL, TABLE_ROW + i, -1, TERM_WHITE, s); adj = p_info[race].r_adj[i]; strnfmt(s, sizeof(s), "%+d", adj); if (adj < 0) attr = TERM_RED; else if (adj == 0) attr = TERM_L_DARK; else if (adj == 1) attr = TERM_GREEN; else if (adj == 2) attr = TERM_L_GREEN; else attr = TERM_L_BLUE; Term_putstr(RACE_AUX_COL + 4, TABLE_ROW + i, -1, attr, s); } /* Display the race flags */ Term_putstr(RACE_AUX_COL, TABLE_ROW + A_MAX + 1, -1, TERM_WHITE, " "); Term_putstr(RACE_AUX_COL, TABLE_ROW + A_MAX + 2, -1, TERM_WHITE, " "); Term_putstr(RACE_AUX_COL, TABLE_ROW + A_MAX + 3, -1, TERM_WHITE, " "); Term_putstr(RACE_AUX_COL, TABLE_ROW + A_MAX + 4, -1, TERM_WHITE, " "); print_rh_flags(race, 0, RACE_AUX_COL, TABLE_ROW + A_MAX + 1); }
static void display_resistance_panel(const struct player_flag_record *rec, size_t size, const region *bounds) { size_t i; int j; int col = bounds->col; int row = bounds->row; int res_cols = 5 + 2 + player->body.count; Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); for (i = 0; i < size - 3; i++, row++) { byte name_attr = COLOUR_WHITE; Term_gotoxy(col + 6, row); /* Repeated extraction of flags is inefficient but more natural */ for (j = 0; j <= player->body.count; j++) { bitflag f[OF_SIZE]; byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res = false, imm = false, vul = false, rune = false; bool timed = false; bool known = false; /* Object or player info? */ if (j < player->body.count) { int index = 0; struct object *obj = slot_object(player, j); struct curse_data *curse = obj ? obj->curses : NULL; while (obj) { /* Wipe flagset */ of_wipe(f); /* Get known properties */ object_flags_known(obj, f); if (rec[i].element != -1) { known = object_element_is_known(obj, rec[i].element); } else if (rec[i].flag != -1) { known = object_flag_is_known(obj, rec[i].flag); } else { known = true; } /* Get resistance, immunity and vulnerability info */ if (rec[i].mod != -1) { if (obj->modifiers[rec[i].mod] != 0) { res = true; } rune = (player->obj_k->modifiers[rec[i].mod] == 1); } else if (rec[i].flag != -1) { if (of_has(f, rec[i].flag)) { res = true; } rune = of_has(player->obj_k->flags, rec[i].flag); } else if (rec[i].element != -1) { if (known) { if (obj->el_info[rec[i].element].res_level == 3) { imm = true; } if (obj->el_info[rec[i].element].res_level == 1) { res = true; } if (obj->el_info[rec[i].element].res_level == -1) { vul = true; } } rune = (player->obj_k->el_info[rec[i].element].res_level == 1); } /* Move to any unprocessed curse object */ if (curse) { index++; obj = NULL; while (index < z_info->curse_max) { if (curse[index].power) { obj = curses[index].obj; break; } else { index++; } } } else { obj = NULL; } } } else { player_flags(player, f); known = true; /* Timed flags only in the player column */ if (rec[i].tmd_flag >= 0) { timed = player->timed[rec[i].tmd_flag] ? true : false; /* There has to be one special case... */ if ((rec[i].tmd_flag == TMD_AFRAID) && (player->timed[TMD_TERROR])) timed = true; } /* Set which (if any) symbol and color are used */ if (rec[i].mod != -1) { int k; /* Shape modifiers */ for (k = 0; k < OBJ_MOD_MAX; k++) { res = (player->shape->modifiers[i] > 0); vul = (player->shape->modifiers[i] > 0); } /* Messy special cases */ if (rec[i].mod == OBJ_MOD_INFRA) res |= (player->race->infra > 0); if (rec[i].mod == OBJ_MOD_TUNNEL) res |= (player->race->r_skills[SKILL_DIGGING] > 0); } else if (rec[i].flag != -1) { res = of_has(f, rec[i].flag); res |= (of_has(player->shape->flags, rec[i].flag) && of_has(player->obj_k->flags, rec[i].flag)); } else if (rec[i].element != -1) { int el = rec[i].element; imm = (player->race->el_info[el].res_level == 3) || ((player->shape->el_info[el].res_level == 3) && (player->obj_k->el_info[el].res_level)); res = (player->race->el_info[el].res_level == 1) || ((player->shape->el_info[el].res_level == 1) && (player->obj_k->el_info[el].res_level)); vul = (player->race->el_info[el].res_level == -1) || ((player->shape->el_info[el].res_level == -1) && (player->obj_k->el_info[el].res_level)); } } /* Colour the name appropriately */ if (imm) { name_attr = COLOUR_GREEN; } else if (res && (name_attr != COLOUR_GREEN)) { name_attr = COLOUR_L_BLUE; } else if (vul && (name_attr != COLOUR_GREEN)) { name_attr = COLOUR_RED; } /* Set the symbols and print them */ if (vul) { sym = '-'; } else if (imm) { sym = '*'; } else if (res) { sym = '+'; } else if (timed) { sym = '!'; attr = COLOUR_L_GREEN; } else if ((j < player->body.count) && slot_object(player, j) && !known && !rune) { sym = '?'; } Term_addch(attr, sym); } /* Check if the rune is known */ if (((rec[i].mod >= 0) && (player->obj_k->modifiers[rec[i].mod] == 0)) || ((rec[i].flag >= 0) && !of_has(player->obj_k->flags, rec[i].flag)) || ((rec[i].element >= 0) && (player->obj_k->el_info[rec[i].element].res_level == 0))) { name_attr = COLOUR_SLATE; } Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name)); } Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col + 6); }
/** * Hack -- change name */ void do_cmd_change_name(void) { ui_event ke; int mode = 0; const char *p; bool more = true; /* Prompt */ p = "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"; /* Save screen */ screen_save(); /* Forever */ while (more) { /* Display the player */ display_player(mode); /* Prompt */ Term_putstr(2, 23, -1, COLOUR_WHITE, p); /* Query */ ke = inkey_ex(); if ((ke.type == EVT_KBRD)||(ke.type == EVT_BUTTON)) { switch (ke.key.code) { case ESCAPE: more = false; break; case 'c': { if(arg_force_name) msg("You are not allowed to change your name!"); else { char namebuf[32] = ""; /* Set player name */ if (get_character_name(namebuf, sizeof namebuf)) my_strcpy(player->full_name, namebuf, sizeof(player->full_name)); } break; } case 'f': { char buf[1024]; char fname[80]; /* Get the filesystem-safe name and append .txt */ player_safe_name(fname, sizeof(fname), player->full_name, false); my_strcat(fname, ".txt", sizeof(fname)); if (get_file(fname, buf, sizeof buf)) { if (dump_save(buf)) msg("Character dump successful."); else msg("Character dump failed!"); } break; } case 'h': case ARROW_LEFT: case ' ': mode = (mode + 1) % INFO_SCREENS; break; case 'l': case ARROW_RIGHT: mode = (mode - 1) % INFO_SCREENS; break; } } else if (ke.type == EVT_MOUSE) { if (ke.mouse.button == 1) { /* Flip through the screens */ mode = (mode + 1) % INFO_SCREENS; } else if (ke.mouse.button == 2) { /* exit the screen */ more = false; } else { /* Flip backwards through the screens */ mode = (mode - 1) % INFO_SCREENS; } } /* Flush messages */ event_signal(EVENT_MESSAGE_FLUSH); } /* Load screen */ screen_load(); }
/* * Handle signals -- simple (interrupt and quit) * * This function was causing a *huge* number of problems, so it has * been simplified greatly. We keep a global variable which counts * the number of times the user attempts to kill the process, and * we commit suicide if the user does this a certain number of times. * * We attempt to give "feedback" to the user as he approaches the * suicide thresh-hold, but without penalizing accidental keypresses. * * To prevent messy accidents, we should reset this global variable * whenever the user enters a keypress, or something like that. */ static void handle_signal_simple(int sig) { /* Protect errno from library calls in signal handler */ int save_errno = errno; /* Disable handler */ (void)(*signal_aux)(sig, SIG_IGN); /* Nothing to save, just quit */ if (!character_generated || character_saved) quit(NULL); /* Count the signals */ signal_count++; /* Terminate dead characters */ if (p_ptr->is_dead) { /* Mark the savefile */ my_strcpy(p_ptr->died_from, "Abortion", sizeof(p_ptr->died_from)); close_game(); /* Quit */ quit("interrupt"); } /* Allow suicide (after 5) */ else if (signal_count >= 5) { /* Cause of "death" */ my_strcpy(p_ptr->died_from, "Interrupting", sizeof(p_ptr->died_from)); /* Commit suicide */ p_ptr->is_dead = TRUE; /* Stop playing */ p_ptr->playing = FALSE; /* Leaving */ p_ptr->leaving = TRUE; /* Close stuff */ close_game(); /* Quit */ quit("interrupt"); } /* Give warning (after 4) */ else if (signal_count >= 4) { /* Make a noise */ Term_xtra(TERM_XTRA_NOISE, 0); /* Clear the top line */ Term_erase(0, 0, 255); /* Display the cause */ Term_putstr(0, 0, -1, TERM_WHITE, "Contemplating suicide!"); /* Flush */ Term_fresh(); } /* Give warning (after 2) */ else if (signal_count >= 2) { /* Make a noise */ Term_xtra(TERM_XTRA_NOISE, 0); } /* Restore handler */ (void)(*signal_aux)(sig, handle_signal_simple); /* Restore errno */ errno = save_errno; }
/** * Modify the "window" options */ static void do_cmd_options_win(const char *name, int row) { int i, j, d; int y = 0; int x = 0; ui_event ke; u32b new_flags[ANGBAND_TERM_MAX]; /* Set new flags to the old values */ for (j = 0; j < ANGBAND_TERM_MAX; j++) new_flags[j] = window_flag[j]; /* Clear screen */ screen_save(); clear_from(0); /* Interact */ while (1) { /* Prompt */ prt("Window flags (<dir> to move, 't'/Enter to toggle, or ESC)", 0, 0); /* Display the windows */ for (j = 0; j < ANGBAND_TERM_MAX; j++) { byte a = COLOUR_WHITE; const char *s = angband_term_name[j]; /* Use color */ if (j == x) a = COLOUR_L_BLUE; /* Window name, staggered, centered */ Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s); } /* Display the options */ for (i = 0; i < PW_MAX_FLAGS; i++) { byte a = COLOUR_WHITE; const char *str = window_flag_desc[i]; /* Use color */ if (i == y) a = COLOUR_L_BLUE; /* Unused option */ if (!str) str = "(Unused option)"; /* Flag name */ Term_putstr(0, i + 5, -1, a, str); /* Display the windows */ for (j = 0; j < ANGBAND_TERM_MAX; j++) { char c = '.'; a = COLOUR_WHITE; /* Use color */ if ((i == y) && (j == x)) a = COLOUR_L_BLUE; /* Active flag */ if (new_flags[j] & (1L << i)) c = 'X'; /* Flag value */ Term_putch(35 + j * 5, i + 5, a, c); } } /* Place Cursor */ Term_gotoxy(35 + x * 5, y + 5); /* Get key */ ke = inkey_ex(); /* Mouse or keyboard interaction */ if (ke.type == EVT_MOUSE) { int choicey = ke.mouse.y - 5; int choicex = (ke.mouse.x - 35)/5; if (ke.mouse.button == 2) break; if ((choicey >= 0) && (choicey < PW_MAX_FLAGS) && (choicex > 0) && (choicex < ANGBAND_TERM_MAX) && !(ke.mouse.x % 5)) { if ((choicey == y) && (choicex == x)) { /* Toggle flag (off) */ if (new_flags[x] & (1L << y)) new_flags[x] &= ~(1L << y); /* Toggle flag (on) */ else new_flags[x] |= (1L << y); } else { y = choicey; x = (ke.mouse.x - 35)/5; } } } else if (ke.type == EVT_KBRD) { if (ke.key.code == ESCAPE || ke.key.code == 'q') break; /* Toggle */ else if (ke.key.code == '5' || ke.key.code == 't' || ke.key.code == KC_ENTER) { /* Hack -- ignore the main window */ if (x == 0) bell("Cannot set main window flags!"); /* Toggle flag (off) */ else if (new_flags[x] & (1L << y)) new_flags[x] &= ~(1L << y); /* Toggle flag (on) */ else new_flags[x] |= (1L << y); /* Continue */ continue; } /* Extract direction */ d = target_dir(ke.key); /* Move */ if (d != 0) { x = (x + ddx[d] + 8) % ANGBAND_TERM_MAX; y = (y + ddy[d] + 16) % PW_MAX_FLAGS; } } } /* Notice changes */ subwindows_set_flags(new_flags, ANGBAND_TERM_MAX); screen_load(); }
/* * Display a string on the screen using an attribute. * * At the given location, using the given attribute, if allowed, * add the given string. Do not clear the line. */ void c_put_str(byte attr, const char *str, int row, int col) { /* Position cursor, Dump the attr/text */ Term_putstr(col, row, -1, attr, str); }
static void colors_modify(const char *title, int row) { int i; static byte a = 0; /* Prompt */ prt("Command: Modify colors", 8, 0); /* Hack -- query until done */ while (1) { const char *name; char index; struct keypress cx; /* Clear */ clear_from(10); /* Exhibit the normal colors */ for (i = 0; i < BASIC_COLORS; i++) { /* Exhibit this color */ Term_putstr(i*3, 20, -1, a, "##"); /* Exhibit character letter */ Term_putstr(i*3, 21, -1, (byte)i, format(" %c", color_table[i].index_char)); /* Exhibit all colors */ Term_putstr(i*3, 22, -1, (byte)i, format("%2d", i)); } /* Describe the color */ name = ((a < BASIC_COLORS) ? color_table[a].name : "undefined"); index = ((a < BASIC_COLORS) ? color_table[a].index_char : '?'); /* Describe the color */ Term_putstr(5, 10, -1, COLOUR_WHITE, format("Color = %d, Name = %s, Index = %c", a, name, index)); /* Label the Current values */ Term_putstr(5, 12, -1, COLOUR_WHITE, format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", angband_color_table[a][0], angband_color_table[a][1], angband_color_table[a][2], angband_color_table[a][3])); /* Prompt */ Term_putstr(0, 14, -1, COLOUR_WHITE, "Command (n/N/k/K/r/R/g/G/b/B): "); /* Get a command */ cx = inkey(); /* All done */ if (cx.code == ESCAPE) break; /* Analyze */ if (cx.code == 'n') a = (byte)(a + 1); if (cx.code == 'N') a = (byte)(a - 1); if (cx.code == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1); if (cx.code == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1); if (cx.code == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1); if (cx.code == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1); if (cx.code == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1); if (cx.code == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1); if (cx.code == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1); if (cx.code == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1); /* Hack -- react to changes */ Term_xtra(TERM_XTRA_REACT, 0); /* Hack -- redraw */ Term_redraw(); } }
/* Allow the user to select from the current menu, and return the corresponding command to the game. Some actions are handled entirely by the UI (displaying help text, for instance). */ static enum birth_stage menu_question(enum birth_stage current, menu_type *current_menu, cmd_code choice_command) { struct birthmenu_data *menu_data = menu_priv(current_menu); ui_event cx; enum birth_stage next = BIRTH_RESET; /* Print the question currently being asked. */ clear_question(); Term_putstr(QUESTION_COL, QUESTION_ROW, -1, TERM_YELLOW, menu_data->hint); current_menu->cmd_keys = "?=*\x18"; /* ?, =, *, <ctl-X> */ while (next == BIRTH_RESET) { /* Display the menu, wait for a selection of some sort to be made. */ cx = menu_select(current_menu, EVT_KBRD, FALSE); /* As all the menus are displayed in "hierarchical" style, we allow use of "back" (left arrow key or equivalent) to step back in the proces as well as "escape". */ if (cx.type == EVT_ESCAPE) { next = BIRTH_BACK; } else if (cx.type == EVT_SELECT) { if (current == BIRTH_ROLLER_CHOICE) { cmd_insert(CMD_FINALIZE_OPTIONS); if (current_menu->cursor) { /* Do a first roll of the stats */ cmd_insert(CMD_ROLL_STATS); next = current + 2; } else { /* * Make sure we've got a point-based char to play with. * We call point_based_start here to make sure we get * an update on the points totals before trying to * display the screen. The call to CMD_RESET_STATS * forces a rebuying of the stats to give us up-to-date * totals. This is, it should go without saying, a hack. */ point_based_start(); cmd_insert(CMD_RESET_STATS); cmd_set_arg_choice(cmd_get_top(), 0, TRUE); next = current + 1; } } else { cmd_insert(choice_command); cmd_set_arg_choice(cmd_get_top(), 0, current_menu->cursor); next = current + 1; } } else if (cx.type == EVT_KBRD) { /* '*' chooses an option at random from those the game's provided. */ if (cx.key.code == '*' && menu_data->allow_random) { current_menu->cursor = randint0(current_menu->count); cmd_insert(choice_command); cmd_set_arg_choice(cmd_get_top(), 0, current_menu->cursor); menu_refresh(current_menu, FALSE); next = current + 1; } else if (cx.key.code == '=') { do_cmd_options_birth(); next = current; } else if (cx.key.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (cx.key.code == '?') { do_cmd_help(); } } } return next; }
/* * Output a message to the top line of the screen. * * Break long messages into multiple pieces (40-72 chars). * * Allow multiple short messages to "share" the top line. * * Prompt the user to make sure he has a chance to read them. * * These messages are memorized for later reference (see above). * * We could do a "Term_fresh()" to provide "flicker" if needed. * * The global "msg_flag" variable can be cleared to tell us to "erase" any * "pending" messages still on the screen, instead of using "msg_flush()". * This should only be done when the user is known to have read the message. * * We must be very careful about using the "msg("%s", )" functions without * explicitly calling the special "msg("%s", NULL)" function, since this may * result in the loss of information if the screen is cleared, or if anything * is displayed on the top line. * * Hack -- Note that "msg("%s", NULL)" will clear the top line even if no * messages are pending. */ static void msg_print_aux(u16b type, const char *msg) { int n; char *t; char buf[1024]; byte color; int w, h; if (!Term) return; /* Obtain the size */ (void)Term_get_size(&w, &h); /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Message Length */ n = (msg ? strlen(msg) : 0); /* Hack -- flush when requested or needed */ if (message_column && (!msg || ((message_column + n) > (w - 8)))) { /* Flush */ msg_flush(message_column); /* Forget it */ msg_flag = FALSE; /* Reset */ message_column = 0; } /* No message */ if (!msg) return; /* Paranoia */ if (n > 1000) return; /* Memorize the message (if legal) */ if (character_generated && !(p_ptr->is_dead)) message_add(msg, type); /* Window stuff */ p_ptr->redraw |= (PR_MESSAGE); /* Copy it */ my_strcpy(buf, msg, sizeof(buf)); /* Analyze the buffer */ t = buf; /* Get the color of the message */ color = message_type_color(type); /* Split message */ while (n > w - 1) { char oops; int check, split; /* Default split */ split = w - 8; /* Find the rightmost split point */ for (check = (w / 2); check < w - 8; check++) if (t[check] == ' ') split = check; /* Save the split character */ oops = t[split]; /* Split the message */ t[split] = '\0'; /* Display part of the message */ Term_putstr(0, 0, split, color, t); /* Flush it */ msg_flush(split + 1); /* Restore the split character */ t[split] = oops; /* Insert a space */ t[--split] = ' '; /* Prepare to recurse on the rest of "buf" */ t += split; n -= split; } /* Display the tail of the message */ Term_putstr(message_column, 0, n, color, t); /* Remember the message */ msg_flag = TRUE; /* Remember the position */ message_column += n + 1; /* Send refresh event */ event_signal(EVENT_MESSAGE); }
/* * Show previous messages to the user -BEN- * * The screen format uses line 0 and 23 for headers and prompts, * skips line 1 and 22, and uses line 2 thru 21 for old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. * * Note that messages may be longer than 80 characters, but they are * displayed using "infinite" length, with a special sub-command to * "slide" the virtual display to the left or right. * * Attempt to only hilite the matching portions of the string. */ void do_cmd_messages(void) { int i, j, k, n, q; char shower[80] = ""; char finder[80] = ""; /* Total messages */ n = message_num(); /* Start on first message */ i = 0; /* Start at leftmost edge */ q = 0; /* Enter "icky" mode */ screen_icky = topline_icky = TRUE; /* Save the screen */ Term_save(); /* Process requests until done */ while (1) { /* Clear screen */ Term_clear(); /* Dump up to 20 lines of messages */ for (j = 0; (j < 20) && (i + j < n); j++) { byte a = TERM_WHITE; cptr str = message_str(i+j); /* Determine color */ message_color(str, &a); /* Apply horizontal scroll */ str = (strlen(str) >= q) ? (str + q) : ""; /* Handle "shower" */ if (shower[0] && strstr(str, shower)) a = TERM_YELLOW; /* Dump the messages, bottom to top */ Term_putstr(0, 21-j, -1, a, str); } /* Display header XXX XXX XXX */ prt(format("Message Recall (%d-%d of %d), Offset %d", i, i+j-1, n, q), 0, 0); /* Display prompt (not very informative) */ prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 23, 0); /* Get a command */ k = inkey(); /* Exit on Escape */ if (k == ESCAPE) break; /* Hack -- Save the old index */ j = i; /* Horizontal scroll */ if (k == '4') { /* Scroll left */ q = (q >= 40) ? (q - 40) : 0; /* Success */ continue; } /* Horizontal scroll */ if (k == '6') { /* Scroll right */ q = q + 40; /* Success */ continue; } /* Hack -- handle show */ if (k == '=') { /* Prompt */ prt("Show: ", 23, 0); /* Get a "shower" string, or continue */ if (!askfor_aux(shower, 80, 0)) continue; /* Okay */ continue; } /* Hack -- handle find */ if (k == '/') { int z; /* Prompt */ prt("Find: ", 23, 0); /* Get a "finder" string, or continue */ if (!askfor_aux(finder, 80, 0)) continue; /* Scan messages */ for (z = i + 1; z < n; z++) { cptr str = message_str(z); /* Handle "shower" */ if (strstr(str, finder)) { /* New location */ i = z; /* Done */ break; } } } /* Recall 1 older message */ if ((k == '8') || (k == '\n') || (k == '\r')) { /* Go newer if legal */ if (i + 1 < n) i += 1; } /* Recall 10 older messages */ if (k == '+') { /* Go older if legal */ if (i + 10 < n) i += 10; } /* Recall 20 older messages */ if ((k == 'p') || (k == KTRL('P')) || (k == ' ')) { /* Go older if legal */ if (i + 20 < n) i += 20; } /* Recall 20 newer messages */ if ((k == 'n') || (k == KTRL('N'))) { /* Go newer (if able) */ i = (i >= 20) ? (i - 20) : 0; } /* Recall 10 newer messages */ if (k == '-') { /* Go newer (if able) */ i = (i >= 10) ? (i - 10) : 0; } /* Recall 1 newer messages */ if (k == '2') { /* Go newer (if able) */ i = (i >= 1) ? (i - 1) : 0; } /* Hack -- Error of some kind */ if (i == j) bell(); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ screen_icky = topline_icky = FALSE; /* Flush any queued events */ Flush_queue(); }
/* * As above, but in "white" */ void put_str(const char *str, int row, int col) { /* Spawn */ Term_putstr(col, row, -1, TERM_WHITE, str); }
static void display_resistance_panel(const struct player_flag_record *rec, size_t size, const region *bounds) { size_t i; int j; int col = bounds->col; int row = bounds->row; int res_cols = 5 + 2 + player->body.count; Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); for (i = 0; i < size - 3; i++, row++) { byte name_attr = COLOUR_WHITE; Term_gotoxy(col + 6, row); /* Repeated extraction of flags is inefficient but more natural */ for (j = 0; j <= player->body.count; j++) { struct object *obj; bitflag f[OF_SIZE]; byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res = false, imm = false, vul = false, rune = false; bool timed = false; bool known = false; /* Wipe flagset */ of_wipe(f); /* Get the object or player info */ obj = j < player->body.count ? slot_object(player, j) : NULL; if (j < player->body.count && obj) { /* Get known properties */ object_flags_known(obj, f); if (rec[i].element != -1) known = object_element_is_known(obj, rec[i].element); else if (rec[i].flag != -1) known = object_flag_is_known(obj, rec[i].flag); else known = true; } else if (j == player->body.count) { player_flags(player, f); known = true; /* Timed flags only in the player column */ if (rec[i].tmd_flag >= 0) { timed = player->timed[rec[i].tmd_flag] ? true : false; /* There has to be one special case... */ if ((rec[i].tmd_flag == TMD_AFRAID) && (player->timed[TMD_TERROR])) timed = true; } } /* Set which (if any) symbol and color are used */ if (rec[i].mod != -1) { if (j != player->body.count) res = (obj && (obj->modifiers[rec[i].mod] != 0)); else { /* Messy special cases */ if (rec[i].mod == OBJ_MOD_INFRA) res = (player->race->infra > 0); if (rec[i].mod == OBJ_MOD_TUNNEL) res = (player->race->r_skills[SKILL_DIGGING] > 0); } rune = (player->obj_k->modifiers[rec[i].mod] == 1); } else if (rec[i].flag != -1) { res = of_has(f, rec[i].flag); rune = of_has(player->obj_k->flags, rec[i].flag); } else if (rec[i].element != -1) { if (j != player->body.count) { imm = obj && known && (obj->el_info[rec[i].element].res_level == 3); res = obj && known && (obj->el_info[rec[i].element].res_level == 1); vul = obj && known && (obj->el_info[rec[i].element].res_level == -1); } else { imm = player->race->el_info[rec[i].element].res_level == 3; res = player->race->el_info[rec[i].element].res_level == 1; vul = player->race->el_info[rec[i].element].res_level == -1; } rune = (player->obj_k->el_info[rec[i].element].res_level == 1); } /* Set the symbols and print them */ if (imm) name_attr = COLOUR_GREEN; else if (!rune) name_attr = COLOUR_SLATE; else if (res && (name_attr != COLOUR_GREEN)) name_attr = COLOUR_L_BLUE; if (vul) sym = '-'; else if (imm) sym = '*'; else if (res) sym = '+'; else if (timed) { sym = '!'; attr = COLOUR_L_GREEN; } else if ((j < player->body.count) && obj && !known && !rune) sym = '?'; Term_addch(attr, sym); } Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name)); } Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col + 6); }