(mcview__get_nroff_real_len): immediately return 0 if viewer is not in nroff mode..
[midnight-commander.git] / src / viewer / nroff.c
blobebf9874f22affd5db8850c49583416a8555644f5
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 static gboolean
62 mcview_nroff_get_char (mcview_nroff_t * nroff, int *ret_val, off_t nroff_index)
64 int c;
65 #ifdef HAVE_CHARSET
66 if (nroff->view->utf8)
68 gboolean utf_result;
69 c = mcview_get_utf (nroff->view, nroff_index, &nroff->char_width, &utf_result);
70 if (!utf_result)
72 /* we need got symbol in any case */
73 nroff->char_width = 1;
74 if (!mcview_get_byte (nroff->view, nroff_index, &c) || !g_ascii_isprint (c))
75 return FALSE;
78 else
79 #endif
81 nroff->char_width = 1;
82 if (!mcview_get_byte (nroff->view, nroff_index, &c))
83 return FALSE;
86 if (!g_unichar_isprint (c))
87 return FALSE;
88 *ret_val = c;
89 return TRUE;
92 /* --------------------------------------------------------------------------------------------- */
93 /*** public functions ****************************************************************************/
94 /* --------------------------------------------------------------------------------------------- */
96 void
97 mcview_display_nroff (mcview_t * view)
99 const screen_dimen left = view->data_area.left;
100 const screen_dimen top = view->data_area.top;
101 const screen_dimen width = view->data_area.width;
102 const screen_dimen height = view->data_area.height;
103 screen_dimen row, col;
104 off_t from;
105 int cw = 1;
106 int c;
107 int c_prev = 0;
108 int c_next = 0;
109 struct hexedit_change_node *curr = view->change_list;
111 mcview_display_clean (view);
112 mcview_display_ruler (view);
114 /* Find the first displayable changed byte */
115 from = view->dpy_start;
116 while (curr && (curr->offset < from))
118 curr = curr->next;
121 tty_setcolor (NORMAL_COLOR);
122 for (row = 0, col = 0; row < height;)
124 #ifdef HAVE_CHARSET
125 if (view->utf8)
127 gboolean read_res = TRUE;
128 c = mcview_get_utf (view, from, &cw, &read_res);
129 if (!read_res)
130 break;
132 else
133 #endif
135 if (!mcview_get_byte (view, from, &c))
136 break;
138 from++;
139 if (cw > 1)
140 from += cw - 1;
142 if (c == '\b')
144 if (from > 1)
146 #ifdef HAVE_CHARSET
147 if (view->utf8)
149 gboolean read_res;
150 c_next = mcview_get_utf (view, from, &cw, &read_res);
152 else
153 #endif
154 mcview_get_byte (view, from, &c_next);
156 if (g_unichar_isprint (c_prev) && g_unichar_isprint (c_next)
157 && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o')))
159 if (col == 0)
161 if (row == 0)
163 /* We're inside an nroff character sequence at the
164 * beginning of the screen -- just skip the
165 * backspace and continue with the next character. */
166 continue;
168 row--;
169 col = width;
171 col--;
172 if (c_prev == '_'
173 && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
174 tty_setcolor (VIEW_UNDERLINED_COLOR);
175 else
176 tty_setcolor (VIEW_BOLD_COLOR);
177 continue;
181 if ((c == '\n') || (col >= width && view->text_wrap_mode))
183 col = 0;
184 row++;
185 if (c == '\n' || row >= height)
186 continue;
189 if (c == '\r')
191 mcview_get_byte_indexed (view, from, 1, &c);
192 if (c == '\r' || c == '\n')
193 continue;
194 col = 0;
195 row++;
196 continue;
199 if (c == '\t')
201 off_t line, column;
202 mcview_offset_to_coord (view, &line, &column, from);
203 col += (option_tab_spacing - col % option_tab_spacing);
204 if (view->text_wrap_mode && col >= width && width != 0)
206 row += col / width;
207 col %= width;
209 continue;
212 if (view->search_start <= from && from < view->search_end)
214 tty_setcolor (SELECTED_COLOR);
217 c_prev = c;
219 if ((off_t) col >= view->dpy_text_column
220 && (off_t) col - view->dpy_text_column < (off_t) width)
222 widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column));
223 #ifdef HAVE_CHARSET
224 if (utf8_display)
226 if (!view->utf8)
228 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
230 if (!g_unichar_isprint (c))
231 c = '.';
233 else
235 if (view->utf8)
237 c = convert_from_utf_to_current_c (c, view->converter);
239 else
241 #endif
242 c = convert_to_display_c (c);
243 #ifdef HAVE_CHARSET
246 #endif
247 tty_print_anychar (c);
249 col++;
250 #ifdef HAVE_CHARSET
251 if (view->utf8)
253 if (g_unichar_iswide (c))
254 col++;
255 else if (g_unichar_iszerowidth (c))
256 col--;
258 #endif
259 tty_setcolor (NORMAL_COLOR);
261 view->dpy_end = from;
264 /* --------------------------------------------------------------------------------------------- */
267 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
269 mcview_nroff_t *nroff;
270 int ret = 0;
271 off_t i = 0;
273 if (!view->text_nroff_mode)
274 return 0;
276 nroff = mcview_nroff_seq_new_num (view, start);
277 if (nroff == NULL)
278 return 0;
280 while (i < length)
282 if (nroff->type != NROFF_TYPE_NONE)
284 ret += 1 + nroff->char_width;
286 i++;
287 mcview_nroff_seq_next (nroff);
290 mcview_nroff_seq_free (&nroff);
291 return ret;
294 /* --------------------------------------------------------------------------------------------- */
296 mcview_nroff_t *
297 mcview_nroff_seq_new_num (mcview_t * view, off_t lc_index)
299 mcview_nroff_t *nroff;
301 nroff = g_try_malloc0 (sizeof (mcview_nroff_t));
302 if (nroff != NULL)
304 nroff->index = lc_index;
305 nroff->view = view;
306 mcview_nroff_seq_info (nroff);
308 return nroff;
311 /* --------------------------------------------------------------------------------------------- */
313 mcview_nroff_t *
314 mcview_nroff_seq_new (mcview_t * view)
316 return mcview_nroff_seq_new_num (view, (off_t) 0);
320 /* --------------------------------------------------------------------------------------------- */
322 void
323 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
325 if (nroff == NULL || *nroff == NULL)
326 return;
327 g_free (*nroff);
328 *nroff = NULL;
331 /* --------------------------------------------------------------------------------------------- */
333 nroff_type_t
334 mcview_nroff_seq_info (mcview_nroff_t * nroff)
336 int next, next2;
338 if (nroff == NULL)
339 return NROFF_TYPE_NONE;
340 nroff->type = NROFF_TYPE_NONE;
342 if (!mcview_nroff_get_char (nroff, &nroff->current_char, nroff->index))
343 return nroff->type;
345 if (!mcview_get_byte (nroff->view, nroff->index + nroff->char_width, &next) || next != '\b')
346 return nroff->type;
348 if (!mcview_nroff_get_char (nroff, &next2, nroff->index + 1 + nroff->char_width))
349 return nroff->type;
351 if (nroff->current_char == '_' && next2 == '_')
353 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
354 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
357 else if (nroff->current_char == next2)
359 nroff->type = NROFF_TYPE_BOLD;
361 else if (nroff->current_char == '_')
363 nroff->current_char = next2;
364 nroff->type = NROFF_TYPE_UNDERLINE;
366 else if (nroff->current_char == '+' && next2 == 'o')
368 /* ??? */
370 return nroff->type;
373 /* --------------------------------------------------------------------------------------------- */
376 mcview_nroff_seq_next (mcview_nroff_t * nroff)
378 if (nroff == NULL)
379 return -1;
381 nroff->prev_type = nroff->type;
383 nroff->index += nroff->char_width;
385 if (nroff->prev_type != NROFF_TYPE_NONE)
386 nroff->index += 2;
387 mcview_nroff_seq_info (nroff);
388 return nroff->current_char;
391 /* --------------------------------------------------------------------------------------------- */