OSDN Git Service

[feature] ソースファイルをC++に対応
[hengbandforosx/hengbandosx.git] / src / autopick / autopick-finder.c
1 /*!
2  * todo get_string_for_search() は長い、要分割
3  * @brief 自動拾いの検索
4  * @date 2020/04/26
5  * @author Hourier
6  */
7
8 #include "autopick/autopick-finder.h"
9 #include "autopick/autopick-dirty-flags.h"
10 #include "autopick/autopick-entry.h"
11 #include "autopick/autopick-matcher.h"
12 #include "core/show-file.h"
13 #include "flavor/flavor-describer.h"
14 #include "flavor/object-flavor-types.h"
15 #include "floor/floor-object.h"
16 #include "io/input-key-acceptor.h"
17 #include "main/sound-of-music.h"
18 #include "object/item-use-flags.h"
19 #include "term/screen-processor.h"
20 #include "term/term-color-types.h"
21 #include "util/int-char-converter.h"
22 #include "util/string-processor.h"
23
24 /*
25  * @brief 与えられたアイテムが自動拾いのリストに登録されているかどうかを検索する
26  * @param player_ptr プレーヤーへの参照ポインタ
27  * @o_ptr アイテムへの参照ポインタ
28  * @return 自動拾いのリストに登録されていたらその登録番号、なかったら-1
29  * @details
30  * A function for Auto-picker/destroyer
31  * Examine whether the object matches to the list of keywords or not.
32  */
33 int find_autopick_list(player_type *player_ptr, object_type *o_ptr)
34 {
35     GAME_TEXT o_name[MAX_NLEN];
36     if (o_ptr->tval == TV_GOLD)
37         return -1;
38
39     describe_flavor(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
40     str_tolower(o_name);
41     for (int i = 0; i < max_autopick; i++) {
42         autopick_type *entry = &autopick_list[i];
43         if (is_autopick_match(player_ptr, o_ptr, entry, o_name))
44             return i;
45     }
46
47     return -1;
48 }
49
50 /*
51  * Choose an item for search
52  */
53 bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
54 {
55     concptr q = _("どのアイテムを検索しますか? ", "Enter which item? ");
56     concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
57     object_type *o_ptr;
58     o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, TV_NONE);
59     if (!o_ptr)
60         return FALSE;
61
62     *o_handle = o_ptr;
63     string_free(*search_strp);
64     char buf[MAX_NLEN + 20];
65     describe_flavor(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
66     *search_strp = string_make(format("<%s>", buf));
67     return TRUE;
68 }
69
70 /*
71  * Prepare for search by destroyed object
72  */
73 bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
74 {
75     if (!autopick_last_destroyed_object.k_idx)
76         return FALSE;
77
78     *o_handle = &autopick_last_destroyed_object;
79     string_free(*search_strp);
80     char buf[MAX_NLEN + 20];
81     describe_flavor(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
82     *search_strp = string_make(format("<%s>", buf));
83     return TRUE;
84 }
85
86 /*
87  * Choose an item or string for search
88  */
89 byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
90 {
91     /*
92      * Text color
93      * TERM_YELLOW : Overwrite mode
94      * TERM_WHITE : Insert mode
95      */
96     byte color = TERM_YELLOW;
97     char buf[MAX_NLEN + 20];
98     const int len = 80;
99     char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): ");
100     int col = sizeof(prompt) - 1;
101     if (*search_strp)
102         strcpy(buf, *search_strp);
103     else
104         buf[0] = '\0';
105
106     if (*o_handle)
107         color = TERM_L_GREEN;
108
109     prt(prompt, 0, 0);
110     int pos = 0;
111     while (TRUE) {
112         bool back = FALSE;
113         term_erase(col, 0, 255);
114         term_putstr(col, 0, -1, color, buf);
115         term_gotoxy(col + pos, 0);
116
117         int skey = inkey_special(TRUE);
118         switch (skey) {
119         case SKEY_LEFT:
120         case KTRL('b'): {
121             int i = 0;
122             color = TERM_WHITE;
123             if (pos == 0)
124                 break;
125
126             while (TRUE) {
127                 int next_pos = i + 1;
128
129 #ifdef JP
130                 if (iskanji(buf[i]))
131                     next_pos++;
132 #endif
133                 if (next_pos >= pos)
134                     break;
135
136                 i = next_pos;
137             }
138
139             pos = i;
140             break;
141         }
142
143         case SKEY_RIGHT:
144         case KTRL('f'):
145             color = TERM_WHITE;
146             if ('\0' == buf[pos])
147                 break;
148
149 #ifdef JP
150             if (iskanji(buf[pos]))
151                 pos += 2;
152             else
153                 pos++;
154 #else
155             pos++;
156 #endif
157             break;
158
159         case ESCAPE:
160             return 0;
161
162         case KTRL('r'):
163             back = TRUE;
164             /* Fall through */
165
166         case '\n':
167         case '\r':
168         case KTRL('s'):
169             if (*o_handle)
170                 return (back ? -1 : 1);
171             string_free(*search_strp);
172             *search_strp = string_make(buf);
173             *o_handle = NULL;
174             return (back ? -1 : 1);
175
176         case KTRL('i'):
177             return get_object_for_search(player_ptr, o_handle, search_strp);
178
179         case KTRL('l'):
180             if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
181                 return 1;
182             break;
183
184         case '\010': {
185             int i = 0;
186             color = TERM_WHITE;
187             if (pos == 0)
188                 break;
189
190             while (TRUE) {
191                 int next_pos = i + 1;
192 #ifdef JP
193                 if (iskanji(buf[i]))
194                     next_pos++;
195 #endif
196                 if (next_pos >= pos)
197                     break;
198
199                 i = next_pos;
200             }
201
202             pos = i;
203         }
204             /* Fall through */
205
206         case 0x7F:
207         case KTRL('d'): {
208             int dst, src;
209             color = TERM_WHITE;
210             if (buf[pos] == '\0')
211                 break;
212
213             src = pos + 1;
214 #ifdef JP
215             if (iskanji(buf[pos]))
216                 src++;
217 #endif
218             dst = pos;
219             while ('\0' != (buf[dst++] = buf[src++]))
220                 ;
221
222             break;
223         }
224
225         default: {
226             char tmp[100];
227             char c;
228             if (skey & SKEY_MASK)
229                 break;
230
231             c = (char)skey;
232             if (color != TERM_WHITE) {
233                 if (color == TERM_L_GREEN) {
234                     *o_handle = NULL;
235                     string_free(*search_strp);
236                     *search_strp = NULL;
237                 }
238
239                 buf[0] = '\0';
240                 color = TERM_WHITE;
241             }
242
243             strcpy(tmp, buf + pos);
244 #ifdef JP
245             if (iskanji(c)) {
246                 char next;
247                 inkey_base = TRUE;
248                 next = inkey();
249
250                 if (pos + 1 < len) {
251                     buf[pos++] = c;
252                     buf[pos++] = next;
253                 } else {
254                     bell();
255                 }
256             } else
257 #endif
258 #ifdef JP
259                 if (pos < len && (isprint(c) || iskana(c)))
260 #else
261             if (pos < len && isprint(c))
262 #endif
263             {
264                 buf[pos++] = c;
265             } else {
266                 bell();
267             }
268
269             buf[pos] = '\0';
270             angband_strcat(buf, tmp, len + 1);
271
272             break;
273         }
274         }
275
276         if (*o_handle == NULL || color == TERM_L_GREEN)
277             continue;
278
279         *o_handle = NULL;
280         buf[0] = '\0';
281         string_free(*search_strp);
282         *search_strp = NULL;
283     }
284 }
285
286 /*
287  * Search next line matches for o_ptr
288  */
289 void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward)
290 {
291     autopick_type an_entry, *entry = &an_entry;
292     GAME_TEXT o_name[MAX_NLEN];
293     int bypassed_cy = -1;
294     int i = tb->cy;
295     describe_flavor(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
296     str_tolower(o_name);
297
298     while (TRUE) {
299         bool match;
300         if (forward) {
301             if (!tb->lines_list[++i])
302                 break;
303         } else {
304             if (--i < 0)
305                 break;
306         }
307
308         if (!autopick_new_entry(entry, tb->lines_list[i], FALSE))
309             continue;
310
311         match = is_autopick_match(player_ptr, o_ptr, entry, o_name);
312         autopick_free_entry(entry);
313         if (!match)
314             continue;
315
316         if (tb->states[i] & LSTAT_BYPASS) {
317             if (bypassed_cy == -1)
318                 bypassed_cy = i;
319             continue;
320         }
321
322         tb->cx = 0;
323         tb->cy = i;
324         if (bypassed_cy != -1) {
325             tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
326         }
327
328         return;
329     }
330
331     if (bypassed_cy == -1) {
332         tb->dirty_flags |= DIRTY_NOT_FOUND;
333         return;
334     }
335
336     tb->cx = 0;
337     tb->cy = bypassed_cy;
338     tb->dirty_flags |= DIRTY_INACTIVE;
339 }
340
341 /*
342  * Search next line matches to the string
343  */
344 void search_for_string(text_body_type *tb, concptr search_str, bool forward)
345 {
346     int bypassed_cy = -1;
347     int bypassed_cx = 0;
348
349     int i = tb->cy;
350     while (TRUE) {
351         concptr pos;
352         if (forward) {
353             if (!tb->lines_list[++i])
354                 break;
355         } else {
356             if (--i < 0)
357                 break;
358         }
359
360         pos = angband_strstr(tb->lines_list[i], search_str);
361         if (!pos)
362             continue;
363
364         if ((tb->states[i] & LSTAT_BYPASS) && !(tb->states[i] & LSTAT_EXPRESSION)) {
365             if (bypassed_cy == -1) {
366                 bypassed_cy = i;
367                 bypassed_cx = (int)(pos - tb->lines_list[i]);
368             }
369
370             continue;
371         }
372
373         tb->cx = (int)(pos - tb->lines_list[i]);
374         tb->cy = i;
375
376         if (bypassed_cy != -1) {
377             tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
378         }
379
380         return;
381     }
382
383     if (bypassed_cy == -1) {
384         tb->dirty_flags |= DIRTY_NOT_FOUND;
385         return;
386     }
387
388     tb->cx = bypassed_cx;
389     tb->cy = bypassed_cy;
390     tb->dirty_flags |= DIRTY_INACTIVE;
391 }