ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/command.C
(Generate patch)

Comparing rxvt-unicode/src/command.C (file contents):
Revision 1.3 by pcg, Tue Nov 25 11:52:42 2003 UTC vs.
Revision 1.5 by pcg, Tue Nov 25 15:44:38 2003 UTC

1/*--------------------------------*-C-*---------------------------------* 1/*--------------------------------*-C-*---------------------------------*
2 * File: command.c 2 * File: command.c
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * $Id: command.C,v 1.3 2003/11/25 11:52:42 pcg Exp $ 4 * $Id: command.C,v 1.5 2003/11/25 15:44:38 pcg Exp $
5 * 5 *
6 * All portions of code are copyright by their respective author/s. 6 * All portions of code are copyright by their respective author/s.
7 * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk> 7 * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
8 * - original version 8 * - original version
9 * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com> 9 * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
632rxvt_cmd_write(pR_ const unsigned char *str, unsigned int count) 632rxvt_cmd_write(pR_ const unsigned char *str, unsigned int count)
633{ 633{
634 unsigned int n, s; 634 unsigned int n, s;
635 unsigned char *cmdbuf_base = R->cmdbuf_base, 635 unsigned char *cmdbuf_base = R->cmdbuf_base,
636 *cmdbuf_endp = R->cmdbuf_endp, 636 *cmdbuf_endp = R->cmdbuf_endp,
637 *cmdbuf_ptr = R->cmdbuf_ptr; 637 *cmdbuf_ptr = R->cmdbuf_ptr;
638 638
639 n = cmdbuf_ptr - cmdbuf_base; 639 n = cmdbuf_ptr - cmdbuf_base;
640 s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp; 640 s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp;
641 if (n > 0 && s < count) { 641 if (n > 0 && s < count) {
642 MEMMOVE(cmdbuf_base, cmdbuf_ptr, 642 MEMMOVE(cmdbuf_base, cmdbuf_ptr,
663 do 663 do
664 { 664 {
665 XEvent xev; 665 XEvent xev;
666 666
667 XNextEvent (Xdisplay, &xev); 667 XNextEvent (Xdisplay, &xev);
668
668#if defined(CURSOR_BLINK) 669#if defined(CURSOR_BLINK)
669 if ((Options & Opt_cursorBlink) 670 if ((Options & Opt_cursorBlink)
670 && xev.type == KeyPress) { 671 && xev.type == KeyPress) {
671 if (hidden_cursor) { 672 if (hidden_cursor) {
672 hidden_cursor = 0; 673 hidden_cursor = 0;
673 want_refresh = 1; 674 want_refresh = 1;
674 } 675 }
675 want_keypress_time = 1; 676 blink_ev.start (NOW + BLINK_INTERVAL);
676 } 677 }
677#endif 678#endif
678 679
679#if defined(POINTER_BLANK) 680#if defined(POINTER_BLANK)
680 if ((Options & Opt_pointerBlank) 681 if ((Options & Opt_pointerBlank)
698 } 699 }
699 while (XPending (Xdisplay)); 700 while (XPending (Xdisplay));
700} 701}
701 702
702void 703void
704rxvt_term::blink_cb (time_watcher &w)
705{
706 w.at += BLINK_INTERVAL;
707 hidden_cursor = !hidden_cursor;
708 want_refresh = 1;
709 flush();
710}
711
712void
703rxvt_term::x_cb (io_watcher &w, short revents) 713rxvt_term::x_cb (io_watcher &w, short revents)
704{ 714{
705 process_x_events (); 715 process_x_events ();
716
717 flush ();
706} 718}
707 719
708// read the next character, currently handles UTF-8 720// read the next character, currently handles UTF-8
709// will probably handle all sorts of other stuff in the future 721// will probably handle all sorts of other stuff in the future
710static uint32_t 722uint32_t
711next_char (pR) 723rxvt_term::next_char ()
712{ 724{
713 mbstate &s = R->mbstate; 725 struct mbstate &s = mbstate;
714 726
715 while (R->cmdbuf_ptr < R->cmdbuf_endp) 727 while (cmdbuf_ptr < cmdbuf_endp)
716 { 728 {
717 uint8_t ch = *R->cmdbuf_ptr; 729 uint8_t ch = *cmdbuf_ptr;
718 730
719 if (s.cnt) 731 if (s.cnt)
720 { 732 {
721 if ((ch & 0xc0) == 0x80) 733 if ((ch & 0xc0) == 0x80)
722 { 734 {
723 R->cmdbuf_ptr++; 735 cmdbuf_ptr++;
724 736
725 /* continuation */ 737 /* continuation */
726 s.reg = (s.reg << 6) | (ch & 0x7f); 738 s.reg = (s.reg << 6) | (ch & 0x7f);
727 739
728 if (--s.cnt == 0 && s.reg >= 128) /* if !inrange then corruption or Racking */ 740 if (--s.cnt == 0 && s.reg >= 128) /* if !inrange then corruption or Racking */
737 } 749 }
738 } 750 }
739 751
740 if ((ch & 0xc0) == 0xc0) 752 if ((ch & 0xc0) == 0xc0)
741 { 753 {
742 R->cmdbuf_ptr++; 754 cmdbuf_ptr++;
743 755
744 /* first byte */ 756 /* first byte */
745 s.orig = ch; /* for broken encodings */ 757 s.orig = ch; /* for broken encodings */
746 s.reg = ch; 758 s.reg = ch;
747 if ((ch & 0xe0) == 0xc0) { s.reg &= 0x1f; s.cnt = 1; } 759 if ((ch & 0xe0) == 0xc0) { s.reg &= 0x1f; s.cnt = 1; }
750 if ((ch & 0xfc) == 0xf8) { s.reg &= 0x03; s.cnt = 4; } 762 if ((ch & 0xfc) == 0xf8) { s.reg &= 0x03; s.cnt = 4; }
751 if ((ch & 0xfe) == 0xfc) { s.reg &= 0x01; s.cnt = 5; } 763 if ((ch & 0xfe) == 0xfc) { s.reg &= 0x01; s.cnt = 5; }
752 } 764 }
753 else 765 else
754 { 766 {
755 R->cmdbuf_ptr++; /* _occasional_ non-utf8 may slip through... */ 767 cmdbuf_ptr++; /* _occasional_ non-utf8 may slip through... */
756 return ch; 768 return ch;
757 } 769 }
758 } 770 }
759 771
760 return NOCHAR; 772 return NOCHAR;
773}
774
775bool
776rxvt_term::pty_fill (size_t count)
777{
778 ssize_t n = cmdbuf_endp - cmdbuf_ptr;
779
780 memmove (cmdbuf_base, cmdbuf_ptr, n);
781 cmdbuf_ptr = cmdbuf_base;
782 cmdbuf_endp = cmdbuf_ptr + n;
783
784 n = read (cmd_fd, cmdbuf_endp, count);
785
786 if (n > 0)
787 {
788 cmdbuf_endp += n;
789 return true;
790 }
791 else if (n < 0 && errno == EAGAIN)
792 return false;
793
794 rxvt_clean_exit();
795 exit(EXIT_FAILURE); /* bad order of events? */
761} 796}
762 797
763void 798void
764rxvt_term::pty_cb (io_watcher &w, short revents) 799rxvt_term::pty_cb (io_watcher &w, short revents)
765{ 800{
766 int n; 801 while (pty_fill (BUFSIZ - (cmdbuf_endp - cmdbuf_ptr)))
767 unsigned int count;
768
769 if (count = (cmdbuf_endp - cmdbuf_ptr))
770 { 802 {
771 memmove (cmdbuf_base, cmdbuf_ptr, count); 803 /* once we know the shell is running, send the screen size. Again! */
772 cmdbuf_ptr = cmdbuf_base; 804 //ch = rxvt_cmd_getc(aR); /* wait for something */
773 cmdbuf_endp = cmdbuf_ptr + count; 805 //rxvt_tt_winsize(cmd_fd, TermWin.ncol, TermWin.nrow, cmd_pid);
774 }
775
776 806
777 for (count = BUFSIZ - count; count; count -= n, cmdbuf_endp += n) 807 uint32_t ch = NOCHAR;
778 if ((n = read(cmd_fd, cmdbuf_endp, count)) > 0) 808
779 continue; 809 for (;;)
780 else if (n == 0 || (n < 0 && errno == EAGAIN))
781 break;
782 else
783 { 810 {
784 rxvt_clean_exit(); 811 if (ch == NOCHAR)
785 exit(EXIT_FAILURE); /* bad order of events? */ 812 ch = next_char ();
813
814 if (ch == NOCHAR) // TODO: improve
815 break;
816
817 if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
818 {
819 /* Read a text string from the input buffer */
820 uint32_t buf[BUFSIZ];
821 bool refreshnow = false;
822 int nlines = 0;
823 uint32_t *str = buf;
824
825 *str++ = ch;
826
827 for (;;)
828 {
829 ch = next_char ();
830
831 if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
832 break;
833 else
834 {
835 *str++ = ch;
836
837 if (ch == '\n')
838 {
839 nlines++;
840 refresh_count++;
841
842 if (!(Options & Opt_jumpScroll)
843 || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
844 {
845 refreshnow = true;
846 ch = NOCHAR;
847 break;
848 }
849 }
850
851 if (str >= buf + BUFSIZ)
852 {
853 ch = NOCHAR;
854 break;
855 }
856 }
857 }
858
859 rxvt_scr_add_lines (this, buf, nlines, str - buf);
860
861 /*
862 * If there have been a lot of new lines, then update the screen
863 * What the heck I'll cheat and only refresh less than every page-full.
864 * the number of pages between refreshes is refresh_limit, which
865 * is incremented here because we must be doing flat-out scrolling.
866 *
867 * refreshing should be correct for small scrolls, because of the
868 * time-out
869 */
870 if (refreshnow)
871 {
872 if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
873 refresh_limit++;
874
875 rxvt_scr_refresh (this, refresh_type);
876 }
877
878 }
879 else
880 {
881 switch (ch)
882 {
883 default:
884 rxvt_process_nonprinting (this, ch);
885 break;
886 case C0_ESC: /* escape char */
887 rxvt_process_escape_seq (this);
888 break;
889 /*case 0x9b: */ /* CSI */
890 /* rxvt_process_csi_seq (this); */
891 }
892
893 ch = NOCHAR;
894 }
786 } 895 }
896 }
787 897
788 if (count != BUFSIZ) /* some characters read in */ 898 flush ();
899}
900
901void
902rxvt_term::flush ()
903{
904#ifdef TRANSPARENT
905 if (want_full_refresh)
789 { 906 {
790 uint32_t c = next_char (this); 907 want_full_refresh = 0;
791 908 rxvt_scr_clear (this);
792#if 0 909 rxvt_scr_touch (this, False);
793 if (c != NOCHAR) 910 want_refresh = 1;
794 return c; 911 }
795#endif 912#endif
913
914 if (want_refresh)
796 } 915 {
916 rxvt_scr_refresh (this, refresh_type);
917 rxvt_scrollbar_show (this, 1);
918#ifdef USE_XIM
919 rxvt_IMSendSpot (this);
920#endif
921 }
922
923 XFlush (Xdisplay);
797} 924}
798 925
799/* rxvt_cmd_getc() - Return next input character */ 926/* rxvt_cmd_getc() - Return next input character */
800/* 927/*
801 * Return the next input character after first passing any keyboard input 928 * Return the next input character after first passing any keyboard input
803 */ 930 */
804/* INTPROTO */ 931/* INTPROTO */
805uint32_t 932uint32_t
806rxvt_cmd_getc(pR) 933rxvt_cmd_getc(pR)
807{ 934{
935 for (;;)
936 {
937 uint32_t c = R->next_char ();
938 if (c != NOCHAR)
939 return c;
940
941 // incomplete sequences should occur rarely, still, a better solution
942 // would be preferred. either setjmp/longjmp or better design.
943 fcntl (R->cmd_fd, F_SETFL, 0);
944 R->pty_fill (1);
945 fcntl (R->cmd_fd, F_SETFL, O_NONBLOCK);
946 }
947
808#define TIMEOUT_USEC 5000 948#define TIMEOUT_USEC 5000
809 fd_set readfds; 949 fd_set readfds;
810 int quick_timeout, select_res; 950 int quick_timeout, select_res;
811 int want_motion_time, want_keypress_time; 951 int want_motion_time, want_keypress_time;
812 struct timeval value; 952 struct timeval value;
813#if defined(POINTER_BLANK) || defined(CURSOR_BLINK) 953#if defined(POINTER_BLANK) || defined(CURSOR_BLINK)
814 struct timeval tp; 954 struct timeval tp;
815#endif 955#endif
816
817 uint32_t c = next_char (aR);
818 if (c != NOCHAR)
819 return c;
820 956
821 for (;;) { 957 for (;;) {
822 /* loop until we can return something */ 958 /* loop until we can return something */
823 959
824 if (R->v_bufstr < R->v_bufptr) /* output any pending chars */ 960 if (R->v_bufstr < R->v_bufptr) /* output any pending chars */
979 } 1115 }
980#if defined(CURSOR_BLINK) 1116#if defined(CURSOR_BLINK)
981 if (R->Options & Opt_cursorBlink) 1117 if (R->Options & Opt_cursorBlink)
982 R->want_refresh = 1; 1118 R->want_refresh = 1;
983#endif 1119#endif
984
985 /* See if we can read new data from the application */
986 if (select_res > 0 && FD_ISSET(R->cmd_fd, &readfds)) {
987 int n;
988 unsigned int count;
989
990 R->cmdbuf_ptr = R->cmdbuf_endp = R->cmdbuf_base;
991 for (count = BUFSIZ; count; count -= n, R->cmdbuf_endp += n)
992 if ((n = read(R->cmd_fd, R->cmdbuf_endp, count)) > 0)
993 continue;
994 else if (n == 0 || (n < 0 && errno == EAGAIN))
995 break;
996 else {
997 rxvt_clean_exit();
998 exit(EXIT_FAILURE); /* bad order of events? */
999 }
1000
1001 if (count != BUFSIZ) /* some characters read in */
1002 {
1003 uint32_t c = next_char (aR);
1004 if (c != NOCHAR)
1005 return c;
1006 }
1007 }
1008#ifdef TRANSPARENT
1009 if (R->want_full_refresh) {
1010 R->want_full_refresh = 0;
1011 rxvt_scr_clear(aR);
1012 rxvt_scr_touch(aR_ False);
1013 R->want_refresh = 1;
1014 }
1015#endif
1016 if (R->want_refresh) {
1017 rxvt_scr_refresh(aR_ R->refresh_type);
1018 rxvt_scrollbar_show(aR_ 1);
1019#ifdef USE_XIM
1020 rxvt_IMSendSpot(aR);
1021#endif
1022 }
1023 } 1120 }
1024/* NOTREACHED */
1025} 1121}
1026/*}}} */
1027 1122
1028/* EXTPROTO */ 1123/* EXTPROTO */
1029void 1124void
1030rxvt_pointer_unblank(pR) 1125rxvt_pointer_unblank(pR)
1031{ 1126{
1320 R->want_refresh = 1; 1415 R->want_refresh = 1;
1321#ifdef USE_XIM 1416#ifdef USE_XIM
1322 if (R->Input_Context != NULL) 1417 if (R->Input_Context != NULL)
1323 XSetICFocus(R->Input_Context); 1418 XSetICFocus(R->Input_Context);
1324#endif 1419#endif
1420#ifdef CURSOR_BLINK
1421 if (R->Options & Opt_cursorBlink)
1422 R->blink_ev.start (NOW + BLINK_INTERVAL);
1423#endif
1325 } 1424 }
1326 break; 1425 break;
1327 1426
1328 case FocusOut: 1427 case FocusOut:
1329 if (R->TermWin.focus) { 1428 if (R->TermWin.focus) {
1330 R->TermWin.focus = 0; 1429 R->TermWin.focus = 0;
1331 R->want_refresh = 1; 1430 R->want_refresh = 1;
1332#ifdef USE_XIM 1431#ifdef USE_XIM
1333 if (R->Input_Context != NULL) 1432 if (R->Input_Context != NULL)
1334 XUnsetICFocus(R->Input_Context); 1433 XUnsetICFocus(R->Input_Context);
1434#endif
1435#ifdef CURSOR_BLINK
1436 if (R->Options & Opt_cursorBlink)
1437 R->blink_ev.stop ();
1438 R->hidden_cursor = 0;
1335#endif 1439#endif
1336 } 1440 }
1337 break; 1441 break;
1338 1442
1339 case ConfigureNotify: 1443 case ConfigureNotify:
3392} 3496}
3393/*}}} */ 3497/*}}} */
3394 3498
3395/* ------------------------------------------------------------------------- */ 3499/* ------------------------------------------------------------------------- */
3396 3500
3397/*{{{ Read and process output from the application */
3398/* LIBPROTO */
3399void
3400rxvt_main_loop(pR)
3401{
3402 uint32_t ch, *str, buf[BUFSIZ];
3403 int nlines, refreshnow;
3404
3405 R->cmdbuf_ptr = R->cmdbuf_endp = R->cmdbuf_base;
3406
3407 /* once we know the shell is running, send the screen size. Again! */
3408 ch = rxvt_cmd_getc(aR); /* wait for something */
3409 rxvt_tt_winsize(R->cmd_fd, R->TermWin.ncol, R->TermWin.nrow, R->cmd_pid);
3410
3411 refreshnow = 0;
3412 for (;;) {
3413 if (ch == NOCHAR)
3414 ch = rxvt_cmd_getc(aR);
3415
3416 if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
3417 {
3418 /* Read a text string from the input buffer */
3419 nlines = 0;
3420 str = buf;
3421 *str++ = ch;
3422 for (;;)
3423 {
3424 ch = next_char (aR);
3425
3426 if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
3427 break;
3428 else
3429 {
3430 *str++ = ch;
3431
3432 if (ch == '\n')
3433 {
3434 nlines++;
3435 R->refresh_count++;
3436 if (!(R->Options & Opt_jumpScroll)
3437 || (R->refresh_count >= (R->refresh_limit
3438 * (R->TermWin.nrow - 1))))
3439 {
3440 refreshnow = 1;
3441 ch = NOCHAR;
3442 break;
3443 }
3444 }
3445
3446 if (str >= buf + BUFSIZ)
3447 {
3448 ch = NOCHAR;
3449 break;
3450 }
3451 }
3452 }
3453
3454 rxvt_scr_add_lines(aR_ buf, nlines, str - buf);
3455
3456 /*
3457 * If there have been a lot of new lines, then update the screen
3458 * What the heck I'll cheat and only refresh less than every page-full.
3459 * the number of pages between refreshes is R->refresh_limit, which
3460 * is incremented here because we must be doing flat-out scrolling.
3461 *
3462 * refreshing should be correct for small scrolls, because of the
3463 * time-out
3464 */
3465
3466 //TODO: REFRESH_PERIOD is one, fix it
3467 if (refreshnow)
3468 {
3469 refreshnow = 0;
3470
3471 if ((R->Options & Opt_jumpScroll) && R->refresh_limit < REFRESH_PERIOD)
3472 R->refresh_limit++;
3473
3474 rxvt_scr_refresh(aR_ R->refresh_type);
3475 }
3476
3477 }
3478 else
3479 {
3480 switch (ch)
3481 {
3482 default:
3483 rxvt_process_nonprinting(aR_ ch);
3484 break;
3485 case C0_ESC: /* escape char */
3486 rxvt_process_escape_seq(aR);
3487 break;
3488 /* case 0x9b: */ /* CSI */
3489 /* rxvt_process_csi_seq(aR); */
3490 }
3491
3492 ch = NOCHAR;
3493 }
3494 }
3495/* NOTREACHED */
3496}
3497
3498/* 3501/*
3499 * Send printf() formatted output to the command. 3502 * Send printf() formatted output to the command.
3500 * Only use for small amounts of data. 3503 * Only use for small amounts of data.
3501 */ 3504 */
3502/* EXTPROTO */ 3505/* EXTPROTO */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines