This source file includes following definitions.
- edit_dlg_init
- edit_dlg_deinit
- edit_about
- edit_help
- edit_restore_size
- edit_window_move
- edit_window_resize
- get_hotkey
- edit_window_list
- edit_get_shortcut
- edit_get_title
- edit_dialog_command_execute
- edit_translate_key
- edit_quit
- edit_set_buttonbar
- edit_total_update
- edit_update_cursor
- edit_dialog_callback
- edit_dialog_mouse_callback
- edit_dialog_bg_callback
- edit_callback
- edit_mouse_handle_move_resize
- edit_mouse_callback
- edit_file
- edit_files
- edit_find_editor
- edit_widget_is_editor
- edit_update_screen
- edit_save_size
- edit_add_window
- edit_handle_move_resize
- edit_toggle_fullscreen
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 <errno.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41
42 #include "lib/global.h"
43
44 #include "lib/tty/tty.h"
45 #include "lib/tty/key.h"
46 #include "lib/tty/color.h"
47 #include "lib/skin.h"
48 #include "lib/fileloc.h"
49 #include "lib/strutil.h"
50 #include "lib/util.h"
51 #include "lib/widget.h"
52 #include "lib/mcconfig.h"
53 #include "lib/event.h"
54 #include "lib/charsets.h"
55
56 #include "src/keymap.h"
57 #include "src/setup.h"
58 #include "src/execute.h"
59 #include "src/filemanager/cmd.h"
60 #include "src/learn.h"
61
62 #include "edit-impl.h"
63 #include "editwidget.h"
64 #include "editmacros.h"
65 #ifdef HAVE_ASPELL
66 #include "spell.h"
67 #endif
68
69
70
71 char *edit_window_state_char = NULL;
72 char *edit_window_close_char = NULL;
73
74
75
76 #define WINDOW_MIN_LINES (2 + 2)
77 #define WINDOW_MIN_COLS (2 + LINE_STATE_WIDTH + 2)
78
79
80
81
82
83
84
85 static unsigned int edit_dlg_init_refcounter = 0;
86
87
88
89
90
91
92
93
94 static void
95 edit_dlg_init (void)
96 {
97 edit_dlg_init_refcounter++;
98
99 if (edit_dlg_init_refcounter == 1)
100 {
101 edit_window_state_char = mc_skin_get ("widget-editor", "window-state-char", "*");
102 edit_window_close_char = mc_skin_get ("widget-editor", "window-close-char", "X");
103
104 #ifdef HAVE_ASPELL
105 aspell_init ();
106 #endif
107 }
108 }
109
110
111
112
113
114
115 static void
116 edit_dlg_deinit (void)
117 {
118 if (edit_dlg_init_refcounter == 1)
119 {
120 g_free (edit_window_state_char);
121 g_free (edit_window_close_char);
122
123 #ifdef HAVE_ASPELL
124 aspell_clean ();
125 #endif
126 }
127
128 if (edit_dlg_init_refcounter != 0)
129 edit_dlg_init_refcounter--;
130 }
131
132
133
134
135
136
137 static void
138 edit_about (void)
139 {
140 char *version;
141 char *package_copyright;
142 char *description;
143
144 version = g_strdup_printf ("MCEdit %s", mc_global.mc_version);
145 package_copyright = mc_get_package_copyright ();
146 description =
147 g_strdup_printf (_ ("A user friendly text editor\nwritten for the %s."), PACKAGE_NAME);
148
149 {
150 quick_widget_t quick_widgets[] = {
151 QUICK_LABEL (version, NULL),
152 QUICK_SEPARATOR (TRUE),
153 QUICK_LABEL (description, NULL),
154 QUICK_SEPARATOR (FALSE),
155 QUICK_LABEL (package_copyright, NULL),
156 QUICK_START_BUTTONS (TRUE, TRUE),
157 QUICK_BUTTON (_ ("&OK"), B_ENTER, NULL, NULL),
158 QUICK_END,
159 };
160
161 WRect r = { -1, -1, 0, 40 };
162
163 quick_dialog_t qdlg = {
164 .rect = r,
165 .title = _ ("About"),
166 .help = "[Internal File Editor]",
167 .widgets = quick_widgets,
168 .callback = NULL,
169 .mouse_callback = NULL,
170 };
171
172 quick_widgets[0].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
173 quick_widgets[2].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
174 quick_widgets[4].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
175
176 (void) quick_dialog (&qdlg);
177 }
178
179 g_free (version);
180 g_free (package_copyright);
181 g_free (description);
182 }
183
184
185
186
187
188
189 static void
190 edit_help (const WDialog *h)
191 {
192 ev_help_t event_data = { NULL, h->help_ctx };
193
194 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
195 }
196
197
198
199
200
201
202
203
204 static void
205 edit_restore_size (WEdit *edit)
206 {
207 Widget *w = WIDGET (edit);
208
209 edit->drag_state = MCEDIT_DRAG_NONE;
210 w->mouse.forced_capture = FALSE;
211 widget_set_size_rect (w, &edit->loc_prev);
212 widget_draw (WIDGET (w->owner));
213 }
214
215
216
217
218
219
220
221
222
223 static void
224 edit_window_move (WEdit *edit, long command)
225 {
226 Widget *we = WIDGET (edit);
227 Widget *wo = WIDGET (we->owner);
228 WRect *w = &we->rect;
229 const WRect *wh = &wo->rect;
230
231 switch (command)
232 {
233 case CK_Up:
234 if (w->y > wh->y + 1)
235 w->y--;
236 break;
237 case CK_Down:
238 if (w->y < wh->y + wh->lines - 2)
239 w->y++;
240 break;
241 case CK_Left:
242 if (w->x + wh->cols > wh->x)
243 w->x--;
244 break;
245 case CK_Right:
246 if (w->x < wh->x + wh->cols)
247 w->x++;
248 break;
249 default:
250 return;
251 }
252
253 edit->force |= REDRAW_PAGE;
254 widget_draw (wo);
255 }
256
257
258
259
260
261
262
263
264
265 static void
266 edit_window_resize (WEdit *edit, long command)
267 {
268 Widget *we = WIDGET (edit);
269 Widget *wo = WIDGET (we->owner);
270 WRect *w = &we->rect;
271 const WRect *wh = &wo->rect;
272
273 switch (command)
274 {
275 case CK_Up:
276 if (w->lines > WINDOW_MIN_LINES)
277 w->lines--;
278 break;
279 case CK_Down:
280 if (w->y + w->lines < wh->y + wh->lines - 1)
281 w->lines++;
282 break;
283 case CK_Left:
284 if (w->cols > WINDOW_MIN_COLS)
285 w->cols--;
286 break;
287 case CK_Right:
288 if (w->x + w->cols < wh->x + wh->cols)
289 w->cols++;
290 break;
291 default:
292 return;
293 }
294
295 edit->force |= REDRAW_COMPLETELY;
296 widget_draw (wo);
297 }
298
299
300
301
302
303
304
305
306
307 static unsigned char
308 get_hotkey (int n)
309 {
310 return (n <= 9) ? '0' + n : 'a' + n - 10;
311 }
312
313
314
315 static void
316 edit_window_list (const WDialog *h)
317 {
318 const WGroup *g = CONST_GROUP (h);
319 const size_t offset = 2;
320 const size_t dlg_num = g_list_length (g->widgets) - offset;
321 int lines, cols;
322 Listbox *listbox;
323 GList *w;
324 WEdit *selected;
325 int i = 0;
326
327 lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
328 cols = COLS * 2 / 3;
329
330 listbox = listbox_window_new (lines, cols, _ ("Open files"), "[Open files]");
331
332 for (w = g->widgets; w != NULL; w = g_list_next (w))
333 if (edit_widget_is_editor (CONST_WIDGET (w->data)))
334 {
335 WEdit *e = EDIT (w->data);
336 char *fname;
337
338 if (e->filename_vpath == NULL)
339 fname = g_strdup_printf ("%c [%s]", e->modified != 0 ? '*' : ' ', _ ("NoName"));
340 else
341 fname = g_strdup_printf ("%c%s", e->modified != 0 ? '*' : ' ',
342 vfs_path_as_str (e->filename_vpath));
343
344 listbox_add_item (listbox->list, LISTBOX_APPEND_AT_END, get_hotkey (i++),
345 str_term_trim (fname, WIDGET (listbox->list)->rect.cols - 2), e,
346 FALSE);
347 g_free (fname);
348 }
349
350 selected = listbox_run_with_data (listbox, g->current->data);
351 if (selected != NULL)
352 widget_select (WIDGET (selected));
353 }
354
355
356
357 static char *
358 edit_get_shortcut (long command)
359 {
360 const char *ext_map;
361 const char *shortcut = NULL;
362
363 shortcut = keybind_lookup_keymap_shortcut (editor_map, command);
364 if (shortcut != NULL)
365 return g_strdup (shortcut);
366
367 ext_map = keybind_lookup_keymap_shortcut (editor_map, CK_ExtendedKeyMap);
368 if (ext_map != NULL)
369 shortcut = keybind_lookup_keymap_shortcut (editor_x_map, command);
370 if (shortcut != NULL)
371 return g_strdup_printf ("%s %s", ext_map, shortcut);
372
373 return NULL;
374 }
375
376
377
378 static char *
379 edit_get_title (const WDialog *h, const ssize_t width)
380 {
381 const WEdit *edit;
382 const char *modified;
383 const char *file_label;
384 char *filename;
385
386 edit = edit_find_editor (h);
387 modified = edit->modified != 0 ? "(*) " : " ";
388
389 const ssize_t width1 = width - strlen (modified);
390
391 if (edit->filename_vpath == NULL)
392 filename = g_strdup (_ ("[NoName]"));
393 else
394 filename = g_strdup (vfs_path_as_str (edit->filename_vpath));
395
396 file_label = str_term_trim (filename, width1 - str_term_width1 (_ ("Edit: ")));
397 g_free (filename);
398
399 return g_strconcat (_ ("Edit: "), modified, file_label, (char *) NULL);
400 }
401
402
403
404 static cb_ret_t
405 edit_dialog_command_execute (WDialog *h, long command)
406 {
407 WGroup *g = GROUP (h);
408 cb_ret_t ret = MSG_HANDLED;
409
410 switch (command)
411 {
412 case CK_EditNew:
413 edit_load_file_from_filename (h, NULL);
414 break;
415 case CK_EditFile:
416 edit_load_cmd (h);
417 break;
418 case CK_History:
419 edit_load_file_from_history (h);
420 break;
421 case CK_EditSyntaxFile:
422 edit_load_syntax_file (h);
423 break;
424 case CK_EditUserMenu:
425 edit_load_menu_file (h);
426 break;
427 case CK_Close:
428
429 if (edit_widget_is_editor (CONST_WIDGET (g->current->data))
430 && edit_close_cmd (EDIT (g->current->data)) && edit_find_editor (h) == NULL)
431 dlg_close (h);
432 break;
433 case CK_Help:
434 edit_help (h);
435 break;
436 case CK_Menu:
437 edit_menu_cmd (h);
438 break;
439 case CK_Quit:
440 case CK_Cancel:
441
442 {
443 Widget *w = WIDGET (g->current->data);
444
445 if (edit_widget_is_editor (w) && EDIT (w)->drag_state != MCEDIT_DRAG_NONE)
446 edit_restore_size (EDIT (w));
447 else if (command == CK_Quit)
448 dlg_close (h);
449 }
450 break;
451 case CK_About:
452 edit_about ();
453 break;
454 case CK_SyntaxOnOff:
455 edit_syntax_onoff_cmd (h);
456 break;
457 case CK_ShowTabTws:
458 edit_show_tabs_tws_cmd (h);
459 break;
460 case CK_ShowMargin:
461 edit_show_margin_cmd (h);
462 break;
463 case CK_ShowNumbers:
464 edit_show_numbers_cmd (h);
465 break;
466 case CK_Refresh:
467 edit_refresh_cmd ();
468 break;
469 case CK_Shell:
470 toggle_subshell ();
471 break;
472 case CK_LearnKeys:
473 learn_keys ();
474 break;
475 case CK_WindowMove:
476 case CK_WindowResize:
477 if (edit_widget_is_editor (CONST_WIDGET (g->current->data)))
478 edit_handle_move_resize (EDIT (g->current->data), command);
479 break;
480 case CK_WindowList:
481 edit_window_list (h);
482 break;
483 case CK_WindowNext:
484 group_select_next_widget (g);
485 break;
486 case CK_WindowPrev:
487 group_select_prev_widget (g);
488 break;
489 case CK_Options:
490 edit_options_dialog (h);
491 break;
492 case CK_OptionsSaveMode:
493 edit_save_mode_cmd ();
494 break;
495 case CK_SaveSetup:
496 save_setup_cmd ();
497 break;
498 default:
499 ret = MSG_NOT_HANDLED;
500 break;
501 }
502
503 return ret;
504 }
505
506
507
508
509
510
511
512 static gboolean
513 edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
514 {
515 Widget *w = WIDGET (edit);
516 long command = CK_InsertChar;
517 int char_for_insertion = -1;
518
519
520 if (!w->ext_mode && x_key < 256)
521 {
522 int c;
523
524 if (edit->charpoint >= MB_LEN_MAX)
525 {
526 edit->charpoint = 0;
527 edit->charbuf[edit->charpoint] = '\0';
528 }
529 if (edit->charpoint < MB_LEN_MAX)
530 {
531 edit->charbuf[edit->charpoint++] = x_key;
532 edit->charbuf[edit->charpoint] = '\0';
533 }
534
535
536 if (!mc_global.utf8_display)
537 {
538
539 c = convert_from_input_c (x_key);
540
541 if (is_printable (c))
542 {
543 if (!edit->utf8)
544 char_for_insertion = c;
545 else
546 char_for_insertion = convert_from_8bit_to_utf_c2 ((char) x_key);
547 goto fin;
548 }
549 }
550 else
551 {
552
553 int res;
554
555 res = str_is_valid_char (edit->charbuf, edit->charpoint);
556 if (res < 0 && res != -2)
557 {
558 edit->charpoint = 0;
559 goto fin;
560 }
561
562 if (edit->utf8)
563 {
564
565 if (res < 0)
566 {
567 char_for_insertion = x_key;
568 goto fin;
569 }
570
571 edit->charbuf[edit->charpoint] = '\0';
572 edit->charpoint = 0;
573 if (g_unichar_isprint (g_utf8_get_char (edit->charbuf)))
574 {
575 char_for_insertion = x_key;
576 goto fin;
577 }
578 }
579 else
580 {
581
582 if (res < 0)
583 {
584
585 goto fin;
586 }
587
588 if (g_unichar_isprint (g_utf8_get_char (edit->charbuf)))
589 {
590 c = convert_from_utf_to_current (edit->charbuf);
591 edit->charbuf[0] = '\0';
592 edit->charpoint = 0;
593 char_for_insertion = c;
594 goto fin;
595 }
596
597
598 edit->charbuf[0] = '\0';
599 edit->charpoint = 0;
600 }
601 }
602 }
603
604
605 command = widget_lookup_key (w, x_key);
606 if (command == CK_IgnoreKey)
607 command = CK_InsertChar;
608
609 fin:
610 *cmd = (int) command;
611 *ch = char_for_insertion;
612
613 return !(command == CK_InsertChar && char_for_insertion == -1);
614 }
615
616
617
618 static inline void
619 edit_quit (WDialog *h)
620 {
621 GList *l;
622 WEdit *e = NULL;
623 GSList *m = NULL;
624 GSList *me;
625
626
627 widget_set_state (WIDGET (h), WST_ACTIVE, TRUE);
628
629
630 for (l = GROUP (h)->widgets; l != NULL; l = g_list_next (l))
631 if (edit_widget_is_editor (CONST_WIDGET (l->data)))
632 {
633 e = EDIT (l->data);
634
635 if (e->drag_state != MCEDIT_DRAG_NONE)
636 {
637 edit_restore_size (e);
638 g_slist_free (m);
639 return;
640 }
641
642
643
644 if (e->modified != 0)
645 m = g_slist_prepend (m, l->data);
646 }
647
648 for (me = m; me != NULL; me = g_slist_next (me))
649 {
650 e = EDIT (me->data);
651
652 widget_select (WIDGET (e));
653
654 if (!edit_ok_to_quit (e))
655 break;
656 }
657
658
659 if (me == NULL)
660 dlg_close (h);
661
662 g_slist_free (m);
663 }
664
665
666
667 static inline void
668 edit_set_buttonbar (WEdit *edit, WButtonBar *bb)
669 {
670 Widget *w = WIDGET (edit);
671
672 buttonbar_set_label (bb, 1, Q_ ("ButtonBar|Help"), w->keymap, NULL);
673 buttonbar_set_label (bb, 2, Q_ ("ButtonBar|Save"), w->keymap, w);
674 buttonbar_set_label (bb, 3, Q_ ("ButtonBar|Mark"), w->keymap, w);
675 buttonbar_set_label (bb, 4, Q_ ("ButtonBar|Replac"), w->keymap, w);
676 buttonbar_set_label (bb, 5, Q_ ("ButtonBar|Copy"), w->keymap, w);
677 buttonbar_set_label (bb, 6, Q_ ("ButtonBar|Move"), w->keymap, w);
678 buttonbar_set_label (bb, 7, Q_ ("ButtonBar|Search"), w->keymap, w);
679 buttonbar_set_label (bb, 8, Q_ ("ButtonBar|Delete"), w->keymap, w);
680 buttonbar_set_label (bb, 9, Q_ ("ButtonBar|PullDn"), w->keymap, NULL);
681 buttonbar_set_label (bb, 10, Q_ ("ButtonBar|Quit"), w->keymap, NULL);
682 }
683
684
685
686 static void
687 edit_total_update (WEdit *edit)
688 {
689 edit_find_bracket (edit);
690 edit->force |= REDRAW_COMPLETELY;
691 edit_update_curs_row (edit);
692 edit_update_screen (edit);
693 }
694
695
696
697 static gboolean
698 edit_update_cursor (WEdit *edit, const mouse_event_t *event)
699 {
700 int x, y;
701 gboolean done;
702
703 x = event->x - (edit->fullscreen != 0 ? 0 : 1);
704 y = event->y - (edit->fullscreen != 0 ? 0 : 1);
705
706 if (edit->mark2 != -1 && event->msg == MSG_MOUSE_UP)
707 return TRUE;
708
709 if (event->msg == MSG_MOUSE_DOWN || event->msg == MSG_MOUSE_UP)
710 edit_push_key_press (edit);
711
712 if (!edit_options.cursor_beyond_eol)
713 edit->prev_col = x - edit->start_col - edit_options.line_state_width;
714 else
715 {
716 long line_len;
717
718 line_len = edit_move_forward3 (edit, edit_buffer_get_current_bol (&edit->buffer), 0,
719 edit_buffer_get_current_eol (&edit->buffer));
720
721 if (x > line_len - 1)
722 {
723 edit->over_col = x - line_len - edit->start_col - edit_options.line_state_width;
724 edit->prev_col = line_len;
725 }
726 else
727 {
728 edit->over_col = 0;
729 edit->prev_col = x - edit_options.line_state_width - edit->start_col;
730 }
731 }
732
733 if (y > edit->curs_row)
734 edit_move_down (edit, y - edit->curs_row, FALSE);
735 else if (y < edit->curs_row)
736 edit_move_up (edit, edit->curs_row - y, FALSE);
737 else
738 edit_move_to_prev_col (edit, edit_buffer_get_current_bol (&edit->buffer));
739
740 if (event->msg == MSG_MOUSE_CLICK)
741 {
742 edit_mark_cmd (edit, TRUE);
743 edit->highlight = 0;
744 }
745
746 done = (event->msg != MSG_MOUSE_DRAG);
747 if (done)
748 edit_mark_cmd (edit, FALSE);
749
750 return done;
751 }
752
753
754
755
756 static cb_ret_t
757 edit_dialog_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
758 {
759 WGroup *g = GROUP (w);
760 WDialog *h = DIALOG (w);
761
762 switch (msg)
763 {
764 case MSG_INIT:
765 edit_dlg_init ();
766 return MSG_HANDLED;
767
768 case MSG_RESIZE:
769 dlg_default_callback (w, NULL, MSG_RESIZE, 0, NULL);
770 menubar_arrange (menubar_find (h));
771 return MSG_HANDLED;
772
773 case MSG_ACTION:
774 {
775
776
777 cb_ret_t result;
778
779 result = edit_dialog_command_execute (h, parm);
780
781
782
783 if (result == MSG_NOT_HANDLED && sender == WIDGET (menubar_find (h)))
784 result = send_message (g->current->data, NULL, MSG_ACTION, parm, NULL);
785
786 return result;
787 }
788
789 case MSG_KEY:
790 {
791 Widget *we = WIDGET (g->current->data);
792 cb_ret_t ret = MSG_NOT_HANDLED;
793
794 if (edit_widget_is_editor (we))
795 {
796 gboolean ext_mode;
797 long command;
798
799
800 ext_mode = we->ext_mode;
801 command = widget_lookup_key (we, parm);
802 we->ext_mode = ext_mode;
803
804 if (command == CK_IgnoreKey)
805 we->ext_mode = FALSE;
806 else
807 {
808 ret = edit_dialog_command_execute (h, command);
809
810
811 if (ret == MSG_HANDLED)
812 we->ext_mode = FALSE;
813 }
814 }
815
816
817
818
819
820
821
822
823 if (!is_idle ())
824 widget_idle (w, TRUE);
825 return ret;
826 }
827
828
829 case MSG_UNHANDLED_KEY:
830 return edit_drop_hotkey_menu (h, parm) ? MSG_HANDLED : MSG_NOT_HANDLED;
831
832 case MSG_VALIDATE:
833 edit_quit (h);
834 return MSG_HANDLED;
835
836 case MSG_DESTROY:
837 edit_dlg_deinit ();
838 return MSG_HANDLED;
839
840 case MSG_IDLE:
841 widget_idle (w, FALSE);
842 return send_message (g->current->data, NULL, MSG_IDLE, 0, NULL);
843
844 default:
845 return dlg_default_callback (w, sender, msg, parm, data);
846 }
847 }
848
849
850
851
852
853
854
855
856
857
858 static void
859 edit_dialog_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
860 {
861 gboolean unhandled = TRUE;
862
863 if (msg == MSG_MOUSE_DOWN && event->y == 0)
864 {
865 WGroup *g = GROUP (w);
866 WDialog *h = DIALOG (w);
867 WMenuBar *b;
868
869 b = menubar_find (h);
870
871 if (!widget_get_state (WIDGET (b), WST_FOCUSED))
872 {
873
874
875 GList *l;
876 GList *top = NULL;
877 int x;
878
879
880 for (l = g->widgets; l != NULL; l = g_list_next (l))
881 if (edit_widget_is_editor (CONST_WIDGET (l->data))
882 && EDIT (l->data)->fullscreen != 0)
883 top = l;
884
885
886 x = w->rect.cols - 6;
887
888 if (top != NULL && event->x >= x)
889 {
890 WEdit *e = EDIT (top->data);
891
892 if (top != g->current)
893 {
894
895 widget_select (WIDGET (e));
896 }
897
898
899 if (event->x - x <= 2)
900 edit_toggle_fullscreen (e);
901 else
902 send_message (h, NULL, MSG_ACTION, CK_Close, NULL);
903
904 unhandled = FALSE;
905 }
906
907 if (unhandled)
908 menubar_activate (b, drop_menus, -1);
909 }
910 }
911
912
913 event->result.abort = unhandled;
914 }
915
916
917
918 static cb_ret_t
919 edit_dialog_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
920 {
921 switch (msg)
922 {
923 case MSG_INIT:
924 w->rect = WIDGET (w->owner)->rect;
925 rect_grow (&w->rect, -1, 0);
926 w->pos_flags |= WPOS_KEEP_ALL;
927 return MSG_HANDLED;
928
929 default:
930 return background_callback (w, sender, msg, parm, data);
931 }
932 }
933
934
935
936 static cb_ret_t
937 edit_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
938 {
939 WEdit *e = EDIT (w);
940
941 switch (msg)
942 {
943 case MSG_FOCUS:
944 edit_set_buttonbar (e, buttonbar_find (DIALOG (w->owner)));
945 return MSG_HANDLED;
946
947 case MSG_DRAW:
948 e->force |= REDRAW_COMPLETELY;
949 edit_update_screen (e);
950 return MSG_HANDLED;
951
952 case MSG_KEY:
953 {
954 int cmd, ch;
955 cb_ret_t ret = MSG_NOT_HANDLED;
956
957
958 if (macro_index == -1 && !bracketed_pasting_in_progress && edit_execute_macro (e, parm))
959 {
960 edit_update_screen (e);
961 ret = MSG_HANDLED;
962 }
963 else if (edit_translate_key (e, parm, &cmd, &ch))
964 {
965 edit_execute_key_command (e, cmd, ch);
966 edit_update_screen (e);
967 ret = MSG_HANDLED;
968 }
969
970 return ret;
971 }
972
973 case MSG_ACTION:
974
975 edit_execute_key_command (e, parm, -1);
976 edit_update_screen (e);
977 return MSG_HANDLED;
978
979 case MSG_CURSOR:
980 {
981 int y, x;
982
983 y = (e->fullscreen != 0 ? 0 : 1) + EDIT_TEXT_VERTICAL_OFFSET + e->curs_row;
984 x = (e->fullscreen != 0 ? 0 : 1) + EDIT_TEXT_HORIZONTAL_OFFSET
985 + edit_options.line_state_width + e->curs_col + e->start_col + e->over_col;
986
987 widget_gotoyx (w, y, x);
988 return MSG_HANDLED;
989 }
990
991 case MSG_IDLE:
992 edit_update_screen (e);
993 return MSG_HANDLED;
994
995 case MSG_DESTROY:
996 edit_clean (e);
997 return MSG_HANDLED;
998
999 default:
1000 return widget_default_callback (w, sender, msg, parm, data);
1001 }
1002 }
1003
1004
1005
1006
1007
1008
1009 static void
1010 edit_mouse_handle_move_resize (Widget *w, mouse_msg_t msg, mouse_event_t *event)
1011 {
1012 WEdit *edit = EDIT (w);
1013 WRect *r = &w->rect;
1014 const WRect *h = &CONST_WIDGET (w->owner)->rect;
1015 int global_x, global_y;
1016
1017 if (msg == MSG_MOUSE_UP)
1018 {
1019
1020 edit_execute_cmd (edit, CK_Enter, -1);
1021 edit_update_screen (edit);
1022 return;
1023 }
1024
1025 if (msg != MSG_MOUSE_DRAG)
1026
1027
1028
1029
1030
1031
1032
1033 return;
1034
1035
1036 global_x = event->x + r->x;
1037 global_y = event->y + r->y;
1038
1039
1040 global_y = CLAMP (global_y, h->y + 1, h->y + h->lines - 2);
1041 global_x =
1042 CLAMP (global_x, h->x,
1043 h->x + h->cols - 1);
1044
1045 if (edit->drag_state == MCEDIT_DRAG_MOVE)
1046 {
1047 r->y = global_y;
1048 r->x = global_x - edit->drag_state_start;
1049 }
1050 else if (edit->drag_state == MCEDIT_DRAG_RESIZE)
1051 {
1052 r->lines = MAX (WINDOW_MIN_LINES, global_y - r->y + 1);
1053 r->cols = MAX (WINDOW_MIN_COLS, global_x - r->x + 1);
1054 }
1055
1056 edit->force |= REDRAW_COMPLETELY;
1057
1058
1059 widget_draw (WIDGET (w->owner));
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 static void
1072 edit_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
1073 {
1074 WEdit *edit = EDIT (w);
1075
1076 int dx = edit->fullscreen != 0 ? 0 : 2;
1077
1078 int close_x, toggle_fullscreen_x;
1079
1080 close_x = (w->rect.cols - 1) - dx - 1;
1081 toggle_fullscreen_x = close_x - 3;
1082
1083 if (edit->drag_state != MCEDIT_DRAG_NONE)
1084 {
1085
1086 edit_mouse_handle_move_resize (w, msg, event);
1087 return;
1088 }
1089
1090
1091
1092
1093
1094 if (msg == MSG_MOUSE_DOWN && (event->y + w->rect.y == LINES - 1))
1095 {
1096 event->result.abort = TRUE;
1097 return;
1098 }
1099
1100 switch (msg)
1101 {
1102 case MSG_MOUSE_DOWN:
1103 widget_select (w);
1104 edit_update_curs_row (edit);
1105 edit_update_curs_col (edit);
1106
1107 if (edit->fullscreen == 0)
1108 {
1109 if (event->y == 0)
1110 {
1111 if (event->x >= close_x - 1 && event->x <= close_x + 1)
1112 ;
1113 else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
1114 ;
1115 else
1116 {
1117
1118 edit_execute_cmd (edit, CK_WindowMove, -1);
1119 edit_update_screen (
1120 edit);
1121 edit->drag_state_start = event->x;
1122 }
1123 break;
1124 }
1125
1126 if (event->y == w->rect.lines - 1 && event->x == w->rect.cols - 1)
1127 {
1128
1129 edit_execute_cmd (edit, CK_WindowResize, -1);
1130 break;
1131 }
1132 }
1133
1134 MC_FALLTHROUGH;
1135
1136 case MSG_MOUSE_UP:
1137 edit_update_cursor (edit, event);
1138 edit_total_update (edit);
1139 break;
1140
1141 case MSG_MOUSE_CLICK:
1142 if (event->y == 0)
1143 {
1144 if (event->x >= close_x - 1 && event->x <= close_x + 1)
1145 send_message (w->owner, NULL, MSG_ACTION, CK_Close, NULL);
1146 else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
1147 edit_toggle_fullscreen (edit);
1148 else if (edit->fullscreen == 0 && event->count == GPM_DOUBLE)
1149
1150 edit_toggle_fullscreen (edit);
1151 }
1152 else if (event->count == GPM_DOUBLE)
1153 {
1154
1155 edit_mark_current_word_cmd (edit);
1156 edit_total_update (edit);
1157 }
1158 else if (event->count == GPM_TRIPLE)
1159 {
1160
1161 edit_mark_current_line_cmd (edit);
1162 edit_total_update (edit);
1163 }
1164 break;
1165
1166 case MSG_MOUSE_DRAG:
1167 edit_update_cursor (edit, event);
1168 edit_total_update (edit);
1169 break;
1170
1171 case MSG_MOUSE_SCROLL_UP:
1172 edit_move_up (edit, 2, TRUE);
1173 edit_total_update (edit);
1174 break;
1175
1176 case MSG_MOUSE_SCROLL_DOWN:
1177 edit_move_down (edit, 2, TRUE);
1178 edit_total_update (edit);
1179 break;
1180
1181 default:
1182 break;
1183 }
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197 gboolean
1198 edit_file (const edit_arg_t *arg)
1199 {
1200 GList *files;
1201 gboolean ok;
1202
1203 files = g_list_prepend (NULL, (edit_arg_t *) arg);
1204 ok = edit_files (files);
1205 g_list_free (files);
1206
1207 return ok;
1208 }
1209
1210
1211
1212 gboolean
1213 edit_files (const GList *files)
1214 {
1215 static gboolean made_directory = FALSE;
1216 WDialog *edit_dlg;
1217 WGroup *g;
1218 WMenuBar *menubar;
1219 Widget *w, *wd;
1220 const GList *file;
1221 gboolean ok = FALSE;
1222
1223 if (!made_directory)
1224 {
1225 char *dir;
1226
1227 dir = mc_build_filename (mc_config_get_cache_path (), EDIT_HOME_DIR, (char *) NULL);
1228 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
1229 g_free (dir);
1230
1231 dir = mc_build_filename (mc_config_get_path (), EDIT_HOME_DIR, (char *) NULL);
1232 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
1233 g_free (dir);
1234
1235 dir = mc_build_filename (mc_config_get_data_path (), EDIT_HOME_DIR, (char *) NULL);
1236 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
1237 g_free (dir);
1238 }
1239
1240
1241 edit_dlg = dlg_create (FALSE, 0, 0, 1, 1, WPOS_FULLSCREEN, FALSE, NULL, edit_dialog_callback,
1242 edit_dialog_mouse_callback, "[Internal File Editor]", NULL);
1243 wd = WIDGET (edit_dlg);
1244 widget_want_tab (wd, TRUE);
1245 wd->keymap = editor_map;
1246 wd->ext_keymap = editor_x_map;
1247
1248 edit_dlg->get_shortcut = edit_get_shortcut;
1249 edit_dlg->get_title = edit_get_title;
1250
1251 g = GROUP (edit_dlg);
1252
1253 edit_dlg->bg = WIDGET (background_new (1, 0, wd->rect.lines - 2, wd->rect.cols,
1254 EDITOR_BACKGROUND_COLOR, ' ', edit_dialog_bg_callback));
1255 group_add_widget (g, edit_dlg->bg);
1256
1257 menubar = menubar_new (NULL);
1258 w = WIDGET (menubar);
1259 group_add_widget_autopos (g, w, w->pos_flags, NULL);
1260 edit_init_menu (menubar);
1261
1262 w = WIDGET (buttonbar_new ());
1263 group_add_widget_autopos (g, w, w->pos_flags, NULL);
1264
1265 for (file = files; file != NULL; file = g_list_next (file))
1266 {
1267 gboolean f_ok;
1268
1269 f_ok = edit_load_file_from_filename (edit_dlg, (const edit_arg_t *) file->data);
1270
1271 ok = ok || f_ok;
1272 }
1273
1274 if (ok)
1275 dlg_run (edit_dlg);
1276
1277 if (!ok || widget_get_state (wd, WST_CLOSED))
1278 widget_destroy (wd);
1279
1280 return ok;
1281 }
1282
1283
1284
1285 WEdit *
1286 edit_find_editor (const WDialog *h)
1287 {
1288 const WGroup *g = CONST_GROUP (h);
1289
1290 if (edit_widget_is_editor (CONST_WIDGET (g->current->data)))
1291 return EDIT (g->current->data);
1292 return EDIT (widget_find_by_type (CONST_WIDGET (h), edit_callback));
1293 }
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 gboolean
1304 edit_widget_is_editor (const Widget *w)
1305 {
1306 return (w != NULL && w->callback == edit_callback);
1307 }
1308
1309
1310
1311 void
1312 edit_update_screen (WEdit *e)
1313 {
1314 edit_scroll_screen_over_cursor (e);
1315 edit_update_curs_col (e);
1316 edit_status (e, widget_get_state (WIDGET (e), WST_FOCUSED));
1317
1318
1319 if (!is_idle ())
1320 e->force |= REDRAW_PAGE;
1321 else
1322 {
1323 if ((e->force & REDRAW_COMPLETELY) != 0)
1324 e->force |= REDRAW_PAGE;
1325 edit_render_keypress (e);
1326 }
1327
1328 widget_draw (WIDGET (buttonbar_find (DIALOG (WIDGET (e)->owner))));
1329 }
1330
1331
1332
1333
1334
1335
1336
1337
1338 void
1339 edit_save_size (WEdit *edit)
1340 {
1341 edit->loc_prev = WIDGET (edit)->rect;
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359 gboolean
1360 edit_add_window (WDialog *h, const WRect *r, const edit_arg_t *arg)
1361 {
1362 WEdit *edit;
1363 Widget *w;
1364
1365 edit = edit_init (NULL, r, arg);
1366 if (edit == NULL)
1367 return FALSE;
1368
1369 w = WIDGET (edit);
1370 w->callback = edit_callback;
1371 w->mouse_callback = edit_mouse_callback;
1372
1373 group_add_widget_autopos (GROUP (h), w, WPOS_KEEP_ALL, NULL);
1374 edit_set_buttonbar (edit, buttonbar_find (h));
1375 widget_draw (WIDGET (h));
1376
1377 return TRUE;
1378 }
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389 gboolean
1390 edit_handle_move_resize (WEdit *edit, long command)
1391 {
1392 Widget *w = WIDGET (edit);
1393 gboolean ret = FALSE;
1394
1395 if (edit->fullscreen != 0)
1396 {
1397 edit->drag_state = MCEDIT_DRAG_NONE;
1398 w->mouse.forced_capture = FALSE;
1399 return ret;
1400 }
1401
1402 switch (edit->drag_state)
1403 {
1404 case MCEDIT_DRAG_NONE:
1405
1406 switch (command)
1407 {
1408 case CK_WindowMove:
1409 edit->drag_state = MCEDIT_DRAG_MOVE;
1410 edit_save_size (edit);
1411 edit_status (edit, TRUE);
1412
1413
1414
1415
1416
1417 edit->drag_state_start = w->rect.cols / 2;
1418 ret = TRUE;
1419 break;
1420 case CK_WindowResize:
1421 edit->drag_state = MCEDIT_DRAG_RESIZE;
1422 edit_save_size (edit);
1423 edit_status (edit, TRUE);
1424 ret = TRUE;
1425 break;
1426 default:
1427 break;
1428 }
1429 break;
1430
1431 case MCEDIT_DRAG_MOVE:
1432 switch (command)
1433 {
1434 case CK_WindowResize:
1435 edit->drag_state = MCEDIT_DRAG_RESIZE;
1436 ret = TRUE;
1437 break;
1438 case CK_Up:
1439 case CK_Down:
1440 case CK_Left:
1441 case CK_Right:
1442 edit_window_move (edit, command);
1443 ret = TRUE;
1444 break;
1445 case CK_Enter:
1446 case CK_WindowMove:
1447 edit->drag_state = MCEDIT_DRAG_NONE;
1448 edit_status (edit, TRUE);
1449 MC_FALLTHROUGH;
1450 default:
1451 ret = TRUE;
1452 break;
1453 }
1454 break;
1455
1456 case MCEDIT_DRAG_RESIZE:
1457 switch (command)
1458 {
1459 case CK_WindowMove:
1460 edit->drag_state = MCEDIT_DRAG_MOVE;
1461 ret = TRUE;
1462 break;
1463 case CK_Up:
1464 case CK_Down:
1465 case CK_Left:
1466 case CK_Right:
1467 edit_window_resize (edit, command);
1468 ret = TRUE;
1469 break;
1470 case CK_Enter:
1471 case CK_WindowResize:
1472 edit->drag_state = MCEDIT_DRAG_NONE;
1473 edit_status (edit, TRUE);
1474 MC_FALLTHROUGH;
1475 default:
1476 ret = TRUE;
1477 break;
1478 }
1479 break;
1480
1481 default:
1482 break;
1483 }
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 w->mouse.forced_capture = (edit->drag_state != MCEDIT_DRAG_NONE);
1495
1496 return ret;
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506 void
1507 edit_toggle_fullscreen (WEdit *edit)
1508 {
1509 Widget *w = WIDGET (edit);
1510
1511 edit->fullscreen = edit->fullscreen != 0 ? 0 : 1;
1512 edit->force = REDRAW_COMPLETELY;
1513
1514 if (edit->fullscreen == 0)
1515 {
1516 edit_restore_size (edit);
1517
1518 w->pos_flags = WPOS_KEEP_DEFAULT;
1519 }
1520 else
1521 {
1522 WRect r;
1523
1524 edit_save_size (edit);
1525 r = WIDGET (w->owner)->rect;
1526 rect_grow (&r, -1, 0);
1527 widget_set_size_rect (w, &r);
1528
1529 w->pos_flags = WPOS_KEEP_ALL;
1530 edit->force |= REDRAW_PAGE;
1531 edit_update_screen (edit);
1532 }
1533 }
1534
1535