summaryrefslogtreecommitdiff
path: root/im.h
diff options
context:
space:
mode:
Diffstat (limited to 'im.h')
-rw-r--r--im.h158
1 files changed, 132 insertions, 26 deletions
diff --git a/im.h b/im.h
index 12d8ac8..dc171a8 100644
--- a/im.h
+++ b/im.h
@@ -1,21 +1,52 @@
+//Input Method Functions and Variables
//#include "imtable.h"
#include "boshiamy.h"
#define IM_BUFFER_LEN 32
+#define IM_PREVIEW 1
+#define IM_PREVIEW_ENTRIES 6
+#define IM_PREVIEW_WIDTH 4*IM_PREVIEW_ENTRIES
#define ENTER_KEY 0x0D
#define BACKSPACE_KEY 0x7F
-//#define BACKSPACE_KEY '+'
//setting it to the actual escape character interferes with arrow keys and
//whatnot
//#define ESCAPE_KEY 0x1B
#define ESCAPE_KEY '`'
//Vertical Tab Ctrl+K
#define TOGGLE_KEY 0x0B
+#define IM_KEY_RANGE_LEN 7
+//Array of Input method key ranges(inclusive) seperate from the above
+char im_key_ranges[IM_KEY_RANGE_LEN][2] = {
+ {'a','z'},
+ {'0','9'},
+ {' ',' '},
+ {',',','},
+ {'.','.'},
+ {'[','['},
+ {']',']'},
+};
+int is_im_key(char input) {
+ for (int i = 0; i < IM_KEY_RANGE_LEN; i++) {
+ if (input >= im_key_ranges[i][0] && input <= im_key_ranges[i][1]) {
+ return 1;
+ }
+ }
+ return 0;
+}
char im_buffer[IM_BUFFER_LEN+1];
char im_buffer_pos = 0;
int im_on = 1;
+//clears the im buffer
+void clear_im_buffer() {
+ im_buffer[0] = 0;
+ im_buffer_pos = 0;
+}
//recursive search, returns -1 on failure
-//searches from [start, end)
-int im_search(char * input, int start, int end) {
+//searches from [start, end),
+//can limit itself to n bytes, if n=0, use IM_TABLE_ENTRY_LEN
+int im_search(char * input, int start, int end, int n) {
+ if (n == 0) {
+ n = IM_TABLE_ENTRY_LEN;
+ }
// 0 width search
if (end <= start) {
return -1;
@@ -23,7 +54,7 @@ int im_search(char * input, int start, int end) {
//test for middle, works even for 1 width middle=start
int middle = start + (end-start)/2;
//printf("testing:%s\n",im_table[middle][0]);
- int test = strncmp(im_table[middle][0], input, IM_TABLE_ENTRY_LEN);
+ int test = strncmp(im_table[middle][0], input, n);
if (test == 0) {
return middle;
}
@@ -39,30 +70,32 @@ int im_search(char * input, int start, int end) {
return 0;
} else {
if (test > 0) {
- return im_search(input,start,middle);
+ return im_search(input,start,middle,n);
} else {
- return im_search(input,middle,end);
+ return im_search(input,middle,end,n);
}
}
}
-//returns output len, since we want to be able to handle null bytes as well
+//update_im_state is fed input characters 1 at a time, and gives 0 to
+//IM_BUFFER_LEN output characters.
+//returns output len
int update_im_state(char input, char * output) {
if (input == TOGGLE_KEY) {
im_on = !im_on;
//clears the im buffer if its toggling off
if (!im_on) {
- im_buffer[0] = 0;
- im_buffer_pos = 0;
+ clear_im_buffer();
}
}
- //just exit if the im is off
+ //just passthrough if the im is off
if (!im_on) {
output[0] = input;
output[1] = 0;
return 1;
}
- if ( ('a' <= input && input <= 'z')||('0' <= input && input <= '9') ||(input == ' ') || (input == ',') || (input == '.')) {
+ if ( is_im_key(input) ) {
+ //check if there's enough room in the im buffer
if ( (im_buffer_pos < IM_BUFFER_LEN) && (im_buffer_pos < IM_TABLE_ENTRY_LEN) ){
im_buffer[im_buffer_pos] = input;
im_buffer_pos++;
@@ -74,13 +107,14 @@ int update_im_state(char input, char * output) {
return 1;
}
//if there's a match return it
- int im_entry = im_search(im_buffer, 0, IM_TABLE_LEN);
+ int im_entry = im_search(im_buffer, 0, IM_TABLE_LEN, 0);
if (im_entry != -1) {
//clear the buffer
- im_buffer[0] = 0;
- im_buffer_pos = 0;
+ clear_im_buffer();
strncpy(output, im_table[im_entry][1], IM_TABLE_ENTRY_LEN);
return strlen(im_table[im_entry][1]);
+ } else {
+ return 0;
}
} else {
//these only do something if there's something in the buffer, otherwise
@@ -89,18 +123,15 @@ int update_im_state(char input, char * output) {
switch (input) {
//escape, cancels
case ESCAPE_KEY:
- im_buffer[0] = 0;
- im_buffer_pos = 0;
+ clear_im_buffer();
return 0;
break;
- //enter, enters the buffer
+ //enter, enters the buffer instead of sending it
+ //to im
case ENTER_KEY:
- for (int i = 0; i <im_buffer_pos; i++) {
- output[i] = im_buffer[i];
- }
- output[im_buffer_pos] = 0;
+ strncpy(output, im_buffer, IM_BUFFER_LEN);
int tmp = im_buffer_pos;
- im_buffer_pos = 0;
+ clear_im_buffer();
return tmp;
break;
//backspace
@@ -113,10 +144,85 @@ int update_im_state(char input, char * output) {
break;
}
}
- //default behavior of passthrough
- output[0] = input;
- output[1] = 0;
- return 1;
}
+ //default behavior of passthrough
+ output[0] = input;
+ output[1] = 0;
+ return 1;
}
+//prints im preview, assumes im_disp already moved it to the proper location
+void im_preview(int fd, int trows, int tcols) {
+ //searches for any im entries that match the im buffer, up to the
+ //im_buffer length, because it's branching search it's not guaranteed to
+ //be the first entry in the table that matches
+ int first_entry = im_search(im_buffer, 0, IM_TABLE_LEN, im_buffer_pos);
+ if (first_entry == -1) {
+ return;
+ }
+ //keeps iterating until it finds the first entry in the table that
+ //matches
+ for (int i = first_entry; i>0 && i < IM_TABLE_LEN && (!strncmp(im_table[i][0],im_buffer,im_buffer_pos)); i--) {
+ first_entry = i;
+ }
+ //preview buffer, each utf8 char could be up to 4 bytes, each new entry
+ //catted on could be IM_TABLE_ENTRY_LEN*2 before next detection in loop,
+ //so that + 1 margin for null byte
+ char preview_buffer[IM_PREVIEW_ENTRIES*IM_TABLE_ENTRY_LEN*2+1] = "";
+ //tracks how many entries we've added to the buffer so far
+ int k = 0;
+ for (int j = first_entry; j> 0 && j < IM_TABLE_LEN && (!strncmp(im_table[j][0],im_buffer,im_buffer_pos)); j++) {
+ if (k >= IM_PREVIEW_ENTRIES) {
+ break;
+ }
+ //even if the string is the same as im_buffer_pos, it will point
+ //to a null pointer, which is treated as empty
+ strncat(preview_buffer,&(im_table[j][0][im_buffer_pos]),1);
+ strncat(preview_buffer,":",1);
+ //assuming that each output is only 2 characters wide display
+ strncat(preview_buffer,im_table[j][1], IM_TABLE_ENTRY_LEN);
+ k++;
+ }
+ //writes the preview
+ write(fd,preview_buffer,strlen(preview_buffer));
+}
+//Displays the IM on the bottom line, input is the number of actual physical
+//rows and columns on the terminal descibed by fd
+void disp_im(int fd, int trows, int tcols) {
+ //generates the position escape sequence for the bottom left corner
+ //4 spaces for the im indicator +1 for automargin
+ int im_col = tcols - IM_TABLE_ENTRY_LEN - 4 - 1;
+ if (IM_PREVIEW) {
+ im_col = im_col - IM_PREVIEW_WIDTH;
+ }
+ char pos_str[32] = "";
+ int l = snprintf(pos_str, 32, "\033[%d;%df", trows, im_col);
+
+ write(fd,"\0337",2); //saves previous cursor position
+ write(fd, pos_str,l);
+ write(fd,"\033[7m",4); //invert video
+
+ //overwrite what was there previously, this works out to leaving 1 space
+ //at the end for automargin b/c you need (tcols-im_col)+1 spaces, but
+ //want -1 space so it doesn't write to the last character position
+ write(fd," ",
+ tcols-im_col);
+
+ write(fd, pos_str,l);
+ //im mode indicator
+ if (im_on) {
+ write(fd,"漢[",4);
+ } else {
+ write(fd,"英[",4);
+ }
+ //actual buffer
+ write(fd,im_buffer,im_buffer_pos);
+ write(fd,"]",1);
+ //if preview is set do that
+ if (IM_PREVIEW) {
+ im_preview(fd, trows, tcols);
+ }
+ //restore cursor pos and attrbutes
+ write(fd,"\033[0m",4);
+ write(fd,"\0338",2);
+}