4
* Process the -filetypes option for the file dialogs on Windows and the
7
* Copyright (c) 1996 Sun Microsystems, Inc.
9
* See the file "license.terms" for information on usage and redistribution
10
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
* RCS: @(#) $Id: tkFileFilter.c,v 1.2 1998/09/14 18:23:10 stanton Exp $
17
#include "tkFileFilter.h"
19
static int AddClause _ANSI_ARGS_((
20
Tcl_Interp * interp, FileFilter * filterPtr,
21
char * patternsStr, char * ostypesStr,
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,
32
*----------------------------------------------------------------------
34
* TkInitFileFilters --
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, ...);
43
* TkFreeFileFilters(&flist);
49
* The fields in flistPtr are initialized.
50
*----------------------------------------------------------------------
54
TkInitFileFilters(flistPtr)
55
FileFilterList * flistPtr; /* The structure to be initialized. */
57
flistPtr->filters = NULL;
58
flistPtr->filtersTail = NULL;
59
flistPtr->numFilters = 0;
63
*----------------------------------------------------------------------
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.
73
* flistPtr must be initialized (See comments in TkInitFileFilters).
76
* A standard TCL return value.
79
* The fields in flistPtr are changed according to string.
80
*----------------------------------------------------------------------
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. */
90
char ** listArgv = NULL;
91
char ** typeInfo = NULL;
95
if (Tcl_SplitList(interp, string, &listArgc, &listArgv) != TCL_OK) {
103
* Free the filter information that have been allocated the previous
104
* time -- the -filefilters option may have been used more than once in
107
TkFreeFileFilters(flistPtr);
109
for (i = 0; i<listArgc; i++) {
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.
116
FileFilter * filterPtr;
118
if (Tcl_SplitList(interp, listArgv[i], &count, &typeInfo) != TCL_OK) {
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);
131
filterPtr = GetFilter(flistPtr, typeInfo[0]);
134
code = AddClause(interp, filterPtr, typeInfo[1], NULL,
137
code = AddClause(interp, filterPtr, typeInfo[1], typeInfo[2],
140
if (code != TCL_OK) {
145
ckfree((char*)typeInfo);
152
ckfree((char*)typeInfo);
155
ckfree((char*)listArgv);
161
*----------------------------------------------------------------------
163
* TkFreeFileFilters --
165
* Frees the malloc'ed file filter information.
171
* The fields allocated by TkGetFileFilters() are freed.
172
*----------------------------------------------------------------------
176
TkFreeFileFilters(flistPtr)
177
FileFilterList * flistPtr; /* List of file filters to free */
179
FileFilter * filterPtr, *toFree;
181
filterPtr=flistPtr->filters;
184
filterPtr=filterPtr->next;
186
ckfree((char*)toFree->name);
187
ckfree((char*)toFree);
189
flistPtr->filters = NULL;
193
*----------------------------------------------------------------------
197
* Add one FileFilterClause to filterPtr.
200
* A standard TCL result.
203
* The list of filter clauses are updated in filterPtr.
204
*----------------------------------------------------------------------
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 */
217
char ** globList = NULL;
219
char ** ostypeList = NULL;
221
FileFilterClause * clausePtr;
225
if (Tcl_SplitList(interp, patternsStr, &globCount, &globList)!= TCL_OK) {
229
if (ostypesStr != NULL) {
230
if (Tcl_SplitList(interp, ostypesStr, &ostypeCount, &ostypeList)
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);
246
* Add the clause into the list of clauses
249
clausePtr = (FileFilterClause*)ckalloc(sizeof(FileFilterClause));
250
clausePtr->patterns = NULL;
251
clausePtr->patternsTail = NULL;
252
clausePtr->macTypes = NULL;
253
clausePtr->macTypesTail = NULL;
255
if (filterPtr->clauses == NULL) {
256
filterPtr->clauses = filterPtr->clausesTail = clausePtr;
258
filterPtr->clausesTail->next = clausePtr;
259
filterPtr->clausesTail = clausePtr;
261
clausePtr->next = NULL;
263
if (globCount > 0 && globList != NULL) {
264
for (i=0; i<globCount; i++) {
265
GlobPattern * globPtr = (GlobPattern*)ckalloc(sizeof(GlobPattern));
268
len = (strlen(globList[i]) + 1) * sizeof(char);
270
if (globList[i][0] && globList[i][0] != '*') {
272
* Prepend a "*" to patterns that do not have a leading "*"
274
globPtr->pattern = (char*)ckalloc(len+1);
275
globPtr->pattern[0] = '*';
276
strcpy(globPtr->pattern+1, globList[i]);
278
else if (isWindows) {
279
if (strcmp(globList[i], "*") == 0) {
280
globPtr->pattern = (char*)ckalloc(4*sizeof(char));
281
strcpy(globPtr->pattern, "*.*");
283
else if (strcmp(globList[i], "") == 0) {
285
* An empty string means "match all files with no
287
* BUG: "*." actually matches with all files on Win95
289
globPtr->pattern = (char*)ckalloc(3*sizeof(char));
290
strcpy(globPtr->pattern, "*.");
293
globPtr->pattern = (char*)ckalloc(len);
294
strcpy(globPtr->pattern, globList[i]);
297
globPtr->pattern = (char*)ckalloc(len);
298
strcpy(globPtr->pattern, globList[i]);
302
* Add the glob pattern into the list of patterns.
305
if (clausePtr->patterns == NULL) {
306
clausePtr->patterns = clausePtr->patternsTail = globPtr;
308
clausePtr->patternsTail->next = globPtr;
309
clausePtr->patternsTail = globPtr;
311
globPtr->next = NULL;
314
if (ostypeCount > 0 && ostypeList != NULL) {
315
for (i=0; i<ostypeCount; i++) {
316
MacFileType * mfPtr = (MacFileType*)ckalloc(sizeof(MacFileType));
318
memcpy(&mfPtr->type, ostypeList[i], sizeof(OSType));
321
* Add the Mac type pattern into the list of Mac types
323
if (clausePtr->macTypes == NULL) {
324
clausePtr->macTypes = clausePtr->macTypesTail = mfPtr;
326
clausePtr->macTypesTail->next = mfPtr;
327
clausePtr->macTypesTail = mfPtr;
335
ckfree((char*)globList);
338
ckfree((char*)ostypeList);
345
*----------------------------------------------------------------------
349
* Add one FileFilter to flistPtr.
352
* A standard TCL result.
355
* The list of filters are updated in flistPtr.
356
*----------------------------------------------------------------------
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
366
FileFilter * filterPtr;
368
for (filterPtr=flistPtr->filters; filterPtr; filterPtr=filterPtr->next) {
369
if (strcmp(filterPtr->name, name)==0) {
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);
380
if (flistPtr->filters == NULL) {
381
flistPtr->filters = flistPtr->filtersTail = filterPtr;
383
flistPtr->filtersTail->next = filterPtr;
384
flistPtr->filtersTail = filterPtr;
386
filterPtr->next = NULL;
388
++flistPtr->numFilters;
393
*----------------------------------------------------------------------
397
* Frees the malloc'ed file type clause
403
* The list of clauses in filterPtr->clauses are freed.
404
*----------------------------------------------------------------------
408
FreeClauses(filterPtr)
409
FileFilter * filterPtr; /* FileFilter whose clauses are to be freed */
411
FileFilterClause * clausePtr, * toFree;
413
clausePtr = filterPtr->clauses;
416
clausePtr=clausePtr->next;
417
FreeGlobPatterns(toFree);
418
FreeMacFileTypes(toFree);
419
ckfree((char*)toFree);
421
filterPtr->clauses = NULL;
422
filterPtr->clausesTail = NULL;
426
*----------------------------------------------------------------------
428
* FreeGlobPatterns --
430
* Frees the malloc'ed glob patterns in a clause
436
* The list of glob patterns in clausePtr->patterns are freed.
437
*----------------------------------------------------------------------
441
FreeGlobPatterns(clausePtr)
442
FileFilterClause * clausePtr;/* The clause whose patterns are to be freed*/
444
GlobPattern * globPtr, * toFree;
446
globPtr = clausePtr->patterns;
449
globPtr=globPtr->next;
451
ckfree((char*)toFree->pattern);
452
ckfree((char*)toFree);
454
clausePtr->patterns = NULL;
458
*----------------------------------------------------------------------
460
* FreeMacFileTypes --
462
* Frees the malloc'ed Mac file types in a clause
468
* The list of Mac file types in clausePtr->macTypes are freed.
469
*----------------------------------------------------------------------
473
FreeMacFileTypes(clausePtr)
474
FileFilterClause * clausePtr; /* The clause whose mac types are to be
477
MacFileType * mfPtr, * toFree;
479
mfPtr = clausePtr->macTypes;
483
ckfree((char*)toFree);
485
clausePtr->macTypes = NULL;