mirror of
https://github.com/irssi/irssi.git
synced 2026-08-22 18:12:12 +02:00
get_alignment: handle UTF-8 strings.
When using irssi along with some tools like e.g. BitlBee, one can encounter nicknames or channels with UTF-8 multibyte characters. It becomes therefore necessary for some irssi functions to better handle UTF-8, starting with get_alignment. Indeed, get_alignment was liable to mess up terminals by splitting strings in the middle of a multibyte character.
This commit is contained in:
parent
0e5a32fb62
commit
24c40f899e
1 changed files with 46 additions and 15 deletions
|
|
@ -318,29 +318,60 @@ static int get_alignment_args(char **data, int *align, int *flags, char *pad)
|
|||
/* return the aligned text */
|
||||
static char *get_alignment(const char *text, int align, int flags, char pad)
|
||||
{
|
||||
GString *str;
|
||||
char *ret;
|
||||
gchar *ret;
|
||||
gchar *ret_p;
|
||||
uint i;
|
||||
uint start_length;
|
||||
uint cut_length;
|
||||
uint final_length;
|
||||
uint pad_count;
|
||||
|
||||
g_return_val_if_fail(text != NULL, NULL);
|
||||
|
||||
str = g_string_new(text);
|
||||
/* abort if non-valid UTF-8 */
|
||||
if (!g_utf8_validate(text, -1, NULL))
|
||||
return NULL;
|
||||
|
||||
/* cut */
|
||||
if ((flags & ALIGN_CUT) && align > 0 && str->len > align)
|
||||
g_string_truncate(str, align);
|
||||
/* how many characters do we have in the first place? */
|
||||
start_length = g_utf8_strlen(text, 1024);
|
||||
/* how many characters will we have after the cut? */
|
||||
cut_length = start_length;
|
||||
if ((flags & ALIGN_CUT) && align > 0 && start_length > align)
|
||||
cut_length = align;
|
||||
/* how many characters will we have after the pad? */
|
||||
final_length = cut_length;
|
||||
pad_count = 0;
|
||||
if ((flags & ALIGN_PAD) && align > cut_length) {
|
||||
final_length = align;
|
||||
pad_count = final_length - cut_length;
|
||||
}
|
||||
|
||||
/* add pad characters */
|
||||
if (flags & ALIGN_PAD) {
|
||||
while (str->len < align) {
|
||||
if (flags & ALIGN_RIGHT)
|
||||
g_string_prepend_c(str, pad);
|
||||
else
|
||||
g_string_append_c(str, pad);
|
||||
/* allocate 4 bytes for each character we will have in the end */
|
||||
ret = g_malloc((4 * final_length) + 1);
|
||||
ret_p = ret;
|
||||
|
||||
/* left pad to align right, if necessary */
|
||||
if (pad_count && (flags & ALIGN_RIGHT)) {
|
||||
for (i = 0; i < pad_count; i++) {
|
||||
*ret_p = pad;
|
||||
ret_p ++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = str->str;
|
||||
g_string_free(str, FALSE);
|
||||
/* copy the original string (either n characters or the whole of it) */
|
||||
g_utf8_strncpy(ret_p, text, cut_length);
|
||||
/* sadly, at this point, we have no idea where g_utf8_strncpy put the trailing \0... */
|
||||
ret_p += strlen(ret_p);
|
||||
|
||||
/* right pad to align left, if necessary */
|
||||
if (pad_count && !(flags & ALIGN_RIGHT)) {
|
||||
for (i = 0; i < pad_count; i++) {
|
||||
*ret_p = pad;
|
||||
ret_p ++;
|
||||
}
|
||||
*ret_p = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue