ff317e59abd4aebaa4f9ceb9a854cacab07b3f60
[xboard.git] / filebrowser / dir.c
1 /*
2  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
3  *
4  * Permission to use, copy, modify, and distribute this software and its
5  * documentation for any purpose and without fee is hereby granted, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Software Research Associates not be used
9  * in advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  Software Research Associates
11  * makes no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
17  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Author: Erik M. van der Poel
23  *         Software Research Associates, Inc., Tokyo, Japan
24  *         erik@sra.co.jp
25  */
26
27 #include <stdio.h>
28 #include <stdlib.h> /* for qsort */
29 #include "config.h" /* to check for dirent.h */
30
31 #ifdef SEL_FILE_IGNORE_CASE
32 #include <ctype.h>
33 #endif /* def SEL_FILE_IGNORE_CASE */
34
35 #ifdef HAVE_DIRENT_H
36 #include <dirent.h>
37 #else
38 #include <sys/dir.h>
39 #define dirent direct
40 #endif
41
42 #include <sys/stat.h>
43
44 #include "selfile.h"
45
46 #ifdef SEL_FILE_IGNORE_CASE
47 int
48 SFcompareEntries(p, q)
49         SFEntry *p;
50         SFEntry *q;
51 {
52         register char   *r, *s;
53         register char   c1, c2;
54
55         r = p->real;
56         s = q->real;
57
58         c1 = *r++;
59         if (islower(c1)) {
60                 c1 = toupper(c1);
61         }
62         c2 = *s++;
63         if (islower(c2)) {
64                 c2 = toupper(c2);
65         }
66
67         while (c1 == c2) {
68                 if (!c1) {
69                         return strcmp(p->real, q->real);
70                 }
71                 c1 = *r++;
72                 if (islower(c1)) {
73                         c1 = toupper(c1);
74                 }
75                 c2 = *s++;
76                 if (islower(c2)) {
77                         c2 = toupper(c2);
78                 }
79         }
80
81         return c1 - c2;
82 }
83 #else /* def SEL_FILE_IGNORE_CASE */
84 int
85 SFcompareEntries(p, q)
86         SFEntry *p;
87         SFEntry *q;
88 {
89         return strcmp(p->real, q->real);
90 }
91 #endif /* def SEL_FILE_IGNORE_CASE */
92
93 int
94 SFgetDir(dir)
95         SFDir   *dir;
96 {
97         SFEntry         *result = NULL;
98         int             alloc = 0;
99         int             i;
100         DIR             *dirp;
101         struct dirent   *dp;
102         char            *str;
103         int             len;
104         int             maxChars;
105         struct stat     statBuf;
106
107         maxChars = strlen(dir->dir) - 1;
108
109         dir->entries = NULL;
110         dir->nEntries = 0;
111         dir->nChars = 0;
112
113         result = NULL;
114         i = 0;
115
116         dirp = opendir(".");
117         if (!dirp) {
118                 return 1;
119         }
120
121         (void) stat(".", &statBuf);
122         dir->mtime = statBuf.st_mtime;
123
124         while (dp = readdir(dirp)) {
125
126                 struct stat statBuf;
127                 if(!strcmp(dp->d_name, ".")) continue; /* Throw away "." */
128                 if(!strcmp(dp->d_name, "..")) continue; /* Throw away ".." */
129 #ifndef S_IFLNK
130 #endif /* ndef S_IFLNK */
131                 if (i >= alloc) {
132                         alloc = 2 * (alloc + 1);
133                         result = (SFEntry *) XtRealloc((char *) result,
134                                 (unsigned) (alloc * sizeof(SFEntry)));
135                 }
136                 result[i].statDone = 0;
137                 str = dp->d_name;
138                 len = strlen(str);
139                 result[i].real = XtMalloc((unsigned) (len + 2));
140                 (void) strcat(strcpy(result[i].real, str), " ");
141                 if (len > maxChars) {
142                         maxChars = len;
143                 }
144                 result[i].shown = result[i].real;
145                 if(SFpathFlag) { // [HGM] only show directories
146                         if (stat(str, &statBuf) || SFstatChar(&statBuf) != '/') continue;
147                 } else if(SFfilterBuffer[0]) { // [HGM] filter on extension
148                     char *p = SFfilterBuffer, match, *q;
149                     match = !(stat(str, &statBuf) || SFstatChar(&statBuf) != '/');
150                     do {
151                         if(q = strchr(p, ' ')) *q = 0;
152                         if(strstr(str, p)) match++;
153                         if(q) *q = ' ';
154                     } while(q && (p = q+1));
155                     if(!match) continue;
156                 }
157                 i++;
158         }
159
160         qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
161
162         dir->entries = result;
163         dir->nEntries = i;
164         dir->nChars = maxChars + 1;
165
166         closedir(dirp);
167
168         return 0;
169 }