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