OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [win/] [tkWinDialog.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkWinDialog.c --
3
 *
4
 *      Contains the Windows implementation of the common dialog boxes.
5
 *
6
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
7
 *
8
 * See the file "license.terms" for information on usage and redistribution
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
 *
11
 * RCS: @(#) $Id: tkWinDialog.c,v 1.1.1.1 2002-01-16 10:26:02 markom Exp $
12
 *
13
 */
14
 
15
#include "tkWinInt.h"
16
#include "tkFileFilter.h"
17
 
18
#include <commdlg.h>    /* includes common dialog functionality */
19
#include <dlgs.h>       /* includes common dialog template defines */
20
#include <cderr.h>      /* includes the common dialog error codes */
21
 
22
#if ((TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION <= 2))
23
/*
24
 * The following function is implemented on tk4.3 and after only
25
 */
26
#define Tk_GetHWND TkWinGetHWND
27
#endif
28
 
29
#define SAVE_FILE 0
30
#define OPEN_FILE 1
31
 
32
/*----------------------------------------------------------------------
33
 * MsgTypeInfo --
34
 *
35
 *      This structure stores the type of available message box in an
36
 *      easy-to-process format. Used by th Tk_MessageBox() function
37
 *----------------------------------------------------------------------
38
 */
39
typedef struct MsgTypeInfo {
40
    char * name;
41
    int type;
42
    int numButtons;
43
    char * btnNames[3];
44
} MsgTypeInfo;
45
 
46
#define NUM_TYPES 6
47
 
48
static MsgTypeInfo
49
msgTypeInfo[NUM_TYPES] = {
50
    {"abortretryignore", MB_ABORTRETRYIGNORE, 3, {"abort", "retry", "ignore"}},
51
    {"ok",               MB_OK,               1, {"ok"                      }},
52
    {"okcancel",         MB_OKCANCEL,         2, {"ok",    "cancel"         }},
53
    {"retrycancel",      MB_RETRYCANCEL,      2, {"retry", "cancel"         }},
54
    {"yesno",            MB_YESNO,            2, {"yes",   "no"             }},
55
    {"yesnocancel",      MB_YESNOCANCEL,      3, {"yes",   "no",    "cancel"}}
56
};
57
 
58
/*
59
 * The following structure is used in the GetOpenFileName() and
60
 * GetSaveFileName() calls.
61
 */
62
typedef struct _OpenFileData {
63
    Tcl_Interp * interp;
64
    TCHAR szFile[(256*MAX_PATH)+1];
65
} OpenFileData;
66
 
67
/*
68
 * The following structure is used in the ChooseColor() call.
69
 */
70
typedef struct _ChooseColorData {
71
    Tcl_Interp * interp;
72
    char * title;                       /* Title of the color dialog */
73
} ChooseColorData;
74
 
75
 
76
static int              GetFileName _ANSI_ARGS_((ClientData clientData,
77
                            Tcl_Interp *interp, int argc, char **argv,
78
                            int isOpen));
79
static UINT CALLBACK    ColorDlgHookProc _ANSI_ARGS_((HWND hDlg, UINT uMsg,
80
                            WPARAM wParam, LPARAM lParam));
81
static int              MakeFilter _ANSI_ARGS_((Tcl_Interp *interp,
82
                            OPENFILENAME *ofnPtr, char * string));
83
static int              ParseFileDlgArgs _ANSI_ARGS_((Tcl_Interp * interp,
84
                            OPENFILENAME *ofnPtr, int argc, char ** argv,
85
                            int isOpen));
86
static int              ProcessCDError _ANSI_ARGS_((Tcl_Interp * interp,
87
                            DWORD dwErrorCode, HWND hWnd));
88
 
89
/*
90
 *----------------------------------------------------------------------
91
 *
92
 * EvalArgv --
93
 *
94
 *      Invokes the Tcl procedure with the arguments. argv[0] is set by
95
 *      the caller of this function. It may be different than cmdName.
96
 *      The TCL command will see argv[0], not cmdName, as its name if it
97
 *      invokes [lindex [info level 0] 0]
98
 *
99
 * Results:
100
 *      TCL_ERROR if the command does not exist and cannot be autoloaded.
101
 *      Otherwise, return the result of the evaluation of the command.
102
 *
103
 * Side effects:
104
 *      The command may be autoloaded.
105
 *
106
 *----------------------------------------------------------------------
107
 */
108
 
109
static int
110
EvalArgv(interp, cmdName, argc, argv)
111
    Tcl_Interp *interp;         /* Current interpreter. */
112
    char * cmdName;             /* Name of the TCL command to call */
113
    int argc;                   /* Number of arguments. */
114
    char **argv;                /* Argument strings. */
115
{
116
    Tcl_CmdInfo cmdInfo;
117
 
118
    if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
119
        char * cmdArgv[2];
120
 
121
        /*
122
         * This comand is not in the interpreter yet -- looks like we
123
         * have to auto-load it
124
         */
125
        if (!Tcl_GetCommandInfo(interp, "auto_load", &cmdInfo)) {
126
            Tcl_ResetResult(interp);
127
            Tcl_AppendResult(interp, "cannot execute command \"auto_load\"",
128
                NULL);
129
            return TCL_ERROR;
130
        }
131
 
132
        cmdArgv[0] = "auto_load";
133
        cmdArgv[1] = cmdName;
134
 
135
        if ((*cmdInfo.proc)(cmdInfo.clientData, interp, 2, cmdArgv)!= TCL_OK){
136
            return TCL_ERROR;
137
        }
138
 
139
        if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
140
            Tcl_ResetResult(interp);
141
            Tcl_AppendResult(interp, "cannot auto-load command \"",
142
                cmdName, "\"",NULL);
143
            return TCL_ERROR;
144
        }
145
    }
146
 
147
    return (*cmdInfo.proc)(cmdInfo.clientData, interp, argc, argv);
148
}
149
 
150
/*
151
 *----------------------------------------------------------------------
152
 *
153
 * Tk_ChooseColorCmd --
154
 *
155
 *      This procedure implements the color dialog box for the Windows
156
 *      platform. See the user documentation for details on what it
157
 *      does.
158
 *
159
 * Results:
160
 *      See user documentation.
161
 *
162
 * Side effects:
163
 *      A dialog window is created the first time this procedure is called.
164
 *      This window is not destroyed and will be reused the next time the
165
 *      application invokes the "tk_chooseColor" command.
166
 *
167
 *----------------------------------------------------------------------
168
 */
169
 
170
int
171
Tk_ChooseColorCmd(clientData, interp, argc, argv)
172
    ClientData clientData;      /* Main window associated with interpreter. */
173
    Tcl_Interp *interp;         /* Current interpreter. */
174
    int argc;                   /* Number of arguments. */
175
    char **argv;                /* Argument strings. */
176
{
177
    Tk_Window parent = Tk_MainWindow(interp);
178
    ChooseColorData custData;
179
    int oldMode;
180
    CHOOSECOLOR chooseColor;
181
    char * colorStr = NULL;
182
    int i;
183
    int winCode, tclCode;
184
    XColor * colorPtr = NULL;
185
    static inited = 0;
186
    static long dwCustColors[16];
187
    static long oldColor;               /* the color selected last time */
188
 
189
    custData.title     = NULL;
190
 
191
    if (!inited) {
192
        /*
193
         * dwCustColors stores the custom color which the user can
194
         * modify. We store these colors in a fixed array so that the next
195
         * time the color dialog pops up, the same set of custom colors
196
         * remain in the dialog.
197
         */
198
        for (i=0; i<16; i++) {
199
            dwCustColors[i] = (RGB(255-i*10, i, i*10)) ;
200
        }
201
        oldColor = RGB(0xa0,0xa0,0xa0);
202
        inited = 1;
203
    }
204
 
205
    /*
206
     * 1. Parse the arguments
207
     */
208
 
209
    chooseColor.lStructSize  = sizeof(CHOOSECOLOR) ;
210
    chooseColor.hwndOwner    = 0;                        /* filled in below */
211
    chooseColor.hInstance    = 0;
212
    chooseColor.rgbResult    = oldColor;
213
    chooseColor.lpCustColors = (LPDWORD) dwCustColors ;
214
    chooseColor.Flags        = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
215
    chooseColor.lCustData    = (LPARAM)&custData;
216
    chooseColor.lpfnHook     = ColorDlgHookProc;
217
    chooseColor.lpTemplateName = NULL;
218
 
219
    for (i=1; i<argc; i+=2) {
220
        int v = i+1;
221
        int len = strlen(argv[i]);
222
 
223
        if (strncmp(argv[i], "-initialcolor", len)==0) {
224
            if (v==argc) {goto arg_missing;}
225
 
226
            colorStr = argv[v];
227
        }
228
        else if (strncmp(argv[i], "-parent", len)==0) {
229
            if (v==argc) {goto arg_missing;}
230
 
231
            parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
232
            if (parent == NULL) {
233
                return TCL_ERROR;
234
            }
235
        }
236
        else if (strncmp(argv[i], "-title", len)==0) {
237
            if (v==argc) {goto arg_missing;}
238
 
239
            custData.title = argv[v];
240
        }
241
        else {
242
            Tcl_AppendResult(interp, "unknown option \"",
243
                argv[i], "\", must be -initialcolor, -parent or -title",
244
                NULL);
245
                return TCL_ERROR;
246
        }
247
    }
248
 
249
    if (Tk_WindowId(parent) == None) {
250
        Tk_MakeWindowExist(parent);
251
    }
252
    chooseColor.hwndOwner = Tk_GetHWND(Tk_WindowId(parent));
253
 
254
    if (colorStr != NULL) {
255
        colorPtr = Tk_GetColor(interp, Tk_MainWindow(interp), colorStr);
256
        if (!colorPtr) {
257
            return TCL_ERROR;
258
        }
259
        chooseColor.rgbResult = RGB((colorPtr->red/0x100),
260
            (colorPtr->green/0x100), (colorPtr->blue/0x100));
261
    }
262
 
263
    /*
264
     * 2. Popup the dialog
265
     */
266
 
267
    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
268
    winCode = ChooseColor(&chooseColor);
269
    (void) Tcl_SetServiceMode(oldMode);
270
 
271
    /*
272
     * Clear the interp result since anything may have happened during the
273
     * modal loop.
274
     */
275
 
276
    Tcl_ResetResult(interp);
277
 
278
    /*
279
     * 3. Process the result of the dialog
280
     */
281
    if (winCode) {
282
        /*
283
         * User has selected a color
284
         */
285
        char result[100];
286
 
287
        sprintf(result, "#%02x%02x%02x",
288
            GetRValue(chooseColor.rgbResult),
289
            GetGValue(chooseColor.rgbResult),
290
            GetBValue(chooseColor.rgbResult));
291
        Tcl_AppendResult(interp, result, NULL);
292
        tclCode = TCL_OK;
293
 
294
        oldColor = chooseColor.rgbResult;
295
    } else {
296
        /*
297
         * User probably pressed Cancel, or an error occurred
298
         */
299
        tclCode = ProcessCDError(interp, CommDlgExtendedError(),
300
             chooseColor.hwndOwner);
301
    }
302
 
303
    if (colorPtr) {
304
        Tk_FreeColor(colorPtr);
305
    }
306
 
307
    return tclCode;
308
 
309
  arg_missing:
310
    Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
311
        NULL);
312
    return TCL_ERROR;
313
}
314
 
315
/*
316
 *----------------------------------------------------------------------
317
 *
318
 * ColorDlgHookProc --
319
 *
320
 *      Gets called during the execution of the color dialog. It processes
321
 *      the "interesting" messages that Windows send to the dialog.
322
 *
323
 * Results:
324
 *      TRUE if the message has been processed, FALSE otherwise.
325
 *
326
 * Side effects:
327
 *      Changes the title of the dialog window when it is popped up.
328
 *
329
 *----------------------------------------------------------------------
330
 */
331
 
332
static UINT
333
CALLBACK ColorDlgHookProc(hDlg, uMsg, wParam, lParam)
334
    HWND hDlg;                  /* Handle to the color dialog */
335
    UINT uMsg;                  /* Type of message */
336
    WPARAM wParam;              /* word param, interpretation depends on uMsg*/
337
    LPARAM lParam;              /* long param, interpretation depends on uMsg*/
338
{
339
    CHOOSECOLOR * ccPtr;
340
    ChooseColorData * pCustData;
341
 
342
    switch (uMsg) {
343
      case WM_INITDIALOG:
344
        /* Save the pointer to CHOOSECOLOR so that we can use it later */
345
        SetWindowLong(hDlg, DWL_USER, lParam);
346
 
347
        /* Set the title string of the dialog */
348
        ccPtr = (CHOOSECOLOR*)lParam;
349
        pCustData = (ChooseColorData*)(ccPtr->lCustData);
350
        if (pCustData->title && *(pCustData->title)) {
351
            SetWindowText(hDlg, (LPCSTR)pCustData->title);
352
        }
353
 
354
        return TRUE;
355
    }
356
 
357
    return FALSE;
358
}
359
 
360
/*
361
 *----------------------------------------------------------------------
362
 *
363
 * Tk_GetOpenFileCmd --
364
 *
365
 *      This procedure implements the "open file" dialog box for the
366
 *      Windows platform. See the user documentation for details on what
367
 *      it does.
368
 *
369
 * Results:
370
 *      See user documentation.
371
 *
372
 * Side effects:
373
 *      A dialog window is created the first this procedure is called.
374
 *      This window is not destroyed and will be reused the next time
375
 *      the application invokes the "tk_getOpenFile" or
376
 *      "tk_getSaveFile" command.
377
 *
378
 *----------------------------------------------------------------------
379
 */
380
 
381
int
382
Tk_GetOpenFileCmd(clientData, interp, argc, argv)
383
    ClientData clientData;      /* Main window associated with interpreter. */
384
    Tcl_Interp *interp;         /* Current interpreter. */
385
    int argc;                   /* Number of arguments. */
386
    char **argv;                /* Argument strings. */
387
{
388
    return GetFileName(clientData, interp, argc, argv, OPEN_FILE);
389
}
390
 
391
/*
392
 *----------------------------------------------------------------------
393
 *
394
 * Tk_GetSaveFileCmd --
395
 *
396
 *      Same as Tk_GetOpenFileCmd but opens a "save file" dialog box
397
 *      instead
398
 *
399
 * Results:
400
 *      Same as Tk_GetOpenFileCmd.
401
 *
402
 * Side effects:
403
 *      Same as Tk_GetOpenFileCmd.
404
 *
405
 *----------------------------------------------------------------------
406
 */
407
 
408
int
409
Tk_GetSaveFileCmd(clientData, interp, argc, argv)
410
    ClientData clientData;      /* Main window associated with interpreter. */
411
    Tcl_Interp *interp;         /* Current interpreter. */
412
    int argc;                   /* Number of arguments. */
413
    char **argv;                /* Argument strings. */
414
{
415
    return GetFileName(clientData, interp, argc, argv, SAVE_FILE);
416
}
417
 
418
/*
419
 *----------------------------------------------------------------------
420
 *
421
 * GetFileName --
422
 *
423
 *      Calls GetOpenFileName() or GetSaveFileName().
424
 *
425
 * Results:
426
 *      See user documentation.
427
 *
428
 * Side effects:
429
 *      See user documentation.
430
 *
431
 *----------------------------------------------------------------------
432
 */
433
 
434
static int
435
GetFileName(clientData, interp, argc, argv, isOpen)
436
    ClientData clientData;      /* Main window associated with interpreter. */
437
    Tcl_Interp *interp;         /* Current interpreter. */
438
    int argc;                   /* Number of arguments. */
439
    char **argv;                /* Argument strings. */
440
    int isOpen;                 /* true if we should call GetOpenFileName(),
441
                                 * false if we should call GetSaveFileName() */
442
{
443
    OPENFILENAME openFileName, *ofnPtr;
444
    int tclCode, winCode, oldMode;
445
    OpenFileData *custData;
446
    char buffer[MAX_PATH+1];
447
 
448
    ofnPtr = &openFileName;
449
 
450
    /*
451
     * 1. Parse the arguments.
452
     */
453
    if (ParseFileDlgArgs(interp, ofnPtr, argc, argv, isOpen) != TCL_OK) {
454
        return TCL_ERROR;
455
    }
456
    custData = (OpenFileData*) ofnPtr->lCustData;
457
 
458
    /*
459
     * 2. Call the common dialog function.
460
     */
461
    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
462
    GetCurrentDirectory(MAX_PATH+1, buffer);
463
    if (isOpen) {
464
        winCode = GetOpenFileName(ofnPtr);
465
    } else {
466
        winCode = GetSaveFileName(ofnPtr);
467
    }
468
    SetCurrentDirectory(buffer);
469
    (void) Tcl_SetServiceMode(oldMode);
470
 
471
    /*
472
     * Clear the interp result since anything may have happened during the
473
     * modal loop.
474
     */
475
 
476
    Tcl_ResetResult(interp);
477
 
478
    if (ofnPtr->lpstrInitialDir != NULL) {
479
        ckfree((char*) ofnPtr->lpstrInitialDir);
480
    }
481
 
482
    /*
483
     * 3. Process the results.
484
     */
485
    if (winCode) {
486
        if (ofnPtr->Flags & OFN_ALLOWMULTISELECT) {
487
            /* The result in custData->szFile contains many items,
488
               separated with null characters.  It is terminated with
489
               two nulls in a row.  The first element is the directory
490
               path. */
491
            char *dir;
492
            int dirlen;
493
            char *p;
494
            Tcl_DString fullname;
495
            Tcl_ResetResult(interp);
496
 
497
            /* Get directory */
498
            dir = custData->szFile;
499
            for (p = custData->szFile; p && *p; p++) {
500
                /*
501
                 * Change the pathname to the Tcl "normalized" pathname, where
502
                 * back slashes are used instead of forward slashes
503
                 */
504
                if (*p == '\\') {
505
                    *p = '/';
506
                }
507
            }
508
 
509
            if (p[1] == '\0') {
510
                /* Only one file was returned.  */
511
                Tcl_AppendElement(interp, dir);
512
            } else {
513
                while (*(++p)) {
514
                    char *filname = p;
515
                    for (; p && *p; p++) {
516
                        if (*p == '\\') { *p = '/'; }
517
                    }
518
                    Tcl_DStringInit(&fullname);
519
                    /* Add "dir/fname" to list */
520
                    Tcl_DStringAppend(&fullname, dir, -1);
521
                    Tcl_DStringAppend(&fullname, "/", -1);
522
                    Tcl_DStringAppend(&fullname, filname, -1);
523
                    /* Add to result string */
524
                    Tcl_AppendElement(interp, Tcl_DStringValue(&fullname));
525
                    /* Reset dynamic string */
526
                    Tcl_DStringFree(&fullname);
527
                }
528
            }
529
            tclCode = TCL_OK;
530
        } else {
531
            /* Not a multiple-selection box; just treat it as a single
532
               element. */
533
            char *p;
534
            Tcl_ResetResult(interp);
535
 
536
            for (p = custData->szFile; p && *p; p++) {
537
                /*
538
                 * Change the pathname to the Tcl "normalized" pathname, where
539
                 * back slashes are used instead of forward slashes
540
                 */
541
                if (*p == '\\') {
542
                    *p = '/';
543
                }
544
            }
545
            Tcl_AppendResult(interp, custData->szFile, NULL);
546
            tclCode = TCL_OK;
547
        }
548
    } else {
549
        tclCode = ProcessCDError(interp, CommDlgExtendedError(),
550
                                 ofnPtr->hwndOwner);
551
    }
552
 
553
    if (custData) {
554
        ckfree((char*)custData);
555
    }
556
    if (ofnPtr->lpstrFilter) {
557
        ckfree((char*)ofnPtr->lpstrFilter);
558
    }
559
 
560
    return tclCode;
561
}
562
 
563
/*
564
 *----------------------------------------------------------------------
565
 *
566
 * ParseFileDlgArgs --
567
 *
568
 *      Parses the arguments passed to tk_getOpenFile and tk_getSaveFile.
569
 *
570
 * Results:
571
 *      A standard TCL return value.
572
 *
573
 * Side effects:
574
 *      The OPENFILENAME structure is initialized and modified according
575
 *      to the arguments.
576
 *
577
 *----------------------------------------------------------------------
578
 */
579
 
580
static int
581
ParseFileDlgArgs(interp, ofnPtr, argc, argv, isOpen)
582
    Tcl_Interp * interp;        /* Current interpreter. */
583
    OPENFILENAME *ofnPtr;       /* Info about the file dialog */
584
    int argc;                   /* Number of arguments. */
585
    char **argv;                /* Argument strings. */
586
    int isOpen;                 /* true if we should call GetOpenFileName(),
587
                                 * false if we should call GetSaveFileName() */
588
{
589
    OpenFileData * custData;
590
    int i;
591
    Tk_Window parent = Tk_MainWindow(interp);
592
    int doneFilter = 0;
593
    int windowsMajorVersion;
594
    Tcl_DString buffer;
595
 
596
    custData = (OpenFileData*)ckalloc(sizeof(OpenFileData));
597
    custData->interp = interp;
598
    strcpy(custData->szFile, "");
599
 
600
    /* Fill in the OPENFILENAME structure to */
601
    ofnPtr->lStructSize       = sizeof(OPENFILENAME);
602
    ofnPtr->hwndOwner         = 0;                       /* filled in below */
603
    ofnPtr->lpstrFilter       = NULL;
604
    ofnPtr->lpstrCustomFilter = NULL;
605
    ofnPtr->nMaxCustFilter    = 0;
606
    ofnPtr->nFilterIndex      = 0;
607
    ofnPtr->lpstrFile         = custData->szFile;
608
    ofnPtr->nMaxFile          = sizeof(custData->szFile);
609
    ofnPtr->lpstrFileTitle    = NULL;
610
    ofnPtr->nMaxFileTitle     = 0;
611
    ofnPtr->lpstrInitialDir   = NULL;
612
    ofnPtr->lpstrTitle        = NULL;
613
    ofnPtr->nFileOffset       = 0;
614
    ofnPtr->nFileExtension    = 0;
615
    ofnPtr->lpstrDefExt       = NULL;
616
    ofnPtr->lpfnHook          = NULL;
617
    ofnPtr->lCustData         = (DWORD)custData;
618
    ofnPtr->lpTemplateName    = NULL;
619
    ofnPtr->Flags             = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
620
 
621
    windowsMajorVersion = LOBYTE(LOWORD(GetVersion()));
622
    if (windowsMajorVersion >= 4) {
623
        /*
624
         * Use the "explorer" style file selection box on platforms that
625
         * support it (Win95 and NT4.0, both have a major version number
626
         * of 4)
627
         */
628
        ofnPtr->Flags |= OFN_EXPLORER;
629
    }
630
 
631
 
632
    if (isOpen) {
633
        ofnPtr->Flags |= OFN_FILEMUSTEXIST;
634
    } else {
635
        ofnPtr->Flags |= OFN_OVERWRITEPROMPT;
636
    }
637
 
638
    for (i=1; i<argc; i+=2) {
639
        int v = i+1;
640
        int len = strlen(argv[i]);
641
 
642
        if (strncmp(argv[i], "-defaultextension", len)==0) {
643
            if (v==argc) {goto arg_missing;}
644
 
645
            ofnPtr->lpstrDefExt = argv[v];
646
            if (ofnPtr->lpstrDefExt[0] == '.') {
647
                /* Windows will insert the dot for us */
648
                ofnPtr->lpstrDefExt ++;
649
            }
650
        }
651
        else if (strncmp(argv[i], "-filetypes", len)==0) {
652
            if (v==argc) {goto arg_missing;}
653
 
654
            if (MakeFilter(interp, ofnPtr, argv[v]) != TCL_OK) {
655
                return TCL_ERROR;
656
            }
657
            doneFilter = 1;
658
        }
659
        else if (strncmp(argv[i], "-initialdir", len)==0) {
660
            if (v==argc) {goto arg_missing;}
661
 
662
            if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
663
                return TCL_ERROR;
664
            }
665
            ofnPtr->lpstrInitialDir = ckalloc(Tcl_DStringLength(&buffer)+1);
666
            strcpy((char*)ofnPtr->lpstrInitialDir, Tcl_DStringValue(&buffer));
667
            Tcl_DStringFree(&buffer);
668
        }
669
        else if (strncmp(argv[i], "-initialfile", len)==0) {
670
            if (v==argc) {goto arg_missing;}
671
 
672
            if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
673
                return TCL_ERROR;
674
            }
675
            strcpy(ofnPtr->lpstrFile, Tcl_DStringValue(&buffer));
676
            Tcl_DStringFree(&buffer);
677
        }
678
        else if (strncmp(argv[i], "-parent", len)==0) {
679
            if (v==argc) {goto arg_missing;}
680
 
681
            parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
682
            if (parent == NULL) {
683
                return TCL_ERROR;
684
            }
685
        }
686
        else if (strncmp(argv[i], "-title", len)==0) {
687
            if (v==argc) {goto arg_missing;}
688
 
689
            ofnPtr->lpstrTitle = argv[v];
690
        }
691
        else if (strncmp(argv[i], "-multiple", len)==0) {
692
            int tmp;
693
            if (v==argc) {goto arg_missing;}
694
 
695
            if (Tcl_GetBoolean(interp, argv[i+1], &tmp) != TCL_OK) {
696
                return TCL_ERROR;
697
            }
698
            if (tmp) {
699
                ofnPtr->Flags |= OFN_ALLOWMULTISELECT;
700
            }
701
        }
702
        else {
703
            Tcl_AppendResult(interp, "unknown option \"",
704
                argv[i], "\", must be -defaultextension, ",
705
                "-filetypes, -initialdir, -initialfile, -parent or -title",
706
                NULL);
707
            return TCL_ERROR;
708
        }
709
    }
710
 
711
    if (!doneFilter) {
712
        if (MakeFilter(interp, ofnPtr, "") != TCL_OK) {
713
            return TCL_ERROR;
714
        }
715
    }
716
 
717
    if (Tk_WindowId(parent) == None) {
718
        Tk_MakeWindowExist(parent);
719
    }
720
    ofnPtr->hwndOwner = Tk_GetHWND(Tk_WindowId(parent));
721
 
722
    return TCL_OK;
723
 
724
  arg_missing:
725
    Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
726
        NULL);
727
    return TCL_ERROR;
728
}
729
 
730
/*
731
 *----------------------------------------------------------------------
732
 *
733
 * MakeFilter --
734
 *
735
 *      Allocate a buffer to store the filters in a format understood by
736
 *      Windows
737
 *
738
 * Results:
739
 *      A standard TCL return value.
740
 *
741
 * Side effects:
742
 *      ofnPtr->lpstrFilter is modified.
743
 *
744
 *----------------------------------------------------------------------
745
 */
746
static int MakeFilter(interp, ofnPtr, string)
747
    Tcl_Interp *interp;         /* Current interpreter. */
748
    OPENFILENAME *ofnPtr;       /* Info about the file dialog */
749
    char *string;               /* String value of the -filetypes option */
750
{
751
    char *filterStr;
752
    char *p;
753
    int pass;
754
    FileFilterList flist;
755
    FileFilter *filterPtr;
756
 
757
    TkInitFileFilters(&flist);
758
    if (TkGetFileFilters(interp, &flist, string, 1) != TCL_OK) {
759
        return TCL_ERROR;
760
    }
761
 
762
    if (flist.filters == NULL) {
763
        /*
764
         * Use "All Files (*.*) as the default filter is none is specified
765
         */
766
        char *defaultFilter = "All Files (*.*)";
767
 
768
        p = filterStr = (char*)ckalloc(30 * sizeof(char));
769
 
770
        strcpy(p, defaultFilter);
771
        p+= strlen(defaultFilter);
772
 
773
        *p++ = '\0';
774
        *p++ = '*';
775
        *p++ = '.';
776
        *p++ = '*';
777
        *p++ = '\0';
778
        *p++ = '\0';
779
        *p = '\0';
780
 
781
    } else {
782
        /* We format the filetype into a string understood by Windows:
783
         * {"Text Documents" {.doc .txt} {TEXT}} becomes
784
         * "Text Documents (*.doc,*.txt)\0*.doc;*.txt\0"
785
         *
786
         * See the Windows OPENFILENAME manual page for details on the filter
787
         * string format.
788
         */
789
 
790
        /*
791
         * Since we may only add asterisks (*) to the filter, we need at most
792
         * twice the size of the string to format the filter
793
         */
794
        filterStr = ckalloc(strlen(string) * 3);
795
 
796
        for (filterPtr = flist.filters, p = filterStr; filterPtr;
797
                filterPtr = filterPtr->next) {
798
            char *sep;
799
            FileFilterClause *clausePtr;
800
 
801
            /*
802
             *  First, put in the name of the file type
803
             */
804
            strcpy(p, filterPtr->name);
805
            p+= strlen(filterPtr->name);
806
            *p++ = ' ';
807
            *p++ = '(';
808
 
809
            for (pass = 1; pass <= 2; pass++) {
810
                /*
811
                 * In the first pass, we format the extensions in the
812
                 * name field. In the second pass, we format the extensions in
813
                 * the filter pattern field
814
                 */
815
                sep = "";
816
                for (clausePtr=filterPtr->clauses;clausePtr;
817
                         clausePtr=clausePtr->next) {
818
                    GlobPattern *globPtr;
819
 
820
 
821
                    for (globPtr=clausePtr->patterns; globPtr;
822
                            globPtr=globPtr->next) {
823
                        strcpy(p, sep);
824
                        p+= strlen(sep);
825
                        strcpy(p, globPtr->pattern);
826
                        p+= strlen(globPtr->pattern);
827
 
828
                        if (pass==1) {
829
                            sep = ",";
830
                        } else {
831
                            sep = ";";
832
                        }
833
                    }
834
                }
835
                if (pass == 1) {
836
                    if (pass == 1) {
837
                        *p ++ = ')';
838
                    }
839
                }
840
                *p ++ = '\0';
841
            }
842
        }
843
 
844
        /*
845
         * Windows requires the filter string to be ended by two NULL
846
         * characters.
847
         */
848
        *p++ = '\0';
849
        *p = '\0';
850
    }
851
 
852
    if (ofnPtr->lpstrFilter != NULL) {
853
        ckfree((char*)ofnPtr->lpstrFilter);
854
    }
855
    ofnPtr->lpstrFilter = filterStr;
856
 
857
    TkFreeFileFilters(&flist);
858
    return TCL_OK;
859
}
860
 
861
/*
862
 *----------------------------------------------------------------------
863
 *
864
 * Tk_MessageBoxCmd --
865
 *
866
 *      This procedure implements the MessageBox window for the
867
 *      Windows platform. See the user documentation for details on what
868
 *      it does.
869
 *
870
 * Results:
871
 *      See user documentation.
872
 *
873
 * Side effects:
874
 *      None. The MessageBox window will be destroy before this procedure
875
 *      returns.
876
 *
877
 *----------------------------------------------------------------------
878
 */
879
 
880
int
881
Tk_MessageBoxCmd(clientData, interp, argc, argv)
882
    ClientData clientData;      /* Main window associated with interpreter. */
883
    Tcl_Interp *interp;         /* Current interpreter. */
884
    int argc;                   /* Number of arguments. */
885
    char **argv;                /* Argument strings. */
886
{
887
    int flags;
888
    Tk_Window parent = NULL;
889
    HWND hWnd;
890
    char *message = "";
891
    char *title = "";
892
    int icon = MB_ICONINFORMATION;
893
    int type = MB_OK;
894
    int modal = MB_SYSTEMMODAL;
895
    int i, j;
896
    char *result;
897
    int code, oldMode;
898
    char *defaultBtn = NULL;
899
    int defaultBtnIdx = -1;
900
 
901
    for (i=1; i<argc; i+=2) {
902
        int v = i+1;
903
        int len = strlen(argv[i]);
904
 
905
        if (strncmp(argv[i], "-default", len)==0) {
906
            if (v==argc) {goto arg_missing;}
907
 
908
            defaultBtn = argv[v];
909
        }
910
        else if (strncmp(argv[i], "-icon", len)==0) {
911
            if (v==argc) {goto arg_missing;}
912
 
913
            if (strcmp(argv[v], "error") == 0) {
914
                icon = MB_ICONERROR;
915
            }
916
            else if (strcmp(argv[v], "info") == 0) {
917
                icon = MB_ICONINFORMATION;
918
            }
919
            else if (strcmp(argv[v], "question") == 0) {
920
                icon = MB_ICONQUESTION;
921
            }
922
            else if (strcmp(argv[v], "warning") == 0) {
923
                icon = MB_ICONWARNING;
924
            }
925
            else {
926
                Tcl_AppendResult(interp, "invalid icon \"", argv[v],
927
                    "\", must be error, info, question or warning", NULL);
928
                return TCL_ERROR;
929
            }
930
        }
931
        else if (strncmp(argv[i], "-message", len)==0) {
932
            if (v==argc) {goto arg_missing;}
933
 
934
            message = argv[v];
935
        }
936
        else if (strncmp(argv[i], "-parent", len)==0) {
937
            if (v==argc) {goto arg_missing;}
938
 
939
            parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
940
            if (parent == NULL) {
941
                return TCL_ERROR;
942
            }
943
        }
944
        else if (strncmp(argv[i], "-title", len)==0) {
945
            if (v==argc) {goto arg_missing;}
946
 
947
            title = argv[v];
948
        }
949
        else if (strncmp(argv[i], "-type", len)==0) {
950
            int found = 0;
951
 
952
            if (v==argc) {goto arg_missing;}
953
 
954
            for (j=0; j<NUM_TYPES; j++) {
955
                if (strcmp(argv[v], msgTypeInfo[j].name) == 0) {
956
                    type = msgTypeInfo[j].type;
957
                    found = 1;
958
                    break;
959
                }
960
            }
961
            if (!found) {
962
                Tcl_AppendResult(interp, "invalid message box type \"",
963
                    argv[v], "\", must be abortretryignore, ok, ",
964
                    "okcancel, retrycancel, yesno or yesnocancel", NULL);
965
                return TCL_ERROR;
966
            }
967
        }
968
        else if (strncmp (argv[i], "-modal", len) == 0) {
969
            if (v==argc) {goto arg_missing;}
970
 
971
            if (strcmp(argv[v], "system") == 0) {
972
                modal = MB_SYSTEMMODAL;
973
            }
974
            else if (strcmp(argv[v], "task") == 0) {
975
                modal = MB_TASKMODAL;
976
            }
977
            else if (strcmp(argv[v], "owner") == 0) {
978
                modal = MB_APPLMODAL;
979
            }
980
            else {
981
                Tcl_AppendResult(interp, "invalid modality \"", argv[v],
982
                    "\", must be system, task or owner", NULL);
983
                return TCL_ERROR;
984
            }
985
        }
986
        else {
987
            Tcl_AppendResult(interp, "unknown option \"",
988
                argv[i], "\", must be -default, -icon, ",
989
                "-message, -parent, -title or -type", NULL);
990
                return TCL_ERROR;
991
        }
992
    }
993
 
994
    /* Make sure we have a valid hWnd to act as the parent of this message box
995
     */
996
    if (parent == NULL && modal == MB_TASKMODAL) {
997
        hWnd = NULL;
998
    }
999
    else {
1000
        if (parent == NULL) {
1001
            parent = Tk_MainWindow(interp);
1002
        }
1003
        if (Tk_WindowId(parent) == None) {
1004
            Tk_MakeWindowExist(parent);
1005
        }
1006
        hWnd = Tk_GetHWND(Tk_WindowId(parent));
1007
    }
1008
 
1009
    if (defaultBtn != NULL) {
1010
        for (i=0; i<NUM_TYPES; i++) {
1011
            if (type == msgTypeInfo[i].type) {
1012
                for (j=0; j<msgTypeInfo[i].numButtons; j++) {
1013
                    if (strcmp(defaultBtn, msgTypeInfo[i].btnNames[j])==0) {
1014
                        defaultBtnIdx = j;
1015
                        break;
1016
                    }
1017
                }
1018
                if (defaultBtnIdx < 0) {
1019
                    Tcl_AppendResult(interp, "invalid default button \"",
1020
                        defaultBtn, "\"", NULL);
1021
                    return TCL_ERROR;
1022
                }
1023
                break;
1024
            }
1025
        }
1026
 
1027
        switch (defaultBtnIdx) {
1028
          case 0: flags = MB_DEFBUTTON1; break;
1029
          case 1: flags = MB_DEFBUTTON2; break;
1030
          case 2: flags = MB_DEFBUTTON3; break;
1031
          case 3: flags = MB_DEFBUTTON4; break;
1032
        }
1033
    } else {
1034
        flags = 0;
1035
    }
1036
 
1037
    flags |= icon | type;
1038
    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
1039
    code = MessageBox(hWnd, message, title, flags|modal);
1040
    (void) Tcl_SetServiceMode(oldMode);
1041
 
1042
    switch (code) {
1043
      case IDABORT:     result = "abort";  break;
1044
      case IDCANCEL:    result = "cancel"; break;
1045
      case IDIGNORE:    result = "ignore"; break;
1046
      case IDNO:        result = "no";     break;
1047
      case IDOK:        result = "ok";     break;
1048
      case IDRETRY:     result = "retry";  break;
1049
      case IDYES:       result = "yes";    break;
1050
      default:          result = "";
1051
    }
1052
 
1053
    /*
1054
     * When we come to here interp->result may have been changed by some
1055
     * background scripts. Call Tcl_SetResult() to make sure that any stuff
1056
     * lingering in interp->result will not appear in the result of
1057
     * this command.
1058
     */
1059
 
1060
    Tcl_SetResult(interp, result, TCL_STATIC);
1061
    return TCL_OK;
1062
 
1063
  arg_missing:
1064
    Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
1065
        NULL);
1066
    return TCL_ERROR;
1067
}
1068
 
1069
/*
1070
 *----------------------------------------------------------------------
1071
 *
1072
 * ProcessCDError --
1073
 *
1074
 *      This procedure gets called if a Windows-specific error message
1075
 *      has occurred during the execution of a common dialog or the
1076
 *      user has pressed the CANCEL button.
1077
 *
1078
 * Results:
1079
 *      If an error has indeed happened, returns a standard TCL result
1080
 *      that reports the error code in string format. If the user has
1081
 *      pressed the CANCEL button (dwErrorCode == 0), resets
1082
 *      interp->result to the empty string.
1083
 *
1084
 * Side effects:
1085
 *      interp->result is changed.
1086
 *
1087
 *----------------------------------------------------------------------
1088
 */
1089
static int ProcessCDError(interp, dwErrorCode, hWnd)
1090
    Tcl_Interp * interp;                /* Current interpreter. */
1091
    DWORD dwErrorCode;                  /* The Windows-specific error code */
1092
    HWND hWnd;                          /* window in which the error happened*/
1093
{
1094
    char *string;
1095
 
1096
    Tcl_ResetResult(interp);
1097
 
1098
    switch(dwErrorCode) {
1099
      case 0:      /* User has hit CANCEL */
1100
        return TCL_OK;
1101
 
1102
      case CDERR_DIALOGFAILURE:   string="CDERR_DIALOGFAILURE";         break;
1103
      case CDERR_STRUCTSIZE:      string="CDERR_STRUCTSIZE";            break;
1104
      case CDERR_INITIALIZATION:  string="CDERR_INITIALIZATION";        break;
1105
      case CDERR_NOTEMPLATE:      string="CDERR_NOTEMPLATE";            break;
1106
      case CDERR_NOHINSTANCE:     string="CDERR_NOHINSTANCE";           break;
1107
      case CDERR_LOADSTRFAILURE:  string="CDERR_LOADSTRFAILURE";        break;
1108
      case CDERR_FINDRESFAILURE:  string="CDERR_FINDRESFAILURE";        break;
1109
      case CDERR_LOADRESFAILURE:  string="CDERR_LOADRESFAILURE";        break;
1110
      case CDERR_LOCKRESFAILURE:  string="CDERR_LOCKRESFAILURE";        break;
1111
      case CDERR_MEMALLOCFAILURE: string="CDERR_MEMALLOCFAILURE";       break;
1112
      case CDERR_MEMLOCKFAILURE:  string="CDERR_MEMLOCKFAILURE";        break;
1113
      case CDERR_NOHOOK:          string="CDERR_NOHOOK";                break;
1114
      case PDERR_SETUPFAILURE:    string="PDERR_SETUPFAILURE";          break;
1115
      case PDERR_PARSEFAILURE:    string="PDERR_PARSEFAILURE";          break;
1116
      case PDERR_RETDEFFAILURE:   string="PDERR_RETDEFFAILURE";         break;
1117
      case PDERR_LOADDRVFAILURE:  string="PDERR_LOADDRVFAILURE";        break;
1118
      case PDERR_GETDEVMODEFAIL:  string="PDERR_GETDEVMODEFAIL";        break;
1119
      case PDERR_INITFAILURE:     string="PDERR_INITFAILURE";           break;
1120
      case PDERR_NODEVICES:       string="PDERR_NODEVICES";             break;
1121
      case PDERR_NODEFAULTPRN:    string="PDERR_NODEFAULTPRN";          break;
1122
      case PDERR_DNDMMISMATCH:    string="PDERR_DNDMMISMATCH";          break;
1123
      case PDERR_CREATEICFAILURE: string="PDERR_CREATEICFAILURE";       break;
1124
      case PDERR_PRINTERNOTFOUND: string="PDERR_PRINTERNOTFOUND";       break;
1125
      case CFERR_NOFONTS:         string="CFERR_NOFONTS";               break;
1126
      case FNERR_SUBCLASSFAILURE: string="FNERR_SUBCLASSFAILURE";       break;
1127
      case FNERR_INVALIDFILENAME: string="FNERR_INVALIDFILENAME";       break;
1128
      case FNERR_BUFFERTOOSMALL:  string="FNERR_BUFFERTOOSMALL";        break;
1129
 
1130
      default:
1131
        string="unknown error";
1132
    }
1133
 
1134
    Tcl_AppendResult(interp, "Win32 internal error: ", string, NULL);
1135
    return TCL_ERROR;
1136
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.