Fixed broken search results highlighting
[midnight-commander.git] / src / viewer / nroff.c
blob0597382aca871e123588a58e2a2129a938861223
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 *ret_val = c;
88 return g_unichar_isprint (c);
91 /* --------------------------------------------------------------------------------------------- */
92 /*** public functions ****************************************************************************/
93 /* --------------------------------------------------------------------------------------------- */
95 void
96 mcview_display_nroff (mcview_t * view)
98 const screen_dimen left = view->data_area.left;
99 const screen_dimen top = view->data_area.top;
100 const screen_dimen width = view->data_area.width;
101 const screen_dimen height = view->data_area.height;
102 screen_dimen row, col;
103 off_t from;
104 int cw = 1;
105 int c;
106 int c_prev = 0;
107 int c_next = 0;
108 struct hexedit_change_node *curr = view->change_list;
110 mcview_display_clean (view);
111 mcview_display_ruler (view);
113 /* Find the first displayable changed byte */
114 from = view->dpy_start;
115 while (curr && (curr->offset < from))
117 curr = curr->next;
120 tty_setcolor (NORMAL_COLOR);
121 for (row = 0, col = 0; row < height;)
123 #ifdef HAVE_CHARSET
124 if (view->utf8)
126 gboolean read_res = TRUE;
127 c = mcview_get_utf (view, from, &cw, &read_res);
128 if (!read_res)
129 break;
131 else
132 #endif
134 if (!mcview_get_byte (view, from, &c))
135 break;
137 from++;
138 if (cw > 1)
139 from += cw - 1;
141 if (c == '\b')
143 if (from > 1)
145 #ifdef HAVE_CHARSET
146 if (view->utf8)
148 gboolean read_res;
149 c_next = mcview_get_utf (view, from, &cw, &read_res);
151 else
152 #endif
153 mcview_get_byte (view, from, &c_next);
155 if (g_unichar_isprint (c_prev) && g_unichar_isprint (c_next)
156 && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o')))
158 if (col == 0)
160 if (row == 0)
162 /* We're inside an nroff character sequence at the
163 * beginning of the screen -- just skip the
164 * backspace and continue with the next character. */
165 continue;
167 row--;
168 col = width;
170 col--;
171 if (c_prev == '_'
172 && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
173 tty_setcolor (VIEW_UNDERLINED_COLOR);
174 else
175 tty_setcolor (VIEW_BOLD_COLOR);
176 continue;
180 if ((c == '\n') || (col >= width && view->text_wrap_mode))
182 col = 0;
183 row++;
184 if (c == '\n' || row >= height)
185 continue;
188 if (c == '\r')
190 mcview_get_byte_indexed (view, from, 1, &c);
191 if (c == '\r' || c == '\n')
192 continue;
193 col = 0;
194 row++;
195 continue;
198 if (c == '\t')
200 off_t line, column;
201 mcview_offset_to_coord (view, &line, &column, from);
202 col += (option_tab_spacing - col % option_tab_spacing);
203 if (view->text_wrap_mode && col >= width && width != 0)
205 row += col / width;
206 col %= width;
208 continue;
211 if (view->search_start <= from && from < view->search_end)
213 tty_setcolor (SELECTED_COLOR);
216 c_prev = c;
218 if ((off_t) col >= view->dpy_text_column
219 && (off_t) col - view->dpy_text_column < (off_t) width)
221 widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column));
222 #ifdef HAVE_CHARSET
223 if (utf8_display)
225 if (!view->utf8)
227 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
229 if (!g_unichar_isprint (c))
230 c = '.';
232 else
234 if (view->utf8)
236 c = convert_from_utf_to_current_c (c, view->converter);
238 else
240 #endif
241 c = convert_to_display_c (c);
242 #ifdef HAVE_CHARSET
245 #endif
246 tty_print_anychar (c);
248 col++;
249 #ifdef HAVE_CHARSET
250 if (view->utf8)
252 if (g_unichar_iswide (c))
253 col++;
254 else if (g_unichar_iszerowidth (c))
255 col--;
257 #endif
258 tty_setcolor (NORMAL_COLOR);
260 view->dpy_end = from;
263 /* --------------------------------------------------------------------------------------------- */
266 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
268 mcview_nroff_t *nroff;
269 int ret = 0;
270 off_t i = 0;
272 if (!view->text_nroff_mode)
273 return 0;
275 nroff = mcview_nroff_seq_new_num (view, start);
276 if (nroff == NULL)
277 return 0;
278 while (i < length)
280 switch (nroff->type)
282 case NROFF_TYPE_BOLD:
283 ret += 1 + nroff->char_width; /* real char width and 0x8 */
284 break;
285 case NROFF_TYPE_UNDERLINE:
286 ret += 2; /* underline symbol and ox8 */
287 break;
288 default:
289 break;
291 i += nroff->char_width;
292 mcview_nroff_seq_next (nroff);
295 mcview_nroff_seq_free (&nroff);
296 return ret;
299 /* --------------------------------------------------------------------------------------------- */
301 mcview_nroff_t *
302 mcview_nroff_seq_new_num (mcview_t * view, off_t lc_index)
304 mcview_nroff_t *nroff;
306 nroff = g_try_malloc0 (sizeof (mcview_nroff_t));
307 if (nroff != NULL)
309 nroff->index = lc_index;
310 nroff->view = view;
311 mcview_nroff_seq_info (nroff);
313 return nroff;
316 /* --------------------------------------------------------------------------------------------- */
318 mcview_nroff_t *
319 mcview_nroff_seq_new (mcview_t * view)
321 return mcview_nroff_seq_new_num (view, (off_t) 0);
325 /* --------------------------------------------------------------------------------------------- */
327 void
328 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
330 if (nroff == NULL || *nroff == NULL)
331 return;
332 g_free (*nroff);
333 *nroff = NULL;
336 /* --------------------------------------------------------------------------------------------- */
338 nroff_type_t
339 mcview_nroff_seq_info (mcview_nroff_t * nroff)
341 int next, next2;
343 if (nroff == NULL)
344 return NROFF_TYPE_NONE;
345 nroff->type = NROFF_TYPE_NONE;
347 if (!mcview_nroff_get_char (nroff, &nroff->current_char, nroff->index))
348 return nroff->type;
350 if (!mcview_get_byte (nroff->view, nroff->index + nroff->char_width, &next) || next != '\b')
351 return nroff->type;
353 if (!mcview_nroff_get_char (nroff, &next2, nroff->index + 1 + nroff->char_width))
354 return nroff->type;
356 if (nroff->current_char == '_' && next2 == '_')
358 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
359 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
362 else if (nroff->current_char == next2)
364 nroff->type = NROFF_TYPE_BOLD;
366 else if (nroff->current_char == '_')
368 nroff->current_char = next2;
369 nroff->type = NROFF_TYPE_UNDERLINE;
371 else if (nroff->current_char == '+' && next2 == 'o')
373 /* ??? */
375 return nroff->type;
378 /* --------------------------------------------------------------------------------------------- */
381 mcview_nroff_seq_next (mcview_nroff_t * nroff)
383 if (nroff == NULL)
384 return -1;
386 nroff->prev_type = nroff->type;
388 switch (nroff->type)
390 case NROFF_TYPE_BOLD:
391 nroff->index += 1 + nroff->char_width;
392 break;
393 case NROFF_TYPE_UNDERLINE:
394 nroff->index += 2;
395 break;
396 default:
397 break;
400 nroff->index += nroff->char_width;
402 mcview_nroff_seq_info (nroff);
403 return nroff->current_char;
406 /* --------------------------------------------------------------------------------------------- */