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