1 /* look-cool.c - look 'n feel type: COOL
2 Copyright (C) 1996-2017 Paul Sheer
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307, USA.
18 */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <my_string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25
26 #include <X11/Intrinsic.h>
27 #include "lkeysym.h"
28
29 #include "stringtools.h"
30 #include "app_glob.c"
31 #include "coolwidget.h"
32 #include "coollocal.h"
33
34 #include "mad.h"
35
36 extern struct look *look;
37
38 /* {{{ search replace dialog */
39
40 extern int replace_scanf;
41 extern int replace_regexp;
42 extern int replace_all;
43 extern int replace_prompt;
44 extern int replace_whole;
45 extern int replace_case;
46 extern int replace_backwards;
47 extern int search_create_bookmark;
48
49 struct look_cool_list {
50 struct file_entry *l;
51 int n;
52 };
53
look_cool_search_replace_dialog(Window parent,int x,int y,char ** search_text,char ** replace_text,char ** arg_order,const char * heading,int option)54 void look_cool_search_replace_dialog (Window parent, int x, int y, char **search_text, char **replace_text, char **arg_order, const char *heading, int option)
55 {
56 Window win;
57 XEvent xev;
58 CEvent cev;
59 CState s;
60 int xh, yh, h, xb, ys, yc, yb, yr;
61 CWidget *m;
62 int text_input_width ;
63
64 CBackupState (&s);
65 CDisable ("*");
66
67 win = CDrawHeadedDialog ("replace", parent, x, y, heading);
68 CGetHintPos (&xh, &h);
69
70 /* NLS hotkey ? */
71 CIdent ("replace")->position = WINDOW_ALWAYS_RAISED;
72 /* An input line comes after the ':' */
73 (CDrawText ("replace.t1", win, xh, h, _(" Enter search text : ")))->hotkey = 'E';
74
75 CGetHintPos (0, &yh);
76 (m = CDrawTextInput ("replace.sinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *search_text))->hotkey = 'E';
77
78 if (replace_text) {
79 CGetHintPos (0, &yh);
80 (CDrawText ("replace.t2", win, xh, yh, _(" Enter replace text : ")))->hotkey = 'n';
81 CGetHintPos (0, &yh);
82 (CDrawTextInput ("replace.rinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *replace_text))->hotkey = 'n';
83 CSetToolHint ("replace.t2", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
84 CSetToolHint ("replace.rinp", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
85 CGetHintPos (0, &yh);
86 (CDrawText ("replace.t3", win, xh, yh, _(" Enter argument (or substring) order : ")))->hotkey = 'o';
87 CGetHintPos (0, &yh);
88 (CDrawTextInput ("replace.ainp", win, xh, yh, 10, AUTO_HEIGHT, 256, *arg_order))->hotkey = 'o';
89 /* Tool hint */
90 CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
91 CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
92 }
93 CGetHintPos (0, &yh);
94 ys = yh;
95 /* The following are check boxes */
96 CDrawSwitch ("replace.ww", win, xh, yh, replace_whole, _(" Whole words only "), 0);
97 CGetHintPos (0, &yh);
98 CDrawSwitch ("replace.case", win, xh, yh, replace_case, _(" Case sensitive "), 0);
99 yc = yh;
100 CGetHintPos (0, &yh);
101 CDrawSwitch ("replace.reg", win, xh, yh, replace_regexp, _(" Regular expression "), 1);
102 CSetToolHint ("replace.reg", _("See the regex man page for how\nto compose a regular expression"));
103 CSetToolHint ("replace.reg.label", _("See the regex man page for how\nto compose a regular expression"));
104 yb = yh;
105 CGetHintPos (0, &yh);
106 CGetHintPos (&xb, 0);
107 if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
108 CDrawSwitch ("replace.bkwd", win, xh, yh, replace_backwards, _(" Backwards "), 0);
109 /* Tool hint */
110 CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow"));
111 CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow"));
112 }
113 if (replace_text) {
114 yr = ys;
115 if (option & SEARCH_DIALOG_OPTION_BACKWARDS)
116 yr = yc;
117 } else {
118 if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
119 if (option & SEARCH_DIALOG_OPTION_BOOKMARK)
120 yr = yb;
121 else
122 yr = yh;
123 } else {
124 if (option & SEARCH_DIALOG_OPTION_BOOKMARK)
125 yr = yc;
126 else
127 yr = yb;
128 }
129 }
130
131 if (replace_text) {
132 CDrawSwitch ("replace.pr", win, xb, yr, replace_prompt, _(" Prompt on replace "), 0);
133 /* Tool hint */
134 CSetToolHint ("replace.pr", _("Ask before making each replacement"));
135 CGetHintPos (0, &yr);
136 CDrawSwitch ("replace.all", win, xb, yr, replace_all, _(" Replace all "), 0);
137 /* Tool hint */
138 CSetToolHint ("replace.all", _("Replace repeatedly"));
139 CGetHintPos (0, &yr);
140 }
141 if (option & SEARCH_DIALOG_OPTION_BOOKMARK) {
142 CDrawSwitch ("replace.bkmk", win, xb, yr, search_create_bookmark, _(" Bookmarks "), 0);
143 /* Tool hint */
144 CSetToolHint ("replace.bkmk", _("Create bookmarks at all lines found"));
145 CSetToolHint ("replace.bkmk.label", _("Create bookmarks at all lines found"));
146 CGetHintPos (0, &yr);
147 }
148 CDrawSwitch ("replace.scanf", win, xb, yr, replace_scanf, _(" Scanf expression "), 1);
149 /* Tool hint */
150 CSetToolHint ("replace.scanf", _("Allows entering of a C format string,\nsee the scanf man page"));
151
152 get_hint_limits (&x, &y);
153 CDrawPixmapButton ("replace.ok", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h, PIXMAP_BUTTON_TICK);
154 CDrawPixmapButton ("replace.cancel", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h + WIDGET_SPACING + TICK_BUTTON_WIDTH, PIXMAP_BUTTON_CROSS);
155 /* Tool hint */
156 CSetToolHint ("replace.ok", _("Begin search, Enter"));
157 CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
158 CSetSizeHintPos ("replace");
159 CMapDialog ("replace");
160
161 m = CIdent ("replace");
162 text_input_width = m->width - WIDGET_SPACING * 3 - 4 - TICK_BUTTON_WIDTH ;
163 CSetWidgetSize ("replace.sinp", text_input_width, (CIdent ("replace.sinp"))->height);
164 if (replace_text) {
165 CSetWidgetSize ("replace.rinp", text_input_width, (CIdent ("replace.rinp"))->height);
166 CSetWidgetSize ("replace.ainp", text_input_width, (CIdent ("replace.ainp"))->height);
167 }
168 CFocus (CIdent ("replace.sinp"));
169
170 for (;;) {
171 CNextEvent (&xev, &cev);
172 if (!CIdent ("replace")) {
173 *search_text = 0;
174 break;
175 }
176 if (!strcmp (cev.ident, "replace.cancel") || cev.command == CK_Cancel) {
177 *search_text = 0;
178 break;
179 }
180 if (!strcmp (cev.ident, "replace.reg") || !strcmp (cev.ident, "replace.scanf")) {
181 if (CIdent ("replace.reg")->keypressed || CIdent ("replace.scanf")->keypressed) {
182 if (!(CIdent ("replace.case")->keypressed)) {
183 CIdent ("replace.case")->keypressed = 1;
184 CExpose ("replace.case");
185 }
186 }
187 }
188 if (!strcmp (cev.ident, "replace.ok") || cev.command == CK_Enter) {
189 if (replace_text) {
190 replace_all = CIdent ("replace.all")->keypressed;
191 replace_prompt = CIdent ("replace.pr")->keypressed;
192 *replace_text = (char *) strdup (CIdent ("replace.rinp")->text);
193 *arg_order = (char *) strdup (CIdent ("replace.ainp")->text);
194 }
195 *search_text = (char *) strdup (CIdent ("replace.sinp")->text);
196 replace_whole = CIdent ("replace.ww")->keypressed;
197 replace_case = CIdent ("replace.case")->keypressed;
198 replace_scanf = CIdent ("replace.scanf")->keypressed;
199 replace_regexp = CIdent ("replace.reg")->keypressed;
200
201 if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
202 replace_backwards = CIdent ("replace.bkwd")->keypressed;
203 } else {
204 replace_backwards = 0;
205 }
206
207 if (option & SEARCH_DIALOG_OPTION_BOOKMARK) {
208 search_create_bookmark = CIdent ("replace.bkmk")->keypressed;
209 } else {
210 search_create_bookmark = 0;
211 }
212
213 break;
214 }
215 }
216 CDestroyWidget ("replace");
217 CRestoreState (&s);
218 }
219
220 /* }}} search replace dialog */
221
222 /* {{{ file list stuff */
223
destroy_filelist(CWidget * w)224 static void destroy_filelist (CWidget * w)
225 {
226 if (w->hook) {
227 struct look_cool_list *fe = (struct look_cool_list *) w->hook;
228 if (fe->l)
229 free (fe->l);
230 free (w->hook);
231 w->hook = 0;
232 }
233 }
234
235 /* This doesn't apply to solaris: */
236 /*
237 * struct dirent {
238 * long d_ino;
239 * __kernel_off_t d_off;
240 * unsigned short d_reclen;
241 * char d_name[256];
242 * };
243 */
244
245 /*
246 *
247 * #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
248 * #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
249 * #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
250 * #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
251 * #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
252 * #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
253 * #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
254 *
255 * #define S_IRWXU 00700
256 * #define S_IRUSR 00400
257 * #define S_IWUSR 00200
258 * #define S_IXUSR 00100
259 *
260 * #define S_IRWXG 00070
261 * #define S_IRGRP 00040
262 * #define S_IWGRP 00020
263 * #define S_IXGRP 00010
264 *
265 * #define S_IRWXO 00007
266 * #define S_IROTH 00004
267 * #define S_IWOTH 00002
268 * #define S_IXOTH 00001
269 */
270
271 #if 0
272 static char *dname (struct dirent *directentry);
273 #endif
274
275 #ifdef HAVE_STRFTIME
276 /* We want our own dates for NLS */
277 #undef HAVE_STRFTIME
278 #endif
279
280 #undef gettext_noop
281 #define gettext_noop(x) x
282
283 void get_file_time (char *timestr, time_t file_time, int l);
284
get_filelist_line(void * data,int line_number,int * num_fields,int * tagged)285 static char **get_filelist_line (void *data, int line_number, int *num_fields, int *tagged)
286 {
287 struct file_entry *directentry;
288 struct look_cool_list *fe;
289 static char *fields[10], size[24], mode[12], timestr[32];
290 static char name[520], *n;
291 mode_t m;
292
293 *num_fields = 4; /* name, size, date, mode only (for the mean time) */
294
295 fe = (struct look_cool_list *) data;
296 if (line_number >= fe->n)
297 return 0;
298 directentry = fe->l;
299
300 n = name;
301 strcpy (name, directentry[line_number].name);
302 fields[0] = name;
303 sprintf (size, "\t%u", (unsigned int) directentry[line_number].stat.st_size);
304 fields[1] = size;
305
306 get_file_time (timestr, directentry[line_number].stat.st_mtime, 0);
307 fields[2] = timestr;
308
309 memset (mode, ' ', 11);
310 mode[11] = 0;
311 mode[0] = '-';
312 m = directentry[line_number].stat.st_mode;
313 switch ((int) m & S_IFMT) {
314 case S_IFLNK:
315 mode[0] = 'l';
316 break;
317 case S_IFDIR:
318 mode[0] = 'd';
319 break;
320 case S_IFCHR:
321 mode[0] = 'c';
322 break;
323 case S_IFBLK:
324 mode[0] = 'b';
325 break;
326 case S_IFIFO:
327 mode[0] = 'f';
328 break;
329 case S_IFSOCK:
330 mode[0] = 's';
331 break;
332 }
333
334 mode[1] = m & S_IRUSR ? 'r' : '-';
335 mode[2] = m & S_IWUSR ? 'w' : '-';
336 mode[3] = m & S_IXUSR ? 'x' : '-';
337
338 mode[4] = m & S_IRGRP ? 'r' : '-';
339 mode[5] = m & S_IWGRP ? 'w' : '-';
340 mode[6] = m & S_IXGRP ? 'x' : '-';
341
342 mode[7] = m & S_IROTH ? 'r' : '-';
343 mode[8] = m & S_IWOTH ? 'w' : '-';
344 mode[9] = m & S_IXOTH ? 'x' : '-';
345
346 if (S_ISLNK (m)) {
347 int l, i;
348 char *p;
349 p = directentry[line_number].name;
350 l = strlen (n);
351 for (i = 0; i < l; i++) {
352 *n++ = '\b';
353 *n++ = *p++;
354 }
355 *n++ = '\0';
356 } else if (m & (S_IXUSR | S_IXGRP | S_IXOTH)) {
357 int l, i;
358 char *p;
359 p = directentry[line_number].name;
360 l = strlen (n);
361 for (i = 0; i < l; i++) {
362 *n++ = '\r';
363 *n++ = *p++;
364 }
365 *n++ = '\0';
366 }
367 fields[3] = mode;
368 fields[*num_fields] = 0;
369 if (directentry[line_number].options & FILELIST_TAGGED_ENTRY)
370 *tagged = 1;
371 return fields;
372 }
373
374
look_cool_draw_file_list(const char * identifier,Window parent,int x,int y,int width,int height,int line,int column,struct file_entry * directentry,long options)375 CWidget *look_cool_draw_file_list (const char *identifier, Window parent, int x, int y,
376 int width, int height, int line, int column,
377 struct file_entry *directentry,
378 long options)
379 {
380 struct file_entry e;
381 struct look_cool_list *fe;
382 CWidget *w;
383 int n;
384
385 for (n = 0; directentry && !(directentry[n].options & FILELIST_LAST_ENTRY); n++); /* count entries */
386
387 fe = CMalloc (sizeof (struct look_cool_list));
388 fe->l = CMalloc (sizeof (struct file_entry) * (n + 1));
389 memcpy (fe->l, directentry, sizeof (struct file_entry) * n);
390 fe->n = n;
391
392 w = CDrawFieldedTextbox (identifier, parent, x, y,
393 width, height, line, column,
394 get_filelist_line,
395 options, fe);
396 w->hook = (void *) fe;
397 w->destroy = destroy_filelist;
398
399 return w;
400 }
401
look_cool_redraw_file_list(const char * identifier,struct file_entry * directentry,int preserve)402 CWidget *look_cool_redraw_file_list (const char *identifier, struct file_entry *directentry, int preserve)
403 {
404 struct file_entry e;
405 struct look_cool_list *fe;
406 CWidget *w;
407 int n;
408
409 for (n = 0; directentry && !(directentry[n].options & FILELIST_LAST_ENTRY); n++); /* count entries */
410
411 w = CIdent (identifier);
412 fe = (struct look_cool_list *) w->hook;
413 free (fe->l);
414 fe->l = CMalloc (sizeof (struct file_entry) * (n + 1));
415 memcpy (fe->l, directentry, sizeof (struct file_entry) * n);
416 fe->n = n;
417
418 w = CRedrawFieldedTextbox (identifier, preserve);
419
420 return w;
421 }
422
look_cool_get_file_list_line(CWidget * w,int line)423 struct file_entry *look_cool_get_file_list_line (CWidget * w, int line)
424 {
425 struct look_cool_list *fe;
426 static struct file_entry r;
427 memset (&r, 0, sizeof (r));
428 fe = (struct look_cool_list *) w->hook;
429 if (line >= fe->n)
430 r.options = FILELIST_LAST_ENTRY;
431 else
432 r = fe->l[line];
433 return &r;
434 }
435
436
437
438 /* }}} file list stuff */
439
440 /* {{{ file browser stuff */
441
442 extern int option_file_browser_width;
443 extern int option_file_browser_height;
444
445 static char *mime_majors[3] =
446 {"url", "text", 0};
447
draw_file_browser(const char * identifier,Window parent,int x,int y,const char * directory,const char * file,const char * label)448 static Window draw_file_browser (const char *identifier, Window parent, int x, int y,
449 const char *directory, const char *file, const char *label)
450 {
451 CWidget * w;
452 struct file_entry *filelist = 0, *directorylist = 0;
453 char *dir;
454 char *resolved_path, *p;
455 int y2, x2, x3, y3;
456 Window win;
457
458 dir = (char *) strdup (directory);
459
460 if (parent == CRoot)
461 win = CDrawMainWindow (identifier, label);
462 else
463 win = CDrawHeadedDialog (identifier, parent, x, y, label);
464 (CIdent (identifier))->options |= WINDOW_ALWAYS_RAISED;
465 CHourGlass (CFirstWindow);
466 for (;;) {
467 filelist = get_file_entry_list (dir, FILELIST_FILES_ONLY, CLastInput (catstrs (identifier, ".filt", NULL)));
468 if (!filelist) {
469 char *s;
470 s = strrchr (dir, '/');
471 if (s) {
472 *s = '\0';
473 continue;
474 }
475 }
476 break;
477 }
478 CUnHourGlass (CFirstWindow);
479 if (!filelist || !(directorylist = get_file_entry_list (dir, FILELIST_DIRECTORIES_ONLY, ""))) {
480 CErrorDialog (parent, 20, 20, _(" File browser "), _(" Unable to read directory "));
481 CDestroyWidget (identifier);
482 goto error;
483 }
484 CGetHintPos (&x, &y);
485 resolved_path = pathdup (dir);
486 p = resolved_path + strlen (resolved_path) - 1;
487 if (*p != '/') {
488 *++p = '/';
489 *++p = '\0';
490 }
491 (CDrawText (catstrs (identifier, ".dir", NULL), win, x, y, "%s", resolved_path))->position |= POSITION_FILL;
492 free (resolved_path);
493 CGetHintPos (0, &y);
494 reset_hint_pos (x, y);
495 y3 = y;
496 (w = CDrawFilelist (catstrs (identifier, ".fbox", NULL), win, x, y,
497 FONT_MEAN_WIDTH * option_file_browser_width + 7, FONT_PIX_PER_LINE * option_file_browser_height + 6, 0, 0, filelist, TEXTBOX_FILE_LIST))->position |= POSITION_WIDTH | POSITION_HEIGHT;
498 xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFiles]);
499 (CIdent (catstrs (identifier, ".fbox", NULL)))->options |= TEXTBOX_MARK_WHOLE_LINES;
500
501 /* the vertical scroll bar is named the same as the text box, with a ".vsc" at the end: */
502 CSetMovement (catstrs (identifier, ".fbox.vsc", NULL), POSITION_HEIGHT | POSITION_RIGHT);
503 CSetMovement (catstrs (identifier, ".fbox.hsc", NULL), POSITION_WIDTH | POSITION_BOTTOM);
504 CGetHintPos (&x2, &y2);
505 x3 = x2;
506 (w = CDrawFilelist (catstrs (identifier, ".dbox", NULL), win, x2, y + TICK_BUTTON_WIDTH + WIDGET_SPACING,
507 FONT_MEAN_WIDTH * 24 + 7, y2 - WIDGET_SPACING * 3 - 12 - y - TICK_BUTTON_WIDTH, 0, 0, directorylist, TEXTBOX_FILE_LIST))->position |= POSITION_HEIGHT | POSITION_RIGHT;
508 xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFiles]);
509
510 /* Toolhint */
511 CSetToolHint (catstrs (identifier, ".dbox", NULL), _("Double click to enter directories"));
512 (CIdent (catstrs (identifier, ".dbox", NULL)))->options |= TEXTBOX_MARK_WHOLE_LINES;
513 CSetMovement (catstrs (identifier, ".dbox.vsc", NULL), POSITION_HEIGHT | POSITION_RIGHT);
514 CSetMovement (catstrs (identifier, ".dbox.hsc", NULL), POSITION_RIGHT | POSITION_BOTTOM);
515 CGetHintPos (&x2, &y2);
516 (CDrawText (catstrs (identifier, ".msg", NULL), win, x, y2, _("Ctrl-Tab to complete, Alt-Ins for clip history, Shift-Up for history")))->position |= POSITION_FILL | POSITION_BOTTOM;
517 CGetHintPos (0, &y2);
518 (w = CDrawTextInput (catstrs (identifier, ".finp", NULL), win, x, y2,
519 WIDGET_SPACING * 2 - 2, AUTO_HEIGHT, 256, file))->position |= POSITION_FILL | POSITION_BOTTOM;
520 xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFile]);
521 w->funcs->types = DndFile;
522 w->funcs->mime_majors = mime_majors;
523
524 CGetHintPos (0, &y2);
525 /* Label for file filter input line. For example, to list files matching '*.c' */
526 (CDrawText (catstrs (identifier, ".filx", NULL), win, x, y2, _("Filter : ")))->position |= POSITION_BOTTOM;
527 CGetHintPos (&x, 0);
528 (CDrawTextInput (catstrs (identifier, ".filt", NULL), win, x, y2,
529 WIDGET_SPACING * 2 - 2, AUTO_HEIGHT, 256, TEXTINPUT_LAST_INPUT))->position |= POSITION_FILL | POSITION_BOTTOM;
530 /* Toolhint */
531 CSetToolHint (catstrs (identifier, ".filt", NULL), _("List only files matching this shell filter"));
532 CSetToolHint (catstrs (identifier, ".filx", NULL), _("List only files matching this shell filter"));
533 (CDrawPixmapButton (catstrs (identifier, ".ok", NULL), win, x3, y3,
534 PIXMAP_BUTTON_TICK))->position |= POSITION_RIGHT;
535 /* Toolhint */
536 CSetToolHint (catstrs (identifier, ".ok", NULL), _("Accept, Enter"));
537
538 (CDrawPixmapButton (catstrs (identifier, ".cancel", NULL), win, x2 - WIDGET_SPACING * 2 - TICK_BUTTON_WIDTH - 20, y3,
539 PIXMAP_BUTTON_CROSS))->position |= POSITION_RIGHT;
540 /* Toolhint */
541 CSetToolHint (catstrs (identifier, ".cancel", NULL), _("Abort this dialog, Escape"));
542 CSetSizeHintPos (identifier);
543 CMapDialog (identifier);
544 y = (CIdent (identifier))->height;
545 CSetWindowResizable (identifier, FONT_MEAN_WIDTH * 40, min (FONT_PIX_PER_LINE * 5 + 210, y), 1600, 1200); /* minimum and maximum sizes */
546
547 error:
548 if (directorylist)
549 free (directorylist);
550 if (filelist)
551 free (filelist);
552 free (dir);
553 return win;
554 }
555
how_much_matches(const char * a,const char * b)556 static int how_much_matches (const char *a, const char *b)
557 {
558 int n = 0;
559 while (*a && *b && *a++ == *b++)
560 n++;
561 return n;
562 }
563
564 /* returns 0 on fail */
goto_partial_file_name(CWidget * list,char * text)565 static int goto_partial_file_name (CWidget * list, char *text)
566 {
567 int i = 0;
568 struct file_entry *fe = 0;
569 char *e;
570 int max_match = -1;
571 int found_matchiest = -1;
572
573 for (;;) {
574 int n;
575 if (!strlen (text))
576 break;
577 if (list->kind == C_FIELDED_TEXTBOX_WIDGET) {
578 fe = CGetFilelistLine (list, i);
579 e = fe->name;
580 } else {
581 e = CGetTextBoxLine (list, i);
582 if (e)
583 while (*e == '/')
584 e++;
585 }
586 if (!e)
587 break;
588 n = how_much_matches (e, text);
589 if (max_match < n) {
590 max_match = n;
591 found_matchiest = i;
592 }
593 if (list->kind == C_FIELDED_TEXTBOX_WIDGET) {
594 if (fe->options & FILELIST_LAST_ENTRY)
595 break;
596 } else {
597 if (i >= list->numlines - 1)
598 break;
599 }
600 i++;
601 }
602 if (max_match >= 1) {
603 CSetTextboxPos (list, TEXT_SET_CURSOR_LINE, found_matchiest);
604 CSetTextboxPos (list, TEXT_SET_LINE, found_matchiest);
605 return 1;
606 }
607 return 0;
608 }
609
610 /* options */
611 #define GETFILE_GET_DIRECTORY 1
612 #define GETFILE_GET_EXISTING_FILE 2
613 #define GETFILE_BROWSER 4
614
615 void input_insert (CWidget * w, int c);
616
file_error(void)617 static char *file_error (void)
618 {
619 if (errno) {
620 const char *error_msg;
621 #ifdef HAVE_STRERROR
622 error_msg = _ (strerror (errno));
623 #else
624 extern int sys_nerr;
625 extern char *sys_errlist[];
626 if ((0 <= errno) && (errno < sys_nerr))
627 error_msg = _ (sys_errlist[errno]);
628 else
629 /* The returned value, 'errno' has an unknown meaning */
630 error_msg = _ ("strange errno");
631 #endif
632 return catstrs ("[", error_msg, "]", NULL);
633 }
634 return "";
635 }
636
637
638 /*
639 Returns "" on no file entered and NULL on exit (i.e. Cancel button pushed)
640 else returns the file or directory. Result must be immediately copied.
641 Result must not be free'd.
642 */
handle_browser(const char * identifier,CEvent * cwevent,int options)643 static char *handle_browser (const char *identifier, CEvent * cwevent, int options)
644 {
645 struct stat st;
646 char *q;
647 char *idd = catstrs (identifier, ".dbox", NULL);
648 char *idf = catstrs (identifier, ".fbox", NULL);
649 static char estr[MAX_PATH_LEN + 1];
650 CWidget *directory = CIdent (catstrs (identifier, ".dir", NULL));
651 CWidget *filelist = CIdent (idf);
652 CWidget *directorylist = CIdent (idd);
653 CWidget *textinput = CIdent (catstrs (identifier, ".finp", NULL));
654 CWidget *filterinput = CIdent (catstrs (identifier, ".filt", NULL));
655
656 CSetDndDirectory (directory->text);
657
658 if (cwevent->type == ButtonPress || cwevent->type == KeyPress)
659 CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error());
660
661 if (!strcmp (cwevent->ident, filterinput->ident) && cwevent->command == CK_Enter) {
662 struct file_entry *f;
663 if (!(*(filterinput->text))) {
664 filterinput->text[0] = '*';
665 filterinput->text[1] = '\0';
666 CExpose (filterinput->ident);
667 }
668 CHourGlass (CFirstWindow);
669 CRedrawFilelist (catstrs (identifier, ".fbox", NULL),
670 f = get_file_entry_list (directory->text, FILELIST_FILES_ONLY, filterinput->text),
671 0);
672 if (f)
673 free (f);
674 CUnHourGlass (CFirstWindow);
675 return "";
676 }
677 if (!strcmp (cwevent->ident, idf) && !(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER))) {
678 if (cwevent->button == Button1 || cwevent->command == CK_Enter) {
679 q = (CGetFilelistLine (filelist, filelist->cursor))->name;
680 CDrawTextInput (textinput->ident, CIdent (identifier)->winid, textinput->x, textinput->y,
681 textinput->width, textinput->height, 256, q);
682 } else if (cwevent->insert > 0) {
683 input_insert (textinput, cwevent->insert);
684 if (goto_partial_file_name (filelist, textinput->text))
685 CExpose (filelist->ident);
686 CExpose (textinput->ident);
687 } else if (cwevent->command == CK_BackSpace && textinput->cursor > 0) {
688 textinput->text[--textinput->cursor] = '\0';
689 if (goto_partial_file_name (filelist, textinput->text))
690 CExpose (filelist->ident);
691 CExpose (textinput->ident);
692 }
693 }
694 if (!strcmp (cwevent->ident, idd)) {
695 if (cwevent->button == Button1 || cwevent->command == CK_Enter) {
696 q = (CGetFilelistLine (directorylist, directorylist->cursor))->name;
697 CDrawTextInput (catstrs (identifier, ".finp", NULL), CIdent (identifier)->winid, textinput->x, textinput->y,
698 textinput->width, textinput->height, 256, q);
699 } else if (cwevent->insert > 0) {
700 input_insert (textinput, cwevent->insert);
701 if (goto_partial_file_name (directorylist, textinput->text))
702 CExpose (directorylist->ident);
703 CExpose (textinput->ident);
704 } else if (cwevent->command == CK_BackSpace && textinput->cursor > 0) {
705 textinput->text[--textinput->cursor] = '\0';
706 if (goto_partial_file_name (directorylist, textinput->text))
707 CExpose (directorylist->ident);
708 CExpose (textinput->ident);
709 }
710 }
711 if (!strcmp (cwevent->ident, textinput->ident)) {
712 switch ((int) cwevent->command) {
713 case CK_Enter:
714 if (!(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER)))
715 if (!strncmp ((CGetFilelistLine (filelist, filelist->cursor))->name, textinput->text, strlen (textinput->text))) {
716 CFocus (filelist);
717 CExpose (filelist->ident);
718 return "";
719 }
720 break;
721 case CK_Down:
722 if (textinput->keypressed) {
723 if (goto_partial_file_name (filelist, textinput->text)) {
724 CFocus (filelist);
725 CExpose (filelist->ident);
726 break;
727 }
728 }
729 CFocus (filelist);
730 CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, 0);
731 CExpose (filelist->ident);
732 break;
733 case CK_Up:
734 if (textinput->keypressed) {
735 if (goto_partial_file_name (filelist, textinput->text)) {
736 CFocus (filelist);
737 CExpose (filelist->ident);
738 break;
739 }
740 }
741 CFocus (filelist);
742 CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, 999999);
743 CExpose (filelist->ident);
744 break;
745 case CK_Page_Down:
746 CFocus (filelist);
747 CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, filelist->height / FONT_PIX_PER_LINE - 1);
748 CExpose (filelist->ident);
749 break;
750 case CK_Page_Up:
751 CFocus (filelist);
752 CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, filelist->numlines - filelist->height / FONT_PIX_PER_LINE + 1);
753 CExpose (filelist->ident);
754 break;
755 default:
756 if (cwevent->insert > 0)
757 if (goto_partial_file_name (filelist, textinput->text))
758 CExpose (filelist->ident);
759 break;
760 }
761 }
762 if (cwevent->command == CK_Cancel || !strcmp (cwevent->ident, catstrs (identifier, ".cancel", NULL)))
763 return 0;
764
765 if (options & GETFILE_GET_DIRECTORY) {
766 if (!strcmp (cwevent->ident, catstrs (identifier, ".ok", NULL))) {
767 char *resolved_path;
768 resolved_path = pathdup (directory->text);
769 strcpy (estr, resolved_path);
770 free (resolved_path);
771 return estr;
772 }
773 }
774 if (!strcmp (cwevent->ident, catstrs (identifier, ".ok", NULL))
775 || cwevent->command == CK_Enter
776 || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".finp", NULL)))
777 || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".dbox", NULL)))
778 || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".fbox", NULL)))) {
779 char *resolved_path;
780 if (*textinput->text == '/' || *textinput->text == '~')
781 *estr = '\0';
782 else {
783 strcpy (estr, directory->text);
784 strcat (estr, "/");
785 }
786 strcat (estr, textinput->text);
787 resolved_path = pathdup (estr);
788 strcpy (estr, resolved_path);
789 free (resolved_path);
790 textinput->keypressed = 0;
791 q = estr + strlen (estr) - 1;
792 if (!estr[0])
793 return "";
794 if (stat (estr, &st)) {
795 if (errno == ENOENT) {
796 /* The user wanted a directory, but typed in one that doesn't exist */
797 if (*q != '/' && !(options & GETFILE_GET_EXISTING_FILE) && !(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER)))
798 /* user wants a new file */
799 return estr;
800 }
801 /* ********* */
802 CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error());
803 return "";
804 }
805 if (S_ISDIR (st.st_mode)) {
806 struct file_entry *g = 0, *f = 0;
807 CHourGlass (CFirstWindow);
808 g = get_file_entry_list (estr, FILELIST_FILES_ONLY, filterinput->text);
809 CUnHourGlass (CFirstWindow);
810 if (g) {
811 CRedrawFilelist (catstrs (identifier, ".fbox", NULL), g, 0);
812 CRedrawFilelist (catstrs (identifier, ".dbox", NULL), f = get_file_entry_list (estr, FILELIST_DIRECTORIES_ONLY, ""), 0);
813 if (*q != '/') {
814 *++q = '/';
815 *++q = '\0';
816 }
817 CRedrawText (catstrs (identifier, ".dir", NULL), "%s", estr);
818 if (options & GETFILE_BROWSER)
819 CAddToTextInputHistory (textinput->ident, estr);
820 }
821 if (g)
822 free (g);
823 if (f)
824 free (f);
825 return "";
826 } else {
827 if (options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER)) {
828 CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error());
829 return "";
830 }
831 return estr; /* entry exists and is a file */
832 }
833 }
834 return "";
835 }
836
837 Window find_mapped_window (Window w);
838
839 /* result must be free'd */
look_cool_get_file_or_dir(Window parent,int x,int y,const char * dir,const char * file,const char * label,int options)840 char *look_cool_get_file_or_dir (Window parent, int x, int y,
841 const char *dir, const char *file, const char *label, int options)
842 {
843 CEvent cwevent;
844 XEvent xevent;
845 CState s;
846 CWidget *w;
847
848 CBackupState (&s);
849 CDisable ("*");
850 CEnable ("_cfileBr*");
851
852 parent = find_mapped_window (parent);
853 if (!(x | y)) {
854 x = 20;
855 y = 20;
856 }
857 draw_file_browser ("CGetFile", parent, x, y, dir, file, label);
858
859 CFocus (CIdent ("CGetFile.finp"));
860
861 file = "";
862 do {
863 CNextEvent (&xevent, &cwevent);
864 if (xevent.type == Expose || !xevent.type
865 || xevent.type == InternalExpose || xevent.type == TickEvent)
866 continue;
867 if (!CIdent ("CGetFile")) {
868 file = 0;
869 break;
870 }
871 if (xevent.type == Expose || !xevent.type || xevent.type == AlarmEvent
872 || xevent.type == InternalExpose || xevent.type == TickEvent) {
873 file = "";
874 continue;
875 }
876 file = handle_browser ("CGetFile", &cwevent, options);
877 if (!file)
878 break;
879 } while (!(*file));
880
881 /* here we want to add the complete path to the text-input history: */
882 w = CIdent ("CGetFile.finp");
883 if (w) {
884 if (w->text) {
885 free (w->text);
886 w->text = 0;
887 }
888 if (file)
889 w->text = (char *) strdup (file);
890 }
891 w = CIdent ("CGetFile.fbox");
892 if (w) {
893 option_file_browser_width = (w->width - 7) / FONT_MEAN_WIDTH;
894 if (option_file_browser_width < 10)
895 option_file_browser_width = 10;
896 option_file_browser_height = (w->height - 6) / FONT_PIX_PER_LINE;
897 if (option_file_browser_height < 10)
898 option_file_browser_height = 10;
899 }
900 CDestroyWidget ("CGetFile"); /* text is added to history
901 when text-input widget is destroyed */
902
903 CRestoreState (&s);
904
905 if (file) {
906 return (char *) strdup (file);
907 } else
908 return 0;
909 }
910
cb_browser(CWidget * w,XEvent * x,CEvent * c)911 static int cb_browser (CWidget * w, XEvent * x, CEvent * c)
912 {
913 char id[32], *s;
914 strcpy (id, w->ident);
915 s = strchr (id, '.');
916 if (s)
917 *s = 0;
918 if (!handle_browser (id, c, GETFILE_BROWSER)) {
919 w = CIdent (catstrs (id, ".finp", NULL));
920 if (w)
921 if (w->text) {
922 free (w->text);
923 w->text = 0;
924 }
925 CDestroyWidget (id);
926 }
927 return 0;
928 }
929
look_cool_draw_browser(const char * ident,Window parent,int x,int y,const char * dir,const char * file,const char * label)930 void look_cool_draw_browser (const char *ident, Window parent, int x, int y,
931 const char *dir, const char *file, const char *label)
932 {
933 if (!(parent | x | y)) {
934 parent = CFirstWindow;
935 x = 20;
936 y = 20;
937 }
938
939 draw_file_browser (ident, parent, x, y, dir, file, label);
940
941 CAddCallback (catstrs (ident, ".dbox", NULL), cb_browser);
942 CAddCallback (catstrs (ident, ".fbox", NULL), cb_browser);
943 CAddCallback (catstrs (ident, ".finp", NULL), cb_browser);
944 CAddCallback (catstrs (ident, ".filt", NULL), cb_browser);
945 CAddCallback (catstrs (ident, ".ok", NULL), cb_browser);
946 CAddCallback (catstrs (ident, ".cancel", NULL), cb_browser);
947
948 CFocus (CIdent (catstrs (ident, ".finp", NULL)));
949 }
950
951
952 /* }}} file browser stuff */
953
954 int find_menu_hotkey (struct menu_item m[], int this, int num);
955
956 /* outermost bevel */
957 #define BEVEL_MAIN 2
958 /* next-outermost bevel */
959 #define BEVEL_IN 4
960 #define BEVEL_OUT 5
961 /* between items, and between items and next-outermost bevel */
962 #define SPACING 4
963 /* between items rectangle and text */
964 #define RELIEF (TEXT_RELIEF + 1)
965
966 #define S SPACING
967 /* between window border and items */
968 #define O (BEVEL_OUT + SPACING)
969 /* total height of an item */
970
971 /* size of bar item */
972 #define BAR_HEIGHT 8
973 #define ITEM_BEVEL_TYPE 1
974 #define ITEM_BEVEL 1
975
976 #define H (FONT_PIX_PER_LINE + RELIEF * 2)
977
978 #define B BAR_HEIGHT
979
look_cool_get_default_widget_font(void)980 static char *look_cool_get_default_widget_font (void)
981 {
982 return "-*-helvetica-bold-r-*--%d-*-*-*-*-*-*";
983 }
984
look_cool_get_menu_item_extents(int n,int j,struct menu_item m[],int * border,int * relief,int * y1,int * y2)985 static void look_cool_get_menu_item_extents (int n, int j, struct menu_item m[], int *border, int *relief, int *y1, int *y2)
986 {
987 int i, n_items = 0, n_bars = 0;
988
989 *border = O;
990 *relief = RELIEF;
991
992 if (!n || j < 0) {
993 *y1 = O;
994 *y2 = *y1 + H;
995 } else {
996 int not_bar;
997 not_bar = (m[j].text[2] != '\0');
998 for (i = 0; i < j; i++)
999 if (m[i].text[2])
1000 n_items++;
1001 else
1002 n_bars++;
1003 *y1 = O + n_items * (H + S) + n_bars * (B + S) + (not_bar ? 0 : 2);
1004 *y2 = *y1 + (not_bar ? H : (B - 4));
1005 }
1006 }
1007
look_cool_menu_draw(Window win,int w,int h,struct menu_item m[],int n,int light)1008 static void look_cool_menu_draw (Window win, int w, int h, struct menu_item m[], int n, int light)
1009 {
1010 int i, y1, y2, offset = 0;
1011 static int last_light = 0, last_n = 0;
1012 static Window last_win = 0;
1013
1014 render_bevel (win, 0, 0, w - 1, h - 1, BEVEL_MAIN, 0);
1015 render_bevel (win, BEVEL_IN, BEVEL_IN, w - 1 - BEVEL_IN, h - 1 - BEVEL_IN, BEVEL_OUT - BEVEL_IN, 1);
1016
1017 if (last_win == win && last_n != n) {
1018 XClearWindow (CDisplay, win);
1019 } else if (last_light >= 0 && last_light < n) {
1020 int border, relief;
1021 look_cool_get_menu_item_extents (n, last_light, m, &border, &relief, &y1, &y2);
1022 CSetColor (COLOR_FLAT);
1023 CRectangle (win, O - 1, y1 - 1, w - O * 2 + 2, y2 - y1 + 2);
1024 }
1025 last_win = win;
1026 last_n = n;
1027 CPushFont ("widget", 0);
1028 for (i = 0; i < n; i++) {
1029 int border, relief;
1030 look_cool_get_menu_item_extents (n, i, m, &border, &relief, &y1, &y2);
1031 if (i == light && m[i].text[2]) {
1032 offset = 1;
1033 CSetColor (color_widget (11));
1034 CRectangle (win, O + 1, y1 + 1, w - O * 2 - 2, y2 - y1 - 2);
1035 render_bevel (win, O - 1, y1 - 1, w - O, y2, 2, 0);
1036 } else {
1037 if (!(m[i].text[2]))
1038 render_bevel (win, O + 6, y1, w - O - 1 - 6, y2 - 1, 2, 0);
1039 else
1040 render_bevel (win, O, y1, w - O - 1, y2 - 1, ITEM_BEVEL, ITEM_BEVEL_TYPE);
1041 offset = 0;
1042 }
1043 if (m[i].text[2]) {
1044
1045 char *u;
1046 u = strrchr (m[i].text, '\t');
1047 if (u)
1048 *u = 0;
1049 CSetColor (COLOR_BLACK);
1050 if (m[i].hot_key == '~')
1051 m[i].hot_key = find_menu_hotkey (m, i, n);
1052 if (i == light)
1053 CSetBackgroundColor (color_widget (11));
1054 else
1055 CSetBackgroundColor (COLOR_FLAT);
1056 drawstring_xy_hotkey (win, RELIEF + O - offset,
1057 RELIEF + y1 - offset, m[i].text, m[i].hot_key);
1058 if (u) {
1059 drawstring_xy (win, RELIEF + O + (w - (O + RELIEF) * 2 - CImageStringWidth (u + 1)) - offset,
1060 RELIEF + y1 - offset, u + 1);
1061 *u = '\t';
1062 }
1063 }
1064 }
1065 last_light = light;
1066 CPopFont ();
1067 }
1068
look_cool_render_menu_button(CWidget * wdt)1069 static void look_cool_render_menu_button (CWidget * wdt)
1070 {
1071 int w = wdt->width, h = wdt->height;
1072 int x = 0, y = 0;
1073
1074 Window win = wdt->winid;
1075
1076 if (wdt->disabled)
1077 goto disabled;
1078 if (wdt->options & BUTTON_PRESSED) {
1079 render_bevel (win, x, y, x + w - 1, y + h - 1, 2, 1);
1080 } else if (wdt->options & BUTTON_HIGHLIGHT) {
1081 CSetColor (COLOR_FLAT);
1082 XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3);
1083 render_bevel (win, x, y, x + w - 1, y + h - 1, 1, 0);
1084 } else {
1085 disabled:
1086 CSetColor (COLOR_FLAT);
1087 XDrawRectangle (CDisplay, win, CGC, x, y, w - 1, h - 1);
1088 XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3);
1089 }
1090
1091 if (!wdt->label)
1092 return;
1093 if (!(*(wdt->label)))
1094 return;
1095 CSetColor (COLOR_BLACK);
1096 CPushFont ("widget", 0);
1097 CSetBackgroundColor (COLOR_FLAT);
1098 drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey);
1099 CPopFont ();
1100 }
1101
look_cool_render_button(CWidget * wdt)1102 static void look_cool_render_button (CWidget * wdt)
1103 {
1104 int w = wdt->width, h = wdt->height;
1105 int x = 0, y = 0;
1106
1107 Window win = wdt->winid;
1108 #define BUTTON_BEVEL 2
1109
1110 if (wdt->disabled)
1111 goto disabled;
1112 if (wdt->options & BUTTON_PRESSED) {
1113 render_bevel (win, x, y, x + w - 1, y + h - 1, BUTTON_BEVEL, 1);
1114 } else if (wdt->options & BUTTON_HIGHLIGHT) {
1115 CSetColor (COLOR_FLAT);
1116 XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3);
1117 render_bevel (win, x, y, x + w - 1, y + h - 1, 1, 0);
1118 } else {
1119 disabled:
1120 render_bevel (win, x, y, x + w - 1, y + h - 1, BUTTON_BEVEL, 0);
1121 }
1122
1123 if (!wdt->label)
1124 return;
1125 if (!(*(wdt->label)))
1126 return;
1127 CSetColor (COLOR_BLACK);
1128 CSetBackgroundColor (COLOR_FLAT);
1129 CPushFont ("widget", 0);
1130 drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey);
1131 CPopFont ();
1132 }
1133
look_cool_render_bar(CWidget * wdt)1134 static void look_cool_render_bar (CWidget * wdt)
1135 {
1136 int w = wdt->width, h = wdt->height;
1137
1138 Window win = wdt->winid;
1139
1140 CSetColor (COLOR_FLAT);
1141 CLine (win, 1, 1, w - 2, 1);
1142 render_bevel (win, 0, 0, w - 1, h - 1, 1, 1);
1143 }
1144
look_cool_render_sunken_bevel(Window win,int x1,int y1,int x2,int y2,int thick,int sunken)1145 void look_cool_render_sunken_bevel (Window win, int x1, int y1, int x2, int y2, int thick, int sunken)
1146 {
1147 int i;
1148
1149 if ((sunken & 2)) {
1150 CSetColor (COLOR_FLAT);
1151 CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1);
1152 }
1153
1154 i = /* thick - 1 */ 0;
1155
1156 CSetColor (color_widget (11));
1157 CLine (win, x1 + i, y2 - i, x2 - 1 - i, y2 - i);
1158 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i - 1);
1159
1160 CSetColor (color_widget (7));
1161 CLine (win, x1, y1, x1, y2 - 1);
1162 CLine (win, x1, y1, x2 - 1, y1);
1163
1164 if (thick > 1) {
1165 CSetColor (color_widget (4));
1166 for (i = 1; i < thick; i++) {
1167 CLine (win, x1 + i + 1, y1 + i, x2 - 1 - i, y1 + i);
1168 CLine (win, x1 + i, y1 + i, x1 + i, y2 - 1 - i);
1169 }
1170 CSetColor (color_widget (13));
1171 for (i = 1; i < thick; i++) {
1172 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i - 1);
1173 CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i);
1174 }
1175 }
1176 CSetColor (color_widget (14));
1177 for (i = 0; i < thick; i++)
1178 XDrawPoint (CDisplay, win, CGC, x2 - i, y2 - i);
1179 }
1180
look_cool_render_raised_bevel(Window win,int x1,int y1,int x2,int y2,int thick,int sunken)1181 static void look_cool_render_raised_bevel (Window win, int x1, int y1, int x2, int y2, int thick, int sunken)
1182 {
1183 int i;
1184
1185 if ((sunken & 2)) {
1186 CSetColor (COLOR_FLAT);
1187 CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1);
1188 }
1189
1190 i = thick - 1;
1191
1192 CSetColor (color_widget (7));
1193 CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i);
1194 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i);
1195
1196 CSetColor (color_widget (12));
1197 CLine (win, x1 + i, y1 + i, x1 + i, y2 - 1 - i);
1198 CLine (win, x1 + 1 + i, y1 + i, x2 - 1 - i, y1 + i);
1199
1200 if (thick > 1) {
1201 CSetColor (color_widget (11));
1202 for (i = 0; i < thick - 1; i++) {
1203 CLine (win, x1 + i + 1, y1 + i, x2 - 1 - i, y1 + i);
1204 CLine (win, x1 + i, y1 + i + 1, x1 + i, y2 - 1 - i);
1205 }
1206 CSetColor (color_widget (4));
1207 for (i = 0; i < thick - 1; i++) {
1208 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i);
1209 CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i);
1210 }
1211 }
1212 CSetColor (color_widget (15));
1213 for (i = 0; i < thick; i++)
1214 XDrawPoint (CDisplay, win, CGC, x1 + i, y1 + i);
1215 }
1216
look_cool_draw_hotkey_understroke(Window win,int x,int y,int hotkey)1217 static void look_cool_draw_hotkey_understroke (Window win, int x, int y, int hotkey)
1218 {
1219 CLine (win, x, y, x + FONT_PER_CHAR (hotkey), y);
1220 CLine (win, x - 1, y + 1, x + FONT_PER_CHAR (hotkey) / 2, y + 1);
1221 CLine (win, x - 1, y + 2, x + FONT_PER_CHAR (hotkey) / 4 - 1, y + 2);
1222 }
1223
look_cool_render_text(CWidget * wdt)1224 static void look_cool_render_text (CWidget * wdt)
1225 {
1226 Window win = wdt->winid;
1227 char text[1024], *p, *q;
1228 int hot, y, w = wdt->width, center = 0;
1229
1230 CPushFont ("widget", 0);
1231
1232 CSetColor (COLOR_FLAT);
1233 CRectangle (win, 1, 1, w - 2, wdt->height - 2);
1234 CSetColor (COLOR_BLACK);
1235
1236 hot = wdt->hotkey; /* a letter that needs underlining */
1237 y = 1; /* bevel */
1238 q = wdt->text;
1239
1240 CSetBackgroundColor (COLOR_FLAT);
1241 for (;;) {
1242 p = strchr (q, '\n');
1243 if (!p) { /* last line */
1244 if (wdt->options & TEXT_CENTRED)
1245 center = (wdt->width - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, strlen (q))) / 2;
1246 drawstring_xy_hotkey (win, TEXT_RELIEF + 1 + center,
1247 TEXT_RELIEF + y, q, hot);
1248 break;
1249 } else {
1250 int l;
1251 l = min (1023, (unsigned long) p - (unsigned long) q);
1252 memcpy (text, q, l);
1253 text[l] = 0;
1254 if (wdt->options & TEXT_CENTRED)
1255 center = (wdt->width - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, l)) / 2;
1256 drawstring_xy_hotkey (win, TEXT_RELIEF + 1 + center,
1257 TEXT_RELIEF + y, text, hot);
1258 }
1259 y += FONT_PIX_PER_LINE;
1260 hot = 0; /* only for first line */
1261 q = p + 1; /* next line */
1262 }
1263 render_bevel (win, 0, 0, w - 1, wdt->height - 1, 1, 1);
1264 CPopFont ();
1265 }
1266
look_cool_render_window(CWidget * wdt)1267 static void look_cool_render_window (CWidget * wdt)
1268 {
1269 int w = wdt->width, h = wdt->height;
1270
1271 Window win = wdt->winid;
1272
1273 if (wdt->options & WINDOW_NO_BORDER)
1274 return;
1275
1276 if (wdt->position & WINDOW_RESIZABLE) {
1277 CSetColor (color_widget (13));
1278 CLine (win, w - 4, h - 31, w - 31, h - 4);
1279 CLine (win, w - 4, h - 21, w - 21, h - 4);
1280 CLine (win, w - 4, h - 11, w - 11, h - 4);
1281
1282 CLine (win, w - 4, h - 32, w - 32, h - 4);
1283 CLine (win, w - 4, h - 22, w - 22, h - 4);
1284 CLine (win, w - 4, h - 12, w - 12, h - 4);
1285
1286 CSetColor (color_widget (3));
1287 CLine (win, w - 4, h - 27, w - 27, h - 4);
1288 CLine (win, w - 4, h - 17, w - 17, h - 4);
1289 CLine (win, w - 4, h - 7, w - 7, h - 4);
1290
1291 CLine (win, w - 4, h - 28, w - 28, h - 4);
1292 CLine (win, w - 4, h - 18, w - 18, h - 4);
1293 CLine (win, w - 4, h - 8, w - 8, h - 4);
1294 }
1295 render_bevel (win, 0, 0, w - 1, h - 1, 2, 0);
1296 if (CRoot != wdt->parentid)
1297 if (win == CGetFocus ())
1298 render_bevel (win, 4, 4, w - 5, h - 5, 3, 1);
1299 }
1300
look_cool_render_vert_scrollbar(Window win,int x,int y,int w,int h,int pos,int prop,int pos2,int prop2,int flags)1301 static void look_cool_render_vert_scrollbar (Window win, int x, int y, int w, int h, int pos, int prop, int pos2, int prop2, int flags)
1302 {
1303 int l = h - 10 * w / 3 - 5;
1304
1305 render_bevel (win, 0, 0, w - 1, h - 1, 2, 1);
1306 CSetColor (COLOR_FLAT);
1307 CRectangle (win, 2, w + 2 * w / 3 + 2, w - 4, (l - 5) * pos / 65535);
1308 CRectangle (win, 2, w + 2 * w / 3 + 3 + l * (prop + pos) / 65535, w - 4, h - 1 - w - 2 * w / 3 - (w + 2 * w / 3 + 4 + l * (prop + pos) / 65535));
1309
1310 if (flags & 32) {
1311 render_bevel (win, 2, 2, w - 3, w + 1, 2 - ((flags & 15) == 1), 2);
1312 render_bevel (win, 2, w + 2, w - 3, w + 2 * w / 3 + 1, 2 - ((flags & 15) == 2), 2);
1313 render_bevel (win, 2, h - 2 - w, w - 3, h - 3, 2 - ((flags & 15) == 4), 2);
1314 render_bevel (win, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w, 2 - ((flags & 15) == 5), 2);
1315 render_bevel (win, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, 2 - ((flags & 15) == 3), 2);
1316 } else {
1317 render_bevel (win, 2, 2, w - 3, w + 1, 2, 2 | ((flags & 15) == 1));
1318 render_bevel (win, 2, w + 2, w - 3, w + 2 * w / 3 + 1, 2, 2 | ((flags & 15) == 2));
1319 render_bevel (win, 2, h - 2 - w, w - 3, h - 3, 2, 2 | ((flags & 15) == 4));
1320 render_bevel (win, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w, 2, 2 | ((flags & 15) == 5));
1321 if ((flags & 15) == 3) {
1322 CSetColor (color_widget (5));
1323 XDrawRectangle (CDisplay, win, CGC, 4, w + 2 * w / 3 + 4 + (l - 5) * pos2 / 65535, w - 10, 2 + (l - 5) * prop2 / 65535);
1324 }
1325 render_bevel (win, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, 2, 2 | ((flags & 15) == 3));
1326 }
1327 }
1328
look_cool_render_hori_scrollbar(Window win,int x,int y,int h,int w,int pos,int prop,int flags)1329 static void look_cool_render_hori_scrollbar (Window win, int x, int y, int h, int w, int pos, int prop, int flags)
1330 {
1331 int l = h - 10 * w / 3 - 5, k;
1332 k = (l - 5) * pos / 65535;
1333
1334 render_bevel (win, 0, 0, h - 1, w - 1, 2, 1);
1335 CSetColor (COLOR_FLAT);
1336
1337 CRectangle (win, w + 2 * w / 3 + 2, 2, (l - 5) * pos / 65535, w - 4);
1338 CRectangle (win, w + 2 * w / 3 + 3 + l * (prop + pos) / 65535, 2, h - 1 - w - 2 * w / 3 - (w + 2 * w / 3 + 4 + l * (prop + pos) / 65535), w - 4);
1339
1340 if (flags & 32) {
1341 render_bevel (win, 2, 2, w + 1, w - 3, 2 - ((flags & 15) == 1), 2);
1342 render_bevel (win, w + 2, 2, w + 2 * w / 3 + 1, w - 3, 2 - ((flags & 15) == 2), 2);
1343 render_bevel (win, h - 2 - w, 2, h - 3, w - 3, 2 - ((flags & 15) == 4), 2);
1344 render_bevel (win, h - 2 - w - 2 * w / 3, 2, h - 3 - w, w - 3, 2 - ((flags & 15) == 5), 2);
1345 render_bevel (win, w + 2 * w / 3 + 2 + k, 2, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, w - 3, 2 - ((flags & 15) == 3), 2);
1346 } else {
1347 render_bevel (win, 2, 2, w + 1, w - 3, 2, 2 | ((flags & 15) == 1));
1348 render_bevel (win, w + 2, 2, w + 2 * w / 3 + 1, w - 3, 2, 2 | ((flags & 15) == 2));
1349 render_bevel (win, h - 2 - w, 2, h - 3, w - 3, 2, 2 | ((flags & 15) == 4));
1350 render_bevel (win, h - 2 - w - 2 * w / 3, 2, h - 3 - w, w - 3, 2, 2 | ((flags & 15) == 5));
1351 render_bevel (win, w + 2 * w / 3 + 2 + k, 2, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, w - 3, 2, 2 | ((flags & 15) == 3));
1352 }
1353 }
1354
look_cool_render_scrollbar(CWidget * wdt)1355 static void look_cool_render_scrollbar (CWidget * wdt)
1356 {
1357 int flags = wdt->options;
1358 if (!wdt)
1359 return;
1360 if (wdt->numlines < 0)
1361 wdt->numlines = 0;
1362 if (wdt->firstline < 0)
1363 wdt->firstline = 0;
1364 if (wdt->firstline > 65535)
1365 wdt->firstline = 65535;
1366 if (wdt->firstline + wdt->numlines >= 65535)
1367 wdt->numlines = 65535 - wdt->firstline;
1368 if (wdt->kind == C_VERTSCROLL_WIDGET) {
1369 look_cool_render_vert_scrollbar (wdt->winid,
1370 wdt->x, wdt->y,
1371 wdt->width, wdt->height,
1372 wdt->firstline, wdt->numlines, wdt->search_start, wdt->search_len, flags);
1373 } else
1374 look_cool_render_hori_scrollbar (wdt->winid,
1375 wdt->x, wdt->y,
1376 wdt->width, wdt->height,
1377 wdt->firstline, wdt->numlines, flags);
1378 if (wdt->scroll_bar_extra_render)
1379 (*wdt->scroll_bar_extra_render) (wdt);
1380 }
1381
1382 /*
1383 Which scrollbar button was pressed: 3 is the middle button ?
1384 */
look_cool_which_scrollbar_button(int bx,int by,CWidget * wdt)1385 static int look_cool_which_scrollbar_button (int bx, int by, CWidget * wdt)
1386 {
1387 int w, h;
1388 int pos = wdt->firstline;
1389 int prop = wdt->numlines;
1390 int l;
1391
1392 if (wdt->kind == C_VERTSCROLL_WIDGET) {
1393 w = wdt->width;
1394 h = wdt->height;
1395 } else {
1396 int t = bx;
1397 bx = by;
1398 by = t;
1399 w = wdt->height;
1400 h = wdt->width;
1401 }
1402 l = h - 10 * w / 3 - 5;
1403
1404 if (inbounds (bx, by, 2, 2, w - 3, w + 1))
1405 return 1;
1406 if (inbounds (bx, by, 2, w + 2, w - 3, w + 2 * w / 3 + 1))
1407 return 2;
1408 if (inbounds (bx, by, 2, h - 2 - w, w - 3, h - 3))
1409 return 4;
1410 if (inbounds (bx, by, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w))
1411 return 5;
1412 if (inbounds (bx, by, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535))
1413 return 3;
1414 return 0;
1415 }
1416
look_cool_scrollbar_handler(CWidget * w,XEvent * xevent,CEvent * cwevent)1417 int look_cool_scrollbar_handler (CWidget * w, XEvent * xevent, CEvent * cwevent)
1418 {
1419 static int buttonypos, y, whichscrbutton = 0; /* which of the five scroll bar buttons was pressed */
1420 int xevent_xbutton_y, length, width;
1421
1422 if (w->kind == C_VERTSCROLL_WIDGET) {
1423 xevent_xbutton_y = xevent->xbutton.y;
1424 length = w->height;
1425 width = w->width;
1426 } else {
1427 xevent_xbutton_y = xevent->xbutton.x;
1428 length = w->width;
1429 width = w->height;
1430 }
1431
1432 switch (xevent->type) {
1433 case LeaveNotify:
1434 case Expose:
1435 w->options = 0;
1436 break;
1437 case ButtonRepeat:
1438 resolve_button (xevent, cwevent);
1439 if (cwevent->button == Button1 || cwevent->button == Button2) {
1440 int b;
1441 b = (*look->which_scrollbar_button) (cwevent->x, cwevent->y, w);
1442 if (b == 3 || !b)
1443 return 0;
1444 y = w->firstline;
1445 buttonypos = xevent_xbutton_y;
1446 w->options = whichscrbutton = b;
1447 cwevent->ident = w->ident;
1448 xevent->type = cwevent->type = ButtonPress;
1449 }
1450 break;
1451 case ButtonPress:
1452 resolve_button (xevent, cwevent);
1453 if (cwevent->button == Button1 || cwevent->button == Button2) {
1454 buttonypos = xevent_xbutton_y;
1455 y = w->firstline;
1456 w->options = whichscrbutton =
1457 (*look->which_scrollbar_button) (cwevent->x, cwevent->y, w);
1458 cwevent->ident = w->ident;
1459 w->search_start = w->firstline;
1460 w->search_len = w->numlines;
1461 }
1462 break;
1463 case ButtonRelease:
1464 resolve_button (xevent, cwevent);
1465 w->options = 32 + whichscrbutton;
1466 if (whichscrbutton == 3) {
1467 y +=
1468 (double) (xevent_xbutton_y - buttonypos) * (double) 65535.0 / (length -
1469 10 * width / 3 - 10);
1470 w->firstline = y;
1471 buttonypos = xevent_xbutton_y;
1472 }
1473 break;
1474 case MotionNotify:
1475 resolve_button (xevent, cwevent);
1476 if (cwevent->state & (Button1Mask | Button2Mask)) {
1477 w->options = whichscrbutton;
1478 if (whichscrbutton == 3) {
1479 y +=
1480 (double) (xevent_xbutton_y - buttonypos) * (double) 65535.0 / (length -
1481 10 * width / 3 -
1482 10);
1483 w->firstline = y;
1484 buttonypos = xevent_xbutton_y;
1485 }
1486 } else
1487 w->options =
1488 32 + (*look->which_scrollbar_button) (xevent->xmotion.x, xevent->xmotion.y, w);
1489 break;
1490 default:
1491 return 0;
1492 }
1493
1494 if (w->firstline > 65535)
1495 w->firstline = 65535;
1496 if (cwevent->state & (Button1Mask | Button2Mask) || cwevent->type == ButtonPress
1497 || cwevent->type == ButtonRelease)
1498 if (w->scroll_bar_link && w->vert_scrollbar)
1499 (*w->scroll_bar_link) (w, w->vert_scrollbar, xevent, cwevent, whichscrbutton);
1500
1501 if (xevent->type != Expose || !xevent->xexpose.count)
1502 (*look->render_scrollbar) (w);
1503
1504 return 0;
1505 }
1506
look_cool_init_scrollbar_icons(CWidget * w)1507 static void look_cool_init_scrollbar_icons (CWidget * w)
1508 {
1509 return;
1510 }
1511
look_cool_get_scrollbar_size(int type)1512 static int look_cool_get_scrollbar_size (int type)
1513 {
1514 if (type == C_HORISCROLL_WIDGET)
1515 return 13;
1516 return 20;
1517 }
1518
1519 extern char *init_fg_color_red;
1520 extern char *init_fg_color_green;
1521 extern char *init_fg_color_blue;
1522
look_cool_get_button_color(XColor * color,int i)1523 static void look_cool_get_button_color (XColor * color, int i)
1524 {
1525 double r, g, b, min_wc;
1526
1527 r = 1 / atof (init_fg_color_red);
1528 g = 1 / atof (init_fg_color_green);
1529 b = 1 / atof (init_fg_color_blue);
1530
1531 min_wc = min (r, min (g, b));
1532
1533 color->red = (float) 65535 *my_pow ((float) i / 20, r) * my_pow (0.75, -min_wc);
1534 color->green = (float) 65535 *my_pow ((float) i / 20, g) * my_pow (0.75, -min_wc);
1535 color->blue = (float) 65535 *my_pow ((float) i / 20, b) * my_pow (0.75, -min_wc);
1536 color->flags = DoRed | DoBlue | DoGreen;
1537 }
1538
look_cool_get_default_interwidget_spacing(void)1539 static int look_cool_get_default_interwidget_spacing (void)
1540 {
1541 return 4;
1542 }
1543
look_cool_window_handler(CWidget * w,XEvent * xevent,CEvent * cwevent)1544 int look_cool_window_handler (CWidget * w, XEvent * xevent, CEvent * cwevent)
1545 {
1546 static Window window_is_resizing = 0;
1547 static int windowx, windowy;
1548 static int wx = 0, wy = 0;
1549 static int wwidth = 0, wheight = 0;
1550 static int allowwindowmove = 0;
1551 static int allowwindowresize = 0;
1552
1553 switch (xevent->type) {
1554 case ClientMessage:
1555 if (!w->disabled)
1556 cwevent->ident = w->ident;
1557 break;
1558 case Expose:
1559 if (!xevent->xexpose.count)
1560 render_window (w);
1561 break;
1562 case ButtonRelease:
1563 strcpy (cwevent->ident, w->ident);
1564 window_is_resizing = 0;
1565 resolve_button (xevent, cwevent);
1566 allowwindowmove = 0;
1567 allowwindowresize = 0;
1568 break;
1569 case ButtonPress:
1570 strcpy (cwevent->ident, w->ident);
1571 resolve_button (xevent, cwevent);
1572 if (cwevent->double_click == 1) {
1573 CWidget *c = CChildFocus (w);
1574 if (c)
1575 CFocus (c);
1576 }
1577 if (cwevent->button == Button1 && !(w->position & WINDOW_ALWAYS_LOWERED)) {
1578 XRaiseWindow (CDisplay, w->winid);
1579 CRaiseWindows ();
1580 } else if (cwevent->button == Button2 && !(w->position & WINDOW_ALWAYS_RAISED)) {
1581 XLowerWindow (CDisplay, w->winid);
1582 CLowerWindows ();
1583 }
1584 windowx = xevent->xbutton.x_root - w->x;
1585 windowy = xevent->xbutton.y_root - w->y;
1586 wx = xevent->xbutton.x;
1587 wy = xevent->xbutton.y;
1588 wwidth = w->width;
1589 wheight = w->height;
1590 if (wx + wy > w->width + w->height - 33 && w->position & WINDOW_RESIZABLE)
1591 allowwindowresize = 1;
1592 else
1593 allowwindowmove = 1;
1594 break;
1595 case MotionNotify:
1596 resolve_button (xevent, cwevent);
1597 if (!(w->position & WINDOW_UNMOVEABLE) && allowwindowmove
1598 && (cwevent->state & (Button1Mask | Button2Mask))) {
1599 w->x = xevent->xmotion.x_root - windowx;
1600 w->y = xevent->xmotion.y_root - windowy;
1601 if (w->x + xevent->xmotion.x < 2)
1602 w->x = -wx + 2;
1603 if (w->y + xevent->xmotion.y < 2)
1604 w->y = -wy + 2;
1605 XMoveWindow (CDisplay, w->winid, w->x, w->y);
1606 }
1607 if ((w->position & WINDOW_RESIZABLE) && allowwindowresize
1608 && (cwevent->state & (Button1Mask | Button2Mask))) {
1609 int wi, he;
1610 window_is_resizing = w->winid;
1611 wi = wwidth + xevent->xmotion.x_root - windowx - w->x;
1612 he = wheight + xevent->xmotion.y_root - windowy - w->y;
1613
1614 /* this is actually for the edit windows, and needs to be generalized */
1615 if (wi < w->mark1)
1616 wi = w->mark1;
1617 if (he < w->mark2)
1618 he = w->mark2;
1619
1620 wi -= w->firstcolumn;
1621 wi -= wi % w->textlength;
1622 wi += w->firstcolumn;
1623 he -= w->firstline;
1624 he -= he % w->numlines;
1625 he += w->firstline;
1626 w->position &= ~WINDOW_MAXIMISED;
1627 CSetSize (w, wi, he);
1628 }
1629 break;
1630 }
1631 return 0;
1632 }
1633
1634 extern Pixmap Cswitchon;
1635 extern Pixmap Cswitchoff;
1636
look_cool_render_switch(CWidget * wdt)1637 static void look_cool_render_switch (CWidget * wdt)
1638 {
1639 int w = wdt->width, h = wdt->height;
1640 Window win = wdt->winid;
1641 int x = 0, y = 0;
1642
1643 CSetColor (COLOR_FLAT);
1644 CRectangle (win, x+5, y+5, w - 10, h - 10);
1645
1646 CSetColor (wdt->fg);
1647 CSetBackgroundColor (wdt->bg);
1648 if (wdt->options & SWITCH_PICTURE_TYPE) {
1649 if (wdt->keypressed)
1650 XCopyPlane (CDisplay, Cswitchon, win, CGC, 0, 0,
1651 w, h, x, y, 1);
1652 else
1653 XCopyPlane (CDisplay, Cswitchoff, win, CGC, 0, 0,
1654 w, h, x, y, 1);
1655 } else {
1656 if (wdt->keypressed)
1657 {
1658 render_bevel (win, x + 3, y + 3, x + w - 4, y + h - 4, 2, 1);
1659 }else
1660 render_bevel (win, x + 3, y + 3, x + w - 4, y + h - 4, 2, 0);
1661 }
1662 if (wdt->options & (BUTTON_HIGHLIGHT | BUTTON_PRESSED))
1663 render_rounded_bevel (win, x, y, x + w - 1, y + h - 1, 7, 1, 1);
1664 else
1665 render_rounded_bevel (win, x, y, x + w - 1, y + h - 1, 7, 1, 0);
1666 }
1667
1668 extern unsigned long edit_normal_background_color;
1669
look_cool_edit_render_tidbits(CWidget * wdt)1670 static void look_cool_edit_render_tidbits (CWidget * wdt)
1671 {
1672 int isfocussed;
1673 int w = wdt->width, h = wdt->height;
1674 Window win;
1675
1676 win = wdt->winid;
1677 isfocussed = (win == CGetFocus ());
1678 CSetColor (COLOR_FLAT);
1679 if (isfocussed) {
1680 render_bevel (win, 0, 0, w - 1, h - 1, 3, 1); /*most outer border bevel */
1681 } else {
1682 render_bevel (win, 2, 2, w - 3, h - 3, 1, 1); /*border bevel */
1683 render_bevel (win, 0, 0, w - 1, h - 1, 2, 0); /*most outer border bevel */
1684 }
1685 CSetColor (edit_normal_background_color);
1686 CLine (CWindowOf (wdt), 3, 3, 3, CHeightOf (wdt) - 4);
1687 }
1688
look_cool_draw_exclam_cancel_button(char * ident,Window win,int x,int y)1689 CWidget *look_cool_draw_exclam_cancel_button (char *ident, Window win, int x, int y)
1690 {
1691 CWidget *wdt;
1692 wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_EXCLAMATION);
1693 return wdt;
1694 }
1695
look_cool_draw_tick_cancel_button(char * ident,Window win,int x,int y)1696 CWidget *look_cool_draw_tick_cancel_button (char *ident, Window win, int x, int y)
1697 {
1698 CWidget *wdt;
1699 wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_TICK);
1700 return wdt;
1701 }
1702
look_cool_draw_cross_cancel_button(char * ident,Window win,int x,int y)1703 CWidget *look_cool_draw_cross_cancel_button (char *ident, Window win, int x, int y)
1704 {
1705 CWidget *wdt;
1706 wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_CROSS);
1707 return wdt;
1708 }
1709
look_cool_render_fielded_textbox_tidbits(CWidget * w,int isfocussed)1710 static void look_cool_render_fielded_textbox_tidbits (CWidget * w, int isfocussed)
1711 {
1712 if (isfocussed) {
1713 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 3, 1); /*most outer border bevel */
1714 } else {
1715 render_bevel (w->winid, 2, 2, w->width - 3, w->height - 3, 1, 1); /*border bevel */
1716 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 2, 0); /*most outer border bevel */
1717 }
1718 CSetColor (edit_normal_background_color);
1719 CLine (w->winid, 3, 3, 3, w->height - 4);
1720 }
1721
look_cool_render_textbox_tidbits(CWidget * w,int isfocussed)1722 static void look_cool_render_textbox_tidbits (CWidget * w, int isfocussed)
1723 {
1724 if (isfocussed) {
1725 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 3, 1); /*most outer border bevel */
1726 } else {
1727 render_bevel (w->winid, 2, 2, w->width - 3, w->height - 3, 1, 1); /*border bevel */
1728 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 2, 0); /*most outer border bevel */
1729 }
1730 }
1731
look_cool_render_passwordinput_tidbits(CWidget * wdt,int isfocussed)1732 static void look_cool_render_passwordinput_tidbits (CWidget * wdt, int isfocussed)
1733 {
1734 int w = wdt->width, h = wdt->height;
1735 Window win = wdt->winid;
1736 if (isfocussed) {
1737 render_bevel (win, 0, 0, w - 1, h - 1, 3, 1);
1738 } else {
1739 render_bevel (win, 2, 2, w - 3, h - 3, 1, 1);
1740 render_bevel (win, 0, 0, w - 1, h - 1, 2, 0);
1741 }
1742 }
1743
look_cool_render_textinput_tidbits(CWidget * wdt,int isfocussed)1744 static void look_cool_render_textinput_tidbits (CWidget * wdt, int isfocussed)
1745 {
1746 int w = wdt->width, h = wdt->height;
1747 Window win = wdt->winid;
1748 if (isfocussed) {
1749 render_bevel (win, 0, 0, w - h - 1, h - 1, 3, 1); /*most outer border bevel */
1750 } else {
1751 render_bevel (win, 2, 2, w - h - 3, h - 3, 1, 1); /*border bevel */
1752 render_bevel (win, 0, 0, w - h - 1, h - 1, 2, 0); /*most outer border bevel */
1753 }
1754 if (wdt->options & BUTTON_PRESSED) {
1755 CRectangle (win, w - h + 2, 2, h - 4, h - 4);
1756 render_bevel (win, w - h, 0, w - 1, h - 1, 2, 3);
1757 } else if (wdt->options & BUTTON_HIGHLIGHT) {
1758 CRectangle (win, w - h + 1, 1, h - 2, h - 2);
1759 render_bevel (win, w - h, 0, w - 1, h - 1, 1, 2);
1760 } else {
1761 CRectangle (win, w - h + 2, 2, h - 4, h - 4);
1762 render_bevel (win, w - h, 0, w - 1, h - 1, 2, 2);
1763 }
1764 }
1765
1766 extern struct focus_win focus_border;
1767
render_focus_border_n(Window win,int i)1768 static void render_focus_border_n (Window win, int i)
1769 {
1770 int j;
1771 j = (i > 3) + 1;
1772 if (win == focus_border.top) {
1773 render_bevel (win, 0, 0, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, focus_border.height + 2 * WIDGET_FOCUS_RING - 1, j, 0);
1774 render_bevel (win, i, i, focus_border.width + 2 * WIDGET_FOCUS_RING - 1 - i, focus_border.height + 2 * WIDGET_FOCUS_RING - 1 - i, 2, 1);
1775 } else if (win == focus_border.bottom) {
1776 render_bevel (win, 0, 0 - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, WIDGET_FOCUS_RING - 1, j, 0);
1777 render_bevel (win, i, i - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1 - i, WIDGET_FOCUS_RING - 1 - i, 2, 1);
1778 } else if (win == focus_border.left) {
1779 render_bevel (win, 0, 0 - WIDGET_FOCUS_RING, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, focus_border.height + WIDGET_FOCUS_RING - 1, j, 0);
1780 render_bevel (win, i, i - WIDGET_FOCUS_RING, focus_border.width + 2 * WIDGET_FOCUS_RING - 1 - i, focus_border.height + WIDGET_FOCUS_RING - 1 - i, 2, 1);
1781 } else if (win == focus_border.right) {
1782 render_bevel (win, 0 + WIDGET_FOCUS_RING - focus_border.width, 0 - WIDGET_FOCUS_RING, WIDGET_FOCUS_RING - 1, focus_border.height + WIDGET_FOCUS_RING - 1, j, 0);
1783 render_bevel (win, i + WIDGET_FOCUS_RING - focus_border.width, i - WIDGET_FOCUS_RING, WIDGET_FOCUS_RING - 1 - i, focus_border.height + WIDGET_FOCUS_RING - 1 - i, 2, 1);
1784 }
1785 }
1786
look_cool_render_focus_border(Window win)1787 static void look_cool_render_focus_border (Window win)
1788 {
1789 render_focus_border_n (win, focus_border.border);
1790 }
1791
look_cool_get_extra_window_spacing(void)1792 static int look_cool_get_extra_window_spacing (void)
1793 {
1794 return 2;
1795 }
1796
look_cool_get_focus_ring_size(void)1797 static int look_cool_get_focus_ring_size (void)
1798 {
1799 return 4;
1800 }
1801
look_cool_get_button_flat_color(void)1802 static unsigned long look_cool_get_button_flat_color (void)
1803 {
1804 return color_widget(9);
1805 }
1806
look_cool_get_window_resize_bar_thickness(void)1807 static int look_cool_get_window_resize_bar_thickness (void)
1808 {
1809 return 0;
1810 }
1811
look_cool_get_switch_size(void)1812 static int look_cool_get_switch_size (void)
1813 {
1814 return FONT_PIX_PER_LINE + TEXT_RELIEF * 2 + 2 + 4;
1815 }
1816
look_cool_get_fielded_textbox_hscrollbar_width(void)1817 static int look_cool_get_fielded_textbox_hscrollbar_width (void)
1818 {
1819 return 12;
1820 }
1821
1822 struct look look_cool = {
1823 look_cool_get_default_interwidget_spacing,
1824 look_cool_menu_draw,
1825 look_cool_get_menu_item_extents,
1826 look_cool_render_menu_button,
1827 look_cool_render_button,
1828 look_cool_render_bar,
1829 look_cool_render_raised_bevel,
1830 look_cool_render_sunken_bevel,
1831 look_cool_draw_hotkey_understroke,
1832 look_cool_get_default_widget_font,
1833 look_cool_render_text,
1834 look_cool_render_window,
1835 look_cool_render_scrollbar,
1836 look_cool_get_scrollbar_size,
1837 look_cool_init_scrollbar_icons,
1838 look_cool_which_scrollbar_button,
1839 look_cool_scrollbar_handler,
1840 look_cool_get_button_color,
1841 look_cool_get_extra_window_spacing,
1842 look_cool_window_handler,
1843 look_cool_get_focus_ring_size,
1844 look_cool_get_button_flat_color,
1845 look_cool_get_window_resize_bar_thickness,
1846 look_cool_render_switch,
1847 look_cool_get_switch_size,
1848 look_cool_draw_browser,
1849 look_cool_get_file_or_dir,
1850 look_cool_draw_file_list,
1851 look_cool_redraw_file_list,
1852 look_cool_get_file_list_line,
1853 look_cool_search_replace_dialog,
1854 look_cool_edit_render_tidbits,
1855 look_cool_draw_exclam_cancel_button,
1856 look_cool_draw_tick_cancel_button,
1857 look_cool_draw_cross_cancel_button,
1858 look_cool_draw_tick_cancel_button,
1859 look_cool_render_fielded_textbox_tidbits,
1860 look_cool_render_textbox_tidbits,
1861 look_cool_get_fielded_textbox_hscrollbar_width,
1862 look_cool_render_textinput_tidbits,
1863 look_cool_render_passwordinput_tidbits,
1864 look_cool_render_focus_border,
1865 };
1866
1867