This source file includes following definitions.
- mcview_mouse_callback
- mcview_new
- mcview_viewer
- mcview_load
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <config.h>
37 #include <errno.h>
38
39 #include "lib/global.h"
40 #include "lib/tty/tty.h"
41 #include "lib/vfs/vfs.h"
42 #include "lib/strutil.h"
43 #include "lib/util.h"
44 #include "lib/widget.h"
45
46 #include "src/filemanager/layout.h"
47 #include "src/filemanager/filemanager.h"
48
49 #include "internal.h"
50
51
52
53 mcview_mode_flags_t mcview_global_flags = {
54 .wrap = TRUE, .hex = FALSE, .magic = TRUE, .nroff = FALSE
55 };
56
57 mcview_mode_flags_t mcview_altered_flags = {
58 .wrap = FALSE, .hex = FALSE, .magic = FALSE, .nroff = FALSE
59 };
60
61 gboolean mcview_remember_file_position = FALSE;
62
63
64 int mcview_max_dirt_limit = 10;
65
66
67 gboolean mcview_mouse_move_pages = TRUE;
68
69
70 char *mcview_show_eof = NULL;
71
72
73
74
75
76
77
78
79
80
81
82
83
84 static void
85 mcview_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
86 {
87 WView *view = (WView *) w;
88 const WRect *r = &view->data_area;
89 gboolean ok = TRUE;
90
91 switch (msg)
92 {
93 case MSG_MOUSE_DOWN:
94 if (mcview_is_in_panel (view))
95 {
96 if (event->y == WIDGET (w->owner)->rect.y)
97 {
98
99 event->result.abort = TRUE;
100
101 ok = FALSE;
102 break;
103 }
104
105 if (!widget_get_state (w, WST_FOCUSED))
106 {
107
108 (void) change_panel ();
109 }
110 }
111 MC_FALLTHROUGH;
112
113 case MSG_MOUSE_CLICK:
114 if (!view->mode_flags.wrap)
115 {
116
117 int x;
118
119 x = event->x + 1;
120
121 if (x < r->cols * 1 / 4)
122 {
123 mcview_move_left (view, 1);
124 event->result.repeat = msg == MSG_MOUSE_DOWN;
125 }
126 else if (x < r->cols * 3 / 4)
127 {
128
129 ok = FALSE;
130 }
131 else
132 {
133 mcview_move_right (view, 1);
134 event->result.repeat = msg == MSG_MOUSE_DOWN;
135 }
136 }
137 else
138 {
139
140 int y;
141
142 y = event->y + 1;
143
144 if (y < r->y + r->lines * 1 / 3)
145 {
146 if (mcview_mouse_move_pages)
147 mcview_move_up (view, r->lines / 2);
148 else
149 mcview_move_up (view, 1);
150
151 event->result.repeat = msg == MSG_MOUSE_DOWN;
152 }
153 else if (y < r->y + r->lines * 2 / 3)
154 {
155
156 ok = FALSE;
157 }
158 else
159 {
160 if (mcview_mouse_move_pages)
161 mcview_move_down (view, r->lines / 2);
162 else
163 mcview_move_down (view, 1);
164
165 event->result.repeat = msg == MSG_MOUSE_DOWN;
166 }
167 }
168 break;
169
170 case MSG_MOUSE_SCROLL_UP:
171 mcview_move_up (view, 2);
172 break;
173
174 case MSG_MOUSE_SCROLL_DOWN:
175 mcview_move_down (view, 2);
176 break;
177
178 default:
179 ok = FALSE;
180 break;
181 }
182
183 if (ok)
184 mcview_update (view);
185 }
186
187
188
189
190
191 WView *
192 mcview_new (const WRect *r, gboolean is_panel)
193 {
194 WView *view;
195 Widget *w;
196
197 view = g_new0 (WView, 1);
198 w = WIDGET (view);
199
200 widget_init (w, r, mcview_callback, mcview_mouse_callback);
201 w->options |= WOP_SELECTABLE | WOP_TOP_SELECT;
202 w->keymap = viewer_map;
203
204 mcview_clear_mode_flags (&view->mode_flags);
205 view->hexedit_mode = FALSE;
206 view->hex_keymap = viewer_hex_map;
207 view->hexview_in_text = FALSE;
208 view->locked = FALSE;
209
210 view->dpy_frame_size = is_panel ? 1 : 0;
211 view->converter = str_cnv_from_term;
212
213 mcview_init (view);
214
215 if (mcview_global_flags.hex)
216 mcview_toggle_hex_mode (view);
217 if (mcview_global_flags.nroff)
218 mcview_toggle_nroff_mode (view);
219 if (mcview_global_flags.wrap)
220 mcview_toggle_wrap_mode (view);
221 if (mcview_global_flags.magic)
222 mcview_toggle_magic_mode (view);
223
224 return view;
225 }
226
227
228
229
230 gboolean
231 mcview_viewer (const char *command, const vfs_path_t *file_vpath, int start_line,
232 off_t search_start, off_t search_end)
233 {
234 gboolean succeeded;
235 WView *lc_mcview;
236 WDialog *view_dlg;
237 Widget *vw, *b;
238 WGroup *g;
239 WRect r;
240
241
242 view_dlg = dlg_create (FALSE, 0, 0, 1, 1, WPOS_FULLSCREEN, FALSE, NULL, mcview_dialog_callback,
243 NULL, "[Internal File Viewer]", NULL);
244 vw = WIDGET (view_dlg);
245 widget_want_tab (vw, TRUE);
246
247 g = GROUP (view_dlg);
248
249 r = vw->rect;
250 r.lines--;
251 lc_mcview = mcview_new (&r, FALSE);
252 group_add_widget_autopos (g, lc_mcview, WPOS_KEEP_ALL, NULL);
253
254 b = WIDGET (buttonbar_new ());
255 group_add_widget_autopos (g, b, b->pos_flags, NULL);
256
257 view_dlg->get_title = mcview_get_title;
258
259 succeeded = mcview_load (lc_mcview, command, vfs_path_as_str (file_vpath), start_line,
260 search_start, search_end);
261
262 if (succeeded)
263 dlg_run (view_dlg);
264 else
265 dlg_close (view_dlg);
266
267 if (widget_get_state (vw, WST_CLOSED))
268 widget_destroy (vw);
269
270 return succeeded;
271 }
272
273
274
275
276
277 gboolean
278 mcview_load (WView *view, const char *command, const char *file, int start_line, off_t search_start,
279 off_t search_end)
280 {
281 gboolean retval = FALSE;
282 vfs_path_t *vpath = NULL;
283
284 g_assert (view->bytes_per_line != 0);
285
286 view->filename_vpath = vfs_path_from_str (file);
287
288
289 if (file != NULL && file[0] != '\0')
290 {
291 vfs_path_free (view->workdir_vpath, TRUE);
292
293 if (!g_path_is_absolute (file))
294 {
295 vfs_path_t *p;
296
297 p = vfs_path_clone (vfs_get_raw_current_dir ());
298 view->workdir_vpath = vfs_path_append_new (p, file, (char *) NULL);
299 vfs_path_free (p, TRUE);
300 }
301 else
302 {
303
304 const char *fname;
305 char *dir;
306
307 fname = x_basename (file);
308 dir = g_strndup (file, (size_t) (fname - file));
309 view->workdir_vpath = vfs_path_from_str (dir);
310 g_free (dir);
311 }
312 }
313
314 if (!mcview_is_in_panel (view))
315 view->dpy_text_column = 0;
316
317 mcview_set_codeset (view);
318
319 if (command != NULL && (view->mode_flags.magic || file == NULL || file[0] == '\0'))
320 retval = mcview_load_command_output (view, command);
321 else if (file != NULL && file[0] != '\0')
322 {
323 int fd;
324 char tmp[BUF_MEDIUM];
325 struct stat st;
326
327
328 vpath = vfs_path_from_str (file);
329 fd = mc_open (vpath, O_RDONLY | O_NONBLOCK);
330 if (fd == -1)
331 {
332 g_snprintf (tmp, sizeof (tmp), _ ("Cannot open \"%s\"\n%s"), file,
333 unix_error_string (errno));
334 mcview_close_datasource (view);
335 mcview_show_error (view, tmp);
336 vfs_path_free (view->filename_vpath, TRUE);
337 view->filename_vpath = NULL;
338 vfs_path_free (view->workdir_vpath, TRUE);
339 view->workdir_vpath = NULL;
340 goto finish;
341 }
342
343
344 if (mc_fstat (fd, &st) == -1)
345 {
346 mc_close (fd);
347 g_snprintf (tmp, sizeof (tmp), _ ("Cannot stat \"%s\"\n%s"), file,
348 unix_error_string (errno));
349 mcview_close_datasource (view);
350 mcview_show_error (view, tmp);
351 vfs_path_free (view->filename_vpath, TRUE);
352 view->filename_vpath = NULL;
353 vfs_path_free (view->workdir_vpath, TRUE);
354 view->workdir_vpath = NULL;
355 goto finish;
356 }
357
358 if (!S_ISREG (st.st_mode))
359 {
360 mc_close (fd);
361 mcview_close_datasource (view);
362 mcview_show_error (view, _ ("Cannot view: not a regular file"));
363 vfs_path_free (view->filename_vpath, TRUE);
364 view->filename_vpath = NULL;
365 vfs_path_free (view->workdir_vpath, TRUE);
366 view->workdir_vpath = NULL;
367 goto finish;
368 }
369
370 if (st.st_size == 0 || mc_lseek (fd, 0, SEEK_SET) == -1)
371 {
372
373 mcview_set_datasource_vfs_pipe (view, fd);
374 }
375 else
376 {
377 if (view->mode_flags.magic)
378 {
379 int type;
380
381 type = get_compression_type (fd, file);
382
383 if (type != COMPRESSION_NONE)
384 {
385 char *tmp_filename;
386 vfs_path_t *vpath1;
387 int fd1;
388
389 tmp_filename = g_strconcat (file, decompress_extension (type), (char *) NULL);
390 vpath1 = vfs_path_from_str (tmp_filename);
391 g_free (tmp_filename);
392 fd1 = mc_open (vpath1, O_RDONLY | O_NONBLOCK);
393 vfs_path_free (vpath1, TRUE);
394
395 if (fd1 == -1)
396 {
397 g_snprintf (tmp, sizeof (tmp), _ ("Cannot open \"%s\" in parse mode\n%s"),
398 file, unix_error_string (errno));
399 mcview_close_datasource (view);
400 mcview_show_error (view, tmp);
401 }
402 else
403 {
404 mc_close (fd);
405 fd = fd1;
406 mc_fstat (fd, &st);
407 }
408 }
409 }
410
411 mcview_set_datasource_file (view, fd, &st);
412 }
413 retval = TRUE;
414 }
415
416 finish:
417 view->command = g_strdup (command);
418 view->dpy_start = 0;
419 view->dpy_paragraph_skip_lines = 0;
420 mcview_state_machine_init (&view->dpy_state_top, 0);
421 view->dpy_wrap_dirty = FALSE;
422 view->force_max = -1;
423 view->dpy_text_column = 0;
424
425 mcview_compute_areas (view);
426 mcview_update_bytes_per_line (view);
427
428 if (mcview_remember_file_position && view->filename_vpath != NULL && start_line == 0)
429 {
430 long line, col;
431 off_t new_offset, max_offset;
432
433 load_file_position (view->filename_vpath, &line, &col, &new_offset, &view->saved_bookmarks);
434 max_offset = mcview_get_filesize (view) - 1;
435 if (max_offset < 0)
436 new_offset = 0;
437 else
438 new_offset = MIN (new_offset, max_offset);
439 if (!view->mode_flags.hex)
440 {
441 view->dpy_start = mcview_bol (view, new_offset, 0);
442 view->dpy_wrap_dirty = TRUE;
443 }
444 else
445 {
446 view->dpy_start = new_offset - new_offset % view->bytes_per_line;
447 view->hex_cursor = new_offset;
448 }
449 }
450 else if (start_line > 0)
451 mcview_moveto (view, start_line - 1, 0);
452
453 view->search_start = search_start;
454 view->search_end = search_end;
455 view->hexedit_lownibble = FALSE;
456 view->hexview_in_text = FALSE;
457 view->change_list = NULL;
458 vfs_path_free (vpath, TRUE);
459 return retval;
460 }
461
462