OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / autopick / autopick-inserter-killer.cpp
1 #include "autopick/autopick-inserter-killer.h"
2 #include "autopick/autopick-dirty-flags.h"
3 #include "autopick/autopick-util.h"
4 #include "cmd-io/macro-util.h"
5 #include "game-option/input-options.h"
6 #include "game-option/keymap-directory-getter.h"
7 #include "io/input-key-acceptor.h"
8 #include "io/input-key-requester.h"
9 #include "main/sound-of-music.h"
10 #include "term/screen-processor.h"
11 #include "util/string-processor.h"
12
13 /*!
14  * @brief Check if this line is expression or not. And update it if it is.
15  */
16 void check_expression_line(text_body_type *tb, int y)
17 {
18     concptr s = tb->lines_list[y];
19
20     if ((s[0] == '?' && s[1] == ':') || (tb->states[y] & LSTAT_BYPASS)) {
21         tb->dirty_flags |= DIRTY_EXPRESSION;
22     }
23 }
24
25 /*!
26  * @brief 行を追加可能かチェックする
27  * @param tb text_body_type
28  * @param add_num 追加する行数
29  * @retval true 追加可能
30  * @retval false 最大行数を超えるため追加不可
31  */
32 bool can_insert_line(text_body_type *tb, int add_num)
33 {
34     const int count = count_line(tb);
35     return !is_greater_autopick_max_line(count + add_num);
36 }
37
38 /*!
39  * @brief Insert return code and split the line
40  */
41 bool insert_return_code(text_body_type *tb)
42 {
43     char buf[MAX_LINELEN];
44     int i, j, num_lines;
45
46     num_lines = count_line(tb);
47     if (is_greater_autopick_max_line(num_lines)) {
48         return false;
49     }
50
51     num_lines--;
52
53     for (; tb->cy < num_lines; num_lines--) {
54         tb->lines_list[num_lines + 1] = tb->lines_list[num_lines];
55         tb->states[num_lines + 1] = tb->states[num_lines];
56     }
57
58     for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) {
59 #ifdef JP
60         if (iskanji(tb->lines_list[tb->cy][i])) {
61             buf[j++] = tb->lines_list[tb->cy][i++];
62         }
63 #endif
64         buf[j++] = tb->lines_list[tb->cy][i];
65     }
66
67     buf[j] = '\0';
68     tb->lines_list[tb->cy + 1] = string_make(&tb->lines_list[tb->cy][i]);
69     string_free(tb->lines_list[tb->cy]);
70     tb->lines_list[tb->cy] = string_make(buf);
71     tb->dirty_flags |= DIRTY_EXPRESSION;
72     tb->changed = true;
73     return true;
74 }
75
76 /*!
77  * @brief Get a trigger key and insert ASCII string for the trigger
78  */
79 bool insert_macro_line(text_body_type *tb)
80 {
81     if (!can_insert_line(tb, 2)) {
82         return false;
83     }
84     int i, n = 0;
85     flush();
86     inkey_base = true;
87     i = inkey();
88     char buf[1024];
89     while (i) {
90         buf[n++] = (char)i;
91         inkey_base = true;
92         inkey_scan = true;
93         i = inkey();
94     }
95
96     buf[n] = '\0';
97     flush();
98
99     char tmp[1024];
100     ascii_to_text(tmp, buf, sizeof(tmp));
101     if (!tmp[0]) {
102         return false;
103     }
104
105     tb->cx = 0;
106     insert_return_code(tb);
107     string_free(tb->lines_list[tb->cy]);
108     tb->lines_list[tb->cy] = string_make(format("P:%s", tmp).data());
109
110     i = macro_find_exact(buf);
111     if (i == -1) {
112         tmp[0] = '\0';
113     } else {
114         ascii_to_text(tmp, macro_actions[i], sizeof(tmp));
115     }
116
117     insert_return_code(tb);
118     string_free(tb->lines_list[tb->cy]);
119     tb->lines_list[tb->cy] = string_make(format("A:%s", tmp).data());
120
121     return true;
122 }
123
124 /*!
125  * @brief Get a command key and insert ASCII string for the key
126  */
127 bool insert_keymap_line(text_body_type *tb)
128 {
129     if (!can_insert_line(tb, 2)) {
130         return false;
131     }
132     BIT_FLAGS mode;
133     if (rogue_like_commands) {
134         mode = KEYMAP_MODE_ROGUE;
135     } else {
136         mode = KEYMAP_MODE_ORIG;
137     }
138
139     flush();
140     char buf[2];
141     buf[0] = inkey();
142     buf[1] = '\0';
143
144     flush();
145     char tmp[1024];
146     ascii_to_text(tmp, buf, sizeof(tmp));
147     if (!tmp[0]) {
148         return false;
149     }
150
151     tb->cx = 0;
152     insert_return_code(tb);
153     string_free(tb->lines_list[tb->cy]);
154     tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp).data());
155
156     concptr act = keymap_act[mode][(byte)(buf[0])];
157     if (act) {
158         ascii_to_text(tmp, act, sizeof(tmp));
159     }
160
161     insert_return_code(tb);
162     string_free(tb->lines_list[tb->cy]);
163     tb->lines_list[tb->cy] = string_make(format("A:%s", tmp).data());
164
165     return true;
166 }
167
168 /*!
169  * @brief Insert single letter at cursor position.
170  */
171 void insert_single_letter(text_body_type *tb, int key)
172 {
173     int i, j, len;
174     char buf[MAX_LINELEN];
175
176     for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) {
177         buf[j++] = tb->lines_list[tb->cy][i];
178     }
179
180 #ifdef JP
181     if (iskanji(key)) {
182         int next;
183
184         inkey_base = true;
185         next = inkey();
186         if (j + 2 < MAX_LINELEN) {
187             buf[j++] = (char)key;
188             buf[j++] = (char)next;
189             tb->cx += 2;
190         } else {
191             bell();
192         }
193     } else
194 #endif
195     {
196         if (j + 1 < MAX_LINELEN) {
197             buf[j++] = (char)key;
198         }
199         tb->cx++;
200     }
201
202     for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++) {
203         buf[j++] = tb->lines_list[tb->cy][i];
204     }
205     buf[j] = '\0';
206
207     string_free(tb->lines_list[tb->cy]);
208     tb->lines_list[tb->cy] = string_make(buf);
209     len = strlen(tb->lines_list[tb->cy]);
210     if (len < tb->cx) {
211         tb->cx = len;
212     }
213
214     tb->dirty_line = tb->cy;
215     check_expression_line(tb, tb->cy);
216     tb->changed = true;
217 }
218
219 /*!
220  * @brief Kill segment of a line
221  */
222 void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
223 {
224     concptr s = tb->lines_list[y];
225     if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1]) {
226         string_free(tb->lines_list[y]);
227
228         int i;
229         for (i = y; tb->lines_list[i + 1]; i++) {
230             tb->lines_list[i] = tb->lines_list[i + 1];
231         }
232         tb->lines_list[i] = nullptr;
233
234         tb->dirty_flags |= DIRTY_EXPRESSION;
235
236         return;
237     }
238
239     if (x0 == x1) {
240         return;
241     }
242
243     char buf[MAX_LINELEN];
244     char *d = buf;
245     for (int x = 0; x < x0; x++) {
246         *(d++) = s[x];
247     }
248
249     for (int x = x1; s[x]; x++) {
250         *(d++) = s[x];
251     }
252
253     *d = '\0';
254     string_free(tb->lines_list[y]);
255     tb->lines_list[y] = string_make(buf);
256     check_expression_line(tb, y);
257     tb->changed = true;
258 }