summaryrefslogtreecommitdiff
path: root/riscos/query.c
blob: 8d3383f1627763bf105ecedb3fbcf4bdb40fcadf (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
 * This file is part of NetSurf, http://netsurf.sourceforge.net/
 * Licensed under the GNU General Public License,
 *                http://www.opensource.org/licenses/gpl-license
 * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
 */

#include <stdlib.h>

#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/query.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"


/** Data for a query window */
struct gui_query_window
{
	struct gui_query_window *prev;	/** Previous query in list */
	struct gui_query_window *next;	/** Next query in list */

	query_id id;	/** unique ID number for this query */
	wimp_w window;	/** RISC OS window handle */

	const query_callback *cb;	/** Table of callback functions */
	void *pw;	/** Handle passed to callback functions */

	bool default_confirm;	/** Default action is to confirm */
};


/** Next unallocated query id */
static query_id next_id = (query_id)1;

/** List of all query windows. */
static struct gui_query_window *gui_query_window_list = 0;

/** Template for a query window. */
static struct wimp_window *query_template;

static void ro_gui_query_window_destroy(struct gui_query_window *qw);
static struct gui_query_window *ro_gui_query_window_lookup_id(query_id id);


void ro_gui_query_init(void)
{
	query_template = ro_gui_dialog_load_template("query");
}


/**
 * Lookup a query window using its RISC OS window handle
 *
 * \param  w  RISC OS window handle
 * \return pointer to query window or NULL
 */

struct gui_query_window *ro_gui_query_window_lookup(wimp_w w)
{
	struct gui_query_window *qw = gui_query_window_list;
	while (qw && qw->window != w)
		qw = qw->next;
	return qw;
}


/**
 * Lookup a query window using its ID number
 *
 * \param  id  id to search for
 * \return pointer to query window or NULL
 */

struct gui_query_window *ro_gui_query_window_lookup_id(query_id id)
{
	struct gui_query_window *qw = gui_query_window_list;
	while (qw && qw->id != id)
		qw = qw->next;
	return qw;
}


/**
 * Display a query to the user, requesting a response.
 *
 * \param  query   message token of query
 * \param  detail  parameter used in expanding tokenised message
 * \param  cb      table of callback functions to be called when user responds
 * \param  pw      handle to be passed to callback functions
 * \return id number of the query (or QUERY_INVALID if it failed)
 */

query_id query_user(const char *query, const char *detail, const query_callback *cb, void *pw)
{
	struct gui_query_window *qw;
	char query_buffer[300];
	os_error *error;

	qw = malloc(sizeof(struct gui_query_window));
	if (!qw) {
		warn_user("NoMemory", NULL);
		return QUERY_INVALID;
	}

	qw->cb = cb;
	qw->pw = pw;
	qw->id = next_id++;
	qw->default_confirm = false;

	if (next_id == QUERY_INVALID)
		next_id++;

	error = xwimp_create_window(query_template, &qw->window);
	if (error) {
		warn_user("WimpError", error->errmess);
	}

	snprintf(query_buffer, sizeof query_buffer, "%s %s",
			messages_get(query), detail ? detail : "");
	query_buffer[sizeof query_buffer - 1] = 0;

	ro_gui_set_icon_string(qw->window, ICON_QUERY_MESSAGE, query_buffer);

	xwimp_set_icon_state(qw->window, ICON_QUERY_HELP,
			wimp_ICON_DELETED, wimp_ICON_DELETED);

	ro_gui_open_window_centre(NULL, qw->window);

	error = xwimp_set_caret_position(qw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
	if (error) {
		LOG(("xwimp_get_caret_position: 0x%x : %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}

	/* put this query window at the head of our list */
	if (gui_query_window_list)
		gui_query_window_list->prev = qw;

	qw->prev = NULL;
	qw->next = gui_query_window_list;
	gui_query_window_list = qw;

	return qw->id;
}


/**
 * Close and destroy a query window, releasing all resources
 *
 * \param  qw  query window
 */

void ro_gui_query_window_destroy(struct gui_query_window *qw)
{
	os_error *error = xwimp_delete_window(qw->window);
	if (error) {
		LOG(("xwimp_delete_window: 0x%x:%s",
			error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}

	/* remove from linked-list of query windows and release memory */
	if (qw->prev)
		qw->prev->next = qw->next;
	else
		gui_query_window_list = qw->next;

	if (qw->next)
		qw->next->prev = qw->prev;

	free(qw);
}


/**
 * Close a query window without waiting for a response from the user.
 * (should normally only be called if the user has responded in some other
 *  way of which the query window in unaware.)
 *
 * \param  id  id of query window to close
 */

void query_close(query_id id)
{
	struct gui_query_window *qw = ro_gui_query_window_lookup_id(id);
	if (qw) ro_gui_query_window_destroy(qw);
}


void ro_gui_query_window_bring_to_front(query_id id)
{
	struct gui_query_window *qw = ro_gui_query_window_lookup_id(id);
	if (qw) {
		os_error *error;

		ro_gui_open_window_centre(NULL, qw->window);

		error = xwimp_set_caret_position(qw->window, (wimp_i)-1, 0, 0, 1 << 25, -1);
		if (error) {
			LOG(("xwimp_get_caret_position: 0x%x : %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
		}
	}
}


/**
 * Handle mouse clicks in a query window.
 *
 * \param  qw   query window
 * \param  key  key press info from the Wimp
 */

void ro_gui_query_window_click(struct gui_query_window *qw, wimp_pointer *pointer)
{
	const query_callback *cb = qw->cb;
	switch (pointer->i) {
		case ICON_QUERY_YES:
			cb->confirm(qw->id, QUERY_YES, qw->pw);
			ro_gui_query_window_destroy(qw);
			break;

		case ICON_QUERY_NO:
			cb->cancel(qw->id, QUERY_NO, qw->pw);
			ro_gui_query_window_destroy(qw);
			break;

		case ICON_QUERY_HELP:
			/* \todo */
			break;
	}
}


/**
 * Handle keypresses in a query window.
 *
 * \param  qw       query window
 * \param  pointer  mouse pointer state from Wimp.
 * \return true iff the key press is the key press has been handled
 */

bool ro_gui_query_window_keypress(struct gui_query_window *qw, wimp_key *key)
{
	const query_callback *cb = qw->cb;
	switch (key->c) {

		case wimp_KEY_ESCAPE:
			cb->escape(qw->id, QUERY_ESCAPE, qw->pw);
			ro_gui_query_window_destroy(qw);
			return true;

		case wimp_KEY_RETURN:
			if (qw->default_confirm)
				cb->confirm(qw->id, QUERY_YES, qw->pw);
			else
				cb->cancel(qw->id, QUERY_NO, qw->pw);
			ro_gui_query_window_destroy(qw);
			return true;
	}

	return true;
}