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