src/layout.c: fixed missin case statement in set_display_type()
[free-mc.git] / src / viewer / lib.c
blob271055f15e57b9c4b2ccad40f9ea640fc02346ed
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 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
10 1995 Jakub Jelinek
11 1996 Joseph M. Hinkle
12 1997 Norbert Warmuth
13 1998 Pavel Machek
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
35 MA 02110-1301, USA.
38 #include <config.h>
40 #include <limits.h>
41 #include <sys/types.h>
43 #include "lib/global.h"
44 #include "lib/vfs/mc-vfs/vfs.h"
45 #include "lib/strutil.h"
47 #include "src/wtools.h"
48 #include "src/main.h"
49 #include "lib/lock.h" /* unlock_file() */
50 #include "src/charsets.h"
51 #include "src/selcodepage.h"
53 #include "internal.h"
54 #include "mcviewer.h"
56 /*** global variables ****************************************************************************/
58 #define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
59 const off_t INVALID_OFFSET = (off_t) - 1;
60 const off_t OFFSETTYPE_MAX = ((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1;
62 /*** file scope macro definitions ****************************************************************/
64 /*** file scope type declarations ****************************************************************/
66 /*** file scope variables ************************************************************************/
68 /*** file scope functions ************************************************************************/
70 /*** public functions ****************************************************************************/
72 /* --------------------------------------------------------------------------------------------- */
74 void
75 mcview_toggle_magic_mode (mcview_t * view)
77 char *filename, *command;
79 mcview_altered_magic_flag = 1;
80 view->magic_mode = !view->magic_mode;
81 filename = g_strdup (view->filename);
82 command = g_strdup (view->command);
84 mcview_done (view);
85 mcview_init (view);
86 mcview_load (view, command, filename, 0);
87 g_free (filename);
88 g_free (command);
89 view->dpy_bbar_dirty = TRUE;
90 view->dirty++;
93 /* --------------------------------------------------------------------------------------------- */
95 void
96 mcview_toggle_wrap_mode (mcview_t * view)
98 if (view->text_wrap_mode)
99 view->dpy_start = mcview_bol (view, view->dpy_start);
100 view->text_wrap_mode = !view->text_wrap_mode;
101 view->dpy_bbar_dirty = TRUE;
102 view->dirty++;
105 /* --------------------------------------------------------------------------------------------- */
107 void
108 mcview_toggle_nroff_mode (mcview_t * view)
110 view->text_nroff_mode = !view->text_nroff_mode;
111 mcview_altered_nroff_flag = 1;
112 view->dpy_bbar_dirty = TRUE;
113 view->dirty++;
116 /* --------------------------------------------------------------------------------------------- */
118 void
119 mcview_toggle_hex_mode (mcview_t * view)
121 view->hex_mode = !view->hex_mode;
123 if (view->hex_mode)
125 view->hex_cursor = view->dpy_start;
126 view->dpy_start = mcview_offset_rounddown (view->dpy_start, view->bytes_per_line);
127 widget_want_cursor (view->widget, 1);
129 else
131 view->dpy_start = view->hex_cursor;
132 mcview_moveto_bol (view);
133 widget_want_cursor (view->widget, 0);
135 mcview_altered_hex_mode = 1;
136 view->dpy_bbar_dirty = TRUE;
137 view->dirty++;
140 /* --------------------------------------------------------------------------------------------- */
142 gboolean
143 mcview_ok_to_quit (mcview_t * view)
145 int r;
147 if (view->change_list == NULL)
148 return TRUE;
150 if (!midnight_shutdown)
152 query_set_sel (2);
153 r = query_dialog (_("Quit"),
154 _("File was modified. Save with exit?"), D_NORMAL, 3,
155 _("&Yes"), _("&No"), _("&Cancel quit"));
157 else
159 r = query_dialog (_("Quit"),
160 _("Midnight Commander is being shut down.\nSave modified file?"),
161 D_NORMAL, 2, _("&Yes"), _("&No"));
162 /* Esc is No */
163 if (r == -1)
164 r = 1;
167 switch (r)
169 case 0: /* Yes */
170 return mcview_hexedit_save_changes (view) || midnight_shutdown;
171 case 1: /* No */
172 mcview_hexedit_free_change_list (view);
173 return TRUE;
174 default:
175 return FALSE;
179 /* --------------------------------------------------------------------------------------------- */
181 void
182 mcview_init (mcview_t * view)
184 size_t i;
186 view->filename = NULL;
187 view->workdir = NULL;
188 view->command = NULL;
189 view->search_nroff_seq = NULL;
191 mcview_set_datasource_none (view);
193 view->growbuf_in_use = FALSE;
194 /* leave the other growbuf fields uninitialized */
196 view->hexedit_lownibble = FALSE;
197 view->locked = FALSE;
198 view->coord_cache = NULL;
200 view->dpy_start = 0;
201 view->dpy_text_column = 0;
202 view->dpy_end = 0;
203 view->hex_cursor = 0;
204 view->cursor_col = 0;
205 view->cursor_row = 0;
206 view->change_list = NULL;
208 /* {status,ruler,data}_area are left uninitialized */
210 view->dirty = 0;
211 view->dpy_bbar_dirty = TRUE;
212 view->bytes_per_line = 1;
214 view->search_start = 0;
215 view->search_end = 0;
217 view->marker = 0;
218 for (i = 0; i < sizeof (view->marks) / sizeof (view->marks[0]); i++)
219 view->marks[i] = 0;
221 view->move_dir = 0;
222 view->update_steps = 0;
223 view->update_activate = 0;
226 /* --------------------------------------------------------------------------------------------- */
228 void
229 mcview_done (mcview_t * view)
231 /* Save current file position */
232 if (mcview_remember_file_position && view->filename != NULL)
234 char *canon_fname;
235 canon_fname = vfs_canon (view->filename);
236 save_file_position (canon_fname, -1, 0, view->dpy_start);
237 g_free (canon_fname);
240 /* Write back the global viewer mode */
241 mcview_default_hex_mode = view->hex_mode;
242 mcview_default_nroff_flag = view->text_nroff_mode;
243 mcview_default_magic_flag = view->magic_mode;
244 mcview_global_wrap_mode = view->text_wrap_mode;
246 /* Free memory used by the viewer */
248 /* view->widget needs no destructor */
250 g_free (view->filename);
251 view->filename = NULL;
252 g_free (view->workdir);
253 view->workdir = NULL;
254 g_free (view->command);
255 view->command = NULL;
257 mcview_close_datasource (view);
258 /* the growing buffer is freed with the datasource */
260 coord_cache_free (view->coord_cache), view->coord_cache = NULL;
262 if (view->converter == INVALID_CONV)
263 view->converter = str_cnv_from_term;
265 if (view->converter != str_cnv_from_term)
267 str_close_conv (view->converter);
268 view->converter = str_cnv_from_term;
271 mc_search_free (view->search);
272 view->search = NULL;
273 g_free (view->last_search_string);
274 view->last_search_string = NULL;
275 mcview_nroff_seq_free (&view->search_nroff_seq);
276 mcview_hexedit_free_change_list (view);
279 /* --------------------------------------------------------------------------------------------- */
281 void
282 mcview_set_codeset (mcview_t * view)
284 #ifdef HAVE_CHARSET
285 const char *cp_id = NULL;
287 view->utf8 = TRUE;
288 cp_id = get_codepage_id (source_codepage >= 0 ? source_codepage : display_codepage);
289 if (cp_id != NULL)
291 GIConv conv;
292 conv = str_crt_conv_from (cp_id);
293 if (conv != INVALID_CONV)
295 if (view->converter != str_cnv_from_term)
296 str_close_conv (view->converter);
297 view->converter = conv;
299 view->utf8 = (gboolean) str_isutf8 (cp_id);
301 #else
302 (void) view;
303 #endif
306 /* --------------------------------------------------------------------------------------------- */
308 void
309 mcview_select_encoding (mcview_t * view)
311 #ifdef HAVE_CHARSET
312 if (do_select_codepage ())
314 mcview_set_codeset (view);
316 #else
317 (void) view;
318 #endif
321 /* --------------------------------------------------------------------------------------------- */
323 void
324 mcview_show_error (mcview_t * view, const char *msg)
326 mcview_close_datasource (view);
327 if (mcview_is_in_panel (view))
329 mcview_set_datasource_string (view, msg);
331 else
333 message (D_ERROR, MSG_ERROR, "%s", msg);
337 /* --------------------------------------------------------------------------------------------- */
339 /* returns index of the first char in the line */
340 /* it is constant for all line characters */
341 off_t
342 mcview_bol (mcview_t * view, off_t current)
344 int c;
345 off_t filesize;
346 filesize = mcview_get_filesize (view);
347 if (current <= 0)
348 return 0;
349 if (current > filesize)
350 return filesize;
351 if (!mcview_get_byte (view, current, &c))
352 return current;
353 if (c == '\n')
355 if (!mcview_get_byte (view, current - 1, &c))
356 return current;
357 if (c == '\r')
358 current--;
360 while (current > 0)
362 if (!mcview_get_byte (view, current - 1, &c))
363 break;
364 if (c == '\r' || c == '\n')
365 break;
366 current--;
368 return current;
371 /* --------------------------------------------------------------------------------------------- */
373 /* returns index of last char on line + width EOL */
374 /* mcview_eol of the current line == mcview_bol next line */
375 off_t
376 mcview_eol (mcview_t * view, off_t current)
378 int c, prev_ch = 0;
379 off_t filesize;
380 filesize = mcview_get_filesize (view);
381 if (current < 0)
382 return 0;
383 if (current >= filesize)
384 return filesize;
385 while (current < filesize)
387 if (!mcview_get_byte (view, current, &c))
388 break;
389 if (c == '\n')
391 current++;
392 break;
394 else if (prev_ch == '\r')
396 break;
398 current++;
399 prev_ch = c;
401 return current;
404 /* --------------------------------------------------------------------------------------------- */
406 char *
407 mcview_get_title (const Dlg_head * h, size_t len)
409 const mcview_t *view = (const mcview_t *) find_widget_type (h, mcview_callback);
410 const char *modified = view->hexedit_mode && (view->change_list != NULL) ? "(*) " : " ";
411 const char *file_label;
413 len -= 4;
415 file_label = view->filename != NULL ? view->filename :
416 view->command != NULL ? view->command : "";
417 file_label = str_term_trim (file_label, len - str_term_width1 (_("View: ")));
419 return g_strconcat (_("View: "), modified, file_label, (char *) NULL);
421 /* --------------------------------------------------------------------------------------------- */
423 gboolean
424 mcview_lock_file (mcview_t * view)
426 char *fullpath;
427 gboolean ret;
429 fullpath = g_build_filename (view->workdir, view->filename, (char *) NULL);
430 ret = lock_file (fullpath);
431 g_free (fullpath);
433 return ret;
436 /* --------------------------------------------------------------------------------------------- */
438 gboolean
439 mcview_unlock_file (mcview_t * view)
441 char *fullpath;
442 gboolean ret;
444 fullpath = g_build_filename (view->workdir, view->filename, (char *) NULL);
445 ret = unlock_file (fullpath);
446 g_free (fullpath);
448 return ret;
451 /* --------------------------------------------------------------------------------------------- */