(filevercmp): make inline.
[midnight-commander.git] / src / viewer / internal.h
blobdbbf984272257ac32b13f7ad7c45305f896703ea
1 #ifndef MC__VIEWER_INTERNAL_H
2 #define MC__VIEWER_INTERNAL_H
4 #include <limits.h> /* CHAR_BIT */
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <sys/types.h>
9 #include "lib/global.h"
11 #include "lib/search.h"
12 #include "lib/widget.h"
13 #include "lib/vfs/vfs.h" /* vfs_path_t */
14 #include "lib/util.h" /* mc_pipe_t */
16 #include "src/keymap.h" /* global_keymap_t */
17 #include "src/filemanager/dir.h" /* dir_list */
19 #include "mcviewer.h"
21 /*** typedefs(not structures) and defined constants **********************************************/
23 #define OFF_T_BITWIDTH ((unsigned int) (sizeof (off_t) * CHAR_BIT - 1))
24 #define OFFSETTYPE_MAX (((off_t) 1 << (OFF_T_BITWIDTH - 1)) - 1)
26 typedef unsigned char byte;
28 /*** enums ***************************************************************************************/
30 /* data sources of the view */
31 enum view_ds
33 DS_NONE, /* No data available */
34 DS_STDIO_PIPE, /* Data comes from a pipe using popen/pclose */
35 DS_VFS_PIPE, /* Data comes from a piped-in VFS file */
36 DS_FILE, /* Data comes from a VFS file */
37 DS_STRING /* Data comes from a string in memory */
40 enum ccache_type
42 CCACHE_OFFSET,
43 CCACHE_LINECOL
46 typedef enum
48 NROFF_TYPE_NONE = 0,
49 NROFF_TYPE_BOLD = 1,
50 NROFF_TYPE_UNDERLINE = 2
51 } nroff_type_t;
53 /*** structures declarations (and typedefs of structures)*****************************************/
55 /* A node for building a change list on change_list */
56 struct hexedit_change_node
58 struct hexedit_change_node *next;
59 off_t offset;
60 byte value;
63 /* A cache entry for mapping offsets into line/column pairs and vice versa.
64 * cc_offset, cc_line, and cc_column are the 0-based values of the offset,
65 * line and column of that cache entry. cc_nroff_column is the column
66 * corresponding to cc_offset in nroff mode.
68 typedef struct
70 off_t cc_offset;
71 off_t cc_line;
72 off_t cc_column;
73 off_t cc_nroff_column;
74 } coord_cache_entry_t;
76 /* TODO: find a better name. This is not actually a "state machine",
77 * but a "state machine's state", but that sounds silly.
78 * Could be parser_state, formatter_state... */
79 typedef struct
81 off_t offset; /* The file offset at which this is the state. */
82 off_t unwrapped_column; /* Columns if the paragraph wasn't wrapped, */
83 /* used for positioning TABs in wrapped lines */
84 gboolean nroff_underscore_is_underlined; /* whether _\b_ is underlined rather than bold */
85 gboolean print_lonely_combining; /* whether lonely combining marks are printed on a dotted circle */
86 } mcview_state_machine_t;
88 struct mcview_nroff_struct;
90 struct WView
92 Widget widget;
94 vfs_path_t *filename_vpath; /* Name of the file */
95 vfs_path_t *workdir_vpath; /* Name of the working directory */
96 char *command; /* Command used to pipe data in */
98 enum view_ds datasource; /* Where the displayed data comes from */
100 /* stdio pipe data source */
101 mc_pipe_t *ds_stdio_pipe; /* Output of a shell command */
102 gboolean pipe_first_err_msg; /* Show only 1st message from stderr */
104 /* vfs pipe data source */
105 int ds_vfs_pipe; /* Non-seekable vfs file descriptor */
107 /* vfs file data source */
108 int ds_file_fd; /* File with random access */
109 off_t ds_file_filesize; /* Size of the file */
110 off_t ds_file_offset; /* Offset of the currently loaded data */
111 byte *ds_file_data; /* Currently loaded data */
112 size_t ds_file_datalen; /* Number of valid bytes in file_data */
113 size_t ds_file_datasize; /* Number of allocated bytes in file_data */
115 /* string data source */
116 byte *ds_string_data; /* The characters of the string */
117 size_t ds_string_len; /* The length of the string */
119 /* Growing buffers information */
120 gboolean growbuf_in_use; /* Use the growing buffers? */
121 GPtrArray *growbuf_blockptr; /* Pointer to the block pointers */
122 size_t growbuf_lastindex; /* Number of bytes in the last page of the
123 growing buffer */
124 gboolean growbuf_finished; /* TRUE when all data has been read. */
126 mcview_mode_flags_t mode_flags;
128 /* Hex editor modes */
129 gboolean hexedit_mode; /* Hexview or Hexedit */
130 const global_keymap_t *hex_keymap;
131 gboolean hexview_in_text; /* Is the hexview cursor in the text area? */
132 int bytes_per_line; /* Number of bytes per line in hex mode */
133 off_t hex_cursor; /* Hexview cursor position in file */
134 gboolean hexedit_lownibble; /* Are we editing the last significant nibble? */
135 gboolean locked; /* We hold lock on current file */
137 #ifdef HAVE_CHARSET
138 gboolean utf8; /* It's multibyte file codeset */
139 #endif
141 GPtrArray *coord_cache; /* Cache for mapping offsets to cursor positions */
143 /* Display information */
144 int dpy_frame_size; /* Size of the frame surrounding the real viewer */
145 off_t dpy_start; /* Offset of the displayed data (start of the paragraph in non-hex mode) */
146 off_t dpy_end; /* Offset after the displayed data */
147 off_t dpy_paragraph_skip_lines; /* Extra lines to skip in wrap mode */
148 mcview_state_machine_t dpy_state_top; /* Parser-formatter state at the topmost visible line in wrap mode */
149 mcview_state_machine_t dpy_state_bottom; /* Parser-formatter state after the bottomvisible line in wrap mode */
150 gboolean dpy_wrap_dirty; /* dpy_state_top needs to be recomputed */
151 off_t dpy_text_column; /* Number of skipped columns in non-wrap
152 * text mode */
153 int cursor_col; /* Cursor column */
154 int cursor_row; /* Cursor row */
155 struct hexedit_change_node *change_list; /* Linked list of changes */
156 WRect status_area; /* Where the status line is displayed */
157 WRect ruler_area; /* Where the ruler is displayed */
158 WRect data_area; /* Where the data is displayed */
160 ssize_t force_max; /* Force a max offset, or -1 */
162 int dirty; /* Number of skipped updates */
163 gboolean dpy_bbar_dirty; /* Does the button bar need to be updated? */
166 /* handle of search engine */
167 mc_search_t *search;
168 gchar *last_search_string;
169 struct mcview_nroff_struct *search_nroff_seq;
170 off_t search_start; /* First character to start searching from */
171 off_t search_end; /* Length of found string or 0 if none was found */
172 int search_numNeedSkipChar;
174 /* Markers */
175 int marker; /* mark to use */
176 off_t marks[10]; /* 10 marks: 0..9 */
178 off_t update_steps; /* The number of bytes between percent increments */
179 off_t update_activate; /* Last point where we updated the status */
181 /* converter for translation of text */
182 GIConv converter;
184 GArray *saved_bookmarks;
186 dir_list *dir; /* List of current directory files
187 * to handle CK_FileNext and CK_FilePrev commands */
188 int *dir_idx; /* Index of current file in dir structure.
189 * Pointer is used here as reference to WPanel::dir::count */
190 vfs_path_t *ext_script; /* Temporary script file created by regex_command_for() */
193 typedef struct mcview_nroff_struct
195 WView *view;
196 off_t index;
197 int char_length;
198 int current_char;
199 nroff_type_t type;
200 nroff_type_t prev_type;
201 } mcview_nroff_t;
203 typedef struct mcview_search_options_t
205 mc_search_type_t type;
206 gboolean case_sens;
207 gboolean backwards;
208 gboolean whole_words;
209 gboolean all_codepages;
210 } mcview_search_options_t;
212 /*** global variables defined in .c file *********************************************************/
214 extern mcview_search_options_t mcview_search_options;
216 /*** declarations of public functions ************************************************************/
218 /* actions_cmd.c: */
219 cb_ret_t mcview_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data);
220 cb_ret_t mcview_dialog_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
221 void *data);
223 /* ascii.c: */
224 void mcview_display_text (WView * view);
225 void mcview_state_machine_init (mcview_state_machine_t *, off_t);
226 void mcview_ascii_move_down (WView * view, off_t lines);
227 void mcview_ascii_move_up (WView * view, off_t lines);
228 void mcview_ascii_moveto_bol (WView * view);
229 void mcview_ascii_moveto_eol (WView * view);
231 #ifdef MC_ENABLE_DEBUGGING_CODE
232 void mcview_ccache_dump (WView * view);
233 #endif
235 void mcview_ccache_lookup (WView * view, coord_cache_entry_t * coord, enum ccache_type lookup_what);
237 /* datasource.c: */
238 void mcview_set_datasource_none (WView * view);
239 off_t mcview_get_filesize (WView * view);
240 void mcview_update_filesize (WView * view);
241 char *mcview_get_ptr_file (WView * view, off_t byte_index);
242 char *mcview_get_ptr_string (WView * view, off_t byte_index);
243 gboolean mcview_get_utf (WView * view, off_t byte_index, int *ch, int *ch_len);
244 gboolean mcview_get_byte_string (WView * view, off_t byte_index, int *retval);
245 gboolean mcview_get_byte_none (WView * view, off_t byte_index, int *retval);
246 void mcview_set_byte (WView * view, off_t offset, byte b);
247 void mcview_file_load_data (WView * view, off_t byte_index);
248 void mcview_close_datasource (WView * view);
249 void mcview_set_datasource_file (WView * view, int fd, const struct stat *st);
250 gboolean mcview_load_command_output (WView * view, const char *command);
251 void mcview_set_datasource_vfs_pipe (WView * view, int fd);
252 void mcview_set_datasource_string (WView * view, const char *s);
254 /* dialog.c: */
255 gboolean mcview_dialog_search (WView * view);
256 gboolean mcview_dialog_goto (WView * view, off_t * offset);
258 /* display.c: */
259 void mcview_update (WView * view);
260 void mcview_display (WView * view);
261 void mcview_compute_areas (WView * view);
262 void mcview_update_bytes_per_line (WView * view);
263 void mcview_display_toggle_ruler (WView * view);
264 void mcview_display_clean (WView * view);
265 void mcview_display_ruler (WView * view);
267 /* growbuf.c: */
268 void mcview_growbuf_init (WView * view);
269 void mcview_growbuf_done (WView * view);
270 void mcview_growbuf_free (WView * view);
271 off_t mcview_growbuf_filesize (WView * view);
272 void mcview_growbuf_read_until (WView * view, off_t ofs);
273 gboolean mcview_get_byte_growing_buffer (WView * view, off_t byte_index, int *retval);
274 char *mcview_get_ptr_growing_buffer (WView * view, off_t byte_index);
276 /* hex.c: */
277 void mcview_display_hex (WView * view);
278 gboolean mcview_hexedit_save_changes (WView * view);
279 void mcview_toggle_hexedit_mode (WView * view);
280 void mcview_hexedit_free_change_list (WView * view);
281 void mcview_enqueue_change (struct hexedit_change_node **head, struct hexedit_change_node *node);
283 /* lib.c: */
284 void mcview_toggle_magic_mode (WView * view);
285 void mcview_toggle_wrap_mode (WView * view);
286 void mcview_toggle_nroff_mode (WView * view);
287 void mcview_toggle_hex_mode (WView * view);
288 void mcview_init (WView * view);
289 void mcview_done (WView * view);
290 #ifdef HAVE_CHARSET
291 void mcview_select_encoding (WView * view);
292 void mcview_set_codeset (WView * view);
293 #endif
294 void mcview_show_error (WView * view, const char *error);
295 off_t mcview_bol (WView * view, off_t current, off_t limit);
296 off_t mcview_eol (WView * view, off_t current);
297 char *mcview_get_title (const WDialog * h, size_t len);
298 int mcview_calc_percent (WView * view, off_t p);
300 /* move.c */
301 void mcview_move_up (WView * view, off_t lines);
302 void mcview_move_down (WView * view, off_t lines);
303 void mcview_move_left (WView * view, off_t columns);
304 void mcview_move_right (WView * view, off_t columns);
305 void mcview_moveto_top (WView * view);
306 void mcview_moveto_bottom (WView * view);
307 void mcview_moveto_bol (WView * view);
308 void mcview_moveto_eol (WView * view);
309 void mcview_moveto_offset (WView * view, off_t offset);
310 void mcview_moveto (WView * view, off_t, off_t col);
311 void mcview_coord_to_offset (WView * view, off_t * ret_offset, off_t line, off_t column);
312 void mcview_offset_to_coord (WView * view, off_t * ret_line, off_t * ret_column, off_t offset);
313 void mcview_place_cursor (WView * view);
314 void mcview_moveto_match (WView * view);
316 /* nroff.c: */
317 int mcview__get_nroff_real_len (WView * view, off_t start, off_t length);
318 mcview_nroff_t *mcview_nroff_seq_new_num (WView * view, off_t lc_index);
319 mcview_nroff_t *mcview_nroff_seq_new (WView * view);
320 void mcview_nroff_seq_free (mcview_nroff_t ** nroff);
321 nroff_type_t mcview_nroff_seq_info (mcview_nroff_t * nroff);
322 int mcview_nroff_seq_next (mcview_nroff_t * nroff);
323 int mcview_nroff_seq_prev (mcview_nroff_t * nroff);
325 /* search.c: */
326 gboolean mcview_search_init (WView * view);
327 void mcview_search_deinit (WView * view);
328 mc_search_cbret_t mcview_search_cmd_callback (const void *user_data, gsize char_offset,
329 int *current_char);
330 mc_search_cbret_t mcview_search_update_cmd_callback (const void *user_data, gsize char_offset);
331 void mcview_do_search (WView * view, off_t want_search_start);
333 /* --------------------------------------------------------------------------------------------- */
334 /*** inline functions ****************************************************************************/
335 /* --------------------------------------------------------------------------------------------- */
337 static inline off_t
338 mcview_offset_rounddown (off_t a, off_t b)
340 g_assert (b != 0);
341 return a - a % b;
344 /* --------------------------------------------------------------------------------------------- */
346 /* {{{ Simple Primitive Functions for WView }}} */
347 static inline gboolean
348 mcview_is_in_panel (WView *view)
350 return (view->dpy_frame_size != 0);
353 /* --------------------------------------------------------------------------------------------- */
355 static inline gboolean
356 mcview_may_still_grow (WView *view)
358 return (view->growbuf_in_use && !view->growbuf_finished);
361 /* --------------------------------------------------------------------------------------------- */
363 /* returns TRUE if the idx lies in the half-open interval
364 * [offset; offset + size), FALSE otherwise.
366 static inline gboolean
367 mcview_already_loaded (off_t offset, off_t idx, size_t size)
369 return (offset <= idx && idx - offset < (off_t) size);
372 /* --------------------------------------------------------------------------------------------- */
374 static inline gboolean
375 mcview_get_byte_file (WView *view, off_t byte_index, int *retval)
377 g_assert (view->datasource == DS_FILE);
379 mcview_file_load_data (view, byte_index);
380 if (mcview_already_loaded (view->ds_file_offset, byte_index, view->ds_file_datalen))
382 if (retval)
383 *retval = view->ds_file_data[byte_index - view->ds_file_offset];
384 return TRUE;
386 if (retval)
387 *retval = -1;
388 return FALSE;
391 /* --------------------------------------------------------------------------------------------- */
393 static inline gboolean
394 mcview_get_byte (WView *view, off_t offset, int *retval)
396 switch (view->datasource)
398 case DS_STDIO_PIPE:
399 case DS_VFS_PIPE:
400 return mcview_get_byte_growing_buffer (view, offset, retval);
401 case DS_FILE:
402 return mcview_get_byte_file (view, offset, retval);
403 case DS_STRING:
404 return mcview_get_byte_string (view, offset, retval);
405 case DS_NONE:
406 return mcview_get_byte_none (view, offset, retval);
407 default:
408 return FALSE;
412 /* --------------------------------------------------------------------------------------------- */
414 static inline gboolean
415 mcview_get_byte_indexed (WView *view, off_t base, off_t ofs, int *retval)
417 if (base <= OFFSETTYPE_MAX - ofs)
418 return mcview_get_byte (view, base + ofs, retval);
420 if (retval != NULL)
421 *retval = -1;
423 return FALSE;
426 /* --------------------------------------------------------------------------------------------- */
428 static inline int
429 mcview_count_backspaces (WView *view, off_t offset)
431 int backspaces = 0;
432 int c;
434 while (offset >= 2 * backspaces && mcview_get_byte (view, offset - 2 * backspaces, &c)
435 && c == '\b')
436 backspaces++;
438 return backspaces;
441 /* --------------------------------------------------------------------------------------------- */
443 static inline gboolean
444 mcview_is_nroff_sequence (WView *view, off_t offset)
446 int c0, c1, c2;
448 /* The following commands are ordered to speed up the calculation. */
450 if (!mcview_get_byte_indexed (view, offset, 1, &c1) || c1 != '\b')
451 return FALSE;
453 if (!mcview_get_byte_indexed (view, offset, 0, &c0) || !g_ascii_isprint (c0))
454 return FALSE;
456 if (!mcview_get_byte_indexed (view, offset, 2, &c2) || !g_ascii_isprint (c2))
457 return FALSE;
459 return (c0 == c2 || c0 == '_' || (c0 == '+' && c2 == 'o'));
462 /* --------------------------------------------------------------------------------------------- */
464 static inline void
465 mcview_growbuf_read_all_data (WView *view)
467 mcview_growbuf_read_until (view, OFFSETTYPE_MAX);
470 /* --------------------------------------------------------------------------------------------- */
472 #endif /* MC__VIEWER_INTERNAL_H */