Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/vt/vt_buf.c
Show First 20 Lines • Show All 740 Lines • ▼ Show 20 Lines | vtbuf_get_marked_len(struct vt_buf *vb) | ||||
si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; | si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col; | ||||
ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; | ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col; | ||||
/* Number symbols and number of rows to inject \r */ | /* Number symbols and number of rows to inject \r */ | ||||
sz = ei - si + (e.tp_row - s.tp_row); | sz = ei - si + (e.tp_row - s.tp_row); | ||||
return (sz * sizeof(term_char_t)); | return (sz * sizeof(term_char_t)); | ||||
} | } | ||||
#endif | |||||
static bool | static bool | ||||
tchar_is_word_separator(term_char_t ch) | tchar_is_word_separator(term_char_t ch) | ||||
{ | { | ||||
/* List of unicode word separator characters: */ | /* List of unicode word separator characters: */ | ||||
switch (TCHAR_CHARACTER(ch)) { | switch (TCHAR_CHARACTER(ch)) { | ||||
case 0x0020: /* SPACE */ | case 0x0020: /* SPACE */ | ||||
case 0x180E: /* MONGOLIAN VOWEL SEPARATOR */ | case 0x180E: /* MONGOLIAN VOWEL SEPARATOR */ | ||||
case 0x2002: /* EN SPACE (nut) */ | case 0x2002: /* EN SPACE (nut) */ | ||||
case 0x2003: /* EM SPACE (mutton) */ | case 0x2003: /* EM SPACE (mutton) */ | ||||
case 0x2004: /* THREE-PER-EM SPACE (thick space) */ | case 0x2004: /* THREE-PER-EM SPACE (thick space) */ | ||||
case 0x2005: /* FOUR-PER-EM SPACE (mid space) */ | case 0x2005: /* FOUR-PER-EM SPACE (mid space) */ | ||||
case 0x2006: /* SIX-PER-EM SPACE */ | case 0x2006: /* SIX-PER-EM SPACE */ | ||||
case 0x2008: /* PUNCTUATION SPACE */ | case 0x2008: /* PUNCTUATION SPACE */ | ||||
case 0x2009: /* THIN SPACE */ | case 0x2009: /* THIN SPACE */ | ||||
case 0x200A: /* HAIR SPACE */ | case 0x200A: /* HAIR SPACE */ | ||||
case 0x200B: /* ZERO WIDTH SPACE */ | case 0x200B: /* ZERO WIDTH SPACE */ | ||||
case 0x3000: /* IDEOGRAPHIC SPACE */ | case 0x3000: /* IDEOGRAPHIC SPACE */ | ||||
return (true); | return (true); | ||||
default: | default: | ||||
return (false); | return (false); | ||||
} | } | ||||
} | } | ||||
static bool | |||||
vtbuf_extract_utf8(term_char_t ch, char *buffer, size_t *ppos, size_t size) | |||||
{ | |||||
char temp[4]; | |||||
size_t len; | |||||
ch = TCHAR_CHARACTER(ch); | |||||
/* Convert to UTF-8. */ | |||||
if (ch < 0x80) { | |||||
temp[0] = ch; | |||||
len = 1; | |||||
} else if (ch < 0x800) { | |||||
temp[0] = 0xc0 | (ch >> 6); | |||||
temp[1] = 0x80 | (ch & 0x3f); | |||||
len = 2; | |||||
} else if (ch < 0x10000) { | |||||
temp[0] = 0xe0 | (ch >> 12); | |||||
temp[1] = 0x80 | ((ch >> 6) & 0x3f); | |||||
temp[2] = 0x80 | (ch & 0x3f); | |||||
len = 3; | |||||
} else { | |||||
temp[0] = 0xf0 | (ch >> 18); | |||||
temp[1] = 0x80 | ((ch >> 12) & 0x3f); | |||||
temp[2] = 0x80 | ((ch >> 6) & 0x3f); | |||||
temp[3] = 0x80 | (ch & 0x3f); | |||||
len = 4; | |||||
} | |||||
/* | |||||
* Make sure everything fits into the buffer. | |||||
*/ | |||||
if (*ppos + len > size) | |||||
return (false); | |||||
memcpy(buffer + *ppos, temp, len); | |||||
*ppos += len; | |||||
return (true); | |||||
} | |||||
static const char vt_access_overflow[] = { "Line is not accessible" }; | |||||
int | |||||
vtbuf_extract_accessibility(char *buffer, size_t *ppos, term_pos_t *cursor, | |||||
size_t lines, size_t bufsz) | |||||
{ | |||||
struct vt_device *vd; | |||||
struct vt_window *vw; | |||||
struct vt_buf *vb; | |||||
term_pos_t max; | |||||
term_char_t ch; | |||||
size_t lines_old; | |||||
size_t last_sep_off; | |||||
size_t last_line_off; | |||||
int last_sep_col; | |||||
int c; | |||||
int i; | |||||
int r; | |||||
MPASS(bufsz != 0); | |||||
MPASS(lines != 0); | |||||
vd = main_vd; | |||||
if (vd == NULL) | |||||
return (EINVAL); | |||||
vw = vd->vd_curwindow; | |||||
if (vw == NULL) | |||||
return (EINVAL); | |||||
vb = &vw->vw_buf; | |||||
max = vb->vb_scr_size; | |||||
lines_old = lines; | |||||
/* set default cursor */ | |||||
cursor->tp_row = 0; | |||||
cursor->tp_col = 0; | |||||
VTBUF_LOCK(vb); | |||||
for (i = 0; lines != 0 && i != max.tp_row; i++) { | |||||
/* Get real row number in VT buffer. */ | |||||
r = (vb->vb_roffset + i) % vb->vb_history_size; | |||||
/* Find first character, get whole word, if any. */ | |||||
for (c = 0; c != max.tp_col; c++) { | |||||
ch = vb->vb_rows[r][c]; | |||||
if (TCHAR_ACCESSIBILITY(ch) != 0 || | |||||
TCHAR_CHARACTER(ch) == 0) | |||||
continue; | |||||
if (tchar_is_word_separator(ch)) | |||||
break; | |||||
/* Go back a bit to get context, if any. */ | |||||
while (c != 0) { | |||||
c--; | |||||
ch = vb->vb_rows[r][c]; | |||||
if (TCHAR_CHARACTER(ch) == 0) | |||||
continue; | |||||
if (tchar_is_word_separator(ch)) | |||||
break; | |||||
} | |||||
break; | |||||
} | |||||
if (c == max.tp_col) | |||||
continue; | |||||
if (lines == lines_old) { | |||||
cursor->tp_row = i; | |||||
cursor->tp_col = c; | |||||
} | |||||
lines--; | |||||
last_sep_col = c; | |||||
last_sep_off = *ppos; | |||||
last_line_off = *ppos; | |||||
/* Try to output line. */ | |||||
for( ; c != max.tp_col; c++) { | |||||
ch = vb->vb_rows[r][c]; | |||||
if (TCHAR_CHARACTER(ch) == 0) | |||||
continue; | |||||
if (tchar_is_word_separator(ch)) { | |||||
if (vtbuf_extract_utf8(ch, buffer, ppos, bufsz) == false) | |||||
break; | |||||
/* Keep track of sensible stop locations. */ | |||||
last_sep_col = c + 1; | |||||
last_sep_off = *ppos; | |||||
} else { | |||||
if (vtbuf_extract_utf8(ch, buffer, ppos, bufsz) == false) | |||||
break; | |||||
} | |||||
} | |||||
/* Check if buffer is full (whole line was not consumed). */ | |||||
if (c != max.tp_col) { | |||||
/* Check if this is the first line. */ | |||||
if (last_line_off == 0) { | |||||
/* XXX Pretend line was consumed. */ | |||||
*ppos = last_line_off; | |||||
c = max.tp_col; | |||||
for (size_t i = 0; vt_access_overflow[i]; i++) { | |||||
if (vtbuf_extract_utf8(vt_access_overflow[i], | |||||
buffer, ppos, bufsz) == false) | |||||
break; | |||||
} | |||||
} else { | |||||
/* Stop at last separator, if any. */ | |||||
*ppos = last_sep_off; | |||||
c = last_sep_col; | |||||
} | |||||
/* Don't output this part again. */ | |||||
while (c--) | |||||
vb->vb_rows[r][c] |= TACCESSIBILITY; | |||||
break; | |||||
} else { | |||||
/* Don't output this line again. */ | |||||
while (c--) | |||||
vb->vb_rows[r][c] |= TACCESSIBILITY; | |||||
/* Remove trailing white space. */ | |||||
while (*ppos != last_line_off && buffer[*ppos - 1] == ' ') | |||||
(*ppos)--; | |||||
if (*ppos == last_line_off) { | |||||
/* Grab another line, this one is empty. */ | |||||
lines++; | |||||
} else { | |||||
/* Insert a word separator, just in case. */ | |||||
if (vtbuf_extract_utf8(' ', buffer, ppos, bufsz)) | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
VTBUF_UNLOCK(vb); | |||||
/* Remove trailing white space from last line. */ | |||||
while (*ppos != 0 && buffer[*ppos - 1] == ' ') | |||||
(*ppos)--; | |||||
return (lines != lines_old ? 0 : ENOENT); | |||||
} | |||||
#ifndef SC_NO_CUTPASTE | |||||
void | void | ||||
vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) | vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz) | ||||
{ | { | ||||
int i, j, r, c, cs, ce; | int i, j, r, c, cs, ce; | ||||
term_pos_t s, e; | term_pos_t s, e; | ||||
/* Swap according to window coordinates. */ | /* Swap according to window coordinates. */ | ||||
if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), | if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row), | ||||
▲ Show 20 Lines • Show All 145 Lines • Show Last 20 Lines |