- Fixed bug #1189, which caused wide Asian UTF8 characters to be measured as
  narrow characters (thanks to Roy Zuo).
This commit is contained in:
Paul Beckingham 2013-03-02 18:22:21 -05:00
parent 914447c885
commit 6aa0277749
10 changed files with 45 additions and 36 deletions

View file

@ -168,4 +168,5 @@ suggestions:
trHD
Benjamin Weber
alparo
Roy Zuo

View file

@ -83,6 +83,8 @@ Bugs
package (thanks to Jakub Wilk).
+ Fixed bug #1183, correcting error message typos (thanks to Jakub Wilk).
+ Fixed bug #1184, correcting man page formatting (thanks to Jakub Wilk).
+ Fixed bug #1189, which caused wide Asian UTF8 characters to be measured as
narrow characters (thanks to Roy Zuo).
+ Improved hyphenation by splitting on commas (even if no whitespace after).
Leads to better output of, for example, 'task show', where comma-separated
lists are common.

View file

@ -146,7 +146,7 @@ std::string ViewTask::render (std::vector <Task>& data, std::vector <int>& seque
if (print_empty_columns || global_min != 0)
{
unsigned int label_length = utf8_length ((*i)->label ());
unsigned int label_length = utf8_width ((*i)->label ());
if (label_length > global_min) global_min = label_length;
if (label_length > global_ideal) global_ideal = label_length;
minimal.push_back (global_min);

View file

@ -122,7 +122,7 @@ std::string ViewText::render ()
for (unsigned int col = 0; col < _columns.size (); ++col)
{
// Headers factor in to width calculations.
unsigned int global_min = utf8_length (_columns[col]->label ());
unsigned int global_min = utf8_width (_columns[col]->label ());
unsigned int global_ideal = global_min;
for (unsigned int row = 0; row < _data.size (); ++row)

View file

@ -32,6 +32,7 @@
#include <Date.h>
#include <ColDescription.h>
#include <text.h>
#include <utf8.h>
#include <util.h>
#include <i18n.h>
@ -106,14 +107,14 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
int min_desc = longestWord (description);
int min_anno = indent + Date::length (format);
minimum = std::max (min_desc, min_anno);
maximum = description.length ();
maximum = utf8_width (description);
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
{
unsigned int len = min_anno + 1 + i->second.length ();
unsigned int len = min_anno + 1 + utf8_width (i->second);
if (len > maximum)
maximum = len;
}
@ -122,7 +123,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
// Just the text
else if (_style == "desc")
{
maximum = description.length ();
maximum = utf8_width (description);
minimum = longestWord (description);
}
@ -136,20 +137,20 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
int min_desc = longestWord (description);
int min_anno = Date::length (format);
minimum = std::max (min_desc, min_anno);
maximum = description.length ();
maximum = utf8_width (description);
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
maximum += i->second.length () + minimum + 1;
maximum += utf8_width (i->second) + minimum + 1;
}
// The te...
else if (_style == "truncated")
{
minimum = 4;
maximum = description.length ();
maximum = utf8_width (description);
}
// The text [2]
@ -159,7 +160,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
task.getAnnotations (annos);
// <description> + ' ' + '[' + <count> + ']'
maximum = description.length () + 3 + format ((int)annos.size ()).length ();
maximum = utf8_width (description) + 3 + utf8_width (format ((int)annos.size ()));
minimum = longestWord (description);
}
@ -249,7 +250,7 @@ void ColumnDescription::render (
// This is a des...
else if (_style == "truncated")
{
int len = description.length ();
int len = utf8_width (description);
if (len > width)
lines.push_back (color.colorize (description.substr (0, width - 3) + "..."));
else

View file

@ -30,6 +30,7 @@
#include <Context.h>
#include <ColProject.h>
#include <text.h>
#include <utf8.h>
#include <util.h>
#include <i18n.h>
@ -87,7 +88,7 @@ void ColumnProject::measure (Task& task, unsigned int& minimum, unsigned int& ma
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
minimum = longestWord (project);
maximum = project.length ();
maximum = utf8_width (project);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -32,6 +32,7 @@
#include <ColTags.h>
#include <text.h>
#include <i18n.h>
#include <utf8.h>
extern Context context;
@ -85,14 +86,14 @@ void ColumnTags::setStyle (const std::string& value)
// Set the minimum and maximum widths for the value.
void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
{
if (_style == "indicator") minimum = maximum = context.config.get ("tag.indicator").length ();
if (_style == "indicator") minimum = maximum = utf8_width (context.config.get ("tag.indicator"));
else if (_style == "count") minimum = maximum = 3;
else if (_style == "default" ||
_style == "list")
{
std::string tags = task.get (_name);
minimum = 0;
maximum = tags.length ();
maximum = utf8_width (tags);
if (maximum)
{
@ -101,9 +102,9 @@ void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maxim
std::vector <std::string>::iterator i;
for (i = all.begin (); i != all.end (); ++i)
{
unsigned int length_ = i->length ();
if (length_ > minimum)
minimum = i->length () + 1;
unsigned int length = utf8_width (*i);
if (length > minimum)
minimum = length;
}
}
}
@ -121,7 +122,18 @@ void ColumnTags::render (
std::string tags = task.get (_name);
if (tags != "")
{
if (_style == "indicator")
if (_style == "default" ||
_style == "list")
{
std::replace (tags.begin (), tags.end (), ',', ' ');
std::vector <std::string> all;
wrapText (all, tags, width, _hyphenate);
std::vector <std::string>::iterator i;
for (i = all.begin (); i != all.end (); ++i)
lines.push_back (color.colorize (leftJustify (*i, width)));
}
else if (_style == "indicator")
{
lines.push_back (
color.colorize (
@ -135,17 +147,6 @@ void ColumnTags::render (
color.colorize (
rightJustify ("[" + format ((int)all.size ()) + "]", width)));
}
else if (_style == "default" ||
_style == "list")
{
std::replace (tags.begin (), tags.end (), ',', ' ');
std::vector <std::string> all;
wrapText (all, tags, width, _hyphenate);
std::vector <std::string>::iterator i;
for (i = all.begin (); i != all.end (); ++i)
lines.push_back (color.colorize (leftJustify (*i, width)));
}
}
}

View file

@ -32,6 +32,7 @@
#include <Date.h>
#include <ColUDA.h>
#include <text.h>
#include <utf8.h>
#include <i18n.h>
#include <stdlib.h>
@ -99,11 +100,11 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
if (format == "")
format = context.config.get ("dateformat");
minimum = maximum = date.toString (format).length ();
minimum = maximum = utf8_width (date.toString (format));
}
else if (_type == "duration")
{
minimum = maximum = Duration (value).formatCompact ().length ();
minimum = maximum = utf8_width (Duration (value).formatCompact ());
}
else if (_type == "string")
{
@ -113,7 +114,7 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
}
else if (_type == "numeric")
{
minimum = maximum = value.length ();
minimum = maximum = utf8_width (value);
}
}
}

View file

@ -1049,7 +1049,7 @@ std::string leftJustify (const int input, const int width)
////////////////////////////////////////////////////////////////////////////////
std::string leftJustify (const std::string& input, const int width)
{
return input + std::string (width - utf8_text_length (input), ' ');
return input + std::string (width - utf8_text_width (input), ' ');
}
////////////////////////////////////////////////////////////////////////////////
@ -1071,7 +1071,7 @@ std::string rightJustify (const int input, const int width)
////////////////////////////////////////////////////////////////////////////////
std::string rightJustify (const std::string& input, const int width)
{
return std::string (width - utf8_text_length (input), ' ') + input;
return std::string (width - utf8_text_width (input), ' ') + input;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -40,15 +40,17 @@ if (open my $fh, '>', '455.rc')
ok (-r '455.rc', 'Created 455.rc');
}
# Bug #455 - Text alignment in reports is broken when text contains utf8 characters
# Bug #455 - Text alignment in reports is broken when text contains wide utf8
# characters
qx{../src/task rc:455.rc add abc pro:Bar\x{263A} 2>&1};
qx{../src/task rc:455.rc add def pro:Foo! 2>&1};
my $output = qx{../src/task rc:455.rc ls 2>&1};
like ($output, qr/\s{7}abc/ms, 'bug 455 - correct spacing in utf8 task');
like ($output, qr/\s{7}def/ms, 'bug 455 - correct spacing in non utf8 task');
# ' ' + 'Pri' + ' ' == 5
like ($output, qr/\S\s{5}abc/ms, 'bug 455 - correct spacing in utf8 task');
like ($output, qr/\S\s{5}def/ms, 'bug 455 - correct spacing in non utf8 task');
# Cleanup.
unlink qw(pending.data completed.data undo.data backlog.data synch.key 455.rc);