The R Project SVN R

Rev

Rev 58001 | Rev 68288 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4394 ripley 1
/*
2
 * GraphApp - Cross-Platform Graphics Programming Library.
3
 *
4
 * File: dialogs.c -- standard file dialogs and a few others.
5
 * Platform: Windows  Version: 2.42  Date: 1998/07/07
6
 *
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
8
 * Version: 1.50  Changes: Uses new rectangles, callbacks.
9
 * Version: 2.20  Changes: Handle null strings correctly now.
10
 * Version: 2.40  Changes: Now uses YES, NO, CANCEL symbols.
11
 * Version: 2.42  Changes: Askstring fixed by Laurent Piguet.
12
 */
13
 
14
/* Copyright (C) 1993-1998 Lachlan Patrick
15
 
16
   This file is part of GraphApp, a cross-platform C graphics library.
17
 
18
   GraphApp is free software; you can redistribute it and/or modify it
19
   under the terms of the GNU Library General Public License.
20
   GraphApp is distributed in the hope that it will be useful, but
21
   WITHOUT ANY WARRANTY.
22
 
23
   See the file COPYLIB.TXT for details.
24
*/
25
 
45017 ripley 26
/* Copyright (C) 2004--2008	The R Foundation
28991 murdoch 27
 
28
   Additions for R, Chris Jackson
29
   Find and replace dialog boxes and dialog handlers */
30
 
58001 ripley 31
/* Mingw-w64 defines this to be 0x0502 */
32
#ifndef _WIN32_WINNT
33
# define _WIN32_WINNT 0x0500
34
#endif
35
 
42521 ripley 36
#include "win-nls.h"
4394 ripley 37
#include "internal.h"
28991 murdoch 38
#include "ga.h"
4394 ripley 39
 
38793 ripley 40
#include <shlobj.h>
41
 
43863 murdoch 42
typedef struct {
43
    char default_str[MAX_PATH];
44
    char question[40];
45
} browserInfo;
46
 
47
#define STATUSTEXT 14146
48
 
38793 ripley 49
static int CALLBACK
43152 ripley 50
InitBrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lp, LPARAM lpData )
38793 ripley 51
{
43863 murdoch 52
    char szDir[MAX_PATH], status[MAX_PATH + 40];
45017 ripley 53
 
43152 ripley 54
    if (uMsg == BFFM_INITIALIZED) {
43881 ripley 55
	SendMessage(hwnd, BFFM_SETSELECTION, 1,
56
		    (LPARAM)&((browserInfo*)lpData)->default_str);
43152 ripley 57
    } else if (uMsg == BFFM_SELCHANGED) {
43863 murdoch 58
	if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) {
45017 ripley 59
	    snprintf(status, MAX_PATH+40, "%s\n %s",
43881 ripley 60
		     ((browserInfo*)lpData)->question, szDir);
43863 murdoch 61
	    SetDlgItemText(hwnd, STATUSTEXT, status);
62
	    SendMessage(hwnd, BFFM_ENABLEOK, 0, TRUE);
63
	} else
64
	    SendMessage(hwnd, BFFM_ENABLEOK, 0, FALSE);
43152 ripley 65
    }
38793 ripley 66
    return(0);
67
}
68
 
22842 murdoch 69
#define BUFSIZE _MAX_PATH
70
static char strbuf[BUFSIZE];
46843 ripley 71
static wchar_t wcsbuf[65536];
4394 ripley 72
 
41793 ripley 73
static const char *filter[] = {
45017 ripley 74
    "All Files (*.*)",	"*.*",
75
    "Text Files (*.TXT)",	"*.txt",
76
    "HTML Files (*.HTM)",	"*.htm",
77
    "PNG Files (*.PNG)",	"*.png",
78
    "JPEG Files (*.JPG)",	"*.jpg",
79
    "BMP Files (*.BMP)",	"*.bmp",
80
    ""
4394 ripley 81
};
82
 
46843 ripley 83
static const wchar_t *wfilter[] = {
84
    L"All Files (*.*)",	L"*.*",
85
    L"Text Files (*.TXT)",	L"*.txt",
86
    L"HTML Files (*.HTM)",	L"*.htm",
87
    L"PNG Files (*.PNG)",	L"*.png",
88
    L"JPEG Files (*.JPG)",	L"*.jpg",
89
    L"BMP Files (*.BMP)",	L"*.bmp",
90
    L""
91
};
92
 
28854 murdoch 93
unsigned int TopmostDialogs = 0; /* May be MB_TOPMOST */
94
 
41793 ripley 95
static const char *userfilter;
46843 ripley 96
static const wchar_t *userfilterW;
97
 
45017 ripley 98
void setuserfilter(const char *uf)
99
{
100
    userfilter=uf;
4394 ripley 101
}
102
 
46843 ripley 103
void setuserfilterW(const wchar_t *uf)
104
{
105
    userfilterW=uf;
106
}
107
 
28991 murdoch 108
static HWND hModelessDlg = NULL;
109
 
41793 ripley 110
int myMessageBox(HWND h, const char *text, const char *caption, UINT type)
36921 ripley 111
{
43328 ripley 112
    if(localeCP != GetACP()) {
36921 ripley 113
	wchar_t wc[1000], wcaption[100];
114
	mbstowcs(wcaption, caption, 100);
115
	mbstowcs(wc, text, 1000);
116
	return MessageBoxW(h, wc, wcaption, type);
117
    } else
118
	return MessageBoxA(h, text, caption, type);
119
}
120
 
4394 ripley 121
/*
122
 *  Error reporting dialog.
123
 */
41793 ripley 124
void apperror(const char *errstr)
4394 ripley 125
{
45017 ripley 126
    if (! errstr)
127
	errstr = "Unspecified error";
128
    myMessageBox(0, errstr, "Graphics Library Error",
129
		 MB_TASKMODAL | MB_ICONSTOP | MB_OK | TopmostDialogs);
130
    exitapp();
4394 ripley 131
}
132
 
41793 ripley 133
void askok(const char *info)
4394 ripley 134
{
45017 ripley 135
    if (! info)
136
	info = "";
137
    myMessageBox(0, info, "Information",
138
		 MB_TASKMODAL | MB_ICONINFORMATION | MB_OK | TopmostDialogs);
4394 ripley 139
}
140
 
41793 ripley 141
int askokcancel(const char *question)
4394 ripley 142
{
45017 ripley 143
    int result;
4394 ripley 144
 
45017 ripley 145
    if (! question)
146
	question = "";
147
    result = myMessageBox(0, question, G_("Question"),
148
			  MB_TASKMODAL | MB_ICONQUESTION | MB_OKCANCEL | TopmostDialogs);
4394 ripley 149
 
45017 ripley 150
    switch (result) {
151
    case IDOK: result = YES; break;
152
    case IDCANCEL:
153
    default: result = CANCEL; break;
154
    }
155
    return result;
4394 ripley 156
}
157
 
41793 ripley 158
int askyesno(const char *question)
4394 ripley 159
{
45017 ripley 160
    int result;
4394 ripley 161
 
45017 ripley 162
    if (! question)
163
	question = "";
164
    result = myMessageBox(0, question, G_("Question"),
165
			  MB_TASKMODAL | MB_ICONQUESTION | MB_YESNO | TopmostDialogs);
4394 ripley 166
 
45017 ripley 167
    switch (result) {
168
    case IDYES: result = YES; break;
169
    case IDNO:  result = NO; break;
170
    default: result = CANCEL; break;
171
    }
172
    return result;
4394 ripley 173
}
174
 
41793 ripley 175
int askyesnocancel(const char *question)
4394 ripley 176
{
45017 ripley 177
    int result;
4394 ripley 178
 
45017 ripley 179
    if (! question)
180
	question = "";
181
    result = myMessageBox(0, question, G_("Question"),
182
			  MB_TASKMODAL | MB_ICONQUESTION | MB_YESNOCANCEL | MB_SETFOREGROUND | TopmostDialogs);
4394 ripley 183
 
45017 ripley 184
    switch (result) {
185
    case IDYES: result = YES; break;
186
    case IDNO:  result = NO; break;
187
    case IDCANCEL:
188
    default: result = CANCEL; break;
189
    }
190
    return result;
4394 ripley 191
}
192
 
46843 ripley 193
/* This should always have a native encoded name, so don't need Unicode here */
4394 ripley 194
static char cod[MAX_PATH]=""; /*current open directory*/
195
 
196
void askchangedir()
197
{
4606 ripley 198
    char *s, msg[MAX_PATH + 40];
199
 
62096 murdoch 200
/* set cod to current directory */
201
    GetCurrentDirectory(MAX_PATH, cod);
33088 ripley 202
    s = askcdstring(G_(" Change working directory to:"), cod);
4606 ripley 203
    if (s && (SetCurrentDirectory(s) == FALSE)) {
25313 ripley 204
	snprintf(msg, MAX_PATH + 40,
33088 ripley 205
		 G_("Unable to set '%s' as working directory"), s);
4606 ripley 206
	askok(msg);
207
    }
208
    /* in every case reset cod (to new directory if all went ok
46843 ripley 209
       or to old since user may have edited it) */
4606 ripley 210
    GetCurrentDirectory(MAX_PATH, cod);
4394 ripley 211
}
212
 
41793 ripley 213
char *askfilename(const char *title, const char *default_name)
4394 ripley 214
{
45017 ripley 215
    if (*askfilenames(title, default_name, 0, userfilter?userfilter:filter[0], 0,
216
		      strbuf, BUFSIZE, NULL)) return strbuf;
217
    else return NULL;
4394 ripley 218
}
219
 
41793 ripley 220
char *askfilenamewithdir(const char *title, const char *default_name, const char *dir)
37592 murdoch 221
{
46843 ripley 222
    if (*askfilenames(title, default_name, 0, 
223
		      userfilter ? userfilter : filter[0], 0,
45017 ripley 224
		      strbuf, BUFSIZE, dir)) return strbuf;
225
    else return NULL;
37592 murdoch 226
}
227
 
41793 ripley 228
char *askfilenames(const char *title, const char *default_name, int multi,
229
		   const char *filters, int filterindex,
38990 ripley 230
		   char *strbuf, int bufsize,
41793 ripley 231
		   const char *dir)
22842 murdoch 232
{
45017 ripley 233
    int i;
234
    OPENFILENAME ofn;
235
    char cwd[MAX_PATH] = "";
45927 murdoch 236
    HWND prev = GetFocus();
38990 ripley 237
 
45017 ripley 238
    if (!default_name) default_name = "";
239
    strcpy(strbuf, default_name);
240
    GetCurrentDirectory(MAX_PATH, cwd);
46843 ripley 241
    if (!cod[0]) strcpy(cod, cwd);
22842 murdoch 242
 
45017 ripley 243
    ofn.lStructSize     = sizeof(OPENFILENAME);
244
    ofn.hwndOwner       = current_window ? current_window->handle : 0;
245
    ofn.hInstance       = 0;
246
    ofn.lpstrFilter     = filters;
247
    ofn.lpstrCustomFilter = NULL;
248
    ofn.nMaxCustFilter  = 0;
249
    ofn.nFilterIndex    = filterindex;
250
    ofn.lpstrFile       = strbuf;
251
    ofn.nMaxFile        = bufsize;
252
    ofn.lpstrFileTitle  = NULL;
253
    ofn.nMaxFileTitle   = _MAX_FNAME + _MAX_EXT;
46843 ripley 254
    ofn.lpstrInitialDir = dir ? dir : cod;
45017 ripley 255
    ofn.lpstrTitle      = title;
256
    ofn.Flags           = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER;
257
    if (multi) ofn.Flags |= OFN_ALLOWMULTISELECT;
258
    ofn.nFileOffset     = 0;
259
    ofn.nFileExtension  = 0;
260
    ofn.lpstrDefExt     = "*";
261
    ofn.lCustData       = 0L;
262
    ofn.lpfnHook        = NULL;
263
    ofn.lpTemplateName  = NULL;
22842 murdoch 264
 
45017 ripley 265
    if (GetOpenFileName(&ofn) == 0) {
46843 ripley 266
	if(!dir) GetCurrentDirectory(MAX_PATH, cod);
45017 ripley 267
	SetCurrentDirectory(cwd);
268
	strbuf[0] = 0;
269
	strbuf[1] = 0;
270
    } else {
46843 ripley 271
	if(!dir) GetCurrentDirectory(MAX_PATH, cod);
45017 ripley 272
	SetCurrentDirectory(cwd);
273
	for (i = 0; i <  10; i++) if (peekevent()) doevent();
274
    }
45927 murdoch 275
    SetFocus(prev);
276
    return strbuf;
22842 murdoch 277
}
278
 
46843 ripley 279
wchar_t *askfilenameW(const char *title, const char *default_name)
280
{
281
    wchar_t wtitle[1000], wdef_name[MAX_PATH];
282
 
283
    mbstowcs(wtitle, title, 1000);
284
    if (!default_name) wcscpy(wdef_name, L"");
285
    else mbstowcs(wdef_name, default_name, MAX_PATH);
286
    if (*askfilenamesW(wtitle, wdef_name, 0, 
287
		       userfilterW ? userfilterW : wfilter[0], 0,
288
		       NULL)) return wcsbuf;
289
    else return NULL;
290
}
291
 
292
wchar_t *askfilenamesW(const wchar_t *title, const wchar_t *default_name,
293
		       int multi,
294
		       const wchar_t *filters, int filterindex,
295
		       const wchar_t *dir)
296
{
297
    int i;
298
    OPENFILENAMEW ofn;
299
    char cwd[MAX_PATH];
300
    wchar_t wcod[MAX_PATH];
301
    HWND prev = GetFocus();
302
 
303
    if (!default_name) default_name = L"";
304
    wcscpy(wcsbuf, default_name);
305
    GetCurrentDirectory(MAX_PATH, cwd);
306
    if (!strcmp(cod, "")) {
307
	if (!dir) GetCurrentDirectoryW(MAX_PATH, wcod); else wcscpy(wcod, dir);
308
    } else
309
	mbstowcs(wcod, cod, MAX_PATH);
310
 
311
    ofn.lStructSize     = sizeof(OPENFILENAME);
312
    ofn.hwndOwner       = current_window ? current_window->handle : 0;
313
    ofn.hInstance       = 0;
314
    ofn.lpstrFilter     = filters;
315
    ofn.lpstrCustomFilter = NULL;
316
    ofn.nMaxCustFilter  = 0;
317
    ofn.nFilterIndex    = filterindex;
318
    ofn.lpstrFile       = wcsbuf;
319
    ofn.nMaxFile        = 65520; /* precaution against overflow */
320
    ofn.lpstrFileTitle  = NULL;
321
    ofn.nMaxFileTitle   = _MAX_FNAME + _MAX_EXT;
322
    ofn.lpstrInitialDir = wcod;
323
    ofn.lpstrTitle      = title;
324
    ofn.Flags           = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER;
325
    if (multi) ofn.Flags |= OFN_ALLOWMULTISELECT;
326
    ofn.nFileOffset     = 0;
327
    ofn.nFileExtension  = 0;
328
    ofn.lpstrDefExt     = L"*";
329
    ofn.lCustData       = 0L;
330
    ofn.lpfnHook        = NULL;
331
    ofn.lpTemplateName  = NULL;
332
 
333
    if (GetOpenFileNameW(&ofn) == 0) {
334
	/* This could fail if the Unicode name is not a native name */
335
	DWORD res = GetCurrentDirectory(MAX_PATH, cod);
336
	if(res) strcpy(cod, cwd);
337
	SetCurrentDirectory(cwd);
338
	wcsbuf[0] = 0;
339
	wcsbuf[1] = 0;
340
    } else {
341
	DWORD res = GetCurrentDirectory(MAX_PATH, cod);
342
	if(res) strcpy(cod, cwd);
343
	SetCurrentDirectory(cwd);
344
	for (i = 0; i <  10; i++) if (peekevent()) doevent();
345
    }
346
    SetFocus(prev);
347
    return wcsbuf;
348
}
349
 
41793 ripley 350
int countFilenames(const char *list)
22842 murdoch 351
{
45017 ripley 352
    const char *temp;
353
    int count;
354
    count = 0;
355
    for (temp = list; *temp; temp += strlen(temp)+1) count++;
356
    return count;
22842 murdoch 357
}
358
 
41793 ripley 359
char *askfilesave(const char *title, const char *default_name)
4394 ripley 360
{
8707 ripley 361
    return askfilesavewithdir(title, default_name, NULL);
362
}
363
 
46843 ripley 364
wchar_t *askfilesaveW(const char *title, const char *default_name) 
8707 ripley 365
{
45017 ripley 366
    int i;
46843 ripley 367
    OPENFILENAMEW ofn;
368
    wchar_t cwd[MAX_PATH], wdef_name[MAX_PATH], wtitle[1000];
369
 
370
    if (!default_name) wcscpy(wdef_name, L"");
371
    else mbstowcs(wdef_name, default_name, MAX_PATH);
372
    wcscpy(wcsbuf, wdef_name);
373
    mbstowcs(wtitle, title, 1000);
374
 
375
    ofn.lStructSize     = sizeof(OPENFILENAME);
376
    ofn.hwndOwner       = current_window ? current_window->handle : 0;
377
    ofn.hInstance       = 0;
378
    ofn.lpstrFilter     = userfilterW ? userfilterW : wfilter[0];
379
    ofn.lpstrCustomFilter = NULL;
380
    ofn.nMaxCustFilter  = 0;
381
    ofn.nFilterIndex    = 0;
382
    ofn.lpstrFile       = wcsbuf;
383
    ofn.nMaxFile        = BUFSIZE;
384
    ofn.lpstrFileTitle  = NULL;
385
    ofn.nMaxFileTitle   = _MAX_FNAME + _MAX_EXT;
386
    if (GetCurrentDirectoryW(MAX_PATH, cwd))
387
	ofn.lpstrInitialDir = cwd;
388
    else
389
	ofn.lpstrInitialDir = NULL;
390
    ofn.lpstrTitle      = wtitle;
391
    ofn.Flags           = OFN_OVERWRITEPROMPT |
392
	OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
393
    ofn.nFileOffset     = 0;
394
    ofn.nFileExtension  = 0;
395
    ofn.lpstrDefExt     = NULL;
396
    ofn.lCustData       = 0L;
397
    ofn.lpfnHook        = NULL;
398
    ofn.lpTemplateName  = NULL;
399
 
400
    if (GetSaveFileNameW(&ofn) == 0)
401
	return NULL;
402
    else {
403
	for (i = 0; i < 10; i++) if (peekevent()) doevent();
404
	return wcsbuf;
405
    }
406
}
407
 
408
char *askfilesavewithdir(const char *title, const char *default_name,
409
			 const char *dir)
410
{
411
    int i;
45017 ripley 412
    OPENFILENAME ofn;
46843 ripley 413
    char cwd[MAX_PATH], *defext = NULL;
4394 ripley 414
 
45017 ripley 415
    if (!default_name) default_name = "";
416
    else if(default_name[0] == '|') {
417
	defext = (char *)default_name + 2;
418
	default_name = "";
419
    }
420
    strcpy(strbuf, default_name);
4394 ripley 421
 
45017 ripley 422
    ofn.lStructSize     = sizeof(OPENFILENAME);
423
    ofn.hwndOwner       = current_window ? current_window->handle : 0;
424
    ofn.hInstance       = 0;
425
    ofn.lpstrFilter     = userfilter?userfilter:filter[0];
426
    ofn.lpstrCustomFilter = NULL;
427
    ofn.nMaxCustFilter  = 0;
428
    ofn.nFilterIndex    = 0;
429
    ofn.lpstrFile       = strbuf;
430
    ofn.nMaxFile        = BUFSIZE;
431
    ofn.lpstrFileTitle  = NULL;
432
    ofn.nMaxFileTitle   = _MAX_FNAME + _MAX_EXT;
433
    if(dir && strlen(dir) > 0) {
434
	strcpy(cwd, dir);
46843 ripley 435
	/* This should have been set to use backslashes in the caller */
45017 ripley 436
	ofn.lpstrInitialDir = cwd;
437
    } else {
438
	if (GetCurrentDirectory(MAX_PATH, cwd))
38990 ripley 439
	    ofn.lpstrInitialDir = cwd;
45017 ripley 440
	else
441
	    ofn.lpstrInitialDir = NULL;
442
    }
443
    ofn.lpstrTitle      = title;
444
    ofn.Flags           = OFN_OVERWRITEPROMPT |
445
	OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
446
    ofn.nFileOffset     = 0;
447
    ofn.nFileExtension  = 0;
448
    ofn.lpstrDefExt     = defext;
449
    ofn.lCustData       = 0L;
450
    ofn.lpfnHook        = NULL;
451
    ofn.lpTemplateName  = NULL;
4394 ripley 452
 
45017 ripley 453
    if (GetSaveFileName(&ofn) == 0)
454
	return NULL;
455
    else {
456
	for (i = 0; i < 10; i++) if (peekevent()) doevent();
457
	return strbuf;
458
    }
4394 ripley 459
}
460
 
461
/*
462
 *  Input a string using a dialog box.
463
 */
464
 
465
/*
466
 *  Dialog information structure:
467
 */
45017 ripley 468
#define NOT_CHOSEN_YET -2
4394 ripley 469
 
45017 ripley 470
typedef struct dialog_data_class {
471
    int	hit;
472
    char *	result;
473
    label	question;
474
    field	text, pass;
475
    button	yes, no, cancel;
476
} dialog_data;
4394 ripley 477
 
45017 ripley 478
#define data(w) ((dialog_data *) (getdata(w)))
4394 ripley 479
 
480
/*
481
 *  Some strings to use:
482
 */
37809 ripley 483
/*	static char * OKAY_STRING	= "OK";
4394 ripley 484
	static char * CANCEL_STRING	= "Cancel";
37809 ripley 485
	static char * BROWSE_STRING	= "Browse"; */
4394 ripley 486
 
45017 ripley 487
static const char * QUESTION_TITLE	= "Question";
488
static const char * PASSWORD_TITLE	= "Password Entry";
4394 ripley 489
 
490
static void add_data(window w)
491
{
45017 ripley 492
    dialog_data *d;
4394 ripley 493
 
45017 ripley 494
    d = create (dialog_data);
495
    if (! d)
496
	return;
497
    d->hit = NOT_CHOSEN_YET;
4394 ripley 498
 
45017 ripley 499
    setdata(w, d);
4394 ripley 500
}
501
 
502
static char * get_dialog_string(window w)
503
{
45017 ripley 504
    dialog_data *d = data(w);
4394 ripley 505
 
45017 ripley 506
    if (d->hit < YES) /* cancelled */
507
	return NULL;
508
    del_string(d->result);
509
    if (d->text)	/* question dialog */
510
	d->result = new_string(GA_gettext(d->text));
4394 ripley 511
 
45017 ripley 512
    return d->result;
4394 ripley 513
}
514
 
515
static void hit_button(control c)
516
{
45017 ripley 517
    window w = parentwindow(c);
518
    dialog_data *d = data(w);
519
    int value = getvalue(c);
4394 ripley 520
 
45017 ripley 521
    d->hit = value;
522
    hide(w);
4394 ripley 523
}
524
 
525
static void hit_key(window w, int key)
526
{
45017 ripley 527
    button btn;
528
    char *name = NULL;
4394 ripley 529
 
45017 ripley 530
    w = parentwindow(w);
4394 ripley 531
 
45017 ripley 532
    if (data(w) == NULL)
533
	return;
4394 ripley 534
 
45017 ripley 535
    if ((btn = data(w)->yes) != NULL) {
536
	name = getname(btn);
537
	if ((key == '\n') || (tolower(name[0]) == tolower(key)))
538
	{
539
	    flashcontrol(btn);
540
	    activatecontrol(btn);
541
	    return;
4394 ripley 542
	}
45017 ripley 543
    }
4394 ripley 544
 
45017 ripley 545
    if ((btn = data(w)->cancel) != NULL) {
546
	name = getname(btn);
547
	if ((key == ESC) || (tolower(name[0]) == tolower(key)))
548
	{
549
	    flashcontrol(btn);
550
	    activatecontrol(btn);
551
	    return;
4394 ripley 552
	}
45017 ripley 553
    }
4394 ripley 554
 
45017 ripley 555
    if ((btn = data(w)->no) != NULL) {
556
	name = getname(btn);
557
	if ((key == ESC) || (tolower(name[0]) == tolower(key)))
558
	{
559
	    flashcontrol(btn);
560
	    activatecontrol(btn);
561
	    return;
4394 ripley 562
	}
45017 ripley 563
    }
4394 ripley 564
 
565
}
566
 
567
/*
568
 *  Handle the events from a message dialog, hide the window afterwards.
569
 */
570
static int handle_message_dialog(window w)
571
{
45017 ripley 572
    window old;
573
    dialog_data *d = data(w);
4394 ripley 574
 
45017 ripley 575
    old = currentdrawing();
576
    d->hit = NOT_CHOSEN_YET;
4394 ripley 577
 
45017 ripley 578
    show(w);
579
    while (d->hit == NOT_CHOSEN_YET) {
580
	if (!peekevent()) WaitMessage();
581
	doevent();
582
    }
583
    hide(w);
4394 ripley 584
 
45017 ripley 585
    if (old) drawto(old);
4394 ripley 586
 
45017 ripley 587
    return d->hit;
4394 ripley 588
}
589
 
41793 ripley 590
static window init_askstr_dialog(const char *title, const char *question,
591
				 const char *default_str)
4394 ripley 592
{
45017 ripley 593
    window win;
594
    dialog_data *d;
595
    int tw, bw, h, middle;
4394 ripley 596
 
45017 ripley 597
    if (! question)
598
	question= "";
599
    if (! default_str)
600
	default_str = "";
4394 ripley 601
 
45017 ripley 602
    tw = strwidth(SystemFont, G_("Cancel")) * 8;
603
    h = getheight(SystemFont);
4394 ripley 604
 
45017 ripley 605
    if (tw < 150) tw = 150;
4394 ripley 606
 
45017 ripley 607
    win = newwindow(title, rect(0,0,tw+30,h*9+12),
608
		    Titlebar | Centered | Modal);
609
    setbackground(win, dialog_bg());
610
    add_data(win);
611
    d = data(win);
612
    d->question = newlabel(question, rect(10,h,tw+4,h*2+2),
613
			   AlignLeft);
614
    if (title == PASSWORD_TITLE)
615
	d->text = newpassword(default_str, rect(10,h*4,tw+4,h*3/2));
616
    else
617
	d->text = newfield(default_str, rect(10,h*4,tw+4,h*3/2));
4394 ripley 618
 
45017 ripley 619
    middle = (tw+30)/2;
620
    bw = strwidth(SystemFont, G_("Cancel")) * 3/2;
4394 ripley 621
 
45017 ripley 622
    d->yes = newbutton(G_("OK"),
623
		       rect(middle-bw-10, h*7, bw, h+10), hit_button);
624
    setvalue(d->yes, YES);
4394 ripley 625
 
45017 ripley 626
    d->cancel = newbutton(G_("Cancel"),
627
			  rect(middle+10, h*7, bw, h+10), hit_button);
628
    setvalue(d->cancel, CANCEL);
4394 ripley 629
 
45017 ripley 630
    setkeydown(win, hit_key);
4394 ripley 631
 
45017 ripley 632
    return win;
4394 ripley 633
}
634
 
41793 ripley 635
char *askstring(const char *question, const char *default_str)
4394 ripley 636
{
45017 ripley 637
    static window win = NULL;
638
    window prev = current_window;
4394 ripley 639
 
45017 ripley 640
    if (! win)
641
	win = init_askstr_dialog(QUESTION_TITLE, question, default_str);
642
    else {
643
	settext(data(win)->question, question);
644
	settext(data(win)->text, default_str);
645
    }
646
    if (TopmostDialogs & MB_TOPMOST)
647
	BringToTop(win, 1);
648
    handle_message_dialog(win);
649
    current_window = prev;
28854 murdoch 650
 
45017 ripley 651
    return get_dialog_string(win);
4394 ripley 652
}
653
 
41793 ripley 654
char *askcdstring(const char *question, const char *default_str)
4606 ripley 655
{
43863 murdoch 656
    LPMALLOC g_pMalloc;
657
    BROWSEINFO bi;
658
    LPITEMIDLIST pidlBrowse;
659
    browserInfo info;
43881 ripley 660
    OSVERSIONINFOEX osvi;
45017 ripley 661
 
43863 murdoch 662
    strncpy(info.question, question, 40);
663
    strncpy(info.default_str, default_str, MAX_PATH);
4606 ripley 664
 
43863 murdoch 665
    /* Get the shell's allocator. */
666
    if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) return NULL;
28854 murdoch 667
 
43881 ripley 668
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
669
    GetVersionEx((OSVERSIONINFO *)&osvi);
670
 
43863 murdoch 671
    ZeroMemory(&bi, sizeof(bi));
672
    bi.hwndOwner = 0;
43881 ripley 673
    if(osvi.dwMajorVersion >= 6) { /* future proof */
45017 ripley 674
	/* CSIDL_DESKTOP gets mapped to the User's desktop in Vista
675
	   (a bug).  SHGetFolderLocation is Win2k or later */
676
	if (!SUCCEEDED(SHGetFolderLocation(NULL, CSIDL_DRIVES, NULL, 0,
677
					   (LPITEMIDLIST *) &bi.pidlRoot)))
678
	    return NULL;
43881 ripley 679
    }  /* else it is 0, which is CSIDL_DESKTOP */
43863 murdoch 680
    bi.pszDisplayName = strbuf;
681
    bi.lpszTitle = question;
682
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
683
    bi.lpfn = (BFFCALLBACK) InitBrowseCallbackProc;
684
    bi.lParam = (LPARAM) &info;
685
 
686
    /* Browse for a folder and return its PIDL. */
687
    pidlBrowse = SHBrowseForFolder(&bi);
688
    if (pidlBrowse != NULL) {
689
	SHGetPathFromIDList(pidlBrowse, strbuf);
45017 ripley 690
	g_pMalloc->lpVtbl->Free(g_pMalloc, pidlBrowse);
691
	if (strbuf[0])
692
	    return strbuf;
43863 murdoch 693
    }
694
    return NULL;
4606 ripley 695
}
696
 
41793 ripley 697
char *askpassword(const char *question, const char *default_str)
4394 ripley 698
{
45017 ripley 699
    static window win = NULL;
700
    window prev = current_window;
4394 ripley 701
 
45017 ripley 702
    if (! win)
703
	win = init_askstr_dialog(PASSWORD_TITLE, question, default_str);
704
    else {
705
	settext(data(win)->question, question);
706
	settext(data(win)->text, default_str);
707
    }
708
    if (TopmostDialogs & MB_TOPMOST)
709
	BringToTop(win, 1);
710
    handle_message_dialog(win);
711
    current_window = prev;
28854 murdoch 712
 
45017 ripley 713
    return get_dialog_string(win);
4394 ripley 714
}
715
 
41793 ripley 716
char *askUserPass(const char *title)
22785 ripley 717
{
718
    static window win = NULL;
719
    dialog_data *d;
720
    window prev = current_window;
721
 
722
    if (! win) {
723
	int tw, bw, h, middle;
724
 
37809 ripley 725
	tw = strwidth(SystemFont, G_("Cancel")) * 8;
22785 ripley 726
	h = getheight(SystemFont);
727
	if (tw < 150) tw = 150;
728
	win = newwindow(title, rect(0, 0, tw+30, h*9+12),
729
			Titlebar | Centered | Modal);
45017 ripley 730
	setbackground(win, dialog_bg());
22785 ripley 731
	add_data(win);
732
	d = data(win);
33088 ripley 733
	d->question = newlabel(G_("User"), rect(10, h, tw+4, h*2+2), AlignLeft);
734
	bw = strwidth(SystemFont, G_("Password"));
22785 ripley 735
	d->text = newfield("", rect(20+bw, h, tw-6-bw, h*3/2));
33093 ripley 736
	newlabel(_("Password"), rect(10, h*4, tw+4, h*2+2), AlignLeft);
22785 ripley 737
	d->pass = newpassword("", rect(20+bw, h*4, tw-6-bw, h*3/2));
738
	middle = (tw+30)/2;
37809 ripley 739
	bw = strwidth(SystemFont, G_("Cancel")) * 3/2;
22785 ripley 740
 
37809 ripley 741
	d->yes = newbutton(G_("OK"),
742
			   rect(middle-bw-10, h*7, bw, h+10), hit_button);
22785 ripley 743
	setvalue(d->yes, YES);
744
 
37809 ripley 745
	d->cancel = newbutton(G_("Cancel"),
746
			      rect(middle+10, h*7, bw, h+10), hit_button);
22785 ripley 747
	setvalue(d->cancel, CANCEL);
748
 
749
	setkeydown(win, hit_key);
750
    } else {
751
	d = data(win);
752
	settext(d->text, "");
753
	settext(d->pass, "");
754
    }
28854 murdoch 755
    if (TopmostDialogs & MB_TOPMOST)
756
	BringToTop(win, 1);
22785 ripley 757
    handle_message_dialog(win);
758
    current_window = prev;
759
    {
760
	char *user, *pass;
761
	static char buf[1000];
762
	if (d->hit < YES) /* cancelled */ return "";
39274 ripley 763
	if (d->text) user = new_string(GA_gettext(d->text));
22785 ripley 764
	else return "";
39274 ripley 765
	if (d->pass) pass = new_string(GA_gettext(d->pass));
22785 ripley 766
	else return "";
25313 ripley 767
	snprintf(buf, 1000, "%s:%s", user, pass);
22785 ripley 768
	return buf;
769
    }
770
    return ""; /* -Wall */
771
}
28991 murdoch 772
 
773
int modeless_active()
774
{
775
    if (hModelessDlg)
776
	return 1;
777
    return 0;
778
}
779
 
780
PROTECTED
781
HWND get_modeless()
782
{
783
    return hModelessDlg;
784
}
785
 
45017 ripley 786
void finddialog(textbox t)
787
{
28991 murdoch 788
    static FINDREPLACE fr;
789
    static char szFindWhat[80];
790
 
791
    fr.lStructSize = sizeof(fr);
792
    fr.hwndOwner = t->handle;
793
    fr.lpstrFindWhat = szFindWhat;
794
    fr.wFindWhatLen = 80;
795
    fr.Flags = FR_DOWN;
796
    fr.lCustData        = 0 ;
797
    fr.lpfnHook         = NULL ;
798
    fr.lpTemplateName   = NULL ;
799
 
800
    hModelessDlg = FindText(&fr);
801
}
802
 
45017 ripley 803
void replacedialog(textbox t)
804
{
28991 murdoch 805
    static FINDREPLACE fr;
806
    static char szFindWhat[80];
807
    static char szReplaceWith[80];
808
 
809
    fr.lStructSize = sizeof(fr);
810
    fr.hwndOwner = t->handle;
811
    fr.lpstrFindWhat = szFindWhat;
812
    fr.lpstrReplaceWith = szReplaceWith;
813
    fr.wFindWhatLen = 80;
814
    fr.wReplaceWithLen = 80;
815
    fr.Flags = FR_DOWN;
816
    fr.lCustData        = 0 ;
817
    fr.lpfnHook         = NULL ;
818
    fr.lpTemplateName   = NULL ;
819
 
820
    hModelessDlg = ReplaceText(&fr);
821
}
822
 
823
 
43889 ripley 824
#include <richedit.h>
28991 murdoch 825
/* Find and select a string in a rich edit control */
826
 
41793 ripley 827
static int richeditfind(HWND hwnd, char *what, int matchcase,
828
			int wholeword, int down)
28991 murdoch 829
{
830
    long start, end;
831
    CHARRANGE sel;
832
    WPARAM w = 0;
833
    FINDTEXTEX ft;
834
    sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ;
835
    start = sel.cpMin;
836
    end = sel.cpMax;
837
    ft.lpstrText = what;
838
    ft.chrgText.cpMin = start;
839
    ft.chrgText.cpMax = end;
840
    if (down) {
841
	w = w | FR_DOWN;
842
	ft.chrg.cpMin = end;
843
	ft.chrg.cpMax = -1;
844
    }
845
    else {
846
	ft.chrg.cpMin = start;
847
	ft.chrg.cpMax = 0;
848
    }
849
    if (matchcase) w = w | FR_MATCHCASE;
850
    if (wholeword) w = w | FR_WHOLEWORD;
851
    if (sendmessage(hwnd, EM_FINDTEXTEX, w, &ft) == -1)
852
	return 0;
853
    else {
854
	sendmessage (hwnd, EM_EXSETSEL, 0, &(ft.chrgText));
855
	sendmessage (hwnd, EM_SCROLLCARET, 0, 0) ;
856
    }
857
    return 1;
858
}
859
 
41793 ripley 860
static int richeditreplace(HWND hwnd, char *what, char *replacewith,
861
			   int matchcase, int wholeword, int down)
28991 murdoch 862
{
863
    /* If current selection is the find string, replace it and find next */
864
    long start, end;
865
    CHARRANGE sel;
866
    char *buf;
867
    textbox t = find_by_handle(hwnd);
31401 murdoch 868
    if (t) {
869
	sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ;
870
	start = sel.cpMin;
871
	end = sel.cpMax;
872
	if (start < end) {
873
	    buf = (char *) malloc(end - start + 1);
874
	    sendmessage(hwnd, EM_GETSELTEXT, 0, buf);
875
	    if (!strcmp(buf, what)) {
876
		checklimittext(t, strlen(replacewith) - strlen(what) + 2);
877
		sendmessage (hwnd, EM_REPLACESEL, 1, replacewith);
878
	    }
879
	    free(buf);
28991 murdoch 880
	}
31401 murdoch 881
	/* else just find next */
882
	if (richeditfind(hwnd, what, matchcase, wholeword, down))
883
	    return 1;
28991 murdoch 884
    }
885
    return 0;
886
}
887
 
888
PROTECTED
889
void handle_findreplace(HWND hwnd, LPFINDREPLACE pfr)
890
{
891
    CHARRANGE sel;
892
    int matchcase=0, wholeword=0, down=0;
893
    char buf[100];
894
    if (pfr->Flags & FR_MATCHCASE) matchcase = 1;
895
    if (pfr->Flags & FR_WHOLEWORD) wholeword = 1;
896
    if (pfr->Flags & FR_DOWN) down = 1;
897
 
898
    if (pfr->Flags & FR_FINDNEXT) {
899
	if (!richeditfind(hwnd, pfr->lpstrFindWhat, matchcase, wholeword, down)) {
33088 ripley 900
	    snprintf(buf, 100, G_("\"%s\" not found"), pfr->lpstrFindWhat);
28991 murdoch 901
	    askok(buf);
902
	}
903
    }
904
    else if (pfr->Flags & FR_REPLACE) {
905
	if (!richeditreplace(hwnd, pfr->lpstrFindWhat, pfr->lpstrReplaceWith, matchcase, wholeword, down)) {
33088 ripley 906
	    snprintf(buf, 100, G_("\"%s\" not found"), pfr->lpstrFindWhat);
28991 murdoch 907
	    askok(buf);
908
	}
909
    }
910
    else if (pfr->Flags & FR_REPLACEALL) {
911
	/* replace all in the whole buffer then return to original selection state */
912
	sendmessage (hwnd, EM_EXGETSEL, 0, &sel) ;
913
	sendmessage (hwnd, EM_SETSEL, 0, 0) ;
914
	while ( richeditreplace(hwnd, pfr->lpstrFindWhat, pfr->lpstrReplaceWith, matchcase, wholeword, down) ) ;
915
	sendmessage (hwnd, EM_EXSETSEL, 0, &sel) ;
916
    }
917
 
918
    else if (pfr->Flags & FR_DIALOGTERM)
919
	hModelessDlg = NULL;
920
}