1 #include "rxvtlib.h"
2
3 /*--------------------------------*-C-*---------------------------------*
4 * File: misc.c
5 *----------------------------------------------------------------------*
6 * $Id: misc.c,v 1.21 1999/05/05 22:49:34 mason Exp $
7 *
8 * All portions of code are copyright by their respective author/s.
9 * Copyright (C) 1996 mj olesen <olesen@me.QueensU.CA> Queen's Univ at Kingston
10 * Copyright (C) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
11 * Copyright (C) 1998 Geoff Wing <gcw@pobox.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *----------------------------------------------------------------------*/
27
28 /*----------------------------------------------------------------------*/
29 /* EXTPROTO */
my_basename(const char * str)30 const char *my_basename (const char *str)
31 {
32 const char *base = strrchr (str, '/');
33
34 return (base ? base + 1 : str);
35 }
36
37 /*
38 * Print an error message
39 */
40 /* EXTPROTO */
print_error(const char * fmt,...)41 void print_error (const char *fmt, ...)
42 {
43 va_list arg_ptr;
44
45 va_start (arg_ptr, fmt);
46 fprintf (stderr, APL_NAME ": ");
47 vfprintf (stderr, fmt, arg_ptr);
48 fprintf (stderr, "\n");
49 va_end (arg_ptr);
50 }
51
52 /*
53 * check that the first characters of S1 match S2
54 *
55 * No Match
56 * return: 0
57 * Match
58 * return: strlen (S2)
59 */
60 /* EXTPROTO */
Str_match(const char * s1,const char * s2)61 int Str_match (const char *s1, const char *s2)
62 {
63 int n;
64
65 if (s1 == NULL || s2 == NULL)
66 return 0;
67 for (n = 0; *s2; n++)
68 if (*s1++ != *s2++)
69 return 0;
70 return n;
71 }
72
73 /* EXTPROTO */
Str_skip_space(const char * str)74 const char *Str_skip_space (const char *str)
75 {
76 if (str)
77 while (*str && isspace (*str))
78 str++;
79 return str;
80 }
81
82 /*
83 * remove leading/trailing space and strip-off leading/trailing quotes.
84 * in place.
85 */
86 /* EXTPROTO */
Str_trim(char * str)87 char *Str_trim (char *str)
88 {
89 char *r, *s;
90 int n;
91
92 if (!str)
93 return NULL;
94 if (!*str) /* shortcut */
95 return str;
96
97 /* skip leading spaces */
98 for (s = str; *s && isspace (*s); s++) ;
99 /* goto end of string */
100 for (n = 0, r = s; *r++; n++) ;
101 r -= 2;
102 /* dump return */
103 if (n > 0 && *r == '\n')
104 n--, r--;
105 /* backtrack along trailing spaces */
106 for (; n > 0 && isspace (*r); r--, n--) ;
107 /* skip matching leading/trailing quotes */
108 if (*s == '"' && *r == '"' && n > 1) {
109 s++;
110 n -= 2;
111 }
112 /* copy back over: forwards copy */
113 for (r = str; n; n--)
114 *r++ = *s++;
115 *r = '\0';
116
117 return str;
118 }
119
120 /*
121 * in-place interpretation of string:
122 *
123 * backslash-escaped: "\a\b\E\e\n\r\t", "\octal"
124 * Ctrl chars: ^@ .. ^_, ^?
125 *
126 * Emacs-style: "M-" prefix
127 *
128 * Also,
129 * "M-x" prefixed strings, append "\r" if needed
130 * "\E]" prefixed strings (XTerm escape sequence) append "\a" if needed
131 *
132 * returns the converted string length
133 */
134 /* EXTPROTO */
Str_escaped(char * str)135 int Str_escaped (char *str)
136 {
137 char ch, *s, *d;
138 int i, num, append = 0;
139
140 if (!str || !*str)
141 return 0;
142
143 d = s = str;
144
145 if (*s == 'M' && s[1] == '-') {
146 /* Emacs convenience, replace leading `M-..' with `\E..' */
147 *d++ = '\033';
148 s += 2;
149 if (toupper (*s) == 'X')
150 /* append carriage-return for `M-xcommand' */
151 for (*d++ = 'x', append = '\r', s++; isspace (*s); s++) ;
152 }
153 for (; (ch = *s++);) {
154 if (ch == '\\') {
155 switch ((ch = *s++)) {
156 case '0': /* octal */
157 case '1': /* octal */
158 case '2': /* octal */
159 case '3': /* octal */
160 case '4': /* octal */
161 case '5': /* octal */
162 case '6': /* octal */
163 case '7': /* octal */
164 num = ch - '0';
165 for (i = 0; i < 2; i++, s++) {
166 ch = *s;
167 if (ch < '0' || ch > '7')
168 break;
169 num = num * 8 + ch - '0';
170 }
171 ch = (char)num;
172 break;
173 case 'a': /* bell */
174 ch = 007;
175 break;
176 case 'b': /* backspace */
177 ch = '\b';
178 break;
179 case 'E': /* escape */
180 case 'e':
181 ch = 033;
182 break;
183 case 'n': /* newline */
184 ch = '\n';
185 break;
186 case 'r': /* carriage-return */
187 ch = '\r';
188 break;
189 case 't': /* tab */
190 ch = '\t';
191 break;
192 }
193 } else if (ch == '^') {
194 ch = *s++;
195 ch = toupper (ch);
196 ch = (ch == '?' ? 127 : (ch - '@'));
197 }
198 *d++ = ch;
199 }
200
201 /* ESC] is an XTerm escape sequence, must be ^G terminated */
202 if (*str == '\0' && str[1] == '\033' && str[2] == ']')
203 append = 007;
204
205 /* add trailing character as required */
206 if (append && d[-1] != append)
207 *d++ = append;
208 *d = '\0';
209
210 return (d - str);
211 }
212
213 /*----------------------------------------------------------------------*
214 * file searching
215 */
216
217 /* #define DEBUG_SEARCH_PATH */
218
219 #if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
220 /*
221 * search for FILE in the current working directory, and within the
222 * colon-delimited PATHLIST, adding the file extension EXT if required.
223 *
224 * FILE is either semi-colon or zero terminated
225 */
226 /* INTPROTO */
File_search_path(const char * pathlist,const char * file,const char * ext)227 char *File_search_path (const char *pathlist, const char *file,
228 const char *ext)
229 {
230 int maxpath, len;
231 const char *p, *path;
232 char name[256];
233
234 if (!access (file, R_OK)) /* found (plain name) in current directory */
235 return strdup (file);
236
237 /* semi-colon delimited */
238 if ((p = strchr (file, ';')))
239 len = (p - file);
240 else
241 len = strlen (file);
242
243 #ifdef DEBUG_SEARCH_PATH
244 getcwd (name, sizeof (name));
245 fprintf (stderr, "pwd: \"%s\"\n", name);
246 fprintf (stderr, "find: \"%.*s\"\n", len, file);
247 #endif
248
249 /* leave room for an extra '/' and trailing '\0' */
250 maxpath = sizeof (name) - (len + (ext ? strlen (ext) : 0) + 2);
251 if (maxpath <= 0)
252 return NULL;
253
254 /* check if we can find it now */
255 STRNCPY (name, file, len);
256 name[len] = '\0';
257
258 if (!access (name, R_OK))
259 return strdup (name);
260 if (ext) {
261 strcat (name, ext);
262 if (!access (name, R_OK))
263 return strdup (name);
264 }
265 for (path = pathlist; path != NULL && *path != '\0'; path = p) {
266 int n;
267
268 /* colon delimited */
269 if ((p = strchr (path, ':')) == NULL)
270 p = strchr (path, '\0');
271
272 n = (p - path);
273 if (*p != '\0')
274 p++;
275
276 if (n > 0 && n <= maxpath) {
277 STRNCPY (name, path, n);
278 if (name[n - 1] != '/')
279 name[n++] = '/';
280 name[n] = '\0';
281 strncat (name, file, len);
282
283 if (!access (name, R_OK))
284 return strdup (name);
285 if (ext) {
286 strcat (name, ext);
287 if (!access (name, R_OK))
288 return strdup (name);
289 }
290 }
291 }
292 return NULL;
293 }
294
295 /* EXTPROTO */
rxvtlib_File_find(rxvtlib * o,const char * file,const char * ext)296 char *rxvtlib_File_find (rxvtlib *o, const char *file, const char *ext)
297 {
298 char *f;
299
300 if (file == NULL || *file == '\0')
301 return NULL;
302
303 /* search environment variables here too */
304 if ((f = File_search_path (o->rs[Rs_path], file, ext)) == NULL)
305 #ifdef PATH_ENV
306 if ((f = File_search_path (getenv (PATH_ENV), file, ext)) == NULL)
307 #endif
308 f = File_search_path (getenv ("PATH"), file, ext);
309
310 #ifdef DEBUG_SEARCH_PATH
311 if (f)
312 fprintf (stderr, "found: \"%s\"\n", f);
313 #endif
314
315 return f;
316 }
317 #endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
318
319 /*----------------------------------------------------------------------*
320 * miscellaneous drawing routines
321 */
322
323 /*
324 * Draw top/left and bottom/right border shadows around windows
325 */
326 #if (! defined(NEXT_SCROLLBAR) && ! defined(XTERM_SCROLLBAR)) || defined(MENUBAR)
327 /* EXTPROTO */
rxvtlib_Draw_Shadow(rxvtlib * o,Window win,GC topShadow,GC botShadow,int x,int y,int w,int h)328 void rxvtlib_Draw_Shadow (rxvtlib *o, Window win, GC topShadow, GC botShadow, int x,
329 int y, int w, int h)
330 {
331 int x1, y1, w1, h1, shadow;
332
333 shadow = (w == 0 || h == 0) ? 1 : SHADOW;
334 w1 = w + x - 1;
335 h1 = h + y - 1;
336 x1 = x;
337 y1 = y;
338 for (; shadow-- > 0; x1++, y1++, w1--, h1--) {
339 XDrawLine (o->Xdisplay, win, topShadow, x1, y1, w1, y1);
340 XDrawLine (o->Xdisplay, win, topShadow, x1, y1, x1, h1);
341 }
342
343 shadow = (w == 0 || h == 0) ? 1 : SHADOW;
344 w1 = w + x - 1;
345 h1 = h + y - 1;
346 x1 = x + 1;
347 y1 = y + 1;
348 for (; shadow-- > 0; x1++, y1++, w1--, h1--) {
349 XDrawLine (o->Xdisplay, win, botShadow, w1, h1, w1, y1);
350 XDrawLine (o->Xdisplay, win, botShadow, w1, h1, x1, h1);
351 }
352 }
353 #endif
354
355 /* button shapes */
356 #ifdef MENUBAR
357 /* EXTPROTO */
rxvtlib_Draw_Triangle(rxvtlib * o,Window win,GC topShadow,GC botShadow,int x,int y,int w,int type)358 void rxvtlib_Draw_Triangle (rxvtlib *o, Window win, GC topShadow, GC botShadow, int x,
359 int y, int w, int type)
360 {
361 switch (type) {
362 case 'r': /* right triangle */
363 XDrawLine (o->Xdisplay, win, topShadow, x, y, x, y + w);
364 XDrawLine (o->Xdisplay, win, topShadow, x, y, x + w, y + w / 2);
365 XDrawLine (o->Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2);
366 break;
367
368 case 'l': /* right triangle */
369 XDrawLine (o->Xdisplay, win, botShadow, x + w, y + w, x + w, y);
370 XDrawLine (o->Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2);
371 XDrawLine (o->Xdisplay, win, topShadow, x, y + w / 2, x + w, y);
372 break;
373
374 case 'd': /* down triangle */
375 XDrawLine (o->Xdisplay, win, topShadow, x, y, x + w / 2, y + w);
376 XDrawLine (o->Xdisplay, win, topShadow, x, y, x + w, y);
377 XDrawLine (o->Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w);
378 break;
379
380 case 'u': /* up triangle */
381 XDrawLine (o->Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y);
382 XDrawLine (o->Xdisplay, win, botShadow, x + w, y + w, x, y + w);
383 XDrawLine (o->Xdisplay, win, topShadow, x, y + w, x + w / 2, y);
384 break;
385 #if 0
386 case 's': /* square */
387 XDrawLine (o->Xdisplay, win, topShadow, x + w, y, x, y);
388 XDrawLine (o->Xdisplay, win, topShadow, x, y, x, y + w);
389 XDrawLine (o->Xdisplay, win, botShadow, x, y + w, x + w, y + w);
390 XDrawLine (o->Xdisplay, win, botShadow, x + w, y + w, x + w, y);
391 break;
392 #endif
393 }
394 }
395 #endif
396 /*----------------------- end-of-file (C source) -----------------------*/
397