Identation of some source files.
[midnight-commander.git] / src / viewer / move.c
blobdcf789b8d813f18e91fe0c59a89d3d52fd38d35f
1 /*
2 Internal file viewer for the Midnight Commander
3 Functions for handle cursor movement
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, 2010 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.
39 The following variables have to do with the current position and are
40 updated by the cursor movement functions.
42 In hex view and wrapped text view mode, dpy_start marks the offset of
43 the top-left corner on the screen, in non-wrapping text mode it is
44 the beginning of the current line. In hex mode, hex_cursor is the
45 offset of the cursor. In non-wrapping text mode, dpy_text_column is
46 the number of columns that are hidden on the left side on the screen.
48 In hex mode, dpy_start is updated by the view_fix_cursor_position()
49 function in order to keep the other functions simple. In
50 non-wrapping text mode dpy_start and dpy_text_column are normalized
51 such that dpy_text_column < view_get_datacolumns().
54 #include <config.h>
56 #include "lib/global.h"
57 #include "lib/tty/tty.h"
58 #include "internal.h"
60 /*** global variables ****************************************************************************/
62 /*** file scope macro definitions ****************************************************************/
64 /*** file scope type declarations ****************************************************************/
66 /*** file scope variables ************************************************************************/
68 /*** file scope functions ************************************************************************/
70 static void
71 mcview_movement_fixups (mcview_t * view, gboolean reset_search)
73 mcview_scroll_to_cursor (view);
74 if (reset_search)
76 view->search_start = view->dpy_start;
77 view->search_end = view->dpy_start;
79 view->dirty++;
82 /* --------------------------------------------------------------------------------------------- */
84 /*** public functions ****************************************************************************/
86 /* --------------------------------------------------------------------------------------------- */
88 void
89 mcview_move_up (mcview_t * view, off_t lines)
91 off_t new_offset;
92 if (view->hex_mode)
94 off_t bytes = lines * view->bytes_per_line;
95 if (view->hex_cursor >= bytes)
97 view->hex_cursor -= bytes;
98 if (view->hex_cursor < view->dpy_start)
99 view->dpy_start = mcview_offset_doz (view->dpy_start, bytes);
101 else
103 view->hex_cursor %= view->bytes_per_line;
106 else
108 off_t i;
109 for (i = 0; i < lines; i++)
111 new_offset = mcview_bol (view, view->dpy_start);
112 if (new_offset > 0)
113 new_offset--;
114 new_offset = mcview_bol (view, new_offset);
115 if (new_offset < 0)
116 new_offset = 0;
117 view->dpy_start = new_offset;
120 mcview_movement_fixups (view, TRUE);
123 /* --------------------------------------------------------------------------------------------- */
125 void
126 mcview_move_down (mcview_t * view, off_t lines)
128 off_t last_byte;
129 last_byte = mcview_get_filesize (view);
130 if (view->hex_mode)
132 off_t i, limit;
134 if (last_byte >= (off_t) view->bytes_per_line)
135 limit = last_byte - view->bytes_per_line;
136 else
137 limit = 0;
138 for (i = 0; i < lines && view->hex_cursor < limit; i++)
140 view->hex_cursor += view->bytes_per_line;
141 if (lines != 1)
142 view->dpy_start += view->bytes_per_line;
145 else
147 off_t i;
148 for (i = 0; i < lines; i++)
150 off_t new_offset;
151 new_offset = mcview_eol (view, view->dpy_start);
152 view->dpy_start = new_offset;
155 mcview_movement_fixups (view, TRUE);
158 /* --------------------------------------------------------------------------------------------- */
160 void
161 mcview_move_left (mcview_t * view, off_t columns)
163 if (view->hex_mode)
165 off_t old_cursor = view->hex_cursor;
166 assert (columns == 1);
167 if (view->hexview_in_text || !view->hexedit_lownibble)
169 if (view->hex_cursor > 0)
170 view->hex_cursor--;
172 if (!view->hexview_in_text)
173 if (old_cursor > 0 || view->hexedit_lownibble)
174 view->hexedit_lownibble = !view->hexedit_lownibble;
176 else if (view->text_wrap_mode)
178 /* nothing to do */
180 else
182 if (view->dpy_text_column >= columns)
183 view->dpy_text_column -= columns;
184 else
185 view->dpy_text_column = 0;
187 mcview_movement_fixups (view, FALSE);
190 /* --------------------------------------------------------------------------------------------- */
192 void
193 mcview_move_right (mcview_t * view, off_t columns)
195 if (view->hex_mode)
197 off_t last_byte;
198 off_t old_cursor = view->hex_cursor;
199 last_byte = mcview_offset_doz (mcview_get_filesize (view), 1);
200 assert (columns == 1);
201 if (view->hexview_in_text || view->hexedit_lownibble)
203 if (view->hex_cursor < last_byte)
204 view->hex_cursor++;
206 if (!view->hexview_in_text)
207 if (old_cursor < last_byte || !view->hexedit_lownibble)
208 view->hexedit_lownibble = !view->hexedit_lownibble;
210 else if (view->text_wrap_mode)
212 /* nothing to do */
214 else
216 view->dpy_text_column += columns;
218 mcview_movement_fixups (view, FALSE);
221 /* --------------------------------------------------------------------------------------------- */
223 void
224 mcview_scroll_to_cursor (mcview_t * view)
226 if (view->hex_mode)
228 const off_t bytes = view->bytes_per_line;
229 const off_t displaysize = view->data_area.height * bytes;
230 const off_t cursor = view->hex_cursor;
231 off_t topleft = view->dpy_start;
233 if (topleft + displaysize <= cursor)
234 topleft = mcview_offset_rounddown (cursor, bytes) - (displaysize - bytes);
235 if (cursor < topleft)
236 topleft = mcview_offset_rounddown (cursor, bytes);
237 view->dpy_start = topleft;
241 /* --------------------------------------------------------------------------------------------- */
243 void
244 mcview_moveto_top (mcview_t * view)
246 view->dpy_start = 0;
247 view->hex_cursor = 0;
248 view->dpy_text_column = 0;
249 mcview_movement_fixups (view, TRUE);
252 /* --------------------------------------------------------------------------------------------- */
254 void
255 mcview_moveto_bottom (mcview_t * view)
257 off_t datalines, lines_up, filesize, last_offset;
259 mcview_update_filesize (view);
261 if (view->growbuf_in_use)
262 mcview_growbuf_read_until (view, OFFSETTYPE_MAX);
264 filesize = mcview_get_filesize (view);
265 datalines = view->data_area.height;
266 lines_up = mcview_offset_doz (datalines, 1);
268 if (view->hex_mode)
270 last_offset = mcview_offset_doz (filesize, 1);
271 view->hex_cursor = filesize;
272 mcview_move_up (view, lines_up);
273 view->hex_cursor = last_offset;
275 else
277 view->dpy_start = filesize;
278 mcview_move_up (view, 1);
282 /* --------------------------------------------------------------------------------------------- */
284 void
285 mcview_moveto_bol (mcview_t * view)
287 if (view->hex_mode)
289 view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
291 else if (!view->text_wrap_mode)
293 view->dpy_start = mcview_bol (view, view->dpy_start);
295 mcview_movement_fixups (view, TRUE);
298 /* --------------------------------------------------------------------------------------------- */
300 void
301 mcview_moveto_eol (mcview_t * view)
303 if (view->hex_mode)
305 off_t filesize, bol;
307 bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line);
308 if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE)
310 view->hex_cursor = bol + view->bytes_per_line - 1;
312 else
314 filesize = mcview_get_filesize (view);
315 view->hex_cursor = mcview_offset_doz (filesize, 1);
318 mcview_movement_fixups (view, FALSE);
321 /* --------------------------------------------------------------------------------------------- */
323 void
324 mcview_moveto_offset (mcview_t * view, off_t offset)
326 if (view->hex_mode)
328 view->hex_cursor = offset;
329 view->dpy_start = offset - offset % view->bytes_per_line;
331 else
333 view->dpy_start = offset;
335 mcview_movement_fixups (view, TRUE);
338 /* --------------------------------------------------------------------------------------------- */
340 void
341 mcview_moveto (mcview_t * view, off_t line, off_t col)
343 off_t offset;
345 mcview_coord_to_offset (view, &offset, line, col);
346 mcview_moveto_offset (view, offset);
349 /* --------------------------------------------------------------------------------------------- */
351 void
352 mcview_coord_to_offset (mcview_t * view, off_t * ret_offset, off_t line, off_t column)
354 coord_cache_entry_t coord;
356 coord.cc_line = line;
357 coord.cc_column = column;
358 coord.cc_nroff_column = column;
359 mcview_ccache_lookup (view, &coord, CCACHE_OFFSET);
360 *ret_offset = coord.cc_offset;
363 /* --------------------------------------------------------------------------------------------- */
365 void
366 mcview_offset_to_coord (mcview_t * view, off_t * ret_line, off_t * ret_column, off_t offset)
368 coord_cache_entry_t coord;
370 coord.cc_offset = offset;
371 mcview_ccache_lookup (view, &coord, CCACHE_LINECOL);
373 *ret_line = coord.cc_line;
374 *ret_column = (view->text_nroff_mode) ? coord.cc_nroff_column : coord.cc_column;
377 /* --------------------------------------------------------------------------------------------- */
379 void
380 mcview_place_cursor (mcview_t * view)
382 const screen_dimen top = view->data_area.top;
383 const screen_dimen left = view->data_area.left;
384 screen_dimen col = view->cursor_col;
385 if (!view->hexview_in_text && view->hexedit_lownibble)
386 col++;
387 widget_move (&view->widget, top + view->cursor_row, left + col);
390 /* --------------------------------------------------------------------------------------------- */
392 /* we have set view->search_start and view->search_end and must set
393 * view->dpy_text_column and view->dpy_start
394 * try to display maximum of match */
395 void
396 mcview_moveto_match (mcview_t * view)
398 off_t offset;
400 offset = view->search_start;
402 if (view->hex_mode)
404 view->hex_cursor = offset;
405 view->dpy_start = offset - offset % view->bytes_per_line;
407 else
409 view->dpy_start = mcview_bol (view, offset);
412 mcview_scroll_to_cursor (view);
413 view->dirty++;
416 /* --------------------------------------------------------------------------------------------- */