Fri, 14 Jun 2013 16:00:54 +0300
Converted to 16-bit strings.. again
--- a/src/aboutDialog.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/aboutDialog.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -32,9 +32,9 @@ icon->setPixmap (getIcon ("ldforge")); // Heading - application label and copyright information - QLabel* title = new QLabel (fmt ("<b>" APPNAME " %s</b><br />" + QLabel* title = new QLabel (fmt ("<b>" APPNAME " %1</b><br />" "Copyright (C) 2013 Santeri Piippo", - fullVersionString ().chars ())); + qchars (fullVersionString ()))); // Body text QLabel* info = new QLabel (
--- a/src/addObjectDialog.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/addObjectDialog.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -32,6 +32,7 @@ #include "colorSelectDialog.h" #include "history.h" #include "widgets.h" +#include "misc.h" // ============================================================================= class SubfileListItem : public QTreeWidgetItem { @@ -113,9 +114,9 @@ QList<QTreeWidgetItem*> subfileItems; str fileName = part.sName; - const bool isSubpart = fileName.substr (0, 2) == "s\\"; - const bool isPrimitive = str (part.sTitle).substr (0, 9) == "Primitive"; - const bool isHiRes = fileName.substr (0, 3) == "48\\"; + const bool isSubpart = fileName.mid (0, 2) == "s\\"; + const bool isPrimitive = str (part.sTitle).mid (0, 9) == "Primitive"; + const bool isHiRes = fileName.mid (0, 3) == "48\\"; if ((i == Subparts && isSubpart) || (i == Primitives && isPrimitive) || @@ -123,7 +124,7 @@ (i == Parts && !isSubpart && !isPrimitive && !isHiRes)) { SubfileListItem* item = new SubfileListItem (parentItem, j); - item->setText (0, fmt ("%s - %s", part.sName, part.sTitle)); + item->setText (0, fmt ("%1 - %2", part.sName, part.sTitle)); subfileItems.append (item); } @@ -182,11 +183,11 @@ break; default: - critical (fmt ("Unhandled LDObject type %d (%s) in AddObjectDialog", (int) type, g_saObjTypeNames[type])); + critical (fmt ("Unhandled LDObject type %1 (%2) in AddObjectDialog", (int) type, g_saObjTypeNames[type])); return; } - QPixmap icon = getIcon (fmt ("add-%s", g_saObjTypeIcons[type])); + QPixmap icon = getIcon (fmt ("add-%1", g_saObjTypeIcons[type])); LDObject* defaults = LDObject::getDefault (type); lb_typeIcon = new QLabel; @@ -288,8 +289,8 @@ layout->addWidget (makeButtonBox (*this), 5, 0, 1, 4); setLayout (layout); - setWindowTitle (fmt (APPNAME ": New %s", - g_saObjTypeNames[type]).chars()); + setWindowTitle (fmt (APPNAME ": New %1", + g_saObjTypeNames[type])); setWindowIcon (icon); delete defaults; @@ -301,9 +302,7 @@ void AddObjectDialog::setButtonBackground (QPushButton* button, short color) { button->setIcon (getIcon ("palette")); button->setAutoFillBackground (true); - button->setStyleSheet ( - fmt ("background-color: %s", getColor (color)->hexcode.chars()).chars() - ); + button->setStyleSheet (fmt ("background-color: %1", getColor (color)->hexcode)); } // ============================================================================= @@ -375,14 +374,14 @@ matrix transform = g_identity; if (type == LDObject::Subfile || type == LDObject::Radial) { - vector<str> matrixstrvals = str (dlg.le_matrix->text ()).split (" "); + vector<str> matrixstrvals = container_cast<QStringList, vector<str>> (str (dlg.le_matrix->text ()).split (" ")); if (matrixstrvals.size () == 9) { double matrixvals[9]; int i = 0; for (str val : matrixstrvals) - matrixvals[i++] = atof (val); + matrixvals[i++] = val.toFloat (); transform = matrix (matrixvals); } @@ -446,12 +445,12 @@ case LDObject::Subfile: { str name = dlg.le_subfileName->text (); - if (~name == 0) + if (name.length () == 0) return; // no subfile filename LDOpenFile* file = getFile (name); if (!file) { - critical (fmt ("Couldn't open `%s': %s", name.c (), strerror (errno))); + critical (fmt ("Couldn't open `%1': %2", name, strerror (errno))); return; }
--- a/src/colorSelectDialog.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/colorSelectDialog.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -112,12 +112,12 @@ if (i == maincolor) { // Use the user preferences for main color here - col = gl_maincolor.value.chars (); + col = gl_maincolor.value; col.setAlpha (gl_maincolor_alpha * 255.0f); } gs_scene->addRect (x, y, w, w, pen, col); - QGraphicsTextItem* numtext = gs_scene->addText (fmt ("%d", i).chars()); + QGraphicsTextItem* numtext = gs_scene->addText (fmt ("%1", i)); numtext->setDefaultTextColor ((luma (col) < 80) ? Qt::white : Qt::black); numtext->setPos (x, y); @@ -139,8 +139,8 @@ return; } - lb_colorInfo->setText (fmt ("%d - %s", - selColor, col->name.chars())); + lb_colorInfo->setText (fmt ("%1 - %2", + selColor, col->name)); } // =============================================================================
--- a/src/colors.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/colors.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -26,14 +26,14 @@ static color* g_LDColors[MAX_COLORS]; void initColors () { - printf ("%s: initializing color information.\n", __func__); + print ("%1: initializing color information.\n", __func__); color* col; // Always make sure there's 16 and 24 available. They're special like that. col = new color; col->hexcode = "#AAAAAA"; - col->faceColor = col->hexcode.chars (); + col->faceColor = col->hexcode; col->edgeColor = Qt::black; g_LDColors[maincolor] = col; @@ -81,7 +81,7 @@ FILE* fp = openLDrawFile ("LDConfig.ldr", false); if (!fp) { - critical (fmt ("Unable to open LDConfig.ldr for parsing! (%s)", strerror (errno))); + critical (fmt ("Unable to open LDConfig.ldr for parsing! (%1)", strerror (errno))); return; } @@ -92,7 +92,9 @@ continue; // empty or illogical // Use StringParser to parse the LDConfig.ldr file. - str line = str (buf).strip ({'\n', '\r'}); + str line = buf; + line.remove ('\r'); + line.remove ('\n'); StringParser pars (line, ' '); short code = 0, alpha = 255; @@ -113,8 +115,9 @@ continue; // not a number // Ensure that the code is within [0 - 511] - code = atoi (valuestr); - if (code < 0 || code >= 512) + bool ok; + code = valuestr.toShort (&ok); + if (!ok || code < 0 || code >= 512) continue; // VALUE and EDGE tags @@ -122,15 +125,15 @@ continue; // Ensure that our colors are correct - QColor faceColor (facename.chars()), - edgeColor (edgename.chars()); + QColor faceColor (facename), + edgeColor (edgename); if (!faceColor.isValid () || !edgeColor.isValid ()) continue; // Parse alpha if given. if (parseLDConfigTag (pars, "ALPHA", valuestr)) - alpha = clamp<short> (atoi (valuestr), 0, 255); + alpha = clamp<short> (valuestr.toShort (), 0, 255); color* col = new color; col->name = name; @@ -139,7 +142,6 @@ col->hexcode = facename; col->faceColor.setAlpha (alpha); col->index = code; - g_LDColors[code] = col; }
--- a/src/common.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/common.h Fri Jun 14 16:00:54 2013 +0300 @@ -59,6 +59,10 @@ # define devf(...) #endif // RELEASE +class QFile; +extern QFile g_file_stdout; +extern QFile g_file_stderr; + void doDevf (const char* func, const char* fmtstr, ...); // Version string identifier @@ -139,6 +143,17 @@ #define FUNCNAME __func__ #endif // __GNUC__ +// printf replacement +#ifndef IN_IDE_PARSER +#define print(...) doPrint (g_file_stdout, {__VA_ARGS__}) +#define fprint(F, ...) doPrint (F, {__VA_ARGS__}) +#else +void print (const char* fmtstr, ...); +void fprint (QFile& f, const char* fmtstr, ...); +#endif +void doPrint (QFile& f, initlist<StringFormatArg> args); +void doPrint (FILE* f, initlist<StringFormatArg> args); + // Replace assert with a version that shows a GUI dialog if possible #ifdef assert #undef assert
--- a/src/config.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/config.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -19,6 +19,7 @@ #include <errno.h> #include <time.h> #include <QDir> +#include <qtextstream.h> #include "common.h" #include "config.h" #include "misc.h" @@ -27,33 +28,6 @@ config* g_configPointers[MAX_CONFIG]; static ushort g_cfgPointerCursor = 0; -// ============================================================================= -const char* g_WeekdayNames[7] = { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -}; - -// ============================================================================= -static const char* g_MonthNames[12] = { - "Januray", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November" - "December", -}; - static const char* g_ConfigTypeNames[] = { "None", "Integer", @@ -66,39 +40,38 @@ // ============================================================================= // Load the configuration from file bool config::load () { - printf ("config::load: Loading configuration file...\n"); - printf ("config::load: Path to configuration is %s\n", filepath ().chars ()); + print ("config::load: Loading configuration file...\n"); + print ("config::load: Path to configuration is %1\n", filepath ()); // Locale must be disabled for atof setlocale (LC_NUMERIC, "C"); - FILE* fp = fopen (filepath ().chars(), "r"); - char linedata[MAX_INI_LINE]; - char* line; + QFile f (filepath ()); + if (!f.open (QIODevice::ReadOnly)) + return false; + + QTextStream input (&f); size_t ln = 0; - if (!fp) - return false; // can't open for reading - // Read the values. - while (fgets (linedata, MAX_INI_LINE, fp)) { + while (!input.atEnd ()) { + str line = input.readLine ().simplified (); ln++; - line = linedata; - while (*line != 0 && (*line <= 32 || *line >= 127)) - line++; // Skip junk - - if (*line == '\0' || line[0] == '#') + if (line.isEmpty () || line[0] == '#') continue; // Empty line or comment. // Find the equals sign. - char* equals = strchr (line, '='); - if (!equals) { - fprintf (stderr, "couldn't find `=` sign in entry `%s`\n", line); + int equals = line.indexOf ('='); + if (equals == -1) { + fprint (stderr, "couldn't find `=` sign in entry `%1`\n", line); continue; } - str entry = str (line).substr (0, equals - line); + str entry = line.left (equals); + str valstring = line.right (line.length () - equals - 1); + + print ("config: `%1` -> %2 == %3 (%4)\n", line, entry, valstring, equals); // Find the config entry for this. config* cfg = null; @@ -111,24 +84,13 @@ } if (!cfg) { - fprintf (stderr, "unknown config `%s`\n", entry.chars()); + fprint (stderr, "unknown config `%1`\n", entry); continue; } - str valstring = str (line).substr (equals - line + 1, -1); - - // Trim the crap off the end - while (~valstring) { - char c = valstring[~valstring - 1]; - if (c <= 32 || c >= 127) { - valstring -= 1; - } else - break; - } - switch (cfg->getType()) { case CONFIG_int: - static_cast<intconfig*> (cfg)->value = atoi (valstring.chars()); + static_cast<intconfig*> (cfg)->value = valstring.toInt (); break; case CONFIG_str: @@ -136,22 +98,22 @@ break; case CONFIG_float: - static_cast<floatconfig*> (cfg)->value = atof (valstring.chars()); + static_cast<floatconfig*> (cfg)->value = valstring.toFloat (); break; case CONFIG_bool: { bool& val = static_cast<boolconfig*> (cfg)->value; - if (+valstring == "TRUE" || valstring == "1") + if (valstring.toUpper () == "TRUE" || valstring == "1") val = true; - else if (+valstring == "FALSE" || valstring == "0") + else if (valstring.toUpper () == "FALSE" || valstring == "0") val = false; break; } case CONFIG_keyseq: - static_cast<keyseqconfig*> (cfg)->value = keyseq::fromString (valstring.chars ()); + static_cast<keyseqconfig*> (cfg)->value = keyseq::fromString (valstring); break; default: @@ -159,26 +121,11 @@ } } - fclose (fp); + f.close (); return true; } // ============================================================================= -// Write a given formatted string to the given file stream -static size_t writef (FILE* fp, const char* fmt, ...) { - va_list va; - - va_start (va, fmt); - char* buf = dynafmt (fmt, va, 256); - va_end (va); - - size_t len = fwrite (buf, 1, strlen (buf), fp); - delete[] buf; - - return len; -} - -// ============================================================================= // Save the configuration to disk bool config::save () { // The function will write floats, disable the locale now so that they @@ -187,33 +134,22 @@ // If the directory doesn't exist, create it now. if (QDir (dirpath ()).exists () == false) { - fprintf (stderr, "Creating config path %s...\n", dirpath().chars()); - if (!QDir ().mkpath (dirpath ().chars ())) { - critical ("Failed to create the directory. Configuration cannot be saved!\n"); - return false; // Couldn't create directory + fprint (stderr, "Creating config path %1...\n", dirpath ()); + if (!QDir ().mkpath (dirpath ())) { + critical ("Failed to create the configuration directory. Configuration cannot be saved!\n"); + return false; } } - FILE* fp = fopen (filepath ().chars (), "w"); - printf ("writing cfg to %s\n", filepath().chars()); + QFile f (filepath ()); + print ("writing cfg to %1\n", qchars (filepath ())); - if (!fp) { - critical (fmt ("Cannot save configuration, cannot open %s for writing\n", filepath ().chars ())); + if (!f.open (QIODevice::WriteOnly)) { + critical (fmt ("Cannot save configuration, cannot open %1 for writing\n", filepath ())); return false; } - const time_t curtime = time (NULL); - const struct tm* timeinfo = localtime (&curtime); - const char* daysuffix = - (timeinfo->tm_mday % 10 == 1) ? "st" : - (timeinfo->tm_mday % 10 == 2) ? "nd" : - (timeinfo->tm_mday % 10 == 3) ? "rd" : "th"; - - writef (fp, "# Configuration file for " APPNAME "\n"); - writef (fp, "# Written on %s, %s %d%s %d %.2d:%.2d:%.2d\n", - g_WeekdayNames[timeinfo->tm_wday], g_MonthNames[timeinfo->tm_mon], - timeinfo->tm_mday, daysuffix, timeinfo->tm_year + 1900, - timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + fprint (f, "# Configuration file for " APPNAME "\n"); for (config* cfg : g_configPointers) { if (!cfg) @@ -222,7 +158,7 @@ str valstring; switch (cfg->getType()) { case CONFIG_int: - valstring.format ("%d", static_cast<intconfig*> (cfg)->value); + valstring = fmt ("%1", static_cast<intconfig*> (cfg)->value); break; case CONFIG_str: @@ -230,7 +166,7 @@ break; case CONFIG_float: - valstring.format ("%s", ftoa (static_cast<floatconfig*> (cfg)->value).c ()); + valstring = fmt ("%1", static_cast<floatconfig*> (cfg)->value); break; case CONFIG_bool: @@ -249,11 +185,11 @@ qchars (static_cast<keyseqconfig*> (cfg)->defval.toString ()); // Write the entry now. - writef (fp, "\n# [%s] default: %s\n", g_ConfigTypeNames[cfg->getType()], defstr); - writef (fp, "%s=%s\n", cfg->name, valstring.chars()); + fprint (f, "\n# [%1] default: %2\n", g_ConfigTypeNames[cfg->getType()], defstr); + fprint (f, "%1=%2\n", cfg->name, valstring); } - fclose (fp); + f.close (); return true; } @@ -269,20 +205,18 @@ // ============================================================================= str config::filepath () { - str path; - path.format ("%s%s.cfg", dirpath ().chars (), - str (APPNAME).lower ().chars ()); + str path = fmt ("%1%2.cfg", dirpath (), + str (APPNAME).toLower ()); return path; } // ============================================================================= str config::dirpath () { #ifndef _WIN32 - return fmt ("%s" DIRSLASH ".%s" DIRSLASH, - qchars (QDir::homePath ()), - str (APPNAME).lower ().chars ()); + return fmt ("%1" DIRSLASH ".%2" DIRSLASH, + QDir::homePath (), str (APPNAME).toLower ()); #else - return fmt ("%s" DIRSLASH APPNAME DIRSLASH, qchars (QDir::homePath ())); + return fmt ("%1" DIRSLASH APPNAME DIRSLASH, QDir::homePath ()); #endif // _WIN32 }
--- a/src/config.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/config.h Fri Jun 14 16:00:54 2013 +0300 @@ -171,15 +171,10 @@ DEFINE_COMPARE_OPERATOR (str, !=) DEFINE_ASSIGN_OPERATOR (str, =) DEFINE_ASSIGN_OPERATOR (str, +=) - DEFINE_CAST_OPERATOR (const char*) - char operator[] (size_t n) { + qchar operator[] (int n) { return value[n]; } - - operator QString () { - return QString (value.chars()); - } }; // =============================================================================
--- a/src/configDialog.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/configDialog.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -283,10 +283,10 @@ for (int i = 0; i < g_NumGrids; ++i) { // Icon lb_gridIcons[i] = new QLabel; - lb_gridIcons[i]->setPixmap (getIcon (fmt ("grid-%s", str (g_GridInfo[i].name).lower ().chars ()))); + lb_gridIcons[i]->setPixmap (getIcon (fmt ("grid-%1", str (g_GridInfo[i].name).toLower ()))); // Text label - lb_gridLabels[i] = new QLabel (fmt ("%s:", g_GridInfo[i].name)); + lb_gridLabels[i] = new QLabel (fmt ("%1:", g_GridInfo[i].name)); QHBoxLayout* labellayout = new QHBoxLayout; labellayout->addWidget (lb_gridIcons[i]); @@ -509,16 +509,15 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void ConfigDialog::pickColor (strconfig& cfg, QPushButton* qButton) { - QColorDialog dlg (QColor (cfg.value.chars())); - dlg.setWindowIcon (getIcon ("colorselect")); +void ConfigDialog::pickColor (strconfig& conf, QPushButton* button) { + QColor col = QColorDialog::getColor (QColor (conf)); - if (dlg.exec ()) { - uchar r = dlg.currentColor ().red (), - g = dlg.currentColor ().green (), - b = dlg.currentColor ().blue (); - cfg.value.format ("#%.2X%.2X%.2X", r, g, b); - setButtonBackground (qButton, cfg.value); + if (col.isValid ()) { + uchar r = col.red (), + g = col.green (), + b = col.blue (); + conf.value.sprintf ("#%.2X%.2X%.2X", r, g, b); + setButtonBackground (button, conf.value); } } @@ -533,12 +532,10 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void ConfigDialog::setButtonBackground (QPushButton* qButton, str zValue) { - qButton->setIcon (getIcon ("colorselect")); - qButton->setAutoFillBackground (true); - qButton->setStyleSheet ( - fmt ("background-color: %s", zValue.chars()).chars() - ); +void ConfigDialog::setButtonBackground (QPushButton* button, str value) { + button->setIcon (getIcon ("colorselect")); + button->setAutoFillBackground (true); + button->setStyleSheet (fmt ("background-color: %1", value)); } // ============================================================================= @@ -631,8 +628,8 @@ filter = "Applications (*.exe)(*.exe);;All files (*.*)(*.*)"; #endif // WIN32 - str fpath = QFileDialog::getOpenFileName (this, fmt ("Path to %s", info->name), "", filter); - if (!~fpath) + str fpath = QFileDialog::getOpenFileName (this, fmt ("Path to %1", info->name), "", filter); + if (fpath.length () == 0) return; info->input->setText (fpath); @@ -641,12 +638,12 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void ConfigDialog::setShortcutText (QListWidgetItem* qItem, actionmeta meta) { +void ConfigDialog::setShortcutText (QListWidgetItem* item, actionmeta meta) { QAction* const act = *meta.qAct; - str zLabel = act->iconText (); - str zKeybind = act->shortcut ().toString (); + str label = act->iconText (); + str keybind = act->shortcut ().toString (); - qItem->setText (fmt ("%s (%s)", zLabel.chars () ,zKeybind.chars ()).chars()); + item->setText (fmt ("%1 (%2)", label, keybind)); } // ============================================================================= @@ -656,13 +653,13 @@ str val; for (quickColor entry : quickColorMeta) { - if (~val > 0) + if (val.length () > 0) val += ':'; if (entry.bSeparator) val += '|'; else - val += fmt ("%d", entry.col->index); + val += fmt ("%1", entry.col->index); } return val; @@ -757,7 +754,7 @@ if (seq == QKeySequence ()) shortcut = "<empty>"; - str text = fmt ("<center><b>%s</b></center>", shortcut.chars ()); + str text = fmt ("<center><b>%1</b></center>", shortcut); lb_output->setText (text); }
--- a/src/dialogs.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/dialogs.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -242,11 +242,11 @@ } void SetContentsDialog::setObject (LDObject* obj) { - le_contents->setText (obj->raw ().chars()); + le_contents->setText (obj->raw ()); if (obj->getType() == LDObject::Gibberish) { - lb_error->setText (fmt ("<span style=\"color: #900\">%s</span>", - static_cast<LDGibberish*> (obj)->reason.chars())); + lb_error->setText (fmt ("<span style=\"color: #900\">%1</span>", + static_cast<LDGibberish*> (obj)->reason)); QPixmap errorPixmap = getIcon ("error").scaledToHeight (16); lb_errorIcon->setPixmap (errorPixmap); @@ -326,7 +326,7 @@ void LDrawPathDialog::slot_findPath () { str newpath = QFileDialog::getExistingDirectory (this, "Find LDraw Path"); - if (~newpath > 0 && newpath != filename ()) { + if (newpath.length () > 0 && newpath != filename ()) { setPath (newpath); slot_tryConfigure (); } @@ -338,8 +338,8 @@ void LDrawPathDialog::slot_tryConfigure () { if (LDPaths::tryConfigure (filename ()) == false) { - lb_resolution->setText (fmt ("<span style=\"color:red; font-weight: bold;\">%s</span>", - LDPaths::getError().chars ())); + lb_resolution->setText (fmt ("<span style=\"color:red; font-weight: bold;\">%1</span>", + LDPaths::getError())); okButton ()->setEnabled (false); return; } @@ -418,11 +418,11 @@ *g_curfile << new LDComment (dlg.le_name->text ()); *g_curfile << new LDComment ("Name: <untitled>.dat"); - *g_curfile << new LDComment (fmt ("Author: %s", author.chars())); + *g_curfile << new LDComment (fmt ("Author: %1", author)); *g_curfile << new LDComment (fmt ("!LDRAW_ORG Unofficial_Part")); if (license != null) - *g_curfile << new LDComment (fmt ("!LICENSE %s", license)); + *g_curfile << new LDComment (fmt ("!LICENSE %1", license)); *g_curfile << new LDEmpty; *g_curfile << new LDBFC (BFCType);
--- a/src/extprogs.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/extprogs.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -52,14 +52,14 @@ // ============================================================================= static bool checkProgPath (str path, const extprog prog) { - if (~path) + if (path.length () > 0) return true; const char* name = g_extProgNames[prog]; - critical (fmt ("Couldn't run %s as no path has " + critical (fmt ("Couldn't run %1 as no path has " "been defined for it. Use the configuration dialog's External Programs " - "tab to define a path for %s.", name, name)); + "tab to define a path for %1.", name)); return false; } @@ -70,25 +70,25 @@ switch (proc.error ()) { case QProcess::FailedToStart: - errmsg = fmt ("Failed to launch %s. Check that you have set the proper path " - "to %s and that you have the proper permissions to launch it.", name, name); + errmsg = fmt ("Failed to launch %1. Check that you have set the proper path " + "to %1 and that you have the proper permissions to launch it.", name); break; case QProcess::Crashed: - errmsg = fmt ("%s crashed.", name); + errmsg = fmt ("%1 crashed.", name); break; case QProcess::WriteError: case QProcess::ReadError: - errmsg = fmt ("I/O error while interacting with %s.", name); + errmsg = fmt ("I/O error while interacting with %1.", name); break; case QProcess::UnknownError: - errmsg = fmt ("Unknown error occurred while executing %s.", name); + errmsg = fmt ("Unknown error occurred while executing %1.", name); break; case QProcess::Timedout: - errmsg = fmt ("%s timed out.", name); + errmsg = fmt ("%1 timed out.", name); break; } @@ -121,28 +121,21 @@ for (LDObject* obj : objs) delete obj; } else { - str line = fmt ("%s\r\n", obj->raw ().chars ()); - fwrite (line.chars(), 1, ~line, fp); + str line = obj->raw () + "\r\n"; + fwrite (qchars (line), 1, line.length (), fp); } } } void writeObjects (vector<LDObject*>& objects, str fname) { // Write the input file - FILE* fp = fopen (fname, "w"); + FILE* fp = fopen (qchars (fname), "w"); if (!fp) { - critical (fmt ("Couldn't open temporary file %s for writing.\n", fname.chars ())); + critical (fmt ("Couldn't open temporary file %1 for writing.\n", fname)); return; } writeObjects (objects, fp); - -#if 0 - ushort idx = rand (); - printf ("%s -> debug_%u\n", fname.chars (), idx); - QFile::copy (fname.chars (), fmt ("debug_%u", idx)); -#endif // 0 - fclose (fp); } @@ -170,7 +163,7 @@ str inputname, outputname; QStringList argv = argvstr.split (" ", QString::SkipEmptyParts); - printf ("cmdline: %s %s\n", path.chars (), qchars (argvstr)); + printf ("cmdline: %s %s\n", qchars (path), qchars (argvstr)); if (!mkTempFile (input, inputname) || !mkTempFile (output, outputname)) return; @@ -178,7 +171,7 @@ QProcess proc; // Init stdin - FILE* stdinfp = fopen (inputname, "w"); + FILE* stdinfp = fopen (qchars (inputname), "w"); // Begin! proc.setStandardInputFile (inputname); @@ -210,9 +203,9 @@ #endif // RELEASE // Read the output file - FILE* fp = fopen (fname, "r"); + FILE* fp = fopen (qchars (fname), "r"); if (!fp) { - critical (fmt ("Couldn't open temporary file %s for reading.\n", fname.chars ())); + critical (fmt ("Couldn't open temporary file %1 for reading.\n", fname)); return; } @@ -288,10 +281,15 @@ return; // Compose the command-line arguments - str argv = fmt ("%s %s %f -a %f %s %s", + str argv = join ({ (axis == X) ? "-x" : (axis == Y) ? "-y" : "-z", (mode == Distance) ? "-d" : (mode == Symmetry) ? "-s" : (mode == Projection) ? "-p" : "-r", - depth, condAngle, inDATName.chars (), outDATName.chars ()); + depth, + "-a", + condAngle, + inDATName, + outDATName + }); writeSelection (inDATName); runUtilityProcess (Ytruder, prog_ytruder, argv); @@ -345,12 +343,16 @@ return; // Compose arguments - str argv = fmt ("%s %s %s %s -t %f %s %s", + str argv = join ({ (condense == false) ? "-q" : "", (subst == false) ? "-r" : "", (condlineCheck) ? "-a" : "", (colorize) ? "-c" : "", - coplthres, inDATName.chars (), outDATName.chars ()); + "-t", + coplthres, + inDATName, + outDATName + }); writeSelection (inDATName); runUtilityProcess (Rectifier, prog_rectifier, argv); @@ -438,13 +440,26 @@ return; } - str parms = fmt ("%s %s -s %f", + str parms = join ({ (cb_colorize->isChecked ()) ? "-c" : "", (cb_nocondense->isChecked ()) ? "-t" : "", - dsb_prescale->w ()->value ()); + "-s", + dsb_prescale->w ()->value () + }); - str argv_normal = fmt ("%s %s %s %s", parms.chars (), inDATName.chars (), cutDATName.chars (), outDATName.chars ()); - str argv_inverse = fmt ("%s %s %s %s", parms.chars (), cutDATName.chars (), inDATName.chars (), outDAT2Name.chars ()); + str argv_normal = join ({ + parms, + inDATName, + cutDATName, + outDATName + }); + + str argv_inverse = join ({ + parms, + cutDATName, + inDATName, + outDAT2Name + }); writeColorGroup (inCol, inDATName); writeColorGroup (cutCol, cutDATName); @@ -457,7 +472,7 @@ } if (cb_edges->isChecked ()) { - runUtilityProcess (Isecalc, prog_isecalc, fmt ("%s %s %s", inDATName.chars (), cutDATName.chars (), edgesDATName.chars ())); + runUtilityProcess (Isecalc, prog_isecalc, join ({inDATName, cutDATName, edgesDATName})); insertOutput (edgesDATName, false, {}); } } @@ -520,12 +535,15 @@ if (!mkTempFile (in1dat, in1DATName) || !mkTempFile (in2dat, in2DATName) || !mkTempFile (outdat, outDATName)) return; - str argv = fmt ("%s %s %s %s %s %s %s", + str argv = join ({ (cb_oldsweep->isChecked () ? "-s" : ""), (cb_reverse->isChecked () ? "-r" : ""), - (dsb_segsplit->value () != 0 ? fmt ("-l %f", dsb_segsplit->value ()).c () : ""), - (sb_bias->value () != 0 ? fmt ("-s %d", sb_bias->value ()).c () : ""), - in1DATName.c (), in2DATName.c (), outDATName.c ()); + (dsb_segsplit->value () != 0 ? fmt ("-l %1", dsb_segsplit->value ()) : ""), + (sb_bias->value () != 0 ? fmt ("-s %1", sb_bias->value ()) : ""), + in1DATName, + in2DATName, + outDATName + }); writeColorGroup (in1Col, in1DATName); writeColorGroup (in2Col, in2DATName); @@ -567,7 +585,11 @@ if (!mkTempFile (in1dat, in1DATName) || !mkTempFile (in2dat, in2DATName) || !mkTempFile (outdat, outDATName)) return; - str argv = fmt ("%s %s %s", in1DATName.c (), in2DATName.c (), outDATName.c ()); + str argv = join ({ + in1DATName, + in2DATName, + outDATName + }); writeColorGroup (in1Col, in1DATName); writeColorGroup (in2Col, in2DATName);
--- a/src/file.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/file.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -74,9 +74,9 @@ return false; } - pathInfo.partsPath = fmt ("%s" DIRSLASH "parts", path.chars ()); - pathInfo.LDConfigPath = fmt ("%s" DIRSLASH "LDConfig.ldr", path.chars ()); - pathInfo.primsPath = fmt ("%s" DIRSLASH "p", path.chars ()); + pathInfo.partsPath = fmt ("%1" DIRSLASH "parts", path); + pathInfo.LDConfigPath = fmt ("%1" DIRSLASH "LDConfig.ldr", path); + pathInfo.primsPath = fmt ("%1" DIRSLASH "p", path); return true; } @@ -117,10 +117,10 @@ // ============================================================================= str dirname (str path) { - long lastpos = path.last (DIRSLASH); + long lastpos = path.lastIndexOf (DIRSLASH); if (lastpos > 0) - return path.substr (0, lastpos); + return path.left (lastpos); #ifndef _WIN32 if (path[0] == DIRSLASH_CHAR) @@ -132,54 +132,54 @@ // ============================================================================= str basename (str path) { - long lastpos = path.last (DIRSLASH); + long lastpos = path.lastIndexOf (DIRSLASH); - if (lastpos < (long) path.len () - 1) - return path.substr (lastpos + 1, -1); + if (lastpos != -1) + return path.mid (lastpos + 1); return path; } // ============================================================================= FILE* openLDrawFile (str relpath, bool subdirs) { - printf ("%s: Try to open %s\n", __func__, relpath.c ()); + printf ("%s: Try to open %s\n", __func__, qchars (relpath)); #ifndef WIN32 relpath.replace ("\\", "/"); #endif // WIN32 if (g_curfile != null) { - str partpath = fmt ("%s" DIRSLASH "%s", dirname (g_curfile->name ()).c (), relpath.c ()); - printf ("try %s\n", partpath.c ()); - FILE* fp = fopen (partpath, "r"); + str partpath = fmt ("%1" DIRSLASH "%2", dirname (g_curfile->name ()), relpath); + printf ("try %s\n", qchars (partpath)); + FILE* fp = fopen (qchars (partpath), "r"); if (fp != null) return fp; } - printf ("try %s\n", relpath.chars ()); - FILE* fp = fopen (relpath, "r"); + printf ("try %s\n", qchars (relpath)); + FILE* fp = fopen (qchars (relpath), "r"); str fullPath; if (fp != null) return fp; - if (~io_ldpath.value) { + if (io_ldpath.value.length () > 0) { // Try with just the LDraw path first - fullPath = fmt ("%s" DIRSLASH "%s", io_ldpath.value.chars(), relpath.chars()); - printf ("try %s\n", fullPath.chars ()); + fullPath = fmt ("%1" DIRSLASH "%2", io_ldpath, relpath); + printf ("try %s\n", qchars (fullPath)); - fp = fopen (fullPath, "r"); + fp = fopen (qchars (fullPath), "r"); if (fp != null) return fp; if (subdirs) { for (auto subdir : initlist<const char*> ({"parts", "p"})) { - fullPath = fmt ("%s" DIRSLASH "%s" DIRSLASH "%s", - io_ldpath.value.chars(), subdir, relpath.chars()); + fullPath = fmt ("%1" DIRSLASH "%2" DIRSLASH "%3", + io_ldpath, subdir, relpath); - printf ("try %s\n", fullPath.chars ()); - fp = fopen (fullPath.chars (), "r"); + printf ("try %s\n", qchars (fullPath)); + fp = fopen (qchars (fullPath), "r"); if (fp) return fp; @@ -201,8 +201,9 @@ while (fgets (line, sizeof line, filePointer ())) { // Trim the trailing newline str data = line; - while (data[~data - 1] == '\n' || data[~data - 1] == '\r') - data -= 1; + qchar c; + while ((c = data[data.length () - 1]) == '\n' || c == '\r') + data.chop (1); LDObject* obj = parseLine (data); assert (obj != null); @@ -210,9 +211,9 @@ // Check for parse errors and warn about tthem if (obj->getType () == LDObject::Gibberish) { logf (LOG_Warning, "Couldn't parse line #%lu: %s\n", - m_progress + 1, static_cast<LDGibberish*> (obj)->reason.chars()); + m_progress + 1, qchars (static_cast<LDGibberish*> (obj)->reason)); - logf (LOG_Warning, "- Line was: %s\n", data.chars()); + logf (LOG_Warning, "- Line was: %s\n", qchars (data)); if (m_warningsPointer) (*m_warningsPointer)++; @@ -300,21 +301,17 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= LDOpenFile* openDATFile (str path, bool search) { - logf ("Opening %s...\n", path.chars()); - // Convert the file name to lowercase since some parts contain uppercase // file names. I'll assume here that the library will always use lowercase // file names for the actual parts.. FILE* fp; if (search) - fp = openLDrawFile (-path, true); + fp = openLDrawFile (path.toLower (), true); else - fp = fopen (path, "r"); + fp = fopen (qchars (path), "r"); - if (!fp) { - logf (LOG_Error, "Couldn't open %s: %s\n", path.chars (), strerror (errno)); + if (!fp) return null; - } LDOpenFile* oldLoad = g_curfile; LDOpenFile* load = new LDOpenFile; @@ -341,7 +338,7 @@ g_loadedFiles << load; logf ("File %s parsed successfully (%lu warning%s).\n", - path.chars(), numWarnings, plural (numWarnings)); + qchars (path), numWarnings, plural (numWarnings)); return load; } @@ -355,25 +352,25 @@ // If we have unsaved changes, warn and give the option of saving. if (!implicit () && history ().pos () != savePos ()) { switch (QMessageBox::question (g_win, "Unsaved Changes", - fmt ("There are unsaved changes to %s. Should it be saved?", - (name ().len () > 0) ? name ().c () : "<anonymous>"), + fmt ("There are unsaved changes to %1. Should it be saved?", + (name ().length () > 0) ? name () : "<anonymous>"), (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel), QMessageBox::Cancel)) { case QMessageBox::Yes: // If we don't have a file path yet, we have to ask the user for one. - if (name ().len () == 0) { + if (name ().length () == 0) { str newpath = QFileDialog::getSaveFileName (g_win, "Save As", g_curfile->name (), "LDraw files (*.dat *.ldr)"); - if (newpath.len () == 0) + if (newpath.length () == 0) return false; setName (newpath); } if (!save ()) { - str errormsg = fmt ("Failed to save %s: %s\nDo you still want to close?", - name ().c (), strerror (errno)); + str errormsg = fmt ("Failed to save %1: %2\nDo you still want to close?", + name (), strerror (errno)); if (QMessageBox::critical (g_win, "Save Failure", errormsg, (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::No) @@ -438,28 +435,35 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void addRecentFile (str path) { - vector<str> rfiles = io_recentfiles.value.split ('@'); + QStringList rfiles = io_recentfiles.value.split ('@'); + + int idx = 0; - ulong idx = rfiles.find (path); + for (str& it : rfiles) { + if (it == path) + break; + + idx++; + } // If this file already is in the list, pop it out. - if (idx != -1u) { + if (idx != rfiles.size ()) { if (rfiles.size () == 1) return; // only recent file - do nothing // Pop it out. - rfiles.erase (idx); + rfiles.removeAt (idx); } // If there's too many recent files, drop one out. while (rfiles.size () > (5 - 1)) - rfiles.erase (0); + rfiles.removeAt (0); // Add the file rfiles.push_back (path); // Rebuild the config string - io_recentfiles = str::join (rfiles, "@"); + io_recentfiles = rfiles.join ("@"); config::save (); g_win->updateRecentFilesMenu (); @@ -477,7 +481,7 @@ if (!file) { // Tell the user loading failed. setlocale (LC_ALL, "C"); - critical (fmt ("Failed to open %s: %s", path.chars(), strerror (errno))); + critical (fmt ("Failed to open %1: %2", path, strerror (errno))); g_loadingMainFile = false; return; @@ -504,10 +508,10 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= bool LDOpenFile::save (str savepath) { - if (!~savepath) + if (!savepath.length ()) savepath = name (); - FILE* fp = fopen (savepath, "w"); + FILE* fp = fopen (qchars (savepath), "w"); if (!fp) return false; @@ -519,15 +523,15 @@ if (!implicit () && objs ().size () >= 2 && object (1)->getType () == LDObject::Comment) { fpathComment = static_cast<LDComment*> (object (1)); - if (fpathComment->text.substr (0, 6) == "Name: ") { + if (fpathComment->text.left (6) == "Name: ") { str newfname; str dir = basename (dirname (savepath)); if (dir == "s" || dir == "48") - newfname = fmt ("%s\\", dir.c ()); + newfname = dir + "\\"; newfname += basename (savepath); - fpathComment->text = fmt ("Name: %s", newfname.c ()); + fpathComment->text = fmt ("Name: %1", newfname); g_win->buildObjList (); } } @@ -535,8 +539,8 @@ // Write all entries now for (LDObject* obj : objs ()) { // LDraw requires files to have DOS line endings - str line = fmt ("%s\r\n", obj->raw ().chars ()); - fwrite (line.chars(), 1, line.len (), fp); + str line = obj->raw () + "\r\n"; + fwrite (qchars (line), 1, line.length (), fp); } fclose (fp); @@ -556,13 +560,13 @@ #define CHECK_TOKEN_NUMBERS(MIN,MAX) \ for (ushort i = MIN; i <= MAX; ++i) \ if (!isNumber (tokens[i])) \ - return new LDGibberish (line, fmt ("Token #%u was `%s`, expected a number", \ - (i + 1), tokens[i].chars())); + return new LDGibberish (line, fmt ("Token #%1 was `%2`, expected a number", \ + (i + 1), tokens[i])); // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -static vertex parseVertex (vector<str>& s, const ushort n) { +static vertex parseVertex (QStringList& s, const ushort n) { // Disable the locale while parsing the line or atof's behavior changes // between locales (i.e. fails to read decimals properly). That is // quite undesired... @@ -570,7 +574,7 @@ vertex v; for (const Axis ax : g_Axes) - v[ax] = atof (s[n + ax]); + v[ax] = s[n + ax].toFloat (); return v; } @@ -579,23 +583,23 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= LDObject* parseLine (str line) { - vector<str> tokens = line.split (" "); + QStringList tokens = line.split (" ", str::SkipEmptyParts); if (!tokens.size ()) { // Line was empty, or only consisted of whitespace return new LDEmpty; } - if (~tokens[0] != 1) + if (tokens[0].length () != 1) return new LDGibberish (line, "Illogical line code"); - const char c = tokens[0][0]; - switch (c - '0') { + const qchar c = tokens[0][0]; + switch (c.toAscii () - '0') { case 0: { // Comment str comm; - for (uint i = 1; i < tokens.size(); ++i) { + for (int i = 1; i < tokens.size(); ++i) { comm += tokens[i]; if (i != tokens.size() - 1) @@ -605,7 +609,7 @@ // Handle BFC statements if (tokens.size() > 2 && tokens[1] == "BFC") { for (short i = 0; i < LDBFC::NumStatements; ++i) - if (comm == fmt ("BFC %s", LDBFC::statements [i])) + if (comm == fmt ("BFC %1", LDBFC::statements [i])) return new LDBFC ((LDBFC::Type) i); // MLCAD is notorious for stuffing these statements in parts it @@ -624,10 +628,10 @@ CHECK_TOKEN_NUMBERS (3, 6) LDVertex* obj = new LDVertex; - obj->setColor (atol (tokens[3])); + obj->setColor (tokens[3].toLong ()); for (const Axis ax : g_Axes) - obj->pos[ax] = atof (tokens[4 + ax]); // 4 - 6 + obj->pos[ax] = tokens[4 + ax].toDouble (); // 4 - 6 return obj; } @@ -639,27 +643,27 @@ LDRadial::Type eType = LDRadial::NumTypes; for (int i = 0; i < LDRadial::NumTypes; ++i) { - if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).upper ().strip (' ') == tokens[3]) { + if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).toUpper ().remove (' ') == tokens[3]) { eType = (LDRadial::Type) i; break; } } if (eType == LDRadial::NumTypes) - return new LDGibberish (line, fmt ("Unknown radial type %s", tokens[3].chars ())); + return new LDGibberish (line, fmt ("Unknown radial type %1", tokens[3])); LDRadial* obj = new LDRadial; obj->setType (eType); - obj->setColor (atol (tokens[4])); - obj->setSegments (atol (tokens[5])); - obj->setDivisions (atol (tokens[6])); - obj->setNumber (atol (tokens[7])); + obj->setColor (tokens[4].toLong ()); + obj->setSegments (tokens[5].toLong ()); + obj->setDivisions (tokens[6].toLong ()); + obj->setNumber (tokens[7].toLong ()); obj->setPosition (parseVertex (tokens, 8)); // 8 - 10 matrix transform; for (short i = 0; i < 9; ++i) - transform[i] = atof (tokens[i + 11]); // 11 - 19 + transform[i] = tokens[i + 11].toDouble (); // 11 - 19 obj->setTransform (transform); return obj; @@ -689,12 +693,12 @@ return new LDGibberish (line, "Could not open referred file"); LDSubfile* obj = new LDSubfile; - obj->setColor (atol (tokens[1])); + obj->setColor (tokens[1].toLong ()); obj->setPosition (parseVertex (tokens, 2)); // 2 - 4 matrix transform; for (short i = 0; i < 9; ++i) - transform[i] = atof (tokens[i + 5]); // 5 - 13 + transform[i] = tokens[i + 5].toDouble (); // 5 - 13 obj->setTransform (transform); obj->setFileInfo (load); @@ -708,7 +712,7 @@ // Line LDLine* obj = new LDLine; - obj->setColor (atol (tokens[1])); + obj->setColor (tokens[1].toLong ()); for (short i = 0; i < 2; ++i) obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 7 return obj; @@ -721,7 +725,7 @@ // Triangle LDTriangle* obj = new LDTriangle; - obj->setColor (atol (tokens[1])); + obj->setColor (tokens[1].toLong ()); for (short i = 0; i < 3; ++i) obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 10 @@ -736,7 +740,7 @@ // Quadrilateral LDQuad* obj = new LDQuad; - obj->setColor (atol (tokens[1])); + obj->setColor (tokens[1].toLong ()); for (short i = 0; i < 4; ++i) obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13 @@ -751,7 +755,7 @@ // Conditional line LDCondLine* obj = new LDCondLine; - obj->setColor (atol (tokens[1])); + obj->setColor (tokens[1].toLong ()); for (short i = 0; i < 4; ++i) obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13 @@ -858,8 +862,6 @@ vector<partListEntry> g_PartList; void initPartList () { - logf ("%s: initializing parts.lst\n", __func__); - FILE* fp = openLDrawFile ("parts.lst", false); if (!fp)
--- a/src/gldraw.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/gldraw.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -113,8 +113,7 @@ // Init camera icons for (const GL::Camera cam : g_Cameras) { - str iconname; - iconname.format ("camera-%s", str (g_CameraNames[cam]).lower ().c ()); + str iconname = fmt ("camera-%1", str (g_CameraNames[cam]).toLower ()); CameraIcon* info = &g_CameraIcons[cam]; info->img = new QPixmap (getIcon (iconname)); @@ -193,7 +192,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= QColor GLRenderer::getMainColor () { - QColor col (gl_maincolor.value.chars()); + QColor col (gl_maincolor); if (!col.isValid ()) return QColor (0, 0, 0); @@ -204,7 +203,7 @@ // ----------------------------------------------------------------------------- void GLRenderer::setBackground () { - QColor col (gl_bgcolor.value.chars()); + QColor col (gl_bgcolor); if (!col.isValid ()) return; @@ -436,9 +435,10 @@ cx *= negXFac; cy *= negYFac; + str tmp; pos3d = g_origin; - pos3d[axisX] = atof (fmt ("%.3f", cx)); - pos3d[axisY] = atof (fmt ("%.3f", cy)); + pos3d[axisX] = tmp.sprintf ("%.3f", cx).toDouble (); + pos3d[axisY] = tmp.sprintf ("%.3f", cy).toDouble (); pos3d[3 - axisX - axisY] = depthValue (); return pos3d; } @@ -503,8 +503,7 @@ } // Paint the coordinates onto the screen. - str text = fmt ("X: %s, Y: %s, Z: %s", ftoa (m_hoverpos[X]).chars (), - ftoa (m_hoverpos[Y]).chars (), ftoa (m_hoverpos[Z]).chars ()); + str text = fmt ("X: %1, Y: %2, Z: %3", m_hoverpos[X], m_hoverpos[Y], m_hoverpos[Z]); QFontMetrics metrics = QFontMetrics (font ()); QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); @@ -600,7 +599,7 @@ const ushort margin = 4; str label; - label.format ("%s Camera", g_CameraNames[camera ()]); + label = fmt ("%1 Camera", g_CameraNames[camera ()]); paint.setPen (m_darkbg ? Qt::white : Qt::black); paint.drawText (QPoint (margin, margin + metrics.ascent ()), label); } @@ -617,8 +616,7 @@ ushort x0 = m_pos.x (), y0 = m_pos.y (); - str label; - label.format ("%s Camera", g_CameraNames[m_toolTipCamera]); + str label = fmt ("%1 Camera", g_CameraNames[m_toolTipCamera]); const ushort textWidth = metrics.width (label), textHeight = metrics.height (), @@ -1398,7 +1396,7 @@ if (!dlg.exec ()) return; - QImage* img = new QImage (dlg.fpath ().chars ()); + QImage* img = new QImage (dlg.fpath ()); overlayMeta& info = getOverlay (camera ()); if (img->isNull ()) {
--- a/src/gui.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/gui.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -290,10 +290,8 @@ delete recent; m_recentFiles.clear (); - vector<str> files = io_recentfiles.value / "@"; - for (long i = files.size() - 1; i >= 0; --i) { - str file = files[i]; - + vector<str> files = container_cast<QStringList, vector<str>> (io_recentfiles.value.split ("@")); + for (str file : c_rev<str> (files)) { QAction* recent = new QAction (getIcon ("open-recent"), file, this); connect (recent, SIGNAL (triggered ()), this, SLOT (slot_recentFile ())); @@ -436,11 +434,11 @@ vector<quickColor> parseQuickColorMeta () { vector<quickColor> meta; - for (str colorname : gui_colortoolbar.value / ":") { + for (str colorname : gui_colortoolbar.value.split (":")) { if (colorname == "|") { meta << quickColor ({null, null, true}); } else { - color* col = getColor (atoi (colorname)); + color* col = getColor (colorname.toLong ()); assert (col != null); meta << quickColor ({col, null, false}); } @@ -501,12 +499,12 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void ForgeWindow::updateTitle () { - str title = fmt (APPNAME " %s", fullVersionString().chars ()); + str title = fmt (APPNAME " %1", fullVersionString()); // Append our current file if we have one if (g_curfile) { - if (g_curfile->name ().len () > 0) - title += fmt (": %s", basename (g_curfile->name ()).c ()); + if (g_curfile->name ().length () > 0) + title += fmt (": %1", basename (g_curfile->name ())); else title += fmt (": <anonymous>"); @@ -515,7 +513,7 @@ { // Append title LDComment* comm = static_cast<LDComment*> (g_curfile->obj (0)); - title += fmt (": %s", comm->text.chars()); + title += fmt (": %1", comm->text); } if (g_curfile->history ().pos () != g_curfile->savePos ()) @@ -602,11 +600,11 @@ switch (obj->getType ()) { case LDObject::Comment: - descr = static_cast<LDComment*> (obj)->text.chars(); + descr = static_cast<LDComment*> (obj)->text; // Remove leading whitespace - while (~descr && descr[0] == ' ') - descr -= -1; + while (descr[0] == ' ') + descr.remove (0, 1); break; case LDObject::Empty: @@ -625,23 +623,22 @@ break; case LDObject::Gibberish: - descr.format ("ERROR: %s", - static_cast<LDGibberish*> (obj)->contents.chars()); + descr = fmt ("ERROR: %1", static_cast<LDGibberish*> (obj)->contents); break; case LDObject::Vertex: - descr.format ("%s", static_cast<LDVertex*> (obj)->pos.stringRep (true).chars()); + descr = static_cast<LDVertex*> (obj)->pos.stringRep (true); break; case LDObject::Subfile: { LDSubfile* ref = static_cast<LDSubfile*> (obj); - descr.format ("%s %s, (", ref->fileInfo ()->name ().chars (), - ref->position ().stringRep (true).chars ()); + descr = fmt ("%1 %2, (", ref->fileInfo ()->name (), + ref->position ().stringRep (true)); for (short i = 0; i < 9; ++i) - descr += fmt ("%s%s", ftoa (ref->transform ()[i]).chars (), + descr += fmt ("%1%2", ftoa (ref->transform ()[i]), (i != 8) ? " " : ""); descr += ')'; @@ -655,12 +652,12 @@ case LDObject::Radial: { LDRadial* rad = static_cast<LDRadial*> (obj); - descr.format ("%d / %d %s", rad->segments (), rad->divisions (), rad->radialTypeName ()); + descr = fmt ("%1 / %2 %3", rad->segments (), rad->divisions (), rad->radialTypeName ()); if (rad->type () == LDRadial::Ring || rad->type () == LDRadial::Cone) - descr += fmt (" %d", rad->number ()); + descr += fmt (" %1", rad->number ()); - descr += fmt (" %s", rad->position ().stringRep (true).chars ()); + descr += " " + rad->position ().stringRep (true); } break; @@ -671,11 +668,10 @@ // Put it into brackets if it's hidden if (obj->hidden ()) { - str copy = descr.chars (); - descr.format ("[[ %s ]]", copy.chars ()); + descr = fmt ("[[ %1 ]]", descr); } - QListWidgetItem* item = new QListWidgetItem (descr.chars()); + QListWidgetItem* item = new QListWidgetItem (descr); item->setIcon (getIcon (g_saObjTypeIcons[obj->getType ()])); // Color gibberish orange on red so it stands out. @@ -1004,8 +1000,8 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -QPixmap getIcon (const char* iconName) { - return (QPixmap (fmt (":/icons/%s.png", iconName))); +QPixmap getIcon (str iconName) { + return (QPixmap (fmt (":/icons/%1.png", iconName))); } // ============================================================================= @@ -1047,7 +1043,7 @@ return *meta.qAct; } - fatal (fmt ("%s: couldn't find action named `%s'!\n", __func__, name.chars ())); + fatal (fmt ("Couldn't find action named `%2'!", name)); abort (); return null; } @@ -1061,7 +1057,7 @@ QColor col = colinfo->faceColor; if (colinfo->index == maincolor) { // Use the user preferences for main color here - col = gl_maincolor.value.chars (); + col = gl_maincolor.value; col.setAlpha (gl_maincolor_alpha * 255.0f); } @@ -1093,8 +1089,8 @@ assert (col != null); QIcon ico = makeColorIcon (col, 16); - box->addItem (ico, fmt ("[%d] %s (%lu object%s)", - pair.first, col->name.chars (), pair.second, plural (pair.second))); + box->addItem (ico, fmt ("[%1] %2 (%3 object%4)", + pair.first, col->name, pair.second, plural (pair.second))); box->setItemData (row, pair.first); ++row;
--- a/src/gui.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/gui.h Fri Jun 14 16:00:54 2013 +0300 @@ -169,7 +169,7 @@ // ----------------------------------------------------------------------------- // Other GUI-related stuff not directly part of ForgeWindow: -QPixmap getIcon (const char* sIconName); +QPixmap getIcon (str iconName); vector<quickColor> parseQuickColorMeta (); bool confirm (str title, str msg); bool confirm (str msg);
--- a/src/gui_actions.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/gui_actions.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -55,7 +55,7 @@ str name = QFileDialog::getOpenFileName (g_win, "Open File", "", "LDraw files (*.dat *.ldr)"); - if (name.len () == 0) + if (name.length () == 0) return; closeAll (); @@ -68,11 +68,11 @@ void doSave (bool saveAs) { str path = g_curfile->name (); - if (~path == 0 || saveAs) { + if (path.length () == 0 || saveAs) { path = QFileDialog::getSaveFileName (g_win, "Save As", g_curfile->name (), "LDraw files (*.dat *.ldr)"); - if (~path == 0) { + if (path.length () == 0) { // User didn't give a file name. This happens if the user cancelled // saving in the save file dialog. Abort. return; @@ -82,14 +82,12 @@ if (g_curfile->save (path)) { g_curfile->setName (path); g_win->updateTitle (); - - logf ("Saved successfully to %s\n", path.chars ()); } else { setlocale (LC_ALL, "C"); // Tell the user the save failed, and give the option for saving as with it. QMessageBox dlg (QMessageBox::Critical, "Save Failure", - fmt ("Failed to save to %s\nReason: %s", path.chars(), strerror (errno)), + fmt ("Failed to save to %1\nReason: %2", path, strerror (errno)), QMessageBox::Close, g_win); QPushButton* saveAsBtn = new QPushButton ("Save As"); @@ -301,12 +299,12 @@ str fname = QFileDialog::getOpenFileName (); ulong idx = g_win->getInsertionPoint (); - if (!~fname) + if (!fname.length ()) return; - FILE* fp = fopen (fname, "r"); + FILE* fp = fopen (qchars (fname), "r"); if (!fp) { - critical (fmt ("Couldn't open %s\n%s", fname.chars(), strerror (errno))); + critical (fmt ("Couldn't open %1 (%2)", fname, strerror (errno))); return; } @@ -333,18 +331,19 @@ return; str fname = QFileDialog::getSaveFileName (); - if (fname.len () == 0) + if (fname.length () == 0) return; QFile file (fname); if (!file.open (QIODevice::WriteOnly | QIODevice::Text)) { - critical (fmt ("Unable to open %s for writing (%s)", fname.chars (), strerror (errno))); + critical (fmt ("Unable to open %1 for writing (%2)", fname, strerror (errno))); return; } for (LDObject* obj : g_win->sel ()) { str contents = obj->raw (); - file.write (contents, contents.len ()); + QByteArray data = contents.toUtf8 (); + file.write (data, data.size ()); file.write ("\r\n", 2); } } @@ -393,15 +392,15 @@ QImage img = imageFromScreencap (imgdata, w, h); str root = basename (g_curfile->name ()); - if (~root >= 4 && root.substr (~root - 4, -1) == ".dat") - root -= 4; + if (root.right (4) == ".dat") + root.chop (4); - str defaultname = (~root > 0) ? fmt ("%s.png", root.c ()) : ""; + str defaultname = (root.length () > 0) ? fmt ("%1.png", root) : ""; str fname = QFileDialog::getSaveFileName (g_win, "Save Screencap", defaultname, "PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;All Files (*.*)"); - if (~fname > 0 && !img.save (fname)) - critical (fmt ("Couldn't open %s for writing to save screencap: %s", fname.c (), strerror (errno))); + if (fname.length () > 0 && !img.save (fname)) + critical (fmt ("Couldn't open %1 for writing to save screencap: %2", fname, strerror (errno))); delete[] imgdata; } @@ -452,7 +451,7 @@ bool ok; double depth = QInputDialog::getDouble (g_win, "Set Draw Depth", - fmt ("Depth value for %s Camera:", g_win->R ()->cameraName ()), + fmt ("Depth value for %1 Camera:", g_win->R ()->cameraName ()), g_win->R ()->depthValue (), -10000.0f, 10000.0f, 3, &ok); if (ok)
--- a/src/gui_editactions.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/gui_editactions.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -173,7 +173,7 @@ str errmsg = fmt ("Couldn't replace %lu radials as replacement subfiles could not be loaded:<br />", (ulong)fails.size ()); for (str& fail : fails) - errmsg += fmt ("* %s<br />", fail.chars ()); + errmsg += fmt ("* %1<br />", fail); critical (errmsg); } @@ -516,8 +516,12 @@ for (short i = 0; i < obj->vertices (); ++i) { vertex v = obj->getVertex (i); - for (const Axis ax : g_Axes) - v[ax] = atof (fmt ("%.3f", v[ax])); + for (const Axis ax : g_Axes) { + // HACK: :p + char valstr[64]; + sprintf (valstr, "%.3f", v[ax]); + v[ax] = atof (valstr); + } obj->setVertex (i, v); }
--- a/src/ldtypes.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/ldtypes.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -72,11 +72,11 @@ // ============================================================================= str LDComment::raw () { - return fmt ("0 %s", text.chars ()); + return fmt ("0 %1", text); } str LDSubfile::raw () { - str val = fmt ("1 %d %s ", color (), position ().stringRep (false).chars ()); + str val = fmt ("1 %1 %2 ", color (), position ()); val += transform ().stringRep (); val += ' '; val += fileInfo ()->name (); @@ -84,38 +84,38 @@ } str LDLine::raw () { - str val = fmt ("2 %d", color ()); + str val = fmt ("2 %1", color ()); for (ushort i = 0; i < 2; ++i) - val += fmt (" %s", getVertex (i).stringRep (false).chars ()); + val += fmt (" %1", getVertex (i)); return val; } str LDTriangle::raw () { - str val = fmt ("3 %d", color ()); + str val = fmt ("3 %1", color ()); for (ushort i = 0; i < 3; ++i) - val += fmt (" %s", getVertex (i).stringRep (false).chars ()); + val += fmt (" %1", getVertex (i)); return val; } str LDQuad::raw () { - str val = fmt ("4 %d", color ()); + str val = fmt ("4 %1", color ()); for (ushort i = 0; i < 4; ++i) - val += fmt (" %s", getVertex (i).stringRep (false).chars ()); + val += fmt (" %1", getVertex (i)); return val; } str LDCondLine::raw () { - str val = fmt ("5 %d", color ()); + str val = fmt ("5 %1", color ()); // Add the coordinates for (ushort i = 0; i < 4; ++i) - val += fmt (" %s", getVertex (i).stringRep (false).chars ()); + val += fmt (" %1", getVertex (i)); return val; } @@ -125,7 +125,7 @@ } str LDVertex::raw () { - return fmt ("0 !LDFORGE VERTEX %d %s", color (), pos.stringRep (false).chars()); + return fmt ("0 !LDFORGE VERTEX %1 %2", color (), pos); } str LDEmpty::raw () { @@ -145,7 +145,7 @@ }; str LDBFC::raw () { - return fmt ("0 BFC %s", LDBFC::statements[type]); + return fmt ("0 BFC %1", LDBFC::statements[type]); } // ============================================================================= @@ -394,13 +394,13 @@ if (!firstDetails) text += ", "; - str noun = fmt ("%s%s", g_saObjTypeNames[objType], plural (objCount)); + str noun = fmt ("%1%2", g_saObjTypeNames[objType], plural (objCount)); // Plural of "vertex" is "vertices". Stupid English. if (objType == LDObject::Vertex && objCount != 1) noun = "vertices"; - text += fmt ("%lu %s", objCount, noun.chars ()); + text += fmt ("%1 %2", objCount, noun); firstDetails = false; } @@ -645,10 +645,10 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= str LDRadial::raw () { - return fmt ("0 !LDFORGE RADIAL %s %d %d %d %d %s %s", - str (radialTypeName ()).upper ().strip (' ').c (), + return fmt ("0 !LDFORGE RADIAL %1 %2 %3 %4 %5 %6 %7", + str (radialTypeName ()).toUpper ().remove (' '), color (), segments (), divisions (), number (), - position ().stringRep (false).chars (), transform ().stringRep().chars ()); + position ().stringRep (false), transform ().stringRep()); } char const* g_radialNameRoots[] = { @@ -679,18 +679,18 @@ } // Compose some general information: prefix, fraction, root, ring number - str prefix = (divisions () == lores) ? "" : fmt ("%d/", divisions ()); - str frac = fmt ("%d-%d", numer, denom); + str prefix = (divisions () == lores) ? "" : fmt ("%1/", divisions ()); + str frac = fmt ("%1-%2", numer, denom); str root = g_radialNameRoots[type ()]; - str num = (type () == Ring || type () == Cone) ? fmt ("%d", number ()) : ""; + str num = (type () == Ring || type () == Cone) ? fmt ("%1", number ()) : ""; // Truncate the root if necessary (7-16rin4.dat for instance). // However, always keep the root at least 2 characters. - short extra = (~frac + ~num + ~root) - 8; - root -= min<short> (max<short> (extra, 0), 2); + short extra = (frac.length () + num.length () + root.length ()) - 8; + root.chop (min<short> (max<short> (extra, 0), 2)); // Stick them all together and return the result. - return fmt ("%s%s%s%s.dat", prefix.chars(), frac.chars (), root.chars (), num.chars ()); + return (prefix + frac + root + num + ".dat"); } // =============================================================================
--- a/src/main.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/main.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -19,6 +19,7 @@ #include <QApplication> #include <QMessageBox> #include <QAbstractButton> +#include <qfile.h> #include "gui.h" #include "file.h" #include "bbox.h" @@ -32,14 +33,33 @@ ForgeWindow* g_win = null; bbox g_BBox; const QApplication* g_app = null; +QFile g_file_stdout, g_file_stderr; const vertex g_origin (0.0f, 0.0f, 0.0f); const matrix g_identity ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}); +void doPrint (QFile& f, initlist<StringFormatArg> args) { + str msg = DoFormat (args); + f.write (msg.toUtf8 (), msg.length ()); + f.flush (); +} + +void doPrint (FILE* fp, initlist<StringFormatArg> args) { + if (fp == stdout) + doPrint (g_file_stdout, args); + else if (fp == stderr) + doPrint (g_file_stderr, args); + + fatal ("unknown FILE* argument"); +} + // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= int main (int argc, char* argv[]) { + g_file_stdout.open (stdout, QIODevice::WriteOnly); + g_file_stderr.open (stderr, QIODevice::WriteOnly); + const QApplication app (argc, argv); g_app = &app; g_curfile = NULL; @@ -94,9 +114,9 @@ str versionString () { #if VERSION_PATCH == 0 - return fmt ("%d.%d", VERSION_MAJOR, VERSION_MINOR); + return fmt ("%1.%2", VERSION_MAJOR, VERSION_MINOR); #else - return fmt ("%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); + return fmt ("%1.%2.%3", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); #endif // VERSION_PATCH } @@ -115,7 +135,7 @@ } str fullVersionString () { - return fmt ("v%s%s", versionString ().chars (), versionMoniker ()); + return fmt ("v%1%2", versionString (), versionMoniker ()); } static void bombBox (str msg) { @@ -134,7 +154,7 @@ } void assertionFailure (const char* file, const ulong line, const char* funcname, const char* expr) { - str errmsg = fmt ("File %s\nLine: %lu:\nFunction %s:\n\nAssertion `%s' failed", + str errmsg = fmt ("File: %1\nLine: %2:\nFunction %3:\n\nAssertion `%4' failed", file, line, funcname, expr); #if BUILD_ID == BUILD_INTERNAL @@ -143,7 +163,7 @@ errmsg += "."; #endif - printf ("%s\n", errmsg.chars ()); + printf ("%s\n", qchars (errmsg)); #if BUILD_ID == BUILD_INTERNAL if (g_win) @@ -155,10 +175,10 @@ } void fatalError (const char* file, const ulong line, const char* funcname, str msg) { - str errmsg = fmt ("Aborting over a call to fatal():\nFile: %s\nLine: %lu\nFunction: %s\n\n%s", - file, line, funcname, msg.chars ()); + str errmsg = fmt ("Aborting over a call to fatal():\nFile: %1\nLine: %2\nFunction: %3\n\n%4", + file, line, funcname, msg); - printf ("%s\n", errmsg.chars ()); + printf ("%s\n", qchars (errmsg)); if (g_win) g_win->deleteLater ();
--- a/src/misc.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/misc.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -137,16 +137,17 @@ // turn into anything weird (like commas) setlocale (LC_NUMERIC, "C"); - str rep = fmt ("%f", num); + str rep; + rep.sprintf ("%f", num); // Remove trailing zeroes - while (rep[~rep - 1] == '0') - rep -= 1; + while (rep.right (1) == "0") + rep.chop (1); - // If there was only zeroes in the decimal place, remove + // If there were only zeroes in the decimal place, remove // the decimal point now. - if (rep[~rep - 1] == '.') - rep -= 1; + if (rep.right (1) == ".") + rep.chop (1); return rep; } @@ -157,9 +158,11 @@ bool isNumber (const str& tok) { bool gotDot = false; - for (const char& c : tok) { + for (int i = 0; i < tok.length (); ++i) { + const qchar c = tok[i]; + // Allow leading hyphen for negatives - if (&c == &tok[0] && c == '-') + if (i == 0 && c == '-') continue; // Check for decimal point @@ -238,11 +241,20 @@ edit_rotpoint_z = pos[Z]; } +str join (initlist<StringFormatArg> vals, str delim) { + QStringList list; + for (const StringFormatArg& arg : vals) + list << arg.value (); + + return list.join (delim); +} + + // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= StringParser::StringParser (str inText, char sep) { - m_tokens = inText.split (sep); + m_tokens = container_cast<QStringList, vector<str>> (inText.split (sep, QString::SkipEmptyParts)); m_pos = -1; }
--- a/src/misc.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/misc.h Fri Jun 14 16:00:54 2013 +0300 @@ -21,6 +21,7 @@ #include "config.h" #include "common.h" +#include "types.h" #define NUM_PRIMES 500 @@ -39,6 +40,8 @@ // Simplifies the given fraction. void simplify (short& numer, short& denom); +str join (initlist<StringFormatArg> vals, str delim = " "); + // Grid stuff typedef struct { const char* const name; @@ -58,6 +61,15 @@ vertex rotPoint (const vector<LDObject*>& objs); void configRotationPoint (); +template<class T, class R> R container_cast (const T& a) { + R b; + + for (auto i : a) + b << i; + + return b; +} + // ============================================================================= namespace Grid { enum Type {
--- a/src/string.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/string.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -1,434 +0,0 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 Santeri Piippo - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ - -#include <stdexcept> -#include "common.h" -#include "string.h" - -String::String () {} - -String::String (const char* data) { - m_string = data; -} - -String::String (const QString data) { - m_string = data.toStdString (); -} - -String::String (std::string data) { - m_string = data; -} - -str fmt (const char* fmtstr, ...) { - va_list va; - - va_start (va, fmtstr); - char* buf = dynafmt (fmtstr, va, 256); - va_end (va); - - str msg = buf; - delete[] buf; - return msg; -} - -char* dynafmt (const char* fmtstr, va_list va, ulong size) { - char* buf = null; - ushort run = 0; - - do { - try { - buf = new char[size]; - } catch (std::bad_alloc&) { - // fmt uses dynafmt, so using fmt here is dangerous and could lead - // into infinite recursion. Thus, use a C string this one time. - char err[256]; - sprintf (err, "caught std::bad_alloc on run #%u while trying to allocate %lu bytes", run + 1, size); - fatal (err); - } - - if (!vsnprintf (buf, size - 1, fmtstr, va)) { - delete[] buf; - buf = null; - } - - size *= 2; - ++run; - } while (buf == null); - - return buf; -} - -void String::append (const char* data) { - m_string.append (data); -} - -void String::append (const char data) { - m_string.push_back (data); -} - -void String::append (const String data) { - m_string.append (data.chars ()); -} - -String::it String::begin () { - return m_string.begin (); -} - -String::c_it String::begin () const { - return m_string.cbegin (); -} - -const char* String::c () const { - return chars (); -} - -size_t String::capacity () const { - return m_string.capacity (); -} - -const char* String::chars () const { - return m_string.c_str (); -} - -int String::compare (const char* other) const { - return m_string.compare (other); -} - -int String::compare (String other) const { - return m_string.compare (other); -} - -String::it String::end () { - return m_string.end (); -} - -String::c_it String::end () const { - return m_string.end (); -} - -void String::clear () { - m_string.clear (); -} - -bool String::empty() const { - return m_string.empty (); -} - -void String::erase (size_t pos) { - m_string.erase (m_string.begin () + pos); -} - -void String::insert (size_t pos, char c) { - m_string.insert (m_string.begin () + pos, c); -} - -size_t String::len () const { - return m_string.length (); -} - -size_t String::maxSize () const { - return m_string.max_size (); -} - -void String::resize (size_t n) { - m_string.resize (n); -} - -void String::shrinkToFit () { - m_string.shrink_to_fit (); -} - - - -void String::trim (short n) { - if (n > 0) - for (short i = 0; i < n; ++i) - m_string.erase (m_string.end () - 1 - i); - else - for (short i = abs (n) - 1; i >= 0; ++i) - m_string.erase (m_string.begin () + i); -} - -String String::strip (char unwanted) { - return strip ({unwanted}); -} - -String String::strip (std::initializer_list<char> unwanted) { - String copy (m_string); - - for (char c : unwanted) { - for (long i = len (); i >= 0; --i) - if (copy[(size_t) i] == c) - copy.erase (i); - } - - return copy; -} - -String String::upper() const { - String newstr = m_string; - - for (char& c : newstr) - if (c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - - return newstr; -} - -String String::lower () const { - String newstr = m_string; - - for (char& c : newstr) - if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - - return newstr; -} - -vector<String> String::split (char del) const { - String delimstr; - delimstr += del; - return split (delimstr); -} - -vector<String> String::split (String del) const { - vector<String> res; - size_t a = 0; - - // Find all separators and store the text left to them. - while (1) { - long b = first (del, a); - - if (b == -1) - break; - - String sub = substr (a, b); - if (~sub > 0) - res.push_back (substr (a, b)); - - a = b + strlen (del); - } - - // Add the string at the right of the last separator - if (a < len ()) - res.push_back (substr (a, len())); - - return res; -} - -void String::replace (const char* a, const char* b) { - long pos; - - while ((pos = first (a)) != -1) - m_string = m_string.replace (pos, strlen (a), b); -} - -void String::format (const char* fmtstr, ...) { - va_list va; - - va_start (va, fmtstr); - char* buf = dynafmt (fmtstr, va, 256); - va_end (va); - - m_string = buf; - delete[] buf; -} - -ushort String::count (const char needle) const { - ushort numNeedles = 0; - - for (const char& c : m_string) - if (c == needle) - numNeedles++; - - return numNeedles; -} - -String String::substr (long a, long b) const { - if (b == -1) - b = len (); - - str sub; - - try { - sub = m_string.substr (a, b - a); - } catch (const std::out_of_range& e) { - fatal (fmt ("caught std::out_of_range, coords were: (%ld, %ld), string: `%s', length: %lu", - a, b, chars (), (ulong) len ())); - } - - return sub; -} - -// ============================================================================ -int String::first (const char* c, int a) const { - unsigned int r = 0; - unsigned int index = 0; - for (; a < (int) len (); a++) { - if (m_string[a] == c[r]) { - if (r == 0) - index = a; - - r++; - if (r == strlen (c)) - return index; - } else { - if (r != 0) { - // If the string sequence broke at this point, we need to - // check this character again, for a new sequence just - // might start right here. - a--; - } - - r = 0; - } - } - - return -1; -} - -// ============================================================================ -int String::last (const char* c, int a) const { - if (a == -1) - a = len(); - - int max = strlen (c) - 1; - - int r = max; - for (; a >= 0; a--) { - if (m_string[a] == c[r]) { - r--; - if (r == -1) - return a; - } else { - if (r != max) - a++; - - r = max; - } - } - - return -1; -} - -String String::operator+ (const String data) const { - String newstr = *this; - newstr += data; - return newstr; -} - -String String::operator+ (const char* data) const { - String newstr = *this; - newstr += data; - return newstr; -} - -String& String::operator+= (const String data) { - append (data); - return *this; -} - -String& String::operator+= (const char* data) { - append (data); - return *this; -} - -String& String::operator+= (const char data) { - append (data); - return *this; -} - -String String::operator+ () const { - return upper (); -} - -String String::operator- () const { - return lower (); -} - -String String::operator- (size_t n) const { - String newstr = m_string; - newstr -= n; - return newstr; -} - -String& String::operator-= (size_t n) { - trim (n); - return *this; -} - -size_t String::operator~ () const { - return len (); -} - -vector<String> String::operator/ (String del) const { - return split (del); -} - -char& String::operator[] (size_t n) { - return m_string[n]; -} - -const char& String::operator[] (size_t n) const { - return m_string[n]; -} - -bool String::operator== (const String other) const { - return compare (other) == 0; -} - -bool String::operator== (const char* other) const { - return compare (other) == 0; -} - -bool String::operator!= (const String other) const { - return compare (other) != 0; -} - -bool String::operator!= (const char* other) const { - return compare (other) != 0; -} - -bool String::operator! () const { - return empty (); -} - -String::operator const char* () const { - return chars (); -} - -String::operator QString () { - return chars (); -} - -String::operator const QString () const { - return chars (); -} - -str String::join (const vector<str>& items, const str& delim) { - str text; - - for (const str& item : items) { - if (item != items[0]) - text += delim; - - text += item; - } - - return text; -} \ No newline at end of file
--- a/src/string.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/string.h Fri Jun 14 16:00:54 2013 +0300 @@ -24,81 +24,5 @@ #include <QString> #include "types.h" -typedef class String { -public: - typedef typename std::string::iterator it; - typedef typename std::string::const_iterator c_it; - typedef vector<String> stringlist; - - String (); - String (const char* data); - String (const QString data); - String (std::string data); - - void append (const char* data); - void append (const char data); - void append (const String data); - it begin (); - c_it begin () const; - const char* c () const; - size_t capacity () const; - const char* chars () const; - int compare (const char* other) const; - int compare (String other) const; - it end (); - c_it end () const; - void clear (); - ushort count (const char needle) const; - bool empty () const; - void erase (size_t pos); - int first (const char* c, int a = 0) const; - void format (const char* fmtstr, ...); - void insert (size_t pos, char c); - int last (const char* c, int a = -1) const; - size_t len () const; - String lower () const; - size_t maxSize () const; - void replace (const char* a, const char* b); - void resize (size_t n); - void shrinkToFit (); - stringlist split (String del) const; - stringlist split (char del) const; - String strip (char unwanted); - String strip (std::initializer_list<char> unwanted); - String substr (long a, long b) const; - void trim (short n); - String upper () const; - - String operator+ (const String data) const; - String operator+ (const char* data) const; - String& operator+= (const String data); - String& operator+= (const char* data); - String& operator+= (const char data); - String operator+ () const; - String operator- () const; - String operator- (size_t n) const; - String& operator-= (size_t n); - size_t operator~ () const; - vector<String> operator/ (String del) const; - char& operator[] (size_t n); - const char& operator[] (size_t n) const; - bool operator== (const String other) const; - bool operator== (const char* other) const; - bool operator!= (const String other) const; - bool operator!= (const char* other) const; - bool operator! () const; - operator const char* () const; - operator QString (); - operator const QString () const; - - static str join (const vector<str>& items, const str& delim); - -private: - std::string m_string; -} str; - -// Accessories -char* dynafmt (const char* fmtstr, va_list va, ulong size); -str fmt (const char* fmtstr, ...); #endif // STR_H \ No newline at end of file
--- a/src/types.cpp Thu Jun 13 16:33:17 2013 +0300 +++ b/src/types.cpp Fri Jun 14 16:00:54 2013 +0300 @@ -16,11 +16,23 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <QObject> +#include <QStringList> #include <assert.h> #include "common.h" #include "types.h" #include "misc.h" +str DoFormat (vector<StringFormatArg> args) { + assert (args.size () >= 1); + str text = args[0].value (); + + for (uchar i = 1; i < args.size (); ++i) + text = text.arg (args[i].value ()); + + return text; +} + vertex::vertex (double x, double y, double z) { m_coords[X] = x; m_coords[Y] = y; @@ -45,10 +57,14 @@ // ============================================================================= str vertex::stringRep (bool mangled) const { - return fmt (mangled ? "(%s, %s, %s)" : "%s %s %s", - ftoa (coord (X)).chars(), - ftoa (coord (Y)).chars(), - ftoa (coord (Z)).chars()); + if (mangled) + return (str ("(") + + ftoa (coord (X)) + ", " + + ftoa (coord (Y)) + ", " + + ftoa (coord (Z)) + ")"); + + return QStringList ({ftoa (coord (X)), ftoa (coord (Y)), + ftoa (coord (Z))}).join (" "); } // ============================================================================= @@ -165,7 +181,7 @@ if (i > 0) val += ' '; - val += fmt ("%s", ftoa (m_vals[i]).chars()); + val += ftoa (m_vals[i]); } return val; @@ -204,4 +220,53 @@ (val (2) * val (4) * val (6)) - (val (1) * val (3) * val (8)) - (val (0) * val (5) * val (7)); +} + +// ============================================================================= +StringFormatArg::StringFormatArg (const str& v) { + m_val = v; +} + +StringFormatArg::StringFormatArg (const char& v) { + m_val = v; +} + +StringFormatArg::StringFormatArg (const uchar& v) { + m_val = v; +} + +StringFormatArg::StringFormatArg (const qchar& v) { + m_val = v; +} + +StringFormatArg::StringFormatArg (const float& v) { + m_val = ftoa (v); +} + +StringFormatArg::StringFormatArg (const double& v) { + m_val = ftoa (v); +} + +StringFormatArg::StringFormatArg (const vertex& v) { + m_val = v.stringRep (false); +} + +StringFormatArg::StringFormatArg (const matrix& v) { + m_val = v.stringRep (); +} + +StringFormatArg::StringFormatArg (const char* v) { + m_val = v; +} + +StringFormatArg::StringFormatArg (const strconfig& v) { + m_val = v.value; +} + +StringFormatArg::StringFormatArg (const intconfig& v) { + m_val.number (v.value); +} + +StringFormatArg::StringFormatArg (const floatconfig& v) { + m_val.number (v.value); } \ No newline at end of file
--- a/src/types.h Thu Jun 13 16:33:17 2013 +0300 +++ b/src/types.h Fri Jun 14 16:00:54 2013 +0300 @@ -19,13 +19,17 @@ #ifndef TYPES_H #define TYPES_H +#include <QString> #include <vector> #include "common.h" -class String; -typedef String str; +typedef QChar qchar; +typedef QString str; template<class T> class ConstVectorReverser; template<class T> using c_rev = ConstVectorReverser<T>; +class strconfig; +class intconfig; +class floatconfig; typedef unsigned int uint; typedef unsigned short ushort; @@ -316,4 +320,47 @@ template<class T> using rev = VectorReverser<T>; template<class T> using c_rev = ConstVectorReverser<T>; +// ============================================================================= +class StringFormatArg { +public: + StringFormatArg (const str& v); + StringFormatArg (const char& v); + StringFormatArg (const uchar& v); + StringFormatArg (const qchar& v); + +#define NUMERIC_FORMAT_ARG(T,C) \ + StringFormatArg (const T& v) { \ + char valstr[32]; \ + sprintf (valstr, "%" #C, v); \ + m_val = valstr; \ + } + + NUMERIC_FORMAT_ARG (int, d) + NUMERIC_FORMAT_ARG (short, d) + NUMERIC_FORMAT_ARG (long, ld) + NUMERIC_FORMAT_ARG (uint, u) + NUMERIC_FORMAT_ARG (ushort, u) + NUMERIC_FORMAT_ARG (ulong, lu) + + StringFormatArg (const float& v); + StringFormatArg (const double& v); + StringFormatArg (const vertex& v); + StringFormatArg (const matrix& v); + StringFormatArg (const char* v); + StringFormatArg (const strconfig& v); + StringFormatArg (const intconfig& v); + StringFormatArg (const floatconfig& v); + + str value () const { return m_val; } +private: + str m_val; +}; + +str DoFormat (vector< StringFormatArg > args); +#ifndef IN_IDE_PARSER +#define fmt(...) DoFormat ({__VA_ARGS__}) +#else +str fmt (const char* fmtstr, ...); +#endif + #endif // TYPES_H \ No newline at end of file