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

/src/utils.cc

https://github.com/snmsts/xyzzy
C++ | 558 lines | 512 code | 46 blank | 0 comment | 126 complexity | bb9e7c3249c06a82ec3fd4ca6510828b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #include "stdafx.h"
  2. #include "cdecl.h"
  3. #include "ed.h"
  4. #include "utils.h"
  5. #include "chtype.h"
  6. void *
  7. xmalloc (size_t size)
  8. {
  9. if (!size)
  10. size = 1;
  11. void *p = malloc (size);
  12. if (!p)
  13. FEstorage_error ();
  14. return p;
  15. }
  16. void *
  17. xrealloc (void *p, size_t size)
  18. {
  19. if (!size)
  20. size = 1;
  21. if (!p)
  22. p = malloc (size);
  23. else
  24. p = realloc (p, size);
  25. if (!p)
  26. FEstorage_error ();
  27. return p;
  28. }
  29. void
  30. xfree (void *p)
  31. {
  32. if (p)
  33. free (p);
  34. }
  35. char *
  36. xstrdup (const char *s)
  37. {
  38. return strcpy ((char *)xmalloc (strlen (s) + 1), s);
  39. }
  40. void *
  41. xmemdup (const void *p, size_t size)
  42. {
  43. return memcpy (xmalloc (size), p, size);
  44. }
  45. char *
  46. stpcpy (char *d, const char *s)
  47. {
  48. while ((*d++ = *s++))
  49. ;
  50. return d - 1;
  51. }
  52. char *
  53. stpncpy (char *d, const char *s, int n)
  54. {
  55. for (; n > 0; n--)
  56. {
  57. if (!(*d++ = *s++))
  58. return d - 1;
  59. }
  60. *d = 0;
  61. return d;
  62. }
  63. char *
  64. jindex (const char *p, int c)
  65. {
  66. for (const u_char *s = (const u_char *)p; *s;)
  67. {
  68. if (SJISP (*s) && s[1])
  69. s += 2;
  70. else
  71. {
  72. if (*s == c)
  73. return (char *)s;
  74. s++;
  75. }
  76. }
  77. return 0;
  78. }
  79. char *
  80. jrindex (const char *p, int c)
  81. {
  82. const u_char *save, *s;
  83. for (save = 0, s = (const u_char *)p; *s;)
  84. {
  85. if (SJISP (*s) && s[1])
  86. s += 2;
  87. else
  88. {
  89. if (*s == c)
  90. save = s;
  91. s++;
  92. }
  93. }
  94. return (char *)save;
  95. }
  96. char *
  97. find_slash (const char *p)
  98. {
  99. for (u_char *s = (u_char *)p; *s;)
  100. {
  101. if (SJISP (*s) && s[1])
  102. s += 2;
  103. else
  104. {
  105. if (*s == '/' || *s == '\\')
  106. return (char *)s;
  107. s++;
  108. }
  109. }
  110. return 0;
  111. }
  112. char *
  113. find_last_slash (const char *p)
  114. {
  115. u_char *save, *s;
  116. for (save = 0, s = (u_char *)p; *s;)
  117. {
  118. if (SJISP (*s) && s[1])
  119. s += 2;
  120. else
  121. {
  122. if (*s == '/' || *s == '\\')
  123. save = s;
  124. s++;
  125. }
  126. }
  127. return (char *)save;
  128. }
  129. long
  130. log2 (u_long x)
  131. {
  132. long l;
  133. for (l = 0; x; x >>= 1, l++)
  134. ;
  135. return l;
  136. }
  137. #define NF_SIGN 1
  138. #define NF_LEADNUM 2
  139. #define NF_DOT 4
  140. #define NF_TRAILNUM 8
  141. #define NF_EXPSIGN 16
  142. #define NF_EXP (NF_EXPCHAR | NF_EXPNUM)
  143. #define NF_EXPCHAR 32
  144. #define NF_EXPNUM 64
  145. #define NF_SLASH 128
  146. int
  147. default_float_format ()
  148. {
  149. lisp f = xsymbol_value (Vread_default_float_format);
  150. if (f == Qshort_float)
  151. return NF_FLOAT_S;
  152. if (f == Qdouble_float)
  153. return NF_FLOAT_D;
  154. if (f == Qlong_float)
  155. return NF_FLOAT_L;
  156. return NF_FLOAT_F;
  157. }
  158. int
  159. parse_number_format (const Char *p, const Char *pe, int base)
  160. {
  161. Char expchar = 'e';
  162. int f = 0;
  163. if (p < pe && (*p == '+' || *p == '-'))
  164. p++;
  165. if (p < pe && digit_char (*p) < base)
  166. {
  167. f |= NF_LEADNUM;
  168. for (p++; p < pe && digit_char (*p) < base; p++)
  169. ;
  170. }
  171. if (p < pe && *p == '.')
  172. {
  173. f |= NF_DOT;
  174. p++;
  175. }
  176. if (p < pe && *p == '/')
  177. {
  178. f |= NF_SLASH;
  179. p++;
  180. }
  181. if (p < pe && digit_char (*p) < base)
  182. {
  183. f |= NF_TRAILNUM;
  184. for (p++; p < pe && digit_char (*p) < base; p++)
  185. ;
  186. }
  187. if (p < pe)
  188. {
  189. Char c = char_downcase (*p);
  190. switch (c)
  191. {
  192. case 'e':
  193. case 's':
  194. case 'f':
  195. case 'd':
  196. case 'l':
  197. f |= NF_EXPCHAR;
  198. expchar = c;
  199. p++;
  200. }
  201. }
  202. if (p < pe && (*p == '+' || *p == '-'))
  203. {
  204. f |= NF_EXPSIGN;
  205. p++;
  206. }
  207. if (p < pe && digit_char_p (*p))
  208. {
  209. f |= NF_EXPNUM;
  210. for (p++; p < pe && digit_char_p (*p); p++)
  211. ;
  212. }
  213. if ((f & (NF_EXP | NF_EXPSIGN)) == NF_EXPSIGN)
  214. return NF_BAD;
  215. f &= ~NF_EXPSIGN;
  216. if (p == pe)
  217. {
  218. switch (f)
  219. {
  220. case NF_LEADNUM:
  221. return NF_INTEGER;
  222. case NF_LEADNUM | NF_DOT:
  223. return NF_INTEGER_DOT;
  224. case NF_LEADNUM | NF_SLASH | NF_TRAILNUM:
  225. return NF_FRACTION;
  226. case NF_DOT | NF_TRAILNUM:
  227. case NF_DOT | NF_TRAILNUM | NF_EXP:
  228. case NF_LEADNUM | NF_DOT | NF_TRAILNUM:
  229. case NF_LEADNUM | NF_DOT | NF_TRAILNUM | NF_EXP:
  230. case NF_LEADNUM | NF_EXP:
  231. case NF_LEADNUM | NF_DOT | NF_EXP:
  232. return NF_FLOAT | expchar;
  233. }
  234. }
  235. return NF_BAD;
  236. }
  237. int
  238. check_integer_format (const char *s, int *n)
  239. {
  240. Char *b = (Char *)alloca (strlen (s) * 2);
  241. Char *be = s2w (b, s);
  242. for (; b < be && (*b == ' ' || *b == '\t'); b++)
  243. ;
  244. for (; be > b && (b[-1] == ' ' || b[-1] == '\t'); b--)
  245. ;
  246. switch (parse_number_format (b, be, 10))
  247. {
  248. case NF_INTEGER:
  249. case NF_INTEGER_DOT:
  250. *n = atoi (s);
  251. return 1;
  252. default:
  253. return 0;
  254. }
  255. }
  256. int
  257. streq (const Char *p, int l, const char *s)
  258. {
  259. for (const Char *pe = p + l; p < pe; p++, s++)
  260. if (*p != *s)
  261. return 0;
  262. return 1;
  263. }
  264. int
  265. strequal (const char *cp, const Char *Cp)
  266. {
  267. while (*cp)
  268. {
  269. Char c = *Cp++;
  270. if (DBCP (c))
  271. {
  272. if (!cp[1] || c != Char ((u_char (*cp) << 8) | u_char (cp[1])))
  273. return 0;
  274. cp += 2;
  275. }
  276. else
  277. {
  278. if (char_downcase (c) != char_downcase (u_char (*cp)))
  279. return 0;
  280. cp++;
  281. }
  282. }
  283. return 1;
  284. }
  285. int
  286. strequal (const char *cp, const Char *Cp, int l)
  287. {
  288. for (const Char *Ce = Cp + l; Cp < Ce; Cp++)
  289. {
  290. Char c = *Cp;
  291. if (DBCP (c))
  292. {
  293. if (c != Char ((u_char (*cp) << 8) | u_char (cp[1])))
  294. return 0;
  295. cp += 2;
  296. }
  297. else
  298. {
  299. if (char_downcase (c) != char_downcase (u_char (*cp)))
  300. return 0;
  301. cp++;
  302. }
  303. }
  304. return 1;
  305. }
  306. int
  307. strcasecmp (const char *s1, const char *s2)
  308. {
  309. const u_char *p1 = (const u_char *)s1;
  310. const u_char *p2 = (const u_char *)s2;
  311. while (1)
  312. {
  313. u_char c1 = *p1++;
  314. u_char c2 = *p2++;
  315. if (SJISP (c1))
  316. {
  317. if (c1 != c2)
  318. return c1 - c2;
  319. c1 = *p1++;
  320. c2 = *p2++;
  321. }
  322. else
  323. {
  324. c1 = char_downcase (c1);
  325. c2 = char_downcase (c2);
  326. }
  327. if (c1 != c2)
  328. return c1 - c2;
  329. if (!c1)
  330. return 0;
  331. }
  332. }
  333. void
  334. convert_backsl_with_sl (char *path, int f, int t)
  335. {
  336. for (u_char *s = (u_char *)path; *s;)
  337. {
  338. if (SJISP (*s) && s[1])
  339. s += 2;
  340. else
  341. {
  342. if (*s == f)
  343. *s = t;
  344. s++;
  345. }
  346. }
  347. }
  348. void
  349. fill_rect (HDC hdc, const RECT &r, COLORREF c)
  350. {
  351. COLORREF oc = SetBkColor (hdc, c);
  352. ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &r, 0, 0, 0);
  353. SetBkColor (hdc, oc);
  354. }
  355. void
  356. fill_rect (HDC hdc, int x, int y, int cx, int cy, COLORREF c)
  357. {
  358. RECT r;
  359. r.left = x;
  360. r.top = y;
  361. r.right = x + cx;
  362. r.bottom = y + cy;
  363. COLORREF oc = SetBkColor (hdc, c);
  364. ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &r, 0, 0, 0);
  365. SetBkColor (hdc, oc);
  366. }
  367. void
  368. draw_hline (HDC hdc, int x1, int x2, int y, COLORREF c)
  369. {
  370. RECT r;
  371. r.left = x1;
  372. r.top = y;
  373. r.right = x2;
  374. r.bottom = y + 1;
  375. COLORREF oc = SetBkColor (hdc, c);
  376. ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &r, 0, 0, 0);
  377. SetBkColor (hdc, oc);
  378. }
  379. void
  380. draw_vline (HDC hdc, int y1, int y2, int x, COLORREF c)
  381. {
  382. RECT r;
  383. r.left = x;
  384. r.top = y1;
  385. r.right = x + 1;
  386. r.bottom = y2;
  387. COLORREF oc = SetBkColor (hdc, c);
  388. ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &r, 0, 0, 0);
  389. SetBkColor (hdc, oc);
  390. }
  391. #if 0
  392. void
  393. paint_button_off (HDC hdc, const RECT &r)
  394. {
  395. HGDIOBJ open = SelectObject (hdc, CreatePen (PS_SOLID, 0, sysdep.btn_highlight));
  396. MoveToEx (hdc, r.left, r.bottom - 1, 0);
  397. LineTo (hdc, r.left, r.top);
  398. LineTo (hdc, r.right - 1, r.top);
  399. DeleteObject (SelectObject (hdc, open));
  400. open = SelectObject (hdc, sysdep.hpen_black);
  401. LineTo (hdc, r.right - 1, r.bottom - 1);
  402. LineTo (hdc, r.left - 1, r.bottom - 1);
  403. SelectObject (hdc, open);
  404. open = SelectObject (hdc, CreatePen (PS_SOLID, 0, sysdep.btn_shadow));
  405. MoveToEx (hdc, r.left + 1, r.bottom - 2, 0);
  406. LineTo (hdc, r.right - 2, r.bottom - 2);
  407. LineTo (hdc, r.right - 2, r.top);
  408. DeleteObject (SelectObject (hdc, open));
  409. }
  410. void
  411. paint_button_on (HDC hdc, const RECT &r)
  412. {
  413. HGDIOBJ open = SelectObject (hdc, sysdep.hpen_black);
  414. MoveToEx (hdc, r.left, r.bottom - 1, 0);
  415. LineTo (hdc, r.left, r.top);
  416. LineTo (hdc, r.right - 1, r.top);
  417. SelectObject (hdc, open);
  418. open = SelectObject (hdc, CreatePen (PS_SOLID, 0, sysdep.btn_highlight));
  419. LineTo (hdc, r.right - 1, r.bottom - 1);
  420. LineTo (hdc, r.left - 1, r.bottom - 1);
  421. DeleteObject (SelectObject (hdc, open));
  422. open = SelectObject (hdc, CreatePen (PS_SOLID, 0, sysdep.btn_shadow));
  423. MoveToEx (hdc, r.left + 1, r.bottom - 3, 0);
  424. LineTo (hdc, r.left + 1, r.top + 1);
  425. LineTo (hdc, r.right - 2, r.top + 1);
  426. DeleteObject (SelectObject (hdc, open));
  427. SetPixel (hdc, r.left + 1, r.bottom - 2, sysdep.btn_face);
  428. SetPixel (hdc, r.right -2, r.top + 1, sysdep.btn_face);
  429. }
  430. #else
  431. void
  432. paint_button_off (HDC hdc, const RECT &r)
  433. {
  434. draw_vline (hdc, r.top, r.bottom - 1, r.left, sysdep.btn_highlight);
  435. draw_hline (hdc, r.left, r.right - 1, r.top, sysdep.btn_highlight);
  436. draw_vline (hdc, r.top, r.bottom, r.right - 1, sysdep.btn_shadow);
  437. draw_hline (hdc, r.left, r.right, r.bottom - 1, sysdep.btn_shadow);
  438. }
  439. void
  440. paint_button_on (HDC hdc, const RECT &r)
  441. {
  442. draw_vline (hdc, r.top, r.bottom - 1, r.left, sysdep.btn_shadow);
  443. draw_hline (hdc, r.left, r.right - 1, r.top, sysdep.btn_shadow);
  444. draw_vline (hdc, r.top, r.bottom, r.right - 1, sysdep.btn_highlight);
  445. draw_hline (hdc, r.left, r.right, r.bottom - 1, sysdep.btn_highlight);
  446. }
  447. #endif
  448. frameDC::frameDC (HWND hwnd, int flags)
  449. : f_hwnd (hwnd)
  450. {
  451. f_hdc = GetDCEx (f_hwnd, 0,
  452. flags | DCX_CACHE | (LockWindowUpdate (f_hwnd)
  453. ? DCX_LOCKWINDOWUPDATE : 0));
  454. HBITMAP hbm = LoadBitmap (app.hinst, MAKEINTRESOURCE (IDB_CHECK));
  455. f_obr = SelectObject (f_hdc, CreatePatternBrush (hbm));
  456. DeleteObject (hbm);
  457. }
  458. frameDC::~frameDC ()
  459. {
  460. DeleteObject (SelectObject (f_hdc, f_obr));
  461. LockWindowUpdate (0);
  462. ReleaseDC (f_hwnd, f_hdc);
  463. }
  464. void
  465. frameDC::frame_rect (const RECT &r, int w) const
  466. {
  467. HRGN hrgn1 = CreateRectRgnIndirect (&r);
  468. HRGN hrgn2 = CreateRectRgn (r.left + w, r.top + w,
  469. r.right - w, r.bottom - w);
  470. CombineRgn (hrgn1, hrgn1, hrgn2, RGN_XOR);
  471. DeleteObject (hrgn2);
  472. SelectClipRgn (f_hdc, hrgn1);
  473. DeleteObject (hrgn1);
  474. paint (r);
  475. SelectClipRgn (f_hdc, 0);
  476. }
  477. ucs2_t *
  478. i2w (const Char *p, int l, ucs2_t *b)
  479. {
  480. for (const Char *const pe = p + l; p < pe; p++)
  481. {
  482. ucs2_t c = i2w (*p);
  483. if (c == ucs2_t (-1))
  484. {
  485. if (utf16_undef_char_high_p (*p) && p < pe - 1
  486. && utf16_undef_char_low_p (p[1]))
  487. {
  488. c = utf16_undef_pair_to_ucs2 (*p, p[1]);
  489. p++;
  490. }
  491. else
  492. c = DEFCHAR;
  493. }
  494. *b++ = c;
  495. }
  496. *b = 0;
  497. return b;
  498. }
  499. int
  500. i2wl (const Char *p, int l)
  501. {
  502. int r = 0;
  503. for (const Char *const pe = p + l; p < pe; p++, r++)
  504. {
  505. ucs2_t c = i2w (*p);
  506. if (c == ucs2_t (-1)
  507. && utf16_undef_char_high_p (*p) && p < pe - 1
  508. && utf16_undef_char_low_p (p[1]))
  509. p++;
  510. }
  511. return r + 1;
  512. }