Example #1
0
static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) {
	Win *prompt = vis->win;
	View *view = prompt->view;
	Text *txt = prompt->file->text;
	Win *win = prompt->parent;
	char *cmd = NULL;

	Filerange range = view_selection_get(view);
	if (!text_range_valid(&range))
		range = text_object_line(txt, view_cursor_get(view));
	if (text_range_valid(&range))
		cmd = text_bytes_alloc0(txt, range.start, text_range_size(&range));

	if (!win || !cmd) {
		vis_info_show(vis, "Prompt window invalid\n");
		prompt_restore(prompt);
		prompt_hide(prompt);
		free(cmd);
		return keys;
	}

	size_t len = strlen(cmd);
	if (len > 0 && cmd[len-1] == '\n')
		cmd[len-1] = '\0';

	bool lastline = (range.end == text_size(txt));

	prompt_restore(prompt);
	if (vis_prompt_cmd(vis, cmd)) {
		prompt_hide(prompt);
		if (!lastline) {
			text_delete(txt, range.start, text_range_size(&range));
			text_appendf(txt, "%s\n", cmd);
		}
	} else {
		vis->win = prompt;
		vis->mode = &vis_modes[VIS_MODE_INSERT];
	}
	free(cmd);
	vis_draw(vis);
	return keys;
}
Example #2
0
File: view.c Project: mulianov/vis
/* redraw the complete with data starting from view->start bytes into the file.
 * stop once the screen is full, update view->end, view->lastline */
void view_draw(View *view) {
	view_clear(view);
	/* current absolute file position */
	size_t pos = view->start;
	/* number of bytes to read in one go */
	size_t text_len = view->width * view->height;
	/* current buffer to work with */
	char text[text_len+1];
	/* remaining bytes to process in buffer*/
	size_t rem = text_bytes_get(view->text, pos, text_len, text);
	/* NUL terminate because regex(3) function expect it */
	text[rem] = '\0';
	/* current position into buffer from which to interpret a character */
	char *cur = text;
	/* current selection */
	Filerange sel = view_selection_get(view);
	/* syntax definition to use */
	Syntax *syntax = view->syntax;
	/* matched tokens for each syntax rule */
	regmatch_t match[syntax ? LENGTH(syntax->rules) : 1][1], *matched = NULL;
	memset(match, 0, sizeof match);
	/* default and current curses attributes to use */
	int default_attrs = COLOR_PAIR(0) | A_NORMAL, attrs = default_attrs;

	while (rem > 0) {

		/* current 'parsed' character' */
		wchar_t wchar;
		Cell cell;
		memset(&cell, 0, sizeof cell);
	
		if (syntax) {
			if (matched && cur >= text + matched->rm_eo) {
				/* end of current match */
				matched = NULL;
				attrs = default_attrs;
				for (int i = 0; i < LENGTH(syntax->rules); i++) {
					if (match[i][0].rm_so == -1)
						continue; /* no match on whole text */
					/* reset matches which overlap with matched */
					if (text + match[i][0].rm_so <= cur && cur < text + match[i][0].rm_eo) {
						match[i][0].rm_so = 0;
						match[i][0].rm_eo = 0;
					}
				}
			}

			if (!matched) {
				size_t off = cur - text; /* number of already processed bytes */
				for (int i = 0; i < LENGTH(syntax->rules); i++) {
					SyntaxRule *rule = &syntax->rules[i];
					if (!rule->rule)
						break;
					if (match[i][0].rm_so == -1)
						continue; /* no match on whole text */
					if (off >= (size_t)match[i][0].rm_eo) {
						/* past match, continue search from current position */
						if (regexec(&rule->regex, cur, 1, match[i], 0) ||
						    match[i][0].rm_so == match[i][0].rm_eo) {
							match[i][0].rm_so = -1;
							match[i][0].rm_eo = -1;
							continue;
						}
						match[i][0].rm_so += off;
						match[i][0].rm_eo += off;
					}

					if (text + match[i][0].rm_so <= cur && cur < text + match[i][0].rm_eo) {
						/* within matched expression */
						matched = &match[i][0];
						attrs = rule->color->attr;
						break; /* first match views */
					}
				}
			}
		}

		size_t len = mbrtowc(&wchar, cur, rem, NULL);
		if (len == (size_t)-1 && errno == EILSEQ) {
			/* ok, we encountered an invalid multibyte sequence,
			 * replace it with the Unicode Replacement Character
			 * (FFFD) and skip until the start of the next utf8 char */
			for (len = 1; rem > len && !ISUTF8(cur[len]); len++);
			cell = (Cell){ .data = "\xEF\xBF\xBD", .len = len, .width = 1, .istab = false };
		} else if (len == (size_t)-2) {
			/* not enough bytes available to convert to a
			 * wide character. advance file position and read
			 * another junk into buffer.
			 */
			rem = text_bytes_get(view->text, pos, text_len, text);
			text[rem] = '\0';
			cur = text;
			continue;
		} else if (len == 0) {
			/* NUL byte encountered, store it and continue */
			cell = (Cell){ .data = "\x00", .len = 1, .width = 0, .istab = false };
		} else {
			for (size_t i = 0; i < len; i++)
				cell.data[i] = cur[i];
			cell.data[len] = '\0';
			cell.istab = false;
			cell.len = len;
			cell.width = wcwidth(wchar);
			if (cell.width == -1)
				cell.width = 1;
		}

		if (cur[0] == '\r' && rem > 1 && cur[1] == '\n') {
			/* convert views style newline \r\n into a single char with len = 2 */
			cell = (Cell){ .data = "\n", .len = 2, .width = 1, .istab = false };
		}

		cell.attr = attrs;
		if (sel.start <= pos && pos < sel.end)
			cell.attr |= A_REVERSE;
		if (!view_addch(view, &cell))
			break;

 		rem -= cell.len;
		cur += cell.len;
		pos += cell.len;
	}
Example #3
0
static void ui_window_draw(UiWin *w) {
    UiCursesWin *win = (UiCursesWin*)w;
    if (!ui_window_draw_sidebar(win))
        return;

    debug("ui-win-draw[%s]\n", win->file->name ? win->file->name : "noname");
    wbkgd(win->win, style_to_attr(&win->styles[UI_STYLE_DEFAULT]));
    wmove(win->win, 0, 0);
    int width = view_width_get(win->view);
    CellStyle *prev_style = NULL;
    size_t cursor_lineno = -1;

    if (win->options & UI_OPTION_CURSOR_LINE && win->ui->selwin == win) {
        Filerange selection = view_selection_get(win->view);
        if (!view_cursors_multiple(win->view) && !text_range_valid(&selection)) {
            const Line *line = view_line_get(win->view);
            cursor_lineno = line->lineno;
        }
    }

    short selection_bg = win->styles[UI_STYLE_SELECTION].bg;
    short cursor_line_bg = win->styles[UI_STYLE_CURSOR_LINE].bg;
    bool multiple_cursors = view_cursors_multiple(win->view);
    attr_t attr = A_NORMAL;

    for (const Line *l = view_lines_get(win->view); l; l = l->next) {
        bool cursor_line = l->lineno == cursor_lineno;
        for (int x = 0; x < width; x++) {
            enum UiStyle style_id = l->cells[x].style;
            if (style_id == 0)
                style_id = UI_STYLE_DEFAULT;
            CellStyle *style = &win->styles[style_id];

            if (l->cells[x].cursor && win->ui->selwin == win) {
                if (multiple_cursors && l->cells[x].cursor_primary)
                    attr = style_to_attr(&win->styles[UI_STYLE_CURSOR_PRIMARY]);
                else
                    attr = style_to_attr(&win->styles[UI_STYLE_CURSOR]);
                prev_style = NULL;
            } else if (l->cells[x].selected) {
                if (style->fg == selection_bg)
                    attr |= A_REVERSE;
                else
                    attr = style->attr | COLOR_PAIR(color_pair_get(style->fg, selection_bg));
                prev_style = NULL;
            } else if (cursor_line) {
                attr = style->attr | COLOR_PAIR(color_pair_get(style->fg, cursor_line_bg));
                prev_style = NULL;
            } else if (style != prev_style) {
                attr = style_to_attr(style);
                prev_style = style;
            }
            wattrset(win->win, attr);
            waddstr(win->win, l->cells[x].data);
        }
        /* try to fixup display issues, in theory we should always output a full line */
        int x, y;
        getyx(win->win, y, x);
        (void)y;
        wattrset(win->win, A_NORMAL);
        for (; 0 < x && x < width; x++)
            waddstr(win->win, " ");
    }

    wclrtobot(win->win);
}