OSDN Git Service

[Refactor] #40413 Separated buffer-shper.c/h from util.c/h
[hengband/hengband.git] / src / autopick / autopick-finder.c
1 /*!
2  * todo get_string_for_search() \82Í\92·\82¢\81A\97v\95ª\8a\84
3  * @brief \8e©\93®\8fE\82¢\82Ì\8c\9f\8dõ
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 "inventory/player-inventory.h"
14 #include "io/input-key-acceptor.h"
15 #include "main/sound-of-music.h"
16 #include "object/item-use-flags.h"
17 #include "object/object-flavor.h"
18 #include "term/screen-processor.h"
19 #include "term/term-color-types.h"
20 #include "util/int-char-converter.h"
21 #include "util/string-processor.h"
22
23  /*
24   * @brief \97^\82¦\82ç\82ê\82½\83A\83C\83e\83\80\82ª\8e©\93®\8fE\82¢\82Ì\83\8a\83X\83g\82É\93o\98^\82³\82ê\82Ä\82¢\82é\82©\82Ç\82¤\82©\82ð\8c\9f\8dõ\82·\82é
25   * @param player_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
26   * @o_ptr \83A\83C\83e\83\80\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
27   * @return \8e©\93®\8fE\82¢\82Ì\83\8a\83X\83g\82É\93o\98^\82³\82ê\82Ä\82¢\82½\82ç\82»\82Ì\93o\98^\94Ô\8d\86\81A\82È\82©\82Á\82½\82ç-1
28   * @details
29   * A function for Auto-picker/destroyer
30   * Examine whether the object matches to the list of keywords or not.
31   */
32 int find_autopick_list(player_type *player_ptr, object_type *o_ptr)
33 {
34         GAME_TEXT o_name[MAX_NLEN];
35         if (o_ptr->tval == TV_GOLD) return -1;
36
37         object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
38         str_tolower(o_name);
39         for (int i = 0; i < max_autopick; i++)
40         {
41                 autopick_type *entry = &autopick_list[i];
42                 if (is_autopick_match(player_ptr, o_ptr, entry, o_name))
43                         return i;
44         }
45
46         return -1;
47 }
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 = _("\82Ç\82Ì\83A\83C\83e\83\80\82ð\8c\9f\8dõ\82µ\82Ü\82·\82©? ", "Enter which item? ");
56         concptr s = _("\83A\83C\83e\83\80\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81B", "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, 0);
59         if (!o_ptr) return FALSE;
60
61         *o_handle = o_ptr;
62         string_free(*search_strp);
63         char buf[MAX_NLEN + 20];
64         object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
65         *search_strp = string_make(format("<%s>", buf));
66         return TRUE;
67 }
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) return FALSE;
76
77         *o_handle = &autopick_last_destroyed_object;
78         string_free(*search_strp);
79         char buf[MAX_NLEN + 20];
80         object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
81         *search_strp = string_make(format("<%s>", buf));
82         return TRUE;
83 }
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[] = _("\8c\9f\8dõ(^I:\8e\9d\82¿\95¨ ^L:\94j\89ó\82³\82ê\82½\95¨): ", "Search key(^I:inven ^L:destroyed): ");
100         int col = sizeof(prompt) - 1;
101         if (*search_strp) strcpy(buf, *search_strp);
102         else buf[0] = '\0';
103
104         if (*o_handle) color = TERM_L_GREEN;
105
106         prt(prompt, 0, 0);
107         int pos = 0;
108         while (TRUE)
109         {
110                 bool back = FALSE;
111                 Term_erase(col, 0, 255);
112                 Term_putstr(col, 0, -1, color, buf);
113                 Term_gotoxy(col + pos, 0);
114
115                 int skey = inkey_special(TRUE);
116                 switch (skey)
117                 {
118                 case SKEY_LEFT:
119                 case KTRL('b'):
120                 {
121                         int i = 0;
122                         color = TERM_WHITE;
123                         if (pos == 0) break;
124
125                         while (TRUE)
126                         {
127                                 int next_pos = i + 1;
128
129 #ifdef JP
130                                 if (iskanji(buf[i])) next_pos++;
131 #endif
132                                 if (next_pos >= pos) break;
133
134                                 i = next_pos;
135                         }
136
137                         pos = i;
138                         break;
139                 }
140
141                 case SKEY_RIGHT:
142                 case KTRL('f'):
143                         color = TERM_WHITE;
144                         if ('\0' == buf[pos]) break;
145
146 #ifdef JP
147                         if (iskanji(buf[pos])) pos += 2;
148                         else pos++;
149 #else
150                         pos++;
151 #endif
152                         break;
153
154                 case ESCAPE:
155                         return 0;
156
157                 case KTRL('r'):
158                         back = TRUE;
159                         /* Fall through */
160
161                 case '\n':
162                 case '\r':
163                 case KTRL('s'):
164                         if (*o_handle) return (back ? -1 : 1);
165                         string_free(*search_strp);
166                         *search_strp = string_make(buf);
167                         *o_handle = NULL;
168                         return (back ? -1 : 1);
169
170                 case KTRL('i'):
171                         return get_object_for_search(player_ptr, o_handle, search_strp);
172
173                 case KTRL('l'):
174                         if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
175                                 return 1;
176                         break;
177
178                 case '\010':
179                 {
180                         int i = 0;
181                         color = TERM_WHITE;
182                         if (pos == 0) break;
183
184                         while (TRUE)
185                         {
186                                 int next_pos = i + 1;
187 #ifdef JP
188                                 if (iskanji(buf[i])) next_pos++;
189 #endif
190                                 if (next_pos >= pos) break;
191
192                                 i = next_pos;
193                         }
194
195                         pos = i;
196                 }
197                 /* Fall through */
198
199                 case 0x7F:
200                 case KTRL('d'):
201                 {
202                         int dst, src;
203                         color = TERM_WHITE;
204                         if (buf[pos] == '\0') break;
205
206                         src = pos + 1;
207 #ifdef JP
208                         if (iskanji(buf[pos])) src++;
209 #endif
210                         dst = pos;
211                         while ('\0' != (buf[dst++] = buf[src++]));
212
213                         break;
214                 }
215
216                 default:
217                 {
218                         char tmp[100];
219                         char c;
220                         if (skey & SKEY_MASK) break;
221
222                         c = (char)skey;
223                         if (color != TERM_WHITE)
224                         {
225                                 if (color == TERM_L_GREEN)
226                                 {
227                                         *o_handle = NULL;
228                                         string_free(*search_strp);
229                                         *search_strp = NULL;
230                                 }
231
232                                 buf[0] = '\0';
233                                 color = TERM_WHITE;
234                         }
235
236                         strcpy(tmp, buf + pos);
237 #ifdef JP
238                         if (iskanji(c))
239                         {
240                                 char next;
241                                 inkey_base = TRUE;
242                                 next = inkey();
243
244                                 if (pos + 1 < len)
245                                 {
246                                         buf[pos++] = c;
247                                         buf[pos++] = next;
248                                 }
249                                 else
250                                 {
251                                         bell();
252                                 }
253                         }
254                         else
255 #endif
256 #ifdef JP
257                         if (pos < len && (isprint(c) || iskana(c)))
258 #else
259                         if (pos < len && isprint(c))
260 #endif
261                         {
262                                 buf[pos++] = c;
263                         }
264                         else
265                         {
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) continue;
277
278                 *o_handle = NULL;
279                 buf[0] = '\0';
280                 string_free(*search_strp);
281                 *search_strp = NULL;
282         }
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         object_desc(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         {
300                 bool match;
301                 if (forward)
302                 {
303                         if (!tb->lines_list[++i]) break;
304                 }
305                 else
306                 {
307                         if (--i < 0) break;
308                 }
309
310                 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
311
312                 match = is_autopick_match(player_ptr, o_ptr, entry, o_name);
313                 autopick_free_entry(entry);
314                 if (!match)     continue;
315
316                 if (tb->states[i] & LSTAT_BYPASS)
317                 {
318                         if (bypassed_cy == -1) bypassed_cy = i;
319                         continue;
320                 }
321
322                 tb->cx = 0;
323                 tb->cy = i;
324                 if (bypassed_cy != -1)
325                 {
326                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
327                 }
328
329                 return;
330         }
331
332         if (bypassed_cy == -1)
333         {
334                 tb->dirty_flags |= DIRTY_NOT_FOUND;
335                 return;
336         }
337
338         tb->cx = 0;
339         tb->cy = bypassed_cy;
340         tb->dirty_flags |= DIRTY_INACTIVE;
341 }
342
343
344 /*
345  * Search next line matches to the string
346  */
347 void search_for_string(text_body_type *tb, concptr search_str, bool forward)
348 {
349         int bypassed_cy = -1;
350         int bypassed_cx = 0;
351
352         int i = tb->cy;
353         while (TRUE)
354         {
355                 concptr pos;
356                 if (forward)
357                 {
358                         if (!tb->lines_list[++i]) break;
359                 }
360                 else
361                 {
362                         if (--i < 0) break;
363                 }
364
365                 pos = angband_strstr(tb->lines_list[i], search_str);
366                 if (!pos) continue;
367
368                 if ((tb->states[i] & LSTAT_BYPASS) &&
369                         !(tb->states[i] & LSTAT_EXPRESSION))
370                 {
371                         if (bypassed_cy == -1)
372                         {
373                                 bypassed_cy = i;
374                                 bypassed_cx = (int)(pos - tb->lines_list[i]);
375                         }
376
377                         continue;
378                 }
379
380                 tb->cx = (int)(pos - tb->lines_list[i]);
381                 tb->cy = i;
382
383                 if (bypassed_cy != -1)
384                 {
385                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
386                 }
387
388                 return;
389         }
390
391         if (bypassed_cy == -1)
392         {
393                 tb->dirty_flags |= DIRTY_NOT_FOUND;
394                 return;
395         }
396
397         tb->cx = bypassed_cx;
398         tb->cy = bypassed_cy;
399         tb->dirty_flags |= DIRTY_INACTIVE;
400 }