diff --git a/src/command.cpp b/src/command.cpp index ebab72b11..3e50b35b5 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -44,8 +44,10 @@ #include #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 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 '" diff --git a/src/edit.cpp b/src/edit.cpp index 30be75ec7..42d8c615d 100644 --- a/src/edit.cpp +++ b/src/edit.cpp @@ -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 ' 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 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); } diff --git a/src/import.cpp b/src/import.cpp index bcb154147..f5b5a0f1d 100644 --- a/src/import.cpp +++ b/src/import.cpp @@ -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 & 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 & lines) { std::vector 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 & lines) { std::vector 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 & lines) { std::vector failed; @@ -659,7 +658,6 @@ static std::string importTask_1_6_0 ( //////////////////////////////////////////////////////////////////////////////// static std::string importTaskCmdLine ( TDB& tdb, - Config& conf, const std::vector & lines) { std::vector 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 & lines) { std::vector 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 & lines) { std::vector 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 & lines) { std::vector 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; } } diff --git a/src/parse.cpp b/src/parse.cpp index 4397eaba1..f78bf4f40 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -30,12 +30,15 @@ #include #include +#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 & 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 all; - conf.all (all); + context.config.all (all); foreach (i, all) { diff --git a/src/report.cpp b/src/report.cpp index 73912b0f3..cc46dc21d 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -48,6 +48,8 @@ #include #endif +extern Context context; + //////////////////////////////////////////////////////////////////////////////// void filterSequence (std::vector& all, T& task) { @@ -202,14 +204,14 @@ void filter (std::vector& all, T& task) //////////////////////////////////////////////////////////////////////////////// // Successively apply filters based on the task object built from the command // line. Tasks that match all the specified criteria are listed. -std::string handleCompleted (TDB& tdb, T& task, Config& conf) +std::string handleCompleted (TDB& tdb, T& task) { 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; @@ -222,18 +224,18 @@ std::string handleCompleted (TDB& tdb, T& task, Config& conf) tdb.completedT (tasks); filter (tasks, task); - initializeColorRules (conf); + initializeColorRules (); // 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 ("Done"); table.addColumn ("Project"); table.addColumn ("Description"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -266,7 +268,7 @@ std::string handleCompleted (TDB& tdb, T& task, Config& conf) // All criteria match, so add refTask to the output table. int row = table.addRow (); - table.addCell (row, 0, end.toString (conf.get ("dateformat", "m/d/Y"))); + table.addCell (row, 0, end.toString (context.config.get ("dateformat", "m/d/Y"))); table.addCell (row, 1, refTask.getAttribute ("project")); std::string description = refTask.getDescription (); @@ -276,25 +278,25 @@ std::string handleCompleted (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } table.addCell (row, 2, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (refTask.getAttribute ("fg")); Text::color bg = Text::colorCode (refTask.getAttribute ("bg")); - autoColorize (refTask, fg, bg, conf); + autoColorize (refTask, fg, bg); table.setRowFg (row, fg); table.setRowBg (row, bg); } } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " task" : " tasks") << std::endl; @@ -307,14 +309,14 @@ std::string handleCompleted (TDB& tdb, T& task, Config& conf) //////////////////////////////////////////////////////////////////////////////// // Display all information for the given task. -std::string handleInfo (TDB& tdb, T& task, Config& conf) +std::string handleInfo (TDB& tdb, T& task) { 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; @@ -334,13 +336,13 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) Table table; table.setTableWidth (width); - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); table.addColumn ("Name"); table.addColumn ("Value"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -378,7 +380,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } @@ -446,7 +448,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) table.addCell (row, 0, "Due"); Date dt (::atoi (due.c_str ())); - due = dt.toString (conf.get ("dateformat", "m/d/Y")); + due = dt.toString (context.config.get ("dateformat", "m/d/Y")); table.addCell (row, 1, due); if (due.length ()) @@ -455,12 +457,12 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) Date nextweek = now + 7 * 86400; imminent = dt < nextweek ? true : false; - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { if (overdue) - table.setCellFg (row, 1, Text::colorCode (conf.get ("color.overdue", "red"))); + table.setCellFg (row, 1, Text::colorCode (context.config.get ("color.overdue", "red"))); else if (imminent) - table.setCellFg (row, 1, Text::colorCode (conf.get ("color.due", "yellow"))); + table.setCellFg (row, 1, Text::colorCode (context.config.get ("color.due", "yellow"))); } } } @@ -471,7 +473,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) row = table.addRow (); table.addCell (row, 0, "Start"); Date dt (::atoi (refTask.getAttribute ("start").c_str ())); - table.addCell (row, 1, dt.toString (conf.get ("dateformat", "m/d/Y"))); + table.addCell (row, 1, dt.toString (context.config.get ("dateformat", "m/d/Y"))); } // end @@ -480,7 +482,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) row = table.addRow (); table.addCell (row, 0, "End"); Date dt (::atoi (refTask.getAttribute ("end").c_str ())); - table.addCell (row, 1, dt.toString (conf.get ("dateformat", "m/d/Y"))); + table.addCell (row, 1, dt.toString (context.config.get ("dateformat", "m/d/Y"))); } // tags ... @@ -505,7 +507,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) row = table.addRow (); table.addCell (row, 0, "Entered"); Date dt (::atoi (refTask.getAttribute ("entry").c_str ())); - std::string entry = dt.toString (conf.get ("dateformat", "m/d/Y")); + std::string entry = dt.toString (context.config.get ("dateformat", "m/d/Y")); std::string age; std::string created = refTask.getAttribute ("entry"); @@ -535,7 +537,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) table.addCell (row, 1, color); } - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () << std::endl; } @@ -550,7 +552,7 @@ std::string handleInfo (TDB& tdb, T& task, Config& conf) // Project Remaining Avg Age Complete 0% 100% // A 12 13d 55% XXXXXXXXXXXXX----------- // B 109 3d 12h 10% XXX--------------------- -std::string handleReportSummary (TDB& tdb, T& task, Config& conf) +std::string handleReportSummary (TDB& tdb, T& task) { std::stringstream out; @@ -615,8 +617,8 @@ std::string handleReportSummary (TDB& tdb, T& task, Config& conf) table.addColumn ("Complete"); table.addColumn ("0% 100%"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -631,7 +633,7 @@ std::string handleReportSummary (TDB& tdb, T& task, Config& conf) table.setColumnJustification (3, Table::right); table.sortOn (0, Table::ascendingCharacter); - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); int barWidth = 30; foreach (i, allProjects) @@ -653,7 +655,7 @@ std::string handleReportSummary (TDB& tdb, T& task, Config& conf) int completedBar = (c * barWidth) / (c + p); std::string bar; - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { bar = "\033[42m"; for (int b = 0; b < completedBar; ++b) @@ -682,9 +684,9 @@ std::string handleReportSummary (TDB& tdb, T& task, Config& conf) } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " project" : " projects") << std::endl; @@ -713,7 +715,7 @@ std::string handleReportSummary (TDB& tdb, T& task, Config& conf) // // Make the "three" tasks a configurable number // -std::string handleReportNext (TDB& tdb, T& task, Config& conf) +std::string handleReportNext (TDB& tdb, T& task) { std::stringstream out; @@ -725,12 +727,12 @@ std::string handleReportNext (TDB& tdb, T& task, Config& conf) // Restrict to matching subset. std::vector matching; - gatherNextTasks (tdb, task, conf, pending, matching); + gatherNextTasks (tdb, task, pending, matching); // 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; @@ -743,12 +745,12 @@ std::string handleReportNext (TDB& tdb, T& task, Config& conf) tdb.pendingT (tasks); filter (tasks, task); - initializeColorRules (conf); + initializeColorRules (); // 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 ("ID"); table.addColumn ("Project"); table.addColumn ("Pri"); @@ -757,8 +759,8 @@ std::string handleReportNext (TDB& tdb, T& task, Config& conf) table.addColumn ("Age"); table.addColumn ("Description"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -808,7 +810,7 @@ std::string handleReportNext (TDB& tdb, T& task, Config& conf) } Date dt (::atoi (due.c_str ())); - due = dt.toString (conf.get ("dateformat", "m/d/Y")); + due = dt.toString (context.config.get ("dateformat", "m/d/Y")); } std::string active; @@ -839,34 +841,34 @@ std::string handleReportNext (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } table.addCell (row, 6, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (refTask.getAttribute ("fg")); Text::color bg = Text::colorCode (refTask.getAttribute ("bg")); - autoColorize (refTask, fg, bg, conf); + autoColorize (refTask, fg, bg); table.setRowFg (row, fg); table.setRowBg (row, bg); if (fg == Text::nocolor) { if (overdue) - table.setCellFg (row, 3, Text::colorCode (conf.get ("color.overdue", "red"))); + table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.overdue", "red"))); else if (imminent) - table.setCellFg (row, 3, Text::colorCode (conf.get ("color.due", "yellow"))); + table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.due", "yellow"))); } } } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " task" : " tasks") << std::endl; @@ -899,7 +901,7 @@ time_t monthlyEpoch (const std::string& date) return 0; } -std::string handleReportHistory (TDB& tdb, T& task, Config& conf) +std::string handleReportHistory (TDB& tdb, T& task) { std::stringstream out; @@ -992,7 +994,7 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) // Now build the table. Table table; - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); table.addColumn ("Year"); table.addColumn ("Month"); table.addColumn ("Added"); @@ -1000,8 +1002,8 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) table.addColumn ("Deleted"); table.addColumn ("Net"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -1064,7 +1066,7 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) } table.addCell (row, 5, net); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && net) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && net) table.setCellFg (row, 5, net > 0 ? Text::red: Text::green); } @@ -1074,7 +1076,7 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) row = table.addRow (); table.addCell (row, 1, "Average"); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) table.setRowFg (row, Text::bold); + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) table.setRowFg (row, Text::bold); table.addCell (row, 2, totalAdded / (table.rowCount () - 2)); table.addCell (row, 3, totalCompleted / (table.rowCount () - 2)); table.addCell (row, 4, totalDeleted / (table.rowCount () - 2)); @@ -1082,7 +1084,7 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () << std::endl; else @@ -1092,14 +1094,14 @@ std::string handleReportHistory (TDB& tdb, T& task, Config& conf) } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportGHistory (TDB& tdb, T& task, Config& conf) +std::string handleReportGHistory (TDB& tdb, T& task) { 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; @@ -1197,13 +1199,13 @@ std::string handleReportGHistory (TDB& tdb, T& task, Config& conf) // Now build the table. Table table; - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); table.addColumn ("Year"); table.addColumn ("Month"); table.addColumn ("Number Added/Completed/Deleted"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -1259,7 +1261,7 @@ std::string handleReportGHistory (TDB& tdb, T& task, Config& conf) unsigned int deletedBar = (widthOfBar * deletedGroup[i->first]) / maxLine; std::string bar = ""; - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { char number[24]; std::string aBar = ""; @@ -1314,18 +1316,18 @@ std::string handleReportGHistory (TDB& tdb, T& task, Config& conf) if (table.rowCount ()) { - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () << std::endl; - 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 << "Legend: " << Text::colorize (Text::black, Text::on_red, "added") << ", " << Text::colorize (Text::black, Text::on_green, "completed") << ", " << Text::colorize (Text::black, Text::on_yellow, "deleted") - << optionalBlankLine (conf) + << optionalBlankLine () << std::endl; else out << "Legend: + added, X completed, - deleted" << std::endl; @@ -1337,14 +1339,14 @@ std::string handleReportGHistory (TDB& tdb, T& task, Config& conf) } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) +std::string handleReportTimesheet (TDB& tdb, T& task) { 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; @@ -1358,7 +1360,7 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) filter (tasks, task); // What day of the week does the user consider the first? - int weekStart = Date::dayOfWeek (conf.get ("weekstart", "Sunday")); + int weekStart = Date::dayOfWeek (context.config.get ("weekstart", "Sunday")); if (weekStart != 0 && weekStart != 1) throw std::string ("The 'weekstart' configuration variable may " "only contain 'Sunday' or 'Monday'."); @@ -1382,9 +1384,9 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) { out << std::endl << Text::colorize (Text::bold, Text::nocolor) - << start.toString (conf.get ("dateformat", "m/d/Y")) + << start.toString (context.config.get ("dateformat", "m/d/Y")) << " - " - << end.toString (conf.get ("dateformat", "m/d/Y")) + << end.toString (context.config.get ("dateformat", "m/d/Y")) << Text::colorize () << std::endl; @@ -1425,7 +1427,7 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) if (due.length ()) { Date d (::atoi (due.c_str ())); - due = d.toString (conf.get ("dateformat", "m/d/Y")); + due = d.toString (context.config.get ("dateformat", "m/d/Y")); completed.addCell (row, 2, due); } @@ -1436,16 +1438,16 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } completed.addCell (row, 3, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (t->getAttribute ("fg")); Text::color bg = Text::colorCode (t->getAttribute ("bg")); - autoColorize (*t, fg, bg, conf); + autoColorize (*t, fg, bg); completed.setRowFg (row, fg); completed.setRowBg (row, bg); } @@ -1496,7 +1498,7 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) if (due.length ()) { Date d (::atoi (due.c_str ())); - due = d.toString (conf.get ("dateformat", "m/d/Y")); + due = d.toString (context.config.get ("dateformat", "m/d/Y")); started.addCell (row, 2, due); } @@ -1507,16 +1509,16 @@ std::string handleReportTimesheet (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } started.addCell (row, 3, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (t->getAttribute ("fg")); Text::color bg = Text::colorCode (t->getAttribute ("bg")); - autoColorize (*t, fg, bg, conf); + autoColorize (*t, fg, bg); started.setRowFg (row, fg); started.setRowBg (row, bg); } @@ -1545,14 +1547,13 @@ std::string renderMonths ( int firstYear, const Date& today, std::vector & all, - Config& conf, int monthsPerLine) { Table table; - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); // What day of the week does the user consider the first? - int weekStart = Date::dayOfWeek (conf.get ("weekstart", "Sunday")); + int weekStart = Date::dayOfWeek (context.config.get ("weekstart", "Sunday")); if (weekStart != 0 && weekStart != 1) throw std::string ("The 'weekstart' configuration variable may " "only contain 'Sunday' or 'Monday'."); @@ -1583,8 +1584,8 @@ std::string renderMonths ( table.addColumn ("Sa"); } - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (i + 1); table.setColumnUnderline (i + 2); @@ -1655,7 +1656,7 @@ std::string renderMonths ( int dow = temp.dayOfWeek (); int woy = temp.weekOfYear (weekStart); - if (conf.get ("displayweeknumber", true)) + if (context.config.get ("displayweeknumber", true)) table.addCell (row, (8 * mpl), woy); // Calculate column id. @@ -1668,7 +1669,7 @@ std::string renderMonths ( table.addCell (row, thisCol, d); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && today.day () == d && today.month () == months.at (mpl) && today.year () == years.at (mpl)) @@ -1679,7 +1680,7 @@ std::string renderMonths ( { Date due (::atoi (it->getAttribute ("due").c_str ())); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && due.day () == d && due.month () == months.at (mpl) && due.year () == years.at (mpl)) @@ -1702,14 +1703,14 @@ std::string renderMonths ( } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportCalendar (TDB& tdb, T& task, Config& conf) +std::string handleReportCalendar (TDB& tdb, T& task) { 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; @@ -1719,7 +1720,7 @@ std::string handleReportCalendar (TDB& tdb, T& task, Config& conf) // Each month requires 28 text columns width. See how many will actually // fit. But if a preference is specified, and it fits, use it. - int preferredMonthsPerLine = (conf.get (std::string ("monthsperline"), 0)); + int preferredMonthsPerLine = (context.config.get (std::string ("monthsperline"), 0)); int monthsThatFit = width / 26; int monthsPerLine = monthsThatFit; @@ -1801,8 +1802,8 @@ std::string handleReportCalendar (TDB& tdb, T& task, Config& conf) } out << std::endl - << optionalBlankLine (conf) - << renderMonths (mFrom, yFrom, today, pending, conf, monthsPerLine) + << optionalBlankLine () + << renderMonths (mFrom, yFrom, today, pending, monthsPerLine) << std::endl; mFrom += monthsPerLine; @@ -1813,7 +1814,7 @@ std::string handleReportCalendar (TDB& tdb, T& task, Config& conf) } } - 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 << "Legend: " << Text::colorize (Text::cyan, Text::nocolor, "today") << ", " @@ -1821,21 +1822,21 @@ std::string handleReportCalendar (TDB& tdb, T& task, Config& conf) << ", " << Text::colorize (Text::black, Text::on_red, "overdue") << "." - << optionalBlankLine (conf) + << optionalBlankLine () << std::endl; return out.str (); } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportActive (TDB& tdb, T& task, Config& conf) +std::string handleReportActive (TDB& tdb, T& task) { 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; @@ -1848,20 +1849,20 @@ std::string handleReportActive (TDB& tdb, T& task, Config& conf) tdb.pendingT (tasks); filter (tasks, task); - initializeColorRules (conf); + initializeColorRules (); // 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 ("ID"); table.addColumn ("Project"); table.addColumn ("Pri"); table.addColumn ("Due"); table.addColumn ("Description"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -1906,7 +1907,7 @@ std::string handleReportActive (TDB& tdb, T& task, Config& conf) } Date dt (::atoi (due.c_str ())); - due = dt.toString (conf.get ("dateformat", "m/d/Y")); + due = dt.toString (context.config.get ("dateformat", "m/d/Y")); } // All criteria match, so add refTask to the output table. @@ -1923,35 +1924,35 @@ std::string handleReportActive (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } table.addCell (row, 4, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (refTask.getAttribute ("fg")); Text::color bg = Text::colorCode (refTask.getAttribute ("bg")); - autoColorize (refTask, fg, bg, conf); + autoColorize (refTask, fg, bg); table.setRowFg (row, fg); table.setRowBg (row, bg); if (fg == Text::nocolor) { if (overdue) - table.setCellFg (row, 3, Text::colorCode (conf.get ("color.overdue", "red"))); + table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.overdue", "red"))); else if (imminent) - table.setCellFg (row, 3, Text::colorCode (conf.get ("color.due", "yellow"))); + table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.due", "yellow"))); } } } } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " task" : " tasks") << std::endl; @@ -1962,14 +1963,14 @@ std::string handleReportActive (TDB& tdb, T& task, Config& conf) } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) +std::string handleReportOverdue (TDB& tdb, T& task) { 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; @@ -1982,20 +1983,20 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) tdb.pendingT (tasks); filter (tasks, task); - initializeColorRules (conf); + initializeColorRules (); // 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 ("ID"); table.addColumn ("Project"); table.addColumn ("Pri"); table.addColumn ("Due"); table.addColumn ("Description"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -2031,7 +2032,7 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) if (due.length ()) { Date dt (::atoi (due.c_str ())); - due = dt.toString (conf.get ("dateformat", "m/d/Y")); + due = dt.toString (context.config.get ("dateformat", "m/d/Y")); // If overdue. if (dt < now) @@ -2050,17 +2051,17 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } table.addCell (row, 4, description); - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (refTask.getAttribute ("fg")); Text::color bg = Text::colorCode (refTask.getAttribute ("bg")); - autoColorize (refTask, fg, bg, conf); + autoColorize (refTask, fg, bg); table.setRowFg (row, fg); table.setRowBg (row, bg); @@ -2073,9 +2074,9 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) } if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " task" : " tasks") << std::endl; @@ -2086,14 +2087,14 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf) } //////////////////////////////////////////////////////////////////////////////// -std::string handleReportStats (TDB& tdb, T& task, Config& conf) +std::string handleReportStats (TDB& tdb, T& task) { 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; @@ -2164,12 +2165,12 @@ std::string handleReportStats (TDB& tdb, T& task, 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 ("Category"); table.addColumn ("Data"); - if ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) { table.setColumnUnderline (0); table.setColumnUnderline (1); @@ -2230,12 +2231,12 @@ std::string handleReportStats (TDB& tdb, T& task, Config& conf) Date e (earliest); row = table.addRow (); table.addCell (row, 0, "Oldest task"); - table.addCell (row, 1, e.toString (conf.get ("dateformat", "m/d/Y"))); + table.addCell (row, 1, e.toString (context.config.get ("dateformat", "m/d/Y"))); Date l (latest); row = table.addRow (); table.addCell (row, 0, "Newest task"); - table.addCell (row, 1, l.toString (conf.get ("dateformat", "m/d/Y"))); + table.addCell (row, 1, l.toString (context.config.get ("dateformat", "m/d/Y"))); row = table.addRow (); table.addCell (row, 0, "Task used for"); @@ -2279,9 +2280,9 @@ std::string handleReportStats (TDB& tdb, T& task, Config& conf) table.addCell (row, 1, value.str ()); } - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render () - << optionalBlankLine (conf); + << optionalBlankLine (); return out.str (); } @@ -2290,7 +2291,6 @@ std::string handleReportStats (TDB& tdb, T& task, Config& conf) void gatherNextTasks ( const TDB& tdb, T& task, - Config& conf, std::vector & pending, std::vector & all) { @@ -2301,7 +2301,7 @@ void gatherNextTasks ( Date now; // How many items per project? Default 3. - int limit = conf.get ("next", 3); + int limit = context.config.get ("next", 3); // due:< 1wk, pri:* for (unsigned int i = 0; i < pending.size (); ++i) @@ -2478,13 +2478,12 @@ void gatherNextTasks ( std::string handleCustomReport ( TDB& tdb, T& task, - Config& conf, const std::string& report) { // 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; @@ -2493,12 +2492,12 @@ std::string handleCustomReport ( #endif // Load report configuration. - std::string columnList = conf.get ("report." + report + ".columns"); + std::string columnList = context.config.get ("report." + report + ".columns"); std::vector columns; split (columns, columnList, ','); validReportColumns (columns); - std::string labelList = conf.get ("report." + report + ".labels"); + std::string labelList = context.config.get ("report." + report + ".labels"); std::vector labels; split (labels, labelList, ','); @@ -2511,12 +2510,12 @@ std::string handleCustomReport ( for (unsigned int i = 0; i < columns.size (); ++i) columnLabels[columns[i]] = labels[i]; - std::string sortList = conf.get ("report." + report + ".sort"); + std::string sortList = context.config.get ("report." + report + ".sort"); std::vector sortOrder; split (sortOrder, sortList, ','); validSortColumns (columns, sortOrder); - std::string filterList = conf.get ("report." + report + ".filter"); + std::string filterList = context.config.get ("report." + report + ".filter"); std::vector filterArgs; split (filterArgs, filterList, ' '); @@ -2529,18 +2528,18 @@ std::string handleCustomReport ( { std::string ignore; T filterTask; - parse (filterArgs, ignore, filterTask, conf); + parse (filterArgs, ignore, filterTask); filter (tasks, filterTask); // Filter from custom report filter (tasks, task); // Filter from command line } // Initialize colorization for subsequent auto colorization. - initializeColorRules (conf); + initializeColorRules (); Table table; table.setTableWidth (width); - table.setDateFormat (conf.get ("dateformat", "m/d/Y")); + table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); for (unsigned int i = 0; i < tasks.size (); ++i) table.addRow (); @@ -2603,7 +2602,7 @@ std::string handleCustomReport ( if (entered.length ()) { Date dt (::atoi (entered.c_str ())); - entered = dt.toString (conf.get ("dateformat", "m/d/Y")); + entered = dt.toString (context.config.get ("dateformat", "m/d/Y")); table.addCell (row, columnCount, entered); } } @@ -2622,7 +2621,7 @@ std::string handleCustomReport ( if (started.length ()) { Date dt (::atoi (started.c_str ())); - started = dt.toString (conf.get ("dateformat", "m/d/Y")); + started = dt.toString (context.config.get ("dateformat", "m/d/Y")); table.addCell (row, columnCount, started); } } @@ -2641,7 +2640,7 @@ std::string handleCustomReport ( if (due.length ()) { Date dt (::atoi (due.c_str ())); - due = dt.toString (conf.get ("dateformat", "m/d/Y")); + due = dt.toString (context.config.get ("dateformat", "m/d/Y")); table.addCell (row, columnCount, due); } } @@ -2723,7 +2722,7 @@ std::string handleCustomReport ( foreach (anno, annotations) { Date dt (anno->first); - when = dt.toString (conf.get ("dateformat", "m/d/Y")); + when = dt.toString (context.config.get ("dateformat", "m/d/Y")); description += "\n" + when + " " + anno->second; } @@ -2765,8 +2764,8 @@ std::string handleCustomReport ( // Common to all columns. // Add underline. - if ((conf.get (std::string ("color"), true) || conf.get (std::string ("_forcecolor"), false)) && - conf.get (std::string ("fontunderline"), "true")) + if ((context.config.get (std::string ("color"), true) || context.config.get (std::string ("_forcecolor"), false)) && + context.config.get (std::string ("fontunderline"), "true")) table.setColumnUnderline (columnCount); else table.setTableDashedUnderline (); @@ -2837,11 +2836,11 @@ std::string handleCustomReport ( } } - if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false)) + if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) { Text::color fg = Text::colorCode (tasks[row].getAttribute ("fg")); Text::color bg = Text::colorCode (tasks[row].getAttribute ("bg")); - autoColorize (tasks[row], fg, bg, conf); + autoColorize (tasks[row], fg, bg); table.setRowFg (row, fg); table.setRowBg (row, bg); @@ -2850,20 +2849,20 @@ std::string handleCustomReport ( if (dueColumn != -1) { if (overdue) - table.setCellFg (row, columnCount, Text::colorCode (conf.get ("color.overdue", "red"))); + table.setCellFg (row, columnCount, Text::colorCode (context.config.get ("color.overdue", "red"))); else if (imminent) - table.setCellFg (row, columnCount, Text::colorCode (conf.get ("color.due", "yellow"))); + table.setCellFg (row, columnCount, Text::colorCode (context.config.get ("color.due", "yellow"))); } } } } // Limit the number of rows according to the report definition. - int maximum = conf.get (std::string ("report.") + report + ".limit", (int)0); + int maximum = context.config.get (std::string ("report.") + report + ".limit", (int)0); // If the custom report has a defined limit, then allow an override, which // will show up as a single ID sequence. - if (conf.get (std::string ("report.") + report + ".limit", (int)0) != 0) + if (context.config.get (std::string ("report.") + report + ".limit", (int)0) != 0) { std::vector sequence = task.getAllIds (); if (sequence.size () == 1) @@ -2872,9 +2871,9 @@ std::string handleCustomReport ( std::stringstream out; if (table.rowCount ()) - out << optionalBlankLine (conf) + out << optionalBlankLine () << table.render (maximum) - << optionalBlankLine (conf) + << optionalBlankLine () << table.rowCount () << (table.rowCount () == 1 ? " task" : " tasks") << std::endl; diff --git a/src/rules.cpp b/src/rules.cpp index 2030e1a36..3d2fab931 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -26,13 +26,15 @@ //////////////////////////////////////////////////////////////////////////////// #include #include -#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 gsFg; static std::map gsBg; @@ -63,17 +65,17 @@ static void parseColorRule ( } //////////////////////////////////////////////////////////////////////////////// -void initializeColorRules (Config& conf) +void initializeColorRules () { std::vector 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) diff --git a/src/sandbox/main.cpp b/src/sandbox/main.cpp index 22e56c672..904c117e5 100644 --- a/src/sandbox/main.cpp +++ b/src/sandbox/main.cpp @@ -3,25 +3,26 @@ #include #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 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 (); //////////////////////////////////////////////////////////////////////////////// diff --git a/src/task.cpp b/src/task.cpp index 0981503ef..dbb00d3ac 100644 --- a/src/task.cpp +++ b/src/task.cpp @@ -50,16 +50,17 @@ #include #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 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 & 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; } diff --git a/src/task.h b/src/task.h index 04294ca6d..092bc993a 100644 --- a/src/task.h +++ b/src/task.h @@ -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&, T&, Config&); +void parse (std::vector &, 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 &); // task.cpp -void gatherNextTasks (const TDB&, T&, Config&, std::vector &, std::vector &); -void nag (TDB&, T&, Config&); +void gatherNextTasks (const TDB&, T&, std::vector &, std::vector &); +void nag (TDB&, T&); int getDueState (const std::string&); void handleRecurrence (TDB&, std::vector &); bool generateDueDates (T&, std::vector &); Date getNextRecurrence (Date&, std::string&); void updateRecurrenceMask (TDB&, std::vector &, T&); void onChangeCallback (); -std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true, bool shadow = true); -std::string runTaskCommand (std::vector &, 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 &, 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 &); 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&); void filter (std::vector&, 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 &); void validSortColumns (const std::vector &, const std::vector &); // 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 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/tests/Makefile b/src/tests/Makefile index d95ee1490..971e560b8 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -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) diff --git a/src/tests/att.t.cpp b/src/tests/att.t.cpp index 6c6958605..7726bd91c 100644 --- a/src/tests/att.t.cpp +++ b/src/tests/att.t.cpp @@ -24,9 +24,12 @@ // USA // //////////////////////////////////////////////////////////////////////////////// +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/autocomplete.t.cpp b/src/tests/autocomplete.t.cpp index aac9b31ec..806a3f840 100644 --- a/src/tests/autocomplete.t.cpp +++ b/src/tests/autocomplete.t.cpp @@ -29,6 +29,8 @@ #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/date.t.cpp b/src/tests/date.t.cpp index 517313576..97c87ce01 100644 --- a/src/tests/date.t.cpp +++ b/src/tests/date.t.cpp @@ -25,9 +25,12 @@ // //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/duration.t.cpp b/src/tests/duration.t.cpp index ffd4ff39e..d72a75403 100644 --- a/src/tests/duration.t.cpp +++ b/src/tests/duration.t.cpp @@ -25,9 +25,12 @@ // //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// // daily, day, Nd // weekly, 1w, sennight, biweekly, fortnight diff --git a/src/tests/mod.t.cpp b/src/tests/mod.t.cpp index 385a57038..be37a3f5f 100644 --- a/src/tests/mod.t.cpp +++ b/src/tests/mod.t.cpp @@ -24,9 +24,12 @@ // USA // //////////////////////////////////////////////////////////////////////////////// +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/nibbler.t.cpp b/src/tests/nibbler.t.cpp index 93bbf3cef..03d5ae96e 100644 --- a/src/tests/nibbler.t.cpp +++ b/src/tests/nibbler.t.cpp @@ -24,9 +24,12 @@ // USA // //////////////////////////////////////////////////////////////////////////////// +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/parse.t.cpp b/src/tests/parse.t.cpp index 430150e15..2df17d913 100644 --- a/src/tests/parse.t.cpp +++ b/src/tests/parse.t.cpp @@ -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 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 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 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 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 sequence = task.getAllIds (); t.is (sequence.size (), (size_t)1, "(5) sequence length"); if (sequence.size () == 1) diff --git a/src/tests/record.t.cpp b/src/tests/record.t.cpp index 2f694013f..598967ffb 100644 --- a/src/tests/record.t.cpp +++ b/src/tests/record.t.cpp @@ -25,10 +25,13 @@ // //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/seq.t.cpp b/src/tests/seq.t.cpp index 0459dd5cd..8b48c5a5d 100644 --- a/src/tests/seq.t.cpp +++ b/src/tests/seq.t.cpp @@ -25,9 +25,12 @@ // //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// Sequence parseSequence (const std::string& input) { diff --git a/src/tests/stringtable.t.cpp b/src/tests/stringtable.t.cpp index 4d282d0b4..e05234dec 100644 --- a/src/tests/stringtable.t.cpp +++ b/src/tests/stringtable.t.cpp @@ -25,10 +25,13 @@ // //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/subst.t.cpp b/src/tests/subst.t.cpp index 982ef205a..add082125 100644 --- a/src/tests/subst.t.cpp +++ b/src/tests/subst.t.cpp @@ -24,10 +24,13 @@ // USA // //////////////////////////////////////////////////////////////////////////////// +#include #include #include #include +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/t.benchmark.t.cpp b/src/tests/t.benchmark.t.cpp index 857ab84aa..1a19c8db1 100644 --- a/src/tests/t.benchmark.t.cpp +++ b/src/tests/t.benchmark.t.cpp @@ -29,6 +29,8 @@ #include "task.h" #include "test.h" +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/t.t.cpp b/src/tests/t.t.cpp index 484866fa9..ca6d91d36 100644 --- a/src/tests/t.t.cpp +++ b/src/tests/t.t.cpp @@ -29,6 +29,8 @@ #include "task.h" #include "test.h" +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/tdb.t.cpp b/src/tests/tdb.t.cpp index fd19d0ada..8931e7d4d 100644 --- a/src/tests/tdb.t.cpp +++ b/src/tests/tdb.t.cpp @@ -31,6 +31,8 @@ #include "task.h" #include "test.h" +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/tests/text.t.cpp b/src/tests/text.t.cpp index 24da8ca2b..dcabb4d5a 100644 --- a/src/tests/text.t.cpp +++ b/src/tests/text.t.cpp @@ -29,6 +29,8 @@ #include "text.h" #include "test.h" +Context context; + //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { diff --git a/src/text.cpp b/src/text.cpp index ac1015031..9db0d7e5a 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -27,10 +27,12 @@ #include #include #include -#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; diff --git a/src/text.h b/src/text.h index 458d714d0..121c1babf 100644 --- a/src/text.h +++ b/src/text.h @@ -29,7 +29,6 @@ #include #include -#include "Config.h" #include "../auto.h" // text.cpp @@ -45,7 +44,7 @@ void join (std::string&, const std::string&, const std::vector&); 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 //////////////////////////////////////////////////////////////////////////////// diff --git a/src/utf8.cpp b/src/utf8.cpp new file mode 100644 index 000000000..3854f8916 --- /dev/null +++ b/src/utf8.cpp @@ -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 +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#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]; +} + diff --git a/src/utf8.h b/src/utf8.h new file mode 100644 index 000000000..82ead15d8 --- /dev/null +++ b/src/utf8.h @@ -0,0 +1,113 @@ +#ifdef NOPE +#include + +/* 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 + +// 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 +