Hex patterns: fix Russian manual page.
[midnight-commander.git] / src / viewer / move.c
blobc0a7bba22406afe437458c03465966255717b029
1 /*
2 Internal file viewer for the Midnight Commander
3 Functions for handle cursor movement
5 Copyright (C) 1994-2016
6 Free Software Foundation, Inc.
8 Written by:
9 Miguel de Icaza, 1994, 1995, 1998
10 Janne Kukonlehto, 1994, 1995
11 Jakub Jelinek, 1995
12 Joseph M. Hinkle, 1996
13 Norbert Warmuth, 1997
14 Pavel Machek, 1998
15 Roland Illig <roland.illig@gmx.de>, 2004, 2005
16 Slava Zanko <slavazanko@google.com>, 2009
17 Andrew Borodin <aborodin@vmail.ru>, 2009, 2013
18 Ilia Maslakov <il.smind@gmail.com>, 2009, 2010
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 3 of the License,
25 or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU 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, see <http://www.gnu.org/licenses/>.
37 The following variables have to do with the current position and are
38 updated by the cursor movement functions.
40 In hex view and wrapped text view mode, dpy_start marks the offset of
41 the top-left corner on the screen, in non-wrapping text mode it is
42 the beginning of the current line. In hex mode, hex_cursor is the
43 offset of the cursor. In non-wrapping text mode, dpy_text_column is
44 the number of columns that are hidden on the left side on the screen.
46 In hex mode, dpy_start is updated by the view_fix_cursor_position()
47 function in order to keep the other functions simple. In
48 non-wrapping text mode dpy_start and dpy_text_column are normalized
49 such that dpy_text_column < view_get_datacolumns().
52 #include <config.h>
54 #include "lib/global.h"
55 #include "lib/tty/tty.h"
56 #include "internal.h"
58 /*** global variables ****************************************************************************/
60 /*** file scope macro definitions ****************************************************************/
62 /*** file scope type declarations ****************************************************************/
64 /*** file scope variables ************************************************************************/
66 /* --------------------------------------------------------------------------------------------- */
67 /*** file scope functions ************************************************************************/
68 /* --------------------------------------------------------------------------------------------- */
70 static void
71 mcview_scroll_to_cursor (WView * view)
73 if (view->hex_mode)
75 off_t bytes = view->bytes_per_line;
76 off_t cursor = view->hex_cursor;
77 off_t topleft = view->dpy_start;
78 off_t displaysize;
80 displaysize = view->data_area.height * bytes;
81 if (topleft + displaysize <= cursor)
82 topleft = mcview_offset_rounddown (cursor, bytes) - (displaysize - bytes);
83 if (cursor < topleft)
84 topleft = mcview_offset_rounddown (cursor, bytes);
85 view->dpy_start = topleft;
86 view->dpy_paragraph_skip_lines = 0;
87 view->dpy_wrap_dirty = TRUE;
91 /* --------------------------------------------------------------------------------------------- */
93 static void
94 mcview_movement_fixups (WView * view, gboolean reset_search)
96 mcview_scroll_to_cursor (view);
97 if (reset_search)
99 view->search_start = view->hex_mode ? view->hex_cursor : view->dpy_start;
100 view->search_end = view->search_start;
102 view->dirty++;
105 /* --------------------------------------------------------------------------------------------- */
106 /*** public functions ****************************************************************************/
107 /* --------------------------------------------------------------------------------------------- */
109 void
110 mcview_move_up (WView * view, off_t lines)
112 if (view->hex_mode)
114 off_t bytes = lines * view->bytes_per_line;
115 if (view->hex_cursor >= bytes)
117 view->hex_cursor -= bytes;
118 if (view->hex_cursor < view->dpy_start)
120 view->dpy_start = mcview_offset_doz (view->dpy_start, bytes);
121 view->dpy_paragraph_skip_lines = 0;
122 view->dpy_wrap_dirty = TRUE;
125 else
127 view->hex_cursor %= view->bytes_per_line;
130 else
132 mcview_ascii_move_up (view, lines);
134 mcview_movement_fixups (view, TRUE);
137 /* --------------------------------------------------------------------------------------------- */
139 void
140 mcview_move_down (WView * view, off_t lines)
142 off_t last_byte;
143 last_byte = mcview_get_filesize (view);
144 if (view->hex_mode)
146 off_t i, limit;
148 limit = mcview_offset_doz (last_byte, (off_t) view->bytes_per_line);
150 for (i = 0; i < lines && view->hex_cursor < limit; i++)
152 view->hex_cursor += view->bytes_per_line;
153 if (lines != 1)
155 view->dpy_start += view->bytes_per_line;
156 view->dpy_paragraph_skip_lines = 0;
157 view->dpy_wrap_dirty = TRUE;
161 else
163 mcview_ascii_move_down (view, lines);
165 mcview_movement_fixups (view, TRUE);
168 /* --------------------------------------------------------------------------------------------- */
170 void
171 mcview_move_left (WView * view, off_t columns)
173 if (view->hex_mode)
175 off_t old_cursor = view->hex_cursor;
176 #ifdef HAVE_ASSERT_H
177 assert (columns == 1);
178 #endif
179 if (view->hexview_in_text || !view->hexedit_lownibble)
181 if (view->hex_cursor > 0)
182 view->hex_cursor--;
184 if (!view->hexview_in_text)
185 if (old_cursor > 0 || view->hexedit_lownibble)
186 view->hexedit_lownibble = !view->hexedit_lownibble;
188 else if (!view->text_wrap_mode)
189 view->dpy_text_column = mcview_offset_doz (view->dpy_text_column, columns);
190 mcview_movement_fixups (view, FALSE);
193 /* --------------------------------------------------------------------------------------------- */
195 void
196 mcview_move_right (WView * view, off_t columns)
198 if (view->hex_mode)
200 off_t last_byte;
201 off_t old_cursor = view->hex_cursor;
203 last_byte = mcview_offset_doz (mcview_get_filesize (view), 1);
204 #ifdef HAVE_ASSERT_H
205 assert (columns == 1);
206 #endif
207 if (view->hexview_in_text || view->hexedit_lownibble)
209 if (view->hex_cursor < last_byte)
210 view->hex_cursor++;
212 if (!view->hexview_in_text)
213 if (old_cursor < last_byte || !view->hexedit_lownibble)
214 view->hexedit_lownibble = !view->hexedit_lownibble;
216 else if (!view->text_wrap_mode)
218 view->dpy_text_column += columns;
220 mcview_movement_fixups (view, FALSE);
223 /* --------------------------------------------------------------------------------------------- */
225 void
226 mcview_moveto_top (WView * view)
228 view->dpy_start = 0;
229 view->dpy_paragraph_skip_lines = 0;
230 mcview_state_machine_init (&view->dpy_state_top, 0);
231 view->hex_cursor = 0;
232 view->dpy_text_column = 0;
233 mcview_movement_fixups (view, TRUE);
236 /* --------------------------------------------------------------------------------------------- */
238 void
239 mcview_moveto_bottom (WView * view)
241 off_t filesize;
243 mcview_update_filesize (view);
245 if (view->growbuf_in_use)
246 mcview_growbuf_read_until (view, OFFSETTYPE_MAX);
248 filesize = mcview_get_filesize (view);
250 if (view->hex_mode)
252 view->hex_cursor = mcview_offset_doz (filesize, 1);
253 mcview_movement_fixups (view, TRUE);
255 else
257 const off_t datalines = view->data_area.height;
259 view->dpy_start = filesize;
260 view->dpy_paragraph_skip_lines = 0;
261 view->dpy_wrap_dirty = TRUE;
262 mcview_move_up (view, datalines);
266 /* --------------------------------------------------------------------------------------------- */
268 void
269 mcview_moveto_bol (WView * view)
271 if (view->hex_mode)
273 view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
274 view->dpy_text_column = 0;
276 else
278 mcview_ascii_moveto_bol (view);
280 mcview_movement_fixups (view, TRUE);
283 /* --------------------------------------------------------------------------------------------- */
285 void
286 mcview_moveto_eol (WView * view)
288 off_t bol;
289 if (view->hex_mode)
291 off_t filesize;
293 bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line);
294 if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE)
296 view->hex_cursor = bol + view->bytes_per_line - 1;
298 else
300 filesize = mcview_get_filesize (view);
301 view->hex_cursor = mcview_offset_doz (filesize, 1);
304 else
306 mcview_ascii_moveto_eol (view);
308 mcview_movement_fixups (view, FALSE);
311 /* --------------------------------------------------------------------------------------------- */
313 void
314 mcview_moveto_offset (WView * view, off_t offset)
316 if (view->hex_mode)
318 view->hex_cursor = offset;
319 view->dpy_start = offset - offset % view->bytes_per_line;
320 view->dpy_paragraph_skip_lines = 0;
321 view->dpy_wrap_dirty = TRUE;
323 else
325 view->dpy_start = offset;
326 view->dpy_paragraph_skip_lines = 0;
327 view->dpy_wrap_dirty = TRUE;
329 mcview_movement_fixups (view, TRUE);
332 /* --------------------------------------------------------------------------------------------- */
334 void
335 mcview_moveto (WView * view, off_t line, off_t col)
337 off_t offset;
339 mcview_coord_to_offset (view, &offset, line, col);
340 mcview_moveto_offset (view, offset);
343 /* --------------------------------------------------------------------------------------------- */
345 void
346 mcview_coord_to_offset (WView * view, off_t * ret_offset, off_t line, off_t column)
348 coord_cache_entry_t coord;
350 coord.cc_line = line;
351 coord.cc_column = column;
352 coord.cc_nroff_column = column;
353 mcview_ccache_lookup (view, &coord, CCACHE_OFFSET);
354 *ret_offset = coord.cc_offset;
357 /* --------------------------------------------------------------------------------------------- */
359 void
360 mcview_offset_to_coord (WView * view, off_t * ret_line, off_t * ret_column, off_t offset)
362 coord_cache_entry_t coord;
364 coord.cc_offset = offset;
365 mcview_ccache_lookup (view, &coord, CCACHE_LINECOL);
367 *ret_line = coord.cc_line;
368 *ret_column = (view->text_nroff_mode) ? coord.cc_nroff_column : coord.cc_column;
371 /* --------------------------------------------------------------------------------------------- */
373 void
374 mcview_place_cursor (WView * view)
376 const screen_dimen top = view->data_area.top;
377 const screen_dimen left = view->data_area.left;
378 screen_dimen col = view->cursor_col;
379 if (!view->hexview_in_text && view->hexedit_lownibble)
380 col++;
381 widget_move (view, top + view->cursor_row, left + col);
384 /* --------------------------------------------------------------------------------------------- */
385 /** we have set view->search_start and view->search_end and must set
386 * view->dpy_text_column and view->dpy_start
387 * try to display maximum of match */
389 void
390 mcview_moveto_match (WView * view)
392 if (view->hex_mode)
394 view->hex_cursor = view->search_start;
395 view->hexedit_lownibble = FALSE;
396 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
397 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
398 view->dpy_paragraph_skip_lines = 0;
399 view->dpy_wrap_dirty = TRUE;
401 else
403 view->dpy_start = mcview_bol (view, view->search_start, 0);
404 view->dpy_paragraph_skip_lines = 0;
405 view->dpy_wrap_dirty = TRUE;
408 mcview_scroll_to_cursor (view);
409 view->dirty++;
412 /* --------------------------------------------------------------------------------------------- */