1 /* $Header: /home/yav/catty/fkiss/RCS/selcnf.c,v 1.26 2000/09/28 07:53:44 yav Exp $
2 * fkiss config selecter
3 * written by yav <yav@bigfoot.com>
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
20 #include <X11/Xos.h>
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23 #include <stdio.h>
24 #include "config.h"
25 #include "headers.h"
26 #include "fkiss.h"
27 #include "work.h"
28 #define PUBLIC_SELCNF_C
29 #include "extern.h"
30
31 #if HAVE_SYS_STAT_H
32 # include <sys/stat.h>
33 #else
34 # if HAVE_STAT_H
35 # include <stat.h>
36 # endif
37 #endif
38
39 #define BASE_MARGIN 2
40 #define BASE_TOP_MARGIN BASE_MARGIN
41 #define BASE_BOTTOM_MARGIN BASE_MARGIN
42 #define BASE_LEFT_MARGIN BASE_MARGIN
43 #define BASE_RIGHT_MARGIN BASE_MARGIN
44
45 #define MENU_TOP_MARGIN 2
46 #define MENU_BOTTOM_MARGIN 3
47 #define MENU_LEFT_MARGIN 4
48 #define MENU_RIGHT_MARGIN 4
49
50 char id_selcnf[] = "$Id: selcnf.c,v 1.26 2000/09/28 07:53:44 yav Exp $";
51 static Window selwin;
52 static int menuw = 128;
53 static int menuh = MENU_TOP_MARGIN+11+2+MENU_BOTTOM_MARGIN;
54 static char **conflist = NULL;
55 static char *str_cancel = "(Cancel)";
56 static MW *mwsel;
57 static char default_cnf_suffix[] = ".cnf";
58 static char current_dir[] = ".";
59
is_regular_file(str)60 int is_regular_file(str)
61 char *str;
62 {
63 struct stat st;
64
65 return stat(str, &st) == 0 && (st.st_mode & S_IFMT) == S_IFREG;
66 }
67
match_cnf(char * p)68 int match_cnf(char *p)
69 {
70 return is_suffix(p, default_cnf_suffix);
71 }
72
find_cnf_file(path)73 char **find_cnf_file(path)
74 char *path;
75 {
76 debug_printf("find_cnf_file ``%s''\n", path);
77 return dir_ls(path, match_cnf);
78 }
79
set_menu_font(list)80 void set_menu_font(list)
81 char **list; /* menu string list */
82 {
83 int i, maxwidth;
84
85 if (fsp == NULL)
86 return;
87 maxwidth = calc_text_size(str_cancel);
88 for (; *list != NULL; list++) {
89 i = calc_text_size(*list);
90 if (i > maxwidth)
91 maxwidth = i;
92 }
93 menuh = MENU_TOP_MARGIN + font_ascent + font_descent + MENU_BOTTOM_MARGIN;
94 menuw = MENU_LEFT_MARGIN + maxwidth + MENU_RIGHT_MARGIN;
95 debug_printf("font: %s\nfont ascent %d, descent %d\n",
96 str_font, font_ascent, font_descent);
97 }
98
which_menuwin(win)99 int which_menuwin(win)
100 Window win;
101 {
102 return which_winlist(win, mwsel);
103 }
104
set_menu_status(n,mode)105 void set_menu_status(n, mode)
106 int n;
107 int mode;
108 {
109 change_menu_status((mwsel+n)->win, (mwsel+n)->st = mode);
110 }
111
select_menu(title,geomstr,mlist)112 int select_menu(title, geomstr, mlist)
113 char *title; /* window title */
114 char *geomstr; /* window geometry string */
115 char **mlist; /* menu string list */
116 {
117 int i, r;
118 int menucnt;
119 int x, y, w, h, f;
120 XSizeHints hint;
121 XEvent ev;
122 Bool fin;
123 unsigned long atrmask;
124 XSetWindowAttributes atr;
125
126 set_menu_font(mlist);
127 for (menucnt = 0; *(mlist+menucnt) != NULL; menucnt++)
128 ;
129 menucnt++; /* append "Cancel" menu */
130 hint.flags = PSize;
131 x = y = 0;
132 atr.save_under = True;
133 atrmask = CWSaveUnder;
134 if (geomstr != NULL && geomstr[0]) {
135 /* window geometry is specified */
136 f = XGeometry(dsp, scr, geomstr, "", 1, 1, 1, 0, 0, &x, &y, &w, &h);
137 if (f & XValue)
138 hint.flags |= USPosition;
139 if (f & YValue)
140 hint.flags |= USPosition;
141 atr.override_redirect = True;
142 atrmask |= CWOverrideRedirect;
143 }
144
145 w = menuw+BASE_LEFT_MARGIN+BASE_RIGHT_MARGIN;
146 h = menuh*menucnt+BASE_TOP_MARGIN+BASE_BOTTOM_MARGIN;
147 hint.x = x;
148 hint.y = y;
149 hint.width = w;
150 hint.height = h;
151 selwin = XCreateSimpleWindow(dsp, rootwin, x, y, w, h,
152 1, spx[SPX_FG], spx[SPX_BG]);
153 XSetStandardProperties(dsp, selwin, title, title, 0,
154 oargv, oargc, &hint);
155 XSelectInput(dsp, selwin, ExposureMask);
156 XChangeWindowAttributes(dsp, selwin, atrmask, &atr);
157
158 mwsel = alloc_mw(menucnt);
159 for (i = 0; i < menucnt; i++) {
160 (mwsel+i)->win =
161 XCreateSimpleWindow(dsp, selwin,
162 BASE_LEFT_MARGIN, BASE_TOP_MARGIN+i*menuh,
163 menuw, menuh,
164 0, spx[SPX_FG], spx[SPX_BT]);
165 XSelectInput(dsp, (mwsel+i)->win, ExposureMask|
166 ButtonPressMask|ButtonReleaseMask|OwnerGrabButtonMask|
167 EnterWindowMask|LeaveWindowMask);
168 }
169 cursor_set(selwin, 3); /* 3: CUR_ARROW */
170 XMapRaised(dsp, selwin);
171 XMapSubwindows(dsp, selwin);
172 r = -1;
173 fin = False;
174 while (!fin) {
175 XNextEvent(dsp, &ev);
176 switch(ev.type) {
177 case Expose:
178 if (!ev.xexpose.count) {
179 i = which_menuwin(ev.xexpose.window);
180 if (i >= 0) {
181 draw_menu_string((mwsel+i)->win, (mwsel+i)->st, menuw, menuh,
182 MENU_LEFT_MARGIN, MENU_TOP_MARGIN,
183 (i == menucnt-1)?str_cancel:*(mlist+i));
184 #if 0
185 if ((mwsel+i)->st & 2)
186 fin = True;
187 #endif
188 }
189 }
190 break;
191 case EnterNotify:
192 case LeaveNotify:
193 i = which_menuwin(ev.xcrossing.window);
194 if (i >= 0)
195 set_menu_status(i, (ev.type == EnterNotify));
196 break;
197 /* case ButtonPress: */
198 case ButtonRelease:
199 i = (ev.xbutton.button == Button1) ?
200 which_menuwin(ev.xbutton.window) : menucnt-1;
201 if (i >= 0) {
202 r = (i == menucnt-1) ? -1 : i; /* -1 for Cancel */
203 set_menu_status(i, 2);
204 fin = True;
205 }
206 break;
207 }
208 }
209 XDestroyWindow(dsp, selwin);
210 XFlush(dsp);
211 free(mwsel);
212 return r;
213 }
214
cnf_exist_check(name)215 int cnf_exist_check(name)
216 char *name;
217 {
218 int i;
219
220 conf_file = ks_strdup(name);
221 i = is_regular_file(conf_file);
222 if (!i && extract_dir != NULL) {
223 conf_file = ks_realloc(strlen(extract_dir) + 1 + strlen(name) + 1);
224 sprintf(conf_file, "%s/%s", extract_dir, name);
225 i = is_regular_file(conf_file);
226 }
227 return i;
228 }
229
230 /*
231 * input:
232 * name config file
233 * extract_dir LHa extracted directory
234 * output:
235 * conf_dir[] cell and kcf file base directory
236 * conf_file[] configuration file
237 */
select_cnf(name)238 int select_cnf(name)
239 char *name;
240 {
241 int i, r;
242 char *p;
243 LSTR buf;
244
245 conf_dir = NULL;
246 conf_file = NULL;
247 lstr_init(&buf);
248 if (name != NULL) {
249 i = cnf_exist_check(name);
250 if (!i) {
251 lstr_cat(&buf, name);
252 lstr_cat(&buf, default_cnf_suffix);
253 i = cnf_exist_check(buf.buf);
254 }
255 if (i) {
256 conf_dir = get_directory(conf_file);
257 if (!*conf_dir) {
258 free(conf_dir);
259 conf_dir = ks_strdup(current_dir);
260 }
261 return 0;
262 }
263 /* name will be directory */
264 conf_dir = ks_strdup(name);
265 }
266 if (extract_dir != NULL) {
267 if (conf_dir != NULL)
268 free(conf_dir);
269 conf_dir = ks_strdup(extract_dir);
270 }
271 if (conf_dir == NULL || !conf_dir[0]) {
272 if (conf_dir != NULL)
273 free(conf_dir);
274 conf_dir = ks_strdup(current_dir);
275 }
276 conflist = find_cnf_file(conf_dir);
277 if (conflist == NULL) {
278 msg("W ``%s'' open error!\n", conf_dir);
279 r = -2;
280 } else if (*conflist == NULL) {
281 r = -2; /* No *.cnf */
282 } else if (*(conflist+1) == NULL) {
283 r = 0; /* One *.cnf */
284 } else {
285 r = select_menu("fkiss sel", str_geometry, conflist);
286 }
287 if (r >= 0) {
288 if (conf_file != NULL)
289 free(conf_file);
290 conf_file = ks_malloc(strlen(conf_dir) + 1 + strlen(*(conflist+r)) + 1);
291 sprintf(conf_file, "%s/%s", conf_dir, *(conflist+r));
292
293 free(conf_dir);
294 conf_dir = ks_strdup(conf_file);
295 p = rindex(conf_dir, '/');
296 if (p)
297 *p = '\0';
298
299 }
300 if (conflist != NULL)
301 dir_free(conflist);
302 debug_printf("selconf conf_dir [%s]\n", conf_dir);
303 return r;
304 }
305
306 /* End of file */
307