OSDN Git Service

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