1 /* $Header: /home/yav/xpx/RCS/file.c,v 1.62 1996/04/23 10:58:05 yav Exp $
2  * xpx file menu
3  * written by yav (UHD98984@pcvan.or.jp)
4  */
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/keysym.h>
9 
10 #include "headers.h"
11 #include "xpx.h"
12 #include "work.h"
13 #include "icondef.h"
14 #include "infodef.h"
15 #define PUBLIC_FILE_C
16 #include "extern.h"
17 
18 # ifdef HAVE_SYS_WAIT_H
19 #  include <sys/wait.h>
20 # endif
21 
22 #define FILEWINWIDTH	320
23 #define FILEWINHEIGHT	320
24 
25 #define MAXFILE	1024
26 #define MAXFILENAME	64
27 
28 #define PATHX	8
29 #define PATHY	8
30 #define PATHW	300
31 #define PATHH	24
32 
33 #define NAMEX	160
34 #define NAMEY	100
35 #define NAMEW	140
36 #define NAMEH	PATHH
37 
38 #define DIRSLOTMAX	12
39 #define FILESLOTMAX	14	/* >= DIRSLOTMAX+1 */
40 
41 #define SCROLLX		(8-BDW)
42 #define SCROLLY		40
43 #define SCROLLW		128
44 #define SCROLLH		20
45 #define DIRSLOTX	(SCROLLX+BDW)
46 #define DIRSLOTY	(SCROLLY+SCROLLH+BDW*2)
47 #define DIRSLOTW	SCROLLW
48 #define DIRSLOTH	18
49 
50 #define FILEMENUX	196
51 #define FILEMENUY	160
52 #define FILEMENUW	64
53 #define FILEMENUH	20
54 
55 #define SLIDERW	16
56 #define SLIDERH	(DIRSLOTH*DIRSLOTMAX)
57 
58 #define COLNMX	0
59 #define COLNMY	0
60 #define COLNMW	112
61 #define COLNMH	16
62 #define IMGNMX	COLNMX+COLNMW+8
63 #define IMGNMY	COLNMY
64 #define IMGNMW	COLNMW
65 #define IMGNMH	COLNMH
66 
67 char rcsid_file[] = "$Id: file.c,v 1.62 1996/04/23 10:58:05 yav Exp $";
68 
69 static Window file2win;
70 static int select_slot;
71 static char *filenamebuf;
72 static char current_path[MAXPATH];
73 static char current_name[MAXFILENAME];
74 static int files_count;
75 static int scroll_range;
76 static int scroll_pos;
77 static int slotindex[FILESLOTMAX];
78 static int file_scroll_speed;
79 static char *rcfile = ".xpxrc";
80 
81 #define F_IMG	(1<<0)
82 #define F_COL	(1<<1)
83 #define F_ALL	(F_IMG|F_COL)
84 
85 typedef struct {
86   char suffix[8];
87   int mode;
88   int (*readroutine)();
89   int (*writeroutine)();
90   char *decoder;
91   char *encoder;
92 } FTYPE;
93 
94 #define FTYPEMAX 32
95 static FTYPE *file_type_tbl = NULL;
96 static FTYPE default_file_type[] = {
97   {".cbb",	F_IMG,	rd_cbb,	wr_cbb,	NULL,		NULL},
98   {".csb",	F_IMG,	rd_csb,	NULL,	NULL,		NULL},
99   {".ccb",	F_COL,	rd_ccb,	wr_ccb,	NULL,		NULL},
100   {".cxb",	F_COL,	rd_cxb,	wr_cxb, NULL,		NULL},
101   {".kcf",	F_COL,	rd_kcf,	wr_kcf, NULL,		NULL},
102   {".cel",	F_IMG,	rd_cel,	wr_cel, NULL,		NULL},
103   {".pbm",	F_ALL,	rd_pnm,	NULL,	NULL,		NULL},
104   {".pgm",	F_ALL,	rd_pnm,	NULL,	NULL,		NULL},
105   {".ppm",	F_ALL,	rd_pnm,	wr_ppm,	NULL,		NULL},
106   {".mag",	F_ALL,	rd_mag,	wr_mag,	NULL,		NULL},
107   {".xbm",	F_IMG,	rd_xbm,	wr_xbm,	NULL,		NULL},
108   {".gif",	F_ALL,	rd_pnm,	wr_ppm,	"giftoppm",	"ppmtogif"},
109   {".tim",	F_ALL,	rd_tim,	wr_tim,	NULL,		NULL},
110   {".nbn",	F_ALL,	rd_nbn,	NULL,	NULL,		NULL},
111   {".cls",	F_COL,	rd_cls,	NULL,	NULL,		NULL},
112   {"",		0,	NULL,	NULL,	NULL,		NULL}
113 };
114 
115 #define FILE_PATH	0
116 #define FILE_NAME	1
117 #define FILE_OPEN	2
118 #define FILE_SAVE	3
119 #define FILE_MASK	4
120 #define FILE_REMOVE	5
121 #define FILE_DUMMY2	6
122 #define FILE_OK		7
123 #define FILE_SLIDER	8
124 
125 int fileev();
126 int slotev();
127 int slotev2();
128 void scroll_down();
129 void scroll_up();
130 
131 #define IMASK (ExposureMask|EnterWindowMask|LeaveWindowMask|\
132 	       ButtonPressMask|ButtonReleaseMask)
133 static MENU filemenu[] = {
134   {
135     FILE_PATH,	MenuModeMaskBorder,
136     PATHX, PATHY, PATHW, PATHH,
137     0, ExposureMask|EnterWindowMask|LeaveWindowMask|KeyPressMask, 0,
138     fileev, NULL, 0, MAXPATH, NULL},
139   {
140     FILE_NAME,	MenuModeMaskBorder,
141     NAMEX, NAMEY, NAMEW, NAMEH,
142     0, ExposureMask|EnterWindowMask|LeaveWindowMask|KeyPressMask, 0,
143     fileev, NULL, 0, 64, NULL},
144   {
145     FILE_OPEN,	MenuModeMaskBorder,
146     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*0, FILEMENUW, FILEMENUH,
147     0, IMASK, 0,
148     fileev, NULL, 0, 0, "Open"},
149   {
150     FILE_SAVE,	MenuModeMaskBorder,
151     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*1, FILEMENUW, FILEMENUH,
152     0, IMASK, 0,
153     fileev, NULL, 0, 0, "Save"},
154   {
155     FILE_MASK,	MenuModeMaskBorder|MenuModeMaskOn,
156     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*2, FILEMENUW, FILEMENUH,
157     0, ExposureMask|EnterWindowMask|LeaveWindowMask|ButtonPressMask, 0,
158     fileev, NULL, 0, 0, "Mask"},
159   {
160     FILE_REMOVE,	MenuModeMaskBorder,
161     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*3, FILEMENUW, FILEMENUH,
162     0, IMASK, 0,
163     fileev, NULL, 0, 0, "Remove"},
164   {
165     FILE_DUMMY2,	MenuModeMaskBorder,
166     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*4, FILEMENUW, FILEMENUH,
167     0, ExposureMask, 0,
168     NULL, NULL, 0, 0, "----"},
169   {
170     FILE_OK,	MenuModeMaskBorder,
171     FILEMENUX, FILEMENUY+(FILEMENUH+BDW)*5, FILEMENUW, FILEMENUH,
172     0, IMASK, 0,
173     fileev, NULL, 0, 0, "OK"},
174   {
175     FILE_SLIDER,	MenuModeMaskBorder,
176     DIRSLOTX+DIRSLOTW+BDW*2, DIRSLOTY, SLIDERW, SLIDERH,
177     0, ExposureMask|ButtonPressMask, 0,
178     NULL, NULL, 0, 0, NULL},
179   {
180     -1,	0,
181     0, 0, 0, 0,
182     0, 0, 0,
183     NULL, NULL, 0, 0, NULL}};
184 #undef IMASK
185 
186 static MENU *fileslot;
187 
188 #define DIRSLOT_UP	0
189 #define DIRSLOT_DOWN	1
190 #define IMASK (ExposureMask|EnterWindowMask|LeaveWindowMask|\
191 	       ButtonPressMask|ButtonReleaseMask)
192 static MENU slotwin[] = {
193   {
194     DIRSLOT_UP,	MenuModeMaskBorder,
195     SCROLLX, SCROLLY, SCROLLW, SCROLLH,
196     0, IMASK, 0,
197     slotev2, NULL, 0, 0, NULL},
198   {
199     DIRSLOT_DOWN,	MenuModeMaskBorder,
200     SCROLLX, SCROLLY+SCROLLH+BDW*4+DIRSLOTH*DIRSLOTMAX, SCROLLW, SCROLLH,
201     0, IMASK, 0,
202     slotev2, NULL, 0, 0, NULL},
203   {
204     -1,	0,
205     0, 0, 0, 0,
206     0, 0, 0,
207     NULL, NULL, 0, 0, NULL}};
208 #undef IMASK
209 
210 #define NAMEMENU_IMAGE	0
211 #define NAMEMENU_COLOR	1
212 
213 char *namemenu_str();
214 
215 static MENU namemenu[] = {
216   {
217     NAMEMENU_IMAGE,	MenuModeMaskBorder,
218     IMGNMX, IMGNMY, IMGNMW, IMGNMH,
219     0, ExposureMask, 0,
220     NULL, namemenu_str, 0, 0, NULL},
221   {
222     NAMEMENU_COLOR,	MenuModeMaskBorder,
223     COLNMX, COLNMY, COLNMW, COLNMH,
224     0, ExposureMask, 0,
225     NULL, namemenu_str, 0, 0, NULL},
226   {
227     -1,	0,
228     0, 0, 0, 0,
229     0, 0, 0,
230     NULL, NULL, 0, 0, NULL}};
231 
namemenu_str(p)232 char *namemenu_str(p)
233      MENU *p;
234 {
235   switch(p->n) {
236   case NAMEMENU_IMAGE:
237     return filename(imgfilename);
238   case NAMEMENU_COLOR:
239     return filename(colfilename);
240   }
241   /* NOT REACHED */
242   return NULL;
243 }
244 
sliderev(p,ev)245 int sliderev(p, ev)
246      MENU *p;
247      XEvent *ev;
248 {
249   int i, rx, ry, cx, cy;
250   unsigned int key;
251   Window rw, cw;
252   static int dy, sy;
253 
254   switch(ev->type) {
255   case ButtonPress:
256     dy = p->y + ev->xbutton.y;
257     dy = ev->xbutton.y_root;
258     sy = scroll_pos;
259     return 1;
260     break;
261   case ButtonRelease:
262     return 1;
263     break;
264   case MotionNotify:
265     XQueryPointer(dsp, ev->xmotion.window, &rw, &cw, &rx, &ry, &cx, &cy, &key);
266     i = ((ry - dy)*scroll_range)/(SLIDERH-p->h) + sy;
267     if (i > scroll_pos)
268       scroll_up(i - scroll_pos);
269     else if (i < scroll_pos)
270       scroll_down(scroll_pos - i);
271     break;
272   }
273   return 0;
274 }
275 
276 #define IMASK	(ExposureMask|ButtonPressMask|ButtonReleaseMask|\
277 		 PointerMotionHintMask|ButtonMotionMask)
278 
279 static MENU slidermenu[] = {
280   {
281     0,	MenuModeMaskBorder,
282     0, 0, SLIDERW-BDW*2, 1,
283     0, IMASK, 0,
284     sliderev, NULL, 0, 0, NULL},
285   {
286     -1,	0,
287     0, 0, 0, 0,
288     0, 0, 0,
289     NULL, NULL, 0, 0, NULL}};
290 #undef IMASK
291 
resize_slider()292 void resize_slider()
293 {
294   int movearea, fcnt;
295   MENU *p;
296 
297   fcnt = files_count < DIRSLOTMAX ? DIRSLOTMAX : files_count;
298   p = slidermenu+0;
299   p->h = ((SLIDERH-BDW*2)*DIRSLOTMAX)/fcnt;
300   if (p->h < p->w)
301     p->h = p->w;
302   movearea = (SLIDERH-BDW*2) - p->h;
303   p->y = 0;
304   fcnt -= DIRSLOTMAX;
305   if (fcnt > 0)
306     p->y = (movearea*scroll_pos)/fcnt/DIRSLOTH;
307   XMoveResizeWindow(dsp, p->win, p->x, p->y, p->w, p->h);
308 }
309 
get_filetype_max(void)310 int get_filetype_max(
311 #if NeedFunctionPrototypes
312 		     void
313 #endif
314 		     )
315 {
316   int i;
317 
318   for (i = 0; i < FTYPEMAX; i++) {
319     if (file_type_tbl[i].suffix[0] == '\0')
320       break;
321   }
322   return i;
323 }
324 
is_supported_suffix(char * name)325 int is_supported_suffix(
326 #if NeedFunctionPrototypes
327 			char *name)
328 #else
329      name)
330      char *name;
331 #endif
332 {
333   int i;
334   int len, suflen;
335 
336   len = strlen(name);
337   i = get_filetype_max();
338   while (--i >= 0) {
339     suflen = strlen(file_type_tbl[i].suffix);
340     if ((len - suflen >= 0) &&
341 	(strncmp(name+len-suflen, file_type_tbl[i].suffix, suflen) == 0))
342       return 1;
343   }
344   return 0;
345 }
346 
select_suffix(char * buf,int len,int n)347 int select_suffix(
348 #if NeedFunctionPrototypes
349 		  char *buf, int len, int n)
350 #else
351      buf, len, n)
352      char *buf;
353      int len;
354      int n;
355 #endif
356 {
357   int i, j, r;
358   char *p, *p2;
359 
360   p = buf;
361   r = 0;
362   for (i = 0; i < n && *p; i++) {
363     j = strlen(p);
364     if ((j && *(p+j-1) == '/')||
365 	is_supported_suffix(p))
366       r++;
367     else
368       *p = '\0';
369     p += len;
370   }
371   p = p2 = buf;
372   for (i = 0; i < n; i++) {
373     if (*p) {
374       if (p != p2)
375 	memcpy(p2, p, len);
376       p2 += len;
377     }
378     p += len;
379   }
380   while (p2 != p) {
381     *p2 = '\0';
382     p2 += len;
383   }
384   return r;
385 }
386 
387 /*
388  * return number of file (0 is error!)
389  */
get_filenames()390 int get_filenames()
391 {
392   int i, n;
393 
394   n = get_dir(current_path, filenamebuf, MAXFILENAME, MAXFILE);
395   for (i = n; i < MAXFILE; i++)
396     *(filenamebuf+i*MAXFILENAME) = '\0';
397   if (filemenu[FILE_MASK].mode & MenuModeMaskOn)
398     n = select_suffix(filenamebuf, MAXFILENAME, n);
399   redraw_window(filemenu[FILE_PATH].win);
400   files_count = n;
401   scroll_range = (n-DIRSLOTMAX)*DIRSLOTH;
402   if (scroll_range < 0)
403     scroll_range = 0;
404   return n;
405 }
406 
slotwin_strfunc(p)407 char *slotwin_strfunc(p)
408      MENU *p;
409 {
410   return filenamebuf+slotindex[p->n]*MAXFILENAME;
411 }
412 
redraw_fileslot()413 void redraw_fileslot()
414 {
415   int i;
416   MENU *p;
417 
418   p = fileslot;
419   for (i = 0; i < FILESLOTMAX; i++) {
420     XMoveWindow(dsp, p->win, p->x, p->y);
421     redraw_window(p->win);
422     p++;
423   }
424 }
425 
set_slotmode(n)426 void set_slotmode(n)
427      int n;
428 {
429   if (slotindex[n] == select_slot)
430     (fileslot+n)->mode |= MenuModeMaskOn;
431   else
432     (fileslot+n)->mode &= ~MenuModeMaskOn;
433 }
434 
init_fileslot_pos()435 void init_fileslot_pos()
436 {
437   int i, y;
438   int startindex;
439   MENU *p;
440 
441   p = fileslot;
442   startindex = scroll_pos / DIRSLOTH;
443   y = - (scroll_pos % DIRSLOTH);
444   for (i = 0; i < FILESLOTMAX; i++) {
445     slotindex[i] = startindex+i;
446     p->x = 0;
447     p->y = y;
448     y += DIRSLOTH;
449     set_slotmode(i);
450     p++;
451   }
452 }
453 
454 
create_file_window()455 int create_file_window()
456 {
457   int i;
458   MENU *p;
459   XSetWindowAttributes attr;
460 
461   filenamebuf = malloc(MAXFILE*MAXFILENAME);
462   create_toplevel_window(&filewin, "file", str_file_geom,
463 			 FILEWINWIDTH, FILEWINHEIGHT);
464   menuwin_create(filemenu, filewin, 0, 0);
465   file2win = XCreateSimpleWindow(dsp, filewin, DIRSLOTX, DIRSLOTY,
466 				 DIRSLOTW, DIRSLOTH*DIRSLOTMAX,
467 				 BDW, border_color, bg);
468   XMapRaised(dsp, file2win);
469   fileslot = (MENU *)malloc(sizeof(MENU)*(FILESLOTMAX+1));
470   p = fileslot;
471   for (i = 0; i < FILESLOTMAX; i++) {
472     bzero(p, sizeof(*p));
473     p->n = i;
474     p->w = DIRSLOTW;
475     p->h = DIRSLOTH;
476     p->mode = MenuModeMaskLeft;
477     p->im = ExposureMask|EnterWindowMask|LeaveWindowMask|ButtonPressMask;
478     p->event = slotev;
479     p->strfunc = slotwin_strfunc;
480     p++;
481   }
482   p->n = -1;
483   select_slot = 0;
484   scroll_pos = 0;
485   init_fileslot_pos();
486   menuwin_create(fileslot, file2win, 0, 0);
487   menuwin_create(slotwin, filewin, BDW, 0);
488   attr.background_pixmap = hatch_pixmap;
489   XChangeWindowAttributes(dsp, filemenu[FILE_SLIDER].win, CWBackPixmap, &attr);
490   menuwin_create(slidermenu, filemenu[FILE_SLIDER].win, 0, 0);
491 
492   change_directory("");		/* get current */
493   return 0;
494 }
495 
map_file_window()496 void map_file_window()
497 {
498   XMapRaised(dsp, filewin);
499 }
500 
unmap_file_window()501 void unmap_file_window()
502 {
503   XUnmapWindow(dsp, filewin);
504 }
505 
close_file_window()506 void close_file_window()
507 {
508   XDestroyWindow(dsp, filewin);
509   free(filenamebuf);
510 }
511 
get_parent_pathname(path)512 char *get_parent_pathname(path)
513      char *path;
514 {
515   char *p;
516 
517   p = strrchr(path, '/');
518   if (p != NULL) {
519     if (p == path)
520       p++;
521     *p = '\0';
522   }
523   return path;
524 }
525 
set_current_name(name)526 void set_current_name(name)
527      char *name;
528 {
529   strcpy(current_name, name);
530   strcpy(filemenu[FILE_NAME].str, name);
531   filemenu[FILE_NAME].cursor = strlen(current_name);
532   redraw_window(filemenu[FILE_NAME].win);
533 }
534 
set_select_slot_name(void)535 void set_select_slot_name(
536 #if NeedFunctionPrototypes
537 			  void
538 #endif
539 			  )
540 {
541   set_current_name(filenamebuf+(select_slot)*MAXFILENAME);
542 }
543 
rescan_disp_fileslot(void)544 void rescan_disp_fileslot(
545 #if NeedFunctionPrototypes
546 			  void
547 #endif
548 			  )
549 {
550   int i;
551 
552   cursor_busy();
553   i = get_filenames();
554   if (select_slot >= i)
555     select_slot = i-1;
556   scroll_pos = select_slot*DIRSLOTH - (DIRSLOTMAX*DIRSLOTH)/2;
557   if (scroll_pos < 0)
558     scroll_pos = 0;
559   else if (scroll_pos >= scroll_range)
560     scroll_pos = scroll_range;
561   init_fileslot_pos();
562   resize_slider();
563   redraw_fileslot();
564 }
565 
change_directory(dir)566 int change_directory(dir)
567      char *dir;
568 {
569   int i;
570   char buf[MAXPATH];
571   char buf2[MAXPATH];
572 
573   switch(*dir) {
574   case '\0':
575     /* current working directory pathname */
576     get_current_dir(buf);
577     break;
578   case '/':
579     /* absolute pathname */
580     strcpy(buf, dir);
581     break;
582   default:
583     /* relative pathname */
584     strcpy(buf, current_path);
585     strcpy(buf2, dir);
586     i = strlen(buf2);
587     if (i && buf2[i-1] == '/')
588       buf2[i-1] = '\0';
589     if (strcmp(buf2, "..") == 0) {
590       get_parent_pathname(buf);
591     } else if (strcmp(buf2, ".") != 0) {
592       i = strlen(buf);
593       if (i && buf[i-1] != '/')
594 	strcat(buf, "/");
595       strcat(buf, buf2);
596     }
597   }
598   if (get_dir(buf, buf2, sizeof(buf2), 1)) {
599     strcpy(current_path, buf);
600     strcpy(filemenu[FILE_PATH].str, buf);
601     filemenu[FILE_PATH].cursor = strlen(filemenu[FILE_PATH].str);
602     redraw_window(filemenu[FILE_PATH].win);
603     select_slot = 0;
604     scroll_pos = 0;
605     rescan_disp_fileslot();
606     set_select_slot_name();
607     return 0;
608   }
609   return 1;
610 }
611 
set_imgfilename(name)612 void set_imgfilename(name)
613      char *name;
614 {
615   strcpy(imgfilename, name);
616   redraw_window(namemenu[NAMEMENU_IMAGE].win);
617   redraw_window(infomenu[INFOMENU_IMGFILE].win);
618 }
619 
set_colfilename(name)620 void set_colfilename(name)
621      char *name;
622 {
623   strcpy(colfilename, name);
624   redraw_window(namemenu[NAMEMENU_COLOR].win);
625   redraw_window(infomenu[INFOMENU_COLFILE].win);
626   redraw_window(infomenu[INFOMENU_COLCOUNT].win);
627 }
628 
create_filename_window(win,x,y)629 void create_filename_window(win, x, y)
630      Window win;
631      int x;
632      int y;
633 {
634   topmenuwin_create(namemenu, x, y);
635 }
636 
skip_space(p)637 char *skip_space(p)
638      char *p;
639 {
640   while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
641     p++;
642   return p;
643 }
644 
645 /* Search matching string in structures
646  * structure first member must be (char *).
647  * if not found matching string, return NULL
648  */
match_struct(tbl,len,p)649 char *match_struct(tbl, len, p)
650      char *tbl;			/* structure list pointer */
651      int len;			/* size of a structure */
652      char *p;			/* string */
653 {
654   char *s;
655 
656   while ((s = *((char **)tbl)) != NULL) {
657     if (strncmp(p, s, strlen(s)) == 0)
658       return tbl;
659     tbl += len;			/* get next structure address */
660   }
661   return NULL;			/* not found */
662 }
663 
664 /* if not found matching string, return -1 */
match_string(tbl,p)665 int match_string(tbl, p)
666      char *tbl[];
667      char *p;
668 {
669   int i;
670 
671   for (i = 0; tbl[i] != NULL; i++) {
672     if (strncmp(p, tbl[i], strlen(tbl[i])) == 0)
673       return i;
674   }
675   return -1;			/* not found */
676 }
677 
get_string(char str[],char * p,int n)678 char *get_string(
679 #if NeedFunctionProtorypes
680 		 char str[], char *p, int n)
681 #else
682      str, p, n)
683      char str[];
684      char *p;
685      int n;
686 #endif
687 {
688   int i;
689   int quote;
690 
691   p = skip_space(p);
692   quote = i = 0;
693   if (*p == '"' || *p == '\'')
694     quote = *p++;
695   while (i < n-1 && *p) {
696     if (*p == quote) {
697       p++;
698       break;
699     }
700     if (!quote && (*p == ' ' || *p == '\t'))
701       break;
702     str[i++] = *p++;
703   }
704   str[i] = '\0';
705   return p;
706 }
707 
708 /* Parse string in structure
709  * structure first member must be (char *).
710  * if not found matching string, return NULL
711  */
712 #if NeedFunctionPrototypes
parse_str2(void * tbl,int len,char ** p)713 void *parse_str2(void *tbl, int len, char **p)
714 #else
715      char *parse_str2(
716 		      tbl, len, p)
717      char *tbl;			/* structure list pointer */
718      int len;			/* size of one structure */
719      char **p;			/* string */
720 #endif
721 {
722   char *r;
723   char buf[256];
724 
725   *p = get_string(buf, *p, sizeof(buf));
726   if (strcmp(buf, "None") == 0 || strcmp(buf, "-") == 0)
727     return NULL;
728   r = match_struct(tbl, len, buf);
729   if (r == NULL) {
730     error("parse ``%s'' unknown!", buf);
731     *p += strlen(*p);
732   }
733   return r;
734 }
735 
736 /* type */
737 typedef struct _MODETBL {
738   char *symbol;
739   int mode;
740 } MODETBL;
741 
742 static MODETBL modetbll[] = {
743   {"color", F_COL},
744   {"image", F_IMG},
745   {"all", F_ALL},
746   {NULL, 0}
747 };
748 
749 typedef struct _FUNCTBL {
750   char *symbol;
751   int (*func)();
752 } FUNCTBL;
753 
754 /* read routine */
755 static FUNCTBL rdfunc[] = {
756   {"ccb", rd_ccb},
757   {"cbb", rd_cbb},
758   {"csb", rd_csb},
759   {"cxb", rd_cxb},
760   {"kcf", rd_kcf},
761   {"cel", rd_cel},
762   {"pnm", rd_pnm},
763   {"ppm", rd_pnm},
764   {"xbm", rd_xbm},
765   {"mag", rd_mag},
766   {"tim", rd_tim},
767   {"nbn", rd_nbn},
768   {"cls", rd_cls},
769   {NULL, NULL}
770 };
771 
772 /* write routine */
773 static FUNCTBL wrfunc[] = {
774   {"ccb", wr_ccb},
775   {"cbb", wr_cbb},
776   {"cxb", wr_cxb},
777   {"kcf", wr_kcf},
778   {"cel", wr_cel},
779   {"ppm", wr_ppm},
780   {"xbm", wr_xbm},
781   {"mag", wr_mag},
782   {"tim", wr_tim},
783   {NULL, NULL}
784 };
785 
parse_ftype(char * p)786 int parse_ftype(
787 #if NeedFunctionPrototypes
788 		char *p)
789 #else
790      p)
791      char *p;
792 #endif
793 {
794   int i;
795   FTYPE *pp;
796   FUNCTBL *funcp;
797   MODETBL *modep;
798   char buf[256];
799 
800   i = get_filetype_max();
801   pp = file_type_tbl + i;
802   p = get_string(pp->suffix, p, sizeof(pp->suffix));
803   if (!*p)
804     return 1;
805   modep = parse_str2(modetbll, sizeof(*modetbll), &p);
806   pp->mode = (modep != NULL) ? modep->mode : 0;
807   funcp = parse_str2(rdfunc, sizeof(*rdfunc), &p);
808   pp->readroutine = (funcp != NULL) ? funcp->func : NULL;
809   funcp = parse_str2(wrfunc, sizeof(*wrfunc), &p);
810   pp->writeroutine = (funcp != NULL) ? funcp->func : NULL;
811   pp->decoder = NULL;
812   p = get_string(buf, p, sizeof(buf));
813   if (buf[0]) {
814     pp->decoder = (char *)malloc(strlen(buf)+1);
815     strcpy(pp->decoder, buf);
816   }
817   pp->encoder = NULL;
818   p = get_string(buf, p, sizeof(buf));
819   if (buf[0]) {
820     pp->encoder = (char *)malloc(strlen(buf)+1);
821     strcpy(pp->encoder, buf);
822   }
823   return 0;
824 }
825 
parse_option_configuration(char * p)826 int parse_option_configuration(
827 #if NeedFunctionProtorypes
828 			       char *p)
829 #else
830      p)
831      char *p;
832 #endif
833 {
834   int i;
835   char *bufp;
836   char **argv;
837   char buf[1024];
838   char *av[64];
839 
840   i = 0;
841   bufp = buf;
842   while (i < 64-1) {
843     p = get_string(bufp, p, sizeof(buf)-(bufp-buf));
844     if (!*bufp)
845       break;
846     av[i++] = bufp;
847     bufp += strlen(bufp) + 1;
848     if (bufp >= buf+sizeof(buf))
849       break;
850   }
851   av[i] = NULL;
852   argv = av;
853   return parse_option(&i, &argv);
854 }
855 
856 static char *section_name[] = {"*end", "*file", "*window", "*option", NULL};
857 
858 typedef struct _WINGEOMTBL {
859   char *symbol;
860   char *geom;
861   Window *win;
862 } WINGEOMTBL;
863 
864 static WINGEOMTBL wintbl[] = {
865   {"file", str_file_geom, &filewin},
866   {"info", str_info_geom, &infowin},
867   {"edit", str_edit_geom, &editwin},
868   {NULL, NULL, NULL}
869 };
870 
871 
parse_window_configuration(char * p)872 int parse_window_configuration(
873 #if NeedFunctionProtorypes
874 			       char *p)
875 #else
876      p)
877      char *p;
878 #endif
879 {
880   WINGEOMTBL *wp;
881   char buf[256];
882 
883   wp = parse_str2(wintbl, sizeof(*wintbl), &p);
884   if (wp == NULL)
885     return -1;
886   get_string(buf, p, sizeof(buf));
887   strncpy(wp->geom, buf, 32);
888   return 0;
889 }
890 
891 
read_config_file(char * name)892 int read_config_file(
893 #if NeedFunctionPrototypes
894 		     char *name)
895 #else
896      name)
897      char *name;
898 #endif
899 {
900   int i;
901   int section;			/* 0:None 1:file 2:window 3:option */
902   FILE *fp;
903   char buf[1024];
904 
905   fp = fopen(name, "r");
906   if (fp == NULL)
907     return 1;
908   section = 0;
909   while (fgets(buf, sizeof(buf), fp) != NULL) {
910     i = strlen(buf);
911     if (i && buf[i-1] == '\n')
912       buf[i-1] = '\0';
913     if (buf[0] == '#' || buf[0] == '\0')
914       continue;
915     if (buf[0] == '*') {
916       i = match_string(section_name, buf);
917       if (i < 0)
918 	i = 0;
919       section = i;
920       continue;
921     }
922     switch(section) {
923     case 1:
924       if (parse_ftype(buf))
925 	error("file type parse error ``%s''", buf);
926       break;
927     case 2:
928       parse_window_configuration(buf);
929       break;
930     case 3:
931       parse_option_configuration(buf);
932       break;
933     }
934   }
935   fclose(fp);
936   return 0;
937 }
938 
939 /*
940  * return 0: no error!
941  * Caution! This routine is called before XOpenDisplay.
942  */
read_config(void)943 int read_config(
944 #if NeedFunctionPrototypes
945 		void
946 #endif
947 		)
948 {
949   int i;
950   char *p;
951   char buf[MAXPATH];
952 
953   file_type_tbl = (FTYPE *)malloc(sizeof(FTYPE)*FTYPEMAX);
954   if (file_type_tbl == NULL) {
955     error("more core!");
956     return 1;
957   }
958   bzero(file_type_tbl, sizeof(FTYPE)*FTYPEMAX);
959   for (i = 0; default_file_type[i].suffix[0]; i++)
960     file_type_tbl[i] = default_file_type[i];
961   p = getenv("HOME");
962   if (p != NULL) {
963     sprintf(buf, "%s/%s", p, rcfile);
964     read_config_file(buf);
965   }
966   read_config_file(rcfile);
967   return 0;
968 }
969 
gen_geometry_string(char * buf,Window win)970 void gen_geometry_string(
971 #if NeedFunctionProtorypes
972 			 char *buf, Window win)
973 #else
974      buf, win)
975      char *buf;
976      Window win;
977 #endif
978 {
979   int x0, y0;
980   unsigned int width0, height0;
981   int x, y;
982   unsigned int width, height, border, depth;
983   Window root, parent;
984   Window *children;
985   unsigned int nchildren;
986 
987   width0 = height0 = x0 = y0 = 0;
988   while (XQueryTree(dsp, win, &root, &parent, &children, &nchildren)) {
989     XFree((char *)children);
990     XGetGeometry(dsp, win, &root, &x, &y, &width, &height, &border, &depth);
991     if (!width0) {
992       width0 = width;
993       height0 = height;
994     }
995     x0 = x;
996     y0 = y;
997     win = parent;
998     if (win == DefaultRootWindow(dsp))
999       break;
1000   }
1001   sprintf(buf, "%dx%d+%d+%d", width0, height0, x0, y0);
1002 }
1003 
1004 /* return 0: no error */
write_window_geometry(FILE * fp)1005 int write_window_geometry(
1006 #if NeedFunctionProtorypes
1007 			  FILE *fp)
1008 #else
1009      fp)
1010      FILE *fp;
1011 #endif
1012 {
1013   WINGEOMTBL *wp;
1014   char buf[1024];
1015 
1016   fprintf(fp, "%s\n", section_name[2]);
1017   for (wp = wintbl; wp->symbol != NULL; wp++) {
1018     gen_geometry_string(buf, *(wp->win));
1019     fprintf(fp, "%s\t%s\n", wp->symbol, buf);
1020   }
1021   return ferror(fp);
1022 }
1023 
1024 /* update configuration file
1025  *
1026  * return
1027  *	0	no error
1028  *	other	error
1029  */
update_config_file(void)1030 int update_config_file(
1031 #if NeedFunctionProtorypes
1032 		       void
1033 #endif
1034 		       )
1035 {
1036   FILE *fp, *ofp;
1037   char *p;
1038   Bool f;
1039   int r, i, section;
1040   char orgfile[MAXPATH];
1041   char buf[MAXPATH];
1042 
1043   strcpy(orgfile, rcfile);
1044   fp = fopen(orgfile, "r+");	/* "r+" for writable check */
1045   if (fp == NULL) {
1046     p = (char *)getenv("HOME");
1047     if (p != NULL) {
1048       sprintf(orgfile, "%s/%s", p, rcfile);
1049       fp = fopen(orgfile, "r+");
1050     }
1051   }
1052   if (fp == NULL)
1053     return 1;
1054   strcpy(buf, orgfile);
1055   strcat(buf, ".new");
1056   ofp = fopen(buf, "w");
1057   if (ofp == NULL)
1058     return 1;
1059   r = section = 0;
1060   while (fgets(buf, sizeof(buf), fp) != NULL) {
1061     f = True;
1062     if (buf[0] == '*') {
1063       i = match_string(section_name, buf);
1064       if (i < 0)
1065 	i = 0;
1066       section = i;
1067     }
1068     if (section == 2)
1069       f = False;
1070     if (f && fputs(buf, ofp) == EOF)
1071       r = 1;
1072     if (r)
1073       break;
1074   }
1075   r |= write_window_geometry(ofp);
1076   fclose(ofp);
1077   fclose(fp);
1078   /* rename file, if no error */
1079   if (!r) {
1080     strcpy(buf, orgfile);
1081     strcat(buf, ".new");
1082     r = rename(buf, orgfile);
1083   }
1084   return r;
1085 }
1086 
split_command(str,filename)1087 char **split_command(str, filename)
1088      char *str;
1089      char *filename;
1090 {
1091   char *p;
1092   int i;
1093   char form[1024];
1094   static char *args[128];
1095   static char buf[1024];
1096 
1097   strcpy(form, str);
1098   strcat(form, " %s");		/* for decoder string without filename %s */
1099   sprintf(buf, form, filename, "");
1100   p = buf;
1101   for (i = 0; i < 128-1; i++) {
1102     p = skip_space(p);
1103     if (*p == '\0' || *p == '\n')
1104       break;
1105     args[i] = p;
1106     while (*p > ' ')
1107       p++;
1108     while (*p == ' '|| *p == '\t' || *p == '\n')
1109       *p++ = '\0';
1110   }
1111   args[i] = NULL;
1112   return args;
1113 }
1114 
autosavecol()1115 int autosavecol()
1116 {
1117   FILE *fp;
1118   char *p;
1119   char name[MAXPATH];
1120 
1121   reset_color_pushed(-1);
1122   p = (char *)getenv("HOME");
1123   if (p == NULL)
1124     p = ".";
1125   strcpy(name, p);
1126   strcat(name, "/#xpxsave.kcf");
1127   fp = fopen(name, "w");
1128   if (fp == NULL)
1129     return 1;
1130   wr_kcf(fp);
1131   return fclose(fp);
1132 }
1133 
autosaveimg()1134 int autosaveimg()
1135 {
1136   FILE *fp;
1137   char *p;
1138   char name[MAXPATH];
1139 
1140   p = (char *)getenv("HOME");
1141   if (p == NULL)
1142     p = ".";
1143   strcpy(name, p);
1144   strcat(name, "/#xpxsave.cel");
1145   fp = fopen(name, "w");
1146   if (fp == NULL)
1147     return 1;
1148   wr_cel(fp);
1149   return fclose(fp);
1150 }
1151 
autosave()1152 int autosave()
1153 {
1154   int r;
1155 
1156   r = 0;
1157   if (colchanged)
1158     r |= autosavecol();
1159   if (imgchanged)
1160     r |= autosaveimg();
1161   return r;
1162 }
1163 
read_any_file(p,name)1164 int read_any_file(p, name)
1165      FTYPE *p;
1166      char *name;
1167 {
1168   FILE *fp;
1169   int i, r, fd[2];
1170 
1171   cursor_busy();
1172   autosave();
1173   undo_clear();
1174   message("``%s'' reading...", name);
1175   if (p->decoder != NULL) {
1176     pipe(fd);
1177     if (vfork() == 0) {
1178       char **av;
1179       close(1);
1180       dup(fd[1]);
1181       close(fd[1]);
1182       close(fd[0]);
1183       av = split_command(p->decoder, name);
1184       execvp(*av, av);
1185       _exit(1);
1186     }
1187     fp = fdopen(fd[0], "r");
1188     close(fd[1]);
1189   } else {
1190     fp = fopen(name, "r");
1191     if (fp == NULL) {
1192       message("!open error!\n");
1193       return 1;
1194     }
1195   }
1196   if (p->mode & F_COL) {
1197     set_colfilename(name);
1198     colchanged = missed_color = 0;
1199     colposx = colposy = 0;
1200   }
1201   if (p->mode & F_IMG) {
1202     set_imgfilename(name);
1203     imgchanged = 0;
1204     hotspotx = hotspoty = -1;
1205     imgposx = imgposy = imgfiledepth = 0;
1206   }
1207   r = 1;
1208   if (p->readroutine != NULL)
1209     r = p->readroutine(fp);
1210   fclose(fp);
1211   if (p->decoder != NULL)
1212     wait(&i);
1213   if (r) {
1214     if (p->mode & F_COL)
1215       set_colfilename("");
1216     if (p->mode & F_IMG)
1217       set_imgfilename("");
1218     message("!read error!\n");
1219     return r;
1220   }
1221   img_scroll_posreset();
1222   message("done.\n");
1223   info_imgsize_set();		/* update info numbers */
1224   return 0;
1225 }
1226 
1227 
write_any_file(p,name)1228 int write_any_file(p, name)
1229      FTYPE *p;
1230      char *name;
1231 {
1232   FILE *fp;
1233   int r, i, fd[2];
1234 
1235   cursor_busy();
1236   autosave();
1237   undo_clear();
1238   message("``%s'' writing...", name);
1239   if (p->writeroutine == NULL) {
1240     message("!\nNot supported format!\nAbort.\n");
1241     return 1;
1242   }
1243   fp = fopen(name, "w");
1244   if (fp == NULL) {
1245     message("!open error!\n");
1246     return 1;
1247   }
1248   if (p->encoder != NULL) {
1249     char **av;
1250 
1251     pipe(fd);
1252     if (vfork() == 0) {
1253       close(0);
1254       dup(fd[0]);
1255       close(1);
1256       dup(fileno(fp));
1257       close(fd[1]);
1258       close(fd[0]);
1259       av = split_command(p->encoder, "");
1260       execvp(*av, av);
1261       _exit(1);
1262     }
1263     fp = fdopen(fd[1], "w");
1264     close(fd[0]);
1265   }
1266   r = p->writeroutine(fp, name);
1267   fclose(fp);
1268   if (p->encoder != NULL)
1269     wait(&i);
1270   if (r) {
1271     message("!write error!\n");
1272     return r;
1273   }
1274   if (p->mode & F_COL) {
1275     colchanged = 0;
1276     set_colfilename(name);
1277   }
1278   if (p->mode & F_IMG) {
1279     imgchanged = 0;
1280     set_imgfilename(name);
1281   }
1282   message("done.\n");
1283   return 0;
1284 }
1285 
get_filetype(name)1286 int get_filetype(name)
1287      char *name;
1288 {
1289   int i, n;
1290 
1291   n = get_filetype_max();
1292   while (--n >= 0) {
1293     i = strlen(name) - strlen(file_type_tbl[n].suffix);
1294     if (i >= 0 && strcmp(name+i, file_type_tbl[n].suffix) == 0)
1295       break;
1296   }
1297   return n;
1298 }
1299 
read_data_file(name)1300 int read_data_file(name)
1301      char *name;
1302 {
1303   int i;
1304 
1305   i = get_filetype(name);
1306   if (i < 0)
1307     return 1;
1308   return read_any_file(file_type_tbl+i, name);
1309 }
1310 
file_open()1311 int file_open()
1312 {
1313   int i;
1314   char buf[MAXPATH];
1315 
1316   i = strlen(current_name);
1317   if (i && current_name[i-1] == '/') {
1318     strcpy(buf, current_name);
1319     buf[i-1] = '\0';
1320     change_directory(buf);
1321     set_current_name("");
1322   }
1323   if (current_name[0] == '\0')
1324     return 1;
1325   sprintf(buf, "%s/%s", current_path, current_name);
1326   return read_data_file(buf);
1327 }
1328 
change_select_slot(char * name)1329 int change_select_slot(
1330 #if NeedFunctionProtorypes
1331 		       char *name)
1332 #else
1333      name)
1334      char *name;
1335 #endif
1336 {
1337   int i;
1338 
1339   for (i = 0; i < files_count; i++) {
1340     if (strcmp(filenamebuf+i*MAXFILENAME, name) == 0)
1341       return select_slot = i;
1342   }
1343   return -1;
1344 }
1345 
file_save()1346 int file_save()
1347 {
1348   int i, r;
1349   char buf[MAXPATH];
1350 
1351   i = strlen(current_name);
1352   if (!i || current_name[i-1] == '/')
1353     return 1;
1354   sprintf(buf, "%s/%s", current_path, current_name);
1355   i = get_filetype(buf);
1356   if (i < 0)
1357     return 1;
1358   r = write_any_file(file_type_tbl+i, buf);
1359   if (r == 0) {
1360     rescan_disp_fileslot();
1361     change_select_slot(current_name);
1362     rescan_disp_fileslot();
1363   }
1364   return r;
1365 }
1366 
file_remove()1367 int file_remove()
1368 {
1369   int i;
1370   char buf[MAXPATH];
1371 
1372   i = strlen(current_name);
1373   if (!i || current_name[i-1] == '/')
1374     return 1;
1375   sprintf(buf, "%s/%s", current_path, current_name);
1376   if (unlink(buf) == 0) {
1377     rescan_disp_fileslot();
1378     set_select_slot_name();
1379   }
1380   return 0;
1381 }
1382 
max_sloty()1383 MENU *max_sloty()
1384 {
1385   int i;
1386   MENU *p, *rp;
1387 
1388   rp = p = fileslot;
1389   for (i = 0; i < FILESLOTMAX; i++) {
1390     if (rp->y < p->y)
1391       rp = p;
1392     p++;
1393   }
1394   return rp;
1395 }
1396 
min_sloty()1397 MENU *min_sloty()
1398 {
1399   int i;
1400   MENU *p, *rp;
1401 
1402   rp = p = fileslot;
1403   for (i = 0; i < FILESLOTMAX; i++) {
1404     if (rp->y > p->y)
1405       rp = p;
1406     p++;
1407   }
1408   return rp;
1409 }
1410 
1411 typedef struct {
1412   int n;
1413   MENU m;
1414 } SMENU;
1415 
cmp_slot(p1,p2)1416 int cmp_slot(p1, p2)
1417      SMENU *p1;
1418      SMENU *p2;
1419 {
1420   return p1->m.y - p2->m.y;
1421 }
1422 
sort_slot()1423 void sort_slot()
1424 {
1425   int i;
1426   SMENU buf[FILESLOTMAX];
1427 
1428   for (i = 0; i < FILESLOTMAX; i++) {
1429     buf[i].n = slotindex[i];
1430     buf[i].m = *(fileslot+i);
1431   }
1432   qsort(buf, FILESLOTMAX, sizeof(*buf), cmp_slot);
1433   for (i = 0; i < FILESLOTMAX; i++) {
1434     slotindex[i] = buf[i].n;
1435     *(fileslot+i) = buf[i].m;
1436     (fileslot+i)->n = i;
1437   }
1438 }
1439 
scroll_up(n)1440 void scroll_up(n)
1441      int n;
1442 {
1443   int i;
1444   MENU *p, *mx;
1445 
1446   if (scroll_pos + n > scroll_range)
1447     n = scroll_range - scroll_pos;
1448   scroll_pos += n;
1449   for (i = 0; i < FILESLOTMAX; i++)
1450     (fileslot+i)->y -= n;
1451   while (p = min_sloty(), p->y + p->h <= 0) {
1452     mx = max_sloty();
1453     p->y = mx->y + mx->h;
1454     slotindex[p-fileslot] += FILESLOTMAX;
1455     set_slotmode(p-fileslot);
1456     redraw_window(p->win);
1457   }
1458   sort_slot();
1459   p = fileslot;
1460   for (i = 0; i < FILESLOTMAX; i++) {
1461     XMoveWindow(dsp, p->win, p->x, p->y);
1462     p++;
1463   }
1464   resize_slider();
1465 }
1466 
scroll_down(n)1467 void scroll_down(n)
1468      int n;
1469 {
1470   int i;
1471   MENU *p, *mn;
1472 
1473   if (scroll_pos - n < 0)
1474     n = scroll_pos;
1475   scroll_pos -= n;
1476   for (i = 0; i < FILESLOTMAX; i++)
1477     (fileslot+i)->y += n;
1478   while (p = max_sloty(), p->y >= DIRSLOTH*DIRSLOTMAX) {
1479     mn = min_sloty();
1480     p->y = mn->y - p->h;
1481     slotindex[p-fileslot] -= FILESLOTMAX;
1482     set_slotmode(p-fileslot);
1483     redraw_window(p->win);
1484   }
1485   sort_slot();
1486   for (i = FILESLOTMAX-1; i >= 0; --i) {
1487     p = fileslot+i;
1488     XMoveWindow(dsp, p->win, p->x, p->y);
1489   }
1490   resize_slider();
1491 }
1492 
slotev(p,ev)1493 int slotev(p, ev)
1494      MENU *p;
1495      XEvent *ev;
1496 {
1497   int i, oldsel;
1498 
1499   switch(ev->type) {
1500   case ButtonPress:
1501     oldsel = select_slot;
1502     select_slot = slotindex[p->n];
1503     set_current_name(filenamebuf+select_slot*MAXFILENAME);
1504     for (i = 0; i < FILESLOTMAX; i++) {
1505       if (slotindex[i] == oldsel) {
1506 	(fileslot+i)->mode &= ~MenuModeMaskOn;
1507 	redraw_window((fileslot+i)->win);
1508       }
1509     }
1510     for (i = 0; i < FILESLOTMAX; i++) {
1511       if (slotindex[i] == select_slot) {
1512 	(fileslot+i)->mode |= MenuModeMaskOn;
1513 	redraw_window((fileslot+i)->win);
1514       }
1515     }
1516     if (double_clicked)
1517       file_open();
1518     return 1;
1519   }
1520   return 0;
1521 }
1522 
slotev2(p,ev)1523 int slotev2(p, ev)
1524      MENU *p;
1525      XEvent *ev;
1526 {
1527   switch(ev->type) {
1528   case Expose:
1529     switch(p->n) {
1530     case DIRSLOT_UP:
1531       menu_icon_center(p, ICON_up);
1532       break;
1533     case DIRSLOT_DOWN:
1534       menu_icon_center(p, ICON_down);
1535       break;
1536     }
1537     return 1;
1538   case ButtonPress:
1539     if (ev->xbutton.button == Button1)
1540       file_scroll_speed = menu_speed;
1541     else
1542       file_scroll_speed = DIRSLOTH*DIRSLOTMAX/2;
1543   }
1544   return 0;
1545 }
1546 
fileev(p,ev)1547 int fileev(p, ev)
1548      MENU *p;
1549      XEvent *ev;
1550 {
1551   switch(ev->type) {
1552   case ButtonPress:
1553     switch(p->n) {
1554     case FILE_MASK:
1555       p->mode ^= MenuModeMaskOn;
1556       rescan_disp_fileslot();
1557       p->mode ^= MenuModeMaskOn;
1558       break;
1559     }
1560     break;
1561   case ButtonRelease:
1562     if (p->mode & MenuModeMaskEnter && p->mode & MenuModeMaskOn) {
1563       switch(p->n) {
1564       case FILE_OPEN:
1565 	file_open();
1566 	break;
1567       case FILE_SAVE:
1568 	file_save();
1569 	break;
1570       case FILE_REMOVE:
1571 	file_remove();
1572 	break;
1573       case FILE_DUMMY2:
1574 	break;
1575       case FILE_OK:
1576 	menu_stat_change(1, 0);
1577 	break;
1578       }
1579     }
1580     break;
1581   case KeyPress:
1582     switch(p->n) {
1583     case FILE_PATH:
1584       {
1585 	int i;
1586 	KeySym key;
1587 	char buf[16];
1588 	i = XLookupString((XKeyEvent *)ev, buf, sizeof(buf)-1, &key, NULL);
1589 	buf[i] -= '\0';
1590 	switch(key) {
1591 	case XK_KP_Enter:
1592 	case XK_Return:
1593 	  change_directory(p->str);
1594 	  return 1;
1595 	}
1596       }
1597       break;
1598     }
1599     break;
1600   case EnterNotify:
1601     switch(p->n) {
1602     case FILE_PATH:
1603       break;
1604     case FILE_NAME:
1605       strcpy(p->str, current_name);
1606       break;
1607     }
1608     break;
1609   case LeaveNotify:
1610     switch(p->n) {
1611     case FILE_PATH:
1612       break;
1613     case FILE_NAME:
1614       strcpy(current_name, p->str);
1615       break;
1616     }
1617     break;
1618   }
1619   return 0;
1620 }
1621 
file_background()1622 void file_background()
1623 {
1624   if (slotwin[DIRSLOT_UP].mode & MenuModeMaskOn)
1625     scroll_down(file_scroll_speed);
1626   if (slotwin[DIRSLOT_DOWN].mode & MenuModeMaskOn)
1627     scroll_up(file_scroll_speed);
1628 }
1629 
1630 /* End of file */
1631