std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width) { std::wstring s(str); if (!Config.header_text_scrolling) return s; std::wstring result; size_t len = wideLength(s); if (len > width) { s += L" ** "; len = 0; auto b = s.begin(), e = s.end(); for (auto it = b+pos; it < e && len < width; ++it) { if ((len += wcwidth(*it)) > width) break; result += *it; } if (++pos >= s.length()) pos = 0; for (; len < width; ++b) { if ((len += wcwidth(*b)) > width) break; result += *b; } } else result = s; return result; }
/* This function is equivalent to wcwidth() for multibyte characters. */ int mbwidth(const char *c) { assert(c != NULL); #ifdef ENABLE_UTF8 if (use_utf8) { wchar_t wc; int width; if (mbtowc(&wc, c, MB_CUR_MAX) < 0) { mbtowc_reset(); wc = bad_wchar; } width = wcwidth(wc); if (width == -1) { wc = bad_wchar; width = wcwidth(wc); } return width; } else #endif return 1; }
static void cmd_ctrl_h(key_info_t key_info, keys_info_t *keys_info) { input_stat.history_search = HIST_NONE; stop_completion(); if(input_stat.index == 0 && input_stat.len == 0 && sub_mode != PROMPT_SUBMODE) { cmd_ctrl_c(key_info, keys_info); return; } if(input_stat.index == 0) return; if(input_stat.index == input_stat.len) { input_stat.index--; input_stat.len--; input_stat.curs_pos -= wcwidth(input_stat.line[input_stat.index]); input_stat.line[input_stat.index] = L'\0'; } else { input_stat.index--; input_stat.len--; input_stat.curs_pos -= wcwidth(input_stat.line[input_stat.index]); wcsdel(input_stat.line, input_stat.index + 1, 1); } update_cmdline_text(); }
std::wstring wideShorten(const std::wstring &ws, size_t max_length) { std::wstring result; if (wideLength(ws) > max_length) { const size_t half_max = max_length/2 - 1; size_t len = 0; // get beginning of string for (auto it = ws.begin(); it != ws.end(); ++it) { len += wcwidth(*it); if (len > half_max) break; result += *it; } len = 0; std::wstring end; // get end of string in reverse order for (auto it = ws.rbegin(); it != ws.rend(); ++it) { len += wcwidth(*it); if (len > half_max) break; end += *it; } // apply end of string to its beginning result += L".."; result.append(end.rbegin(), end.rend()); } else result = ws; return result; }
std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, size_t &pos, size_t width) { std::basic_string<my_char_t> s(str); if (!Config.header_text_scrolling) return s; std::basic_string<my_char_t> result; size_t len = Window::Length(s); if (len > width) { s += U(" ** "); len = 0; std::basic_string<my_char_t>::const_iterator b = s.begin(), e = s.end(); for (std::basic_string<my_char_t>::const_iterator it = b+pos; it < e && len < width; ++it) { if ((len += wcwidth(*it)) > width) break; result += *it; } if (++pos >= s.length()) pos = 0; for (; len < width; ++b) { if ((len += wcwidth(*b)) > width) break; result += *b; } } else result = s; return result; }
void wbkgrndset(WINDOW *win, const cchar_t *wch) { attr_t battr; nschar_t *np, *tnp; unsigned int i; /* ignore multi-column characters */ if ( !wch->elements || wcwidth( wch->vals[ 0 ]) > 1 ) return; /* Background character. */ tnp = np = win->bnsp; if ( wcwidth( wch->vals[ 0 ])) win->bch = wch->vals[ 0 ]; else { if ( !np ) { np = (nschar_t *)malloc(sizeof(nschar_t)); if (!np) return; np->next = NULL; win->bnsp = np; } np->ch = wch->vals[ 0 ]; tnp = np; np = np->next; } /* add non-spacing characters */ if ( wch->elements > 1 ) { for ( i = 1; i < wch->elements; i++ ) { if ( !np ) { np = (nschar_t *)malloc(sizeof(nschar_t)); if (!np) return; np->next = NULL; if ( tnp ) tnp->next = np; else win->bnsp = np; } np->ch = wch->vals[ i ]; tnp = np; np = np->next; } } /* clear the old non-spacing characters */ while ( np ) { tnp = np->next; free( np ); np = tnp; } /* Background attributes (check colour). */ battr = wch->attributes & WA_ATTRIBUTES; if (__using_color && !( battr & __COLOR)) battr |= __default_color; win->battr = battr; SET_BGWCOL((*win), 1); }
/* output a string, but wrap words properly with a specified indentation */ void indentprint(const char *str, unsigned short indent, unsigned short cols) { wchar_t *wcstr; const wchar_t *p; size_t len, cidx; if(!str) { return; } /* if we're not a tty, or our tty is not wide enough that wrapping even makes * sense, print without indenting */ if(cols == 0 || indent > cols) { fputs(str, stdout); return; } len = strlen(str) + 1; wcstr = calloc(len, sizeof(wchar_t)); len = mbstowcs(wcstr, str, len); p = wcstr; cidx = indent; if(!p || !len) { return; } while(*p) { if(*p == L' ') { const wchar_t *q, *next; p++; if(p == NULL || *p == L' ') continue; next = wcschr(p, L' '); if(next == NULL) { next = p + wcslen(p); } /* len captures # cols */ len = 0; q = p; while(q < next) { len += wcwidth(*q++); } if((len + 1) > (cols - cidx)) { /* wrap to a newline and reindent */ printf("\n%-*s", (int)indent, ""); cidx = indent; } else { printf(" "); cidx++; } continue; } printf("%lc", (wint_t)*p); cidx += wcwidth(*p); p++; } free(wcstr); }
void writeCyclicBuffer(const NC::WBuffer &buf, NC::Window &w, size_t &start_pos, size_t width, const std::wstring &separator) { const auto &s = buf.str(); size_t len = wideLength(s); if (len > width) { len = 0; const auto &ps = buf.properties(); auto p = ps.begin(); // load attributes from before starting pos for (; p != ps.end() && p->position() < start_pos; ++p) w << *p; auto write_buffer = [&](size_t start) { for (size_t i = start; i < s.length() && len < width; ++i) { for (; p != ps.end() && p->position() == i; ++p) w << *p; len += wcwidth(s[i]); if (len > width) break; w << s[i]; } for (; p != ps.end(); ++p) w << *p; p = ps.begin(); }; write_buffer(start_pos); size_t i = 0; if (start_pos > s.length()) i = start_pos - s.length(); for (; i < separator.length() && len < width; ++i) { len += wcwidth(separator[i]); if (len > width) break; w << separator[i]; } write_buffer(0); ++start_pos; if (start_pos >= s.length() + separator.length()) start_pos = 0; } else w << buf; }
static unsigned int compute_len_from_width(const wchar_t *p, unsigned int width) { unsigned int len = 0; unsigned int end_loop = 0; while (p && *p && !end_loop) { if (wcwidth(*p) > width) { end_loop = 1; } else { width -= wcwidth(*p); p++; len++; } } return len; }
int xwaddnstr (WINDOW *win, const char *str, const int n) { int res, width, inv_char; wchar_t *ucs; char *mstr, *lstr; size_t size, num_chars; assert (n > 0); assert (str != NULL); mstr = iconv_str (iconv_desc, str); size = xmbstowcs (NULL, mstr, -1, NULL) + 1; ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size); xmbstowcs (ucs, mstr, size, &inv_char); width = wcswidth (ucs, WIDTH_MAX); if (width == -1) { size_t clidx; for (clidx = 0; clidx < size - 1; clidx++) { if (wcwidth (ucs[clidx]) == -1) ucs[clidx] = L'?'; } width = wcswidth (ucs, WIDTH_MAX); inv_char = 1; } if (width > n) { while (width > n) width -= wcwidth (ucs[--size]); ucs[size] = L'\0'; } num_chars = wcstombs (NULL, ucs, 0); lstr = (char *)xmalloc (num_chars + 1); if (inv_char) wcstombs (lstr, ucs, num_chars + 1); else snprintf (lstr, num_chars + 1, "%s", mstr); res = waddstr (win, lstr); free (ucs); free (lstr); free (mstr); return res; }
/** * Validates data needed for text scrolling in widget * * @param __edit - edit for which validate scrolling information */ static void edit_validate_scrolling (w_edit_t *__edit) { if (!__edit) { return; } size_t scrolled = __edit->scrolled, i; /* Relative position of caret */ size_t caret_pos_rel = __edit->caret_pos - scrolled + 1; for (i = scrolled; i < __edit->caret_pos; ++i) { caret_pos_rel += wcwidth (__edit->text.data[i]) - 1; } /* Cursor is far too left */ if (__edit->caret_pos < __edit->scrolled) { __edit->scrolled = __edit->caret_pos; } else { /* Cursor is far too right */ if (caret_pos_rel >= __edit->position.width) { __edit->scrolled += caret_pos_rel - __edit->position.width; } } }
static void loadLanguageList(void) { char * file = "/etc/lang-table"; FILE * f; char line[256]; char name[256], key[256], font[256], code[256], keyboard[256], timezone[256]; int lineNum = 0; wcwidth(0); f = fopen(file, "r"); if (!f) { newtWinMessage(_("Error"), _("OK"), "cannot open %s: %m", file); return; } while (fgets(line, sizeof(line), f)) { lineNum++; languages = realloc(languages, sizeof(*languages) * (numLanguages + 1)); if (sscanf(line, "%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\n", name, key, font, code, keyboard, timezone) != 6) { printf("bad line %d in lang-table", lineNum); logMessage(WARNING, "bad line %d in lang-table", lineNum); } else { languages[numLanguages].lang = strdup(name); languages[numLanguages].key = strdup(key); languages[numLanguages].font = strdup(font); languages[numLanguages].lc_all = strdup(code); languages[numLanguages++].keyboard = strdup(keyboard); } } fclose(f); }
/* Return a malloc()ed string containing the tail of 'str' up to a * maximum of 'len' characters (in columns occupied on the screen). */ char *xstrtail (const char *str, const int len) { wchar_t *ucs; wchar_t *ucs_tail; size_t size; int width; char *tail; assert (str != NULL); assert (len > 0); size = xmbstowcs(NULL, str, -1, NULL) + 1; ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size); xmbstowcs (ucs, str, size, NULL); ucs_tail = ucs; width = wcswidth (ucs, WIDTH_MAX); assert (width >= 0); while (width > len) width -= wcwidth (*ucs_tail++); size = wcstombs (NULL, ucs_tail, 0) + 1; tail = (char *)xmalloc (size); wcstombs (tail, ucs_tail, size); free (ucs); return tail; }
static int putxy(WINDOW *win, int width, int *i, int *y, int *x, char *str) { if ((unsigned char) str[0] > 0x7F) { wchar_t dest[2]; int bytes = mbtowc(dest, &str[0], 3) - 1; if (bytes >= 0) { /* To deal with non-latin characters that can take up more than one character's alotted width, with offset x by wcwidth(character) rather than 1 */ /* Took me forever to find that function, thanks Andreas (newsbeuter) for that one. */ int rwidth = wcwidth(dest[0]); if (rwidth < 0) rwidth = 1; if (rwidth > (width - *x)) return 1; dest[1] = 0; mvwaddwstr(win, *y, *x, dest); *x += rwidth; *i += bytes; } } else mvwaddch(win, *y, (*x)++, str[0]); return 0; }
static void putline(FILE *file, char *start, int num) { char *cp, *end; int i, len, d_col; wchar_t wc; cp = start; end = cp + num; while (cp < end) { if (isascii(*cp)) { (void) putc(*cp++, file); continue; } if ((len = end - cp) > MB_LEN_MAX) len = MB_LEN_MAX; if ((len = mbtowc(&wc, cp, len)) <= 0) { (void) putc(*cp++, file); continue; } if ((d_col = wcwidth(wc)) <= 0) d_col = len; if ((cp + d_col) > end) return; for (i = 0; i < len; i++) (void) putc(*cp++, file); } }
/* * Experimental variant: use wide characters * (we assume UTF-8 encoding) * * We assume that int is large enough to store any character. * To do this properly, we should use wint_t. */ static int file_reader_next_wchar(reader_t *reader) { wint_t c; assert(reader->is_stream); if (reader->current == EOF) { return EOF; } if (reader->current == '\n') { // this should works in UTF-8? reader->line ++; reader->column ++; } #if defined(LINUX) c = fgetwc_unlocked(reader->input.stream); #else c = fgetwc(reader->input.stream); #endif if (c == WEOF) { reader->current = EOF; } else { reader->current = c; reader->pos ++; reader->column += wcwidth(c); } return c; }
/** * mutt_strwidth - Measure a string's width in screen cells * @param s String to be measured * @retval num Screen cells string would use */ int mutt_strwidth(const char *s) { wchar_t wc; int w; size_t k, n; mbstate_t mbstate; if (!s) return 0; n = mutt_str_strlen(s); memset(&mbstate, 0, sizeof(mbstate)); for (w = 0; n && (k = mbrtowc(&wc, s, n, &mbstate)); s += k, n -= k) { if (*s == MUTT_SPECIAL_INDEX) { s += 2; /* skip the index coloring sequence */ k = 0; continue; } if ((k == (size_t)(-1)) || (k == (size_t)(-2))) { if (k == (size_t)(-1)) memset(&mbstate, 0, sizeof(mbstate)); k = (k == (size_t)(-1)) ? 1 : n; wc = ReplacementChar; } if (!IsWPrint(wc)) wc = '?'; w += wcwidth(wc); } return w; }
VALUE tui_wcwidth(VALUE self, VALUE glyph) { long ig; int res; ig = FIX2LONG(glyph); res = wcwidth(ig); return INT2FIX(res); }
/* re_putc(): * Draw the character given */ libedit_private void re_putc(EditLine *el, wint_t c, int shift) { coord_t *cur = &el->el_refresh.r_cursor; int i, w = wcwidth(c); int sizeh = el->el_terminal.t_size.h; ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c)); if (w == -1) w = 0; while (shift && (cur->h + w > sizeh)) re_putc(el, ' ', 1); el->el_vdisplay[cur->v][cur->h] = c; /* assumes !shift is only used for single-column chars */ i = w; while (--i > 0) el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR; if (!shift) return; cur->h += w; /* advance to next place */ if (cur->h >= sizeh) { /* assure end of line */ el->el_vdisplay[cur->v][sizeh] = '\0'; re_nextline(el); } }
int mbsprint(const char *mbs, int print) { wchar_t wc; int len; /* length in bytes of UTF-8 encoded string */ int width; /* display width of a single Unicode char */ int total_width; /* display width of the whole string */ for (total_width = 0; *mbs != '\0'; mbs += len) { if ((len = mbtowc(&wc, mbs, MB_CUR_MAX)) == -1) { (void)mbtowc(NULL, NULL, MB_CUR_MAX); if (print) putchar(f_nonprint ? '?' : *mbs); total_width++; len = 1; } else if ((width = wcwidth(wc)) == -1) { if (print) { if (f_nonprint) putchar('?'); else fwrite(mbs, 1, len, stdout); } total_width++; } else { if (print) fwrite(mbs, 1, len, stdout); total_width += width; } } return total_width; }
static int theme_strlen(char *message, char end) { int len = 0; int i = 0; while ((message[i] != end) && (message[i] != 0)) { if (message[i] == '%') { i++; } else if (message[i] == '\\') { i++; len++; } else if ((unsigned char) message[i] > 0x7f) { wchar_t dest[2]; int bytes = mbtowc(dest, &message[i], 3) - 1; if (bytes >= 0) { int rwidth = wcwidth(dest[0]); if(rwidth < 0) rwidth = 1; i += bytes; len += rwidth; } else { i++; len += 1; } } else if (message[i] != '\n') len++; i++; } return len; }
/* * Update the current column position for a character. */ static int newpos(int col, wint_t ch) { char buf[MB_LEN_MAX]; size_t len; int w; if (bflag) { len = wcrtomb(buf, ch, NULL); col += len; } else switch (ch) { case '\b': if (col > 0) --col; break; case '\r': col = 0; break; case '\t': col = (col + 8) & ~7; break; default: if ((w = wcwidth(ch)) > 0) col += w; break; } return (col); }
int main(void) { int wc; int i, n; if (setlocale(LC_CTYPE, "en_US.utf8") == NULL) if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) return 1; for (wc = 0; wc <= 0xffff; wc++) { if ((wc&017) == 0) printf("U+%04X ", wc); if (wc < 040) n = printf("%s", ctl[wc]); else if (wc == 0177) n = printf("del"); else if (wc >= 0200 && wc < 0240) n = printf("CTL"); else if (iswprint(wc)) { if ((n = wcwidth(wc)) == 0) n = 1; printf("%lc", wc); } else n = 0; for (i = n; i < 4; i++) putchar(' '); if ((wc+1&017) == 0) putchar('\n'); } return 0; }
/** * mutt_paddstr - Display a string on screen, padded if necessary * @param n Final width of field * @param s String to display */ void mutt_paddstr(int n, const char *s) { wchar_t wc; size_t k; size_t len = mutt_str_strlen(s); mbstate_t mbstate; memset(&mbstate, 0, sizeof(mbstate)); for (; len && (k = mbrtowc(&wc, s, len, &mbstate)); s += k, len -= k) { if ((k == (size_t)(-1)) || (k == (size_t)(-2))) { if (k == (size_t)(-1)) memset(&mbstate, 0, sizeof(mbstate)); k = (k == (size_t)(-1)) ? 1 : len; wc = ReplacementChar; } if (!IsWPrint(wc)) wc = '?'; const int w = wcwidth(wc); if (w >= 0) { if (w > n) break; addnstr((char *) s, k); n -= w; } } while (n-- > 0) addch(' '); }
/* Calculate display width of an UTF-8 string */ int utf8_width(char *str) { int w = 0; size_t nbytes = strlen(str); mbstate_t mbstate; memset(&mbstate, 0, sizeof(mbstate)); while (nbytes > 0) { /* Convert to unicode */ wchar_t ch; size_t n = mbrtowc(&ch, str, nbytes, &mbstate); if (n >= (size_t)(-2)) { ++w; ++str; continue; } /* Should not happen if locale is correct */ if (n == 0) break; str += n; nbytes -= n; int cw = wcwidth(ch); if (cw > 0) w += cw; } return w; } /* End of 'utf8_width' function */
int prn_normal(const char *s) { mbstate_t mbs; wchar_t wc; int i, n; size_t clen; memset(&mbs, 0, sizeof(mbs)); n = 0; while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) { if (clen == (size_t)-2) { n += printf("%s", s); break; } if (clen == (size_t)-1) { memset(&mbs, 0, sizeof(mbs)); putchar((unsigned char)*s); s++; n++; continue; } for (i = 0; i < (int)clen; i++) putchar((unsigned char)s[i]); s += clen; if (iswprint(wc)) n += wcwidth(wc); } return (n); }
TSTLStrSize MBWidth(std::string str) { if (str.empty()) return 0; TSTLStrSize ret = 0; std::wstring utf16; std::string::iterator end = utf8::find_invalid(str.begin(), str.end()); assert(end == str.end()); // HACK: Just append length of invalid part if (end != str.end()) ret = std::distance(end, str.end()); utf8::utf8to16(str.begin(), end, std::back_inserter(utf16)); // As wcswidth returns -1 when it finds a non printable char, we just use // wcwidth and assume a 0 width for those chars. TSTLStrSize n = 0, length = utf16.length(); for (; n<length; n++) { int w = wcwidth(utf16[n]); if (w > 0) ret += static_cast<TSTLStrSize>(w); } return ret; }
/* * Insert the given character, updating the current location to simplify * inserting a string. */ static int _nc_insert_wch(WINDOW *win, const cchar_t *wch) { int cells = wcwidth(CharOf(CHDEREF(wch))); int cell; if (cells <= 0) cells = 1; if (win->_curx <= win->_maxx) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T *end = &(line->text[win->_curx]); NCURSES_CH_T *temp1 = &(line->text[win->_maxx]); NCURSES_CH_T *temp2 = temp1 - cells; CHANGED_TO_EOL(line, win->_curx, win->_maxx); while (temp1 > end) *temp1-- = *temp2--; *temp1 = _nc_render(win, *wch); for (cell = 1; cell < cells; ++cell) { SetWidecExt(temp1[cell], cell); } win->_curx++; } return OK; }
/* ARGSUSED */ static size_t locale_width(const struct termp *p, int c) { int rc; return((rc = wcwidth(c)) < 0 ? 0 : rc); }
_nc_insert_wch(WINDOW *win, const cchar_t *wch) { int cells = wcwidth(CharOf(CHDEREF(wch))); int cell; int code = OK; if (cells < 0) { code = winsch(win, (chtype) CharOf(CHDEREF(wch))); } else { if (cells == 0) cells = 1; if (win->_curx <= win->_maxx) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T *end = &(line->text[win->_curx]); NCURSES_CH_T *temp1 = &(line->text[win->_maxx]); NCURSES_CH_T *temp2 = temp1 - cells; CHANGED_TO_EOL(line, win->_curx, win->_maxx); while (temp1 > end) *temp1-- = *temp2--; *temp1 = _nc_render(win, *wch); for (cell = 1; cell < cells; ++cell) { SetWidecExt(temp1[cell], cell); } win->_curx = (NCURSES_SIZE_T) (win->_curx + cells); } } return code; }