1 /* look-cool.c - look 'n feel type: NeXT
2 Copyright (C) 1996-2002 Paul Sheer
3 Copyright (C) 1999-2002 Sasha Vasko
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., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307, USA.
19 */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <my_string.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26
27 #include <X11/Intrinsic.h>
28 #include "lkeysym.h"
29
30 #include "stringtools.h"
31 #include "app_glob.c"
32 #include "coolwidget.h"
33 #include "coollocal.h"
34
35 #include "mad.h"
36
37 #ifdef NEXT_LOOK
38
39 extern struct look *look;
40
41 /* {{{ search replace dialog */
42
43 extern int replace_scanf;
44 extern int replace_regexp;
45 extern int replace_all;
46 extern int replace_prompt;
47 extern int replace_whole;
48 extern int replace_case;
49 extern int replace_backwards;
50 extern int search_create_bookmark;
51
look_next_search_replace_dialog(Window parent,int x,int y,char ** search_text,char ** replace_text,char ** arg_order,const char * heading,int option)52 static void look_next_search_replace_dialog (Window parent, int x, int y, char **search_text, char **replace_text, char **arg_order, const char *heading, int option)
53 {
54 Window win;
55 XEvent xev;
56 CEvent cev;
57 CState s;
58 int xh, yh, h, xb, ys, yc, yb, yr;
59 CWidget *m;
60 int text_input_width ;
61
62 CBackupState (&s);
63 CDisable ("*");
64
65 win = CDrawHeadedDialog ("replace", parent, x, y, heading);
66 CGetHintPos (&xh, &h);
67 xh += WINDOW_EXTRA_SPACING ;
68
69 /* NLS hotkey ? */
70 CIdent ("replace")->position = WINDOW_ALWAYS_RAISED;
71 /* An input line comes after the ':' */
72 (CDrawText ("replace.t1", win, xh, h, _(" Enter search text : ")))->hotkey = 'E';
73
74 CGetHintPos (0, &yh);
75 (m = CDrawTextInput ("replace.sinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *search_text))->hotkey = 'E';
76
77 if (replace_text) {
78 CGetHintPos (0, &yh);
79 (CDrawText ("replace.t2", win, xh, yh, _(" Enter replace text : ")))->hotkey = 'n';
80 CGetHintPos (0, &yh);
81 (CDrawTextInput ("replace.rinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *replace_text))->hotkey = 'n';
82 CSetToolHint ("replace.t2", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
83 CSetToolHint ("replace.rinp", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
84 CGetHintPos (0, &yh);
85 (CDrawText ("replace.t3", win, xh, yh, _(" Enter argument (or substring) order : ")))->hotkey = 'o';
86 CGetHintPos (0, &yh);
87 (CDrawTextInput ("replace.ainp", win, xh, yh, 10, AUTO_HEIGHT, 256, *arg_order))->hotkey = 'o';
88 /* Tool hint */
89 CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
90 CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
91 }
92 CGetHintPos (0, &yh);
93 ys = yh;
94 /* The following are check boxes */
95 CDrawSwitch ("replace.ww", win, xh, yh, replace_whole, _(" Whole words only "), 0);
96 CGetHintPos (0, &yh);
97 CDrawSwitch ("replace.case", win, xh, yh, replace_case, _(" Case sensitive "), 0);
98 yc = yh;
99 CGetHintPos (0, &yh);
100 CDrawSwitch ("replace.reg", win, xh, yh, replace_regexp, _(" Regular expression "), 1);
101 CSetToolHint ("replace.reg", _("See the regex man page for how\nto compose a regular expression"));
102 CSetToolHint ("replace.reg.label", _("See the regex man page for how\nto compose a regular expression"));
103 yb = yh;
104 CGetHintPos (0, &yh);
105 CGetHintPos (&xb, 0);
106 xb += WINDOW_EXTRA_SPACING ;
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 {
154 int btn_width, x, y ;
155 CGetHintPos (&x, &y);
156
157 y += WINDOW_EXTRA_SPACING * 2 ;
158 x += WINDOW_EXTRA_SPACING * 2 ;
159 CTextSize (&btn_width, 0, " Cancel ");
160 btn_width += 4 + BUTTON_RELIEF * 2;
161 x -= (btn_width + WINDOW_EXTRA_SPACING) * 2 + WINDOW_EXTRA_SPACING;
162
163 CDrawButton ("replace.ok", win, x+btn_width + WINDOW_EXTRA_SPACING * 2, y, AUTO_WIDTH, AUTO_HEIGHT, " Ok ");
164 CDrawButton ("replace.cancel", win, x, y, AUTO_WIDTH, AUTO_HEIGHT, " Cancel ");
165 CGetHintPos (0, &y);
166 x += (btn_width + WINDOW_EXTRA_SPACING) * 2 + WINDOW_EXTRA_SPACING;
167 reset_hint_pos (x, y + WINDOW_EXTRA_SPACING*2);
168 }
169 /* Tool hint */
170 CSetToolHint ("replace.ok", _("Begin search, Enter"));
171 CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
172 CSetSizeHintPos ("replace");
173 CMapDialog ("replace");
174
175 m = CIdent ("replace");
176 text_input_width = m->width - WIDGET_SPACING * 3 - 4 - WINDOW_EXTRA_SPACING*2 ;
177 CSetWidgetSize ("replace.sinp", text_input_width, (CIdent ("replace.sinp"))->height);
178 if (replace_text) {
179 CSetWidgetSize ("replace.rinp", text_input_width, (CIdent ("replace.rinp"))->height);
180 CSetWidgetSize ("replace.ainp", text_input_width, (CIdent ("replace.ainp"))->height);
181 }
182 CFocus (CIdent ("replace.sinp"));
183
184 for (;;) {
185 CNextEvent (&xev, &cev);
186 if (!CIdent ("replace")) {
187 *search_text = 0;
188 break;
189 }
190 if (!strcmp (cev.ident, "replace.cancel") || cev.command == CK_Cancel) {
191 *search_text = 0;
192 break;
193 }
194 if (!strcmp (cev.ident, "replace.reg") || !strcmp (cev.ident, "replace.scanf")) {
195 if (CIdent ("replace.reg")->keypressed || CIdent ("replace.scanf")->keypressed) {
196 if (!(CIdent ("replace.case")->keypressed)) {
197 CIdent ("replace.case")->keypressed = 1;
198 CExpose ("replace.case");
199 }
200 }
201 }
202 if (!strcmp (cev.ident, "replace.ok") || cev.command == CK_Enter) {
203 if (replace_text) {
204 replace_all = CIdent ("replace.all")->keypressed;
205 replace_prompt = CIdent ("replace.pr")->keypressed;
206 *replace_text = (char *) strdup (CIdent ("replace.rinp")->text);
207 *arg_order = (char *) strdup (CIdent ("replace.ainp")->text);
208 }
209 *search_text = (char *) strdup (CIdent ("replace.sinp")->text);
210 replace_whole = CIdent ("replace.ww")->keypressed;
211 replace_case = CIdent ("replace.case")->keypressed;
212 replace_scanf = CIdent ("replace.scanf")->keypressed;
213 replace_regexp = CIdent ("replace.reg")->keypressed;
214
215 if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
216 replace_backwards = CIdent ("replace.bkwd")->keypressed;
217 } else {
218 replace_backwards = 0;
219 }
220
221 if (option & SEARCH_DIALOG_OPTION_BOOKMARK) {
222 search_create_bookmark = CIdent ("replace.bkmk")->keypressed;
223 } else {
224 search_create_bookmark = 0;
225 }
226
227 break;
228 }
229 }
230 CDestroyWidget ("replace");
231 CRestoreState (&s);
232 }
233
234 /* }}} search replace dialog */
235
236
237 /* {{{ file list stuff */
238
239 #if 0
240 static char *dname (struct dirent *directentry);
241 #endif
242
243 #ifdef HAVE_STRFTIME
244 /* We want our own dates for NLS */
245 #undef HAVE_STRFTIME
246 #endif
247
248 #undef gettext_noop
249 #define gettext_noop(x) x
250
251 void get_file_time (char *timestr, time_t file_time, int l);
252
253 #if 0
254 static char **get_filelist_line (void *data, int line_number, int *num_fields, int *tagged)
255 {
256 struct file_entry *directentry;
257 static char *fields[10], size[24], mode[12], timestr[32];
258 static char name[520], *n;
259 mode_t m;
260
261 *num_fields = 4; /* name, size, date, mode only (for the mean time) */
262
263 directentry = (struct file_entry *) data;
264 if (directentry[line_number].options & FILELIST_LAST_ENTRY)
265 return 0;
266
267 n = name;
268 strcpy (name, directentry[line_number].name);
269 fields[0] = name;
270 sprintf (size, "\t%u", (unsigned int) directentry[line_number].stat.st_size);
271 fields[1] = size;
272
273 get_file_time (timestr, directentry[line_number].stat.st_mtime, 0);
274 fields[2] = timestr;
275
276 memset (mode, ' ', 11);
277 mode[11] = 0;
278 mode[0] = '-';
279 m = directentry[line_number].stat.st_mode;
280 switch ((int) m & S_IFMT) {
281 case S_IFLNK:
282 mode[0] = 'l';
283 break;
284 case S_IFDIR:
285 mode[0] = 'd';
286 break;
287 case S_IFCHR:
288 mode[0] = 'c';
289 break;
290 case S_IFBLK:
291 mode[0] = 'b';
292 break;
293 case S_IFIFO:
294 mode[0] = 'f';
295 break;
296 case S_IFSOCK:
297 mode[0] = 's';
298 break;
299 }
300
301 mode[1] = m & S_IRUSR ? 'r' : '-';
302 mode[2] = m & S_IWUSR ? 'w' : '-';
303 mode[3] = m & S_IXUSR ? 'x' : '-';
304
305 mode[4] = m & S_IRGRP ? 'r' : '-';
306 mode[5] = m & S_IWGRP ? 'w' : '-';
307 mode[6] = m & S_IXGRP ? 'x' : '-';
308
309 mode[7] = m & S_IROTH ? 'r' : '-';
310 mode[8] = m & S_IWOTH ? 'w' : '-';
311 mode[9] = m & S_IXOTH ? 'x' : '-';
312
313 if (S_ISLNK (m)) {
314 int l, i;
315 char *p;
316 p = directentry[line_number].name;
317 l = strlen (n);
318 for (i = 0; i < l; i++) {
319 *n++ = '\b';
320 *n++ = *p++;
321 }
322 *n++ = '\0';
323 } else if (m & (S_IXUSR | S_IXGRP | S_IXOTH)) {
324 int l, i;
325 char *p;
326 p = directentry[line_number].name;
327 l = strlen (n);
328 for (i = 0; i < l; i++) {
329 *n++ = '\r';
330 *n++ = *p++;
331 }
332 *n++ = '\0';
333 }
334 fields[3] = mode;
335 fields[*num_fields] = 0;
336 if (directentry[line_number].options & FILELIST_TAGGED_ENTRY)
337 *tagged = 1;
338 return fields;
339 }
340 #endif
341
get_filelist_line_short(void * data,int line_number,char buffer[512])342 static char *get_filelist_line_short (void *data, int line_number, char buffer[512])
343 {
344 struct file_entry *directentry;
345 static char ctimestr[32], mtimestr[32];
346 mode_t m;
347 char *ptr;
348 unsigned long size_bytes;
349
350 directentry = (struct file_entry *) data;
351 if (directentry[line_number].options & FILELIST_LAST_ENTRY)
352 return 0;
353
354 buffer[0] = 6;
355 strncpy (&(buffer[1]), directentry[line_number].name, 256);
356 ptr = &(buffer[strlen (buffer)]);
357
358 sprintf (ptr, "%c\nMode: %c", 27, 9);
359 ptr += strlen (ptr);
360
361 m = directentry[line_number].stat.st_mode;
362 switch ((int) m & S_IFMT) {
363 case S_IFLNK:
364 *ptr = 'l';
365 break;
366 case S_IFDIR:
367 *ptr = 'd';
368 break;
369 case S_IFCHR:
370 *ptr = 'c';
371 break;
372 case S_IFBLK:
373 *ptr = 'b';
374 break;
375 case S_IFIFO:
376 *ptr = 'f';
377 break;
378 case S_IFSOCK:
379 *ptr = 's';
380 break;
381 default:
382 *ptr = '-';
383 }
384 ptr++;
385 *(ptr++) = m & S_IRUSR ? 'r' : '-';
386 *(ptr++) = m & S_IWUSR ? 'w' : '-';
387 *(ptr++) = m & S_IXUSR ? 'x' : '-';
388
389 *(ptr++) = m & S_IRGRP ? 'r' : '-';
390 *(ptr++) = m & S_IWGRP ? 'w' : '-';
391 *(ptr++) = m & S_IXGRP ? 'x' : '-';
392
393 *(ptr++) = m & S_IROTH ? 'r' : '-';
394 *(ptr++) = m & S_IWOTH ? 'w' : '-';
395 *(ptr++) = m & S_IXOTH ? 'x' : '-';
396
397
398 size_bytes = directentry[line_number].stat.st_size;
399 sprintf (ptr, "%c ; Size: [%c%9lu%c] bytes or [%c%6lu%c] KBytes", 27, 7, size_bytes, 27, 7, size_bytes >> 10, 27);
400 ptr += strlen (ptr);
401
402 get_file_time (ctimestr, directentry[line_number].stat.st_ctime, 0);
403 get_file_time (mtimestr, directentry[line_number].stat.st_mtime, 0);
404
405 sprintf (ptr, "\nCreated on: %c%s%c ; Modified on: %c%s%c", 1, ctimestr, 27, 1, mtimestr, 27);
406
407 return buffer;
408 }
409
is_directory(struct file_entry * directentry,int line_number)410 static Bool is_directory (struct file_entry * directentry, int line_number)
411 {
412 if (directentry[line_number].options & FILELIST_LAST_ENTRY)
413 return False;
414 switch ((int) (directentry[line_number].stat.st_mode) & S_IFMT) {
415 case S_IFLNK:
416 /* fixme : add check if it is linked to dir or file */
417 return True;
418 case S_IFDIR:
419 return True;
420 }
421 return False;
422 }
423
424 typedef struct FilelistCache {
425 Pixmap cache;
426 unsigned int width, height;
427 unsigned int firstline, hilited;
428 int current;
429 unsigned int rowheight;
430 unsigned long options;
431 } FilelistCache;
432
free_filelist_cache(void * vcache)433 static void free_filelist_cache (void *vcache)
434 {
435 if (vcache) {
436 FilelistCache *cache = (FilelistCache *) vcache;
437 if (cache->cache) {
438 XFreePixmap (CDisplay, cache->cache);
439 cache->cache = None;
440 }
441 free (vcache);
442 }
443 }
444
445 #define NEXT_ARROW_SIZE 8
446 #define NEXT_ARROW_FIELD (NEXT_ARROW_SIZE*2)
447
restrict_text_area(FilelistCache * cache)448 static void restrict_text_area (FilelistCache * cache)
449 {
450 XRectangle clip_rec;
451 clip_rec.x = 1;
452 clip_rec.y = 1;
453 clip_rec.width = cache->width - NEXT_ARROW_FIELD;
454 clip_rec.height = cache->height - 2;
455 XSetClipRectangles (CDisplay, CGC, 0, 0, &clip_rec, 1, YXSorted);
456 }
457
push_filelist_line(FilelistCache * cache,Bool pushed)458 static void push_filelist_line (FilelistCache * cache, Bool pushed)
459 {
460 int y1, y2;
461 if (cache->current < 0)
462 return;
463 y1 = (cache->current - cache->firstline) * cache->rowheight;
464 y2 = y1 + cache->rowheight;
465
466 if (y1 < cache->height && y2 > 0) {
467 if (pushed)
468 CSetColor (COLOR_BLACK);
469 else
470 CSetColor ((cache->hilited == cache->current) ? color_widget (15) : COLOR_FLAT);
471
472 CLine (cache->cache, 0, y2, 0, y1);
473 CLine (cache->cache, 1, y1, cache->width - 2, y1);
474
475 if (pushed)
476 CSetColor ((cache->hilited == cache->current) ? COLOR_FLAT : color_widget (15));
477
478 CLine (cache->cache, 0, y2, cache->width - 2, y2);
479 CLine (cache->cache, cache->width - 2, y2, cache->width - 2, y1);
480 }
481 }
482
hilite_filelist_line(FilelistCache * cache,int color,struct file_entry * directentry)483 static void hilite_filelist_line (FilelistCache * cache, int color, struct file_entry *directentry)
484 {
485 int y1, y2, x2;
486 y1 = (cache->hilited - cache->firstline) * cache->rowheight;
487 y2 = y1 + (cache->rowheight / 2 - 4);
488 x2 = cache->width - NEXT_ARROW_FIELD + NEXT_ARROW_SIZE / 2;
489
490 if (y1 >= 0 && y1 < cache->height - FONT_OVERHEAD) {
491 CSetColor (color);
492 CRectangle (cache->cache, 0, y1, cache->width - 1, cache->rowheight - 1);
493 CSetColor (COLOR_BLACK);
494 if (!(directentry[cache->hilited].options & FILELIST_LAST_ENTRY) &&
495 directentry[cache->hilited].name != NULL) {
496 restrict_text_area (cache);
497 CSetBackgroundColor (color);
498 CImageString (cache->cache, FONT_OFFSET_X + 1, FONT_OFFSET_Y + y1,
499 directentry[cache->hilited].name);
500 XSetClipMask (CDisplay, CGC, None);
501 if (is_directory (directentry, cache->hilited)) {
502 CSetColor (COLOR_BLACK);
503 CLine (cache->cache, x2, y2, x2 + 7, y2 + 4);
504 CLine (cache->cache, x2, y2, x2, y2 + 8);
505 CSetColor (COLOR_FLAT);
506 CLine (cache->cache, x2, y2 + 8, x2 + 7, y2 + 4);
507 }
508 }
509 }
510 }
511
scroll_cache(FilelistCache * cache,unsigned int new_first,int * start,int * end)512 static void scroll_cache (FilelistCache * cache, unsigned int new_first, int *start, int *end)
513 {
514 int good_start, good_end, scroll_to;
515
516 if (cache->firstline > new_first) { /* scrolling up */
517 good_start = 0;
518 scroll_to = (cache->firstline - new_first) * cache->rowheight;
519 good_end = cache->height - scroll_to;
520 } else {
521 good_start = (new_first - cache->firstline) * cache->rowheight;
522 good_end = cache->height;
523 scroll_to = 0;
524 }
525 if (good_start < good_end) {
526 XCopyArea (CDisplay, cache->cache, cache->cache, CGC, 0, good_start, cache->width, good_end, 0, scroll_to);
527 if (cache->firstline > new_first) { /* scrolling up */
528 *start = 0;
529 *end = scroll_to;
530 } else {
531 *start = (cache->height - good_start);
532 *end = cache->height;
533 }
534 } else {
535 *start = 0;
536 *end = cache->height;
537 }
538 if (*start < *end) {
539 CSetColor (COLOR_FLAT);
540 CRectangle (cache->cache, 0, *start, cache->width, *end);
541 }
542 *start /= cache->rowheight;
543 *end /= cache->rowheight;
544 }
545
check_filelist_cache(CWidget * wdt,unsigned int w,unsigned int h,FilelistCache * cache)546 static void check_filelist_cache (CWidget * wdt, unsigned int w, unsigned int h, FilelistCache * cache)
547 {
548 struct file_entry *directentry = (struct file_entry *) wdt->hook;
549 int y, x, start_y;
550 int i, start = 0, end = 0;
551
552 if (cache->cache) {
553 if (cache->width == w && cache->height == h) {
554 if (cache->firstline == wdt->firstline &&
555 cache->hilited == wdt->cursor &&
556 cache->options == wdt->options)
557 return;
558 } else {
559 XFreePixmap (CDisplay, cache->cache);
560 cache->cache = None;
561 }
562 }
563 if (cache->cache == None) {
564 cache->cache = XCreatePixmap (CDisplay, wdt->winid, w, h, CDepth);
565 cache->width = w;
566 cache->height = h;
567 CTextSize (NULL, (int *) &(cache->rowheight), "Ty~g$V|&^.,/_'I}[@");
568 if (cache->rowheight == 0)
569 cache->rowheight = 1;
570 cache->rowheight += FONT_OVERHEAD;
571 CSetColor (COLOR_FLAT);
572 CRectangle (cache->cache, 0, 0, w, h);
573 end = h / cache->rowheight;
574 } else {
575 push_filelist_line (cache, False);
576 if (cache->hilited != wdt->cursor)
577 hilite_filelist_line (cache, COLOR_FLAT, directentry);
578
579 if (cache->firstline != wdt->firstline)
580 scroll_cache (cache, wdt->firstline, &start, &end);
581 }
582
583 cache->firstline = wdt->firstline;
584 cache->hilited = wdt->cursor;
585 hilite_filelist_line (cache, (wdt->options & BUTTON_HIGHLIGHT) ? COLOR_WHITE : color_widget (12), directentry);
586 cache->current = wdt->current;
587 push_filelist_line (cache, True);
588
589 cache->options = wdt->options;
590
591 start_y = start * cache->rowheight;
592 y = start_y + FONT_OFFSET_Y;
593 start += wdt->firstline;
594 end += wdt->firstline;
595
596 CSetColor (COLOR_BLACK);
597 restrict_text_area (cache);
598 for (i = start;
599 i <= end &&
600 i < wdt->numlines && y < cache->height &&
601 !(directentry[i].options & FILELIST_LAST_ENTRY); i++) {
602 if (directentry[i].name && i != cache->hilited) {
603 CSetBackgroundColor (COLOR_FLAT);
604 CImageString (cache->cache, FONT_OFFSET_X + 1, y,
605 directentry[i].name);
606 }
607
608 y += cache->rowheight;
609 }
610 XSetClipMask (CDisplay, CGC, None);
611 /* now drawing arrows */
612 y = start_y + (cache->rowheight / 2 - 4);
613 x = cache->width - NEXT_ARROW_FIELD + NEXT_ARROW_SIZE / 2;
614 for (i = start;
615 i <= end &&
616 i < wdt->numlines && y < cache->height &&
617 !(directentry[i].options & FILELIST_LAST_ENTRY); i++) {
618 if (is_directory (directentry, i)) {
619 CSetColor (COLOR_BLACK);
620 CLine (cache->cache, x, y, x + 7, y + 4);
621 CLine (cache->cache, x, y, x, y + 8);
622 CSetColor ((i == cache->hilited) ? COLOR_FLAT : COLOR_WHITE);
623 CLine (cache->cache, x, y + 8, x + 7, y + 4);
624 }
625 y += cache->rowheight;
626 }
627 }
628
render_NeXT_filelist(CWidget * wdt)629 static void render_NeXT_filelist (CWidget * wdt)
630 {
631 FilelistCache *cache;
632
633 if (wdt->hook == NULL) {
634 render_bevel (wdt->winid, 0, 0, wdt->width - 1, wdt->height - 1, 1, 3);
635 return;
636 }
637 if (wdt->user == NULL) {
638 wdt->user = calloc (sizeof (FilelistCache), 1);
639 wdt->free_user = free_filelist_cache;
640 }
641 cache = (FilelistCache *) (wdt->user);
642
643 CPushFont ("widget", 0);
644 check_filelist_cache (wdt, wdt->width - 3, wdt->height - 3, cache);
645 CPopFont ();
646
647 render_bevel (wdt->winid, 0, 0, wdt->width - 1, wdt->height - 1, 1, 1);
648
649 XCopyArea (CDisplay, cache->cache, wdt->winid, CGC, 0, 0, cache->width, cache->height, 2, 2);
650 }
651
link_scrollbar_to_NeXT_filelist(CWidget * scrollbar,CWidget * w,XEvent * xevent,CEvent * cwevent,int whichscrbutton)652 static void link_scrollbar_to_NeXT_filelist (CWidget * scrollbar, CWidget * w, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
653 {
654 /* fix me : add stuf */
655 int redrawtext = 0;
656 int new_first = w->firstline;
657 FilelistCache *cache;
658 int box_size;
659
660 if (w->user == NULL)
661 return;
662 cache = (FilelistCache *) (w->user);
663 box_size = cache->height / cache->rowheight;
664
665 if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
666 new_first = (double) scrollbar->firstline * w->numlines / 65535.0;
667 } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
668 new_first = w->firstline;
669 switch (whichscrbutton) {
670 case 1:
671 new_first -= box_size - 1;
672 break;
673 case 2:
674 new_first--;
675 break;
676 case 5:
677 new_first++;
678 break;
679 case 4:
680 new_first += box_size - 1;
681 break;
682 }
683 }
684 if (new_first < 0)
685 new_first = 0;
686 else if (new_first > w->numlines - box_size)
687 new_first = w->numlines - box_size;
688 redrawtext = (new_first != w->firstline);
689 w->firstline = new_first;
690
691 if (xevent->type == ButtonRelease ||
692 (redrawtext && !CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0)))
693 render_NeXT_filelist (w);
694
695 scrollbar->firstline = (double) 65535.0 *w->firstline / (w->numlines ? w->numlines : 1);
696 scrollbar->numlines = (double) 65535.0 *box_size / (w->numlines ? w->numlines : 1);
697
698 }
699
700 static int eh_NeXT_filelist (CWidget * w, XEvent * xevent, CEvent * cwevent);
701
look_next_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)702 static CWidget *look_next_draw_file_list (const char *identifier, Window parent, int x, int y,
703 int width, int height, int line, int column,
704 struct file_entry *directentry,
705 long options)
706 {
707 struct file_entry e;
708 CWidget *w;
709 int x_hint;
710 int lines = 0;
711 unsigned int prop;
712
713 if (!directentry) {
714 memset (&e, 0, sizeof (e));
715 e.options = FILELIST_LAST_ENTRY;
716 directentry = &e;
717 } else {
718 while (!(directentry[lines].options & FILELIST_LAST_ENTRY))
719 lines++;
720 }
721
722 if (height == AUTO_HEIGHT)
723 height = max (1, lines) * FONT_PIX_PER_LINE + 6;
724
725 if (width == AUTO_WIDTH)
726 width = (FONT_MEAN_WIDTH * 24 + 15);
727
728 w = CSetupWidget (identifier, parent, x, y,
729 width, height, C_TEXTBOX_WIDGET, INPUT_KEY, COLOR_FLAT, 1);
730
731 x_hint = x + width + WIDGET_SPACING;
732 prop = (double) 65535.0 *(height / FONT_PIX_PER_LINE) / (lines ? lines : 1);
733 w->vert_scrollbar = CDrawVerticalScrollbar (catstrs (identifier, ".vsc", NULL), parent,
734 x_hint, y, height, AUTO_WIDTH, 0, prop);
735 w->vert_scrollbar->position |= POSITION_HEIGHT;
736 CSetScrollbarCallback (w->vert_scrollbar->ident, w->ident, link_scrollbar_to_NeXT_filelist);
737 CGetHintPos (&x_hint, 0);
738
739 set_hint_pos (x_hint, y + height + WIDGET_SPACING);
740 w->eh = eh_NeXT_filelist;
741 w->current = -1;
742 w->cursor = -1;
743 w->firstline = 0;
744 w->numlines = lines;
745 w->hook = directentry;
746 return w;
747 }
748
look_next_redraw_file_list(const char * identifier,struct file_entry * directentry,int preserve)749 CWidget *look_next_redraw_file_list (const char *identifier, struct file_entry * directentry, int preserve)
750 {
751 CWidget *w = CIdent (identifier);
752
753 if (w) {
754 w->hook = directentry;
755 if (!directentry)
756 w->numlines = 1;
757 else {
758 register int i = 0;
759 while (!(directentry[i].options & FILELIST_LAST_ENTRY))
760 i++;
761 w->numlines = i;
762 }
763 w->current = -1;
764 w->cursor = -1;
765 w->firstline = 0;
766
767 free_filelist_cache (w->user);
768 w->user = NULL;
769 render_NeXT_filelist (w);
770 if (w->user) {
771 FilelistCache *cache;
772 int box_size;
773 cache = (FilelistCache *) (w->user);
774 box_size = cache->height / cache->rowheight;
775 w->vert_scrollbar->firstline = (double) 65535.0 *w->firstline / (w->numlines ? w->numlines : 1);
776 w->vert_scrollbar->numlines = (double) 65535.0 *box_size / (w->numlines ? w->numlines : 1);
777 render_scrollbar (w->vert_scrollbar);
778 }
779 }
780 return w;
781 }
782
CSetFilelistPosition(const char * identifier,long current,long cursor,long firstline)783 void CSetFilelistPosition (const char *identifier, long current, long cursor, long firstline)
784 {
785 CWidget *w = CIdent (identifier);
786
787 if (w) {
788 FilelistCache *cache;
789 int redraw_scrollbar = 0;
790 if (current >= w->numlines)
791 current = w->numlines - 1;
792 if (cursor >= w->numlines)
793 cursor = w->numlines - 1;
794 w->current = current;
795 w->cursor = cursor;
796 if (firstline >= 0 && (cache = (FilelistCache *) (w->user))) {
797 long max_fline = w->numlines - cache->height / cache->rowheight;
798 if (max_fline <= 0)
799 if (firstline >= max_fline)
800 firstline = max_fline - 1;
801 /* if our window is larger then numlines : */
802 if (firstline < 0)
803 firstline = 0;
804 redraw_scrollbar = (w->firstline != firstline);
805 w->firstline = firstline;
806 }
807 render_NeXT_filelist (w);
808 if (redraw_scrollbar) {
809 w->vert_scrollbar->firstline = (double) 65535.0 *w->firstline / (w->numlines ? w->numlines : 1);
810 render_scrollbar (w->vert_scrollbar);
811 }
812 }
813 }
814
look_next_get_file_list_line(CWidget * w,int line)815 struct file_entry *look_next_get_file_list_line (CWidget * w, int line)
816 {
817 struct file_entry *e;
818 static struct file_entry r;
819
820 memset (&r, 0, sizeof (r));
821 e = (struct file_entry *) w->hook;
822 if (e[line].options & FILELIST_LAST_ENTRY)
823 r.options = FILELIST_LAST_ENTRY;
824 else
825 r = e[line];
826 return &r;
827 }
828
filelist_handle_mouse(CWidget * wdt,FilelistCache * cache,int y)829 int filelist_handle_mouse (CWidget * wdt, FilelistCache * cache, int y)
830 {
831 int new_hilite;
832 new_hilite = (int) (wdt->firstline) + y / (int) (cache->rowheight);
833 if (y < 0)
834 new_hilite--;
835 /* we don't want to remove hilite even if user wants to go
836 beyound the beginning */
837 if (new_hilite < 0)
838 new_hilite = 0;
839
840 return new_hilite;
841 }
842
filelist_handle_keypress(CWidget * wdt,FilelistCache * cache,KeySym key)843 int filelist_handle_keypress (CWidget * wdt, FilelistCache * cache, KeySym key)
844 {
845 int new_cursor = wdt->cursor;
846
847 /* when text is highlighted, the cursor must be off */
848 switch ((int) key) {
849 case CK_Up:
850 new_cursor--;
851 break;
852 case CK_Down:
853 new_cursor++;
854 break;
855 case CK_Page_Up:
856 new_cursor -= cache->height / cache->rowheight - 1;
857 break;
858 case CK_Page_Down:
859 new_cursor += cache->height / cache->rowheight - 1;
860 break;
861 case CK_Home:
862 new_cursor = 0;
863 break;
864 case CK_End:
865 new_cursor = wdt->numlines;
866 break;
867 default:
868 return -1;
869 }
870 /* we don't want to remove hilite even if user wants to go
871 beyound the beginning */
872 if (new_cursor < 0)
873 new_cursor = 0;
874 return new_cursor;
875 }
876
change_hilite(CWidget * w,int new_hilite)877 int change_hilite (CWidget * w, int new_hilite)
878 {
879 FilelistCache *cache = (FilelistCache *) (w->user);
880 if (new_hilite >= w->numlines)
881 new_hilite = w->numlines - 1;
882 if (new_hilite != w->cursor) {
883 int new_firstline = w->firstline;
884 #if 0
885 struct file_entry *directentry = (struct file_entry *) w->hook;
886 #endif
887 if (new_hilite < w->firstline && new_hilite >= 0)
888 new_firstline = new_hilite;
889 if (new_hilite >= w->firstline + w->height / cache->rowheight)
890 new_firstline = new_hilite - w->height / cache->rowheight + 1;
891 if (new_firstline != w->firstline) {
892 w->cursor = new_hilite;
893 w->firstline = new_firstline;
894 w->vert_scrollbar->firstline = (double) 65535.0 *w->firstline / (w->numlines ? w->numlines : 1);
895 render_scrollbar (w->vert_scrollbar);
896 }
897 w->cursor = new_hilite;
898 return 1;
899 }
900 return 0;
901 }
902
903 void selection_send (XSelectionRequestEvent * rq);
904
eh_NeXT_filelist(CWidget * w,XEvent * xevent,CEvent * cwevent)905 int eh_NeXT_filelist (CWidget * w, XEvent * xevent, CEvent * cwevent)
906 {
907 #if 0
908 int xevent_xbutton_y;
909 #endif
910 int need_redraw = 0;
911 FilelistCache *cache = (FilelistCache *) (w->user);
912 int handled = 0;
913
914 if ((w == NULL || w->hook == NULL || cache == NULL) &&
915 xevent->type != Expose)
916 return handled;
917
918 switch (xevent->type) {
919 case SelectionRequest:
920 /* fixme: later
921 {
922 int type;
923 if (selection.text) free (selection.text);
924 selection.text = (unsigned char *) get_block (w, 0, 0, &type, &selection.len);
925 selection_send (&(xevent->xselectionrequest));
926 }
927 return 1;
928 */ case Expose:
929 handled = 1;
930 break;
931 case ButtonPress:
932 resolve_button (xevent, cwevent);
933 need_redraw = change_hilite (w, filelist_handle_mouse (w, cache, cwevent->y));
934 handled = 1;
935 break;
936 case ButtonRelease:
937 resolve_button (xevent, cwevent);
938 need_redraw = change_hilite (w, filelist_handle_mouse (w, cache, cwevent->y));
939 handled = 1;
940 break;
941 case MotionNotify:
942 resolve_button (xevent, cwevent);
943 if (cwevent->state & (Button1Mask | Button2Mask)) {
944 need_redraw = change_hilite (w, filelist_handle_mouse (w, cache, cwevent->y));
945 handled = 1;
946 }
947 break;
948 case FocusIn:
949 w->options |= BUTTON_HIGHLIGHT;
950 need_redraw = 1;
951 handled = 1;
952 break;
953 case FocusOut:
954 w->options &= ~BUTTON_HIGHLIGHT;
955 need_redraw = 1;
956 handled = 1;
957 break;
958 case EnterNotify: /* we simply let our parent to process it */
959 case LeaveNotify:
960 cwevent->ident = w->ident;
961 break;
962 case KeyPress:
963 {
964 int move_to = filelist_handle_keypress (w, cache, cwevent->command);
965
966 if (move_to >= 0) {
967 need_redraw = change_hilite (w, move_to);
968 handled = 1;
969 } else {
970 switch (cwevent->command) {
971 case CK_Left:
972 case CK_Right:
973 case CK_Home:
974 case CK_End:
975 case CK_Enter:
976 case CK_BackSpace:
977 cwevent->ident = w->ident;
978 return 1;
979 default:
980 if (cwevent->insert > 0) {
981 cwevent->ident = w->ident;
982 return 1;
983 }
984 }
985 }
986 }
987 break;
988
989 default:
990 return handled;
991 }
992
993 if (need_redraw || cwevent->double_click)
994 cwevent->ident = w->ident;
995
996 if ((xevent->type == Expose && !xevent->xexpose.count) || need_redraw)
997 render_NeXT_filelist (w);
998
999 return handled;
1000 }
1001
1002
1003 /* }}} file list stuff */
1004
1005 /* {{{ file browser stuff */
1006
1007 /*****************************************************************/
1008 /* Miscellaneous read only text widget for dynamic text */
1009 /*****************************************************************/
1010
render_dyn_text(CWidget * wdt)1011 static void render_dyn_text (CWidget * wdt)
1012 {
1013 Window win = wdt->winid;
1014 char text[1024], *p, *q;
1015 int y, x = 0, w = wdt->width;
1016 int color = 0;
1017 int new_line = 1;
1018
1019 CSetColor (COLOR_LIGHT);
1020 CRectangle (win, 1, 1, w - 2, wdt->height - 2);
1021 CSetColor (COLOR_BLACK);
1022 CSetBackgroundColor (COLOR_LIGHT);
1023
1024 y = 1; /* bevel */
1025 if ((q = wdt->text) == NULL)
1026 return;
1027 CPushFont ("widget", 0);
1028 for (;;) {
1029 long len;
1030
1031 CSetColor (color_palette (color));
1032 /* looking for control characters */
1033 for (p = q; *p && *p >= ' '; p++);
1034
1035 len = min ((unsigned long) p - (unsigned long) q, 1023);
1036
1037 if (new_line) {
1038 if (wdt->options & TEXT_CENTRED)
1039 x = (w - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, len)) / 2;
1040 else
1041 x = 0;
1042 new_line = 0;
1043 }
1044 if (!*p) { /* last line */
1045 drawstring_xy (win, TEXT_RELIEF + 1 + x, TEXT_RELIEF + y, q);
1046 break;
1047 } else {
1048 memcpy (text, q, len);
1049 text[len] = 0;
1050 drawstring_xy (win, TEXT_RELIEF + 1 + x,
1051 TEXT_RELIEF + y, text);
1052 x += CImageTextWidth (q, len);
1053 }
1054
1055 if (*p == '\n') {
1056 new_line = 1;
1057 y += FONT_PIX_PER_LINE; /* next line */
1058 } else if (*p == 28)
1059 color = (int) '\n';
1060 else
1061 color = *p;
1062
1063 color %= 27;
1064 q = p + 1;
1065 }
1066 CPopFont ();
1067 render_bevel (win, 0, 0, w - 1, wdt->height - 1, 1, 1);
1068 }
1069
1070
1071 /*-----------------------------------------------------------------------*/
eh_dyn_text(CWidget * w,XEvent * xevent,CEvent * cwevent)1072 static int eh_dyn_text (CWidget * w, XEvent * xevent, CEvent * cwevent)
1073 {
1074 switch (xevent->type) {
1075 case Expose:
1076 if (!xevent->xexpose.count)
1077 render_dyn_text (w);
1078 break;
1079 }
1080 return 0;
1081 }
1082
CDrawDynText(const char * identifier,Window parent,int x,int y,int width,int rows,const char * fmt,...)1083 static CWidget *CDrawDynText (const char *identifier, Window parent,
1084 int x, int y, int width, int rows, const char *fmt,...)
1085 {
1086 va_list pa;
1087 char *str;
1088 int w, h;
1089 CWidget *wdt;
1090
1091 va_start (pa, fmt);
1092 str = vsprintf_alloc (fmt, pa);
1093 va_end (pa);
1094
1095 CPushFont ("widget", 0);
1096 CTextSize (&w, &h, str);
1097 if (width != AUTO_WIDTH && width)
1098 w = width;
1099 else
1100 w += TEXT_RELIEF * 2 + 2;
1101
1102 if (rows != AUTO_HEIGHT && rows) {
1103 CTextSize (0, &h, "Ty~g$V|&^.,/_'I}[@");
1104 h = (h + FONT_OVERHEAD) * rows;
1105 }
1106 h += TEXT_RELIEF * 2 + 2;
1107
1108 wdt = CSetupWidget (identifier, parent, x, y,
1109 w, h, C_TEXT_WIDGET, INPUT_EXPOSE, COLOR_FLAT, 0);
1110 wdt->text = (char *) strdup (str);
1111 wdt->eh = eh_dyn_text;
1112 free (str);
1113 set_hint_pos (x + w + WIDGET_SPACING, y + h + WIDGET_SPACING);
1114 CPopFont ();
1115 return wdt;
1116 }
1117
CRedrawDynText(const char * identifier,const char * fmt,...)1118 static CWidget *CRedrawDynText (const char *identifier, const char *fmt,...)
1119 {
1120 va_list pa;
1121 char *str;
1122 CWidget *wdt;
1123 #if 0
1124 int w, h;
1125 #endif
1126
1127 wdt = CIdent (identifier);
1128 if (!wdt)
1129 return 0;
1130
1131 va_start (pa, fmt);
1132 str = vsprintf_alloc (fmt, pa);
1133 va_end (pa);
1134
1135 if (wdt->text)
1136 free (wdt->text);
1137 wdt->text = (char *) strdup (str);
1138
1139 render_dyn_text (wdt);
1140 free (str);
1141 return wdt;
1142 }
1143
1144
1145 /******************************************************************/
1146 /* NeXT Directory Tree stuff */
1147 /******************************************************************/
1148 typedef struct NeXTDir {
1149 struct NeXTDir *next, *prev;
1150
1151 char *name;
1152 char *filter;
1153 long cursor;
1154 long current;
1155 long firstline;
1156 struct file_entry *list;
1157
1158 } NeXTDir;
1159
1160 typedef struct NeXTDirTree {
1161 NeXTDir *first, *last, *selected;
1162 NeXTDir *discarded; /* when we chdir - it will store previos tail */
1163 int pos;
1164 int numdirs;
1165 int numpanes;
1166 char *path;
1167 int path_length;
1168
1169 int dirty; /* can't change dirs - need to redraw widgets first */
1170 } NeXTDirTree;
1171
1172 extern Bool is_directory (struct file_entry *directentry, int line_number);
1173
create_dir_elem(char * name,int name_len)1174 static NeXTDir *create_dir_elem (char *name, int name_len)
1175 {
1176 NeXTDir *dir;
1177 dir = (NeXTDir *) calloc (sizeof (NeXTDir), 1);
1178 dir->prev = dir->next = NULL;
1179 dir->filter = (char *) strdup ("*");
1180 dir->current = -1;
1181 dir->list = NULL;
1182 if (name == NULL || name_len == 0) { /* root directory then */
1183 dir->name = (char *) strdup ("");
1184 } else {
1185 dir->name = malloc (name_len + 1);
1186 strncpy (dir->name, name, name_len);
1187 dir->name[name_len] = '\0';
1188 }
1189 return dir;
1190 }
1191
destroy_dir_elem(NeXTDir ** dir)1192 static void destroy_dir_elem (NeXTDir ** dir)
1193 {
1194 if (dir) {
1195 if (*dir) {
1196 if ((*dir)->filter)
1197 free ((*dir)->filter);
1198 if ((*dir)->name)
1199 free ((*dir)->name);
1200 if ((*dir)->list)
1201 free ((*dir)->list);
1202 memset (*dir, 0x00, sizeof (NeXTDir)); /* just in case */
1203 free (*dir);
1204 *dir = NULL;
1205 }
1206 }
1207 }
1208
create_dir_tree(const char * path,int numpanes)1209 static NeXTDirTree *create_dir_tree (const char *path, int numpanes)
1210 {
1211 NeXTDirTree *tree = NULL;
1212 char *ptr = 0;
1213
1214 tree = (NeXTDirTree *) calloc (sizeof (NeXTDirTree), 1);
1215
1216 if (path == NULL) { /* defaulting to the root */
1217 tree->path_length = 1;
1218 tree->path = (char *) strdup ("/");
1219 tree->first = tree->last = tree->selected = create_dir_elem ("", 0);
1220 tree->numdirs++;
1221 } else {
1222 tree->path_length = strlen (path);
1223 tree->path = malloc (tree->path_length + 1);
1224 strcpy (tree->path, path);
1225
1226 ptr = tree->path;
1227
1228 if (*ptr == '/') {
1229 tree->first = tree->last = tree->selected = create_dir_elem ("", 0);
1230 tree->numdirs++;
1231 }
1232 while (*ptr) {
1233 int len = 0;
1234 while (*(ptr + len) && *(ptr + len) != '/')
1235 len++;
1236 if (len) {
1237 tree->selected = create_dir_elem (ptr, len);
1238 if (tree->last == NULL)
1239 tree->first = tree->last = tree->selected;
1240 else {
1241 tree->selected->prev = tree->last;
1242 tree->last->next = tree->selected;
1243 tree->last = tree->selected;
1244 }
1245 tree->numdirs++;
1246 }
1247 ptr += len;
1248 if (*ptr)
1249 ptr++; /* skipping / */
1250 }
1251 }
1252 tree->numpanes = numpanes;
1253 tree->discarded = NULL;
1254
1255 if (tree->selected == NULL)
1256 tree->selected = tree->last;
1257 tree->pos = tree->numdirs - tree->numpanes;
1258 if (tree->pos < 0)
1259 tree->pos = 0;
1260 return tree;
1261 }
1262
destroy_dir_chain(NeXTDir ** start)1263 static void destroy_dir_chain (NeXTDir ** start)
1264 {
1265 NeXTDir *dir;
1266 for (dir = *start; dir; dir = *start) {
1267 *start = dir->next;
1268 destroy_dir_elem (&dir);
1269 }
1270 }
1271
destroy_dir_tree(NeXTDirTree ** tree)1272 static void destroy_dir_tree (NeXTDirTree ** tree)
1273 {
1274 if (tree) {
1275 destroy_dir_chain (&((*tree)->first));
1276 destroy_dir_chain (&((*tree)->discarded));
1277 free (*tree);
1278 *tree = NULL;
1279 }
1280 }
1281
get_dir_path(NeXTDirTree * tree,NeXTDir * dir,char * buffer)1282 static char *get_dir_path (NeXTDirTree * tree, NeXTDir * dir, char *buffer)
1283 {
1284 register NeXTDir *d;
1285 register char *ptr1 = buffer, *ptr2;
1286 if (!ptr1 || !tree || !dir)
1287 return NULL;
1288
1289 for (d = tree->first; d && d != dir; d = d->next) {
1290 *(ptr1++) = '/';
1291 ptr2 = d->name;
1292 if (*ptr2)
1293 while (*ptr2)
1294 *(ptr1++) = *(ptr2++);
1295 else /* we don't really want //, even thou it is not a violation */
1296 ptr1--;
1297 }
1298 *ptr1 = '\0';
1299 return buffer;
1300 }
1301
read_dir_filelist(NeXTDir * dir,char * path)1302 static struct file_entry *read_dir_filelist (NeXTDir * dir, char *path)
1303 {
1304 if (dir && path) {
1305 register int k;
1306 char *next_dir = NULL;
1307 CHourGlass (CFirstWindow);
1308 if (dir->list)
1309 free (dir->list);
1310 dir->list = get_file_entry_list (path, FILELIST_ALL_FILES, (dir->filter) ? dir->filter : "*");
1311 if (dir->next)
1312 next_dir = dir->next->name;
1313 dir->current = -1;
1314 if (dir->list && next_dir) {
1315 for (k = 0; !(dir->list[k].options & FILELIST_LAST_ENTRY); k++)
1316 if (is_directory (dir->list, k))
1317 if (strcmp (dir->list[k].name, next_dir) == 0) {
1318 dir->current = k;
1319 break;
1320 }
1321 }
1322 dir->cursor = dir->firstline = (dir->current >= 0) ? dir->current : 0;
1323 CUnHourGlass (CFirstWindow);
1324 }
1325 return dir->list;
1326 }
1327
update_tree_integrity(NeXTDirTree * tree,NeXTDir * selected)1328 static void update_tree_integrity (NeXTDirTree * tree, NeXTDir * selected)
1329 {
1330 NeXTDir *t;
1331 tree->selected = NULL;
1332 tree->numdirs = 0;
1333 tree->path_length = 0;
1334
1335 for (t = tree->first; t; t = t->next) {
1336 tree->last = t;
1337 if (selected == t)
1338 tree->selected = selected;
1339 tree->numdirs++;
1340 tree->path_length += 1 + strlen (t->name);
1341 }
1342
1343 tree->path_length++;
1344
1345 tree->pos = tree->numdirs - tree->numpanes;
1346 if (tree->pos < 0)
1347 tree->pos = 0;
1348
1349 if (tree->selected == NULL)
1350 tree->selected = tree->last;
1351 }
1352
change_dir(NeXTDirTree * tree,NeXTDir * dir,long item_num)1353 static void change_dir (NeXTDirTree * tree, NeXTDir * dir, long item_num)
1354 {
1355 struct file_entry *item;
1356 NeXTDir *tmp;
1357
1358 if (!tree || tree->dirty || !dir || item_num < 0)
1359 return;
1360 item = &(dir->list[item_num]);
1361
1362 if (item->name[0] == '.') {
1363 if (item->name[1] == '\0')
1364 return;
1365 else if (item->name[1] == '.' && item->name[2] == '\0') { /* poping Up */
1366 if (dir->prev == NULL)
1367 return;
1368 dir = dir->prev;
1369 if (tree->discarded)
1370 destroy_dir_chain (&(tree->discarded));
1371 tree->discarded = dir->next;
1372 dir->next = NULL;
1373 tree->dirty = 1;
1374 update_tree_integrity (tree, dir);
1375 return;
1376 }
1377 }
1378 if (tree->discarded) {
1379 if (tree->discarded->prev == dir &&
1380 strcmp (tree->discarded->name, item->name) == 0) {
1381 tmp = dir->next;
1382 dir->next = tree->discarded;
1383 tree->discarded = tmp;
1384 } else {
1385 destroy_dir_chain (&(tree->discarded));
1386 tree->discarded = dir->next;
1387 dir->next = NULL;
1388 }
1389 } else {
1390 tree->discarded = dir->next;
1391 dir->next = NULL;
1392 }
1393
1394 if (dir->next == NULL) {
1395 dir->next = create_dir_elem (item->name, strlen (item->name));
1396 dir->next->prev = dir;
1397 }
1398 tree->dirty = 1;
1399
1400 dir->current = item_num;
1401 /* taking some precautions so not to destroy tree integrity */
1402 update_tree_integrity (tree, dir);
1403 }
1404
get_full_filename(NeXTDirTree * tree,NeXTDir * dir,long item)1405 static char *get_full_filename (NeXTDirTree * tree, NeXTDir * dir, long item)
1406 {
1407 char *buffer, *path_tail;
1408 if (!tree || item < 0 || !dir || !(dir->list))
1409 return NULL;
1410 buffer = malloc (tree->path_length + 1 + strlen (dir->list[item].name) + 1);
1411 get_dir_path (tree, dir, buffer);
1412 path_tail = buffer + strlen (buffer);
1413 sprintf (path_tail, "/%s/%s", dir->name, dir->list[item].name);
1414 return buffer;
1415 }
1416
commit(NeXTDirTree * tree,NeXTDir * dir)1417 static char *commit (NeXTDirTree * tree, NeXTDir * dir)
1418 { /* when user presses Enter on selected item or dobleclicks */
1419 if (tree) {
1420 if (dir) {
1421 if (dir->list && dir->cursor >= 0) {
1422 if (is_directory (dir->list, dir->cursor))
1423 change_dir (tree, dir, dir->cursor);
1424 else
1425 return get_full_filename (tree, dir, dir->cursor);
1426 }
1427 }
1428 }
1429 return NULL;
1430 }
1431
1432 /******************************************************************/
1433 /* NeXT Browser widget stuff */
1434 /******************************************************************/
1435
1436 #define FILEBROWSER_PANES 2
1437 #define STANDALONE_FILEBROWSER_PANES 3
1438
1439 static char *mime_majors[3] =
1440 {"url", "text", 0};
1441
1442 typedef struct NeXTFileBrowser {
1443 int numpanes;
1444 int focused;
1445
1446 #define MAX_PARTIAL_NAME 32
1447 char partial_name[MAX_PARTIAL_NAME];
1448 int partial_end;
1449
1450 char **labels;
1451 char **lists;
1452 char *hscroll;
1453 char *fileattr;
1454 char *name;
1455 char *filter;
1456 NeXTDirTree *tree;
1457 } NeXTFileBrowser;
1458
clear_partial_buffer(NeXTFileBrowser * browser)1459 static void clear_partial_buffer (NeXTFileBrowser * browser)
1460 {
1461 if (browser) {
1462 browser->partial_end = 0;
1463 }
1464 }
1465
1466
1467 extern void CSetFilelistPosition (const char *identifier, long current, long cursor, long firstline);
1468
dir_save_position(NeXTDir * dir,long cursor,long current,long firstline)1469 static void dir_save_position (NeXTDir * dir, long cursor, long current, long firstline)
1470 {
1471 dir->cursor = cursor;
1472 dir->current = current;
1473 dir->firstline = firstline;
1474 }
1475
destroy_next_filebrowser(CWidget * w)1476 static void destroy_next_filebrowser (CWidget * w)
1477 {
1478 if (w->hook) {
1479 NeXTFileBrowser *browser = (NeXTFileBrowser *) w->hook;
1480 int i;
1481 destroy_dir_tree (&(browser->tree));
1482 if (browser->labels) {
1483 for (i = 0; i < browser->numpanes; i++)
1484 if (browser->labels[i])
1485 free (browser->labels[i]);
1486 free (browser->labels);
1487 }
1488 if (browser->lists) {
1489 for (i = 0; i < browser->numpanes; i++)
1490 if (browser->lists[i])
1491 free (browser->lists[i]);
1492 free (browser->lists);
1493 }
1494 if (browser->fileattr)
1495 free (browser->fileattr);
1496 if (browser->name)
1497 free (browser->name);
1498 if (browser->filter)
1499 free (browser->filter);
1500 /* just in case */
1501 memset (browser, 0x00, sizeof (NeXTFileBrowser));
1502
1503 free (browser);
1504 w->hook = 0;
1505 }
1506 }
1507
get_dir_by_num(NeXTDirTree * tree,int num)1508 static NeXTDir *get_dir_by_num (NeXTDirTree * tree, int num)
1509 {
1510 NeXTDir *dir = NULL;
1511 register int i;
1512 if (tree)
1513 dir = tree->first;
1514 for (i = 0; dir && i < num; i++)
1515 dir = dir->next;
1516 return dir;
1517 }
1518
1519 static void update_filter (NeXTFileBrowser * browser, NeXTDir * dir);
1520
link_browser_to_data(NeXTFileBrowser * browser,int start)1521 static void link_browser_to_data (NeXTFileBrowser * browser, int start)
1522 {
1523 NeXTDir *dir;
1524 char *path = NULL, *path_tail = 0;
1525 int i, todo = browser->numpanes;
1526 if (browser == NULL)
1527 return;
1528 if (start < 0 || start >= browser->numpanes)
1529 start = 0;
1530
1531 if (start == 0)
1532 browser->tree->dirty = 0;
1533
1534 if (browser->tree) {
1535 todo -= start;
1536 start += browser->tree->pos;
1537 dir = get_dir_by_num (browser->tree, start);
1538 } else
1539 dir = NULL;
1540
1541 if (dir) {
1542 path = malloc (browser->tree->path_length + 1);
1543 get_dir_path (browser->tree, dir, path);
1544 path_tail = path + strlen (path);
1545 }
1546 for (i = 0; i < todo; i++) {
1547 if (!dir) {
1548 CRedrawDynText (browser->labels[i], "");
1549 CRedrawFilelist (browser->lists[i], 0, 0);
1550 } else {
1551
1552 if (dir->name) {
1553 *(path_tail++) = '/';
1554 strcpy (path_tail, dir->name);
1555 path_tail += strlen (dir->name);
1556 CRedrawDynText (browser->labels[i], "%s/%s", dir->name, dir->filter);
1557 } else
1558 CRedrawDynText (browser->labels[i], "/%s", dir->filter); /* root */
1559
1560 if (dir->list == NULL)
1561 read_dir_filelist (dir, path);
1562 CRedrawFilelist (browser->lists[i], dir->list, 0);
1563 CSetFilelistPosition (browser->lists[i], dir->current, dir->cursor, dir->firstline);
1564 dir = dir->next;
1565 }
1566 }
1567 }
1568
update_scrollbar(CWidget * scrollbar,NeXTFileBrowser * browser,int redraw)1569 static void update_scrollbar (CWidget * scrollbar, NeXTFileBrowser * browser, int redraw)
1570 {
1571 scrollbar->firstline = (double) 65535.0 *browser->tree->pos / (browser->tree->numdirs ? browser->tree->numdirs : 1);
1572 scrollbar->numlines = (double) 65535.0 *browser->numpanes / (browser->tree->numdirs ? browser->tree->numdirs : 1);
1573 if (redraw)
1574 render_scrollbar (scrollbar);
1575 }
1576
link_scrollbar_to_NeXT_browser(CWidget * scrollbar,CWidget * w,XEvent * xevent,CEvent * cwevent,int whichscrbutton)1577 static void link_scrollbar_to_NeXT_browser (CWidget * scrollbar, CWidget * w, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
1578 {
1579 /* fix me : add stuf */
1580 int redraw = 0;
1581 int new_first = w->firstline;
1582 NeXTFileBrowser *browser;
1583 #if 0
1584 static int r = 0;
1585 NeXTDir *dir;
1586 #endif
1587
1588 if (w->hook == NULL)
1589 return;
1590 browser = (NeXTFileBrowser *) (w->hook);
1591 new_first = browser->tree->pos;
1592
1593 if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
1594 new_first = (double) scrollbar->firstline * browser->tree->numdirs / 65535.0;
1595 } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
1596 switch (whichscrbutton) {
1597 case 1:
1598 new_first -= browser->numpanes - 1;
1599 break;
1600 case 2:
1601 new_first--;
1602 break;
1603 case 5:
1604 new_first++;
1605 break;
1606 case 4:
1607 new_first += browser->numpanes - 1;
1608 break;
1609 }
1610 }
1611 if (new_first > browser->tree->numdirs - browser->numpanes)
1612 new_first = browser->tree->numdirs - browser->numpanes;
1613 if (new_first < 0)
1614 new_first = 0;
1615
1616 redraw = (new_first != browser->tree->pos);
1617 browser->tree->pos = new_first;
1618
1619 if (xevent->type == ButtonRelease ||
1620 (redraw && !CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0)))
1621 link_browser_to_data (browser, 0);
1622
1623 update_scrollbar (w->hori_scrollbar, browser, 0);
1624 }
1625
update_input(NeXTFileBrowser * browser,NeXTDir * dir)1626 static void update_input (NeXTFileBrowser * browser, NeXTDir * dir)
1627 {
1628 char *text = NULL;
1629 CWidget *inp_w = CIdent (browser->name);
1630
1631 clear_partial_buffer (browser);
1632
1633 text = get_full_filename (browser->tree, dir, dir->cursor);
1634
1635 CDrawTextInput (browser->name, inp_w->parentid, inp_w->x, inp_w->y,
1636 inp_w->width, inp_w->height, 256, text);
1637 if (text)
1638 free (text);
1639
1640 }
1641
filter_changed(NeXTFileBrowser * browser,NeXTDir * dir)1642 static void filter_changed (NeXTFileBrowser * browser, NeXTDir * dir)
1643 {
1644 CWidget *inp_w = CIdent (browser->filter);
1645 char *new_filter = "*";
1646 if (inp_w->text)
1647 new_filter = inp_w->text;
1648
1649 if (strcmp (dir->filter, new_filter)) {
1650 struct file_entry *list;
1651 if (dir->filter)
1652 free (dir->filter);
1653 dir->filter = (char *) strdup (new_filter);
1654 list = dir->list;
1655 dir->list = NULL;
1656 link_browser_to_data (browser, browser->focused - browser->tree->pos);
1657 /* now after all filelists has updated its information
1658 we no longer need old data */
1659 if (list)
1660 free (list);
1661 }
1662 }
1663
update_filter(NeXTFileBrowser * browser,NeXTDir * dir)1664 static void update_filter (NeXTFileBrowser * browser, NeXTDir * dir)
1665 {
1666 CWidget *inp_w = CIdent (browser->filter);
1667
1668 if (strcmp (dir->filter, inp_w->text) == 0)
1669 return;
1670 if (strlen (inp_w->text))
1671 CAddToTextInputHistory (browser->name, inp_w->text);
1672
1673 CDrawTextInput (browser->filter, inp_w->parentid, inp_w->x, inp_w->y,
1674 inp_w->width, inp_w->height, 256, dir->filter);
1675
1676 }
1677
1678 /* returns 0 on fail */
goto_partial_file_name(NeXTFileBrowser * browser,NeXTDir * dir,int new_char)1679 static int goto_partial_file_name (NeXTFileBrowser * browser, NeXTDir * dir, int new_char)
1680 {
1681 int success = 0;
1682 if (browser && dir && dir->list && browser->partial_end < MAX_PARTIAL_NAME - 1) {
1683 register int i;
1684 if (new_char != 0) {
1685 browser->partial_name[browser->partial_end] = (char) new_char;
1686 browser->partial_end++;
1687 } else if (browser->partial_end <= 0)
1688 return success;
1689 else
1690 browser->partial_end--;
1691
1692 for (i = 0; !(dir->list[i].options & FILELIST_LAST_ENTRY); i++)
1693 if (strncmp (dir->list[i].name, browser->partial_name, browser->partial_end) == 0) {
1694 dir->cursor = i;
1695 dir->firstline = dir->cursor;
1696 CSetFilelistPosition (browser->lists[browser->focused], dir->current, dir->cursor, dir->firstline);
1697 success++;
1698 break;
1699 }
1700 if (!success)
1701 browser->partial_end--;
1702
1703 }
1704 return success;
1705 }
1706
draw_file_browser(const char * identifier,Window parent,int x,int y,const char * directory,const char * file,const char * label)1707 static Window draw_file_browser (const char *identifier, Window parent, int x, int y,
1708 const char *directory, const char *file, const char *label)
1709 {
1710 CWidget *w, *tmp = 0;
1711 int y2, x2, x3, btn_width, btn_height;
1712 int text_w1, text_w2;
1713 Window win;
1714 NeXTFileBrowser *browser;
1715 int i;
1716 char *ident, *ctrl_name;
1717 int panes = FILEBROWSER_PANES;
1718
1719 if (strcmp (identifier, "browser") == 0)
1720 panes = STANDALONE_FILEBROWSER_PANES;
1721
1722 if (parent == CRoot)
1723 win = CDrawMainWindow (identifier, label);
1724 else
1725 win = CDrawHeadedDialog (identifier, parent, x, y, label);
1726
1727 w = CIdent (identifier);
1728 w->options |= WINDOW_ALWAYS_RAISED;
1729 CHourGlass (CFirstWindow);
1730 /* allocating, initializing and storing our data */
1731 browser = (NeXTFileBrowser *) calloc (sizeof (NeXTFileBrowser), 1);
1732 w->hook = browser;
1733 w->destroy = destroy_next_filebrowser;
1734 browser->tree = create_dir_tree (directory, panes);
1735 browser->numpanes = 0;
1736 CUnHourGlass (CFirstWindow);
1737
1738 if (browser->tree->numdirs == 0) {
1739 CErrorDialog (parent, 20, 20, _ (" File browser "), _ (" Unable to read directory "));
1740 CDestroyWidget (identifier);
1741 return None;
1742 }
1743 browser->labels = (char **) calloc (sizeof (char *), panes);
1744 browser->lists = (char **) calloc (sizeof (char *), panes);
1745 browser->numpanes = panes;
1746
1747 CGetHintPos (&x, &y);
1748 x += WINDOW_EXTRA_SPACING;
1749 y += WINDOW_EXTRA_SPACING;
1750 #define FILE_BOX_WIDTH (FONT_MEAN_WIDTH * 32 + 7)
1751 /* we'll use it to construct our widget names */
1752 ident = malloc (strlen (identifier) + 20);
1753 strcpy (ident, identifier);
1754 ctrl_name = ident + strlen (identifier);
1755 y2 = 0;
1756 for (i = 0; i < browser->numpanes; i++) {
1757 CGetHintPos (&x2, 0);
1758 x2 += WINDOW_EXTRA_SPACING;
1759 sprintf (ctrl_name, ".label%3.3d", i);
1760 browser->labels[i] = (char *) strdup (ident);
1761 tmp = CDrawDynText (ident, win, x2, y, FILE_BOX_WIDTH, 1, "");
1762 tmp->options |= TEXT_CENTRED;
1763
1764 /* only first time */
1765 if (y2 == 0) {
1766 CGetHintPos (0, &y2);
1767 /* y2+=WINDOW_EXTRA_SPACING ; */
1768 }
1769 sprintf (ctrl_name, ".flist%3.3d", i);
1770 browser->lists[i] = (char *) strdup (ident);
1771 tmp = CDrawFilelist (ident, win, x2, y2,
1772 FILE_BOX_WIDTH, FONT_PIX_PER_LINE * 10, 0, 0, NULL, TEXTBOX_FILE_LIST);
1773 tmp->position |= POSITION_HEIGHT;
1774 xdnd_set_type_list (CDndClass, tmp->winid, xdnd_typelist_send[DndFiles]);
1775 /* Toolhint */
1776 CSetToolHint (ident, _ ("Double click to enter dir or open file."));
1777 }
1778 /* we want to automagically resize rightmost filelist */
1779 tmp->position |= POSITION_WIDTH;
1780 if (tmp->vert_scrollbar)
1781 tmp->vert_scrollbar->position |= POSITION_RIGHT;
1782 tmp = CIdent (browser->labels[browser->numpanes - 1]);
1783 tmp->position |= POSITION_WIDTH;
1784
1785 /* the right end of dialog */
1786 CGetHintPos (&x3, &y2);
1787
1788 strcpy (ctrl_name, ".hsc");
1789 i = (double) 65535.0 *browser->tree->numpanes / (browser->tree->numdirs ? browser->tree->numdirs : 1);
1790 w->hori_scrollbar = CDrawHorizontalScrollbar (ident, win,
1791 x, y2 + WINDOW_EXTRA_SPACING, x3 - x, AUTO_HEIGHT, i, i);
1792 CSetScrollbarCallback (ident, w->ident, link_scrollbar_to_NeXT_browser);
1793 w->hori_scrollbar->position = POSITION_BOTTOM | POSITION_WIDTH;
1794 update_scrollbar (w->hori_scrollbar, browser, 1);
1795
1796 CPushFont ("widget", 0);
1797
1798 CGetHintPos (0, &y2);
1799 strcpy (ctrl_name, ".fileattr");
1800 browser->fileattr = (char *) strdup (ident);
1801 tmp = CDrawDynText (ident, win, x, y2 + WINDOW_EXTRA_SPACING, x3 - x, 3, "");
1802 tmp->position |= POSITION_FILL | POSITION_BOTTOM;
1803
1804 CTextSize (&text_w1, 0, "Name : ");
1805 CTextSize (&text_w2, 0, "Filter : ");
1806 /* filename input stuff: */
1807 CGetHintPos (0, &y2);
1808 y2 += WINDOW_EXTRA_SPACING;
1809 /* label */
1810 strcpy (ctrl_name, ".namex");
1811 x2 = x;
1812 if (text_w1 < text_w2)
1813 x2 += text_w2 - text_w1;
1814 tmp = CDrawText (ident, win, x2, y2, _ ("Name : "));
1815 tmp->position |= POSITION_BOTTOM;
1816 /* we want filter and name inputs to be right underneath of each other */
1817 x2 += text_w1 + WINDOW_EXTRA_SPACING;
1818 /* input */
1819 strcpy (ctrl_name, ".finp");
1820 browser->name = (char *) strdup (ident);
1821 tmp = CDrawTextInput (ident, win, x2, y2, AUTO_WIDTH, AUTO_HEIGHT, 256, file);
1822 tmp->position |= POSITION_FILL | POSITION_BOTTOM;
1823 /* Toolhint */
1824 CSetToolHint (ident, _ ("Filename of the file to load."));
1825 /* DnD stuff */
1826 xdnd_set_type_list (CDndClass, tmp->winid, xdnd_typelist_send[DndFile]);
1827 tmp->funcs->types = DndFile;
1828 tmp->funcs->mime_majors = mime_majors;
1829
1830 /* file filter input stuff */
1831 CGetHintPos (0, &y2);
1832 y2 += WINDOW_EXTRA_SPACING;
1833 /* label */
1834 x2 = x;
1835 if (text_w2 < text_w1)
1836 x2 += text_w1 - text_w2;
1837 strcpy (ctrl_name, ".filtx");
1838 (CDrawText (ident, win, x2, y2, _ ("Filter :")))->position |= POSITION_BOTTOM;
1839 x2 += text_w2 + WINDOW_EXTRA_SPACING;
1840 /* input (we already know where to place it - right under filename input ) */
1841 strcpy (ctrl_name, ".filtinp");
1842 browser->filter = (char *) strdup (ident);
1843 tmp = CDrawTextInput (ident, win, x2, y2, AUTO_WIDTH, AUTO_HEIGHT, 256, TEXTINPUT_LAST_INPUT);
1844 tmp->position |= POSITION_FILL | POSITION_BOTTOM;
1845 /* Toolhint */
1846 CSetToolHint (ident, _ ("List only files matching this shell filter"));
1847
1848 /* buttons stuff */
1849 CGetHintPos (0, &y2);
1850 y2 += WINDOW_EXTRA_SPACING * 2;
1851 /* determining buttons size */
1852 CTextSize (&btn_width, &btn_height, " Cancel ");
1853 btn_height += 5 + BUTTON_RELIEF * 2;
1854 btn_width += 4 + BUTTON_RELIEF * 2;
1855 /* cancel button */
1856 x2 = x3 - (btn_width + WINDOW_EXTRA_SPACING) * 2 - WINDOW_EXTRA_SPACING;
1857 strcpy (ctrl_name, ".cancel");
1858 tmp = CDrawButton (ident, win, x2, y2, btn_width, btn_height, " Cancel ");
1859 tmp->position |= POSITION_RIGHT | POSITION_BOTTOM;
1860 CSetToolHint (ident, _ ("Abort this dialog, Escape"));
1861 /* ok button */
1862 x2 += btn_width + WINDOW_EXTRA_SPACING * 2;
1863 strcpy (ctrl_name, ".ok");
1864 tmp = CDrawButton (ident, win, x2, y2, btn_width, btn_height, " Ok ");
1865 tmp->position |= POSITION_RIGHT | POSITION_BOTTOM;
1866 CSetToolHint (ident, _ ("Accept, Enter"));
1867
1868 CPopFont ();
1869
1870 /* all done - no longer need that : */
1871 free (ident);
1872
1873 /* make us real ! */
1874 link_browser_to_data (browser, 0);
1875 /* that will be our width/height : */
1876 y2 += btn_height + WINDOW_EXTRA_SPACING * 2;
1877 reset_hint_pos (x3, y2);
1878 CSetSizeHintPos (identifier);
1879 /* map us */
1880 CMapDialog (identifier);
1881 /* enable resizing */
1882 CSetWindowResizable (identifier, FONT_MEAN_WIDTH * 40, min (FONT_PIX_PER_LINE * 5 + 230, w->height), 1600, 1200); /* minimum and maximum sizes */
1883
1884 return win;
1885 }
1886
1887 /* options */
1888 #define GETFILE_GET_DIRECTORY 1
1889 #define GETFILE_GET_EXISTING_FILE 2
1890 #define GETFILE_BROWSER 4
1891
1892 void input_insert (CWidget * w, int c);
1893
1894 #if 0
1895 static char *file_error (void)
1896 {
1897 if (errno) {
1898 char *error_msg;
1899 #ifdef HAVE_STRERROR
1900 error_msg = _ (strerror (errno));
1901 #else
1902 extern int sys_nerr;
1903 extern char *sys_errlist[];
1904 if ((0 <= errno) && (errno < sys_nerr))
1905 error_msg = _ (sys_errlist[errno]);
1906 else
1907 /* The returned value, 'errno' has an unknown meaning */
1908 error_msg = _ ("strange errno");
1909 #endif
1910 return catstrs ("[", error_msg, "]", NULL);
1911 }
1912 return "";
1913 }
1914 #endif
1915
run_cmd(const char * fmt,...)1916 static void run_cmd (const char *fmt,...)
1917 {
1918 signal (SIGCHLD, SIG_IGN);
1919 if (!fork ()) { /* child process */
1920 va_list pa;
1921 char *str;
1922
1923 va_start (pa, fmt);
1924 str = vsprintf_alloc (fmt, pa);
1925 va_end (pa);
1926
1927 execlp ("/bin/sh", "/bin/sh", "-c", str, (char *) NULL);
1928
1929 /* if all is fine then the thread will exit here */
1930 /* so displaying error if not */
1931 fprintf (stderr, "\nBad luck running command [%s].\n", str);
1932 exit (0); /*thread completed */
1933 }
1934 }
1935
1936 static char *empty_line = "";
1937
item_selected(const char * identifier,NeXTFileBrowser * browser,NeXTDir * dir)1938 static char *item_selected (const char *identifier, NeXTFileBrowser * browser, NeXTDir * dir)
1939 {
1940 char *ptr = NULL;
1941 CWidget *w;
1942
1943 if (!browser || !identifier)
1944 return 0; /* something terrible has happen ! */
1945 if (dir == NULL) {
1946 if ((w = CIdent (browser->name)) && w->text)
1947 {
1948 ptr = strdup (w->text);
1949 if (strlen (w->text))
1950 CAddToTextInputHistory (browser->name, w->text);
1951 }
1952 } else {
1953 ptr = commit (browser->tree, dir);
1954 if (browser->tree->dirty)
1955 link_browser_to_data (browser, 0);
1956 }
1957
1958 if (ptr == NULL)
1959 ptr = empty_line;
1960 else if (strcmp (identifier, "browser") == 0) {
1961 struct file_entry *item = &(dir->list[dir->cursor]);
1962
1963 if ((item->stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
1964 run_cmd (ptr);
1965 } else {
1966 static char *default_editor = "smalledit";
1967 static char *editor = NULL;
1968 if (editor == NULL) {
1969 editor = getenv ("EDITOR");
1970 if (editor == NULL)
1971 editor = default_editor;
1972 }
1973 run_cmd ("%s %s", editor, ptr);
1974 }
1975 free (ptr);
1976 ptr = empty_line;
1977 }
1978 return ptr;
1979 }
1980
1981 char *get_filelist_line_short (void *data, int line_number, char buffer[1024]);
1982
cursor_moved(NeXTFileBrowser * browser,NeXTDir * dir,CWidget * list_w)1983 static void cursor_moved (NeXTFileBrowser * browser, NeXTDir * dir, CWidget * list_w)
1984 {
1985 if (browser && dir && list_w) {
1986 dir_save_position (dir, list_w->cursor, list_w->current, list_w->firstline);
1987 if (dir->cursor >= 0) {
1988 char buffer[512];
1989 #if 0
1990 struct file_entry *item = &(dir->list[dir->cursor]);
1991 char *tail;
1992 #endif
1993 if (get_filelist_line_short (dir->list, dir->cursor, buffer))
1994 CRedrawDynText (browser->fileattr, buffer);
1995 }
1996 }
1997 }
1998
1999 /*
2000 Returns "" on no file entered and NULL on exit (i.e. Cancel button pushed)
2001 else returns the file or directory. Result must be immediately copied.
2002 Result must not be free'd.
2003 */
handle_browser(const char * identifier,CEvent * cwevent,int options)2004 static char *handle_browser (const char *identifier, CEvent * cwevent, int options)
2005 {
2006 #if 0
2007 int i;
2008 #endif
2009 CWidget *w = CIdent (identifier);
2010 NeXTFileBrowser *browser;
2011 int flist = -1;
2012 char *ptr;
2013
2014 if (!w)
2015 return empty_line;
2016
2017 if (cwevent->command == CK_Cancel)
2018 return 0;
2019 if ((browser = (NeXTFileBrowser *) w->hook) == NULL)
2020 return empty_line;
2021
2022 /* that will be our subwidget name : */
2023 if ((ptr = strrchr (cwevent->ident, '.')) == NULL)
2024 /* nothing to do here - messege for self */
2025 return empty_line;
2026
2027 ptr++;
2028 /* lets find out which one we have (starting from the shortest) */
2029 if (strcmp (ptr, "ok") == 0)
2030 /* we take text from text input and use it as filename */
2031 return item_selected (identifier, browser, NULL);
2032 else if (strncmp (ptr, "flist", 5) == 0)
2033 /* all filelists ends with flistNNN */
2034 flist = atoi (ptr + 5); /* will process them later */
2035 else if (strcmp (ptr, "cancel") == 0)
2036 return 0;
2037 else if (strcmp (ptr, "finp") == 0) {
2038 if (cwevent->type == KeyPress && cwevent->command == CK_Enter)
2039 return item_selected (identifier, browser, NULL);
2040 return empty_line;
2041 } else if (strcmp (ptr, "filtinp") == 0) {
2042 if (cwevent->type == KeyPress && cwevent->command == CK_Enter)
2043 filter_changed (browser, browser->tree->selected);
2044 return empty_line;
2045 }
2046 if (flist >= 0 && flist < browser->numpanes) { /* filelist event */
2047 NeXTDir *dir = get_dir_by_num (browser->tree, flist + browser->tree->pos);
2048 CWidget *list_w = CIdent (browser->lists[flist]);
2049
2050 /* saving status */
2051 browser->focused = flist;
2052 browser->tree->selected = dir;
2053
2054 switch (cwevent->type) {
2055 case EnterNotify:
2056 CFocus (list_w);
2057 update_filter (browser, dir);
2058 break;
2059 /* case LeaveNotify :
2060 fprintf(stderr, "LeaveNotify\n");
2061 browser->focused = -1 ;
2062 CFocus( CIdent(browser->name));
2063 break ;
2064 */
2065 case ButtonPress:
2066 case ButtonRelease:
2067 case MotionNotify:
2068 cursor_moved (browser, dir, list_w);
2069 if (cwevent->type != ButtonRelease)
2070 update_input (browser, dir);
2071 else if (cwevent->double_click)
2072 return item_selected (identifier, browser, dir);
2073 break;
2074 case KeyPress:
2075 {
2076 int scroll = 0;
2077 switch (cwevent->command) {
2078 case CK_Enter:
2079 update_input (browser, dir);
2080 return item_selected (identifier, browser, dir);
2081 case CK_Up:
2082 case CK_Down:
2083 case CK_Page_Up:
2084 case CK_Page_Down:
2085 cursor_moved (browser, dir, list_w);
2086 break;
2087 case CK_Left:
2088 if (browser->tree->pos > 0)
2089 scroll = -1;
2090 break;
2091 case CK_Right:
2092 if (browser->tree->pos < browser->tree->numdirs - browser->numpanes)
2093 scroll = 1;
2094 break;
2095 case CK_Home:
2096 scroll = -(browser->tree->pos);
2097 break;
2098 case CK_End:
2099 scroll = (browser->tree->numdirs - browser->numpanes) - browser->tree->pos;
2100 break;
2101 case CK_BackSpace:
2102 /* remove last typed partial filename char */
2103 goto_partial_file_name (browser, dir, 0);
2104 break;
2105 default:
2106 if (cwevent->insert > 0) {
2107 if (cwevent->key == ' ')
2108 update_input (browser, dir);
2109 else if (isprint (cwevent->key)) {
2110 goto_partial_file_name (browser, dir, cwevent->key);
2111 cursor_moved (browser, dir, list_w);
2112 }
2113 }
2114 }
2115 if (scroll != 0) {
2116 browser->tree->pos += scroll;
2117 link_browser_to_data (browser, 0);
2118 dir = get_dir_by_num (browser->tree, browser->tree->pos + flist);
2119 update_filter (browser, dir);
2120 update_scrollbar (w->hori_scrollbar, browser, 1);
2121 }
2122 }
2123 break;
2124 default:
2125 break;
2126 }
2127 }
2128 return empty_line;
2129 }
2130
2131 Window find_mapped_window (Window w);
2132
2133 /* result must be free'd */
look_next_get_file_or_dir(Window parent,int x,int y,const char * dir,const char * file,const char * label,int options)2134 static char *look_next_get_file_or_dir (Window parent, int x, int y,
2135 const char *dir, const char *file, const char *label, int options)
2136 {
2137 CEvent cwevent;
2138 XEvent xevent;
2139 CState s;
2140 CWidget *w;
2141
2142 CBackupState (&s);
2143 CDisable ("*");
2144 CEnable ("_cfileBr*");
2145
2146 parent = find_mapped_window (parent);
2147 if (!(x | y)) {
2148 x = 20;
2149 y = 20;
2150 }
2151 draw_file_browser ("CGetFile", parent, x, y, dir, file, label);
2152
2153 CFocus (CIdent ("CGetFile.finp"));
2154
2155 file = "";
2156 do {
2157 CNextEvent (&xevent, &cwevent);
2158 if (xevent.type == Expose || !xevent.type
2159 || xevent.type == InternalExpose || xevent.type == TickEvent)
2160 continue;
2161 if (!CIdent ("CGetFile")) {
2162 file = 0;
2163 break;
2164 }
2165 if (xevent.type == Expose || !xevent.type || xevent.type == AlarmEvent
2166 || xevent.type == InternalExpose || xevent.type == TickEvent) {
2167 file = "";
2168 continue;
2169 }
2170 file = handle_browser ("CGetFile", &cwevent, options);
2171 if (!file)
2172 break;
2173 } while (!(*file));
2174
2175 /* here we want to add the complete path to the text-input history: */
2176 w = CIdent ("CGetFile.finp");
2177 if (w) {
2178 if (w->text) {
2179 free (w->text);
2180 w->text = 0;
2181 }
2182 if (file)
2183 w->text = (char *) strdup (file);
2184 }
2185 CDestroyWidget ("CGetFile"); /* text is added to history
2186 when text-input widget is destroyed */
2187 CRestoreState (&s);
2188
2189 if (file)
2190 return (char *) ((*file) ? file : 0);
2191 else
2192 return 0;
2193 }
2194
2195 /*
2196 cb_browser():
2197 1) if filelist has decided that browser should be notifyed about event
2198 it sets CEvent.ident member, and we get into handle_browser.
2199 That includes events external for filelist (Left, Right, Home,
2200 End, Space, Enter, Esc) even thou filelist does no processing of it.
2201 Note also that if user types in some characters while in filelist -
2202 filelist will do search for filename, not the browser, as it was
2203 happening in original version.
2204 2) handle_browser do all the neccessary processing of received events -
2205 updates edit boxes, updates NexTDirTree status, changes dir if needed,
2206 scrolls left, right, home and end.
2207 Sasha.
2208 */
2209
get_browser_name(char * ident,char * buffer)2210 static char *get_browser_name (char *ident, char *buffer)
2211 {
2212 char *start = buffer;
2213 while (*ident && *ident != '.')
2214 *(buffer++) = *(ident++);
2215 *buffer = '\0';
2216
2217 return start;
2218 }
2219
cb_browser(CWidget * w,XEvent * x,CEvent * c)2220 static int cb_browser (CWidget * w, XEvent * x, CEvent * c)
2221 {
2222 char id[32];
2223 get_browser_name (w->ident, id);
2224 if (!handle_browser (id, c, GETFILE_BROWSER)) {
2225 w = CIdent (catstrs (id, ".finp", NULL));
2226 if (w)
2227 if (w->text) {
2228 free (w->text);
2229 w->text = 0;
2230 }
2231 CDestroyWidget (id);
2232 }
2233 return 0;
2234 }
2235
look_next_draw_browser(const char * ident,Window parent,int x,int y,const char * dir,const char * file,const char * label)2236 static void look_next_draw_browser (const char *ident, Window parent, int x, int y,
2237 const char *dir, const char *file, const char *label)
2238 {
2239 CWidget *w;
2240
2241 if (!(parent | x | y)) {
2242 parent = CFirstWindow;
2243 x = 20;
2244 y = 20;
2245 }
2246 draw_file_browser (ident, parent, x, y, dir, file, label);
2247 if ((w = CIdent (ident))) {
2248 NeXTFileBrowser *browser = w->hook;
2249 int i;
2250 if (browser) {
2251 for (i = 0; i < browser->numpanes; i++)
2252 CAddCallback (browser->lists[i], cb_browser);
2253
2254 CAddCallback (browser->name, cb_browser);
2255 CAddCallback (browser->filter, cb_browser);
2256 CAddCallback (catstrs (ident, ".ok", NULL), cb_browser);
2257 CAddCallback (catstrs (ident, ".cancel", NULL), cb_browser);
2258
2259 CFocus (CIdent (catstrs (ident, ".finp", NULL)));
2260 }
2261 }
2262 }
2263
2264
2265 /* }}} file browser stuff */
2266
2267 /* {{{ scrollbar extras */
2268
2269 #define PURENEXT
2270 /*****************************************/
2271 /* start NeXT scrollbar specific fetures */
2272 /* could be anything from 13 to 19 but the true NeXT is 17 */
2273 #define SB_WIDTH 17
2274 /* this will define somemore parameters for shaping NeXTish scrollbars */
2275 /* NEXT_SCROLL_CLEAN if defined removes shades of grey from buttons */
2276 #undef NEXT_SCROLL_CLEAN
2277 #define NEXT_SCROLL_SQUARE_ARROWS
2278 #define SB_BORDER_WIDTH 1
2279 /* this makes buttons thinner then scrollbar's base ( if more then 0 ) */
2280 #define SIDE_STEP_WIDTH 1
2281 /* end NeXT scrollbar specific fetures */
2282 /*****************************************/
2283
2284 /*****************************************/
2285 /* scrollbarr configuration stuff */
2286
2287 #define Xdisplay CDisplay
2288 #define Xroot CRoot
2289 #define Xdepth CDepth
2290
2291 static char *SCROLLER_DIMPLE[] =
2292 {
2293 ".%###.",
2294 "%#%%%%",
2295 "#%%...",
2296 "#%.. ",
2297 "#%. ",
2298 ".%. ."
2299 };
2300
2301 #define SCROLLER_DIMPLE_WIDTH 6
2302 #define SCROLLER_DIMPLE_HEIGHT 6
2303
2304 static char *SCROLLER_ARROW[4][13] =
2305 {
2306 {".............",
2307 ".............",
2308 "......%......",
2309 "......#......",
2310 ".....%#%.....",
2311 ".....###.....",
2312 "....%###%....",
2313 "....#####....",
2314 "...%#####%...",
2315 "...#######...",
2316 "..%#######%..",
2317 ".............",
2318 "............."
2319 },
2320 {".............",
2321 ".............",
2322 "..%#######%..",
2323 "...#######...",
2324 "...%#####%...",
2325 "....#####....",
2326 "....%###%....",
2327 ".....###.....",
2328 ".....%#%.....",
2329 "......#......",
2330 "......%......",
2331 ".............",
2332 "............."
2333 },
2334 {" ",
2335 " ",
2336 " % ",
2337 " % ",
2338 " %%% ",
2339 " %%% ",
2340 " %%%%% ",
2341 " %%%%% ",
2342 " %%%%%%% ",
2343 " %%%%%%% ",
2344 " %%%%%%%%% ",
2345 " ",
2346 " "
2347 },
2348 {" ",
2349 " ",
2350 " %%%%%%%%% ",
2351 " %%%%%%% ",
2352 " %%%%%%% ",
2353 " %%%%% ",
2354 " %%%%% ",
2355 " %%% ",
2356 " %%% ",
2357 " % ",
2358 " % ",
2359 " ",
2360 " "
2361 }};
2362
2363 #define ARROW_SOURCE_WIDTH 13
2364 #define ARROW_SOURCE_HEIGHT 13
2365
2366 typedef struct {
2367 Pixmap icon;
2368 Pixmap icon_mask;
2369 int origin_x, origin_y, width, height;
2370 } Icon;
2371
2372 typedef struct {
2373 unsigned arrow_width, arrow_height;
2374 int bValid;
2375 Icon dimple;
2376 Icon Arrows[8];
2377 Pixmap stipple;
2378 /* this stuff is related to cache */
2379 XRectangle thumb;
2380 XRectangle buttons[2];
2381 unsigned int button_arrow[2];
2382 unsigned int width, height;
2383 int work_length;
2384 Pixmap cache;
2385 } ScrollIcons;
2386
2387 #define UP_ARROW (next_icons->Arrows[0])
2388 #define UP_ARROW_HI (next_icons->Arrows[1])
2389 #define DOWN_ARROW (next_icons->Arrows[2])
2390 #define DOWN_ARROW_HI (next_icons->Arrows[3])
2391
2392 #define ARROW_WIDTH (next_icons->arrow_width)
2393 #define ARROW_HEIGHT (next_icons->arrow_height)
2394
2395 #define BEVEL_HI_WIDTH 1
2396 #define BEVEL_LO_WIDTH 2
2397 #define BEVEL_SIZE (BEVEL_HI_WIDTH+BEVEL_LO_WIDTH)
2398
2399 #define SB_BUTTON_HEIGHT (BEVEL_SIZE+ARROW_HEIGHT)
2400 #define SB_BUTTONS_HEIGHT ((SB_BUTTON_HEIGHT<<1)-SIDE_STEP_WIDTH)
2401
2402 #ifndef SB_BORDER_WIDTH
2403 #define SB_BORDER_WIDTH 1
2404 #endif
2405 #define SB_BORDER_SIZE (SB_BORDER_WIDTH<<1)
2406
2407 #ifndef SIDE_STEP_WIDTH
2408 #define SIDE_STEP_WIDTH 0
2409 #endif
2410
2411 #define SB_MIN_THUMB_SIZE (SCROLLER_DIMPLE_WIDTH+2+BEVEL_SIZE)
2412
2413 /* end NeXT unconfigurable stuff */
2414 /*********************************/
2415
2416 #define stp_width 8
2417 #define stp_height 8
2418
2419 #if 0
2420 static unsigned char stp_bits[] =
2421 {
2422 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
2423 #endif
2424
2425 #undef TRANSPARENT
2426 #define IS_TRANSP_SCROLL 0
2427
2428
2429 typedef struct {
2430 GC blackGC;
2431 GC whiteGC;
2432 GC darkGC;
2433 GC maskGC;
2434 GC maskGC_0;
2435 } IconGC;
2436
init_scroll_size(ScrollIcons * next_icons)2437 static void init_scroll_size (ScrollIcons * next_icons)
2438 {
2439 ARROW_WIDTH = (SB_WIDTH - BEVEL_SIZE - SB_BORDER_SIZE - SIDE_STEP_WIDTH);
2440 ARROW_WIDTH = min (ARROW_WIDTH, ARROW_SOURCE_WIDTH);
2441
2442 #ifdef NEXT_SCROLL_SQUARE_ARROWS
2443 ARROW_HEIGHT = ARROW_WIDTH;
2444 #else
2445 ARROW_HEIGHT = ARROW_SOURCE_HEIGHT;
2446 #endif
2447 next_icons->bValid = 1;
2448 }
2449
2450 /* PROTO */
GetScrollArrowsHeight(ScrollIcons * next_icons)2451 unsigned GetScrollArrowsHeight (ScrollIcons * next_icons)
2452 {
2453 if (!next_icons->bValid)
2454 init_scroll_size (next_icons);
2455 return (SB_BUTTONS_HEIGHT);
2456 }
2457
CheckIconGC(IconGC * igc,Pixmap icon,Pixmap icon_mask)2458 static void CheckIconGC (IconGC * igc, Pixmap icon, Pixmap icon_mask)
2459 {
2460 XGCValues values;
2461 unsigned long valuemask = GCForeground | GCGraphicsExposures;
2462
2463 values.graphics_exposures = False;
2464
2465 if (igc == NULL)
2466 return;
2467 if (igc->maskGC == None) {
2468 values.foreground = 1;
2469 igc->maskGC = XCreateGC (Xdisplay, icon_mask, valuemask, &values);
2470 }
2471 if (igc->maskGC_0 == None) {
2472 values.foreground = 0;
2473 igc->maskGC_0 = XCreateGC (Xdisplay, icon_mask, valuemask, &values);
2474 }
2475 if (igc->whiteGC == None) {
2476 values.foreground = COLOR_WHITE;
2477 igc->whiteGC = XCreateGC (Xdisplay, icon, valuemask, &values);
2478 }
2479 if (igc->darkGC == None) {
2480 values.foreground = COLOR_DARK;
2481 igc->darkGC = XCreateGC (Xdisplay, icon, valuemask, &values);
2482 }
2483 if (igc->blackGC == None) {
2484 values.foreground = COLOR_BLACK;
2485 igc->blackGC = XCreateGC (Xdisplay, icon, valuemask, &values);
2486 }
2487 }
2488
FreeIconGC(IconGC * igc)2489 static void FreeIconGC (IconGC * igc)
2490 {
2491 if (igc) {
2492 if (igc->maskGC != None) {
2493 XFreeGC (Xdisplay, igc->maskGC);
2494 igc->maskGC = None;
2495 }
2496 if (igc->maskGC_0 != None) {
2497 XFreeGC (Xdisplay, igc->maskGC_0);
2498 igc->maskGC_0 = None;
2499 }
2500 if (igc->whiteGC == None) {
2501 XFreeGC (Xdisplay, igc->whiteGC);
2502 igc->whiteGC = None;
2503 }
2504 if (igc->darkGC == None) {
2505 XFreeGC (Xdisplay, igc->darkGC);
2506 igc->darkGC = None;
2507 }
2508 if (igc->blackGC != None) {
2509 XFreeGC (Xdisplay, igc->blackGC);
2510 igc->blackGC = None;
2511 }
2512 }
2513 }
2514
renderIcon(Window win,char ** data,Icon * pIcon,IconGC * igc,Bool rotate)2515 static void renderIcon (Window win, char **data, Icon * pIcon, IconGC * igc, Bool rotate)
2516 {
2517 Pixmap d, mask;
2518 register int i, k;
2519 int x, y, max_x, max_y;
2520 GC maskgc, paintgc;
2521 char pixel;
2522
2523 d = XCreatePixmap (Xdisplay, win, pIcon->width, pIcon->height, Xdepth);
2524 mask = XCreatePixmap (Xdisplay, win, pIcon->width, pIcon->height, 1);
2525
2526 if (rotate) {
2527 max_x = pIcon->height;
2528 max_y = pIcon->width;
2529 } else {
2530 max_x = pIcon->width;
2531 max_y = pIcon->height;
2532 }
2533
2534 CheckIconGC (igc, d, mask);
2535 y = pIcon->origin_y;
2536
2537 for (i = 0; i < max_y; y++, i++) {
2538 x = pIcon->origin_x;
2539 for (k = 0; k < max_x; k++, x++) {
2540 maskgc = igc->maskGC;
2541 if (rotate)
2542 pixel = data[x][y];
2543 else
2544 pixel = data[y][x];
2545 switch (pixel) {
2546 case ' ':
2547 case 'w':
2548 paintgc = igc->whiteGC;
2549 break;
2550 case '%':
2551 case 'd':
2552 paintgc = igc->darkGC;
2553 break;
2554 case '#':
2555 case 'b':
2556 paintgc = igc->blackGC;
2557 break;
2558 case '.':
2559 case 'l':
2560 default:
2561 paintgc = CGC;
2562 maskgc = igc->maskGC_0;
2563 break;
2564 }
2565 XDrawPoint (Xdisplay, d, paintgc, k, i);
2566 XDrawPoint (Xdisplay, mask, maskgc, k, i);
2567 }
2568 }
2569
2570 pIcon->icon = d;
2571 pIcon->icon_mask = mask;
2572 }
2573
2574 static ScrollIcons *
init_next_icons(Window win)2575 init_next_icons (Window win)
2576 {
2577 unsigned arrow_x_offset, arrow_y_offset;
2578 IconGC icongc =
2579 {None, None, None, None};
2580 int i;
2581 ScrollIcons *next_icons = calloc (1, sizeof (ScrollIcons));
2582
2583 if (next_icons == NULL)
2584 return next_icons;
2585
2586 CSetColor (COLOR_FLAT);
2587
2588 next_icons->dimple.width = SCROLLER_DIMPLE_WIDTH;
2589 next_icons->dimple.height = SCROLLER_DIMPLE_WIDTH;
2590 renderIcon (win, SCROLLER_DIMPLE, &(next_icons->dimple), &icongc, False);
2591
2592 init_scroll_size (next_icons);
2593 arrow_x_offset = (ARROW_SOURCE_WIDTH - ARROW_WIDTH) >> 1;
2594 #ifdef NEXT_SCROLL_SQUARE_ARROWS
2595 arrow_y_offset = arrow_x_offset;
2596 #else
2597 arrow_y_offset = 0; /* not implemented yet */
2598 #endif
2599
2600 for (i = 0; i < 4; i++) {
2601 next_icons->Arrows[i].origin_x = arrow_x_offset;
2602 next_icons->Arrows[i].origin_y = arrow_y_offset;
2603 next_icons->Arrows[i].width = ARROW_WIDTH;
2604 next_icons->Arrows[i].height = ARROW_HEIGHT;
2605 renderIcon (win, SCROLLER_ARROW[i], &(next_icons->Arrows[i]), &icongc, False);
2606 }
2607 for (; i < 8; i++) {
2608 next_icons->Arrows[i].origin_x = arrow_y_offset;
2609 next_icons->Arrows[i].origin_y = arrow_x_offset;
2610 next_icons->Arrows[i].width = ARROW_HEIGHT;
2611 next_icons->Arrows[i].height = ARROW_WIDTH;
2612 renderIcon (win, SCROLLER_ARROW[i - 4], &(next_icons->Arrows[i]), &icongc, True);
2613 }
2614
2615 FreeIconGC (&icongc);
2616
2617 next_icons->stipple = XCreatePixmap (Xdisplay, win, 2, 2, Xdepth);
2618 XDrawPoint (Xdisplay, next_icons->stipple, CGC, 0, 0);
2619 XDrawPoint (Xdisplay, next_icons->stipple, CGC, 1, 1);
2620
2621 CSetColor (COLOR_DARK);
2622 XDrawPoint (Xdisplay, next_icons->stipple, CGC, 0, 1);
2623 XDrawPoint (Xdisplay, next_icons->stipple, CGC, 1, 0);
2624
2625 return next_icons;
2626 }
2627
free_next_icons(void * ptr)2628 void free_next_icons (void *ptr)
2629 {
2630 ScrollIcons *next_icons = (ScrollIcons *) ptr;
2631 if (next_icons) {
2632 register int i;
2633 if (next_icons->dimple.icon) {
2634 XFreePixmap (Xdisplay, next_icons->dimple.icon);
2635 next_icons->dimple.icon = None;
2636 }
2637 if (next_icons->stipple) {
2638 XFreePixmap (Xdisplay, next_icons->stipple);
2639 next_icons->stipple = None;
2640 }
2641 for (i = 0; i < 4; i++)
2642 if (next_icons->Arrows[i].icon) {
2643 XFreePixmap (Xdisplay, next_icons->Arrows[i].icon);
2644 next_icons->Arrows[i].icon = None;
2645 }
2646 if (next_icons->cache) {
2647 XFreePixmap (Xdisplay, next_icons->cache);
2648 next_icons->cache = None;
2649 }
2650 }
2651 }
2652
render_next_icon(Drawable d,Icon * i,int x,int y)2653 static void render_next_icon (Drawable d, Icon * i, int x, int y)
2654 {
2655 #ifdef TRANSPARENT
2656 if (IS_TRANSP_SCROLL) {
2657 XSetClipMask (Xdisplay, CGC, i->icon_mask);
2658 XSetClipOrigin (Xdisplay, CGC, x, y);
2659 }
2660 #endif
2661 XCopyArea (Xdisplay, i->icon, d, CGC, 0, 0,
2662 i->width, i->height, x, y);
2663
2664 #ifdef TRANSPARENT
2665 if (IS_TRANSP_SCROLL)
2666 XSetClipMask (Xdisplay, CGC, None);
2667 #endif
2668 }
2669
2670
2671 /* Draw bezel & arrows */
render_next_button(Drawable d,XRectangle * rec,Icon * icon,Bool pressed)2672 static void render_next_button (Drawable d, XRectangle * rec, Icon * icon, Bool pressed)
2673 {
2674 int x2 = rec->x + rec->width - 1, y2 = rec->y + rec->height - 1;
2675 CSetColor ((pressed) ? COLOR_BLACK : COLOR_WHITE);
2676
2677 CLine (d, rec->x, rec->y, rec->x, y2);
2678 CLine (d, rec->x, rec->y, x2, rec->y);
2679
2680 CSetColor ((pressed) ? COLOR_WHITE : COLOR_BLACK);
2681 CLine (d, rec->x, y2, x2, y2);
2682 CLine (d, x2, y2, x2, rec->y);
2683
2684 if (!pressed)
2685 CSetColor (COLOR_FLAT);
2686
2687 CRectangle (d, rec->x + 1, rec->y + 1, rec->width - 3, rec->height - 3);
2688
2689 render_next_icon (d, icon, rec->x + ((rec->width - icon->width) / 2),
2690 rec->y + ((rec->height - icon->height) / 2));
2691 }
2692
check_cache(ScrollIcons * next_icons,Window win,int width,int height,int pos,int prop,int flags)2693 Bool check_cache (ScrollIcons * next_icons, Window win, int width, int height, int pos, int prop, int flags)
2694 {
2695 unsigned int l, wl, thumb_start, thumb_length;
2696 unsigned int button_arrow[2];
2697 #if 0
2698 int cache_valid = 0;
2699 #endif
2700
2701 if (width > height) {
2702 if (height > SB_WIDTH + SB_BORDER_SIZE) /* vertical */
2703 height = SB_WIDTH + SB_BORDER_SIZE;
2704 l = width;
2705 } else {
2706 if (width > SB_WIDTH + SB_BORDER_SIZE)
2707 width = SB_WIDTH + SB_BORDER_SIZE;
2708 l = height;
2709 }
2710 wl = l - SB_BORDER_SIZE - SB_BUTTONS_HEIGHT - SIDE_STEP_WIDTH;
2711
2712 button_arrow[0] = 0;
2713 button_arrow[1] = 1;
2714
2715 if (prop == 65535 || prop == 0) {
2716 thumb_length = 0;
2717 thumb_start = 0;
2718 } else {
2719 thumb_length = (double) (wl * prop) / 65535.0;
2720 if (thumb_length < SB_MIN_THUMB_SIZE) {
2721 wl -= SB_MIN_THUMB_SIZE - thumb_length;
2722 thumb_length = SB_MIN_THUMB_SIZE;
2723 } else if (thumb_length > wl)
2724 thumb_length = wl;
2725
2726 if (pos >= 65535 - prop - 1)
2727 thumb_start = l - thumb_length - SB_BUTTONS_HEIGHT;
2728 else
2729 thumb_start = ((double) (wl * pos) / 65535.0) + SB_BORDER_WIDTH;
2730
2731 if (thumb_start - SB_BORDER_WIDTH > wl - thumb_length)
2732 thumb_start = SB_BORDER_WIDTH + wl - thumb_length;
2733 if (thumb_start < SB_BORDER_WIDTH)
2734 thumb_start = SB_BORDER_WIDTH;
2735
2736 next_icons->work_length = wl;
2737
2738 if (!(flags & 0x20)) {
2739 if ((flags & 0x0f) == 2)
2740 button_arrow[0] = 2;
2741 if ((flags & 0x0f) == 5)
2742 button_arrow[1] = 3;
2743 }
2744 }
2745 if (l != height) {
2746 button_arrow[0] += 4;
2747 button_arrow[1] += 4;
2748 }
2749 if (next_icons->cache) {
2750 if (width == next_icons->width && height == next_icons->height) {
2751 if (button_arrow[0] == next_icons->button_arrow[0] &&
2752 button_arrow[1] == next_icons->button_arrow[1]) {
2753 if (l == height) {
2754 if (next_icons->thumb.height == thumb_length &&
2755 next_icons->thumb.y == thumb_start)
2756 return True;
2757 } else if (next_icons->thumb.width == thumb_length &&
2758 next_icons->thumb.x == thumb_start)
2759 return True;
2760 }
2761 } else {
2762 XFreePixmap (Xdisplay, next_icons->cache);
2763 next_icons->cache = None;
2764 }
2765 }
2766 next_icons->button_arrow[0] = button_arrow[0];
2767 next_icons->button_arrow[1] = button_arrow[1];
2768
2769 if (l == height) {
2770 next_icons->thumb.height = thumb_length;
2771 next_icons->thumb.y = thumb_start;
2772 next_icons->thumb.width = SB_WIDTH;
2773 next_icons->thumb.x = SB_BORDER_WIDTH;
2774 } else {
2775 next_icons->thumb.width = thumb_length;
2776 next_icons->thumb.x = thumb_start;
2777 next_icons->thumb.height = SB_WIDTH;
2778 next_icons->thumb.y = SB_BORDER_WIDTH;
2779 }
2780 if (next_icons->cache == None) { /* create double buffer */
2781 next_icons->cache = XCreatePixmap (Xdisplay, win, width, height, Xdepth);
2782 next_icons->width = width;
2783 next_icons->height = height;
2784 if (l == height) {
2785 next_icons->buttons[0].x = next_icons->buttons[1].x = SB_BORDER_WIDTH;
2786 next_icons->buttons[0].width = next_icons->buttons[1].width = SB_WIDTH;
2787 next_icons->buttons[0].height = next_icons->buttons[1].height = SB_BUTTON_HEIGHT;
2788 next_icons->buttons[1].y = l - next_icons->buttons[1].height - SIDE_STEP_WIDTH;
2789 next_icons->buttons[0].y = next_icons->buttons[1].y - next_icons->buttons[0].height;
2790 } else {
2791 next_icons->buttons[0].y = next_icons->buttons[1].y = SB_BORDER_WIDTH;
2792 next_icons->buttons[0].height = next_icons->buttons[1].height = SB_WIDTH;
2793 next_icons->buttons[0].width = next_icons->buttons[1].width = SB_BUTTON_HEIGHT;
2794 next_icons->buttons[1].x = l - next_icons->buttons[1].width - SIDE_STEP_WIDTH;
2795 next_icons->buttons[0].x = next_icons->buttons[1].x - next_icons->buttons[0].width;
2796 }
2797 }
2798 return False;
2799 }
2800
scrollbar_fill_back(ScrollIcons * next_icons)2801 void scrollbar_fill_back (ScrollIcons * next_icons)
2802 {
2803 int x2, y2;
2804 register int i;
2805
2806 /* draw the background */
2807 XSetTile (Xdisplay, CGC, next_icons->stipple);
2808 XSetFillStyle (Xdisplay, CGC, FillTiled);
2809 XSetTSOrigin (Xdisplay, CGC, 0, 0);
2810
2811 CSetColor (COLOR_WHITE);
2812 CRectangle (next_icons->cache,
2813 SB_BORDER_WIDTH, SB_BORDER_WIDTH,
2814 (next_icons->width) - SB_BORDER_SIZE,
2815 (next_icons->height) - SB_BORDER_SIZE);
2816
2817 XSetTile (Xdisplay, CGC, None);
2818 XSetFillStyle (Xdisplay, CGC, FillSolid);
2819
2820 x2 = next_icons->width - 1;
2821 y2 = next_icons->height - 1;
2822
2823 CSetColor (COLOR_WHITE);
2824 for (i = 0; i < SB_BORDER_WIDTH; i++) {
2825 CLine (next_icons->cache, i, y2 - i, x2 - i, y2 - i);
2826 CLine (next_icons->cache, x2 - i, y2 - i, x2 - i, i);
2827 }
2828 CSetColor (COLOR_BLACK);
2829 for (i = 0; i < SB_BORDER_WIDTH; i++) {
2830 CLine (next_icons->cache, i, y2 - i, i, i);
2831 CLine (next_icons->cache, i, i, x2 - i, i);
2832 }
2833
2834
2835 }
2836
render_next_scrollbar(ScrollIcons * next_icons,Window win,int x,int y,int width,int height,int pos,int prop,int flags)2837 int render_next_scrollbar (ScrollIcons * next_icons, Window win, int x, int y, int width, int height, int pos, int prop, int flags)
2838 {
2839 int cache_valid;
2840
2841 cache_valid = check_cache (next_icons, win, width, height, pos, prop, flags);
2842 /*fprintf( stderr, "%dx%d,pos: %d, prop: %d ->%s, whole: %dx%d, thumb: %dx%d%+d%+d\n",
2843 width, height, pos, prop,
2844 (cache_valid)?"Cached":"Redrawing",
2845 next_icons->width, next_icons->height,
2846 next_icons->thumb.width, next_icons->thumb.height,
2847 next_icons->thumb.x, next_icons->thumb.y );
2848 */ if (!cache_valid) {
2849 int i;
2850 scrollbar_fill_back (next_icons);
2851 if (next_icons->thumb.width > 0 &&
2852 next_icons->thumb.height > 0) {
2853 render_next_button (next_icons->cache,
2854 &(next_icons->thumb),
2855 &(next_icons->dimple),
2856 False);
2857 for (i = 0; i < 2; i++) {
2858 render_next_button (next_icons->cache,
2859 &(next_icons->buttons[i]),
2860 &(next_icons->Arrows[next_icons->button_arrow[i]]),
2861 (next_icons->button_arrow[i] & 0x02));
2862 }
2863 }
2864 }
2865 XCopyArea (Xdisplay, next_icons->cache, win, CGC, 0, 0, next_icons->width, next_icons->height, 0, 0);
2866 return 1;
2867 }
2868
2869 /* }}} end scrollbar extras */
2870
2871 int find_menu_hotkey (struct menu_item m[], int this, int num);
2872
2873 /* outermost bevel */
2874 #define BEVEL_MAIN 1
2875 /* next-outermost bevel */
2876 #define BEVEL_IN 1
2877 #define BEVEL_OUT 1
2878 /* between items, and between items and next-outermost bevel */
2879 #define SPACING 0
2880
2881 /* between items rectangle and text */
2882 #define RELIEF 4
2883
2884 #define S SPACING
2885 /* between window border and items */
2886 #define O (BEVEL_OUT + SPACING)
2887 /* total height of an item */
2888
2889 /* size of bar item */
2890 #define BAR_HEIGHT H
2891 #define ITEM_BEVEL_TYPE 0
2892 #define ITEM_BEVEL 1
2893
2894 #define H (FONT_PIX_PER_LINE + RELIEF * 2 + 1)
2895
2896 #define B BAR_HEIGHT
2897
look_next_get_default_widget_font(void)2898 static char *look_next_get_default_widget_font (void)
2899 {
2900 return "-*-fixed-medium-r-normal--%d-*-*-*-*-*-*";
2901 }
2902
look_next_get_menu_item_extents(int n,int j,struct menu_item m[],int * border,int * relief,int * y1,int * y2)2903 static void look_next_get_menu_item_extents (int n, int j, struct menu_item m[], int *border, int *relief, int *y1, int *y2)
2904 {
2905 int i, n_items = 0, n_bars = 0;
2906
2907 *border = O;
2908 *relief = RELIEF;
2909
2910 if (!n || j < 0) {
2911 *y1 = O;
2912 *y2 = *y1 + H;
2913 } else {
2914 int not_bar;
2915 not_bar = 1;
2916 for (i = 0; i < j; i++)
2917 if (m[i].text[2])
2918 n_items++;
2919 else
2920 n_bars++;
2921 *y1 = O + n_items * (H + S) + n_bars * (B + S) + (not_bar ? 0 : 2);
2922 *y2 = *y1 + (not_bar ? H : (B - 4));
2923 }
2924 }
2925
look_next_menu_draw(Window win,int w,int h,struct menu_item m[],int n,int light)2926 static void look_next_menu_draw (Window win, int w, int h, struct menu_item m[], int n, int light)
2927 {
2928 int i, y1, y2, offset = 0;
2929 static int last_light = 0, last_n = 0;
2930 static Window last_win = 0;
2931
2932 if (last_win == win && last_n != n) {
2933 XClearWindow (CDisplay, win);
2934 render_bevel (win, 0, 0, w - 1, h - 1, BEVEL_MAIN, 0);
2935 render_bevel (win, BEVEL_IN, BEVEL_IN, w - 1 - BEVEL_IN, h - 1 - BEVEL_IN, BEVEL_OUT - BEVEL_IN, 1);
2936 } else if (last_light >= 0 && last_light < n) {
2937 int border, relief;
2938 look_next_get_menu_item_extents (n, last_light, m, &border, &relief, &y1, &y2);
2939 CSetColor (COLOR_FLAT);
2940 CRectangle (win, O + 1, y1 - 1, w - O * 2 + 2, y2 - y1 + 2);
2941 }
2942 last_win = win;
2943 last_n = n;
2944 CPushFont ("widget", 0);
2945 for (i = 0; i < n; i++) {
2946 int border, relief;
2947 look_next_get_menu_item_extents (n, i, m, &border, &relief, &y1, &y2);
2948 render_bevel (win, O, y1, w - O - 1, y2 - 1, ITEM_BEVEL, ITEM_BEVEL_TYPE);
2949 if (i == light && m[i].text[2]) {
2950 CSetColor (color_widget (14));
2951 CRectangle (win, O + 1, y1 + 1, w - O * 2 - 4, y2 - y1 - 4);
2952 }
2953 if (m[i].text[2]) {
2954 char *u;
2955 u = strrchr (m[i].text, '\t');
2956 if (u)
2957 *u = 0;
2958 CSetColor (COLOR_BLACK);
2959 if (m[i].hot_key == '~')
2960 m[i].hot_key = find_menu_hotkey (m, i, n);
2961 if (i == light)
2962 CSetBackgroundColor (color_widget (14));
2963 else
2964 CSetBackgroundColor (COLOR_FLAT);
2965 drawstring_xy_hotkey (win, RELIEF + O - offset, RELIEF + y1 - offset, m[i].text, m[i].hot_key);
2966 if (u) {
2967 drawstring_xy (win, RELIEF + O + (w - (O + RELIEF) * 2 - CImageStringWidth (u + 1)) - offset,
2968 RELIEF + y1 - offset, u + 1);
2969 *u = '\t';
2970 }
2971 }
2972 }
2973 last_light = light;
2974 CPopFont ();
2975 }
2976
look_next_render_menu_button(CWidget * wdt)2977 static void look_next_render_menu_button (CWidget * wdt)
2978 {
2979 int w = wdt->width, h = wdt->height;
2980 int x = 0, y = 0;
2981
2982 Window win = wdt->winid;
2983
2984 if (wdt->disabled || !((wdt->droppedmenu) ||
2985 (wdt->options & (BUTTON_PRESSED | BUTTON_HIGHLIGHT)))) {
2986 CSetColor (COLOR_FLAT);
2987 CRectangle (win, x, y, x + w, y + h);
2988 CSetColor (COLOR_BLACK);
2989 CSetBackgroundColor (COLOR_FLAT);
2990 } else {
2991 CSetColor (COLOR_DARK);
2992 CRectangle (win, x, y, x + w - 1, y + h - 1);
2993 if (wdt->options & BUTTON_PRESSED)
2994 render_bevel (win, x, y, x + w - 1, y + h - 1, 2, 1);
2995 CSetColor (COLOR_WHITE);
2996 CSetBackgroundColor (COLOR_DARK);
2997 }
2998 if (!wdt->label)
2999 return;
3000 if (!(*(wdt->label)))
3001 return;
3002 CPushFont ("widget", 0);
3003 drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey);
3004 CPopFont ();
3005 }
3006
look_next_render_button(CWidget * wdt)3007 static void look_next_render_button (CWidget * wdt)
3008 {
3009 int w = wdt->width, h = wdt->height;
3010 int x = 0, y = 0;
3011
3012 Window win = wdt->winid;
3013 #define BUTTON_BEVEL 1
3014
3015 if((wdt->options & BUTTON_HIGHLIGHT) && !wdt->disabled)
3016 {
3017 CSetColor (COLOR_BLACK);
3018 XDrawRectangle (CDisplay, win, CGC, x, y, w-1, h-1);
3019 } else
3020 render_bevel (win, x, y, x + w - 1, y + h - 1, BUTTON_BEVEL, ( wdt->options & BUTTON_PRESSED )?1:0);
3021
3022 if (!wdt->label)
3023 return;
3024 if (!(*(wdt->label)))
3025 return;
3026 CSetColor (COLOR_BLACK);
3027 CSetBackgroundColor (COLOR_FLAT);
3028 CPushFont ("widget", 0);
3029 drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey);
3030 CPopFont ();
3031 }
3032
look_next_render_bar(CWidget * wdt)3033 static void look_next_render_bar (CWidget * wdt)
3034 {
3035 int w = wdt->width, h = wdt->height;
3036
3037 Window win = wdt->winid;
3038
3039 CSetColor (COLOR_FLAT);
3040 CLine (win, 1, 1, w - 2, 1);
3041 render_bevel (win, 0, 0, w - 1, h - 1, 1, 1);
3042 }
3043
look_next_render_sunken_bevel(Window win,int x1,int y1,int x2,int y2,int thick,int sunken)3044 static void look_next_render_sunken_bevel (Window win, int x1, int y1, int x2, int y2, int thick,
3045 int sunken)
3046 {
3047 int i;
3048 if ((sunken & 2) && (y2 - y1 - 2 * thick + 1 > 0) && (x2 - x1 - 2 * thick + 1 > 0)) {
3049 CSetColor (COLOR_FLAT);
3050 CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1);
3051 }
3052 CSetColor (COLOR_BLACK);
3053 CLine (win, x1, y1, x2, y1);
3054 CLine (win, x1, y1, x1, y2);
3055
3056 CSetColor (COLOR_WHITE);
3057 for (i = 0; i < thick; i++) {
3058 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i);
3059 CLine (win, x1 + i, y2 - i, x2 - i, y2 - i);
3060 }
3061 if (x2 - x1 - i > 0)
3062 XClearArea (CDisplay, win, x1 + i, y1 + i, x2 - x1 - i, 1, False);
3063 if (y2 - y1 - i > 0)
3064 XClearArea (CDisplay, win, x1 + i, y1 + i, 1, y2 - y1 - i, False);
3065
3066 CSetColor (COLOR_DARK);
3067 XDrawPoint (CDisplay, win, CGC, x1, y2);
3068 XDrawPoint (CDisplay, win, CGC, x2, y1);
3069 x1++;
3070 x2--;
3071 y1++;
3072 y2--;
3073 for (i = 0; i < thick; i++) {
3074 CLine (win, x1 + i, y2 - i, x1 + i, y1 + i);
3075 CLine (win, x1 + i, y1 + i, x2 - i, y1 + i);
3076 }
3077 }
3078
look_next_render_raised_bevel(Window win,int x1,int y1,int x2,int y2,int thick,int sunken)3079 static void look_next_render_raised_bevel (Window win, int x1, int y1, int x2, int y2, int thick,
3080 int sunken)
3081 {
3082 int i;
3083 if ((sunken & 2) && (y2 - y1 - 2 * thick + 1 > 0) && (x2 - x1 - 2 * thick + 1 > 0)) {
3084 CSetColor (COLOR_FLAT);
3085 CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1);
3086 }
3087 CSetColor (COLOR_WHITE);
3088 for (i = 0; i < thick; i++) {
3089 CLine (win, x1 + i, y1 + i, x2 - i, y1 + i);
3090 CLine (win, x1 + i, y1 + i, x1 + i, y2 - i);
3091 }
3092
3093 if (x2 - x1 - i > 0)
3094 XClearArea (CDisplay, win, x1 + i, y1 + i, x2 - x1 - i, 1, False);
3095 if (y2 - y1 - i > 0)
3096 XClearArea (CDisplay, win, x1 + i, y1 + i, 1, y2 - y1 - i, False);
3097
3098 CSetColor (COLOR_BLACK);
3099 CLine (win, x2, y1, x2, y2);
3100 CLine (win, x1, y2, x2, y2);
3101 CSetColor (COLOR_DARK);
3102 XDrawPoint (CDisplay, win, CGC, x1, y2);
3103 XDrawPoint (CDisplay, win, CGC, x2, y1);
3104 x1++;
3105 x2--;
3106 y1++;
3107 y2--;
3108 for (i = 0; i < thick; i++) {
3109 CLine (win, x1 + i, y2 - i, x2 - i, y2 - i);
3110 CLine (win, x2 - i, y1 + i, x2 - i, y2 - i);
3111 }
3112 }
3113
look_next_draw_hotkey_understroke(Window win,int x,int y,int hotkey)3114 static void look_next_draw_hotkey_understroke (Window win, int x, int y, int hotkey)
3115 {
3116 CLine (win, x+1, y , x + FONT_PER_CHAR (hotkey) - 2, y);
3117 y++;
3118 CLine (win, x+1, y, x + FONT_PER_CHAR (hotkey) - 2, y);
3119 }
3120
look_next_render_text(CWidget * wdt)3121 static void look_next_render_text (CWidget * wdt)
3122 {
3123 Window win = wdt->winid;
3124 char text[1024], *p, *q;
3125 int hot, y, w = wdt->width, center = 0;
3126 int releif = 1 ;
3127
3128 releif += TEXT_RELIEF ;
3129 CSetColor (COLOR_FLAT);
3130 CRectangle (win, 1, 1, w - 2, wdt->height - 2);
3131 CSetColor (COLOR_BLACK);
3132
3133 hot = wdt->hotkey; /* a letter that needs underlining */
3134 y = 1; /* bevel */
3135 q = wdt->text;
3136 CPushFont ("widget", 0);
3137 CSetBackgroundColor (COLOR_FLAT);
3138 for (;;) {
3139 p = strchr (q, '\n');
3140 if (!p) { /* last line */
3141 if (wdt->options & TEXT_CENTRED)
3142 center = (wdt->width - releif * 2 - CImageTextWidth (q, strlen (q))) / 2;
3143 drawstring_xy_hotkey (win, releif + center, releif + y - 1, q, hot);
3144 break;
3145 } else {
3146 int l;
3147 l = min (1023, (unsigned long) p - (unsigned long) q);
3148 memcpy (text, q, l);
3149 text[l] = 0;
3150 if (wdt->options & TEXT_CENTRED)
3151 center = (wdt->width - releif * 2 - CImageTextWidth (q, l)) / 2;
3152 drawstring_xy_hotkey (win, releif + center, releif + y - 1, text, hot);
3153 }
3154 y += FONT_PIX_PER_LINE;
3155 hot = 0; /* only for first line */
3156 q = p + 1; /* next line */
3157 }
3158 CPopFont ();
3159 }
3160
3161 #define NEXT_HANDLE 25
3162 #define NEXT_LOWBAR 7
3163
look_next_render_window(CWidget * wdt)3164 static void look_next_render_window (CWidget * wdt)
3165 {
3166 int w = wdt->width, h = wdt->height;
3167
3168 Window win = wdt->winid;
3169
3170 if (wdt->options & WINDOW_NO_BORDER)
3171 return;
3172 if ((wdt->position & WINDOW_RESIZABLE) && CRoot != wdt->parentid) {
3173 CSetColor (COLOR_FLAT);
3174 CRectangle (win, 0, 0, w - 1, h - 1);
3175 render_bevel (win, 1, h - NEXT_LOWBAR - 1, NEXT_HANDLE + 1, h - 1, 1, 0);
3176 render_bevel (win, NEXT_HANDLE + 2, h - NEXT_LOWBAR - 1, w - NEXT_HANDLE - 3, h - 1, 1, 0);
3177 render_bevel (win, w - NEXT_HANDLE - 2, h - NEXT_LOWBAR - 1, w - 1, h - 1, 1, 0);
3178 }
3179 render_bevel (win, 0, 0, w - 1, h - 1, 2, 0);
3180 if (CRoot != wdt->parentid)
3181 if (win == CGetFocus ())
3182 render_bevel (win, 4, 4, w - 5, h - 5, 3, 1);
3183 }
3184
look_next_render_scrollbar(CWidget * wdt)3185 static void look_next_render_scrollbar (CWidget * wdt)
3186 {
3187 int pos, prop;
3188 int flags = wdt->options;
3189 if (!wdt)
3190 return;
3191
3192 pos = wdt->firstline;
3193 prop = wdt->numlines;
3194
3195 if (prop < 0)
3196 prop = 0;
3197 if (pos < 0)
3198 pos = 0;
3199 if (pos > 65535)
3200 pos = 65535;
3201 if (pos + prop >= 65535)
3202 prop = 65535 - pos;
3203
3204 render_next_scrollbar ((ScrollIcons *) wdt->user, wdt->winid,
3205 wdt->x, wdt->y, wdt->width, wdt->height,
3206 pos, prop, flags);
3207
3208 if (wdt->scroll_bar_extra_render)
3209 (*wdt->scroll_bar_extra_render) (wdt);
3210 }
3211
3212 /*
3213 Which scrollbar button was pressed: 3 is the middle button ?
3214 */
look_next_which_scrollbar_button(int bx,int by,CWidget * wdt)3215 static int look_next_which_scrollbar_button (int bx, int by, CWidget * wdt)
3216 {
3217 #if 0
3218 int pos;
3219 int prop;
3220 #endif
3221 ScrollIcons *next_icons = (ScrollIcons *) wdt->user;
3222 /*
3223 fprintf( stderr, "button: (%d,%d) thumb: (%d,%d)\n",bx, by, next_icons->thumb.x, next_icons->thumb.y );
3224 */
3225 if (wdt->kind == C_VERTSCROLL_WIDGET) {
3226 if (by > 0 && by < next_icons->thumb.y)
3227 return 1;
3228 if (by >= next_icons->thumb.y &&
3229 by <= next_icons->thumb.y + next_icons->thumb.height)
3230 return 3;
3231 if (by > next_icons->thumb.y + next_icons->thumb.height &&
3232 by < next_icons->buttons[0].y)
3233 return 4;
3234 if (by >= next_icons->buttons[0].y &&
3235 by <= next_icons->buttons[0].y + next_icons->buttons[0].height)
3236 return 2;
3237 if (by >= next_icons->buttons[1].y &&
3238 by <= next_icons->buttons[1].y + next_icons->buttons[1].height)
3239 return 5;
3240 } else {
3241 if (bx > 0 && bx < next_icons->thumb.x)
3242 return 1;
3243 if (bx >= next_icons->thumb.x &&
3244 bx <= next_icons->thumb.x + next_icons->thumb.width)
3245 return 3;
3246 if (bx > next_icons->thumb.x + next_icons->thumb.width &&
3247 bx < next_icons->buttons[0].x)
3248 return 4;
3249 if (bx >= next_icons->buttons[0].x &&
3250 bx <= next_icons->buttons[0].x + next_icons->buttons[0].width)
3251 return 2;
3252 if (bx >= next_icons->buttons[1].x &&
3253 bx <= next_icons->buttons[1].x + next_icons->buttons[1].width)
3254 return 5;
3255
3256 }
3257 return 0;
3258 }
3259
look_next_scrollbar_handler(CWidget * w,XEvent * xevent,CEvent * cwevent)3260 static int look_next_scrollbar_handler (CWidget * w, XEvent * xevent, CEvent * cwevent)
3261 {
3262 static int buttonypos, y, offset, whichscrbutton = 0; /* which of the five scroll bar buttons was pressed */
3263 int xevent_xbutton_y, length, width, thumb_pos;
3264 ScrollIcons *next_icons = (ScrollIcons *) w->user;
3265
3266 if (w->kind == C_VERTSCROLL_WIDGET) {
3267 xevent_xbutton_y = xevent->xbutton.y;
3268 length = w->height - SB_BUTTONS_HEIGHT - SB_BORDER_SIZE - next_icons->thumb.height;
3269 width = w->width;
3270 thumb_pos = next_icons->thumb.y;
3271 } else {
3272 xevent_xbutton_y = xevent->xbutton.x;
3273 length = w->width - SB_BUTTONS_HEIGHT - SB_BORDER_SIZE - next_icons->thumb.width;
3274 width = w->height;
3275 thumb_pos = next_icons->thumb.x;
3276 }
3277
3278 if (next_icons->thumb.width == 0 || next_icons->thumb.height == 0) {
3279 if (xevent->type == Expose && !xevent->xexpose.count)
3280 render_scrollbar (w);
3281 return 0;
3282 }
3283 switch (xevent->type) {
3284 /* case LeaveNotify:
3285 */
3286 case Expose:
3287 w->options = whichscrbutton = 0;
3288 break;
3289 case ButtonRepeat:
3290 resolve_button (xevent, cwevent);
3291 if (whichscrbutton != 3 &&
3292 (cwevent->button == Button1 || cwevent->button == Button2)) {
3293 int b;
3294 b = look_next_which_scrollbar_button (cwevent->x, cwevent->y, w);
3295 if (b != 3 && b > 0) {
3296 y = w->firstline;
3297 buttonypos = xevent_xbutton_y;
3298 w->options = whichscrbutton = b;
3299 cwevent->ident = w->ident;
3300 xevent->type = cwevent->type = ButtonPress;
3301 }
3302 }
3303 break;
3304 case ButtonPress:
3305 resolve_button (xevent, cwevent);
3306 if (cwevent->button == Button1 || cwevent->button == Button2) {
3307 buttonypos = xevent_xbutton_y;
3308 y = w->firstline;
3309 w->options = whichscrbutton = look_next_which_scrollbar_button (cwevent->x, cwevent->y, w);
3310 if (whichscrbutton == 3) {
3311 offset = thumb_pos - buttonypos + SB_BORDER_WIDTH;
3312 } else
3313 offset = 0;
3314 cwevent->ident = w->ident;
3315 w->search_start = w->firstline;
3316 w->search_len = w->numlines;
3317 }
3318 break;
3319 case ButtonRelease:
3320 resolve_button (xevent, cwevent);
3321 if (whichscrbutton == 3) {
3322 w->options = 0x20 + whichscrbutton;
3323 y = (double) (xevent_xbutton_y + offset) * (double) 65535.0 / next_icons->work_length;
3324 w->firstline = y;
3325 buttonypos = xevent_xbutton_y;
3326 }
3327 break;
3328 case MotionNotify:
3329 if (whichscrbutton == 0)
3330 return 0;
3331 resolve_button (xevent, cwevent);
3332 if (cwevent->state & (Button1Mask | Button2Mask)) {
3333 w->options = whichscrbutton;
3334 if (whichscrbutton == 3) {
3335 y = (double) (xevent_xbutton_y + offset) * (double) 65535.0 / (next_icons->work_length);
3336 w->firstline = y;
3337 buttonypos = xevent_xbutton_y;
3338 }
3339 }
3340 break;
3341 default:
3342 return 0;
3343 }
3344
3345 if (w->firstline > 65535)
3346 w->firstline = 65535;
3347 if (cwevent->state & (Button1Mask | Button2Mask) || cwevent->type == ButtonPress || cwevent->type == ButtonRelease)
3348 if (w->scroll_bar_link && w->vert_scrollbar)
3349 (*w->scroll_bar_link) (w, w->vert_scrollbar, xevent, cwevent, whichscrbutton);
3350
3351 if (cwevent->type == ButtonRelease)
3352 w->options = whichscrbutton = 0;
3353 if (xevent->type != Expose || !xevent->xexpose.count)
3354 look_next_render_scrollbar (w);
3355
3356 return 0;
3357 }
3358
look_next_init_scrollbar_icons(CWidget * w)3359 static void look_next_init_scrollbar_icons (CWidget * w)
3360 {
3361 w->user = init_next_icons (w->winid);
3362 w->free_user = free_next_icons;
3363 }
3364
look_next_get_scrollbar_size(int type)3365 static int look_next_get_scrollbar_size (int type)
3366 {
3367 return SB_WIDTH + SB_BORDER_SIZE;
3368 }
3369
look_next_get_button_color(XColor * color,int i)3370 static void look_next_get_button_color (XColor * color, int i)
3371 {
3372 color->red = color->green = (i * 4) * 65535 / 63;
3373 color->blue = (i * 4) * 65535 / 63;
3374 color->flags = DoRed | DoBlue | DoGreen;
3375 }
3376
look_next_window_handler(CWidget * w,XEvent * xevent,CEvent * cwevent)3377 static int look_next_window_handler (CWidget * w, XEvent * xevent, CEvent * cwevent)
3378 {
3379 static Window window_is_resizing = 0;
3380 static int windowx, windowy;
3381 static int wx = 0, wy = 0;
3382 static int wwidth = 0, wheight = 0;
3383 static int allowwindowmove = 0;
3384 static int allowwindowresize = 0;
3385
3386 switch (xevent->type) {
3387 case ClientMessage:
3388 if (!w->disabled)
3389 cwevent->ident = w->ident;
3390 break;
3391 case Expose:
3392 if (!xevent->xexpose.count)
3393 render_window (w);
3394 break;
3395 case ButtonRelease:
3396 strcpy (cwevent->ident, w->ident);
3397 window_is_resizing = 0;
3398 resolve_button (xevent, cwevent);
3399 allowwindowmove = 0;
3400 allowwindowresize = 0;
3401 break;
3402 case ButtonPress:
3403 strcpy (cwevent->ident, w->ident);
3404 resolve_button (xevent, cwevent);
3405 if (cwevent->double_click == 1) {
3406 CWidget *c = CChildFocus (w);
3407 if (c)
3408 CFocus (c);
3409 }
3410 if (cwevent->button == Button1 && !(w->position & WINDOW_ALWAYS_LOWERED)) {
3411 XRaiseWindow (CDisplay, w->winid);
3412 CRaiseWindows ();
3413 } else if (cwevent->button == Button2 && !(w->position & WINDOW_ALWAYS_RAISED)) {
3414 XLowerWindow (CDisplay, w->winid);
3415 CLowerWindows ();
3416 }
3417 windowx = xevent->xbutton.x_root - w->x;
3418 windowy = xevent->xbutton.y_root - w->y;
3419 wx = xevent->xbutton.x;
3420 wy = xevent->xbutton.y;
3421 wwidth = w->width;
3422 wheight = w->height;
3423 if (wy > w->height - NEXT_LOWBAR && w->position & WINDOW_RESIZABLE) {
3424 allowwindowresize = 1;
3425 if (wx < NEXT_HANDLE) {
3426 allowwindowresize++;
3427 if (w->position & WINDOW_UNMOVEABLE)
3428 allowwindowresize++;
3429 } else if (wx < w->width - NEXT_HANDLE - 1)
3430 allowwindowresize = 3;
3431 } else
3432 allowwindowmove = 1;
3433 break;
3434 case MotionNotify:
3435 resolve_button (xevent, cwevent);
3436 if ((w->position & WINDOW_RESIZABLE) && allowwindowresize
3437 && (cwevent->state & (Button1Mask | Button2Mask))) {
3438 int wi, he;
3439 #if 0
3440 int new_x, new_y;
3441 #endif
3442 int dx = xevent->xmotion.x_root - windowx - w->x;
3443 int dy = xevent->xmotion.y_root - windowy - w->y;
3444 window_is_resizing = w->winid;
3445 he = wheight + dy;
3446 wi = wwidth;
3447
3448 if (allowwindowresize == 1)
3449 wi += dx;
3450 else if (allowwindowresize == 2)
3451 wi -= dx;
3452
3453 /* this is actually for the edit windows, and needs to be generalized */
3454 if (wi < w->mark1)
3455 wi = w->mark1;
3456 if (he < w->mark2)
3457 he = w->mark2;
3458
3459 wi -= w->firstcolumn;
3460 wi -= wi % w->textlength;
3461 wi += w->firstcolumn;
3462 he -= w->firstline;
3463 he -= he % w->numlines;
3464 he += w->firstline;
3465 w->position &= ~WINDOW_MAXIMISED;
3466 dx = wi - w->width;
3467 CSetSize (w, wi, he);
3468 if (allowwindowresize == 2 && dx != 0) {
3469 w->x -= dx;
3470 wwidth = w->width;
3471 XMoveWindow (CDisplay, w->winid, w->x, w->y);
3472 }
3473 }
3474 if (!(w->position & WINDOW_UNMOVEABLE) && allowwindowmove
3475 && (cwevent->state & (Button1Mask | Button2Mask))) {
3476 w->x = xevent->xmotion.x_root - windowx;
3477 w->y = xevent->xmotion.y_root - windowy;
3478 if (w->x + xevent->xmotion.x < 2)
3479 w->x = -wx + 2;
3480 if (w->y + xevent->xmotion.y < 2)
3481 w->y = -wy + 2;
3482 XMoveWindow (CDisplay, w->winid, w->x, w->y);
3483 }
3484 break;
3485 }
3486 return 0;
3487 }
3488
3489 extern Pixmap Cswitchon;
3490 extern Pixmap Cswitchoff;
3491
look_next_render_switch(CWidget * wdt)3492 static void look_next_render_switch (CWidget * wdt)
3493 {
3494 int w = wdt->width, h = wdt->height;
3495 Window win = wdt->winid;
3496 int x = 0, y = 0;
3497
3498 CSetColor (COLOR_FLAT);
3499 CRectangle (win, x+2, y+2, w - 4, h - 4);
3500
3501 CSetColor (wdt->fg);
3502 CSetBackgroundColor (wdt->bg);
3503 if (wdt->options & SWITCH_PICTURE_TYPE) {
3504 if (wdt->keypressed)
3505 XCopyPlane (CDisplay, Cswitchon, win, CGC, 0, 0,
3506 w, h, x, y, 1);
3507 else
3508 XCopyPlane (CDisplay, Cswitchoff, win, CGC, 0, 0,
3509 w, h, x, y, 1);
3510 } else {
3511 if (wdt->keypressed)
3512 {
3513 render_bevel (win, x + 1, y + 1, x + w - 1, y + h - 1, 1, 0);
3514 CSetColor (COLOR_DARK);
3515 CLine( win, x+1+3, y+1+11, x+1+10, y+1+3 );
3516 CSetColor( COLOR_BLACK );
3517 CLine( win, x+1+4, y+1+5, x+1+4, y+1+8 );
3518 CLine( win, x+1+4, y+1+11, x+1+10, y+1+4 );
3519 CSetColor( COLOR_WHITE );
3520 CLine(win, x+1+3, y+1+5, x+1+3, y+1+10 );
3521 CLine(win, x+1+3, y+1+10, x+1+9, y+1+3 );
3522 }else
3523 render_bevel (win, x + 1, y + 1, x + w - 2, y + h - 2, 1, 0);
3524
3525 }
3526 if (wdt->options & (BUTTON_HIGHLIGHT | BUTTON_PRESSED))
3527 CSetColor(COLOR_BLACK);
3528 else
3529 CSetColor(COLOR_FLAT);
3530 XDrawRectangle (CDisplay, win, CGC, x, y, w-1, h-1);
3531 }
3532
look_next_edit_render_tidbits(CWidget * wdt)3533 static void look_next_edit_render_tidbits (CWidget * wdt)
3534 {
3535 int isfocussed;
3536 int w = wdt->width, h = wdt->height;
3537 Window win;
3538
3539 win = wdt->winid;
3540 isfocussed = (win == CGetFocus ());
3541 CSetColor (COLOR_FLAT);
3542 render_bevel (win, 0, 0, w - 1, h - 1, 1, 1); /*most outer border bevel */
3543 }
3544
look_next_draw_cancel_button(char * ident,Window win,int x,int y)3545 static CWidget *look_next_draw_cancel_button (char *ident, Window win, int x, int y)
3546 {
3547 CWidget *wdt;
3548 #if 0
3549 CGetHintPos (&x, 0);
3550 #endif
3551 wdt = CDrawButton (ident, win, x, y, AUTO_WIDTH, AUTO_HEIGHT, _(" Cancel "));
3552 #if 0
3553 CGetHintPos (0, &y);
3554 reset_hint_pos (x + WINDOW_EXTRA_SPACING, y + 2 * WINDOW_EXTRA_SPACING);
3555 #endif
3556 return wdt;
3557 }
3558
look_next_draw_ok_button(char * ident,Window win,int x,int y)3559 static CWidget *look_next_draw_ok_button (char *ident, Window win, int x, int y)
3560 {
3561 CWidget *wdt;
3562 #if 0
3563 CGetHintPos (&x, 0);
3564 #endif
3565 wdt = CDrawButton (ident, win, x, y, AUTO_WIDTH, AUTO_HEIGHT, _(" Ok "));
3566 #if 0
3567 CGetHintPos (0, &y);
3568 reset_hint_pos (x + WINDOW_EXTRA_SPACING, y + 2 * WINDOW_EXTRA_SPACING);
3569 #endif
3570 return wdt;
3571 }
3572
look_next_render_fielded_textbox_tidbits(CWidget * w,int isfocussed)3573 static void look_next_render_fielded_textbox_tidbits (CWidget *w, int isfocussed)
3574 {
3575 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 1, 1); /*most outer border bevel */
3576 }
3577
look_next_render_textbox_tidbits(CWidget * w,int isfocussed)3578 static void look_next_render_textbox_tidbits (CWidget * w, int isfocussed)
3579 {
3580 if (isfocussed) {
3581 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 1, 1); /*most outer border bevel */
3582 } else {
3583 render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 1, 0); /*most outer border bevel */
3584 }
3585 }
3586
look_next_render_passwordinput_tidbits(CWidget * wdt,int isfocussed)3587 static void look_next_render_passwordinput_tidbits (CWidget * wdt, int isfocussed)
3588 {
3589 int w = wdt->width, h = wdt->height;
3590 Window win = wdt->winid;
3591 CSetColor (COLOR_WHITE);
3592 XDrawRectangle (CDisplay, win, CGC, 1, 1, w - 2, h - 2);
3593 XDrawRectangle (CDisplay, win, CGC, 2, 2, w - 4, h - 4);
3594 if (win == CGetFocus ()) {
3595 render_bevel (win, 0, 0, w - 1, h - 1, 1, 1);
3596 } else {
3597 render_bevel (win, 0, 0, w - 1, h - 1, 1, 1);
3598 }
3599 }
3600
look_next_render_textinput_tidbits(CWidget * wdt,int isfocussed)3601 static void look_next_render_textinput_tidbits (CWidget * wdt, int isfocussed)
3602 {
3603 int w = wdt->width, h = wdt->height;
3604 Window win = wdt->winid;
3605 CSetColor (COLOR_WHITE);
3606 XDrawRectangle (CDisplay, win, CGC, 1, 1, w - h - 3, h - 3);
3607 XDrawRectangle (CDisplay, win, CGC, 2, 2, w - h - 5, h - 5);
3608 if (isfocussed) {
3609 render_bevel (win, 0, 0, w - h - 1, h - 1, 1, 1); /*most outer border bevel */
3610 } else {
3611 render_bevel (win, 0, 0, w - h - 1, h - 1, 1, 1); /*most outer border bevel */
3612 }
3613 /* history button to the right */
3614 if (wdt->options & BUTTON_PRESSED) {
3615 CRectangle (win, w - h + 2, 2, h - 4, h - 4);
3616 render_bevel (win, w - h, 0, w - 1, h - 1, 2, 3);
3617 } else if (wdt->options & BUTTON_HIGHLIGHT) {
3618 CRectangle (win, w - h + 1, 1, h - 2, h - 2);
3619 render_bevel (win, w - h, 0, w - 1, h - 1, 1, 2);
3620 } else {
3621 CRectangle (win, w - h + 2, 2, h - 4, h - 4);
3622 render_bevel (win, w - h, 0, w - 1, h - 1, 2, 2);
3623 }
3624 }
3625
3626 extern struct focus_win focus_border;
3627
render_focus_border_n(Window win,int i)3628 static void render_focus_border_n (Window win, int i)
3629 {
3630 int j;
3631 j = (i > 3) + 1;
3632 if (win == focus_border.top) {
3633 render_bevel (win, 0, 0, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, focus_border.height + 2 * WIDGET_FOCUS_RING - 1, j, 0);
3634 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);
3635 } else if (win == focus_border.bottom) {
3636 render_bevel (win, 0, 0 - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, WIDGET_FOCUS_RING - 1, j, 0);
3637 render_bevel (win, i, i - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1 - i, WIDGET_FOCUS_RING - 1 - i, 2, 1);
3638 } else if (win == focus_border.left) {
3639 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);
3640 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);
3641 } else if (win == focus_border.right) {
3642 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);
3643 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);
3644 }
3645 }
3646
look_next_render_focus_border(Window win)3647 static void look_next_render_focus_border (Window win)
3648 {
3649 render_focus_border_n (win, focus_border.border);
3650 }
3651
look_next_get_extra_window_spacing(void)3652 static int look_next_get_extra_window_spacing (void)
3653 {
3654 return 3;
3655 }
3656
look_next_get_default_interwidget_spacing(void)3657 static int look_next_get_default_interwidget_spacing (void)
3658 {
3659 return 1;
3660 }
3661
look_next_get_focus_ring_size(void)3662 static int look_next_get_focus_ring_size (void)
3663 {
3664 return 1;
3665 }
3666
look_next_get_window_resize_bar_thickness(void)3667 static int look_next_get_window_resize_bar_thickness (void)
3668 {
3669 return 7;
3670 }
3671
look_next_get_button_flat_color(void)3672 static unsigned long look_next_get_button_flat_color (void)
3673 {
3674 return color_widget(10);
3675 }
3676
look_next_get_switch_size(void)3677 static int look_next_get_switch_size (void)
3678 {
3679 return 16;
3680 }
3681
look_next_get_fielded_textbox_hscrollbar_width(void)3682 static int look_next_get_fielded_textbox_hscrollbar_width (void)
3683 {
3684 return AUTO_WIDTH;
3685 }
3686
3687 struct look look_next = {
3688 look_next_get_default_interwidget_spacing,
3689 look_next_menu_draw,
3690 look_next_get_menu_item_extents,
3691 look_next_render_menu_button,
3692 look_next_render_button,
3693 look_next_render_bar,
3694 look_next_render_raised_bevel,
3695 look_next_render_sunken_bevel,
3696 look_next_draw_hotkey_understroke,
3697 look_next_get_default_widget_font,
3698 look_next_render_text,
3699 look_next_render_window,
3700 look_next_render_scrollbar,
3701 look_next_get_scrollbar_size,
3702 look_next_init_scrollbar_icons,
3703 look_next_which_scrollbar_button,
3704 look_next_scrollbar_handler,
3705 look_next_get_button_color,
3706 look_next_get_extra_window_spacing,
3707 look_next_window_handler,
3708 look_next_get_focus_ring_size,
3709 look_next_get_button_flat_color,
3710 look_next_get_window_resize_bar_thickness,
3711 look_next_render_switch,
3712 look_next_get_switch_size,
3713 look_next_draw_browser,
3714 look_next_get_file_or_dir,
3715 look_next_draw_file_list,
3716 look_next_redraw_file_list,
3717 look_next_get_file_list_line,
3718 look_next_search_replace_dialog,
3719 look_next_edit_render_tidbits,
3720 look_next_draw_cancel_button,
3721 look_next_draw_cancel_button,
3722 look_next_draw_cancel_button,
3723 look_next_draw_ok_button,
3724 look_next_render_fielded_textbox_tidbits,
3725 look_next_render_textbox_tidbits,
3726 look_next_get_fielded_textbox_hscrollbar_width,
3727 look_next_render_textinput_tidbits,
3728 look_next_render_passwordinput_tidbits,
3729 look_next_render_focus_border,
3730 };
3731
3732 #endif /* NEXT_LOOK */
3733
3734
3735