PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/rxvt-2-4-10/src/misc.c

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