const char *vis_keys_next(Vis *vis, const char *keys) { if (!keys || !*keys) return NULL; TermKeyKey key; TermKey *termkey = vis->ui->termkey_get(vis->ui); const char *next = NULL; /* first try to parse a special key of the form <Key> */ if (*keys == '<' && (next = termkey_strpkey(termkey, keys+1, &key, TERMKEY_FORMAT_VIM)) && *next == '>') return next+1; if (*keys == '<') { const char *start = keys + 1, *end = start; while (*end && *end != '>') end++; if (end > start && end - start - 1 < 64 && *end == '>') { char key[64]; memcpy(key, start, end - start); key[end - start] = '\0'; if (map_get(vis->actions, key)) return end + 1; } } while (!ISUTF8(*keys)) keys++; return termkey_strpkey(termkey, keys, &key, TERMKEY_FORMAT_VIM); }
static uint32_t possibleEncodings(const char* s) { ALOGI("+possibleEncodings %s \n",s); uint32_t result = kEncodingAll; uint8_t ch1, ch2; uint8_t* chp = (uint8_t *)s; #ifndef ANDROID_DEFAULT_CODE //added by xu.lai for enhance if(*s!=0xFF){ if(ISUTF8(s)) return 0xFFFFFFFF; } else s++; if(*chp==0xFF) chp++; //added by xu.lai for enhance uint32_t uiISO8859 = kEncodingISO8859; int GBK_count=0; int BIG5_count=0; while ((ch1 = *chp++)) { if(ch1&0x80){ if(uiISO8859 && charMatchISO8859(ch1)){ uiISO8859 &= kEncodingISO8859; } else uiISO8859 = 0; ch2=*chp++; if(uiISO8859 && charMatchISO8859(ch2)){ uiISO8859 &= kEncodingISO8859; } else uiISO8859 = 0; int ch = (int)ch1 << 8 | (int)ch2; // ALOGD("ch %x \n",ch); result &= findPossibleEncodings(ch); // ALOGD("result %x \n",result); if(charMatchestest(ch,kGBKSWRanges,ARRAY_SIZE(kGBKSWRanges))) GBK_count++; if(charMatchestest(ch,kBig5SWRanges,ARRAY_SIZE(kBig5SWRanges))) BIG5_count++; } } // else ASCII character, which could be anything result |= uiISO8859; //contain the iso8859 info in the result // ALOGD("result 0x%x,GBK_count %d,BIG5_count %d \n",result,GBK_count,BIG5_count); /* //BIG5 & GBK enhance if(GBK_count|BIG5_count){ if(GBK_count>BIG5_count) result&=0xFFFB; else if(GBK_count<BIG5_count) result&=0xFFFD; } */ ALOGI("-possibleEncodings %d \n",result); #else while ((ch1 = *chp++)) { if (ch1 & 0x80) { ch2 = *chp++; ch1 = ((ch1 << 6) & 0xC0) | (ch2 & 0x3F); // ch1 is now the first byte of the potential native char ch2 = *chp++; if (ch2 & 0x80) ch2 = ((ch2 << 6) & 0xC0) | (*chp++ & 0x3F); // ch2 is now the second byte of the potential native char int ch = (int)ch1 << 8 | (int)ch2; result &= findPossibleEncodings(ch); } // else ASCII character, which could be anything } #endif return result; }
/* 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; }
Filerange text_range_union(const Filerange *r1, const Filerange *r2) { if (!text_range_valid(r1)) return *r2; if (!text_range_valid(r2)) return *r1; return (Filerange) { .start = MIN(r1->start, r2->start), .end = MAX(r1->end, r2->end), }; } Filerange text_range_new(size_t a, size_t b) { return (Filerange) { .start = MIN(a, b), .end = MAX(a, b), }; } bool text_range_equal(const Filerange *r1, const Filerange *r2) { if (!text_range_valid(r1) && !text_range_valid(r2)) return true; return r1->start == r2->start && r1->end == r2->end; } bool text_range_overlap(const Filerange *r1, const Filerange *r2) { if (!text_range_valid(r1) || !text_range_valid(r2)) return false; return r1->start <= r2->end && r2->start <= r1->end; } bool text_range_contains(const Filerange *r, size_t pos) { return text_range_valid(r) && r->start <= pos && pos <= r->end; } int text_char_count(const char *data, size_t len) { int count = 0; mbstate_t ps = { 0 }; while (len > 0) { wchar_t wc; size_t wclen = mbrtowc(&wc, data, len, &ps); if (wclen == (size_t)-1 && errno == EILSEQ) { count++; while (!ISUTF8(*data)) data++, len--; } else if (wclen == (size_t)-2) { break; } else if (wclen == 0) { count++; data++; len--; } else { int width = wcwidth(wc); if (width != 0) count++; data += wclen; len -= wclen; } } return count; } int text_string_width(const char *data, size_t len) { int width = 0; mbstate_t ps = { 0 }; const char *s = data; while (len > 0) { char buf[MB_CUR_MAX]; wchar_t wc; size_t wclen = mbrtowc(&wc, s, len, &ps); if (wclen == (size_t)-1 && errno == EILSEQ) { /* assume a replacement symbol will be displayed */ width++; wclen = 1; } else if (wclen == (size_t)-2) { /* do nothing, advance to next character */ wclen = 1; } else if (wclen == 0) { /* assume NUL byte will be displayed as ^@ */ width += 2; wclen = 1; } else if (buf[0] == '\t') { width++; wclen = 1; } else { int w = wcwidth(wc); if (w == -1) w = 2; /* assume non-printable will be displayed as ^{char} */ width += w; } len -= wclen; s += wclen; } return width; }