summaryrefslogtreecommitdiffstats
path: root/src/input.c
diff options
context:
space:
mode:
authormongo <mongo@iomega>2016-04-15 16:20:17 -0300
committermongo <mongo@iomega>2016-04-15 16:20:17 -0300
commitf686ba184e0af3fd37aa8a743631a7a376f30843 (patch)
treee9a48dc691511a2961f93163944ba0ca1a84e5b3 /src/input.c
parentc0a088d7a4bc61e6e69fa5bd8964c39f68507c71 (diff)
Renamed src.scim2 to src
Diffstat (limited to 'src/input.c')
-rwxr-xr-xsrc/input.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/src/input.c b/src/input.c
new file mode 100755
index 0000000..eec056f
--- /dev/null
+++ b/src/input.c
@@ -0,0 +1,296 @@
+#include <sys/time.h>
+#include <string.h>
+#include <ctype.h> // for isdigit
+#include <ncursesw/curses.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "screen.h"
+#include "maps.h"
+#include "cmds.h"
+#include "history.h"
+#include "conf.h"
+#include "utils/string.h"
+#include "cmds_visual.h"
+#include "buffer.h"
+
+
+static wint_t wd; // char read from stdin
+static int d; // char read from stdin
+int return_value; // return value of getch()
+int cmd_multiplier = 0; // Multiplier
+int cmd_pending = 0; // Command pending
+int shall_quit; // Break loop if ESC key is pressed
+
+
+/* Reads stdin for a valid command.
+ * Details: Read characters from stdin to a input buffer.
+ * When filled up, validate the command and call the appropriate handler.
+ * When a timeout is reached, flush the buffer.
+*/
+void handle_input(struct block * buffer) {
+
+ // For measuring timeout
+ struct timeval start_tv, m_tv;
+ gettimeofday(&start_tv, NULL);
+ gettimeofday(&m_tv, NULL);
+ long msec = (m_tv.tv_sec - start_tv.tv_sec) * 1000L +
+ (m_tv.tv_usec - start_tv.tv_usec) / 1000L;
+
+ cmd_multiplier = 0;
+ cmd_pending = 0;
+
+ while ( ! has_cmd(buffer, msec) && msec <= CMDTIMEOUT ) {
+
+ // if command pending, refresh 'ef' only. Multiplier and cmd pending
+ if (cmd_pending) {
+ print_mult_pend(input_win);
+ wrefresh(input_win);
+ }
+
+ // Modify cursor state according to the current mode
+ handle_cursor();
+
+ // Read new character from stdin
+ return_value = wget_wch(input_win, & wd);
+ d = wd;
+ if ( d == OKEY_ESC) {
+ break_waitcmd_loop(buffer);
+ return;
+ }
+
+ // Handle multiplier of commands in NORMAL mode.
+ if ( return_value != -1 && isdigit(d)
+ && ( buffer->value == L'\0' || iswdigit((wchar_t) buffer->value))
+ && ( curmode == NORMAL_MODE || curmode == VISUAL_MODE || curmode == EDIT_MODE )
+ && ( cmd_multiplier || d != L'0' )
+ && ( ! atoi(get_conf_value("numeric")))
+ ) {
+ cmd_multiplier *= 10;
+ cmd_multiplier += (int) (d - '0');
+ if (cmd_multiplier > MAX_MULTIPLIER) cmd_multiplier = 0;
+
+ gettimeofday(&start_tv, NULL);
+ msec = (m_tv.tv_sec - start_tv.tv_sec) * 1000L +
+ (m_tv.tv_usec - start_tv.tv_usec) / 1000L;
+
+ print_mult_pend(input_win);
+ wrefresh(input_win);
+ continue;
+ }
+
+ // Update time stap to reset timeout after each loop
+ // (Only if current mode is COMMAND, INSERT or EDIT) and for each
+ // user input as well.
+ fix_timeout(&start_tv);
+
+ // Handle special characters input: BS TAG ENTER HOME END DEL PGUP
+ // PGDOWN and alphanumeric characters
+ if (is_idchar(d) || return_value != -1) {
+ // If in NORMAL, VISUAL or EDITION mode , change top left corner
+ // indicator
+ if ( (curmode == NORMAL_MODE && d >= ' ') || //FIXME
+ (curmode == EDIT_MODE && d >= ' ') ||
+ (curmode == VISUAL_MODE && d >= ' ') ) {
+ cmd_pending = 1;
+ }
+
+ addto_buf(buffer, wd);
+
+ // Replace maps in buffer
+ replace_maps(buffer);
+
+ }
+
+ gettimeofday(&m_tv, NULL);
+ msec = (m_tv.tv_sec - start_tv.tv_sec) * 1000L +
+ (m_tv.tv_usec - start_tv.tv_usec) / 1000L;
+ }
+
+ // timeout. Command incomplete
+ if (msec >= CMDTIMEOUT) {
+
+ // No longer wait for a command, set flag.
+ cmd_pending = 0;
+
+ // Reset multiplier
+ cmd_multiplier = 0;
+
+ // Clean second line
+ //clr_header(input_win, 1); // commented on 22/06/2014
+
+ // Execute command or mapping
+ } else {
+
+ cmd_pending = 0;
+ //if (curmode == NORMAL_MODE) show_header(input_win); commented on 08/06
+
+ // Clean second line
+ clr_header(input_win, 1);
+
+ // Handle command and repeat as many times as the multiplier dictates
+ handle_mult( &cmd_multiplier, buffer, msec );
+ }
+
+ print_mult_pend(input_win);
+
+ // Flush the buffer
+ flush_buf(buffer);
+ return;
+}
+
+// Break waiting command loop
+void break_waitcmd_loop(struct block * buffer) {
+ if (curmode == COMMAND_MODE) {
+#ifdef HISTORY_FILE
+ del_item_from_history(commandline_history, 0);
+ commandline_history->pos = 0;
+ set_comp(0);
+#endif
+ } else if (curmode == VISUAL_MODE) {
+ exit_visualmode();
+ }
+
+ curmode = NORMAL_MODE;
+
+ // No longer wait for command. Set flag.
+ cmd_pending = 0;
+
+ // Reset the multiplier
+ cmd_multiplier = 0;
+
+ // clean inputline
+ inputline[0] = L'\0';
+
+ flush_buf(buffer);
+ //clr_header(input_win, 0);
+ //show_header(input_win);
+ print_mult_pend(input_win);
+ update(TRUE);
+ return;
+}
+
+// Handle timeout depending on the current mode
+// there is NO timeout for COMMAND, INSERT and EDIT modes.
+void fix_timeout(struct timeval * start_tv) {
+ switch (curmode) {
+ case COMMAND_MODE:
+ case INSERT_MODE:
+ gettimeofday(start_tv, NULL);
+ break;
+ case VISUAL_MODE:
+ case EDIT_MODE:
+ case NORMAL_MODE:
+ if (d != 0) gettimeofday(start_tv, NULL);
+ }
+ return;
+}
+
+
+// Traverse 'stuffbuff' and determines if there is a valid command
+// Ej. buffer = "diw"
+int has_cmd (struct block * buf, long timeout) {
+ int len = get_bufsize(buf);
+ if ( ! len ) return 0;
+ int k, found = 0;
+
+ struct block * auxb = (struct block *) create_buf();
+
+ for (k = 0; k < len; k++) {
+ addto_buf(auxb, get_bufval(buf, k));
+ if ( is_single_command(auxb, timeout)) { found = 1; break; }
+ }
+ erase_buf(auxb);
+ auxb = NULL;
+ return found;
+}
+
+void do_commandmode(struct block * sb);
+void do_normalmode (struct block * buf);
+void do_insertmode(struct block * sb);
+void do_editmode(struct block * sb);
+void do_visualmode(struct block * sb);
+
+// Use specific functions for every command on each mode
+void exec_single_cmd (struct block * sb) {
+ switch (curmode) {
+ case NORMAL_MODE:
+ do_normalmode(sb);
+ break;
+ case INSERT_MODE:
+ do_insertmode(sb);
+ break;
+ case COMMAND_MODE:
+ do_commandmode(sb);
+ break;
+ case EDIT_MODE:
+ do_editmode(sb);
+ break;
+ case VISUAL_MODE:
+ do_visualmode(sb);
+ break;
+ }
+ return;
+}
+
+// Handle the final command to be executed, using the multiplier
+void handle_mult(int * cmd_multiplier, struct block * buf, long timeout) {
+ int j, k;
+ struct block * b_copy = buf;
+ int lenbuf = get_bufsize(b_copy);
+ if ( ! *cmd_multiplier) *cmd_multiplier = 1;
+
+ for (j = 1; j < *cmd_multiplier; j++) {
+ for (k = 0; k < lenbuf; k++) {
+ addto_buf(buf, b_copy->value);
+ b_copy = b_copy->pnext;
+ }
+ }
+
+ //if (is_single_command(buf, timeout) == EDITION_CMD)
+ // copybuffer(buf, lastcmd_buffer); // save stdin buffer content in lastcmd buffer
+ exec_mult(buf, timeout);
+ if (*cmd_multiplier > 1) { *cmd_multiplier = 1; update(TRUE); }
+ *cmd_multiplier = 0;
+
+ return;
+}
+
+// Handle multiple command execution in sequence
+void exec_mult (struct block * buf, long timeout) {
+ int k, res, len = get_bufsize(buf);
+ if ( ! len ) return;
+
+ // Try to execute the whole buffer content
+ if ((res = is_single_command(buf, timeout))) {
+ if (res == EDITION_CMD) copybuffer(buf, lastcmd_buffer); // save stdin buffer content in lastcmd buffer
+ //cmd_multiplier--;
+ exec_single_cmd(buf);
+
+ // If not possible, traverse blockwise
+ } else {
+ struct block * auxb = (struct block *) create_buf();
+ for (k = 0; k < len; k++) {
+ addto_buf(auxb, get_bufval(buf, k));
+
+ if ((res = is_single_command(auxb, timeout))) {
+ if (res == EDITION_CMD) copybuffer(buf, lastcmd_buffer); // save stdin buffer content in lastcmd buffer
+ //cmd_multiplier--;
+ exec_single_cmd(auxb);
+ flush_buf(auxb);
+
+ // Take the first K values from 'buf'
+ k++;
+ while ( k-- ) buf = dequeue(buf);
+ // Execute again
+ if (cmd_multiplier == 0) break;
+ exec_mult (buf, timeout);
+ break;
+ }
+ }
+ erase_buf(auxb);
+ auxb = NULL;
+ }
+ return;
+}