list.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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_order)
  328. {
  329. int cnt;
  330. char **buffer;
  331. array_add(ses, list, arg, var);
  332. buffer = malloc(list->root->used * sizeof(char *));
  333. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  334. {
  335. buffer[cnt] = list->root->list[cnt]->arg2;
  336. }
  337. quadsort(buffer, list->root->used, sizeof(char *), cmp_num);
  338. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  339. {
  340. list->root->list[cnt]->arg2 = buffer[cnt];
  341. }
  342. free(buffer);
  343. return ses;
  344. }
  345. DO_ARRAY(array_reverse)
  346. {
  347. char *swap;
  348. int cnt, rev;
  349. array_add(ses, list, arg, var);
  350. for (cnt = 0 ; cnt < list->root->used / 2 ; cnt++)
  351. {
  352. rev = list->root->used - 1 - cnt;
  353. swap = list->root->list[cnt]->arg2;
  354. list->root->list[cnt]->arg2 = list->root->list[rev]->arg2;
  355. list->root->list[rev]->arg2 = swap;
  356. }
  357. return ses;
  358. }
  359. DO_ARRAY(array_simplify)
  360. {
  361. char arg1[BUFFER_SIZE], *str;
  362. int index;
  363. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  364. /*
  365. if (*arg1 == 0)
  366. {
  367. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} SIMPLIFY {variable}");
  368. return ses;
  369. }
  370. */
  371. if (list->root)
  372. {
  373. for (index = 0 ; index < list->root->used ; index++)
  374. {
  375. if (index == 0)
  376. {
  377. str = str_dup(list->root->list[index]->arg2);
  378. }
  379. else
  380. {
  381. str_cat_printf(&str, ";%s", list->root->list[index]->arg2);
  382. }
  383. }
  384. if (*arg1 == 0)
  385. {
  386. set_nest_node_ses(ses, list->arg1, "%s", str);
  387. }
  388. else
  389. {
  390. set_nest_node_ses(ses, arg1, "%s", str);
  391. }
  392. str_free(str);
  393. return ses;
  394. }
  395. else
  396. {
  397. show_error(ses, LIST_VARIABLE, "#LIST SIMPLIFY: {%s} is not a list.", list->arg1);
  398. }
  399. return ses;
  400. }
  401. DO_ARRAY(array_size)
  402. {
  403. char arg1[BUFFER_SIZE];
  404. arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
  405. if (*arg1 == 0)
  406. {
  407. show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} SIZE {variable}");
  408. return ses;
  409. }
  410. if (list->root)
  411. {
  412. set_nest_node_ses(ses, arg1, "%d", list->root->used);
  413. }
  414. else
  415. {
  416. set_nest_node_ses(ses, arg1, "0");
  417. }
  418. return ses;
  419. }
  420. DO_ARRAY(array_set)
  421. {
  422. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  423. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  424. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
  425. if (list->root)
  426. {
  427. int index = search_nest_index(list->root, arg1);
  428. if (atoi(arg1) == 0 || index == -1)
  429. {
  430. show_error(ses, LIST_VARIABLE, "#LIST SET: Invalid index: %s", arg1);
  431. return ses;
  432. }
  433. // set_nest_node(list->root, ntos(index + 1), "%s", arg2);
  434. str_cpy(&list->root->list[index]->arg2, arg2);
  435. return ses;
  436. }
  437. show_error(ses, LIST_VARIABLE, "#LIST SET: {%s} is not a list.", var);
  438. return ses;
  439. }
  440. DO_ARRAY(array_shuffle)
  441. {
  442. char *swap;
  443. int cnt, rnd;
  444. array_add(ses, list, arg, var);
  445. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  446. {
  447. rnd = generate_rand(ses) % list->root->used;
  448. swap = list->root->list[cnt]->arg2;
  449. list->root->list[cnt]->arg2 = list->root->list[rnd]->arg2;
  450. list->root->list[rnd]->arg2 = swap;
  451. }
  452. return ses;
  453. }
  454. DO_ARRAY(array_sort)
  455. {
  456. int cnt;
  457. char **buffer;
  458. array_add(ses, list, arg, var);
  459. buffer = malloc(list->root->used * sizeof(char *));
  460. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  461. {
  462. buffer[cnt] = list->root->list[cnt]->arg2;
  463. }
  464. quadsort(buffer, list->root->used, sizeof(char *), cmp_str);
  465. for (cnt = 0 ; cnt < list->root->used ; cnt++)
  466. {
  467. list->root->list[cnt]->arg2 = buffer[cnt];
  468. }
  469. free(buffer);
  470. return ses;
  471. }
  472. DO_ARRAY(array_tokenize)
  473. {
  474. char buf[BUFFER_SIZE], tmp[BUFFER_SIZE];
  475. int index = 1, i;
  476. sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
  477. if (list->root)
  478. {
  479. free_list(list->root);
  480. }
  481. list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
  482. i = 0;
  483. while (buf[i] != 0)
  484. {
  485. if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, &buf[i]))
  486. {
  487. i += sprintf(tmp, "%.*s", get_euc_size(ses, &buf[i]), &buf[i]);
  488. }
  489. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&buf[i]))
  490. {
  491. i += sprintf(tmp, "%.*s", get_utf8_size(&buf[i]), &buf[i]);
  492. }
  493. else
  494. {
  495. i += sprintf(tmp, "%c", buf[i]);
  496. }
  497. set_nest_node(list->root, ntos(index++), "%s", tmp);
  498. }
  499. return ses;
  500. }