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