1 /*
2 *****************************************************************************
3 ** FILE: misc.c
4 **
5 ** xbmbrowser is Public Domain. However it, and all the code still belong to me.
6 ** I do, however grant permission for you to freely copy and distribute it on
7 ** the condition that this and all other copyright notices remain unchanged in
8 ** all distributions.
9 **
10 ** This software comes with NO warranty whatsoever. I therefore take no
11 ** responsibility for any damages, losses or problems that the program may
12 ** cause.
13 ** Anthony Thyssen and Ashley Roll
14 *****************************************************************************
15 */
16
17 #include <sys/types.h> /* for missing types in stat.h */
18 #include <sys/stat.h>
19 #include "xbmbrowser.h"
20
21 /* Marco for brain dead Ultrix and SVR4 machines
22 ** Brian Dowling <bdowling@ccs.neu.edu> -- Ultrix
23 ** John Polstra <jdp@polstra.com> -- SVR4
24 */
25 #ifndef S_ISLNK
26 # ifdef S_IFLNK
27 # if defined(_S_IFMT) /* Ultrix */
28 # define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK)
29 # elif defined(S_IFMT) /* SVR4 */
30 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
31 # endif
32 # else /* no S_IFLNK then system probably has no symlinks */
33 # define S_ISLNK(mode) (0)
34 # endif
35 #endif
36
37
38 /*========================================================================*/
39 /* Cursour Control for Application */
40
41 void
set_busywait()42 set_busywait()
43 /* change the cursour to a busy symbol */
44 {
45 XtVaSetValues(mainpw, XtNcursor, (XtArgVal)waitCursor, NULL);
46 XFlush(display);
47 }
48
49
50 void
clear_busywait()51 clear_busywait()
52 /* clear the busywait cursour back to normal */
53 {
54 XtVaSetValues(mainpw, XtNcursor, (XtArgVal)normalCursor, NULL);
55 XFlush(display);
56 }
57
58 /*========================================================================*/
59 /* Control over the stipple of the icon box display */
60 static Pixmap stipple = (Pixmap)None;
61
62 void
set_stipple()63 set_stipple()
64 /* set/reset the stipple pattern on the iconbox */
65 {
66 XtVaSetValues(iconbox,
67 XtNbackgroundPixmap,
68 (XtArgVal)(app_data.solid_bgnd ? XtUnspecifiedPixmap
69 : stipple ), NULL );
70 }
71
72 void
init_stipple()73 init_stipple()
74 /* initialize the ability to and and remove the stipple in iconbox */
75 {
76 Pixel foreground;
77
78 /* find and set the stipple background pattern */
79 XtVaGetValues(iconbox, XtNborderColor, &foreground, NULL);
80 stipple = XmuCreateStippledPixmap(
81 XtScreen(iconbox), foreground, app_data.stipple_bg, depth);
82 XtVaSetValues(iconbox,
83 XtNbackground, app_data.solid_bg,
84 XtNbackgroundPixmap,
85 (XtArgVal)(app_data.solid_bgnd ? XtUnspecifiedPixmap
86 : stipple ), NULL );
87 }
88
89 /*========================================================================*/
90 /* sort a linked list of the files just read in */
91
92 static Item *r; /* remainer of the list (find the second half to merge) */
93
94 static Item *
merge(a,b)95 merge(a,b)
96 Item *a, *b;
97 {
98 Item aux, *temp = &aux;
99
100 while(b != NULL)
101 if(a == NULL) {
102 a = b;
103 break;
104 } else
105 if( strcmp( b->fname, a->fname ) > 0) {
106 temp = temp->next = a;
107 a = a->next;
108 } else {
109 temp = temp->next = b;
110 b = b->next;
111 }
112
113 temp->next = a;
114 return(aux.next);
115 }
116
117 static Item *
sort(n)118 sort(n)
119 int n;
120 {
121 Item *fi,*la, *temp;
122
123 if(r == NULL) return(NULL);
124 else if(n > 1)
125 return(merge(sort(n/2),sort((n+1)/2)));
126 else {
127 fi = r;
128 la = r;
129 /* build list as long as possible */
130 for(r = r->next; r != NULL;)
131 if(strcmp(r->fname,la->fname) >= 0) {
132 la->next = r;
133 la = r;
134 r = r->next;
135 }
136 else if(strcmp(r->fname,fi->fname) <= 0) {
137 temp = r;
138 r = r->next;
139 temp->next = fi;
140 fi = temp;
141 }
142 else break;
143
144 la->next = NULL;
145 return(fi);
146 }
147 }
148
149 /*------------------------------------------------------------------------*/
150
151 /* global variables to ease building of linked list */
152 static Item **last_link;
153 static int count;
154
155 static Boolean
read_dir(dir)156 read_dir(dir)
157 /* scan the directory given appending any files found to the list given.
158 ** Recursively decend into subdirectories as required.
159 ** Assumes that directory names end in `/'.
160 */
161 char *dir; /* the directory to scan */
162 {
163 DIR *dirp; /* directory file pointer */
164 struct dirent *dp; /* current directory item */
165 struct stat info; /* file stat info for current item */
166 Item *item; /* the file items infomation (output) */
167 Boolean subdir; /* are we in a sub directory? */
168
169 subdir = strcmp(dir, "./") != 0;
170
171 if( (dirp = opendir(dir)) == NULL )
172 return FALSE; /* this (sub)directory is unaccessable -- Bad! */
173
174 while( (dp = readdir(dirp)) != NULL ) {
175
176 if( strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0 )
177 continue; /* skip directory links */
178
179 item = (Item *)alloc_item();
180 *last_link = item;
181 last_link = &(item->next);
182 count++;
183
184 if( subdir )
185 strncpy(item->fname, dir, MAXNAMLEN);
186 strncat(item->fname, dp->d_name, MAXNAMLEN);
187
188 stat(item->fname, &info); /* discover information about this file */
189
190 if( S_ISREG(info.st_mode) ) { /* IF Plain File */
191 item->type = File; /* normal file (to study further) */
192 item->mtime = info.st_mtime; /* save its last modification time */
193 }
194 else
195 if( S_ISDIR(info.st_mode) ) { /* IF directory -- check if sym-link */
196 lstat(item->fname, &info);
197 item->type = ( S_ISLNK(info.st_mode) ? DirLink : Dir );
198 strncat(item->fname, "/", MAXNAMLEN); /* append `/' to dir name */
199 if( app_data.recursive ) /* do recursion if needed */
200 if( ! read_dir( item->fname ) )
201 item->type = DirBad;
202 } else
203 item->type = Unknown; /* Unknown or Special file type */
204 }
205
206 closedir(dirp);
207
208 return TRUE; /* success -- Good sub-directory */
209 }
210
211 /*------------------------------------------------------------------------*/
212 /*------------------------ Public Functions ------------------------------*/
213
214 Item *
get_files()215 get_files()
216 /* return a linked link of all directory items found in the current
217 ** directory (recursively?). The list is sorted and the first item
218 ** in the list is the parent directory link.
219 */
220 {
221 Item *item; /* pointer to the first item */
222
223 item = (Item *)alloc_item(); /* always alloc at least one item */
224 last_link = &(item->next); /* initialize the lask link pointer */
225 count = 0; /* and no other itams are in the list */
226
227 strcpy(item->fname, "../"); /* this item is the parent link */
228
229 /* do the actual reading of the current directory
230 ** set the first items type in the process.
231 */
232 item->type = (read_dir("./") ? DirUp : DirBad);
233
234 r = item->next; /* don't include first item in the sort */
235 item->next = sort(count);
236 return item;
237 }
238
239 time_t
check_file_time(file)240 check_file_time(file)
241 /* just return the current modification time for this file
242 ** or 0 if deleted or not a file. This is just a quick check
243 ** routine for the rescan_file() function in "images.c"
244 */
245 char *file;
246 {
247 struct stat info; /* file stat info for current item */
248
249 if( stat(file, &info) == 0 && S_ISREG(info.st_mode) ) {
250 return info.st_mtime;
251 }
252 return 0;
253 }
254
255
256