This source file includes following definitions.
- etags_hash_free
- parse_define
- etags_set_definition_hash
- editcmd_dialog_select_definition_add
- editcmd_dialog_select_definition_show
- edit_get_match_keyword_cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <config.h>
34
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "lib/global.h"
41 #include "lib/fileloc.h"
42 #include "lib/tty/tty.h"
43 #include "lib/strutil.h"
44 #include "lib/util.h"
45
46 #include "editwidget.h"
47
48 #include "etags.h"
49
50
51
52
53
54
55
56
57
58
59
60 static int def_max_width;
61
62
63
64
65
66 static void
67 etags_hash_free (gpointer data)
68 {
69 etags_hash_t *hash = (etags_hash_t *) data;
70
71 g_free (hash->filename);
72 g_free (hash->fullpath);
73 g_free (hash->short_define);
74 g_free (hash);
75 }
76
77
78
79 static gboolean
80 parse_define (const char *buf, char **long_name, char **short_name, long *line)
81 {
82
83 enum
84 {
85 in_longname,
86 in_shortname,
87 in_shortname_first_char,
88 in_line,
89 finish
90 } def_state = in_longname;
91
92
93 GString *longdef = NULL;
94 GString *shortdef = NULL;
95 GString *linedef = NULL;
96
97 char c = *buf;
98
99 while (!(c == '\0' || c == '\n'))
100 {
101 switch (def_state)
102 {
103 case in_longname:
104 if (c == 0x01)
105 def_state = in_line;
106 else if (c == 0x7F)
107 def_state = in_shortname;
108 else
109 {
110 if (longdef == NULL)
111 longdef = g_string_sized_new (32);
112
113 g_string_append_c (longdef, c);
114 }
115 break;
116
117 case in_shortname_first_char:
118 if (isdigit (c))
119 {
120 if (shortdef == NULL)
121 shortdef = g_string_sized_new (32);
122 else
123 g_string_set_size (shortdef, 0);
124
125 buf--;
126 def_state = in_line;
127 }
128 else if (c == 0x01)
129 def_state = in_line;
130 else
131 {
132 if (shortdef == NULL)
133 shortdef = g_string_sized_new (32);
134
135 g_string_append_c (shortdef, c);
136 def_state = in_shortname;
137 }
138 break;
139
140 case in_shortname:
141 if (c == 0x01)
142 def_state = in_line;
143 else if (c == '\n')
144 def_state = finish;
145 else
146 {
147 if (shortdef == NULL)
148 shortdef = g_string_sized_new (32);
149
150 g_string_append_c (shortdef, c);
151 }
152 break;
153
154 case in_line:
155 if (c == ',' || c == '\n')
156 def_state = finish;
157 else if (isdigit (c))
158 {
159 if (linedef == NULL)
160 linedef = g_string_sized_new (32);
161
162 g_string_append_c (linedef, c);
163 }
164 break;
165
166 case finish:
167 *long_name = longdef == NULL ? NULL : g_string_free (longdef, FALSE);
168 *short_name = shortdef == NULL ? NULL : g_string_free (shortdef, FALSE);
169
170 if (linedef == NULL)
171 *line = 0;
172 else
173 {
174 *line = atol (linedef->str);
175 g_string_free (linedef, TRUE);
176 }
177 return TRUE;
178
179 default:
180 break;
181 }
182
183 buf++;
184 c = *buf;
185 }
186
187 *long_name = NULL;
188 *short_name = NULL;
189 *line = 0;
190
191 return FALSE;
192 }
193
194
195
196 static GPtrArray *
197 etags_set_definition_hash (const char *tagfile, const char *start_path, const char *match_func)
198 {
199
200 enum
201 {
202 start,
203 in_filename,
204 in_define
205 } state = start;
206
207
208 FILE *f;
209 char buf[BUF_LARGE];
210 char *filename = NULL;
211 GPtrArray *ret = NULL;
212
213 if (match_func == NULL || tagfile == NULL)
214 return NULL;
215
216
217 f = fopen (tagfile, "r");
218 if (f == NULL)
219 return NULL;
220
221 while (fgets (buf, sizeof (buf), f) != NULL)
222 switch (state)
223 {
224 case start:
225 if (buf[0] == 0x0C)
226 state = in_filename;
227 break;
228
229 case in_filename:
230 {
231 size_t pos;
232
233 pos = strcspn (buf, ",");
234 g_free (filename);
235 filename = g_strndup (buf, pos);
236 state = in_define;
237 break;
238 }
239
240 case in_define:
241 if (buf[0] == 0x0C)
242 state = in_filename;
243 else
244 {
245 char *chekedstr;
246
247
248 chekedstr = strstr (buf, match_func);
249 if (chekedstr != NULL)
250 {
251 char *longname = NULL;
252 char *shortname = NULL;
253 etags_hash_t *def_hash;
254
255 def_hash = g_new (etags_hash_t, 1);
256
257 def_hash->fullpath = mc_build_filename (start_path, filename, (char *) NULL);
258 def_hash->filename = g_strdup (filename);
259
260 def_hash->line = 0;
261
262 parse_define (chekedstr, &longname, &shortname, &def_hash->line);
263
264 if (shortname != NULL && *shortname != '\0')
265 {
266 def_hash->short_define = shortname;
267 g_free (longname);
268 }
269 else
270 {
271 def_hash->short_define = longname;
272 g_free (shortname);
273 }
274
275 if (ret == NULL)
276 ret = g_ptr_array_new_with_free_func (etags_hash_free);
277
278 g_ptr_array_add (ret, def_hash);
279 }
280 }
281 break;
282
283 default:
284 break;
285 }
286
287 g_free (filename);
288 fclose (f);
289
290 return ret;
291 }
292
293
294
295 static void
296 editcmd_dialog_select_definition_add (gpointer data, gpointer user_data)
297 {
298 etags_hash_t *def_hash = (etags_hash_t *) data;
299 WListbox *def_list = (WListbox *) user_data;
300 char *label_def;
301 int def_width;
302
303 label_def =
304 g_strdup_printf ("%s -> %s:%ld", def_hash->short_define, def_hash->filename,
305 def_hash->line);
306 listbox_add_item_take (def_list, LISTBOX_APPEND_AT_END, 0, label_def, def_hash, FALSE);
307 def_width = str_term_width1 (label_def);
308 def_max_width = MAX (def_max_width, def_width);
309 }
310
311
312
313
314 static void
315 editcmd_dialog_select_definition_show (WEdit *edit, char *match_expr, GPtrArray *def_hash)
316 {
317 const WRect *w = &CONST_WIDGET (edit)->rect;
318 int start_x, start_y, offset;
319 char *curr = NULL;
320 WDialog *def_dlg;
321 WListbox *def_list;
322 int def_dlg_h;
323 int def_dlg_w;
324
325
326 def_dlg_h = def_hash->len + 2;
327 def_dlg_w = COLS - 2;
328 start_x = w->x + edit->curs_col + edit->start_col + EDIT_TEXT_HORIZONTAL_OFFSET +
329 (edit->fullscreen ? 0 : 1) + edit_options.line_state_width;
330 start_y = w->y + edit->curs_row + EDIT_TEXT_VERTICAL_OFFSET + (edit->fullscreen ? 0 : 1) + 1;
331
332 if (start_x < 0)
333 start_x = 0;
334 if (start_x < w->x + 1)
335 start_x = w->x + 1 + edit_options.line_state_width;
336
337 if (def_dlg_h > LINES - 2)
338 def_dlg_h = LINES - 2;
339
340 offset = start_y + def_dlg_h - LINES;
341 if (offset > 0)
342 start_y -= (offset + 1);
343
344 def_dlg = dlg_create (TRUE, start_y, start_x, def_dlg_h, def_dlg_w, WPOS_KEEP_DEFAULT, TRUE,
345 dialog_colors, NULL, NULL, "[Definitions]", match_expr);
346 def_list = listbox_new (1, 1, def_dlg_h - 2, def_dlg_w - 2, FALSE, NULL);
347 group_add_widget_autopos (GROUP (def_dlg), def_list, WPOS_KEEP_ALL, NULL);
348
349
350 def_max_width = 0;
351 g_ptr_array_foreach (def_hash, editcmd_dialog_select_definition_add, def_list);
352
353
354 def_dlg_w = def_max_width + 4;
355 offset = start_x + def_dlg_w - COLS;
356 if (offset > 0)
357 start_x -= offset;
358
359 widget_set_size (WIDGET (def_dlg), start_y, start_x, def_dlg_h, def_dlg_w);
360
361
362 if (dlg_run (def_dlg) == B_ENTER)
363 {
364 etags_hash_t *curr_def = NULL;
365 gboolean do_moveto = FALSE;
366
367 listbox_get_current (def_list, &curr, (void **) &curr_def);
368
369 if (!edit->modified)
370 do_moveto = TRUE;
371 else if (!edit_query_dialog2
372 (_("Warning"),
373 _("Current text was modified without a file save.\n"
374 "Continue discards these changes."), _("C&ontinue"), _("&Cancel")))
375 {
376 edit->force |= REDRAW_COMPLETELY;
377 do_moveto = TRUE;
378 }
379
380 if (curr != NULL && do_moveto && edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
381 {
382 vfs_path_t *vpath;
383
384
385 if (edit->filename_vpath != NULL && edit->filename_vpath->relative
386 && edit->dir_vpath != NULL)
387 vpath = vfs_path_append_vpath_new (edit->dir_vpath, edit->filename_vpath, NULL);
388 else
389 vpath = vfs_path_clone (edit->filename_vpath);
390
391 edit_arg_assign (&edit_history_moveto[edit_stack_iterator], vpath,
392 edit->start_line + edit->curs_row + 1);
393 edit_stack_iterator++;
394 edit_arg_assign (&edit_history_moveto[edit_stack_iterator],
395 vfs_path_from_str ((char *) curr_def->fullpath), curr_def->line);
396 edit_reload_line (edit, &edit_history_moveto[edit_stack_iterator]);
397 }
398 }
399
400
401 widget_destroy (WIDGET (def_dlg));
402 }
403
404
405
406
407
408 void
409 edit_get_match_keyword_cmd (WEdit *edit)
410 {
411 gsize word_len = 0;
412 gsize i;
413 off_t word_start = 0;
414 GString *match_expr;
415 char *path = NULL;
416 char *ptr = NULL;
417 char *tagfile = NULL;
418 GPtrArray *def_hash = NULL;
419
420
421 if (!edit_buffer_find_word_start (&edit->buffer, &word_start, &word_len))
422 return;
423
424
425 match_expr = g_string_sized_new (word_len);
426 for (i = 0; i < word_len; i++)
427 g_string_append_c (match_expr, edit_buffer_get_byte (&edit->buffer, word_start + i));
428
429 ptr = my_get_current_dir ();
430 path = g_strconcat (ptr, PATH_SEP_STR, (char *) NULL);
431 g_free (ptr);
432
433
434 do
435 {
436 ptr = g_path_get_dirname (path);
437 g_free (path);
438 path = ptr;
439 g_free (tagfile);
440 tagfile = mc_build_filename (path, TAGS_NAME, (char *) NULL);
441 if (tagfile != NULL && exist_file (tagfile))
442 break;
443 }
444 while (strcmp (path, PATH_SEP_STR) != 0);
445
446 if (tagfile != NULL)
447 {
448 def_hash = etags_set_definition_hash (tagfile, path, match_expr->str);
449 g_free (tagfile);
450 }
451 g_free (path);
452
453 if (def_hash != NULL)
454 {
455 editcmd_dialog_select_definition_show (edit, match_expr->str, def_hash);
456
457 g_ptr_array_free (def_hash, TRUE);
458 }
459
460 g_string_free (match_expr, TRUE);
461 }
462
463