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