source: trunk/third/gtkhtml3/src/htmlengine-edit-movement.c @ 21116

Revision 21116, 10.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21115, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/* This file is part of the GtkHTML library.
3   
4   Copyright (C) 2000 Helix Code, Inc.
5   
6   This library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Library General Public
8   License as published by the Free Software Foundation; either
9   version 2 of the License, or (at your option) any later version.
10   
11   This library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15   
16   You should have received a copy of the GNU Library General Public License
17   along with this library; see the file COPYING.LIB.  If not, write to
18   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.
20*/
21
22#include <config.h>
23#include <ctype.h>
24
25#include "gtkhtml.h"
26#include "gtkhtml-private.h"
27#include "htmlengine-edit-cursor.h"
28#include "htmlengine-edit-selection-updater.h"
29#include "htmlengine-edit-movement.h"
30#include "htmlobject.h"
31
32
33void
34html_engine_update_selection_if_necessary (HTMLEngine *e)
35{
36        if (e->mark == NULL)
37                return;
38
39        html_engine_edit_selection_updater_schedule (e->selection_updater);
40}
41
42
43guint
44html_engine_move_cursor (HTMLEngine *e,
45                         HTMLEngineCursorMovement movement,
46                         guint count)
47{
48        gboolean (* movement_func) (HTMLCursor *, HTMLEngine *);
49        guint c;
50
51        g_return_val_if_fail (e != NULL, 0);
52        g_return_val_if_fail (HTML_IS_ENGINE (e), 0);
53
54        if (count == 0)
55                return 0;
56
57        switch (movement) {
58        case HTML_ENGINE_CURSOR_RIGHT:
59                movement_func = html_cursor_forward;
60                break;
61
62        case HTML_ENGINE_CURSOR_LEFT:
63                movement_func = html_cursor_backward;
64                break;
65
66        case HTML_ENGINE_CURSOR_UP:
67                movement_func = html_cursor_up;
68                break;
69
70        case HTML_ENGINE_CURSOR_DOWN:
71                movement_func = html_cursor_down;
72                break;
73
74        default:
75                g_warning ("Unsupported movement %d\n", (gint) movement);
76                return 0;
77        }
78
79        html_engine_hide_cursor (e);
80
81        for (c = 0; c < count; c++) {
82                if (! (* movement_func) (e->cursor, e))
83                        break;
84        }
85
86        html_engine_update_focus_if_necessary (e, e->cursor->object, e->cursor->offset);
87        html_engine_show_cursor (e);
88        html_engine_update_selection_if_necessary (e);
89
90        return c;
91}
92
93
94/**
95 * html_engine_jump_to_object:
96 * @e: An HTMLEngine object
97 * @object: Object to move the cursor to
98 * @offset: Cursor offset within @object
99 *
100 * Move the cursor to object @object, at the specified @offset.
101 * Notice that this does *not* modify the selection.
102 *
103 * Return value:
104 **/
105void
106html_engine_jump_to_object (HTMLEngine *e,
107                            HTMLObject *object,
108                            guint offset)
109{
110        g_return_if_fail (e != NULL);
111        g_return_if_fail (HTML_IS_ENGINE (e));
112        g_return_if_fail (object != NULL);
113
114        /* Delete the cursor in the original position.  */
115        html_engine_hide_cursor (e);
116
117        /* Jump to the specified position.  FIXME: Beep if it fails?  */
118        html_cursor_jump_to (e->cursor, e, object, offset);
119        html_cursor_normalize (e->cursor);
120
121        /* Draw the cursor in the new position.  */
122        html_engine_show_cursor (e);
123}
124
125/**
126 * html_engine_jump_at:
127 * @e: An HTMLEngine object
128 * @x: X coordinate
129 * @y: Y coordinate
130 *
131 * Make the cursor jump at the specified @x, @y pointer position.
132 **/
133void
134html_engine_jump_at (HTMLEngine *e,
135                     gint x, gint y)
136{
137        HTMLObject *obj;
138        guint offset;
139
140        g_return_if_fail (e != NULL);
141        g_return_if_fail (HTML_IS_ENGINE (e));
142
143        gtk_html_im_reset (e->widget);
144
145        obj = html_engine_get_object_at (e, x, y, &offset, TRUE);
146        if (obj == NULL)
147                return;
148
149        /* printf ("jump to object type %d - %p\n", HTML_OBJECT_TYPE (obj), obj); */
150        html_engine_jump_to_object (e, obj, offset);
151        /* printf ("jumped to object type %d - %p\n", HTML_OBJECT_TYPE (e->cursor->object), e->cursor->object); */
152}
153
154
155void
156html_engine_beginning_of_document (HTMLEngine *engine)
157{
158        g_return_if_fail (engine != NULL);
159        g_return_if_fail (HTML_IS_ENGINE (engine));
160
161        html_engine_hide_cursor (engine);
162        html_cursor_beginning_of_document (engine->cursor, engine);
163        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
164        html_engine_show_cursor (engine);
165
166        html_engine_update_selection_if_necessary (engine);
167}
168
169void
170html_engine_end_of_document (HTMLEngine *engine)
171{
172        g_return_if_fail (engine != NULL);
173        g_return_if_fail (HTML_IS_ENGINE (engine));
174
175        html_engine_hide_cursor (engine);
176        html_cursor_end_of_document (engine->cursor, engine);
177        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
178        html_engine_show_cursor (engine);
179
180        html_engine_update_selection_if_necessary (engine);
181}
182
183
184gboolean
185html_engine_beginning_of_line (HTMLEngine *engine)
186{
187        gboolean retval;
188
189        g_return_val_if_fail (engine != NULL, FALSE);
190        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
191
192        html_engine_hide_cursor (engine);
193        retval = html_cursor_beginning_of_line (engine->cursor, engine);
194        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
195        html_engine_show_cursor (engine);
196
197        html_engine_update_selection_if_necessary (engine);
198
199        return retval;
200}
201
202gboolean
203html_engine_end_of_line (HTMLEngine *engine)
204{
205        gboolean retval;
206
207        g_return_val_if_fail (engine != NULL, FALSE);
208        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
209
210        html_engine_hide_cursor (engine);
211        retval = html_cursor_end_of_line (engine->cursor, engine);
212        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
213        html_engine_show_cursor (engine);
214
215        html_engine_update_selection_if_necessary (engine);
216
217        return retval;
218}
219
220gboolean
221html_engine_beginning_of_paragraph (HTMLEngine *engine)
222{
223        gboolean retval;
224
225        g_return_val_if_fail (engine != NULL, FALSE);
226        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
227
228        html_engine_hide_cursor (engine);
229        retval = html_cursor_beginning_of_paragraph (engine->cursor, engine);
230        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
231        html_engine_show_cursor (engine);
232
233        html_engine_update_selection_if_necessary (engine);
234
235        return retval;
236}
237
238gboolean
239html_engine_end_of_paragraph (HTMLEngine *engine)
240{
241        gboolean retval;
242
243        g_return_val_if_fail (engine != NULL, FALSE);
244        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
245
246        html_engine_hide_cursor (engine);
247        retval = html_cursor_end_of_paragraph (engine->cursor, engine);
248        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
249        html_engine_show_cursor (engine);
250
251        html_engine_update_selection_if_necessary (engine);
252
253        return retval;
254}
255
256
257gint
258html_engine_scroll_down (HTMLEngine *engine,
259                         gint amount)
260{
261        HTMLCursor *cursor;
262        HTMLCursor prev_cursor;
263        gint start_x, start_y;
264        gint x, y, new_y;
265
266        g_return_val_if_fail (engine != NULL, FALSE);
267        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
268
269        cursor = engine->cursor;
270
271        html_object_get_cursor_base (cursor->object, engine->painter, cursor->offset, &start_x, &start_y);
272
273        html_engine_hide_cursor (engine);
274
275        y = new_y = start_y;
276
277        while (1) {
278                html_cursor_copy (&prev_cursor, cursor);
279
280                new_y = html_cursor_down (cursor, engine);
281                html_object_get_cursor_base (cursor->object, engine->painter, cursor->offset, &x, &new_y);
282
283                /* FIXME html_cursor_down() is broken.  It should
284                   return FALSE and TRUE appropriately.  But I am lazy
285                   now.  */
286                if (new_y == y)
287                        break;
288
289                if (new_y < start_y) {
290                        html_engine_show_cursor (engine);
291                        return 0;
292                }
293
294                if (new_y - start_y >= amount) {
295                        html_cursor_copy (cursor, &prev_cursor);
296                        break;
297                }
298
299                y = new_y;
300        }
301
302        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
303        html_engine_show_cursor (engine);
304
305        html_engine_update_selection_if_necessary (engine);
306
307        return new_y - start_y;
308}
309
310gint
311html_engine_scroll_up (HTMLEngine *engine,
312                       gint amount)
313{
314        HTMLCursor *cursor;
315        HTMLCursor prev_cursor;
316        gint start_x, start_y;
317        gint x, y, new_y;
318
319        g_return_val_if_fail (engine != NULL, FALSE);
320        g_return_val_if_fail (HTML_IS_ENGINE (engine), FALSE);
321
322        cursor = engine->cursor;
323
324        html_object_get_cursor_base (cursor->object, engine->painter, cursor->offset, &start_x, &start_y);
325
326        html_engine_hide_cursor (engine);
327
328        y = start_y;
329
330        while (1) {
331                html_cursor_copy (&prev_cursor, cursor);
332
333                html_cursor_up (cursor, engine);
334                html_object_get_cursor_base (cursor->object, engine->painter, cursor->offset, &x, &new_y);
335
336                /* FIXME html_cursor_down() is broken.  It should
337                   return FALSE and TRUE appropriately.  But I am lazy
338                   now.  */
339                if (new_y == y)
340                        break;
341
342                if (new_y > start_y) {
343                        html_engine_show_cursor (engine);
344                        return 0;
345                }
346
347                if (start_y - new_y >= amount) {
348                        html_cursor_copy (cursor, &prev_cursor);
349                        break;
350                }
351
352                y = new_y;
353        }
354
355        html_engine_update_focus_if_necessary (engine, engine->cursor->object, engine->cursor->offset);
356        html_engine_show_cursor (engine);
357
358        html_engine_update_selection_if_necessary (engine);
359
360        return start_y - new_y;
361}
362
363
364gboolean
365html_engine_forward_word (HTMLEngine *e)
366{
367        gboolean rv = FALSE;
368
369        g_return_val_if_fail (e != NULL, FALSE);
370        g_return_val_if_fail (HTML_IS_ENGINE (e), FALSE);
371
372        html_engine_hide_cursor (e);
373        while (!g_unichar_isalnum (html_cursor_get_current_char (e->cursor)) && html_cursor_forward (e->cursor, e))
374                rv = TRUE;
375        while (g_unichar_isalnum (html_cursor_get_current_char (e->cursor)) && html_cursor_forward (e->cursor, e))
376                rv = TRUE;
377        html_engine_update_focus_if_necessary (e, e->cursor->object, e->cursor->offset);
378        html_engine_show_cursor (e);
379        html_engine_update_selection_if_necessary (e);
380
381        return rv;
382}
383
384gboolean
385html_engine_backward_word (HTMLEngine *e)
386{
387        gboolean rv = FALSE;
388
389        g_return_val_if_fail (e != NULL, FALSE);
390        g_return_val_if_fail (HTML_IS_ENGINE (e), FALSE);
391
392        html_engine_hide_cursor (e);
393        while (!g_unichar_isalnum (html_cursor_get_prev_char (e->cursor)) && html_cursor_backward (e->cursor, e))
394                rv = TRUE;
395        while (g_unichar_isalnum (html_cursor_get_prev_char (e->cursor)) && html_cursor_backward (e->cursor, e))
396                rv = TRUE;
397        html_engine_update_focus_if_necessary (e, e->cursor->object, e->cursor->offset);
398        html_engine_show_cursor (e);
399        html_engine_update_selection_if_necessary (e);
400
401        return rv;
402}
403
404void
405html_engine_edit_cursor_position_save (HTMLEngine *e)
406{
407        g_return_if_fail (e != NULL);
408        g_return_if_fail (HTML_IS_ENGINE (e));
409
410        e->cursor_position_stack = g_slist_prepend (e->cursor_position_stack, GINT_TO_POINTER (e->cursor->position));
411}
412
413void
414html_engine_edit_cursor_position_restore (HTMLEngine *e)
415{
416        g_return_if_fail (e != NULL);
417        g_return_if_fail (HTML_IS_ENGINE (e));
418
419        if (!e->cursor_position_stack)
420                return;
421
422        html_engine_hide_cursor (e);
423        html_cursor_jump_to_position (e->cursor, e, GPOINTER_TO_INT (e->cursor_position_stack->data));
424        e->cursor_position_stack = g_slist_remove_link (e->cursor_position_stack, e->cursor_position_stack);
425        html_engine_show_cursor (e);
426}
Note: See TracBrowser for help on using the repository browser.