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.10 by pcg, Thu Nov 27 16:49:45 2003 UTC vs.
Revision 1.15 by pcg, Tue Dec 16 23:04:13 2003 UTC

1/*--------------------------------*-C-*---------------------------------* 1/*--------------------------------*-C-*---------------------------------*
2 * File: command.c 2 * File: command.c
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * $Id: command.C,v 1.10 2003/11/27 16:49:45 pcg Exp $ 4 * $Id: command.C,v 1.15 2003/12/16 23:04:13 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>
61 unsigned int newlen; 61 unsigned int newlen;
62 KeySym keysym; 62 KeySym keysym;
63#ifdef DEBUG_CMD 63#ifdef DEBUG_CMD
64 static int debug_key = 1; /* accessible by a debugger only */ 64 static int debug_key = 1; /* accessible by a debugger only */
65#endif 65#endif
66#ifdef USE_XIM
67 int valid_keysym; 66 int valid_keysym;
68#endif
69 unsigned char *kbuf = R->kbuf; 67 unsigned char *kbuf = R->kbuf;
70 68
71/* 69/*
72 * use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an 70 * use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an
73 * escape sequence to toggle the Keypad. 71 * escape sequence to toggle the Keypad.
75 * Always permit `shift' to override the current setting 73 * Always permit `shift' to override the current setting
76 */ 74 */
77 shft = (ev->state & ShiftMask); 75 shft = (ev->state & ShiftMask);
78 ctrl = (ev->state & ControlMask); 76 ctrl = (ev->state & ControlMask);
79 meta = (ev->state & R->ModMetaMask); 77 meta = (ev->state & R->ModMetaMask);
78
80 if (R->numlock_state || (ev->state & R->ModNumLockMask)) { 79 if (R->numlock_state || (ev->state & R->ModNumLockMask))
80 {
81 R->numlock_state = (ev->state & R->ModNumLockMask); 81 R->numlock_state = (ev->state & R->ModNumLockMask);
82 PrivMode((!R->numlock_state), PrivMode_aplKP); 82 PrivMode((!R->numlock_state), PrivMode_aplKP);
83 } 83 }
84
85 kbuf[0] = 0;
86
84#ifdef USE_XIM 87#ifdef USE_XIM
85 if (R->Input_Context != NULL) { 88 if (R->Input_Context)
89 {
86 Status status_return; 90 Status status_return;
87 91
88 kbuf[0] = '\0';
89#ifdef X_HAVE_UTF8_STRING 92#ifdef X_HAVE_UTF8_STRING
90 len = Xutf8LookupString(R->Input_Context, ev, (char *)kbuf, 93 len = Xutf8LookupString(R->Input_Context, ev, (char *)kbuf,
91 KBUFSZ, &keysym, &status_return); 94 KBUFSZ, &keysym, &status_return);
92#else 95#else
93 len = XmbLookupString(R->Input_Context, ev, (char *)kbuf, 96 len = XmbLookupString(R->Input_Context, ev, (char *)kbuf,
94 KBUFSZ, &keysym, &status_return); 97 KBUFSZ, &keysym, &status_return);
95#endif 98#endif
96 valid_keysym = ((status_return == XLookupKeySym) 99 valid_keysym = ((status_return == XLookupKeySym)
97 || (status_return == XLookupBoth)); 100 || (status_return == XLookupBoth));
101 }
98 } else { 102 else
103#endif
104 {
99 len = XLookupString(ev, (char *)kbuf, KBUFSZ, &keysym, 105 len = XLookupString(ev, (char *)kbuf, KBUFSZ, &keysym, &R->compose);
100 &R->compose);
101 valid_keysym = 1; 106 valid_keysym = !len;
102 } 107 }
103#else /* USE_XIM */
104 len = XLookupString(ev, (char *)kbuf, KBUFSZ, &keysym,
105 &R->compose);
106/*
107 * map unmapped Latin[2-4]/Katakana/Arabic/Cyrillic/Greek entries -> Latin1
108 * good for installations with correct fonts, but without XLOCALE
109 */
110 if (!len) {
111 if ((keysym >= 0x0100) && (keysym < 0x0800)) {
112 kbuf[0] = (keysym & 0xFF);
113 kbuf[1] = '\0';
114 len = 1;
115 } else
116 kbuf[0] = '\0';
117 }
118#endif /* USE_XIM */
119 108
120#ifdef USE_XIM
121 if (valid_keysym) 109 if (valid_keysym)
122#endif
123 { 110 {
124/* for some backwards compatibility */ 111/* for some backwards compatibility */
125#if defined(HOTKEY_CTRL) || defined(HOTKEY_META) 112#if defined(HOTKEY_CTRL) || defined(HOTKEY_META)
126# ifdef HOTKEY_CTRL 113# ifdef HOTKEY_CTRL
127 if (ctrl) { 114 if (ctrl)
128# else 115# else
129 if (meta) { 116 if (meta)
130# endif 117# endif
118 {
131 if (keysym == R->ks_bigfont) { 119 if (keysym == R->ks_bigfont)
120 {
132 rxvt_change_font(aR_ 0, FONT_UP); 121 rxvt_change_font(aR_ 0, FONT_UP);
133 return; 122 return;
123 }
134 } else if (keysym == R->ks_smallfont) { 124 else if (keysym == R->ks_smallfont)
125 {
135 rxvt_change_font(aR_ 0, FONT_DN); 126 rxvt_change_font(aR_ 0, FONT_DN);
136 return; 127 return;
137 } 128 }
138 } 129 }
139#endif 130#endif
140 131
141 if (R->TermWin.saveLines) { 132 if (R->TermWin.saveLines) {
142#ifdef UNSHIFTED_SCROLLKEYS 133#ifdef UNSHIFTED_SCROLLKEYS
143 if (!ctrl && !meta) { 134 if (!ctrl && !meta) {
237 /* escape prefix */ 228 /* escape prefix */
238 if (meta) 229 if (meta)
239# ifdef META8_OPTION 230# ifdef META8_OPTION
240 if (R->meta_char == C0_ESC) 231 if (R->meta_char == C0_ESC)
241# endif 232# endif
242 R->tt_write(&ch, 1); 233 R->tt_write (&ch, 1);
243 R->tt_write(kbuf0, l); 234 R->tt_write (kbuf0, l);
244 return; 235 return;
245 } else 236 } else
246#endif 237#endif
247 { 238 {
248 newlen = 1; 239 newlen = 1;
572 if (R->greek_mode) 563 if (R->greek_mode)
573 len = greek_xlat(kbuf, len); 564 len = greek_xlat(kbuf, len);
574#endif 565#endif
575 /* nil */ ; 566 /* nil */ ;
576 } 567 }
577 } 568 }
578 569
579 if (len <= 0) 570 if (len <= 0)
580 return; /* not mapped */ 571 return; /* not mapped */
581 572
582 if (R->Options & Opt_scrollTtyKeypress) 573 if (R->Options & Opt_scrollTtyKeypress)
656 return 0; 647 return 0;
657} 648}
658#endif /* MENUBAR_MAX */ 649#endif /* MENUBAR_MAX */
659 650
660void 651void
652rxvt_term::flush ()
653{
654#ifdef TRANSPARENT
655 if (want_full_refresh)
656 {
657 want_full_refresh = 0;
658 rxvt_scr_clear (this);
659 rxvt_scr_touch (this, False);
660 want_refresh = 1;
661 }
662#endif
663
664 if (want_refresh)
665 {
666 rxvt_scr_refresh (this, refresh_type);
667 rxvt_scrollbar_show (this, 1);
668#ifdef USE_XIM
669 rxvt_IMSendSpot (this);
670#endif
671 }
672
673 XFlush (Xdisplay);
674#if 0
675 if (XPending (Xdisplay)) process_x_events ();
676 if (XPending (Xdisplay)) process_x_events ();
677#endif
678}
679
680void
681rxvt_term::check_cb (check_watcher &w)
682{
683 SET_R (this);
684
685 flush ();
686}
687
688void
661rxvt_term::process_x_events () 689rxvt_term::process_x_events ()
662{ 690{
663 do 691 do
664 { 692 {
665 XEvent xev; 693 XEvent xev;
709 SET_R (this); 737 SET_R (this);
710 738
711 w.at += BLINK_INTERVAL; 739 w.at += BLINK_INTERVAL;
712 hidden_cursor = !hidden_cursor; 740 hidden_cursor = !hidden_cursor;
713 want_refresh = 1; 741 want_refresh = 1;
714 flush ();
715} 742}
716 743
717void 744void
718rxvt_term::x_cb (io_watcher &w, short revents) 745rxvt_term::x_cb (io_watcher &w, short revents)
719{ 746{
720 SET_R (this); 747 SET_R (this);
721 748
722 process_x_events (); 749 process_x_events ();
750}
723 751
724 flush (); 752bool
753rxvt_term::pty_fill ()
754{
755 ssize_t n = cmdbuf_endp - cmdbuf_ptr;
756
757 memmove (cmdbuf_base, cmdbuf_ptr, n);
758 cmdbuf_ptr = cmdbuf_base;
759 cmdbuf_endp = cmdbuf_ptr + n;
760
761 n = read (cmd_fd, cmdbuf_endp, BUFSIZ - n);
762
763 if (n > 0)
764 {
765 cmdbuf_endp += n;
766 return true;
767 }
768 else if (n < 0 && errno != EAGAIN)
769 destroy ();
770
771 return false;
772}
773
774void
775rxvt_term::pty_cb (io_watcher &w, short revents)
776{
777 SET_R (this);
778
779 if (revents & EVENT_WRITE)
780 tt_write (0, 0);
781 else if (revents & EVENT_READ)
782 {
783 bool flag = true;
784
785 // loop, but don't allow a single term to monopolize us
786 // the number of loops is fully arbitrary, and thus wrong
787 while (flag && pty_fill ())
788 {
789 if (!seen_input)
790 {
791 seen_input = 1;
792 /* once we know the shell is running, send the screen size. Again! */
793 tt_winch ();
794 }
795
796 uint32_t ch = NOCHAR;
797
798 for (;;)
799 {
800 if (ch == NOCHAR)
801 ch = next_char ();
802
803 if (ch == NOCHAR) // TODO: improve
804 break;
805
806 if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
807 {
808 /* Read a text string from the input buffer */
809 uint32_t buf[BUFSIZ];
810 bool refreshnow = false;
811 int nlines = 0;
812 uint32_t *str = buf;
813
814 *str++ = ch;
815
816 for (;;)
817 {
818 ch = next_char ();
819
820 if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
821 break;
822 else
823 {
824 *str++ = ch;
825
826 if (ch == '\n')
827 {
828 nlines++;
829 refresh_count++;
830
831 if (!(Options & Opt_jumpScroll)
832 || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
833 {
834 refreshnow = true;
835 flag = false;
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 }
885 }
886 }
887 }
725} 888}
726 889
727// read the next character, currently handles UTF-8 890// read the next character, currently handles UTF-8
728// will probably handle all sorts of other stuff in the future 891// will probably handle all sorts of other stuff in the future
729uint32_t 892uint32_t
775 return ch; 938 return ch;
776 } 939 }
777 } 940 }
778 941
779 return NOCHAR; 942 return NOCHAR;
780}
781
782bool
783rxvt_term::pty_fill ()
784{
785 ssize_t n = cmdbuf_endp - cmdbuf_ptr;
786
787 memmove (cmdbuf_base, cmdbuf_ptr, n);
788 cmdbuf_ptr = cmdbuf_base;
789 cmdbuf_endp = cmdbuf_ptr + n;
790
791 n = read (cmd_fd, cmdbuf_endp, BUFSIZ - n);
792
793 if (n > 0)
794 {
795 cmdbuf_endp += n;
796 return true;
797 }
798 else if (n < 0 && errno == EAGAIN)
799 return false;
800
801 destroy ();
802}
803
804void
805rxvt_term::pty_cb (io_watcher &w, short revents)
806{
807 SET_R (this);
808
809 if (revents & EVENT_WRITE)
810 tt_write (0, 0);
811 else if (revents & EVENT_READ)
812 // loop, but don't allow a single term to monopolize us
813 // the number of loops is fully arbitrary, and thus wrong
814 for (int i = 7; i-- && pty_fill (); )
815 {
816 //TODO:
817 /* once we know the shell is running, send the screen size. Again! */
818 //ch = rxvt_cmd_getc(aR); /* wait for something */
819 //rxvt_tt_winsize(cmd_fd, TermWin.ncol, TermWin.nrow, cmd_pid);
820
821 uint32_t ch = NOCHAR;
822
823 for (;;)
824 {
825 if (ch == NOCHAR)
826 ch = next_char ();
827
828 if (ch == NOCHAR) // TODO: improve
829 break;
830
831 if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
832 {
833 /* Read a text string from the input buffer */
834 uint32_t buf[BUFSIZ];
835 bool refreshnow = false;
836 int nlines = 0;
837 uint32_t *str = buf;
838
839 *str++ = ch;
840
841 for (;;)
842 {
843 ch = next_char ();
844
845 if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
846 break;
847 else
848 {
849 *str++ = ch;
850
851 if (ch == '\n')
852 {
853 nlines++;
854 refresh_count++;
855
856 if (!(Options & Opt_jumpScroll)
857 || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
858 {
859 refreshnow = true;
860 ch = NOCHAR;
861 break;
862 }
863 }
864
865 if (str >= buf + BUFSIZ)
866 {
867 ch = NOCHAR;
868 break;
869 }
870 }
871 }
872
873 rxvt_scr_add_lines (this, buf, nlines, str - buf);
874
875 /*
876 * If there have been a lot of new lines, then update the screen
877 * What the heck I'll cheat and only refresh less than every page-full.
878 * the number of pages between refreshes is refresh_limit, which
879 * is incremented here because we must be doing flat-out scrolling.
880 *
881 * refreshing should be correct for small scrolls, because of the
882 * time-out
883 */
884 if (refreshnow)
885 {
886 if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
887 refresh_limit++;
888
889 rxvt_scr_refresh (this, refresh_type);
890 }
891
892 }
893 else
894 {
895 switch (ch)
896 {
897 default:
898 rxvt_process_nonprinting (this, ch);
899 break;
900 case C0_ESC: /* escape char */
901 rxvt_process_escape_seq (this);
902 break;
903 /*case 0x9b: */ /* CSI */
904 /* rxvt_process_csi_seq (this); */
905 }
906
907 ch = NOCHAR;
908 }
909 }
910 }
911
912 flush ();
913}
914
915void
916rxvt_term::flush ()
917{
918#ifdef TRANSPARENT
919 if (want_full_refresh)
920 {
921 want_full_refresh = 0;
922 rxvt_scr_clear (this);
923 rxvt_scr_touch (this, False);
924 want_refresh = 1;
925 }
926#endif
927
928 if (want_refresh)
929 {
930 rxvt_scr_refresh (this, refresh_type);
931 rxvt_scrollbar_show (this, 1);
932#ifdef USE_XIM
933 rxvt_IMSendSpot (this);
934#endif
935 }
936
937 if (XPending (Xdisplay)) process_x_events ();
938 XFlush (Xdisplay);
939 if (XPending (Xdisplay)) process_x_events ();
940} 943}
941 944
942/* rxvt_cmd_getc() - Return next input character */ 945/* rxvt_cmd_getc() - Return next input character */
943/* 946/*
944 * Return the next input character after first passing any keyboard input 947 * Return the next input character after first passing any keyboard input
1143{ 1146{
1144 int i, want_timeout; 1147 int i, want_timeout;
1145 Window unused_root, unused_child; 1148 Window unused_root, unused_child;
1146 int unused_root_x, unused_root_y; 1149 int unused_root_x, unused_root_y;
1147 unsigned int unused_mask; 1150 unsigned int unused_mask;
1148 struct timeval tp;
1149 1151
1150#ifdef DEBUG_X 1152#ifdef DEBUG_X
1151 const char *const eventnames[] = 1153 const char *const eventnames[] =
1152 { /* mason - this matches my system */ 1154 { /* mason - this matches my system */
1153 "", 1155 "",
1184 "SelectionNotify", 1186 "SelectionNotify",
1185 "ColormapNotify", 1187 "ColormapNotify",
1186 "ClientMessage", 1188 "ClientMessage",
1187 "MappingNotify" 1189 "MappingNotify"
1188 }; 1190 };
1191#endif
1192
1193#ifdef DEBUG_X
1194 struct timeval tp;
1189 struct tm *ltt; 1195 struct tm *ltt;
1190#endif
1191
1192 /*
1193 * check if we need to get the time for any timeouts
1194 */
1195
1196 for (i = NUM_TIMEOUTS; i--; )
1197 if (R->timeout[i].tv_sec) {
1198 want_timeout = 1;
1199 break;
1200 }
1201
1202#ifndef DEBUG_X
1203 if (want_timeout)
1204#endif
1205 (void)gettimeofday(&tp, NULL); 1196 (void)gettimeofday(&tp, NULL);
1206
1207#ifdef DEBUG_X
1208 ltt = localtime(&(tp.tv_sec)); 1197 ltt = localtime(&(tp.tv_sec));
1209 D_X((stderr, "Event: %-16s %-7s %08lx (%4d-%02d-%02d %02d:%02d:%02d.%.6ld) %s %lu", eventnames[ev->type], (ev->xany.window == R->TermWin.parent[0] ? "parent" : (ev->xany.window == R->TermWin.vt ? "vt" : (ev->xany.window == R->scrollBar.win ? "scroll" : (ev->xany.window == R->menuBar.win ? "menubar" : "UNKNOWN")))), (ev->xany.window == R->TermWin.parent[0] ? R->TermWin.parent[0] : (ev->xany.window == R->TermWin.vt ? R->TermWin.vt : (ev->xany.window == R->scrollBar.win ? R->scrollBar.win : (ev->xany.window == R->menuBar.win ? R->menuBar.win : 0)))), ltt->tm_year + 1900, ltt->tm_mon + 1, ltt->tm_mday, ltt->tm_hour, ltt->tm_min, ltt->tm_sec, tp.tv_usec, ev->xany.send_event ? "S" : " ", ev->xany.serial)); 1198 D_X((stderr, "Event: %-16s %-7s %08lx (%4d-%02d-%02d %02d:%02d:%02d.%.6ld) %s %lu", eventnames[ev->type], (ev->xany.window == R->TermWin.parent[0] ? "parent" : (ev->xany.window == R->TermWin.vt ? "vt" : (ev->xany.window == R->scrollBar.win ? "scroll" : (ev->xany.window == R->menuBar.win ? "menubar" : "UNKNOWN")))), (ev->xany.window == R->TermWin.parent[0] ? R->TermWin.parent[0] : (ev->xany.window == R->TermWin.vt ? R->TermWin.vt : (ev->xany.window == R->scrollBar.win ? R->scrollBar.win : (ev->xany.window == R->menuBar.win ? R->menuBar.win : 0)))), ltt->tm_year + 1900, ltt->tm_mon + 1, ltt->tm_mday, ltt->tm_hour, ltt->tm_min, ltt->tm_sec, tp.tv_usec, ev->xany.send_event ? "S" : " ", ev->xany.serial));
1210#endif 1199#endif
1211
1212 /* X event timeouts */
1213 if (want_timeout)
1214 for (i = NUM_TIMEOUTS; i--; ) {
1215 if (R->timeout[i].tv_sec == 0)
1216 continue;
1217 if ((tp.tv_sec < R->timeout[i].tv_sec)
1218 || (tp.tv_sec == R->timeout[i].tv_sec
1219 && tp.tv_usec < R->timeout[i].tv_usec))
1220 continue;
1221 R->timeout[i].tv_sec = 0;
1222 switch(i) {
1223 case TIMEOUT_INCR:
1224 rxvt_print_error("data loss: timeout on INCR selection paste");
1225 R->selection_wait = Sel_none;
1226 break;
1227 default:
1228 break;
1229 }
1230 }
1231 1200
1232 switch (ev->type) { 1201 switch (ev->type) {
1233 case KeyPress: 1202 case KeyPress:
1234 rxvt_lookup_key(aR_ (XKeyEvent *)ev); 1203 rxvt_lookup_key(aR_ (XKeyEvent *)ev);
1235 break; 1204 break;
2094 return stream; 2063 return stream;
2095} 2064}
2096 2065
2097/* EXTPROTO */ 2066/* EXTPROTO */
2098int 2067int
2099rxvt_pclose_printer(FILE *stream) 2068rxvt_pclose_printer (FILE *stream)
2100{ 2069{
2101 fflush(stream); 2070 fflush (stream);
2102/* pclose() reported not to work on SunOS 4.1.3 */ 2071/* pclose() reported not to work on SunOS 4.1.3 */
2103# if defined (__sun__) /* TODO: RESOLVE THIS */ 2072# if defined (__sun__) /* TODO: RESOLVE THIS */
2104/* pclose works provided SIGCHLD handler uses waitpid */ 2073/* pclose works provided SIGCHLD handler uses waitpid */
2105 return pclose(stream); /* return fclose (stream); */ 2074 return pclose (stream); /* return fclose (stream); */
2106# else 2075# else
2107 return pclose(stream); 2076 return pclose (stream);
2108# endif 2077# endif
2109} 2078}
2110 2079
2111/* 2080/*
2112 * simulate attached vt100 printer 2081 * simulate attached vt100 printer

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines