Example #1
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 #2
0
int viewglut_key(viewglut *P, int k, int d)
{
    double s = 5;
    int mine = 1;

    assert(P);

    if (d)
    {
        /* Interpret a key press. */

        switch (tolower(k))
        {
        case 27:
            exit(EXIT_SUCCESS);
            break;

        case  7:
            viewglut_grab();
            break;
        case  6:
            viewglut_fwd(P);
            break;
        case  2:
            viewglut_rev(P);
            break;

        case 16:
            view_prev(P->V);
            break;
        case 14:
            view_next(P->V);
            break;
        case  8:
            view_home(P->V);
            break;
        case 10:
            view_jump(P->V);
            break;

        case 19:
            view_save(P->V, VIEW_DAT);
            break;
        case 12:
            view_load(P->V, VIEW_DAT);
            break;

        case 18:
            view_remove(P->V);
            break;
        case  9:
            view_insert(P->V);
            break;
        case  3:
            view_clear (P->V);
            break;

        case 'd':
        case 'e':
            P->d[0] += s;
            break;
        case 'a':
            P->d[0] -= s;
            break;
        case 'r':
        case 'p':
            P->d[1] += s;
            break;
        case 'f':
        case 'u':
            P->d[1] -= s;
            break;
        case 's':
        case 'o':
            P->d[2] += s;
            break;
        case 'w':
        case ',':
            P->d[2] -= s;
            break;

        default:
            mine = 0; /* Not a viewglut key */
        }
    }
    else
    {
        /* Interpret a key release. */

        switch (tolower(k))
        {
        case 'd':
        case 'e':
            P->d[0] -= s;
            break;
        case 'a':
            P->d[0] += s;
            break;
        case 'r':
        case 'p':
            P->d[1] -= s;
            break;
        case 'f':
        case 'u':
            P->d[1] += s;
            break;
        case 's':
        case 'o':
            P->d[2] -= s;
            break;
        case 'w':
        case ',':
            P->d[2] += s;
            break;

        default:
            mine = 0; /* Not a viewglut key */
        }
    }

    if (mine)
    {
        view_move(P->V, P->d);
        glutPostRedisplay();
    }
    return mine;
}