[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project
main.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * file main.cpp
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist@bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id: main.cpp 744 2011-10-09 12:21:06Z phfaist $ */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <time.h>
29 
30 #include <signal.h>
31 
32 #include <QApplication>
33 #include <QDebug>
34 #include <QTranslator>
35 #include <QFileInfo>
36 #include <QDir>
37 #include <QResource>
38 #include <QProcess>
39 #include <QPluginLoader>
40 #include <QMessageBox>
41 #include <QLibraryInfo>
42 #include <QMetaType>
43 #include <QClipboard>
44 #include <QFontDatabase>
45 
46 #include <klfbackend.h>
47 
48 #include <klfutil.h>
49 #include <klfcolorchooser.h>
50 #include "klflib.h"
51 #include "klflibdbengine.h"
52 #include "klfliblegacyengine.h"
53 #include "klflibview.h"
54 #include "klfmain.h"
55 #include "klfconfig.h"
56 #include "klfmainwin.h"
57 #include "klfdbus.h"
58 #include "klfpluginiface.h"
59 
74 // Name of the environment variable to check for paths to extra resources
75 #ifndef KLF_RESOURCES_ENVNAM
76 #define KLF_RESOURCES_ENVNAM "KLF_RESOURCES"
77 #endif
78 
79 
80 // Program Exit Error Codes
81 #define EXIT_ERR_FILEINPUT 100
82 #define EXIT_ERR_FILESAVE 101
83 #define EXIT_ERR_OPT 102
84 
85 
86 // COMMAND-LINE-OPTION SPECIFIC DEFINITIONS
87 // using getopt.h library (specifically getopt_long())
88 
89 // flags
90 int opt_interactive = -1; // -1: not specified, 0: NOT interactive, 1: interactive
91 char *opt_input = NULL;
92 char *opt_latexinput = NULL;
93 int opt_paste = -1; // -1: don't paste, 1: paste clipboard, 2: paste selection
94 bool opt_noeval = false;
95 bool opt_base64arg = false;
96 char *opt_output = NULL;
97 char *opt_format = NULL;
98 char *opt_fgcolor = NULL;
99 char *opt_bgcolor = NULL;
100 int opt_dpi = -1;
101 char *opt_mathmode = NULL;
102 char *opt_preamble = NULL;
103 bool opt_quiet = false;
104 char *opt_redirect_debug = NULL;
105 bool opt_daemonize = false;
107 bool opt_skip_plugins = false;
108 
114 
116 char *opt_latex;
117 char *opt_dvips;
118 char *opt_gs;
120 
121 bool opt_help_requested = false;
122 FILE * opt_help_fp = stderr;
124 FILE * opt_version_fp = stderr;
125 char *opt_version_format = (char*)"KLatexFormula: Version %k using Qt %q\n";
126 
127 char **klf_args;
128 
130 char *qt_argv[1024];
131 
132 // We will occasionally need to strdup some strings to keep persistent copies. Save these copies
133 // in this array, so that we can free() them in main_exit().
134 char *opt_strdup_free_list[64] = { NULL };
136 
137 
138 static struct { bool has_error; int retcode; } opt_error;
139 
140 // option identifiers
141 enum {
142  // if you change short options here, be sure to change the short option list below.
144  OPT_INPUT = 'i',
148  OPT_NOEVAL = 'n',
150  OPT_OUTPUT = 'o',
151  OPT_FORMAT = 'F',
152  OPT_FGCOLOR = 'f',
153  OPT_BGCOLOR = 'b',
154  OPT_DPI = 'X',
157  OPT_QUIET = 'q',
159 
160  OPT_HELP = 'h',
161  OPT_VERSION = 'V',
162 
163  OPT_QTOPT = 'Q',
164 
175 
179 };
180 
186 static struct option klfcmdl_optlist[] = {
187  { "interactive", 0, NULL, OPT_INTERACTIVE },
188  { "input", 1, NULL, OPT_INPUT },
189  { "latexinput", 1, NULL, OPT_LATEXINPUT },
190  { "paste-clipboard", 0, NULL, OPT_PASTE_CLIPBOARD },
191  { "paste-selection", 0, NULL, OPT_PASTE_SELECTION },
192  { "noeval", 0, NULL, OPT_NOEVAL },
193  { "base64arg", 0, NULL, OPT_BASE64ARG },
194  { "output", 1, NULL, OPT_OUTPUT },
195  { "format", 1, NULL, OPT_FORMAT },
196  { "fgcolor", 1, NULL, OPT_FGCOLOR },
197  { "bgcolor", 1, NULL, OPT_BGCOLOR },
198  { "dpi", 1, NULL, OPT_DPI },
199  { "mathmode", 1, NULL, OPT_MATHMODE },
200  { "preamble", 1, NULL, OPT_PREAMBLE },
201  { "quiet", 2, NULL, OPT_QUIET },
202  { "redirect-debug", 1, NULL, OPT_REDIRECT_DEBUG },
203  { "daemonize", 0, NULL, OPT_DAEMONIZE },
204  { "dbus-export-mainwin", 0, NULL, OPT_DBUS_EXPORT_MAINWIN },
205  { "skip-plugins", 2, NULL, OPT_SKIP_PLUGINS },
206  // -----
207  { "outlinefonts", 2 /*optional arg*/, NULL, OPT_OUTLINEFONTS },
208  { "lborderoffset", 1, NULL, OPT_LBORDEROFFSET },
209  { "tborderoffset", 1, NULL, OPT_TBORDEROFFSET },
210  { "rborderoffset", 1, NULL, OPT_RBORDEROFFSET },
211  { "bborderoffset", 1, NULL, OPT_BBORDEROFFSET },
212  // -----
213  { "tempdir", 1, NULL, OPT_TEMPDIR },
214  { "latex", 1, NULL, OPT_LATEX },
215  { "dvips", 1, NULL, OPT_DVIPS },
216  { "gs", 1, NULL, OPT_GS },
217  { "epstopdf", 1, NULL, OPT_EPSTOPDF },
218  // -----
219  { "help", 2, NULL, OPT_HELP },
220  { "version", 2, NULL, OPT_VERSION },
221  // -----
222  { "qtoption", 1, NULL, OPT_QTOPT },
223  // ---- end of option list ----
224  {0, 0, 0, 0}
225 };
226 
227 
228 
229 // TRAP SOME SIGNALS TO EXIT GRACEFULLY
230 
231 void signal_act(int sig)
232 {
233  FILE *ftty = NULL;
234 #ifdef Q_OS_LINUX
235  ftty = fopen("/dev/tty", "w");
236 #endif
237  if (ftty == NULL)
238  ftty = stderr;
239 
240  if (sig == SIGINT) {
241  fprintf(ftty, "Interrupt\n");
242  if (ftty != stderr) fprintf(stderr, "*** Interrupt\n");
243 
244  static long last_sigint_time = 0;
245  long curtime;
246  time(&curtime);
247  bool isInsisted = (curtime - last_sigint_time <= 2); // re-pressed Ctrl-C after less than 2 secs
248  if (!isInsisted && qApp != NULL) {
249  qApp->quit();
250  last_sigint_time = curtime;
251  } else {
252  fprintf(ftty, "Exiting\n");
253  if (ftty != stderr) fprintf(stderr, "*** Exiting\n");
254  ::exit(128);
255  }
256  }
257  if (sig == SIGSEGV) {
258  fprintf(ftty, "Segmentation Fault :-(\n");
259  if (ftty != stderr) fprintf(stderr, "** Segmentation Fault :-( **\n");
260 
261  qApp->exit(127);
262 
263  // next time SIGSEGV is sent, use default handler (exit and dump core)
264  signal(SIGSEGV, SIG_DFL);
265  }
266 }
267 
268 
269 // DEBUG, WARNING AND FATAL MESSAGES HANDLER
270 
271 // redirect deboug output to this file (if non-NULL) instead of stderr
272 static FILE *klf_qt_msg_fp = NULL;
273 
274 // in case we want to print messages directly into terminal
275 static FILE *klf_fp_tty = NULL;
276 static bool klf_fp_tty_failed = false;
277 
278 void klf_qt_message(QtMsgType type, const char *msg)
279 {
280  if (opt_quiet)
281  return;
282 
283  FILE *fout = stderr;
284  if (klf_qt_msg_fp != NULL) fout = klf_qt_msg_fp;
285 
286 #ifdef Q_OS_LINUX
287  if (klf_fp_tty == NULL && !klf_fp_tty_failed)
288  if ( !(klf_fp_tty = fopen("/dev/tty", "w")) )
289  klf_fp_tty_failed = true;
290 #else
291  Q_UNUSED(klf_fp_tty_failed) ;
292 #endif
293 
294  switch (type) {
295  case QtDebugMsg:
296  // only with debugging enabled
297 #ifdef KLF_DEBUG
298  fprintf(fout, "D: %s\n", msg);
299  fflush(fout);
300 #endif
301  break;
302  case QtWarningMsg:
303  fprintf(fout, "Warning: %s\n", msg);
304  fflush(fout);
305 #ifdef KLF_DEBUG
306  // in debug mode, also print warning messages to TTY (because they get lost in the debug messages!)
307  if (klf_fp_tty) fprintf(klf_fp_tty, "Warning: %s\n", msg);
308 #endif
309 
310 #if defined Q_WS_WIN && defined KLF_DEBUG
311 # define SAFECOUNTER_NUM 10
312  // only show dialog after having created a QApplication
313  if (qApp != NULL && qApp->inherits("QApplication")) {
314  static int safecounter = SAFECOUNTER_NUM;
315  if (safecounter-- >= 0) {
316  if (!QString::fromLocal8Bit(msg).startsWith("MNG error")) { // ignore these "MNG" errors...
317  QMessageBox::warning(0, "Warning",
318  QString("KLatexFormula System Warning:\n%1")
319  .arg(QString::fromLocal8Bit(msg)));
320  }
321  }
322  if (safecounter == -1) {
323  QMessageBox::information(0, "Information",
324  QString("Shown %1 system warnings. Will stop displaying them.").arg(SAFECOUNTER_NUM));
325  safecounter = -2;
326  }
327  if (safecounter < -2) safecounter = -2;
328  }
329 #endif
330  break;
331  case QtCriticalMsg:
332  fprintf(fout, "Error: %s\n", msg);
333  fflush(fout);
334 #ifdef Q_WS_WIN
335  if (qApp != NULL && qApp->inherits("QApplication")) {
336  QMessageBox::critical(0, QObject::tr("Error", "[[KLF's Qt Message Handler: dialog title]]"),
337  QObject::tr("KLatexFormula System Error:\n%1",
338  "[[KLF's Qt Message Handler: dialog text]]")
339  .arg(QString::fromLocal8Bit(msg)));
340  }
341 #endif
342  break;
343  case QtFatalMsg:
344  fprintf(fout, "Fatal: %s\n", msg);
345  fflush(fout);
346 #ifdef Q_WS_WIN
347  if (qApp != NULL && qApp->inherits("QApplication")) {
348  QMessageBox::critical(0, QObject::tr("FATAL ERROR",
349  "[[KLF's Qt Message Handler: dialog title]]"),
350  QObject::tr("KLatexFormula System FATAL ERROR:\n%1",
351  "[[KLF's Qt Message Handler: dialog text]]")
352  .arg(QString::fromLocal8Bit(msg)));
353  }
354 #endif
355  ::exit(255);
356  default:
357  fprintf(fout, "?????: %s\n", msg);
358  fflush(fout);
359  break;
360  }
361 }
362 
363 
364 
365 
366 
367 // UTILITY FUNCTIONS
368 
369 
370 void main_parse_options(int argc, char *argv[]);
371 
374 {
376  // FIXME: under windows, we have a proliferation of qt_temp.XXXXXX files
377  // in local plugin directory, what's going on?
379  QStringList qttempfiles = pdir.entryList(QStringList() << "qt_temp.??????", QDir::Files);
380  foreach(QString s, qttempfiles) {
382  }
383  // free strdup()'ed strings
384  while (--opt_strdup_free_list_n >= 0)
386 
387 }
388 
390 void main_exit(int code)
391 {
392  main_cleanup();
393  exit(code);
394 }
395 
401 QString main_get_input(char *input, char *latexinput, int paste)
402 {
403  QString latex;
404  if (latexinput != NULL && strlen(latexinput) != 0) {
405  latex += QString::fromLocal8Bit(latexinput);
406  }
407  if (input != NULL && strlen(input) != 0) {
408  QString fname = QString::fromLocal8Bit(input);
409  QFile f;
410  if ( fname == "-" ) {
411  if ( ! f.open(stdin, QIODevice::ReadOnly) ) {
412  qCritical("%s", qPrintable(QObject::tr("Can't read standard input (!)")));
414  }
415  } else {
416  f.setFileName(fname);
417  if ( ! f.open(QIODevice::ReadOnly) ) {
418  qCritical("%s", qPrintable(QObject::tr("Can't read input file `%1'.").arg(fname)));
420  }
421  }
422  // now file is opened properly.
423  QByteArray contents = f.readAll();
424  // contents is assumed to be local 8 bit encoding.
425  latex += QString::fromLocal8Bit(contents);
426  }
427  if (paste >= 0) {
428  if (!qApp->inherits("QApplication")) {
429  qWarning("%s",
430  qPrintable(QObject::tr("--paste-{clipboard|selection} requires interactive mode. Ignoring option.")));
431  } else {
432  if (paste == 1)
433  latex += QApplication::clipboard()->text();
434  else
435  latex += QApplication::clipboard()->text(QClipboard::Selection);
436  }
437  }
438 
439  return latex;
440 }
441 
444 void main_save(KLFBackend::klfOutput klfoutput, const QString& f_output, QString format)
445 {
446  KLFBackend::saveOutputToFile(klfoutput, f_output, format);
447 }
448 
450 {
452 
453  // this function is called with running Q[Core]Application and klfconfig all set up.
454 
456  QRegExp rgx("^" KLF_RESOURCES_ENVNAM "=");
457  QStringList klf_resources_l = env.filter(rgx);
458  QString klf_resources = QString::null;
459  if (klf_resources_l.size() > 0) {
460  klf_resources = klf_resources_l[0].replace(rgx, "");
461  }
462 
463  bool klfsettings_can_import = false;
464 
465  // Find global system-wide klatexformula rccresources dir
466  QStringList defaultrccpaths;
467 #ifdef KLF_SHARE_RCCRESOURCES_DIR
468  defaultrccpaths << klfPrefixedPath(KLF_SHARE_RCCRESOURCES_DIR); // prefixed by app-dir-path
469 #endif
470  defaultrccpaths << klfconfig.globalShareDir+"/rccresources/";
471  defaultrccpaths << klfconfig.homeConfigDirRCCResources;
472  klfDbg("RCC search path is "<<defaultrccpaths.join(QString()+KLF_PATH_SEP)) ;
473  QString rccfilepath;
474  if ( klf_resources.isNull() ) {
475  rccfilepath = "";
476  } else {
477  rccfilepath = klf_resources;
478  }
479  // printf("DEBUG: Rcc file list is \"%s\"\n", rccfilepath.toLocal8Bit().constData());
480  QStringList rccfiles = rccfilepath.split(KLF_PATH_SEP, QString::KeepEmptyParts);
481  int j, k;
482  for (QStringList::iterator it = rccfiles.begin(); it != rccfiles.end(); ++it) {
483  if ((*it).isEmpty()) {
484  // empty split section: meaning that we want default paths at this point
485  it = rccfiles.erase(it, it+1);
486  for (j = 0; j < defaultrccpaths.size(); ++j) {
487  it = rccfiles.insert(it, defaultrccpaths[j]) + 1;
488  }
489  // having the default paths added, it is safe for klfsettings to import add-ons to ~/.klf.../rccresources/
490  klfsettings_can_import = true;
491  --it; // we already point to the next entry, compensate the ++it in for
492  }
493  }
494  QStringList rccfilesToLoad;
495  for (j = 0; j < rccfiles.size(); ++j) {
496  QFileInfo fi(rccfiles[j]);
497  if (fi.isDir()) {
498  QDir dir(rccfiles[j]);
499  QFileInfoList files = dir.entryInfoList(QStringList()<<"*.rcc", QDir::Files);
500  for (k = 0; k < files.size(); ++k) {
501  QString f = files[k].canonicalFilePath();
502  if (!rccfilesToLoad.contains(f))
503  rccfilesToLoad << f;
504  }
505  } else if (fi.isFile() && fi.suffix() == "rcc") {
506  QString f = fi.canonicalFilePath();
507  if (!rccfilesToLoad.contains(f))
508  rccfilesToLoad << f;
509  }
510  }
511  for (j = 0; j < rccfilesToLoad.size(); ++j) {
512  KLFAddOnInfo addoninfo(rccfilesToLoad[j]);
513  // resource registered.
514  klf_addons.append(addoninfo);
515  klfDbg("registered resource "<<addoninfo.fpath()<<".") ;
516  }
517 
518  // set the global "can-import" flag
519  klf_addons_canimport = klfsettings_can_import;
520 
521  void dumpDir(const QDir&, int = 0);
522  klfDbg( "dump of :/ :" ) ;
523  dumpDir(QDir(":/"));
524 }
525 
526 
527 void dumpDir(const QDir& d, int indent = 0)
528 {
529  char sindent[] = " ";
530  uint nindent = indent*2; // 2 spaces per indentation
531  if (nindent < strlen(sindent))
532  sindent[nindent] = '\0';
533 
534  QStringList dchildren = d.entryList(QDir::Dirs);
535 
536  int k;
537  for (k = 0; k < dchildren.size(); ++k) {
538  // skip system ":/trolltech"
539  if (indent == 0 && dchildren[k] == "trolltech")
540  continue;
541  qDebug("%s%s/", sindent, qPrintable(dchildren[k]));
542  dumpDir(QDir(d.absoluteFilePath(dchildren[k])), indent+1);
543  }
544 
545  QStringList fchildren = d.entryList(QDir::Files);
546  for (k = 0; k < fchildren.size(); ++k) {
547  qDebug("%s%s", sindent, qPrintable(fchildren[k]));
548  }
549 }
550 
553  int prefixLen;
554 public:
556  VersionCompareWithPrefixGreaterThan(const QString& prefix) : prefixLen(prefix.length()) { }
557  bool operator()(const QString& a, const QString& b) {
558  return klfVersionCompare(a.mid(prefixLen), b.mid(prefixLen)) > 0;
559  }
560 };
561 
563 {
565 
566  QStringList baseplugindirs =
568 
569  klfDbg("base plugins dirs are "<<baseplugindirs) ;
570 
571  // first step: copy all resource-located plugin libraries to our local config
572  // directory because we can only load filesystem-located plugins.
573  int i, k, j;
574  for (k = 0; k < klf_addons.size(); ++k) {
575  QStringList pluginList = klf_addons[k].pluginList();
576  for (j = 0; j < pluginList.size(); ++j) {
577  KLFAddOnInfo::PluginSysInfo psinfo = klf_addons[k].pluginSysInfo(pluginList[j]);
578  klfDbg( "Testing plugin psinfo="<<psinfo<<"\n\tTo our system: qtver="<<qVersion()
579  <<"; klfver="<<KLF_VERSION_STRING<<"; os="<<KLFSysInfo::osString()
580  <<"; arch="<<KLFSysInfo::arch() ) ;
581  if ( psinfo.isCompatibleWithCurrentSystem() ) {
582  // ok to install plugin
583  QString resfn = klf_addons[k].rccmountroot() + "/plugins/" + pluginList[j];
584  QString locsubdir = klf_addons[k].pluginLocalSubDirName(pluginList[j]);
585  QString locfn = klfconfig.homeConfigDirPlugins + "/" + locsubdir + "/"
586  + QFileInfo(pluginList[j]).fileName();
587  QDateTime installedplugin_dt = QFileInfo(locfn).lastModified();
588  QDateTime resourceplugin_dt = QFileInfo(klf_addons[k].fpath()).lastModified();
589  qDebug("Comparing resource datetime (%s) with installed plugin datetime (%s)",
590  qPrintable(resourceplugin_dt.toString()), qPrintable(installedplugin_dt.toString()));
591  if ( ! QFile::exists( locfn ) ||
592  installedplugin_dt.isNull() || resourceplugin_dt.isNull() ||
593  ( resourceplugin_dt > installedplugin_dt ) ) {
594  // create path to that plugin dir
595  if (!locsubdir.isEmpty() &&
596  !QDir(klfconfig.homeConfigDirPlugins + "/plugins/" + locsubdir).exists())
598  // remove old version if exists
599  if (QFile::exists(locfn)) QFile::remove(locfn);
600  // copy plugin to local plugin dir
601  klfDbg( "\tcopy "<<resfn<<" to "<<locfn ) ;
602  bool res = QFile::copy( resfn , locfn );
603  if ( ! res ) {
604  qWarning("Unable to copy plugin '%s' to local directory!", qPrintable(pluginList[j]));
605  } else {
606  QFile::setPermissions(locfn, QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
607  QFile::ReadUser|QFile::WriteUser|QFile::ExeUser|
608  QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther);
609  qDebug("Copied plugin %s to local directory %s.", qPrintable(resfn), qPrintable(locfn));
610  }
611  }
612  }
613  // OK, plugin locally installed.
614  }
615  }
616 
617  // explore all base plugins dir, eg. /usr/share/klatexformula/plugins, and ~/.klatexformula/plugins/
618  int n;
619  for (n = 0; n < baseplugindirs.size(); ++n) {
620  QString baseplugindir = baseplugindirs[n];
621  klfDbg("exploring base plugin directory "<<baseplugindir) ;
622  // build a list of plugin directories to search. We will need to load plugins in our version directory
623  // + all prior version directories + root plugin path.
624  QStringList pluginsdirs;
625  // For each path in pluginsdirs, in this array (at same index pos) we have the relative path from baseplugindir.
626  QStringList pluginsdirsbaserel;
627  QDir pdir(baseplugindir);
628  QStringList pdirlist = pdir.entryList(QStringList()<<"klf*", QDir::Dirs);
629  // sort plugin dirs so that for a plugin existing in multiple versions, we load the one for the
630  // most recent first, then ignore the others.
631  qSort(pdirlist.begin(), pdirlist.end(), VersionCompareWithPrefixGreaterThan("klf"));
632  for (i = 0; i < pdirlist.size(); ++i) {
633  klfDbg( "maybe adding plugin dir"<<pdirlist[i]<<"; klfver="<<pdirlist[i].mid(3) ) ;
634  if (klfVersionCompare(pdirlist[i].mid(3), KLF_VERSION_STRING) <= 0) { // Version OK
635  pluginsdirs << pdir.absoluteFilePath(pdirlist[i]) ;
636  pluginsdirsbaserel << pdirlist[i]+"/";
637  }
638  }
639  pluginsdirs << klfconfig.homeConfigDirPlugins ;
640  pluginsdirsbaserel << "" ;
641 
642  klfDbg( "pluginsdirs="<<pluginsdirs ) ;
643 
644  for (i = 0; i < pluginsdirs.size(); ++i) {
645  if ( ! QFileInfo(pluginsdirs[i]).isDir() )
646  continue;
647 
648  QDir thisplugdir(pluginsdirs[i]);
649  QStringList plugins = thisplugdir.entryList(KLF_DLL_EXT_LIST, QDir::Files);
650  KLFPluginGenericInterface * pluginInstance;
651  for (j = 0; j < plugins.size(); ++j) {
652  QString pluginfname = plugins[j];
653  QString pluginfnamebaserel = pluginsdirsbaserel[i]+plugins[j];
654  bool plugin_already_loaded = false;
655  int k;
656  for (k = 0; k < klf_plugins.size(); ++k) {
657  if (QFileInfo(klf_plugins[k].fname).fileName() == pluginfname) {
658  klfDbg( "Rejecting loading of plugin "<<pluginfname<<" in dir "<<pluginsdirs[i]
659  <<"; already loaded." ) ;
660  plugin_already_loaded = true;
661  break;
662  }
663  }
664  if (plugin_already_loaded)
665  continue;
666  QString pluginpath = thisplugdir.absoluteFilePath(pluginfname);
667  QPluginLoader pluginLoader(pluginpath, app);
668  bool loaded = pluginLoader.load();
669  if (!loaded) {
670  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<". Skipping.");
671  continue;
672  }
673  QObject *pluginInstObject = pluginLoader.instance();
674  if (pluginInstObject == NULL) {
675  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<" (object is NULL). Skipping.");
676  continue;
677  }
678  pluginInstance = qobject_cast<KLFPluginGenericInterface *>(pluginInstObject);
679  if (pluginInstance == NULL) {
680  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<" (instance is NULL). Skipping.");
681  continue;
682  }
683  // plugin file successfully loaded.
684  QString nm = pluginInstance->pluginName();
685  klfDbg("Successfully loaded plugin library "<<nm<<" ("<<qPrintable(pluginInstance->pluginDescription())
686  <<") from file "<<pluginfnamebaserel);
687 
688  if ( ! klfconfig.Plugins.pluginConfig.contains(nm) ) {
689  // create default plugin configuration if non-existant
691  // ask plugin whether it's supposed to be loaded by default
692  klfconfig.Plugins.pluginConfig[nm]["__loadenabled"] =
693  pluginInstance->pluginDefaultLoadEnable();
694  }
695  bool keepPlugin = true;
696 
697  // make sure this plugin wasn't already loaded (eg. in a different klf-version sub-dir)
698  bool pluginRejected = false;
699  for (k = 0; k < klf_plugins.size(); ++k) {
700  if (klf_plugins[k].name == nm) {
701  klfDbg( "Rejecting loading of plugin "<<nm<<" in "<<pluginfname<<"; already loaded." ) ;
702  pluginLoader.unload();
703  pluginRejected = true;
704  break;
705  }
706  }
707  if (pluginRejected)
708  continue;
709 
710  KLFPluginInfo pluginInfo;
711  pluginInfo.name = nm;
712  pluginInfo.title = pluginInstance->pluginTitle();
713  pluginInfo.description = pluginInstance->pluginDescription();
714  pluginInfo.author = pluginInstance->pluginAuthor();
715  pluginInfo.fname = pluginfnamebaserel;
716  pluginInfo.fpath = pluginpath;
717  pluginInfo.instance = NULL;
718 
719  // if we are configured to load this plugin, load it.
720  keepPlugin = keepPlugin && klfconfig.Plugins.pluginConfig[nm]["__loadenabled"].toBool();
721  klfDbg("got plugin info. keeping plugin? "<<keepPlugin);
722  if ( keepPlugin ) {
725  klfDbg("prepared a configaccess "<<c);
726  pluginInstance->initialize(app, mainWin, c);
727  pluginInfo.instance = pluginInstance;
728  qDebug("\tPlugin %s loaded and initialized.", qPrintable(nm));
729  } else {
730  // if we aren't configured to load it, then discard it, but keep info with NULL instance,
731  // so that user can configure to load or not this plugin in the settings dialog.
732  delete pluginInstance;
733  pluginInfo.instance = NULL;
734  qDebug("\tPlugin %s NOT loaded.", qPrintable(nm));
735  }
736  klf_plugins.push_back(pluginInfo);
737  }
738  }
739  }
740 }
741 
742 
743 
744 
745 // function to set up the Q[Core]Application correctly
747 {
748  a->setApplicationName(QLatin1String("KLatexFormula"));
749  a->setApplicationVersion(QLatin1String(KLF_VERSION_STRING));
750  a->setOrganizationDomain(QLatin1String("klatexformula.org"));
751  a->setOrganizationName(QLatin1String("KLatexFormula"));
752 
753 #ifdef KLF_LIBKLFTOOLS_STATIC
754  Q_INIT_RESOURCE(klftoolsres) ;
755 #endif
756 #ifdef KLF_LIBKLFAPP_STATIC
757  Q_INIT_RESOURCE(klfres) ;
758 #endif
759 
760  // add [share dir]/qt-plugins to library path.
761  // under windows, that is were plugins are packaged with the executable
764 
765  klfDbg("Library paths are:\n"<<qPrintable(QCoreApplication::libraryPaths().join("\n")));
766 
767  qRegisterMetaType< QImage >("QImage");
768  qRegisterMetaType< KLFStyle >();
769  qRegisterMetaTypeStreamOperators< KLFStyle >("KLFStyle");
770  qRegisterMetaType< KLFLibEntry >();
771  qRegisterMetaTypeStreamOperators< KLFLibEntry >("KLFLibEntry");
772  qRegisterMetaType< KLFLibResourceEngine::KLFLibEntryWithId >();
773  qRegisterMetaTypeStreamOperators< KLFLibResourceEngine::KLFLibEntryWithId >
774  /* */ ("KLFLibResourceEngine::KLFLibEntryWithId");
775 
776  // for delayed calls in klflibview.cpp
777  qRegisterMetaType< QItemSelection >("QItemSelection");
778  qRegisterMetaType< QItemSelectionModel::SelectionFlags >("QItemSelectionModel::SelectionFlags");
779 }
780 
781 
782 // OUR MAIN FUNCTION
783 
784 int main(int argc, char **argv)
785 {
786  int k;
787  klfDbgT("$$main()$$") ;
788 
789  qInstallMsgHandler(klf_qt_message);
790 
791  // // DEBUG: command-line arguments
792  // for (int jjj = 0; jjj < argc; ++jjj)
793  // qDebug("arg: %s", argv[jjj]);
794 
795  // signal acting -- catch SIGINT to exit gracefully
796  signal(SIGINT, signal_act);
797  // signal acting -- catch SIGSEGV to attempt graceful exit
798  signal(SIGSEGV, signal_act);
799 
800  klfDbg("about to parse options") ;
801 
802  // parse command-line options
803  main_parse_options(argc, argv);
804 
805  klfDbg("options parsed.") ;
806 
807  // error handling
808  if (opt_error.has_error) {
809  qCritical("Error while parsing command-line arguments.");
810  qCritical("Use --help to display command-line help.");
812  }
813 
814  // redirect debug output if requested
815  if (opt_redirect_debug != NULL) {
816  // force the file name to end in .klfdebug to make sure we don't overwrite an important file
817  char fname[1024];
818  const char * SUFFIX = ".klfdebug";
819  strcpy(fname, opt_redirect_debug);
820  if (strncmp(fname+(strlen(fname)-strlen(SUFFIX)), SUFFIX, strlen(SUFFIX)) != 0) {
821  // fname does not end with SUFFIX
822  strcat(fname, SUFFIX);
823  }
824  // before performing the redirect...
825  klfDbg("Redirecting debug output to file "<<QString::fromLocal8Bit(fname)) ;
826  klf_qt_msg_fp = fopen(fname, "w");
827  KLF_ASSERT_NOT_NULL( klf_qt_msg_fp, "debug output redirection failed." , /* no fail action */; ) ;
828  if (klf_qt_msg_fp != NULL) {
829  fprintf(klf_qt_msg_fp, "\n\n"
830  "-------------------------------------------------\n"
831  " KLATEXFORMULA DEBUG OUTPUT\n"
832  "-------------------------------------------------\n"
833  "Started on %s\n\n",
834  qPrintable(QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate)));
835  }
836  }
837 
838  if ( opt_interactive ) {
839  // save the qt_argv options separately to pass them to daemonized process if needed, before
840  // QApplication modifies the qt_argv array
841  QStringList qtargvlist;
842  for (k = 0; k < qt_argc && qt_argv[k] != NULL; ++k)
843  qtargvlist << QString::fromLocal8Bit(qt_argv[k]);
844 
845  // Create the QApplication
847 
848 #ifdef Q_WS_MAC
849  extern void __klf_init_the_macpasteboardmime();
851 #endif
852 
853  // add our default application font(s) ;-)
854  QFileInfoList appFontsInfoList = QDir(":/data/fonts/").entryInfoList(QStringList()<<"*.otf"<<"*.ttf");
855  int k;
856  for (k = 0; k < appFontsInfoList.size(); ++k) {
857  QFontDatabase::addApplicationFont(appFontsInfoList[k].absoluteFilePath());
858  }
859 
860  // main_get_input relies on a Q[Core]Application
862 
863  // see if we have to daemonize
864  if ( opt_daemonize ) {
865  // try to start detached process, with our arguments. This is preferred to feeding D-BUS input
866  // to the new process, since we cannot be sure this system supports D-BUS, and we would have
867  // to wait to see the new process appear, etc. and I really don't see the big advantage over
868  // cmdl options here.
870  QStringList args;
871  args << "-I";
872  if (!latexinput.isNull())
873  args << "--latexinput="+latexinput;
874  if (opt_noeval)
875  args << "--noeval";
876  if (opt_output != NULL)
877  args << "--output="+QString::fromLocal8Bit(opt_output);
878  if (opt_format != NULL)
879  args << "--format="+QString::fromLocal8Bit(opt_format);
880  if (opt_fgcolor != NULL)
881  args << "--fgcolor="+QString::fromLocal8Bit(opt_fgcolor);
882  if (opt_bgcolor != NULL)
883  args << "--bgcolor="+QString::fromLocal8Bit(opt_bgcolor);
884  if (opt_dpi >= 0)
885  args << "--dpi="+QString::number(opt_dpi);
886  if (opt_mathmode != NULL)
887  args << "--mathmode="+QString::fromLocal8Bit(opt_mathmode);
888  if (opt_preamble != NULL)
889  args << "--preamble="+QString::fromLocal8Bit(opt_preamble);
890  if (opt_quiet)
891  args << "--quiet";
892  if (opt_redirect_debug != NULL)
893  args << "--redirect-debug="+QString::fromLocal8Bit(opt_redirect_debug);
894  if (opt_outlinefonts >= 0)
895  args << "--outlinefonts="+QString::fromLatin1(opt_outlinefonts?"TRUE":"FALSE");
896  const struct { char c; int optval; } borderoffsets[] =
897  { {'t', opt_tborderoffset}, {'r', opt_rborderoffset},
898  {'b', opt_bborderoffset}, {'l', opt_lborderoffset},
899  {'\0', -1} };
900  for (k = 0; borderoffsets[k].c != 0; ++k)
901  if (borderoffsets[k].optval != -1)
902  args << (QString::fromLatin1("--")+QLatin1Char(borderoffsets[k].c)+"borderoffset="
903  +QString::number(borderoffsets[k].optval)) ;
904  if (opt_tempdir != NULL)
905  args << "--tempdir="+QString::fromLocal8Bit(opt_tempdir);
906  if (opt_latex != NULL)
907  args << "--latex="+QString::fromLocal8Bit(opt_latex);
908  if (opt_dvips != NULL)
909  args << "--dvips="+QString::fromLocal8Bit(opt_dvips);
910  if (opt_gs != NULL)
911  args << "--gs="+QString::fromLocal8Bit(opt_gs);
912  if (opt_epstopdf != NULL)
913  args << "--epstopdf="+QString::fromLocal8Bit(opt_epstopdf);
914  for (k = 0; k < qtargvlist.size(); ++k)
915  args << "--qtoption="+qtargvlist[k];
916  // add additional args
917  for (k = 0; klf_args[k] != NULL; ++k)
918  args << QString::fromLocal8Bit(klf_args[k]);
919 
920  klfDbg("Prepared deamonized process' command-line: progexe="<<progexe<<"; args="<<args) ;
921  // now launch the klatexformula 'daemon' process
922  qint64 pid;
923  bool result = QProcess::startDetached(progexe, args, QDir::currentPath(), &pid);
924  if (result) { // Success
925  if (!opt_quiet)
926  fprintf(stderr, "%s",
927  qPrintable(QObject::tr("KLatexFormula Daemon Process successfully launched with pid %1\n")
928  .arg(pid)));
929  return 0;
930  }
931  qWarning()<<qPrintable(QObject::tr("Failed to launch daemon process. Not daemonizing."));
932  }
933 
934  main_setup_app(&app);
935 
936 #if defined(KLF_USE_DBUS)
937  // see if an instance of KLatexFormula is running...
938  KLFDBusAppInterface *iface
939  = new KLFDBusAppInterface("org.klatexformula.KLatexFormula", "/MainApplication",
941  if (iface->isValid()) {
942  iface->raiseWindow();
943  // load everything via DBus
944  if ( opt_fgcolor != NULL )
945  iface->setInputData("fgcolor", opt_fgcolor);
946  if ( opt_bgcolor != NULL )
947  iface->setInputData("bgcolor", opt_bgcolor);
948  if ( opt_dpi > 0 )
949  iface->setInputData("dpi", QString::null, opt_dpi);
950  if (opt_mathmode != NULL)
951  iface->setInputData("mathmode", QString::fromLocal8Bit(opt_mathmode));
952  if (opt_preamble != NULL)
953  iface->setInputData("preamble", QString::fromLocal8Bit(opt_preamble));
954  // load latex after preamble, so that the interface doesn't prompt to include missing packages
955  if ( ! latexinput.isNull() )
956  iface->setInputData("latex", latexinput);
957  if (opt_outlinefonts >= 0)
959  if (opt_lborderoffset != -1)
961  if (opt_tborderoffset != -1)
963  if (opt_rborderoffset != -1)
965  if (opt_bborderoffset != -1)
967  if (opt_tempdir != NULL)
969  if (opt_latex != NULL)
971  if (opt_dvips != NULL)
973  if (opt_gs != NULL)
975  if (opt_epstopdf != NULL)
977  // will actually save only if output is non empty.
978  if (!opt_noeval || opt_output) {
980  }
981  // and import KLF files if wanted
982  QStringList flist;
983  for (int k = 0; klf_args[k] != NULL; ++k)
984  flist << QString::fromLocal8Bit(klf_args[k]);
985  iface->openFiles(flist);
986  main_cleanup();
987  return 0;
988  }
989 #endif
990 
991  if ( ! opt_quiet )
992  fprintf(stderr, "KLatexFormula Version %s by Philippe Faist (c) 2005-2011\n"
993  "Licensed under the terms of the GNU Public License GPL\n\n",
994  KLF_VERSION_STRING);
995 
996  klfDbgT("$$About to load config$$");
997 
998  // now load default config
999  klfconfig.loadDefaults(); // must be called before 'readFromConfig'
1002 
1003  klfDbgT("$$About to main_load_extra_resources$$");
1005 
1006  klfDbgT("$$About to main_reload_translations$$");
1008 
1013 
1014  klfDbgT("$$About to create lib factories$$");
1015 
1016  // initialize and register some library resource engine + view factories
1017  (void)new KLFLibBasicWidgetFactory(qApp);
1018  (void)new KLFLibDBEngineFactory(qApp);
1019  (void)new KLFLibLegacyEngineFactory(qApp);
1020  (void)new KLFLibDefaultViewFactory(qApp);
1021 
1022  klfDbgT( "$$START LOADING$$" ) ;
1023 
1024  KLFMainWin mainWin;
1025 
1028 
1029  mainWin.refreshWindowSizes();
1030 
1031  if (!opt_skip_plugins)
1032  main_load_plugins(&app, &mainWin);
1033 
1034  mainWin.show();
1035 
1036  mainWin.startupFinished();
1037 
1038  klfDbgT( "$$END LOADING$$" ) ;
1039 
1040 #if defined(KLF_USE_DBUS)
1041  new KLFDBusAppAdaptor(&app, &mainWin);
1043  dbusconn.registerService("org.klatexformula.KLatexFormula");
1044  dbusconn.registerObject("/MainApplication", &app);
1046  dbusconn.registerObject("/MainWindow/KLFMainWin", &mainWin, QDBusConnection::ExportAllContents
1047  | QDBusConnection::ExportChildObjects);
1048 #endif
1049 
1050  // parse command-line given actions
1051 
1052  // consistency check warning
1053  if (opt_output && latexinput.isEmpty()) {
1054  qWarning("%s", qPrintable(QObject::tr("Can't use --output without any input")));
1055  }
1056 
1057  if ( ! latexinput.isNull() )
1058  mainWin.slotSetLatex(latexinput);
1059 
1060  if ( opt_fgcolor != NULL ) {
1062  }
1063  if ( opt_bgcolor != NULL ) {
1065  }
1066  if ( opt_dpi > 0 ) {
1067  mainWin.slotSetDPI(opt_dpi);
1068  }
1069  if (opt_mathmode != NULL) {
1071  }
1072  if (opt_preamble != NULL) {
1073  qDebug("opt_preamble != NULL, gui mode, preamble=%s", opt_preamble);
1075  }
1076  if (opt_outlinefonts >= 0)
1078  if (opt_lborderoffset != -1)
1080  if (opt_tborderoffset != -1)
1082  if (opt_rborderoffset != -1)
1084  if (opt_bborderoffset != -1)
1086  if (opt_tempdir != NULL)
1088  if (opt_latex != NULL)
1090  if (opt_dvips != NULL)
1092  if (opt_gs != NULL)
1094  if (opt_epstopdf != NULL)
1096 
1097  if (!opt_noeval && opt_output) {
1098  // will actually save only if output is non empty.
1101  }
1102 
1103 
1104  // IMPORT .klf (or other) files passed as arguments
1105  QStringList flist;
1106  for (int k = 0; klf_args[k] != NULL; ++k)
1107  flist << QString::fromLocal8Bit(klf_args[k]);
1108 
1109  QMetaObject::invokeMethod(&mainWin, "openFiles", Qt::QueuedConnection, Q_ARG(QStringList, flist));
1110 
1111  app.setQuitOnLastWindowClosed(false);
1112  int r = app.exec();
1113  main_cleanup();
1114  klfDbg("application has quit; we have cleaned up main(), ready to return. code="<<r) ;
1115  // and exit.
1116  // DO NOT CALL ::exit() as this prevents KLFMainWin's destructor from being called.
1117  // This includes not calling main_exit().
1118  return r;
1119 
1120  } else {
1121  // NON-INTERACTIVE (BATCH MODE, no X11)
1122 
1123  // Create the QCoreApplication
1125 
1126  // main_get_input relies on a Q[Core]Application
1128 
1129  main_setup_app(&app);
1130 
1131  // now load default config
1132  klfconfig.loadDefaults(); // must be called before 'readFromConfig'
1135 
1137 
1139 
1140  // show version number ?
1141  if ( opt_version_requested ) {
1142  /* Remember: the format here should NOT change from one version to another, so that it
1143  * can be parsed eg. by scripts if needed. */
1145  version_string.replace(QLatin1String("%k"), QLatin1String(KLF_VERSION_STRING));
1146  version_string.replace(QLatin1String("%q"), QLatin1String(qVersion()));
1147  version_string.replace(QLatin1String("%%"), QLatin1String("%"));
1148  fprintf(opt_version_fp, "%s\n", qPrintable(version_string));
1149  main_exit(0);
1150  }
1151 
1152  // show program help ?
1153  if ( opt_help_requested ) {
1154  QFile cmdlHelpFile(klfFindTranslatedDataFile(":/data/cmdl-help", ".txt"));
1155  if (!cmdlHelpFile.open(QIODevice::ReadOnly)) {
1156  qWarning()<<KLF_FUNC_NAME<<": Can't access command-line-help file :/data/cmdl-help.txt!";
1157  main_exit(-1);
1158  }
1159  QString helpData = QString::fromUtf8(cmdlHelpFile.readAll());
1160  fprintf(opt_help_fp, "%s", helpData.toLocal8Bit().constData());
1161  main_exit(0);
1162  }
1163 
1164  if ( ! opt_quiet )
1165  fprintf(stderr, "KLatexFormula Version %s by Philippe Faist (c) 2005-2011\n"
1166  "Licensed under the terms of the GNU Public License GPL\n\n",
1167  KLF_VERSION_STRING);
1168 
1169  if ( opt_daemonize ) {
1170  qWarning()<<qPrintable(QObject::tr("The option --daemonize can only be used in interactive mode."));
1171  }
1172 
1173  // warn for ignored arguments
1174  for (int kl = 0; klf_args[kl] != NULL; ++kl)
1175  qWarning()<<qPrintable(QObject::tr("[Non-Interactive Mode] Ignoring additional command-line argument: %1")
1176  .arg(klf_args[kl]));
1177 
1178 
1179  // now process required actions.
1180  KLFBackend::klfInput input;
1181  KLFBackend::klfSettings settings;
1182  KLFBackend::klfOutput klfoutput;
1183 
1184  if ( (opt_input == NULL || !strlen(opt_input)) &&
1185  (opt_latexinput == NULL || !strlen(opt_latexinput)) ) {
1186  // read from stdin by default
1187  opt_input = strdup("-");
1189  }
1190 
1191  input.latex = latexinput;
1192 
1193  if (opt_mathmode != NULL) {
1195  } else {
1196  input.mathmode = "\\[ ... \\]";
1197  }
1198 
1199  if (opt_preamble != NULL) {
1201  } else {
1202  input.preamble = "";
1203  }
1204 
1205  if ( ! opt_fgcolor ) {
1206  opt_fgcolor = strdup("#000000");
1208  }
1209  QColor fgcolor;
1210  fgcolor.setNamedColor(opt_fgcolor);
1211  input.fg_color = fgcolor.rgb();
1212  if ( ! opt_bgcolor ) {
1213  opt_bgcolor = strdup("-");
1215  }
1216  QColor bgcolor;
1217  if (!strcmp(opt_bgcolor, "-"))
1218  bgcolor.setRgb(255, 255, 255, 0); // white transparent
1219  else
1220  bgcolor.setNamedColor(opt_bgcolor);
1221  input.bg_color = bgcolor.rgba();
1222 
1223  input.dpi = (opt_dpi > 0) ? opt_dpi : 1200;
1224 
1225  settings.outlineFonts = true;
1226  if (opt_outlinefonts >= 0)
1227  settings.outlineFonts = (bool)opt_outlinefonts;
1228  settings.lborderoffset = settings.tborderoffset
1229  = settings.rborderoffset = settings.bborderoffset = 1;
1230  if (opt_lborderoffset != -1)
1231  settings.lborderoffset = opt_lborderoffset;
1232  if (opt_tborderoffset != -1)
1233  settings.tborderoffset = opt_tborderoffset;
1234  if (opt_rborderoffset != -1)
1235  settings.rborderoffset = opt_rborderoffset;
1236  if (opt_bborderoffset != -1)
1237  settings.bborderoffset = opt_bborderoffset;
1243 
1244  if (opt_tempdir != NULL)
1246  if (opt_latex != NULL)
1248  if (opt_dvips != NULL)
1250  if (opt_gs != NULL)
1251  settings.gsexec = QString::fromLocal8Bit(opt_gs);
1252  if (opt_epstopdf != NULL)
1254 
1255  klfoutput = KLFBackend::getLatexFormula(input, settings);
1256 
1257  if (klfoutput.status != 0) {
1258  // error occurred
1259 
1260  if ( ! opt_quiet )
1261  fprintf(stderr, "%s\n", klfoutput.errorstr.toLocal8Bit().constData());
1262 
1263  main_exit(klfoutput.status);
1264  }
1265 
1267  QString format = QString::fromLocal8Bit(opt_format).trimmed().toUpper();
1268  main_save(klfoutput, output, format);
1269 
1270  main_exit( 0 );
1271  }
1272 
1273  main_exit( 0 );
1274 }
1275 
1276 
1277 // PARSE COMMAND-LINE OPTIONS
1278 
1279 FILE *main_msg_get_fp_arg(const char *arg)
1280 {
1281  FILE *fp = NULL;
1282  if (arg != NULL) {
1283  if (arg[0] == '&') { // file descriptor number
1284  int fd = atoi(&arg[1]);
1285  if (fd > 0)
1286  fp = fdopen(fd, "a");
1287  if (fd <= 0 || fp == NULL) {
1288  qWarning("Failed to open file descriptor %d.", fd);
1289  return stderr;
1290  }
1291  return fp;
1292  }
1293  if (!strcmp(arg, "-")) { // stdout
1294  return stdout;
1295  }
1296  // file name
1297  fp = fopen(arg, "a");
1298  if (fp == NULL) {
1299  qWarning("Failed to open file `%s' to print help message.", arg);
1300  return stderr;
1301  }
1302  return fp;
1303  }
1304  return stderr;
1305 }
1306 
1307 static bool __klf_parse_bool_arg(const char * arg, bool defaultvalue)
1308 {
1309  if (arg == NULL)
1310  return defaultvalue;
1311 
1312  QRegExp booltruerx = QRegExp("^\\s*on|y(es)?|1|t(rue)?\\s*", Qt::CaseInsensitive);
1313  QRegExp boolfalserx = QRegExp("^\\s*off|n(o)?|0|f(alse)?\\s*", Qt::CaseInsensitive);
1314 
1315  if ( booltruerx.exactMatch(arg) )
1316  return true;
1317  if ( boolfalserx.exactMatch(arg) )
1318  return false;
1319 
1320  qWarning()<<KLF_FUNC_NAME<<": Can't parse boolean argument: "<<QString(arg);
1321  opt_error.has_error = true;
1322  opt_error.retcode = -1;
1323 
1324  return defaultvalue;
1325 }
1326 
1327 void main_parse_options(int argc, char *argv[])
1328 {
1329  // argument processing
1330  int c;
1331  char *arg = NULL;
1332 
1333  // prepare fake command-line options as will be seen by Q[Core]Application
1334  qt_argc = 1;
1335  qt_argv[0] = argv[0];
1336  qt_argv[1] = NULL;
1337 
1338  // build getopt_long short option list
1339  char klfcmdl_optstring[1024];
1340  int k, j;
1341  for (k = 0, j = 0; klfcmdl_optlist[k].name != NULL; ++k) {
1342  if (klfcmdl_optlist[k].val < 127) { // has short option char
1343  klfcmdl_optstring[j++] = klfcmdl_optlist[k].val;
1344  if (klfcmdl_optlist[k].has_arg)
1345  klfcmdl_optstring[j++] = ':';
1346  }
1347  }
1348  klfcmdl_optstring[j] = '\0'; // terminate C string
1349 
1350  // loop for each option
1351  for (;;) {
1352  // get an option from command line
1353  c = getopt_long(argc, argv, klfcmdl_optstring, klfcmdl_optlist, NULL);
1354  if (c == -1)
1355  break;
1356 
1357  arg = NULL;
1358  if (optarg != NULL) {
1359  if (opt_base64arg) {
1360  // this argument is to be decoded from base64
1361  //
1362  // note that here QByteArray can function without a Q[Core]Application
1363  // (officially? this is just suggested by the fact that they mention it
1364  // explicitely for QString:
1365  // http://doc.trolltech.com/4.4/qcoreapplication.html#details)
1366  QByteArray decoded = QByteArray::fromBase64(optarg);
1367  arg = strdup(decoded.constData());
1368  } else {
1369  arg = strdup(optarg);
1370  }
1372  }
1373  // immediately reset this flag, as it applies to the argument of the next option
1374  // only (which we have just retrieved and possibly decoded)
1375  opt_base64arg = false;
1376 
1377  switch (c) {
1378  case OPT_INTERACTIVE:
1379  opt_interactive = 1;
1380  break;
1381  case OPT_INPUT:
1382  if (opt_interactive == -1) opt_interactive = 0;
1383  opt_input = arg;
1384  break;
1385  case OPT_LATEXINPUT:
1386  if (opt_interactive == -1) opt_interactive = 0;
1387  opt_latexinput = arg;
1388  break;
1389  case OPT_PASTE_CLIPBOARD:
1390  if (opt_interactive <= 0) {
1391  if (opt_interactive == 0)
1392  qWarning("%s", qPrintable(QObject::tr("--paste-clipboard requires interactive mode. Switching.")));
1393  opt_interactive = 1;
1394  }
1395  opt_paste = 1;
1396  break;
1397  case OPT_PASTE_SELECTION:
1398  if (opt_interactive <= 0) {
1399  if (opt_interactive == 0)
1400  qWarning("%s", qPrintable(QObject::tr("--paste-selection requires interactive mode. Switching.")));
1401  opt_interactive = 1;
1402  }
1403  opt_paste = 2;
1404  break;
1405  case OPT_NOEVAL:
1406  opt_noeval = true;
1407  break;
1408  case OPT_BASE64ARG:
1409  opt_base64arg = true;
1410  break;
1411  case OPT_OUTPUT:
1412  opt_output = arg;
1413  break;
1414  case OPT_FORMAT:
1415  opt_format = arg;
1416  break;
1417  case OPT_FGCOLOR:
1418  opt_fgcolor = arg;
1419  break;
1420  case OPT_BGCOLOR:
1421  opt_bgcolor = arg;
1422  break;
1423  case OPT_DPI:
1424  opt_dpi = atoi(arg);
1425  break;
1426  case OPT_MATHMODE:
1427  opt_mathmode = arg;
1428  break;
1429  case OPT_PREAMBLE:
1430 #if defined(Q_WS_MAC)
1431  // NASTY WORKAROUND FOR a mysterious -psn_**** option passed to the application
1432  // when opened using the apple 'open' command-line utility, and thus when the
1433  // application is launched via an icon..
1434  if ( !strncmp(arg, "sn_", 3) )
1435  break;
1436 #endif
1437  opt_preamble = arg;
1438  break;
1439  case OPT_QUIET:
1440  opt_quiet = __klf_parse_bool_arg(arg, true);
1441  break;
1442  case OPT_REDIRECT_DEBUG:
1443  opt_redirect_debug = arg;
1444  break;
1445  case OPT_DAEMONIZE:
1446  opt_daemonize = true;
1447  break;
1449  opt_dbus_export_mainwin = true;
1450  break;
1451  case OPT_SKIP_PLUGINS:
1452  // default value 'true' (default value if option is given)
1454  break;
1455  case OPT_OUTLINEFONTS:
1457  break;
1458  case OPT_LBORDEROFFSET:
1459  opt_lborderoffset = atoi(arg);
1460  break;
1461  case OPT_TBORDEROFFSET:
1462  opt_tborderoffset = atoi(arg);
1463  break;
1464  case OPT_RBORDEROFFSET:
1465  opt_rborderoffset = atoi(arg);
1466  break;
1467  case OPT_BBORDEROFFSET:
1468  opt_bborderoffset = atoi(arg);
1469  break;
1470  case OPT_TEMPDIR:
1471  opt_tempdir = arg;
1472  break;
1473  case OPT_LATEX:
1474  opt_latex = arg;
1475  break;
1476  case OPT_DVIPS:
1477  opt_dvips = arg;
1478  break;
1479  case OPT_GS:
1480  opt_gs = arg;
1481  break;
1482  case OPT_EPSTOPDF:
1483  opt_epstopdf = arg;
1484  break;
1485  case OPT_HELP:
1487  opt_help_requested = true;
1488  break;
1489  case OPT_VERSION:
1490  if (arg != NULL) {
1491  char *colonptr = strchr(arg, ':');
1492  if (colonptr != NULL) {
1493  *colonptr = '\0';
1494  opt_version_format = colonptr+1;
1495  }
1496  }
1498  opt_version_requested = true;
1499  break;
1500  case OPT_QTOPT:
1501  qt_argv[qt_argc] = arg;
1502  qt_argc++;
1503  break;
1504  default:
1505  opt_error.has_error = true;
1506  opt_error.retcode = c;
1507  return;
1508  }
1509  }
1510 
1511  qt_argv[qt_argc] = NULL;
1512 
1513  // possibly pointing on NULL if no extra arguments
1514  klf_args = & argv[optind];
1515 
1517  opt_interactive = 0;
1518 
1519  if (opt_interactive == -1) {
1520  // interactive (open GUI) by default
1521  opt_interactive = 1;
1522  }
1523 
1524  // Constistency checks
1525  if (opt_noeval && !opt_interactive) {
1526  qWarning("%s", qPrintable(QObject::tr("--noeval is relevant only in interactive mode.")));
1527  opt_noeval = false;
1528  }
1529  if (opt_noeval && opt_output) {
1530  qWarning("%s", qPrintable(QObject::tr("--noeval may not be used when --output is present.")));
1531  opt_noeval = false;
1532  }
1533  if (opt_interactive && opt_format && !opt_output) {
1534  qWarning("%s", qPrintable(QObject::tr("Ignoring --format without --output.")));
1535  opt_format = NULL;
1536  }
1537 
1538  return;
1539 }
QDBusReply< void > openFiles(const QStringList &fileNameList)
Definition: klfdbus.cpp:162
KLF_EXPORT void klf_reload_translations(QCoreApplication *app, const QString &currentLocale)
Definition: klfmain.cpp:396
char * opt_output
Definition: main.cpp:96
char * opt_fgcolor
Definition: main.cpp:98
#define KLF_RESOURCES_ENVNAM
Definition: main.cpp:76
int opt_dpi
Definition: main.cpp:100
QString locale
When setting this, don't forget to call QLocale::setDefault().
Definition: klfconfig.h:177
entryInfoList(const QStringList &nameFilters, Filters filters=NoFilter, SortFlags sort=NoSort)
contains(const Key &key)
systemEnvironment()
QList< QColor > colorChooseWidgetRecent
Definition: klfconfig.h:187
toString(const QString &format)
QFont applicationFont
Definition: klfconfig.h:179
QString homeConfigDirRCCResources
Definition: klfconfig.h:155
QMap< QString, QMap< QString, QVariant > > pluginConfig
Definition: klfconfig.h:254
bool opt_noeval
Definition: main.cpp:94
QList< QColor > userColorList
Definition: klfconfig.h:186
char * opt_redirect_debug
Definition: main.cpp:104
void signal_act(int sig)
Definition: main.cpp:231
#define klfDbgT(streamableItems)
KLFConfig klfconfig
Definition: klfconfig.cpp:88
void slotSetLatex(const QString &latex)
struct KLFConfig::@1 UI
int opt_strdup_free_list_n
Definition: main.cpp:135
setFont(const QFont &font, const char *className=0)
char * opt_tempdir
Definition: main.cpp:115
int main(int argc, char **argv)
Definition: main.cpp:784
QDBusReply< void > evaluateAndSave(const QString &output, const QString &fmt)
Definition: klfdbus.cpp:151
startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid=0)
QString fpath
Definition: klfmain.h:191
char * opt_epstopdf
Definition: main.cpp:119
registerObject(const QString &path, QObject *object, RegisterOptions options=ExportAdaptors)
contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive)
void slotSetDPI(int DPI)
setFileName(const QString &name)
#define klfDbg(streamableItems)
#define KLF_DEBUG_BLOCK(msg)
bool opt_skip_plugins
Definition: main.cpp:107
int opt_bborderoffset
Definition: main.cpp:113
void slotSetFgColor(const QColor &fgcolor)
static FILE * klf_fp_tty
Definition: main.cpp:275
static bool __klf_parse_bool_arg(const char *arg, bool defaultvalue)
Definition: main.cpp:1307
QDBusReply< void > setAlterSetting_s(int setting, const QString &value)
Definition: klfdbus.cpp:144
setPermissions(Permissions permissions)
void main_parse_options(int argc, char *argv[])
Definition: main.cpp:1327
#define EXIT_ERR_FILEINPUT
Definition: main.cpp:81
join(const QString &separator)
QDBusReply< void > setAlterSetting_i(int setting, int value)
Definition: klfdbus.cpp:137
char * qt_argv[1024]
Definition: main.cpp:130
QString tempDir
Definition: klfconfig.h:220
Utility class for plugins to access their configuration space in KLFConfig.
Definition: klfconfig.h:61
KLFPluginGenericInterface * instance
Definition: klfmain.h:194
currentPath()
char * opt_latex
Definition: main.cpp:116
QString title
Definition: klfmain.h:188
setRgb(int r, int g, int b, int a=255)
setNamedColor(const QString &name)
char ** klf_args
Definition: main.cpp:127
tr(const char *sourceText, const char *comment=0, int n=-1)
information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
FILE * main_msg_get_fp_arg(const char *arg)
Definition: main.cpp:1279
copy(const QString &newName)
KLF_EXPORT QString klfPrefixedPath(const QString &path, const QString &reference)
addLibraryPath(const QString &path)
#define KLF_ASSERT_NOT_NULL(ptr, msg, failaction)
replace(int position, int n, const QString &after)
void __klf_init_the_macpasteboardmime()
Definition: klfmime.cpp:53
bool isCompatibleWithCurrentSystem() const
Definition: klfmain.cpp:150
static bool klf_fp_tty_failed
Definition: main.cpp:276
char * opt_preamble
Definition: main.cpp:102
QString pluginName() const
QString name
Definition: klfmain.h:186
QString pluginAuthor() const
QString fpath()
Definition: klfmain.h:89
number(long n, int base=10)
QString execLatex
Definition: klfconfig.h:221
QList< QColor > colorChooseWidgetCustom
Definition: klfconfig.h:188
canonicalFilePath()
split(const QRegExp &sep, const QString &str, bool allowEmptyEntries=false)
fromLocal8Bit(const char *str, int size=-1)
int readFromConfig()
Definition: klfconfig.cpp:394
fromUtf8(const char *str, int size=-1)
int opt_rborderoffset
Definition: main.cpp:112
char * opt_gs
Definition: main.cpp:118
static void setColorList(const QList< QColor > &colorlist)
static struct @13 opt_error
addApplicationFont(const QString &fileName)
char * opt_mathmode
Definition: main.cpp:101
static struct option klfcmdl_optlist[]
Definition: main.cpp:186
entryList(const QStringList &nameFilters, Filters filters=NoFilter, SortFlags sort=NoSort)
static void setRecentCustomColors(QList< QColor > recentcolors, QList< QColor > customcolors)
void startupFinished()
Definition: klfmainwin.cpp:517
void main_save(KLFBackend::klfOutput klfoutput, const QString &f_output, QString format)
Definition: main.cpp:444
unsigned long fg_color
void slotSetPreamble(const QString &preamble)
char * opt_dvips
Definition: main.cpp:117
QString execGs
Definition: klfconfig.h:223
QString pluginDescription() const
KLF_EXPORT QString klf_share_dir_abspath()
Definition: klfconfig.cpp:65
unsigned long bg_color
VersionCompareWithPrefixGreaterThan(const QString &prefix)
Definition: main.cpp:556
bool useSystemAppFont
Definition: klfconfig.h:178
Definition: main.cpp:173
void main_load_extra_resources()
Definition: main.cpp:449
open(OpenMode mode)
QString execDvips
Definition: klfconfig.h:222
bool opt_quiet
Definition: main.cpp:103
void alterSetting(altersetting_which, int ivalue)
bool opt_help_requested
Definition: main.cpp:121
KLF_EXPORT QString arch()
QString author
Definition: klfmain.h:187
QDBusReply< void > setInputData(const QString &key, const QString &svalue, int ivalue=-1)
Definition: klfdbus.cpp:130
#define KLF_DLL_EXT_LIST
Definition: klfmain.h:48
#define KLF_FUNC_NAME
void main_exit(int code)
Definition: main.cpp:390
int opt_lborderoffset
Definition: main.cpp:110
FILE * opt_help_fp
Definition: main.cpp:122
QList< KLFPluginInfo > klf_plugins
Definition: klfmain.cpp:50
bool opt_version_requested
Definition: main.cpp:123
bool opt_daemonize
Definition: main.cpp:105
invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0)
struct KLFConfig::@3 BackendSettings
void slotSetBgColor(const QColor &bgcolor)
virtual void initialize(QApplication *app, KLFMainWin *mainWin, KLFPluginConfigAccess *config)=0
void klf_qt_message(QtMsgType type, const char *msg)
Definition: main.cpp:278
int maxUserColors
Definition: klfconfig.h:189
QString pluginTitle() const
QDBusReply< void > raiseWindow()
Definition: klfdbus.cpp:124
int opt_paste
Definition: main.cpp:93
int opt_outlinefonts
Definition: main.cpp:109
void refreshWindowSizes()
Definition: klfmainwin.cpp:555
char * opt_format
Definition: main.cpp:97
void detectMissingSettings()
Definition: klfconfig.cpp:336
mid(int position, int n=-1)
void main_cleanup()
Definition: main.cpp:373
char * opt_input
Definition: main.cpp:91
static FILE * klf_qt_msg_fp
Definition: main.cpp:272
fromBase64(const QByteArray &base64)
KLF_EXPORT QString osString(KLFSysInfo::Os sysos=os())
KLF_EXPORT int klfVersionCompare(const QString &v1, const QString &v2)
void slotEvaluateAndSave(const QString &output, const QString &format)
KLF_EXPORT QString klfFindTranslatedDataFile(const QString &baseFileName, const QString &extension)
Definition: klfmain.cpp:504
QList< KLFAddOnInfo > klf_addons
Definition: klfmain.cpp:54
bool has_error
Definition: main.cpp:138
critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
KLFPluginConfigAccess getPluginConfigAccess(const QString &name)
Definition: klfconfig.cpp:712
absoluteFilePath(const QString &fileName)
void dumpDir(const QDir &d, int indent=0)
Definition: main.cpp:527
char * opt_strdup_free_list[64]
Definition: main.cpp:134
void main_setup_app(QCoreApplication *a)
Definition: main.cpp:746
static bool saveOutputToFile(const klfOutput &output, const QString &fileName, const QString &format=QString(), QString *errorString=NULL)
int opt_interactive
Definition: main.cpp:90
fromLatin1(const char *str, int size=-1)
void loadDefaults()
Definition: klfconfig.cpp:164
bool opt_dbus_export_mainwin
Definition: main.cpp:106
warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
char * opt_bgcolor
Definition: main.cpp:99
#define EXIT_ERR_OPT
Definition: main.cpp:83
FILE * opt_version_fp
Definition: main.cpp:124
QString globalShareDir
Definition: klfconfig.h:152
exists(const QString &name)
int qt_argc
Definition: main.cpp:129
int opt_tborderoffset
Definition: main.cpp:111
char * opt_version_format
Definition: main.cpp:125
bool klf_addons_canimport
Definition: klfmain.cpp:55
bool opt_base64arg
Definition: main.cpp:95
filter(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive)
QString execEpstopdf
Definition: klfconfig.h:224
bool given as an int value
Definition: klfmainwin.h:254
QString description
Definition: klfmain.h:189
char * opt_latexinput
Definition: main.cpp:92
void slotSetMathMode(const QString &mathmode)
bool operator()(const QString &a, const QString &b)
Definition: main.cpp:557
exactMatch(const QString &str)
static klfOutput getLatexFormula(const klfInput &in, const klfSettings &settings)
struct KLFConfig::@5 Plugins
QString fname
Definition: klfmain.h:192
bool pluginDefaultLoadEnable() const
registerService(const QString &serviceName)
mkpath(const QString &dirPath)
void main_load_plugins(QApplication *app, KLFMainWin *mainWin)
Definition: main.cpp:562
QString main_get_input(char *input, char *latexinput, int paste)
Definition: main.cpp:401
QString homeConfigDirPlugins
Definition: klfconfig.h:156
int retcode
Definition: main.cpp:138
static void setUserMaxColors(int maxcolors)
#define KLF_PATH_SEP
Provides some basic UIs to access resources.
Definition: klflibview.h:1136

Generated by doxygen 1.8.6