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.4 by pcg, Tue Nov 25 15:25:16 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.4 2003/11/25 15:25:16 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,
701 701
702void 702void
703rxvt_term::x_cb (io_watcher &w, short revents) 703rxvt_term::x_cb (io_watcher &w, short revents)
704{ 704{
705 process_x_events (); 705 process_x_events ();
706
707 flush ();
706} 708}
707 709
708// read the next character, currently handles UTF-8 710// read the next character, currently handles UTF-8
709// will probably handle all sorts of other stuff in the future 711// will probably handle all sorts of other stuff in the future
710static uint32_t 712uint32_t
711next_char (pR) 713rxvt_term::next_char ()
712{ 714{
713 mbstate &s = R->mbstate; 715 struct mbstate &s = mbstate;
714 716
715 while (R->cmdbuf_ptr < R->cmdbuf_endp) 717 while (cmdbuf_ptr < cmdbuf_endp)
716 { 718 {
717 uint8_t ch = *R->cmdbuf_ptr; 719 uint8_t ch = *cmdbuf_ptr;
718 720
719 if (s.cnt) 721 if (s.cnt)
720 { 722 {
721 if ((ch & 0xc0) == 0x80) 723 if ((ch & 0xc0) == 0x80)
722 { 724 {
723 R->cmdbuf_ptr++; 725 cmdbuf_ptr++;
724 726
725 /* continuation */ 727 /* continuation */
726 s.reg = (s.reg << 6) | (ch & 0x7f); 728 s.reg = (s.reg << 6) | (ch & 0x7f);
727 729
728 if (--s.cnt == 0 && s.reg >= 128) /* if !inrange then corruption or Racking */ 730 if (--s.cnt == 0 && s.reg >= 128) /* if !inrange then corruption or Racking */
737 } 739 }
738 } 740 }
739 741
740 if ((ch & 0xc0) == 0xc0) 742 if ((ch & 0xc0) == 0xc0)
741 { 743 {
742 R->cmdbuf_ptr++; 744 cmdbuf_ptr++;
743 745
744 /* first byte */ 746 /* first byte */
745 s.orig = ch; /* for broken encodings */ 747 s.orig = ch; /* for broken encodings */
746 s.reg = ch; 748 s.reg = ch;
747 if ((ch & 0xe0) == 0xc0) { s.reg &= 0x1f; s.cnt = 1; } 749 if ((ch & 0xe0) == 0xc0) { s.reg &= 0x1f; s.cnt = 1; }
750 if ((ch & 0xfc) == 0xf8) { s.reg &= 0x03; s.cnt = 4; } 752 if ((ch & 0xfc) == 0xf8) { s.reg &= 0x03; s.cnt = 4; }
751 if ((ch & 0xfe) == 0xfc) { s.reg &= 0x01; s.cnt = 5; } 753 if ((ch & 0xfe) == 0xfc) { s.reg &= 0x01; s.cnt = 5; }
752 } 754 }
753 else 755 else
754 { 756 {
755 R->cmdbuf_ptr++; /* _occasional_ non-utf8 may slip through... */ 757 cmdbuf_ptr++; /* _occasional_ non-utf8 may slip through... */
756 return ch; 758 return ch;
757 } 759 }
758 } 760 }
759 761
760 return NOCHAR; 762 return NOCHAR;
763}
764
765bool
766rxvt_term::pty_fill (size_t count)
767{
768 ssize_t n = cmdbuf_endp - cmdbuf_ptr;
769
770 memmove (cmdbuf_base, cmdbuf_ptr, n);
771 cmdbuf_ptr = cmdbuf_base;
772 cmdbuf_endp = cmdbuf_ptr + n;
773
774 n = read (cmd_fd, cmdbuf_endp, count);
775
776 if (n > 0)
777 {
778 cmdbuf_endp += n;
779 return true;
780 }
781 else if (n < 0 && errno == EAGAIN)
782 return false;
783
784 rxvt_clean_exit();
785 exit(EXIT_FAILURE); /* bad order of events? */
761} 786}
762 787
763void 788void
764rxvt_term::pty_cb (io_watcher &w, short revents) 789rxvt_term::pty_cb (io_watcher &w, short revents)
765{ 790{
766 int n; 791 while (pty_fill (BUFSIZ - (cmdbuf_endp - cmdbuf_ptr)))
767 unsigned int count;
768
769 if (count = (cmdbuf_endp - cmdbuf_ptr))
770 { 792 {
771 memmove (cmdbuf_base, cmdbuf_ptr, count); 793 /* once we know the shell is running, send the screen size. Again! */
772 cmdbuf_ptr = cmdbuf_base; 794 //ch = rxvt_cmd_getc(aR); /* wait for something */
773 cmdbuf_endp = cmdbuf_ptr + count; 795 //rxvt_tt_winsize(cmd_fd, TermWin.ncol, TermWin.nrow, cmd_pid);
774 }
775
776 796
777 for (count = BUFSIZ - count; count; count -= n, cmdbuf_endp += n) 797 uint32_t ch = NOCHAR;
778 if ((n = read(cmd_fd, cmdbuf_endp, count)) > 0) 798
779 continue; 799 for (;;)
780 else if (n == 0 || (n < 0 && errno == EAGAIN))
781 break;
782 else
783 { 800 {
784 rxvt_clean_exit(); 801 if (ch == NOCHAR)
785 exit(EXIT_FAILURE); /* bad order of events? */ 802 ch = next_char ();
803
804 if (ch == NOCHAR) // TODO: improve
805 break;
806
807 if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
808 {
809 /* Read a text string from the input buffer */
810 uint32_t buf[BUFSIZ];
811 bool refreshnow = false;
812 int nlines = 0;
813 uint32_t *str = buf;
814
815 *str++ = ch;
816
817 for (;;)
818 {
819 ch = next_char ();
820
821 if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
822 break;
823 else
824 {
825 *str++ = ch;
826
827 if (ch == '\n')
828 {
829 nlines++;
830 refresh_count++;
831
832 if (!(Options & Opt_jumpScroll)
833 || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
834 {
835 refreshnow = true;
836 ch = NOCHAR;
837 break;
838 }
839 }
840
841 if (str >= buf + BUFSIZ)
842 {
843 ch = NOCHAR;
844 break;
845 }
846 }
847 }
848
849 rxvt_scr_add_lines (this, buf, nlines, str - buf);
850
851 /*
852 * If there have been a lot of new lines, then update the screen
853 * What the heck I'll cheat and only refresh less than every page-full.
854 * the number of pages between refreshes is refresh_limit, which
855 * is incremented here because we must be doing flat-out scrolling.
856 *
857 * refreshing should be correct for small scrolls, because of the
858 * time-out
859 */
860 if (refreshnow)
861 {
862 if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
863 refresh_limit++;
864
865 rxvt_scr_refresh (this, refresh_type);
866 }
867
868 }
869 else
870 {
871 switch (ch)
872 {
873 default:
874 rxvt_process_nonprinting (this, ch);
875 break;
876 case C0_ESC: /* escape char */
877 rxvt_process_escape_seq (this);
878 break;
879 /*case 0x9b: */ /* CSI */
880 /* rxvt_process_csi_seq (this); */
881 }
882
883 ch = NOCHAR;
884 }
786 } 885 }
886 }
787 887
788 if (count != BUFSIZ) /* some characters read in */ 888 flush ();
889}
890
891void
892rxvt_term::flush ()
893{
894#ifdef TRANSPARENT
895 if (want_full_refresh)
789 { 896 {
790 uint32_t c = next_char (this); 897 want_full_refresh = 0;
791 898 rxvt_scr_clear (this);
792#if 0 899 rxvt_scr_touch (this, False);
793 if (c != NOCHAR) 900 want_refresh = 1;
794 return c; 901 }
795#endif 902#endif
903
904 if (want_refresh)
796 } 905 {
906 rxvt_scr_refresh (this, refresh_type);
907 rxvt_scrollbar_show (this, 1);
908#ifdef USE_XIM
909 rxvt_IMSendSpot (this);
910#endif
911 }
912
913 XFlush (Xdisplay);
797} 914}
798 915
799/* rxvt_cmd_getc() - Return next input character */ 916/* rxvt_cmd_getc() - Return next input character */
800/* 917/*
801 * Return the next input character after first passing any keyboard input 918 * Return the next input character after first passing any keyboard input
803 */ 920 */
804/* INTPROTO */ 921/* INTPROTO */
805uint32_t 922uint32_t
806rxvt_cmd_getc(pR) 923rxvt_cmd_getc(pR)
807{ 924{
925 for (;;)
926 {
927 uint32_t c = R->next_char ();
928 if (c != NOCHAR)
929 return c;
930
931 // incomplete sequences should occur rarely, still, a better solution
932 // would be preferred. either setjmp/longjmp or better design.
933 fcntl (R->cmd_fd, F_SETFL, 0);
934 R->pty_fill (1);
935 fcntl (R->cmd_fd, F_SETFL, O_NONBLOCK);
936 }
937
808#define TIMEOUT_USEC 5000 938#define TIMEOUT_USEC 5000
809 fd_set readfds; 939 fd_set readfds;
810 int quick_timeout, select_res; 940 int quick_timeout, select_res;
811 int want_motion_time, want_keypress_time; 941 int want_motion_time, want_keypress_time;
812 struct timeval value; 942 struct timeval value;
813#if defined(POINTER_BLANK) || defined(CURSOR_BLINK) 943#if defined(POINTER_BLANK) || defined(CURSOR_BLINK)
814 struct timeval tp; 944 struct timeval tp;
815#endif 945#endif
816
817 uint32_t c = next_char (aR);
818 if (c != NOCHAR)
819 return c;
820 946
821 for (;;) { 947 for (;;) {
822 /* loop until we can return something */ 948 /* loop until we can return something */
823 949
824 if (R->v_bufstr < R->v_bufptr) /* output any pending chars */ 950 if (R->v_bufstr < R->v_bufptr) /* output any pending chars */
979 } 1105 }
980#if defined(CURSOR_BLINK) 1106#if defined(CURSOR_BLINK)
981 if (R->Options & Opt_cursorBlink) 1107 if (R->Options & Opt_cursorBlink)
982 R->want_refresh = 1; 1108 R->want_refresh = 1;
983#endif 1109#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 } 1110 }
1024/* NOTREACHED */
1025} 1111}
1026/*}}} */
1027 1112
1028/* EXTPROTO */ 1113/* EXTPROTO */
1029void 1114void
1030rxvt_pointer_unblank(pR) 1115rxvt_pointer_unblank(pR)
1031{ 1116{
3392} 3477}
3393/*}}} */ 3478/*}}} */
3394 3479
3395/* ------------------------------------------------------------------------- */ 3480/* ------------------------------------------------------------------------- */
3396 3481
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/* 3482/*
3499 * Send printf() formatted output to the command. 3483 * Send printf() formatted output to the command.
3500 * Only use for small amounts of data. 3484 * Only use for small amounts of data.
3501 */ 3485 */
3502/* EXTPROTO */ 3486/* EXTPROTO */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines