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