Code Cleanup

- Integrated Context.config.
- Eliminated Config& as a function argument.
- Added extern references to Context where needed.
This commit is contained in:
Paul Beckingham 2009-06-03 02:03:49 -04:00
parent 98978c7c00
commit 66bd5fc3c0
29 changed files with 1115 additions and 451 deletions

View file

@ -44,8 +44,10 @@
#include <ncurses.h>
#endif
extern Context context;
////////////////////////////////////////////////////////////////////////////////
std::string handleAdd (TDB& tdb, T& task, Config& conf)
std::string handleAdd (TDB& tdb, T& task)
{
std::stringstream out;
@ -69,12 +71,12 @@ std::string handleAdd (TDB& tdb, T& task, Config& conf)
// Override with default.project, if not specified.
if (task.getAttribute ("project") == "")
task.setAttribute ("project", conf.get ("default.project", ""));
task.setAttribute ("project", context.config.get ("default.project", ""));
// Override with default.priority, if not specified.
if (task.getAttribute ("priority") == "")
{
std::string defaultPriority = conf.get ("default.priority", "");
std::string defaultPriority = context.config.get ("default.priority", "");
if (validPriority (defaultPriority))
task.setAttribute ("priority", defaultPriority);
}
@ -90,7 +92,7 @@ std::string handleAdd (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleProjects (TDB& tdb, T& task, Config& conf)
std::string handleProjects (TDB& tdb, T& task)
{
std::stringstream out;
@ -114,14 +116,15 @@ std::string handleProjects (TDB& tdb, T& task, Config& conf)
table.addColumn ("Project");
table.addColumn ("Tasks");
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
if (context.config.get ("color", true) ||
context.config.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
}
table.setColumnJustification (1, Table::right);
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
foreach (i, unique)
{
@ -130,9 +133,9 @@ std::string handleProjects (TDB& tdb, T& task, Config& conf)
table.addCell (row, 1, i->second);
}
out << optionalBlankLine (conf)
out << optionalBlankLine ()
<< table.render ()
<< optionalBlankLine (conf)
<< optionalBlankLine ()
<< unique.size ()
<< (unique.size () == 1 ? " project" : " projects")
<< std::endl;
@ -145,7 +148,7 @@ std::string handleProjects (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleTags (TDB& tdb, T& task, Config& conf)
std::string handleTags (TDB& tdb, T& task)
{
std::stringstream out;
@ -168,12 +171,12 @@ std::string handleTags (TDB& tdb, T& task, Config& conf)
}
// Render a list of tag names from the map.
std::cout << optionalBlankLine (conf);
std::cout << optionalBlankLine ();
foreach (i, unique)
std::cout << i->first << std::endl;
if (unique.size ())
out << optionalBlankLine (conf)
out << optionalBlankLine ()
<< unique.size ()
<< (unique.size () == 1 ? " tag" : " tags")
<< std::endl;
@ -187,7 +190,7 @@ std::string handleTags (TDB& tdb, T& task, Config& conf)
////////////////////////////////////////////////////////////////////////////////
// If a task is deleted, but is still in the pending file, then it may be
// undeleted simply by changing it's status.
std::string handleUndelete (TDB& tdb, T& task, Config& conf)
std::string handleUndelete (TDB& tdb, T& task)
{
std::stringstream out;
@ -225,7 +228,7 @@ std::string handleUndelete (TDB& tdb, T& task, Config& conf)
////////////////////////////////////////////////////////////////////////////////
// If a task is done, but is still in the pending file, then it may be undone
// simply by changing it's status.
std::string handleUndo (TDB& tdb, T& task, Config& conf)
std::string handleUndo (TDB& tdb, T& task)
{
std::stringstream out;
@ -261,14 +264,14 @@ std::string handleUndo (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleVersion (Config& conf)
std::string handleVersion ()
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", (int) 80);
int width = context.config.get ("defaultwidth", (int) 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
if (context.config.get ("curses", true))
{
WINDOW* w = initscr ();
width = w->_maxx + 1;
@ -301,11 +304,11 @@ std::string handleVersion (Config& conf)
// Create a table for output.
Table table;
table.setTableWidth (width);
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
table.addColumn ("Config variable");
table.addColumn ("Value");
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
@ -320,10 +323,10 @@ std::string handleVersion (Config& conf)
table.sortOn (0, Table::ascendingCharacter);
std::vector <std::string> all;
conf.all (all);
context.config.all (all);
foreach (i, all)
{
std::string value = conf.get (*i);
std::string value = context.config.get (*i);
if (value != "")
{
int row = table.addRow ();
@ -334,11 +337,11 @@ std::string handleVersion (Config& conf)
out << "Copyright (C) 2006 - 2009, P. Beckingham."
<< std::endl
<< ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
<< ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false))
? Text::colorize (Text::bold, Text::nocolor, PACKAGE)
: PACKAGE)
<< " "
<< ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
<< ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false))
? Text::colorize (Text::bold, Text::nocolor, VERSION)
: VERSION)
<< std::endl
@ -407,12 +410,12 @@ std::string handleVersion (Config& conf)
<< std::endl;
else
{
if (conf.get ("data.location") == "")
if (context.config.get ("data.location") == "")
out << "Configuration error: data.location not specified in .taskrc "
"file."
<< std::endl;
if (access (expandPath (conf.get ("data.location")).c_str (), X_OK))
if (access (expandPath (context.config.get ("data.location")).c_str (), X_OK))
out << "Configuration error: data.location contains a directory name"
" that doesn't exist, or is unreadable."
<< std::endl;
@ -422,7 +425,7 @@ std::string handleVersion (Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleDelete (TDB& tdb, T& task, Config& conf)
std::string handleDelete (TDB& tdb, T& task)
{
std::stringstream out;
@ -443,7 +446,7 @@ std::string handleDelete (TDB& tdb, T& task, Config& conf)
<< t->getDescription ()
<< "'?";
if (!conf.get (std::string ("confirmation"), false) || confirm (question.str ()))
if (!context.config.get (std::string ("confirmation"), false) || confirm (question.str ()))
{
// Check for the more complex case of a recurring task. If this is a
// recurring task, get confirmation to delete them all.
@ -463,7 +466,7 @@ std::string handleDelete (TDB& tdb, T& task, Config& conf)
sibling->setAttribute ("end", endTime);
tdb.modifyT (*sibling);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Deleting recurring task "
<< sibling->getId ()
<< " '"
@ -496,7 +499,7 @@ std::string handleDelete (TDB& tdb, T& task, Config& conf)
t->setAttribute ("end", endTime);
tdb.modifyT (*t);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Deleting task "
<< t->getId ()
<< " '"
@ -513,7 +516,7 @@ std::string handleDelete (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleStart (TDB& tdb, T& task, Config& conf)
std::string handleStart (TDB& tdb, T& task)
{
std::stringstream out;
@ -531,14 +534,14 @@ std::string handleStart (TDB& tdb, T& task, Config& conf)
tdb.modifyT (*t);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Started "
<< t->getId ()
<< " '"
<< t->getDescription ()
<< "'"
<< std::endl;
nag (tdb, task, conf);
nag (tdb, task);
}
else
{
@ -550,7 +553,7 @@ std::string handleStart (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleStop (TDB& tdb, T& task, Config& conf)
std::string handleStop (TDB& tdb, T& task)
{
std::stringstream out;
@ -565,7 +568,7 @@ std::string handleStop (TDB& tdb, T& task, Config& conf)
t->removeAttribute ("start");
tdb.modifyT (*t);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Stopped " << t->getId () << " '" << t->getDescription () << "'" << std::endl;
}
else
@ -578,7 +581,7 @@ std::string handleStop (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleDone (TDB& tdb, T& task, Config& conf)
std::string handleDone (TDB& tdb, T& task)
{
int count = 0;
std::stringstream out;
@ -608,7 +611,7 @@ std::string handleDone (TDB& tdb, T& task, Config& conf)
if (!tdb.modifyT (*seq))
throw std::string ("Could not mark task as completed.");
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Completed "
<< seq->getId ()
<< " '"
@ -617,7 +620,7 @@ std::string handleDone (TDB& tdb, T& task, Config& conf)
<< std::endl;
updateRecurrenceMask (tdb, all, *seq);
nag (tdb, *seq, conf);
nag (tdb, *seq);
++count;
}
@ -630,7 +633,7 @@ std::string handleDone (TDB& tdb, T& task, Config& conf)
<< std::endl;
}
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Marked "
<< count
<< " task"
@ -642,7 +645,7 @@ std::string handleDone (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleExport (TDB& tdb, T& task, Config& conf)
std::string handleExport (TDB& tdb, T& task)
{
std::stringstream output;
@ -699,7 +702,7 @@ std::string handleExport (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleModify (TDB& tdb, T& task, Config& conf)
std::string handleModify (TDB& tdb, T& task)
{
int count = 0;
std::stringstream out;
@ -746,14 +749,14 @@ std::string handleModify (TDB& tdb, T& task, Config& conf)
}
}
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Modified " << count << " task" << (count == 1 ? "" : "s") << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleAppend (TDB& tdb, T& task, Config& conf)
std::string handleAppend (TDB& tdb, T& task)
{
int count = 0;
std::stringstream out;
@ -783,7 +786,7 @@ std::string handleAppend (TDB& tdb, T& task, Config& conf)
{
tdb.modifyT (*other);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Appended '"
<< task.getDescription ()
<< "' to task "
@ -796,14 +799,14 @@ std::string handleAppend (TDB& tdb, T& task, Config& conf)
}
}
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Appended " << count << " task" << (count == 1 ? "" : "s") << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleDuplicate (TDB& tdb, T& task, Config& conf)
std::string handleDuplicate (TDB& tdb, T& task)
{
int count = 0;
std::stringstream out;
@ -833,7 +836,7 @@ std::string handleDuplicate (TDB& tdb, T& task, Config& conf)
if (!tdb.addT (dup))
throw std::string ("Could not create new task.");
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Duplicated "
<< seq->getId ()
<< " '"
@ -851,20 +854,20 @@ std::string handleDuplicate (TDB& tdb, T& task, Config& conf)
<< std::endl;
}
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Duplicated " << count << " task" << (count == 1 ? "" : "s") << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleColor (Config& conf)
std::string handleColor ()
{
std::stringstream out;
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false))
{
out << optionalBlankLine (conf) << "Foreground" << std::endl
out << optionalBlankLine () << "Foreground" << std::endl
<< " "
<< Text::colorize (Text::bold, Text::nocolor, "bold") << " "
<< Text::colorize (Text::underline, Text::nocolor, "underline") << " "
@ -935,7 +938,7 @@ std::string handleColor (Config& conf)
<< " " << Text::colorize (Text::nocolor, Text::on_white, "on_white") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_white, "on_bright_white") << std::endl
<< optionalBlankLine (conf);
<< optionalBlankLine ();
}
else
{
@ -946,7 +949,7 @@ std::string handleColor (Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
std::string handleAnnotate (TDB& tdb, T& task, Config& conf)
std::string handleAnnotate (TDB& tdb, T& task)
{
if (task.getDescription () == "")
throw std::string ("Cannot apply a blank annotation.");
@ -961,7 +964,7 @@ std::string handleAnnotate (TDB& tdb, T& task, Config& conf)
t->addAnnotation (task.getDescription ());
tdb.modifyT (*t);
if (conf.get ("echo.command", true))
if (context.config.get ("echo.command", true))
out << "Annotated "
<< t->getId ()
<< " with '"

View file

@ -40,6 +40,8 @@
#include "util.h"
#include "task.h"
extern Context context;
////////////////////////////////////////////////////////////////////////////////
static std::string findValue (
const std::string& text,
@ -64,7 +66,6 @@ static std::string findValue (
////////////////////////////////////////////////////////////////////////////////
static std::string findDate (
Config& conf,
const std::string& text,
const std::string& name)
{
@ -80,7 +81,7 @@ static std::string findDate (
if (value != "")
{
Date dt (value, conf.get ("dateformat", "m/d/Y"));
Date dt (value, context.config.get ("dateformat", "m/d/Y"));
char epoch [16];
sprintf (epoch, "%d", (int)dt.toEpoch ());
return std::string (epoch);
@ -107,7 +108,6 @@ static std::string formatStatus (T& task)
////////////////////////////////////////////////////////////////////////////////
static std::string formatDate (
Config& conf,
T& task,
const std::string& attribute)
{
@ -115,14 +115,14 @@ static std::string formatDate (
if (value.length ())
{
Date dt (::atoi (value.c_str ()));
value = dt.toString (conf.get ("dateformat", "m/d/Y"));
value = dt.toString (context.config.get ("dateformat", "m/d/Y"));
}
return value;
}
////////////////////////////////////////////////////////////////////////////////
static std::string formatTask (Config& conf, T task)
static std::string formatTask (T task)
{
std::stringstream before;
before << "# The 'task edit <id>' command allows you to modify all aspects of a task" << std::endl
@ -159,11 +159,11 @@ static std::string formatTask (Config& conf, T task)
<< "# The description field is allowed to wrap and use multiple lines. Task" << std::endl
<< "# will combine them." << std::endl
<< " Description: " << task.getDescription () << std::endl
<< " Created: " << formatDate (conf, task, "entry") << std::endl
<< " Started: " << formatDate (conf, task, "start") << std::endl
<< " Ended: " << formatDate (conf, task, "end") << std::endl
<< " Due: " << formatDate (conf, task, "due") << std::endl
<< " Until: " << formatDate (conf, task, "until") << std::endl
<< " Created: " << formatDate (task, "entry") << std::endl
<< " Started: " << formatDate (task, "start") << std::endl
<< " Ended: " << formatDate (task, "end") << std::endl
<< " Due: " << formatDate (task, "due") << std::endl
<< " Until: " << formatDate (task, "until") << std::endl
<< " Recur: " << task.getAttribute ("recur") << std::endl
<< " Parent: " << task.getAttribute ("parent") << std::endl
<< " Foreground color: " << task.getAttribute ("fg") << std::endl
@ -176,7 +176,7 @@ static std::string formatTask (Config& conf, T task)
foreach (anno, annotations)
{
Date dt (anno->first);
before << " Annotation: " << dt.toString (conf.get ("dateformat", "m/d/Y"))
before << " Annotation: " << dt.toString (context.config.get ("dateformat", "m/d/Y"))
<< " " << anno->second << std::endl;
}
@ -187,7 +187,7 @@ static std::string formatTask (Config& conf, T task)
}
////////////////////////////////////////////////////////////////////////////////
static void parseTask (Config& conf, T& task, const std::string& after)
static void parseTask (T& task, const std::string& after)
{
// project
std::string value = findValue (after, "Project:");
@ -245,7 +245,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
}
// entry
value = findDate (conf, after, "Created:");
value = findDate (after, "Created:");
if (value != "")
{
Date edited (::atoi (value.c_str ()));
@ -261,7 +261,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
throw std::string ("Cannot remove creation date");
// start
value = findDate (conf, after, "Started:");
value = findDate (after, "Started:");
if (value != "")
{
Date edited (::atoi (value.c_str ()));
@ -291,7 +291,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
}
// end
value = findDate (conf, after, "Ended:");
value = findDate (after, "Ended:");
if (value != "")
{
Date edited (::atoi (value.c_str ()));
@ -319,7 +319,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
}
// due
value = findDate (conf, after, "Due:");
value = findDate (after, "Due:");
if (value != "")
{
Date edited (::atoi (value.c_str ()));
@ -357,7 +357,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
}
// until
value = findDate (conf, after, "Until:");
value = findDate (after, "Until:");
if (value != "")
{
Date edited (::atoi (value.c_str ()));
@ -496,7 +496,7 @@ static void parseTask (Config& conf, T& task, const std::string& after)
// Introducing the Silver Bullet. This feature is the catch-all fixative for
// various other ills. This is like opening up the hood and going in with a
// wrench. To be used sparingly.
std::string handleEdit (TDB& tdb, T& task, Config& conf)
std::string handleEdit (TDB& tdb, T& task)
{
std::stringstream out;
std::vector <T> all;
@ -506,7 +506,7 @@ std::string handleEdit (TDB& tdb, T& task, Config& conf)
foreach (seq, all)
{
// Check for file permissions.
std::string dataLocation = expandPath (conf.get ("data.location"));
std::string dataLocation = expandPath (context.config.get ("data.location"));
if (access (dataLocation.c_str (), X_OK))
throw std::string ("Your data.location directory is not writable.");
@ -519,11 +519,11 @@ std::string handleEdit (TDB& tdb, T& task, Config& conf)
char* file = cpattern;
// Format the contents, T -> text, write to a file.
std::string before = formatTask (conf, *seq);
std::string before = formatTask (*seq);
spit (file, before);
// Determine correct editor: .taskrc:editor > $VISUAL > $EDITOR > vi
std::string editor = conf.get ("editor", "");
std::string editor = context.config.get ("editor", "");
char* peditor = getenv ("VISUAL");
if (editor == "" && peditor) editor = std::string (peditor);
peditor = getenv ("EDITOR");
@ -558,7 +558,7 @@ ARE_THESE_REALLY_HARMFUL:
try
{
parseTask (conf, *seq, after);
parseTask (*seq, after);
tdb.modifyT (*seq);
}

View file

@ -35,6 +35,8 @@
#include "util.h"
#include "task.h"
extern Context context;
////////////////////////////////////////////////////////////////////////////////
enum fileType
{
@ -159,19 +161,19 @@ static fileType determineFileType (const std::vector <std::string>& lines)
}
////////////////////////////////////////////////////////////////////////////////
static void decorateTask (T& task, Config& conf)
static void decorateTask (T& task)
{
char entryTime[16];
sprintf (entryTime, "%u", (unsigned int) time (NULL));
task.setAttribute ("entry", entryTime);
// Override with default.project, if not specified.
std::string defaultProject = conf.get ("default.project", "");
std::string defaultProject = context.config.get ("default.project", "");
if (task.getAttribute ("project") == "" && defaultProject != "")
task.setAttribute ("project", defaultProject);
// Override with default.priority, if not specified.
std::string defaultPriority = conf.get ("default.priority", "");
std::string defaultPriority = context.config.get ("default.priority", "");
if (task.getAttribute ("priority") == "" &&
defaultPriority != "" &&
validPriority (defaultPriority))
@ -181,7 +183,6 @@ static void decorateTask (T& task, Config& conf)
////////////////////////////////////////////////////////////////////////////////
static std::string importTask_1_4_3 (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -337,7 +338,6 @@ static std::string importTask_1_4_3 (
////////////////////////////////////////////////////////////////////////////////
static std::string importTask_1_5_0 (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -498,7 +498,6 @@ static std::string importTask_1_5_0 (
////////////////////////////////////////////////////////////////////////////////
static std::string importTask_1_6_0 (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -659,7 +658,6 @@ static std::string importTask_1_6_0 (
////////////////////////////////////////////////////////////////////////////////
static std::string importTaskCmdLine (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -676,8 +674,8 @@ static std::string importTaskCmdLine (
T task;
std::string command;
parse (args, command, task, conf);
handleAdd (tdb, task, conf);
parse (args, command, task);
handleAdd (tdb, task);
}
catch (...)
@ -707,7 +705,6 @@ static std::string importTaskCmdLine (
////////////////////////////////////////////////////////////////////////////////
static std::string importTodoSh_2_0 (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -782,8 +779,8 @@ static std::string importTodoSh_2_0 (
T task;
std::string command;
parse (args, command, task, conf);
decorateTask (task, conf);
parse (args, command, task);
decorateTask (task);
if (isPending)
{
@ -829,7 +826,6 @@ static std::string importTodoSh_2_0 (
////////////////////////////////////////////////////////////////////////////////
static std::string importText (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -856,8 +852,8 @@ static std::string importText (
T task;
std::string command;
parse (args, command, task, conf);
decorateTask (task, conf);
parse (args, command, task);
decorateTask (task);
if (! tdb.addT (task))
failed.push_back (*it);
@ -891,7 +887,6 @@ static std::string importText (
////////////////////////////////////////////////////////////////////////////////
static std::string importCSV (
TDB& tdb,
Config& conf,
const std::vector <std::string>& lines)
{
std::vector <std::string> failed;
@ -921,7 +916,7 @@ static std::string importCSV (
std::string name = lowerCase (trim (unquoteText (trim (headings[h]))));
// If there is a mapping for the field, use the value.
if (name == conf.get ("import.synonym.id") ||
if (name == context.config.get ("import.synonym.id") ||
name == "id" ||
name == "#" ||
name == "sequence" ||
@ -930,7 +925,7 @@ static std::string importCSV (
mapping["id"] = (int)h;
}
else if (name == conf.get ("import.synonym.uuid") ||
else if (name == context.config.get ("import.synonym.uuid") ||
name == "uuid" ||
name == "guid" ||
name.find ("unique") != std::string::npos)
@ -938,7 +933,7 @@ static std::string importCSV (
mapping["uuid"] = (int)h;
}
else if (name == conf.get ("import.synonym.status") ||
else if (name == context.config.get ("import.synonym.status") ||
name == "status" ||
name == "condition" ||
name == "state")
@ -946,7 +941,7 @@ static std::string importCSV (
mapping["status"] = (int)h;
}
else if (name == conf.get ("import.synonym.tags") ||
else if (name == context.config.get ("import.synonym.tags") ||
name == "tags" ||
name.find ("categor") != std::string::npos ||
name.find ("tag") != std::string::npos)
@ -954,7 +949,7 @@ static std::string importCSV (
mapping["tags"] = (int)h;
}
else if (name == conf.get ("import.synonym.entry") ||
else if (name == context.config.get ("import.synonym.entry") ||
name == "entry" ||
name.find ("added") != std::string::npos ||
name.find ("created") != std::string::npos ||
@ -963,7 +958,7 @@ static std::string importCSV (
mapping["entry"] = (int)h;
}
else if (name == conf.get ("import.synonym.start") ||
else if (name == context.config.get ("import.synonym.start") ||
name == "start" ||
name.find ("began") != std::string::npos ||
name.find ("begun") != std::string::npos ||
@ -972,21 +967,21 @@ static std::string importCSV (
mapping["start"] = (int)h;
}
else if (name == conf.get ("import.synonym.due") ||
else if (name == context.config.get ("import.synonym.due") ||
name == "due" ||
name.find ("expected") != std::string::npos)
{
mapping["due"] = (int)h;
}
else if (name == conf.get ("import.synonym.recur") ||
else if (name == context.config.get ("import.synonym.recur") ||
name == "recur" ||
name == "frequency")
{
mapping["recur"] = (int)h;
}
else if (name == conf.get ("import.synonym.end") ||
else if (name == context.config.get ("import.synonym.end") ||
name == "end" ||
name == "done" ||
name.find ("complete") != std::string::npos)
@ -994,14 +989,14 @@ static std::string importCSV (
mapping["end"] = (int)h;
}
else if (name == conf.get ("import.synonym.project") ||
else if (name == context.config.get ("import.synonym.project") ||
name == "project" ||
name.find ("proj") != std::string::npos)
{
mapping["project"] = (int)h;
}
else if (name == conf.get ("import.synonym.priority") ||
else if (name == context.config.get ("import.synonym.priority") ||
name == "priority" ||
name == "pri" ||
name.find ("importan") != std::string::npos)
@ -1009,7 +1004,7 @@ static std::string importCSV (
mapping["priority"] = (int)h;
}
else if (name == conf.get ("import.synonym.fg") ||
else if (name == context.config.get ("import.synonym.fg") ||
name.find ("fg") != std::string::npos ||
name.find ("foreground") != std::string::npos ||
name.find ("color") != std::string::npos)
@ -1017,14 +1012,14 @@ static std::string importCSV (
mapping["fg"] = (int)h;
}
else if (name == conf.get ("import.synonym.bg") ||
else if (name == context.config.get ("import.synonym.bg") ||
name == "bg" ||
name.find ("background") != std::string::npos)
{
mapping["bg"] = (int)h;
}
else if (name == conf.get ("import.synonym.description") ||
else if (name == context.config.get ("import.synonym.description") ||
name.find ("desc") != std::string::npos ||
name.find ("detail") != std::string::npos ||
name.find ("task") != std::string::npos ||
@ -1132,7 +1127,7 @@ static std::string importCSV (
}
////////////////////////////////////////////////////////////////////////////////
std::string handleImport (TDB& tdb, T& task, Config& conf)
std::string handleImport (TDB& tdb, T& task)
{
std::stringstream out;
@ -1187,13 +1182,13 @@ std::string handleImport (TDB& tdb, T& task, Config& conf)
// Determine which type it might be, then attempt an import.
switch (type)
{
case task_1_4_3: out << importTask_1_4_3 (tdb, conf, lines); break;
case task_1_5_0: out << importTask_1_5_0 (tdb, conf, lines); break;
case task_1_6_0: out << importTask_1_6_0 (tdb, conf, lines); break;
case task_cmd_line: out << importTaskCmdLine (tdb, conf, lines); break;
case todo_sh_2_0: out << importTodoSh_2_0 (tdb, conf, lines); break;
case csv: out << importCSV (tdb, conf, lines); break;
case text: out << importText (tdb, conf, lines); break;
case task_1_4_3: out << importTask_1_4_3 (tdb, lines); break;
case task_1_5_0: out << importTask_1_5_0 (tdb, lines); break;
case task_1_6_0: out << importTask_1_6_0 (tdb, lines); break;
case task_cmd_line: out << importTaskCmdLine (tdb, lines); break;
case todo_sh_2_0: out << importTodoSh_2_0 (tdb, lines); break;
case csv: out << importCSV (tdb, lines); break;
case text: out << importText (tdb, lines); break;
case not_a_clue: /* to stop the compiler from complaining. */ break;
}
}

View file

@ -30,12 +30,15 @@
#include <vector>
#include <map>
#include "Context.h"
#include "Date.h"
#include "Duration.h"
#include "T.h"
#include "text.h"
#include "util.h"
extern Context context;
////////////////////////////////////////////////////////////////////////////////
// NOTE: These are static arrays only because there is no initializer list for
// std::vector.
@ -220,9 +223,9 @@ static bool isCommand (const std::string& candidate)
}
////////////////////////////////////////////////////////////////////////////////
bool validDate (std::string& date, Config& conf)
bool validDate (std::string& date)
{
Date test (date, conf.get ("dateformat", "m/d/Y"));
Date test (date, context.config.get ("dateformat", "m/d/Y"));
char epoch[16];
sprintf (epoch, "%d", (int) test.toEpoch ());
@ -248,8 +251,7 @@ bool validPriority (const std::string& input)
////////////////////////////////////////////////////////////////////////////////
static bool validAttribute (
std::string& name,
std::string& value,
Config& conf)
std::string& value)
{
guess ("attribute", attributes, name);
if (name != "")
@ -258,10 +260,10 @@ static bool validAttribute (
guess ("color", colors, value);
else if (name == "due" && value != "")
validDate (value, conf);
validDate (value);
else if (name == "until" && value != "")
validDate (value, conf);
validDate (value);
else if (name == "priority")
{
@ -456,8 +458,7 @@ bool validDuration (std::string& input)
void parse (
std::vector <std::string>& args,
std::string& command,
T& task,
Config& conf)
T& task)
{
command = "";
@ -518,7 +519,7 @@ void parse (
std::string name = lowerCase (arg.substr (0, colon));
std::string value = arg.substr (colon + 1, std::string::npos);
if (validAttribute (name, value, conf))
if (validAttribute (name, value))
{
if (name != "recur" || validDuration (value))
task.setAttribute (name, value);
@ -589,10 +590,10 @@ void parse (
}
////////////////////////////////////////////////////////////////////////////////
void loadCustomReports (Config& conf)
void loadCustomReports ()
{
std::vector <std::string> all;
conf.all (all);
context.config.all (all);
foreach (i, all)
{

File diff suppressed because it is too large Load diff

View file

@ -26,13 +26,15 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <stdlib.h>
#include "Config.h"
#include "Context.h"
#include "Table.h"
#include "Date.h"
#include "T.h"
#include "text.h"
#include "util.h"
extern Context context;
static std::map <std::string, Text::color> gsFg;
static std::map <std::string, Text::color> gsBg;
@ -63,17 +65,17 @@ static void parseColorRule (
}
////////////////////////////////////////////////////////////////////////////////
void initializeColorRules (Config& conf)
void initializeColorRules ()
{
std::vector <std::string> ruleNames;
conf.all (ruleNames);
context.config.all (ruleNames);
foreach (it, ruleNames)
{
if (it->substr (0, 6) == "color.")
{
Text::color fg;
Text::color bg;
parseColorRule (conf.get (*it), fg, bg);
parseColorRule (context.config.get (*it), fg, bg);
gsFg[*it] = fg;
gsBg[*it] = bg;
}
@ -84,8 +86,7 @@ void initializeColorRules (Config& conf)
void autoColorize (
T& task,
Text::color& fg,
Text::color& bg,
Config& conf)
Text::color& bg)
{
// Note: fg, bg already contain colors specifically assigned via command.
// Note: These rules form a hierarchy - the last rule is King.
@ -208,7 +209,7 @@ void autoColorize (
{
Date dueDate (::atoi (due.c_str ()));
Date now;
Date then (now + conf.get ("due", 7) * 86400);
Date then (now + context.config.get ("due", 7) * 86400);
// Overdue
if (dueDate < now)

View file

@ -3,25 +3,26 @@
#include <string>
#include "Context.h"
Context context;
int main (int argc, char** argv)
{
try
{
Context c;
c.initialize (argc, argv);
// c.run ();
context.initialize (argc, argv);
// context.run ();
////////////////////////////////////////////////////////////////////////////////
c.tdb.lock (c.config.get ("locking", true));
context.tdb.lock (context.config.get ("locking", true));
c.filter.push_back (Att ("priority", "L"));
context.filter.push_back (Att ("priority", "L"));
std::vector <T2> tasks;
int quantity = c.tdb.load (tasks, c.filter);
std::cout << "# " << quantity << " <-- c.tdb.load" << std::endl;
int quantity = context.tdb.load (tasks, context.filter);
std::cout << "# " << quantity << " <-- context.tdb.load" << std::endl;
c.tdb.unlock ();
context.tdb.unlock ();
////////////////////////////////////////////////////////////////////////////////

View file

@ -50,16 +50,17 @@
#include <ncurses.h>
#endif
// Global context for use by all.
Context context;
////////////////////////////////////////////////////////////////////////////////
static std::string shortUsage (Config& conf)
static std::string shortUsage ()
{
std::stringstream out;
Table table;
int width = conf.get ("defaultwidth", (int) 80);
int width = context.config.get ("defaultwidth", (int) 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
if (context.config.get ("curses", true))
{
WINDOW* w = initscr ();
width = w->_maxx + 1;
@ -79,7 +80,7 @@ static std::string shortUsage (Config& conf)
table.setColumnWidth (1, Table::minimum);
table.setColumnWidth (2, Table::flexible);
table.setTableWidth (width);
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
int row = table.addRow ();
table.addCell (row, 0, "Usage:");
@ -219,7 +220,7 @@ static std::string shortUsage (Config& conf)
foreach (report, all)
{
std::string command = std::string ("task ") + *report + std::string (" [tags] [attrs] desc...");
std::string description = conf.get (
std::string description = context.config.get (
std::string ("report.") + *report + ".description", std::string ("(missing description)"));
row = table.addRow ();
@ -240,10 +241,10 @@ static std::string shortUsage (Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
static std::string longUsage (Config& conf)
static std::string longUsage ()
{
std::stringstream out;
out << shortUsage (conf)
out << shortUsage ()
<< "ID is the numeric identifier displayed by the 'task list' command. "
<< "You can specify multiple IDs for task commands, and multiple tasks "
<< "will be affected. To specify multiple IDs make sure you use one "
@ -283,32 +284,6 @@ static std::string longUsage (Config& conf)
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void loadConfFile (int argc, char** argv, Config& conf)
{
for (int i = 1; i < argc; ++i)
{
if (! strncmp (argv[i], "rc:", 3))
{
if (! access (&(argv[i][3]), F_OK))
{
std::string file = &(argv[i][3]);
conf.load (file);
return;
}
else
throw std::string ("Could not read configuration file '") + &(argv[i][3]) + "'";
}
}
struct passwd* pw = getpwuid (getuid ());
if (!pw)
throw std::string ("Could not read home directory from passwd file.");
std::string file = pw->pw_dir;
conf.createDefault (file);
}
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
@ -323,30 +298,25 @@ int main (int argc, char** argv)
{
context.initialize (argc, argv);
// Load the config file from the home directory. If the file cannot be
// found, offer to create a sample one.
Config conf;
loadConfFile (argc, argv, conf);
// When redirecting output to a file, do not use color, curses.
if (!isatty (fileno (stdout)))
{
conf.set ("curses", "off");
context.config.set ("curses", "off");
if (! conf.get (std::string ("_forcecolor"), false))
conf.set ("color", "off");
if (! context.config.get (std::string ("_forcecolor"), false))
context.config.set ("color", "off");
}
TDB tdb;
std::string dataLocation = expandPath (conf.get ("data.location"));
std::string dataLocation = expandPath (context.config.get ("data.location"));
tdb.dataDirectory (dataLocation);
// Allow user override of file locking. Solaris/NFS machines may want this.
if (! conf.get ("locking", true))
if (! context.config.get ("locking", true))
tdb.noLock ();
// Check for silly shadow file settings.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
std::string shadowFile = expandPath (context.config.get ("shadow.file"));
if (shadowFile != "")
{
if (shadowFile == dataLocation + "/pending.data")
@ -358,7 +328,7 @@ int main (int argc, char** argv)
"overwrite your completed tasks. Please change it.");
}
std::cout << runTaskCommand (argc, argv, tdb, conf);
std::cout << runTaskCommand (argc, argv, tdb);
}
catch (std::string& error)
@ -377,9 +347,9 @@ int main (int argc, char** argv)
}
////////////////////////////////////////////////////////////////////////////////
void nag (TDB& tdb, T& task, Config& conf)
void nag (TDB& tdb, T& task)
{
std::string nagMessage = conf.get ("nag", std::string (""));
std::string nagMessage = context.config.get ("nag", std::string (""));
if (nagMessage != "")
{
// Load all pending tasks.
@ -780,26 +750,26 @@ void updateRecurrenceMask (
}
////////////////////////////////////////////////////////////////////////////////
void updateShadowFile (TDB& tdb, Config& conf)
void updateShadowFile (TDB& tdb)
{
try
{
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
std::string shadowFile = expandPath (context.config.get ("shadow.file"));
if (shadowFile != "")
{
std::string oldCurses = conf.get ("curses");
std::string oldColor = conf.get ("color");
conf.set ("curses", "off");
conf.set ("color", "off");
std::string oldCurses = context.config.get ("curses");
std::string oldColor = context.config.get ("color");
context.config.set ("curses", "off");
context.config.set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
std::string command = conf.get ("shadow.command",
conf.get ("default.command", "list"));
std::string command = context.config.get ("shadow.command",
context.config.get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
std::string result = runTaskCommand (args, tdb, conf);
std::string result = runTaskCommand (args, tdb);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
@ -810,12 +780,12 @@ void updateShadowFile (TDB& tdb, Config& conf)
else
throw std::string ("Could not write file '") + shadowFile + "'";
conf.set ("curses", oldCurses);
conf.set ("color", oldColor);
context.config.set ("curses", oldCurses);
context.config.set ("color", oldColor);
}
// Optionally display a notification that the shadow file was updated.
if (conf.get (std::string ("shadow.notify"), false))
if (context.config.get (std::string ("shadow.notify"), false))
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
}
@ -835,7 +805,6 @@ std::string runTaskCommand (
int argc,
char** argv,
TDB& tdb,
Config& conf,
bool gc /* = true */,
bool shadow /* = true */)
{
@ -843,20 +812,19 @@ std::string runTaskCommand (
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
return runTaskCommand (args, tdb, conf, gc, shadow);
return runTaskCommand (args, tdb, gc, shadow);
}
////////////////////////////////////////////////////////////////////////////////
std::string runTaskCommand (
std::vector <std::string>& args,
TDB& tdb,
Config& conf,
bool gc /* = false */,
bool shadow /* = false */)
{
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::string defaultCommand = conf.get ("default.command");
std::string defaultCommand = context.config.get ("default.command");
if ((args.size () == 0 ||
(args.size () == 1 && args[0].substr (0, 3) == "rc:")) &&
defaultCommand != "")
@ -867,60 +835,60 @@ std::string runTaskCommand (
std::cout << "[task " << defaultCommand << "]" << std::endl;
}
loadCustomReports (conf);
loadCustomReports ();
std::string command;
T task;
parse (args, command, task, conf);
parse (args, command, task);
bool gcMod = false; // Change occurred by way of gc.
bool cmdMod = false; // Change occurred by way of command type.
std::string out;
// Read-only commands with no side effects.
if (command == "export") { out = handleExport (tdb, task, conf); }
else if (command == "projects") { out = handleProjects (tdb, task, conf); }
else if (command == "tags") { out = handleTags (tdb, task, conf); }
else if (command == "info") { out = handleInfo (tdb, task, conf); }
else if (command == "stats") { out = handleReportStats (tdb, task, conf); }
else if (command == "history") { out = handleReportHistory (tdb, task, conf); }
else if (command == "ghistory") { out = handleReportGHistory (tdb, task, conf); }
else if (command == "calendar") { out = handleReportCalendar (tdb, task, conf); }
else if (command == "summary") { out = handleReportSummary (tdb, task, conf); }
else if (command == "timesheet") { out = handleReportTimesheet (tdb, task, conf); }
else if (command == "colors") { out = handleColor ( conf); }
else if (command == "version") { out = handleVersion ( conf); }
else if (command == "help") { out = longUsage ( conf); }
if (command == "export") { out = handleExport (tdb, task); }
else if (command == "projects") { out = handleProjects (tdb, task); }
else if (command == "tags") { out = handleTags (tdb, task); }
else if (command == "info") { out = handleInfo (tdb, task); }
else if (command == "stats") { out = handleReportStats (tdb, task); }
else if (command == "history") { out = handleReportHistory (tdb, task); }
else if (command == "ghistory") { out = handleReportGHistory (tdb, task); }
else if (command == "calendar") { out = handleReportCalendar (tdb, task); }
else if (command == "summary") { out = handleReportSummary (tdb, task); }
else if (command == "timesheet") { out = handleReportTimesheet (tdb, task); }
else if (command == "colors") { out = handleColor ( ); }
else if (command == "version") { out = handleVersion ( ); }
else if (command == "help") { out = longUsage ( ); }
// Commands that cause updates.
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task, conf); }
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task, conf); }
else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task, conf); }
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (tdb, task, conf); }
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task, conf); }
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task, conf); }
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task, conf); }
else if (command == "start") { cmdMod = true; out = handleStart (tdb, task, conf); }
else if (command == "stop") { cmdMod = true; out = handleStop (tdb, task, conf); }
else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task, conf); }
else if (command == "import") { cmdMod = true; out = handleImport (tdb, task, conf); }
else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (tdb, task, conf); }
else if (command == "edit") { cmdMod = true; out = handleEdit (tdb, task, conf); }
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task); }
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task); }
else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task); }
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (tdb, task); }
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task); }
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task); }
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task); }
else if (command == "start") { cmdMod = true; out = handleStart (tdb, task); }
else if (command == "stop") { cmdMod = true; out = handleStop (tdb, task); }
else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task); }
else if (command == "import") { cmdMod = true; out = handleImport (tdb, task); }
else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (tdb, task); }
else if (command == "edit") { cmdMod = true; out = handleEdit (tdb, task); }
// Command that display IDs and therefore need TDB::gc first.
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task, conf); }
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (tdb, task, conf); }
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (tdb, task, conf); }
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (tdb, task, conf); }
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (tdb, task, conf, command); }
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task); }
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (tdb, task); }
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (tdb, task); }
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (tdb, task); }
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (tdb, task, command); }
// If the command is not recognized, display usage.
else { out = shortUsage (conf); }
else { out = shortUsage (); }
// Only update the shadow file if such an update was not suppressed (shadow),
// and if an actual change occurred (gcMod || cmdMod).
if (shadow && (gcMod || cmdMod))
updateShadowFile (tdb, conf);
updateShadowFile (tdb);
return out;
}

View file

@ -32,50 +32,49 @@
#include "Context.h"
#include "T.h"
#include "TDB.h"
#include "Config.h"
#include "Table.h"
#include "Date.h"
#include "color.h"
#include "../auto.h"
// parse.cpp
void parse (std::vector <std::string>&, std::string&, T&, Config&);
void parse (std::vector <std::string>&, std::string&, T&);
bool validPriority (const std::string&);
bool validDate (std::string&, Config&);
bool validDate (std::string&);
bool validDuration (std::string&);
void loadCustomReports (Config&);
void loadCustomReports ();
bool isCustomReport (const std::string&);
void allCustomReports (std::vector <std::string>&);
// task.cpp
void gatherNextTasks (const TDB&, T&, Config&, std::vector <T>&, std::vector <int>&);
void nag (TDB&, T&, Config&);
void gatherNextTasks (const TDB&, T&, std::vector <T>&, std::vector <int>&);
void nag (TDB&, T&);
int getDueState (const std::string&);
void handleRecurrence (TDB&, std::vector <T>&);
bool generateDueDates (T&, std::vector <Date>&);
Date getNextRecurrence (Date&, std::string&);
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
void onChangeCallback ();
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true, bool shadow = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false, bool shadow = false);
std::string runTaskCommand (int, char**, TDB&, bool gc = true, bool shadow = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, bool gc = false, bool shadow = false);
// command.cpp
std::string handleAdd (TDB&, T&, Config&);
std::string handleAppend (TDB&, T&, Config&);
std::string handleExport (TDB&, T&, Config&);
std::string handleDone (TDB&, T&, Config&);
std::string handleModify (TDB&, T&, Config&);
std::string handleProjects (TDB&, T&, Config&);
std::string handleTags (TDB&, T&, Config&);
std::string handleUndelete (TDB&, T&, Config&);
std::string handleVersion (Config&);
std::string handleDelete (TDB&, T&, Config&);
std::string handleStart (TDB&, T&, Config&);
std::string handleStop (TDB&, T&, Config&);
std::string handleUndo (TDB&, T&, Config&);
std::string handleColor (Config&);
std::string handleAnnotate (TDB&, T&, Config&);
std::string handleDuplicate (TDB&, T&, Config&);
std::string handleAdd (TDB&, T&);
std::string handleAppend (TDB&, T&);
std::string handleExport (TDB&, T&);
std::string handleDone (TDB&, T&);
std::string handleModify (TDB&, T&);
std::string handleProjects (TDB&, T&);
std::string handleTags (TDB&, T&);
std::string handleUndelete (TDB&, T&);
std::string handleVersion ();
std::string handleDelete (TDB&, T&);
std::string handleStart (TDB&, T&);
std::string handleStop (TDB&, T&);
std::string handleUndo (TDB&, T&);
std::string handleColor ();
std::string handleAnnotate (TDB&, T&);
std::string handleDuplicate (TDB&, T&);
T findT (int, const std::vector <T>&);
int deltaAppend (T&, T&);
int deltaDescription (T&, T&);
@ -84,33 +83,33 @@ int deltaAttributes (T&, T&);
int deltaSubstitutions (T&, T&);
// edit.cpp
std::string handleEdit (TDB&, T&, Config&);
std::string handleEdit (TDB&, T&);
// report.cpp
void filterSequence (std::vector<T>&, T&);
void filter (std::vector<T>&, T&);
std::string handleInfo (TDB&, T&, Config&);
std::string handleCompleted (TDB&, T&, Config&);
std::string handleReportSummary (TDB&, T&, Config&);
std::string handleReportNext (TDB&, T&, Config&);
std::string handleReportHistory (TDB&, T&, Config&);
std::string handleReportGHistory (TDB&, T&, Config&);
std::string handleReportCalendar (TDB&, T&, Config&);
std::string handleReportActive (TDB&, T&, Config&);
std::string handleReportOverdue (TDB&, T&, Config&);
std::string handleReportStats (TDB&, T&, Config&);
std::string handleReportTimesheet (TDB&, T&, Config&);
std::string handleInfo (TDB&, T&);
std::string handleCompleted (TDB&, T&);
std::string handleReportSummary (TDB&, T&);
std::string handleReportNext (TDB&, T&);
std::string handleReportHistory (TDB&, T&);
std::string handleReportGHistory (TDB&, T&);
std::string handleReportCalendar (TDB&, T&);
std::string handleReportActive (TDB&, T&);
std::string handleReportOverdue (TDB&, T&);
std::string handleReportStats (TDB&, T&);
std::string handleReportTimesheet (TDB&, T&);
std::string handleCustomReport (TDB&, T&, Config&, const std::string&);
std::string handleCustomReport (TDB&, T&, const std::string&);
void validReportColumns (const std::vector <std::string>&);
void validSortColumns (const std::vector <std::string>&, const std::vector <std::string>&);
// rules.cpp
void initializeColorRules (Config&);
void autoColorize (T&, Text::color&, Text::color&, Config&);
void initializeColorRules ();
void autoColorize (T&, Text::color&, Text::color&);
// import.cpp
std::string handleImport (TDB&, T&, Config&);
std::string handleImport (TDB&, T&);
// list template
///////////////////////////////////////////////////////////////////////////////

View file

@ -5,7 +5,7 @@ LFLAGS = -L/usr/local/lib
OBJECTS = ../TDB.o ../TDB2.o ../T.o ../T2.o ../parse.o ../text.o ../Date.o \
../Duration.o ../util.o ../Config.o ../Sequence.o ../Att.o \
../Record.o ../Mod.o ../StringTable.o ../Subst.o ../Nibbler.o \
../Filter.o ../Location.o
../Filter.o ../Location.o ../Context.o ../Keymap.o
all: $(PROJECT)

View file

@ -24,9 +24,12 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <Context.h>
#include <Att.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -29,6 +29,8 @@
#include <util.h>
#include <task.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -25,9 +25,12 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <Context.h>
#include <Date.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -25,9 +25,12 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <Context.h>
#include <Duration.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
// daily, day, Nd
// weekly, 1w, sennight, biweekly, fortnight

View file

@ -24,9 +24,12 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <Context.h>
#include <Mod.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -24,9 +24,12 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <Context.h>
#include <Nibbler.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -29,6 +29,8 @@
#include "text.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
@ -37,13 +39,12 @@ int main (int argc, char** argv)
std::vector <std::string> args;
std::string command;
Config conf;
conf.set ("dateformat", "m/d/Y");
context.config.set ("dateformat", "m/d/Y");
{
T task;
split (args, "add foo", ' ');
parse (args, command, task, conf);
parse (args, command, task);
t.is (command, "add", "(1) command found");
t.is (task.getId (), 0, "(1) zero id on add");
t.is (task.getDescription (), "foo", "(1) correct description");
@ -52,7 +53,7 @@ int main (int argc, char** argv)
{
T task;
split (args, "delete 1,3-5,7", ' ');
parse (args, command, task, conf);
parse (args, command, task);
std::vector <int> sequence = task.getAllIds ();
t.is (sequence.size (), (size_t)5, "(2) sequence length");
if (sequence.size () == 5)
@ -76,7 +77,7 @@ int main (int argc, char** argv)
{
T task;
split (args, "delete 1,2 3,4", ' ');
parse (args, command, task, conf);
parse (args, command, task);
std::vector <int> sequence = task.getAllIds ();
t.is (sequence.size (), (size_t)4, "(3) sequence length");
if (sequence.size () == 4)
@ -98,7 +99,7 @@ int main (int argc, char** argv)
{
T task;
split (args, "1 There are 7 days in a week", ' ');
parse (args, command, task, conf);
parse (args, command, task);
std::vector <int> sequence = task.getAllIds ();
t.is (sequence.size (), (size_t)1, "(4) sequence length");
if (sequence.size () == 1)
@ -116,7 +117,7 @@ int main (int argc, char** argv)
args.clear ();
args.push_back ("1");
args.push_back ("4-123 is back-ordered");
parse (args, command, task, conf);
parse (args, command, task);
std::vector <int> sequence = task.getAllIds ();
t.is (sequence.size (), (size_t)1, "(5) sequence length");
if (sequence.size () == 1)

View file

@ -25,10 +25,13 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <Context.h>
#include <Att.h>
#include <Record.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -25,9 +25,12 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <Context.h>
#include <Sequence.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
Sequence parseSequence (const std::string& input)
{

View file

@ -25,10 +25,13 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <unistd.h>
#include <Context.h>
#include <StringTable.h>
#include <util.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -24,10 +24,13 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <Context.h>
#include <T2.h>
#include <Subst.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -29,6 +29,8 @@
#include "task.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -29,6 +29,8 @@
#include "task.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -31,6 +31,8 @@
#include "task.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -29,6 +29,8 @@
#include "text.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{

View file

@ -27,10 +27,12 @@
#include <iostream>
#include <vector>
#include <string>
#include "Config.h"
#include "Context.h"
#include "util.h"
#include "text.h"
extern Context context;
static const char* newline = "\n";
static const char* noline = "";
@ -294,9 +296,9 @@ std::string upperCase (const std::string& input)
}
////////////////////////////////////////////////////////////////////////////////
const char* optionalBlankLine (Config& conf)
const char* optionalBlankLine ()
{
if (conf.get ("blanklines", true) == true)
if (context.config.get ("blanklines", true) == true)
return newline;
return noline;

View file

@ -29,7 +29,6 @@
#include <string>
#include <vector>
#include "Config.h"
#include "../auto.h"
// text.cpp
@ -45,7 +44,7 @@ void join (std::string&, const std::string&, const std::vector<std::string>&);
std::string commify (const std::string&);
std::string lowerCase (const std::string&);
std::string upperCase (const std::string&);
const char* optionalBlankLine (Config&);
const char* optionalBlankLine ();
#endif
////////////////////////////////////////////////////////////////////////////////

545
src/utf8.cpp Normal file
View file

@ -0,0 +1,545 @@
#ifdef NOPE
/*
Basic UTF-8 manipulation routines
by Jeff Bezanson
placed in the public domain Fall 2005
This code is designed to provide the utilities you need to manipulate
UTF-8 as an internal string encoding. These functions do not perform the
error checking normally needed when handling UTF-8 data, so if you happen
to be from the Unicode Consortium you will want to flay me alive.
I do this because error checking can be performed at the boundaries (I/O),
with these routines reserved for higher performance on data known to be
valid.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif
#include "utf8.h"
static const u_int32_t offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL
};
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/* returns length of next utf-8 sequence */
int u8_seqlen(char *s)
{
return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1;
}
/* conversions without error checking
only works for valid UTF-8, i.e. no 5- or 6-byte sequences
srcsz = source size in bytes, or -1 if 0-terminated
sz = dest size in # of wide characters
returns # characters converted
dest will always be L'\0'-terminated, even if there isn't enough room
for all the characters.
if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space.
*/
int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz)
{
u_int32_t ch;
char *src_end = src + srcsz;
int nb;
int i=0;
while (i < sz-1) {
nb = trailingBytesForUTF8[(unsigned char)*src];
if (srcsz == -1) {
if (*src == 0)
goto done_toucs;
}
else {
if (src + nb >= src_end)
goto done_toucs;
}
ch = 0;
switch (nb) {
/* these fall through deliberately */
case 3: ch += (unsigned char)*src++; ch <<= 6;
case 2: ch += (unsigned char)*src++; ch <<= 6;
case 1: ch += (unsigned char)*src++; ch <<= 6;
case 0: ch += (unsigned char)*src++;
}
ch -= offsetsFromUTF8[nb];
dest[i++] = ch;
}
done_toucs:
dest[i] = 0;
return i;
}
/* srcsz = number of source characters, or -1 if 0-terminated
sz = size of dest buffer in bytes
returns # characters converted
dest will only be '\0'-terminated if there is enough space. this is
for consistency; imagine there are 2 bytes of space left, but the next
character requires 3 bytes. in this case we could NUL-terminate, but in
general we can't when there's insufficient space. therefore this function
only NUL-terminates if all the characters fit, and there's space for
the NUL as well.
the destination string will never be bigger than the source string.
*/
int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz)
{
u_int32_t ch;
int i = 0;
char *dest_end = dest + sz;
while (srcsz<0 ? src[i]!=0 : i < srcsz) {
ch = src[i];
if (ch < 0x80) {
if (dest >= dest_end)
return i;
*dest++ = (char)ch;
}
else if (ch < 0x800) {
if (dest >= dest_end-1)
return i;
*dest++ = (ch>>6) | 0xC0;
*dest++ = (ch & 0x3F) | 0x80;
}
else if (ch < 0x10000) {
if (dest >= dest_end-2)
return i;
*dest++ = (ch>>12) | 0xE0;
*dest++ = ((ch>>6) & 0x3F) | 0x80;
*dest++ = (ch & 0x3F) | 0x80;
}
else if (ch < 0x110000) {
if (dest >= dest_end-3)
return i;
*dest++ = (ch>>18) | 0xF0;
*dest++ = ((ch>>12) & 0x3F) | 0x80;
*dest++ = ((ch>>6) & 0x3F) | 0x80;
*dest++ = (ch & 0x3F) | 0x80;
}
i++;
}
if (dest < dest_end)
*dest = '\0';
return i;
}
int u8_wc_toutf8(char *dest, u_int32_t ch)
{
if (ch < 0x80) {
dest[0] = (char)ch;
return 1;
}
if (ch < 0x800) {
dest[0] = (ch>>6) | 0xC0;
dest[1] = (ch & 0x3F) | 0x80;
return 2;
}
if (ch < 0x10000) {
dest[0] = (ch>>12) | 0xE0;
dest[1] = ((ch>>6) & 0x3F) | 0x80;
dest[2] = (ch & 0x3F) | 0x80;
return 3;
}
if (ch < 0x110000) {
dest[0] = (ch>>18) | 0xF0;
dest[1] = ((ch>>12) & 0x3F) | 0x80;
dest[2] = ((ch>>6) & 0x3F) | 0x80;
dest[3] = (ch & 0x3F) | 0x80;
return 4;
}
return 0;
}
/* charnum => byte offset */
int u8_offset(char *str, int charnum)
{
int offs=0;
while (charnum > 0 && str[offs]) {
(void)(isutf(str[++offs]) || isutf(str[++offs]) ||
isutf(str[++offs]) || ++offs);
charnum--;
}
return offs;
}
/* byte offset => charnum */
int u8_charnum(char *s, int offset)
{
int charnum = 0, offs=0;
while (offs < offset && s[offs]) {
(void)(isutf(s[++offs]) || isutf(s[++offs]) ||
isutf(s[++offs]) || ++offs);
charnum++;
}
return charnum;
}
/* number of characters */
int u8_strlen(char *s)
{
int count = 0;
int i = 0;
while (u8_nextchar(s, &i) != 0)
count++;
return count;
}
/* reads the next utf-8 sequence out of a string, updating an index */
u_int32_t u8_nextchar(char *s, int *i)
{
u_int32_t ch = 0;
int sz = 0;
do {
ch <<= 6;
ch += (unsigned char)s[(*i)++];
sz++;
} while (s[*i] && !isutf(s[*i]));
ch -= offsetsFromUTF8[sz-1];
return ch;
}
void u8_inc(char *s, int *i)
{
(void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) ||
isutf(s[++(*i)]) || ++(*i));
}
void u8_dec(char *s, int *i)
{
(void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) ||
isutf(s[--(*i)]) || --(*i));
}
int octal_digit(char c)
{
return (c >= '0' && c <= '7');
}
int hex_digit(char c)
{
return ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f'));
}
/* assumes that src points to the character after a backslash
returns number of input characters processed */
int u8_read_escape_sequence(char *str, u_int32_t *dest)
{
u_int32_t ch;
char digs[9]="\0\0\0\0\0\0\0\0";
int dno=0, i=1;
ch = (u_int32_t)str[0]; /* take literal character */
if (str[0] == 'n')
ch = L'\n';
else if (str[0] == 't')
ch = L'\t';
else if (str[0] == 'r')
ch = L'\r';
else if (str[0] == 'b')
ch = L'\b';
else if (str[0] == 'f')
ch = L'\f';
else if (str[0] == 'v')
ch = L'\v';
else if (str[0] == 'a')
ch = L'\a';
else if (octal_digit(str[0])) {
i = 0;
do {
digs[dno++] = str[i++];
} while (octal_digit(str[i]) && dno < 3);
ch = strtol(digs, NULL, 8);
}
else if (str[0] == 'x') {
while (hex_digit(str[i]) && dno < 2) {
digs[dno++] = str[i++];
}
if (dno > 0)
ch = strtol(digs, NULL, 16);
}
else if (str[0] == 'u') {
while (hex_digit(str[i]) && dno < 4) {
digs[dno++] = str[i++];
}
if (dno > 0)
ch = strtol(digs, NULL, 16);
}
else if (str[0] == 'U') {
while (hex_digit(str[i]) && dno < 8) {
digs[dno++] = str[i++];
}
if (dno > 0)
ch = strtol(digs, NULL, 16);
}
*dest = ch;
return i;
}
/* convert a string with literal \uxxxx or \Uxxxxxxxx characters to UTF-8
example: u8_unescape(mybuf, 256, "hello\\u220e")
note the double backslash is needed if called on a C string literal */
int u8_unescape(char *buf, int sz, char *src)
{
int c=0, amt;
u_int32_t ch;
char temp[4];
while (*src && c < sz) {
if (*src == '\\') {
src++;
amt = u8_read_escape_sequence(src, &ch);
}
else {
ch = (u_int32_t)*src;
amt = 1;
}
src += amt;
amt = u8_wc_toutf8(temp, ch);
if (amt > sz-c)
break;
memcpy(&buf[c], temp, amt);
c += amt;
}
if (c < sz)
buf[c] = '\0';
return c;
}
int u8_escape_wchar(char *buf, int sz, u_int32_t ch)
{
if (ch == L'\n')
return snprintf(buf, sz, "\\n");
else if (ch == L'\t')
return snprintf(buf, sz, "\\t");
else if (ch == L'\r')
return snprintf(buf, sz, "\\r");
else if (ch == L'\b')
return snprintf(buf, sz, "\\b");
else if (ch == L'\f')
return snprintf(buf, sz, "\\f");
else if (ch == L'\v')
return snprintf(buf, sz, "\\v");
else if (ch == L'\a')
return snprintf(buf, sz, "\\a");
else if (ch == L'\\')
return snprintf(buf, sz, "\\\\");
else if (ch < 32 || ch == 0x7f)
return snprintf(buf, sz, "\\x%hhX", (unsigned char)ch);
else if (ch > 0xFFFF)
return snprintf(buf, sz, "\\U%.8X", (u_int32_t)ch);
else if (ch >= 0x80 && ch <= 0xFFFF)
return snprintf(buf, sz, "\\u%.4hX", (unsigned short)ch);
return snprintf(buf, sz, "%c", (char)ch);
}
int u8_escape(char *buf, int sz, char *src, int escape_quotes)
{
int c=0, i=0, amt;
while (src[i] && c < sz) {
if (escape_quotes && src[i] == '"') {
amt = snprintf(buf, sz - c, "\\\"");
i++;
}
else {
amt = u8_escape_wchar(buf, sz - c, u8_nextchar(src, &i));
}
c += amt;
buf += amt;
}
if (c < sz)
*buf = '\0';
return c;
}
char *u8_strchr(char *s, u_int32_t ch, int *charn)
{
int i = 0, lasti=0;
u_int32_t c;
*charn = 0;
while (s[i]) {
c = u8_nextchar(s, &i);
if (c == ch) {
return &s[lasti];
}
lasti = i;
(*charn)++;
}
return NULL;
}
char *u8_memchr(char *s, u_int32_t ch, size_t sz, int *charn)
{
int i = 0, lasti=0;
u_int32_t c;
int csz;
*charn = 0;
while (i < sz) {
c = csz = 0;
do {
c <<= 6;
c += (unsigned char)s[i++];
csz++;
} while (i < sz && !isutf(s[i]));
c -= offsetsFromUTF8[csz-1];
if (c == ch) {
return &s[lasti];
}
lasti = i;
(*charn)++;
}
return NULL;
}
int u8_is_locale_utf8(char *locale)
{
/* this code based on libutf8 */
const char* cp = locale;
for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) {
if (*cp == '.') {
const char* encoding = ++cp;
for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++)
;
if ((cp-encoding == 5 && !strncmp(encoding, "UTF-8", 5))
|| (cp-encoding == 4 && !strncmp(encoding, "utf8", 4)))
return 1; /* it's UTF-8 */
break;
}
}
return 0;
}
int u8_vprintf(char *fmt, va_list ap)
{
int cnt, sz=0;
char *buf;
u_int32_t *wcs;
sz = 512;
buf = (char*)alloca(sz);
try_print:
cnt = vsnprintf(buf, sz, fmt, ap);
if (cnt >= sz) {
buf = (char*)alloca(cnt - sz + 1);
sz = cnt + 1;
goto try_print;
}
wcs = (u_int32_t*)alloca((cnt+1) * sizeof(u_int32_t));
cnt = u8_toucs(wcs, cnt+1, buf, cnt);
printf("%ls", (wchar_t*)wcs);
return cnt;
}
int u8_printf(char *fmt, ...)
{
int cnt;
va_list args;
va_start(args, fmt);
cnt = u8_vprintf(fmt, args);
va_end(args);
return cnt;
}
#endif
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include "utf8.h"
static const u_int32_t offsetsFromUTF8[6] =
{
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL,
};
////////////////////////////////////////////////////////////////////////////////
// number of characters in a string.
int utf8_length (const std::string& s)
{
int count = 0;
int i = 0;
while (utf8_nextchar (s.c_str (), &i) != 0)
count++;
return count;
}
////////////////////////////////////////////////////////////////////////////////
// reads the next utf-8 sequence out of a string, updating an index.
u_int32_t utf8_nextchar (const char* s, int* i)
{
u_int32_t ch = 0;
int sz = 0;
do
{
ch <<= 6;
ch += (unsigned char) s[(*i)++];
sz++;
}
while (s[*i] && ! isutf (s[*i]));
return ch - offsetsFromUTF8[sz - 1];
}

113
src/utf8.h Normal file
View file

@ -0,0 +1,113 @@
#ifdef NOPE
#include <stdarg.h>
/* is c the start of a utf8 sequence? */
#define isutf(c) (((c)&0xC0)!=0x80)
/* convert UTF-8 data to wide character */
int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz);
/* the opposite conversion */
int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz);
/* single character to UTF-8 */
int u8_wc_toutf8(char *dest, u_int32_t ch);
/* character number to byte offset */
int u8_offset(char *str, int charnum);
/* byte offset to character number */
int u8_charnum(char *s, int offset);
/* return next character, updating an index variable */
u_int32_t u8_nextchar(char *s, int *i);
/* move to next character */
void u8_inc(char *s, int *i);
/* move to previous character */
void u8_dec(char *s, int *i);
/* returns length of next utf-8 sequence */
int u8_seqlen(char *s);
/* assuming src points to the character after a backslash, read an
escape sequence, storing the result in dest and returning the number of
input characters processed */
int u8_read_escape_sequence(char *src, u_int32_t *dest);
/* given a wide character, convert it to an ASCII escape sequence stored in
buf, where buf is "sz" bytes. returns the number of characters output. */
int u8_escape_wchar(char *buf, int sz, u_int32_t ch);
/* convert a string "src" containing escape sequences to UTF-8 */
int u8_unescape(char *buf, int sz, char *src);
/* convert UTF-8 "src" to ASCII with escape sequences.
if escape_quotes is nonzero, quote characters will be preceded by
backslashes as well. */
int u8_escape(char *buf, int sz, char *src, int escape_quotes);
/* utility predicates used by the above */
int octal_digit(char c);
int hex_digit(char c);
/* return a pointer to the first occurrence of ch in s, or NULL if not
found. character index of found character returned in *charn. */
char *u8_strchr(char *s, u_int32_t ch, int *charn);
/* same as the above, but searches a buffer of a given size instead of
a NUL-terminated string. */
char *u8_memchr(char *s, u_int32_t ch, size_t sz, int *charn);
/* count the number of characters in a UTF-8 string */
int u8_strlen(char *s);
int u8_is_locale_utf8(char *locale);
/* printf where the format string and arguments may be in UTF-8.
you can avoid this function and just use ordinary printf() if the current
locale is UTF-8. */
int u8_vprintf(char *fmt, va_list ap);
int u8_printf(char *fmt, ...);
#endif
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_UTF8
#define INCLUDED_UTF8
#include <string>
// is c the start of a utf8 sequence?
#define isutf(c) (((c)&0xC0)!=0x80)
int utf8_length (const std::string&);
u_int32_t utf8_nextchar (const char*, int*);
#endif