Ticket #2170: Color collisions
[midnight-commander.git] / src / viewer / nroff.c
blobb55d47677e2adf1272c041a0d1c439dde5a39455
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"
44 #include "src/main.h" /* utf8_display */
45 #include "src/setup.h" /* option_tab_spacing */
46 #include "src/charsets.h"
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 ************************************************************************/
60 /*** public functions ****************************************************************************/
62 /* --------------------------------------------------------------------------------------------- */
64 void
65 mcview_display_nroff (mcview_t * view)
67 const screen_dimen left = view->data_area.left;
68 const screen_dimen top = view->data_area.top;
69 const screen_dimen width = view->data_area.width;
70 const screen_dimen height = view->data_area.height;
71 screen_dimen row, col;
72 off_t from;
73 int cw = 1;
74 int c;
75 int c_prev = 0;
76 int c_next = 0;
77 struct hexedit_change_node *curr = view->change_list;
79 mcview_display_clean (view);
80 mcview_display_ruler (view);
82 /* Find the first displayable changed byte */
83 from = view->dpy_start;
84 while (curr && (curr->offset < from))
86 curr = curr->next;
89 tty_setcolor (NORMAL_COLOR);
90 for (row = 0, col = 0; row < height;)
92 #ifdef HAVE_CHARSET
93 if (view->utf8)
95 gboolean read_res = TRUE;
96 c = mcview_get_utf (view, from, &cw, &read_res);
97 if (!read_res)
98 break;
100 else
101 #endif
103 if (!mcview_get_byte (view, from, &c))
104 break;
106 from++;
107 if (cw > 1)
108 from += cw - 1;
110 if (c == '\b')
112 if (from > 1)
114 mcview_get_byte (view, from - 2, &c_prev);
115 mcview_get_byte (view, from, &c_next);
117 if (g_ascii_isprint (c_prev) && g_ascii_isprint (c_prev)
118 && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o')))
120 if (col == 0)
122 if (row == 0)
124 /* We're inside an nroff character sequence at the
125 * beginning of the screen -- just skip the
126 * backspace and continue with the next character. */
127 continue;
129 row--;
130 col = width;
132 col--;
133 if (c_prev == '_'
134 && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
135 tty_setcolor (VIEW_UNDERLINED_COLOR);
136 else
137 tty_setcolor (VIEW_BOLD_COLOR);
138 continue;
142 if ((c == '\n') || (col >= width && view->text_wrap_mode))
144 col = 0;
145 row++;
146 if (c == '\n' || row >= height)
147 continue;
150 if (c == '\r')
152 mcview_get_byte_indexed (view, from, 1, &c);
153 if (c == '\r' || c == '\n')
154 continue;
155 col = 0;
156 row++;
157 continue;
160 if (c == '\t')
162 off_t line, column;
163 mcview_offset_to_coord (view, &line, &column, from);
164 col += (option_tab_spacing - col % option_tab_spacing);
165 if (view->text_wrap_mode && col >= width && width != 0)
167 row += col / width;
168 col %= width;
170 continue;
173 if (view->search_start <= from && from < view->search_end)
175 tty_setcolor (SELECTED_COLOR);
178 if ((off_t) col >= view->dpy_text_column
179 && (off_t) col - view->dpy_text_column < (off_t) width)
181 widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column));
182 #ifdef HAVE_CHARSET
183 if (utf8_display)
185 if (!view->utf8)
187 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
189 if (!g_unichar_isprint (c))
190 c = '.';
192 else
194 if (view->utf8)
196 c = convert_from_utf_to_current_c (c, view->converter);
198 else
200 #endif
201 c = convert_to_display_c (c);
202 #ifdef HAVE_CHARSET
205 #endif
206 tty_print_anychar (c);
208 col++;
209 #ifdef HAVE_CHARSET
210 if (view->utf8)
212 if (g_unichar_iswide (c))
213 col++;
214 else if (g_unichar_iszerowidth (c))
215 col--;
217 #endif
218 tty_setcolor (NORMAL_COLOR);
220 view->dpy_end = from;
223 /* --------------------------------------------------------------------------------------------- */
226 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
228 mcview_nroff_t *nroff;
229 int ret = 0;
230 off_t i = 0;
232 nroff = mcview_nroff_seq_new_num (view, start);
233 if (nroff == NULL)
234 return 0;
236 while (i < length)
238 if (nroff->type != NROFF_TYPE_NONE)
240 ret += 2;
242 i++;
243 mcview_nroff_seq_next (nroff);
246 mcview_nroff_seq_free (&nroff);
247 return ret;
250 /* --------------------------------------------------------------------------------------------- */
252 mcview_nroff_t *
253 mcview_nroff_seq_new_num (mcview_t * view, off_t lc_index)
255 mcview_nroff_t *nroff;
257 nroff = g_try_malloc0 (sizeof (mcview_nroff_t));
258 if (nroff != NULL)
260 nroff->index = lc_index;
261 nroff->view = view;
262 mcview_nroff_seq_info (nroff);
264 return nroff;
267 /* --------------------------------------------------------------------------------------------- */
269 mcview_nroff_t *
270 mcview_nroff_seq_new (mcview_t * view)
272 return mcview_nroff_seq_new_num (view, (off_t) 0);
276 /* --------------------------------------------------------------------------------------------- */
278 void
279 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
281 if (nroff == NULL || *nroff == NULL)
282 return;
283 g_free (*nroff);
284 *nroff = NULL;
287 /* --------------------------------------------------------------------------------------------- */
289 nroff_type_t
290 mcview_nroff_seq_info (mcview_nroff_t * nroff)
292 int next, next2;
294 if (nroff == NULL)
295 return NROFF_TYPE_NONE;
296 nroff->type = NROFF_TYPE_NONE;
298 if (!mcview_get_byte (nroff->view, nroff->index, &nroff->current_char) || !g_ascii_isprint (nroff->current_char)) /* FIXME: utf-8 and g_ascii_isprint */
299 return nroff->type;
301 nroff->char_width = 1;
303 if (!mcview_get_byte (nroff->view, nroff->index + 1, &next) || next != '\b')
304 return nroff->type;
306 if (!mcview_get_byte (nroff->view, nroff->index + 2, &next2) || !g_ascii_isprint (next2)) /* FIXME: utf-8 and g_ascii_isprint */
307 return nroff->type;
309 if (nroff->current_char == '_' && next2 == '_')
311 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
312 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
315 else if (nroff->current_char == next2)
317 nroff->type = NROFF_TYPE_BOLD;
319 else if (nroff->current_char == '_')
321 nroff->current_char = next2;
322 nroff->type = NROFF_TYPE_UNDERLINE;
324 else if (nroff->current_char == '+' && next2 == 'o')
326 /* ??? */
329 return nroff->type;
332 /* --------------------------------------------------------------------------------------------- */
335 mcview_nroff_seq_next (mcview_nroff_t * nroff)
337 if (nroff == NULL)
338 return -1;
340 nroff->prev_type = nroff->type;
342 nroff->index += nroff->char_width;
344 if (nroff->prev_type != NROFF_TYPE_NONE)
345 nroff->index += 2;
346 mcview_nroff_seq_info (nroff);
347 return nroff->current_char;
350 /* --------------------------------------------------------------------------------------------- */