~ubuntu-branches/ubuntu/dapper/tk8.0/dapper-updates

« back to all changes in this revision

Viewing changes to generic/tkFileFilter.c

  • Committer: Bazaar Package Importer
  • Author(s): Mike Markley
  • Date: 2001-07-24 21:57:40 UTC
  • Revision ID: james.westby@ubuntu.com-20010724215740-r70t25rtmbqjil2h
Tags: upstream-8.0.5
ImportĀ upstreamĀ versionĀ 8.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * tkFileFilter.c --
 
3
 *
 
4
 *      Process the -filetypes option for the file dialogs on Windows and the
 
5
 *      Mac.
 
6
 *
 
7
 * Copyright (c) 1996 Sun Microsystems, Inc.
 
8
 *
 
9
 * See the file "license.terms" for information on usage and redistribution
 
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 
11
 *
 
12
 * RCS: @(#) $Id: tkFileFilter.c,v 1.2 1998/09/14 18:23:10 stanton Exp $
 
13
 *
 
14
 */
 
15
 
 
16
#include "tkInt.h"
 
17
#include "tkFileFilter.h"
 
18
 
 
19
static int              AddClause _ANSI_ARGS_((
 
20
                            Tcl_Interp * interp, FileFilter * filterPtr,
 
21
                            char * patternsStr, char * ostypesStr,
 
22
                            int isWindows));
 
23
static void             FreeClauses _ANSI_ARGS_((FileFilter * filterPtr));
 
24
static void             FreeGlobPatterns _ANSI_ARGS_((
 
25
                            FileFilterClause * clausePtr));
 
26
static void             FreeMacFileTypes _ANSI_ARGS_((
 
27
                            FileFilterClause * clausePtr));
 
28
static FileFilter *     GetFilter _ANSI_ARGS_((FileFilterList * flistPtr,
 
29
                            char * name));
 
30
 
 
31
/*
 
32
 *----------------------------------------------------------------------
 
33
 *
 
34
 * TkInitFileFilters --
 
35
 *
 
36
 *      Initializes a FileFilterList data structure. A FileFilterList
 
37
 *      must be initialized EXACTLY ONCE before any calls to
 
38
 *      TkGetFileFilters() is made. The usual flow of control is:
 
39
 *              TkInitFileFilters(&flist);
 
40
 *                  TkGetFileFilters(&flist, ...);
 
41
 *                  TkGetFileFilters(&flist, ...);
 
42
 *                  ...
 
43
 *              TkFreeFileFilters(&flist);
 
44
 *
 
45
 * Results:
 
46
 *      None.
 
47
 *
 
48
 * Side effects:
 
49
 *      The fields in flistPtr are initialized.
 
50
 *----------------------------------------------------------------------
 
51
 */
 
52
 
 
53
void
 
54
TkInitFileFilters(flistPtr)
 
55
    FileFilterList * flistPtr;  /* The structure to be initialized. */
 
56
{
 
57
    flistPtr->filters = NULL;
 
58
    flistPtr->filtersTail = NULL;
 
59
    flistPtr->numFilters = 0;
 
60
}
 
61
 
 
62
/*
 
63
 *----------------------------------------------------------------------
 
64
 *
 
65
 * TkGetFileFilters --
 
66
 *
 
67
 *      This function is called by the Mac and Windows implementation
 
68
 *      of tk_getOpenFile and tk_getSaveFile to translate the string
 
69
 *      value of the -filetypes option of into an easy-to-parse C
 
70
 *      structure (flistPtr). The caller of this function will then use
 
71
 *      flistPtr to perform filetype matching in a platform specific way.
 
72
 *
 
73
 *      flistPtr must be initialized (See comments in TkInitFileFilters).
 
74
 *
 
75
 * Results:
 
76
 *      A standard TCL return value.
 
77
 *
 
78
 * Side effects:
 
79
 *      The fields in flistPtr are changed according to string.
 
80
 *----------------------------------------------------------------------
 
81
 */
 
82
int
 
83
TkGetFileFilters(interp, flistPtr, string, isWindows)
 
84
    Tcl_Interp *interp;         /* Interpreter to use for error reporting. */
 
85
    FileFilterList * flistPtr;  /* Stores the list of file filters. */
 
86
    char * string;              /* Value of the -filetypes option. */
 
87
    int isWindows;              /* True if we are running on Windows. */
 
88
{
 
89
    int listArgc;
 
90
    char ** listArgv = NULL;
 
91
    char ** typeInfo = NULL;
 
92
    int code = TCL_OK;
 
93
    int i;
 
94
 
 
95
    if (Tcl_SplitList(interp, string, &listArgc, &listArgv) != TCL_OK) {
 
96
        return TCL_ERROR;
 
97
    }
 
98
    if (listArgc == 0) {
 
99
        goto done;
 
100
    }
 
101
 
 
102
    /*
 
103
     * Free the filter information that have been allocated the previous
 
104
     * time -- the -filefilters option may have been used more than once in
 
105
     * the command line.
 
106
     */
 
107
    TkFreeFileFilters(flistPtr);
 
108
 
 
109
    for (i = 0; i<listArgc; i++) {
 
110
        /*
 
111
         * Each file type should have two or three elements: the first one
 
112
         * is the name of the type and the second is the filter of the type.
 
113
         * The third is the Mac OSType ID, but we don't care about them here.
 
114
         */
 
115
        int count;
 
116
        FileFilter * filterPtr;
 
117
 
 
118
        if (Tcl_SplitList(interp, listArgv[i], &count, &typeInfo) != TCL_OK) {
 
119
            code = TCL_ERROR;
 
120
            goto done;
 
121
        }
 
122
        
 
123
        if (count != 2 && count != 3) {
 
124
            Tcl_AppendResult(interp, "bad file type \"", listArgv[i], "\", ",
 
125
                "should be \"typeName {extension ?extensions ...?} ",
 
126
                "?{macType ?macTypes ...?}?\"", NULL);
 
127
            code = TCL_ERROR;
 
128
            goto done;
 
129
        }
 
130
 
 
131
        filterPtr = GetFilter(flistPtr, typeInfo[0]);
 
132
 
 
133
        if (count == 2) {
 
134
            code = AddClause(interp, filterPtr, typeInfo[1], NULL,
 
135
                isWindows);
 
136
        } else {
 
137
            code = AddClause(interp, filterPtr, typeInfo[1], typeInfo[2],
 
138
                isWindows);
 
139
        }
 
140
        if (code != TCL_OK) {
 
141
            goto done;
 
142
        }
 
143
 
 
144
        if (typeInfo) {
 
145
            ckfree((char*)typeInfo);
 
146
        }
 
147
        typeInfo = NULL;
 
148
    }
 
149
 
 
150
  done:
 
151
    if (typeInfo) {
 
152
       ckfree((char*)typeInfo);
 
153
    }
 
154
    if (listArgv) {
 
155
        ckfree((char*)listArgv);
 
156
    }
 
157
    return code;
 
158
}
 
159
 
 
160
/*
 
161
 *----------------------------------------------------------------------
 
162
 *
 
163
 * TkFreeFileFilters --
 
164
 *
 
165
 *      Frees the malloc'ed file filter information.
 
166
 *
 
167
 * Results:
 
168
 *      None.
 
169
 *
 
170
 * Side effects:
 
171
 *      The fields allocated by TkGetFileFilters() are freed.
 
172
 *----------------------------------------------------------------------
 
173
 */
 
174
 
 
175
void
 
176
TkFreeFileFilters(flistPtr)
 
177
    FileFilterList * flistPtr;  /* List of file filters to free */
 
178
{
 
179
    FileFilter * filterPtr, *toFree;
 
180
 
 
181
    filterPtr=flistPtr->filters;
 
182
    while (filterPtr) {
 
183
        toFree = filterPtr;
 
184
        filterPtr=filterPtr->next;
 
185
        FreeClauses(toFree);
 
186
        ckfree((char*)toFree->name);
 
187
        ckfree((char*)toFree);
 
188
    }
 
189
    flistPtr->filters = NULL;
 
190
}
 
191
 
 
192
/*
 
193
 *----------------------------------------------------------------------
 
194
 *
 
195
 * AddClause --
 
196
 *
 
197
 *      Add one FileFilterClause to filterPtr.
 
198
 *
 
199
 * Results:
 
200
 *      A standard TCL result.
 
201
 *
 
202
 * Side effects:
 
203
 *      The list of filter clauses are updated in filterPtr.
 
204
 *----------------------------------------------------------------------
 
205
 */
 
206
 
 
207
static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows)
 
208
    Tcl_Interp * interp;        /* Interpreter to use for error reporting. */
 
209
    FileFilter * filterPtr;     /* Stores the new filter clause */
 
210
    char * patternsStr;         /* A TCL list of glob patterns. */
 
211
    char * ostypesStr;          /* A TCL list of Mac OSType strings. */
 
212
    int isWindows;              /* True if we are running on Windows; False
 
213
                                 * if we are running on the Mac; Glob
 
214
                                 * patterns need to be processed differently
 
215
                                 * on these two platforms */
 
216
{
 
217
    char ** globList = NULL;
 
218
    int globCount;
 
219
    char ** ostypeList = NULL;
 
220
    int ostypeCount;
 
221
    FileFilterClause * clausePtr;
 
222
    int i;
 
223
    int code = TCL_OK;
 
224
 
 
225
    if (Tcl_SplitList(interp, patternsStr, &globCount, &globList)!= TCL_OK) {
 
226
        code = TCL_ERROR;
 
227
        goto done;
 
228
    }
 
229
    if (ostypesStr != NULL) {
 
230
        if (Tcl_SplitList(interp, ostypesStr, &ostypeCount, &ostypeList)
 
231
                != TCL_OK) {
 
232
            code = TCL_ERROR;
 
233
            goto done;
 
234
        }
 
235
        for (i=0; i<ostypeCount; i++) {
 
236
            if (strlen(ostypeList[i]) != 4) {
 
237
                Tcl_AppendResult(interp, "bad Macintosh file type \"",
 
238
                    ostypeList[i], "\"", NULL);
 
239
                code = TCL_ERROR;
 
240
                goto done;
 
241
            }
 
242
        }
 
243
    }
 
244
 
 
245
    /*
 
246
     * Add the clause into the list of clauses 
 
247
     */
 
248
 
 
249
    clausePtr = (FileFilterClause*)ckalloc(sizeof(FileFilterClause));
 
250
    clausePtr->patterns     = NULL;
 
251
    clausePtr->patternsTail = NULL;
 
252
    clausePtr->macTypes     = NULL;
 
253
    clausePtr->macTypesTail = NULL;
 
254
 
 
255
    if (filterPtr->clauses == NULL) {
 
256
        filterPtr->clauses = filterPtr->clausesTail = clausePtr;
 
257
    } else {
 
258
        filterPtr->clausesTail->next = clausePtr;
 
259
        filterPtr->clausesTail = clausePtr;
 
260
    }
 
261
    clausePtr->next = NULL;
 
262
 
 
263
    if (globCount > 0 && globList != NULL) {
 
264
        for (i=0; i<globCount; i++) {
 
265
            GlobPattern * globPtr = (GlobPattern*)ckalloc(sizeof(GlobPattern));
 
266
            int len;
 
267
            
 
268
            len = (strlen(globList[i]) + 1) * sizeof(char);
 
269
 
 
270
            if (globList[i][0] && globList[i][0] != '*') {
 
271
                /*
 
272
                 * Prepend a "*" to patterns that do not have a leading "*"
 
273
                 */
 
274
                globPtr->pattern = (char*)ckalloc(len+1);
 
275
                globPtr->pattern[0] = '*';
 
276
                strcpy(globPtr->pattern+1, globList[i]);
 
277
            }
 
278
            else if (isWindows) {
 
279
                if (strcmp(globList[i], "*") == 0) {
 
280
                    globPtr->pattern = (char*)ckalloc(4*sizeof(char));
 
281
                    strcpy(globPtr->pattern, "*.*");
 
282
                }
 
283
                else if (strcmp(globList[i], "") == 0) {
 
284
                    /*
 
285
                     * An empty string means "match all files with no
 
286
                     * extensions"
 
287
                     * BUG: "*." actually matches with all files on Win95
 
288
                     */
 
289
                    globPtr->pattern = (char*)ckalloc(3*sizeof(char));
 
290
                    strcpy(globPtr->pattern, "*.");
 
291
                }
 
292
                else {
 
293
                    globPtr->pattern = (char*)ckalloc(len);
 
294
                    strcpy(globPtr->pattern, globList[i]);
 
295
                }
 
296
            } else {
 
297
                globPtr->pattern = (char*)ckalloc(len);
 
298
                strcpy(globPtr->pattern, globList[i]);
 
299
            }
 
300
 
 
301
            /*
 
302
             * Add the glob pattern into the list of patterns.
 
303
             */
 
304
 
 
305
            if (clausePtr->patterns == NULL) {
 
306
                clausePtr->patterns = clausePtr->patternsTail = globPtr;
 
307
            } else {
 
308
                clausePtr->patternsTail->next = globPtr;
 
309
                clausePtr->patternsTail = globPtr;
 
310
            }
 
311
            globPtr->next = NULL;
 
312
        }
 
313
    }
 
314
    if (ostypeCount > 0 && ostypeList != NULL) {
 
315
        for (i=0; i<ostypeCount; i++) {
 
316
            MacFileType * mfPtr = (MacFileType*)ckalloc(sizeof(MacFileType));
 
317
 
 
318
            memcpy(&mfPtr->type, ostypeList[i], sizeof(OSType));
 
319
 
 
320
            /*
 
321
             * Add the Mac type pattern into the list of Mac types
 
322
             */
 
323
            if (clausePtr->macTypes == NULL) {
 
324
                clausePtr->macTypes = clausePtr->macTypesTail = mfPtr;
 
325
            } else {
 
326
                clausePtr->macTypesTail->next = mfPtr;
 
327
                clausePtr->macTypesTail = mfPtr;
 
328
            }
 
329
            mfPtr->next = NULL;
 
330
        }
 
331
    }
 
332
 
 
333
  done:
 
334
    if (globList) {
 
335
        ckfree((char*)globList);
 
336
    }
 
337
    if (ostypeList) {
 
338
        ckfree((char*)ostypeList);
 
339
    }
 
340
 
 
341
    return code;
 
342
}       
 
343
 
 
344
/*
 
345
 *----------------------------------------------------------------------
 
346
 *
 
347
 * GetFilter --
 
348
 *
 
349
 *      Add one FileFilter to flistPtr.
 
350
 *
 
351
 * Results:
 
352
 *      A standard TCL result.
 
353
 *
 
354
 * Side effects:
 
355
 *      The list of filters are updated in flistPtr.
 
356
 *----------------------------------------------------------------------
 
357
 */
 
358
 
 
359
static FileFilter * GetFilter(flistPtr, name)
 
360
    FileFilterList * flistPtr;  /* The FileFilterList that contains the
 
361
                                 * newly created filter */
 
362
    char * name;                /* Name of the filter. It is usually displayed
 
363
                                 * in the "File Types" listbox in the file
 
364
                                 * dialogs. */
 
365
{
 
366
    FileFilter * filterPtr;
 
367
 
 
368
    for (filterPtr=flistPtr->filters; filterPtr; filterPtr=filterPtr->next) {
 
369
        if (strcmp(filterPtr->name, name)==0) {
 
370
            return filterPtr;
 
371
        }
 
372
    }
 
373
 
 
374
    filterPtr = (FileFilter*)ckalloc(sizeof(FileFilter));
 
375
    filterPtr->clauses = NULL;
 
376
    filterPtr->clausesTail = NULL;
 
377
    filterPtr->name = (char*)ckalloc((strlen(name)+1) * sizeof(char));
 
378
    strcpy(filterPtr->name, name);
 
379
 
 
380
    if (flistPtr->filters == NULL) {
 
381
        flistPtr->filters = flistPtr->filtersTail = filterPtr;
 
382
    } else {
 
383
        flistPtr->filtersTail->next = filterPtr;
 
384
        flistPtr->filtersTail = filterPtr;
 
385
    }
 
386
    filterPtr->next = NULL;
 
387
 
 
388
    ++flistPtr->numFilters;
 
389
    return filterPtr;
 
390
}
 
391
 
 
392
/*
 
393
 *----------------------------------------------------------------------
 
394
 *
 
395
 * FreeClauses --
 
396
 *
 
397
 *      Frees the malloc'ed file type clause
 
398
 *
 
399
 * Results:
 
400
 *      None.
 
401
 *
 
402
 * Side effects:
 
403
 *      The list of clauses in filterPtr->clauses are freed.
 
404
 *----------------------------------------------------------------------
 
405
 */
 
406
 
 
407
static void
 
408
FreeClauses(filterPtr)
 
409
    FileFilter * filterPtr;     /* FileFilter whose clauses are to be freed */
 
410
{
 
411
    FileFilterClause * clausePtr, * toFree;
 
412
 
 
413
    clausePtr = filterPtr->clauses;
 
414
    while (clausePtr) {
 
415
        toFree = clausePtr;
 
416
        clausePtr=clausePtr->next;
 
417
        FreeGlobPatterns(toFree);
 
418
        FreeMacFileTypes(toFree);
 
419
        ckfree((char*)toFree);
 
420
    }
 
421
    filterPtr->clauses = NULL;
 
422
    filterPtr->clausesTail = NULL;
 
423
}
 
424
 
 
425
/*
 
426
 *----------------------------------------------------------------------
 
427
 *
 
428
 * FreeGlobPatterns --
 
429
 *
 
430
 *      Frees the malloc'ed glob patterns in a clause
 
431
 *
 
432
 * Results:
 
433
 *      None.
 
434
 *
 
435
 * Side effects:
 
436
 *      The list of glob patterns in clausePtr->patterns are freed.
 
437
 *----------------------------------------------------------------------
 
438
 */
 
439
 
 
440
static void
 
441
FreeGlobPatterns(clausePtr)
 
442
    FileFilterClause * clausePtr;/* The clause whose patterns are to be freed*/
 
443
{
 
444
    GlobPattern * globPtr, * toFree;
 
445
 
 
446
    globPtr = clausePtr->patterns;
 
447
    while (globPtr) {
 
448
        toFree = globPtr;
 
449
        globPtr=globPtr->next;
 
450
 
 
451
        ckfree((char*)toFree->pattern);
 
452
        ckfree((char*)toFree);
 
453
    }
 
454
    clausePtr->patterns = NULL;
 
455
}
 
456
 
 
457
/*
 
458
 *----------------------------------------------------------------------
 
459
 *
 
460
 * FreeMacFileTypes --
 
461
 *
 
462
 *      Frees the malloc'ed Mac file types in a clause
 
463
 *
 
464
 * Results:
 
465
 *      None.
 
466
 *
 
467
 * Side effects:
 
468
 *      The list of Mac file types in clausePtr->macTypes are freed.
 
469
 *----------------------------------------------------------------------
 
470
 */
 
471
 
 
472
static void
 
473
FreeMacFileTypes(clausePtr)
 
474
    FileFilterClause * clausePtr;  /* The clause whose mac types are to be
 
475
                                    * freed */
 
476
{
 
477
    MacFileType * mfPtr, * toFree;
 
478
 
 
479
    mfPtr = clausePtr->macTypes;
 
480
    while (mfPtr) {
 
481
        toFree = mfPtr;
 
482
        mfPtr=mfPtr->next;
 
483
        ckfree((char*)toFree);
 
484
    }
 
485
    clausePtr->macTypes = NULL;
 
486
}