list.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2019 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  19. ******************************************************************************/
  20. /******************************************************************************
  21. * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t *
  22. * *
  23. * coded by Igor van den Hoven 2004 *
  24. ******************************************************************************/
  25. #include "tintin.h"
  26. DO_COMMAND(do_list)
  27. {
  28. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  29. struct listnode *node;
  30. int index, cnt;
  31. arg = sub_arg_in_braces(ses, arg, arg1, GET_NST, SUB_VAR|SUB_FUN);
  32. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  33. if (*arg1 == 0)
  34. {
  35. tintin_header(ses, " LIST OPTIONS ");
  36. for (index = 0 ; *array_table[index].fun ; index++)
  37. {
  38. if (array_table[index].desc && *array_table[index].name)
  39. {
  40. tintin_printf2(ses, " [%-24s] %s", array_table[index].name, array_table[index].desc);
  41. }
  42. }
  43. tintin_header(ses, "");
  44. }
  45. else if (*arg2 == 0)
  46. {
  47. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} {option} {argument}");
  48. }
  49. else
  50. {
  51. for (cnt = 0 ; *array_table[cnt].name ; cnt++)
  52. {
  53. if (is_abbrev(arg2, array_table[cnt].name))
  54. {
  55. break;
  56. }
  57. }
  58. if (*array_table[cnt].name == 0)
  59. {
  60. return do_list(ses, "");
  61. }
  62. else
  63. {
  64. if ((node = search_nest_node_ses(ses, arg1)) == NULL)
  65. {
  66. node = set_nest_node_ses(ses, arg1, "");
  67. }
  68. array_table[cnt].fun(ses, node, arg, arg1);
  69. }
  70. }
  71. return ses;
  72. }
  73. DO_ARRAY(array_add)
  74. {
  75. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], *str;
  76. int index;
  77. if (!list->root)
  78. {
  79. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  80. }
  81. index = list->root->used + 1;
  82. while (*arg)
  83. {
  84. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  85. str = arg1;
  86. while (*str)
  87. {
  88. str = get_arg_in_braces(ses, str, arg2, GET_ALL);
  89. set_nest_node(list->root, ntos(index++), "%s", arg2);
  90. if (*str == COMMAND_SEPARATOR)
  91. {
  92. str++;
  93. }
  94. }
  95. if (*arg == COMMAND_SEPARATOR)
  96. {
  97. arg++;
  98. }
  99. }
  100. return ses;
  101. }
  102. DO_ARRAY(array_clear)
  103. {
  104. if (list->root)
  105. {
  106. free_list(list->root);
  107. list->root = NULL;
  108. }
  109. set_nest_node_ses(ses, var, "");
  110. return ses;
  111. }
  112. DO_ARRAY(array_collapse)
  113. {
  114. int index;
  115. if (list->root)
  116. {
  117. str_cpy(&list->arg2, "");
  118. for (index = 0 ; index < list->root->used ; index++)
  119. {
  120. str_cat(&list->arg2, list->root->list[index]->arg2);
  121. }
  122. free_list(list->root);
  123. list->root = NULL;
  124. }
  125. return ses;
  126. }
  127. DO_ARRAY(array_create)
  128. {
  129. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], buf[BUFFER_SIZE], *str;
  130. int index = 1;
  131. substitute(ses, arg, buf, SUB_VAR|SUB_FUN);
  132. arg = buf;
  133. if (list->root)
  134. {
  135. free_list(list->root);
  136. }
  137. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  138. while (*arg)
  139. {
  140. arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
  141. str = arg1;
  142. while (*str)
  143. {
  144. str = get_arg_in_braces(ses, str, arg2, GET_ALL);
  145. set_nest_node(list->root, ntos(index++), "%s", arg2);
  146. if (*str == COMMAND_SEPARATOR)
  147. {
  148. str++;
  149. }
  150. }
  151. if (*arg == COMMAND_SEPARATOR)
  152. {
  153. arg++;
  154. }
  155. }
  156. return ses;
  157. }
  158. DO_ARRAY(array_delete)
  159. {
  160. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  161. int index, cnt, loop;
  162. if (list->root)
  163. {
  164. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  165. arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
  166. loop = *arg2 ? (int) get_number(ses, arg2) : 1;
  167. while (loop--)
  168. {
  169. index = search_nest_index(list->root, arg1);
  170. if (atoi(arg1) == 0 || index == -1)
  171. {
  172. show_error(ses, LIST_VARIABLE, "#LIST DEL: Invalid index: %s", arg1);
  173. return ses;
  174. }
  175. for (cnt = index + 1 ; cnt < list->root->used ; cnt++)
  176. {
  177. str_cpy_printf(&list->root->list[cnt]->arg1, "%d", cnt);
  178. }
  179. delete_index_list(list->root, index);
  180. }
  181. }
  182. else
  183. {
  184. show_error(ses, LIST_VARIABLE, "#LIST DEL: {%s} is not a list.", var);
  185. }
  186. return ses;
  187. }
  188. DO_ARRAY(array_explode)
  189. {
  190. char buf[BUFFER_SIZE], tmp[BUFFER_SIZE], *pti;
  191. int index = 1;
  192. if (list->root)
  193. {
  194. array_collapse(ses, list, "", "");
  195. }
  196. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  197. pti = list->arg2;
  198. while (*pti)
  199. {
  200. if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
  201. {
  202. pti += sprintf(tmp, "%.*s", get_euc_size(ses, pti), pti);
  203. }
  204. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(pti))
  205. {
  206. pti += sprintf(tmp, "%.*s", get_utf8_size(pti), pti);
  207. }
  208. else
  209. {
  210. pti += sprintf(tmp, "%c", *pti);
  211. }
  212. set_nest_node(list->root, ntos(index++), "%s", tmp);
  213. }
  214. sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
  215. pti = buf;
  216. while (*pti)
  217. {
  218. if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
  219. {
  220. pti += sprintf(tmp, "%.*s", get_euc_size(ses, pti), pti);
  221. }
  222. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(pti))
  223. {
  224. pti += sprintf(tmp, "%.*s", get_utf8_size(pti), pti);
  225. }
  226. else
  227. {
  228. pti += sprintf(tmp, "%c", *pti);
  229. }
  230. set_nest_node(list->root, ntos(index++), "%s", tmp);
  231. }
  232. return ses;
  233. }
  234. DO_ARRAY(array_find)
  235. {
  236. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  237. int index;
  238. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  239. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  240. if (*arg2 == 0)
  241. {
  242. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} FIND {string} {variable}");
  243. return ses;
  244. }
  245. if (list->root)
  246. {
  247. for (index = 0 ; index < list->root->used ; index++)
  248. {
  249. if (match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
  250. {
  251. break;
  252. }
  253. }
  254. if (index < list->root->used)
  255. {
  256. set_nest_node_ses(ses, arg2, "%d", index + 1);
  257. }
  258. else
  259. {
  260. set_nest_node_ses(ses, arg2, "0");
  261. }
  262. return ses;
  263. }
  264. else
  265. {
  266. set_nest_node_ses(ses, arg2, "0");
  267. }
  268. return ses;
  269. }
  270. DO_ARRAY(array_get)
  271. {
  272. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  273. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  274. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  275. if (*arg2 == 0)
  276. {
  277. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} GET {index} {variable}");
  278. return ses;
  279. }
  280. if (list->root)
  281. {
  282. int index = search_nest_index(list->root, arg1);
  283. if (atoi(arg1) == 0 || index == -1)
  284. {
  285. set_nest_node_ses(ses, arg2, "0");
  286. }
  287. else
  288. {
  289. set_nest_node_ses(ses, arg2, "%s", list->root->list[index]->arg2);
  290. }
  291. return ses;
  292. }
  293. else
  294. {
  295. set_nest_node_ses(ses, arg2, "0");
  296. }
  297. return ses;
  298. }
  299. DO_ARRAY(array_insert)
  300. {
  301. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  302. int cnt, index;
  303. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  304. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  305. if (!list->root)
  306. {
  307. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  308. }
  309. index = search_nest_index(list->root, arg1);
  310. if (atoi(arg1) == 0)
  311. {
  312. show_error(ses, LIST_VARIABLE, "#LIST INS: Invalid index: %s", arg1);
  313. return ses;
  314. }
  315. if (index == -1 || atoi(arg1) < 0)
  316. {
  317. index++;
  318. }
  319. for (cnt = index ; cnt < list->root->used ; cnt++)
  320. {
  321. str_cpy_printf(&list->root->list[cnt]->arg1, "%d", cnt + 2);
  322. }
  323. set_nest_node(list->root, ntos(index + 1), "%s", arg2);
  324. // insert_node_list(list->root, ntos(index + 1), arg2, "");
  325. return ses;
  326. }
  327. DO_ARRAY(array_simplify)
  328. {
  329. char arg1[BUFFER_SIZE], *str;
  330. int index;
  331. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  332. /*
  333. if (*arg1 == 0)
  334. {
  335. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} SIMPLIFY {variable}");
  336. return ses;
  337. }
  338. */
  339. if (list->root)
  340. {
  341. for (index = 0 ; index < list->root->used ; index++)
  342. {
  343. if (index == 0)
  344. {
  345. str = str_dup(list->root->list[index]->arg2);
  346. }
  347. else
  348. {
  349. str_cat_printf(&str, ";%s", list->root->list[index]->arg2);
  350. }
  351. }
  352. if (*arg1 == 0)
  353. {
  354. set_nest_node_ses(ses, list->arg1, "%s", str);
  355. }
  356. else
  357. {
  358. set_nest_node_ses(ses, arg1, "%s", str);
  359. }
  360. str_free(str);
  361. return ses;
  362. }
  363. else
  364. {
  365. show_error(ses, LIST_VARIABLE, "#LIST SIMPLIFY: {%s} is not a list.", list->arg1);
  366. }
  367. return ses;
  368. }
  369. DO_ARRAY(array_size)
  370. {
  371. char arg1[BUFFER_SIZE];
  372. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  373. if (*arg1 == 0)
  374. {
  375. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} SIZE {variable}");
  376. return ses;
  377. }
  378. if (list->root)
  379. {
  380. set_nest_node_ses(ses, arg1, "%d", list->root->used);
  381. }
  382. else
  383. {
  384. set_nest_node_ses(ses, arg1, "0");
  385. }
  386. return ses;
  387. }
  388. DO_ARRAY(array_set)
  389. {
  390. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  391. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  392. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  393. if (list->root)
  394. {
  395. int index = search_nest_index(list->root, arg1);
  396. if (atoi(arg1) == 0 || index == -1)
  397. {
  398. show_error(ses, LIST_VARIABLE, "#LIST SET: Invalid index: %s", arg1);
  399. return ses;
  400. }
  401. set_nest_node(list->root, ntos(index + 1), "%s", arg2);
  402. // RESTRING(list->root->list[index]->arg2, arg2);
  403. return ses;
  404. }
  405. show_error(ses, LIST_VARIABLE, "#LIST SET: {%s} is not a list.", var);
  406. return ses;
  407. }
  408. DO_ARRAY(array_shuffle)
  409. {
  410. char *swap;
  411. int cnt, rnd;
  412. if (!list->root)
  413. {
  414. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  415. }
  416. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  417. {
  418. rnd = generate_rand(ses) % list->root->used;
  419. swap = list->root->list[cnt]->arg2;
  420. list->root->list[cnt]->arg2 = list->root->list[rnd]->arg2;
  421. list->root->list[rnd]->arg2 = swap;
  422. }
  423. return ses;
  424. }
  425. DO_ARRAY(array_sort)
  426. {
  427. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], *str;
  428. int cnt;
  429. if (!list->root)
  430. {
  431. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  432. }
  433. while (*arg)
  434. {
  435. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  436. str = arg1;
  437. while (*str)
  438. {
  439. str = get_arg_in_braces(ses, str, arg2, GET_ALL);
  440. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  441. {
  442. if (strcmp(arg2, list->root->list[cnt]->arg2) <= 0)
  443. {
  444. break;
  445. }
  446. }
  447. if (cnt == list->root->used)
  448. {
  449. sprintf(arg3, "{%d} {%s}", -1, arg2);
  450. }
  451. else
  452. {
  453. sprintf(arg3, "{%d} {%s}", cnt + 1, arg2);
  454. }
  455. array_insert(ses, list, arg3, var);
  456. if (*str == COMMAND_SEPARATOR)
  457. {
  458. str++;
  459. }
  460. }
  461. if (*arg == COMMAND_SEPARATOR)
  462. {
  463. arg++;
  464. }
  465. }
  466. return ses;
  467. }
  468. DO_ARRAY(array_tokenize)
  469. {
  470. char buf[BUFFER_SIZE], tmp[BUFFER_SIZE];
  471. int index = 1, i;
  472. sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
  473. if (list->root)
  474. {
  475. free_list(list->root);
  476. }
  477. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  478. i = 0;
  479. while (buf[i] != 0)
  480. {
  481. if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, &buf[i]))
  482. {
  483. i += sprintf(tmp, "%.*s", get_euc_size(ses, &buf[i]), &buf[i]);
  484. }
  485. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&buf[i]))
  486. {
  487. i += sprintf(tmp, "%.*s", get_utf8_size(&buf[i]), &buf[i]);
  488. }
  489. else
  490. {
  491. i += sprintf(tmp, "%c", buf[i]);
  492. }
  493. set_nest_node(list->root, ntos(index++), "%s", tmp);
  494. }
  495. return ses;
  496. }