… | |
… | |
110 | SET_LOCALE (locale); |
110 | SET_LOCALE (locale); |
111 | |
111 | |
112 | if (status_return == XLookupChars |
112 | if (status_return == XLookupChars |
113 | || status_return == XLookupBoth) |
113 | || status_return == XLookupBoth) |
114 | { |
114 | { |
|
|
115 | /* make sure the user can type ctrl-@, i.e. NUL */ |
|
|
116 | if (len == 1 && *wkbuf == 0) |
|
|
117 | { |
|
|
118 | kbuf[0] = 0; |
|
|
119 | len = 1; |
|
|
120 | } |
|
|
121 | else |
|
|
122 | { |
115 | wkbuf[len] = 0; |
123 | wkbuf[len] = 0; |
116 | len = wcstombs ((char *)kbuf, wkbuf, KBUFSZ); |
124 | len = wcstombs ((char *)kbuf, wkbuf, KBUFSZ); |
117 | if (len < 0) |
125 | if (len < 0) |
118 | len = 0; |
126 | len = 0; |
|
|
127 | } |
119 | } |
128 | } |
120 | else |
129 | else |
121 | len = 0; |
130 | len = 0; |
122 | } |
131 | } |
123 | |
132 | |
… | |
… | |
653 | kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~')); |
662 | kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~')); |
654 | |
663 | |
655 | /* escape prefix */ |
664 | /* escape prefix */ |
656 | if (meta |
665 | if (meta |
657 | #ifdef META8_OPTION |
666 | #ifdef META8_OPTION |
658 | && (meta_char == C0_ESC) |
667 | && meta_char == C0_ESC |
659 | #endif |
668 | #endif |
660 | ) |
669 | ) |
661 | { |
670 | { |
662 | const unsigned char ch = C0_ESC; |
671 | const unsigned char ch = C0_ESC; |
663 | |
|
|
664 | tt_write (&ch, 1); |
672 | tt_write (&ch, 1); |
665 | } |
673 | } |
|
|
674 | |
666 | #ifdef DEBUG_CMD |
675 | #if defined(DEBUG_CMD) |
667 | if (debug_key) |
|
|
668 | { /* Display keyboard buffer contents */ |
676 | /* Display keyboard buffer contents */ |
669 | char *p; |
677 | unsigned char *p; |
670 | int i; |
678 | int i; |
671 | |
679 | |
672 | fprintf (stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len); |
680 | fprintf (stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len); |
673 | for (i = 0, p = kbuf; i < len; i++, p++) |
681 | for (i = 0, p = kbuf; i < len; i++, p++) |
674 | fprintf (stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p); |
682 | fprintf (stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p); |
675 | fprintf (stderr, "'\n"); |
683 | fprintf (stderr, "'\n"); |
676 | } |
|
|
677 | #endif /* DEBUG_CMD */ |
684 | #endif /* DEBUG_CMD */ |
678 | tt_write (kbuf, (unsigned int)len); |
685 | tt_write (kbuf, (unsigned int)len); |
679 | } |
686 | } |
680 | /*}}} */ |
687 | /*}}} */ |
681 | |
688 | |
… | |
… | |
687 | { |
694 | { |
688 | unsigned int n, s; |
695 | unsigned int n, s; |
689 | |
696 | |
690 | n = cmdbuf_ptr - cmdbuf_base; |
697 | n = cmdbuf_ptr - cmdbuf_base; |
691 | s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp; |
698 | s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp; |
|
|
699 | |
692 | if (n > 0 && s < count) |
700 | if (n > 0 && s < count) |
693 | { |
701 | { |
694 | MEMMOVE (cmdbuf_base, cmdbuf_ptr, |
702 | MEMMOVE (cmdbuf_base, cmdbuf_ptr, |
695 | (unsigned int) (cmdbuf_endp - cmdbuf_ptr)); |
703 | (unsigned int) (cmdbuf_endp - cmdbuf_ptr)); |
696 | cmdbuf_ptr = cmdbuf_base; |
704 | cmdbuf_ptr = cmdbuf_base; |
697 | cmdbuf_endp -= n; |
705 | cmdbuf_endp -= n; |
698 | s += n; |
706 | s += n; |
699 | } |
707 | } |
|
|
708 | |
700 | if (count > s) |
709 | if (count > s) |
701 | { |
710 | { |
702 | rxvt_print_error ("data loss: cmd_write too large"); |
711 | rxvt_print_error ("data loss: cmd_write too large"); |
703 | count = s; |
712 | count = s; |
704 | } |
713 | } |
|
|
714 | |
705 | for (; count--;) |
715 | for (; count--;) |
706 | *cmdbuf_endp++ = *str++; |
716 | *cmdbuf_endp++ = *str++; |
|
|
717 | |
|
|
718 | cmd_parse (); |
|
|
719 | |
707 | return 0; |
720 | return 0; |
708 | } |
721 | } |
709 | #endif /* MENUBAR_MAX */ |
722 | #endif /* MENUBAR_MAX */ |
710 | |
723 | |
711 | void |
724 | void |
… | |
… | |
783 | cmdbuf_endp += n; |
796 | cmdbuf_endp += n; |
784 | return true; |
797 | return true; |
785 | } |
798 | } |
786 | else if (n < 0 && errno != EAGAIN) |
799 | else if (n < 0 && errno != EAGAIN) |
787 | destroy (); |
800 | destroy (); |
788 | |
801 | |
789 | return false; |
802 | return false; |
790 | } |
803 | } |
791 | |
804 | |
792 | void |
805 | void |
793 | rxvt_term::pty_cb (io_watcher &w, short revents) |
806 | rxvt_term::pty_cb (io_watcher &w, short revents) |
… | |
… | |
810 | seen_input = 1; |
823 | seen_input = 1; |
811 | /* once we know the shell is running, send the screen size. Again! */ |
824 | /* once we know the shell is running, send the screen size. Again! */ |
812 | tt_winch (); |
825 | tt_winch (); |
813 | } |
826 | } |
814 | |
827 | |
|
|
828 | if (cmd_parse ()) |
|
|
829 | break; |
|
|
830 | } |
|
|
831 | } |
|
|
832 | } |
|
|
833 | |
|
|
834 | bool |
|
|
835 | rxvt_term::cmd_parse () |
|
|
836 | { |
|
|
837 | bool flag = false; |
815 | uint32_t ch = NOCHAR; |
838 | uint32_t ch = NOCHAR; |
|
|
839 | |
|
|
840 | for (;;) |
|
|
841 | { |
|
|
842 | if (ch == NOCHAR) |
|
|
843 | ch = next_char (); |
|
|
844 | |
|
|
845 | if (ch == NOCHAR) // TODO: improve |
|
|
846 | break; |
|
|
847 | |
|
|
848 | if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') |
|
|
849 | { |
|
|
850 | /* Read a text string from the input buffer */ |
|
|
851 | uint32_t buf[BUFSIZ]; |
|
|
852 | bool refreshnow = false; |
|
|
853 | int nlines = 0; |
|
|
854 | uint32_t *str = buf; |
|
|
855 | |
|
|
856 | *str++ = ch; |
816 | |
857 | |
817 | for (;;) |
858 | for (;;) |
818 | { |
859 | { |
819 | if (ch == NOCHAR) |
|
|
820 | ch = next_char (); |
860 | ch = next_char (); |
821 | |
861 | |
822 | if (ch == NOCHAR) // TODO: improve |
862 | if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r')) |
823 | break; |
863 | break; |
824 | |
864 | else |
825 | if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') |
|
|
826 | { |
865 | { |
827 | /* Read a text string from the input buffer */ |
|
|
828 | uint32_t buf[BUFSIZ]; |
|
|
829 | bool refreshnow = false; |
|
|
830 | int nlines = 0; |
|
|
831 | uint32_t *str = buf; |
|
|
832 | |
|
|
833 | *str++ = ch; |
866 | *str++ = ch; |
834 | |
867 | |
835 | for (;;) |
868 | if (ch == '\n') |
836 | { |
869 | { |
837 | ch = next_char (); |
|
|
838 | |
|
|
839 | if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r')) |
|
|
840 | break; |
|
|
841 | else |
870 | nlines++; |
|
|
871 | refresh_count++; |
|
|
872 | |
|
|
873 | if (! (Options & Opt_jumpScroll) |
|
|
874 | || (refresh_count >= (refresh_limit * (TermWin.nrow - 1)))) |
842 | { |
875 | { |
843 | *str++ = ch; |
|
|
844 | |
|
|
845 | if (ch == '\n') |
|
|
846 | { |
|
|
847 | nlines++; |
|
|
848 | refresh_count++; |
|
|
849 | |
|
|
850 | if (! (Options & Opt_jumpScroll) |
|
|
851 | || (refresh_count >= (refresh_limit * (TermWin.nrow - 1)))) |
|
|
852 | { |
|
|
853 | refreshnow = true; |
876 | refreshnow = true; |
854 | flag = false; |
877 | flag = false; |
855 | ch = NOCHAR; |
878 | ch = NOCHAR; |
856 | break; |
879 | break; |
857 | } |
880 | } |
858 | |
881 | |
859 | // scr_add_lines only works for nlines < TermWin.nrow - 1. |
882 | // scr_add_lines only works for nlines < TermWin.nrow - 1. |
860 | if (nlines >= TermWin.nrow - 1) |
883 | if (nlines >= TermWin.nrow - 1) |
861 | { |
884 | { |
862 | scr_add_lines (buf, nlines, str - buf); |
885 | scr_add_lines (buf, nlines, str - buf); |
863 | nlines = 0; |
886 | nlines = 0; |
864 | str = buf; |
887 | str = buf; |
865 | } |
|
|
866 | } |
|
|
867 | |
|
|
868 | if (str >= buf + BUFSIZ) |
|
|
869 | { |
|
|
870 | ch = NOCHAR; |
|
|
871 | break; |
|
|
872 | } |
|
|
873 | } |
888 | } |
874 | } |
889 | } |
875 | |
890 | |
876 | scr_add_lines (buf, nlines, str - buf); |
891 | if (str >= buf + BUFSIZ) |
877 | |
|
|
878 | /* |
|
|
879 | * If there have been a lot of new lines, then update the screen |
|
|
880 | * What the heck I'll cheat and only refresh less than every page-full. |
|
|
881 | * the number of pages between refreshes is refresh_limit, which |
|
|
882 | * is incremented here because we must be doing flat-out scrolling. |
|
|
883 | * |
|
|
884 | * refreshing should be correct for small scrolls, because of the |
|
|
885 | * time-out |
|
|
886 | */ |
|
|
887 | if (refreshnow) |
|
|
888 | { |
892 | { |
889 | if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD) |
893 | ch = NOCHAR; |
890 | refresh_limit++; |
894 | break; |
891 | |
|
|
892 | scr_refresh (refresh_type); |
|
|
893 | } |
895 | } |
894 | |
|
|
895 | } |
|
|
896 | else |
|
|
897 | { |
|
|
898 | switch (ch) |
|
|
899 | { |
|
|
900 | default: |
|
|
901 | process_nonprinting (ch); |
|
|
902 | break; |
|
|
903 | case C0_ESC: /* escape char */ |
|
|
904 | process_escape_seq (); |
|
|
905 | break; |
|
|
906 | /*case 0x9b: */ /* CSI */ |
|
|
907 | /* process_csi_seq (); */ |
|
|
908 | } |
|
|
909 | |
|
|
910 | ch = NOCHAR; |
|
|
911 | } |
896 | } |
912 | } |
897 | } |
|
|
898 | |
|
|
899 | scr_add_lines (buf, nlines, str - buf); |
|
|
900 | |
|
|
901 | /* |
|
|
902 | * If there have been a lot of new lines, then update the screen |
|
|
903 | * What the heck I'll cheat and only refresh less than every page-full. |
|
|
904 | * the number of pages between refreshes is refresh_limit, which |
|
|
905 | * is incremented here because we must be doing flat-out scrolling. |
|
|
906 | * |
|
|
907 | * refreshing should be correct for small scrolls, because of the |
|
|
908 | * time-out |
|
|
909 | */ |
|
|
910 | if (refreshnow) |
|
|
911 | { |
|
|
912 | if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD) |
|
|
913 | refresh_limit++; |
|
|
914 | |
|
|
915 | scr_refresh (refresh_type); |
|
|
916 | } |
|
|
917 | |
|
|
918 | } |
|
|
919 | else |
913 | } |
920 | { |
|
|
921 | switch (ch) |
|
|
922 | { |
|
|
923 | default: |
|
|
924 | process_nonprinting (ch); |
|
|
925 | break; |
|
|
926 | case C0_ESC: /* escape char */ |
|
|
927 | process_escape_seq (); |
|
|
928 | break; |
|
|
929 | /*case 0x9b: */ /* CSI */ |
|
|
930 | /* process_csi_seq (); */ |
|
|
931 | } |
|
|
932 | |
|
|
933 | ch = NOCHAR; |
|
|
934 | } |
914 | } |
935 | } |
|
|
936 | |
|
|
937 | return flag; |
915 | } |
938 | } |
916 | |
939 | |
917 | // read the next character, currently handles UTF-8 |
940 | // read the next character, currently handles UTF-8 |
918 | // will probably handle all sorts of other stuff in the future |
941 | // will probably handle all sorts of other stuff in the future |
919 | uint32_t |
942 | uint32_t |
… | |
… | |
997 | pointer_blank (); |
1020 | pointer_blank (); |
998 | } |
1021 | } |
999 | #endif |
1022 | #endif |
1000 | |
1023 | |
1001 | void |
1024 | void |
1002 | rxvt_term::mouse_report (const XButtonEvent &ev) |
1025 | rxvt_term::mouse_report (XButtonEvent &ev) |
1003 | { |
1026 | { |
1004 | int button_number, key_state = 0; |
1027 | int button_number, key_state = 0; |
1005 | int x, y; |
1028 | int x, y; |
1006 | |
1029 | |
1007 | x = ev.x; |
1030 | x = ev.x; |
1008 | y = ev.y; |
1031 | y = ev.y; |
1009 | pixel_position (&x, &y); |
1032 | pixel_position (&x, &y); |
1010 | |
1033 | |
… | |
… | |
1415 | pointer_unblank (); |
1438 | pointer_unblank (); |
1416 | #endif |
1439 | #endif |
1417 | #if MENUBAR |
1440 | #if MENUBAR |
1418 | if (isMenuBarWindow (ev.xany.window)) |
1441 | if (isMenuBarWindow (ev.xany.window)) |
1419 | { |
1442 | { |
1420 | menubar_control (& (ev.xbutton)); |
1443 | menubar_control (ev.xbutton); |
1421 | break; |
1444 | break; |
1422 | } |
1445 | } |
1423 | #endif |
1446 | #endif |
1424 | if ((PrivateModes & PrivMode_mouse_report) && ! (bypass_keystate)) |
1447 | if ((PrivateModes & PrivMode_mouse_report) && ! (bypass_keystate)) |
1425 | break; |
1448 | break; |
… | |
… | |
1554 | #endif |
1577 | #endif |
1555 | } |
1578 | } |
1556 | } |
1579 | } |
1557 | |
1580 | |
1558 | void |
1581 | void |
1559 | rxvt_term::button_press (const XButtonEvent &ev) |
1582 | rxvt_term::button_press (XButtonEvent &ev) |
1560 | { |
1583 | { |
1561 | int reportmode = 0, clickintime; |
1584 | int reportmode = 0, clickintime; |
1562 | |
1585 | |
1563 | bypass_keystate = ev.state & (ModMetaMask | ShiftMask); |
1586 | bypass_keystate = ev.state & (ModMetaMask | ShiftMask); |
1564 | if (!bypass_keystate) |
1587 | if (!bypass_keystate) |
… | |
… | |
1792 | menubar_control (ev); |
1815 | menubar_control (ev); |
1793 | #endif |
1816 | #endif |
1794 | } |
1817 | } |
1795 | |
1818 | |
1796 | void |
1819 | void |
1797 | rxvt_term::button_release (const XButtonEvent &ev) |
1820 | rxvt_term::button_release (XButtonEvent &ev) |
1798 | { |
1821 | { |
1799 | int reportmode = 0; |
1822 | int reportmode = 0; |
1800 | |
1823 | |
1801 | csrO = 0; /* reset csr Offset */ |
1824 | csrO = 0; /* reset csr Offset */ |
1802 | if (!bypass_keystate) |
1825 | if (!bypass_keystate) |
… | |
… | |
2694 | break; |
2717 | break; |
2695 | #endif |
2718 | #endif |
2696 | case 8: /* unofficial extension */ |
2719 | case 8: /* unofficial extension */ |
2697 | xterm_seq (XTerm_title, APL_NAME "-" VERSION, CHAR_ST); |
2720 | xterm_seq (XTerm_title, APL_NAME "-" VERSION, CHAR_ST); |
2698 | break; |
2721 | break; |
2699 | |
|
|
2700 | case XTerm_locale: /* unofficial extension */ |
|
|
2701 | tt_printf ("%-.250s\n", locale); |
|
|
2702 | break; |
|
|
2703 | } |
2722 | } |
2704 | break; |
2723 | break; |
2705 | |
2724 | |
2706 | case CSI_TBC: /* 8.3.155: (0) TABULATION CLEAR */ |
2725 | case CSI_TBC: /* 8.3.155: (0) TABULATION CLEAR */ |
2707 | switch (arg[0]) |
2726 | switch (arg[0]) |
… | |
… | |
3079 | break; |
3098 | break; |
3080 | case XTerm_font: |
3099 | case XTerm_font: |
3081 | change_font (str); |
3100 | change_font (str); |
3082 | break; |
3101 | break; |
3083 | case XTerm_locale: |
3102 | case XTerm_locale: |
|
|
3103 | if (str[0] == '?' && !str[1]) |
|
|
3104 | tt_printf ("%-.250s\n", locale); |
|
|
3105 | else |
|
|
3106 | { |
3084 | set_locale (str); |
3107 | set_locale (str); |
3085 | im_cb (); |
3108 | im_cb (); |
|
|
3109 | |
|
|
3110 | // TODO: call selection_make with the right values set |
|
|
3111 | // to re-fresh the selection. |
|
|
3112 | if (display->selection_owner == this) |
|
|
3113 | display->set_selection_owner (0); |
|
|
3114 | } |
3086 | break; |
3115 | break; |
3087 | #if 0 |
3116 | #if 0 |
3088 | case XTerm_dumpscreen: /* no error notices */ |
3117 | case XTerm_dumpscreen: /* no error notices */ |
3089 | { |
3118 | { |
3090 | int fd; |
3119 | int fd; |