aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-01-29 23:42:43 +1000
committerDavid Walter Seikel2014-01-29 23:42:43 +1000
commit4ccfa7a186862f1b1f0bddc9f016f9948d5a510b (patch)
tree195be0241bcf9d339219fcd1cd2f8211ab6dc82e
parentSome clean ups, mostly to do with ^C now working. (diff)
downloadboxes-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.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/boxes.c b/boxes.c
index 05bd518..bc95825 100644
--- a/boxes.c
+++ b/boxes.c
@@ -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
37signals. If we use poll or select, we get the race condition from the
38signals, which can cause crashes. Poll is preferable over select in
39general. So I was using poll originally. However, ppoll is Linux
40specific, and worse, needs to define the following swear words...
41*/
42#define _GNU_SOURCE
36#include "toys.h" 43#include "toys.h"
37 44
38GLOBALS( 45GLOBALS(
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
660static box *currentBox; 666static box *currentBox;
661static view *commandLine; 667static view *commandLine;
662static int commandMode; 668static int commandMode;
663 669static /*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[] =
1868void editLine(long extra, void (*lineChar)(long extra, char *buffer), struct keyCommand * (*lineCommand)(long extra, char *command)) 1874void 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
2796static void handleSignals(int signo)
2797{
2798 sigWinch = 1;
2799}
2770 2800
2771void boxes_main(void) 2801void 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