input.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2020 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. * You should have received a copy of the GNU General Public License *
  17. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  18. ******************************************************************************/
  19. /******************************************************************************
  20. * T I N T I N + + *
  21. * *
  22. * coded by Igor van den Hoven 2006 *
  23. ******************************************************************************/
  24. #include "tintin.h"
  25. int processed_keypress(char *input, int index, int catch);
  26. void process_input(void)
  27. {
  28. char *input;
  29. struct session *input_ses;
  30. int len, out;
  31. push_call("process_input(void)");
  32. input = str_alloc_stack(0);
  33. if (gtd->detach_port)
  34. {
  35. if (gtd->detach_sock > 0)
  36. {
  37. len = read(gtd->detach_sock, input, 1);
  38. if (len <= 0)
  39. {
  40. if (len == -1)
  41. {
  42. syserr_printf(gtd->ses, "process_input: read", gtd->detach_sock);
  43. }
  44. else
  45. {
  46. show_message(gtd->ses, LIST_COMMAND, "#DAEMON UPDATE: DETACHING FROM {%s} DUE TO READ FAILURE.", gtd->detach_file);
  47. }
  48. gtd->detach_sock = close(gtd->detach_sock);
  49. dirty_screen(gtd->ses);
  50. pop_call();
  51. return;
  52. }
  53. }
  54. else
  55. {
  56. len = 0;
  57. printf("process_input: error?\n");
  58. }
  59. }
  60. else
  61. {
  62. len = read(0, input, 1);
  63. }
  64. input[len] = 0;
  65. if (gtd->attach_sock)
  66. {
  67. out = write(gtd->attach_sock, input, 1);
  68. if (out >= 0)
  69. {
  70. pop_call();
  71. return;
  72. }
  73. gtd->attach_sock = close(gtd->attach_sock);
  74. show_message(gtd->ses, LIST_COMMAND, "#DAEMON ATTACH: WRITE ERROR: UNATTACHING.");
  75. }
  76. if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR))
  77. {
  78. if (gtd->convert_time == 0)
  79. {
  80. gtd->convert_time = 100000LL + utime();
  81. }
  82. else
  83. {
  84. if (gtd->convert_time < gtd->utime)
  85. {
  86. gtd->convert_time = 0;
  87. DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR);
  88. }
  89. }
  90. }
  91. if (HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) && !HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO))
  92. {
  93. read_key(input, len);
  94. }
  95. else
  96. {
  97. read_line(input, len);
  98. }
  99. if (!HAS_BIT(gtd->flags, TINTIN_FLAG_PROCESSINPUT))
  100. {
  101. pop_call();
  102. return;
  103. }
  104. DEL_BIT(gtd->flags, TINTIN_FLAG_PROCESSINPUT);
  105. if (gtd->chat && gtd->chat->paste_time)
  106. {
  107. chat_paste(gtd->ses->input->buf, NULL);
  108. cursor_enter_finish(gtd->ses, "");
  109. pop_call();
  110. return;
  111. }
  112. if (HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO))
  113. {
  114. echo_command(gtd->ses, gtd->ses->input->buf);
  115. }
  116. else
  117. {
  118. echo_command(gtd->ses, "");
  119. }
  120. input_ses = gtd->ses;
  121. check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_INPUT, 0, 1, "RECEIVED INPUT", gtd->ses->input->buf);
  122. if (*gtd->ses->input->line_name)
  123. {
  124. check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_INPUT, 1, 1, "RECEIVED INPUT %s", gtd->ses->input->line_name, gtd->ses->input->buf);
  125. if (check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_CATCH, 1, 1, "CATCH RECEIVED INPUT %s", gtd->ses->input->line_name, gtd->ses->input->buf))
  126. {
  127. cursor_enter_finish(input_ses, "");
  128. pop_call();
  129. return;
  130. }
  131. }
  132. if (check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 1, "CATCH RECEIVED INPUT", gtd->ses->input->buf) == 1)
  133. {
  134. cursor_enter_finish(input_ses, "");
  135. pop_call();
  136. return;
  137. }
  138. if (HAS_BIT(gtd->flags, TINTIN_FLAG_CHILDLOCK))
  139. {
  140. parse_input(gtd->ses, gtd->ses->input->buf);
  141. }
  142. else
  143. {
  144. gtd->ses = script_driver(gtd->ses, LIST_COMMAND, NULL, gtd->ses->input->buf);
  145. }
  146. if (HAS_BIT(input_ses->telopts, TELOPT_FLAG_ECHO))
  147. {
  148. add_line_history(input_ses, input_ses->input->buf);
  149. }
  150. cursor_enter_finish(input_ses, "");
  151. fflush(NULL);
  152. pop_call();
  153. return;
  154. }
  155. void read_line(char *input, int len)
  156. {
  157. char buf[BUFFER_SIZE];
  158. int size, width, index;
  159. if (HAS_BIT(gtd->ses->log->mode, LOG_FLAG_LOW) && gtd->ses->log->file)
  160. {
  161. fwrite(input, 1, len, gtd->ses->log->file);
  162. }
  163. if (HAS_BIT(gtd->ses->config_flags, CONFIG_FLAG_CONVERTMETA) || gtd->level->convert)
  164. {
  165. convert_meta(input, &gtd->macro_buf[strlen(gtd->macro_buf)], FALSE);
  166. }
  167. else if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR))
  168. {
  169. convert_meta(input, &gtd->macro_buf[strlen(gtd->macro_buf)], TRUE);
  170. }
  171. else
  172. {
  173. strcat(gtd->macro_buf, input);
  174. }
  175. get_utf8_index(input, &index);
  176. if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(gtd->macro_buf))
  177. {
  178. if (get_utf8_size(gtd->macro_buf) == 1)
  179. {
  180. return;
  181. }
  182. }
  183. if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_EUC) && is_euc_head(gtd->ses, gtd->macro_buf))
  184. {
  185. if (gtd->macro_buf[1] == 0)
  186. {
  187. return;
  188. }
  189. }
  190. if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
  191. {
  192. check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 2, "RECEIVED KEYPRESS", input, ntos(index));
  193. }
  194. if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_CATCH))
  195. {
  196. if (check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_CATCH, 0, 2, "CATCH RECEIVED KEYPRESS", input, ntos(index)) == 1)
  197. {
  198. check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
  199. return;
  200. }
  201. }
  202. if (check_key(input, len))
  203. {
  204. if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
  205. {
  206. check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
  207. }
  208. return;
  209. }
  210. if (gtd->macro_buf[0] < 32)
  211. {
  212. switch (gtd->macro_buf[0])
  213. {
  214. case ASCII_CR:
  215. case ASCII_LF:
  216. break;
  217. default:
  218. strcpy(buf, gtd->macro_buf);
  219. convert_meta(buf, gtd->macro_buf, FALSE);
  220. break;
  221. }
  222. }
  223. while (gtd->macro_buf[0])
  224. {
  225. switch (gtd->macro_buf[0])
  226. {
  227. case ASCII_CR:
  228. case ASCII_LF:
  229. cursor_enter(gtd->ses, "");
  230. memmove(gtd->macro_buf, &gtd->macro_buf[1], 1 + strlen(&gtd->macro_buf[1]));
  231. break;
  232. default:
  233. if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(gtd->macro_buf) && gtd->macro_buf[1])
  234. {
  235. size = get_utf8_width(gtd->macro_buf, &width, &index);
  236. }
  237. else if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_EUC) && is_euc_head(gtd->ses, gtd->macro_buf) && gtd->macro_buf[1])
  238. {
  239. size = get_euc_width(gtd->ses, gtd->macro_buf, &width);
  240. }
  241. else
  242. {
  243. size = get_ascii_width(gtd->macro_buf, &width);
  244. index = (int) gtd->macro_buf[0];
  245. }
  246. snprintf(buf, BUFFER_SIZE, "%.*s", size, gtd->macro_buf);
  247. inputline_insert(buf, -1);
  248. if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
  249. {
  250. check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "RECEIVED INPUT CHARACTER", buf, ntos(index), ntos(size), ntos(width));
  251. }
  252. /*
  253. if (width && HAS_BIT(gtd->flags, TINTIN_FLAG_INSERTINPUT) && gtd->ses->input->raw_len != gtd->ses->input->raw_pos)
  254. {
  255. cursor_delete(gtd->ses, "");
  256. }
  257. str_ins_printf(&gtd->ses->input->buf, gtd->ses->input->raw_pos, "%.*s", size, gtd->macro_buf);
  258. gtd->ses->input->str_pos += width;
  259. gtd->ses->input->str_len += width;
  260. gtd->ses->input->raw_pos += size;
  261. gtd->ses->input->raw_len += size;
  262. */
  263. if (width && gtd->ses->input->raw_len != gtd->ses->input->raw_pos)
  264. {
  265. cursor_redraw_line(gtd->ses, "");
  266. }
  267. else
  268. {
  269. input_printf("%.*s", size, gtd->macro_buf);
  270. }
  271. memmove(gtd->macro_buf, &gtd->macro_buf[size], 1 + strlen(&gtd->macro_buf[size]));
  272. cursor_check_line_modified(gtd->ses, "");
  273. DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE);
  274. kill_list(gtd->ses->list[LIST_COMMAND]);
  275. cursor_history_find(gtd->ses, "");
  276. break;
  277. }
  278. }
  279. if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
  280. {
  281. check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
  282. }
  283. }
  284. void read_key(char *input, int len)
  285. {
  286. int cnt;
  287. if (gtd->ses->input->buf[0] == gtd->tintin_char)
  288. {
  289. read_line(input, len);
  290. return;
  291. }
  292. if (HAS_BIT(gtd->ses->config_flags, CONFIG_FLAG_CONVERTMETA))
  293. {
  294. convert_meta(input, &gtd->macro_buf[strlen(gtd->macro_buf)], FALSE);
  295. }
  296. else if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR))
  297. {
  298. convert_meta(input, &gtd->macro_buf[strlen(gtd->macro_buf)], TRUE);
  299. }
  300. else
  301. {
  302. strcat(gtd->macro_buf, input);
  303. }
  304. if (check_key(input, len))
  305. {
  306. return;
  307. }
  308. for (cnt = 0 ; gtd->macro_buf[cnt] ; cnt++)
  309. {
  310. switch (gtd->macro_buf[cnt])
  311. {
  312. case ASCII_CR:
  313. case ASCII_LF:
  314. str_cpy(&gtd->ses->input->buf, "");
  315. gtd->ses->input->raw_len = 0;
  316. gtd->ses->input->str_len = 0;
  317. gtd->ses->input->raw_pos = 0;
  318. gtd->ses->input->str_pos = 0;
  319. if (HAS_BIT(gtd->ses->flags, SES_FLAG_RUN))
  320. {
  321. socket_printf(gtd->ses, 1, "%c", '\r');
  322. }
  323. else
  324. {
  325. socket_printf(gtd->ses, 2, "%c%c", '\r', '\n');
  326. }
  327. break;
  328. default:
  329. if (gtd->macro_buf[cnt] == gtd->tintin_char && gtd->ses->input->buf[0] == 0)
  330. {
  331. print_stdout(0, 0, "%c", gtd->macro_buf[cnt]);
  332. str_cpy_printf(&gtd->ses->input->buf, "%c", gtd->tintin_char);
  333. gtd->ses->input->raw_len = 1;
  334. gtd->ses->input->str_len = 1;
  335. gtd->ses->input->raw_pos = 1;
  336. gtd->ses->input->str_pos = 1;
  337. }
  338. else
  339. {
  340. socket_printf(gtd->ses, 1, "%c", gtd->macro_buf[cnt]);
  341. str_cpy(&gtd->ses->input->buf, "\r");
  342. }
  343. break;
  344. }
  345. gtd->macro_buf[0] = 0;
  346. }
  347. }
  348. int check_key(char *input, int len)
  349. {
  350. char buf[BUFFER_SIZE];
  351. struct listroot *root;
  352. struct listnode *node;
  353. int cnt, val[6], partial;
  354. push_call("check_key(%p,%d)",input,len);
  355. // tintin_printf2(gtd->ses, "check_key(%d,%s)",*gtd->macro_buf, gtd->macro_buf);
  356. if (!HAS_BIT(gtd->ses->config_flags, CONFIG_FLAG_CONVERTMETA))
  357. {
  358. root = gtd->ses->list[LIST_MACRO];
  359. if (!HAS_BIT(root->flags, LIST_FLAG_IGNORE))
  360. {
  361. partial = 0;
  362. for (root->update = 0 ; root->update < root->used ; root->update++)
  363. {
  364. node = root->list[root->update];
  365. if (*node->arg1 == '^' && gtd->ses->input->raw_len)
  366. {
  367. continue;
  368. }
  369. else if (!strcmp(gtd->macro_buf, node->arg4))
  370. {
  371. strcpy(buf, node->arg2);
  372. show_debug(gtd->ses, LIST_MACRO, node, COLOR_DEBUG "#DEBUG MACRO " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
  373. if (node->shots && --node->shots == 0)
  374. {
  375. delete_node_list(gtd->ses, LIST_MACRO, node);
  376. }
  377. script_driver(gtd->ses, LIST_MACRO, node, buf);
  378. if (HAS_BIT(gtd->flags, TINTIN_FLAG_PRESERVEMACRO))
  379. {
  380. DEL_BIT(gtd->flags, TINTIN_FLAG_PRESERVEMACRO);
  381. }
  382. else
  383. {
  384. gtd->macro_buf[0] = 0;
  385. }
  386. pop_call();
  387. return TRUE;
  388. }
  389. else if (!strncmp(gtd->macro_buf, node->arg4, strlen(gtd->macro_buf)))
  390. {
  391. partial = TRUE;
  392. }
  393. }
  394. if (partial)
  395. {
  396. pop_call();
  397. return TRUE;
  398. }
  399. }
  400. if (gtd->macro_buf[0] < 32 || gtd->macro_buf[0] == 127)
  401. {
  402. if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) || HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) || gtd->ses->input->buf[0] == gtd->tintin_char)
  403. {
  404. for (cnt = 0 ; *cursor_table[cnt].fun != NULL ; cnt++)
  405. {
  406. if (*cursor_table[cnt].code)
  407. {
  408. if (!strcmp(gtd->macro_buf, cursor_table[cnt].code))
  409. {
  410. cursor_table[cnt].fun(gtd->ses, cursor_table[cnt].arg);
  411. gtd->macro_buf[0] = 0;
  412. pop_call();
  413. return TRUE;
  414. }
  415. else if (!strncmp(gtd->macro_buf, cursor_table[cnt].code, strlen(gtd->macro_buf)))
  416. {
  417. pop_call();
  418. return TRUE;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. if (gtd->macro_buf[0] == ASCII_ESC)
  425. {
  426. if (gtd->macro_buf[1] == '[')
  427. {
  428. if (gtd->macro_buf[2] == 'I')
  429. {
  430. gtd->macro_buf[0] = 0;
  431. gtd->screen->focus = 1;
  432. check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
  433. msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
  434. pop_call();
  435. return TRUE;
  436. }
  437. if (gtd->macro_buf[2] == 'O')
  438. {
  439. gtd->macro_buf[0] = 0;
  440. gtd->screen->focus = 0;
  441. check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
  442. msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
  443. pop_call();
  444. return TRUE;
  445. }
  446. if (gtd->macro_buf[2] == '<' && HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
  447. {
  448. val[0] = val[1] = val[2] = cnt = input[0] = 0;
  449. for (len = 3 ; gtd->macro_buf[len] ; len++)
  450. {
  451. if (is_digit(gtd->macro_buf[len]))
  452. {
  453. cat_sprintf(input, "%c", gtd->macro_buf[len]);
  454. }
  455. else
  456. {
  457. switch (gtd->macro_buf[len])
  458. {
  459. case ';':
  460. val[cnt++] = get_number(gtd->ses, input);
  461. input[0] = 0;
  462. break;
  463. case 'm':
  464. SET_BIT(val[0], MOUSE_FLAG_RELEASE);
  465. case 'M':
  466. val[cnt++] = get_number(gtd->ses, input);
  467. mouse_handler(gtd->ses, val[0], val[2], val[1]); // swap x y to row col
  468. gtd->macro_buf[0] = 0;
  469. pop_call();
  470. return TRUE;
  471. default:
  472. print_stdout(0, 0, "unknownmouse input error (%s)\n", str_convert_meta(gtd->macro_buf, TRUE));
  473. gtd->macro_buf[0] = 0;
  474. pop_call();
  475. return TRUE;
  476. }
  477. }
  478. }
  479. pop_call();
  480. return TRUE;
  481. }
  482. if (is_digit(gtd->macro_buf[2]))
  483. {
  484. cnt = input[0] = 0;
  485. memset(val, 0, sizeof(val));
  486. // tintin_printf2(gtd->ses, "debug: %d %d %d %d %d", val[0], val[1], val[2], val[3], val[4], val[5]);
  487. for (len = 2 ; gtd->macro_buf[len] ; len++)
  488. {
  489. if (cnt > 5)
  490. {
  491. pop_call();
  492. return FALSE;
  493. }
  494. if (is_digit(gtd->macro_buf[len]))
  495. {
  496. cat_sprintf(input, "%c", gtd->macro_buf[len]);
  497. }
  498. else
  499. {
  500. switch (gtd->macro_buf[len])
  501. {
  502. case '-':
  503. if (input[0] == 0)
  504. {
  505. strcat(input, "-");
  506. }
  507. else
  508. {
  509. tintin_printf2(NULL, "\e[1;31merror: bad csi input (%s)\n", &gtd->macro_buf[1]);
  510. gtd->macro_buf[0] = 0;
  511. continue;
  512. }
  513. break;
  514. case ';':
  515. val[cnt++] = get_number(gtd->ses, input);
  516. input[0] = 0;
  517. break;
  518. case '&':
  519. val[cnt++] = get_number(gtd->ses, input);
  520. input[0] = 0;
  521. break;
  522. case '#':
  523. val[cnt++] = get_number(gtd->ses, input);
  524. input[0] = 0;
  525. break;
  526. case 'w':
  527. rqlp_handler(val[0], val[1], val[2], val[3]);
  528. gtd->macro_buf[0] = 0;
  529. pop_call();
  530. return TRUE;
  531. case 't':
  532. val[cnt++] = get_number(gtd->ses, input);
  533. csit_handler(val[0], val[1], val[2]);
  534. gtd->macro_buf[0] = 0;
  535. pop_call();
  536. return TRUE;
  537. case 'd':
  538. if (gtd->macro_buf[len - 1] == '#')
  539. {
  540. check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 3, "SCROLLBAR POSITION", ntos(val[0]), ntos(val[1]), ntos(val[2]));
  541. if (!check_all_events(gtd->ses, EVENT_FLAG_CATCH, 0, 3, "CATCH SCROLLBAR POSITION", ntos(val[0]), ntos(val[1]), ntos(val[2])))
  542. {
  543. command(gtd->ses, do_buffer, "JUMP %d", URANGE(0, val[0] + get_scroll_rows(gtd->ses), gtd->ses->scroll->used));
  544. }
  545. gtd->macro_buf[0] = 0;
  546. pop_call();
  547. return TRUE;
  548. }
  549. pop_call();
  550. return FALSE;
  551. case 'e':
  552. if (gtd->macro_buf[len - 1] == '#')
  553. {
  554. check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 3, "SCROLLBAR MOVE", ntos(val[0]), ntos(val[1]), ntos(val[2]));
  555. if (!check_all_events(gtd->ses, EVENT_FLAG_CATCH, 0, 3, "CATCH SCROLLBAR MOVE", ntos(val[0]), ntos(val[1]), ntos(val[2])))
  556. {
  557. switch (val[0])
  558. {
  559. case 5:
  560. cursor_page(gtd->ses, "up");
  561. break;
  562. case 6:
  563. cursor_page(gtd->ses, "down");
  564. break;
  565. case 65:
  566. cursor_page(gtd->ses, "up 1");
  567. break;
  568. case 66:
  569. cursor_page(gtd->ses, "down 1");
  570. break;
  571. }
  572. }
  573. gtd->macro_buf[0] = 0;
  574. pop_call();
  575. return TRUE;
  576. }
  577. pop_call();
  578. return FALSE;
  579. default:
  580. pop_call();
  581. return FALSE;
  582. }
  583. }
  584. }
  585. pop_call();
  586. return TRUE;
  587. }
  588. if (gtd->macro_buf[2] == 0)
  589. {
  590. pop_call();
  591. return TRUE;
  592. }
  593. }
  594. else if (gtd->macro_buf[1] == ']')
  595. {
  596. switch (gtd->macro_buf[2])
  597. {
  598. case 'L':
  599. case 'l':
  600. for (len = 3 ; gtd->macro_buf[len] ; len++)
  601. {
  602. if (gtd->macro_buf[len] < 32)
  603. {
  604. input[len - 3] = 0;
  605. osc_handler(gtd->macro_buf[2], input);
  606. gtd->macro_buf[0] = 0;
  607. pop_call();
  608. return TRUE;
  609. }
  610. else
  611. {
  612. input[len - 3 ] = gtd->macro_buf[len];
  613. }
  614. }
  615. break;
  616. default:
  617. for (len = 3 ; gtd->macro_buf[len] ; len++)
  618. {
  619. if (gtd->macro_buf[len] == '\a' || (gtd->macro_buf[len] == '\e' && gtd->macro_buf[len + 1] == '\\'))
  620. {
  621. break;
  622. }
  623. }
  624. if (gtd->macro_buf[len] == 0 && len < 30)
  625. {
  626. pop_call();
  627. return TRUE;
  628. }
  629. print_stdout(0, 0, "\e[1;31merror: unknown osc input (%s)\n", str_convert_meta(gtd->macro_buf, TRUE));
  630. gtd->macro_buf[0] = 0;
  631. pop_call();
  632. return TRUE;
  633. }
  634. }
  635. else if (gtd->macro_buf[1] == 0)
  636. {
  637. pop_call();
  638. return TRUE;
  639. }
  640. }
  641. }
  642. pop_call();
  643. return FALSE;
  644. }
  645. void convert_meta(char *input, char *output, int eol)
  646. {
  647. char *pti, *pto;
  648. push_call("convert_meta(%p,%p,%d)",input,output,eol);
  649. pti = input;
  650. pto = output;
  651. while (*pti && pti - input < BUFFER_SIZE / 2)
  652. {
  653. switch ((unsigned char) *pti)
  654. {
  655. case 255:
  656. *pto++ = '\\';
  657. *pto++ = 'x';
  658. *pto++ = 'F';
  659. *pto++ = 'F';
  660. pti++;
  661. break;
  662. case ASCII_ESC:
  663. *pto++ = '\\';
  664. *pto++ = 'e';
  665. pti++;
  666. break;
  667. case ASCII_DEL:
  668. *pto++ = '\\';
  669. *pto++ = 'x';
  670. *pto++ = '7';
  671. *pto++ = 'F';
  672. pti++;
  673. break;
  674. case ASCII_BEL:
  675. *pto++ = '\\';
  676. *pto++ = 'a';
  677. pti++;
  678. break;
  679. case ASCII_BS:
  680. *pto++ = '\\';
  681. *pto++ = 'b';
  682. pti++;
  683. break;
  684. /*
  685. case ASCII_FF:
  686. *pto++ = '\\';
  687. *pto++ = 'f';
  688. pti++;
  689. break;
  690. */
  691. case ASCII_HTAB:
  692. *pto++ = '\\';
  693. *pto++ = 't';
  694. pti++;
  695. break;
  696. case ASCII_CR:
  697. if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR))
  698. {
  699. *pto++ = '\\';
  700. *pto++ = 'r';
  701. pti++;
  702. }
  703. else if (eol)
  704. {
  705. *pto++ = '\\';
  706. *pto++ = 'r';
  707. *pto++ = *pti++;
  708. }
  709. else
  710. {
  711. *pto++ = *pti++;
  712. }
  713. break;
  714. /*
  715. case ASCII_VTAB:
  716. *pto++ = '\\';
  717. *pto++ = 'v';
  718. pti++;
  719. break;
  720. */
  721. case ASCII_LF:
  722. if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR) || gtd->level->convert)
  723. {
  724. *pto++ = '\\';
  725. *pto++ = 'n';
  726. pti++;
  727. }
  728. else if (eol)
  729. {
  730. *pto++ = '\\';
  731. *pto++ = 'n';
  732. *pto++ = *pti++;
  733. }
  734. else
  735. {
  736. *pto++ = *pti++;
  737. }
  738. break;
  739. default:
  740. if (*pti > 0 && *pti < 32)
  741. {
  742. *pto++ = '\\';
  743. *pto++ = 'c';
  744. if (*pti <= 26)
  745. {
  746. *pto++ = 'a' + *pti - 1;
  747. }
  748. else
  749. {
  750. *pto++ = 'A' + *pti - 1;
  751. }
  752. pti++;
  753. break;
  754. }
  755. else
  756. {
  757. *pto++ = *pti++;
  758. }
  759. break;
  760. }
  761. }
  762. *pto = 0;
  763. if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_CONVERTMETACHAR))
  764. {
  765. gtd->convert_time = 200000LL + gtd->utime;
  766. }
  767. pop_call();
  768. return;
  769. }
  770. char *str_convert_meta(char *input, int eol)
  771. {
  772. static char buf[BUFFER_SIZE];
  773. convert_meta(input, buf, eol);
  774. return buf;
  775. }
  776. /*
  777. Currenly only used in split mode.
  778. */
  779. void echo_command(struct session *ses, char *line)
  780. {
  781. char buffer[BUFFER_SIZE];
  782. int split = HAS_BIT(ses->flags, SES_FLAG_SPLIT) == SES_FLAG_SPLIT;
  783. DEL_BIT(ses->telopts, TELOPT_FLAG_PROMPT);
  784. if (ses->check_output)
  785. {
  786. process_more_output(ses, "", split); // add newline if not in split mode
  787. }
  788. if (ses->scroll->line != -1)
  789. {
  790. buffer_end(gtd->ses, "", "", "");
  791. if (!split)
  792. {
  793. printf("%s\n", line);
  794. }
  795. }
  796. if (!split)
  797. {
  798. add_line_buffer(ses, line, -1);
  799. return;
  800. }
  801. if (HAS_BIT(ses->config_flags, CONFIG_FLAG_ECHOCOMMAND))
  802. {
  803. sprintf(buffer, "%s%s\e[0m", ses->cmd_color, line);
  804. }
  805. else
  806. {
  807. if (strip_vt102_strlen(ses, ses->scroll->input) == 0)
  808. {
  809. return;
  810. }
  811. sprintf(buffer, "\e[0m");
  812. }
  813. gtd->level->scroll++;
  814. tintin_printf2(ses, "%s%s", ses->scroll->input, buffer);
  815. gtd->level->scroll--;
  816. add_line_buffer(ses, buffer, -1);
  817. }
  818. void init_input(struct session *ses, int top_row, int top_col, int bot_row, int bot_col)
  819. {
  820. push_call("init_input(%p,%d,%d,%d,%d)",ses,top_row,top_col,bot_row,bot_col);
  821. if (ses->input->buf == NULL)
  822. {
  823. ses->input->str_off = 1;
  824. ses->input->edit = create_editor();
  825. ses->input->line = create_editor(); // unused for now
  826. ses->input->edit_name = str_dup("");
  827. ses->input->line_name = str_dup("");
  828. ses->input->buf = str_dup("");
  829. ses->input->tmp = str_dup("");
  830. ses->input->cut = str_dup("");
  831. }
  832. if (top_row && top_col && bot_row && bot_col)
  833. {
  834. ses->input->sav_top_row = top_row;
  835. ses->input->sav_top_col = top_col;
  836. ses->input->sav_bot_row = bot_row;
  837. ses->input->sav_bot_col = bot_col;
  838. }
  839. else
  840. {
  841. if (ses == gts)
  842. {
  843. ses->input->sav_top_row = -1;
  844. ses->input->sav_top_col = 1;
  845. ses->input->sav_bot_row = -1;
  846. ses->input->sav_bot_col = -1;
  847. }
  848. else
  849. {
  850. ses->input->sav_top_row = gts->input->sav_top_row;
  851. ses->input->sav_top_col = gts->input->sav_top_col;
  852. ses->input->sav_bot_row = gts->input->sav_bot_row;
  853. ses->input->sav_bot_col = gts->input->sav_bot_col;
  854. }
  855. }
  856. top_row = get_row_index(ses, ses->input->sav_top_row);
  857. top_col = get_col_index(ses, ses->input->sav_top_col);
  858. bot_row = get_row_index(ses, ses->input->sav_bot_row);
  859. bot_col = get_col_index(ses, ses->input->sav_bot_col);
  860. ses->input->top_row = top_row;
  861. ses->input->top_col = top_col;
  862. ses->input->bot_row = bot_row;
  863. ses->input->bot_col = bot_col;
  864. ses->input->cur_row = top_row;
  865. pop_call();
  866. return;
  867. }
  868. void free_input(struct session *ses)
  869. {
  870. delete_editor(ses->input->line);
  871. delete_editor(ses->input->edit);
  872. str_free(ses->input->edit_name);
  873. str_free(ses->input->line_name);
  874. str_free(ses->input->buf);
  875. str_free(ses->input->tmp);
  876. }
  877. void input_printf(char *format, ...)
  878. {
  879. char *buf;
  880. va_list args;
  881. if (!HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH) && !HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_REDRAW))
  882. {
  883. if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) && gtd->ses->input->buf[0] != gtd->tintin_char)
  884. {
  885. return;
  886. }
  887. }
  888. va_start(args, format);
  889. if (vasprintf(&buf, format, args) == -1)
  890. {
  891. syserr_printf(gtd->ses, "input_printf(%s): vasprintf:", format);
  892. }
  893. else
  894. {
  895. print_stdout(0, 0, "%s", buf);
  896. free(buf);
  897. }
  898. va_end(args);
  899. return;
  900. }
  901. void modified_input(void)
  902. {
  903. kill_list(gtd->ses->list[LIST_COMMAND]);
  904. cursor_history_find(gtd->ses, "");
  905. if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE))
  906. {
  907. DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE);
  908. }
  909. }