Dillo v3.2.0-143-gabad1053
Loading...
Searching...
No Matches
dialog.cc
Go to the documentation of this file.
1/*
2 * File: dialog.cc
3 *
4 * Copyright (C) 2005-2007 Jorge Arellano Cid <jcid@dillo.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 */
11
16#include <math.h> // for rint()
17#include <string.h>
18#include <errno.h>
19
20#include <FL/fl_ask.H>
21#include <FL/Fl_Window.H>
22#include <FL/Fl_File_Chooser.H>
23#include <FL/Fl_Return_Button.H>
24#include <FL/Fl_Text_Display.H>
25#include <FL/Fl_Button.H>
26#include <FL/Fl_Return_Button.H>
27#include <FL/Fl_Output.H>
28#include <FL/Fl_Input.H>
29#include <FL/Fl_Secret_Input.H>
30#include <FL/Fl_Choice.H>
31#include <FL/Fl_Menu_Item.H>
32
33#include "msg.h"
34#include "dialog.hh"
35#include "misc.h"
36#include "prefs.h"
37#include "dlib/dlib.h"
38
39/*
40 * Local Data
41 */
42static int input_answer;
43static char *input_str = NULL;
44static int choice_answer;
45
46
47/*
48 * Local sub classes
49 */
50
51//----------------------------------------------------------------------------
56class CustInput3 : public Fl_Input {
57public:
58 CustInput3 (int x, int y, int w, int h, const char* l=0) :
59 Fl_Input(x,y,w,h,l) {};
60 int handle(int e);
61};
62
63int CustInput3::handle(int e)
64{
65 int k = Fl::event_key();
66
67 _MSG("CustInput3::handle event=%d\n", e);
68
69 // We're only interested in some flags
70 unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT);
71
72 if (e == FL_KEYBOARD && modifier == FL_CTRL) {
73 if (k == 'a' || k == 'e') {
74 position(k == 'a' ? 0 : size());
75 return 1;
76 } else if (k == 'k') {
77 cut(position(), size());
78 return 1;
79 } else if (k == 'd') {
80 cut(position(), position()+1);
81 return 1;
82 }
83 }
84 return Fl_Input::handle(e);
85}
86
90class CustChoice2 : public Fl_Choice {
91public:
92 CustChoice2 (int x, int y, int w, int h, const char* l=0) :
93 Fl_Choice(x,y,w,h,l) {};
94 int handle(int e) {
95 if (e == FL_KEYBOARD &&
96 (Fl::event_key() == FL_Enter || Fl::event_key() == FL_Down) &&
97 (Fl::event_state() & (FL_SHIFT|FL_CTRL|FL_ALT|FL_META)) == 0) {
98 return Fl_Choice::handle(FL_PUSH);
99 }
100 return Fl_Choice::handle(e);
101 };
102};
103
104class EnterButton : public Fl_Button {
105public:
106 EnterButton (int x,int y,int w,int h, const char* label = 0) :
107 Fl_Button (x,y,w,h,label) {};
108 int handle(int e);
109};
110
111int EnterButton::handle(int e)
112{
113 if (e == FL_KEYBOARD && Fl::focus() == this && Fl::event_key() == FL_Enter){
114 set_changed();
115 simulate_key_action();
116 do_callback();
117 return 1;
118 }
119 return Fl_Button::handle(e);
120}
121
122//----------------------------------------------------------------------------
123
124
128void a_Dialog_msg(const char *title, const char *msg)
129{
130 if (!(title && *title))
131 title = "Dillo: Message";
132 fl_message_title(title);
133 fl_message("%s", msg);
134}
135
136
140static void input_cb(Fl_Widget *button, void *number)
141{
142 input_answer = VOIDP2INT(number);
143 button->window()->hide();
144}
145
152const char *a_Dialog_input(const char *title, const char *msg)
153{
154 static Fl_Menu_Item *pm = 0;
155 int ww = 450, wh = 130, gap = 10, ih = 60, bw = 80, bh = 30;
156
157 input_answer = 0;
158
159 if (!(title && *title))
160 title = "Dillo: Input";
161
162 Fl_Window *window = new Fl_Window(ww,wh,title);
163 window->set_modal();
164 window->begin();
165 Fl_Group* ib = new Fl_Group(0,0,window->w(),window->h());
166 ib->begin();
167 window->resizable(ib);
168
169 /* '?' Icon */
170 Fl_Box* o = new Fl_Box(gap, gap, ih, ih);
171 o->box(FL_THIN_UP_BOX);
172 o->labelfont(FL_TIMES_BOLD);
173 o->labelsize(34);
174 o->label("?");
175 o->show();
176
177 Fl_Box *box = new Fl_Box(ih+2*gap,gap,ww-(ih+3*gap),ih/2, msg);
178 box->labelfont(FL_HELVETICA);
179 box->labelsize(14);
180 box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP|FL_ALIGN_WRAP);
181
182 CustInput3 *c_inp = new CustInput3(ih+2*gap,gap+ih/2+gap,ww-(ih+3*gap),24);
183 c_inp->labelsize(14);
184 c_inp->textsize(14);
185
186 CustChoice2 *ch = new CustChoice2(1*gap,ih+3*gap,180,24);
187 if (!pm) {
188 int n_it = dList_length(prefs.search_urls);
189 pm = (Fl_Menu_Item *) calloc(n_it+1, sizeof(Fl_Menu_Item));
190 if (pm == NULL) {
191 MSG("calloc failed: %s\n", strerror(errno));
192 exit(1);
193 }
194 for (int i = 0, j = 0; i < n_it; i++) {
195 char *label, *url, *source;
196 source = (char *)dList_nth_data(prefs.search_urls, i);
197 if (!source || a_Misc_parse_search_url(source, &label, &url) < 0)
198 continue;
199 pm[j++].label(FL_NORMAL_LABEL, dStrdup(label));
200 }
201 }
202 ch->tooltip("Select search engine");
203 ch->menu(pm);
204 ch->value(prefs.search_url_idx);
205
206 int xpos = ww-2*(gap+bw), ypos = ih+3*gap;
207 Fl_Return_Button *rb = new Fl_Return_Button(xpos, ypos, bw, bh, "OK");
208 rb->align(FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
209 rb->box(FL_UP_BOX);
210 rb->callback(input_cb, INT2VOIDP(1));
211
212 xpos = ww-(gap+bw);
213 Fl_Button *b = new Fl_Button(xpos, ypos, bw, bh, "Cancel");
214 b->align(FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
215 b->box(FL_UP_BOX);
216 b->callback(input_cb, INT2VOIDP(2));
217
218 window->end();
219
220 window->show();
221 while (window->shown())
222 Fl::wait();
223 if (input_answer == 1) {
224 /* we have a string, save it */
226 input_str = dStrdup(c_inp->value());
227 prefs.search_url_idx = ch->value();
228 }
229 delete window;
230
231 return (input_answer == 1) ? input_str : NULL;
232}
233
237const char *a_Dialog_passwd(const char *title, const char *msg)
238{
239 if (!(title && *title))
240 title = "Dillo: Password";
241 fl_message_title(title);
242 return fl_password("%s", "", msg);
243}
244
250const char *a_Dialog_save_file(const char *title,
251 const char *pattern, const char *fname)
252{
253 return fl_file_chooser(title, pattern, fname);
254}
255
261const char *a_Dialog_select_file(const char *title,
262 const char *pattern, const char *fname)
263{
264 /*
265 * FileChooser::type(MULTI) appears to allow multiple files to be selected,
266 * but just follow save_file's path for now.
267 */
268 return a_Dialog_save_file(title, pattern, fname);
269}
270
276char *a_Dialog_open_file(const char *title,
277 const char *pattern, const char *fname)
278{
279 const char *fc_name;
280
281 fc_name = fl_file_chooser(title, pattern, fname);
282 return (fc_name) ? a_Misc_escape_chars(fc_name, "% #") : NULL;
283}
284
288static void text_window_close_cb(Fl_Widget *, void *vtd)
289{
290 Fl_Text_Display *td = (Fl_Text_Display *)vtd;
291 Fl_Text_Buffer *buf = td->buffer();
292
293 delete (Fl_Window*)td->window();
294 delete buf;
295}
296
300void a_Dialog_text_window(const char *title, const char *txt)
301{
302 int wh = prefs.height, ww = prefs.width, bh = 30;
303
304 if (!(title && *title))
305 title = "Dillo: Text";
306
307 Fl_Window *window = new Fl_Window(ww, wh, title);
308 Fl_Group::current(0);
309
310
311 Fl_Text_Buffer *buf = new Fl_Text_Buffer();
312 buf->text(txt);
313 Fl_Text_Display *td = new Fl_Text_Display(0,0,ww, wh-bh);
314 td->buffer(buf);
315 td->textsize((int) rint(14.0 * prefs.font_factor));
316
317 /* enable wrapping lines; text uses entire width of window */
318 td->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0);
319 window->add(td);
320
321 Fl_Return_Button *b = new Fl_Return_Button (0, wh-bh, ww, bh, "Close");
322 b->callback(text_window_close_cb, td);
323 window->add(b);
324
325 window->callback(text_window_close_cb, td);
326 window->resizable(td);
327 window->show();
328}
329
330/*--------------------------------------------------------------------------*/
331
332static void choice_cb(Fl_Widget *button, void *number)
333{
334 choice_answer = VOIDP2INT(number);
335 _MSG("choice_cb: %d\n", choice_answer);
336
337 button->window()->hide();
338}
339
346int a_Dialog_choice(const char *title, const char *msg, ...)
347{
348 va_list ap;
349 int i, n;
350
351 if (title == NULL || *title == '\0')
352 title = "Dillo: Choice";
353
354 va_start(ap, msg);
355 for (n = 0; va_arg(ap, char *) != NULL; n++);
356 va_end(ap);
357
358 if (n == 0) {
359 MSG_ERR("Dialog_choice: no alternatives.\n");
360 return 0;
361 }
362
363 int gap = 8;
364 int ww = 140 + n * 60, wh = 120;
365 int bw = (ww - gap) / n - gap, bh = 45;
366
367 Fl_Window *window = new Fl_Window(ww, wh, title);
368 window->set_modal();
369 window->begin();
370
371 Fl_Text_Buffer *buf = new Fl_Text_Buffer();
372 buf->text(msg);
373 Fl_Text_Display *td = new Fl_Text_Display(0, 0, ww, wh - bh);
374 td->buffer(buf);
375 td->textsize((int) rint(14.0 * prefs.font_factor));
376 td->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0);
377
378 window->resizable(td);
379
380 int xpos = gap;
381 va_start(ap, msg);
382 for (i = 1; i <= n; i++) {
383 Fl_Button *b = new EnterButton(xpos, wh-bh, bw, bh, va_arg(ap, char *));
384 b->align(FL_ALIGN_WRAP | FL_ALIGN_CLIP);
385 b->box(FL_UP_BOX);
386 b->callback(choice_cb, INT2VOIDP(i));
387 xpos += bw + gap;
388 /* TODO: set focus to the *-prefixed alternative */
389 }
390 va_end(ap);
391 window->end();
392
393 choice_answer = 0;
394
395 window->show();
396 while (window->shown())
397 Fl::wait();
398 _MSG("Dialog_choice answer = %d\n", answer);
399 td->buffer(NULL);
400 delete buf;
401 delete window;
402
403 return choice_answer;
404}
405
406/*--------------------------------------------------------------------------*/
407static void Dialog_user_password_cb(Fl_Widget *button, void *)
408{
409 button->window()->user_data(button);
410 button->window()->hide();
411}
412
418int a_Dialog_user_password(const char *title, const char *msg,
419 UserPasswordCB cb, void *vp)
420{
421 int ok = 0, window_h = 280, y, msg_w, msg_h;
422 const int window_w = 300, input_x = 80, input_w = 200, input_h = 30,
423 button_h = 30;
424
425 /* window is resized below */
426 if (!(title && *title))
427 title = "Dillo: User/Password";
428 Fl_Window *window = new Fl_Window(window_w,window_h,title);
429 Fl_Group::current(0);
430 window->user_data(NULL);
431
432 /* message */
433 y = 20;
434 msg_w = window_w - 40;
435 Fl_Box *msg_box = new Fl_Box(20, y, msg_w, 100); /* resized below */
436 msg_box->label(msg);
437 msg_box->labelfont(FL_HELVETICA);
438 msg_box->labelsize(14);
439 msg_box->align(FL_ALIGN_INSIDE | FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP);
440
441 fl_font(msg_box->labelfont(), msg_box->labelsize());
442 msg_w -= 6; /* The label doesn't fill the entire box. */
443 fl_measure(msg_box->label(), msg_w, msg_h, 0); // fl_measure wraps at msg_w
444 msg_box->size(msg_box->w(), msg_h);
445 window->add(msg_box);
446
447 /* inputs */
448 y += msg_h + 20;
449 Fl_Input *user_input = new Fl_Input(input_x, y, input_w, input_h, "User");
450 user_input->labelsize(14);
451 user_input->textsize(14);
452 window->add(user_input);
453 y += input_h + 10;
454 Fl_Secret_Input *password_input =
455 new Fl_Secret_Input(input_x, y, input_w, input_h, "Password");
456 password_input->labelsize(14);
457 password_input->textsize(14);
458 window->add(password_input);
459
460 /* "OK" button */
461 y += input_h + 20;
462 Fl_Button *ok_button = new EnterButton(200, y, 50, button_h, "OK");
463 ok_button->labelsize(14);
464 ok_button->callback(Dialog_user_password_cb);
465 window->add(ok_button);
466
467 /* "Cancel" button */
468 Fl_Button *cancel_button =
469 new EnterButton(50, y, 100, button_h, "Cancel");
470 cancel_button->labelsize(14);
471 cancel_button->callback(Dialog_user_password_cb);
472 window->add(cancel_button);
473
474 y += button_h + 20;
475 window_h = y;
476 window->size(window_w, window_h);
477 window->size_range(window_w, window_h, window_w, window_h);
478 window->resizable(window);
479
480 window->show();
481 while (window->shown())
482 Fl::wait();
483
484 ok = ((Fl_Widget *)window->user_data()) == ok_button ? 1 : 0;
485
486 if (ok) {
487 /* call the callback */
488 const char *user, *password;
489 user = user_input->value();
490 password = password_input->value();
491 _MSG("a_Dialog_user_passwd: ok = %d\n", ok);
492 (*cb)(user, password, vp);
493 }
494 delete window;
495
496 return ok;
497}
498
#define _MSG(...)
Definition bookmarks.c:45
#define MSG(...)
Definition bookmarks.c:46
char * a_Dialog_open_file(const char *title, const char *pattern, const char *fname)
Show the open file dialog.
Definition dialog.cc:276
static char * input_str
Definition dialog.cc:43
int a_Dialog_choice(const char *title, const char *msg,...)
Make a question-dialog with a question and alternatives.
Definition dialog.cc:346
static int input_answer
Definition dialog.cc:42
void a_Dialog_msg(const char *title, const char *msg)
Display a message in a popup window.
Definition dialog.cc:128
static void Dialog_user_password_cb(Fl_Widget *button, void *)
Definition dialog.cc:407
const char * a_Dialog_save_file(const char *title, const char *pattern, const char *fname)
Show the save file dialog.
Definition dialog.cc:250
const char * a_Dialog_passwd(const char *title, const char *msg)
Dialog for password.
Definition dialog.cc:237
static int choice_answer
Definition dialog.cc:44
static void choice_cb(Fl_Widget *button, void *number)
Definition dialog.cc:332
void a_Dialog_text_window(const char *title, const char *txt)
Show a new window with the provided text.
Definition dialog.cc:300
static void text_window_close_cb(Fl_Widget *, void *vtd)
Close text window.
Definition dialog.cc:288
static void input_cb(Fl_Widget *button, void *number)
Callback for a_Dialog_input()
Definition dialog.cc:140
const char * a_Dialog_select_file(const char *title, const char *pattern, const char *fname)
Show the select file dialog.
Definition dialog.cc:261
int a_Dialog_user_password(const char *title, const char *msg, UserPasswordCB cb, void *vp)
Make a user/password dialog.
Definition dialog.cc:418
const char * a_Dialog_input(const char *title, const char *msg)
Dialog for one line of Input with a message.
Definition dialog.cc:152
void(* UserPasswordCB)(const char *user, const char *password, void *vp)
Definition dialog.hh:8
void dFree(void *mem)
Definition dlib.c:68
char * dStrdup(const char *s)
Definition dlib.c:77
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:641
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:690
#define VOIDP2INT(p)
Definition dlib.h:61
#define INT2VOIDP(i)
Definition dlib.h:62
#define MSG_ERR(...)
Definition dpid_common.h:23
static Fl_Window * window
int a_Misc_parse_search_url(char *source, char **label, char **urlstr)
Parse dillorc's search_url string ([<label> ]<url>) Return value: -1 on error, 0 on success (and labe...
Definition misc.c:391
char * a_Misc_escape_chars(const char *str, const char *esc_set)
Escape characters as XX sequences.
Definition misc.c:26
DilloPrefs prefs
Global Data.
Definition prefs.c:33
int width
Definition prefs.h:38
Dlist * search_urls
Definition prefs.h:120
double font_factor
Definition prefs.h:75
int height
Definition prefs.h:39
bool_t search_url_idx
Definition prefs.h:119