3 * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
6 * Copyright (c) 2002 Mogami\n
8 * This software may be copied and distributed for educational, research, and\n
9 * not for profit purposes provided that this copyright and statement are\n
10 * included in all such copies.\n
11 * 2014 Deskull rearranged comment for Doxygen.\n
16 #include "autopick/autopick-commands-table.h"
17 #include "autopick/autopick-dirty-flags.h"
18 #include "autopick/autopick-flags-table.h"
19 #include "autopick/autopick-initializer.h"
20 #include "autopick/autopick-key-flag-process.h"
21 #include "autopick/autopick-menu-data-table.h"
22 #include "autopick/autopick-methods-table.h"
23 #include "autopick/autopick-destroyer.h"
24 #include "autopick/autopick-entry.h"
25 #include "autopick/autopick-reader-writer.h"
26 #include "autopick/autopick-finder.h"
27 #include "autopick/autopick-adder.h"
28 #include "autopick/autopick-drawer.h"
29 #include "autopick/autopick-searcher.h"
30 #include "autopick/autopick-inserter-killer.h"
32 #include "autopick/autopick.h"
33 #include "core/show-file.h"
34 #include "cmd/cmd-save.h"
35 #include "io/read-pref-file.h"
39 #include "market/store.h"
40 #include "player-move.h"
41 #include "player-class.h"
42 #include "player-race.h"
43 #include "view/display-player.h" // 暫定。後で消す.
44 #include "object/object-kind.h"
45 #include "object-flavor.h"
46 #include "object-hook.h"
49 #include "view/display-main-window.h" // 暫定。後で消す.
52 * Auto-destroy marked item
54 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
57 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
59 if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return;
61 GAME_TEXT o_name[MAX_NLEN];
62 object_desc(player_ptr, o_name, o_ptr, 0);
65 inven_item_increase(player_ptr, item, -(o_ptr->number));
66 inven_item_optimize(player_ptr, item);
70 delete_object_idx(player_ptr, 0 - item);
73 msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
78 * Auto-destroy marked items in inventry and on floor
80 void autopick_delayed_alter(player_type *owner_ptr)
85 * Scan inventry in reverse order to prevent
86 * skipping after inven_item_optimize()
88 for (item = INVEN_TOTAL - 1; item >= 0; item--)
89 autopick_delayed_alter_aux(owner_ptr, item);
91 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
92 item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
95 OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
96 autopick_delayed_alter_aux(owner_ptr, -item);
103 * Auto-inscription and/or destroy
105 * Auto-destroyer works only on inventory or on floor stack only when
108 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
111 o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
112 int idx = find_autopick_list(player_ptr, o_ptr);
113 auto_inscribe_item(player_ptr, o_ptr, idx);
114 if (destroy && item <= INVEN_PACK)
115 auto_destroy_item(player_ptr, o_ptr, idx);
120 * Automatically pickup/destroy items in this grid.
122 void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr)
124 OBJECT_IDX this_o_idx, next_o_idx = 0;
125 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
127 object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
128 next_o_idx = o_ptr->next_o_idx;
129 int idx = find_autopick_list(player_ptr, o_ptr);
130 auto_inscribe_item(player_ptr, o_ptr, idx);
131 bool is_auto_pickup = idx >= 0;
132 is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0;
135 auto_destroy_item(player_ptr, o_ptr, idx);
139 disturb(player_ptr, FALSE, FALSE);
140 if (!inven_carry_okay(o_ptr))
142 GAME_TEXT o_name[MAX_NLEN];
143 object_desc(player_ptr, o_name, o_ptr, 0);
144 msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
145 o_ptr->marked |= OM_NOMSG;
149 if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK))
151 py_pickup_aux(player_ptr, this_o_idx);
155 char out_val[MAX_NLEN + 20];
156 GAME_TEXT o_name[MAX_NLEN];
157 if (o_ptr->marked & OM_NO_QUERY)
162 object_desc(player_ptr, o_name, o_ptr, 0);
163 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
164 if (!get_check(out_val))
166 o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
170 py_pickup_aux(player_ptr, this_o_idx);
175 static const char autoregister_header[] = "?:$AUTOREGISTER";
178 * Clear auto registered lines in the picktype.prf .
180 static bool clear_auto_register(player_type *player_ptr)
182 char pref_file[1024];
183 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
185 pref_fff = my_fopen(pref_file, "r");
189 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
190 pref_fff = my_fopen(pref_file, "r");
200 tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
204 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
209 bool autoregister = FALSE;
214 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
218 if (buf[0] != '#' && buf[0] != '?') num++;
222 if (streq(buf, autoregister_header))
228 fprintf(tmp_fff, "%s\n", buf);
238 msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。",
239 "Auto registered lines (%d lines) for previous character are remaining."), num);
240 strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted. Are you sure? "));
245 autoregister = FALSE;
247 msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。",
248 "Use cut & paste of auto picker editor (_) to keep old prefs."));
254 tmp_fff = my_fopen(tmp_file, "r");
255 pref_fff = my_fopen(pref_file, "w");
257 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
258 fprintf(pref_fff, "%s\n", buf);
270 * Automatically register an auto-destroy preference line
272 bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr)
275 char pref_file[1024];
277 autopick_type an_entry, *entry = &an_entry;
278 int match_autopick = find_autopick_list(player_ptr, o_ptr);
279 if (match_autopick != -1)
282 byte act = autopick_list[match_autopick].action;
283 if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup");
284 else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy");
285 else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor");
286 else what = _("確認して拾う", "query auto-pickup");
288 msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
292 if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) ||
293 ((o_ptr->ident & IDENT_SENSE) &&
294 (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
296 GAME_TEXT o_name[MAX_NLEN];
297 object_desc(player_ptr, o_name, o_ptr, 0);
298 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
302 if (!player_ptr->autopick_autoregister)
304 if (!clear_auto_register(player_ptr)) return FALSE;
307 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
308 pref_fff = my_fopen(pref_file, "r");
312 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
313 pref_fff = my_fopen(pref_file, "r");
320 if (my_fgets(pref_fff, buf, sizeof(buf)))
322 player_ptr->autopick_autoregister = FALSE;
326 if (streq(buf, autoregister_header))
328 player_ptr->autopick_autoregister = TRUE;
338 * File could not be opened for reading. Assume header not
341 player_ptr->autopick_autoregister = FALSE;
344 pref_fff = my_fopen(pref_file, "a");
347 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file);
352 if (!player_ptr->autopick_autoregister)
354 fprintf(pref_fff, "%s\n", autoregister_header);
356 fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。",
357 "# *Warning!* The lines below will be deleted later."));
358 fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。",
359 "# Keep it by cut & paste if you need these lines for future characters."));
360 player_ptr->autopick_autoregister = TRUE;
363 autopick_entry_from_object(player_ptr, entry, o_ptr);
364 entry->action = DO_AUTODESTROY;
365 add_autopick_list(entry);
367 concptr tmp = autopick_line_from_entry(entry);
368 fprintf(pref_fff, "%s\n", tmp);
376 * Delete or insert string
378 static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
385 by1 = MIN(tb->my, tb->cy);
386 by2 = MAX(tb->my, tb->cy);
388 else /* if (!tb->mark) */
393 for (int y = by1; y <= by2; y++)
395 autopick_type an_entry, *entry = &an_entry;
396 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
398 string_free(tb->lines_list[y]);
401 if (!IS_FLG(flg)) add = TRUE;
407 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
410 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
413 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
416 for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
419 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
422 for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
425 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
428 for (i = FLG_RARE; i <= FLG_COMMON; i++)
432 if (add) ADD_FLG(flg);
435 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
436 tb->dirty_flags |= DIRTY_ALL;
443 * Change command letter
445 static void toggle_command_letter(text_body_type *tb, byte flg)
447 autopick_type an_entry;
448 autopick_type *entry = &an_entry;
454 by1 = MIN(tb->my, tb->cy);
455 by2 = MAX(tb->my, tb->cy);
457 else /* if (!tb->mark) */
462 for (int y = by1; y <= by2; y++)
466 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
468 string_free(tb->lines_list[y]);
472 if (!(entry->action & flg)) add = TRUE;
478 if (entry->action & DONT_AUTOPICK) wid--;
479 else if (entry->action & DO_AUTODESTROY) wid--;
480 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
481 if (!(entry->action & DO_DISPLAY)) wid--;
483 if (flg != DO_DISPLAY)
485 entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
486 if (add) entry->action |= flg;
487 else entry->action |= DO_AUTOPICK;
491 entry->action &= ~(DO_DISPLAY);
492 if (add) entry->action |= flg;
497 if (entry->action & DONT_AUTOPICK) wid++;
498 else if (entry->action & DO_AUTODESTROY) wid++;
499 else if (entry->action & DO_QUERY_AUTOPICK) wid++;
500 if (!(entry->action & DO_DISPLAY)) wid++;
502 if (wid > 0) tb->cx++;
503 if (wid < 0 && tb->cx > 0) tb->cx--;
506 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
507 tb->dirty_flags |= DIRTY_ALL;
514 * Delete or insert string
516 static void add_keyword(text_body_type *tb, BIT_FLAGS flg)
521 by1 = MIN(tb->my, tb->cy);
522 by2 = MAX(tb->my, tb->cy);
529 for (int y = by1; y <= by2; y++)
531 autopick_type an_entry, *entry = &an_entry;
532 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
536 autopick_free_entry(entry);
540 string_free(tb->lines_list[y]);
541 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
544 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
549 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
550 tb->dirty_flags |= DIRTY_ALL;
557 * Add an empty line at the last of the file
559 static bool add_empty_line(text_body_type *tb)
562 for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
564 if (num_lines >= MAX_LINES - 2) return FALSE;
565 if (!tb->lines_list[num_lines - 1][0]) return FALSE;
567 tb->lines_list[num_lines] = string_make("");
568 tb->dirty_flags |= DIRTY_EXPRESSION;
575 * Display the menu, and get a command
577 static int do_command_menu(int level, int start)
580 int col0 = 5 + level * 7;
581 int row0 = 1 + level * 3;
582 int menu_id_list[26];
584 char linestr[MAX_LINELEN];
587 for (int i = start; menu_data[i].level >= level; i++)
589 /* Ignore lower level sub menus */
590 if (menu_data[i].level > level) continue;
592 int len = strlen(menu_data[i].name);
593 if (len > max_len) max_len = len;
595 menu_id_list[menu_key] = i;
599 while (menu_key < 26)
601 menu_id_list[menu_key] = -1;
605 int max_menu_wid = max_len + 3 + 3;
607 /* Prepare box line */
609 strcat(linestr, "+");
610 for (int i = 0; i < max_menu_wid + 2; i++)
612 strcat(linestr, "-");
615 strcat(linestr, "+");
622 Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
625 for (int i = start; menu_data[i].level >= level; i++)
629 if (menu_data[i].level > level) continue;
631 if (menu_data[i].com_id == -1)
633 strcpy(com_key_str, _("▼", ">"));
635 else if (menu_data[i].key != -1)
637 com_key_str[0] = '^';
638 com_key_str[1] = menu_data[i].key + '@';
639 com_key_str[2] = '\0';
643 com_key_str[0] = '\0';
646 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
648 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
653 Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
657 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
660 if (key == ESCAPE) return 0;
663 bool is_alphabet = key >= 'a' && key <= 'z';
666 com_id = get_com_id(key);
675 int menu_id = menu_id_list[key - 'a'];
677 if (menu_id < 0) continue;
679 com_id = menu_data[menu_id].com_id;
683 com_id = do_command_menu(level + 1, menu_id + 1);
685 if (com_id) return com_id;
696 static chain_str_type *new_chain_str(concptr str)
698 chain_str_type *chain;
699 size_t len = strlen(str);
700 chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
701 strcpy(chain->s, str);
707 static void kill_yank_chain(text_body_type *tb)
709 chain_str_type *chain = tb->yank;
715 chain_str_type *next = chain->next;
716 size_t len = strlen(chain->s);
718 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
725 static void add_str_to_yank(text_body_type *tb, concptr str)
727 tb->yank_eol = FALSE;
728 if (NULL == tb->yank)
730 tb->yank = new_chain_str(str);
734 chain_str_type *chain;
741 chain->next = new_chain_str(str);
752 * Do work for the copy editor-command
754 static void copy_text_to_yank(text_body_type *tb)
756 int len = strlen(tb->lines_list[tb->cy]);
757 if (tb->cx > len) tb->cx = len;
767 if (tb->my != tb->cy)
769 int by1 = MIN(tb->my, tb->cy);
770 int by2 = MAX(tb->my, tb->cy);
772 for (int y = by1; y <= by2; y++)
774 add_str_to_yank(tb, tb->lines_list[y]);
777 add_str_to_yank(tb, "");
779 tb->dirty_flags |= DIRTY_ALL;
783 char buf[MAX_LINELEN];
784 int bx1 = MIN(tb->mx, tb->cx);
785 int bx2 = MAX(tb->mx, tb->cx);
786 if (bx2 > len) bx2 = len;
788 if (bx1 == 0 && bx2 == len)
790 add_str_to_yank(tb, tb->lines_list[tb->cy]);
791 add_str_to_yank(tb, "");
796 for (int i = 0; i < bx2 - bx1; i++)
798 buf[i] = tb->lines_list[tb->cy][bx1 + i];
802 add_str_to_yank(tb, buf);
806 tb->dirty_flags |= DIRTY_ALL;
811 * Execute a single editor command
813 static bool do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id)
820 if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
821 "Discard all changes and quit. Are you sure? "))) break;
824 return QUIT_WITHOUT_SAVE;
827 return QUIT_AND_SAVE;
830 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
831 "Discard all changes and revert to original file. Are you sure? "))) break;
833 free_text_lines(tb->lines_list);
834 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
835 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
843 (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
844 tb->dirty_flags |= DIRTY_SCREEN;
852 tb->dirty_flags |= DIRTY_ALL;
855 insert_return_code(tb);
859 tb->dirty_flags |= DIRTY_ALL;
871 len = strlen(tb->lines_list[tb->cy]);
872 if (len < tb->cx) tb->cx = len;
874 for (i = 0; tb->lines_list[tb->cy][i]; i++)
876 if (iskanji(tb->lines_list[tb->cy][i]))
891 tb->cx = strlen(tb->lines_list[tb->cy]);
897 if (!tb->lines_list[tb->cy + 1])
899 if (!add_empty_line(tb)) break;
906 if (tb->cy > 0) tb->cy--;
912 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
915 int len = strlen(tb->lines_list[tb->cy]);
919 if (!tb->lines_list[tb->cy + 1])
921 if (!add_empty_line(tb)) break;
935 tb->cx = strlen(tb->lines_list[tb->cy]);
939 while (0 < tb->cy && tb->upper <= tb->cy)
941 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
946 while (tb->cy < tb->upper + tb->hgt)
948 if (!tb->lines_list[tb->cy + 1])
950 if (!add_empty_line(tb)) break;
966 if (!tb->lines_list[tb->cy + 1])
968 if (!add_empty_line(tb)) break;
979 copy_text_to_yank(tb);
980 if (tb->my == tb->cy)
982 int bx1 = MIN(tb->mx, tb->cx);
983 int bx2 = MAX(tb->mx, tb->cx);
984 int len = strlen(tb->lines_list[tb->cy]);
985 if (bx2 > len) bx2 = len;
987 kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
992 int by1 = MIN(tb->my, tb->cy);
993 int by2 = MAX(tb->my, tb->cy);
995 for (int y = by2; y >= by1; y--)
997 int len = strlen(tb->lines_list[y]);
999 kill_line_segment(tb, y, 0, len, TRUE);
1007 tb->dirty_flags |= DIRTY_ALL;
1012 copy_text_to_yank(tb);
1015 * Move cursor position to the end of the selection
1017 * Pressing ^C ^V correctly duplicates the selection.
1019 if (tb->my != tb->cy)
1021 tb->cy = MAX(tb->cy, tb->my);
1022 if (!tb->lines_list[tb->cy + 1])
1024 if (!add_empty_line(tb)) break;
1031 tb->cx = MAX(tb->cx, tb->mx);
1032 if (!tb->lines_list[tb->cy][tb->cx])
1034 if (!tb->lines_list[tb->cy + 1])
1036 if (!add_empty_line(tb)) break;
1047 chain_str_type *chain = tb->yank;
1048 int len = strlen(tb->lines_list[tb->cy]);
1050 if (tb->cx > len) tb->cx = len;
1055 tb->dirty_flags |= DIRTY_ALL;
1060 concptr yank_str = chain->s;
1061 char buf[MAX_LINELEN];
1063 char rest[MAX_LINELEN], *rest_ptr = rest;
1064 for (i = 0; i < tb->cx; i++)
1065 buf[i] = tb->lines_list[tb->cy][i];
1067 strcpy(rest, &(tb->lines_list[tb->cy][i]));
1068 while (*yank_str && i < MAX_LINELEN - 1)
1070 buf[i++] = *yank_str++;
1074 chain = chain->next;
1075 if (chain || tb->yank_eol)
1077 insert_return_code(tb);
1078 string_free(tb->lines_list[tb->cy]);
1079 tb->lines_list[tb->cy] = string_make(buf);
1086 tb->cx = strlen(buf);
1087 while (*rest_ptr && i < MAX_LINELEN - 1)
1089 buf[i++] = *rest_ptr++;
1093 string_free(tb->lines_list[tb->cy]);
1094 tb->lines_list[tb->cy] = string_make(buf);
1098 tb->dirty_flags |= DIRTY_ALL;
1099 tb->dirty_flags |= DIRTY_EXPRESSION;
1108 tb->dirty_flags |= DIRTY_ALL;
1112 tb->mark = MARK_MARK;
1113 if (com_id == tb->old_com_id)
1121 tb->dirty_flags |= DIRTY_ALL;
1125 int len = strlen(tb->lines_list[tb->cy]);
1129 if (tb->cx > len) tb->mx = len;
1134 int len = strlen(tb->lines_list[tb->cy]);
1135 if (tb->cx > len) tb->cx = len;
1140 tb->dirty_flags |= DIRTY_ALL;
1143 if (tb->old_com_id != com_id)
1145 kill_yank_chain(tb);
1151 add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
1152 kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
1153 tb->dirty_line = tb->cy;
1157 if (tb->yank_eol) add_str_to_yank(tb, "");
1159 tb->yank_eol = TRUE;
1160 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
1163 case EC_DELETE_CHAR:
1168 tb->dirty_flags |= DIRTY_ALL;
1172 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
1175 int len = strlen(tb->lines_list[tb->cy]);
1178 do_editor_command(player_ptr, tb, EC_BACKSPACE);
1182 if (tb->lines_list[tb->cy + 1])
1193 do_editor_command(player_ptr, tb, EC_BACKSPACE);
1199 char buf[MAX_LINELEN];
1203 tb->dirty_flags |= DIRTY_ALL;
1206 len = strlen(tb->lines_list[tb->cy]);
1207 if (len < tb->cx) tb->cx = len;
1211 if (tb->cy == 0) break;
1212 tb->cx = strlen(tb->lines_list[tb->cy - 1]);
1213 strcpy(buf, tb->lines_list[tb->cy - 1]);
1214 strcat(buf, tb->lines_list[tb->cy]);
1215 string_free(tb->lines_list[tb->cy - 1]);
1216 string_free(tb->lines_list[tb->cy]);
1217 tb->lines_list[tb->cy - 1] = string_make(buf);
1219 for (i = tb->cy; tb->lines_list[i + 1]; i++)
1220 tb->lines_list[i] = tb->lines_list[i + 1];
1222 tb->lines_list[i] = NULL;
1224 tb->dirty_flags |= DIRTY_ALL;
1225 tb->dirty_flags |= DIRTY_EXPRESSION;
1230 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
1234 if (iskanji(tb->lines_list[tb->cy][i]))
1235 buf[j++] = tb->lines_list[tb->cy][i++];
1237 buf[j++] = tb->lines_list[tb->cy][i];
1246 for (; tb->lines_list[tb->cy][i]; i++)
1248 buf[j++] = tb->lines_list[tb->cy][i];
1252 string_free(tb->lines_list[tb->cy]);
1253 tb->lines_list[tb->cy] = string_make(buf);
1254 tb->dirty_line = tb->cy;
1255 check_expression_line(tb, tb->cy);
1262 tb->dirty_flags |= DIRTY_SCREEN;
1263 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
1265 if (!search_dir) break;
1267 if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
1268 else do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
1271 case EC_SEARCH_FORW:
1272 if (tb->search_o_ptr)
1274 search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE);
1278 if (tb->search_str && tb->search_str[0])
1280 search_for_string(tb, tb->search_str, TRUE);
1284 tb->dirty_flags |= DIRTY_NO_SEARCH;
1287 case EC_SEARCH_BACK:
1288 if (tb->search_o_ptr)
1290 search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE);
1294 if (tb->search_str && tb->search_str[0])
1296 search_for_string(tb, tb->search_str, FALSE);
1300 tb->dirty_flags |= DIRTY_NO_SEARCH;
1304 tb->dirty_flags |= DIRTY_SCREEN;
1306 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break;
1308 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
1311 case EC_SEARCH_DESTROYED:
1312 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str))
1314 tb->dirty_flags |= DIRTY_NO_SEARCH;
1318 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
1321 case EC_INSERT_OBJECT:
1323 autopick_type an_entry, *entry = &an_entry;
1324 if (!entry_from_choosed_object(player_ptr, entry))
1326 tb->dirty_flags |= DIRTY_SCREEN;
1331 insert_return_code(tb);
1332 string_free(tb->lines_list[tb->cy]);
1333 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
1334 tb->dirty_flags |= DIRTY_SCREEN;
1337 case EC_INSERT_DESTROYED:
1338 if (!tb->last_destroyed) break;
1341 insert_return_code(tb);
1342 string_free(tb->lines_list[tb->cy]);
1343 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
1344 tb->dirty_flags |= DIRTY_ALL;
1348 case EC_INSERT_BLOCK:
1350 char expression[80];
1351 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
1353 rp_ptr->E_title, cp_ptr->E_title,
1355 rp_ptr->title, cp_ptr->title,
1359 insert_return_code(tb);
1360 string_free(tb->lines_list[tb->cy]);
1361 tb->lines_list[tb->cy] = string_make(expression);
1363 insert_return_code(tb);
1364 string_free(tb->lines_list[tb->cy]);
1365 tb->lines_list[tb->cy] = string_make("?:1");
1366 tb->dirty_flags |= DIRTY_ALL;
1371 case EC_INSERT_MACRO:
1372 draw_text_editor(player_ptr, tb);
1373 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
1374 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
1375 if (!insert_macro_line(tb)) break;
1378 tb->dirty_flags |= DIRTY_ALL;
1382 case EC_INSERT_KEYMAP:
1383 draw_text_editor(player_ptr, tb);
1384 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
1385 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
1386 format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
1388 if (!insert_keymap_line(tb)) break;
1391 tb->dirty_flags |= DIRTY_ALL;
1395 case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
1396 case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
1397 case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
1398 case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
1399 case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
1401 case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
1402 case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
1403 case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
1404 case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
1405 case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
1406 case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
1407 case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
1408 case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
1409 case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
1410 case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
1411 case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
1412 case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
1413 case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
1414 case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
1415 case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
1416 case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
1417 case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
1418 case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
1419 case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
1420 case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
1421 case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
1422 case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
1423 case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
1424 case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
1425 case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
1426 case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
1427 case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
1428 case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
1429 case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
1430 case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
1431 case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
1432 case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
1433 case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
1434 case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
1435 case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
1436 case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
1437 case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
1438 case EC_OK_UNREADABLE:
1439 toggle_keyword(tb, FLG_UNREADABLE);
1440 add_keyword(tb, FLG_SPELLBOOKS);
1443 toggle_keyword(tb, FLG_REALM1);
1444 add_keyword(tb, FLG_SPELLBOOKS);
1447 toggle_keyword(tb, FLG_REALM2);
1448 add_keyword(tb, FLG_SPELLBOOKS);
1451 toggle_keyword(tb, FLG_FIRST);
1452 add_keyword(tb, FLG_SPELLBOOKS);
1455 toggle_keyword(tb, FLG_SECOND);
1456 add_keyword(tb, FLG_SPELLBOOKS);
1459 toggle_keyword(tb, FLG_THIRD);
1460 add_keyword(tb, FLG_SPELLBOOKS);
1463 toggle_keyword(tb, FLG_FOURTH);
1464 add_keyword(tb, FLG_SPELLBOOKS);
1468 tb->old_com_id = com_id;
1474 * Check special key code and get a movement command id
1476 static int analyze_move_key(text_body_type *tb, int skey)
1479 if (!(skey & SKEY_MASK)) return 0;
1481 switch (skey & ~SKEY_MOD_MASK)
1483 case SKEY_DOWN: com_id = EC_DOWN; break;
1484 case SKEY_LEFT: com_id = EC_LEFT; break;
1485 case SKEY_RIGHT: com_id = EC_RIGHT; break;
1486 case SKEY_UP: com_id = EC_UP; break;
1487 case SKEY_PGUP: com_id = EC_PGUP; break;
1488 case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
1489 case SKEY_TOP: com_id = EC_TOP; break;
1490 case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
1495 if (!(skey & SKEY_MOD_SHIFT))
1498 * Un-shifted cursor keys cancells
1499 * selection created by shift+cursor.
1501 if (tb->mark & MARK_BY_SHIFT)
1504 tb->dirty_flags |= DIRTY_ALL;
1510 if (tb->mark) return com_id;
1512 int len = strlen(tb->lines_list[tb->cy]);
1513 tb->mark = MARK_MARK | MARK_BY_SHIFT;
1516 if (tb->cx > len) tb->mx = len;
1518 if (com_id == EC_UP || com_id == EC_DOWN)
1520 tb->dirty_flags |= DIRTY_ALL;
1524 tb->dirty_line = tb->cy;
1531 * In-game editor of Object Auto-picker/Destoryer
1532 * @param player_ptr プレーヤーへの参照ポインタ
1534 void do_cmd_edit_autopick(player_type *player_ptr)
1536 static int cx_save = 0;
1537 static int cy_save = 0;
1538 autopick_type an_entry, *entry = &an_entry;
1539 char buf[MAX_LINELEN];
1542 static s32b old_autosave_turn = 0L;
1545 text_body_type text_body;
1546 text_body_type *tb = &text_body;
1547 tb->changed = FALSE;
1550 tb->upper = tb->left = 0;
1552 tb->mx = tb->my = 0;
1553 tb->old_cy = tb->old_upper = tb->old_left = -1;
1554 tb->old_wid = tb->old_hgt = -1;
1558 tb->search_o_ptr = NULL;
1559 tb->search_str = NULL;
1560 tb->last_destroyed = NULL;
1561 tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
1562 tb->dirty_line = -1;
1563 tb->filename_mode = PT_DEFAULT;
1565 if (current_world_ptr->game_turn < old_autosave_turn)
1567 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
1570 if (current_world_ptr->game_turn > old_autosave_turn + 100L)
1572 do_cmd_save_game(player_ptr, TRUE);
1573 old_autosave_turn = current_world_ptr->game_turn;
1578 if (autopick_last_destroyed_object.k_idx)
1580 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
1581 tb->last_destroyed = autopick_line_from_entry_kill(entry);
1584 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
1585 for (i = 0; i < tb->cy; i++)
1587 if (!tb->lines_list[i])
1589 tb->cy = tb->cx = 0;
1598 draw_text_editor(player_ptr, tb);
1599 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
1600 "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
1603 prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
1607 prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
1610 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
1611 tb->dirty_flags = 0;
1612 tb->dirty_line = -1;
1613 tb->old_cy = tb->cy;
1614 tb->old_upper = tb->upper;
1615 tb->old_left = tb->left;
1616 tb->old_wid = tb->wid;
1617 tb->old_hgt = tb->hgt;
1619 key = inkey_special(TRUE);
1621 if (key & SKEY_MASK)
1623 com_id = analyze_move_key(tb, key);
1625 else if (key == ESCAPE)
1627 com_id = do_command_menu(0, 0);
1628 tb->dirty_flags |= DIRTY_SCREEN;
1630 else if (!iscntrl((unsigned char)key))
1635 tb->dirty_flags |= DIRTY_ALL;
1638 insert_single_letter(tb, key);
1643 com_id = get_com_id((char)key);
1646 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
1650 strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
1652 if (quit == QUIT_AND_SAVE)
1653 write_text_lines(buf, tb->lines_list);
1655 free_text_lines(tb->lines_list);
1656 string_free(tb->search_str);
1657 string_free(tb->last_destroyed);
1658 kill_yank_chain(tb);
1660 process_autopick_file(player_ptr, buf);
1661 current_world_ptr->start_time = (u32b)time(NULL);