LibIRCClient 1.10 Used by Probotic
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
Это архивный репозиторий. Вы можете его клонировать или просматривать файлы, но не вносить изменения или открывать задачи/запросы на слияние.

389 строки
8.4KB

  1. /*
  2. * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
  3. *
  4. * This library is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  12. * License for more details.
  13. */
  14. #include <ctype.h>
  15. #define LIBIRC_COLORPARSER_BOLD (1<<1)
  16. #define LIBIRC_COLORPARSER_UNDERLINE (1<<2)
  17. #define LIBIRC_COLORPARSER_REVERSE (1<<3)
  18. #define LIBIRC_COLORPARSER_COLOR (1<<4)
  19. #define LIBIRC_COLORPARSER_MAXCOLORS 15
  20. static const char * color_replacement_table[] =
  21. {
  22. "WHITE",
  23. "BLACK",
  24. "DARKBLUE",
  25. "DARKGREEN",
  26. "RED",
  27. "BROWN",
  28. "PURPLE",
  29. "OLIVE",
  30. "YELLOW",
  31. "GREEN",
  32. "TEAL",
  33. "CYAN",
  34. "BLUE",
  35. "MAGENTA",
  36. "DARKGRAY",
  37. "LIGHTGRAY",
  38. 0
  39. };
  40. static inline void libirc_colorparser_addorcat (char ** destline, unsigned int * destlen, const char * str)
  41. {
  42. unsigned int len = strlen(str);
  43. if ( *destline )
  44. {
  45. strcpy (*destline, str);
  46. *destline += len;
  47. }
  48. else
  49. *destlen += len;
  50. }
  51. static void libirc_colorparser_applymask (unsigned int * mask,
  52. char ** destline, unsigned int * destlen,
  53. unsigned int bitmask, const char * start, const char * end)
  54. {
  55. if ( (*mask & bitmask) != 0 )
  56. {
  57. *mask &= ~bitmask;
  58. libirc_colorparser_addorcat (destline, destlen, end);
  59. }
  60. else
  61. {
  62. *mask |= bitmask;
  63. libirc_colorparser_addorcat (destline, destlen, start);
  64. }
  65. }
  66. static void libirc_colorparser_applycolor (unsigned int * mask,
  67. char ** destline, unsigned int * destlen,
  68. unsigned int colorid, unsigned int bgcolorid)
  69. {
  70. const char * end = "[/COLOR]";
  71. char startbuf[64];
  72. if ( bgcolorid != 0 )
  73. sprintf (startbuf, "[COLOR=%s/%s]", color_replacement_table[colorid], color_replacement_table[bgcolorid]);
  74. else
  75. sprintf (startbuf, "[COLOR=%s]", color_replacement_table[colorid]);
  76. if ( (*mask & LIBIRC_COLORPARSER_COLOR) != 0 )
  77. libirc_colorparser_addorcat (destline, destlen, end);
  78. *mask |= LIBIRC_COLORPARSER_COLOR;
  79. libirc_colorparser_addorcat (destline, destlen, startbuf);
  80. }
  81. static void libirc_colorparser_closetags (unsigned int * mask,
  82. char ** destline, unsigned int * destlen)
  83. {
  84. if ( *mask & LIBIRC_COLORPARSER_BOLD )
  85. libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_BOLD, 0, "[/B]");
  86. if ( *mask & LIBIRC_COLORPARSER_UNDERLINE )
  87. libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_UNDERLINE, 0, "[/U]");
  88. if ( *mask & LIBIRC_COLORPARSER_REVERSE )
  89. libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_REVERSE, 0, "[/I]");
  90. if ( *mask & LIBIRC_COLORPARSER_COLOR )
  91. libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_COLOR, 0, "[/COLOR]");
  92. }
  93. /*
  94. * IRC to [code] color conversion. Or strip.
  95. */
  96. static char * libirc_colorparser_irc2code (const char * source, int strip)
  97. {
  98. unsigned int mask = 0, destlen = 0;
  99. char * destline = 0, *d = 0;
  100. const char *p;
  101. int current_bg = 0;
  102. /*
  103. * There will be two passes. First pass calculates the total length of
  104. * the destination string. The second pass allocates memory for the string,
  105. * and fills it.
  106. */
  107. while ( destline == 0 ) // destline will be set after the 2nd pass
  108. {
  109. if ( destlen > 0 )
  110. {
  111. // This is the 2nd pass; allocate memory.
  112. if ( (destline = malloc (destlen)) == 0 )
  113. return 0;
  114. d = destline;
  115. }
  116. for ( p = source; *p; p++ )
  117. {
  118. switch (*p)
  119. {
  120. case 0x02: // bold
  121. if ( strip )
  122. continue;
  123. libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_BOLD, "[B]", "[/B]");
  124. break;
  125. case 0x1F: // underline
  126. if ( strip )
  127. continue;
  128. libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_UNDERLINE, "[U]", "[/U]");
  129. break;
  130. case 0x16: // reverse
  131. if ( strip )
  132. continue;
  133. libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_REVERSE, "[I]", "[/I]");
  134. break;
  135. case 0x0F: // reset colors
  136. if ( strip )
  137. continue;
  138. libirc_colorparser_closetags (&mask, &d, &destlen);
  139. break;
  140. case 0x03: // set color
  141. if ( isdigit (p[1]) )
  142. {
  143. // Parse
  144. int bgcolor = -1, color = p[1] - 0x30;
  145. p++;
  146. if ( isdigit (p[1]) )
  147. {
  148. color = color * 10 + (p[1] - 0x30);
  149. p++;
  150. }
  151. // If there is a comma, search for the following
  152. // background color
  153. if ( p[1] == ',' && isdigit (p[2]) )
  154. {
  155. bgcolor = p[2] - 0x30;
  156. p += 2;
  157. if ( isdigit (p[1]) )
  158. {
  159. bgcolor = bgcolor * 10 + (p[1] - 0x30);
  160. p++;
  161. }
  162. }
  163. // Check for range
  164. if ( color <= LIBIRC_COLORPARSER_MAXCOLORS
  165. && bgcolor <= LIBIRC_COLORPARSER_MAXCOLORS )
  166. {
  167. if ( strip )
  168. continue;
  169. if ( bgcolor != -1 )
  170. current_bg = bgcolor;
  171. libirc_colorparser_applycolor (&mask, &d, &destlen, color, current_bg);
  172. }
  173. }
  174. break;
  175. default:
  176. if ( destline )
  177. *d++ = *p;
  178. else
  179. destlen++;
  180. break;
  181. }
  182. }
  183. // Close all the opened tags
  184. libirc_colorparser_closetags (&mask, &d, &destlen);
  185. destlen++; // for 0-terminator
  186. }
  187. *d = '\0';
  188. return destline;
  189. }
  190. static int libirc_colorparser_colorlookup (const char * color)
  191. {
  192. int i;
  193. for ( i = 0; color_replacement_table[i]; i++ )
  194. if ( !strcmp (color, color_replacement_table[i]) )
  195. return i;
  196. return -1;
  197. }
  198. /*
  199. * [code] to IRC color conversion.
  200. */
  201. char * irc_color_convert_to_mirc (const char * source)
  202. {
  203. unsigned int destlen = 0;
  204. char * destline = 0, *d = 0;
  205. const char *p1, *p2, *cur;
  206. /*
  207. * There will be two passes. First pass calculates the total length of
  208. * the destination string. The second pass allocates memory for the string,
  209. * and fills it.
  210. */
  211. while ( destline == 0 ) // destline will be set after the 2nd pass
  212. {
  213. if ( destlen > 0 )
  214. {
  215. // This is the 2nd pass; allocate memory.
  216. if ( (destline = malloc (destlen)) == 0 )
  217. return 0;
  218. d = destline;
  219. }
  220. cur = source;
  221. while ( (p1 = strchr (cur, '[')) != 0 )
  222. {
  223. const char * replacedval = 0;
  224. p2 = 0;
  225. // Check if the closing bracket is available after p1
  226. // and the tag length is suitable
  227. if ( p1[1] != '\0'
  228. && (p2 = strchr (p1, ']')) != 0
  229. && (p2 - p1) > 1
  230. && (p2 - p1) < 31 )
  231. {
  232. // Get the tag
  233. char tagbuf[32];
  234. int taglen = p2 - p1 - 1;
  235. memcpy (tagbuf, p1 + 1, taglen);
  236. tagbuf[taglen] = '\0';
  237. if ( !strcmp (tagbuf, "/COLOR") )
  238. replacedval = "\x0F";
  239. else if ( strstr (tagbuf, "COLOR=") == tagbuf )
  240. {
  241. int color, bgcolor = -2;
  242. char * bcol;
  243. bcol = strchr (tagbuf + 6, '/');
  244. if ( bcol )
  245. {
  246. *bcol++ = '\0';
  247. bgcolor = libirc_colorparser_colorlookup (bcol);
  248. }
  249. color = libirc_colorparser_colorlookup (tagbuf + 6);
  250. if ( color != -1 && bgcolor == -2 )
  251. {
  252. sprintf (tagbuf, "\x03%02d", color);
  253. replacedval = tagbuf;
  254. }
  255. else if ( color != -1 && bgcolor >= 0 )
  256. {
  257. sprintf (tagbuf, "\x03%02d,%02d", color, bgcolor);
  258. replacedval = tagbuf;
  259. }
  260. }
  261. else if ( !strcmp (tagbuf, "B") || !strcmp (tagbuf, "/B") )
  262. replacedval = "\x02";
  263. else if ( !strcmp (tagbuf, "U") || !strcmp (tagbuf, "/U") )
  264. replacedval = "\x1F";
  265. else if ( !strcmp (tagbuf, "I") || !strcmp (tagbuf, "/I") )
  266. replacedval = "\x16";
  267. }
  268. if ( replacedval )
  269. {
  270. // add a part before the tag
  271. int partlen = p1 - cur;
  272. if ( destline )
  273. {
  274. memcpy (d, cur, partlen);
  275. d += partlen;
  276. }
  277. else
  278. destlen += partlen;
  279. // Add the replacement
  280. libirc_colorparser_addorcat (&d, &destlen, replacedval);
  281. // And move the pointer
  282. cur = p2 + 1;
  283. }
  284. else
  285. {
  286. // add a whole part before the end tag
  287. int partlen;
  288. if ( !p2 )
  289. p2 = cur + strlen(cur);
  290. partlen = p2 - cur + 1;
  291. if ( destline )
  292. {
  293. memcpy (d, cur, partlen);
  294. d += partlen;
  295. }
  296. else
  297. destlen += partlen;
  298. // And move the pointer
  299. cur = p2 + 1;
  300. }
  301. }
  302. // Add the rest of string
  303. libirc_colorparser_addorcat (&d, &destlen, cur);
  304. destlen++; // for 0-terminator
  305. }
  306. *d = '\0';
  307. return destline;
  308. }
  309. char * irc_color_strip_from_mirc (const char * message)
  310. {
  311. return libirc_colorparser_irc2code (message, 1);
  312. }
  313. char * irc_color_convert_from_mirc (const char * message)
  314. {
  315. return libirc_colorparser_irc2code (message, 0);
  316. }