x86_64: Cleanup of code for master
[midnight-commander.git] / src / viewer / move.c
blob2951d1337893a4f6281d7beb528778a18964d1fb
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) {
75 view->search_start = view->dpy_start;
76 view->search_end = view->dpy_start;
78 view->dirty++;
81 /* --------------------------------------------------------------------------------------------- */
83 /*** public functions ****************************************************************************/
85 /* --------------------------------------------------------------------------------------------- */
87 void
88 mcview_move_up (mcview_t * view, off_t lines)
90 off_t new_offset;
91 if (view->hex_mode) {
92 off_t bytes = lines * view->bytes_per_line;
93 if (view->hex_cursor >= bytes) {
94 view->hex_cursor -= bytes;
95 if (view->hex_cursor < view->dpy_start)
96 view->dpy_start = mcview_offset_doz (view->dpy_start, bytes);
97 } else {
98 view->hex_cursor %= view->bytes_per_line;
100 } else {
101 off_t i;
102 for (i = 0; i < lines; i++) {
103 new_offset = mcview_bol (view, view->dpy_start);
104 if (new_offset > 0)
105 new_offset--;
106 new_offset = mcview_bol (view, new_offset);
107 if (new_offset < 0)
108 new_offset = 0;
109 view->dpy_start = new_offset;
112 mcview_movement_fixups (view, TRUE);
115 /* --------------------------------------------------------------------------------------------- */
117 void
118 mcview_move_down (mcview_t * view, off_t lines)
120 off_t last_byte;
121 last_byte = mcview_get_filesize (view);
122 if (view->hex_mode) {
123 off_t i, limit;
125 if (last_byte >= (off_t) view->bytes_per_line)
126 limit = last_byte - view->bytes_per_line;
127 else
128 limit = 0;
129 for (i = 0; i < lines && view->hex_cursor < limit; i++) {
130 view->hex_cursor += view->bytes_per_line;
131 if (lines != 1)
132 view->dpy_start += view->bytes_per_line;
134 } else {
135 off_t i;
136 for (i = 0; i < lines; i++) {
137 off_t new_offset;
138 new_offset = mcview_eol (view, view->dpy_start);
139 view->dpy_start = new_offset;
142 mcview_movement_fixups (view, TRUE);
145 /* --------------------------------------------------------------------------------------------- */
147 void
148 mcview_move_left (mcview_t * view, off_t columns)
150 if (view->hex_mode) {
151 off_t old_cursor = view->hex_cursor;
152 assert (columns == 1);
153 if (view->hexview_in_text || !view->hexedit_lownibble) {
154 if (view->hex_cursor > 0)
155 view->hex_cursor--;
157 if (!view->hexview_in_text)
158 if (old_cursor > 0 || view->hexedit_lownibble)
159 view->hexedit_lownibble = !view->hexedit_lownibble;
160 } else if (view->text_wrap_mode) {
161 /* nothing to do */
162 } else {
163 if (view->dpy_text_column >= columns)
164 view->dpy_text_column -= columns;
165 else
166 view->dpy_text_column = 0;
168 mcview_movement_fixups (view, FALSE);
171 /* --------------------------------------------------------------------------------------------- */
173 void
174 mcview_move_right (mcview_t * view, off_t columns)
176 if (view->hex_mode) {
177 off_t last_byte;
178 off_t old_cursor = view->hex_cursor;
179 last_byte = mcview_offset_doz(mcview_get_filesize (view), 1);
180 assert (columns == 1);
181 if (view->hexview_in_text || view->hexedit_lownibble) {
182 if (view->hex_cursor < last_byte)
183 view->hex_cursor++;
185 if (!view->hexview_in_text)
186 if (old_cursor < last_byte || !view->hexedit_lownibble)
187 view->hexedit_lownibble = !view->hexedit_lownibble;
188 } else if (view->text_wrap_mode) {
189 /* nothing to do */
190 } else {
191 view->dpy_text_column += columns;
193 mcview_movement_fixups (view, FALSE);
196 /* --------------------------------------------------------------------------------------------- */
198 void
199 mcview_scroll_to_cursor (mcview_t * view)
201 if (view->hex_mode) {
202 const off_t bytes = view->bytes_per_line;
203 const off_t displaysize = view->data_area.height * bytes;
204 const off_t cursor = view->hex_cursor;
205 off_t topleft = view->dpy_start;
207 if (topleft + displaysize <= cursor)
208 topleft = mcview_offset_rounddown (cursor, bytes)
209 - (displaysize - bytes);
210 if (cursor < topleft)
211 topleft = mcview_offset_rounddown (cursor, bytes);
212 view->dpy_start = topleft;
216 /* --------------------------------------------------------------------------------------------- */
218 void
219 mcview_moveto_top (mcview_t * view)
221 view->dpy_start = 0;
222 view->hex_cursor = 0;
223 view->dpy_text_column = 0;
224 mcview_movement_fixups (view, TRUE);
227 /* --------------------------------------------------------------------------------------------- */
229 void
230 mcview_moveto_bottom (mcview_t * view)
232 off_t datalines, lines_up, filesize, last_offset;
234 mcview_update_filesize (view);
236 if (view->growbuf_in_use)
237 mcview_growbuf_read_until (view, OFFSETTYPE_MAX);
239 filesize = mcview_get_filesize (view);
240 datalines = view->data_area.height;
241 lines_up = mcview_offset_doz (datalines, 1);
243 if (view->hex_mode) {
244 last_offset = mcview_offset_doz (filesize, 1);
245 view->hex_cursor = filesize;
246 mcview_move_up (view, lines_up);
247 view->hex_cursor = last_offset;
248 } else {
249 view->dpy_start = filesize;
250 mcview_move_up (view, 1);
254 /* --------------------------------------------------------------------------------------------- */
256 void
257 mcview_moveto_bol (mcview_t * view)
259 if (view->hex_mode) {
260 view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
261 } else if (!view->text_wrap_mode) {
262 view->dpy_start = mcview_bol (view, view->dpy_start);
264 mcview_movement_fixups (view, TRUE);
267 /* --------------------------------------------------------------------------------------------- */
269 void
270 mcview_moveto_eol (mcview_t * view)
272 if (view->hex_mode) {
273 off_t filesize, bol;
275 bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line);
276 if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE) {
277 view->hex_cursor = bol + view->bytes_per_line - 1;
278 } else {
279 filesize = mcview_get_filesize (view);
280 view->hex_cursor = mcview_offset_doz (filesize, 1);
283 mcview_movement_fixups (view, FALSE);
286 /* --------------------------------------------------------------------------------------------- */
288 void
289 mcview_moveto_offset (mcview_t * view, off_t offset)
291 if (view->hex_mode) {
292 view->hex_cursor = offset;
293 view->dpy_start = offset - offset % view->bytes_per_line;
294 } else {
295 view->dpy_start = offset;
297 mcview_movement_fixups (view, TRUE);
300 /* --------------------------------------------------------------------------------------------- */
302 void
303 mcview_moveto (mcview_t * view, off_t line, off_t col)
305 off_t offset;
307 mcview_coord_to_offset (view, &offset, line, col);
308 mcview_moveto_offset (view, offset);
311 /* --------------------------------------------------------------------------------------------- */
313 void
314 mcview_coord_to_offset (mcview_t * view, off_t * ret_offset, off_t line, off_t column)
316 coord_cache_entry_t coord;
318 coord.cc_line = line;
319 coord.cc_column = column;
320 coord.cc_nroff_column = column;
321 mcview_ccache_lookup (view, &coord, CCACHE_OFFSET);
322 *ret_offset = coord.cc_offset;
325 /* --------------------------------------------------------------------------------------------- */
327 void
328 mcview_offset_to_coord (mcview_t * view, off_t * ret_line, off_t * ret_column, off_t offset)
330 coord_cache_entry_t coord;
332 coord.cc_offset = offset;
333 mcview_ccache_lookup (view, &coord, CCACHE_LINECOL);
335 *ret_line = coord.cc_line;
336 *ret_column = (view->text_nroff_mode)
337 ? coord.cc_nroff_column : coord.cc_column;
340 /* --------------------------------------------------------------------------------------------- */
342 void
343 mcview_place_cursor (mcview_t * view)
345 const screen_dimen top = view->data_area.top;
346 const screen_dimen left = view->data_area.left;
347 screen_dimen col = view->cursor_col;
348 if (!view->hexview_in_text && view->hexedit_lownibble)
349 col++;
350 widget_move (&view->widget, top + view->cursor_row, left + col);
353 /* --------------------------------------------------------------------------------------------- */
355 /* we have set view->search_start and view->search_end and must set
356 * view->dpy_text_column and view->dpy_start
357 * try to display maximum of match */
358 void
359 mcview_moveto_match (mcview_t * view)
361 off_t offset;
363 offset = view->search_start;
365 if (view->hex_mode) {
366 view->hex_cursor = offset;
367 view->dpy_start = offset - offset % view->bytes_per_line;
368 } else {
369 view->dpy_start = mcview_bol (view, offset);
372 mcview_scroll_to_cursor (view);
373 view->dirty++;
376 /* --------------------------------------------------------------------------------------------- */