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
;
176 else if (view
->text_wrap_mode
)
182 if (view
->dpy_text_column
>= columns
)
183 view
->dpy_text_column
-= columns
;
185 view
->dpy_text_column
= 0;
187 mcview_movement_fixups (view
, FALSE
);
190 /* --------------------------------------------------------------------------------------------- */
193 mcview_move_right (mcview_t
* view
, off_t columns
)
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
)
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
)
216 view
->dpy_text_column
+= columns
;
218 mcview_movement_fixups (view
, FALSE
);
221 /* --------------------------------------------------------------------------------------------- */
224 mcview_scroll_to_cursor (mcview_t
* view
)
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 /* --------------------------------------------------------------------------------------------- */
244 mcview_moveto_top (mcview_t
* view
)
247 view
->hex_cursor
= 0;
248 view
->dpy_text_column
= 0;
249 mcview_movement_fixups (view
, TRUE
);
252 /* --------------------------------------------------------------------------------------------- */
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);
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
;
277 view
->dpy_start
= filesize
;
278 mcview_move_up (view
, 1);
282 /* --------------------------------------------------------------------------------------------- */
285 mcview_moveto_bol (mcview_t
* view
)
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 /* --------------------------------------------------------------------------------------------- */
301 mcview_moveto_eol (mcview_t
* view
)
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;
314 filesize
= mcview_get_filesize (view
);
315 view
->hex_cursor
= mcview_offset_doz (filesize
, 1);
318 mcview_movement_fixups (view
, FALSE
);
321 /* --------------------------------------------------------------------------------------------- */
324 mcview_moveto_offset (mcview_t
* view
, off_t offset
)
328 view
->hex_cursor
= offset
;
329 view
->dpy_start
= offset
- offset
% view
->bytes_per_line
;
333 view
->dpy_start
= offset
;
335 mcview_movement_fixups (view
, TRUE
);
338 /* --------------------------------------------------------------------------------------------- */
341 mcview_moveto (mcview_t
* view
, off_t line
, off_t col
)
345 mcview_coord_to_offset (view
, &offset
, line
, col
);
346 mcview_moveto_offset (view
, offset
);
349 /* --------------------------------------------------------------------------------------------- */
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 /* --------------------------------------------------------------------------------------------- */
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 /* --------------------------------------------------------------------------------------------- */
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
)
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 */
396 mcview_moveto_match (mcview_t
* view
)
400 offset
= view
->search_start
;
404 view
->hex_cursor
= offset
;
405 view
->dpy_start
= offset
- offset
% view
->bytes_per_line
;
409 view
->dpy_start
= mcview_bol (view
, offset
);
412 mcview_scroll_to_cursor (view
);
416 /* --------------------------------------------------------------------------------------------- */