OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / autopick / autopick-editor-util.c
1 #include "autopick/autopick-editor-util.h"
2 #include "autopick/autopick-flags-table.h"
3 #include "autopick/autopick-methods-table.h"
4 #include "autopick/autopick-dirty-flags.h"
5 #include "autopick/autopick-entry.h"
6 #include "autopick/autopick-key-flag-process.h"
7
8 /*
9  * Delete or insert string
10  */
11 void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
12 {
13         int by1, by2;
14         bool add = TRUE;
15         bool fixed = FALSE;
16         if (tb->mark)
17         {
18                 by1 = MIN(tb->my, tb->cy);
19                 by2 = MAX(tb->my, tb->cy);
20         }
21         else /* if (!tb->mark) */
22         {
23                 by1 = by2 = tb->cy;
24         }
25
26         for (int y = by1; y <= by2; y++)
27         {
28                 autopick_type an_entry, *entry = &an_entry;
29                 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
30
31                 string_free(tb->lines_list[y]);
32                 if (!fixed)
33                 {
34                         if (!IS_FLG(flg)) add = TRUE;
35                         else add = FALSE;
36
37                         fixed = TRUE;
38                 }
39
40                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
41                 {
42                         int i;
43                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
44                                 REM_FLG(i);
45                 }
46                 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
47                 {
48                         int i;
49                         for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
50                                 REM_FLG(i);
51                 }
52                 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
53                 {
54                         int i;
55                         for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
56                                 REM_FLG(i);
57                 }
58                 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
59                 {
60                         int i;
61                         for (i = FLG_RARE; i <= FLG_COMMON; i++)
62                                 REM_FLG(i);
63                 }
64
65                 if (add) ADD_FLG(flg);
66                 else REM_FLG(flg);
67
68                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
69                 tb->dirty_flags |= DIRTY_ALL;
70                 tb->changed = TRUE;
71         }
72 }
73
74
75 /*
76  * Change command letter
77  */
78 void toggle_command_letter(text_body_type *tb, byte flg)
79 {
80         autopick_type an_entry;
81         autopick_type *entry = &an_entry;
82         int by1, by2;
83         bool add = TRUE;
84         bool fixed = FALSE;
85         if (tb->mark)
86         {
87                 by1 = MIN(tb->my, tb->cy);
88                 by2 = MAX(tb->my, tb->cy);
89         }
90         else /* if (!tb->mark) */
91         {
92                 by1 = by2 = tb->cy;
93         }
94
95         for (int y = by1; y <= by2; y++)
96         {
97                 int wid = 0;
98
99                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
100
101                 string_free(tb->lines_list[y]);
102
103                 if (!fixed)
104                 {
105                         if (!(entry->action & flg)) add = TRUE;
106                         else add = FALSE;
107
108                         fixed = TRUE;
109                 }
110
111                 if (entry->action & DONT_AUTOPICK) wid--;
112                 else if (entry->action & DO_AUTODESTROY) wid--;
113                 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
114                 if (!(entry->action & DO_DISPLAY)) wid--;
115
116                 if (flg != DO_DISPLAY)
117                 {
118                         entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
119                         if (add) entry->action |= flg;
120                         else entry->action |= DO_AUTOPICK;
121                 }
122                 else
123                 {
124                         entry->action &= ~(DO_DISPLAY);
125                         if (add) entry->action |= flg;
126                 }
127
128                 if (tb->cy == y)
129                 {
130                         if (entry->action & DONT_AUTOPICK) wid++;
131                         else if (entry->action & DO_AUTODESTROY) wid++;
132                         else if (entry->action & DO_QUERY_AUTOPICK) wid++;
133                         if (!(entry->action & DO_DISPLAY)) wid++;
134
135                         if (wid > 0) tb->cx++;
136                         if (wid < 0 && tb->cx > 0) tb->cx--;
137                 }
138
139                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
140                 tb->dirty_flags |= DIRTY_ALL;
141                 tb->changed = TRUE;
142         }
143 }
144
145
146 /*
147  * Delete or insert string
148  */
149 void add_keyword(text_body_type *tb, BIT_FLAGS flg)
150 {
151         int by1, by2;
152         if (tb->mark)
153         {
154                 by1 = MIN(tb->my, tb->cy);
155                 by2 = MAX(tb->my, tb->cy);
156         }
157         else
158         {
159                 by1 = by2 = tb->cy;
160         }
161
162         for (int y = by1; y <= by2; y++)
163         {
164                 autopick_type an_entry, *entry = &an_entry;
165                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
166
167                 if (IS_FLG(flg))
168                 {
169                         autopick_free_entry(entry);
170                         continue;
171                 }
172
173                 string_free(tb->lines_list[y]);
174                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
175                 {
176                         int i;
177                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
178                                 REM_FLG(i);
179                 }
180
181                 ADD_FLG(flg);
182                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
183                 tb->dirty_flags |= DIRTY_ALL;
184                 tb->changed = TRUE;
185         }
186 }
187
188
189 /*
190  * Add an empty line at the last of the file
191  */
192 bool add_empty_line(text_body_type *tb)
193 {
194         int num_lines;
195         for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
196
197         if (num_lines >= MAX_LINES - 2) return FALSE;
198         if (!tb->lines_list[num_lines - 1][0]) return FALSE;
199
200         tb->lines_list[num_lines] = string_make("");
201         tb->dirty_flags |= DIRTY_EXPRESSION;
202         tb->changed = TRUE;
203         return TRUE;
204 }
205
206
207 static chain_str_type *new_chain_str(concptr str)
208 {
209         chain_str_type *chain;
210         size_t len = strlen(str);
211         chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
212         strcpy(chain->s, str);
213         chain->next = NULL;
214         return chain;
215 }
216
217
218 void kill_yank_chain(text_body_type *tb)
219 {
220         chain_str_type *chain = tb->yank;
221         tb->yank = NULL;
222         tb->yank_eol = TRUE;
223
224         while (chain)
225         {
226                 chain_str_type *next = chain->next;
227                 size_t len = strlen(chain->s);
228
229                 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
230
231                 chain = next;
232         }
233 }
234
235
236 void add_str_to_yank(text_body_type *tb, concptr str)
237 {
238         tb->yank_eol = FALSE;
239         if (NULL == tb->yank)
240         {
241                 tb->yank = new_chain_str(str);
242                 return;
243         }
244
245         chain_str_type *chain;
246         chain = tb->yank;
247
248         while (TRUE)
249         {
250                 if (!chain->next)
251                 {
252                         chain->next = new_chain_str(str);
253                         return;
254                 }
255
256                 /* Go to next */
257                 chain = chain->next;
258         }
259 }
260
261
262 /*
263  * Do work for the copy editor-command
264  */
265 void copy_text_to_yank(text_body_type *tb)
266 {
267         int len = strlen(tb->lines_list[tb->cy]);
268         if (tb->cx > len) tb->cx = len;
269
270         if (!tb->mark)
271         {
272                 tb->cx = 0;
273                 tb->my = tb->cy;
274                 tb->mx = len;
275         }
276
277         kill_yank_chain(tb);
278         if (tb->my != tb->cy)
279         {
280                 int by1 = MIN(tb->my, tb->cy);
281                 int by2 = MAX(tb->my, tb->cy);
282
283                 for (int y = by1; y <= by2; y++)
284                 {
285                         add_str_to_yank(tb, tb->lines_list[y]);
286                 }
287
288                 add_str_to_yank(tb, "");
289                 tb->mark = 0;
290                 tb->dirty_flags |= DIRTY_ALL;
291                 return;
292         }
293
294         char buf[MAX_LINELEN];
295         int bx1 = MIN(tb->mx, tb->cx);
296         int bx2 = MAX(tb->mx, tb->cx);
297         if (bx2 > len) bx2 = len;
298
299         if (bx1 == 0 && bx2 == len)
300         {
301                 add_str_to_yank(tb, tb->lines_list[tb->cy]);
302                 add_str_to_yank(tb, "");
303         }
304         else
305         {
306                 int end = bx2 - bx1;
307                 for (int i = 0; i < bx2 - bx1; i++)
308                 {
309                         buf[i] = tb->lines_list[tb->cy][bx1 + i];
310                 }
311
312                 buf[end] = '\0';
313                 add_str_to_yank(tb, buf);
314         }
315
316         tb->mark = 0;
317         tb->dirty_flags |= DIRTY_ALL;
318 }