// Similar to the session function, this will keep looping until it has read a line form a socket descriptor. It takes // the socket explicitly. This function is used by the message sending code. int network_readline(int socket_descriptor, char *buffer, sizer_t buffer_length, sizer_t *line_length, sizer_t *buffered_bytes) { char *place; int readin; int characters = 0; #ifdef DEBUG_FRAMEWORK if (socket_descriptor < 0 || buffer == NULL || buffer_length == 0 || line_length == NULL || buffered_bytes == NULL) { lavalog("Invalid data passed in."); return -1; } #endif // Check to see if there are characters already in the buffer, and move them. if (*line_length < *buffered_bytes) { move_bytes(buffer, buffer + *line_length, *buffered_bytes - *line_length); *buffered_bytes -= *line_length; characters = complete_line(buffer, *buffered_bytes); } else { *buffered_bytes = 0; } // Reset the current line counter, and advance the place holder to where we are supposed to write. *line_length = 0; place = buffer + *buffered_bytes; while (continue_processing(0) && !characters && buffer_length > *buffered_bytes) { readin = read(socket_descriptor, place, buffer_length - *buffered_bytes); if (readin < 0) { #ifdef DEBUG_FRAMEWORK lavalog("Received an error while reading from the socket. {errno = %i}", errno); #endif return -1; } else { *buffered_bytes += readin; place += readin; } // Check whether we have a complete line to return yet. characters = complete_line(buffer, *buffered_bytes); } // Tell the session how many characters are on the current line. if (buffer_length <= *buffered_bytes) { return -1; } else { *line_length = characters; } return characters; }
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd) { char b_path[MAX_STR_SIZE]; char b_name[MAX_STR_SIZE]; char b_cmd[MAX_STR_SIZE]; const wchar_t *tmpline = &line[wcslen(cmd) + 2]; /* start after "/command \"" */ if (wcs_to_mbs_buf(b_path, tmpline, sizeof(b_path)) == -1) return -1; if (wcs_to_mbs_buf(b_cmd, cmd, sizeof(b_cmd)) == -1) return -1; if (b_path[0] == '~') complt_home_dir(self, b_path, sizeof(b_path), b_cmd, strlen(b_cmd) + 2); int si = char_rfind(b_path, '/', strlen(b_path)); if (!b_path[0]) { /* list everything in pwd */ b_path[0] = '.'; b_path[1] = '\0'; } else if (!si && b_path[0] != '/') { /* look for matches in pwd */ char tmp[MAX_STR_SIZE]; snprintf(tmp, sizeof(tmp), ".%s", b_path); snprintf(b_path, sizeof(b_path), "%s", tmp); } snprintf(b_name, sizeof(b_name), "%s", &b_path[si + 1]); b_path[si + 1] = '\0'; int b_name_len = strlen(b_name); DIR *dp = opendir(b_path); if (dp == NULL) return -1; char dirnames[MAX_DIRS][NAME_MAX]; struct dirent *entry; int dircount = 0; while ((entry = readdir(dp)) && dircount < MAX_DIRS) { if (strncmp(entry->d_name, b_name, b_name_len) == 0 && strcmp(".", entry->d_name) && strcmp("..", entry->d_name)) { snprintf(dirnames[dircount], sizeof(dirnames[dircount]), "%s", entry->d_name); ++dircount; } } closedir(dp); if (dircount == 0) return -1; if (dircount > 1) { qsort(dirnames, dircount, NAME_MAX, qsort_strcasecmp_hlpr); print_matches(self, m, dirnames, dircount, NAME_MAX); } return complete_line(self, dirnames, dircount, NAME_MAX); }
static char * line_completion_function (const char *text, int matches, char *line_buffer, int point) { static char **list = (char **) NULL; /* Cache of completions. */ static int index; /* Next cached completion. */ char *output = NULL; if (matches == 0) { /* The caller is beginning to accumulate a new set of completions, so we need to find all of them now, and cache them for returning one at a time on future calls. */ if (list) { /* Free the storage used by LIST, but not by the strings inside. This is because rl_complete_internal () frees the strings. As complete_line may abort by calling `error' clear LIST now. */ xfree (list); list = NULL; } index = 0; list = complete_line (text, line_buffer, point); } /* If we found a list of potential completions during initialization then dole them out one at a time. The vector of completions is NULL terminated, so after returning the last one, return NULL (and continue to do so) each time we are called after that, until a new list is available. */ if (list) { output = list[index]; if (output) { index++; } } #if 0 /* Can't do this because readline hasn't yet checked the word breaks for figuring out whether to insert a quote. */ if (output == NULL) /* Make sure the word break characters are set back to normal for the next time that readline tries to complete something. */ rl_completer_word_break_characters = current_language->la_word_break_characters(); #endif return (output); }
void proper_line(t_d *d, char *line, unsigned int *j) { unsigned int i; unsigned int start; unsigned int nb_read; int neg; int num; i = 0; neg = 0; nb_read = 0; while (line[i] != '\0' && nb_read != d->line_length) { if (line[i] == 45) if (ft_isdigit(line[i + 1]) == 1) { neg = 1; i++; } if (ft_isdigit(line[i]) == 1) { printf("i = %d\n", i); start = i; while (ft_isdigit(line[i]) == 1) i++; printf("i = %d\n", i); if (i == start) num = i; else num = ft_atoi(ft_strsub(line, start, (i - start))); if (neg == 1) num = (-num); d->map[*j] = num; printf("start = %d and i = %d and j = %d and num = %d\n", start, i, *j, num); ++*j; } neg = 0; printf(" Nouveau tour dans le while\n"); i++; nb_read++; } if (nb_read < d->line_length) complete_line(&*j, nb_read, d); printf(" FIN DE LA FONCTION PROPER LINE\n"); }
char *get_next_command(t_shell *shell) { if (shell->edit->prompt) ft_strdel(&(shell->edit)->prompt); shell->edit->prompt = print_prompt(shell, &shell->edit->prompt_len); ft_printf_fd(shell->edit->term->fd, "%s", shell->edit->prompt); if (get_input(shell->edit, &handle_key) == 0) clean_exit(shell->edit->term, 1, shell); if (shell->edit->term->term_name) { while (!is_closed(shell->edit->input, "\"'`([{") && interrupt(-1) == 0) complete_line(shell->edit); } if (!search_in_hist(shell->edit)) { goto_end_list(shell->edit); ft_strdel(&(shell->edit->hist)->line); return (NULL); } hist_update(shell->edit, 0); if (shell->edit->input && interrupt(-1) != 1) append_hist(shell->edit); return (shell->edit->input); }
static void complete_command (char *arg, int from_tty) { int argpoint; char **completions, *point, *arg_prefix; dont_repeat (); if (arg == NULL) arg = ""; argpoint = strlen (arg); /* complete_line assumes that its first argument is somewhere within, and except for filenames at the beginning of, the word to be completed. The following crude imitation of readline's word-breaking tries to accomodate this. */ point = arg + argpoint; while (point > arg) { if (strchr (rl_completer_word_break_characters, point[-1]) != 0) break; point--; } arg_prefix = alloca (point - arg + 1); memcpy (arg_prefix, arg, point - arg); arg_prefix[point - arg] = 0; completions = complete_line (point, arg, argpoint); if (completions) { int item, size; for (size = 0; completions[size]; ++size) ; qsort (completions, size, sizeof (char *), compare_strings); /* We do extra processing here since we only want to print each unique item once. */ item = 0; while (item < size) { int next_item; printf_unfiltered ("%s%s\n", arg_prefix, completions[item]); next_item = item + 1; while (next_item < size && ! strcmp (completions[item], completions[next_item])) { xfree (completions[next_item]); ++next_item; } xfree (completions[item]); item = next_item; } xfree (completions); } }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); if (x2 <= 0) return; /* ignore non-menu related input if active */ if (self->help->active) { help_onKey(self, key); return; } if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); return; } if (line_info_onKey(self, key)) return; input_handle(self, key, x, y, x2, y2); if (key == '\t') { /* TAB key: auto-completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { int diff = complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE); if (diff != -1) { if (x + diff > x2 - 1) { wmove(self->window, y, x + diff); ctx->start += diff; } else { wmove(self->window, y, x + diff); } } else { beep(); } } else { beep(); } } else if (key == '\n') { rm_trailing_spaces_buf(ctx); uint8_t line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0); execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); reset_buf(ctx); } }
static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); if (x2 <= 0 || y2 <= 0) return; if (self->help->active) { help_onKey(self, key); return; } if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); return; } if (line_info_onKey(self, key)) return; if (input_handle(self, key, x, y, x2, y2)) return; if (key == '\t') { /* TAB key: auto-completes peer name or command */ if (ctx->len > 0) { int diff; /* TODO: make this not suck */ if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) { diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH); } else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) { diff = dir_match(self, m, ctx->line, L"/avatar"); } else { diff = complete_line(self, group_cmd_list, AC_NUM_GROUP_COMMANDS, MAX_CMDNAME_SIZE); } if (diff != -1) { if (x + diff > x2 - 1) { int wlen = MAX(0, wcswidth(ctx->line, sizeof(ctx->line) / sizeof(wchar_t))); ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { sound_notify(self, notif_error, 0, NULL); } } else { sound_notify(self, notif_error, 0, NULL); } } else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */ int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST; if (groupchats[self->num].side_pos < groupchats[self->num].num_peers - L) ++groupchats[self->num].side_pos; } else if (key == user_settings->key_peer_list_up) { if (groupchats[self->num].side_pos > 0) --groupchats[self->num].side_pos; } else if (key == '\n') { rm_trailing_spaces_buf(ctx); char line[MAX_STR_SIZE]; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); if (line[0] == '/') { if (strcmp(line, "/close") == 0) { close_groupchat(self, m, self->num); return; } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { send_group_action(self, ctx, m, line + strlen("/me ")); } else { execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE); } } else if (!string_is_empty(line)) { if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) { const char *errmsg = " * Failed to send message."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg); } } wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); reset_buf(ctx); } }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) { PromptBuf *prt = self->promptbuf; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); /* BACKSPACE key: Remove one character from line */ if (key == 0x107 || key == 0x8 || key == 0x7f) { if (prt->pos > 0) { del_char_buf_bck(prt->line, &prt->pos, &prt->len); wmove(self->window, y, x-1); /* not necessary but fixes a display glitch */ prt->scroll = false; } else { beep(); } } else if (key == KEY_DC) { /* DEL key: Remove character at pos */ if (prt->pos != prt->len) { del_char_buf_frnt(prt->line, &prt->pos, &prt->len); prt->scroll = false; } else { beep(); } } else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */ if (prt->pos > 0) { wmove(self->window, prt->orig_y, X_OFST); wclrtobot(self->window); discard_buf(prt->line, &prt->pos, &prt->len); } else { beep(); } } else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */ if (prt->len != prt->pos) kill_buf(prt->line, &prt->pos, &prt->len); else beep(); } else if (key == KEY_HOME || key == T_KEY_C_A) { /* HOME/C-a key: Move cursor to start of line */ if (prt->pos != 0) prt->pos = 0; } else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */ if (prt->pos != prt->len) prt->pos = prt->len; } else if (key == KEY_LEFT) { if (prt->pos > 0) --prt->pos; else beep(); } else if (key == KEY_RIGHT) { if (prt->pos < prt->len) ++prt->pos; else beep(); } else if (key == KEY_UP) { /* fetches previous item in history */ wmove(self->window, prt->orig_y, X_OFST); fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot, &prt->hst_pos, LN_HIST_MV_UP); /* adjust line y origin appropriately when window scrolls down */ if (prt->at_bottom && prt->len >= x2 - X_OFST) { int px2 = prt->len >= x2 ? x2 : x2 - X_OFST; int p_ofst = px2 != x2 ? 0 : X_OFST; if (px2 <= 0) return; int k = prt->orig_y + ((prt->len + p_ofst) / px2); if (k >= y2) { wprintw(self->window, "\n"); --prt->orig_y; } } } else if (key == KEY_DOWN) { /* fetches next item in history */ wmove(self->window, prt->orig_y, X_OFST); fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot, &prt->hst_pos, LN_HIST_MV_DWN); } else if (key == '\t') { /* TAB key: completes command */ if (prt->len > 1 && prt->line[0] == '/') { if (complete_line(prt->line, &prt->pos, &prt->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE) == -1) beep(); } else { beep(); } } else #if HAVE_WIDECHAR if (iswprint(key)) #else if (isprint(key)) #endif { if (prt->len < (MAX_STR_SIZE-1)) { add_char_to_buf(prt->line, &prt->pos, &prt->len, key); prt->scroll = true; } } /* RETURN key: execute command */ else if (key == '\n') { wprintw(self->window, "\n"); uint8_t line[MAX_STR_SIZE]; if (wcs_to_mbs_buf(line, prt->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(prt->line, prt->len, prt->ln_history, &prt->hst_tot, &prt->hst_pos); execute(self->window, self, m, line, GLOBAL_COMMAND_MODE); reset_buf(prt->line, &prt->pos, &prt->len); } }
// This function takes a buffer and reads from the network. It will detect // SSL sessions, and read from an SSL struct if one is found. int session_readline(session_common_t *session) { char *place; int readin; int characters = 0; int length = config.in_buffer; #ifdef DEBUG_FRAMEWORK if (session == NULL) { lavalog("Passed an invalid pointer. This should never happen."); return -1; } #endif // Check to see if there are characters already in the buffer, and move them. if (session->current_line < session->buffered_bytes) { move_bytes(session->in_buffer, session->in_buffer + session->current_line, session->buffered_bytes - session->current_line); session->buffered_bytes -= session->current_line; characters = complete_line(session->in_buffer, session->buffered_bytes); } else { session->buffered_bytes = 0; } // Reset the current line counter, and advance the place holder to where we are supposed to write. session->current_line = 0; place = session->in_buffer + session->buffered_bytes; while (continue_processing(0) == 1 && !characters && length > session->buffered_bytes) { if (session->ssl) { readin = ssl_read(session->ssl, place, length - session->buffered_bytes); } else { readin = read(session->sock_descriptor, place, length - session->buffered_bytes); } if (readin < 0) { #ifdef DEBUG_FRAMEWORK lavalog("Received an error while reading from the socket."); #endif return -1; } else { session->buffered_bytes += readin; place += readin; } // Check whether we have a complete line to return yet. characters = complete_line(session->in_buffer, session->buffered_bytes); } // Tell the session how many characters are on the current line. if (length <= session->buffered_bytes) { return -1; } else { session->current_line = characters; } return characters; }
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; StatusBar *statusbar = self->stb; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); if (x2 <= 0) return; if (self->help->active) { help_onKey(self, key); return; } if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->is_online) set_self_typingstatus(self, m, 1); return; } if (line_info_onKey(self, key)) return; input_handle(self, key, x, y, x2, y2); if (key == '\t' && ctx->len > 1 && ctx->line[0] == '/') { /* TAB key: auto-complete */ int diff = -1; if (wcsncmp(ctx->line, L"/sendfile \"", wcslen(L"/sendfile \"")) == 0) { diff = dir_match(self, m, ctx->line); } else { diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE); } if (diff != -1) { if (x + diff > x2 - 1) { int wlen = wcswidth(ctx->line, sizeof(ctx->line)); ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { notify(self, error, 0); } } else if (key == '\n') { rm_trailing_spaces_buf(ctx); char line[MAX_STR_SIZE]; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); if (line[0] == '/') { if (strcmp(line, "/close") == 0) { kill_chat_window(self); return; } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { send_action(self, ctx, m, line + strlen("/me ")); } else { execute(ctx->history, self, m, line, CHAT_COMMAND_MODE); } } else if (!string_is_empty(line)) { char selfname[TOX_MAX_NAME_LENGTH]; uint16_t len = tox_get_self_name(m, (uint8_t *) selfname); selfname[len] = '\0'; char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, line); if (!statusbar->is_online || tox_send_message(m, self->num, (uint8_t *) line, strlen(line)) == 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message."); } else { write_to_log(line, selfname, ctx->log, false); } } wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); reset_buf(ctx); } if (ctx->len <= 0 && ctx->self_is_typing) set_self_typingstatus(self, m, 0); }
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) { ChatContext *ctx = self->chatwin; StatusBar *statusbar = self->stb; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); int cur_len = 0; if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key: Remove character behind pos */ if (ctx->pos > 0) { cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1])); del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len); if (x == 0) wmove(self->window, y-1, x2 - cur_len); else wmove(self->window, y, x - cur_len); } else { beep(); } } else if (key == KEY_DC) { /* DEL key: Remove character at pos */ if (ctx->pos != ctx->len) del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len); else beep(); } else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */ if (ctx->pos > 0) { discard_buf(ctx->line, &ctx->pos, &ctx->len); wmove(self->window, y2 - CURS_Y_OFFSET, 0); } else { beep(); } } else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */ if (ctx->pos != ctx->len) kill_buf(ctx->line, &ctx->pos, &ctx->len); else beep(); } else if (key == KEY_HOME) { /* HOME key: Move cursor to beginning of line */ if (ctx->pos > 0) { ctx->pos = 0; wmove(self->window, y2 - CURS_Y_OFFSET, 0); } } else if (key == KEY_END) { /* END key: move cursor to end of line */ if (ctx->pos != ctx->len) { ctx->pos = ctx->len; mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT-1)*x2)), y2, x2); } } else if (key == KEY_LEFT) { if (ctx->pos > 0) { --ctx->pos; cur_len = MAX(1, wcwidth(ctx->line[ctx->pos])); if (x == 0) wmove(self->window, y-1, x2 - cur_len); else wmove(self->window, y, x - cur_len); } else { beep(); } } else if (key == KEY_RIGHT) { if (ctx->pos < ctx->len) { cur_len = MAX(1, wcwidth(ctx->line[ctx->pos])); ++ctx->pos; if (x == x2-1) wmove(self->window, y+1, 0); else wmove(self->window, y, x + cur_len); } else { beep(); } } else if (key == KEY_UP) { /* fetches previous item in history */ fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, LN_HIST_MV_UP); mv_curs_end(self->window, ctx->len, y2, x2); } else if (key == KEY_DOWN) { /* fetches next item in history */ fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, LN_HIST_MV_DWN); mv_curs_end(self->window, ctx->len, y2, x2); } else if (key == '\t') { /* TAB key: completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { int diff = complete_line(ctx->line, &ctx->pos, &ctx->len, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE); if (diff != -1) { if (x + diff > x2 - 1) { int ofst = (x + diff - 1) - (x2 - 1); wmove(self->window, y+1, ofst); } else { wmove(self->window, y, x+diff); } } else { beep(); } } else { beep(); } } else #if HAVE_WIDECHAR if (iswprint(key)) #else if (isprint(key)) #endif { /* prevents buffer overflows and strange behaviour when cursor goes past the window */ if ( (ctx->len < MAX_STR_SIZE-1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1)-1)) ) { add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key); if (x == x2-1) wmove(self->window, y+1, 0); else wmove(self->window, y, x + MAX(1, wcwidth(key))); } } /* RETURN key: Execute command or print line */ else if (key == '\n') { uint8_t line[MAX_STR_SIZE]; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); wclrtobot(self->window); bool close_win = false; if (!string_is_empty(line)) add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos); if (line[0] == '/') { if (close_win = !strcmp(line, "/close")) { int f_num = self->num; delwin(ctx->linewin); delwin(statusbar->topline); del_window(self); disable_chatwin(f_num); } else if (strncmp(line, "/me ", strlen("/me ")) == 0) send_action(self, ctx, m, line + strlen("/me ")); else execute(ctx->history, self, m, line, CHAT_COMMAND_MODE); } else if (!string_is_empty(line)) { uint8_t selfname[TOX_MAX_NAME_LENGTH]; tox_get_self_name(m, selfname, TOX_MAX_NAME_LENGTH); print_time(ctx->history); wattron(ctx->history, COLOR_PAIR(GREEN)); wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(GREEN)); if (line[0] == '>') { wattron(ctx->history, COLOR_PAIR(GREEN)); wprintw(ctx->history, "%s\n", line); wattroff(ctx->history, COLOR_PAIR(GREEN)); } else wprintw(ctx->history, "%s\n", line); if (!statusbar->is_online || tox_send_message(m, self->num, line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(RED)); } } if (close_win) { free(ctx); free(statusbar); } else { reset_buf(ctx->line, &ctx->pos, &ctx->len); } } }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(ctx->history, y, x); getmaxyx(ctx->history, y2, x2); /* this is buggy */ //if (key == T_KEY_ESC) { /* ESC key: Toggle history scroll mode */ // bool scroll = ctx->hst->scroll_mode ? false : true; // line_info_toggle_scroll(self, scroll); //} /* If we're in scroll mode ignore rest of function */ if (ctx->hst->scroll_mode) { line_info_onKey(self, key); return; } /* BACKSPACE key: Remove one character from line */ if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len); wmove(ctx->history, y, x-1); /* not necessary but fixes a display glitch */ } else { beep(); } } else if (key == KEY_DC) { /* DEL key: Remove character at pos */ if (ctx->pos != ctx->len) { del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len); } else { beep(); } } else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */ if (ctx->pos > 0) { wmove(ctx->history, ctx->orig_y, X_OFST); wclrtobot(ctx->history); discard_buf(ctx->line, &ctx->pos, &ctx->len); } else { beep(); } } else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */ if (ctx->len != ctx->pos) kill_buf(ctx->line, &ctx->pos, &ctx->len); else beep(); } else if (key == KEY_HOME || key == T_KEY_C_A) { /* HOME/C-a key: Move cursor to start of line */ if (ctx->pos != 0) ctx->pos = 0; } else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */ if (ctx->pos != ctx->len) ctx->pos = ctx->len; } else if (key == KEY_LEFT) { if (ctx->pos > 0) --ctx->pos; else beep(); } else if (key == KEY_RIGHT) { if (ctx->pos < ctx->len) ++ctx->pos; else beep(); } else if (key == KEY_UP) { /* fetches previous item in history */ wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, MOVE_UP); /* adjust line y origin appropriately when window scrolls down */ if (ctx->at_bottom && ctx->len >= x2 - X_OFST) { int px2 = ctx->len >= x2 ? x2 : x2 - X_OFST; int p_ofst = px2 != x2 ? 0 : X_OFST; if (px2 <= 0) return; int k = ctx->orig_y + ((ctx->len + p_ofst) / px2); if (k >= y2) { --ctx->orig_y; } } } else if (key == KEY_DOWN) { /* fetches next item in history */ wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, MOVE_DOWN); } else if (key == '\t') { /* TAB key: completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { if (complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE) == -1) beep(); } else { beep(); } } else #if HAVE_WIDECHAR if (iswprint(key)) #else if (isprint(key)) #endif { if (ctx->len < (MAX_STR_SIZE-1)) { add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key); } } /* RETURN key: execute command */ else if (key == '\n') { wprintw(ctx->history, "\n"); uint8_t line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos); line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0); execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); reset_buf(ctx->line, &ctx->pos, &ctx->len); } }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); if (x2 <= 0) return; /* ignore non-menu related input if active */ if (self->help->active) { help_onKey(self, key); return; } if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); return; } if (line_info_onKey(self, key)) return; input_handle(self, key, x, y, x2, y2); if (key == '\t') { /* TAB key: auto-completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { int diff = -1; if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) diff = dir_match(self, m, ctx->line, L"/avatar"); else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0){ const char status_cmd_list[3][8] = { {"online"}, {"away"}, {"busy"}, }; diff = complete_line(self, status_cmd_list, 3, 8); } else diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE); if (diff != -1) { if (x + diff > x2 - 1) { int wlen = MAX(0, wcswidth(ctx->line, sizeof(ctx->line) / sizeof(wchar_t))); ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { sound_notify(self, notif_error, 0, NULL); } } else { sound_notify(self, notif_error, 0, NULL); } } else if (key == '\n') { rm_trailing_spaces_buf(ctx); char line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line); execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); reset_buf(ctx); } }