/* look-cool.c - look 'n feel type: COOL Copyright (C) 1996-2000 Paul Sheer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "lkeysym.h" #include "stringtools.h" #include "app_glob.c" #include "coolwidget.h" #include "coollocal.h" #include "mad.h" extern struct look *look; /* {{{ search replace dialog */ extern int replace_scanf; extern int replace_regexp; extern int replace_all; extern int replace_prompt; extern int replace_whole; extern int replace_case; extern int replace_backwards; extern int search_create_bookmark; void look_cool_search_replace_dialog (Window parent, int x, int y, char **search_text, char **replace_text, char **arg_order, const char *heading, int option) { Window win; XEvent xev; CEvent cev; CState s; int xh, yh, h, xb, ys, yc, yb, yr; CWidget *m; int text_input_width ; CBackupState (&s); CDisable ("*"); win = CDrawHeadedDialog ("replace", parent, x, y, heading); CGetHintPos (&xh, &h); /* NLS hotkey ? */ CIdent ("replace")->position = WINDOW_ALWAYS_RAISED; /* An input line comes after the ':' */ (CDrawText ("replace.t1", win, xh, h, _(" Enter search text : ")))->hotkey = 'E'; CGetHintPos (0, &yh); (m = CDrawTextInput ("replace.sinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *search_text))->hotkey = 'E'; if (replace_text) { CGetHintPos (0, &yh); (CDrawText ("replace.t2", win, xh, yh, _(" Enter replace text : ")))->hotkey = 'n'; CGetHintPos (0, &yh); (CDrawTextInput ("replace.rinp", win, xh, yh, 10, AUTO_HEIGHT, 8192, *replace_text))->hotkey = 'n'; CSetToolHint ("replace.t2", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\"")); CSetToolHint ("replace.rinp", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\"")); CGetHintPos (0, &yh); (CDrawText ("replace.t3", win, xh, yh, _(" Enter argument (or substring) order : ")))->hotkey = 'o'; CGetHintPos (0, &yh); (CDrawTextInput ("replace.ainp", win, xh, yh, 10, AUTO_HEIGHT, 256, *arg_order))->hotkey = 'o'; /* Tool hint */ CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2")); CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2")); } CGetHintPos (0, &yh); ys = yh; /* The following are check boxes */ CDrawSwitch ("replace.ww", win, xh, yh, replace_whole, _(" Whole words only "), 0); CGetHintPos (0, &yh); CDrawSwitch ("replace.case", win, xh, yh, replace_case, _(" Case sensitive "), 0); yc = yh; CGetHintPos (0, &yh); CDrawSwitch ("replace.reg", win, xh, yh, replace_regexp, _(" Regular expression "), 1); CSetToolHint ("replace.reg", _("See the regex man page for how\nto compose a regular expression")); CSetToolHint ("replace.reg.label", _("See the regex man page for how\nto compose a regular expression")); yb = yh; CGetHintPos (0, &yh); CGetHintPos (&xb, 0); if (option & SEARCH_DIALOG_OPTION_BACKWARDS) { CDrawSwitch ("replace.bkwd", win, xh, yh, replace_backwards, _(" Backwards "), 0); /* Tool hint */ CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow")); CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow")); } if (replace_text) { yr = ys; if (option & SEARCH_DIALOG_OPTION_BACKWARDS) yr = yc; } else { if (option & SEARCH_DIALOG_OPTION_BACKWARDS) { if (option & SEARCH_DIALOG_OPTION_BOOKMARK) yr = yb; else yr = yh; } else { if (option & SEARCH_DIALOG_OPTION_BOOKMARK) yr = yc; else yr = yb; } } if (replace_text) { CDrawSwitch ("replace.pr", win, xb, yr, replace_prompt, _(" Prompt on replace "), 0); /* Tool hint */ CSetToolHint ("replace.pr", _("Ask before making each replacement")); CGetHintPos (0, &yr); CDrawSwitch ("replace.all", win, xb, yr, replace_all, _(" Replace all "), 0); /* Tool hint */ CSetToolHint ("replace.all", _("Replace repeatedly")); CGetHintPos (0, &yr); } if (option & SEARCH_DIALOG_OPTION_BOOKMARK) { CDrawSwitch ("replace.bkmk", win, xb, yr, search_create_bookmark, _(" Bookmarks "), 0); /* Tool hint */ CSetToolHint ("replace.bkmk", _("Create bookmarks at all lines found")); CSetToolHint ("replace.bkmk.label", _("Create bookmarks at all lines found")); CGetHintPos (0, &yr); } CDrawSwitch ("replace.scanf", win, xb, yr, replace_scanf, _(" Scanf expression "), 1); /* Tool hint */ CSetToolHint ("replace.scanf", _("Allows entering of a C format string,\nsee the scanf man page")); get_hint_limits (&x, &y); CDrawPixmapButton ("replace.ok", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h, PIXMAP_BUTTON_TICK); CDrawPixmapButton ("replace.cancel", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h + WIDGET_SPACING + TICK_BUTTON_WIDTH, PIXMAP_BUTTON_CROSS); /* Tool hint */ CSetToolHint ("replace.ok", _("Begin search, Enter")); CSetToolHint ("replace.cancel", _("Abort this dialog, Esc")); CSetSizeHintPos ("replace"); CMapDialog ("replace"); m = CIdent ("replace"); text_input_width = m->width - WIDGET_SPACING * 3 - 4 - TICK_BUTTON_WIDTH ; CSetWidgetSize ("replace.sinp", text_input_width, (CIdent ("replace.sinp"))->height); if (replace_text) { CSetWidgetSize ("replace.rinp", text_input_width, (CIdent ("replace.rinp"))->height); CSetWidgetSize ("replace.ainp", text_input_width, (CIdent ("replace.ainp"))->height); } CFocus (CIdent ("replace.sinp")); for (;;) { CNextEvent (&xev, &cev); if (!CIdent ("replace")) { *search_text = 0; break; } if (!strcmp (cev.ident, "replace.cancel") || cev.command == CK_Cancel) { *search_text = 0; break; } if (!strcmp (cev.ident, "replace.reg") || !strcmp (cev.ident, "replace.scanf")) { if (CIdent ("replace.reg")->keypressed || CIdent ("replace.scanf")->keypressed) { if (!(CIdent ("replace.case")->keypressed)) { CIdent ("replace.case")->keypressed = 1; CExpose ("replace.case"); } } } if (!strcmp (cev.ident, "replace.ok") || cev.command == CK_Enter) { if (replace_text) { replace_all = CIdent ("replace.all")->keypressed; replace_prompt = CIdent ("replace.pr")->keypressed; *replace_text = (char *) strdup (CIdent ("replace.rinp")->text); *arg_order = (char *) strdup (CIdent ("replace.ainp")->text); } *search_text = (char *) strdup (CIdent ("replace.sinp")->text); replace_whole = CIdent ("replace.ww")->keypressed; replace_case = CIdent ("replace.case")->keypressed; replace_scanf = CIdent ("replace.scanf")->keypressed; replace_regexp = CIdent ("replace.reg")->keypressed; if (option & SEARCH_DIALOG_OPTION_BACKWARDS) { replace_backwards = CIdent ("replace.bkwd")->keypressed; } else { replace_backwards = 0; } if (option & SEARCH_DIALOG_OPTION_BOOKMARK) { search_create_bookmark = CIdent ("replace.bkmk")->keypressed; } else { search_create_bookmark = 0; } break; } } CDestroyWidget ("replace"); CRestoreState (&s); } /* }}} search replace dialog */ /* {{{ file list stuff */ static void destroy_filelist (CWidget * w) { if (w->hook) { free (w->hook); w->hook = 0; } } /* This doesn't apply to solaris: */ /* * struct dirent { * long d_ino; * __kernel_off_t d_off; * unsigned short d_reclen; * char d_name[256]; * }; */ /* * * #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) * #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) * #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) * #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) * #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) * #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) * #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) * * #define S_IRWXU 00700 * #define S_IRUSR 00400 * #define S_IWUSR 00200 * #define S_IXUSR 00100 * * #define S_IRWXG 00070 * #define S_IRGRP 00040 * #define S_IWGRP 00020 * #define S_IXGRP 00010 * * #define S_IRWXO 00007 * #define S_IROTH 00004 * #define S_IWOTH 00002 * #define S_IXOTH 00001 */ #if 0 static char *dname (struct dirent *directentry); #endif #ifdef HAVE_STRFTIME /* We want our own dates for NLS */ #undef HAVE_STRFTIME #endif #undef gettext_noop #define gettext_noop(x) x void get_file_time (char *timestr, time_t file_time, int l); static char **get_filelist_line (void *data, int line_number, int *num_fields, int *tagged) { struct file_entry *directentry; static char *fields[10], size[24], mode[12], timestr[32]; static char name[520], *n; mode_t m; *num_fields = 4; /* name, size, date, mode only (for the mean time) */ directentry = (struct file_entry *) data; if (directentry[line_number].options & FILELIST_LAST_ENTRY) return 0; n = name; strcpy (name, directentry[line_number].name); fields[0] = name; sprintf (size, "\t%u", (unsigned int) directentry[line_number].stat.st_size); fields[1] = size; get_file_time (timestr, directentry[line_number].stat.st_mtime, 0); fields[2] = timestr; memset (mode, ' ', 11); mode[11] = 0; mode[0] = '-'; m = directentry[line_number].stat.st_mode; switch ((int) m & S_IFMT) { case S_IFLNK: mode[0] = 'l'; break; case S_IFDIR: mode[0] = 'd'; break; case S_IFCHR: mode[0] = 'c'; break; case S_IFBLK: mode[0] = 'b'; break; case S_IFIFO: mode[0] = 'f'; break; case S_IFSOCK: mode[0] = 's'; break; } mode[1] = m & S_IRUSR ? 'r' : '-'; mode[2] = m & S_IWUSR ? 'w' : '-'; mode[3] = m & S_IXUSR ? 'x' : '-'; mode[4] = m & S_IRGRP ? 'r' : '-'; mode[5] = m & S_IWGRP ? 'w' : '-'; mode[6] = m & S_IXGRP ? 'x' : '-'; mode[7] = m & S_IROTH ? 'r' : '-'; mode[8] = m & S_IWOTH ? 'w' : '-'; mode[9] = m & S_IXOTH ? 'x' : '-'; if (S_ISLNK (m)) { int l, i; char *p; p = directentry[line_number].name; l = strlen (n); for (i = 0; i < l; i++) { *n++ = '\b'; *n++ = *p++; } *n++ = '\0'; } else if (m & (S_IXUSR | S_IXGRP | S_IXOTH)) { int l, i; char *p; p = directentry[line_number].name; l = strlen (n); for (i = 0; i < l; i++) { *n++ = '\r'; *n++ = *p++; } *n++ = '\0'; } fields[3] = mode; fields[*num_fields] = 0; if (directentry[line_number].options & FILELIST_TAGGED_ENTRY) *tagged = 1; return fields; } CWidget *look_cool_draw_file_list (const char *identifier, Window parent, int x, int y, int width, int height, int line, int column, struct file_entry *directentry, long options) { struct file_entry e; CWidget *w; int n; if (!directentry) { memset (&e, 0, sizeof(e)); e.options = FILELIST_LAST_ENTRY; directentry = &e; n = 0; } else { for (n = 0; !(directentry[n].options & FILELIST_LAST_ENTRY); n++); /* count entries */ } w = CDrawFieldedTextbox (identifier, parent, x, y, width, height, line, column, get_filelist_line, options, directentry); w->destroy = destroy_filelist; w->hook = CMalloc (sizeof (struct file_entry) * (n + 1)); memcpy (w->hook, directentry, sizeof (struct file_entry) * (n + 1)); return w; } CWidget *look_cool_redraw_file_list (const char *identifier, struct file_entry *directentry, int preserve) { struct file_entry e; CWidget *w; int n; if (!directentry) { e.options = FILELIST_LAST_ENTRY; directentry = &e; n = 0; } else { for (n = 0; !(directentry[n].options & FILELIST_LAST_ENTRY); n++); /* count entries */ } w = CIdent (identifier); if (w->hook) free (w->hook); w->hook = CMalloc (sizeof (struct file_entry) * (n + 1)); memcpy (w->hook, directentry, sizeof (struct file_entry) * (n + 1)); w = CRedrawFieldedTextbox (identifier, preserve); return w; } struct file_entry *look_cool_get_file_list_line (CWidget * w, int line) { struct file_entry *e; static struct file_entry r; memset (&r, 0, sizeof (r)); e = (struct file_entry *) w->hook; if (e[line].options & FILELIST_LAST_ENTRY) r.options = FILELIST_LAST_ENTRY; else r = e[line]; return &r; } /* }}} file list stuff */ /* {{{ file browser stuff */ extern int option_file_browser_width; extern int option_file_browser_height; static char *mime_majors[3] = {"url", "text", 0}; static Window draw_file_browser (const char *identifier, Window parent, int x, int y, const char *directory, const char *file, const char *label) { CWidget * w; struct file_entry *filelist = 0, *directorylist = 0; char *dir; char *resolved_path, *p; int y2, x2, x3, y3; Window win; dir = (char *) strdup (directory); if (parent == CRoot) win = CDrawMainWindow (identifier, label); else win = CDrawHeadedDialog (identifier, parent, x, y, label); (CIdent (identifier))->options |= WINDOW_ALWAYS_RAISED; CHourGlass (CFirstWindow); for (;;) { filelist = get_file_entry_list (dir, FILELIST_FILES_ONLY, CLastInput (catstrs (identifier, ".filt", NULL))); if (!filelist) { char *s; s = strrchr (dir, '/'); if (s) { *s = '\0'; continue; } } break; } CUnHourGlass (CFirstWindow); if (!filelist || !(directorylist = get_file_entry_list (dir, FILELIST_DIRECTORIES_ONLY, ""))) { CErrorDialog (parent, 20, 20, _(" File browser "), _(" Unable to read directory ")); CDestroyWidget (identifier); goto error; } CGetHintPos (&x, &y); resolved_path = pathdup (dir); p = resolved_path + strlen (resolved_path) - 1; if (*p != '/') { *++p = '/'; *++p = '\0'; } (CDrawText (catstrs (identifier, ".dir", NULL), win, x, y, "%s", resolved_path))->position |= POSITION_FILL; free (resolved_path); CGetHintPos (0, &y); reset_hint_pos (x, y); y3 = y; (w = CDrawFilelist (catstrs (identifier, ".fbox", NULL), win, x, y, FONT_MEAN_WIDTH * option_file_browser_width + 7, FONT_PIX_PER_LINE * option_file_browser_height + 6, 0, 0, filelist, TEXTBOX_FILE_LIST))->position |= POSITION_WIDTH | POSITION_HEIGHT; xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFiles]); (CIdent (catstrs (identifier, ".fbox", NULL)))->options |= TEXTBOX_MARK_WHOLE_LINES; /* the vertical scroll bar is named the same as the text box, with a ".vsc" at the end: */ CSetMovement (catstrs (identifier, ".fbox.vsc", NULL), POSITION_HEIGHT | POSITION_RIGHT); CSetMovement (catstrs (identifier, ".fbox.hsc", NULL), POSITION_WIDTH | POSITION_BOTTOM); CGetHintPos (&x2, &y2); x3 = x2; (w = CDrawFilelist (catstrs (identifier, ".dbox", NULL), win, x2, y + TICK_BUTTON_WIDTH + WIDGET_SPACING, FONT_MEAN_WIDTH * 24 + 7, y2 - WIDGET_SPACING * 3 - 12 - y - TICK_BUTTON_WIDTH, 0, 0, directorylist, TEXTBOX_FILE_LIST))->position |= POSITION_HEIGHT | POSITION_RIGHT; xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFiles]); /* Toolhint */ CSetToolHint (catstrs (identifier, ".dbox", NULL), _("Double click to enter directories")); (CIdent (catstrs (identifier, ".dbox", NULL)))->options |= TEXTBOX_MARK_WHOLE_LINES; CSetMovement (catstrs (identifier, ".dbox.vsc", NULL), POSITION_HEIGHT | POSITION_RIGHT); CSetMovement (catstrs (identifier, ".dbox.hsc", NULL), POSITION_RIGHT | POSITION_BOTTOM); CGetHintPos (&x2, &y2); (CDrawText (catstrs (identifier, ".msg", NULL), win, x, y2, _("Ctrl-Tab to complete, Alt-Ins for clip history, Shift-Up for history")))->position |= POSITION_FILL | POSITION_BOTTOM; CGetHintPos (0, &y2); (w = CDrawTextInput (catstrs (identifier, ".finp", NULL), win, x, y2, WIDGET_SPACING * 2 - 2, AUTO_HEIGHT, 256, file))->position |= POSITION_FILL | POSITION_BOTTOM; xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndFile]); w->funcs->types = DndFile; w->funcs->mime_majors = mime_majors; CGetHintPos (0, &y2); /* Label for file filter input line. For example, to list files matching '*.c' */ (CDrawText (catstrs (identifier, ".filx", NULL), win, x, y2, _("Filter : ")))->position |= POSITION_BOTTOM; CGetHintPos (&x, 0); (CDrawTextInput (catstrs (identifier, ".filt", NULL), win, x, y2, WIDGET_SPACING * 2 - 2, AUTO_HEIGHT, 256, TEXTINPUT_LAST_INPUT))->position |= POSITION_FILL | POSITION_BOTTOM; /* Toolhint */ CSetToolHint (catstrs (identifier, ".filt", NULL), _("List only files matching this shell filter")); CSetToolHint (catstrs (identifier, ".filx", NULL), _("List only files matching this shell filter")); (CDrawPixmapButton (catstrs (identifier, ".ok", NULL), win, x3, y3, PIXMAP_BUTTON_TICK))->position |= POSITION_RIGHT; /* Toolhint */ CSetToolHint (catstrs (identifier, ".ok", NULL), _("Accept, Enter")); (CDrawPixmapButton (catstrs (identifier, ".cancel", NULL), win, x2 - WIDGET_SPACING * 2 - TICK_BUTTON_WIDTH - 20, y3, PIXMAP_BUTTON_CROSS))->position |= POSITION_RIGHT; /* Toolhint */ CSetToolHint (catstrs (identifier, ".cancel", NULL), _("Abort this dialog, Escape")); CSetSizeHintPos (identifier); CMapDialog (identifier); y = (CIdent (identifier))->height; CSetWindowResizable (identifier, FONT_MEAN_WIDTH * 40, min (FONT_PIX_PER_LINE * 5 + 210, y), 1600, 1200); /* minimum and maximum sizes */ error: if (directorylist) free (directorylist); if (filelist) free (filelist); free (dir); return win; } /* returns 0 on fail */ static int goto_partial_file_name (CWidget * list, char *text) { int i = 0; struct file_entry *fe = 0; char *e; for (;;) { if (!strlen (text)) break; if (list->kind == C_FIELDED_TEXTBOX_WIDGET) { fe = CGetFilelistLine (list, i); e = fe->name; } else { e = CGetTextBoxLine (list, i); if (e) while (*e == '/') e++; } if (!e) break; if (!strncmp (e, text, strlen (text))) { CSetTextboxPos (list, TEXT_SET_CURSOR_LINE, i); CSetTextboxPos (list, TEXT_SET_LINE, i); return 1; break; } if (list->kind == C_FIELDED_TEXTBOX_WIDGET) { if (fe->options & FILELIST_LAST_ENTRY) break; } else { if (i >= list->numlines - 1) break; } i++; } return 0; } /* options */ #define GETFILE_GET_DIRECTORY 1 #define GETFILE_GET_EXISTING_FILE 2 #define GETFILE_BROWSER 4 void input_insert (CWidget * w, int c); static char *file_error (void) { if (errno) { const char *error_msg; #ifdef HAVE_STRERROR error_msg = _ (strerror (errno)); #else extern int sys_nerr; extern char *sys_errlist[]; if ((0 <= errno) && (errno < sys_nerr)) error_msg = _ (sys_errlist[errno]); else /* The returned value, 'errno' has an unknown meaning */ error_msg = _ ("strange errno"); #endif return catstrs ("[", error_msg, "]", NULL); } return ""; } /* Returns "" on no file entered and NULL on exit (i.e. Cancel button pushed) else returns the file or directory. Result must be immediately copied. Result must not be free'd. */ static char *handle_browser (const char *identifier, CEvent * cwevent, int options) { struct stat st; char *q; char *idd = catstrs (identifier, ".dbox", NULL); char *idf = catstrs (identifier, ".fbox", NULL); static char estr[MAX_PATH_LEN + 1]; CWidget *directory = CIdent (catstrs (identifier, ".dir", NULL)); CWidget *filelist = CIdent (idf); CWidget *directorylist = CIdent (idd); CWidget *textinput = CIdent (catstrs (identifier, ".finp", NULL)); CWidget *filterinput = CIdent (catstrs (identifier, ".filt", NULL)); CSetDndDirectory (directory->text); if (cwevent->type == ButtonPress || cwevent->type == KeyPress) CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error()); if (!strcmp (cwevent->ident, filterinput->ident) && cwevent->command == CK_Enter) { struct file_entry *f; if (!(*(filterinput->text))) { filterinput->text[0] = '*'; filterinput->text[1] = '\0'; CExpose (filterinput->ident); } CHourGlass (CFirstWindow); CRedrawFilelist (catstrs (identifier, ".fbox", NULL), f = get_file_entry_list (directory->text, FILELIST_FILES_ONLY, filterinput->text), 0); if (f) free (f); CUnHourGlass (CFirstWindow); return ""; } if (!strcmp (cwevent->ident, idf) && !(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER))) { if (cwevent->button == Button1 || cwevent->command == CK_Enter) { q = (CGetFilelistLine (filelist, filelist->cursor))->name; CDrawTextInput (textinput->ident, CIdent (identifier)->winid, textinput->x, textinput->y, textinput->width, textinput->height, 256, q); } else if (cwevent->insert > 0) { input_insert (textinput, cwevent->insert); if (goto_partial_file_name (filelist, textinput->text)) CExpose (filelist->ident); CExpose (textinput->ident); } else if (cwevent->command == CK_BackSpace && textinput->cursor > 0) { textinput->text[--textinput->cursor] = '\0'; if (goto_partial_file_name (filelist, textinput->text)) CExpose (filelist->ident); CExpose (textinput->ident); } } if (!strcmp (cwevent->ident, idd)) { if (cwevent->button == Button1 || cwevent->command == CK_Enter) { q = (CGetFilelistLine (directorylist, directorylist->cursor))->name; CDrawTextInput (catstrs (identifier, ".finp", NULL), CIdent (identifier)->winid, textinput->x, textinput->y, textinput->width, textinput->height, 256, q); } else if (cwevent->insert > 0) { input_insert (textinput, cwevent->insert); if (goto_partial_file_name (directorylist, textinput->text)) CExpose (directorylist->ident); CExpose (textinput->ident); } else if (cwevent->command == CK_BackSpace && textinput->cursor > 0) { textinput->text[--textinput->cursor] = '\0'; if (goto_partial_file_name (directorylist, textinput->text)) CExpose (directorylist->ident); CExpose (textinput->ident); } } if (!strcmp (cwevent->ident, textinput->ident)) { switch ((int) cwevent->command) { case CK_Enter: if (!(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER))) if (!strncmp ((CGetFilelistLine (filelist, filelist->cursor))->name, textinput->text, strlen (textinput->text))) { CFocus (filelist); CExpose (filelist->ident); return ""; } break; case CK_Down: if (textinput->keypressed) { if (goto_partial_file_name (filelist, textinput->text)) { CFocus (filelist); CExpose (filelist->ident); break; } } CFocus (filelist); CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, 0); CExpose (filelist->ident); break; case CK_Up: if (textinput->keypressed) { if (goto_partial_file_name (filelist, textinput->text)) { CFocus (filelist); CExpose (filelist->ident); break; } } CFocus (filelist); CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, 999999); CExpose (filelist->ident); break; case CK_Page_Down: CFocus (filelist); CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, filelist->height / FONT_PIX_PER_LINE - 1); CExpose (filelist->ident); break; case CK_Page_Up: CFocus (filelist); CSetTextboxPos (filelist, TEXT_SET_CURSOR_LINE, filelist->numlines - filelist->height / FONT_PIX_PER_LINE + 1); CExpose (filelist->ident); break; default: if (cwevent->insert > 0) if (goto_partial_file_name (filelist, textinput->text)) CExpose (filelist->ident); break; } } if (cwevent->command == CK_Cancel || !strcmp (cwevent->ident, catstrs (identifier, ".cancel", NULL))) return 0; if (options & GETFILE_GET_DIRECTORY) { if (!strcmp (cwevent->ident, catstrs (identifier, ".ok", NULL))) { char *resolved_path; resolved_path = pathdup (directory->text); strcpy (estr, resolved_path); free (resolved_path); return estr; } } if (!strcmp (cwevent->ident, catstrs (identifier, ".ok", NULL)) || cwevent->command == CK_Enter || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".finp", NULL))) || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".dbox", NULL))) || (cwevent->double_click && !strcmp (cwevent->ident, catstrs (identifier, ".fbox", NULL)))) { char *resolved_path; if (*textinput->text == '/' || *textinput->text == '~') *estr = '\0'; else { strcpy (estr, directory->text); strcat (estr, "/"); } strcat (estr, textinput->text); resolved_path = pathdup (estr); strcpy (estr, resolved_path); free (resolved_path); textinput->keypressed = 0; q = estr + strlen (estr) - 1; if (!estr[0]) return ""; if (stat (estr, &st)) { if (errno == ENOENT) { /* The user wanted a directory, but typed in one that doesn't exist */ if (*q != '/' && !(options & GETFILE_GET_EXISTING_FILE) && !(options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER))) /* user wants a new file */ return estr; } /* ********* */ CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error()); return ""; } if (S_ISDIR (st.st_mode)) { struct file_entry *g = 0, *f = 0; CHourGlass (CFirstWindow); g = get_file_entry_list (estr, FILELIST_FILES_ONLY, filterinput->text); CUnHourGlass (CFirstWindow); if (g) { CRedrawFilelist (catstrs (identifier, ".fbox", NULL), g, 0); CRedrawFilelist (catstrs (identifier, ".dbox", NULL), f = get_file_entry_list (estr, FILELIST_DIRECTORIES_ONLY, ""), 0); if (*q != '/') { *++q = '/'; *++q = '\0'; } CRedrawText (catstrs (identifier, ".dir", NULL), "%s", estr); if (options & GETFILE_BROWSER) CAddToTextInputHistory (textinput->ident, estr); } if (g) free (g); if (f) free (f); return ""; } else { if (options & (GETFILE_GET_DIRECTORY | GETFILE_BROWSER)) { CRedrawText (catstrs (identifier, ".msg", NULL), "%s", file_error()); return ""; } return estr; /* entry exists and is a file */ } } return ""; } Window find_mapped_window (Window w); /* result must be free'd */ char *look_cool_get_file_or_dir (Window parent, int x, int y, const char *dir, const char *file, const char *label, int options) { CEvent cwevent; XEvent xevent; CState s; CWidget *w; CBackupState (&s); CDisable ("*"); CEnable ("_cfileBr*"); parent = find_mapped_window (parent); if (!(x | y)) { x = 20; y = 20; } draw_file_browser ("CGetFile", parent, x, y, dir, file, label); CFocus (CIdent ("CGetFile.finp")); file = ""; do { CNextEvent (&xevent, &cwevent); if (xevent.type == Expose || !xevent.type || xevent.type == InternalExpose || xevent.type == TickEvent) continue; if (!CIdent ("CGetFile")) { file = 0; break; } if (xevent.type == Expose || !xevent.type || xevent.type == AlarmEvent || xevent.type == InternalExpose || xevent.type == TickEvent) { file = ""; continue; } file = handle_browser ("CGetFile", &cwevent, options); if (!file) break; } while (!(*file)); /* here we want to add the complete path to the text-input history: */ w = CIdent ("CGetFile.finp"); if (w) { if (w->text) { free (w->text); w->text = 0; } if (file) w->text = (char *) strdup (file); } w = CIdent ("CGetFile.fbox"); if (w) { option_file_browser_width = (w->width - 7) / FONT_MEAN_WIDTH; if (option_file_browser_width < 10) option_file_browser_width = 10; option_file_browser_height = (w->height - 6) / FONT_PIX_PER_LINE; if (option_file_browser_height < 10) option_file_browser_height = 10; } CDestroyWidget ("CGetFile"); /* text is added to history when text-input widget is destroyed */ CRestoreState (&s); if (file) { return (char *) strdup (file); } else return 0; } static int cb_browser (CWidget * w, XEvent * x, CEvent * c) { char id[32], *s; strcpy (id, w->ident); s = strchr (id, '.'); if (s) *s = 0; if (!handle_browser (id, c, GETFILE_BROWSER)) { w = CIdent (catstrs (id, ".finp", NULL)); if (w) if (w->text) { free (w->text); w->text = 0; } CDestroyWidget (id); } return 0; } void look_cool_draw_browser (const char *ident, Window parent, int x, int y, const char *dir, const char *file, const char *label) { if (!(parent | x | y)) { parent = CFirstWindow; x = 20; y = 20; } draw_file_browser (ident, parent, x, y, dir, file, label); CAddCallback (catstrs (ident, ".dbox", NULL), cb_browser); CAddCallback (catstrs (ident, ".fbox", NULL), cb_browser); CAddCallback (catstrs (ident, ".finp", NULL), cb_browser); CAddCallback (catstrs (ident, ".filt", NULL), cb_browser); CAddCallback (catstrs (ident, ".ok", NULL), cb_browser); CAddCallback (catstrs (ident, ".cancel", NULL), cb_browser); CFocus (CIdent (catstrs (ident, ".finp", NULL))); } /* }}} file browser stuff */ int find_menu_hotkey (struct menu_item m[], int this, int num); /* outermost bevel */ #define BEVEL_MAIN 2 /* next-outermost bevel */ #define BEVEL_IN 4 #define BEVEL_OUT 5 /* between items, and between items and next-outermost bevel */ #define SPACING 4 /* between items rectangle and text */ #define RELIEF (TEXT_RELIEF + 1) #define S SPACING /* between window border and items */ #define O (BEVEL_OUT + SPACING) /* total height of an item */ /* size of bar item */ #define BAR_HEIGHT 8 #define ITEM_BEVEL_TYPE 1 #define ITEM_BEVEL 1 #define H (FONT_PIX_PER_LINE + RELIEF * 2) #define B BAR_HEIGHT static char *look_cool_get_default_widget_font (void) { return "-*-helvetica-bold-r-*--%d-*-*-*-*-*-*"; } static void look_cool_get_menu_item_extents (int n, int j, struct menu_item m[], int *border, int *relief, int *y1, int *y2) { int i, n_items = 0, n_bars = 0; *border = O; *relief = RELIEF; if (!n || j < 0) { *y1 = O; *y2 = *y1 + H; } else { int not_bar; not_bar = (m[j].text[2] != '\0'); for (i = 0; i < j; i++) if (m[i].text[2]) n_items++; else n_bars++; *y1 = O + n_items * (H + S) + n_bars * (B + S) + (not_bar ? 0 : 2); *y2 = *y1 + (not_bar ? H : (B - 4)); } } static void look_cool_menu_draw (Window win, int w, int h, struct menu_item m[], int n, int light) { int i, y1, y2, offset = 0; static int last_light = 0, last_n = 0; static Window last_win = 0; render_bevel (win, 0, 0, w - 1, h - 1, BEVEL_MAIN, 0); render_bevel (win, BEVEL_IN, BEVEL_IN, w - 1 - BEVEL_IN, h - 1 - BEVEL_IN, BEVEL_OUT - BEVEL_IN, 1); if (last_win == win && last_n != n) { XClearWindow (CDisplay, win); } else if (last_light >= 0 && last_light < n) { int border, relief; look_cool_get_menu_item_extents (n, last_light, m, &border, &relief, &y1, &y2); CSetColor (COLOR_FLAT); CRectangle (win, O - 1, y1 - 1, w - O * 2 + 2, y2 - y1 + 2); } last_win = win; last_n = n; CPushFont ("widget", 0); for (i = 0; i < n; i++) { int border, relief; look_cool_get_menu_item_extents (n, i, m, &border, &relief, &y1, &y2); if (i == light && m[i].text[2]) { offset = 1; CSetColor (color_widget (11)); CRectangle (win, O + 1, y1 + 1, w - O * 2 - 2, y2 - y1 - 2); render_bevel (win, O - 1, y1 - 1, w - O, y2, 2, 0); } else { if (!(m[i].text[2])) render_bevel (win, O + 6, y1, w - O - 1 - 6, y2 - 1, 2, 0); else render_bevel (win, O, y1, w - O - 1, y2 - 1, ITEM_BEVEL, ITEM_BEVEL_TYPE); offset = 0; } if (m[i].text[2]) { char *u; u = strrchr (m[i].text, '\t'); if (u) *u = 0; CSetColor (COLOR_BLACK); if (m[i].hot_key == '~') m[i].hot_key = find_menu_hotkey (m, i, n); if (i == light) CSetBackgroundColor (color_widget (11)); else CSetBackgroundColor (COLOR_FLAT); drawstring_xy_hotkey (win, RELIEF + O - offset, RELIEF + y1 - offset, m[i].text, m[i].hot_key); if (u) { drawstring_xy (win, RELIEF + O + (w - (O + RELIEF) * 2 - CImageStringWidth (u + 1)) - offset, RELIEF + y1 - offset, u + 1); *u = '\t'; } } } last_light = light; CPopFont (); } static void look_cool_render_menu_button (CWidget * wdt) { int w = wdt->width, h = wdt->height; int x = 0, y = 0; Window win = wdt->winid; if (wdt->disabled) goto disabled; if (wdt->options & BUTTON_PRESSED) { render_bevel (win, x, y, x + w - 1, y + h - 1, 2, 1); } else if (wdt->options & BUTTON_HIGHLIGHT) { CSetColor (COLOR_FLAT); XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3); render_bevel (win, x, y, x + w - 1, y + h - 1, 1, 0); } else { disabled: CSetColor (COLOR_FLAT); XDrawRectangle (CDisplay, win, CGC, x, y, w - 1, h - 1); XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3); } if (!wdt->label) return; if (!(*(wdt->label))) return; CSetColor (COLOR_BLACK); CPushFont ("widget", 0); CSetBackgroundColor (COLOR_FLAT); drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey); CPopFont (); } static void look_cool_render_button (CWidget * wdt) { int w = wdt->width, h = wdt->height; int x = 0, y = 0; Window win = wdt->winid; #define BUTTON_BEVEL 2 if (wdt->disabled) goto disabled; if (wdt->options & BUTTON_PRESSED) { render_bevel (win, x, y, x + w - 1, y + h - 1, BUTTON_BEVEL, 1); } else if (wdt->options & BUTTON_HIGHLIGHT) { CSetColor (COLOR_FLAT); XDrawRectangle (CDisplay, win, CGC, x + 1, y + 1, w - 3, h - 3); render_bevel (win, x, y, x + w - 1, y + h - 1, 1, 0); } else { disabled: render_bevel (win, x, y, x + w - 1, y + h - 1, BUTTON_BEVEL, 0); } if (!wdt->label) return; if (!(*(wdt->label))) return; CSetColor (COLOR_BLACK); CSetBackgroundColor (COLOR_FLAT); CPushFont ("widget", 0); drawstring_xy_hotkey (win, x + 2 + BUTTON_RELIEF, y + 2 + BUTTON_RELIEF, wdt->label, wdt->hotkey); CPopFont (); } static void look_cool_render_bar (CWidget * wdt) { int w = wdt->width, h = wdt->height; Window win = wdt->winid; CSetColor (COLOR_FLAT); CLine (win, 1, 1, w - 2, 1); render_bevel (win, 0, 0, w - 1, h - 1, 1, 1); } void look_cool_render_sunken_bevel (Window win, int x1, int y1, int x2, int y2, int thick, int sunken) { int i; if ((sunken & 2)) { CSetColor (COLOR_FLAT); CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1); } i = /* thick - 1 */ 0; CSetColor (color_widget (11)); CLine (win, x1 + i, y2 - i, x2 - 1 - i, y2 - i); CLine (win, x2 - i, y1 + i, x2 - i, y2 - i - 1); CSetColor (color_widget (7)); CLine (win, x1, y1, x1, y2 - 1); CLine (win, x1, y1, x2 - 1, y1); if (thick > 1) { CSetColor (color_widget (4)); for (i = 1; i < thick; i++) { CLine (win, x1 + i + 1, y1 + i, x2 - 1 - i, y1 + i); CLine (win, x1 + i, y1 + i, x1 + i, y2 - 1 - i); } CSetColor (color_widget (13)); for (i = 1; i < thick; i++) { CLine (win, x2 - i, y1 + i, x2 - i, y2 - i - 1); CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i); } } CSetColor (color_widget (14)); for (i = 0; i < thick; i++) XDrawPoint (CDisplay, win, CGC, x2 - i, y2 - i); } static void look_cool_render_raised_bevel (Window win, int x1, int y1, int x2, int y2, int thick, int sunken) { int i; if ((sunken & 2)) { CSetColor (COLOR_FLAT); CRectangle (win, x1 + thick, y1 + thick, x2 - x1 - 2 * thick + 1, y2 - y1 - 2 * thick + 1); } i = thick - 1; CSetColor (color_widget (7)); CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i); CLine (win, x2 - i, y1 + i, x2 - i, y2 - i); CSetColor (color_widget (12)); CLine (win, x1 + i, y1 + i, x1 + i, y2 - 1 - i); CLine (win, x1 + 1 + i, y1 + i, x2 - 1 - i, y1 + i); if (thick > 1) { CSetColor (color_widget (11)); for (i = 0; i < thick - 1; i++) { CLine (win, x1 + i + 1, y1 + i, x2 - 1 - i, y1 + i); CLine (win, x1 + i, y1 + i + 1, x1 + i, y2 - 1 - i); } CSetColor (color_widget (4)); for (i = 0; i < thick - 1; i++) { CLine (win, x2 - i, y1 + i, x2 - i, y2 - i); CLine (win, x1 + i, y2 - i, x2 - i - 1, y2 - i); } } CSetColor (color_widget (15)); for (i = 0; i < thick; i++) XDrawPoint (CDisplay, win, CGC, x1 + i, y1 + i); } static void look_cool_draw_hotkey_understroke (Window win, int x, int y, int hotkey) { CLine (win, x, y, x + FONT_PER_CHAR (hotkey), y); CLine (win, x - 1, y + 1, x + FONT_PER_CHAR (hotkey) / 2, y + 1); CLine (win, x - 1, y + 2, x + FONT_PER_CHAR (hotkey) / 4 - 1, y + 2); } static void look_cool_render_text (CWidget * wdt) { Window win = wdt->winid; char text[1024], *p, *q; int hot, y, w = wdt->width, center = 0; CPushFont ("widget", 0); CSetColor (COLOR_FLAT); CRectangle (win, 1, 1, w - 2, wdt->height - 2); CSetColor (COLOR_BLACK); hot = wdt->hotkey; /* a letter that needs underlining */ y = 1; /* bevel */ q = wdt->text; CSetBackgroundColor (COLOR_FLAT); for (;;) { p = strchr (q, '\n'); if (!p) { /* last line */ if (wdt->options & TEXT_CENTRED) center = (wdt->width - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, strlen (q))) / 2; drawstring_xy_hotkey (win, TEXT_RELIEF + 1 + center, TEXT_RELIEF + y, q, hot); break; } else { int l; l = min (1023, (unsigned long) p - (unsigned long) q); memcpy (text, q, l); text[l] = 0; if (wdt->options & TEXT_CENTRED) center = (wdt->width - (TEXT_RELIEF + 1) * 2 - CImageTextWidth (q, l)) / 2; drawstring_xy_hotkey (win, TEXT_RELIEF + 1 + center, TEXT_RELIEF + y, text, hot); } y += FONT_PIX_PER_LINE; hot = 0; /* only for first line */ q = p + 1; /* next line */ } render_bevel (win, 0, 0, w - 1, wdt->height - 1, 1, 1); CPopFont (); } static void look_cool_render_window (CWidget * wdt) { int w = wdt->width, h = wdt->height; Window win = wdt->winid; if (wdt->options & WINDOW_NO_BORDER) return; if (wdt->position & WINDOW_RESIZABLE) { CSetColor (color_widget (13)); CLine (win, w - 4, h - 31, w - 31, h - 4); CLine (win, w - 4, h - 21, w - 21, h - 4); CLine (win, w - 4, h - 11, w - 11, h - 4); CLine (win, w - 4, h - 32, w - 32, h - 4); CLine (win, w - 4, h - 22, w - 22, h - 4); CLine (win, w - 4, h - 12, w - 12, h - 4); CSetColor (color_widget (3)); CLine (win, w - 4, h - 27, w - 27, h - 4); CLine (win, w - 4, h - 17, w - 17, h - 4); CLine (win, w - 4, h - 7, w - 7, h - 4); CLine (win, w - 4, h - 28, w - 28, h - 4); CLine (win, w - 4, h - 18, w - 18, h - 4); CLine (win, w - 4, h - 8, w - 8, h - 4); } render_bevel (win, 0, 0, w - 1, h - 1, 2, 0); if (CRoot != wdt->parentid) if (win == CGetFocus ()) render_bevel (win, 4, 4, w - 5, h - 5, 3, 1); } static void look_cool_render_vert_scrollbar (Window win, int x, int y, int w, int h, int pos, int prop, int pos2, int prop2, int flags) { int l = h - 10 * w / 3 - 5; render_bevel (win, 0, 0, w - 1, h - 1, 2, 1); CSetColor (COLOR_FLAT); CRectangle (win, 2, w + 2 * w / 3 + 2, w - 4, (l - 5) * pos / 65535); CRectangle (win, 2, w + 2 * w / 3 + 3 + l * (prop + pos) / 65535, w - 4, h - 1 - w - 2 * w / 3 - (w + 2 * w / 3 + 4 + l * (prop + pos) / 65535)); if (flags & 32) { render_bevel (win, 2, 2, w - 3, w + 1, 2 - ((flags & 15) == 1), 2); render_bevel (win, 2, w + 2, w - 3, w + 2 * w / 3 + 1, 2 - ((flags & 15) == 2), 2); render_bevel (win, 2, h - 2 - w, w - 3, h - 3, 2 - ((flags & 15) == 4), 2); render_bevel (win, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w, 2 - ((flags & 15) == 5), 2); render_bevel (win, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, 2 - ((flags & 15) == 3), 2); } else { render_bevel (win, 2, 2, w - 3, w + 1, 2, 2 | ((flags & 15) == 1)); render_bevel (win, 2, w + 2, w - 3, w + 2 * w / 3 + 1, 2, 2 | ((flags & 15) == 2)); render_bevel (win, 2, h - 2 - w, w - 3, h - 3, 2, 2 | ((flags & 15) == 4)); render_bevel (win, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w, 2, 2 | ((flags & 15) == 5)); if ((flags & 15) == 3) { CSetColor (color_widget (5)); XDrawRectangle (CDisplay, win, CGC, 4, w + 2 * w / 3 + 4 + (l - 5) * pos2 / 65535, w - 10, 2 + (l - 5) * prop2 / 65535); } render_bevel (win, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, 2, 2 | ((flags & 15) == 3)); } } static void look_cool_render_hori_scrollbar (Window win, int x, int y, int h, int w, int pos, int prop, int flags) { int l = h - 10 * w / 3 - 5, k; k = (l - 5) * pos / 65535; render_bevel (win, 0, 0, h - 1, w - 1, 2, 1); CSetColor (COLOR_FLAT); CRectangle (win, w + 2 * w / 3 + 2, 2, (l - 5) * pos / 65535, w - 4); CRectangle (win, w + 2 * w / 3 + 3 + l * (prop + pos) / 65535, 2, h - 1 - w - 2 * w / 3 - (w + 2 * w / 3 + 4 + l * (prop + pos) / 65535), w - 4); if (flags & 32) { render_bevel (win, 2, 2, w + 1, w - 3, 2 - ((flags & 15) == 1), 2); render_bevel (win, w + 2, 2, w + 2 * w / 3 + 1, w - 3, 2 - ((flags & 15) == 2), 2); render_bevel (win, h - 2 - w, 2, h - 3, w - 3, 2 - ((flags & 15) == 4), 2); render_bevel (win, h - 2 - w - 2 * w / 3, 2, h - 3 - w, w - 3, 2 - ((flags & 15) == 5), 2); render_bevel (win, w + 2 * w / 3 + 2 + k, 2, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, w - 3, 2 - ((flags & 15) == 3), 2); } else { render_bevel (win, 2, 2, w + 1, w - 3, 2, 2 | ((flags & 15) == 1)); render_bevel (win, w + 2, 2, w + 2 * w / 3 + 1, w - 3, 2, 2 | ((flags & 15) == 2)); render_bevel (win, h - 2 - w, 2, h - 3, w - 3, 2, 2 | ((flags & 15) == 4)); render_bevel (win, h - 2 - w - 2 * w / 3, 2, h - 3 - w, w - 3, 2, 2 | ((flags & 15) == 5)); render_bevel (win, w + 2 * w / 3 + 2 + k, 2, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535, w - 3, 2, 2 | ((flags & 15) == 3)); } } static void look_cool_render_scrollbar (CWidget * wdt) { int flags = wdt->options; if (!wdt) return; if (wdt->numlines < 0) wdt->numlines = 0; if (wdt->firstline < 0) wdt->firstline = 0; if (wdt->firstline > 65535) wdt->firstline = 65535; if (wdt->firstline + wdt->numlines >= 65535) wdt->numlines = 65535 - wdt->firstline; if (wdt->kind == C_VERTSCROLL_WIDGET) { look_cool_render_vert_scrollbar (wdt->winid, wdt->x, wdt->y, wdt->width, wdt->height, wdt->firstline, wdt->numlines, wdt->search_start, wdt->search_len, flags); } else look_cool_render_hori_scrollbar (wdt->winid, wdt->x, wdt->y, wdt->width, wdt->height, wdt->firstline, wdt->numlines, flags); if (wdt->scroll_bar_extra_render) (*wdt->scroll_bar_extra_render) (wdt); } /* Which scrollbar button was pressed: 3 is the middle button ? */ static int look_cool_which_scrollbar_button (int bx, int by, CWidget * wdt) { int w, h; int pos = wdt->firstline; int prop = wdt->numlines; int l; if (wdt->kind == C_VERTSCROLL_WIDGET) { w = wdt->width; h = wdt->height; } else { int t = bx; bx = by; by = t; w = wdt->height; h = wdt->width; } l = h - 10 * w / 3 - 5; if (inbounds (bx, by, 2, 2, w - 3, w + 1)) return 1; if (inbounds (bx, by, 2, w + 2, w - 3, w + 2 * w / 3 + 1)) return 2; if (inbounds (bx, by, 2, h - 2 - w, w - 3, h - 3)) return 4; if (inbounds (bx, by, 2, h - 2 - w - 2 * w / 3, w - 3, h - 3 - w)) return 5; if (inbounds (bx, by, 2, w + 2 * w / 3 + 2 + (l - 5) * pos / 65535, w - 3, w + 2 * w / 3 + 7 + (l - 5) * (prop + pos) / 65535)) return 3; return 0; } int look_cool_scrollbar_handler (CWidget * w, XEvent * xevent, CEvent * cwevent) { static int buttonypos, y, whichscrbutton = 0; /* which of the five scroll bar buttons was pressed */ int xevent_xbutton_y, length, width; if (w->kind == C_VERTSCROLL_WIDGET) { xevent_xbutton_y = xevent->xbutton.y; length = w->height; width = w->width; } else { xevent_xbutton_y = xevent->xbutton.x; length = w->width; width = w->height; } switch (xevent->type) { case LeaveNotify: case Expose: w->options = 0; break; case ButtonRepeat: resolve_button (xevent, cwevent); if (cwevent->button == Button1 || cwevent->button == Button2) { int b; b = (*look->which_scrollbar_button) (cwevent->x, cwevent->y, w); if (b == 3 || !b) return 0; y = w->firstline; buttonypos = xevent_xbutton_y; w->options = whichscrbutton = b; cwevent->ident = w->ident; xevent->type = cwevent->type = ButtonPress; } break; case ButtonPress: resolve_button (xevent, cwevent); if (cwevent->button == Button1 || cwevent->button == Button2) { buttonypos = xevent_xbutton_y; y = w->firstline; w->options = whichscrbutton = (*look->which_scrollbar_button) (cwevent->x, cwevent->y, w); cwevent->ident = w->ident; w->search_start = w->firstline; w->search_len = w->numlines; } break; case ButtonRelease: resolve_button (xevent, cwevent); w->options = 32 + whichscrbutton; if (whichscrbutton == 3) { y += (double) (xevent_xbutton_y - buttonypos) * (double) 65535.0 / (length - 10 * width / 3 - 10); w->firstline = y; buttonypos = xevent_xbutton_y; } break; case MotionNotify: resolve_button (xevent, cwevent); if (cwevent->state & (Button1Mask | Button2Mask)) { w->options = whichscrbutton; if (whichscrbutton == 3) { y += (double) (xevent_xbutton_y - buttonypos) * (double) 65535.0 / (length - 10 * width / 3 - 10); w->firstline = y; buttonypos = xevent_xbutton_y; } } else w->options = 32 + (*look->which_scrollbar_button) (xevent->xmotion.x, xevent->xmotion.y, w); break; default: return 0; } if (w->firstline > 65535) w->firstline = 65535; if (cwevent->state & (Button1Mask | Button2Mask) || cwevent->type == ButtonPress || cwevent->type == ButtonRelease) if (w->scroll_bar_link && w->vert_scrollbar) (*w->scroll_bar_link) (w, w->vert_scrollbar, xevent, cwevent, whichscrbutton); if (xevent->type != Expose || !xevent->xexpose.count) (*look->render_scrollbar) (w); return 0; } static void look_cool_init_scrollbar_icons (CWidget * w) { return; } static int look_cool_get_scrollbar_size (int type) { if (type == C_HORISCROLL_WIDGET) return 13; return 20; } extern char *init_fg_color_red; extern char *init_fg_color_green; extern char *init_fg_color_blue; static void look_cool_get_button_color (XColor * color, int i) { double r, g, b, min_wc; r = 1 / atof (init_fg_color_red); g = 1 / atof (init_fg_color_green); b = 1 / atof (init_fg_color_blue); min_wc = min (r, min (g, b)); color->red = (float) 65535 *my_pow ((float) i / 20, r) * my_pow (0.75, -min_wc); color->green = (float) 65535 *my_pow ((float) i / 20, g) * my_pow (0.75, -min_wc); color->blue = (float) 65535 *my_pow ((float) i / 20, b) * my_pow (0.75, -min_wc); color->flags = DoRed | DoBlue | DoGreen; } static int look_cool_get_default_interwidget_spacing (void) { return 4; } int look_cool_window_handler (CWidget * w, XEvent * xevent, CEvent * cwevent) { static Window window_is_resizing = 0; static int windowx, windowy; static int wx = 0, wy = 0; static int wwidth = 0, wheight = 0; static int allowwindowmove = 0; static int allowwindowresize = 0; switch (xevent->type) { case ClientMessage: if (!w->disabled) cwevent->ident = w->ident; break; case Expose: if (!xevent->xexpose.count) render_window (w); break; case ButtonRelease: strcpy (cwevent->ident, w->ident); window_is_resizing = 0; resolve_button (xevent, cwevent); allowwindowmove = 0; allowwindowresize = 0; break; case ButtonPress: strcpy (cwevent->ident, w->ident); resolve_button (xevent, cwevent); if (cwevent->double_click == 1) { CWidget *c = CChildFocus (w); if (c) CFocus (c); } if (cwevent->button == Button1 && !(w->position & WINDOW_ALWAYS_LOWERED)) { XRaiseWindow (CDisplay, w->winid); CRaiseWindows (); } else if (cwevent->button == Button2 && !(w->position & WINDOW_ALWAYS_RAISED)) { XLowerWindow (CDisplay, w->winid); CLowerWindows (); } windowx = xevent->xbutton.x_root - w->x; windowy = xevent->xbutton.y_root - w->y; wx = xevent->xbutton.x; wy = xevent->xbutton.y; wwidth = w->width; wheight = w->height; if (wx + wy > w->width + w->height - 33 && w->position & WINDOW_RESIZABLE) allowwindowresize = 1; else allowwindowmove = 1; break; case MotionNotify: resolve_button (xevent, cwevent); if (!(w->position & WINDOW_UNMOVEABLE) && allowwindowmove && (cwevent->state & (Button1Mask | Button2Mask))) { w->x = xevent->xmotion.x_root - windowx; w->y = xevent->xmotion.y_root - windowy; if (w->x + xevent->xmotion.x < 2) w->x = -wx + 2; if (w->y + xevent->xmotion.y < 2) w->y = -wy + 2; XMoveWindow (CDisplay, w->winid, w->x, w->y); } if ((w->position & WINDOW_RESIZABLE) && allowwindowresize && (cwevent->state & (Button1Mask | Button2Mask))) { int wi, he; window_is_resizing = w->winid; wi = wwidth + xevent->xmotion.x_root - windowx - w->x; he = wheight + xevent->xmotion.y_root - windowy - w->y; /* this is actually for the edit windows, and needs to be generalized */ if (wi < w->mark1) wi = w->mark1; if (he < w->mark2) he = w->mark2; wi -= w->firstcolumn; wi -= wi % w->textlength; wi += w->firstcolumn; he -= w->firstline; he -= he % w->numlines; he += w->firstline; w->position &= ~WINDOW_MAXIMISED; CSetSize (w, wi, he); } break; } return 0; } extern Pixmap Cswitchon; extern Pixmap Cswitchoff; static void look_cool_render_switch (CWidget * wdt) { int w = wdt->width, h = wdt->height; Window win = wdt->winid; int x = 0, y = 0; CSetColor (COLOR_FLAT); CRectangle (win, x+5, y+5, w - 10, h - 10); CSetColor (wdt->fg); CSetBackgroundColor (wdt->bg); if (wdt->options & SWITCH_PICTURE_TYPE) { if (wdt->keypressed) XCopyPlane (CDisplay, Cswitchon, win, CGC, 0, 0, w, h, x, y, 1); else XCopyPlane (CDisplay, Cswitchoff, win, CGC, 0, 0, w, h, x, y, 1); } else { if (wdt->keypressed) { render_bevel (win, x + 3, y + 3, x + w - 4, y + h - 4, 2, 1); }else render_bevel (win, x + 3, y + 3, x + w - 4, y + h - 4, 2, 0); } if (wdt->options & (BUTTON_HIGHLIGHT | BUTTON_PRESSED)) render_rounded_bevel (win, x, y, x + w - 1, y + h - 1, 7, 1, 1); else render_rounded_bevel (win, x, y, x + w - 1, y + h - 1, 7, 1, 0); } extern unsigned long edit_normal_background_color; static void look_cool_edit_render_tidbits (CWidget * wdt) { int isfocussed; int w = wdt->width, h = wdt->height; Window win; win = wdt->winid; isfocussed = (win == CGetFocus ()); CSetColor (COLOR_FLAT); if (isfocussed) { render_bevel (win, 0, 0, w - 1, h - 1, 3, 1); /*most outer border bevel */ } else { render_bevel (win, 2, 2, w - 3, h - 3, 1, 1); /*border bevel */ render_bevel (win, 0, 0, w - 1, h - 1, 2, 0); /*most outer border bevel */ } CSetColor (edit_normal_background_color); CLine (CWindowOf (wdt), 3, 3, 3, CHeightOf (wdt) - 4); } CWidget *look_cool_draw_exclam_cancel_button (char *ident, Window win, int x, int y) { CWidget *wdt; wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_EXCLAMATION); return wdt; } CWidget *look_cool_draw_tick_cancel_button (char *ident, Window win, int x, int y) { CWidget *wdt; wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_TICK); return wdt; } CWidget *look_cool_draw_cross_cancel_button (char *ident, Window win, int x, int y) { CWidget *wdt; wdt = CDrawPixmapButton (ident, win, x, y, PIXMAP_BUTTON_CROSS); return wdt; } static void look_cool_render_fielded_textbox_tidbits (CWidget * w, int isfocussed) { if (isfocussed) { render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 3, 1); /*most outer border bevel */ } else { render_bevel (w->winid, 2, 2, w->width - 3, w->height - 3, 1, 1); /*border bevel */ render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 2, 0); /*most outer border bevel */ } CSetColor (edit_normal_background_color); CLine (w->winid, 3, 3, 3, w->height - 4); } static void look_cool_render_textbox_tidbits (CWidget * w, int isfocussed) { if (isfocussed) { render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 3, 1); /*most outer border bevel */ } else { render_bevel (w->winid, 2, 2, w->width - 3, w->height - 3, 1, 1); /*border bevel */ render_bevel (w->winid, 0, 0, w->width - 1, w->height - 1, 2, 0); /*most outer border bevel */ } } static void look_cool_render_passwordinput_tidbits (CWidget * wdt, int isfocussed) { int w = wdt->width, h = wdt->height; Window win = wdt->winid; if (isfocussed) { render_bevel (win, 0, 0, w - 1, h - 1, 3, 1); } else { render_bevel (win, 2, 2, w - 3, h - 3, 1, 1); render_bevel (win, 0, 0, w - 1, h - 1, 2, 0); } } static void look_cool_render_textinput_tidbits (CWidget * wdt, int isfocussed) { int w = wdt->width, h = wdt->height; Window win = wdt->winid; if (isfocussed) { render_bevel (win, 0, 0, w - h - 1, h - 1, 3, 1); /*most outer border bevel */ } else { render_bevel (win, 2, 2, w - h - 3, h - 3, 1, 1); /*border bevel */ render_bevel (win, 0, 0, w - h - 1, h - 1, 2, 0); /*most outer border bevel */ } if (wdt->options & BUTTON_PRESSED) { CRectangle (win, w - h + 2, 2, h - 4, h - 4); render_bevel (win, w - h, 0, w - 1, h - 1, 2, 3); } else if (wdt->options & BUTTON_HIGHLIGHT) { CRectangle (win, w - h + 1, 1, h - 2, h - 2); render_bevel (win, w - h, 0, w - 1, h - 1, 1, 2); } else { CRectangle (win, w - h + 2, 2, h - 4, h - 4); render_bevel (win, w - h, 0, w - 1, h - 1, 2, 2); } } extern struct focus_win focus_border; static void render_focus_border_n (Window win, int i) { int j; j = (i > 3) + 1; if (win == focus_border.top) { render_bevel (win, 0, 0, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, focus_border.height + 2 * WIDGET_FOCUS_RING - 1, j, 0); 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); } else if (win == focus_border.bottom) { render_bevel (win, 0, 0 - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1, WIDGET_FOCUS_RING - 1, j, 0); render_bevel (win, i, i - focus_border.height, focus_border.width + 2 * WIDGET_FOCUS_RING - 1 - i, WIDGET_FOCUS_RING - 1 - i, 2, 1); } else if (win == focus_border.left) { 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); 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); } else if (win == focus_border.right) { 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); 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); } } static void look_cool_render_focus_border (Window win) { render_focus_border_n (win, focus_border.border); } static int look_cool_get_extra_window_spacing (void) { return 2; } static int look_cool_get_focus_ring_size (void) { return 4; } static unsigned long look_cool_get_button_flat_color (void) { return color_widget(9); } static int look_cool_get_window_resize_bar_thickness (void) { return 0; } static int look_cool_get_switch_size (void) { return FONT_PIX_PER_LINE + TEXT_RELIEF * 2 + 2 + 4; } static int look_cool_get_fielded_textbox_hscrollbar_width (void) { return 12; } struct look look_cool = { look_cool_get_default_interwidget_spacing, look_cool_menu_draw, look_cool_get_menu_item_extents, look_cool_render_menu_button, look_cool_render_button, look_cool_render_bar, look_cool_render_raised_bevel, look_cool_render_sunken_bevel, look_cool_draw_hotkey_understroke, look_cool_get_default_widget_font, look_cool_render_text, look_cool_render_window, look_cool_render_scrollbar, look_cool_get_scrollbar_size, look_cool_init_scrollbar_icons, look_cool_which_scrollbar_button, look_cool_scrollbar_handler, look_cool_get_button_color, look_cool_get_extra_window_spacing, look_cool_window_handler, look_cool_get_focus_ring_size, look_cool_get_button_flat_color, look_cool_get_window_resize_bar_thickness, look_cool_render_switch, look_cool_get_switch_size, look_cool_draw_browser, look_cool_get_file_or_dir, look_cool_draw_file_list, look_cool_redraw_file_list, look_cool_get_file_list_line, look_cool_search_replace_dialog, look_cool_edit_render_tidbits, look_cool_draw_exclam_cancel_button, look_cool_draw_tick_cancel_button, look_cool_draw_cross_cancel_button, look_cool_draw_tick_cancel_button, look_cool_render_fielded_textbox_tidbits, look_cool_render_textbox_tidbits, look_cool_get_fielded_textbox_hscrollbar_width, look_cool_render_textinput_tidbits, look_cool_render_passwordinput_tidbits, look_cool_render_focus_border, };