PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/cygwin/src/misc.c

#
C | 406 lines | 255 code | 48 blank | 103 comment | 114 complexity | e641851916cb3f918359cded1526ed1f MD5 | raw file
  1. /*--------------------------------*-C-*---------------------------------*
  2. * File: misc.c
  3. *----------------------------------------------------------------------*
  4. * $Id: misc.c 1512 2001-10-10 07:17:49Z gcw $
  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-2000 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 "../config.h" /* NECESSARY */
  26. #include "rxvt.h" /* NECESSARY */
  27. #include "misc.intpro" /* PROTOS for internal routines */
  28. /* EXTPROTO */
  29. char *
  30. rxvt_r_basename(const char *str)
  31. {
  32. char *base = STRRCHR(str, '/');
  33. return (char *)(base ? base + 1 : str);
  34. }
  35. /*
  36. * Print an error message
  37. */
  38. /* EXTPROTO */
  39. void
  40. rxvt_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. rxvt_Str_match(const char *s1, const char *s2)
  60. {
  61. int n = STRLEN(s2);
  62. return ((STRNCMP(s1, s2, n) == 0) ? n : 0);
  63. }
  64. /* EXTPROTO */
  65. const char *
  66. rxvt_Str_skip_space(const char *str)
  67. {
  68. if (str)
  69. while (*str && isspace(*str))
  70. str++;
  71. return str;
  72. }
  73. /*
  74. * remove leading/trailing space and strip-off leading/trailing quotes.
  75. * in place.
  76. */
  77. /* EXTPROTO */
  78. char *
  79. rxvt_Str_trim(char *str)
  80. {
  81. char *r, *s;
  82. int n;
  83. if (!str || !*str) /* shortcut */
  84. return str;
  85. /* skip leading spaces */
  86. for (s = str; *s && isspace(*s); s++) ;
  87. /* goto end of string */
  88. for (n = 0, r = s; *r++; n++) ;
  89. r -= 2;
  90. /* dump return */
  91. if (n > 0 && *r == '\n')
  92. n--, r--;
  93. /* backtrack along trailing spaces */
  94. for (; n > 0 && isspace(*r); r--, n--) ;
  95. /* skip matching leading/trailing quotes */
  96. if (*s == '"' && *r == '"' && n > 1) {
  97. s++;
  98. n -= 2;
  99. }
  100. /* copy back over: forwards copy */
  101. for (r = str; n; n--)
  102. *r++ = *s++;
  103. *r = '\0';
  104. return str;
  105. }
  106. /*
  107. * in-place interpretation of string:
  108. *
  109. * backslash-escaped: "\a\b\E\e\n\r\t", "\octal"
  110. * Ctrl chars: ^@ .. ^_, ^?
  111. *
  112. * Emacs-style: "M-" prefix
  113. *
  114. * Also,
  115. * "M-x" prefixed strings, append "\r" if needed
  116. * "\E]" prefixed strings (XTerm escape sequence) append ST if needed
  117. *
  118. * returns the converted string length
  119. */
  120. /* EXTPROTO */
  121. int
  122. rxvt_Str_escaped(char *str)
  123. {
  124. char ch, *s, *d;
  125. int i, num, append = 0;
  126. if (!str || !*str)
  127. return 0;
  128. d = s = str;
  129. if (*s == 'M' && s[1] == '-') {
  130. /* Emacs convenience, replace leading `M-..' with `\E..' */
  131. *d++ = C0_ESC;
  132. s += 2;
  133. if (toupper(*s) == 'X')
  134. /* append carriage-return for `M-xcommand' */
  135. for (*d++ = 'x', append = '\r', s++; isspace(*s); s++) ;
  136. }
  137. for (; (ch = *s++);) {
  138. if (ch == '\\') {
  139. ch = *s++;
  140. if (ch >= '0' && ch <= '7') { /* octal */
  141. num = ch - '0';
  142. for (i = 0; i < 2; i++, s++) {
  143. ch = *s;
  144. if (ch < '0' || ch > '7')
  145. break;
  146. num = num * 8 + ch - '0';
  147. }
  148. ch = (char)num;
  149. } else if (ch == 'a')
  150. ch = C0_BEL; /* bell */
  151. else if (ch == 'b')
  152. ch = C0_BS; /* backspace */
  153. else if (ch == 'E' || ch == 'e')
  154. ch = C0_ESC; /* escape */
  155. else if (ch == 'n')
  156. ch = '\n'; /* newline */
  157. else if (ch == 'r')
  158. ch = '\r'; /* carriage-return */
  159. else if (ch == 't')
  160. ch = C0_HT; /* tab */
  161. } else if (ch == '^') {
  162. ch = *s++;
  163. ch = toupper(ch);
  164. ch = (ch == '?' ? 127 : (ch - '@'));
  165. }
  166. *d++ = ch;
  167. }
  168. /* ESC] is an XTerm escape sequence, must be terminated */
  169. if (*str == '\0' && str[1] == C0_ESC && str[2] == ']')
  170. append = CHAR_ST;
  171. /* add trailing character as required */
  172. if (append && d[-1] != append)
  173. *d++ = append;
  174. *d = '\0';
  175. return (d - str);
  176. }
  177. /*
  178. * Split a comma-separated string into an array, stripping leading and
  179. * trailing spaces (and paired quotes) from each entry. Empty strings
  180. * are properly returned
  181. * Caller should free each entry and array when done
  182. */
  183. /* EXTPROTO */
  184. char **
  185. rxvt_splitcommastring(const char *cs)
  186. {
  187. int l, n, p;
  188. const char *s, *t;
  189. char **ret;
  190. if ((s = cs) == NULL)
  191. s = "";
  192. for (n = 1, t = s; *t; t++)
  193. if (*t == ',')
  194. n++;
  195. ret = malloc((n + 1) * sizeof(char *));
  196. ret[n] = NULL;
  197. for (l = 0, t = s; l < n; l++) {
  198. for ( ; *t && *t != ','; t++) ;
  199. p = t - s;
  200. ret[l] = malloc(p + 1);
  201. strncpy(ret[l], s, p);
  202. ret[l][p] = '\0';
  203. rxvt_Str_trim(ret[l]);
  204. s = ++t;
  205. }
  206. return ret;
  207. }
  208. /*----------------------------------------------------------------------*
  209. * file searching
  210. */
  211. /* #define DEBUG_SEARCH_PATH */
  212. #if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
  213. /*
  214. * search for FILE in the current working directory, and within the
  215. * colon-delimited PATHLIST, adding the file extension EXT if required.
  216. *
  217. * FILE is either semi-colon or zero terminated
  218. */
  219. /* INTPROTO */
  220. char *
  221. rxvt_File_search_path(const char *pathlist, const char *file, const char *ext)
  222. {
  223. int maxpath, len;
  224. const char *p, *path;
  225. char name[256];
  226. if (!access(file, R_OK)) /* found (plain name) in current directory */
  227. return STRDUP(file);
  228. /* semi-colon delimited */
  229. if ((p = STRCHR(file, ';')))
  230. len = (p - file);
  231. else
  232. len = STRLEN(file);
  233. #ifdef DEBUG_SEARCH_PATH
  234. getcwd(name, sizeof(name));
  235. fprintf(stderr, "pwd: \"%s\"\n", name);
  236. fprintf(stderr, "find: \"%.*s\"\n", len, file);
  237. #endif
  238. /* leave room for an extra '/' and trailing '\0' */
  239. maxpath = sizeof(name) - (len + (ext ? STRLEN(ext) : 0) + 2);
  240. if (maxpath <= 0)
  241. return NULL;
  242. /* check if we can find it now */
  243. STRNCPY(name, file, len);
  244. name[len] = '\0';
  245. if (!access(name, R_OK))
  246. return STRDUP(name);
  247. if (ext) {
  248. STRCAT(name, ext);
  249. if (!access(name, R_OK))
  250. return STRDUP(name);
  251. }
  252. for (path = pathlist; path != NULL && *path != '\0'; path = p) {
  253. int n;
  254. /* colon delimited */
  255. if ((p = STRCHR(path, ':')) == NULL)
  256. p = STRCHR(path, '\0');
  257. n = (p - path);
  258. if (*p != '\0')
  259. p++;
  260. if (n > 0 && n <= maxpath) {
  261. STRNCPY(name, path, n);
  262. if (name[n - 1] != '/')
  263. name[n++] = '/';
  264. name[n] = '\0';
  265. STRNCAT(name, file, len);
  266. if (!access(name, R_OK))
  267. return STRDUP(name);
  268. if (ext) {
  269. STRCAT(name, ext);
  270. if (!access(name, R_OK))
  271. return STRDUP(name);
  272. }
  273. }
  274. }
  275. return NULL;
  276. }
  277. /* EXTPROTO */
  278. char *
  279. rxvt_File_find(const char *file, const char *ext, const char *path)
  280. {
  281. char *f;
  282. if (file == NULL || *file == '\0')
  283. return NULL;
  284. /* search environment variables here too */
  285. if ((f = rxvt_File_search_path(path, file, ext)) == NULL)
  286. #ifdef PATH_ENV
  287. if ((f = rxvt_File_search_path(getenv(PATH_ENV), file, ext)) == NULL)
  288. #endif
  289. f = rxvt_File_search_path(getenv("PATH"), file, ext);
  290. #ifdef DEBUG_SEARCH_PATH
  291. if (f)
  292. fprintf(stderr, "found: \"%s\"\n", f);
  293. #endif
  294. return f;
  295. }
  296. #endif /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
  297. /*----------------------------------------------------------------------*
  298. * miscellaneous drawing routines
  299. */
  300. /*
  301. * Draw top/left and bottom/right border shadows around windows
  302. */
  303. #if defined(RXVT_SCROLLBAR) || defined(MENUBAR)
  304. /* EXTPROTO */
  305. void
  306. rxvt_Draw_Shadow(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int h)
  307. {
  308. int shadow;
  309. shadow = (w == 0 || h == 0) ? 1 : SHADOW;
  310. w += x - 1;
  311. h += y - 1;
  312. for (; shadow-- > 0; x++, y++, w--, h--) {
  313. XDrawLine(Xdisplay, win, topShadow, x, y, w, y);
  314. XDrawLine(Xdisplay, win, topShadow, x, y, x, h);
  315. XDrawLine(Xdisplay, win, botShadow, w, h, w, y + 1);
  316. XDrawLine(Xdisplay, win, botShadow, w, h, x + 1, h);
  317. }
  318. }
  319. #endif
  320. /* button shapes */
  321. #ifdef MENUBAR
  322. /* EXTPROTO */
  323. void
  324. rxvt_Draw_Triangle(Display *Xdisplay, Window win, GC topShadow, GC botShadow, int x, int y, int w, int type)
  325. {
  326. switch (type) {
  327. case 'r': /* right triangle */
  328. XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
  329. XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y + w / 2);
  330. XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2);
  331. break;
  332. case 'l': /* left triangle */
  333. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
  334. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2);
  335. XDrawLine(Xdisplay, win, topShadow, x, y + w / 2, x + w, y);
  336. break;
  337. case 'd': /* down triangle */
  338. XDrawLine(Xdisplay, win, topShadow, x, y, x + w / 2, y + w);
  339. XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y);
  340. XDrawLine(Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w);
  341. break;
  342. case 'u': /* up triangle */
  343. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y);
  344. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w);
  345. XDrawLine(Xdisplay, win, topShadow, x, y + w, x + w / 2, y);
  346. break;
  347. #if 0
  348. case 's': /* square */
  349. XDrawLine(Xdisplay, win, topShadow, x + w, y, x, y);
  350. XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w);
  351. XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w);
  352. XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y);
  353. break;
  354. #endif
  355. }
  356. }
  357. #endif
  358. /*----------------------- end-of-file (C source) -----------------------*/