void J_Text_Box::standard_text_box_input_parser(int i_key, int , int i_action, int ){
	
	if((J_PRESS != i_action) && (J_REPEAT != i_action)){
		return;
	}

	if(read_only_status()){
		return;
	}

	switch(i_key){
	case J_KEY_BACKSPACE:
		backspace();
		break;
	case J_KEY_TAB:
		insert_char('\t');
		break;
	case J_KEY_ENTER:
		insert_char('\n');
		break;
	case J_KEY_LEFT:
		move_cursor(-1);
		break;
	case J_KEY_RIGHT:
		move_cursor(1);
		break;
	case J_KEY_DELETE:
		delete_char();
		break;
	default:
		;
	}
}
Esempio n. 2
0
static el_status_t emacs(int c)
{
    el_status_t  s;
    el_keymap_t *kp;

    /* Save point before interpreting input character 'c'. */
    old_point = rl_point;

    if (rl_meta_chars && ISMETA(c)) {
	tty_push(UNMETA(c));
        return meta();
    }

    for (kp = Map; kp->Function; kp++) {
        if (kp->Key == c)
            break;
    }

    if (kp->Function) {
	s = kp->Function();
	if (s == CSdispatch)	/* If Function is inhibited. */
	    s = insert_char(c);
    } else {
	s = insert_char(c);
    }

    if (!el_pushed) {
        /* No pushback means no repeat count; hacky, but true. */
        Repeat = NO_ARG;
    }

    return s;
}
Esempio n. 3
0
/**
 * Handle input on the line editor.
 *
 * @param editor        Line editor state.
 * @param key           Key that was pressed.
 */
void line_editor_input(line_editor_t *editor, uint16_t key) {
  switch (key) {
  case CONSOLE_KEY_LEFT:
    if (editor->offset) {
      console_putc(editor->console, '\b');
      editor->offset--;
    }

    break;
  case CONSOLE_KEY_RIGHT:
    if (editor->offset != editor->len) {
      console_putc(editor->console, editor->buf[editor->offset]);
      editor->offset++;
    }

    break;
  case CONSOLE_KEY_HOME:
    while (editor->offset) {
      console_putc(editor->console, '\b');
      editor->offset--;
    }

    break;
  case CONSOLE_KEY_END:
    while (editor->offset < editor->len) {
      console_putc(editor->console, editor->buf[editor->offset]);
      editor->offset++;
    }

    break;
  case '\b':
    erase_char(editor, false);
    break;
  case 0x7f:
    erase_char(editor, true);
    break;
  case '\n':
    /* The shell code sends \n to place it at the end of the buffer. */
    editor->offset = editor->len;
    insert_char(editor, key);
    break;
  default:
    if (isprint(key))
      insert_char(editor, key);

    break;
  }
}
Esempio n. 4
0
void ttext_::signal_handler_sdl_text_input(const event::tevent event
        , bool& handled
        , const char* text)
{
    // for windows, ascii char will send WM_KEYDOWN and WM_CHAR,
    // WM_KEYDOWN result to call signal_handler_sdl_key_down,
    // WM_CHAR result to call signal_handler_sdl_text_input,
    // so ascii will generate two input.
    const std::string str = text;
    bool inserted = false;
    utils::utf8_iterator ch(str);
    for (utils::utf8_iterator end = utils::utf8_iterator::end(str); ch != end; ++ch) {
        if (*ch <= 0x7f) {
            // ASCII char, don't insert.
            continue;
        }
        insert_char(*ch);
        fire(event::NOTIFY_MODIFIED, *this, NULL);
        inserted = true;
    }
    if (inserted && text_changed_callback_) {
        text_changed_callback_(this, this->text());
    }

    handled = true;
}
Esempio n. 5
0
File: input.c Progetto: dmt4/ne
static void input_move_left(const bool do_refresh) {
	if (pos > 0) {

		const int x_delta = get_char_width(&input_buffer[pos = prev_pos(input_buffer, pos, encoding)], encoding);

		assert(pos >= 0);

		if (x == start_x) {
			offset = pos;

			if (char_ins_del_ok) {
				int i, j;
				for(i = start_x, j = offset; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding));
				if (j < len) {
					move_cursor(ne_lines - 1, i);
					delete_chars(get_char_width(&input_buffer[j], encoding));
				}
				move_cursor(ne_lines - 1, start_x);
				insert_char(get_char(&input_buffer[pos], encoding), 0, encoding);
				move_cursor(ne_lines - 1, start_x);
			}
			else if (do_refresh) input_refresh();
		}
		else x -= x_delta;
	}
}
Esempio n. 6
0
File: tty.c Progetto: cosmos72/twin
INLINE void csi_at(ldat nr) {
    if (nr > (ldat)SizeX - X)
	nr = (ldat)SizeX - X;
    else if (!nr)
	nr = 1;
    insert_char(nr);
}
Esempio n. 7
0
File: dll.c Progetto: troglobit/gul
void insert(buffer_t *buf, int ch)
{
	/* Skriv in tecknet i strukturen ... mycket jox... */
	if (13 == (char)ch) {
		insert_char(buf, (int)10);
		buf->scr.y++;
		buf->scr.x = 0;
	} else {
		if (isprint(ch)) {
			insert_char(buf, ch);
			buf->scr.x++;
		} else {
//         beep(); /* Finns bara i curses!! */
		}
	}
}
Esempio n. 8
0
void		get_raw_input(t_raw *raw, t_hist *hist, int *enter, int *move)
{
  int		err;

  while (!*enter)
    {
      *move = 0;
      raw->rd = raw_alloc(sizeof(char) * 10);
      raw->line->oldcursor = raw->line->cursor;
      if (read(0, raw->rd, 10) < 0)
	continue ;
      if (raw->rd[0] > 31 && raw->rd[0] < 127)
	{
	  err = insert_char(raw, raw->rd[0]);
	  raw->complete = 0;
	  raw->beg = NULL;
	}
      else
	err = get_std_escape(raw, raw->rd, enter, move);
      (err != SUCCESS) ? (input_error(err)) : (0);
      if (err == ERROR && raw->line->input->buffer[0] == 0)
	return ;
      redraw(raw, *move, *enter);
      free(raw->rd);
    }
  free_hist(raw->history);
}
Esempio n. 9
0
void ttext_::handle_key_default(
		bool& handled, SDLKey /*key*/, SDLMod /*modifier*/, Uint16 unicode)
{
	DBG_GUI_E << LOG_SCOPE_HEADER << '\n';

	if(unicode >= 32 && unicode != 127) {
		handled = true;
		insert_char(unicode);
	}
}
Esempio n. 10
0
void	insert_string(char *c, t_print *print)
{
	int		i;

	i = 0;
	while (c[i] != '\0')
	{
		insert_char(c[i], print);
		i++;
	}
}
Esempio n. 11
0
const struct dfont_rect * 
dfont_insert(struct dfont *df, int c, int font, int width, int height) {
	if (width > df->width)
		return NULL;
	assert(dfont_lookup(df,c,font) == NULL);
	for (;;) {
		struct font_line *line = find_line(df, width, height);
		if (line == NULL)
			break;
		struct hash_rect * hr = find_space(df, line, width);
		if (hr) {
			return insert_char(df,c,font,hr);
		}
	}
	struct hash_rect * hr = release_space(df, width, height);
	if (hr) {
		return insert_char(df,c,font,hr);
	}
	return NULL;
}
Esempio n. 12
0
/** Handle key without modifier. */
static void key_handle_unmod(kbd_event_t const *ev)
{
	switch (ev->key) {
	case KC_ENTER:
		selection_delete();
		insert_char('\n');
		caret_update();
		break;
	case KC_LEFT:
	case KC_RIGHT:
	case KC_UP:
	case KC_DOWN:
	case KC_HOME:
	case KC_END:
	case KC_PAGE_UP:
	case KC_PAGE_DOWN:
		key_handle_movement(ev->key, false);
		break;
	case KC_BACKSPACE:
		if (selection_active())
			selection_delete();
		else
			delete_char_before();
		caret_update();
		break;
	case KC_DELETE:
		if (selection_active())
			selection_delete();
		else
			delete_char_after();
		caret_update();
		break;
	default:
		if (ev->c >= 32 || ev->c == '\t') {
			selection_delete();
			insert_char(ev->c);
			caret_update();
		}
		break;
	}
}
Esempio n. 13
0
int insert_tab(void)
{
	if (warn_if_readonly_buffer())
		return FALSE;

	if (!lookup_bool_variable("expand-tabs"))
		insert_char('\t');
	else
		insert_expanded_tab();

	return TRUE;
}
Esempio n. 14
0
void ttext_::handle_key_default(bool& handled,
								SDL_Keycode /*key*/,
								SDL_Keymod /*modifier*/,
								const utf8::string& unicode)
{
	DBG_GUI_E << LOG_SCOPE_HEADER << '\n';

	if(unicode.size() > 1 || unicode[0] != 0) {
		handled = true;
		insert_char(unicode);
		fire(event::NOTIFY_MODIFIED, *this, nullptr);
	}
}
Esempio n. 15
0
File: line.c Progetto: M1lan/zile
static bool
insert_tab (void)
{
  if (warn_if_readonly_buffer ())
    return false;

  if (get_variable_bool ("indent-tabs-mode"))
    insert_char ('\t');
  else
    insert_expanded_tab ();

  return true;
}
Esempio n. 16
0
/*
 * read text from file into editor buffer
 */
static void read_file(const char *filename)
{
	register int fd;
	unsigned char ch;

	vedit_init();
	if ((fd = open(filename, O_RDONLY)) < 0)
	{
		if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) > 0)
		{
			close(fd);
			return;
		}
		indigestion(4);
		abort_bbs(0);
	}

	while (read(fd, &ch, 1) > 0)
	{
		if (ch == '\t')
		{
			do
			{
				insert_char(' ');
			}
			while (currpnt & 0x7);
		}
#if	defined(BIT8)
		else if (isprint2(ch))
#else
		else if (isprint(ch))
#endif
			insert_char(ch);
		else if (ch == '\n')
			split(currline, currpnt);
	}
	close(fd);
}
Esempio n. 17
0
void replaceword( unsigned int *p_xCursorPos, unsigned int *y_CursorPos ) {
	int i;

	for ( i = strlen( source ); i != 0; i-- ) {
		backspace( p_xCursorPos );
	}

	while ( replace[i] != '\0' ) {
		insert_char( replace[i], p_xCursorPos, y_CursorPos );
		i++;
	}

	refreshline( 0, *y_CursorPos );
}
Esempio n. 18
0
static void insert_expanded_tab(void)
{
	int col = 0, t = cur_bp->tab_width;
	char *sp = cur_wp->pointp->text, *p = sp;

	while (p < sp + cur_wp->pointo) {
		if (*p == '\t')
			col |= t - 1;
		++col, ++p;
	}

	for (col = t - col % t; col > 0; --col)
		insert_char(' ');
}
Esempio n. 19
0
/**
 * Inserts the characters (string) 'chars' at the cursor position 'pos'.
 *
 * Returns 0 if no chars were inserted or non-zero otherwise.
 */
static int insert_chars(struct current *current, int pos, const char *chars) {
    int inserted = 0;

    while (*chars) {
        int ch;
        int n = utf8_tounicode(chars, &ch);
        if (insert_char(current, pos, ch) == 0) {
            break;
        }
        inserted++;
        pos++;
        chars += n;
    }
    return inserted;
}
Esempio n. 20
0
File: FED.C Progetto: MegaGod/TW
int select_font( int *page, char *status ) {
	static int ch = 0;
	char tmp;
	int dum;
	extern int cur_char;
	unsigned maxx, maxy;
	int save = get_active_clock( );
	static new_page = -1;
	char key, ch2;

	start_clock( SELECT_FONT );

	maxx = 256 / char_per_col( );
	maxy = char_per_col( );
	cur_char = ch;
	while ( !( ( key = get_pos( &sel_x, &sel_y, maxx, maxy - 1, 1, 1 ) ) == RET ||
		key == 3 ) ) {
		ch = sel_y + sel_x*char_per_col( );
		if ( ch>255 ) {
			sel_x = maxx;
			sel_y = char_per_col( ) - ( ( char_per_col( )*( 1 + sel_x ) ) - 255 );
			ch = 255;
		};
		cur_char = ch;
		if ( new_page == -1 ) {
			switch ( tolower( key ) ) {
			case 'o':
				new_page = 0;
				ch2 = select_font( &dum, &tmp );
				if ( *status == RET ) {
					or_char( ch, ch2 );
					print_table( which_page( ch ) );
				}
				new_page = -1;
				break;
			case '?':
				help_select( ); break;
			case 1:
				insert_char( ch ); break;
			case 2:
				delete_char( ch ); break;
			}
		}
	}
	start_clock( save );
	*status = key;
	return ch;
}
Esempio n. 21
0
/* Insert a character at the current position in the insert mode
 * whetever the current insert mode is.
 */
int insert_char_in_insert_mode(int c)
{
	int overwrite_mode_save, ret_value;

	/* save current mode */
	overwrite_mode_save = cur_bp->flags & BFLAG_OVERWRITE;
	
	/* force insert mode */
	cur_bp->flags &= ~BFLAG_OVERWRITE;

	ret_value = insert_char(c);

	/* restore previous mode */
	cur_bp->flags |= overwrite_mode_save;

	return ret_value;
}
Esempio n. 22
0
void insert_pinyin (const char* pinyin, int pos, pinyin_trie* root)
{
    int i = 0;
    int k = 0;
    int len = 0;
    pinyin_trie* cur_node = root;

    if ( !pinyin || !root ) {
        g_warning ("args error in insert trie!\n");
        return ;
    }

    for (; pinyin[i] != '\0'; i++ ) {
        k = ch_to_num (pinyin[i]);
        insert_char (pinyin[i], pos, cur_node);
        cur_node = cur_node->next[k];
    }
}
Esempio n. 23
0
/** Handle Shift-key combination. */
static void key_handle_shift(kbd_event_t const *ev)
{
	switch (ev->key) {
	case KC_LEFT:
	case KC_RIGHT:
	case KC_UP:
	case KC_DOWN:
	case KC_HOME:
	case KC_END:
	case KC_PAGE_UP:
	case KC_PAGE_DOWN:
		key_handle_movement(ev->key, true);
		break;
	default:
		if (ev->c >= 32 || ev->c == '\t') {
			selection_delete();
			insert_char(ev->c);
			caret_update();
		}
		break;
	}
}
Esempio n. 24
0
static void insert_clipboard_data(void)
{
	char *str;
	size_t off;
	wchar_t c;
	int rc;

	rc = clipboard_get_str(&str);
	if (rc != EOK || str == NULL)
		return;

	off = 0;

	while (true) {
		c = str_decode(str, &off, STR_NO_LIMIT);
		if (c == '\0')
			break;

		insert_char(c);
	}

	free(str);
}
Esempio n. 25
0
void screen_insert_char(struct te_buffer *buf, char c)
{
	if (buf == NULL)
		return;

	if (buf->dirty < 1)
		buf->dirty = 1;

	insert_char(buf, c);

	if (c == '\n') {
		clrtoeol();
		clear_nfirst_lines(buffer_win, max(buf->y - 1, 0));
		scroll_down(buffer_win);
		paint_buffer_nlines(buf, buf->y + 1);
		paint_nthline(buf, buf->y + 2, buf->y + 1);
		screen_move_right(buf);
	} else {
		bstring s = current_line_as_bstring(buf->contents, buf->point);
		draw_line(s, buf->y);
		screen_move_right(buf);
	}
}
Esempio n. 26
0
/** Insert file at caret position.
 *
 * Reads in the contents of a file and inserts them at the current position
 * of the caret.
 */
static int file_insert(char *fname)
{
	FILE *f;
	wchar_t c;
	char buf[BUF_SIZE];
	int bcnt;
	int n_read;
	size_t off;

	f = fopen(fname, "rt");
	if (f == NULL)
		return EINVAL;

	bcnt = 0;

	while (true) {
		if (bcnt < STR_BOUNDS(1)) {
			n_read = fread(buf + bcnt, 1, BUF_SIZE - bcnt, f);
			bcnt += n_read;
		}

		off = 0;
		c = str_decode(buf, &off, bcnt);
		if (c == '\0')
			break;

		bcnt -= off;
		memcpy(buf, buf + off, bcnt);

		insert_char(c);
	}

	fclose(f);

	return EOK;
}
Esempio n. 27
0
void uart_console_isr(struct device *unused)
{
	ARG_UNUSED(unused);

	while (uart_irq_update(uart_console_dev) &&
	       uart_irq_is_pending(uart_console_dev)) {
		static struct uart_console_input *cmd;
		uint8_t byte;
		int rx;

		if (!uart_irq_rx_ready(uart_console_dev)) {
			continue;
		}

		/* Character(s) have been received */

		rx = read_uart(uart_console_dev, &byte, 1);
		if (rx < 0) {
			return;
		}

		if (uart_irq_input_hook(uart_console_dev, byte) != 0) {
			/*
			 * The input hook indicates that no further processing
			 * should be done by this handler.
			 */
			return;
		}

		if (!cmd) {
			cmd = nano_isr_fifo_get(avail_queue, TICKS_NONE);
			if (!cmd)
				return;
		}

		/* Handle ANSI escape mode */
		if (atomic_test_bit(&esc_state, ESC_ANSI)) {
			handle_ansi(byte);
			continue;
		}

		/* Handle escape mode */
		if (atomic_test_and_clear_bit(&esc_state, ESC_ESC)) {
			switch (byte) {
			case ANSI_ESC:
				atomic_set_bit(&esc_state, ESC_ANSI);
				atomic_set_bit(&esc_state, ESC_ANSI_FIRST);
				break;
			default:
				break;
			}

			continue;
		}

		/* Handle special control characters */
		if (!isprint(byte)) {
			switch (byte) {
			case DEL:
				if (cur > 0) {
					del_char(&cmd->line[--cur], end);
				}
				break;
			case ESC:
				atomic_set_bit(&esc_state, ESC_ESC);
				break;
			case '\r':
				cmd->line[cur + end] = '\0';
				uart_poll_out(uart_console_dev, '\r');
				uart_poll_out(uart_console_dev, '\n');
				cur = 0;
				end = 0;
				nano_isr_fifo_put(lines_queue, cmd);
				cmd = NULL;
				break;
			case '\t':
				if (completion_cb && !end) {
					cur += completion_cb(cmd->line, cur);
				}
				break;
			default:
				break;
			}

			continue;
		}

		/* Ignore characters if there's no more buffer space */
		if (cur + end < sizeof(cmd->line) - 1) {
			insert_char(&cmd->line[cur++], byte, end);
		}
	}
}
Esempio n. 28
0
void uart_console_isr(struct device *unused)
{
	ARG_UNUSED(unused);

	while (uart_irq_update(uart_console_dev) &&
	       uart_irq_is_pending(uart_console_dev)) {
		static struct console_input *cmd;
		u8_t byte;
		int rx;

		if (!uart_irq_rx_ready(uart_console_dev)) {
			continue;
		}

		/* Character(s) have been received */

		rx = read_uart(uart_console_dev, &byte, 1);
		if (rx < 0) {
			return;
		}

#ifdef CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS
		if (debug_hook_in != NULL && debug_hook_in(byte) != 0) {
			/*
			 * The input hook indicates that no further processing
			 * should be done by this handler.
			 */
			return;
		}
#endif

		if (!cmd) {
			cmd = k_fifo_get(avail_queue, K_NO_WAIT);
			if (!cmd) {
				return;
			}
		}

#ifdef CONFIG_UART_CONSOLE_MCUMGR
		/* Divert this byte from normal console handling if it is part
		 * of an mcumgr frame.
		 */
		if (handle_mcumgr(cmd, byte)) {
			continue;
		}
#endif          /* CONFIG_UART_CONSOLE_MCUMGR */

		/* Handle ANSI escape mode */
		if (atomic_test_bit(&esc_state, ESC_ANSI)) {
			handle_ansi(byte, cmd->line);
			continue;
		}

		/* Handle escape mode */
		if (atomic_test_and_clear_bit(&esc_state, ESC_ESC)) {
			if (byte == ANSI_ESC) {
				atomic_set_bit(&esc_state, ESC_ANSI);
				atomic_set_bit(&esc_state, ESC_ANSI_FIRST);
			}

			continue;
		}

		/* Handle special control characters */
		if (!isprint(byte)) {
			switch (byte) {
			case DEL:
				if (cur > 0) {
					del_char(&cmd->line[--cur], end);
				}
				break;
			case ESC:
				atomic_set_bit(&esc_state, ESC_ESC);
				break;
			case '\r':
				cmd->line[cur + end] = '\0';
				uart_poll_out(uart_console_dev, '\r');
				uart_poll_out(uart_console_dev, '\n');
				cur = 0;
				end = 0;
				k_fifo_put(lines_queue, cmd);
				cmd = NULL;
				break;
			case '\t':
				if (completion_cb && !end) {
					cur += completion_cb(cmd->line, cur);
				}
				break;
			default:
				break;
			}

			continue;
		}

		/* Ignore characters if there's no more buffer space */
		if (cur + end < sizeof(cmd->line) - 1) {
			insert_char(&cmd->line[cur++], byte, end);
		}
	}
}
Esempio n. 29
0
static int
glw_text_bitmap_event(glw_t *w, event_t *e)
{
  glw_text_bitmap_t *gtb = (glw_text_bitmap_t *)w;

  if(event_is_action(e, ACTION_BS)) {

    del_char(gtb);
    gtb_notify(gtb);
    return 1;

  } else if(event_is_type(e, EVENT_UNICODE)) {

    event_int_t *eu = (event_int_t *)e;

    if(insert_char(gtb, eu->val))
      gtb_notify(gtb);
    return 1;

  } else if(event_is_type(e, EVENT_INSERT_STRING)) {
    event_payload_t *ep = (event_payload_t *)e;
    const char *str = ep->payload;
    int uc;
    while((uc = utf8_get(&str)) != 0) {
      insert_char(gtb, uc);
    }
    gtb_notify(gtb);
    return 1;

  } else if(event_is_action(e, ACTION_LEFT)) {

    if(gtb->gtb_edit_ptr > 0) {
      gtb->gtb_edit_ptr--;
      gtb->gtb_update_cursor = 1;
    }
    return 1;

  } else if(event_is_action(e, ACTION_RIGHT)) {

    if(gtb->gtb_edit_ptr < gtb->gtb_uc_len) {
      gtb->gtb_edit_ptr++;
      gtb->gtb_update_cursor = 1;
    }
    return 1;

  } else if(event_is_action(e, ACTION_ACTIVATE) ||
            event_is_action(e, ACTION_ITEMMENU)) {
    
    gtb_caption_refresh(gtb);

    if(gtb->gtb_flags & (GTB_FILE_REQUEST | GTB_DIR_REQUEST)) {

      if(gtb->gtb_p == NULL) {
        TRACE(TRACE_ERROR, "GLW",
              "File requests on unbound widgets is not supported");
      } else {

        int flags =
          (gtb->gtb_flags & GTB_FILE_REQUEST ? FILEPICKER_FILES : 0) |
          (gtb->gtb_flags & GTB_DIR_REQUEST  ? FILEPICKER_DIRECTORIES : 0);

        filepicker_pick_to_prop(gtb->gtb_description,
                                gtb->gtb_p, gtb->gtb_caption,
                                flags);
      }

    } else {

      if(event_is_action(e, ACTION_ACTIVATE) && e->e_flags & EVENT_MOUSE)
        return 1;

      w->glw_root->gr_open_osk(w->glw_root,
                               gtb->gtb_description,
                               gtb->gtb_caption, w,
                               gtb->gtb_flags & GTB_PASSWORD);
    }
    return 1;
  }
  return 0;
}
Esempio n. 30
0
static int linenoiseEdit(struct current *current) {
    int history_index = 0;

    /* The latest history entry is always our current buffer, that
     * initially is just an empty string. */
    linenoiseHistoryAdd("");

    set_current(current, "");
    refreshLine(current->prompt, current);

    while(1) {
        int dir = -1;
        int c = fd_read(current);

#ifndef NO_COMPLETION
        /* Only autocomplete when the callback is set. It returns < 0 when
         * there was an error reading from fd. Otherwise it will return the
         * character that should be handled next. */
        if (c == '\t' && current->pos == current->chars && completionCallback != NULL) {
            c = completeLine(current);
            /* Return on errors */
            if (c < 0) return current->len;
            /* Read next character when 0 */
            if (c == 0) continue;
        }
#endif

process_char:
        if (c == -1) return current->len;
#ifdef USE_TERMIOS
        if (c == 27) {   /* escape sequence */
            c = check_special(current->fd);
        }
#endif
        switch(c) {
        case '\r':    /* enter */
            history_len--;
            free(history[history_len]);
            return current->len;
        case ctrl('C'):     /* ctrl-c */
            errno = EAGAIN;
            return -1;
        case 127:   /* backspace */
        case ctrl('H'):
            if (remove_char(current, current->pos - 1) == 1) {
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('D'):     /* ctrl-d */
            if (current->len == 0) {
                /* Empty line, so EOF */
                history_len--;
                free(history[history_len]);
                return -1;
            }
            /* Otherwise fall through to delete char to right of cursor */
        case SPECIAL_DELETE:
            if (remove_char(current, current->pos) == 1) {
                refreshLine(current->prompt, current);
            }
            break;
        case SPECIAL_INSERT:
            /* Ignore. Expansion Hook.
             * Future possibility: Toggle Insert/Overwrite Modes
             */
            break;
        case ctrl('W'):    /* ctrl-w, delete word at left. save deleted chars */
            /* eat any spaces on the left */
            {
                int pos = current->pos;
                while (pos > 0 && get_char(current, pos - 1) == ' ') {
                    pos--;
                }

                /* now eat any non-spaces on the left */
                while (pos > 0 && get_char(current, pos - 1) != ' ') {
                    pos--;
                }

                if (remove_chars(current, pos, current->pos - pos)) {
                    refreshLine(current->prompt, current);
                }
            }
            break;
        case ctrl('R'):    /* ctrl-r */
            {
                /* Display the reverse-i-search prompt and process chars */
                char rbuf[50];
                char rprompt[80];
                int rchars = 0;
                int rlen = 0;
                int searchpos = history_len - 1;

                rbuf[0] = 0;
                while (1) {
                    int n = 0;
                    const char *p = NULL;
                    int skipsame = 0;
                    int searchdir = -1;

                    snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
                    refreshLine(rprompt, current);
                    c = fd_read(current);
                    if (c == ctrl('H') || c == 127) {
                        if (rchars) {
                            int p = utf8_index(rbuf, --rchars);
                            rbuf[p] = 0;
                            rlen = strlen(rbuf);
                        }
                        continue;
                    }
#ifdef USE_TERMIOS
                    if (c == 27) {
                        c = check_special(current->fd);
                    }
#endif
                    if (c == ctrl('P') || c == SPECIAL_UP) {
                        /* Search for the previous (earlier) match */
                        if (searchpos > 0) {
                            searchpos--;
                        }
                        skipsame = 1;
                    }
                    else if (c == ctrl('N') || c == SPECIAL_DOWN) {
                        /* Search for the next (later) match */
                        if (searchpos < history_len) {
                            searchpos++;
                        }
                        searchdir = 1;
                        skipsame = 1;
                    }
                    else if (c >= ' ') {
                        if (rlen >= (int)sizeof(rbuf) + 3) {
                            continue;
                        }

                        n = utf8_getchars(rbuf + rlen, c);
                        rlen += n;
                        rchars++;
                        rbuf[rlen] = 0;

                        /* Adding a new char resets the search location */
                        searchpos = history_len - 1;
                    }
                    else {
                        /* Exit from incremental search mode */
                        break;
                    }

                    /* Now search through the history for a match */
                    for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
                        p = strstr(history[searchpos], rbuf);
                        if (p) {
                            /* Found a match */
                            if (skipsame && strcmp(history[searchpos], current->buf) == 0) {
                                /* But it is identical, so skip it */
                                continue;
                            }
                            /* Copy the matching line and set the cursor position */
                            set_current(current,history[searchpos]);
                            current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
                            break;
                        }
                    }
                    if (!p && n) {
                        /* No match, so don't add it */
                        rchars--;
                        rlen -= n;
                        rbuf[rlen] = 0;
                    }
                }
                if (c == ctrl('G') || c == ctrl('C')) {
                    /* ctrl-g terminates the search with no effect */
                    set_current(current, "");
                    c = 0;
                }
                else if (c == ctrl('J')) {
                    /* ctrl-j terminates the search leaving the buffer in place */
                    c = 0;
                }
                /* Go process the char normally */
                refreshLine(current->prompt, current);
                goto process_char;
            }
            break;
        case ctrl('T'):    /* ctrl-t */
            if (current->pos > 0 && current->pos <= current->chars) {
                /* If cursor is at end, transpose the previous two chars */
                int fixer = (current->pos == current->chars);
                c = get_char(current, current->pos - fixer);
                remove_char(current, current->pos - fixer);
                insert_char(current, current->pos - 1, c);
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('V'):    /* ctrl-v */
            if (has_room(current, 3)) {
                /* Insert the ^V first */
                if (insert_char(current, current->pos, c)) {
                    refreshLine(current->prompt, current);
                    /* Now wait for the next char. Can insert anything except \0 */
                    c = fd_read(current);

                    /* Remove the ^V first */
                    remove_char(current, current->pos - 1);
                    if (c != -1) {
                        /* Insert the actual char */
                        insert_char(current, current->pos, c);
                    }
                    refreshLine(current->prompt, current);
                }
            }
            break;
        case ctrl('B'):
        case SPECIAL_LEFT:
            if (current->pos > 0) {
                current->pos--;
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('F'):
        case SPECIAL_RIGHT:
            if (current->pos < current->chars) {
                current->pos++;
                refreshLine(current->prompt, current);
            }
            break;
        case SPECIAL_PAGE_UP:
          dir = history_len - history_index - 1; /* move to start of history */
          goto history_navigation;
        case SPECIAL_PAGE_DOWN:
          dir = -history_index; /* move to 0 == end of history, i.e. current */
          goto history_navigation;
        case ctrl('P'):
        case SPECIAL_UP:
            dir = 1;
          goto history_navigation;
        case ctrl('N'):
        case SPECIAL_DOWN:
history_navigation:
            if (history_len > 1) {
                /* Update the current history entry before to
                 * overwrite it with tne next one. */
                free(history[history_len - 1 - history_index]);
                history[history_len - 1 - history_index] = strdup(current->buf);
                /* Show the new entry */
                history_index += dir;
                if (history_index < 0) {
                    history_index = 0;
                    break;
                } else if (history_index >= history_len) {
                    history_index = history_len - 1;
                    break;
                }
                set_current(current, history[history_len - 1 - history_index]);
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('A'): /* Ctrl+a, go to the start of the line */
        case SPECIAL_HOME:
            current->pos = 0;
            refreshLine(current->prompt, current);
            break;
        case ctrl('E'): /* ctrl+e, go to the end of the line */
        case SPECIAL_END:
            current->pos = current->chars;
            refreshLine(current->prompt, current);
            break;
        case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
            if (remove_chars(current, 0, current->pos)) {
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
            if (remove_chars(current, current->pos, current->chars - current->pos)) {
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
            if (current->capture && insert_chars(current, current->pos, current->capture)) {
                refreshLine(current->prompt, current);
            }
            break;
        case ctrl('L'): /* Ctrl+L, clear screen */
            linenoiseClearScreen();
            /* Force recalc of window size for serial terminals */
            current->cols = 0;
            refreshLine(current->prompt, current);
            break;
        default:
            /* Only tab is allowed without ^V */
            if (c == '\t' || c >= ' ') {
                if (insert_char(current, current->pos, c) == 1) {
                    refreshLine(current->prompt, current);
                }
            }
            break;
        }
    }
    return current->len;
}