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