Handle CK_ShowNumbers action in dialog level instead of widget one.
[midnight-commander.git] / src / editor / editwidget.c
blob580f204f7239d1b4072961fb866adfbe406c8986
1 /*
2 Editor initialisation and callback handler.
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
5 2007,2011
6 The Free Software Foundation, Inc.
8 Written by:
9 Paul Sheer, 1996, 1997
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 /** \file
28 * \brief Source: editor initialisation and callback handler
29 * \author Paul Sheer
30 * \date 1996, 1997
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <sys/stat.h>
43 #include <stdlib.h>
45 #include "lib/global.h"
47 #include "lib/tty/tty.h" /* LINES, COLS */
48 #include "lib/tty/key.h" /* is_idle() */
49 #include "lib/tty/color.h" /* tty_setcolor() */
50 #include "lib/skin.h" /* EDITOR_NORMAL_COLOR */
51 #include "lib/strutil.h" /* str_term_trim() */
52 #include "lib/util.h" /* mc_build_filename() */
53 #include "lib/widget.h"
54 #include "lib/mcconfig.h"
55 #include "lib/event.h" /* mc_event_raise() */
57 #include "src/keybind-defaults.h"
58 #include "src/main.h" /* home_dir */
59 #include "src/filemanager/cmd.h" /* view_other_cmd(), save_setup_cmd() */
60 #include "src/learn.h" /* learn_keys() */
62 #include "edit-impl.h"
63 #include "editwidget.h"
65 /*** global variables ****************************************************************************/
67 /*** file scope macro definitions ****************************************************************/
69 #define WINDOW_MIN_LINES (2 + 2)
70 #define WINDOW_MIN_COLS (2 + LINE_STATE_WIDTH)
72 /*** file scope type declarations ****************************************************************/
74 /*** file scope variables ************************************************************************/
76 /*** file scope functions ************************************************************************/
78 static cb_ret_t edit_callback (Widget * w, widget_msg_t msg, int parm);
80 /* --------------------------------------------------------------------------------------------- */
81 /**
82 * Show info about editor
85 static void
86 edit_about (void)
88 const char *header = N_("About");
89 const char *button_name = N_("&OK");
90 const char *const version = "MCEdit " VERSION;
91 char text[BUF_LARGE];
93 int win_len, version_len, button_len;
94 int cols, lines;
96 Dlg_head *about_dlg;
98 #ifdef ENABLE_NLS
99 header = _(header);
100 button_name = _(button_name);
101 #endif
103 button_len = str_term_width1 (button_name) + 5;
104 version_len = str_term_width1 (version);
106 g_snprintf (text, sizeof (text),
107 _("Copyright (C) 1996-2012 the Free Software Foundation\n\n"
108 " A user friendly text editor\n"
109 " written for the Midnight Commander"));
111 win_len = str_term_width1 (header);
112 win_len = max (win_len, version_len);
113 win_len = max (win_len, button_len);
115 /* count width and height of text */
116 str_msg_term_size (text, &lines, &cols);
117 lines += 9;
118 cols = max (win_len, cols) + 6;
120 /* dialog */
121 about_dlg = create_dlg (TRUE, 0, 0, lines, cols, dialog_colors, NULL, NULL,
122 "[Internal File Editor]", header, DLG_CENTER | DLG_TRYUP);
124 add_widget (about_dlg, label_new (3, (cols - version_len) / 2, version));
125 add_widget (about_dlg, label_new (5, 3, text));
126 add_widget (about_dlg, button_new (lines - 3, (cols - button_len) / 2,
127 B_ENTER, NORMAL_BUTTON, button_name, NULL));
129 run_dlg (about_dlg);
130 destroy_dlg (about_dlg);
133 /* --------------------------------------------------------------------------------------------- */
135 * Show a help window
138 static void
139 edit_help (void)
141 ev_help_t event_data = { NULL, "[Internal File Editor]" };
142 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
145 /* --------------------------------------------------------------------------------------------- */
147 * Restore saved window size.
149 * @param edit editor object
152 static void
153 edit_restore_size (WEdit * edit)
155 edit->drag_state = MCEDIT_DRAG_NORMAL;
156 widget_set_size ((Widget *) edit, edit->y_prev, edit->x_prev,
157 edit->lines_prev, edit->cols_prev);
158 dlg_redraw (((Widget *) edit)->owner);
161 /* --------------------------------------------------------------------------------------------- */
163 * Move window by one row or column in any direction.
165 * @param edit editor object
166 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
169 static void
170 edit_window_move (WEdit * edit, unsigned long command)
172 Widget *w = (Widget *) edit;
173 Dlg_head *h = w->owner;
175 switch (command)
177 case CK_Up:
178 if (w->y > h->y + 1) /* menubar */
179 w->y--;
180 break;
181 case CK_Down:
182 if (w->y < h->y + h->lines - 2) /* buttonbar */
183 w->y++;
184 break;
185 case CK_Left:
186 if (w->x + w->cols > h->x)
187 w->x--;
188 break;
189 case CK_Right:
190 if (w->x < h->x + h->cols)
191 w->x++;
192 break;
193 default:
194 return;
197 edit->force |= REDRAW_PAGE;
198 dlg_redraw (h);
201 /* --------------------------------------------------------------------------------------------- */
203 * Resize window by one row or column in any direction.
205 * @param edit editor object
206 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
209 static void
210 edit_window_resize (WEdit * edit, unsigned long command)
212 Widget *w = (Widget *) edit;
213 Dlg_head *h = w->owner;
215 switch (command)
217 case CK_Up:
218 if (w->lines > WINDOW_MIN_LINES)
219 w->lines--;
220 break;
221 case CK_Down:
222 if (w->y + w->lines < h->y + h->lines - 1) /* buttonbar */
223 w->lines++;
224 break;
225 case CK_Left:
226 if (w->cols > WINDOW_MIN_COLS)
227 w->cols--;
228 break;
229 case CK_Right:
230 if (w->x + w->cols < h->x + h->cols)
231 w->cols++;
232 break;
233 default:
234 return;
237 edit->force |= REDRAW_COMPLETELY;
238 dlg_redraw (h);
241 /* --------------------------------------------------------------------------------------------- */
243 static unsigned char
244 get_hotkey (int n)
246 return (n <= 9) ? '0' + n : 'a' + n - 10;
249 /* --------------------------------------------------------------------------------------------- */
251 static void
252 edit_window_list (const Dlg_head * h)
254 const size_t offset = 2; /* skip menu and buttonbar */
255 const size_t dlg_num = g_list_length (h->widgets) - offset;
256 int lines, cols;
257 Listbox *listbox;
258 GList *w;
259 int i = 0;
260 int rv;
262 lines = min ((size_t) (LINES * 2 / 3), dlg_num);
263 cols = COLS * 2 / 3;
265 listbox = create_listbox_window (lines, cols, _("Open files"), "[Open files]");
267 for (w = h->widgets; w != NULL; w = g_list_next (w))
268 if (edit_widget_is_editor ((Widget *) w->data))
270 WEdit *e = (WEdit *) w->data;
271 char *fname;
273 if (e->filename_vpath == NULL)
274 fname = g_strdup_printf ("%c [%s]", e->modified ? '*' : ' ', _("NoName"));
275 else
277 char *fname2;
279 fname2 = vfs_path_to_str (e->filename_vpath);
280 fname = g_strdup_printf ("%c%s", e->modified ? '*' : ' ', fname2);
281 g_free (fname2);
284 listbox_add_item (listbox->list, LISTBOX_APPEND_AT_END, get_hotkey (i++),
285 str_term_trim (fname, listbox->list->widget.cols - 2), NULL);
286 g_free (fname);
289 rv = g_list_position (h->widgets, h->current) - offset;
290 listbox_select_entry (listbox->list, rv);
291 rv = run_listbox (listbox);
292 if (rv >= 0)
294 w = g_list_nth (h->widgets, rv + offset);
295 dlg_set_top_widget (w->data);
299 /* --------------------------------------------------------------------------------------------- */
301 static char *
302 edit_get_shortcut (unsigned long command)
304 const char *ext_map;
305 const char *shortcut = NULL;
307 shortcut = keybind_lookup_keymap_shortcut (editor_map, command);
308 if (shortcut != NULL)
309 return g_strdup (shortcut);
311 ext_map = keybind_lookup_keymap_shortcut (editor_map, CK_ExtendedKeyMap);
312 if (ext_map != NULL)
313 shortcut = keybind_lookup_keymap_shortcut (editor_x_map, command);
314 if (shortcut != NULL)
315 return g_strdup_printf ("%s %s", ext_map, shortcut);
317 return NULL;
320 /* --------------------------------------------------------------------------------------------- */
322 static char *
323 edit_get_title (const Dlg_head * h, size_t len)
325 const WEdit *edit = find_editor (h);
326 const char *modified = edit->modified ? "(*) " : " ";
327 const char *file_label;
328 char *filename;
330 len -= 4;
332 filename = vfs_path_to_str (edit->filename_vpath);
333 file_label = str_term_trim (filename, len - str_term_width1 (_("Edit: ")));
334 g_free (filename);
336 return g_strconcat (_("Edit: "), modified, file_label, (char *) NULL);
339 /* --------------------------------------------------------------------------------------------- */
341 static int
342 edit_event (Gpm_Event * event, void *data)
344 WEdit *edit = (WEdit *) data;
345 Widget *w = (Widget *) data;
346 Gpm_Event local;
348 if (!mouse_global_in_widget (event, w))
349 return MOU_UNHANDLED;
351 local = mouse_get_local (event, w);
353 /* Unknown event type */
354 if ((event->type & (GPM_DOWN | GPM_DRAG | GPM_UP)) == 0)
355 return MOU_NORMAL;
357 dlg_set_top_widget (w);
359 edit_update_curs_row (edit);
360 edit_update_curs_col (edit);
362 if (!EDIT_WITH_FRAME || (local.buttons & GPM_B_LEFT) == 0 || (local.type & GPM_UP) != 0)
363 edit->drag_state = MCEDIT_DRAG_NORMAL;
364 else if (local.y == 1 && edit->drag_state != MCEDIT_DRAG_RESIZE)
366 /* click on the top line (move) */
368 /* start move; save x coordinate of mouse */
369 if ((local.type & GPM_DOWN) != 0)
370 edit->drag_state_start = local.x;
372 /* moving */
373 if ((local.type & (GPM_DOWN | GPM_DRAG)) != 0)
374 edit->drag_state = MCEDIT_DRAG_MOVE;
376 else if (local.y == w->lines && local.x == w->cols)
378 /* click on bottom-right corner (resize) */
379 if ((local.type & (GPM_DOWN | GPM_DRAG)) != 0)
380 edit->drag_state = MCEDIT_DRAG_RESIZE;
383 if (edit->drag_state == MCEDIT_DRAG_NORMAL)
385 gboolean done = TRUE;
387 /* Double click */
388 if ((local.type & (GPM_DOUBLE | GPM_UP)) == (GPM_UP | GPM_DOUBLE))
390 edit_mark_current_word_cmd (edit);
391 goto update;
393 #if 0
394 /* Triple click */
395 if ((local.type & (GPM_TRIPLE | GPM_UP)) == (GPM_UP | GPM_TRIPLE))
397 edit_mark_current_line_cmd (edit);
398 goto update;
400 #endif
401 /* Wheel events */
402 if ((local.buttons & GPM_B_UP) != 0 && (local.type & GPM_DOWN) != 0)
404 edit_move_up (edit, 2, 1);
405 goto update;
407 if ((local.buttons & GPM_B_DOWN) != 0 && (local.type & GPM_DOWN) != 0)
409 edit_move_down (edit, 2, 1);
410 goto update;
413 /* continue handle current event */
414 goto cont;
416 /* handle DRAG mouse event, don't use standard way to continue
417 * event handling outside of widget */
420 int c;
422 c = tty_get_event (event, FALSE, TRUE);
423 if (c == EV_NONE || c != EV_MOUSE)
424 break;
426 local = mouse_get_local (event, w);
428 cont:
429 /* A lone up mustn't do anything */
430 if (edit->mark2 != -1 && (local.type & (GPM_UP | GPM_DRAG)) != 0)
431 return MOU_NORMAL;
433 if ((local.type & (GPM_DOWN | GPM_UP)) != 0)
434 edit_push_key_press (edit);
436 local.x--;
437 if (!option_cursor_beyond_eol)
438 edit->prev_col = local.x - edit->start_col - option_line_state_width - 1;
439 else
441 long line_len = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
442 edit_eol (edit, edit->curs1));
444 if (local.x > line_len)
446 edit->over_col =
447 local.x - line_len - edit->start_col - option_line_state_width - 1;
448 edit->prev_col = line_len;
450 else
452 edit->over_col = 0;
453 edit->prev_col = local.x - option_line_state_width - edit->start_col - 1;
457 if (EDIT_WITH_FRAME)
458 local.y--;
459 if (local.y > (edit->curs_row + 1))
460 edit_move_down (edit, local.y - (edit->curs_row + 1), 0);
461 else if (local.y < (edit->curs_row + 1))
462 edit_move_up (edit, (edit->curs_row + 1) - local.y, 0);
463 else
464 edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
466 if ((local.type & GPM_DOWN) != 0)
468 edit_mark_cmd (edit, 1); /* reset */
469 edit->highlight = 0;
472 done = (local.type & GPM_DRAG) == 0;
473 if (done)
474 edit_mark_cmd (edit, 0);
476 update:
477 edit_find_bracket (edit);
478 edit->force |= REDRAW_COMPLETELY;
479 edit_update_curs_row (edit);
480 edit_update_curs_col (edit);
481 edit_update_screen (edit);
483 while (EDIT_WITH_FRAME && !done);
485 else
486 while (edit->drag_state != MCEDIT_DRAG_NORMAL)
488 int c;
490 c = tty_get_event (event, FALSE, TRUE);
492 if (c == EV_NONE || c != EV_MOUSE)
494 /* redraw frame */
495 edit->drag_state = MCEDIT_DRAG_NORMAL;
496 edit->force |= REDRAW_COMPLETELY;
497 edit_update_screen (edit);
499 else
501 Dlg_head *h = w->owner;
503 if (edit->drag_state == MCEDIT_DRAG_MOVE)
505 int y = event->y - 1;
506 int x = event->x - 1;
508 y = max (y, h->y + 1); /* status line */
509 y = min (y, h->y + h->lines - 2); /* buttonbar */
510 x = max (x, h->x);
511 x = min (x, h->x + h->cols - 1);
512 /* don't use widget_set_size() here to avoid double draw */
513 w->y = y;
514 w->x = x - edit->drag_state_start;
515 edit->force |= REDRAW_PAGE;
517 else if (edit->drag_state == MCEDIT_DRAG_RESIZE)
519 event->y = min (event->y, h->y + h->lines - 1); /* buttonbar */
520 event->x = min (event->x, h->x + h->cols);
521 local = mouse_get_local (event, w);
523 /* don't use widget_set_size() here to avoid double draw */
524 w->lines = max (WINDOW_MIN_LINES, local.y);
525 w->cols = max (WINDOW_MIN_COLS, local.x);
526 edit->force |= REDRAW_COMPLETELY;
529 dlg_redraw (h);
533 return MOU_NORMAL;
536 /* --------------------------------------------------------------------------------------------- */
538 static cb_ret_t
539 edit_dialog_command_execute (Dlg_head * h, unsigned long command)
541 gboolean ret = MSG_HANDLED;
543 switch (command)
545 case CK_EditNew:
546 edit_add_window (h, h->y + 1, h->x, h->lines - 2, h->cols, NULL, 0);
547 break;
548 case CK_EditFile:
549 edit_load_cmd (h);
550 break;
551 case CK_EditSyntaxFile:
552 edit_load_syntax_file (h);
553 break;
554 case CK_EditUserMenu:
555 edit_load_menu_file (h);
556 break;
557 case CK_Close:
558 /* if there are no opened files anymore, close MC editor */
559 if (edit_widget_is_editor ((Widget *) h->current->data) &&
560 edit_close_cmd ((WEdit *) h->current->data) && find_editor (h) == NULL)
561 dlg_stop (h);
562 break;
563 case CK_Help:
564 edit_help ();
565 /* edit->force |= REDRAW_COMPLETELY; */
566 break;
567 case CK_Menu:
568 edit_menu_cmd (h);
569 break;
570 case CK_Quit:
571 case CK_Cancel:
573 Widget *w = (Widget *) h->current->data;
575 if (!edit_widget_is_editor (w) || ((WEdit *) w)->drag_state == MCEDIT_DRAG_NORMAL)
576 dlg_stop (h);
577 else
578 edit_restore_size ((WEdit *) w);
580 break;
581 case CK_About:
582 edit_about ();
583 break;
584 case CK_SyntaxOnOff:
585 edit_syntax_onoff_cmd (h);
586 break;
587 case CK_ShowTabTws:
588 edit_show_tabs_tws_cmd (h);
589 break;
590 case CK_ShowMargin:
591 edit_show_margin_cmd (h);
592 break;
593 case CK_ShowNumbers:
594 edit_show_numbers_cmd (h);
595 break;
596 case CK_Refresh:
597 edit_refresh_cmd ();
598 break;
599 case CK_Shell:
600 view_other_cmd ();
601 break;
602 case CK_LearnKeys:
603 learn_keys ();
604 break;
605 case CK_WindowMove:
606 case CK_WindowResize:
607 if (edit_widget_is_editor ((Widget *) h->current->data))
608 edit_handle_move_resize ((WEdit *) h->current->data, command);
609 break;
610 case CK_WindowList:
611 edit_window_list (h);
612 break;
613 case CK_WindowNext:
614 dlg_one_down (h);
615 dlg_set_top_widget (h->current->data);
616 break;
617 case CK_WindowPrev:
618 dlg_one_up (h);
619 dlg_set_top_widget (h->current->data);
620 break;
621 case CK_Options:
622 edit_options_dialog (h);
623 break;
624 case CK_OptionsSaveMode:
625 edit_save_mode_cmd ();
626 break;
627 case CK_SaveSetup:
628 save_setup_cmd ();
629 break;
630 default:
631 ret = MSG_NOT_HANDLED;
632 break;
635 return ret;
638 /* --------------------------------------------------------------------------------------------- */
640 static inline void
641 edit_quit (Dlg_head * h)
643 GList *l;
644 WEdit *e = NULL;
646 h->state = DLG_ACTIVE; /* don't stop the dialog before final decision */
648 for (l = h->widgets; l != NULL; l = g_list_next (l))
649 if (edit_widget_is_editor ((Widget *) l->data))
651 e = (WEdit *) l->data;
653 if (e->drag_state != MCEDIT_DRAG_NORMAL)
655 edit_restore_size (e);
656 return;
659 if (e->modified)
661 dlg_select_widget (e);
663 if (!edit_ok_to_exit (e))
664 return;
668 /* no editors in dialog at all or no any file required to be saved */
669 if (e == NULL || l == NULL)
670 h->state = DLG_CLOSED;
673 /* --------------------------------------------------------------------------------------------- */
675 static inline void
676 edit_set_buttonbar (WEdit * edit, WButtonBar * bb)
678 buttonbar_set_label (bb, 1, Q_ ("ButtonBar|Help"), editor_map, NULL);
679 buttonbar_set_label (bb, 2, Q_ ("ButtonBar|Save"), editor_map, (Widget *) edit);
680 buttonbar_set_label (bb, 3, Q_ ("ButtonBar|Mark"), editor_map, (Widget *) edit);
681 buttonbar_set_label (bb, 4, Q_ ("ButtonBar|Replac"), editor_map, (Widget *) edit);
682 buttonbar_set_label (bb, 5, Q_ ("ButtonBar|Copy"), editor_map, (Widget *) edit);
683 buttonbar_set_label (bb, 6, Q_ ("ButtonBar|Move"), editor_map, (Widget *) edit);
684 buttonbar_set_label (bb, 7, Q_ ("ButtonBar|Search"), editor_map, (Widget *) edit);
685 buttonbar_set_label (bb, 8, Q_ ("ButtonBar|Delete"), editor_map, (Widget *) edit);
686 buttonbar_set_label (bb, 9, Q_ ("ButtonBar|PullDn"), editor_map, NULL);
687 buttonbar_set_label (bb, 10, Q_ ("ButtonBar|Quit"), editor_map, NULL);
690 /* --------------------------------------------------------------------------------------------- */
691 /** Callback for the edit dialog */
693 static cb_ret_t
694 edit_dialog_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
696 WMenuBar *menubar;
697 WButtonBar *buttonbar;
699 switch (msg)
701 case DLG_DRAW:
702 /* don't use common_dialog_repaint() -- we don't need a frame */
703 tty_setcolor (EDITOR_NORMAL_COLOR);
704 dlg_erase (h);
705 return MSG_HANDLED;
707 case DLG_RESIZE:
708 menubar = find_menubar (h);
709 buttonbar = find_buttonbar (h);
710 /* dlg_set_size() is surplus for this case */
711 h->lines = LINES;
712 h->cols = COLS;
713 widget_set_size (&buttonbar->widget, h->lines - 1, h->x, 1, h->cols);
714 widget_set_size (&menubar->widget, h->y, h->x, 1, h->cols);
715 menubar_arrange (menubar);
716 return MSG_HANDLED;
718 case DLG_ACTION:
719 /* shortcut */
720 if (sender == NULL)
721 return edit_dialog_command_execute (h, parm);
722 /* message from menu */
723 menubar = find_menubar (h);
724 if (sender == (Widget *) menubar)
726 if (edit_dialog_command_execute (h, parm) == MSG_HANDLED)
727 return MSG_HANDLED;
728 /* try send command to the current window */
729 return send_message ((Widget *) h->current->data, WIDGET_COMMAND, parm);
731 /* message from buttonbar */
732 buttonbar = find_buttonbar (h);
733 if (sender == (Widget *) buttonbar)
735 if (data != NULL)
736 return send_message ((Widget *) data, WIDGET_COMMAND, parm);
737 return edit_dialog_command_execute (h, parm);
739 return MSG_NOT_HANDLED;
741 case DLG_KEY:
743 Widget *w = h->current->data;
744 cb_ret_t ret = MSG_NOT_HANDLED;
746 if (edit_widget_is_editor (w))
748 WEdit *e = (WEdit *) w;
749 unsigned long command;
751 if (!e->extmod)
752 command = keybind_lookup_keymap_command (editor_map, parm);
753 else
755 e->extmod = FALSE;
756 command = keybind_lookup_keymap_command (editor_x_map, parm);
759 if (command != CK_IgnoreKey)
760 ret = edit_dialog_command_execute (h, command);
763 return ret;
766 /* hardcoded menu hotkeys (see edit_drop_hotkey_menu) */
767 case DLG_UNHANDLED_KEY:
768 return edit_drop_hotkey_menu (h, parm) ? MSG_HANDLED : MSG_NOT_HANDLED;
770 case DLG_VALIDATE:
771 edit_quit (h);
772 return MSG_HANDLED;
774 default:
775 return default_dlg_callback (h, sender, msg, parm, data);
779 /* --------------------------------------------------------------------------------------------- */
781 static cb_ret_t
782 edit_callback (Widget * w, widget_msg_t msg, int parm)
784 WEdit *e = (WEdit *) w;
786 switch (msg)
788 case WIDGET_FOCUS:
789 edit_set_buttonbar (e, find_buttonbar (e->widget.owner));
790 e->force |= REDRAW_PAGE;
791 edit_update_screen (e);
792 return MSG_HANDLED;
794 case WIDGET_DRAW:
795 e->force |= REDRAW_COMPLETELY;
796 edit_update_screen (e);
797 return MSG_HANDLED;
799 case WIDGET_KEY:
801 int cmd, ch;
802 cb_ret_t ret = MSG_NOT_HANDLED;
804 /* The user may override the access-keys for the menu bar. */
805 if (macro_index == -1 && edit_execute_macro (e, parm))
807 edit_update_screen (e);
808 ret = MSG_HANDLED;
810 else if (edit_translate_key (e, parm, &cmd, &ch))
812 edit_execute_key_command (e, cmd, ch);
813 edit_update_screen (e);
814 ret = MSG_HANDLED;
817 return ret;
820 case WIDGET_COMMAND:
821 /* command from menubar or buttonbar */
822 edit_execute_key_command (e, parm, -1);
823 edit_update_screen (e);
824 return MSG_HANDLED;
826 case WIDGET_CURSOR:
827 widget_move (w, e->curs_row + EDIT_TEXT_VERTICAL_OFFSET + EDIT_WITH_FRAME,
828 e->curs_col + e->start_col + e->over_col +
829 EDIT_TEXT_HORIZONTAL_OFFSET + EDIT_WITH_FRAME + option_line_state_width);
830 return MSG_HANDLED;
832 case WIDGET_DESTROY:
833 edit_clean (e);
834 return MSG_HANDLED;
836 default:
837 return default_proc (msg, parm);
841 /* --------------------------------------------------------------------------------------------- */
842 /*** public functions ****************************************************************************/
843 /* --------------------------------------------------------------------------------------------- */
845 gboolean
846 edit_file (const vfs_path_t * _file_vpath, int line)
848 static gboolean made_directory = FALSE;
849 Dlg_head *edit_dlg;
850 WMenuBar *menubar;
851 gboolean ok;
853 if (!made_directory)
855 char *dir;
857 dir = mc_build_filename (mc_config_get_cache_path (), EDIT_DIR, NULL);
858 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
859 g_free (dir);
861 dir = mc_build_filename (mc_config_get_path (), EDIT_DIR, NULL);
862 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
863 g_free (dir);
865 dir = mc_build_filename (mc_config_get_data_path (), EDIT_DIR, NULL);
866 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
867 g_free (dir);
870 /* Create a new dialog and add it widgets to it */
871 edit_dlg =
872 create_dlg (FALSE, 0, 0, LINES, COLS, NULL, edit_dialog_callback, NULL,
873 "[Internal File Editor]", NULL, DLG_WANT_TAB);
875 edit_dlg->get_shortcut = edit_get_shortcut;
876 edit_dlg->get_title = edit_get_title;
878 menubar = menubar_new (0, 0, COLS, NULL);
879 add_widget (edit_dlg, menubar);
880 edit_init_menu (menubar);
882 add_widget (edit_dlg, buttonbar_new (TRUE));
884 ok = edit_add_window (edit_dlg, edit_dlg->y + 1, edit_dlg->x,
885 edit_dlg->lines - 2, edit_dlg->cols, _file_vpath, line);
887 if (ok)
888 run_dlg (edit_dlg);
890 if (!ok || edit_dlg->state == DLG_CLOSED)
891 destroy_dlg (edit_dlg);
893 return ok;
896 /* --------------------------------------------------------------------------------------------- */
898 char *
899 edit_get_file_name (const WEdit * edit)
901 return vfs_path_to_str (edit->filename_vpath);
904 /* --------------------------------------------------------------------------------------------- */
906 WEdit *
907 find_editor (const Dlg_head * h)
909 return (WEdit *) find_widget_type (h, edit_callback);
912 /* --------------------------------------------------------------------------------------------- */
914 * Check if widget is an WEdit class.
916 * @param w probably editor object
917 * @return TRUE if widget is an WEdit class, FALSE otherwise
920 gboolean
921 edit_widget_is_editor (const Widget * w)
923 return (w != NULL && w->callback == edit_callback);
926 /* --------------------------------------------------------------------------------------------- */
928 void
929 edit_update_screen (WEdit * e)
931 edit_scroll_screen_over_cursor (e);
932 edit_update_curs_col (e);
934 if (!EDIT_WITH_FRAME)
935 edit_status (e);
936 else
938 if ((e->force & REDRAW_COMPLETELY) != 0)
940 /* draw a frame around edit area */
941 tty_setcolor (EDITOR_NORMAL_COLOR);
942 tty_draw_box (e->widget.y, e->widget.x, e->widget.lines, e->widget.cols, TRUE);
945 edit_info_status (e);
948 /* pop all events for this window for internal handling */
949 if (!is_idle ())
950 e->force |= REDRAW_PAGE;
951 else
953 if (e->force & REDRAW_COMPLETELY)
954 e->force |= REDRAW_PAGE;
955 edit_render_keypress (e);
958 buttonbar_redraw (find_buttonbar (((Widget *) e)->owner));
961 /* --------------------------------------------------------------------------------------------- */
963 * Save current window size.
965 * @param edit editor object
968 void
969 edit_save_size (WEdit * edit)
971 edit->y_prev = edit->widget.y;
972 edit->x_prev = edit->widget.x;
973 edit->lines_prev = edit->widget.lines;
974 edit->cols_prev = edit->widget.cols;
977 /* --------------------------------------------------------------------------------------------- */
979 * Create new editor window and insert it into editor screen.
981 * @param h editor dialog (screen)
982 * @param y y coordinate
983 * @param x x coordinate
984 * @param lines window height
985 * @param cols window width
986 * @param f file object
987 * @param fline line number in file
988 * @return TRUE if new window was successfully created and inserted into editor screen,
989 * FALSE otherwise
992 gboolean
993 edit_add_window (Dlg_head * h, int y, int x, int lines, int cols, const vfs_path_t *f, int fline)
995 WEdit *edit;
996 Widget *w;
998 edit = edit_init (NULL, y, x, lines, cols, f, fline);
999 if (edit == NULL)
1000 return FALSE;
1002 w = (Widget *) edit;
1003 w->callback = edit_callback;
1004 w->mouse = edit_event;
1005 widget_want_cursor (*w, TRUE);
1007 add_widget (h, w);
1008 dlg_redraw (h);
1010 return TRUE;
1013 /* --------------------------------------------------------------------------------------------- */
1015 * Handle move/resize events.
1017 * @param edit editor object
1018 * @param command action id
1019 * @return TRUE if mouse actions was handled, FALSE otherwise
1022 gboolean
1023 edit_handle_move_resize (WEdit * edit, unsigned long command)
1025 gboolean ret = FALSE;
1027 switch (edit->drag_state)
1029 case MCEDIT_DRAG_NORMAL:
1030 /* possible start move/resize */
1031 switch (command)
1033 case CK_WindowMove:
1034 edit->drag_state = MCEDIT_DRAG_MOVE;
1035 edit_save_size (edit);
1036 ret = TRUE;
1037 break;
1038 case CK_WindowResize:
1039 edit->drag_state = MCEDIT_DRAG_RESIZE;
1040 edit_save_size (edit);
1041 ret = TRUE;
1042 break;
1043 default:
1044 break;
1046 break;
1048 case MCEDIT_DRAG_MOVE:
1049 switch (command)
1051 case CK_WindowResize:
1052 edit->drag_state = MCEDIT_DRAG_RESIZE;
1053 ret = TRUE;
1054 break;
1055 case CK_Up:
1056 case CK_Down:
1057 case CK_Left:
1058 case CK_Right:
1059 edit_window_move (edit, command);
1060 ret = TRUE;
1061 break;
1062 case CK_Enter:
1063 case CK_WindowMove:
1064 edit->drag_state = MCEDIT_DRAG_NORMAL;
1065 default:
1066 ret = TRUE;
1067 break;
1069 break;
1071 case MCEDIT_DRAG_RESIZE:
1072 switch (command)
1074 case CK_WindowMove:
1075 edit->drag_state = MCEDIT_DRAG_MOVE;
1076 ret = TRUE;
1077 break;
1078 case CK_Up:
1079 case CK_Down:
1080 case CK_Left:
1081 case CK_Right:
1082 edit_window_resize (edit, command);
1083 ret = TRUE;
1084 break;
1085 case CK_Enter:
1086 case CK_WindowResize:
1087 edit->drag_state = MCEDIT_DRAG_NORMAL;
1088 default:
1089 ret = TRUE;
1090 break;
1092 break;
1095 return ret;
1098 /* --------------------------------------------------------------------------------------------- */