summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--escape.h133
-rw-r--r--ptyim.c35
3 files changed, 158 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index 4806a5d..2b3d7ba 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-ptyim: ptyim.c im.h boshiamy.h
+ptyim: ptyim.c im.h escape.h boshiamy.h
gcc ptyim.c -o ptyim
install: ptyim
cp ptyim /usr/bin/ptyim
diff --git a/escape.h b/escape.h
new file mode 100644
index 0000000..8b5f0dd
--- /dev/null
+++ b/escape.h
@@ -0,0 +1,133 @@
+//Types of ANSI Escape Sequences
+
+//C0 [0x07-0x0A|0x0C-0x0D|0x1B]
+//C1/Fe [ESC][0x40-0x5F]
+// technically can be represented in 1 byte w/ bytes above 0x80 but
+// unimplemented b/c of unicode
+// STring Terminator ESC \
+//CSI (ESC\[|0x9B)[0-9:;<=>?]*[!"#$%&'()*+,-./]*[&A-Z[\]^_`a-z{|}~]
+//OSC (ESC\]|0x9D).*(0x9C|0x1B 0x5C)
+//OCS (ESCP|0x90).*(0x9C|0x1B 0x5C)
+//Fs ESC[0x60-0x7E]
+//nF ESC[0x20-02F]*[0x30-0x7E]
+//Fp ESC[0x30-0x3F] save and clear
+
+//last read key
+enum esc_state {
+ //C0 except BEL or ESC, \n ,\r and \f
+ C0,
+ ESC,
+ CSI_START,
+ CSI_MID,
+ CSI_END,
+ //OSC, DCS, PM APC etc ST terminted C1,
+ C1_START,
+ ST,
+ nF_START,
+ nF_END,
+ //other fixed elngth C1, Fs,
+ C1,
+ //save and clear
+ DECSC,
+ DECRC,
+ NORMAL,
+};
+//global stdin -> pty ESC state
+enum esc_state in_state = NORMAL;
+//global pty -> stdout ESC state
+enum esc_state out_state = NORMAL;
+
+//c0 c1 c2 osc, sf nF sequences
+
+//also ESC 7 and ESC 8 up down bit
+//have a semaphore and above lock, IM will draw if available when input updates
+//or if some time has passed since output has been written
+
+enum esc_state update_esc_state(char * buff,unsigned int buff_len, enum esc_state state) {
+ for (int i = 0; i < buff_len; i++) {
+ char c = buff[i];
+ switch (state) {
+ case CSI_END:
+ case ST:
+ case nF_END:
+ case C0:
+ case C1:
+ case DECSC:
+ case DECRC:
+ //all the sequences that have ended don't have an end
+ //and default to normal
+ case NORMAL:
+ if (c >= 0x08 && c <= 0x0A) {
+ state = C0;
+ }
+ if (c == 0x1B) {
+ state = ESC;
+ } else {
+ //return to normal
+ state = NORMAL;
+ }
+ break;
+ case ESC:
+ //fix length C1
+ if (c == 'N' || c == 'O') {
+ state = C1;
+ }
+ else if (c == '[') {
+ state = CSI_START;
+ }
+ //ST terminated C1 OSC, DCS, SOS, PM, APC
+ else if (c == ']' || c =='P' || c == '^' || c == 'X' || c == '_') {
+ state = C1_START;
+ }
+ //nF
+ else if (c >= 0x20 && c <= 0x2F) {
+ state = nF_START;
+ }
+ else if (c == '\\') {
+ state - ST;
+ }
+ else if (c == '7') {
+ state = DECSC;
+ }
+ else if (c == '8') {
+ state = DECSC;
+ //deformed escape sequence
+ } else {
+ state = NORMAL;
+ }
+ break;
+ case C1_START:
+ if (c == 0x1B) {
+ state = ESC;
+ }
+ if (c == 0x9C) {
+ state = ST;
+ }
+ break;
+ case CSI_START:
+ case CSI_MID:
+ if (c >= 0x30 && c <= 0x3F) {
+ state = CSI_MID;
+ } else if (c >= 0x20 && c <= 0x2F) {
+ state = CSI_MID;
+ } else if (c >= 0x40 && c <= 0x7E) {
+ state = CSI_END;
+ } else {
+ //malformed CSI sequence
+ state = NORMAL;
+ }
+ break;
+ case nF_START:
+ if (c >= 0x20 && c <= 0x2F) {
+ state = nF_START;
+ } else if (c >= 0x30 && c <= 0x7E) {
+ state = nF_END;
+ //malformed nF sequence
+ } else {
+ state = NORMAL;
+ }
+ break;
+ }
+ }
+ return state;
+}
diff --git a/ptyim.c b/ptyim.c
index ab4ebe6..34fdbec 100644
--- a/ptyim.c
+++ b/ptyim.c
@@ -12,12 +12,15 @@
#include <signal.h>
#include <sys/prctl.h>
#include "im.h"
+#include "escape.h"
#define WRITE_BUFFER_LEN 128
//determines if the master process is running
int running = 1;
//hook for when the pty child process dies
void childhook(int a) {
running = 0;
+ //this way it exists even if the loop is waiting for 1 last read char
+ _exit(0);
}
//pty master and slave fd
int pty_slave = -1;
@@ -170,17 +173,27 @@ int main (int argc, char * argv[], char * envp[]) {
while (running) {
int rchars_read = read(STDIN_FILENO, read_buffer, 1);
if (rchars_read > 0) {
- //feeds the input char into the im state machine
- char input_buffer[IM_TABLE_ENTRY_LEN+1] = {0};
- int im_chars = update_im_state(read_buffer[0],
- input_buffer);
- //just in case it wasn't null terminated right
- input_buffer[im_chars] = 0;
- if (im_chars >0) {
- //writes the input into pty_master if
- //there was an output from the state
- //machine
- write(pty_master,input_buffer,im_chars);
+ //feeds input char into the escape state
+ //machine
+ in_state = update_esc_state(read_buffer, 1, in_state);
+ fprintf(stderr, "%c: %d\n", read_buffer[0],in_state);
+ //skips if the char was anything but
+ //normal
+ if (in_state == NORMAL) {
+ //feeds the input char into the im state machine
+ char input_buffer[IM_TABLE_ENTRY_LEN+1] = {0};
+ int im_chars = update_im_state(read_buffer[0],
+ input_buffer);
+ //just in case it wasn't null terminated right
+ input_buffer[im_chars] = 0;
+ if (im_chars >0) {
+ //writes the input into pty_master if
+ //there was an output from the state
+ //machine
+ write(pty_master,input_buffer,im_chars);
+ }
+ } else {
+ write(pty_master,read_buffer,1);
}
//any input update will lead to a disp_im update
disp_im(STDIN_FILENO, trows, tcols);