aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/boxes.c
diff options
context:
space:
mode:
Diffstat (limited to 'boxes.c')
-rw-r--r--boxes.c169
1 files changed, 61 insertions, 108 deletions
diff --git a/boxes.c b/boxes.c
index 7329469..d9b39b7 100644
--- a/boxes.c
+++ b/boxes.c
@@ -494,7 +494,7 @@ typedef struct _view view;
494 494
495typedef void (*boxFunction) (box *box); 495typedef void (*boxFunction) (box *box);
496typedef void (*eventHandler) (view *view); 496typedef void (*eventHandler) (view *view);
497typedef char *(*CSIhandler) (long extra, int *code, int count); 497typedef void (*CSIhandler) (long extra, int *code, int count);
498 498
499struct function 499struct function
500{ 500{
@@ -1786,37 +1786,7 @@ void nop(view *view)
1786} 1786}
1787 1787
1788 1788
1789static void lineChar(long extra, char *buffer) 1789static void termSize(long extra, int *params, int count)
1790{
1791 struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away.
1792
1793 // Coz things might change out from under us, find the current view.
1794 if (commandMode) view = commandLine;
1795 else view = currentBox->view;
1796
1797 // TODO - Should check for tabs to, and insert them.
1798 // Though better off having a function for that?
1799 mooshStrings(view->line, buffer, view->iX, 0, !TT.overWriteMode);
1800 view->oW = formatLine(view, view->line->line, &(view->output));
1801 moveCursorRelative(view, strlen(buffer), 0, 0, 0);
1802 updateLine(view);
1803}
1804
1805static struct keyCommand * lineCommand(long extra, char *sequence)
1806{
1807 struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away.
1808
1809 // Coz things might change out from under us, find the current view.
1810 if (commandMode) view = commandLine;
1811 else view = currentBox->view;
1812
1813 doCommand(view, sequence);
1814
1815 // This is using the currentBox instead of view, coz the command line keys are part of the box context now, not separate.
1816 return currentBox->view->content->context->modes[currentBox->view->mode].keys;
1817}
1818
1819char *termSize(long extra, int *params, int count)
1820{ 1790{
1821 struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. 1791 struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away.
1822 int r = params[0], c = params[1]; 1792 int r = params[0], c = params[1];
@@ -1840,8 +1810,6 @@ char *termSize(long extra, int *params, int count)
1840 else view = currentBox->view; 1810 else view = currentBox->view;
1841 updateLine(view); 1811 updateLine(view);
1842 } 1812 }
1843
1844 return NULL;
1845} 1813}
1846 1814
1847struct CSI 1815struct CSI
@@ -1856,21 +1824,54 @@ struct CSI CSI_terminators[] =
1856 {NULL, NULL} 1824 {NULL, NULL}
1857}; 1825};
1858 1826
1827static int handleKeySequence(long extra, char *sequence)
1828{
1829 struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away.
1830 struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys;
1831 int j;
1832
1833 // Coz things might change out from under us, find the current view.
1834 if (commandMode) view = commandLine;
1835 else view = currentBox->view;
1836
1837 // Search for a key sequence bound to a command.
1838 for (j = 0; commands[j].key; j++)
1839 {
1840 if (strcmp(commands[j].key, sequence) == 0)
1841 {
1842 doCommand(view, commands[j].command);
1843 return 1;
1844 }
1845 }
1846
1847 if ((0 == sequence[1]) && isprint(sequence[0])) // See if it's an ordinary key.
1848 {
1849 // TODO - Should check for tabs to, and insert them.
1850 // Though better off having a function for that?
1851 mooshStrings(view->line, sequence, view->iX, 0, !TT.overWriteMode);
1852 view->oW = formatLine(view, view->line->line, &(view->output));
1853 moveCursorRelative(view, strlen(sequence), 0, 0, 0);
1854 updateLine(view);
1855 return 1;
1856 }
1857
1858 return 0;
1859}
1860
1859// Basically this is the main loop. 1861// Basically this is the main loop.
1860 1862
1861// TODO - Unhandled complications - 1863// TODO - Unhandled complications -
1862// Less and more have the "ZZ" command, but nothing else seems to have multi ordinary character commands. 1864// Less and more have the "ZZ" command, but nothing else seems to have multi ordinary character commands.
1863 1865
1864void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct keyCommand * (*lineCommand)(long extra, char *sequence)) 1866void handle_keys(long extra, int (*handle_sequence)(long extra, char *sequence))
1865{ 1867{
1866 fd_set selectFds; 1868 fd_set selectFds;
1867 struct timespec timeout; 1869 struct timespec timeout;
1868 sigset_t signalMask; 1870 sigset_t signalMask;
1869 1871
1870 // Get the initial command set. 1872 // Get the initial command set.
1871 struct keyCommand *commands = lineCommand(extra, "");
1872 char buffer[20], sequence[20], csFinal[8]; 1873 char buffer[20], sequence[20], csFinal[8];
1873 int csi = 0, csCount = 0, csIndex = 0, csParams[8], buffIndex = 0; 1874 int buffIndex = 0;
1874// TODO - multiline editLine is an advanced feature. Editing boxes just moves the editLine up and down. 1875// TODO - multiline editLine is an advanced feature. Editing boxes just moves the editLine up and down.
1875// uint16_t h = 1; 1876// uint16_t h = 1;
1876// TODO - should check if it's at the top of the box, then grow it down instead of up if so. 1877// TODO - should check if it's at the top of the box, then grow it down instead of up if so.
@@ -1885,16 +1886,7 @@ void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct
1885 TT.stillRunning = 1; 1886 TT.stillRunning = 1;
1886 while (TT.stillRunning) 1887 while (TT.stillRunning)
1887 { 1888 {
1888 int j, p; 1889 int j, p, csi = 0;
1889 char *command = NULL;
1890
1891 if (0 == buffIndex)
1892 {
1893 buffer[0] = 0;
1894 csi = 0;
1895 csCount = 0;
1896 csIndex = 0;
1897 }
1898 1890
1899 // Apparently it's more portable to reset these each time. 1891 // Apparently it's more portable to reset these each time.
1900 FD_ZERO(&selectFds); 1892 FD_ZERO(&selectFds);
@@ -1913,7 +1905,7 @@ void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct
1913 sigWinch = 0; 1905 sigWinch = 0;
1914 } 1906 }
1915 1907
1916 // TODO - Should only ask for a time out after we get an Escape. 1908 // TODO - Should only ask for a time out after we get an Escape, or the user requested time ticks.
1917 // I wanted to use poll, but that would mean using ppoll, which is Linux only, and involves defining swear words to get it. 1909 // I wanted to use poll, but that would mean using ppoll, which is Linux only, and involves defining swear words to get it.
1918 p = pselect(0 + 1, &selectFds, NULL, NULL, &timeout, &signalMask); 1910 p = pselect(0 + 1, &selectFds, NULL, NULL, &timeout, &signalMask);
1919 if (0 > p) 1911 if (0 > p)
@@ -1922,18 +1914,18 @@ void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct
1922 continue; 1914 continue;
1923 perror_exit("poll"); 1915 perror_exit("poll");
1924 } 1916 }
1925 if (0 == p) // A timeout, trigger a time event. 1917 else if (0 == p) // A timeout, trigger a time event.
1926 { 1918 {
1927 if ((1 == buffIndex) && ('\x1B' == buffer[0])) 1919 if ((0 == buffer[1]) && ('\x1B' == buffer[0]))
1928 { 1920 {
1929 // After a short delay to check, this is a real Escape key, not part of an escape sequence, so deal with it. 1921 // After a short delay to check, this is a real Escape key, not part of an escape sequence, so deal with it.
1922 // TODO - so far the only uses of this have the escape at the start, but maybe a strcat is needed instead later?
1930 strcpy(sequence, "^["); 1923 strcpy(sequence, "^[");
1931 buffIndex = 0; 1924 buffer[0] = buffIndex = 0;
1932 } 1925 }
1933 // TODO - Send a timer event to lineCommand(). This wont be a precise timed event, but don't think we need one. 1926 // TODO - Call some sort of timer tick callback. This wont be a precise timed event, but don't think we need one.
1934 } 1927 }
1935 1928 else if ((0 < p) && FD_ISSET(0, &selectFds))
1936 if (FD_ISSET(0, &selectFds))
1937 { 1929 {
1938 // I am assuming that we get the input atomically, each multibyte key fits neatly into one read. 1930 // I am assuming that we get the input atomically, each multibyte key fits neatly into one read.
1939 // If that's not true (which is entirely likely), then we have to get complicated with circular buffers and stuff, or just one byte at a time. 1931 // If that's not true (which is entirely likely), then we have to get complicated with circular buffers and stuff, or just one byte at a time.
@@ -1963,7 +1955,7 @@ void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct
1963 fflush(stderr); 1955 fflush(stderr);
1964 buffIndex = 0; 1956 buffIndex = 0;
1965 } 1957 }
1966 else buffer[buffIndex] = 0; 1958 buffer[buffIndex] = 0;
1967 } 1959 }
1968 } 1960 }
1969 1961
@@ -1991,7 +1983,7 @@ void handle_keys(long extra, void (*lineChar)(long extra, char *buffer), struct
1991 if (strcmp(keys[j].code, buffer) == 0) 1983 if (strcmp(keys[j].code, buffer) == 0)
1992 { 1984 {
1993 strcat(sequence, keys[j].name); 1985 strcat(sequence, keys[j].name);
1994 buffIndex = 0; 1986 buffer[0] = buffIndex = 0;
1995 csi = 0; 1987 csi = 0;
1996 break; 1988 break;
1997 } 1989 }
@@ -2015,9 +2007,10 @@ TODO So abort the current CSI and start from scratch.
2015 */ 2007 */
2016 2008
2017 char *t; 2009 char *t;
2010 int csIndex = 1, csParams[8];
2018 2011
2019 csIndex = 1;
2020 csFinal[0] = 0; 2012 csFinal[0] = 0;
2013 p = 0;
2021 // Unspecified params default to a value that is command dependant. 2014 // Unspecified params default to a value that is command dependant.
2022 // However, they will never be negative, so we can use -1 to flag a default value. 2015 // However, they will never be negative, so we can use -1 to flag a default value.
2023 for (j = 0; j < (sizeof(csParams) / sizeof(*csParams)); j++) 2016 for (j = 0; j < (sizeof(csParams) / sizeof(*csParams)); j++)
@@ -2053,9 +2046,9 @@ TODO So abort the current CSI and start from scratch.
2053 if (';' != buffer[csIndex] || (!t)) 2046 if (';' != buffer[csIndex] || (!t))
2054 { 2047 {
2055 // TODO - Might be ":" in the number somewhere, but we are not expecting any in anything we do. 2048 // TODO - Might be ":" in the number somewhere, but we are not expecting any in anything we do.
2056 csParams[csCount] = atoi(&buffer[csIndex]); 2049 csParams[p] = atoi(&buffer[csIndex]);
2057 } 2050 }
2058 csCount++; 2051 p++;
2059 csIndex = j + 1; 2052 csIndex = j + 1;
2060 } 2053 }
2061 j++; 2054 j++;
@@ -2068,9 +2061,7 @@ TODO So abort the current CSI and start from scratch.
2068 { 2061 {
2069 if (strcmp(CSI_terminators[j].code, csFinal) == 0) 2062 if (strcmp(CSI_terminators[j].code, csFinal) == 0)
2070 { 2063 {
2071 t = CSI_terminators[j].func(extra, csParams, csCount); 2064 CSI_terminators[j].func(extra, csParams, p);
2072 if (t)
2073 strcpy(sequence, t);
2074 break; 2065 break;
2075 } 2066 }
2076 } 2067 }
@@ -2078,57 +2069,19 @@ TODO So abort the current CSI and start from scratch.
2078 2069
2079 csi = 0; 2070 csi = 0;
2080 // Wether or not it's a CSI we understand, it's been handled either here or in the key sequence scanning above. 2071 // Wether or not it's a CSI we understand, it's been handled either here or in the key sequence scanning above.
2081 buffIndex = 0; 2072 buffer[0] = buffIndex = 0;
2082 }
2083
2084 // See if it's an ordinary key,
2085 if ((1 == buffIndex) && isprint(buffer[0]))
2086 {
2087 // Here we want to run it through the command finder first, and only "insert" it if it's not a command.
2088 // Yes, this is duplicated below.
2089 for (j = 0; commands[j].key; j++)
2090 {
2091 if (strcmp(commands[j].key, buffer) == 0)
2092 {
2093 strcpy(sequence, buffer);
2094 command = sequence;
2095 break;
2096 }
2097 }
2098 if (NULL == command)
2099 {
2100 // If there's an outstanding sequence, add this to the end of it.
2101 if (sequence[0]) strcat(sequence, buffer);
2102 else lineChar(extra, buffer);
2103 }
2104 buffIndex = 0;
2105 } 2073 }
2106 2074
2107 // Search for a key sequence bound to a command. 2075 // Pass the result to the callback.
2108 if (sequence[0]) 2076 if (sequence[0] || buffer[0])
2109 { 2077 {
2110 if (sizeof(sequence) < (strlen(sequence) + 1)) 2078 char b[strlen(sequence) + strlen(buffer) + 1];
2111 {
2112 fprintf(stderr, "Full key sequence buffer - %s \n", sequence);
2113 fflush(stderr);
2114 sequence[0] = 0;
2115 }
2116 2079
2117 if (NULL == command) 2080 sprintf(b, "%s%s", sequence, buffer);
2118 { 2081 if (handle_sequence(extra, b))
2119 for (j = 0; commands[j].key; j++)
2120 {
2121 if (strcmp(commands[j].key, sequence) == 0)
2122 {
2123 command = commands[j].command;
2124 break;
2125 }
2126 }
2127 }
2128 if (command)
2129 { 2082 {
2130 commands = lineCommand(extra, command);
2131 sequence[0] = 0; 2083 sequence[0] = 0;
2084 buffer[0] = buffIndex = 0;
2132 } 2085 }
2133 } 2086 }
2134 } 2087 }
@@ -2908,7 +2861,7 @@ void boxes_main(void)
2908 updateLine(currentBox->view); 2861 updateLine(currentBox->view);
2909 2862
2910 // Run the main loop. 2863 // Run the main loop.
2911 handle_keys((long) currentBox->view, lineChar, lineCommand); 2864 handle_keys((long) currentBox->view, handleKeySequence);
2912 2865
2913 // TODO - Should remember to turn off mouse reporting when we leave. 2866 // TODO - Should remember to turn off mouse reporting when we leave.
2914 2867