ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/misc.C
Revision: 1.15
Committed: Sun Aug 15 04:54:21 2004 UTC (19 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-4_0, rel-3_7, rel-3_8
Changes since 1.13: +35 -35 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*--------------------------------*-C-*---------------------------------*
2 pcg 1.13 * File: misc.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1996 mj olesen <olesen@me.QueensU.CA> Queen's Univ at Kingston
7     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8     * Copyright (c) 1998-2000 Geoff Wing <gcw@pobox.com>
9 pcg 1.8 * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24     *----------------------------------------------------------------------*/
25    
26     #include "../config.h" /* NECESSARY */
27     #include "rxvt.h" /* NECESSARY */
28     #include "misc.intpro" /* PROTOS for internal routines */
29    
30 root 1.15 /* INTPROTO */
31 pcg 1.3 char *
32 pcg 1.10 rxvt_wcstombs (const wchar_t *str, int len)
33     {
34     mbstate mbs;
35     char *r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1);
36    
37     char *dst = r;
38     while (len--)
39     {
40     int l = wcrtomb (dst, *str++, mbs);
41     if (l < 0)
42     *dst++ = '?';
43     else
44     dst += l;
45     }
46    
47     *dst++ = 0;
48    
49     return r;
50     }
51    
52 root 1.15 /* INTPROTO */
53 pcg 1.10 char *
54 pcg 1.3 rxvt_strdup (const char *str)
55     {
56     return str ? strdup (str) : 0;
57     }
58    
59 root 1.15 /* INTPROTO */
60 pcg 1.8 char *
61 pcg 1.7 rxvt_r_basename (const char *str)
62 pcg 1.1 {
63 root 1.15 char *base = strrchr (str, '/');
64 pcg 1.1
65 pcg 1.7 return (char *) (base ? base + 1 : str);
66 pcg 1.1 }
67    
68     /*
69     * Print an error message
70     */
71 root 1.15 /* INTPROTO */
72 pcg 1.1 void
73 pcg 1.12 rxvt_vlog (const char *fmt, va_list arg_ptr)
74     {
75     char msg[1024];
76    
77     vsnprintf (msg, sizeof msg, fmt, arg_ptr);
78    
79     if (GET_R && GET_R->log_hook)
80     (*GET_R->log_hook) (msg);
81     else
82     write (STDOUT_FILENO, msg, strlen (msg));
83     }
84    
85 root 1.15 /* INTPROTO */
86 pcg 1.12 void
87     rxvt_log (const char *fmt,...)
88 pcg 1.1 {
89 pcg 1.8 va_list arg_ptr;
90 pcg 1.1
91 pcg 1.7 va_start (arg_ptr, fmt);
92 pcg 1.12 rxvt_vlog (fmt, arg_ptr);
93 pcg 1.7 va_end (arg_ptr);
94 pcg 1.1 }
95    
96     /*
97 pcg 1.12 * Print an error message
98     */
99 root 1.15 /* INTPROTO */
100 pcg 1.12 void
101     rxvt_warn (const char *fmt,...)
102     {
103     va_list arg_ptr;
104    
105     rxvt_log ("%s: ", RESNAME);
106    
107     va_start (arg_ptr, fmt);
108     rxvt_vlog (fmt, arg_ptr);
109     va_end (arg_ptr);
110     }
111    
112 root 1.15 /* INTPROTO */
113 pcg 1.12 void
114     rxvt_fatal (const char *fmt,...)
115     {
116     va_list arg_ptr;
117    
118     rxvt_log ("%s: ", RESNAME);
119    
120     va_start (arg_ptr, fmt);
121     rxvt_vlog (fmt, arg_ptr);
122     va_end (arg_ptr);
123    
124     rxvt_exit_failure ();
125     }
126    
127     class rxvt_failure_exception rxvt_failure_exception;
128    
129 root 1.15 /* INTPROTO */
130 pcg 1.12 void
131     rxvt_exit_failure ()
132     {
133     throw (rxvt_failure_exception);
134     }
135    
136     /*
137 pcg 1.1 * check that the first characters of S1 match S2
138     *
139     * No Match
140     * return: 0
141     * Match
142 root 1.15 * return: strlen (S2)
143 pcg 1.1 */
144 root 1.15 /* INTPROTO */
145 pcg 1.1 int
146 pcg 1.7 rxvt_Str_match (const char *s1, const char *s2)
147 pcg 1.1 {
148 root 1.15 int n = strlen (s2);
149 pcg 1.1
150 root 1.15 return ((strncmp (s1, s2, n) == 0) ? n : 0);
151 pcg 1.1 }
152    
153 root 1.15 /* INTPROTO */
154 pcg 1.8 const char *
155 pcg 1.7 rxvt_Str_skip_space (const char *str)
156 pcg 1.1 {
157 pcg 1.5 if (str)
158 pcg 1.7 while (*str && isspace (*str))
159 pcg 1.5 str++;
160 pcg 1.8
161 pcg 1.5 return str;
162 pcg 1.1 }
163    
164     /*
165     * remove leading/trailing space and strip-off leading/trailing quotes.
166     * in place.
167     */
168 root 1.15 /* INTPROTO */
169 pcg 1.1 char *
170 pcg 1.7 rxvt_Str_trim (char *str)
171 pcg 1.1 {
172 pcg 1.8 char *r, *s;
173     int n;
174 pcg 1.1
175 pcg 1.5 if (!str || !*str) /* shortcut */
176     return str;
177 pcg 1.1
178 pcg 1.5 /* skip leading spaces */
179 pcg 1.7 for (s = str; *s && isspace (*s); s++) ;
180 pcg 1.5 /* goto end of string */
181     for (n = 0, r = s; *r++; n++) ;
182     r -= 2;
183     /* dump return */
184     if (n > 0 && *r == '\n')
185     n--, r--;
186     /* backtrack along trailing spaces */
187 pcg 1.7 for (; n > 0 && isspace (*r); r--, n--) ;
188 pcg 1.5 /* skip matching leading/trailing quotes */
189     if (*s == '"' && *r == '"' && n > 1)
190     {
191     s++;
192     n -= 2;
193 pcg 1.1 }
194 pcg 1.8
195 pcg 1.5 /* copy back over: forwards copy */
196     for (r = str; n; n--)
197     *r++ = *s++;
198     *r = '\0';
199 pcg 1.1
200 pcg 1.5 return str;
201 pcg 1.1 }
202    
203     /*
204     * in-place interpretation of string:
205     *
206     * backslash-escaped: "\a\b\E\e\n\r\t", "\octal"
207     * Ctrl chars: ^@ .. ^_, ^?
208     *
209     * Emacs-style: "M-" prefix
210     *
211     * Also,
212     * "M-x" prefixed strings, append "\r" if needed
213     * "\E]" prefixed strings (XTerm escape sequence) append ST if needed
214     *
215     * returns the converted string length
216     */
217 root 1.15 /* INTPROTO */
218 pcg 1.1 int
219 pcg 1.7 rxvt_Str_escaped (char *str)
220 pcg 1.1 {
221 pcg 1.5 char ch, *s, *d;
222     int i, num, append = 0;
223 pcg 1.1
224 pcg 1.5 if (!str || !*str)
225     return 0;
226 pcg 1.1
227 pcg 1.5 d = s = str;
228 pcg 1.1
229 pcg 1.5 if (*s == 'M' && s[1] == '-')
230     {
231     /* Emacs convenience, replace leading `M-..' with `\E..' */
232     *d++ = C0_ESC;
233     s += 2;
234 pcg 1.7 if (toupper (*s) == 'X')
235 pcg 1.5 /* append carriage-return for `M-xcommand' */
236 pcg 1.7 for (*d++ = 'x', append = '\r', s++; isspace (*s); s++) ;
237 pcg 1.1 }
238 pcg 1.5 for (; (ch = *s++);)
239     {
240     if (ch == '\\')
241     {
242     ch = *s++;
243     if (ch >= '0' && ch <= '7')
244     { /* octal */
245     num = ch - '0';
246     for (i = 0; i < 2; i++, s++)
247     {
248     ch = *s;
249     if (ch < '0' || ch > '7')
250     break;
251     num = num * 8 + ch - '0';
252     }
253     ch = (char)num;
254     }
255     else if (ch == 'a')
256     ch = C0_BEL; /* bell */
257     else if (ch == 'b')
258     ch = C0_BS; /* backspace */
259     else if (ch == 'E' || ch == 'e')
260     ch = C0_ESC; /* escape */
261     else if (ch == 'n')
262     ch = '\n'; /* newline */
263     else if (ch == 'r')
264     ch = '\r'; /* carriage-return */
265     else if (ch == 't')
266     ch = C0_HT; /* tab */
267     }
268     else if (ch == '^')
269     {
270     ch = *s++;
271 pcg 1.7 ch = toupper (ch);
272 pcg 1.5 ch = (ch == '?' ? 127 : (ch - '@'));
273     }
274     *d++ = ch;
275 pcg 1.1 }
276    
277 pcg 1.5 /* ESC] is an XTerm escape sequence, must be terminated */
278     if (*str == '\0' && str[1] == C0_ESC && str[2] == ']')
279     append = CHAR_ST;
280    
281     /* add trailing character as required */
282     if (append && d[-1] != append)
283     *d++ = append;
284     *d = '\0';
285 pcg 1.1
286 pcg 1.5 return (d - str);
287 pcg 1.1 }
288    
289     /*
290     * Split a comma-separated string into an array, stripping leading and
291     * trailing spaces (and paired quotes) from each entry. Empty strings
292     * are properly returned
293     * Caller should free each entry and array when done
294     */
295 root 1.15 /* INTPROTO */
296 pcg 1.1 char **
297 pcg 1.7 rxvt_splitcommastring (const char *cs)
298 pcg 1.1 {
299 pcg 1.5 int l, n, p;
300     const char *s, *t;
301     char **ret;
302    
303     if ((s = cs) == NULL)
304     s = "";
305    
306     for (n = 1, t = s; *t; t++)
307     if (*t == ',')
308     n++;
309 pcg 1.7 ret = (char **)malloc ((n + 1) * sizeof (char *));
310 pcg 1.5 ret[n] = NULL;
311    
312     for (l = 0, t = s; l < n; l++)
313     {
314     for ( ; *t && *t != ','; t++) ;
315     p = t - s;
316 pcg 1.7 ret[l] = (char *)malloc (p + 1);
317     strncpy (ret[l], s, p);
318 pcg 1.5 ret[l][p] = '\0';
319 pcg 1.7 rxvt_Str_trim (ret[l]);
320 pcg 1.5 s = ++t;
321 pcg 1.1 }
322 pcg 1.5 return ret;
323 pcg 1.1 }
324    
325     /*----------------------------------------------------------------------*
326     * file searching
327     */
328    
329     /* #define DEBUG_SEARCH_PATH */
330    
331     #if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
332     /*
333     * search for FILE in the current working directory, and within the
334     * colon-delimited PATHLIST, adding the file extension EXT if required.
335     *
336     * FILE is either semi-colon or zero terminated
337     */
338     /* INTPROTO */
339     char *
340 pcg 1.7 rxvt_File_search_path (const char *pathlist, const char *file, const char *ext)
341 pcg 1.1 {
342 pcg 1.5 int maxpath, len;
343     const char *p, *path;
344     char name[256];
345    
346 pcg 1.7 if (!access (file, R_OK)) /* found (plain name) in current directory */
347 root 1.15 return strdup (file);
348 pcg 1.5
349     /* semi-colon delimited */
350 root 1.15 if ((p = strchr (file, ';')))
351 pcg 1.5 len = (p - file);
352     else
353 root 1.15 len = strlen (file);
354 pcg 1.1
355     #ifdef DEBUG_SEARCH_PATH
356 pcg 1.7 getcwd (name, sizeof (name));
357     fprintf (stderr, "pwd: \"%s\"\n", name);
358     fprintf (stderr, "find: \"%.*s\"\n", len, file);
359 pcg 1.1 #endif
360    
361 pcg 1.5 /* leave room for an extra '/' and trailing '\0' */
362 root 1.15 maxpath = sizeof (name) - (len + (ext ? strlen (ext) : 0) + 2);
363 pcg 1.5 if (maxpath <= 0)
364     return NULL;
365    
366     /* check if we can find it now */
367 root 1.15 strncpy (name, file, len);
368 pcg 1.5 name[len] = '\0';
369    
370 pcg 1.7 if (!access (name, R_OK))
371 root 1.15 return strdup (name);
372 pcg 1.5 if (ext)
373     {
374 root 1.15 strcat (name, ext);
375 pcg 1.7 if (!access (name, R_OK))
376 root 1.15 return strdup (name);
377 pcg 1.1 }
378 pcg 1.5 for (path = pathlist; path != NULL && *path != '\0'; path = p)
379     {
380     int n;
381    
382     /* colon delimited */
383 root 1.15 if ((p = strchr (path, ':')) == NULL)
384     p = strchr (path, '\0');
385 pcg 1.5
386     n = (p - path);
387     if (*p != '\0')
388     p++;
389    
390     if (n > 0 && n <= maxpath)
391     {
392 root 1.15 strncpy (name, path, n);
393 pcg 1.5 if (name[n - 1] != '/')
394     name[n++] = '/';
395     name[n] = '\0';
396 root 1.15 strncat (name, file, len);
397 pcg 1.5
398 pcg 1.7 if (!access (name, R_OK))
399 root 1.15 return strdup (name);
400 pcg 1.5 if (ext)
401     {
402 root 1.15 strcat (name, ext);
403 pcg 1.7 if (!access (name, R_OK))
404 root 1.15 return strdup (name);
405 pcg 1.5 }
406     }
407 pcg 1.1 }
408 pcg 1.5 return NULL;
409 pcg 1.1 }
410    
411 root 1.15 /* INTPROTO */
412 pcg 1.1 char *
413 pcg 1.7 rxvt_File_find (const char *file, const char *ext, const char *path)
414 pcg 1.1 {
415 pcg 1.5 char *f;
416 pcg 1.1
417 pcg 1.5 if (file == NULL || *file == '\0')
418     return NULL;
419 pcg 1.1
420 pcg 1.5 /* search environment variables here too */
421 pcg 1.7 if ((f = rxvt_File_search_path (path, file, ext)) == NULL)
422 pcg 1.1 #ifdef PATH_ENV
423 pcg 1.7 if ((f = rxvt_File_search_path (getenv (PATH_ENV), file, ext)) == NULL)
424 pcg 1.1 #endif
425 pcg 1.7 f = rxvt_File_search_path (getenv ("PATH"), file, ext);
426 pcg 1.1
427     #ifdef DEBUG_SEARCH_PATH
428 pcg 1.5 if (f)
429 pcg 1.7 fprintf (stderr, "found: \"%s\"\n", f);
430 pcg 1.1 #endif
431    
432 pcg 1.5 return f;
433 pcg 1.1 }
434     #endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
435    
436     /*----------------------------------------------------------------------*
437     * miscellaneous drawing routines
438     */
439    
440     /*
441     * Draw top/left and bottom/right border shadows around windows
442     */
443     #if defined(RXVT_SCROLLBAR) || defined(MENUBAR)
444 root 1.15 /* INTPROTO */
445 pcg 1.1 void
446 pcg 1.7 rxvt_Draw_Shadow (Display *display, Window win, GC topShadow, GC botShadow, int x, int y, int w, int h)
447 pcg 1.1 {
448 pcg 1.5 int shadow;
449 pcg 1.1
450 pcg 1.5 shadow = (w == 0 || h == 0) ? 1 : SHADOW;
451     w += x - 1;
452     h += y - 1;
453     for (; shadow-- > 0; x++, y++, w--, h--)
454     {
455 pcg 1.7 XDrawLine (display, win, topShadow, x, y, w, y);
456     XDrawLine (display, win, topShadow, x, y, x, h);
457     XDrawLine (display, win, botShadow, w, h, w, y + 1);
458     XDrawLine (display, win, botShadow, w, h, x + 1, h);
459 pcg 1.1 }
460     }
461     #endif
462    
463     /* button shapes */
464     #ifdef MENUBAR
465 root 1.15 /* INTPROTO */
466 pcg 1.1 void
467 pcg 1.7 rxvt_Draw_Triangle (Display *display, Window win, GC topShadow, GC botShadow, int x, int y, int w, int type)
468 pcg 1.1 {
469 pcg 1.5 switch (type)
470     {
471     case 'r': /* right triangle */
472 pcg 1.7 XDrawLine (display, win, topShadow, x, y, x, y + w);
473     XDrawLine (display, win, topShadow, x, y, x + w, y + w / 2);
474     XDrawLine (display, win, botShadow, x, y + w, x + w, y + w / 2);
475 pcg 1.5 break;
476    
477     case 'l': /* left triangle */
478 pcg 1.7 XDrawLine (display, win, botShadow, x + w, y + w, x + w, y);
479     XDrawLine (display, win, botShadow, x + w, y + w, x, y + w / 2);
480     XDrawLine (display, win, topShadow, x, y + w / 2, x + w, y);
481 pcg 1.5 break;
482    
483     case 'd': /* down triangle */
484 pcg 1.7 XDrawLine (display, win, topShadow, x, y, x + w / 2, y + w);
485     XDrawLine (display, win, topShadow, x, y, x + w, y);
486     XDrawLine (display, win, botShadow, x + w, y, x + w / 2, y + w);
487 pcg 1.5 break;
488    
489     case 'u': /* up triangle */
490 pcg 1.7 XDrawLine (display, win, botShadow, x + w, y + w, x + w / 2, y);
491     XDrawLine (display, win, botShadow, x + w, y + w, x, y + w);
492     XDrawLine (display, win, topShadow, x, y + w, x + w / 2, y);
493 pcg 1.5 break;
494 pcg 1.1 #if 0
495 pcg 1.5 case 's': /* square */
496 pcg 1.7 XDrawLine (display, win, topShadow, x + w, y, x, y);
497     XDrawLine (display, win, topShadow, x, y, x, y + w);
498     XDrawLine (display, win, botShadow, x, y + w, x + w, y + w);
499     XDrawLine (display, win, botShadow, x + w, y + w, x + w, y);
500 pcg 1.5 break;
501 pcg 1.1 #endif
502 pcg 1.5
503 pcg 1.1 }
504     }
505     #endif
506     /*----------------------- end-of-file (C source) -----------------------*/