The R Project SVN R

Rev

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