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 #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
64 #include "edit-impl.h"
65 #include "editwidget.h"
66 #include "editmacros.h"
67 #ifdef HAVE_ASPELL
68 #include "spell.h"
69 #endif
70
71
72
73 char *edit_window_state_char = NULL;
74 char *edit_window_close_char = NULL;
75
76
77
78 #define WINDOW_MIN_LINES (2 + 2)
79 #define WINDOW_MIN_COLS (2 + LINE_STATE_WIDTH + 2)
80
81
82
83
84
85
86
87 static unsigned int edit_dlg_init_refcounter = 0;
88
89
90
91
92
93
94
95
96 static void
97 edit_dlg_init (void)
98 {
99 edit_dlg_init_refcounter++;
100
101 if (edit_dlg_init_refcounter == 1)
102 {
103 edit_window_state_char = mc_skin_get ("widget-editor", "window-state-char", "*");
104 edit_window_close_char = mc_skin_get ("widget-editor", "window-close-char", "X");
105
106 #ifdef HAVE_ASPELL
107 aspell_init ();
108 #endif
109 }
110 }
111
112
113
114
115
116
117 static void
118 edit_dlg_deinit (void)
119 {
120 if (edit_dlg_init_refcounter == 1)
121 {
122 g_free (edit_window_state_char);
123 g_free (edit_window_close_char);
124
125 #ifdef HAVE_ASPELL
126 aspell_clean ();
127 #endif
128 }
129
130 if (edit_dlg_init_refcounter != 0)
131 edit_dlg_init_refcounter--;
132 }
133
134
135
136
137
138
139 static void
140 edit_about (void)
141 {
142 char *ver;
143
144 ver = g_strdup_printf ("MCEdit %s", mc_global.mc_version);
145
146 {
147 quick_widget_t quick_widgets[] = {
148
149 QUICK_LABEL (ver, NULL),
150 QUICK_SEPARATOR (TRUE),
151 QUICK_LABEL (N_("A user friendly text editor\n"
152 "written for the Midnight Commander."), NULL),
153 QUICK_SEPARATOR (FALSE),
154 QUICK_LABEL (N_("Copyright (C) 1996-2024 the Free Software Foundation"), NULL),
155 QUICK_START_BUTTONS (TRUE, TRUE),
156 QUICK_BUTTON (N_("&OK"), B_ENTER, NULL, NULL),
157 QUICK_END
158
159 };
160
161 WRect r = { -1, -1, 0, 40 };
162
163 quick_dialog_t qdlg = {
164 r, N_("About"), "[Internal File Editor]",
165 quick_widgets, NULL, NULL
166 };
167
168 quick_widgets[0].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
169 quick_widgets[2].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
170 quick_widgets[4].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
171
172 (void) quick_dialog (&qdlg);
173 }
174
175 g_free (ver);
176 }
177
178
179
180
181
182
183 static void
184 edit_help (const WDialog *h)
185 {
186 ev_help_t event_data = { NULL, h->help_ctx };
187
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 = listbox_window_new (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 = EDIT (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 = 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 ? "(*) " : " ";
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 #ifndef HAVE_CHARSET
518 if (is_printable (x_key))
519 {
520 char_for_insertion = x_key;
521 goto fin;
522 }
523 #else
524 int c;
525
526 if (edit->charpoint >= MB_LEN_MAX)
527 {
528 edit->charpoint = 0;
529 edit->charbuf[edit->charpoint] = '\0';
530 }
531 if (edit->charpoint < MB_LEN_MAX)
532 {
533 edit->charbuf[edit->charpoint++] = x_key;
534 edit->charbuf[edit->charpoint] = '\0';
535 }
536
537
538 if (!mc_global.utf8_display)
539 {
540
541 c = convert_from_input_c (x_key);
542
543 if (is_printable (c))
544 {
545 if (!edit->utf8)
546 char_for_insertion = c;
547 else
548 char_for_insertion = convert_from_8bit_to_utf_c2 ((char) x_key);
549 goto fin;
550 }
551 }
552 else
553 {
554
555 int res;
556
557 res = str_is_valid_char (edit->charbuf, edit->charpoint);
558 if (res < 0 && res != -2)
559 {
560 edit->charpoint = 0;
561 goto fin;
562 }
563
564 if (edit->utf8)
565 {
566
567 if (res < 0)
568 {
569 char_for_insertion = x_key;
570 goto fin;
571 }
572
573 edit->charbuf[edit->charpoint] = '\0';
574 edit->charpoint = 0;
575 if (g_unichar_isprint (g_utf8_get_char (edit->charbuf)))
576 {
577 char_for_insertion = x_key;
578 goto fin;
579 }
580 }
581 else
582 {
583
584 if (res < 0)
585 {
586
587 goto fin;
588 }
589
590 if (g_unichar_isprint (g_utf8_get_char (edit->charbuf)))
591 {
592 c = convert_from_utf_to_current (edit->charbuf);
593 edit->charbuf[0] = '\0';
594 edit->charpoint = 0;
595 char_for_insertion = c;
596 goto fin;
597 }
598
599
600 edit->charbuf[0] = '\0';
601 edit->charpoint = 0;
602 }
603 }
604 #endif
605 }
606
607
608 command = widget_lookup_key (w, x_key);
609 if (command == CK_IgnoreKey)
610 command = CK_InsertChar;
611
612 fin:
613 *cmd = (int) command;
614 *ch = char_for_insertion;
615
616 return !(command == CK_InsertChar && char_for_insertion == -1);
617 }
618
619
620
621
622 static inline void
623 edit_quit (WDialog *h)
624 {
625 GList *l;
626 WEdit *e = NULL;
627 GSList *m = NULL;
628 GSList *me;
629
630
631 widget_set_state (WIDGET (h), WST_ACTIVE, TRUE);
632
633
634 for (l = GROUP (h)->widgets; l != NULL; l = g_list_next (l))
635 if (edit_widget_is_editor (CONST_WIDGET (l->data)))
636 {
637 e = EDIT (l->data);
638
639 if (e->drag_state != MCEDIT_DRAG_NONE)
640 {
641 edit_restore_size (e);
642 g_slist_free (m);
643 return;
644 }
645
646
647
648 if (e->modified)
649 m = g_slist_prepend (m, l->data);
650 }
651
652 for (me = m; me != NULL; me = g_slist_next (me))
653 {
654 e = EDIT (me->data);
655
656 widget_select (WIDGET (e));
657
658 if (!edit_ok_to_exit (e))
659 break;
660 }
661
662
663 if (me == NULL)
664 dlg_close (h);
665
666 g_slist_free (m);
667 }
668
669
670
671 static inline void
672 edit_set_buttonbar (WEdit *edit, WButtonBar *bb)
673 {
674 Widget *w = WIDGET (edit);
675
676 buttonbar_set_label (bb, 1, Q_ ("ButtonBar|Help"), w->keymap, NULL);
677 buttonbar_set_label (bb, 2, Q_ ("ButtonBar|Save"), w->keymap, w);
678 buttonbar_set_label (bb, 3, Q_ ("ButtonBar|Mark"), w->keymap, w);
679 buttonbar_set_label (bb, 4, Q_ ("ButtonBar|Replac"), w->keymap, w);
680 buttonbar_set_label (bb, 5, Q_ ("ButtonBar|Copy"), w->keymap, w);
681 buttonbar_set_label (bb, 6, Q_ ("ButtonBar|Move"), w->keymap, w);
682 buttonbar_set_label (bb, 7, Q_ ("ButtonBar|Search"), w->keymap, w);
683 buttonbar_set_label (bb, 8, Q_ ("ButtonBar|Delete"), w->keymap, w);
684 buttonbar_set_label (bb, 9, Q_ ("ButtonBar|PullDn"), w->keymap, NULL);
685 buttonbar_set_label (bb, 10, Q_ ("ButtonBar|Quit"), w->keymap, NULL);
686 }
687
688
689
690 static void
691 edit_total_update (WEdit *edit)
692 {
693 edit_find_bracket (edit);
694 edit->force |= REDRAW_COMPLETELY;
695 edit_update_curs_row (edit);
696 edit_update_screen (edit);
697 }
698
699
700
701 static gboolean
702 edit_update_cursor (WEdit *edit, const mouse_event_t *event)
703 {
704 int x, y;
705 gboolean done;
706
707 x = event->x - (edit->fullscreen ? 0 : 1);
708 y = event->y - (edit->fullscreen ? 0 : 1);
709
710 if (edit->mark2 != -1 && event->msg == MSG_MOUSE_UP)
711 return TRUE;
712
713 if (event->msg == MSG_MOUSE_DOWN || event->msg == MSG_MOUSE_UP)
714 edit_push_key_press (edit);
715
716 if (!edit_options.cursor_beyond_eol)
717 edit->prev_col = x - edit->start_col - edit_options.line_state_width;
718 else
719 {
720 long line_len;
721
722 line_len =
723 edit_move_forward3 (edit, edit_buffer_get_current_bol (&edit->buffer), 0,
724 edit_buffer_get_current_eol (&edit->buffer));
725
726 if (x > line_len - 1)
727 {
728 edit->over_col = x - line_len - edit->start_col - edit_options.line_state_width;
729 edit->prev_col = line_len;
730 }
731 else
732 {
733 edit->over_col = 0;
734 edit->prev_col = x - edit_options.line_state_width - edit->start_col;
735 }
736 }
737
738 if (y > edit->curs_row)
739 edit_move_down (edit, y - edit->curs_row, FALSE);
740 else if (y < edit->curs_row)
741 edit_move_up (edit, edit->curs_row - y, FALSE);
742 else
743 edit_move_to_prev_col (edit, edit_buffer_get_current_bol (&edit->buffer));
744
745 if (event->msg == MSG_MOUSE_CLICK)
746 {
747 edit_mark_cmd (edit, TRUE);
748 edit->highlight = 0;
749 }
750
751 done = (event->msg != MSG_MOUSE_DRAG);
752 if (done)
753 edit_mark_cmd (edit, FALSE);
754
755 return done;
756 }
757
758
759
760
761 static cb_ret_t
762 edit_dialog_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
763 {
764 WGroup *g = GROUP (w);
765 WDialog *h = DIALOG (w);
766
767 switch (msg)
768 {
769 case MSG_INIT:
770 edit_dlg_init ();
771 return MSG_HANDLED;
772
773 case MSG_RESIZE:
774 dlg_default_callback (w, NULL, MSG_RESIZE, 0, NULL);
775 menubar_arrange (menubar_find (h));
776 return MSG_HANDLED;
777
778 case MSG_ACTION:
779 {
780
781
782 cb_ret_t result;
783
784 result = edit_dialog_command_execute (h, parm);
785
786
787
788 if (result == MSG_NOT_HANDLED && sender == WIDGET (menubar_find (h)))
789 result = send_message (g->current->data, NULL, MSG_ACTION, parm, NULL);
790
791 return result;
792 }
793
794 case MSG_KEY:
795 {
796 Widget *we = WIDGET (g->current->data);
797 cb_ret_t ret = MSG_NOT_HANDLED;
798
799 if (edit_widget_is_editor (we))
800 {
801 gboolean ext_mode;
802 long command;
803
804
805 ext_mode = we->ext_mode;
806 command = widget_lookup_key (we, parm);
807 we->ext_mode = ext_mode;
808
809 if (command == CK_IgnoreKey)
810 we->ext_mode = FALSE;
811 else
812 {
813 ret = edit_dialog_command_execute (h, command);
814
815
816 if (ret == MSG_HANDLED)
817 we->ext_mode = FALSE;
818 }
819 }
820
821
822
823
824
825
826
827
828 if (!is_idle ())
829 widget_idle (w, TRUE);
830 return ret;
831 }
832
833
834 case MSG_UNHANDLED_KEY:
835 return edit_drop_hotkey_menu (h, parm) ? MSG_HANDLED : MSG_NOT_HANDLED;
836
837 case MSG_VALIDATE:
838 edit_quit (h);
839 return MSG_HANDLED;
840
841 case MSG_DESTROY:
842 edit_dlg_deinit ();
843 return MSG_HANDLED;
844
845 case MSG_IDLE:
846 widget_idle (w, FALSE);
847 return send_message (g->current->data, NULL, MSG_IDLE, 0, NULL);
848
849 default:
850 return dlg_default_callback (w, sender, msg, parm, data);
851 }
852 }
853
854
855
856
857
858
859
860
861
862
863 static void
864 edit_dialog_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
865 {
866 gboolean unhandled = TRUE;
867
868 if (msg == MSG_MOUSE_DOWN && event->y == 0)
869 {
870 WGroup *g = GROUP (w);
871 WDialog *h = DIALOG (w);
872 WMenuBar *b;
873
874 b = menubar_find (h);
875
876 if (!widget_get_state (WIDGET (b), WST_FOCUSED))
877 {
878
879
880 GList *l;
881 GList *top = NULL;
882 int x;
883
884
885 for (l = g->widgets; l != NULL; l = g_list_next (l))
886 if (edit_widget_is_editor (CONST_WIDGET (l->data)) && EDIT (l->data)->fullscreen)
887 top = l;
888
889
890 x = w->rect.cols - 6;
891
892 if (top != NULL && event->x >= x)
893 {
894 WEdit *e = EDIT (top->data);
895
896 if (top != g->current)
897 {
898
899 widget_select (WIDGET (e));
900 }
901
902
903 if (event->x - x <= 2)
904 edit_toggle_fullscreen (e);
905 else
906 send_message (h, NULL, MSG_ACTION, CK_Close, NULL);
907
908 unhandled = FALSE;
909 }
910
911 if (unhandled)
912 menubar_activate (b, drop_menus, -1);
913 }
914 }
915
916
917 event->result.abort = unhandled;
918 }
919
920
921
922 static cb_ret_t
923 edit_dialog_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
924 {
925 switch (msg)
926 {
927 case MSG_INIT:
928 w->rect = WIDGET (w->owner)->rect;
929 rect_grow (&w->rect, -1, 0);
930 w->pos_flags |= WPOS_KEEP_ALL;
931 return MSG_HANDLED;
932
933 default:
934 return background_callback (w, sender, msg, parm, data);
935 }
936 }
937
938
939
940 static cb_ret_t
941 edit_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
942 {
943 WEdit *e = EDIT (w);
944
945 switch (msg)
946 {
947 case MSG_FOCUS:
948 edit_set_buttonbar (e, buttonbar_find (DIALOG (w->owner)));
949 return MSG_HANDLED;
950
951 case MSG_DRAW:
952 e->force |= REDRAW_COMPLETELY;
953 edit_update_screen (e);
954 return MSG_HANDLED;
955
956 case MSG_KEY:
957 {
958 int cmd, ch;
959 cb_ret_t ret = MSG_NOT_HANDLED;
960
961
962 if (macro_index == -1 && !bracketed_pasting_in_progress && edit_execute_macro (e, parm))
963 {
964 edit_update_screen (e);
965 ret = MSG_HANDLED;
966 }
967 else if (edit_translate_key (e, parm, &cmd, &ch))
968 {
969 edit_execute_key_command (e, cmd, ch);
970 edit_update_screen (e);
971 ret = MSG_HANDLED;
972 }
973
974 return ret;
975 }
976
977 case MSG_ACTION:
978
979 edit_execute_key_command (e, parm, -1);
980 edit_update_screen (e);
981 return MSG_HANDLED;
982
983 case MSG_CURSOR:
984 {
985 int y, x;
986
987 y = (e->fullscreen ? 0 : 1) + EDIT_TEXT_VERTICAL_OFFSET + e->curs_row;
988 x = (e->fullscreen ? 0 : 1) + EDIT_TEXT_HORIZONTAL_OFFSET +
989 edit_options.line_state_width + e->curs_col + e->start_col + e->over_col;
990
991 widget_gotoyx (w, y, x);
992 return MSG_HANDLED;
993 }
994
995 case MSG_IDLE:
996 edit_update_screen (e);
997 return MSG_HANDLED;
998
999 case MSG_DESTROY:
1000 edit_clean (e);
1001 return MSG_HANDLED;
1002
1003 default:
1004 return widget_default_callback (w, sender, msg, parm, data);
1005 }
1006 }
1007
1008
1009
1010
1011
1012
1013 static void
1014 edit_mouse_handle_move_resize (Widget *w, mouse_msg_t msg, mouse_event_t *event)
1015 {
1016 WEdit *edit = EDIT (w);
1017 WRect *r = &w->rect;
1018 const WRect *h = &CONST_WIDGET (w->owner)->rect;
1019 int global_x, global_y;
1020
1021 if (msg == MSG_MOUSE_UP)
1022 {
1023
1024 edit_execute_cmd (edit, CK_Enter, -1);
1025 edit_update_screen (edit);
1026 return;
1027 }
1028
1029 if (msg != MSG_MOUSE_DRAG)
1030
1031
1032
1033
1034
1035
1036
1037 return;
1038
1039
1040 global_x = event->x + r->x;
1041 global_y = event->y + r->y;
1042
1043
1044 global_y = CLAMP (global_y, h->y + 1, h->y + h->lines - 2);
1045 global_x = CLAMP (global_x, h->x, h->x + h->cols - 1);
1046
1047 if (edit->drag_state == MCEDIT_DRAG_MOVE)
1048 {
1049 r->y = global_y;
1050 r->x = global_x - edit->drag_state_start;
1051 }
1052 else if (edit->drag_state == MCEDIT_DRAG_RESIZE)
1053 {
1054 r->lines = MAX (WINDOW_MIN_LINES, global_y - r->y + 1);
1055 r->cols = MAX (WINDOW_MIN_COLS, global_x - r->x + 1);
1056 }
1057
1058 edit->force |= REDRAW_COMPLETELY;
1059
1060
1061 widget_draw (WIDGET (w->owner));
1062 }
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 static void
1074 edit_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
1075 {
1076 WEdit *edit = EDIT (w);
1077
1078 int dx = edit->fullscreen ? 0 : 2;
1079
1080 int close_x, toggle_fullscreen_x;
1081
1082 close_x = (w->rect.cols - 1) - dx - 1;
1083 toggle_fullscreen_x = close_x - 3;
1084
1085 if (edit->drag_state != MCEDIT_DRAG_NONE)
1086 {
1087
1088 edit_mouse_handle_move_resize (w, msg, event);
1089 return;
1090 }
1091
1092
1093
1094
1095
1096 if (msg == MSG_MOUSE_DOWN && (event->y + w->rect.y == LINES - 1))
1097 {
1098 event->result.abort = TRUE;
1099 return;
1100 }
1101
1102 switch (msg)
1103 {
1104 case MSG_MOUSE_DOWN:
1105 widget_select (w);
1106 edit_update_curs_row (edit);
1107 edit_update_curs_col (edit);
1108
1109 if (!edit->fullscreen)
1110 {
1111 if (event->y == 0)
1112 {
1113 if (event->x >= close_x - 1 && event->x <= close_x + 1)
1114 ;
1115 else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
1116 ;
1117 else
1118 {
1119
1120 edit_execute_cmd (edit, CK_WindowMove, -1);
1121 edit_update_screen (edit);
1122 edit->drag_state_start = event->x;
1123 }
1124 break;
1125 }
1126
1127 if (event->y == w->rect.lines - 1 && event->x == w->rect.cols - 1)
1128 {
1129
1130 edit_execute_cmd (edit, CK_WindowResize, -1);
1131 break;
1132 }
1133 }
1134
1135 MC_FALLTHROUGH;
1136
1137 case MSG_MOUSE_UP:
1138 edit_update_cursor (edit, event);
1139 edit_total_update (edit);
1140 break;
1141
1142 case MSG_MOUSE_CLICK:
1143 if (event->y == 0)
1144 {
1145 if (event->x >= close_x - 1 && event->x <= close_x + 1)
1146 send_message (w->owner, NULL, MSG_ACTION, CK_Close, NULL);
1147 else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
1148 edit_toggle_fullscreen (edit);
1149 else if (!edit->fullscreen && event->count == GPM_DOUBLE)
1150
1151 edit_toggle_fullscreen (edit);
1152 }
1153 else if (event->count == GPM_DOUBLE)
1154 {
1155
1156 edit_mark_current_word_cmd (edit);
1157 edit_total_update (edit);
1158 }
1159 else if (event->count == GPM_TRIPLE)
1160 {
1161
1162 edit_mark_current_line_cmd (edit);
1163 edit_total_update (edit);
1164 }
1165 break;
1166
1167 case MSG_MOUSE_DRAG:
1168 edit_update_cursor (edit, event);
1169 edit_total_update (edit);
1170 break;
1171
1172 case MSG_MOUSE_SCROLL_UP:
1173 edit_move_up (edit, 2, TRUE);
1174 edit_total_update (edit);
1175 break;
1176
1177 case MSG_MOUSE_SCROLL_DOWN:
1178 edit_move_down (edit, 2, TRUE);
1179 edit_total_update (edit);
1180 break;
1181
1182 default:
1183 break;
1184 }
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198 gboolean
1199 edit_file (const edit_arg_t *arg)
1200 {
1201 GList *files;
1202 gboolean ok;
1203
1204 files = g_list_prepend (NULL, (edit_arg_t *) 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 gboolean f_ok;
1272
1273 f_ok = edit_load_file_from_filename (edit_dlg, (const edit_arg_t *) file->data);
1274
1275 ok = ok || f_ok;
1276 }
1277
1278 if (ok)
1279 dlg_run (edit_dlg);
1280
1281 if (!ok || widget_get_state (wd, WST_CLOSED))
1282 widget_destroy (wd);
1283
1284 return ok;
1285 }
1286
1287
1288
1289 WEdit *
1290 edit_find_editor (const WDialog *h)
1291 {
1292 const WGroup *g = CONST_GROUP (h);
1293
1294 if (edit_widget_is_editor (CONST_WIDGET (g->current->data)))
1295 return EDIT (g->current->data);
1296 return EDIT (widget_find_by_type (CONST_WIDGET (h), edit_callback));
1297 }
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 gboolean
1308 edit_widget_is_editor (const Widget *w)
1309 {
1310 return (w != NULL && w->callback == edit_callback);
1311 }
1312
1313
1314
1315 void
1316 edit_update_screen (WEdit *e)
1317 {
1318 edit_scroll_screen_over_cursor (e);
1319 edit_update_curs_col (e);
1320 edit_status (e, widget_get_state (WIDGET (e), WST_FOCUSED));
1321
1322
1323 if (!is_idle ())
1324 e->force |= REDRAW_PAGE;
1325 else
1326 {
1327 if ((e->force & REDRAW_COMPLETELY) != 0)
1328 e->force |= REDRAW_PAGE;
1329 edit_render_keypress (e);
1330 }
1331
1332 widget_draw (WIDGET (buttonbar_find (DIALOG (WIDGET (e)->owner))));
1333 }
1334
1335
1336
1337
1338
1339
1340
1341
1342 void
1343 edit_save_size (WEdit *edit)
1344 {
1345 edit->loc_prev = WIDGET (edit)->rect;
1346 }
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 gboolean
1364 edit_add_window (WDialog *h, const WRect *r, const edit_arg_t *arg)
1365 {
1366 WEdit *edit;
1367 Widget *w;
1368
1369 edit = edit_init (NULL, r, arg);
1370 if (edit == NULL)
1371 return FALSE;
1372
1373 w = WIDGET (edit);
1374 w->callback = edit_callback;
1375 w->mouse_callback = edit_mouse_callback;
1376
1377 group_add_widget_autopos (GROUP (h), w, WPOS_KEEP_ALL, NULL);
1378 edit_set_buttonbar (edit, buttonbar_find (h));
1379 widget_draw (WIDGET (h));
1380
1381 return TRUE;
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393 gboolean
1394 edit_handle_move_resize (WEdit *edit, long command)
1395 {
1396 Widget *w = WIDGET (edit);
1397 gboolean ret = FALSE;
1398
1399 if (edit->fullscreen)
1400 {
1401 edit->drag_state = MCEDIT_DRAG_NONE;
1402 w->mouse.forced_capture = FALSE;
1403 return ret;
1404 }
1405
1406 switch (edit->drag_state)
1407 {
1408 case MCEDIT_DRAG_NONE:
1409
1410 switch (command)
1411 {
1412 case CK_WindowMove:
1413 edit->drag_state = MCEDIT_DRAG_MOVE;
1414 edit_save_size (edit);
1415 edit_status (edit, TRUE);
1416
1417
1418
1419
1420
1421 edit->drag_state_start = w->rect.cols / 2;
1422 ret = TRUE;
1423 break;
1424 case CK_WindowResize:
1425 edit->drag_state = MCEDIT_DRAG_RESIZE;
1426 edit_save_size (edit);
1427 edit_status (edit, TRUE);
1428 ret = TRUE;
1429 break;
1430 default:
1431 break;
1432 }
1433 break;
1434
1435 case MCEDIT_DRAG_MOVE:
1436 switch (command)
1437 {
1438 case CK_WindowResize:
1439 edit->drag_state = MCEDIT_DRAG_RESIZE;
1440 ret = TRUE;
1441 break;
1442 case CK_Up:
1443 case CK_Down:
1444 case CK_Left:
1445 case CK_Right:
1446 edit_window_move (edit, command);
1447 ret = TRUE;
1448 break;
1449 case CK_Enter:
1450 case CK_WindowMove:
1451 edit->drag_state = MCEDIT_DRAG_NONE;
1452 edit_status (edit, TRUE);
1453 MC_FALLTHROUGH;
1454 default:
1455 ret = TRUE;
1456 break;
1457 }
1458 break;
1459
1460 case MCEDIT_DRAG_RESIZE:
1461 switch (command)
1462 {
1463 case CK_WindowMove:
1464 edit->drag_state = MCEDIT_DRAG_MOVE;
1465 ret = TRUE;
1466 break;
1467 case CK_Up:
1468 case CK_Down:
1469 case CK_Left:
1470 case CK_Right:
1471 edit_window_resize (edit, command);
1472 ret = TRUE;
1473 break;
1474 case CK_Enter:
1475 case CK_WindowResize:
1476 edit->drag_state = MCEDIT_DRAG_NONE;
1477 edit_status (edit, TRUE);
1478 MC_FALLTHROUGH;
1479 default:
1480 ret = TRUE;
1481 break;
1482 }
1483 break;
1484
1485 default:
1486 break;
1487 }
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498 w->mouse.forced_capture = (edit->drag_state != MCEDIT_DRAG_NONE);
1499
1500 return ret;
1501 }
1502
1503
1504
1505
1506
1507
1508
1509
1510 void
1511 edit_toggle_fullscreen (WEdit *edit)
1512 {
1513 Widget *w = WIDGET (edit);
1514
1515 edit->fullscreen = !edit->fullscreen;
1516 edit->force = REDRAW_COMPLETELY;
1517
1518 if (!edit->fullscreen)
1519 {
1520 edit_restore_size (edit);
1521
1522 w->pos_flags = WPOS_KEEP_DEFAULT;
1523 }
1524 else
1525 {
1526 WRect r;
1527
1528 edit_save_size (edit);
1529 r = WIDGET (w->owner)->rect;
1530 rect_grow (&r, -1, 0);
1531 widget_set_size_rect (w, &r);
1532
1533 w->pos_flags = WPOS_KEEP_ALL;
1534 edit->force |= REDRAW_PAGE;
1535 edit_update_screen (edit);
1536 }
1537 }
1538
1539