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, >d->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, >d->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, >d->macro_buf[1], 1 + strlen(>d->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(>d->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, >d->macro_buf[size], 1 + strlen(>d->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, >d->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, >d->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(>d->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(>d->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(>d->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", >d->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