summaryrefslogtreecommitdiff
path: root/desktop/textinput.c
blob: 36daa374d43e8e455e2541efc2549d7a1d95d8d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
 * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
 * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
 * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
 * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
 *
 * This file is part of NetSurf, http://www.netsurf-browser.org/
 *
 * NetSurf is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * NetSurf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/** \file
 * Textual input handling (implementation)
 */

#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <dom/dom.h>

#include "desktop/browser_private.h"
#include "desktop/gui.h"
#include "desktop/mouse.h"
#include "desktop/scrollbar.h"
#include "desktop/selection.h"
#include "desktop/textinput.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
#include "render/html_internal.h"
#include "render/layout.h"
#include "utils/log.h"
#include "utils/talloc.h"
#include "utils/utf8.h"
#include "utils/utils.h"

/* Define to enable textinput debug */
#undef TEXTINPUT_DEBUG


/**
 * Position the caret and assign a callback for key presses.
 *
 * \param bw  The browser window in which to place the caret
 * \param x   X coordinate of the caret
 * \param y   Y coordinate
 * \param height    Height of caret
 * \param caret_cb  Callback function for keypresses
 * \param paste_cb  Callback function for pasting text
 * \param move_cb   Callback function for caret movement
 * \param p1  Callback private data pointer, passed to callback function
 * \param p2  Callback private data pointer, passed to callback function
 */
void browser_window_place_caret(struct browser_window *bw,
		int x, int y, int height,
		browser_caret_callback caret_cb,
		browser_paste_callback paste_cb,
		browser_move_callback move_cb,
		void *p1, void *p2)
{
	struct browser_window *root_bw;
	int pos_x = 0;
	int pos_y = 0;

	/* Find top level browser window */
	root_bw = browser_window_get_root(bw);
	browser_window_get_position(bw, true, &pos_x, &pos_y);

	x = x * bw->scale + pos_x;
	y = y * bw->scale + pos_y;

	gui_window_place_caret(root_bw->window, x, y, height * bw->scale);
	bw->caret_callback = caret_cb;
	bw->paste_callback = paste_cb;
	bw->move_callback = move_cb;
	bw->caret_p1 = p1;
	bw->caret_p2 = p2;

	/* Set focus browser window */
	root_bw->focus = bw;
}


/**
 * Removes the caret and callback for key process.
 *
 * \param bw  The browser window from which to remove caret
 */
void browser_window_remove_caret(struct browser_window *bw)
{
	struct browser_window *root_bw;

	root_bw = browser_window_get_root(bw);

	if (root_bw && root_bw->window)
		gui_window_remove_caret(root_bw->window);

	bw->caret_callback = NULL;
	bw->paste_callback = NULL;
	bw->move_callback = NULL;
	bw->caret_p1 = NULL;
	bw->caret_p2 = NULL;
}


/**
 * Handle key presses in a browser window.
 *
 * \param bw   The root browser window
 * \param key  The UCS4 character codepoint
 * \return true if key handled, false otherwise
 */
bool browser_window_key_press(struct browser_window *bw, uint32_t key)
{
	struct browser_window *focus = bw->focus;

	assert(bw->window != NULL);

	if (focus->caret_callback) {
		/* Pass keypress onto anything that has claimed input focus */
		return focus->caret_callback(focus, key,
				focus->caret_p1, focus->caret_p2);
	}

	/* keys that take effect wherever the caret is positioned */
	switch (key) {
		case KEY_SELECT_ALL:
			selection_select_all(bw->cur_sel);
			return true;

		case KEY_COPY_SELECTION:
			gui_copy_to_clipboard(bw->cur_sel);
			return true;

		case KEY_CLEAR_SELECTION:
			selection_clear(bw->cur_sel, true);
			return true;

		case KEY_ESCAPE:
			if (bw->cur_sel && selection_defined(bw->cur_sel)) {
				selection_clear(bw->cur_sel, true);
				return true;
			}
			/* if there's no selection,
			 * leave Escape for the caller */
			return false;
	}

	return false;
}


/**
 * Paste a block of text into a browser window at the caret position.
 *
 * \param  bw        browser window
 * \param  utf8      pointer to block of text
 * \param  utf8_len  length (bytes) of text block
 * \param  last      true iff this is the last chunk (update screen too)
 * \return true iff successful
 */

bool browser_window_paste_text(struct browser_window *bw, const char *utf8,
		unsigned utf8_len, bool last)
{
	if (!bw->focus || !bw->focus->paste_callback)
		return false;

	return bw->focus->paste_callback(bw->focus, utf8, utf8_len, last,
			bw->focus->caret_p1, bw->focus->caret_p2);
}