2 * @brief 自動拾いエディタ画面でキーを押した時の挙動一式
5 * @todo これ単体で700行を超えているので要分割
8 #include "autopick/autopick-editor-command.h"
9 #include "autopick/autopick-commands-table.h"
10 #include "autopick/autopick-dirty-flags.h"
11 #include "autopick/autopick-drawer.h"
12 #include "autopick/autopick-editor-util.h"
13 #include "autopick/autopick-entry.h"
14 #include "autopick/autopick-finder.h"
15 #include "autopick/autopick-flags-table.h"
16 #include "autopick/autopick-inserter-killer.h"
17 #include "autopick/autopick-methods-table.h"
18 #include "autopick/autopick-reader-writer.h"
19 #include "autopick/autopick-util.h"
20 #include "core/asking-player.h"
21 #include "core/show-file.h"
22 #include "game-option/input-options.h"
23 #include "game-option/keymap-directory-getter.h"
24 #include "player-info/class-info.h"
25 #include "player-info/race-info.h"
26 #include "system/player-type-definition.h"
27 #include "term/term-color-types.h"
28 #include "term/z-form.h"
30 #include <string_view>
34 * @param player_ptr プレイヤーへの参照ポインタ
36 * @param com_id エディタ内で打ったコマンド
38 * @details Execute a single editor command
40 ape_quittance do_editor_command(PlayerType *player_ptr, text_body_type *tb, int com_id)
45 if (!input_check(_("全ての変更を破棄してから終了します。よろしいですか? ", "Discard all changes and quit. Are you sure? "))) {
50 return APE_QUIT_WITHOUT_SAVE;
53 return APE_QUIT_AND_SAVE;
55 if (!input_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ", "Discard all changes and revert to original file. Are you sure? "))) {
59 free_text_lines(tb->lines_list);
60 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
61 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
68 (void)show_file(player_ptr, true, _("jeditor.txt", "editor.txt"), 0, 0);
69 tb->dirty_flags |= DIRTY_SCREEN;
75 tb->dirty_flags |= DIRTY_ALL;
78 if (!insert_return_code(tb)) {
83 tb->dirty_flags |= DIRTY_ALL;
93 len = strlen(tb->lines_list[tb->cy]);
98 for (i = 0; tb->lines_list[tb->cy][i]; i++) {
99 if (iskanji(tb->lines_list[tb->cy][i])) {
108 } else if (tb->cy > 0) {
110 tb->cx = strlen(tb->lines_list[tb->cy]);
116 if (!tb->lines_list[tb->cy + 1]) {
117 if (!add_empty_line(tb)) {
131 const int len = strlen(tb->lines_list[tb->cy]);
133 if ((tb->cx + 1 < len) && iskanji(tb->lines_list[tb->cy][tb->cx])) {
141 if (!tb->lines_list[tb->cy + 1]) {
142 if (!add_empty_line(tb)) {
157 tb->cx = strlen(tb->lines_list[tb->cy]);
160 while (0 < tb->cy && tb->upper <= tb->cy) {
164 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt) {
170 while (tb->cy < tb->upper + tb->hgt) {
171 if (!tb->lines_list[tb->cy + 1]) {
172 if (!add_empty_line(tb)) {
187 if (!tb->lines_list[tb->cy + 1]) {
188 if (!add_empty_line(tb)) {
199 copy_text_to_yank(tb);
200 if (tb->my == tb->cy) {
201 int bx1 = std::min(tb->mx, tb->cx);
202 int bx2 = std::max(tb->mx, tb->cx);
203 int len = strlen(tb->lines_list[tb->cy]);
208 kill_line_segment(tb, tb->cy, bx1, bx2, true);
211 int by1 = std::min(tb->my, tb->cy);
212 int by2 = std::max(tb->my, tb->cy);
214 for (int y = by2; y >= by1; y--) {
215 int len = strlen(tb->lines_list[y]);
217 kill_line_segment(tb, y, 0, len, true);
225 tb->dirty_flags |= DIRTY_ALL;
230 copy_text_to_yank(tb);
233 * Move cursor position to the end of the selection
235 * Pressing ^C ^V correctly duplicates the selection.
237 if (tb->my != tb->cy) {
238 tb->cy = std::max(tb->cy, tb->my);
239 if (!tb->lines_list[tb->cy + 1]) {
240 if (!add_empty_line(tb)) {
249 tb->cx = std::max(tb->cx, tb->mx);
250 if (!tb->lines_list[tb->cy][tb->cx]) {
251 if (!tb->lines_list[tb->cy + 1]) {
252 if (!add_empty_line(tb)) {
264 int len = strlen(tb->lines_list[tb->cy]);
265 if (tb->yank.empty()) {
274 tb->dirty_flags |= DIRTY_ALL;
277 for (auto i = 0U; i < tb->yank.size(); ++i) {
278 const std::string_view line(tb->lines_list[tb->cy]);
279 std::string buf(line.substr(0, tb->cx));
280 buf.append(tb->yank[i], 0, MAX_LINELEN - buf.length() - 1);
282 const auto is_last_line = i + 1 == tb->yank.size();
283 if (!is_last_line || tb->yank_eol) {
284 if (!insert_return_code(tb)) {
287 string_free(tb->lines_list[tb->cy]);
288 tb->lines_list[tb->cy] = string_make(buf.data());
295 const auto rest = line.substr(tb->cx);
296 tb->cx = buf.length();
297 buf.append(rest, 0, MAX_LINELEN - buf.length() - 1);
299 string_free(tb->lines_list[tb->cy]);
300 tb->lines_list[tb->cy] = string_make(buf.data());
304 tb->dirty_flags |= DIRTY_ALL;
305 tb->dirty_flags |= DIRTY_EXPRESSION;
312 tb->dirty_flags |= DIRTY_ALL;
316 tb->mark = MARK_MARK;
317 if (com_id == tb->old_com_id) {
324 tb->dirty_flags |= DIRTY_ALL;
328 int len = strlen(tb->lines_list[tb->cy]);
338 int len = strlen(tb->lines_list[tb->cy]);
345 tb->dirty_flags |= DIRTY_ALL;
348 if (tb->old_com_id != com_id) {
353 add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
354 kill_line_segment(tb, tb->cy, tb->cx, len, false);
355 tb->dirty_line = tb->cy;
360 add_str_to_yank(tb, "");
364 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
367 case EC_DELETE_CHAR: {
370 tb->dirty_flags |= DIRTY_ALL;
374 if (iskanji(tb->lines_list[tb->cy][tb->cx])) {
379 int len = strlen(tb->lines_list[tb->cy]);
381 do_editor_command(player_ptr, tb, EC_BACKSPACE);
385 if (tb->lines_list[tb->cy + 1]) {
393 do_editor_command(player_ptr, tb, EC_BACKSPACE);
398 char buf[MAX_LINELEN];
401 tb->dirty_flags |= DIRTY_ALL;
404 len = strlen(tb->lines_list[tb->cy]);
413 tb->cx = strlen(tb->lines_list[tb->cy - 1]);
414 strcpy(buf, tb->lines_list[tb->cy - 1]);
415 strcat(buf, tb->lines_list[tb->cy]);
416 string_free(tb->lines_list[tb->cy - 1]);
417 string_free(tb->lines_list[tb->cy]);
418 tb->lines_list[tb->cy - 1] = string_make(buf);
420 for (i = tb->cy; tb->lines_list[i + 1]; i++) {
421 tb->lines_list[i] = tb->lines_list[i + 1];
424 tb->lines_list[i] = nullptr;
426 tb->dirty_flags |= DIRTY_ALL;
427 tb->dirty_flags |= DIRTY_EXPRESSION;
432 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) {
435 if (iskanji(tb->lines_list[tb->cy][i])) {
436 buf[j++] = tb->lines_list[tb->cy][i++];
439 buf[j++] = tb->lines_list[tb->cy][i];
447 for (; tb->lines_list[tb->cy][i]; i++) {
448 buf[j++] = tb->lines_list[tb->cy][i];
452 string_free(tb->lines_list[tb->cy]);
453 tb->lines_list[tb->cy] = string_make(buf);
454 tb->dirty_line = tb->cy;
455 check_expression_line(tb, tb->cy);
459 case EC_SEARCH_STR: {
461 tb->dirty_flags |= DIRTY_SCREEN;
462 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
468 if (search_dir == 1) {
469 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
471 do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
477 if (tb->search_o_ptr) {
478 search_for_object(player_ptr, tb, tb->search_o_ptr, true);
482 if (tb->search_str && tb->search_str[0]) {
483 search_for_string(tb, tb->search_str, true);
487 tb->dirty_flags |= DIRTY_NO_SEARCH;
490 case EC_SEARCH_BACK: {
491 if (tb->search_o_ptr) {
492 search_for_object(player_ptr, tb, tb->search_o_ptr, false);
496 if (tb->search_str && tb->search_str[0]) {
497 search_for_string(tb, tb->search_str, false);
501 tb->dirty_flags |= DIRTY_NO_SEARCH;
504 case EC_SEARCH_OBJ: {
505 tb->dirty_flags |= DIRTY_SCREEN;
507 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) {
511 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
514 case EC_SEARCH_DESTROYED: {
515 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) {
516 tb->dirty_flags |= DIRTY_NO_SEARCH;
520 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
523 case EC_INSERT_OBJECT: {
524 autopick_type an_entry, *entry = &an_entry;
525 if (!entry_from_choosed_object(player_ptr, entry)) {
526 tb->dirty_flags |= DIRTY_SCREEN;
531 if (!insert_return_code(tb)) {
534 string_free(tb->lines_list[tb->cy]);
535 tb->lines_list[tb->cy] = autopick_line_from_entry(*entry);
536 tb->dirty_flags |= DIRTY_SCREEN;
539 case EC_INSERT_DESTROYED: {
540 if (!tb->last_destroyed) {
545 if (!insert_return_code(tb)) {
548 string_free(tb->lines_list[tb->cy]);
549 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
550 tb->dirty_flags |= DIRTY_ALL;
554 case EC_INSERT_BLOCK: {
555 if (!can_insert_line(tb, 2)) {
559 strnfmt(expression, sizeof(expression), "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
561 rp_ptr->E_title, cp_ptr->E_title,
563 rp_ptr->title, cp_ptr->title,
567 insert_return_code(tb);
568 string_free(tb->lines_list[tb->cy]);
569 tb->lines_list[tb->cy] = string_make(expression);
571 insert_return_code(tb);
572 string_free(tb->lines_list[tb->cy]);
573 tb->lines_list[tb->cy] = string_make("?:1");
574 tb->dirty_flags |= DIRTY_ALL;
578 case EC_INSERT_MACRO: {
579 draw_text_editor(player_ptr, tb);
580 term_erase(0, tb->cy - tb->upper + 1, tb->wid);
581 term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
582 if (!insert_macro_line(tb)) {
587 tb->dirty_flags |= DIRTY_ALL;
591 case EC_INSERT_KEYMAP: {
592 draw_text_editor(player_ptr, tb);
593 term_erase(0, tb->cy - tb->upper + 1, tb->wid);
594 term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
595 format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
597 if (!insert_keymap_line(tb)) {
602 tb->dirty_flags |= DIRTY_ALL;
607 toggle_command_letter(tb, DO_AUTOPICK);
610 toggle_command_letter(tb, DO_AUTODESTROY);
613 toggle_command_letter(tb, DONT_AUTOPICK);
616 toggle_command_letter(tb, DO_QUERY_AUTOPICK);
619 toggle_command_letter(tb, DO_DISPLAY);
622 toggle_keyword(tb, FLG_UNAWARE);
624 case EC_IK_UNIDENTIFIED:
625 toggle_keyword(tb, FLG_UNIDENTIFIED);
627 case EC_IK_IDENTIFIED:
628 toggle_keyword(tb, FLG_IDENTIFIED);
630 case EC_IK_STAR_IDENTIFIED:
631 toggle_keyword(tb, FLG_STAR_IDENTIFIED);
634 toggle_keyword(tb, FLG_WEAPONS);
636 case EC_KK_FAVORITE_WEAPONS:
637 toggle_keyword(tb, FLG_FAVORITE_WEAPONS);
640 toggle_keyword(tb, FLG_ARMORS);
643 toggle_keyword(tb, FLG_MISSILES);
646 toggle_keyword(tb, FLG_DEVICES);
649 toggle_keyword(tb, FLG_LIGHTS);
652 toggle_keyword(tb, FLG_JUNKS);
655 toggle_keyword(tb, FLG_CORPSES);
657 case EC_KK_SPELLBOOKS:
658 toggle_keyword(tb, FLG_SPELLBOOKS);
661 toggle_keyword(tb, FLG_SHIELDS);
664 toggle_keyword(tb, FLG_BOWS);
667 toggle_keyword(tb, FLG_RINGS);
670 toggle_keyword(tb, FLG_AMULETS);
673 toggle_keyword(tb, FLG_SUITS);
676 toggle_keyword(tb, FLG_CLOAKS);
679 toggle_keyword(tb, FLG_HELMS);
682 toggle_keyword(tb, FLG_GLOVES);
685 toggle_keyword(tb, FLG_BOOTS);
687 case EC_OK_COLLECTING:
688 toggle_keyword(tb, FLG_COLLECTING);
691 toggle_keyword(tb, FLG_BOOSTED);
693 case EC_OK_MORE_DICE:
694 toggle_keyword(tb, FLG_MORE_DICE);
696 case EC_OK_MORE_BONUS:
697 toggle_keyword(tb, FLG_MORE_BONUS);
699 case EC_OK_WORTHLESS:
700 toggle_keyword(tb, FLG_WORTHLESS);
703 toggle_keyword(tb, FLG_ARTIFACT);
706 toggle_keyword(tb, FLG_EGO);
709 toggle_keyword(tb, FLG_GOOD);
712 toggle_keyword(tb, FLG_NAMELESS);
715 toggle_keyword(tb, FLG_AVERAGE);
718 toggle_keyword(tb, FLG_RARE);
721 toggle_keyword(tb, FLG_COMMON);
724 toggle_keyword(tb, FLG_WANTED);
727 toggle_keyword(tb, FLG_UNIQUE);
730 toggle_keyword(tb, FLG_HUMAN);
732 case EC_OK_UNREADABLE:
733 toggle_keyword(tb, FLG_UNREADABLE);
734 add_keyword(tb, FLG_SPELLBOOKS);
737 toggle_keyword(tb, FLG_REALM1);
738 add_keyword(tb, FLG_SPELLBOOKS);
741 toggle_keyword(tb, FLG_REALM2);
742 add_keyword(tb, FLG_SPELLBOOKS);
745 toggle_keyword(tb, FLG_FIRST);
746 add_keyword(tb, FLG_SPELLBOOKS);
749 toggle_keyword(tb, FLG_SECOND);
750 add_keyword(tb, FLG_SPELLBOOKS);
753 toggle_keyword(tb, FLG_THIRD);
754 add_keyword(tb, FLG_SPELLBOOKS);
757 toggle_keyword(tb, FLG_FOURTH);
758 add_keyword(tb, FLG_SPELLBOOKS);
762 tb->old_com_id = com_id;