PageRenderTime 41ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/rxvt-xim/src/misc.c

#
C | 400 lines | 258 code | 45 blank | 97 comment | 93 complexity | 5f1a53ff7e48b5e0b81575e50da1c1d6 MD5 | raw file
  1. /*--------------------------------*-C-*---------------------------------*
  2. * File: misc.c
  3. *----------------------------------------------------------------------*
  4. * $Id: misc.c 328 1999-01-07 06:27:36Z 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. case '1': /* octal */
  149. case '2': /* octal */
  150. case '3': /* octal */
  151. case '4': /* octal */
  152. case '5': /* octal */
  153. case '6': /* octal */
  154. case '7': /* octal */
  155. num = ch - '0';
  156. for (i = 0; i < 2; i++, s++) {
  157. ch = *s;
  158. if (ch < '0' || ch > '7')
  159. break;
  160. num = num * 8 + ch - '0';
  161. }
  162. ch = (char) num;
  163. break;
  164. case 'a': /* bell */
  165. ch = 007;
  166. break;
  167. case 'b': /* backspace */
  168. ch = '\b';
  169. break;
  170. case 'E': /* escape */
  171. case 'e':
  172. ch = 033;
  173. break;
  174. case 'n': /* newline */
  175. ch = '\n';
  176. break;
  177. case 'r': /* carriage-return */
  178. ch = '\r';
  179. break;
  180. case 't': /* tab */
  181. ch = '\t';
  182. break;
  183. }
  184. } else if (ch == '^') {
  185. ch = *s++;
  186. ch = toupper(ch);
  187. ch = (ch == '?' ? 127 : (ch - '@'));
  188. }
  189. *d++ = ch;
  190. }
  191. /* ESC] is an XTerm escape sequence, must be ^G terminated */
  192. if (*str == '\0' && str[1] == '\033' && str[2] == ']')
  193. append = 007;
  194. /* add trailing character as required */
  195. if (append && d[-1] != append)
  196. *d++ = append;
  197. *d = '\0';
  198. return (d - str);
  199. }
  200. /*----------------------------------------------------------------------*
  201. * file searching
  202. */
  203. /* #define DEBUG_SEARCH_PATH */
  204. #if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
  205. /*
  206. * search for FILE in the current working directory, and within the
  207. * colon-delimited PATHLIST, adding the file extension EXT if required.
  208. *
  209. * FILE is either semi-colon or zero terminated
  210. */
  211. /* INTPROTO */
  212. char *
  213. File_search_path(const char *pathlist, const char *file, const char *ext)
  214. {
  215. int maxpath, len;
  216. const char *p, *path;
  217. char name[256];
  218. if (!access(file, R_OK)) /* found (plain name) in current directory */
  219. return strdup(file);
  220. /* semi-colon delimited */
  221. if ((p = strchr(file, ';')))
  222. len = (p - file);
  223. else
  224. len = strlen(file);
  225. #ifdef DEBUG_SEARCH_PATH
  226. getcwd(name, sizeof(name));
  227. fprintf(stderr, "pwd: \"%s\"\n", name);
  228. fprintf(stderr, "find: \"%.*s\"\n", len, file);
  229. #endif
  230. /* leave room for an extra '/' and trailing '\0' */
  231. maxpath = sizeof(name) - (len + (ext ? strlen(ext) : 0) + 2);
  232. if (maxpath <= 0)
  233. return NULL;
  234. /* check if we can find it now */
  235. strncpy(name, file, len);
  236. name[len] = '\0';
  237. if (!access(name, R_OK))
  238. return strdup(name);
  239. if (ext) {
  240. strcat(name, ext);
  241. if (!access(name, R_OK))
  242. return strdup(name);
  243. }
  244. for (path = pathlist; path != NULL && *path != '\0'; path = p) {
  245. int n;
  246. /* colon delimited */
  247. if ((p = strchr(path, ':')) == NULL)
  248. p = strchr(path, '\0');
  249. n = (p - path);
  250. if (*p != '\0')
  251. p++;
  252. if (n > 0 && n <= maxpath) {
  253. STRNCPY(name, path, n);
  254. if (name[n - 1] != '/')
  255. name[n++] = '/';
  256. name[n] = '\0';
  257. strncat(name, file, len);
  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. }
  266. }
  267. return NULL;
  268. }
  269. /* EXTPROTO */
  270. char *
  271. File_find(const char *file, const char *ext)
  272. {
  273. char *f;
  274. if (file == NULL || *file == '\0')
  275. return NULL;
  276. /* search environment variables here too */
  277. if ((f = File_search_path(rs[Rs_path], file, ext)) == NULL)
  278. #ifdef PATH_ENV
  279. if ((f = File_search_path(getenv(PATH_ENV), file, ext)) == NULL)
  280. #endif
  281. f = File_search_path(getenv("PATH"), file, ext);
  282. #ifdef DEBUG_SEARCH_PATH
  283. if (f)
  284. fprintf(stderr, "found: \"%s\"\n", f);
  285. #endif
  286. return f;
  287. }
  288. #endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
  289. /*----------------------------------------------------------------------*
  290. * miscellaneous drawing routines
  291. */
  292. /*
  293. * Draw top/left and bottom/right border shadows around windows
  294. */
  295. /* EXTPROTO */
  296. void
  297. Draw_Shadow(Window win, GC topShadow, GC botShadow, int x, int y, int w, int h)
  298. {
  299. int x1, y1, w1, h1, shadow;
  300. shadow = (w == 0 || h == 0) ? 1 : SHADOW;
  301. w1 = w + x - 1;
  302. h1 = h + y - 1;
  303. x1 = x;
  304. y1 = y;
  305. for (; shadow-- > 0; x1++, y1++, w1--, h1--) {
  306. XDrawLine(Xdisplay, win, topShadow, x1, y1, w1, y1);
  307. XDrawLine(Xdisplay, win, topShadow, x1, y1, x1, h1);
  308. }
  309. shadow = (w == 0 || h == 0) ? 1 : SHADOW;
  310. w1 = w + x - 1;
  311. h1 = h + y - 1;
  312. x1 = x + 1;
  313. y1 = y + 1;
  314. for (; shadow-- > 0; x1++, y1++, w1--, h1--) {
  315. XDrawLine(Xdisplay, win, botShadow, w1, h1, w1, y1);
  316. XDrawLine(Xdisplay, win, botShadow, w1, h1, x1, h1);
  317. }
  318. }
  319. /* button shapes */
  320. /* EXTPROTO */
  321. void
  322. Draw_Triangle(Window win, GC topShadow, GC botShadow, int x, int y, int w, int type)
  323. {
  324. switch (type) {
  325. case 'r': /* right triangle */
  326. XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
  327. XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y + w / 2);
  328. XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2);
  329. break;
  330. case 'l': /* right triangle */
  331. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
  332. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2);
  333. XDrawLine(Xdisplay, win, topShadow, x, y + w / 2, x + w, y);
  334. break;
  335. case 'd': /* down triangle */
  336. XDrawLine(Xdisplay, win, topShadow, x, y, x + w / 2, y + w);
  337. XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y);
  338. XDrawLine(Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w);
  339. break;
  340. case 'u': /* up triangle */
  341. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y);
  342. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w);
  343. XDrawLine(Xdisplay, win, topShadow, x, y + w, x + w / 2, y);
  344. break;
  345. #if 0
  346. case 's': /* square */
  347. XDrawLine(Xdisplay, win, topShadow, x + w, y, x, y);
  348. XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
  349. XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w);
  350. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
  351. break;
  352. #endif
  353. }
  354. }
  355. /*----------------------- end-of-file (C source) -----------------------*/