Split file src/keybind.[ch] to lib/keybind.[ch] and src/keybind-defaults.[ch].
[midnight-commander.git] / src / viewer / nroff.c
blob60168d159efc8b876983d1462a70969d7730d0b3
1 /*
2 Internal file viewer for the Midnight Commander
3 Function for nroff-like view
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
10 1995 Jakub Jelinek
11 1996 Joseph M. Hinkle
12 1997 Norbert Warmuth
13 1998 Pavel Machek
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 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,
35 MA 02110-1301, USA.
38 #include <config.h>
40 #include "lib/global.h"
41 #include "lib/tty/tty.h"
42 #include "lib/skin.h"
43 #include "lib/charsets.h"
45 #include "src/main.h" /* utf8_display */
46 #include "src/setup.h" /* option_tab_spacing */
48 #include "internal.h"
50 /*** global variables ****************************************************************************/
52 /*** file scope macro definitions ****************************************************************/
54 /*** file scope type declarations ****************************************************************/
56 /*** file scope variables ************************************************************************/
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
61 /* --------------------------------------------------------------------------------------------- */
62 /*** public functions ****************************************************************************/
63 /* --------------------------------------------------------------------------------------------- */
65 void
66 mcview_display_nroff (mcview_t * view)
68 const screen_dimen left = view->data_area.left;
69 const screen_dimen top = view->data_area.top;
70 const screen_dimen width = view->data_area.width;
71 const screen_dimen height = view->data_area.height;
72 screen_dimen row, col;
73 off_t from;
74 int cw = 1;
75 int c;
76 int c_prev = 0;
77 int c_next = 0;
78 struct hexedit_change_node *curr = view->change_list;
80 mcview_display_clean (view);
81 mcview_display_ruler (view);
83 /* Find the first displayable changed byte */
84 from = view->dpy_start;
85 while (curr && (curr->offset < from))
87 curr = curr->next;
90 tty_setcolor (NORMAL_COLOR);
91 for (row = 0, col = 0; row < height;)
93 #ifdef HAVE_CHARSET
94 if (view->utf8)
96 gboolean read_res = TRUE;
97 c = mcview_get_utf (view, from, &cw, &read_res);
98 if (!read_res)
99 break;
101 else
102 #endif
104 if (!mcview_get_byte (view, from, &c))
105 break;
107 from++;
108 if (cw > 1)
109 from += cw - 1;
111 if (c == '\b')
113 if (from > 1)
115 mcview_get_byte (view, from - 2, &c_prev);
116 mcview_get_byte (view, from, &c_next);
118 if (g_ascii_isprint (c_prev) && g_ascii_isprint (c_prev)
119 && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o')))
121 if (col == 0)
123 if (row == 0)
125 /* We're inside an nroff character sequence at the
126 * beginning of the screen -- just skip the
127 * backspace and continue with the next character. */
128 continue;
130 row--;
131 col = width;
133 col--;
134 if (c_prev == '_'
135 && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
136 tty_setcolor (VIEW_UNDERLINED_COLOR);
137 else
138 tty_setcolor (VIEW_BOLD_COLOR);
139 continue;
143 if ((c == '\n') || (col >= width && view->text_wrap_mode))
145 col = 0;
146 row++;
147 if (c == '\n' || row >= height)
148 continue;
151 if (c == '\r')
153 mcview_get_byte_indexed (view, from, 1, &c);
154 if (c == '\r' || c == '\n')
155 continue;
156 col = 0;
157 row++;
158 continue;
161 if (c == '\t')
163 off_t line, column;
164 mcview_offset_to_coord (view, &line, &column, from);
165 col += (option_tab_spacing - col % option_tab_spacing);
166 if (view->text_wrap_mode && col >= width && width != 0)
168 row += col / width;
169 col %= width;
171 continue;
174 if (view->search_start <= from && from < view->search_end)
176 tty_setcolor (SELECTED_COLOR);
179 if ((off_t) col >= view->dpy_text_column
180 && (off_t) col - view->dpy_text_column < (off_t) width)
182 widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column));
183 #ifdef HAVE_CHARSET
184 if (utf8_display)
186 if (!view->utf8)
188 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
190 if (!g_unichar_isprint (c))
191 c = '.';
193 else
195 if (view->utf8)
197 c = convert_from_utf_to_current_c (c, view->converter);
199 else
201 #endif
202 c = convert_to_display_c (c);
203 #ifdef HAVE_CHARSET
206 #endif
207 tty_print_anychar (c);
209 col++;
210 #ifdef HAVE_CHARSET
211 if (view->utf8)
213 if (g_unichar_iswide (c))
214 col++;
215 else if (g_unichar_iszerowidth (c))
216 col--;
218 #endif
219 tty_setcolor (NORMAL_COLOR);
221 view->dpy_end = from;
224 /* --------------------------------------------------------------------------------------------- */
227 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
229 mcview_nroff_t *nroff;
230 int ret = 0;
231 off_t i = 0;
233 nroff = mcview_nroff_seq_new_num (view, start);
234 if (nroff == NULL)
235 return 0;
237 while (i < length)
239 if (nroff->type != NROFF_TYPE_NONE)
241 ret += 2;
243 i++;
244 mcview_nroff_seq_next (nroff);
247 mcview_nroff_seq_free (&nroff);
248 return ret;
251 /* --------------------------------------------------------------------------------------------- */
253 mcview_nroff_t *
254 mcview_nroff_seq_new_num (mcview_t * view, off_t lc_index)
256 mcview_nroff_t *nroff;
258 nroff = g_try_malloc0 (sizeof (mcview_nroff_t));
259 if (nroff != NULL)
261 nroff->index = lc_index;
262 nroff->view = view;
263 mcview_nroff_seq_info (nroff);
265 return nroff;
268 /* --------------------------------------------------------------------------------------------- */
270 mcview_nroff_t *
271 mcview_nroff_seq_new (mcview_t * view)
273 return mcview_nroff_seq_new_num (view, (off_t) 0);
277 /* --------------------------------------------------------------------------------------------- */
279 void
280 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
282 if (nroff == NULL || *nroff == NULL)
283 return;
284 g_free (*nroff);
285 *nroff = NULL;
288 /* --------------------------------------------------------------------------------------------- */
290 nroff_type_t
291 mcview_nroff_seq_info (mcview_nroff_t * nroff)
293 int next, next2;
295 if (nroff == NULL)
296 return NROFF_TYPE_NONE;
297 nroff->type = NROFF_TYPE_NONE;
299 if (!mcview_get_byte (nroff->view, nroff->index, &nroff->current_char) || !g_ascii_isprint (nroff->current_char)) /* FIXME: utf-8 and g_ascii_isprint */
300 return nroff->type;
302 nroff->char_width = 1;
304 if (!mcview_get_byte (nroff->view, nroff->index + 1, &next) || next != '\b')
305 return nroff->type;
307 if (!mcview_get_byte (nroff->view, nroff->index + 2, &next2) || !g_ascii_isprint (next2)) /* FIXME: utf-8 and g_ascii_isprint */
308 return nroff->type;
310 if (nroff->current_char == '_' && next2 == '_')
312 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
313 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
316 else if (nroff->current_char == next2)
318 nroff->type = NROFF_TYPE_BOLD;
320 else if (nroff->current_char == '_')
322 nroff->current_char = next2;
323 nroff->type = NROFF_TYPE_UNDERLINE;
325 else if (nroff->current_char == '+' && next2 == 'o')
327 /* ??? */
330 return nroff->type;
333 /* --------------------------------------------------------------------------------------------- */
336 mcview_nroff_seq_next (mcview_nroff_t * nroff)
338 if (nroff == NULL)
339 return -1;
341 nroff->prev_type = nroff->type;
343 nroff->index += nroff->char_width;
345 if (nroff->prev_type != NROFF_TYPE_NONE)
346 nroff->index += 2;
347 mcview_nroff_seq_info (nroff);
348 return nroff->current_char;
351 /* --------------------------------------------------------------------------------------------- */