diff options
author | David Walter Seikel | 2014-01-29 23:42:43 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-01-29 23:42:43 +1000 |
commit | 4ccfa7a186862f1b1f0bddc9f016f9948d5a510b (patch) | |
tree | 195be0241bcf9d339219fcd1cd2f8211ab6dc82e | |
parent | Some clean ups, mostly to do with ^C now working. (diff) | |
download | boxes-4ccfa7a186862f1b1f0bddc9f016f9948d5a510b.zip boxes-4ccfa7a186862f1b1f0bddc9f016f9948d5a510b.tar.gz boxes-4ccfa7a186862f1b1f0bddc9f016f9948d5a510b.tar.bz2 boxes-4ccfa7a186862f1b1f0bddc9f016f9948d5a510b.tar.xz |
SIGWINCH, the final piece of the terminal resizing puzzle.
Except for the "not updating everything properly" bug.
-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 | ||