OSDN Git Service

[Refactor] #40413 Incorporated MAX_RACES into player-race-types.h
[hengband/hengband.git] / src / autopick / autopick-drawer.c
1 /*!
2  * @brief 自動拾いエディタを表示させる
3  * @date 2020/04/26
4  * @author Hourier
5  */
6
7 #include "autopick/autopick-drawer.h"
8 #include "autopick/autopick-describer.h"
9 #include "autopick/autopick-dirty-flags.h"
10 #include "autopick/autopick-entry.h"
11 #include "io/pref-file-expressor.h"
12 #include "term/term-color-types.h"
13
14 #define DESCRIPT_HGT 3
15
16 static void process_dirty_expression(player_type *player_ptr, text_body_type *tb)
17 {
18         if ((tb->dirty_flags & DIRTY_EXPRESSION) == 0) return;
19
20         byte state = 0;
21         for (int y = 0; tb->lines_list[y]; y++)
22         {
23                 concptr s = tb->lines_list[y];
24                 char *ss, *s_keep;
25                 tb->states[y] = state;
26
27                 if (*s++ != '?') continue;
28                 if (*s++ != ':') continue;
29
30                 if (streq(s, "$AUTOREGISTER"))
31                         state |= LSTAT_AUTOREGISTER;
32
33                 int s_len = strlen(s);
34                 ss = (char *)string_make(s);
35                 s_keep = ss;
36
37                 char f;
38                 concptr v = process_pref_file_expr(player_ptr, &ss, &f);
39                 if (streq(v, "0")) state |= LSTAT_BYPASS;
40                 else state &= ~LSTAT_BYPASS;
41
42                 C_KILL(s_keep, s_len + 1, char);
43                 tb->states[y] = state | LSTAT_EXPRESSION;
44         }
45
46         tb->dirty_flags |= DIRTY_ALL;
47 }
48
49
50 /*
51  * Draw text
52  */
53 void draw_text_editor(player_type *player_ptr, text_body_type *tb)
54 {
55         int by1 = 0, by2 = 0;
56
57         Term_get_size(&tb->wid, &tb->hgt);
58
59         /*
60          * Top line (-1), description line (-3), separator (-1)
61          *  == -5
62          */
63         tb->hgt -= 2 + DESCRIPT_HGT;
64
65 #ifdef JP
66         /* Don't let cursor at second byte of kanji */
67         for (int i = 0; tb->lines_list[tb->cy][i]; i++)
68                 if (iskanji(tb->lines_list[tb->cy][i]))
69                 {
70                         i++;
71                         if (i == tb->cx)
72                         {
73                                 /*
74                                  * Move to a correct position in the
75                                  * left or right
76                                  */
77                                 if (i & 1) tb->cx--;
78                                 else tb->cx++;
79                                 break;
80                         }
81                 }
82 #endif
83         if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
84                 tb->upper = tb->cy - (tb->hgt) / 2;
85         if (tb->upper < 0)
86                 tb->upper = 0;
87         if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
88                 tb->left = tb->cx - (tb->wid) * 2 / 3;
89         if (tb->left < 0)
90                 tb->left = 0;
91
92         if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
93                 tb->dirty_flags |= DIRTY_SCREEN;
94         else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
95                 tb->dirty_flags |= DIRTY_ALL;
96
97         if (tb->dirty_flags & DIRTY_SCREEN)
98         {
99                 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
100                 Term_clear();
101         }
102
103         if (tb->dirty_flags & DIRTY_MODE)
104         {
105                 char buf[MAX_LINELEN];
106                 int sepa_length = tb->wid;
107                 int j = 0;
108                 for (; j < sepa_length; j++)
109                         buf[j] = '-';
110                 buf[j] = '\0';
111                 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
112         }
113
114         process_dirty_expression(player_ptr, tb);
115         if (tb->mark)
116         {
117                 tb->dirty_flags |= DIRTY_ALL;
118
119                 by1 = MIN(tb->my, tb->cy);
120                 by2 = MAX(tb->my, tb->cy);
121         }
122
123         int i;
124         for (i = 0; i < tb->hgt; i++)
125         {
126                 int leftcol = 0;
127                 concptr msg;
128                 byte color;
129                 int y = tb->upper + i;
130
131                 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
132                         continue;
133
134                 msg = tb->lines_list[y];
135                 if (!msg) break;
136
137                 for (int j = 0; *msg; msg++, j++)
138                 {
139                         if (j == tb->left) break;
140 #ifdef JP
141                         if (j > tb->left)
142                         {
143                                 leftcol = 1;
144                                 break;
145                         }
146                         if (iskanji(*msg))
147                         {
148                                 msg++;
149                                 j++;
150                         }
151 #endif
152                 }
153
154                 Term_erase(0, i + 1, tb->wid);
155                 if (tb->states[y] & LSTAT_AUTOREGISTER)
156                 {
157                         color = TERM_L_RED;
158                 }
159                 else
160                 {
161                         if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
162                         else color = TERM_WHITE;
163                 }
164
165                 if (!tb->mark || (y < by1 || by2 < y))
166                 {
167                         Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
168                 }
169                 else if (by1 != by2)
170                 {
171                         Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
172                 }
173                 else
174                 {
175                         int x0 = leftcol + tb->left;
176                         int len = strlen(tb->lines_list[tb->cy]);
177                         int bx1 = MIN(tb->mx, tb->cx);
178                         int bx2 = MAX(tb->mx, tb->cx);
179
180                         if (bx2 > len) bx2 = len;
181
182                         Term_gotoxy(leftcol, i + 1);
183                         if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
184                         if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
185                         Term_addstr(-1, color, msg + (bx2 - x0));
186                 }
187         }
188
189         for (; i < tb->hgt; i++)
190         {
191                 Term_erase(0, i + 1, tb->wid);
192         }
193
194         bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0;
195         bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy;
196         if (!is_updated) return;
197
198         autopick_type an_entry, *entry = &an_entry;
199         concptr str1 = NULL, str2 = NULL;
200         for (int j = 0; j < DESCRIPT_HGT; j++)
201         {
202                 Term_erase(0, tb->hgt + 2 + j, tb->wid);
203         }
204
205         if (tb->dirty_flags & DIRTY_NOT_FOUND)
206         {
207                 str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
208         }
209         else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
210         {
211                 str1 = format(_("無効状態の行をスキップしました。(%sを検索中)",
212                         "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
213         }
214         else if (tb->dirty_flags & DIRTY_INACTIVE)
215         {
216                 str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
217                         "Found only an inactive line. (Searching %s)"), tb->search_str);
218         }
219         else if (tb->dirty_flags & DIRTY_NO_SEARCH)
220         {
221                 str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
222         }
223         else if (tb->lines_list[tb->cy][0] == '#')
224         {
225                 str1 = _("この行はコメントです。", "This line is a comment.");
226         }
227         else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
228         {
229                 switch (tb->lines_list[tb->cy][0])
230                 {
231                 case '?':
232                         str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
233                         break;
234                 case 'A':
235                         str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
236                         break;
237                 case 'P':
238                         str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
239                         break;
240                 case 'C':
241                         str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
242                         break;
243                 }
244
245                 switch (tb->lines_list[tb->cy][0])
246                 {
247                 case '?':
248                         if (tb->states[tb->cy] & LSTAT_BYPASS)
249                         {
250                                 str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
251                         }
252                         else
253                         {
254                                 str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
255                         }
256                         break;
257
258                 default:
259                         if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
260                         {
261                                 str2 = _("この行は後で削除されます。", "This line will be delete later.");
262                         }
263
264                         else if (tb->states[tb->cy] & LSTAT_BYPASS)
265                         {
266                                 str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
267                         }
268                         break;
269                 }
270         }
271         else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
272         {
273                 char buf[MAX_LINELEN];
274                 char temp[MAX_LINELEN];
275                 concptr t;
276
277                 describe_autopick(buf, entry);
278
279                 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
280                 {
281                         strcat(buf, _("この行は後で削除されます。", "  This line will be delete later."));
282                 }
283
284                 if (tb->states[tb->cy] & LSTAT_BYPASS)
285                 {
286                         strcat(buf, _("この行は現在は無効な状態です。", "  This line is bypassed currently."));
287                 }
288
289                 roff_to_buf(buf, 81, temp, sizeof(temp));
290                 t = temp;
291                 for (int j = 0; j < 3; j++)
292                 {
293                         if (t[0] == 0)
294                                 break;
295                         else
296                         {
297                                 prt(t, tb->hgt + 1 + 1 + j, 0);
298                                 t += strlen(t) + 1;
299                         }
300                 }
301
302                 autopick_free_entry(entry);
303         }
304
305         if (str1) prt(str1, tb->hgt + 1 + 1, 0);
306         if (str2) prt(str2, tb->hgt + 1 + 2, 0);
307 }