Fixed creation of lock files
[midnight-commander.git] / src / viewer / lib.c
blobbfcc32ea6afdb1ccfa93286b2a149a7b73b92de5
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
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
18 Andrew Borodin <aborodin@vmail.ru>, 2009
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 #include "lib/charsets.h"
49 #include "src/main.h"
50 #include "src/selcodepage.h"
52 #include "internal.h"
53 #include "mcviewer.h"
55 /*** global variables ****************************************************************************/
57 #define OFF_T_BITWIDTH (unsigned int) (sizeof (off_t) * CHAR_BIT - 1)
58 const off_t INVALID_OFFSET = (off_t) - 1;
59 const off_t OFFSETTYPE_MAX = ((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1;
61 /*** file scope macro definitions ****************************************************************/
63 /*** file scope type declarations ****************************************************************/
65 /*** file scope variables ************************************************************************/
67 /*** file scope functions ************************************************************************/
68 /* --------------------------------------------------------------------------------------------- */
70 /* --------------------------------------------------------------------------------------------- */
71 /*** 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 = vfs_path_to_str (view->filename_vpath);
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, 0);
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 = mcview_bol (view, view->hex_cursor, 0);
132 view->hex_cursor = view->dpy_start;
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 (!mc_global.widget.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) || mc_global.widget.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_vpath = NULL;
187 view->workdir_vpath = 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;
225 view->saved_bookmarks = NULL;
228 /* --------------------------------------------------------------------------------------------- */
230 void
231 mcview_done (mcview_t * view)
233 /* Save current file position */
234 if (mcview_remember_file_position && view->filename_vpath != NULL)
236 save_file_position (view->filename_vpath, -1, 0,
237 view->hex_mode ? view->hex_cursor : view->dpy_start,
238 view->saved_bookmarks);
239 view->saved_bookmarks = NULL;
242 /* Write back the global viewer mode */
243 mcview_default_hex_mode = view->hex_mode;
244 mcview_default_nroff_flag = view->text_nroff_mode;
245 mcview_default_magic_flag = view->magic_mode;
246 mcview_global_wrap_mode = view->text_wrap_mode;
248 /* Free memory used by the viewer */
250 /* view->widget needs no destructor */
252 vfs_path_free (view->filename_vpath);
253 view->filename_vpath = NULL;
254 vfs_path_free (view->workdir_vpath);
255 view->workdir_vpath = NULL;
256 g_free (view->command);
257 view->command = NULL;
259 mcview_close_datasource (view);
260 /* the growing buffer is freed with the datasource */
262 coord_cache_free (view->coord_cache), view->coord_cache = NULL;
264 if (view->converter == INVALID_CONV)
265 view->converter = str_cnv_from_term;
267 if (view->converter != str_cnv_from_term)
269 str_close_conv (view->converter);
270 view->converter = str_cnv_from_term;
273 mc_search_free (view->search);
274 view->search = NULL;
275 g_free (view->last_search_string);
276 view->last_search_string = NULL;
277 mcview_nroff_seq_free (&view->search_nroff_seq);
278 mcview_hexedit_free_change_list (view);
281 /* --------------------------------------------------------------------------------------------- */
283 void
284 mcview_set_codeset (mcview_t * view)
286 #ifdef HAVE_CHARSET
287 const char *cp_id = NULL;
289 view->utf8 = TRUE;
290 cp_id =
291 get_codepage_id (mc_global.source_codepage >=
292 0 ? mc_global.source_codepage : mc_global.display_codepage);
293 if (cp_id != NULL)
295 GIConv conv;
296 conv = str_crt_conv_from (cp_id);
297 if (conv != INVALID_CONV)
299 if (view->converter != str_cnv_from_term)
300 str_close_conv (view->converter);
301 view->converter = conv;
303 view->utf8 = (gboolean) str_isutf8 (cp_id);
305 #else
306 (void) view;
307 #endif
310 /* --------------------------------------------------------------------------------------------- */
312 void
313 mcview_select_encoding (mcview_t * view)
315 #ifdef HAVE_CHARSET
316 if (do_select_codepage ())
317 mcview_set_codeset (view);
318 #else
319 (void) view;
320 #endif
323 /* --------------------------------------------------------------------------------------------- */
325 void
326 mcview_show_error (mcview_t * view, const char *msg)
328 mcview_close_datasource (view);
329 if (mcview_is_in_panel (view))
331 mcview_set_datasource_string (view, msg);
333 else
335 message (D_ERROR, MSG_ERROR, "%s", msg);
339 /* --------------------------------------------------------------------------------------------- */
340 /** returns index of the first char in the line
341 * it is constant for all line characters
344 off_t
345 mcview_bol (mcview_t * view, off_t current, off_t limit)
347 int c;
348 off_t filesize;
349 filesize = mcview_get_filesize (view);
350 if (current <= 0)
351 return 0;
352 if (current > filesize)
353 return filesize;
354 if (!mcview_get_byte (view, current, &c))
355 return current;
356 if (c == '\n')
358 if (!mcview_get_byte (view, current - 1, &c))
359 return current;
360 if (c == '\r')
361 current--;
363 while (current > 0 && current >= limit)
365 if (!mcview_get_byte (view, current - 1, &c))
366 break;
367 if (c == '\r' || c == '\n')
368 break;
369 current--;
371 return current;
374 /* --------------------------------------------------------------------------------------------- */
375 /** returns index of last char on line + width EOL
376 * mcview_eol of the current line == mcview_bol next line
379 off_t
380 mcview_eol (mcview_t * view, off_t current, off_t limit)
382 int c, prev_ch = 0;
383 off_t filesize;
384 filesize = mcview_get_filesize (view);
385 if (current < 0)
386 return 0;
387 if (current >= filesize)
388 return filesize;
389 while (current < filesize && current < limit)
391 if (!mcview_get_byte (view, current, &c))
392 break;
393 if (c == '\n')
395 current++;
396 break;
398 else if (prev_ch == '\r')
400 break;
402 current++;
403 prev_ch = c;
405 return current;
408 /* --------------------------------------------------------------------------------------------- */
410 char *
411 mcview_get_title (const Dlg_head * h, size_t len)
413 const mcview_t *view = (const mcview_t *) find_widget_type (h, mcview_callback);
414 const char *modified = view->hexedit_mode && (view->change_list != NULL) ? "(*) " : " ";
415 const char *file_label;
416 char *view_filename;
417 char *ret_str;
419 view_filename = view->filename_vpath != NULL ? vfs_path_to_str (view->filename_vpath) : NULL;
421 len -= 4;
423 file_label = view_filename != NULL ? view_filename : view->command != NULL ? view->command : "";
424 file_label = str_term_trim (file_label, len - str_term_width1 (_("View: ")));
426 ret_str = g_strconcat (_("View: "), modified, file_label, (char *) NULL);
427 g_free (view_filename);
428 return ret_str;
431 /* --------------------------------------------------------------------------------------------- */