root/src/viewer/lib.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mcview_toggle_magic_mode
  2. mcview_toggle_wrap_mode
  3. mcview_toggle_nroff_mode
  4. mcview_toggle_hex_mode
  5. mcview_init
  6. mcview_done
  7. mcview_set_codeset
  8. mcview_select_encoding
  9. mcview_show_error
  10. mcview_bol
  11. mcview_eol
  12. mcview_get_title
  13. mcview_calc_percent
  14. mcview_clear_mode_flags

   1 /*
   2    Internal file viewer for the Midnight Commander
   3    Common finctions (used from some other mcviewer functions)
   4 
   5    Copyright (C) 1994-2019
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Miguel de Icaza, 1994, 1995, 1998
  10    Janne Kukonlehto, 1994, 1995
  11    Jakub Jelinek, 1995
  12    Joseph M. Hinkle, 1996
  13    Norbert Warmuth, 1997
  14    Pavel Machek, 1998
  15    Roland Illig <roland.illig@gmx.de>, 2004, 2005
  16    Slava Zanko <slavazanko@google.com>, 2009, 2013
  17    Andrew Borodin <aborodin@vmail.ru>, 2009, 2013, 2014
  18    Ilia Maslakov <il.smind@gmail.com>, 2009
  19 
  20    This file is part of the Midnight Commander.
  21 
  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 3 of the License,
  25    or (at your option) any later version.
  26 
  27    The Midnight Commander is distributed in the hope that it will be useful,
  28    but WITHOUT ANY WARRANTY; without even the implied warranty of
  29    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30    GNU General Public License for more details.
  31 
  32    You should have received a copy of the GNU General Public License
  33    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  34  */
  35 
  36 #include <config.h>
  37 
  38 #include <string.h>             /* memset() */
  39 #include <sys/types.h>
  40 
  41 #include "lib/global.h"
  42 #include "lib/vfs/vfs.h"
  43 #include "lib/strutil.h"
  44 #include "lib/util.h"           /* save_file_position() */
  45 #include "lib/widget.h"
  46 #ifdef HAVE_CHARSET
  47 #include "lib/charsets.h"
  48 #endif
  49 
  50 #ifdef HAVE_CHARSET
  51 #include "src/selcodepage.h"
  52 #endif
  53 
  54 #include "internal.h"
  55 
  56 /*** global variables ****************************************************************************/
  57 
  58 /*** file scope macro definitions ****************************************************************/
  59 
  60 /*** file scope type declarations ****************************************************************/
  61 
  62 /*** file scope variables ************************************************************************/
  63 
  64 /*** file scope functions ************************************************************************/
  65 /* --------------------------------------------------------------------------------------------- */
  66 
  67 /* --------------------------------------------------------------------------------------------- */
  68 /*** public functions ****************************************************************************/
  69 /* --------------------------------------------------------------------------------------------- */
  70 
  71 void
  72 mcview_toggle_magic_mode (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
  73 {
  74     char *filename, *command;
  75     dir_list *dir;
  76     int *dir_idx;
  77 
  78     mcview_altered_flags.magic = TRUE;
  79     view->mode_flags.magic = !view->mode_flags.magic;
  80 
  81     /* reinit view */
  82     filename = g_strdup (vfs_path_as_str (view->filename_vpath));
  83     command = g_strdup (view->command);
  84     dir = view->dir;
  85     dir_idx = view->dir_idx;
  86     view->dir = NULL;
  87     view->dir_idx = NULL;
  88     mcview_done (view);
  89     mcview_init (view);
  90     mcview_load (view, command, filename, 0, 0, 0);
  91     view->dir = dir;
  92     view->dir_idx = dir_idx;
  93     g_free (filename);
  94     g_free (command);
  95 
  96     view->dpy_bbar_dirty = TRUE;
  97     view->dirty++;
  98 }
  99 
 100 /* --------------------------------------------------------------------------------------------- */
 101 
 102 void
 103 mcview_toggle_wrap_mode (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 104 {
 105     view->mode_flags.wrap = !view->mode_flags.wrap;
 106     view->dpy_wrap_dirty = TRUE;
 107     view->dpy_bbar_dirty = TRUE;
 108     view->dirty++;
 109 }
 110 
 111 /* --------------------------------------------------------------------------------------------- */
 112 
 113 void
 114 mcview_toggle_nroff_mode (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 115 {
 116     view->mode_flags.nroff = !view->mode_flags.nroff;
 117     mcview_altered_flags.nroff = TRUE;
 118     view->dpy_wrap_dirty = TRUE;
 119     view->dpy_bbar_dirty = TRUE;
 120     view->dirty++;
 121 }
 122 
 123 /* --------------------------------------------------------------------------------------------- */
 124 
 125 void
 126 mcview_toggle_hex_mode (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 127 {
 128     view->mode_flags.hex = !view->mode_flags.hex;
 129 
 130     if (view->mode_flags.hex)
 131     {
 132         view->hex_cursor = view->dpy_start;
 133         view->dpy_start = mcview_offset_rounddown (view->dpy_start, view->bytes_per_line);
 134         widget_want_cursor (WIDGET (view), TRUE);
 135     }
 136     else
 137     {
 138         view->dpy_start = mcview_bol (view, view->hex_cursor, 0);
 139         view->hex_cursor = view->dpy_start;
 140         widget_want_cursor (WIDGET (view), FALSE);
 141     }
 142     mcview_altered_flags.hex = TRUE;
 143     view->dpy_paragraph_skip_lines = 0;
 144     view->dpy_wrap_dirty = TRUE;
 145     view->dpy_bbar_dirty = TRUE;
 146     view->dirty++;
 147 }
 148 
 149 /* --------------------------------------------------------------------------------------------- */
 150 
 151 void
 152 mcview_init (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 153 {
 154     size_t i;
 155 
 156     view->filename_vpath = NULL;
 157     view->workdir_vpath = NULL;
 158     view->command = NULL;
 159     view->search_nroff_seq = NULL;
 160 
 161     mcview_set_datasource_none (view);
 162 
 163     view->growbuf_in_use = FALSE;
 164     /* leave the other growbuf fields uninitialized */
 165 
 166     view->hexedit_lownibble = FALSE;
 167     view->locked = FALSE;
 168     view->coord_cache = NULL;
 169 
 170     view->dpy_start = 0;
 171     view->dpy_paragraph_skip_lines = 0;
 172     mcview_state_machine_init (&view->dpy_state_top, 0);
 173     view->dpy_wrap_dirty = FALSE;
 174     view->force_max = -1;
 175     view->dpy_text_column = 0;
 176     view->dpy_end = 0;
 177     view->hex_cursor = 0;
 178     view->cursor_col = 0;
 179     view->cursor_row = 0;
 180     view->change_list = NULL;
 181 
 182     /* {status,ruler,data}_area are left uninitialized */
 183 
 184     view->dirty = 0;
 185     view->dpy_bbar_dirty = TRUE;
 186     view->bytes_per_line = 1;
 187 
 188     view->search_start = 0;
 189     view->search_end = 0;
 190 
 191     view->marker = 0;
 192     for (i = 0; i < G_N_ELEMENTS (view->marks); i++)
 193         view->marks[i] = 0;
 194 
 195     view->update_steps = 0;
 196     view->update_activate = 0;
 197 
 198     view->saved_bookmarks = NULL;
 199 }
 200 
 201 /* --------------------------------------------------------------------------------------------- */
 202 
 203 void
 204 mcview_done (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 205 {
 206     /* Save current file position */
 207     if (mcview_remember_file_position && view->filename_vpath != NULL)
 208     {
 209         save_file_position (view->filename_vpath, -1, 0,
 210                             view->mode_flags.hex ? view->hex_cursor : view->dpy_start,
 211                             view->saved_bookmarks);
 212         view->saved_bookmarks = NULL;
 213     }
 214 
 215     /* Write back the global viewer mode */
 216     mcview_global_flags = view->mode_flags;
 217 
 218     /* Free memory used by the viewer */
 219     /* view->widget needs no destructor */
 220     vfs_path_free (view->filename_vpath);
 221     view->filename_vpath = NULL;
 222     vfs_path_free (view->workdir_vpath);
 223     view->workdir_vpath = NULL;
 224     MC_PTR_FREE (view->command);
 225 
 226     mcview_close_datasource (view);
 227     /* the growing buffer is freed with the datasource */
 228 
 229     coord_cache_free (view->coord_cache);
 230     view->coord_cache = NULL;
 231 
 232     if (view->converter == INVALID_CONV)
 233         view->converter = str_cnv_from_term;
 234 
 235     if (view->converter != str_cnv_from_term)
 236     {
 237         str_close_conv (view->converter);
 238         view->converter = str_cnv_from_term;
 239     }
 240 
 241     mc_search_free (view->search);
 242     view->search = NULL;
 243     MC_PTR_FREE (view->last_search_string);
 244     mcview_nroff_seq_free (&view->search_nroff_seq);
 245     mcview_hexedit_free_change_list (view);
 246 
 247     if (mc_global.mc_run_mode == MC_RUN_VIEWER && view->dir != NULL)
 248     {
 249         /* mcviewer is the owner of file list */
 250         dir_list_free_list (view->dir);
 251         g_free (view->dir);
 252         g_free (view->dir_idx);
 253     }
 254 
 255     view->dir = NULL;
 256 }
 257 
 258 /* --------------------------------------------------------------------------------------------- */
 259 
 260 #ifdef HAVE_CHARSET
 261 void
 262 mcview_set_codeset (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 263 {
 264     const char *cp_id = NULL;
 265 
 266     view->utf8 = TRUE;
 267     cp_id =
 268         get_codepage_id (mc_global.source_codepage >=
 269                          0 ? mc_global.source_codepage : mc_global.display_codepage);
 270     if (cp_id != NULL)
 271     {
 272         GIConv conv;
 273         conv = str_crt_conv_from (cp_id);
 274         if (conv != INVALID_CONV)
 275         {
 276             if (view->converter != str_cnv_from_term)
 277                 str_close_conv (view->converter);
 278             view->converter = conv;
 279         }
 280         view->utf8 = (gboolean) str_isutf8 (cp_id);
 281         view->dpy_wrap_dirty = TRUE;
 282     }
 283 }
 284 
 285 /* --------------------------------------------------------------------------------------------- */
 286 
 287 void
 288 mcview_select_encoding (WView * view)
     /* [previous][next][first][last][top][bottom][index][help]  */
 289 {
 290     if (do_select_codepage ())
 291         mcview_set_codeset (view);
 292 }
 293 #endif /* HAVE_CHARSET */
 294 
 295 /* --------------------------------------------------------------------------------------------- */
 296 
 297 void
 298 mcview_show_error (WView * view, const char *msg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 299 {
 300     if (mcview_is_in_panel (view))
 301         mcview_set_datasource_string (view, msg);
 302     else
 303         message (D_ERROR, MSG_ERROR, "%s", msg);
 304 }
 305 
 306 /* --------------------------------------------------------------------------------------------- */
 307 /** returns index of the first char in the line
 308  * it is constant for all line characters
 309  */
 310 
 311 off_t
 312 mcview_bol (WView * view, off_t current, off_t limit)
     /* [previous][next][first][last][top][bottom][index][help]  */
 313 {
 314     int c;
 315     off_t filesize;
 316     filesize = mcview_get_filesize (view);
 317     if (current <= 0)
 318         return 0;
 319     if (current > filesize)
 320         return filesize;
 321     if (!mcview_get_byte (view, current, &c))
 322         return current;
 323     if (c == '\n')
 324     {
 325         if (!mcview_get_byte (view, current - 1, &c))
 326             return current;
 327         if (c == '\r')
 328             current--;
 329     }
 330     while (current > 0 && current > limit)
 331     {
 332         if (!mcview_get_byte (view, current - 1, &c))
 333             break;
 334         if (c == '\r' || c == '\n')
 335             break;
 336         current--;
 337     }
 338     return current;
 339 }
 340 
 341 /* --------------------------------------------------------------------------------------------- */
 342 /** returns index of last char on line + width EOL
 343  * mcview_eol of the current line == mcview_bol next line
 344  */
 345 
 346 off_t
 347 mcview_eol (WView * view, off_t current)
     /* [previous][next][first][last][top][bottom][index][help]  */
 348 {
 349     int c, prev_ch = 0;
 350 
 351     if (current < 0)
 352         return 0;
 353 
 354     while (TRUE)
 355     {
 356         if (!mcview_get_byte (view, current, &c))
 357             break;
 358         if (c == '\n')
 359         {
 360             current++;
 361             break;
 362         }
 363         else if (prev_ch == '\r')
 364         {
 365             break;
 366         }
 367         current++;
 368         prev_ch = c;
 369     }
 370     return current;
 371 }
 372 
 373 /* --------------------------------------------------------------------------------------------- */
 374 
 375 char *
 376 mcview_get_title (const WDialog * h, size_t len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 377 {
 378     const WView *view = (const WView *) find_widget_type (h, mcview_callback);
 379     const char *modified = view->hexedit_mode && (view->change_list != NULL) ? "(*) " : "    ";
 380     const char *file_label;
 381     const char *view_filename;
 382     char *ret_str;
 383 
 384     view_filename = vfs_path_as_str (view->filename_vpath);
 385 
 386     len -= 4;
 387 
 388     file_label = view_filename != NULL ? view_filename : view->command != NULL ? view->command : "";
 389     file_label = str_term_trim (file_label, len - str_term_width1 (_("View: ")));
 390 
 391     ret_str = g_strconcat (_("View: "), modified, file_label, (char *) NULL);
 392     return ret_str;
 393 }
 394 
 395 /* --------------------------------------------------------------------------------------------- */
 396 
 397 int
 398 mcview_calc_percent (WView * view, off_t p)
     /* [previous][next][first][last][top][bottom][index][help]  */
 399 {
 400     const screen_dimen right = view->status_area.left + view->status_area.width;
 401     const screen_dimen height = view->status_area.height;
 402     off_t filesize;
 403     int percent;
 404 
 405     if (height < 1 || right < 4)
 406         return (-1);
 407     if (mcview_may_still_grow (view))
 408         return (-1);
 409 
 410     filesize = mcview_get_filesize (view);
 411     if (view->mode_flags.hex && filesize > 0)
 412     {
 413         /* p can't be beyond the last char, only over that. Compensate for this. */
 414         filesize--;
 415     }
 416 
 417     if (filesize == 0 || p >= filesize)
 418         percent = 100;
 419     else if (p > (INT_MAX / 100))
 420         percent = p / (filesize / 100);
 421     else
 422         percent = p * 100 / filesize;
 423 
 424     return percent;
 425 }
 426 
 427 /* --------------------------------------------------------------------------------------------- */
 428 
 429 void
 430 mcview_clear_mode_flags (mcview_mode_flags_t * flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 431 {
 432     memset (flags, 0, sizeof (*flags));
 433 }
 434 
 435 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */