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