2 Editor initialisation and callback handler.
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
6 The Free Software Foundation, Inc.
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/>.
28 * \brief Source: editor initialisation and callback handler
37 #include <sys/types.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"
56 #include "src/keybind-defaults.h"
57 #include "src/main.h" /* home_dir */
59 #include "edit-impl.h"
60 #include "edit-widget.h"
62 /*** global variables ****************************************************************************/
64 /*** file scope macro definitions ****************************************************************/
66 /*** file scope type declarations ****************************************************************/
68 /*** file scope variables ************************************************************************/
70 /*** file scope functions ************************************************************************/
72 static cb_ret_t
edit_callback (Widget
* w
, widget_msg_t msg
, int parm
);
75 /* --------------------------------------------------------------------------------------------- */
78 edit_get_shortcut (unsigned long command
)
81 const char *shortcut
= NULL
;
83 shortcut
= keybind_lookup_keymap_shortcut (editor_map
, command
);
85 return g_strdup (shortcut
);
87 ext_map
= keybind_lookup_keymap_shortcut (editor_map
, CK_ExtendedKeyMap
);
89 shortcut
= keybind_lookup_keymap_shortcut (editor_x_map
, command
);
91 return g_strdup_printf ("%s %s", ext_map
, shortcut
);
96 /* --------------------------------------------------------------------------------------------- */
99 edit_get_title (const Dlg_head
* h
, size_t len
)
101 const WEdit
*edit
= (const WEdit
*) find_widget_type (h
, edit_callback
);
102 const char *modified
= edit
->modified
? "(*) " : " ";
103 const char *file_label
;
108 filename
= vfs_path_to_str (edit
->filename_vpath
);
109 file_label
= str_term_trim (filename
, len
- str_term_width1 (_("Edit: ")));
112 return g_strconcat (_("Edit: "), modified
, file_label
, (char *) NULL
);
115 /* --------------------------------------------------------------------------------------------- */
118 edit_event (Gpm_Event
* event
, void *data
)
120 WEdit
*edit
= (WEdit
*) data
;
121 Widget
*w
= (Widget
*) data
;
124 if (!mouse_global_in_widget (event
, w
))
125 return MOU_UNHANDLED
;
127 /* Unknown event type */
128 if ((event
->type
& (GPM_DOWN
| GPM_DRAG
| GPM_UP
)) == 0)
131 edit_update_curs_row (edit
);
132 edit_update_curs_col (edit
);
134 local
= mouse_get_local (event
, w
);
137 if ((local
.type
& (GPM_DOUBLE
| GPM_UP
)) == (GPM_UP
| GPM_DOUBLE
))
139 edit_mark_current_word_cmd (edit
);
144 if ((local
.type
& (GPM_TRIPLE
| GPM_UP
)) == (GPM_UP
| GPM_TRIPLE
))
146 edit_mark_current_line_cmd (edit
);
151 if ((local
.buttons
& GPM_B_UP
) != 0 && (local
.type
& GPM_DOWN
) != 0)
153 edit_move_up (edit
, 2, 1);
156 if ((local
.buttons
& GPM_B_DOWN
) != 0 && (local
.type
& GPM_DOWN
) != 0)
158 edit_move_down (edit
, 2, 1);
162 /* A lone up mustn't do anything */
163 if (edit
->mark2
!= -1 && (local
.type
& (GPM_UP
| GPM_DRAG
)) != 0)
166 if ((local
.type
& (GPM_DOWN
| GPM_UP
)) != 0)
167 edit_push_key_press (edit
);
169 if (!option_cursor_beyond_eol
)
170 edit
->prev_col
= local
.x
- edit
->start_col
- option_line_state_width
- 1;
173 long line_len
= edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), 0,
174 edit_eol (edit
, edit
->curs1
));
176 if (local
.x
> line_len
)
178 edit
->over_col
= local
.x
- line_len
- edit
->start_col
- option_line_state_width
- 1;
179 edit
->prev_col
= line_len
;
184 edit
->prev_col
= local
.x
- option_line_state_width
- edit
->start_col
- 1;
189 if (local
.y
> edit
->curs_row
)
190 edit_move_down (edit
, local
.y
- edit
->curs_row
, 0);
191 else if (local
.y
< edit
->curs_row
)
192 edit_move_up (edit
, edit
->curs_row
- local
.y
, 0);
194 edit_move_to_prev_col (edit
, edit_bol (edit
, edit
->curs1
));
196 if ((local
.type
& GPM_DOWN
) != 0)
198 edit_mark_cmd (edit
, 1); /* reset */
202 if ((local
.type
& GPM_DRAG
) == 0)
203 edit_mark_cmd (edit
, 0);
206 edit_find_bracket (edit
);
207 edit
->force
|= REDRAW_COMPLETELY
;
208 edit_update_curs_row (edit
);
209 edit_update_curs_col (edit
);
210 edit_update_screen (edit
);
215 /* --------------------------------------------------------------------------------------------- */
218 edit_command_execute (WEdit
* edit
, unsigned long command
)
220 if (command
== CK_Menu
)
221 edit_menu_cmd (edit
);
224 edit_execute_key_command (edit
, command
, -1);
225 edit_update_screen (edit
);
230 /* --------------------------------------------------------------------------------------------- */
233 edit_set_buttonbar (WEdit
* edit
, WButtonBar
* bb
)
235 buttonbar_set_label (bb
, 1, Q_ ("ButtonBar|Help"), editor_map
, (Widget
*) edit
);
236 buttonbar_set_label (bb
, 2, Q_ ("ButtonBar|Save"), editor_map
, (Widget
*) edit
);
237 buttonbar_set_label (bb
, 3, Q_ ("ButtonBar|Mark"), editor_map
, (Widget
*) edit
);
238 buttonbar_set_label (bb
, 4, Q_ ("ButtonBar|Replac"), editor_map
, (Widget
*) edit
);
239 buttonbar_set_label (bb
, 5, Q_ ("ButtonBar|Copy"), editor_map
, (Widget
*) edit
);
240 buttonbar_set_label (bb
, 6, Q_ ("ButtonBar|Move"), editor_map
, (Widget
*) edit
);
241 buttonbar_set_label (bb
, 7, Q_ ("ButtonBar|Search"), editor_map
, (Widget
*) edit
);
242 buttonbar_set_label (bb
, 8, Q_ ("ButtonBar|Delete"), editor_map
, (Widget
*) edit
);
243 buttonbar_set_label (bb
, 9, Q_ ("ButtonBar|PullDn"), editor_map
, (Widget
*) edit
);
244 buttonbar_set_label (bb
, 10, Q_ ("ButtonBar|Quit"), editor_map
, (Widget
*) edit
);
247 /* --------------------------------------------------------------------------------------------- */
248 /** Callback for the edit dialog */
251 edit_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
255 WButtonBar
*buttonbar
;
257 edit
= (WEdit
*) find_widget_type (h
, edit_callback
);
258 menubar
= find_menubar (h
);
259 buttonbar
= find_buttonbar (h
);
264 edit_set_buttonbar (edit
, buttonbar
);
268 /* don't use common_dialog_repaint() -- we don't need a frame */
269 tty_setcolor (EDITOR_NORMAL_COLOR
);
274 /* dlg_set_size() is surplus for this case */
277 widget_set_size (&buttonbar
->widget
, h
->lines
- 1, h
->x
, 1, h
->cols
);
278 widget_set_size (&menubar
->widget
, h
->y
, h
->x
, 1, h
->cols
);
279 menubar_arrange (menubar
);
280 widget_set_size (&edit
->widget
, h
->y
+ 1, h
->x
, h
->lines
- 2, h
->cols
);
284 if (sender
== (Widget
*) menubar
)
285 return send_message ((Widget
*) edit
, WIDGET_COMMAND
, parm
);
286 if (sender
== (Widget
*) buttonbar
)
287 return send_message ((Widget
*) edit
, WIDGET_COMMAND
, parm
);
288 return MSG_NOT_HANDLED
;
291 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
292 if (edit_ok_to_exit (edit
))
293 h
->state
= DLG_CLOSED
;
297 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
301 /* --------------------------------------------------------------------------------------------- */
304 edit_callback (Widget
* w
, widget_msg_t msg
, int parm
)
306 WEdit
*e
= (WEdit
*) w
;
311 e
->force
|= REDRAW_COMPLETELY
;
315 edit_update_screen (e
);
321 cb_ret_t ret
= MSG_NOT_HANDLED
;
323 /* The user may override the access-keys for the menu bar. */
324 if (macro_index
== -1 && edit_execute_macro (e
, parm
))
326 edit_update_screen (e
);
329 else if (edit_translate_key (e
, parm
, &cmd
, &ch
))
331 edit_execute_key_command (e
, cmd
, ch
);
332 edit_update_screen (e
);
335 else if (edit_drop_hotkey_menu (e
, parm
))
342 /* command from menubar or buttonbar */
343 return edit_command_execute (e
, parm
);
346 widget_move (w
, e
->curs_row
+ EDIT_TEXT_VERTICAL_OFFSET
,
347 e
->curs_col
+ e
->start_col
+ e
->over_col
+
348 EDIT_TEXT_HORIZONTAL_OFFSET
+ option_line_state_width
);
356 return default_proc (msg
, parm
);
360 /* --------------------------------------------------------------------------------------------- */
361 /*** public functions ****************************************************************************/
362 /* --------------------------------------------------------------------------------------------- */
365 edit_file (const vfs_path_t
* _file_vpath
, int line
)
367 static gboolean made_directory
= FALSE
;
376 dir
= mc_build_filename (mc_config_get_cache_path (), EDIT_DIR
, NULL
);
377 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
380 dir
= mc_build_filename (mc_config_get_path (), EDIT_DIR
, NULL
);
381 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
384 dir
= mc_build_filename (mc_config_get_data_path (), EDIT_DIR
, NULL
);
385 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
389 wedit
= edit_init (NULL
, 1, 0, LINES
- 2, COLS
, _file_vpath
, line
);
394 /* Create a new dialog and add it widgets to it */
396 create_dlg (FALSE
, 0, 0, LINES
, COLS
, NULL
, edit_dialog_callback
,
397 "[Internal File Editor]", NULL
, DLG_WANT_TAB
);
399 edit_dlg
->get_shortcut
= edit_get_shortcut
;
400 edit_dlg
->get_title
= edit_get_title
;
402 menubar
= menubar_new (0, 0, COLS
, NULL
);
403 add_widget (edit_dlg
, menubar
);
404 edit_init_menu (menubar
);
406 init_widget (&wedit
->widget
, wedit
->widget
.y
, wedit
->widget
.x
,
407 wedit
->widget
.lines
, wedit
->widget
.cols
, edit_callback
, edit_event
);
408 widget_want_cursor (wedit
->widget
, TRUE
);
410 add_widget (edit_dlg
, wedit
);
412 add_widget (edit_dlg
, buttonbar_new (TRUE
));
416 if (edit_dlg
->state
== DLG_CLOSED
)
417 destroy_dlg (edit_dlg
);
422 /* --------------------------------------------------------------------------------------------- */
425 edit_get_file_name (const WEdit
* edit
)
427 return vfs_path_to_str (edit
->filename_vpath
);
430 /* --------------------------------------------------------------------------------------------- */
433 edit_update_screen (WEdit
* e
)
435 edit_scroll_screen_over_cursor (e
);
437 edit_update_curs_col (e
);
440 /* pop all events for this window for internal handling */
442 e
->force
|= REDRAW_PAGE
;
445 if (e
->force
& REDRAW_COMPLETELY
)
446 e
->force
|= REDRAW_PAGE
;
447 edit_render_keypress (e
);
451 /* --------------------------------------------------------------------------------------------- */