diff options
Diffstat (limited to '')
| -rw-r--r-- | boxes.c | 60 |
1 files changed, 47 insertions, 13 deletions
| @@ -33,14 +33,20 @@ config BOXES | |||
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /* We need to catch some signals, coz some things are only sent as | ||
| 37 | signals. If we use poll or select, we get the race condition from the | ||
| 38 | signals, which can cause crashes. Poll is preferable over select in | ||
| 39 | general. So I was using poll originally. However, ppoll is Linux | ||
| 40 | specific, and worse, needs to define the following swear words... | ||
| 41 | */ | ||
| 42 | #define _GNU_SOURCE | ||
| 36 | #include "toys.h" | 43 | #include "toys.h" |
| 37 | 44 | ||
| 38 | GLOBALS( | 45 | GLOBALS( |
| 39 | char *mode; | 46 | char *mode; |
| 40 | long h, w; | 47 | long h, w; |
| 41 | // TODO - actually, these should be globals in the library, and leave this buffer alone. | 48 | // TODO - actually, these should be globals in the library, and leave this buffer alone. |
| 42 | int stillRunning; | 49 | int stillRunning, overWriteMode; |
| 43 | int overWriteMode; | ||
| 44 | ) | 50 | ) |
| 45 | 51 | ||
| 46 | #define TT this.boxes | 52 | #define TT this.boxes |
| @@ -660,7 +666,7 @@ static box *rootBox; // Parent of the rest of the boxes, or the only box. Alway | |||
| 660 | static box *currentBox; | 666 | static box *currentBox; |
| 661 | static view *commandLine; | 667 | static view *commandLine; |
| 662 | static int commandMode; | 668 | static int commandMode; |
| 663 | 669 | static /*sigatomic_t*/ volatile int sigWinch; | |
| 664 | 670 | ||
| 665 | #define MEM_SIZE 128 // Chunk size for line memory allocation. | 671 | #define MEM_SIZE 128 // Chunk size for line memory allocation. |
| 666 | 672 | ||
| @@ -1836,7 +1842,7 @@ char *termSize(long extra, int *params, int count) | |||
| 1836 | // TODO - Double check what the maximum F3 variations can be. | 1842 | // TODO - Double check what the maximum F3 variations can be. |
| 1837 | if ((2 == count) && (8 < r) && (8 < c)) | 1843 | if ((2 == count) && (8 < r) && (8 < c)) |
| 1838 | { | 1844 | { |
| 1839 | // TODO - The change is not being propogated to everything. | 1845 | // FIXME - The change is not being propogated to everything properly. |
| 1840 | sizeViewToBox(rootBox, rootBox->X, rootBox->Y, c, r - 1); | 1846 | sizeViewToBox(rootBox, rootBox->X, rootBox->Y, c, r - 1); |
| 1841 | calcBoxes(rootBox); | 1847 | calcBoxes(rootBox); |
| 1842 | drawBoxes(rootBox); | 1848 | drawBoxes(rootBox); |
| @@ -1868,6 +1874,9 @@ struct CSI CSI_terminators[] = | |||
| 1868 | void editLine(long extra, void (*lineChar)(long extra, char *buffer), struct keyCommand * (*lineCommand)(long extra, char *command)) | 1874 | void editLine(long extra, void (*lineChar)(long extra, char *buffer), struct keyCommand * (*lineCommand)(long extra, char *command)) |
| 1869 | { | 1875 | { |
| 1870 | struct pollfd pollfds[1]; | 1876 | struct pollfd pollfds[1]; |
| 1877 | struct timespec timeout; | ||
| 1878 | sigset_t signalMask; | ||
| 1879 | |||
| 1871 | // Get the initial command set. | 1880 | // Get the initial command set. |
| 1872 | struct keyCommand *ourKeys = lineCommand(extra, ""); | 1881 | struct keyCommand *ourKeys = lineCommand(extra, ""); |
| 1873 | char buffer[20], command[20], csFinal[8]; | 1882 | char buffer[20], command[20], csFinal[8]; |
| @@ -1879,6 +1888,9 @@ void editLine(long extra, void (*lineChar)(long extra, char *buffer), struct key | |||
| 1879 | buffer[0] = 0; | 1888 | buffer[0] = 0; |
| 1880 | command[0] = 0; | 1889 | command[0] = 0; |
| 1881 | 1890 | ||
| 1891 | sigemptyset(&signalMask); | ||
| 1892 | sigaddset(&signalMask, SIGWINCH); | ||
| 1893 | |||
| 1882 | // TODO - OS buffered keys might be a problem, but we can't do the usual timestamp filter for now. | 1894 | // TODO - OS buffered keys might be a problem, but we can't do the usual timestamp filter for now. |
| 1883 | TT.stillRunning = 1; | 1895 | TT.stillRunning = 1; |
| 1884 | while (TT.stillRunning) | 1896 | while (TT.stillRunning) |
| @@ -1894,17 +1906,31 @@ void editLine(long extra, void (*lineChar)(long extra, char *buffer), struct key | |||
| 1894 | csIndex = 0; | 1906 | csIndex = 0; |
| 1895 | } | 1907 | } |
| 1896 | 1908 | ||
| 1897 | // Apparently it's more portable to reset this each time. | 1909 | // Apparently it's more portable to reset these each time. |
| 1898 | memset(pollfds, 0, pollcount * sizeof(struct pollfd)); | 1910 | memset(pollfds, 0, pollcount * sizeof(struct pollfd)); |
| 1899 | pollfds[0].events = POLLIN; | 1911 | pollfds[0].events = POLLIN; pollfds[0].fd = 0; |
| 1900 | pollfds[0].fd = 0; | 1912 | timeout.tv_sec = 0; timeout.tv_nsec = 100000000; // One tenth of a second. |
| 1901 | 1913 | ||
| 1902 | // TODO - A bit unstable at the moment, something makes it go into a horrid CPU eating edit line flicker mode sometimes. And / or vi mode can crash on exit (stack smash). | 1914 | // TODO - A bit unstable at the moment, something makes it go into a horrid CPU eating edit line flicker mode sometimes. And / or vi mode can crash on exit (stack smash). |
| 1903 | // This might be fixed now. | 1915 | // This might be fixed now. |
| 1904 | 1916 | ||
| 1917 | // We got a "terminal size changed" signal, ask the terminal how big it is now. | ||
| 1918 | if (sigWinch) | ||
| 1919 | { | ||
| 1920 | // Send - save cursor position, down 999, right 999, request cursor position, restore cursor position. | ||
| 1921 | printf("\x1B[s\x1B[999C\x1B[999B\x1B[6n\x1B[u"); | ||
| 1922 | fflush(stdout); | ||
| 1923 | sigWinch = 0; | ||
| 1924 | } | ||
| 1925 | |||
| 1905 | // TODO - Should only ask for a time out after we get an Escape. | 1926 | // TODO - Should only ask for a time out after we get an Escape. |
| 1906 | p = poll(pollfds, pollcount, 100); // Timeout of one tenth of a second (100). | 1927 | p = ppoll(pollfds, pollcount, &timeout, &signalMask); |
| 1907 | if (0 > p) perror_exit("poll"); | 1928 | if (0 > p) |
| 1929 | { | ||
| 1930 | if (EINTR == errno) | ||
| 1931 | continue; | ||
| 1932 | perror_exit("poll"); | ||
| 1933 | } | ||
| 1908 | if (0 == p) // A timeout, trigger a time event. | 1934 | if (0 == p) // A timeout, trigger a time event. |
| 1909 | { | 1935 | { |
| 1910 | if ((1 == index) && ('\x1B' == buffer[0])) | 1936 | if ((1 == index) && ('\x1B' == buffer[0])) |
| @@ -2767,6 +2793,10 @@ struct context simpleVi = | |||
| 2767 | // TODO - have any unrecognised escape key sequence start up a new box (split one) to show the "show keys" content. | 2793 | // TODO - have any unrecognised escape key sequence start up a new box (split one) to show the "show keys" content. |
| 2768 | // That just adds each "Key is X" to the end of the content, and allows scrolling, as well as switching between other boxes. | 2794 | // That just adds each "Key is X" to the end of the content, and allows scrolling, as well as switching between other boxes. |
| 2769 | 2795 | ||
| 2796 | static void handleSignals(int signo) | ||
| 2797 | { | ||
| 2798 | sigWinch = 1; | ||
| 2799 | } | ||
| 2770 | 2800 | ||
| 2771 | void boxes_main(void) | 2801 | void boxes_main(void) |
| 2772 | { | 2802 | { |
| @@ -2774,6 +2804,7 @@ void boxes_main(void) | |||
| 2774 | struct termios termio, oldtermio; | 2804 | struct termios termio, oldtermio; |
| 2775 | char *prompt = "Enter a command : "; | 2805 | char *prompt = "Enter a command : "; |
| 2776 | unsigned W = 80, H = 24; | 2806 | unsigned W = 80, H = 24; |
| 2807 | struct sigaction sigAction, oldSigActions; | ||
| 2777 | 2808 | ||
| 2778 | // For testing purposes, figure out which context we use. When this gets real, the toybox multiplexer will sort this out for us instead. | 2809 | // For testing purposes, figure out which context we use. When this gets real, the toybox multiplexer will sort this out for us instead. |
| 2779 | if (toys.optflags & FLAG_m) | 2810 | if (toys.optflags & FLAG_m) |
| @@ -2854,10 +2885,11 @@ void boxes_main(void) | |||
| 2854 | termio.c_cc[VMIN]=1; | 2885 | termio.c_cc[VMIN]=1; |
| 2855 | tcsetattr(0, TCSANOW, &termio); | 2886 | tcsetattr(0, TCSANOW, &termio); |
| 2856 | 2887 | ||
| 2857 | // TODO - set up a handler for SIGWINCH to find out when the terminal has been resized. | 2888 | // Terminals send the SIGWINCH signal when they resize. |
| 2858 | // TODO - send "\x1B[s\x1B[999C\x1B[999B\x1B[6n\x1B[u" | 2889 | memset(&sigAction, 0, sizeof(sigAction)); |
| 2859 | // Which breaks down to - save cursor position, down 999, right 999, request cursor position (DSR), restore cursor position. | 2890 | sigAction.sa_handler = handleSignals; |
| 2860 | // Already got the stub for dealing with the response. | 2891 | sigAction.sa_flags = SA_RESTART;// Useless since we are using poll. |
| 2892 | if (sigaction(SIGWINCH, &sigAction, &oldSigActions)) perror_exit("can't set signal handler SIGWINCH"); | ||
| 2861 | terminal_size(&W, &H); | 2893 | terminal_size(&W, &H); |
| 2862 | if (toys.optflags & FLAG_w) | 2894 | if (toys.optflags & FLAG_w) |
| 2863 | W = TT.w; | 2895 | W = TT.w; |
| @@ -2902,6 +2934,8 @@ void boxes_main(void) | |||
| 2902 | 2934 | ||
| 2903 | // TODO - Should remember to turn off mouse reporting when we leave. | 2935 | // TODO - Should remember to turn off mouse reporting when we leave. |
| 2904 | 2936 | ||
| 2937 | sigaction(SIGWINCH, &oldSigActions, NULL); | ||
| 2938 | |||
| 2905 | // Restore the old terminal settings. | 2939 | // Restore the old terminal settings. |
| 2906 | tcsetattr(0, TCSANOW, &oldtermio); | 2940 | tcsetattr(0, TCSANOW, &oldtermio); |
| 2907 | 2941 | ||
