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
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,
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().
56 #include "lib/global.h"
57 #include "lib/tty/tty.h"
60 /*** global variables ****************************************************************************/
62 /*** file scope macro definitions ****************************************************************/
64 /*** file scope type declarations ****************************************************************/
66 /*** file scope variables ************************************************************************/
68 /*** file scope functions ************************************************************************/
71 mcview_movement_fixups (mcview_t
* view
, gboolean reset_search
)
73 mcview_scroll_to_cursor (view
);
76 view
->search_start
= view
->dpy_start
;
77 view
->search_end
= view
->dpy_start
;
82 /* --------------------------------------------------------------------------------------------- */
84 /*** public functions ****************************************************************************/
86 /* --------------------------------------------------------------------------------------------- */
89 mcview_move_up (mcview_t
* view
, off_t lines
)
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
);
103 view
->hex_cursor
%= view
->bytes_per_line
;
109 for (i
= 0; i
< lines
; i
++)
111 new_offset
= mcview_bol (view
, view
->dpy_start
);
114 new_offset
= mcview_bol (view
, new_offset
);
117 view
->dpy_start
= new_offset
;
120 mcview_movement_fixups (view
, TRUE
);
123 /* --------------------------------------------------------------------------------------------- */
126 mcview_move_down (mcview_t
* view
, off_t lines
)
129 last_byte
= mcview_get_filesize (view
);
134 if (last_byte
>= (off_t
) view
->bytes_per_line
)
135 limit
= last_byte
- view
->bytes_per_line
;
138 for (i
= 0; i
< lines
&& view
->hex_cursor
< limit
; i
++)
140 view
->hex_cursor
+= view
->bytes_per_line
;
142 view
->dpy_start
+= view
->bytes_per_line
;
148 for (i
= 0; i
< lines
; i
++)
151 new_offset
= mcview_eol (view
, view
->dpy_start
);
152 view
->dpy_start
= new_offset
;
155 mcview_movement_fixups (view
, TRUE
);
158 /* --------------------------------------------------------------------------------------------- */
161 mcview_move_left (mcview_t
* view
, off_t columns
)
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)
172 if (!view
->hexview_in_text
)
173 if (old_cursor
> 0 || view
->hexedit_lownibble
)
174 view
->hexedit_lownibble
= !view
->hexedit_lownibble
;
178 if (view
->dpy_text_column
>= columns
)
179 view
->dpy_text_column
-= columns
;
181 view
->dpy_text_column
= 0;
183 mcview_movement_fixups (view
, FALSE
);
186 /* --------------------------------------------------------------------------------------------- */
189 mcview_move_right (mcview_t
* view
, off_t columns
)
194 off_t old_cursor
= view
->hex_cursor
;
195 last_byte
= mcview_offset_doz (mcview_get_filesize (view
), 1);
196 assert (columns
== 1);
197 if (view
->hexview_in_text
|| view
->hexedit_lownibble
)
199 if (view
->hex_cursor
< last_byte
)
202 if (!view
->hexview_in_text
)
203 if (old_cursor
< last_byte
|| !view
->hexedit_lownibble
)
204 view
->hexedit_lownibble
= !view
->hexedit_lownibble
;
208 view
->dpy_text_column
+= columns
;
210 mcview_movement_fixups (view
, FALSE
);
213 /* --------------------------------------------------------------------------------------------- */
216 mcview_scroll_to_cursor (mcview_t
* view
)
220 const off_t bytes
= view
->bytes_per_line
;
221 const off_t displaysize
= view
->data_area
.height
* bytes
;
222 const off_t cursor
= view
->hex_cursor
;
223 off_t topleft
= view
->dpy_start
;
225 if (topleft
+ displaysize
<= cursor
)
226 topleft
= mcview_offset_rounddown (cursor
, bytes
) - (displaysize
- bytes
);
227 if (cursor
< topleft
)
228 topleft
= mcview_offset_rounddown (cursor
, bytes
);
229 view
->dpy_start
= topleft
;
233 /* --------------------------------------------------------------------------------------------- */
236 mcview_moveto_top (mcview_t
* view
)
239 view
->hex_cursor
= 0;
240 view
->dpy_text_column
= 0;
241 mcview_movement_fixups (view
, TRUE
);
244 /* --------------------------------------------------------------------------------------------- */
247 mcview_moveto_bottom (mcview_t
* view
)
249 off_t datalines
, lines_up
, filesize
, last_offset
;
251 mcview_update_filesize (view
);
253 if (view
->growbuf_in_use
)
254 mcview_growbuf_read_until (view
, OFFSETTYPE_MAX
);
256 filesize
= mcview_get_filesize (view
);
257 datalines
= view
->data_area
.height
;
258 lines_up
= mcview_offset_doz (datalines
, 1);
262 last_offset
= mcview_offset_doz (filesize
, 1);
263 view
->hex_cursor
= filesize
;
264 mcview_move_up (view
, lines_up
);
265 view
->hex_cursor
= last_offset
;
269 view
->dpy_start
= filesize
;
270 mcview_move_up (view
, 1);
274 /* --------------------------------------------------------------------------------------------- */
277 mcview_moveto_bol (mcview_t
* view
)
281 view
->hex_cursor
-= view
->hex_cursor
% view
->bytes_per_line
;
283 else if (!view
->text_wrap_mode
)
285 view
->dpy_start
= mcview_bol (view
, view
->dpy_start
);
287 mcview_movement_fixups (view
, TRUE
);
290 /* --------------------------------------------------------------------------------------------- */
293 mcview_moveto_eol (mcview_t
* view
)
299 bol
= mcview_offset_rounddown (view
->hex_cursor
, view
->bytes_per_line
);
300 if (mcview_get_byte_indexed (view
, bol
, view
->bytes_per_line
- 1, NULL
) == TRUE
)
302 view
->hex_cursor
= bol
+ view
->bytes_per_line
- 1;
306 filesize
= mcview_get_filesize (view
);
307 view
->hex_cursor
= mcview_offset_doz (filesize
, 1);
310 mcview_movement_fixups (view
, FALSE
);
313 /* --------------------------------------------------------------------------------------------- */
316 mcview_moveto_offset (mcview_t
* view
, off_t offset
)
320 view
->hex_cursor
= offset
;
321 view
->dpy_start
= offset
- offset
% view
->bytes_per_line
;
325 view
->dpy_start
= offset
;
327 mcview_movement_fixups (view
, TRUE
);
330 /* --------------------------------------------------------------------------------------------- */
333 mcview_moveto (mcview_t
* view
, off_t line
, off_t col
)
337 mcview_coord_to_offset (view
, &offset
, line
, col
);
338 mcview_moveto_offset (view
, offset
);
341 /* --------------------------------------------------------------------------------------------- */
344 mcview_coord_to_offset (mcview_t
* view
, off_t
* ret_offset
, off_t line
, off_t column
)
346 coord_cache_entry_t coord
;
348 coord
.cc_line
= line
;
349 coord
.cc_column
= column
;
350 coord
.cc_nroff_column
= column
;
351 mcview_ccache_lookup (view
, &coord
, CCACHE_OFFSET
);
352 *ret_offset
= coord
.cc_offset
;
355 /* --------------------------------------------------------------------------------------------- */
358 mcview_offset_to_coord (mcview_t
* view
, off_t
* ret_line
, off_t
* ret_column
, off_t offset
)
360 coord_cache_entry_t coord
;
362 coord
.cc_offset
= offset
;
363 mcview_ccache_lookup (view
, &coord
, CCACHE_LINECOL
);
365 *ret_line
= coord
.cc_line
;
366 *ret_column
= (view
->text_nroff_mode
) ? coord
.cc_nroff_column
: coord
.cc_column
;
369 /* --------------------------------------------------------------------------------------------- */
372 mcview_place_cursor (mcview_t
* view
)
374 const screen_dimen top
= view
->data_area
.top
;
375 const screen_dimen left
= view
->data_area
.left
;
376 screen_dimen col
= view
->cursor_col
;
377 if (!view
->hexview_in_text
&& view
->hexedit_lownibble
)
379 widget_move (&view
->widget
, top
+ view
->cursor_row
, left
+ col
);
382 /* --------------------------------------------------------------------------------------------- */
384 /* we have set view->search_start and view->search_end and must set
385 * view->dpy_text_column and view->dpy_start
386 * try to display maximum of match */
388 mcview_moveto_match (mcview_t
* view
)
392 offset
= view
->search_start
;
396 view
->hex_cursor
= offset
;
397 view
->dpy_start
= offset
- offset
% view
->bytes_per_line
;
401 view
->dpy_start
= mcview_bol (view
, offset
);
404 mcview_scroll_to_cursor (view
);
408 /* --------------------------------------------------------------------------------------------- */