Remove input_set_origin(). Use widget_set_size() instead.
[midnight-commander.git] / src / viewer / lib.c
blob5e932a384f846585a3fd5ca63e54bc5d91b65df6
1 /*
2 Internal file viewer for the Midnight Commander
3 Common finctions (used from some other mcviewer functions)
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009, 2011, 2013
7 The Free Software Foundation, Inc.
9 Written by:
10 Miguel de Icaza, 1994, 1995, 1998
11 Janne Kukonlehto, 1994, 1995
12 Jakub Jelinek, 1995
13 Joseph M. Hinkle, 1996
14 Norbert Warmuth, 1997
15 Pavel Machek, 1998
16 Roland Illig <roland.illig@gmx.de>, 2004, 2005
17 Slava Zanko <slavazanko@google.com>, 2009, 2013
18 Andrew Borodin <aborodin@vmail.ru>, 2009, 2013
19 Ilia Maslakov <il.smind@gmail.com>, 2009
21 This file is part of the Midnight Commander.
23 The Midnight Commander is free software: you can redistribute it
24 and/or modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation, either version 3 of the License,
26 or (at your option) any later version.
28 The Midnight Commander is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program. If not, see <http://www.gnu.org/licenses/>.
37 #include <config.h>
39 #include <limits.h>
40 #include <sys/types.h>
42 #include "lib/global.h"
43 #include "lib/vfs/vfs.h"
44 #include "lib/strutil.h"
45 #include "lib/util.h" /* save_file_position() */
46 #include "lib/widget.h"
47 #ifdef HAVE_CHARSET
48 #include "lib/charsets.h"
49 #endif
51 #ifdef HAVE_CHARSET
52 #include "src/selcodepage.h"
53 #endif
55 #include "internal.h"
57 /*** global variables ****************************************************************************/
59 #define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
60 const off_t INVALID_OFFSET = (off_t) (-1);
61 const off_t OFFSETTYPE_MAX = ((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1;
63 /*** file scope macro definitions ****************************************************************/
65 /*** file scope type declarations ****************************************************************/
67 /*** file scope variables ************************************************************************/
69 /*** file scope functions ************************************************************************/
70 /* --------------------------------------------------------------------------------------------- */
72 /* --------------------------------------------------------------------------------------------- */
73 /*** public functions ****************************************************************************/
74 /* --------------------------------------------------------------------------------------------- */
76 void
77 mcview_toggle_magic_mode (mcview_t * view)
79 char *command;
80 dir_list *dir;
81 int *dir_idx;
83 mcview_altered_magic_flag = 1;
84 view->magic_mode = !view->magic_mode;
86 /* reinit view */
87 command = g_strdup (view->command);
88 dir = view->dir;
89 dir_idx = view->dir_idx;
90 view->dir = NULL;
91 view->dir_idx = NULL;
92 mcview_done (view);
93 mcview_init (view);
94 mcview_load (view, command, vfs_path_as_str (view->filename_vpath), 0);
95 view->dir = dir;
96 view->dir_idx = dir_idx;
97 g_free (command);
99 view->dpy_bbar_dirty = TRUE;
100 view->dirty++;
103 /* --------------------------------------------------------------------------------------------- */
105 void
106 mcview_toggle_wrap_mode (mcview_t * view)
108 if (view->text_wrap_mode)
109 view->dpy_start = mcview_bol (view, view->dpy_start, 0);
110 view->text_wrap_mode = !view->text_wrap_mode;
111 view->dpy_bbar_dirty = TRUE;
112 view->dirty++;
115 /* --------------------------------------------------------------------------------------------- */
117 void
118 mcview_toggle_nroff_mode (mcview_t * view)
120 view->text_nroff_mode = !view->text_nroff_mode;
121 mcview_altered_nroff_flag = 1;
122 view->dpy_bbar_dirty = TRUE;
123 view->dirty++;
126 /* --------------------------------------------------------------------------------------------- */
128 void
129 mcview_toggle_hex_mode (mcview_t * view)
131 view->hex_mode = !view->hex_mode;
133 if (view->hex_mode)
135 view->hex_cursor = view->dpy_start;
136 view->dpy_start = mcview_offset_rounddown (view->dpy_start, view->bytes_per_line);
137 widget_want_cursor (WIDGET (view), TRUE);
139 else
141 view->dpy_start = mcview_bol (view, view->hex_cursor, 0);
142 view->hex_cursor = view->dpy_start;
143 widget_want_cursor (WIDGET (view), FALSE);
145 mcview_altered_hex_mode = 1;
146 view->dpy_bbar_dirty = TRUE;
147 view->dirty++;
150 /* --------------------------------------------------------------------------------------------- */
152 void
153 mcview_init (mcview_t * view)
155 size_t i;
157 view->filename_vpath = NULL;
158 view->workdir_vpath = NULL;
159 view->command = NULL;
160 view->search_nroff_seq = NULL;
162 mcview_set_datasource_none (view);
164 view->growbuf_in_use = FALSE;
165 /* leave the other growbuf fields uninitialized */
167 view->hexedit_lownibble = FALSE;
168 view->locked = FALSE;
169 view->coord_cache = NULL;
171 view->dpy_start = 0;
172 view->dpy_text_column = 0;
173 view->dpy_end = 0;
174 view->hex_cursor = 0;
175 view->cursor_col = 0;
176 view->cursor_row = 0;
177 view->change_list = NULL;
179 /* {status,ruler,data}_area are left uninitialized */
181 view->dirty = 0;
182 view->dpy_bbar_dirty = TRUE;
183 view->bytes_per_line = 1;
185 view->search_start = 0;
186 view->search_end = 0;
188 view->marker = 0;
189 for (i = 0; i < G_N_ELEMENTS (view->marks); i++)
190 view->marks[i] = 0;
192 view->update_steps = 0;
193 view->update_activate = 0;
195 view->saved_bookmarks = NULL;
198 /* --------------------------------------------------------------------------------------------- */
200 void
201 mcview_done (mcview_t * view)
203 /* Save current file position */
204 if (mcview_remember_file_position && view->filename_vpath != NULL)
206 save_file_position (view->filename_vpath, -1, 0,
207 view->hex_mode ? view->hex_cursor : view->dpy_start,
208 view->saved_bookmarks);
209 view->saved_bookmarks = NULL;
212 /* Write back the global viewer mode */
213 mcview_default_hex_mode = view->hex_mode;
214 mcview_default_nroff_flag = view->text_nroff_mode;
215 mcview_default_magic_flag = view->magic_mode;
216 mcview_global_wrap_mode = view->text_wrap_mode;
218 /* Free memory used by the viewer */
220 /* view->widget needs no destructor */
222 vfs_path_free (view->filename_vpath);
223 view->filename_vpath = NULL;
224 vfs_path_free (view->workdir_vpath);
225 view->workdir_vpath = NULL;
226 g_free (view->command);
227 view->command = NULL;
229 mcview_close_datasource (view);
230 /* the growing buffer is freed with the datasource */
232 coord_cache_free (view->coord_cache), view->coord_cache = NULL;
234 if (view->converter == INVALID_CONV)
235 view->converter = str_cnv_from_term;
237 if (view->converter != str_cnv_from_term)
239 str_close_conv (view->converter);
240 view->converter = str_cnv_from_term;
243 mc_search_free (view->search);
244 view->search = NULL;
245 g_free (view->last_search_string);
246 view->last_search_string = NULL;
247 mcview_nroff_seq_free (&view->search_nroff_seq);
248 mcview_hexedit_free_change_list (view);
250 if (mc_global.mc_run_mode == MC_RUN_VIEWER && view->dir != NULL)
252 /* mcviewer is the owner of file list */
253 dir_list_clean (view->dir);
254 g_free (view->dir->list);
255 g_free (view->dir_idx);
256 g_free (view->dir);
259 view->dir = NULL;
262 /* --------------------------------------------------------------------------------------------- */
264 void
265 mcview_set_codeset (mcview_t * view)
267 #ifdef HAVE_CHARSET
268 const char *cp_id = NULL;
270 view->utf8 = TRUE;
271 cp_id =
272 get_codepage_id (mc_global.source_codepage >=
273 0 ? mc_global.source_codepage : mc_global.display_codepage);
274 if (cp_id != NULL)
276 GIConv conv;
277 conv = str_crt_conv_from (cp_id);
278 if (conv != INVALID_CONV)
280 if (view->converter != str_cnv_from_term)
281 str_close_conv (view->converter);
282 view->converter = conv;
284 view->utf8 = (gboolean) str_isutf8 (cp_id);
286 #else
287 (void) view;
288 #endif
291 /* --------------------------------------------------------------------------------------------- */
293 #ifdef HAVE_CHARSET
294 void
295 mcview_select_encoding (mcview_t * view)
297 if (do_select_codepage ())
298 mcview_set_codeset (view);
300 #endif
302 /* --------------------------------------------------------------------------------------------- */
304 void
305 mcview_show_error (mcview_t * view, const char *msg)
307 mcview_close_datasource (view);
308 if (mcview_is_in_panel (view))
310 mcview_set_datasource_string (view, msg);
312 else
314 message (D_ERROR, MSG_ERROR, "%s", msg);
318 /* --------------------------------------------------------------------------------------------- */
319 /** returns index of the first char in the line
320 * it is constant for all line characters
323 off_t
324 mcview_bol (mcview_t * view, off_t current, off_t limit)
326 int c;
327 off_t filesize;
328 filesize = mcview_get_filesize (view);
329 if (current <= 0)
330 return 0;
331 if (current > filesize)
332 return filesize;
333 if (!mcview_get_byte (view, current, &c))
334 return current;
335 if (c == '\n')
337 if (!mcview_get_byte (view, current - 1, &c))
338 return current;
339 if (c == '\r')
340 current--;
342 while (current > 0 && current >= limit)
344 if (!mcview_get_byte (view, current - 1, &c))
345 break;
346 if (c == '\r' || c == '\n')
347 break;
348 current--;
350 return current;
353 /* --------------------------------------------------------------------------------------------- */
354 /** returns index of last char on line + width EOL
355 * mcview_eol of the current line == mcview_bol next line
358 off_t
359 mcview_eol (mcview_t * view, off_t current, off_t limit)
361 int c, prev_ch = 0;
362 off_t filesize;
363 filesize = mcview_get_filesize (view);
364 if (current < 0)
365 return 0;
366 if (current >= filesize)
367 return filesize;
368 while (current < filesize && current < limit)
370 if (!mcview_get_byte (view, current, &c))
371 break;
372 if (c == '\n')
374 current++;
375 break;
377 else if (prev_ch == '\r')
379 break;
381 current++;
382 prev_ch = c;
384 return current;
387 /* --------------------------------------------------------------------------------------------- */
389 char *
390 mcview_get_title (const WDialog * h, size_t len)
392 const mcview_t *view = (const mcview_t *) find_widget_type (h, mcview_callback);
393 const char *modified = view->hexedit_mode && (view->change_list != NULL) ? "(*) " : " ";
394 const char *file_label;
395 const char *view_filename;
396 char *ret_str;
398 view_filename = vfs_path_as_str (view->filename_vpath);
400 len -= 4;
402 file_label = view_filename != NULL ? view_filename : view->command != NULL ? view->command : "";
403 file_label = str_term_trim (file_label, len - str_term_width1 (_("View: ")));
405 ret_str = g_strconcat (_("View: "), modified, file_label, (char *) NULL);
406 return ret_str;
409 /* --------------------------------------------------------------------------------------------- */