194
198
hbox = gtk_hbox_new(TRUE, 6);
195
199
gtk_container_add(GTK_CONTAINER(hbox), fbox);
196
200
gtk_container_add(GTK_CONTAINER(hbox), mbox);
197
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 6);
201
void search_show_find_dialog()
205
static void send_find_dialog_response(GtkButton *button, gpointer user_data)
207
gtk_dialog_response(GTK_DIALOG(widgets.find_dialog), GPOINTER_TO_INT(user_data));
211
/* store text, clear search flags so we can use Search->Find Next/Previous */
212
static void setup_find_next(const gchar *text)
214
g_free(search_data.text);
215
search_data.text = g_strdup(text);
216
search_data.flags = 0;
217
search_data.backwards = FALSE;
218
search_data.search_bar = FALSE;
222
/* Search for next match of the current "selection"
223
* For X11 based systems, this will try to use the system-wide
224
* x-selection first. If it doesn't find anything suitable in
225
* the x-selection (or if we are on Win32) it will try to use
226
* the scintilla selection or current token instead.
227
* Search flags are always zero.
229
void search_find_selection(gint idx, gboolean search_backwards)
233
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
236
g_return_if_fail(DOC_IDX_VALID(idx));
239
s=gtk_clipboard_wait_for_text(clipboard);
242
if (strchr(s,'\n') || strchr(s, '\r'))
251
s=editor_get_default_selection(idx, TRUE, NULL);
255
setup_find_next(s); /* allow find next/prev */
257
if (document_find_text(idx, s, 0, search_backwards, FALSE, NULL) > -1)
258
editor_display_current_line(idx, 0.3F);
264
/* this will load a GTK rc style to set a monospace font for text fields(GtkEntry) in all
265
* search dialogs. This needs to be done only once.
266
* The monospace font should increase readibility of regular expressions containing spaces, points,
267
* commas and similar (#1907117). */
268
static void load_monospace_style()
270
static const gchar *rcstyle =
271
"style \"geany-monospace\"\n" \
273
" font_name=\"Monospace\"\n" \
275
"widget \"GeanyDialogSearch.*.GtkEntry\" style \"geany-monospace\"";
276
static gboolean load = TRUE;
280
gtk_rc_parse_string(rcstyle);
286
void search_show_find_dialog(void)
203
288
gint idx = document_get_cur_idx();
204
289
gchar *sel = NULL;
206
if (idx == -1 || ! doc_list[idx].is_valid) return;
291
g_return_if_fail(DOC_IDX_VALID(idx));
208
if (sci_get_lines_selected(doc_list[idx].sci) == 1)
210
sel = g_malloc(sci_get_selected_text_length(doc_list[idx].sci));
211
sci_get_selected_text(doc_list[idx].sci, sel);
293
sel = editor_get_default_selection(idx, prefs.search_use_current_word, NULL);
214
295
if (widgets.find_dialog == NULL)
216
GtkWidget *label, *entry, *sbox, *align;
297
GtkWidget *label, *entry, *sbox, *vbox;
298
GtkWidget *exp, *bbox, *button, *check_close;
299
GtkTooltips *tooltips = GTK_TOOLTIPS(lookup_widget(app->window, "tooltips"));
301
load_monospace_style();
218
303
widgets.find_dialog = gtk_dialog_new_with_buttons(_("Find"),
219
304
GTK_WINDOW(app->window), GTK_DIALOG_DESTROY_WITH_PARENT,
220
GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
221
GTK_STOCK_FIND, GTK_RESPONSE_ACCEPT, NULL);
223
label = gtk_label_new(_("Search for:"));
305
GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, NULL);
306
vbox = ui_dialog_vbox_new(GTK_DIALOG(widgets.find_dialog));
307
gtk_widget_set_name(widgets.find_dialog, "GeanyDialogSearch");
308
gtk_box_set_spacing(GTK_BOX(vbox), 9);
310
button = ui_button_new_with_image(GTK_STOCK_GO_BACK, _("_Previous"));
311
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.find_dialog), button,
312
GEANY_RESPONSE_FIND_PREVIOUS);
313
g_object_set_data_full(G_OBJECT(widgets.find_dialog), "btn_previous",
314
gtk_widget_ref(button), (GDestroyNotify)gtk_widget_unref);
316
button = ui_button_new_with_image(GTK_STOCK_GO_FORWARD, _("_Next"));
317
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.find_dialog), button,
318
GEANY_RESPONSE_FIND);
320
label = gtk_label_new_with_mnemonic(_("_Search for:"));
224
321
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
226
323
entry = gtk_combo_box_entry_new_text();
324
gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry);
227
325
gtk_entry_set_max_length(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry))), 248);
228
326
gtk_entry_set_width_chars(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry))), 50);
229
327
if (sel) gtk_entry_set_text(GTK_ENTRY(GTK_BIN(entry)->child), sel);
235
333
g_signal_connect((gpointer) widgets.find_dialog, "response",
236
334
G_CALLBACK(on_find_dialog_response), entry);
237
335
g_signal_connect((gpointer) widgets.find_dialog, "delete_event",
238
G_CALLBACK(gtk_widget_hide), NULL);
336
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
240
338
sbox = gtk_hbox_new(FALSE, 6);
241
339
gtk_box_pack_start(GTK_BOX(sbox), label, FALSE, FALSE, 0);
242
340
gtk_box_pack_start(GTK_BOX(sbox), entry, TRUE, TRUE, 0);
243
align = gtk_alignment_new(0, 0, 1, 0);
244
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 6, 0, 0, 0);
245
gtk_container_add(GTK_CONTAINER(align), sbox);
246
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(widgets.find_dialog)->vbox), align);
248
add_find_checkboxes(GTK_DIALOG(widgets.find_dialog));
250
gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(widgets.find_dialog)->vbox), 3);
341
gtk_box_pack_start(GTK_BOX(vbox), sbox, TRUE, FALSE, 0);
343
gtk_container_add(GTK_CONTAINER(vbox),
344
add_find_checkboxes(GTK_DIALOG(widgets.find_dialog)));
346
/* Now add the multiple match options */
347
exp = gtk_expander_new_with_mnemonic(_("_Find All"));
348
bbox = gtk_hbutton_box_new();
350
button = gtk_button_new_with_mnemonic(_("_Mark"));
351
gtk_tooltips_set_tip(tooltips, button,
352
_("Mark all matches in the current document."), NULL);
353
gtk_container_add(GTK_CONTAINER(bbox), button);
354
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_find_dialog_response),
355
GINT_TO_POINTER(GEANY_RESPONSE_MARK));
357
button = gtk_button_new_with_mnemonic(_("In Sessi_on"));
358
gtk_container_add(GTK_CONTAINER(bbox), button);
359
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_find_dialog_response),
360
GINT_TO_POINTER(GEANY_RESPONSE_FIND_IN_SESSION));
362
button = gtk_button_new_with_mnemonic(_("_In Document"));
363
gtk_container_add(GTK_CONTAINER(bbox), button);
364
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_find_dialog_response),
365
GINT_TO_POINTER(GEANY_RESPONSE_FIND_IN_FILE));
367
/* close window checkbox */
368
check_close = gtk_check_button_new_with_mnemonic(_("Close _dialog"));
369
g_object_set_data_full(G_OBJECT(widgets.find_dialog), "check_close",
370
gtk_widget_ref(check_close), (GDestroyNotify) gtk_widget_unref);
371
gtk_button_set_focus_on_click(GTK_BUTTON(check_close), FALSE);
372
gtk_tooltips_set_tip(tooltips, check_close,
373
_("Disable this option to keep the dialog open."), NULL);
374
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_close), TRUE);
375
gtk_container_add(GTK_CONTAINER(bbox), check_close);
376
gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(bbox), check_close, TRUE);
378
ui_hbutton_box_copy_layout(
379
GTK_BUTTON_BOX(GTK_DIALOG(widgets.find_dialog)->action_area),
380
GTK_BUTTON_BOX(bbox));
381
gtk_container_add(GTK_CONTAINER(exp), bbox);
382
gtk_container_add(GTK_CONTAINER(vbox), exp);
252
384
gtk_widget_show_all(widgets.find_dialog);
256
if (sel) gtk_entry_set_text(GTK_ENTRY(GTK_BIN(
388
/* only set selection if the dialog is not already visible */
389
if (! GTK_WIDGET_VISIBLE(widgets.find_dialog) && sel)
390
gtk_entry_set_text(GTK_ENTRY(GTK_BIN(
257
391
lookup_widget(widgets.find_dialog, "entry"))->child), sel);
258
392
gtk_widget_grab_focus(GTK_WIDGET(GTK_BIN(lookup_widget(widgets.find_dialog, "entry"))->child));
259
393
gtk_widget_show(widgets.find_dialog);
394
/* bring the dialog back in the foreground in case it is already open but the focus is away */
395
gtk_window_present(GTK_WINDOW(widgets.find_dialog));
265
void search_show_replace_dialog()
401
static void send_replace_dialog_response(GtkButton *button, gpointer user_data)
403
gtk_dialog_response(GTK_DIALOG(widgets.replace_dialog), GPOINTER_TO_INT(user_data));
407
void search_show_replace_dialog(void)
267
409
gint idx = document_get_cur_idx();
268
410
gchar *sel = NULL;
270
412
if (idx == -1 || ! doc_list[idx].is_valid) return;
272
if (sci_get_lines_selected(doc_list[idx].sci) == 1)
274
sel = g_malloc(sci_get_selected_text_length(doc_list[idx].sci));
275
sci_get_selected_text(doc_list[idx].sci, sel);
414
sel = editor_get_default_selection(idx, prefs.search_use_current_word, NULL);
278
416
if (widgets.replace_dialog == NULL)
280
418
GtkWidget *label_find, *label_replace, *entry_find, *entry_replace,
281
*checkbox6, *checkbox8, *button, *align, *rbox, *fbox, *hbox;
282
GtkSizeGroup *size_group;
419
*check_close, *button, *rbox, *fbox, *vbox, *exp, *bbox;
420
GtkSizeGroup *label_size;
283
421
GtkTooltips *tooltips = GTK_TOOLTIPS(lookup_widget(app->window, "tooltips"));
423
load_monospace_style();
285
425
widgets.replace_dialog = gtk_dialog_new_with_buttons(_("Replace"),
286
426
GTK_WINDOW(app->window), GTK_DIALOG_DESTROY_WITH_PARENT,
287
427
GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, NULL);
428
vbox = ui_dialog_vbox_new(GTK_DIALOG(widgets.replace_dialog));
429
gtk_box_set_spacing(GTK_BOX(vbox), 9);
430
gtk_widget_set_name(widgets.replace_dialog, "GeanyDialogSearch");
289
button = gtk_button_new_with_mnemonic(_("_In Selection"));
290
gtk_tooltips_set_tip(tooltips, button,
291
_("Replace all matches found in the currently selected text"), NULL);
292
gtk_widget_show(button);
293
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.replace_dialog), button,
294
GEANY_RESPONSE_REPLACE_SEL);
295
button = gtk_button_new_with_mnemonic(_("Replace _All"));
296
gtk_widget_show(button);
297
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.replace_dialog), button,
298
GEANY_RESPONSE_REPLACE_ALL);
299
432
button = gtk_button_new_from_stock(GTK_STOCK_FIND);
300
gtk_widget_show(button);
301
433
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.replace_dialog), button,
302
434
GEANY_RESPONSE_FIND);
303
435
button = gtk_button_new_with_mnemonic(_("_Replace"));
304
gtk_widget_show(button);
305
436
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.replace_dialog), button,
306
437
GEANY_RESPONSE_REPLACE);
438
button = gtk_button_new_with_mnemonic(_("Replace & Fi_nd"));
439
gtk_dialog_add_action_widget(GTK_DIALOG(widgets.replace_dialog), button,
440
GEANY_RESPONSE_REPLACE_AND_FIND);
308
label_find = gtk_label_new(_("Search for:"));
442
label_find = gtk_label_new_with_mnemonic(_("_Search for:"));
309
443
gtk_misc_set_alignment(GTK_MISC(label_find), 0, 0.5);
311
label_replace = gtk_label_new(_("Replace with:"));
445
label_replace = gtk_label_new_with_mnemonic(_("Replace wit_h:"));
312
446
gtk_misc_set_alignment(GTK_MISC(label_replace), 0, 0.5);
314
448
entry_find = gtk_combo_box_entry_new_text();
449
gtk_label_set_mnemonic_widget(GTK_LABEL(label_find), entry_find);
315
450
gtk_entry_set_max_length(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_find))), 248);
316
451
gtk_entry_set_width_chars(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_find))), 50);
317
452
if (sel) gtk_entry_set_text(GTK_ENTRY(GTK_BIN(entry_find)->child), sel);
319
454
gtk_widget_ref(entry_find), (GDestroyNotify)gtk_widget_unref);
321
456
entry_replace = gtk_combo_box_entry_new_text();
457
gtk_label_set_mnemonic_widget(GTK_LABEL(label_replace), entry_replace);
322
458
gtk_entry_set_max_length(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_replace))), 248);
323
459
gtk_entry_set_width_chars(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_replace))), 50);
324
460
g_object_set_data_full(G_OBJECT(widgets.replace_dialog), "entry_replace",
325
461
gtk_widget_ref(entry_replace), (GDestroyNotify)gtk_widget_unref);
327
g_signal_connect((gpointer) gtk_bin_get_child(GTK_BIN(entry_find)), "key-press-event",
328
G_CALLBACK(on_combo_entry_key_pressed), gtk_bin_get_child(GTK_BIN(entry_replace)));
463
g_signal_connect((gpointer) gtk_bin_get_child(GTK_BIN(entry_find)),
464
"key-press-event", G_CALLBACK(on_widget_key_pressed_set_focus),
465
gtk_bin_get_child(GTK_BIN(entry_replace)));
329
466
g_signal_connect((gpointer) gtk_bin_get_child(GTK_BIN(entry_replace)), "activate",
330
467
G_CALLBACK(on_replace_entry_activate), NULL);
331
468
g_signal_connect((gpointer) widgets.replace_dialog, "response",
332
469
G_CALLBACK(on_replace_dialog_response), entry_replace);
333
470
g_signal_connect((gpointer) widgets.replace_dialog, "delete_event",
334
G_CALLBACK(gtk_widget_hide), NULL);
471
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
336
473
fbox = gtk_hbox_new(FALSE, 6);
337
474
gtk_box_pack_start(GTK_BOX(fbox), label_find, FALSE, FALSE, 0);
338
475
gtk_box_pack_start(GTK_BOX(fbox), entry_find, TRUE, TRUE, 0);
339
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(widgets.replace_dialog)->vbox), fbox,
342
477
rbox = gtk_hbox_new(FALSE, 6);
343
478
gtk_box_pack_start(GTK_BOX(rbox), label_replace, FALSE, FALSE, 0);
344
479
gtk_box_pack_start(GTK_BOX(rbox), entry_replace, TRUE, TRUE, 0);
345
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(widgets.replace_dialog)->vbox), rbox,
348
size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
349
gtk_size_group_add_widget(size_group, label_find);
350
gtk_size_group_add_widget(size_group, label_replace);
351
g_object_unref(G_OBJECT(size_group)); // auto destroy the size group
353
add_find_checkboxes(GTK_DIALOG(widgets.replace_dialog));
355
checkbox6 = gtk_check_button_new_with_mnemonic(_("Replace in all _open files"));
356
g_object_set_data_full(G_OBJECT(widgets.replace_dialog), "check_all_buffers",
357
gtk_widget_ref(checkbox6), (GDestroyNotify)gtk_widget_unref);
358
gtk_tooltips_set_tip(tooltips, checkbox6,
359
_("Replaces the search text in all opened files. This option is only useful(and used) if you click on \"Replace All\"."), NULL);
360
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox6), FALSE);
362
// Don't close window checkbox
363
checkbox8 = gtk_check_button_new_with_mnemonic(_("_Don't close this dialog"));
364
g_object_set_data_full(G_OBJECT(widgets.replace_dialog), "check_dont_close_window",
365
gtk_widget_ref(checkbox8), (GDestroyNotify) gtk_widget_unref);
366
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox8), FALSE);
367
gtk_tooltips_set_tip(tooltips, checkbox8,
368
_("The dialog window won't be closed when you start the operation."), NULL);
370
hbox = gtk_hbox_new(TRUE, 6);
371
gtk_container_add(GTK_CONTAINER(hbox), checkbox6);
372
gtk_container_add(GTK_CONTAINER(hbox), checkbox8);
374
align = gtk_alignment_new(0, 0, 1, 1);
375
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 9, 0, 0);
376
gtk_container_add(GTK_CONTAINER(align), hbox);
377
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(widgets.replace_dialog)->vbox), align);
481
label_size = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
482
gtk_size_group_add_widget(label_size, label_find);
483
gtk_size_group_add_widget(label_size, label_replace);
484
g_object_unref(G_OBJECT(label_size)); /* auto destroy the size group */
486
gtk_box_pack_start(GTK_BOX(vbox), fbox, TRUE, FALSE, 0);
487
gtk_box_pack_start(GTK_BOX(vbox), rbox, TRUE, FALSE, 0);
488
gtk_container_add(GTK_CONTAINER(vbox),
489
add_find_checkboxes(GTK_DIALOG(widgets.replace_dialog)));
491
/* Now add the multiple replace options */
492
exp = gtk_expander_new_with_mnemonic(_("Re_place All"));
493
bbox = gtk_hbutton_box_new();
495
button = gtk_button_new_with_mnemonic(_("In Se_lection"));
496
gtk_tooltips_set_tip(tooltips, button,
497
_("Replace all matches found in the currently selected text"), NULL);
498
gtk_container_add(GTK_CONTAINER(bbox), button);
499
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_replace_dialog_response),
500
GINT_TO_POINTER(GEANY_RESPONSE_REPLACE_IN_SEL));
502
button = gtk_button_new_with_mnemonic(_("In Sessi_on"));
503
gtk_container_add(GTK_CONTAINER(bbox), button);
504
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_replace_dialog_response),
505
GINT_TO_POINTER(GEANY_RESPONSE_REPLACE_IN_SESSION));
507
button = gtk_button_new_with_mnemonic(_("_In Document"));
508
gtk_container_add(GTK_CONTAINER(bbox), button);
509
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(send_replace_dialog_response),
510
GINT_TO_POINTER(GEANY_RESPONSE_REPLACE_IN_FILE));
512
/* close window checkbox */
513
check_close = gtk_check_button_new_with_mnemonic(_("Close _dialog"));
514
g_object_set_data_full(G_OBJECT(widgets.replace_dialog), "check_close",
515
gtk_widget_ref(check_close), (GDestroyNotify) gtk_widget_unref);
516
gtk_button_set_focus_on_click(GTK_BUTTON(check_close), FALSE);
517
gtk_tooltips_set_tip(tooltips, check_close,
518
_("Disable this option to keep the dialog open."), NULL);
519
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_close), TRUE);
520
gtk_container_add(GTK_CONTAINER(bbox), check_close);
521
gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(bbox), check_close, TRUE);
523
ui_hbutton_box_copy_layout(
524
GTK_BUTTON_BOX(GTK_DIALOG(widgets.replace_dialog)->action_area),
525
GTK_BUTTON_BOX(bbox));
526
gtk_container_add(GTK_CONTAINER(exp), bbox);
527
gtk_container_add(GTK_CONTAINER(vbox), exp);
379
529
gtk_widget_show_all(widgets.replace_dialog);
383
if (sel) gtk_entry_set_text(GTK_ENTRY(GTK_BIN(
533
/* only set selection if the dialog is not already visible */
534
if (! GTK_WIDGET_VISIBLE(widgets.replace_dialog) && sel)
535
gtk_entry_set_text(GTK_ENTRY(GTK_BIN(
384
536
lookup_widget(widgets.replace_dialog, "entry_find"))->child), sel);
385
537
gtk_widget_grab_focus(GTK_WIDGET(GTK_BIN(lookup_widget(widgets.replace_dialog, "entry_find"))->child));
386
538
gtk_widget_show(widgets.replace_dialog);
539
/* bring the dialog back in the foreground in case it is already open but the focus is away */
540
gtk_window_present(GTK_WINDOW(widgets.replace_dialog));
392
void search_show_find_in_files_dialog()
546
static void on_extra_options_toggled(GtkToggleButton *togglebutton, gpointer user_data)
548
/* disable extra option entry when checkbutton not checked */
549
gtk_widget_set_sensitive(GTK_WIDGET(user_data),
550
gtk_toggle_button_get_active(togglebutton));
554
/* dir is the directory to search in (UTF-8 encoding), maybe NULL to determine it the usual way
555
* by using the current file's path */
556
void search_show_find_in_files_dialog(const gchar *dir)
394
558
static GtkWidget *combo = NULL;
395
static GtkWidget *entry1;
396
GtkWidget *entry2; // the child GtkEntry of combo
397
GtkWidget *dirbtn, *openimg;
559
static GtkWidget *dir_combo;
560
GtkWidget *entry; /* the child GtkEntry of combo (or dir_combo) */
398
561
gint idx = document_get_cur_idx();
399
562
gchar *sel = NULL;
402
if (idx == -1 || ! doc_list[idx].is_valid) return;
404
cur_dir = utils_get_current_file_dir();
406
565
if (widgets.find_in_files_dialog == NULL)
408
GtkWidget *label, *label1, *checkbox1, *checkbox2, *check_wholeword;
409
GtkWidget *dbox, *sbox, *cbox, *rbox, *rbtn, *hbox;
567
GtkWidget *label, *label1, *checkbox1, *checkbox2, *check_wholeword,
568
*check_recursive, *check_extra, *entry_extra;
569
GtkWidget *dbox, *sbox, *cbox, *rbox, *rbtn, *hbox, *vbox;
410
570
GtkSizeGroup *size_group;
411
571
GtkTooltips *tooltips = GTK_TOOLTIPS(lookup_widget(app->window, "tooltips"));
573
load_monospace_style();
413
575
widgets.find_in_files_dialog = gtk_dialog_new_with_buttons(
414
_("Find in files"), GTK_WINDOW(app->window), GTK_DIALOG_DESTROY_WITH_PARENT,
576
_("Find in Files"), GTK_WINDOW(app->window), GTK_DIALOG_DESTROY_WITH_PARENT,
415
577
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
578
vbox = ui_dialog_vbox_new(GTK_DIALOG(widgets.find_in_files_dialog));
579
gtk_box_set_spacing(GTK_BOX(vbox), 9);
580
gtk_widget_set_name(widgets.find_in_files_dialog, "GeanyDialogSearch");
417
582
gtk_dialog_add_button(GTK_DIALOG(widgets.find_in_files_dialog), "gtk-find", GTK_RESPONSE_ACCEPT);
418
583
gtk_dialog_set_default_response(GTK_DIALOG(widgets.find_in_files_dialog),
419
584
GTK_RESPONSE_ACCEPT);
421
label1 = gtk_label_new(_("Directory:"));
586
label1 = gtk_label_new_with_mnemonic(_("_Directory:"));
422
587
gtk_misc_set_alignment(GTK_MISC(label1), 0, 0.5);
424
entry1 = gtk_entry_new();
425
gtk_entry_set_max_length(GTK_ENTRY(entry1), 248);
426
gtk_entry_set_width_chars(GTK_ENTRY(entry1), 50);
427
g_object_set_data_full(G_OBJECT(widgets.find_in_files_dialog), "entry_dir",
428
gtk_widget_ref(entry1), (GDestroyNotify)gtk_widget_unref);
430
dirbtn = gtk_button_new();
431
openimg = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
432
gtk_container_add(GTK_CONTAINER(dirbtn), openimg);
433
g_signal_connect(G_OBJECT(dirbtn), "clicked", G_CALLBACK(on_open_dir_dialog_clicked),
436
dbox = gtk_hbox_new(FALSE, 6);
589
dir_combo = gtk_combo_box_entry_new_text();
590
entry = gtk_bin_get_child(GTK_BIN(dir_combo));
591
gtk_label_set_mnemonic_widget(GTK_LABEL(label1), entry);
592
gtk_entry_set_max_length(GTK_ENTRY(entry), 248);
593
gtk_entry_set_width_chars(GTK_ENTRY(entry), 50);
594
g_object_set_data_full(G_OBJECT(widgets.find_in_files_dialog), "dir_combo",
595
gtk_widget_ref(dir_combo), (GDestroyNotify)gtk_widget_unref);
597
dbox = ui_path_box_new(NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
437
599
gtk_box_pack_start(GTK_BOX(dbox), label1, FALSE, FALSE, 0);
438
gtk_box_pack_start(GTK_BOX(dbox), entry1, TRUE, TRUE, 0);
439
gtk_box_pack_start(GTK_BOX(dbox), dirbtn, FALSE, FALSE, 0);
441
label = gtk_label_new(_("Search for:"));
601
label = gtk_label_new_with_mnemonic(_("_Search for:"));
442
602
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
444
604
combo = gtk_combo_box_entry_new_text();
445
entry2 = gtk_bin_get_child(GTK_BIN(combo));
446
gtk_entry_set_max_length(GTK_ENTRY(entry2), 248);
447
gtk_entry_set_width_chars(GTK_ENTRY(entry2), 50);
448
gtk_entry_set_activates_default(GTK_ENTRY(entry2), TRUE);
605
entry = gtk_bin_get_child(GTK_BIN(combo));
606
gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry);
607
gtk_entry_set_max_length(GTK_ENTRY(entry), 248);
608
gtk_entry_set_width_chars(GTK_ENTRY(entry), 50);
609
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
450
611
sbox = gtk_hbox_new(FALSE, 6);
451
612
gtk_box_pack_start(GTK_BOX(sbox), label, FALSE, FALSE, 0);
503
669
gtk_container_add(GTK_CONTAINER(cbox), checkbox1);
504
670
gtk_container_add(GTK_CONTAINER(cbox), check_wholeword);
505
671
gtk_container_add(GTK_CONTAINER(cbox), checkbox2);
672
gtk_container_add(GTK_CONTAINER(cbox), check_recursive);
507
674
hbox = gtk_hbox_new(FALSE, 6);
508
675
gtk_container_add(GTK_CONTAINER(hbox), rbox);
509
676
gtk_container_add(GTK_CONTAINER(hbox), cbox);
511
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(widgets.find_in_files_dialog)->vbox),
512
dbox, TRUE, FALSE, 6);
513
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(widgets.find_in_files_dialog)->vbox),
514
sbox, TRUE, FALSE, 0);
515
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(widgets.find_in_files_dialog)->vbox),
516
hbox, TRUE, TRUE, 6);
518
gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(widgets.find_in_files_dialog)->vbox), 6);
520
g_signal_connect((gpointer) entry1, "key-press-event",
521
G_CALLBACK(on_combo_entry_key_pressed), gtk_bin_get_child(GTK_BIN(combo)));
678
gtk_box_pack_start(GTK_BOX(vbox), dbox, TRUE, FALSE, 0);
679
gtk_box_pack_start(GTK_BOX(vbox), sbox, TRUE, FALSE, 0);
680
gtk_container_add(GTK_CONTAINER(vbox), hbox);
682
check_extra = gtk_check_button_new_with_mnemonic(_("E_xtra options:"));
683
g_object_set_data_full(G_OBJECT(widgets.find_in_files_dialog), "check_extra",
684
gtk_widget_ref(check_extra), (GDestroyNotify)gtk_widget_unref);
685
gtk_button_set_focus_on_click(GTK_BUTTON(check_extra), FALSE);
687
entry_extra = gtk_entry_new();
688
if (search_prefs.fif_extra_options)
689
gtk_entry_set_text(GTK_ENTRY(entry_extra), search_prefs.fif_extra_options);
690
gtk_widget_set_sensitive(entry_extra, FALSE);
691
g_object_set_data_full(G_OBJECT(widgets.find_in_files_dialog), "entry_extra",
692
gtk_widget_ref(entry_extra), (GDestroyNotify)gtk_widget_unref);
693
gtk_tooltips_set_tip(tooltips, entry_extra,
694
_("Other options to pass to Grep"), NULL);
696
/* enable entry_extra when check_extra is checked */
697
g_signal_connect(G_OBJECT(check_extra), "toggled",
698
G_CALLBACK(on_extra_options_toggled), entry_extra);
700
hbox = gtk_hbox_new(FALSE, 6);
701
gtk_box_pack_start(GTK_BOX(hbox), check_extra, FALSE, FALSE, 0);
702
gtk_box_pack_start(GTK_BOX(hbox), entry_extra, TRUE, TRUE, 0);
703
gtk_container_add(GTK_CONTAINER(vbox), hbox);
705
g_signal_connect((gpointer) dir_combo, "key-press-event",
706
G_CALLBACK(on_widget_key_pressed_set_focus), combo);
522
707
g_signal_connect((gpointer) widgets.find_in_files_dialog, "response",
523
708
G_CALLBACK(on_find_in_files_dialog_response), combo);
524
709
g_signal_connect((gpointer) widgets.find_in_files_dialog, "delete_event",
525
G_CALLBACK(gtk_widget_hide), NULL);
710
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
527
712
gtk_widget_show_all(widgets.find_in_files_dialog);
713
sel = editor_get_default_selection(idx, prefs.search_use_current_word, NULL);
530
if (sci_get_lines_selected(doc_list[idx].sci) == 1)
716
entry = GTK_BIN(combo)->child;
717
/* only set selection if the dialog is not already visible, or has just been created */
718
if (! sel && ! GTK_WIDGET_VISIBLE(widgets.find_in_files_dialog))
719
sel = editor_get_default_selection(idx, prefs.search_use_current_word, NULL);
721
gtk_entry_set_text(GTK_ENTRY(entry), sel);
724
entry = GTK_BIN(dir_combo)->child;
726
cur_dir = g_strdup(dir);
728
cur_dir = utils_get_current_file_dir_utf8();
532
sel = g_malloc(sci_get_selected_text_length(doc_list[idx].sci));
533
sci_get_selected_text(doc_list[idx].sci, sel);
536
entry2 = GTK_BIN(combo)->child;
537
if (sel) gtk_entry_set_text(GTK_ENTRY(entry2), sel);
540
if (cur_dir) gtk_entry_set_text(GTK_ENTRY(entry1), cur_dir);
543
// put the focus to the directory entry if it is empty
544
if (utils_strcmp(gtk_entry_get_text(GTK_ENTRY(entry1)), ""))
545
gtk_widget_grab_focus(entry1);
547
gtk_widget_grab_focus(entry2);
731
gtk_entry_set_text(GTK_ENTRY(entry), cur_dir);
735
{ /* use default_open_path if no directory could be determined (e.g. when no files are open) */
736
gtk_entry_set_text(GTK_ENTRY(entry), prefs.default_open_path);
739
/* put the focus to the directory entry if it is empty */
740
if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry)), ""))
741
gtk_widget_grab_focus(dir_combo);
743
gtk_widget_grab_focus(combo);
549
745
gtk_widget_show(widgets.find_in_files_dialog);
553
static void on_open_dir_dialog_clicked(GtkButton *button, gpointer user_data)
555
GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Select folder"),
556
GTK_WINDOW(app->window), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
557
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
558
GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
559
GtkWidget *entry_dir = lookup_widget(widgets.find_in_files_dialog, "entry_dir");
561
const gchar *entry_text;
563
entry_text = gtk_entry_get_text(GTK_ENTRY(entry_dir));
564
dir_locale = utils_get_locale_from_utf8(entry_text);
565
if (g_file_test(dir_locale, G_FILE_TEST_IS_DIR))
566
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir_locale);
569
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
572
dir_locale = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
573
dir_utf8 = utils_get_utf8_from_locale(dir_locale);
575
gtk_entry_set_text(GTK_ENTRY(entry_dir), dir_utf8);
578
gtk_widget_destroy(dialog);
746
/* bring the dialog back in the foreground in case it is already open but the focus is away */
747
gtk_window_present(GTK_WINDOW(widgets.find_in_files_dialog));
792
static gint search_mark(gint idx, const gchar *search_text, gint flags)
794
gint pos, line, count = 0;
795
struct TextToFind ttf;
797
g_return_val_if_fail(DOC_IDX_VALID(idx), 0);
800
ttf.chrg.cpMax = sci_get_length(doc_list[idx].sci);
801
ttf.lpstrText = (gchar *)search_text;
804
pos = sci_find_text(doc_list[idx].sci, flags, &ttf);
805
if (pos == -1) break;
807
line = sci_get_line_from_position(doc_list[idx].sci, pos);
808
sci_set_marker_at_line(doc_list[idx].sci, line, TRUE, 1);
810
ttf.chrg.cpMin = ttf.chrgText.cpMax + 1;
818
on_find_entry_activate(GtkEntry *entry, gpointer user_data)
820
on_find_dialog_response(NULL, GEANY_RESPONSE_FIND,
821
lookup_widget(GTK_WIDGET(entry), "entry"));
825
static gint get_search_flags(GtkWidget *dialog)
827
gboolean fl1, fl2, fl3, fl4;
829
fl1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
830
lookup_widget(dialog, "check_case")));
831
fl2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
832
lookup_widget(dialog, "check_word")));
833
fl3 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
834
lookup_widget(dialog, "check_regexp")));
835
fl4 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
836
lookup_widget(dialog, "check_wordstart")));
838
return (fl1 ? SCFIND_MATCHCASE : 0) |
839
(fl2 ? SCFIND_WHOLEWORD : 0) |
840
(fl3 ? SCFIND_REGEXP | SCFIND_POSIX : 0) |
841
(fl4 ? SCFIND_WORDSTART : 0);
621
846
on_find_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
623
if (response == GTK_RESPONSE_ACCEPT)
848
if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
849
gtk_widget_hide(widgets.find_dialog);
625
852
gint idx = document_get_cur_idx();
626
853
gboolean search_replace_escape;
628
fl1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
629
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_case"))),
630
fl2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
631
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_word"))),
632
fl3 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
633
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_regexp"))),
634
fl4 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
635
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_wordstart")));
854
gboolean check_close = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
855
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_close")));
636
857
search_replace_escape = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
637
858
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_escape")));
638
search_data.backwards = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
639
lookup_widget(GTK_WIDGET(widgets.find_dialog), "check_back")));
859
search_data.backwards = FALSE;
860
search_data.search_bar = FALSE;
862
if (! DOC_IDX_VALID(idx)) return;
641
864
g_free(search_data.text);
642
865
search_data.text = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(user_data)))));
674
927
GtkWidget *entry_find = lookup_widget(GTK_WIDGET(widgets.replace_dialog), "entry_find");
675
928
GtkWidget *entry_replace = lookup_widget(GTK_WIDGET(widgets.replace_dialog), "entry_replace");
676
929
gint search_flags_re;
677
gboolean search_backwards_re, search_replace_escape_re, search_in_all_buffers_re;
678
gboolean fl1, fl2, fl3, fl4;
930
gboolean search_backwards_re, search_replace_escape_re;
679
931
gboolean close_window;
680
932
gchar *find, *replace;
682
if (response == GTK_RESPONSE_CANCEL)
934
if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
684
936
gtk_widget_hide(widgets.replace_dialog);
688
fl1 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
689
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_case")));
690
fl2 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
691
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_word")));
692
fl3 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
693
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_regexp")));
694
fl4 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
695
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_wordstart")));
696
close_window = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
697
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_dont_close_window")));
940
close_window = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
941
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_close")));
698
942
search_backwards_re = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
699
943
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_back")));
700
944
search_replace_escape_re = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
701
945
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_escape")));
702
search_in_all_buffers_re = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
703
lookup_widget(GTK_WIDGET(widgets.replace_dialog), "check_all_buffers")));
704
946
find = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_find)))));
705
947
replace = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry_replace)))));
707
if ((response != GEANY_RESPONSE_FIND) && (! fl1) && (strcasecmp(find, replace) == 0))
949
search_flags_re = get_search_flags(widgets.replace_dialog);
951
if ((response != GEANY_RESPONSE_FIND) && (search_flags_re & SCFIND_MATCHCASE)
952
&& (strcmp(find, replace) == 0))
710
955
gtk_widget_grab_focus(GTK_WIDGET(GTK_BIN(lookup_widget(widgets.replace_dialog, "entry_find"))->child));
714
gtk_combo_box_prepend_text(GTK_COMBO_BOX(entry_find), find);
715
gtk_combo_box_prepend_text(GTK_COMBO_BOX(entry_replace), replace);
959
ui_combo_box_add_to_history(GTK_COMBO_BOX(entry_find), find);
960
ui_combo_box_add_to_history(GTK_COMBO_BOX(entry_replace), replace);
717
962
if (search_replace_escape_re &&
718
963
(! utils_str_replace_escape(find) || ! utils_str_replace_escape(replace)))
725
search_flags_re = (fl1 ? SCFIND_MATCHCASE : 0) |
726
(fl2 ? SCFIND_WHOLEWORD : 0) |
727
(fl3 ? SCFIND_REGEXP | SCFIND_POSIX : 0) |
728
(fl4 ? SCFIND_WORDSTART : 0);
730
if (search_in_all_buffers_re && response == GEANY_RESPONSE_REPLACE_ALL)
733
for (i = 0; i < GEANY_MAX_OPEN_FILES; i++)
735
if (! doc_list[i].is_valid) continue;
737
document_replace_all(i, find, replace, search_flags_re, search_replace_escape_re);
739
if (close_window) gtk_widget_hide(widgets.replace_dialog);
972
case GEANY_RESPONSE_REPLACE_AND_FIND:
974
gint rep = document_replace_text(idx, find, replace, search_flags_re,
975
search_backwards_re);
977
document_find_text(idx, find, search_flags_re, search_backwards_re,
981
case GEANY_RESPONSE_REPLACE:
983
document_replace_text(idx, find, replace, search_flags_re,
984
search_backwards_re);
987
case GEANY_RESPONSE_FIND:
989
document_find_text(idx, find, search_flags_re, search_backwards_re, TRUE,
993
case GEANY_RESPONSE_REPLACE_IN_FILE:
995
if (! document_replace_all(idx, find, replace, search_flags_re,
996
search_replace_escape_re))
1002
case GEANY_RESPONSE_REPLACE_IN_SESSION:
1006
/* replace in all documents following notebook tab order */
1007
for (n = 0; (gint) n < gtk_notebook_get_n_pages(GTK_NOTEBOOK(app->notebook)); n++)
1009
gint ix = document_get_n_idx(n);
1011
if (! doc_list[ix].is_valid) continue;
1013
if (document_replace_all(ix, find, replace, search_flags_re,
1014
search_replace_escape_re)) count++;
1019
ui_set_statusbar(FALSE, _("Replaced text in %u files."), count);
1020
/* show which docs had replacements: */
1021
gtk_notebook_set_current_page(GTK_NOTEBOOK(msgwindow.notebook), MSG_STATUS);
1023
ui_save_buttons_toggle(doc_list[idx].changed); /* update save all */
1026
case GEANY_RESPONSE_REPLACE_IN_SEL:
1028
document_replace_sel(idx, find, replace, search_flags_re, search_replace_escape_re);
745
case GEANY_RESPONSE_REPLACE:
747
document_replace_text(idx, find, replace, search_flags_re,
748
search_backwards_re);
751
case GEANY_RESPONSE_FIND:
753
document_find_text(idx, find, search_flags_re, search_backwards_re);
756
case GEANY_RESPONSE_REPLACE_ALL:
758
document_replace_all(idx, find, replace, search_flags_re, search_replace_escape_re);
759
if (close_window) gtk_widget_hide(widgets.replace_dialog);
762
case GEANY_RESPONSE_REPLACE_SEL:
764
document_replace_sel(idx, find, replace, search_flags_re, search_replace_escape_re);
765
if (close_window) gtk_widget_hide(widgets.replace_dialog);
1034
case GEANY_RESPONSE_REPLACE_IN_SEL:
1035
case GEANY_RESPONSE_REPLACE_IN_FILE:
1036
case GEANY_RESPONSE_REPLACE_IN_SESSION:
1038
gtk_widget_hide(widgets.replace_dialog);
771
1041
g_free(replace);
776
on_replace_entry_activate(GtkEntry *entry, gpointer user_data)
778
on_replace_dialog_response(NULL, GEANY_RESPONSE_REPLACE, NULL);
783
on_combo_entry_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1046
on_widget_key_pressed_set_focus(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
785
// catch tabulator key to set the focus in the replace entry instead of
786
// setting it to the combo box
1048
/* catch tabulator key to set the focus in the replace entry instead of
1049
* setting it to the combo box */
787
1050
if (event->keyval == GDK_Tab)
789
1052
gtk_widget_grab_focus(GTK_WIDGET(user_data));
801
1113
const gchar *search_text =
802
1114
gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(user_data))));
1115
GtkWidget *dir_combo =
1116
lookup_widget(widgets.find_in_files_dialog, "dir_combo");
803
1117
const gchar *utf8_dir =
804
gtk_entry_get_text(GTK_ENTRY(lookup_widget(widgets.find_in_files_dialog, "entry_dir")));
806
if (utf8_dir == NULL || utils_strcmp(utf8_dir, ""))
807
msgwin_status_add(_("Invalid directory for find in files."));
1118
gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(dir_combo))));
1120
/* update extra options pref */
1121
g_free(search_prefs.fif_extra_options);
1122
search_prefs.fif_extra_options = g_strdup(gtk_entry_get_text(GTK_ENTRY(
1123
lookup_widget(widgets.find_in_files_dialog, "entry_extra"))));
1125
if (utf8_dir == NULL || utils_str_equal(utf8_dir, ""))
1126
ui_set_statusbar(FALSE, _("Invalid directory for find in files."));
808
1127
else if (search_text && *search_text)
810
1129
gchar *locale_dir;
811
gboolean invert = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
812
lookup_widget(widgets.find_in_files_dialog, "check_invert")));
813
gboolean case_sens = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
814
lookup_widget(widgets.find_in_files_dialog, "check_case")));
815
gboolean whole_word = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
816
lookup_widget(widgets.find_in_files_dialog, "check_wholeword")));
817
gint opts = (invert ? FIF_INVERT_MATCH : 0) |
818
(case_sens ? FIF_CASE_SENSITIVE : 0) |
819
(whole_word ? FIF_WHOLE_WORD : 0);
820
gboolean fgrep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
821
lookup_widget(widgets.find_in_files_dialog, "radio_fgrep")));
822
gboolean grep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
823
lookup_widget(widgets.find_in_files_dialog, "radio_grep")));
824
gint regex_opt = fgrep ? FIF_FGREP : (grep ? FIF_GREP : FIF_EGREP);
1130
GString *opts = get_grep_options();
826
1132
locale_dir = utils_get_locale_from_utf8(utf8_dir);
828
if (search_find_in_files(search_text, locale_dir, regex_opt, opts))
1134
if (search_find_in_files(search_text, locale_dir, opts->str))
830
gtk_combo_box_prepend_text(GTK_COMBO_BOX(user_data), search_text);
1136
ui_combo_box_add_to_history(GTK_COMBO_BOX(user_data), search_text);
1137
ui_combo_box_add_to_history(GTK_COMBO_BOX(dir_combo), utf8_dir);
831
1138
gtk_widget_hide(widgets.find_in_files_dialog);
833
1140
g_free(locale_dir);
1141
g_string_free(opts, TRUE);
836
msgwin_status_add(_("No text to find."));
1144
ui_set_statusbar(FALSE, _("No text to find."));
839
1147
gtk_widget_hide(widgets.find_in_files_dialog);
844
search_find_in_files(const gchar *search_text, const gchar *dir, fif_match_type regex_opt,
1152
search_find_in_files(const gchar *search_text, const gchar *dir, const gchar *opts)
848
gchar **grep_cmd_argv;
850
gchar grep_opts[] = "-nHI ";
1154
gchar **argv_prefix, **argv, **opts_argv;
1155
gchar *command_grep;
1156
guint opts_argv_len, i;
852
gint stdout_fd, stdin_fd, grep_cmd_argv_len, i, grep_opts_len = 4;
853
1159
GError *error = NULL;
854
1160
gboolean ret = FALSE;
856
1162
if (! search_text || ! *search_text || ! dir) return TRUE;
858
// first process the grep command (need to split it in a argv because it can be "grep -I")
859
grep_cmd_argv = g_strsplit(app->tools_grep_cmd, " ", -1);
860
grep_cmd_argv_len = g_strv_length(grep_cmd_argv);
862
if (! g_file_test(grep_cmd_argv[0], G_FILE_TEST_IS_EXECUTABLE))
864
msgwin_status_add(_("Cannot execute grep tool '%s';"
865
" check the path setting in Preferences."), app->tools_grep_cmd);
1164
command_grep = g_find_program_in_path(prefs.tools_grep_cmd);
1165
if (command_grep == NULL)
1167
ui_set_statusbar(TRUE, _("Cannot execute grep tool '%s';"
1168
" check the path setting in Preferences."), prefs.tools_grep_cmd);
1172
opts_argv = g_strsplit(opts, " ", -1);
1173
opts_argv_len = g_strv_length(opts_argv);
1175
/* set grep command and options */
1176
argv_prefix = g_new0(gchar*, 1 + opts_argv_len + 3 + 1); /* last +1 for recursive arg */
1178
argv_prefix[0] = command_grep;
1179
for (i = 0; i < opts_argv_len; i++)
1181
argv_prefix[i + 1] = g_strdup(opts_argv[i]);
1183
g_strfreev(opts_argv);
1185
i++; /* correct for prefs.tools_grep_cmd */
1186
argv_prefix[i++] = g_strdup("--");
1187
argv_prefix[i++] = g_strdup(search_text);
1189
/* finally add the arguments(files to be searched) */
1190
if (strstr(argv_prefix[1], "r")) /* recursive option set */
1192
argv_prefix[i++] = g_strdup(".");
1193
argv_prefix[i++] = NULL;
1198
argv_prefix[i++] = NULL;
1199
argv = search_get_argv((const gchar**)argv_prefix, dir);
1200
g_strfreev(argv_prefix);
1203
if (argv == NULL) /* no files */
869
1209
gtk_list_store_clear(msgwindow.store_msg);
870
1210
gtk_notebook_set_current_page(GTK_NOTEBOOK(msgwindow.notebook), MSG_MESSAGE);
875
case FIF_FGREP: grep_opts[grep_opts_len++] = 'F'; break;
876
case FIF_GREP: break;
877
case FIF_EGREP: grep_opts[grep_opts_len++] = 'E'; break;
880
if (! (opts & FIF_CASE_SENSITIVE))
881
grep_opts[grep_opts_len++] = 'i';
882
if (opts & FIF_WHOLE_WORD)
883
grep_opts[grep_opts_len++] = 'w';
884
if (opts & FIF_INVERT_MATCH)
885
grep_opts[grep_opts_len++] = 'v';
886
grep_opts[grep_opts_len] = '\0';
888
// set grep command and options
889
argv_prefix = g_new0(gchar*, grep_cmd_argv_len + 4);
890
for (i = 0; i < grep_cmd_argv_len; i++)
892
argv_prefix[i] = g_strdup(grep_cmd_argv[i]);
894
argv_prefix[grep_cmd_argv_len] = g_strdup(grep_opts);
895
argv_prefix[grep_cmd_argv_len + 1] = g_strdup("--");
896
argv_prefix[grep_cmd_argv_len + 2] = g_strdup(search_text);
897
argv_prefix[grep_cmd_argv_len + 3] = NULL;
898
g_strfreev(grep_cmd_argv);
900
// finally add the arguments(files to be searched)
901
argv = search_get_argv((const gchar**)argv_prefix, dir);
902
g_strfreev(argv_prefix);
904
if (argv == NULL) return FALSE;
906
1212
if (! g_spawn_async_with_pipes(dir, (gchar**)argv, NULL,
907
1213
G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_DO_NOT_REAP_CHILD,
908
1214
NULL, NULL, &child_pid,
909
&stdin_fd, &stdout_fd, NULL, &error))
1215
NULL, &stdout_fd, NULL, &error))
911
1217
geany_debug("%s: g_spawn_async_with_pipes() failed: %s", __func__, error->message);
912
msgwin_status_add(_("Process failed (%s)"), error->message);
1218
ui_set_statusbar(TRUE, _("Process failed (%s)"), error->message);
913
1219
g_error_free(error);
1224
gchar *str, *utf8_str;
918
1226
g_free(msgwindow.find_in_files_dir);
919
1227
msgwindow.find_in_files_dir = g_strdup(dir);
920
1228
utils_set_up_io_channel(stdout_fd, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
921
search_read_io, NULL);
1229
TRUE, search_read_io, NULL);
922
1230
g_child_watch_add(child_pid, search_close_pid, NULL);
1232
str = g_strdup_printf(_("%s %s -- %s (in directory: %s)"),
1233
prefs.tools_grep_cmd, opts, search_text, dir);
1234
utf8_str = utils_get_utf8_from_locale(str);
1235
msgwin_msg_add(COLOR_BLUE, -1, -1, utf8_str);
1236
utils_free_pointers(str, utf8_str, NULL);
925
1239
g_strfreev(argv);
1021
1305
static void search_close_pid(GPid child_pid, gint status, gpointer user_data)
1023
1307
#ifdef G_OS_UNIX
1024
gchar *msg = _("Search failed.");
1308
const gchar *msg = _("Search failed.");
1309
gint color = COLOR_DARK_RED;
1026
1311
if (WIFEXITED(status))
1028
1313
switch (WEXITSTATUS(status))
1030
case 0: msg = _("Search completed."); break;
1031
case 1: msg = _("No matches found."); break;
1317
gint count = gtk_tree_model_iter_n_children(
1318
GTK_TREE_MODEL(msgwindow.store_msg), NULL) - 1;
1320
msgwin_msg_add_fmt(COLOR_BLUE, -1, -1,
1321
_("Search completed with %d matches."), count);
1322
ui_set_statusbar(FALSE, _("Search completed with %d matches."), count);
1326
msg = _("No matches found.");
1329
msgwin_msg_add(color, -1, -1, msg);
1330
ui_set_statusbar(FALSE, "%s", msg);
1036
msgwin_msg_add(-1, -1, msg);
1039
1337
g_spawn_close_pid(child_pid);
1341
static gint find_document_usage(gint idx, const gchar *search_text, gint flags)
1343
gchar *buffer, *short_file_name;
1344
struct TextToFind ttf;
1347
g_return_val_if_fail(DOC_IDX_VALID(idx), 0);
1349
short_file_name = g_path_get_basename(DOC_FILENAME(idx));
1352
ttf.chrg.cpMax = sci_get_length(doc_list[idx].sci);
1353
ttf.lpstrText = (gchar *)search_text;
1356
gint pos, line, start, find_len;
1358
pos = sci_find_text(doc_list[idx].sci, flags, &ttf);
1360
break; /* no more matches */
1361
find_len = ttf.chrgText.cpMax - ttf.chrgText.cpMin;
1363
break; /* Ignore regex ^ or $ */
1366
line = sci_get_line_from_position(doc_list[idx].sci, pos);
1367
buffer = sci_get_line(doc_list[idx].sci, line);
1368
msgwin_msg_add_fmt(COLOR_BLACK, line + 1, idx,
1369
"%s:%d : %s", short_file_name, line + 1, g_strstrip(buffer));
1372
start = ttf.chrgText.cpMax + 1;
1373
ttf.chrg.cpMin = start;
1375
g_free(short_file_name);
1380
void search_find_usage(const gchar *search_text, gint flags, gboolean in_session)
1383
gboolean found = FALSE;
1385
idx = document_get_cur_idx();
1386
g_return_if_fail(DOC_IDX_VALID(idx));
1388
gtk_notebook_set_current_page(GTK_NOTEBOOK(msgwindow.notebook), MSG_MESSAGE);
1389
gtk_list_store_clear(msgwindow.store_msg);
1392
{ /* use current document */
1393
found = (find_document_usage(idx, search_text, flags) > 0);
1398
for (i = 0; i < doc_array->len; i++)
1400
if (doc_list[i].is_valid)
1401
if (find_document_usage(i, search_text, flags) > 0) found = TRUE;
1405
if (! found) /* no matches were found */
1407
ui_set_statusbar(FALSE, _("No matches found for \"%s\"."), search_text);
1408
msgwin_msg_add_fmt(COLOR_BLUE, -1, -1, _("No matches found for \"%s\"."), search_text);
1412
gint count = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(msgwindow.store_msg), NULL);
1414
ui_set_statusbar(FALSE, _("Found %d matches for \"%s\"."), count, search_text);
1415
msgwin_msg_add_fmt(COLOR_BLUE, -1, -1, _("Found %d matches for \"%s\"."), count,