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