Modify CK_Refresh command handling.
[midnight-commander.git] / src / editor / editwidget.c
blob50c5db2898d05f0a6810f68a3890a6da84afe661
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_Refresh:
585 edit_refresh_cmd ();
586 break;
587 case CK_Shell:
588 view_other_cmd ();
589 break;
590 case CK_LearnKeys:
591 learn_keys ();
592 break;
593 case CK_WindowMove:
594 case CK_WindowResize:
595 if (edit_widget_is_editor ((Widget *) h->current->data))
596 edit_handle_move_resize ((WEdit *) h->current->data, command);
597 break;
598 case CK_WindowList:
599 edit_window_list (h);
600 break;
601 case CK_WindowNext:
602 dlg_one_down (h);
603 dlg_set_top_widget (h->current->data);
604 break;
605 case CK_WindowPrev:
606 dlg_one_up (h);
607 dlg_set_top_widget (h->current->data);
608 break;
609 case CK_Options:
610 edit_options_dialog (h);
611 break;
612 case CK_OptionsSaveMode:
613 edit_save_mode_cmd ();
614 break;
615 case CK_SaveSetup:
616 save_setup_cmd ();
617 break;
618 default:
619 ret = MSG_NOT_HANDLED;
620 break;
623 return ret;
626 /* --------------------------------------------------------------------------------------------- */
628 static inline void
629 edit_quit (Dlg_head * h)
631 GList *l;
632 WEdit *e = NULL;
634 h->state = DLG_ACTIVE; /* don't stop the dialog before final decision */
636 for (l = h->widgets; l != NULL; l = g_list_next (l))
637 if (edit_widget_is_editor ((Widget *) l->data))
639 e = (WEdit *) l->data;
641 if (e->drag_state != MCEDIT_DRAG_NORMAL)
643 edit_restore_size (e);
644 return;
647 if (e->modified)
649 dlg_select_widget (e);
651 if (!edit_ok_to_exit (e))
652 return;
656 /* no editors in dialog at all or no any file required to be saved */
657 if (e == NULL || l == NULL)
658 h->state = DLG_CLOSED;
661 /* --------------------------------------------------------------------------------------------- */
663 static inline void
664 edit_set_buttonbar (WEdit * edit, WButtonBar * bb)
666 buttonbar_set_label (bb, 1, Q_ ("ButtonBar|Help"), editor_map, NULL);
667 buttonbar_set_label (bb, 2, Q_ ("ButtonBar|Save"), editor_map, (Widget *) edit);
668 buttonbar_set_label (bb, 3, Q_ ("ButtonBar|Mark"), editor_map, (Widget *) edit);
669 buttonbar_set_label (bb, 4, Q_ ("ButtonBar|Replac"), editor_map, (Widget *) edit);
670 buttonbar_set_label (bb, 5, Q_ ("ButtonBar|Copy"), editor_map, (Widget *) edit);
671 buttonbar_set_label (bb, 6, Q_ ("ButtonBar|Move"), editor_map, (Widget *) edit);
672 buttonbar_set_label (bb, 7, Q_ ("ButtonBar|Search"), editor_map, (Widget *) edit);
673 buttonbar_set_label (bb, 8, Q_ ("ButtonBar|Delete"), editor_map, (Widget *) edit);
674 buttonbar_set_label (bb, 9, Q_ ("ButtonBar|PullDn"), editor_map, NULL);
675 buttonbar_set_label (bb, 10, Q_ ("ButtonBar|Quit"), editor_map, NULL);
678 /* --------------------------------------------------------------------------------------------- */
679 /** Callback for the edit dialog */
681 static cb_ret_t
682 edit_dialog_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
684 WMenuBar *menubar;
685 WButtonBar *buttonbar;
687 switch (msg)
689 case DLG_DRAW:
690 /* don't use common_dialog_repaint() -- we don't need a frame */
691 tty_setcolor (EDITOR_NORMAL_COLOR);
692 dlg_erase (h);
693 return MSG_HANDLED;
695 case DLG_RESIZE:
696 menubar = find_menubar (h);
697 buttonbar = find_buttonbar (h);
698 /* dlg_set_size() is surplus for this case */
699 h->lines = LINES;
700 h->cols = COLS;
701 widget_set_size (&buttonbar->widget, h->lines - 1, h->x, 1, h->cols);
702 widget_set_size (&menubar->widget, h->y, h->x, 1, h->cols);
703 menubar_arrange (menubar);
704 return MSG_HANDLED;
706 case DLG_ACTION:
707 /* shortcut */
708 if (sender == NULL)
709 return edit_dialog_command_execute (h, parm);
710 /* message from menu */
711 menubar = find_menubar (h);
712 if (sender == (Widget *) menubar)
714 if (edit_dialog_command_execute (h, parm) == MSG_HANDLED)
715 return MSG_HANDLED;
716 /* try send command to the current window */
717 return send_message ((Widget *) h->current->data, WIDGET_COMMAND, parm);
719 /* message from buttonbar */
720 buttonbar = find_buttonbar (h);
721 if (sender == (Widget *) buttonbar)
723 if (data != NULL)
724 return send_message ((Widget *) data, WIDGET_COMMAND, parm);
725 return edit_dialog_command_execute (h, parm);
727 return MSG_NOT_HANDLED;
729 case DLG_KEY:
731 Widget *w = h->current->data;
732 cb_ret_t ret = MSG_NOT_HANDLED;
734 if (edit_widget_is_editor (w))
736 WEdit *e = (WEdit *) w;
737 unsigned long command;
739 if (!e->extmod)
740 command = keybind_lookup_keymap_command (editor_map, parm);
741 else
743 e->extmod = FALSE;
744 command = keybind_lookup_keymap_command (editor_x_map, parm);
747 if (command != CK_IgnoreKey)
748 ret = edit_dialog_command_execute (h, command);
751 return ret;
754 /* hardcoded menu hotkeys (see edit_drop_hotkey_menu) */
755 case DLG_UNHANDLED_KEY:
756 return edit_drop_hotkey_menu (h, parm) ? MSG_HANDLED : MSG_NOT_HANDLED;
758 case DLG_VALIDATE:
759 edit_quit (h);
760 return MSG_HANDLED;
762 default:
763 return default_dlg_callback (h, sender, msg, parm, data);
767 /* --------------------------------------------------------------------------------------------- */
769 static cb_ret_t
770 edit_callback (Widget * w, widget_msg_t msg, int parm)
772 WEdit *e = (WEdit *) w;
774 switch (msg)
776 case WIDGET_FOCUS:
777 edit_set_buttonbar (e, find_buttonbar (e->widget.owner));
778 e->force |= REDRAW_PAGE;
779 edit_update_screen (e);
780 return MSG_HANDLED;
782 case WIDGET_DRAW:
783 e->force |= REDRAW_COMPLETELY;
784 edit_update_screen (e);
785 return MSG_HANDLED;
787 case WIDGET_KEY:
789 int cmd, ch;
790 cb_ret_t ret = MSG_NOT_HANDLED;
792 /* The user may override the access-keys for the menu bar. */
793 if (macro_index == -1 && edit_execute_macro (e, parm))
795 edit_update_screen (e);
796 ret = MSG_HANDLED;
798 else if (edit_translate_key (e, parm, &cmd, &ch))
800 edit_execute_key_command (e, cmd, ch);
801 edit_update_screen (e);
802 ret = MSG_HANDLED;
805 return ret;
808 case WIDGET_COMMAND:
809 /* command from menubar or buttonbar */
810 edit_execute_key_command (e, parm, -1);
811 edit_update_screen (e);
812 return MSG_HANDLED;
814 case WIDGET_CURSOR:
815 widget_move (w, e->curs_row + EDIT_TEXT_VERTICAL_OFFSET + EDIT_WITH_FRAME,
816 e->curs_col + e->start_col + e->over_col +
817 EDIT_TEXT_HORIZONTAL_OFFSET + EDIT_WITH_FRAME + option_line_state_width);
818 return MSG_HANDLED;
820 case WIDGET_DESTROY:
821 edit_clean (e);
822 return MSG_HANDLED;
824 default:
825 return default_proc (msg, parm);
829 /* --------------------------------------------------------------------------------------------- */
830 /*** public functions ****************************************************************************/
831 /* --------------------------------------------------------------------------------------------- */
833 gboolean
834 edit_file (const vfs_path_t * _file_vpath, int line)
836 static gboolean made_directory = FALSE;
837 Dlg_head *edit_dlg;
838 WMenuBar *menubar;
839 gboolean ok;
841 if (!made_directory)
843 char *dir;
845 dir = mc_build_filename (mc_config_get_cache_path (), EDIT_DIR, NULL);
846 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
847 g_free (dir);
849 dir = mc_build_filename (mc_config_get_path (), EDIT_DIR, NULL);
850 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
851 g_free (dir);
853 dir = mc_build_filename (mc_config_get_data_path (), EDIT_DIR, NULL);
854 made_directory = (mkdir (dir, 0700) != -1 || errno == EEXIST);
855 g_free (dir);
858 /* Create a new dialog and add it widgets to it */
859 edit_dlg =
860 create_dlg (FALSE, 0, 0, LINES, COLS, NULL, edit_dialog_callback, NULL,
861 "[Internal File Editor]", NULL, DLG_WANT_TAB);
863 edit_dlg->get_shortcut = edit_get_shortcut;
864 edit_dlg->get_title = edit_get_title;
866 menubar = menubar_new (0, 0, COLS, NULL);
867 add_widget (edit_dlg, menubar);
868 edit_init_menu (menubar);
870 add_widget (edit_dlg, buttonbar_new (TRUE));
872 ok = edit_add_window (edit_dlg, edit_dlg->y + 1, edit_dlg->x,
873 edit_dlg->lines - 2, edit_dlg->cols, _file_vpath, line);
875 if (ok)
876 run_dlg (edit_dlg);
878 if (!ok || edit_dlg->state == DLG_CLOSED)
879 destroy_dlg (edit_dlg);
881 return ok;
884 /* --------------------------------------------------------------------------------------------- */
886 char *
887 edit_get_file_name (const WEdit * edit)
889 return vfs_path_to_str (edit->filename_vpath);
892 /* --------------------------------------------------------------------------------------------- */
894 WEdit *
895 find_editor (const Dlg_head * h)
897 return (WEdit *) find_widget_type (h, edit_callback);
900 /* --------------------------------------------------------------------------------------------- */
902 * Check if widget is an WEdit class.
904 * @param w probably editor object
905 * @return TRUE if widget is an WEdit class, FALSE otherwise
908 gboolean
909 edit_widget_is_editor (const Widget * w)
911 return (w != NULL && w->callback == edit_callback);
914 /* --------------------------------------------------------------------------------------------- */
916 void
917 edit_update_screen (WEdit * e)
919 edit_scroll_screen_over_cursor (e);
920 edit_update_curs_col (e);
922 if (!EDIT_WITH_FRAME)
923 edit_status (e);
924 else
926 if ((e->force & REDRAW_COMPLETELY) != 0)
928 /* draw a frame around edit area */
929 tty_setcolor (EDITOR_NORMAL_COLOR);
930 tty_draw_box (e->widget.y, e->widget.x, e->widget.lines, e->widget.cols, TRUE);
933 edit_info_status (e);
936 /* pop all events for this window for internal handling */
937 if (!is_idle ())
938 e->force |= REDRAW_PAGE;
939 else
941 if (e->force & REDRAW_COMPLETELY)
942 e->force |= REDRAW_PAGE;
943 edit_render_keypress (e);
946 buttonbar_redraw (find_buttonbar (((Widget *) e)->owner));
949 /* --------------------------------------------------------------------------------------------- */
951 * Save current window size.
953 * @param edit editor object
956 void
957 edit_save_size (WEdit * edit)
959 edit->y_prev = edit->widget.y;
960 edit->x_prev = edit->widget.x;
961 edit->lines_prev = edit->widget.lines;
962 edit->cols_prev = edit->widget.cols;
965 /* --------------------------------------------------------------------------------------------- */
967 * Create new editor window and insert it into editor screen.
969 * @param h editor dialog (screen)
970 * @param y y coordinate
971 * @param x x coordinate
972 * @param lines window height
973 * @param cols window width
974 * @param f file object
975 * @param fline line number in file
976 * @return TRUE if new window was successfully created and inserted into editor screen,
977 * FALSE otherwise
980 gboolean
981 edit_add_window (Dlg_head * h, int y, int x, int lines, int cols, const vfs_path_t *f, int fline)
983 WEdit *edit;
984 Widget *w;
986 edit = edit_init (NULL, y, x, lines, cols, f, fline);
987 if (edit == NULL)
988 return FALSE;
990 w = (Widget *) edit;
991 w->callback = edit_callback;
992 w->mouse = edit_event;
993 widget_want_cursor (*w, TRUE);
995 add_widget (h, w);
996 dlg_redraw (h);
998 return TRUE;
1001 /* --------------------------------------------------------------------------------------------- */
1003 * Handle move/resize events.
1005 * @param edit editor object
1006 * @param command action id
1007 * @return TRUE if mouse actions was handled, FALSE otherwise
1010 gboolean
1011 edit_handle_move_resize (WEdit * edit, unsigned long command)
1013 gboolean ret = FALSE;
1015 switch (edit->drag_state)
1017 case MCEDIT_DRAG_NORMAL:
1018 /* possible start move/resize */
1019 switch (command)
1021 case CK_WindowMove:
1022 edit->drag_state = MCEDIT_DRAG_MOVE;
1023 edit_save_size (edit);
1024 ret = TRUE;
1025 break;
1026 case CK_WindowResize:
1027 edit->drag_state = MCEDIT_DRAG_RESIZE;
1028 edit_save_size (edit);
1029 ret = TRUE;
1030 break;
1031 default:
1032 break;
1034 break;
1036 case MCEDIT_DRAG_MOVE:
1037 switch (command)
1039 case CK_WindowResize:
1040 edit->drag_state = MCEDIT_DRAG_RESIZE;
1041 ret = TRUE;
1042 break;
1043 case CK_Up:
1044 case CK_Down:
1045 case CK_Left:
1046 case CK_Right:
1047 edit_window_move (edit, command);
1048 ret = TRUE;
1049 break;
1050 case CK_Enter:
1051 case CK_WindowMove:
1052 edit->drag_state = MCEDIT_DRAG_NORMAL;
1053 default:
1054 ret = TRUE;
1055 break;
1057 break;
1059 case MCEDIT_DRAG_RESIZE:
1060 switch (command)
1062 case CK_WindowMove:
1063 edit->drag_state = MCEDIT_DRAG_MOVE;
1064 ret = TRUE;
1065 break;
1066 case CK_Up:
1067 case CK_Down:
1068 case CK_Left:
1069 case CK_Right:
1070 edit_window_resize (edit, command);
1071 ret = TRUE;
1072 break;
1073 case CK_Enter:
1074 case CK_WindowResize:
1075 edit->drag_state = MCEDIT_DRAG_NORMAL;
1076 default:
1077 ret = TRUE;
1078 break;
1080 break;
1083 return ret;
1086 /* --------------------------------------------------------------------------------------------- */