static int ui_input_key(struct input *input) { switch (ui.key) { case KEY_LEFT: if (ui.mod == GLFW_MOD_CONTROL + GLFW_MOD_SHIFT) { input->q = prev_word(input->q, input->text); } else if (ui.mod == GLFW_MOD_CONTROL) { if (input->p != input->q) input->p = input->q = input->p < input->q ? input->p : input->q; else input->p = input->q = prev_word(input->q, input->text); } else if (ui.mod == GLFW_MOD_SHIFT) { if (input->q > input->text) input->q = prev_char(input->q, input->text); } else if (ui.mod == 0) { if (input->p != input->q) input->p = input->q = input->p < input->q ? input->p : input->q; else if (input->q > input->text) input->p = input->q = prev_char(input->q, input->text); } break; case KEY_RIGHT: if (ui.mod == GLFW_MOD_CONTROL + GLFW_MOD_SHIFT) { input->q = next_word(input->q, input->end); } else if (ui.mod == GLFW_MOD_CONTROL) { if (input->p != input->q) input->p = input->q = input->p > input->q ? input->p : input->q; else input->p = input->q = next_word(input->q, input->end); } else if (ui.mod == GLFW_MOD_SHIFT) { if (input->q < input->end) input->q = next_char(input->q); } else if (ui.mod == 0) { if (input->p != input->q) input->p = input->q = input->p > input->q ? input->p : input->q; else if (input->q < input->end) input->p = input->q = next_char(input->q); } break; case KEY_UP: case KEY_HOME: if (ui.mod == GLFW_MOD_CONTROL + GLFW_MOD_SHIFT) { input->q = input->text; } else if (ui.mod == GLFW_MOD_CONTROL) { input->p = input->q = input->text; } else if (ui.mod == GLFW_MOD_SHIFT) { input->q = input->text; } else if (ui.mod == 0) { input->p = input->q = input->text; } break; case KEY_DOWN: case KEY_END: if (ui.mod == GLFW_MOD_CONTROL + GLFW_MOD_SHIFT) { input->q = input->end; } else if (ui.mod == GLFW_MOD_CONTROL) { input->p = input->q = input->end; } else if (ui.mod == GLFW_MOD_SHIFT) { input->q = input->end; } else if (ui.mod == 0) { input->p = input->q = input->end; } break; case KEY_DELETE: if (input->p != input->q) ui_input_delete_selection(input); else if (input->p < input->end) { char *np = next_char(input->p); memmove(input->p, np, input->end - np); input->end -= np - input->p; *input->end = 0; input->q = input->p; } break; case KEY_ESCAPE: return -1; case KEY_ENTER: return 1; case KEY_BACKSPACE: if (input->p != input->q) ui_input_delete_selection(input); else if (input->p > input->text) { char *pp = prev_char(input->p, input->text); memmove(pp, input->p, input->end - input->p); input->end -= input->p - pp; *input->end = 0; input->q = input->p = pp; } break; case KEY_CTL_A: input->p = input->q = input->text; break; case KEY_CTL_E: input->p = input->q = input->end; break; case KEY_CTL_W: if (input->p != input->q) ui_input_delete_selection(input); else { input->p = prev_word(input->p, input->text); ui_input_delete_selection(input); } break; case KEY_CTL_U: input->p = input->q = input->end = input->text; break; case KEY_CTL_C: case KEY_CTL_X: if (input->p != input->q) { char buf[sizeof input->text]; char *p = input->p < input->q ? input->p : input->q; char *q = input->p > input->q ? input->p : input->q; memmove(buf, p, q - p); buf[q-p] = 0; glfwSetClipboardString(window, buf); if (ui.key == KEY_CTL_X) ui_input_delete_selection(input); } break; case KEY_CTL_V: { const char *buf = glfwGetClipboardString(window); if (buf) ui_input_paste(input, buf, (int)strlen(buf)); } break; default: if (ui.key >= 32) { int cat = ucdn_get_general_category(ui.key); if (ui.key == ' ' || (cat >= UCDN_GENERAL_CATEGORY_LL && cat < UCDN_GENERAL_CATEGORY_ZL)) { char buf[8]; int n = fz_runetochar(buf, ui.key); ui_input_paste(input, buf, n); } } break; } return 0; }
int input_line(char *string, int length) { char curline[2000]; /* edit buffer */ int noline; unsigned c; int more; int i; if (first) { poolinit(); /* build line pool */ first = 0; } noline = 1; /* no line fetched yet */ for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) { if (usrbrk()) { clrbrk(); break; } switch (c=input_char()) { case F_RETURN: /* CR */ t_sendl("\r\n", 2); /* yes, print it and */ goto done; /* get out */ case F_CLRSCRN: /* clear screen */ asclrs(); t_sendl(curline, cl); ascurs(0, cp); break; case F_CSRUP: if (noline) { /* no line fetched yet */ getnext(); /* getnext so getprev gets current */ noline = 0; /* we now have line */ } bstrncpy(curline, getprev(), sizeof(curline)); prtcur(curline); break; case F_CSRDWN: noline = 0; /* mark line fetched */ bstrncpy(curline, getnext(), sizeof(curline)); prtcur(curline); break; case F_INSCHR: insert_space(curline, sizeof(curline)); break; case F_DELCHR: delchr(1, curline, sizeof(curline)); /* delete one character */ break; case F_CSRLFT: /* Backspace */ backup(curline); break; case F_CSRRGT: forward(curline, sizeof(curline)); break; case F_ERSCHR: /* Rubout */ backup(curline); delchr(1, curline, sizeof(curline)); if (cp == 0) { t_char(' '); t_char(0x8); } break; case F_DELEOL: t_clrline(0, t_width); if (cl > cp) cl = cp; break; case F_NXTWRD: i = next_word(curline); while (i--) { forward(curline, sizeof(curline)); } break; case F_PRVWRD: i = prev_word(curline); while (i--) { backup(curline); } break; case F_DELWRD: delchr(next_word(curline), curline, sizeof(curline)); /* delete word */ break; case F_NXTMCH: /* Ctl-X */ if (cl==0) { *string = EOS; /* terminate string */ return(c); /* give it to him */ } /* Note fall through */ case F_DELLIN: case F_ERSLIN: while (cp > 0) { backup(curline); /* backup to beginning of line */ } t_clrline(0, t_width); /* erase line */ cp = 0; cl = 0; /* reset cursor counter */ t_char(' '); t_char(0x8); break; case F_SOL: while (cp > 0) { backup(curline); } break; case F_EOL: while (cp < cl) { forward(curline, sizeof(curline)); } while (cp > cl) { backup(curline); } break; case F_TINS: /* toggle insert mode */ mode_insert = !mode_insert; /* flip bit */ break; default: if (c > 255) { /* function key hit */ if (cl==0) { /* if first character then */ *string = EOS; /* terminate string */ return c; /* return it */ } t_honk_horn(); /* complain */ } else { if ((c & 0xC0) == 0xC0) { if ((c & 0xFC) == 0xFC) { more = 5; } else if ((c & 0xF8) == 0xF8) { more = 4; } else if ((c & 0xF0) == 0xF0) { more = 3; } else if ((c & 0xE0) == 0xE0) { more = 2; } else { more = 1; } } else { more = 0; } if (mode_insert) { insert_space(curline, sizeof(curline)); } curline[cp++] = c; /* store character in line being built */ t_char(c); /* echo character to terminal */ while (more--) { c= input_char(); insert_hole(curline, sizeof(curline)); curline[cp++] = c; /* store character in line being built */ t_char(c); /* echo character to terminal */ } if (cp > cl) { cl = cp; /* keep current length */ curline[cp] = 0; } } break; } /* end switch */ } /* If we fall through here rather than goto done, the line is too long simply return what we have now. */ done: curline[cl++] = EOS; /* terminate */ bstrncpy(string,curline,length); /* return line to caller */ /* Save non-blank lines. Note, put line zaps curline */ if (curline[0] != EOS) { putline(curline,cl); /* save line for posterity */ } return 0; /* give it to him/her */ }