Example #1
0
// 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;
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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");
}
Example #5
0
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);
}
Example #6
0
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);
    }
}
Example #7
0
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);
    }
}
Example #8
0
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);
    }
}
Example #9
0
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);
    }
}
Example #10
0
// 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;
}
Example #11
0
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);
}
Example #12
0
File: chat.c Project: alevy/toxic
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);
        }
    }
}
Example #13
0
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);
    }
}
Example #14
0
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);
    }
}