ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/crossedit/Cnv/CnvPath.c
Revision: 1.1
Committed: Fri Feb 3 07:11:45 2006 UTC (18 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Branch point for: UPSTREAM
Log Message:
Initial revision

File Contents

# User Rev Content
1 root 1.1 /*
2     * CnvPath - file selector
3     * Copyright (C) 1993 Petri Heinila
4     *
5     * This program is free software; you can redistribute it and/or modify
6     * it under the terms of the GNU General Public License as published by
7     * the Free Software Foundation; either version 2 of the License, or
8     * (at your option) any later version.
9     *
10     * This program is distributed in the hope that it will be useful,
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     * GNU General Public License for more details.
14     *
15     * You should have received a copy of the GNU General Public License
16     * along with this program; if not, write to the Free Software
17     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18     *
19     * Author can be connected by email from hevi@lut.fi
20     */
21    
22     #include <Cnv.h>
23     #include <debug.h>
24     #include <assert.h>
25    
26     /**********************************************************************
27     * declarations
28     **********************************************************************/
29    
30     static void CnvPathListInit(CnvPath p);
31     static void CnvPathListGet(CnvPath p,String path);
32     static void CnvPathEnter(CnvPath self);
33     static Boolean hasActions = False;
34     static CnvPath tmpCnvPath = NULL;
35    
36     /**********************************************************************
37     * actions
38     **********************************************************************/
39    
40     static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc);
41    
42     static XtActionsRec actions[] = {
43     {"CnvPathReturn", CnvPathReturn} /* when user accept */
44     };
45    
46     static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc)
47     {
48     CnvPath self = (CnvPath)tmpCnvPath;
49     assert(self);
50     CnvPathEnter(self);
51     }
52    
53     /**********************************************************************
54     * widgets
55     **********************************************************************/
56    
57     static void CnvPathCancelCb(Widget w,XtPointer client,XtPointer call)
58     {
59     CnvPath p = (CnvPath)client;
60     p->hold = CnvPathCancel;
61     }
62    
63     static void CnvPathEnterCb(Widget w,XtPointer client,XtPointer call)
64     {
65     CnvPath self = (CnvPath)client;
66     CnvPathEnter(self);
67     }
68    
69     static void CnvPathSelectFileCb(Widget w,XtPointer client,XtPointer call)
70     {
71     CnvPath p = (CnvPath)client;
72     XawListReturnStruct *ret = (XawListReturnStruct*)call;
73    
74     XtVaSetValues(p->text,
75     XtNstring,ret->string,
76     NULL);
77     }
78    
79     static void CnvPathSelectDirCb(Widget w,XtPointer client,XtPointer call)
80     {
81     CnvPath p = (CnvPath)client;
82     XawListReturnStruct *ret = (XawListReturnStruct*)call;
83     char path[PATH_MAX+1];
84    
85     if(strcmp(ret->string,"..") == 0) {
86     char *str;
87     pathcpy(path,p->current);
88     str = path + strlen(path);
89     while(*str != '/' && str > path) str--;
90     *str = 0;
91     } else if(strcmp(ret->string,".") == 0) {
92     sprintf(path,"%s",p->current);
93     } else {
94     sprintf(path,"%s/%s",p->current,ret->string);
95     }
96     p->hold = CnvPathHold;
97     CnvPathListGet(p,path);
98     }
99    
100     /**********************************************************************
101     * Layout
102     **********************************************************************/
103    
104     static void Layout(CnvPath self,String name)
105     {
106     Widget cont,cancel,fileView,dirView,ok;
107    
108     self->shell = XtVaCreatePopupShell
109     (name,transientShellWidgetClass,cnv->shell,NULL);
110     cont = XtVaCreateManagedWidget
111     ("cont",formWidgetClass,self->shell,
112     NULL);
113     self->cwd = XtVaCreateManagedWidget
114     ("cwd",labelWidgetClass,cont,
115     /*
116     XtNfromHoriz,NULL,
117     XtNfromVert,NULL,
118     */
119     NULL);
120     self->text = XtVaCreateManagedWidget
121     ("text",asciiTextWidgetClass,cont,
122     XtNtype,XawAsciiString,
123     XtNeditType,XawtextEdit,
124     XtNfromHoriz,self->cwd,
125     XtNfromVert,NULL,
126     XtNaccelerators,XtParseAcceleratorTable
127     ("#override <Key>Return: CnvPathReturn() \n"),
128     XtNtranslations,XtParseTranslationTable
129     ("#override <Key>Tab: CnvNop()\n"
130     "<Key>Return: CnvPathReturn() \n"),
131     NULL);
132     fileView = XtVaCreateManagedWidget
133     ("fileView",viewportWidgetClass,cont,
134     XtNfromHoriz,NULL,
135     XtNfromVert,self->cwd,
136     NULL);
137     self->fileList = XtVaCreateManagedWidget
138     ("fileList",listWidgetClass,fileView,
139     XtNtranslations,XtParseTranslationTable
140     ("#override <Btn1Up>(2): Set() Notify() CnvPathReturn()\n"
141     "<Btn1Down>: Set() Notify() \n"),
142     NULL);
143     XtAddCallback(self->fileList,XtNcallback,CnvPathSelectFileCb,
144     (XtPointer)self);
145     dirView = XtVaCreateManagedWidget
146     ("dirView",viewportWidgetClass,cont,
147     XtNfromHoriz,fileView,
148     XtNfromVert,self->cwd,
149     NULL);
150     self->dirList = XtVaCreateManagedWidget
151     ("dirList",listWidgetClass,dirView,
152     NULL);
153     XtAddCallback(self->dirList,XtNcallback,CnvPathSelectDirCb,(XtPointer)self);
154     ok = XtVaCreateManagedWidget
155     ("ok",commandWidgetClass,cont,
156     XtNfromHoriz,NULL,
157     XtNfromVert,fileView,
158     NULL);
159     XtAddCallback(ok,XtNcallback,CnvPathEnterCb,(XtPointer)self);
160     cancel = XtVaCreateManagedWidget
161     ("cancel",commandWidgetClass,cont,
162     XtNfromHoriz,ok,
163     XtNfromVert,fileView,
164     NULL);
165     XtAddCallback(cancel,XtNcallback,CnvPathCancelCb,(XtPointer)self);
166     XtInstallAllAccelerators(cont,cont);
167     }
168    
169     /**********************************************************************
170     *
171     **********************************************************************/
172    
173     /*
174     * function: select a filepath
175     */
176     static void CnvPathEnter(CnvPath self)
177     {
178     String str;
179    
180     self->hold = CnvPathOk;
181     XtVaGetValues(self->text,
182     XtNstring,&str,
183     NULL);
184     namecpy(self->filename,str);
185     }
186    
187     /*
188     * implicit: App app
189     */
190     static void CnvPathListInit(CnvPath p)
191     {
192     int i;
193    
194     for(i=0; i < EntryMax; i++) {
195     /* debug1("i:%i\n",i); */
196     p->fileTable[i] = NULL;
197     }
198     for(i=0; i < EntryMax; i++) {
199     /* debug1("i2:%i\n",i); */
200     p->dirTable[i] = NULL;
201     }
202     p->fileNro = 0;
203     p->dirNro = 0;
204     *(p->filename) = 0;
205     }
206    
207     /*
208     * compare funtion for sorting in CnvPathListGet()
209     */
210     static int StrCmp (const void **s1, const void **s2)
211     {
212     return strcmp (*s1, *s2);
213     }
214    
215     /*
216     * read files and directories from given absolute dir
217     * update them into Path structure. directoty is a crossfire
218     * part of file name ie. LibDir/MapDir<dirname>, althought
219     * it is absolute name in it part, ie it have to begin with '/'.
220     */
221     static void CnvPathListGet(CnvPath self,String directory)
222     {
223     DIR *dir;
224     #ifdef NeXT
225     struct direct *dirent;
226     #else
227     struct dirent *dirent;
228     #endif
229     struct stat statbuf;
230     Cardinal i,fileOld,dirOld;
231     char path[PATH_MAX+1],full[PATH_MAX+1];
232    
233     /*** form full dir name ***/
234     sprintf(full,"%s%s",self->root,directory);
235     debug1("CnvPathListGet(), rescan %s\n",full);
236    
237     /*** open it ***/
238     if(CnvPathNoAccess(self->shell, full)) return;
239     if((dir = opendir(full)) == NULL) CnvDie(self->shell,full);
240     XtVaSetValues(self->cwd,
241     XtNlabel,directory,
242     NULL);
243     pathcpy(self->current,directory);
244    
245     /*** read dir & files ***/
246     fileOld = self->fileNro;
247     dirOld = self->dirNro;
248     self->fileNro = 0;
249     self->dirNro = 0;
250     while((dirent = readdir(dir)) != NULL) {
251     sprintf(path,"%s/%s",full,dirent->d_name);
252    
253     if (stat ((char *) path, &statbuf) == -1) {
254     perror (path);
255     continue;
256     }
257     if(S_ISDIR(statbuf.st_mode)) {
258     if(self->dirNro >= EntryMax) continue;
259    
260     XtFree(self->dirTable[self->dirNro]);
261     self->dirTable[self->dirNro] = XtNewString(dirent->d_name);
262    
263     self->dirNro++;
264     } else {
265     if(self->fileNro >= EntryMax) continue;
266    
267     XtFree(self->fileTable[self->fileNro]);
268     self->fileTable[self->fileNro] = XtNewString(dirent->d_name);
269    
270     self->fileNro++;
271     }
272     }
273     closedir(dir);
274    
275     /*** free strings ***/
276     for(i = self->fileNro; i < fileOld; i++) {
277     XtFree(self->fileTable[i]);
278     self->fileTable[i] = NULL;
279     }
280     for(i = self->dirNro; i < dirOld; i++) {
281     XtFree(self->dirTable[i]);
282     self->dirTable[i] = NULL;
283     }
284    
285     /*** sort tables ***/
286     qsort(self->fileTable,self->fileNro,sizeof(String),(int (*)())StrCmp);
287     qsort(self->dirTable,self->dirNro,sizeof(String),(int (*)())StrCmp);
288    
289     /*** update ***/
290     XawListChange(self->fileList,self->fileTable,self->fileNro,0,True);
291     XawListChange(self->dirList,self->dirTable,self->dirNro,0,True);
292     }
293    
294     /**********************************************************************
295     * public
296     **********************************************************************/
297    
298     /*
299     * create new instance of file-selector, no show
300     * dir is crossfire path eg "/"
301     * name: name of this module
302     * root: all
303     * dir : starting directory
304     */
305     CnvPath CnvPathCreate(String name,String root,String dir)
306     {
307    
308    
309     CnvPath self;
310    
311     debug3("CnvPathCreate() %s %s %s\n",name,root,dir);
312     self = (CnvPath) XtMalloc (sizeof (struct CnvPath));
313     memset(self,0,sizeof(struct CnvPath));
314     pathcpy(self->root,root);
315    
316     /*** initialize translations if not done ***/
317     if(hasActions == False) {
318     XtAppAddActions(XtWidgetToApplicationContext(cnv->shell),
319     actions,
320     XtNumber(actions));
321     hasActions = True;
322     }
323     Layout(self,name);
324     CnvPathListInit(self);
325     CnvCenterWidget(self->shell);
326     CnvPathListGet(self,dir);
327     return self;
328     }
329    
330     /*
331     * remove instance of file-selector
332     */
333     void CnvPathDestroy(CnvPath self)
334     {
335     Cardinal i;
336     debug("CnvPathDestroy()\n");
337    
338     for(i=0;i<self->dirNro;i++) XtFree(self->dirTable[i]);
339     for(i=0;i<self->fileNro;i++) XtFree(self->fileTable[i]);
340     XtDestroyWidget(self->shell);
341     }
342    
343     /*
344     * member: select a filepath
345     * return: PathResponce & results are in Path-structure
346     */
347     CnvPathResponce CnvPathSelect(CnvPath self)
348     {
349     if(tmpCnvPath) {
350     CnvNotify("File Selector already in use",
351     "Continue",NULL);
352     return CnvPathCancel;
353     }
354     XtVaSetValues(self->text,
355     XtNstring,self->filename,
356     NULL);
357     /*** round ***/
358     tmpCnvPath = self;
359     self->hold = CnvPathHold;
360     XtPopup(self->shell,XtGrabExclusive);
361     while(self->hold == CnvPathHold) {
362     XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
363     }
364     XtPopdown(self->shell);
365     tmpCnvPath = NULL;
366     return self->hold;
367     }
368    
369     /*
370     * member: select a filepath
371     * return: PathResponce & results are in Path-structure
372     */
373     CnvPathResponce CnvPathSelectAbs(CnvPath self,String path)
374     {
375     if(tmpCnvPath) {
376     CnvNotify("File Selector already in use",
377     "Continue",NULL);
378     return CnvPathCancel;
379     }
380     XtVaSetValues(self->text,
381     XtNstring,self->filename,
382     NULL);
383     /*** round ***/
384     tmpCnvPath = self;
385     self->hold = CnvPathHold;
386     XtPopup(self->shell,XtGrabExclusive);
387     while(self->hold == CnvPathHold) {
388     XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
389     }
390     XtPopdown(self->shell);
391     tmpCnvPath = NULL;
392     sprintf(path,"%s%s/%s",self->root,self->current,self->filename);
393     return self->hold;
394     }
395    
396     /**********************************************************************
397     * utility
398     **********************************************************************/
399    
400     /*
401     * - path is full absolute name
402     * - return true if NO access
403     */
404     Boolean CnvPathNoAccess(Widget w, String path)
405     {
406     char buf[BUFSIZ];
407    
408     if (access (path, R_OK | X_OK) == -1) {
409     switch (errno) {
410     case EACCES:
411     sprintf (buf, "Permission denied for %s", path);
412     CnvNotify (buf,Continue,NULL);
413     break;
414     case ENOENT:
415     sprintf (buf, "%s does not exist", path);
416     CnvNotify (buf,Continue,NULL);
417     break;
418     case EIO:
419     sprintf (buf, "IO error in accessing %s", path);
420     CnvNotify (buf,Continue,NULL);
421     break;
422     case ENAMETOOLONG:
423     case ENOTDIR:
424     sprintf (buf, "Error in pathname for %s", path);
425     CnvNotify (buf,Continue);
426     break;
427     default:
428     sprintf (buf, "Error accessing to %s", path);
429     CnvNotify (buf,Continue,NULL);
430     break;
431     }
432     return True;
433     } else {
434     return False;
435     }
436     }
437    
438     /*
439     * - path is full absolute name
440     * - return true if NO access
441     */
442     Boolean CnvPathNoWrite(Widget w, String path)
443     {
444     char buf[BUFSIZ];
445    
446     if (access (path, R_OK | W_OK) == -1) {
447     switch (errno) {
448     case EACCES:
449     sprintf (buf, "Permission denied for %s", path);
450     CnvNotify (buf,Continue,NULL);
451     break;
452     case ENOENT:
453     sprintf (buf, "%s does not exist", path);
454     CnvNotify (buf,Continue,NULL);
455     break;
456     case EIO:
457     sprintf (buf, "IO error in accessing %s", path);
458     CnvNotify (buf,Continue,NULL);
459     break;
460     case ENAMETOOLONG:
461     case ENOTDIR:
462     sprintf (buf, "Error in pathname for %s", path);
463     CnvNotify (buf,Continue);
464     break;
465     default:
466     sprintf (buf, "Error accessing to %s", path);
467     CnvNotify (buf,Continue,NULL);
468     break;
469     }
470     return True;
471     } else {
472     return False;
473     }
474     }
475    
476     /*** end of CnvPath.c ***/
477    
478