diff options
Diffstat (limited to 'im.h')
-rw-r--r-- | im.h | 158 |
1 files changed, 132 insertions, 26 deletions
@@ -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); +} |