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