2 Internal file viewer for the Midnight Commander
3 Function for whow info on display
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
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, 2010 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,
40 #include "lib/global.h"
41 #include "lib/skin/skin.h"
42 #include "lib/tty/tty.h"
43 #include "lib/tty/key.h"
44 #include "src/strutil.h"
46 #include "src/dialog.h" /* Dlg_head */
47 #include "src/widget.h" /* WButtonBar */
52 /*** global variables ****************************************************************************/
54 /*** file scope macro definitions ****************************************************************/
56 /*** file scope type declarations ****************************************************************/
58 /*** file scope variables ************************************************************************/
60 /* If set, show a ruler */
61 static enum ruler_type
{
67 /*** file scope functions ************************************************************************/
69 /* --------------------------------------------------------------------------------------------- */
71 /* Define labels and handlers for functional keys */
73 mcview_set_buttonbar (mcview_t
*view
)
75 Dlg_head
*h
= view
->widget
.parent
;
76 WButtonBar
*b
= find_buttonbar (h
);
77 const global_keymap_t
*keymap
= view
->hex_mode
? view
->hex_map
: view
->plain_map
;
79 buttonbar_set_label (b
, 1, Q_ ("ButtonBar|Help"), keymap
, (Widget
*) view
);
82 if (view
->hexedit_mode
)
83 buttonbar_set_label (b
, 2, Q_ ("ButtonBar|View"), keymap
, (Widget
*) view
);
84 else if (view
->datasource
== DS_FILE
)
85 buttonbar_set_label (b
, 2, Q_ ("ButtonBar|Edit"), keymap
, (Widget
*) view
);
87 buttonbar_set_label (b
, 2, "", keymap
, (Widget
*) view
);
89 buttonbar_set_label (b
, 4, Q_ ("ButtonBar|Ascii"), keymap
, (Widget
*) view
);
90 buttonbar_set_label (b
, 6, Q_ ("ButtonBar|Save"), keymap
, (Widget
*) view
);
91 buttonbar_set_label (b
, 7, Q_ ("ButtonBar|HxSrch"), keymap
, (Widget
*) view
);
94 buttonbar_set_label (b
, 2, view
->text_wrap_mode
? Q_ ("ButtonBar|UnWrap")
95 : Q_ ("ButtonBar|Wrap"),
96 keymap
, (Widget
*) view
);
97 buttonbar_set_label (b
, 4, Q_ ("ButtonBar|Hex"), keymap
, (Widget
*) view
);
98 buttonbar_set_label (b
, 6, "", keymap
, (Widget
*) view
);
99 buttonbar_set_label (b
, 7, Q_ ("ButtonBar|Search"), keymap
, (Widget
*) view
);
102 buttonbar_set_label (b
, 5, Q_ ("ButtonBar|Goto"), keymap
, (Widget
*) view
);
103 buttonbar_set_label (b
, 8, view
->magic_mode
? Q_ ("ButtonBar|Raw")
104 : Q_ ("ButtonBar|Parse"),
105 keymap
, (Widget
*) view
);
107 if (mcview_is_in_panel (view
))
108 buttonbar_set_label (b
, 10, "", keymap
, (Widget
*) view
);
110 /* don't override some panel buttonbar keys */
111 buttonbar_set_label (b
, 3, Q_ ("ButtonBar|Quit"), keymap
, (Widget
*) view
);
112 buttonbar_set_label (b
, 9, view
->text_nroff_mode
? Q_ ("ButtonBar|Unform")
113 : Q_ ("ButtonBar|Format"),
114 keymap
, (Widget
*) view
);
115 buttonbar_set_label (b
, 10, Q_ ("ButtonBar|Quit"), keymap
, (Widget
*) view
);
119 /* --------------------------------------------------------------------------------------------- */
123 mcview_display_status (mcview_t
* view
)
125 const screen_dimen top
= view
->status_area
.top
;
126 const screen_dimen left
= view
->status_area
.left
;
127 const screen_dimen width
= view
->status_area
.width
;
128 const screen_dimen height
= view
->status_area
.height
;
129 const char *file_label
;
130 screen_dimen file_label_width
, i
= 0;
135 tty_setcolor (SELECTED_COLOR
);
136 widget_move (view
, top
, left
);
137 tty_draw_hline (-1, -1, ' ', width
);
139 file_label
= view
->filename
? view
->filename
: view
->command
? view
->command
: "";
140 file_label_width
= str_term_width1 (file_label
) - 2;
142 char buffer
[BUF_TINY
];
143 widget_move (view
, top
, width
- 32);
144 if (view
->hex_mode
) {
145 tty_printf ("0x%08lx", (unsigned long) view
->hex_cursor
);
147 size_trunc_len (buffer
, 5, mcview_get_filesize (view
), 0);
148 tty_printf ("%9lli/%s%s %s", view
->dpy_end
,
150 mcview_may_still_grow (view
) ? "+" : " ",
152 source_codepage
>= 0 ? get_codepage_id (source_codepage
) : ""
159 widget_move (view
, top
, left
);
161 tty_print_string (str_fit_to_term (file_label
, width
- 34, J_LEFT_FIT
));
163 tty_print_string (str_fit_to_term (file_label
, width
- 5, J_LEFT_FIT
));
165 mcview_percent (view
, view
->hex_mode
? view
->hex_cursor
: view
->dpy_end
);
168 /* --------------------------------------------------------------------------------------------- */
170 /*** public functions ****************************************************************************/
172 /* --------------------------------------------------------------------------------------------- */
175 mcview_update (mcview_t
* view
)
177 static int dirt_limit
= 1;
179 if (view
->dpy_bbar_dirty
) {
180 view
->dpy_bbar_dirty
= FALSE
;
181 mcview_set_buttonbar (view
);
182 buttonbar_redraw (find_buttonbar (view
->widget
.parent
));
185 if (view
->dirty
> dirt_limit
) {
186 /* Too many updates skipped -> force a update */
187 mcview_display (view
);
189 /* Raise the update skipping limit */
191 if (dirt_limit
> mcview_max_dirt_limit
)
192 dirt_limit
= mcview_max_dirt_limit
;
193 } else if (view
->dirty
> 0) {
195 /* We have time to update the screen properly */
196 mcview_display (view
);
201 /* We are busy -> skipping full update,
202 only the status line is updated */
203 mcview_display_status (view
);
205 /* Here we had a refresh, if fast scrolling does not work
206 restore the refresh, although this should not happen */
210 /* --------------------------------------------------------------------------------------------- */
212 /* Displays as much data from view->dpy_start as fits on the screen */
214 mcview_display (mcview_t
* view
)
216 if (view
->hex_mode
) {
217 mcview_display_hex (view
);
218 } else if (view
->text_nroff_mode
) {
219 mcview_display_nroff (view
);
221 mcview_display_text (view
);
223 mcview_display_status (view
);
226 /* --------------------------------------------------------------------------------------------- */
229 mcview_compute_areas (mcview_t
* view
)
231 struct area view_area
;
232 screen_dimen height
, rest
, y
;
234 /* The viewer is surrounded by a frame of size view->dpy_frame_size.
235 * Inside that frame, there are: The status line (at the top),
236 * the data area and an optional ruler, which is shown above or
237 * below the data area. */
239 view_area
.top
= view
->dpy_frame_size
;
240 view_area
.left
= view
->dpy_frame_size
;
241 view_area
.height
= mcview_dimen_doz (view
->widget
.lines
, 2 * view
->dpy_frame_size
);
242 view_area
.width
= mcview_dimen_doz (view
->widget
.cols
, 2 * view
->dpy_frame_size
);
244 /* Most coordinates of the areas equal those of the whole viewer */
245 view
->status_area
= view_area
;
246 view
->ruler_area
= view_area
;
247 view
->data_area
= view_area
;
249 /* Compute the heights of the areas */
250 rest
= view_area
.height
;
252 height
= mcview_dimen_min (rest
, 1);
253 view
->status_area
.height
= height
;
256 height
= mcview_dimen_min (rest
, (ruler
== RULER_NONE
|| view
->hex_mode
) ? 0 : 2);
257 view
->ruler_area
.height
= height
;
260 view
->data_area
.height
= rest
;
262 /* Compute the position of the areas */
265 view
->status_area
.top
= y
;
266 y
+= view
->status_area
.height
;
268 if (ruler
== RULER_TOP
) {
269 view
->ruler_area
.top
= y
;
270 y
+= view
->ruler_area
.height
;
273 view
->data_area
.top
= y
;
274 y
+= view
->data_area
.height
;
276 if (ruler
== RULER_BOTTOM
)
277 view
->ruler_area
.top
= y
;
280 /* --------------------------------------------------------------------------------------------- */
283 mcview_update_bytes_per_line (mcview_t
* view
)
285 const screen_dimen cols
= view
->data_area
.width
;
291 bytes
= 4 * ((cols
- 8) / ((cols
< 80) ? 17 : 18));
294 view
->bytes_per_line
= bytes
;
295 view
->dirty
= mcview_max_dirt_limit
+ 1; /* To force refresh */
298 /* --------------------------------------------------------------------------------------------- */
301 mcview_display_toggle_ruler (mcview_t
* view
)
303 static const enum ruler_type next
[3] = {
309 assert ((size_t) ruler
< 3);
310 ruler
= next
[(size_t) ruler
];
314 /* --------------------------------------------------------------------------------------------- */
317 mcview_display_clean (mcview_t
* view
)
319 tty_setcolor (NORMAL_COLOR
);
320 widget_erase ((Widget
*) view
);
321 if (view
->dpy_frame_size
!= 0) {
322 tty_draw_box (view
->widget
.y
, view
->widget
.x
, view
->widget
.lines
, view
->widget
.cols
);
323 /* draw_double_box (view->widget.parent, view->widget.y,
324 view->widget.x, view->widget.lines, view->widget.cols);*/
328 /* --------------------------------------------------------------------------------------------- */
331 mcview_display_ruler (mcview_t
* view
)
333 static const char ruler_chars
[] = "|----*----";
334 const screen_dimen top
= view
->ruler_area
.top
;
335 const screen_dimen left
= view
->ruler_area
.left
;
336 const screen_dimen width
= view
->ruler_area
.width
;
337 const screen_dimen height
= view
->ruler_area
.height
;
338 const screen_dimen line_row
= (ruler
== RULER_TOP
) ? 0 : 1;
339 const screen_dimen nums_row
= (ruler
== RULER_TOP
) ? 1 : 0;
345 if (ruler
== RULER_NONE
|| height
< 1)
348 tty_setcolor (MARKED_COLOR
);
349 for (c
= 0; c
< width
; c
++) {
350 cl
= view
->dpy_text_column
+ c
;
351 if (line_row
< height
) {
352 widget_move (view
, top
+ line_row
, left
+ c
);
353 tty_print_char (ruler_chars
[cl
% 10]);
356 if ((cl
!= 0) && (cl
% 10) == 0) {
357 g_snprintf (r_buff
, sizeof (r_buff
), "%" OFFSETTYPE_PRId
, (long unsigned int) cl
);
358 if (nums_row
< height
) {
359 widget_move (view
, top
+ nums_row
, left
+ c
- 1);
360 tty_print_string (r_buff
);
364 tty_setcolor (NORMAL_COLOR
);
367 /* --------------------------------------------------------------------------------------------- */
370 mcview_percent (mcview_t
* view
, off_t p
)
372 const screen_dimen top
= view
->status_area
.top
;
373 const screen_dimen right
= view
->status_area
.left
+ view
->status_area
.width
;
374 const screen_dimen height
= view
->status_area
.height
;
378 if (height
< 1 || right
< 4)
380 if (mcview_may_still_grow (view
))
382 filesize
= mcview_get_filesize (view
);
384 if (filesize
== 0 || view
->dpy_end
== filesize
)
386 else if (p
> (INT_MAX
/ 100))
387 percent
= p
/ (filesize
/ 100);
389 percent
= p
* 100 / filesize
;
391 widget_move (view
, top
, right
- 4);
392 tty_printf ("%3d%%", percent
);
395 /* --------------------------------------------------------------------------------------------- */