Ticket #1627
[kaloumi3.git] / src / viewer / nroff.c
blob7c759842bd204d48aa5d5d343ea5f57257d99292
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 "../src/global.h"
41 #include "../src/main.h"
42 #include "../src/charsets.h"
43 #include "../src/tty/tty.h"
44 #include "../src/skin/skin.h"
45 #include "internal.h"
48 /*** global variables ****************************************************************************/
50 /*** file scope macro definitions ****************************************************************/
52 /*** file scope type declarations ****************************************************************/
54 /*** file scope variables ************************************************************************/
56 /*** file scope functions ************************************************************************/
58 /*** public functions ****************************************************************************/
60 /* --------------------------------------------------------------------------------------------- */
62 void
63 mcview_display_nroff (mcview_t * view)
65 const screen_dimen left = view->data_area.left;
66 const screen_dimen top = view->data_area.top;
67 const screen_dimen width = view->data_area.width;
68 const screen_dimen height = view->data_area.height;
69 screen_dimen row, col;
70 off_t from;
71 int cw = 1;
72 int c;
73 int c_prev = 0;
74 int c_next = 0;
75 gboolean read_res = TRUE;
76 struct hexedit_change_node *curr = view->change_list;
78 mcview_display_clean (view);
79 mcview_display_ruler (view);
81 /* Find the first displayable changed byte */
82 from = view->dpy_start;
83 while (curr && (curr->offset < from)) {
84 curr = curr->next;
87 tty_setcolor (NORMAL_COLOR);
88 for (row = 0, col = 0; row < height;) {
89 #ifdef HAVE_CHARSET
90 if (view->utf8) {
91 c = mcview_get_utf (view, from, &cw, &read_res);
92 if (!read_res)
93 break;
94 } else
95 #endif
97 if (! mcview_get_byte (view, from, &c))
98 break;
100 from++;
101 if (cw > 1)
102 from += cw - 1;
104 if (c == '\b') {
105 if (from > 1) {
106 mcview_get_byte (view, from - 2, &c_prev);
107 mcview_get_byte (view, from, &c_next);
109 if (g_ascii_isprint (c_prev) && g_ascii_isprint (c_prev)
110 && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o'))) {
111 if (col == 0) {
112 if (row == 0) {
113 /* We're inside an nroff character sequence at the
114 * beginning of the screen -- just skip the
115 * backspace and continue with the next character. */
116 continue;
118 row--;
119 col = width;
121 col--;
122 if (c_prev == '_'
123 && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1))
124 tty_setcolor (VIEW_UNDERLINED_COLOR);
125 else
126 tty_setcolor (MARKED_COLOR);
127 continue;
131 if ((c == '\n') || (col >= width && view->text_wrap_mode)) {
132 col = 0;
133 row++;
134 if (c == '\n' || row >= height)
135 continue;
138 if (c == '\r') {
139 mcview_get_byte_indexed (view, from, 1, &c);
140 if (c == '\r' || c == '\n')
141 continue;
142 col = 0;
143 row++;
144 continue;
147 if (c == '\t') {
148 off_t line, column;
149 mcview_offset_to_coord (view, &line, &column, from);
150 col += (option_tab_spacing - col % option_tab_spacing);
151 if (view->text_wrap_mode && col >= width && width != 0) {
152 row += col / width;
153 col %= width;
155 continue;
158 if (view->search_start <= from && from < view->search_end) {
159 tty_setcolor (SELECTED_COLOR);
162 if (col >= view->dpy_text_column && col - view->dpy_text_column < width) {
163 widget_move (view, top + row, left + (col - view->dpy_text_column));
164 #ifdef HAVE_CHARSET
165 if (utf8_display) {
166 if (!view->utf8) {
167 c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter);
169 if (!g_unichar_isprint (c))
170 c = '.';
171 } else {
172 if (view->utf8) {
173 c = convert_from_utf_to_current_c (c, view->converter);
174 } else {
175 #endif
176 c = convert_to_display_c (c);
177 #ifdef HAVE_CHARSET
180 #endif
181 tty_print_anychar (c);
183 #ifdef HAVE_CHARSET
184 if (view->utf8 && g_unichar_iswide(c))
185 col++;
186 #endif
187 col++;
188 tty_setcolor (NORMAL_COLOR);
190 view->dpy_end = from;
193 /* --------------------------------------------------------------------------------------------- */
196 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
198 mcview_nroff_t *nroff;
199 int ret = 0;
200 off_t i = 0;
202 nroff = mcview_nroff_seq_new_num (view, start);
203 if (nroff == NULL)
204 return 0;
206 while (i < length) {
207 if (nroff->type != NROFF_TYPE_NONE) {
208 ret += 2;
210 i++;
211 mcview_nroff_seq_next (nroff);
214 mcview_nroff_seq_free (&nroff);
215 return ret;
218 /* --------------------------------------------------------------------------------------------- */
220 mcview_nroff_t *
221 mcview_nroff_seq_new_num (mcview_t * view, off_t index)
223 mcview_nroff_t *nroff;
225 nroff = g_malloc0 (sizeof (mcview_nroff_t));
226 if (nroff == NULL)
227 return NULL;
228 nroff->index = index;
229 nroff->view = view;
230 mcview_nroff_seq_info (nroff);
231 return nroff;
234 /* --------------------------------------------------------------------------------------------- */
236 mcview_nroff_t *
237 mcview_nroff_seq_new (mcview_t * view)
239 return mcview_nroff_seq_new_num (view, (off_t) 0);
243 /* --------------------------------------------------------------------------------------------- */
245 void
246 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
248 if (nroff == NULL || *nroff == NULL)
249 return;
250 g_free (*nroff);
251 nroff = NULL;
254 /* --------------------------------------------------------------------------------------------- */
256 nroff_type_t
257 mcview_nroff_seq_info (mcview_nroff_t * nroff)
259 int next, next2;
261 if (nroff == NULL)
262 return NROFF_TYPE_NONE;
263 nroff->type = NROFF_TYPE_NONE;
265 if (! mcview_get_byte (nroff->view, nroff->index, &nroff->current_char)
266 || !g_ascii_isprint (nroff->current_char)) /* FIXME: utf-8 and g_ascii_isprint */
267 return nroff->type;
269 nroff->char_width = 1;
271 if (! mcview_get_byte (nroff->view, nroff->index + 1, &next) || next != '\b')
272 return nroff->type;
274 if (! mcview_get_byte (nroff->view, nroff->index + 2, &next2)
275 || !g_ascii_isprint (next2)) /* FIXME: utf-8 and g_ascii_isprint */
276 return nroff->type;
278 if (nroff->current_char == '_' && next2 == '_') {
279 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
280 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
282 } else if (nroff->current_char == next2) {
283 nroff->type = NROFF_TYPE_BOLD;
284 } else if (nroff->current_char == '_') {
285 nroff->current_char = next2;
286 nroff->type = NROFF_TYPE_UNDERLINE;
287 } else if (nroff->current_char == '+' && next2 == 'o') {
288 /* ??? */
291 return nroff->type;
294 /* --------------------------------------------------------------------------------------------- */
297 mcview_nroff_seq_next (mcview_nroff_t * nroff)
299 if (nroff == NULL)
300 return -1;
302 nroff->prev_type = nroff->type;
304 nroff->index += nroff->char_width;
306 if (nroff->prev_type != NROFF_TYPE_NONE)
307 nroff->index += 2;
308 mcview_nroff_seq_info (nroff);
309 return nroff->current_char;
312 /* --------------------------------------------------------------------------------------------- */