/** * Examine an object */ void textui_obj_examine(void) { char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; struct object *obj; /* Select item */ if (!get_item(&obj, "Examine which item?", "You have nothing to examine.", CMD_NULL, NULL, (USE_EQUIP | USE_INVEN | USE_QUIVER | USE_FLOOR | IS_HARMLESS))) return; /* Track object for object recall */ track_object(player->upkeep, obj); /* Display info */ tb = object_info(obj, OINFO_NONE); object_desc(header, sizeof(header), obj, ODESC_PREFIX | ODESC_FULL | ODESC_CAPITAL); textui_textblock_show(tb, area, header); textblock_free(tb); }
/* Examine an object */ void textui_obj_examine(void) { char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; object_type *o_ptr; int item; /* Select item */ if (!get_item(&item, "Examine which item?", "You have nothing to examine.", CMD_NULL, (USE_EQUIP | USE_INVEN | USE_FLOOR | IS_HARMLESS))) return; /* Track object for object recall */ track_object(item); /* Display info */ o_ptr = object_from_item_idx(item); tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%^s", header)); textblock_free(tb); }
void passthrough_cleanup(void) { if (!passthrough) return; textblock_free(); }
/** * Provide information on an item suitable for writing to the character dump * - keep it brief. */ void object_info_chardump(ang_file *f, const struct object *obj, int indent, int wrap) { textblock *tb = object_info_out(obj, OINFO_TERSE | OINFO_SUBJ); textblock_to_file(tb, f, indent, wrap); textblock_free(tb); }
/* * Show artifact lore */ static void desc_art_fake(int a_idx) { object_type *o_ptr; object_type object_type_body = { 0 }; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; o_ptr = find_artifact(a_idx); /* If it's been lost, make a fake artifact for it */ if (!o_ptr) { o_ptr = &object_type_body; make_fake_artifact(o_ptr, a_idx); /* Check the history entry, to see if it was fully known * before it was lost */ if (history_is_artifact_known(a_idx)) { o_ptr->ident |= IDENT_KNOWN; } } /* Hack -- Handle stuff */ handle_stuff(p_ptr); tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL | ODESC_CAPITAL); textui_textblock_show(tb, area, format("%s", header)); textblock_free(tb); }
/** * Display the monster list statically. This will force the list to be * displayed to the provided dimensions. Contents will be adjusted accordingly. * * In order to support more efficient monster flicker animations, this function * uses a shared list object so that it's not constantly allocating and freeing * the list. * * \param height is the height of the list. * \param width is the width of the list. */ void monster_list_show_subwindow(int height, int width) { textblock *tb; monster_list_t *list; int i; if (height < 1 || width < 1) return; tb = textblock_new(); list = monster_list_shared_instance(); /* Force an update if detected monsters */ for (i = 1; i < cave_monster_max(cave); i++) { if (mflag_has(cave_monster(cave, i)->mflag, MFLAG_MARK)) { list->creation_turn = -1; break; } } monster_list_reset(list); monster_list_collect(list); monster_list_get_glyphs(list); monster_list_sort(list, monster_list_standard_compare); /* Draw the list to exactly fit the subwindow. */ monster_list_format_textblock(list, tb, height, width, NULL, NULL); textui_textblock_place(tb, SCREEN_REGION, NULL); textblock_free(tb); }
/** * Provide information on an item suitable for writing to the character dump - keep it brief. */ void object_info_chardump(const object_type *o_ptr, char_attr_line **line, int *current_line, int indent, int wrap) { textblock *tb = object_info_out(o_ptr, OINFO_TERSE | OINFO_SUBJ); textblock_dump(tb, line, current_line, indent, wrap); textblock_free(tb); }
/* * Menu command: examine items in the inventory. */ static void death_examine(const char *title, int row) { int item; const char *q, *s; /* Get an item */ q = "Examine which item? "; s = "You have nothing to examine."; while (get_item(&item, q, s, 0, (USE_INVEN | USE_EQUIP | IS_HARMLESS))) { char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; object_type *o_ptr = &p_ptr->inventory[item]; tb = object_info(o_ptr, OINFO_FULL); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%^s", header)); textblock_free(tb); } }
/** * This draws the Object Recall subwindow when displaying a particular object * (e.g. a helmet in the backpack, or a scroll on the ground) */ void display_object_recall(struct object *obj) { char header_buf[120]; textblock *tb = object_info(obj, OINFO_NONE); object_desc(header_buf, sizeof(header_buf), obj, ODESC_PREFIX | ODESC_FULL); clear_from(0); textui_textblock_place(tb, SCREEN_REGION, header_buf); textblock_free(tb); }
/** * Display monster recall modally and wait for a keypress. * * This is intended to be called when the main window is active (hence the * message flushing). * * \param race is the monster race we are describing. * \param lore is the known information about the monster race. */ void lore_show_interactive(const monster_race *race, const monster_lore *lore) { textblock *tb; assert(race && lore); event_signal(EVENT_MESSAGE_FLUSH); tb = textblock_new(); lore_description(tb, race, lore, FALSE); textui_textblock_show(tb, SCREEN_REGION, NULL); textblock_free(tb); }
int main(int argc, char **argv) { token_t t; fpo = stdout; mbox_mode = true; /* to allow multiple messages */ process_arglist(argc, argv); process_config_files(false, longopts_bogolexer); if (encoding == E_UNKNOWN) encoding = E_DEFAULT; textblock_init(); if (!passthrough) { if (quiet) fprintf(fpo, "quiet mode.\n"); else fprintf(fpo, "normal mode.\n"); } bogoreader_init(argc, (const char * const *) argv); while ((*reader_more)()) { word_t token; lexer_init(); while ((t = get_token( &token )) != NONE) { count += 1; if (passthrough) { fprintf(fpo, "%s\n", token.u.text); } else if (!quiet) fprintf(fpo, "get_token: %d \"%s\"\n", (int)t, token.u.text); } } if ( !passthrough ) fprintf(fpo, "%d tokens read.\n", count); /* cleanup storage */ token_cleanup(); mime_cleanup(); textblock_free(); MEMDISPLAY; return 0; }
/** * Display object recall modally and wait for a keypress. * * This is set up for use in look mode (see target_set_interactive_aux()). * * \param obj is the object to be described. */ void display_object_recall_interactive(struct object *obj) { char header_buf[120]; textblock *tb; event_signal(EVENT_MESSAGE_FLUSH); tb = object_info(obj, OINFO_NONE); object_desc(header_buf, sizeof(header_buf), obj, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, SCREEN_REGION, header_buf); textblock_free(tb); }
void passthrough_cleanup() { if (!passthrough) return; switch(passmode) { case PASS_MEM: textblock_free(); break; case PASS_SEEK: default: break; } }
/* * Describe fake ego item "lore" */ static void desc_ego_fake(int oid) { int e_idx = default_join[oid].oid; ego_item_type *ego = &e_info[e_idx]; textblock *tb; region area = { 0, 0, 0, 0 }; /* List ego flags */ tb = object_info_ego(ego); textui_textblock_show(tb, area, format("%s %s", ego_grp_name(default_group(oid)), ego->name)); textblock_free(tb); }
/** * Display the monster list interactively. This will dynamically size the list * for the best appearance. This should only be used in the main term. * * \param height is the height limit for the list. * \param width is the width limit for the list. */ void monster_list_show_interactive(int height, int width) { textblock *tb; monster_list_t *list; size_t max_width = 0, max_height = 0; int safe_height, safe_width; region r; if (height < 1 || width < 1) return; tb = textblock_new(); list = monster_list_new(); monster_list_collect(list); monster_list_get_glyphs(list); monster_list_sort(list, monster_list_standard_compare); /* Figure out optimal display rect. Large numbers are passed as the height * and width limit so that we can calculate the maximum number of rows and * columns to display the list nicely. We then adjust those values as * needed to fit in the main term. Height is adjusted to account for the * texblock prompt. The list is positioned on the right side of the term * underneath the status line. */ monster_list_format_textblock(list, NULL, 1000, 1000, &max_height, &max_width); safe_height = MIN(height - 2, (int)max_height + 2); safe_width = MIN(width - 13, (int)max_width); r.col = -safe_width; r.row = 1; r.width = safe_width; r.page_rows = safe_height; /* * Actually draw the list. We pass in max_height to the format function so * that all lines will be appended to the textblock. The textblock itself * will handle fitting it into the region. However, we have to pass * safe_width so that the format function will pad the lines properly so * that the location string is aligned to the right edge of the list. */ monster_list_format_textblock(list, tb, (int)max_height, safe_width, NULL, NULL); region_erase_bordered(&r); textui_textblock_show(tb, r, NULL); textblock_free(tb); monster_list_free(list); }
/*** Examination ***/ void textui_obj_examine(object_type *o_ptr, int item) { char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; track_object(item); tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%^s", header)); textblock_free(tb); }
/* * Describe fake object */ static void desc_obj_fake(int k_idx) { object_kind *k_ptr = &k_info[k_idx]; object_type object_type_body; object_type *o_ptr = &object_type_body; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; /* Check for known artifacts, display them as artifacts */ if (kf_has(k_ptr->flags_kind, KF_INSTA_ART) && artifact_is_known(get_artifact_from_kind(k_ptr))) { desc_art_fake(get_artifact_from_kind(k_ptr)); return; } /* Update the object recall window */ track_object_kind(k_idx); handle_stuff(p_ptr); /* Wipe the object */ object_wipe(o_ptr); /* Create the artifact */ object_prep(o_ptr, k_idx, EXTREMIFY); /* Hack -- its in the store */ if (k_info[k_idx].aware) o_ptr->ident |= (IDENT_STORE); /* It's fully know */ if (!k_info[k_idx].flavor) object_known(o_ptr); /* Hack -- Handle stuff */ handle_stuff(p_ptr); /* Describe */ tb = object_info(o_ptr, OINFO_DUMMY); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL | ODESC_CAPITAL); textui_textblock_show(tb, area, format("%s", header)); textblock_free(tb); }
/** * Display monster recall statically. * * This is intended to be called in a subwindow, since it clears the entire * window before drawing, and has no interactivity. * * \param race is the monster race we are describing. * \param lore is the known information about the monster race. */ void lore_show_subwindow(const monster_race *race, const monster_lore *lore) { int y; textblock *tb; assert(race && lore); /* Erase the window, since textui_textblock_place() only clears what it * needs */ for (y = 0; y < Term->hgt; y++) Term_erase(0, y, 255); tb = textblock_new(); lore_description(tb, race, lore, FALSE); textui_textblock_place(tb, SCREEN_REGION, NULL); textblock_free(tb); }
/** * Display the object list statically. This will force the list to be displayed * to the provided dimensions. Contents will be adjusted accordingly. * * In order to be more efficient, this function uses a shared list object so * that it's not constantly allocating and freeing the list. * * \param height is the height of the list. * \param width is the width of the list. */ void object_list_show_subwindow(int height, int width) { textblock *tb; object_list_t *list; if (height < 1 || width < 1) return; tb = textblock_new(); list = object_list_shared_instance(); object_list_reset(list); object_list_collect(list); object_list_sort(list, object_list_standard_compare); /* Draw the list to exactly fit the subwindow. */ object_list_format_textblock(list, tb, height, width, NULL, NULL); textui_textblock_place(tb, SCREEN_REGION, NULL); textblock_free(tb); }
/* * Show artifact lore */ static void desc_art_fake(int a_idx) { object_type *o_ptr; object_type object_type_body = { 0 }; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; o_ptr = find_artifact(&a_info[a_idx]); /* If it's been lost, make a fake artifact for it */ if (!o_ptr) { o_ptr = &object_type_body; make_fake_artifact(o_ptr, &a_info[a_idx]); o_ptr->ident |= IDENT_NAME; /* Check the history entry, to see if it was fully known before it * was lost */ if (history_is_artifact_known(o_ptr->artifact)) object_notice_everything(o_ptr); } /* Hack -- Handle stuff */ handle_stuff(p_ptr); tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%^s", header)); textblock_free(tb); #if 0 /* XXX This should be in object_info */ if (lost) text_out("\nThis artifact has been lost."); #endif }
/** * Menu command: examine items in the inventory. */ static void death_examine(const char *title, int row) { struct object *obj; const char *q, *s; /* Get an item */ q = "Examine which item? "; s = "You have nothing to examine."; while (get_item(&obj, q, s, 0, NULL, (USE_INVEN | USE_QUIVER | USE_EQUIP | IS_HARMLESS))) { char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; tb = object_info(obj, OINFO_NONE); object_desc(header, sizeof(header), obj, ODESC_PREFIX | ODESC_FULL | ODESC_CAPITAL); textui_textblock_show(tb, area, header); textblock_free(tb); } }
int edit_text(char *buffer, int buflen) { int len = strlen(buffer); bool done = FALSE; int cursor = 0; while (!done) { int x, y; struct keypress ke; region area = { 1, HIST_INSTRUCT_ROW + 1, 71, 5 }; textblock *tb = textblock_new(); size_t *line_starts = NULL, *line_lengths = NULL; size_t n_lines; /* Display on screen */ clear_from(HIST_INSTRUCT_ROW); textblock_append(tb, buffer); textblock_append(tb, "\n"); /* XXX This shouldn't be necessary */ textui_textblock_place(tb, area, NULL); n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, area.width); /* Set cursor to current editing position */ get_screen_loc(cursor, &x, &y, n_lines, line_starts, line_lengths); Term_gotoxy(1 + x, 19 + y); ke = inkey(); switch (ke.code) { case ESCAPE: return -1; case KC_ENTER: done = TRUE; break; case ARROW_LEFT: if (cursor > 0) cursor--; break; case ARROW_RIGHT: if (cursor < len) cursor++; break; case ARROW_DOWN: { int add = line_lengths[y] + 1; if (cursor + add < len) cursor += add; break; } case ARROW_UP: if (y > 0) { int up = line_lengths[y - 1] + 1; if (cursor - up >= 0) cursor -= up; } break; case KC_END: cursor = MAX(0, len); break; case KC_HOME: cursor = 0; break; case KC_BACKSPACE: case KC_DELETE: { /* Refuse to backspace into oblivion */ if ((ke.code == KC_BACKSPACE && cursor == 0) || (ke.code == KC_DELETE && cursor >= len)) break; /* Move the string from k to nul along to the left by 1 */ if (ke.code == KC_BACKSPACE) memmove(&buffer[cursor - 1], &buffer[cursor], len - cursor); else memmove(&buffer[cursor], &buffer[cursor + 1], len - cursor - 1); /* Decrement */ if (ke.code == KC_BACKSPACE) cursor--; len--; /* Terminate */ buffer[len] = '\0'; break; } default: { bool atnull = (buffer[cursor] == 0); if (!isprint(ke.code)) break; if (atnull) { /* Make sure we have enough room for a new character */ if ((cursor + 1) >= buflen) break; } else { /* Make sure we have enough room to add a new character */ if ((cursor + 1) >= buflen) break; /* Move the rest of the buffer along to make room */ memmove(&buffer[cursor + 1], &buffer[cursor], len - cursor); } /* Insert the character */ buffer[cursor++] = (char)ke.code; len++; /* Terminate */ buffer[len] = '\0'; break; } } textblock_free(tb); } return 0; }
/** * Provide spoiler information on an item. * * Practically, this means that we should not print anything which relies upon * the player's current state, since that is not suitable for spoiler material. */ void object_info_spoil(ang_file *f, const object_type *o_ptr, int wrap) { textblock *tb = object_info_out(o_ptr, OINFO_FULL); textblock_to_file(tb, f, 0, wrap); textblock_free(tb); }
/* pick the context menu options appropiate for the item */ int context_menu_object(const object_type *o_ptr, const int slot) { menu_type *m; region r; int selected; char *labels; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; bool allowed = TRUE; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; unsigned char cmdkey; m = menu_dynamic_new(); if (!m || !o_ptr) { return 0; } object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE); labels = string_make(lower_case); m->selections = labels; /* 'I' is used for inspect in both keymaps. */ menu_dynamic_add_label(m, "Inspect", 'I', MENU_VALUE_INSPECT, labels); if (obj_can_browse(o_ptr)) { if (obj_can_cast_from(o_ptr) && player_can_cast(p_ptr, FALSE)) { ADD_LABEL("Cast", CMD_CAST, MN_ROW_VALID); } if (obj_can_study(o_ptr) && player_can_study(p_ptr, FALSE)) { cmd_code study_cmd = player_has(PF_CHOOSE_SPELLS) ? CMD_STUDY_SPELL : CMD_STUDY_BOOK; /* Hack - Use the STUDY_BOOK command key so that we get the correct command key. */ cmdkey = cmd_lookup_key_unktrl(CMD_STUDY_BOOK, mode); menu_dynamic_add_label(m, "Study", cmdkey, study_cmd, labels); } if (player_can_read(p_ptr, FALSE)) { ADD_LABEL("Browse", CMD_BROWSE_SPELL, MN_ROW_VALID); } } else if (obj_is_useable(o_ptr)) { if (obj_is_wand(o_ptr)) { menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Aim", CMD_USE_WAND, valid); } else if (obj_is_rod(o_ptr)) { menu_row_validity_t valid = (obj_can_zap(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Zap", CMD_USE_ROD, valid); } else if (obj_is_staff(o_ptr)) { menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Use", CMD_USE_STAFF, valid); } else if (obj_is_scroll(o_ptr)) { menu_row_validity_t valid = (player_can_read(p_ptr, FALSE)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Read", CMD_READ_SCROLL, valid); } else if (obj_is_potion(o_ptr)) { ADD_LABEL("Quaff", CMD_QUAFF, MN_ROW_VALID); } else if (obj_is_food(o_ptr)) { ADD_LABEL("Eat", CMD_EAT, MN_ROW_VALID); } else if (obj_is_activatable(o_ptr)) { menu_row_validity_t valid = (slot >= INVEN_WIELD && obj_can_activate(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Activate", CMD_ACTIVATE, valid); } else if (obj_can_fire(o_ptr)) { ADD_LABEL("Fire", CMD_FIRE, MN_ROW_VALID); } else { ADD_LABEL("Use", CMD_USE_ANY, MN_ROW_VALID); } } if (obj_can_refill(o_ptr)) { ADD_LABEL("Refill", CMD_REFILL, MN_ROW_VALID); } if (slot >= INVEN_WIELD && obj_can_takeoff(o_ptr)) { ADD_LABEL("Take off", CMD_TAKEOFF, MN_ROW_VALID); } else if (slot < INVEN_WIELD && obj_can_wear(o_ptr)) { //if (obj_is_armor(o_ptr)) { // menu_dynamic_add(m, "Wear", 2); //} else { // menu_dynamic_add(m, "Wield", 2); //} ADD_LABEL("Equip", CMD_WIELD, MN_ROW_VALID); } if (slot >= 0) { if (!store_in_store || cave_shopnum(cave, p_ptr->py, p_ptr->px) == STORE_HOME) { ADD_LABEL("Drop", CMD_DROP, MN_ROW_VALID); if (o_ptr->number > 1) { /* 'D' is used for squelch in rogue keymap, so we'll just swap letters. */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'D' : 'k'; menu_dynamic_add_label(m, "Drop All", cmdkey, MENU_VALUE_DROP_ALL, labels); } } } else { menu_row_validity_t valid = (inven_carry_okay(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Pick up", CMD_PICKUP, valid); } ADD_LABEL("Throw", CMD_THROW, MN_ROW_VALID); ADD_LABEL("Inscribe", CMD_INSCRIBE, MN_ROW_VALID); if (obj_has_inscrip(o_ptr)) { ADD_LABEL("Uninscribe", CMD_UNINSCRIBE, MN_ROW_VALID); } ADD_LABEL( (object_is_squelched(o_ptr) ? "Unignore" : "Ignore"), CMD_DESTROY, MN_ROW_VALID); /* work out display region */ r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ r.col = Term->wid - r.width - 1; r.row = 1; r.page_rows = m->count; area.width = -(r.width + 2); /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); /* Display info */ tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_place(tb, area, format("%s", header)); textblock_free(tb); menu_layout(m, &r); region_erase_bordered(&r); prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); screen_load(); cmdkey = cmd_lookup_key(selected, mode); switch (selected) { case -1: /* User cancelled the menu. */ return 3; case MENU_VALUE_INSPECT: /* copied from textui_obj_examine */ /* Display info */ tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%s", header)); textblock_free(tb); return 2; case MENU_VALUE_DROP_ALL: /* Drop entire stack with confirmation. */ if (get_check(format("Drop %s? ", header))) { cmd_insert(store_in_store ? CMD_STASH : CMD_DROP); cmd_set_arg_item(cmd_get_top(), 0, slot); cmd_set_arg_number(cmd_get_top(), 1, o_ptr->number); } return 1; case CMD_STUDY_SPELL: /* Hack - Use the STUDY_BOOK command key so that get_item_allow() works properly. */ cmdkey = cmd_lookup_key(CMD_STUDY_BOOK, mode); /* Fall through. */ case CMD_BROWSE_SPELL: case CMD_STUDY_BOOK: case CMD_CAST: case CMD_DESTROY: case CMD_WIELD: case CMD_TAKEOFF: case CMD_INSCRIBE: case CMD_UNINSCRIBE: case CMD_PICKUP: case CMD_DROP: case CMD_REFILL: case CMD_THROW: case CMD_USE_WAND: case CMD_USE_ROD: case CMD_USE_STAFF: case CMD_READ_SCROLL: case CMD_QUAFF: case CMD_EAT: case CMD_ACTIVATE: case CMD_FIRE: case CMD_USE_ANY: /* Check for inscriptions that trigger confirmation. */ allowed = key_confirm_command(cmdkey) && get_item_allow(slot, cmdkey, selected, FALSE); break; default: /* Invalid command; prevent anything from happening. */ bell("Invalid context menu command."); allowed = FALSE; break; } if (!allowed) return 1; if (selected == CMD_DESTROY) { /* squelch or unsquelch the item */ textui_cmd_destroy_menu(slot); } else if (selected == CMD_BROWSE_SPELL) { /* browse a spellbook */ /* copied from textui_spell_browse */ textui_book_browse(o_ptr); return 2; } else if (selected == CMD_STUDY_SPELL) { /* study a spell book */ /* copied from textui_obj_study */ int spell = get_spell(o_ptr, "study", spell_okay_to_study); if (spell >= 0) { cmd_insert(CMD_STUDY_SPELL); cmd_set_arg_choice(cmd_get_top(), 0, spell); } } else if (selected == CMD_CAST) { if (obj_can_browse(o_ptr)) { /* copied from textui_obj_cast */ const char *verb = ((p_ptr->class->spell_book == TV_MAGIC_BOOK) ? "cast" : "recite"); int spell = get_spell(o_ptr, verb, spell_okay_to_cast); if (spell >= 0) { cmd_insert(CMD_CAST); cmd_set_arg_choice(cmd_get_top(), 0, spell); } } } else {
/** * Provide spoiler information on an item. * * Practically, this means that we should not print anything which relies upon * the player's current state, since that is not suitable for spoiler material. */ void object_info_spoil(ang_file *f, const struct object *obj, int wrap) { textblock *tb = object_info_out(obj, OINFO_NONE); textblock_to_file(tb, f, 0, wrap); textblock_free(tb); }
/** * Create a spoiler file for monsters (-SHAWN-) */ static void spoil_mon_info(const char *fname) { char buf[1024]; int i, n; u16b *who; int count = 0; textblock *tb = NULL; /* Open the file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump the header */ tb = textblock_new(); textblock_append(tb, "Monster Spoilers for %s\n", buildid); textblock_append(tb, "------------------------------------------\n\n"); textblock_to_file(tb, fh, 0, 75); textblock_free(tb); tb = NULL; /* Allocate the "who" array */ who = mem_zalloc(z_info->r_max * sizeof(u16b)); /* Scan the monsters */ for (i = 1; i < z_info->r_max; i++) { struct monster_race *race = &r_info[i]; /* Use that monster */ if (race->name) who[count++] = (u16b)i; } sort(who, count, sizeof(*who), cmp_monsters); /* List all monsters in order. */ for (n = 0; n < count; n++) { int r_idx = who[n]; const struct monster_race *race = &r_info[r_idx]; const struct monster_lore *lore = &l_list[r_idx]; tb = textblock_new(); /* Line 1: prefix, name, color, and symbol */ if (rf_has(race->flags, RF_QUESTOR)) textblock_append(tb, "[Q] "); else if (rf_has(race->flags, RF_UNIQUE)) textblock_append(tb, "[U] "); else textblock_append(tb, "The "); /* As of 3.5, race->name and race->text are stored as UTF-8 strings; * there is no conversion from the source edit files. */ textblock_append_utf8(tb, race->name); textblock_append(tb, " ("); /* ---)--- */ textblock_append(tb, attr_to_text(race->d_attr)); textblock_append(tb, " '%c')\n", race->d_char); /* Line 2: number, level, rarity, speed, HP, AC, exp */ textblock_append(tb, "=== "); textblock_append(tb, "Num:%d ", r_idx); textblock_append(tb, "Lev:%d ", race->level); textblock_append(tb, "Rar:%d ", race->rarity); if (race->speed >= 110) textblock_append(tb, "Spd:+%d ", (race->speed - 110)); else textblock_append(tb, "Spd:-%d ", (110 - race->speed)); textblock_append(tb, "Hp:%d ", race->avg_hp); textblock_append(tb, "Ac:%d ", race->ac); textblock_append(tb, "Exp:%ld\n", (long)(race->mexp)); /* Normal description (with automatic line breaks) */ lore_description(tb, race, lore, true); textblock_append(tb, "\n"); textblock_to_file(tb, fh, 0, 75); textblock_free(tb); tb = NULL; } /* Free the "who" array */ mem_free(who); /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } msg("Successfully created a spoiler file."); }