diff options
Diffstat (limited to 'src/viewer/internal.h')
-rw-r--r-- | src/viewer/internal.h | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/src/viewer/internal.h b/src/viewer/internal.h new file mode 100644 index 0000000..d6075d8 --- /dev/null +++ b/src/viewer/internal.h @@ -0,0 +1,471 @@ +#ifndef MC__VIEWER_INTERNAL_H +#define MC__VIEWER_INTERNAL_H + +#include <limits.h> /* CHAR_BIT */ +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> + +#include "lib/global.h" + +#include "lib/search.h" +#include "lib/widget.h" +#include "lib/vfs/vfs.h" /* vfs_path_t */ + +#include "src/keymap.h" /* global_keymap_t */ +#include "src/filemanager/dir.h" /* dir_list */ + +#include "mcviewer.h" + +/*** typedefs(not structures) and defined constants **********************************************/ + +#define OFF_T_BITWIDTH ((unsigned int) (sizeof (off_t) * CHAR_BIT - 1)) +#define OFFSETTYPE_MAX (((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1) + +typedef unsigned char byte; + +/*** enums ***************************************************************************************/ + +/* data sources of the view */ +enum view_ds +{ + DS_NONE, /* No data available */ + DS_STDIO_PIPE, /* Data comes from a pipe using popen/pclose */ + DS_VFS_PIPE, /* Data comes from a piped-in VFS file */ + DS_FILE, /* Data comes from a VFS file */ + DS_STRING /* Data comes from a string in memory */ +}; + +enum ccache_type +{ + CCACHE_OFFSET, + CCACHE_LINECOL +}; + +typedef enum +{ + NROFF_TYPE_NONE = 0, + NROFF_TYPE_BOLD = 1, + NROFF_TYPE_UNDERLINE = 2 +} nroff_type_t; + +/*** structures declarations (and typedefs of structures)*****************************************/ + +/* A node for building a change list on change_list */ +struct hexedit_change_node +{ + struct hexedit_change_node *next; + off_t offset; + byte value; +}; + +/* A cache entry for mapping offsets into line/column pairs and vice versa. + * cc_offset, cc_line, and cc_column are the 0-based values of the offset, + * line and column of that cache entry. cc_nroff_column is the column + * corresponding to cc_offset in nroff mode. + */ +typedef struct +{ + off_t cc_offset; + off_t cc_line; + off_t cc_column; + off_t cc_nroff_column; +} coord_cache_entry_t; + +/* TODO: find a better name. This is not actually a "state machine", + * but a "state machine's state", but that sounds silly. + * Could be parser_state, formatter_state... */ +typedef struct +{ + off_t offset; /* The file offset at which this is the state. */ + off_t unwrapped_column; /* Columns if the paragraph wasn't wrapped, */ + /* used for positioning TABs in wrapped lines */ + gboolean nroff_underscore_is_underlined; /* whether _\b_ is underlined rather than bold */ + gboolean print_lonely_combining; /* whether lonely combining marks are printed on a dotted circle */ +} mcview_state_machine_t; + +struct mcview_nroff_struct; + +struct WView +{ + Widget widget; + + vfs_path_t *filename_vpath; /* Name of the file */ + vfs_path_t *workdir_vpath; /* Name of the working directory */ + char *command; /* Command used to pipe data in */ + + enum view_ds datasource; /* Where the displayed data comes from */ + + /* stdio pipe data source */ + mc_pipe_t *ds_stdio_pipe; /* Output of a shell command */ + gboolean pipe_first_err_msg; /* Show only 1st message from stderr */ + + /* vfs pipe data source */ + int ds_vfs_pipe; /* Non-seekable vfs file descriptor */ + + /* vfs file data source */ + int ds_file_fd; /* File with random access */ + off_t ds_file_filesize; /* Size of the file */ + off_t ds_file_offset; /* Offset of the currently loaded data */ + byte *ds_file_data; /* Currently loaded data */ + size_t ds_file_datalen; /* Number of valid bytes in file_data */ + size_t ds_file_datasize; /* Number of allocated bytes in file_data */ + + /* string data source */ + byte *ds_string_data; /* The characters of the string */ + size_t ds_string_len; /* The length of the string */ + + /* Growing buffers information */ + gboolean growbuf_in_use; /* Use the growing buffers? */ + GPtrArray *growbuf_blockptr; /* Pointer to the block pointers */ + size_t growbuf_lastindex; /* Number of bytes in the last page of the + growing buffer */ + gboolean growbuf_finished; /* TRUE when all data has been read. */ + + mcview_mode_flags_t mode_flags; + + /* Hex editor modes */ + gboolean hexedit_mode; /* Hexview or Hexedit */ + const global_keymap_t *hex_keymap; + gboolean hexview_in_text; /* Is the hexview cursor in the text area? */ + int bytes_per_line; /* Number of bytes per line in hex mode */ + off_t hex_cursor; /* Hexview cursor position in file */ + gboolean hexedit_lownibble; /* Are we editing the last significant nibble? */ + gboolean locked; /* We hold lock on current file */ + +#ifdef HAVE_CHARSET + gboolean utf8; /* It's multibyte file codeset */ +#endif + + GPtrArray *coord_cache; /* Cache for mapping offsets to cursor positions */ + + /* Display information */ + int dpy_frame_size; /* Size of the frame surrounding the real viewer */ + off_t dpy_start; /* Offset of the displayed data (start of the paragraph in non-hex mode) */ + off_t dpy_end; /* Offset after the displayed data */ + off_t dpy_paragraph_skip_lines; /* Extra lines to skip in wrap mode */ + mcview_state_machine_t dpy_state_top; /* Parser-formatter state at the topmost visible line in wrap mode */ + mcview_state_machine_t dpy_state_bottom; /* Parser-formatter state after the bottomvisible line in wrap mode */ + gboolean dpy_wrap_dirty; /* dpy_state_top needs to be recomputed */ + off_t dpy_text_column; /* Number of skipped columns in non-wrap + * text mode */ + int cursor_col; /* Cursor column */ + int cursor_row; /* Cursor row */ + struct hexedit_change_node *change_list; /* Linked list of changes */ + WRect status_area; /* Where the status line is displayed */ + WRect ruler_area; /* Where the ruler is displayed */ + WRect data_area; /* Where the data is displayed */ + + ssize_t force_max; /* Force a max offset, or -1 */ + + int dirty; /* Number of skipped updates */ + gboolean dpy_bbar_dirty; /* Does the button bar need to be updated? */ + + + /* handle of search engine */ + mc_search_t *search; + gchar *last_search_string; + struct mcview_nroff_struct *search_nroff_seq; + off_t search_start; /* First character to start searching from */ + off_t search_end; /* Length of found string or 0 if none was found */ + int search_numNeedSkipChar; + + /* Markers */ + int marker; /* mark to use */ + off_t marks[10]; /* 10 marks: 0..9 */ + + off_t update_steps; /* The number of bytes between percent increments */ + off_t update_activate; /* Last point where we updated the status */ + + /* converter for translation of text */ + GIConv converter; + + GArray *saved_bookmarks; + + dir_list *dir; /* List of current directory files + * to handle CK_FileNext and CK_FilePrev commands */ + int *dir_idx; /* Index of current file in dir structure. + * Pointer is used here as reference to WPanel::dir::count */ + vfs_path_t *ext_script; /* Temporary script file created by regex_command_for() */ +}; + +typedef struct mcview_nroff_struct +{ + WView *view; + off_t index; + int char_length; + int current_char; + nroff_type_t type; + nroff_type_t prev_type; +} mcview_nroff_t; + +typedef struct mcview_search_options_t +{ + mc_search_type_t type; + gboolean case_sens; + gboolean backwards; + gboolean whole_words; + gboolean all_codepages; +} mcview_search_options_t; + +/*** global variables defined in .c file *********************************************************/ + +extern mcview_search_options_t mcview_search_options; + +/*** declarations of public functions ************************************************************/ + +/* actions_cmd.c: */ +cb_ret_t mcview_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data); +cb_ret_t mcview_dialog_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, + void *data); + +/* ascii.c: */ +void mcview_display_text (WView * view); +void mcview_state_machine_init (mcview_state_machine_t *, off_t); +void mcview_ascii_move_down (WView * view, off_t lines); +void mcview_ascii_move_up (WView * view, off_t lines); +void mcview_ascii_moveto_bol (WView * view); +void mcview_ascii_moveto_eol (WView * view); + +#ifdef MC_ENABLE_DEBUGGING_CODE +void mcview_ccache_dump (WView * view); +#endif + +void mcview_ccache_lookup (WView * view, coord_cache_entry_t * coord, enum ccache_type lookup_what); + +/* datasource.c: */ +void mcview_set_datasource_none (WView * view); +off_t mcview_get_filesize (WView * view); +void mcview_update_filesize (WView * view); +char *mcview_get_ptr_file (WView * view, off_t byte_index); +char *mcview_get_ptr_string (WView * view, off_t byte_index); +gboolean mcview_get_utf (WView * view, off_t byte_index, int *ch, int *ch_len); +gboolean mcview_get_byte_string (WView * view, off_t byte_index, int *retval); +gboolean mcview_get_byte_none (WView * view, off_t byte_index, int *retval); +void mcview_set_byte (WView * view, off_t offset, byte b); +void mcview_file_load_data (WView * view, off_t byte_index); +void mcview_close_datasource (WView * view); +void mcview_set_datasource_file (WView * view, int fd, const struct stat *st); +gboolean mcview_load_command_output (WView * view, const char *command); +void mcview_set_datasource_vfs_pipe (WView * view, int fd); +void mcview_set_datasource_string (WView * view, const char *s); + +/* dialog.c: */ +gboolean mcview_dialog_search (WView * view); +gboolean mcview_dialog_goto (WView * view, off_t * offset); + +/* display.c: */ +void mcview_update (WView * view); +void mcview_display (WView * view); +void mcview_compute_areas (WView * view); +void mcview_update_bytes_per_line (WView * view); +void mcview_display_toggle_ruler (WView * view); +void mcview_display_clean (WView * view); +void mcview_display_ruler (WView * view); + +/* growbuf.c: */ +void mcview_growbuf_init (WView * view); +void mcview_growbuf_done (WView * view); +void mcview_growbuf_free (WView * view); +off_t mcview_growbuf_filesize (WView * view); +void mcview_growbuf_read_until (WView * view, off_t ofs); +gboolean mcview_get_byte_growing_buffer (WView * view, off_t byte_index, int *retval); +char *mcview_get_ptr_growing_buffer (WView * view, off_t byte_index); + +/* hex.c: */ +void mcview_display_hex (WView * view); +gboolean mcview_hexedit_save_changes (WView * view); +void mcview_toggle_hexedit_mode (WView * view); +void mcview_hexedit_free_change_list (WView * view); +void mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node); + +/* lib.c: */ +void mcview_toggle_magic_mode (WView * view); +void mcview_toggle_wrap_mode (WView * view); +void mcview_toggle_nroff_mode (WView * view); +void mcview_toggle_hex_mode (WView * view); +void mcview_init (WView * view); +void mcview_done (WView * view); +#ifdef HAVE_CHARSET +void mcview_select_encoding (WView * view); +void mcview_set_codeset (WView * view); +#endif +void mcview_show_error (WView * view, const char *error); +off_t mcview_bol (WView * view, off_t current, off_t limit); +off_t mcview_eol (WView * view, off_t current); +char *mcview_get_title (const WDialog * h, size_t len); +int mcview_calc_percent (WView * view, off_t p); + +/* move.c */ +void mcview_move_up (WView * view, off_t lines); +void mcview_move_down (WView * view, off_t lines); +void mcview_move_left (WView * view, off_t columns); +void mcview_move_right (WView * view, off_t columns); +void mcview_moveto_top (WView * view); +void mcview_moveto_bottom (WView * view); +void mcview_moveto_bol (WView * view); +void mcview_moveto_eol (WView * view); +void mcview_moveto_offset (WView * view, off_t offset); +void mcview_moveto (WView * view, off_t, off_t col); +void mcview_coord_to_offset (WView * view, off_t * ret_offset, off_t line, off_t column); +void mcview_offset_to_coord (WView * view, off_t * ret_line, off_t * ret_column, off_t offset); +void mcview_place_cursor (WView * view); +void mcview_moveto_match (WView * view); + +/* nroff.c: */ +int mcview__get_nroff_real_len (WView * view, off_t start, off_t length); +mcview_nroff_t *mcview_nroff_seq_new_num (WView * view, off_t lc_index); +mcview_nroff_t *mcview_nroff_seq_new (WView * view); +void mcview_nroff_seq_free (mcview_nroff_t ** nroff); +nroff_type_t mcview_nroff_seq_info (mcview_nroff_t * nroff); +int mcview_nroff_seq_next (mcview_nroff_t * nroff); +int mcview_nroff_seq_prev (mcview_nroff_t * nroff); + +/* search.c: */ +gboolean mcview_search_init (WView * view); +void mcview_search_deinit (WView * view); +mc_search_cbret_t mcview_search_cmd_callback (const void *user_data, gsize char_offset, + int *current_char); +mc_search_cbret_t mcview_search_update_cmd_callback (const void *user_data, gsize char_offset); +void mcview_do_search (WView * view, off_t want_search_start); + +/* --------------------------------------------------------------------------------------------- */ +/*** inline functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +static inline off_t +mcview_offset_rounddown (off_t a, off_t b) +{ + g_assert (b != 0); + return a - a % b; +} + +/* --------------------------------------------------------------------------------------------- */ + +/* {{{ Simple Primitive Functions for WView }}} */ +static inline gboolean +mcview_is_in_panel (WView * view) +{ + return (view->dpy_frame_size != 0); +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline gboolean +mcview_may_still_grow (WView * view) +{ + return (view->growbuf_in_use && !view->growbuf_finished); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* returns TRUE if the idx lies in the half-open interval + * [offset; offset + size), FALSE otherwise. + */ +static inline gboolean +mcview_already_loaded (off_t offset, off_t idx, size_t size) +{ + return (offset <= idx && idx - offset < (off_t) size); +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline gboolean +mcview_get_byte_file (WView * view, off_t byte_index, int *retval) +{ + g_assert (view->datasource == DS_FILE); + + mcview_file_load_data (view, byte_index); + if (mcview_already_loaded (view->ds_file_offset, byte_index, view->ds_file_datalen)) + { + if (retval) + *retval = view->ds_file_data[byte_index - view->ds_file_offset]; + return TRUE; + } + if (retval) + *retval = -1; + return FALSE; +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline gboolean +mcview_get_byte (WView * view, off_t offset, int *retval) +{ + switch (view->datasource) + { + case DS_STDIO_PIPE: + case DS_VFS_PIPE: + return mcview_get_byte_growing_buffer (view, offset, retval); + case DS_FILE: + return mcview_get_byte_file (view, offset, retval); + case DS_STRING: + return mcview_get_byte_string (view, offset, retval); + case DS_NONE: + return mcview_get_byte_none (view, offset, retval); + default: + return FALSE; + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline gboolean +mcview_get_byte_indexed (WView * view, off_t base, off_t ofs, int *retval) +{ + if (base <= OFFSETTYPE_MAX - ofs) + return mcview_get_byte (view, base + ofs, retval); + + if (retval != NULL) + *retval = -1; + + return FALSE; +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline int +mcview_count_backspaces (WView * view, off_t offset) +{ + int backspaces = 0; + int c; + + while (offset >= 2 * backspaces && mcview_get_byte (view, offset - 2 * backspaces, &c) + && c == '\b') + backspaces++; + + return backspaces; +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline gboolean +mcview_is_nroff_sequence (WView * view, off_t offset) +{ + int c0, c1, c2; + + /* The following commands are ordered to speed up the calculation. */ + + if (!mcview_get_byte_indexed (view, offset, 1, &c1) || c1 != '\b') + return FALSE; + + if (!mcview_get_byte_indexed (view, offset, 0, &c0) || !g_ascii_isprint (c0)) + return FALSE; + + if (!mcview_get_byte_indexed (view, offset, 2, &c2) || !g_ascii_isprint (c2)) + return FALSE; + + return (c0 == c2 || c0 == '_' || (c0 == '+' && c2 == 'o')); +} + +/* --------------------------------------------------------------------------------------------- */ + +static inline void +mcview_growbuf_read_all_data (WView * view) +{ + mcview_growbuf_read_until (view, OFFSETTYPE_MAX); +} + +/* --------------------------------------------------------------------------------------------- */ + +#endif /* MC__VIEWER_INTERNAL_H */ |