Merge branch '54_dlg_mouse_handling'
[midnight-commander.git] / src / viewer / nroff.c
blob57e4b52b8926ee83ae9004f3ba590e1fc6336866
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 += (8 - column % 8);
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 col++;
184 tty_setcolor (NORMAL_COLOR);
186 view->dpy_end = from;
189 /* --------------------------------------------------------------------------------------------- */
192 mcview__get_nroff_real_len (mcview_t * view, off_t start, off_t length)
194 mcview_nroff_t *nroff;
195 int ret = 0;
196 off_t i = 0;
198 nroff = mcview_nroff_seq_new_num (view, start);
199 if (nroff == NULL)
200 return 0;
202 while (i < length) {
203 if (nroff->type != NROFF_TYPE_NONE) {
204 ret += 2;
206 i++;
207 mcview_nroff_seq_next (nroff);
210 mcview_nroff_seq_free (&nroff);
211 return ret;
214 /* --------------------------------------------------------------------------------------------- */
216 mcview_nroff_t *
217 mcview_nroff_seq_new_num (mcview_t * view, off_t index)
219 mcview_nroff_t *nroff;
221 nroff = g_malloc0 (sizeof (mcview_nroff_t));
222 if (nroff == NULL)
223 return NULL;
224 nroff->index = index;
225 nroff->view = view;
226 mcview_nroff_seq_info (nroff);
227 return nroff;
230 /* --------------------------------------------------------------------------------------------- */
232 mcview_nroff_t *
233 mcview_nroff_seq_new (mcview_t * view)
235 return mcview_nroff_seq_new_num (view, (off_t) 0);
239 /* --------------------------------------------------------------------------------------------- */
241 void
242 mcview_nroff_seq_free (mcview_nroff_t ** nroff)
244 if (nroff == NULL || *nroff == NULL)
245 return;
246 g_free (*nroff);
247 nroff = NULL;
250 /* --------------------------------------------------------------------------------------------- */
252 nroff_type_t
253 mcview_nroff_seq_info (mcview_nroff_t * nroff)
255 int next, next2;
257 if (nroff == NULL)
258 return NROFF_TYPE_NONE;
259 nroff->type = NROFF_TYPE_NONE;
261 if (! mcview_get_byte (nroff->view, nroff->index, &nroff->current_char)
262 || !g_ascii_isprint (nroff->current_char)) /* FIXME: utf-8 and g_ascii_isprint */
263 return nroff->type;
265 nroff->char_width = 1;
267 if (! mcview_get_byte (nroff->view, nroff->index + 1, &next) || next != '\b')
268 return nroff->type;
270 if (! mcview_get_byte (nroff->view, nroff->index + 2, &next2)
271 || !g_ascii_isprint (next2)) /* FIXME: utf-8 and g_ascii_isprint */
272 return nroff->type;
274 if (nroff->current_char == '_' && next2 == '_') {
275 nroff->type = (nroff->prev_type == NROFF_TYPE_BOLD)
276 ? NROFF_TYPE_BOLD : NROFF_TYPE_UNDERLINE;
278 } else if (nroff->current_char == next2) {
279 nroff->type = NROFF_TYPE_BOLD;
280 } else if (nroff->current_char == '_') {
281 nroff->current_char = next2;
282 nroff->type = NROFF_TYPE_UNDERLINE;
283 } else if (nroff->current_char == '+' && next2 == 'o') {
284 /* ??? */
287 return nroff->type;
290 /* --------------------------------------------------------------------------------------------- */
293 mcview_nroff_seq_next (mcview_nroff_t * nroff)
295 if (nroff == NULL)
296 return -1;
298 nroff->prev_type = nroff->type;
300 nroff->index += nroff->char_width;
302 if (nroff->prev_type != NROFF_TYPE_NONE)
303 nroff->index += 2;
304 mcview_nroff_seq_info (nroff);
305 return nroff->current_char;
308 /* --------------------------------------------------------------------------------------------- */