[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 894 2014-07-28 19:10:42Z 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 time_t last_sigint_time = 0;
245  time_t 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 
449 #ifdef KLF_DEBUG
450 static void dumpDir(const QDir& d, int indent = 0)
451 {
452  char sindent[] = " ";
453  uint nindent = indent*2; // 2 spaces per indentation
454  if (nindent < strlen(sindent))
455  sindent[nindent] = '\0';
456 
457  QStringList dchildren = d.entryList(QDir::Dirs);
458 
459  int k;
460  for (k = 0; k < dchildren.size(); ++k) {
461  // skip system ":/trolltech"
462  if (indent == 0 && dchildren[k] == "trolltech")
463  continue;
464  qDebug("%s%s/", sindent, qPrintable(dchildren[k]));
465  dumpDir(QDir(d.absoluteFilePath(dchildren[k])), indent+1);
466  }
467 
468  QStringList fchildren = d.entryList(QDir::Files);
469  for (k = 0; k < fchildren.size(); ++k) {
470  qDebug("%s%s", sindent, qPrintable(fchildren[k]));
471  }
472 }
473 #else
474 inline void dumpDir(const QDir&, int = 0) { }
475 #endif
476 
478 {
480 
481  // this function is called with running Q[Core]Application and klfconfig all set up.
482 
484  QRegExp rgx("^" KLF_RESOURCES_ENVNAM "=");
485  QStringList klf_resources_l = env.filter(rgx);
486  QString klf_resources = QString::null;
487  if (klf_resources_l.size() > 0) {
488  klf_resources = klf_resources_l[0].replace(rgx, "");
489  }
490 
491  bool klfsettings_can_import = false;
492 
493  // Find global system-wide klatexformula rccresources dir
494  QStringList defaultrccpaths;
495 #ifdef KLF_SHARE_RCCRESOURCES_DIR
496  defaultrccpaths << klfPrefixedPath(KLF_SHARE_RCCRESOURCES_DIR); // prefixed by app-dir-path
497 #endif
498  defaultrccpaths << klfconfig.globalShareDir+"/rccresources/";
499  defaultrccpaths << klfconfig.homeConfigDirRCCResources;
500  klfDbg("RCC search path is "<<defaultrccpaths.join(QString()+KLF_PATH_SEP)) ;
501  QString rccfilepath;
502  if ( klf_resources.isNull() ) {
503  rccfilepath = "";
504  } else {
505  rccfilepath = klf_resources;
506  }
507  // printf("DEBUG: Rcc file list is \"%s\"\n", rccfilepath.toLocal8Bit().constData());
508  QStringList rccfiles = rccfilepath.split(KLF_PATH_SEP, QString::KeepEmptyParts);
509  int j, k;
510  for (QStringList::iterator it = rccfiles.begin(); it != rccfiles.end(); ++it) {
511  if ((*it).isEmpty()) {
512  // empty split section: meaning that we want default paths at this point
513  it = rccfiles.erase(it, it+1);
514  for (j = 0; j < defaultrccpaths.size(); ++j) {
515  it = rccfiles.insert(it, defaultrccpaths[j]) + 1;
516  }
517  // having the default paths added, it is safe for klfsettings to import add-ons to ~/.klf.../rccresources/
518  klfsettings_can_import = true;
519  --it; // we already point to the next entry, compensate the ++it in for
520  }
521  }
522  QStringList rccfilesToLoad;
523  for (j = 0; j < rccfiles.size(); ++j) {
524  QFileInfo fi(rccfiles[j]);
525  if (fi.isDir()) {
526  QDir dir(rccfiles[j]);
527  QFileInfoList files = dir.entryInfoList(QStringList()<<"*.rcc", QDir::Files);
528  for (k = 0; k < files.size(); ++k) {
529  QString f = files[k].canonicalFilePath();
530  if (!rccfilesToLoad.contains(f))
531  rccfilesToLoad << f;
532  }
533  } else if (fi.isFile() && fi.suffix() == "rcc") {
534  QString f = fi.canonicalFilePath();
535  if (!rccfilesToLoad.contains(f))
536  rccfilesToLoad << f;
537  }
538  }
539  for (j = 0; j < rccfilesToLoad.size(); ++j) {
540  KLFAddOnInfo addoninfo(rccfilesToLoad[j]);
541  // resource registered.
542  klf_addons.append(addoninfo);
543  klfDbg("registered resource "<<addoninfo.fpath()<<".") ;
544  }
545 
546  // set the global "can-import" flag
547  klf_addons_canimport = klfsettings_can_import;
548 
549  klfDbg( "dump of :/ :" ) ;
550  dumpDir(QDir(":/"));
551 }
552 
553 
554 
557  int prefixLen;
558 public:
560  VersionCompareWithPrefixGreaterThan(const QString& prefix) : prefixLen(prefix.length()) { }
561  bool operator()(const QString& a, const QString& b) {
562  return klfVersionCompare(a.mid(prefixLen), b.mid(prefixLen)) > 0;
563  }
564 };
565 
567 {
569 
570  QStringList baseplugindirs =
572 
573  klfDbg("base plugins dirs are "<<baseplugindirs) ;
574 
575  // first step: copy all resource-located plugin libraries to our local config
576  // directory because we can only load filesystem-located plugins.
577  int i, k, j;
578  for (k = 0; k < klf_addons.size(); ++k) {
579  QStringList pluginList = klf_addons[k].pluginList();
580  for (j = 0; j < pluginList.size(); ++j) {
581  KLFAddOnInfo::PluginSysInfo psinfo = klf_addons[k].pluginSysInfo(pluginList[j]);
582  klfDbg( "Testing plugin psinfo="<<psinfo<<"\n\tTo our system: qtver="<<qVersion()
583  <<"; klfver="<<KLF_VERSION_STRING<<"; os="<<KLFSysInfo::osString()
584  <<"; arch="<<KLFSysInfo::arch() ) ;
585  if ( psinfo.isCompatibleWithCurrentSystem() ) {
586  // ok to install plugin
587  QString resfn = klf_addons[k].rccmountroot() + "/plugins/" + pluginList[j];
588  QString locsubdir = klf_addons[k].pluginLocalSubDirName(pluginList[j]);
589  QString locfn = klfconfig.homeConfigDirPlugins + "/" + locsubdir + "/"
590  + QFileInfo(pluginList[j]).fileName();
591  QDateTime installedplugin_dt = QFileInfo(locfn).lastModified();
592  QDateTime resourceplugin_dt = QFileInfo(klf_addons[k].fpath()).lastModified();
593  qDebug("Comparing resource datetime (%s) with installed plugin datetime (%s)",
594  qPrintable(resourceplugin_dt.toString()), qPrintable(installedplugin_dt.toString()));
595  if ( ! QFile::exists( locfn ) ||
596  installedplugin_dt.isNull() || resourceplugin_dt.isNull() ||
597  ( resourceplugin_dt > installedplugin_dt ) ) {
598  // create path to that plugin dir
599  if (!locsubdir.isEmpty() &&
600  !QDir(klfconfig.homeConfigDirPlugins + "/plugins/" + locsubdir).exists())
602  // remove old version if exists
603  if (QFile::exists(locfn)) QFile::remove(locfn);
604  // copy plugin to local plugin dir
605  klfDbg( "\tcopy "<<resfn<<" to "<<locfn ) ;
606  bool res = QFile::copy( resfn , locfn );
607  if ( ! res ) {
608  qWarning("Unable to copy plugin '%s' to local directory!", qPrintable(pluginList[j]));
609  } else {
610  QFile::setPermissions(locfn, QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
611  QFile::ReadUser|QFile::WriteUser|QFile::ExeUser|
612  QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther);
613  qDebug("Copied plugin %s to local directory %s.", qPrintable(resfn), qPrintable(locfn));
614  }
615  }
616  }
617  // OK, plugin locally installed.
618  }
619  }
620 
621  // explore all base plugins dir, eg. /usr/share/klatexformula/plugins, and ~/.klatexformula/plugins/
622  int n;
623  for (n = 0; n < baseplugindirs.size(); ++n) {
624  QString baseplugindir = baseplugindirs[n];
625  klfDbg("exploring base plugin directory "<<baseplugindir) ;
626  // build a list of plugin directories to search. We will need to load plugins in our version directory
627  // + all prior version directories + root plugin path.
628  QStringList pluginsdirs;
629  // For each path in pluginsdirs, in this array (at same index pos) we have the relative path from baseplugindir.
630  QStringList pluginsdirsbaserel;
631  QDir pdir(baseplugindir);
632  QStringList pdirlist = pdir.entryList(QStringList()<<"klf*", QDir::Dirs);
633  // sort plugin dirs so that for a plugin existing in multiple versions, we load the one for the
634  // most recent first, then ignore the others.
635  qSort(pdirlist.begin(), pdirlist.end(), VersionCompareWithPrefixGreaterThan("klf"));
636  for (i = 0; i < pdirlist.size(); ++i) {
637  klfDbg( "maybe adding plugin dir"<<pdirlist[i]<<"; klfver="<<pdirlist[i].mid(3) ) ;
638  if (klfVersionCompare(pdirlist[i].mid(3), KLF_VERSION_STRING) <= 0) { // Version OK
639  pluginsdirs << pdir.absoluteFilePath(pdirlist[i]) ;
640  pluginsdirsbaserel << pdirlist[i]+"/";
641  }
642  }
643  pluginsdirs << klfconfig.homeConfigDirPlugins ;
644  pluginsdirsbaserel << "" ;
645 
646  klfDbg( "pluginsdirs="<<pluginsdirs ) ;
647 
648  for (i = 0; i < pluginsdirs.size(); ++i) {
649  if ( ! QFileInfo(pluginsdirs[i]).isDir() )
650  continue;
651 
652  QDir thisplugdir(pluginsdirs[i]);
653  QStringList plugins = thisplugdir.entryList(KLF_DLL_EXT_LIST, QDir::Files);
654  KLFPluginGenericInterface * pluginInstance;
655  for (j = 0; j < plugins.size(); ++j) {
656  QString pluginfname = plugins[j];
657  QString pluginfnamebaserel = pluginsdirsbaserel[i]+plugins[j];
658  bool plugin_already_loaded = false;
659  int k;
660  for (k = 0; k < klf_plugins.size(); ++k) {
661  if (QFileInfo(klf_plugins[k].fname).fileName() == pluginfname) {
662  klfDbg( "Rejecting loading of plugin "<<pluginfname<<" in dir "<<pluginsdirs[i]
663  <<"; already loaded." ) ;
664  plugin_already_loaded = true;
665  break;
666  }
667  }
668  if (plugin_already_loaded)
669  continue;
670  QString pluginpath = thisplugdir.absoluteFilePath(pluginfname);
671  QPluginLoader pluginLoader(pluginpath, app);
672  bool loaded = pluginLoader.load();
673  if (!loaded) {
674  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<". Skipping.");
675  continue;
676  }
677  QObject *pluginInstObject = pluginLoader.instance();
678  if (pluginInstObject == NULL) {
679  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<" (object is NULL). Skipping.");
680  continue;
681  }
682  pluginInstance = qobject_cast<KLFPluginGenericInterface *>(pluginInstObject);
683  if (pluginInstance == NULL) {
684  klfDbg("QPluginLoader failed to load plugin "<<pluginpath<<" (instance is NULL). Skipping.");
685  continue;
686  }
687  // plugin file successfully loaded.
688  QString nm = pluginInstance->pluginName();
689  klfDbg("Successfully loaded plugin library "<<nm<<" ("<<qPrintable(pluginInstance->pluginDescription())
690  <<") from file "<<pluginfnamebaserel);
691 
692  if ( ! klfconfig.Plugins.pluginConfig.contains(nm) ) {
693  // create default plugin configuration if non-existant
695  // ask plugin whether it's supposed to be loaded by default
696  klfconfig.Plugins.pluginConfig[nm]["__loadenabled"] =
697  pluginInstance->pluginDefaultLoadEnable();
698  }
699  bool keepPlugin = true;
700 
701  // make sure this plugin wasn't already loaded (eg. in a different klf-version sub-dir)
702  bool pluginRejected = false;
703  for (k = 0; k < klf_plugins.size(); ++k) {
704  if (klf_plugins[k].name == nm) {
705  klfDbg( "Rejecting loading of plugin "<<nm<<" in "<<pluginfname<<"; already loaded." ) ;
706  pluginLoader.unload();
707  pluginRejected = true;
708  break;
709  }
710  }
711  if (pluginRejected)
712  continue;
713 
714  KLFPluginInfo pluginInfo;
715  pluginInfo.name = nm;
716  pluginInfo.title = pluginInstance->pluginTitle();
717  pluginInfo.description = pluginInstance->pluginDescription();
718  pluginInfo.author = pluginInstance->pluginAuthor();
719  pluginInfo.fname = pluginfnamebaserel;
720  pluginInfo.fpath = pluginpath;
721  pluginInfo.instance = NULL;
722 
723  // if we are configured to load this plugin, load it.
724  keepPlugin = keepPlugin && klfconfig.Plugins.pluginConfig[nm]["__loadenabled"].toBool();
725  klfDbg("got plugin info. keeping plugin? "<<keepPlugin);
726  if ( keepPlugin ) {
729  klfDbg("prepared a configaccess "<<c);
730  pluginInstance->initialize(app, mainWin, c);
731  pluginInfo.instance = pluginInstance;
732  qDebug("\tPlugin %s loaded and initialized.", qPrintable(nm));
733  } else {
734  // if we aren't configured to load it, then discard it, but keep info with NULL instance,
735  // so that user can configure to load or not this plugin in the settings dialog.
736  delete pluginInstance;
737  pluginInfo.instance = NULL;
738  qDebug("\tPlugin %s NOT loaded.", qPrintable(nm));
739  }
740  klf_plugins.push_back(pluginInfo);
741  }
742  }
743  }
744 }
745 
746 
747 
748 
749 // function to set up the Q[Core]Application correctly
751 {
752  a->setApplicationName(QLatin1String("KLatexFormula"));
753  a->setApplicationVersion(QLatin1String(KLF_VERSION_STRING));
754  a->setOrganizationDomain(QLatin1String("klatexformula.org"));
755  a->setOrganizationName(QLatin1String("KLatexFormula"));
756 
757 #ifdef KLF_LIBKLFTOOLS_STATIC
758  Q_INIT_RESOURCE(klftoolsres) ;
759 #endif
760 #ifdef KLF_LIBKLFAPP_STATIC
761  Q_INIT_RESOURCE(klfres) ;
762 #endif
763 
764  // add [share dir]/qt-plugins to library path.
765  // under windows, that is were plugins are packaged with the executable
768 
769  klfDbg("Library paths are:\n"<<qPrintable(QCoreApplication::libraryPaths().join("\n")));
770 
771  qRegisterMetaType< QImage >("QImage");
772  qRegisterMetaType< KLFStyle >();
773  qRegisterMetaTypeStreamOperators< KLFStyle >("KLFStyle");
774  qRegisterMetaType< KLFLibEntry >();
775  qRegisterMetaTypeStreamOperators< KLFLibEntry >("KLFLibEntry");
776  qRegisterMetaType< KLFLibResourceEngine::KLFLibEntryWithId >();
777  qRegisterMetaTypeStreamOperators< KLFLibResourceEngine::KLFLibEntryWithId >
778  /* */ ("KLFLibResourceEngine::KLFLibEntryWithId");
779 
780  // for delayed calls in klflibview.cpp
781  qRegisterMetaType< QItemSelection >("QItemSelection");
782  qRegisterMetaType< QItemSelectionModel::SelectionFlags >("QItemSelectionModel::SelectionFlags");
783 }
784 
785 
786 // OUR MAIN FUNCTION
787 
788 int main(int argc, char **argv)
789 {
790  int k;
791  klfDbgT("$$main()$$") ;
792 
793  qInstallMsgHandler(klf_qt_message);
794 
795  // // DEBUG: command-line arguments
796  // for (int jjj = 0; jjj < argc; ++jjj)
797  // qDebug("arg: %s", argv[jjj]);
798 
799  // signal acting -- catch SIGINT to exit gracefully
800  signal(SIGINT, signal_act);
801  // signal acting -- catch SIGSEGV to attempt graceful exit
802  signal(SIGSEGV, signal_act);
803 
804  klfDbg("about to parse options") ;
805 
806  // parse command-line options
807  main_parse_options(argc, argv);
808 
809  klfDbg("options parsed.") ;
810 
811  // error handling
812  if (opt_error.has_error) {
813  qCritical("Error while parsing command-line arguments.");
814  qCritical("Use --help to display command-line help.");
816  }
817 
818  // redirect debug output if requested
819  if (opt_redirect_debug != NULL) {
820  // force the file name to end in .klfdebug to make sure we don't overwrite an important file
821  char fname[1024];
822  const char * SUFFIX = ".klfdebug";
823  strcpy(fname, opt_redirect_debug);
824  if (strncmp(fname+(strlen(fname)-strlen(SUFFIX)), SUFFIX, strlen(SUFFIX)) != 0) {
825  // fname does not end with SUFFIX
826  strcat(fname, SUFFIX);
827  }
828  // before performing the redirect...
829  klfDbg("Redirecting debug output to file "<<QString::fromLocal8Bit(fname)) ;
830  klf_qt_msg_fp = fopen(fname, "w");
831  KLF_ASSERT_NOT_NULL( klf_qt_msg_fp, "debug output redirection failed." , /* no fail action */; ) ;
832  if (klf_qt_msg_fp != NULL) {
833  fprintf(klf_qt_msg_fp, "\n\n"
834  "-------------------------------------------------\n"
835  " KLATEXFORMULA DEBUG OUTPUT\n"
836  "-------------------------------------------------\n"
837  "Started on %s\n\n",
838  qPrintable(QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate)));
839  }
840  }
841 
842  if ( opt_interactive ) {
843  // save the qt_argv options separately to pass them to daemonized process if needed, before
844  // QApplication modifies the qt_argv array
845  QStringList qtargvlist;
846  for (k = 0; k < qt_argc && qt_argv[k] != NULL; ++k)
847  qtargvlist << QString::fromLocal8Bit(qt_argv[k]);
848 
849 #ifdef Q_WS_MAC
850  // this is needed to avoid having default app font set right after window activation :(
852 #endif
853 
854  // Create the QApplication
856 
857 #ifdef Q_WS_MAC
858  extern void __klf_init_the_macpasteboardmime();
860 #endif
861 
862  // add our default application font(s) ;-)
863  QFileInfoList appFontsInfoList = QDir(":/data/fonts/").entryInfoList(QStringList()<<"*.otf"<<"*.ttf");
864  int k;
865  for (k = 0; k < appFontsInfoList.size(); ++k) {
866  QFontDatabase::addApplicationFont(appFontsInfoList[k].absoluteFilePath());
867  }
868 
869  // main_get_input relies on a Q[Core]Application
871 
872  // see if we have to daemonize
873  if ( opt_daemonize ) {
874  // try to start detached process, with our arguments. This is preferred to feeding D-BUS input
875  // to the new process, since we cannot be sure this system supports D-BUS, and we would have
876  // to wait to see the new process appear, etc. and I really don't see the big advantage over
877  // cmdl options here.
879  QStringList args;
880  args << "-I";
881  if (!latexinput.isNull())
882  args << "--latexinput="+latexinput;
883  if (opt_noeval)
884  args << "--noeval";
885  if (opt_output != NULL)
886  args << "--output="+QString::fromLocal8Bit(opt_output);
887  if (opt_format != NULL)
888  args << "--format="+QString::fromLocal8Bit(opt_format);
889  if (opt_fgcolor != NULL)
890  args << "--fgcolor="+QString::fromLocal8Bit(opt_fgcolor);
891  if (opt_bgcolor != NULL)
892  args << "--bgcolor="+QString::fromLocal8Bit(opt_bgcolor);
893  if (opt_dpi >= 0)
894  args << "--dpi="+QString::number(opt_dpi);
895  if (opt_mathmode != NULL)
896  args << "--mathmode="+QString::fromLocal8Bit(opt_mathmode);
897  if (opt_preamble != NULL)
898  args << "--preamble="+QString::fromLocal8Bit(opt_preamble);
899  if (opt_quiet)
900  args << "--quiet";
901  if (opt_redirect_debug != NULL)
902  args << "--redirect-debug="+QString::fromLocal8Bit(opt_redirect_debug);
903  if (opt_outlinefonts >= 0)
904  args << "--outlinefonts="+QString::fromLatin1(opt_outlinefonts?"TRUE":"FALSE");
905  const struct { char c; int optval; } borderoffsets[] =
906  { {'t', opt_tborderoffset}, {'r', opt_rborderoffset},
907  {'b', opt_bborderoffset}, {'l', opt_lborderoffset},
908  {'\0', -1} };
909  for (k = 0; borderoffsets[k].c != 0; ++k)
910  if (borderoffsets[k].optval != -1)
911  args << (QString::fromLatin1("--")+QLatin1Char(borderoffsets[k].c)+"borderoffset="
912  +QString::number(borderoffsets[k].optval)) ;
913  if (opt_tempdir != NULL)
914  args << "--tempdir="+QString::fromLocal8Bit(opt_tempdir);
915  if (opt_latex != NULL)
916  args << "--latex="+QString::fromLocal8Bit(opt_latex);
917  if (opt_dvips != NULL)
918  args << "--dvips="+QString::fromLocal8Bit(opt_dvips);
919  if (opt_gs != NULL)
920  args << "--gs="+QString::fromLocal8Bit(opt_gs);
921  if (opt_epstopdf != NULL)
922  args << "--epstopdf="+QString::fromLocal8Bit(opt_epstopdf);
923  for (k = 0; k < qtargvlist.size(); ++k)
924  args << "--qtoption="+qtargvlist[k];
925  // add additional args
926  for (k = 0; klf_args[k] != NULL; ++k)
927  args << QString::fromLocal8Bit(klf_args[k]);
928 
929  klfDbg("Prepared deamonized process' command-line: progexe="<<progexe<<"; args="<<args) ;
930  // now launch the klatexformula 'daemon' process
931  qint64 pid;
932  bool result = QProcess::startDetached(progexe, args, QDir::currentPath(), &pid);
933  if (result) { // Success
934  if (!opt_quiet)
935  fprintf(stderr, "%s",
936  qPrintable(QObject::tr("KLatexFormula Daemon Process successfully launched with pid %1\n")
937  .arg(pid)));
938  return 0;
939  }
940  qWarning()<<qPrintable(QObject::tr("Failed to launch daemon process. Not daemonizing."));
941  }
942 
943  main_setup_app(&app);
944 
945 #if defined(KLF_USE_DBUS)
946  // see if an instance of KLatexFormula is running...
947  KLFDBusAppInterface *iface
948  = new KLFDBusAppInterface("org.klatexformula.KLatexFormula", "/MainApplication",
950  if (iface->isValid()) {
951  iface->raiseWindow();
952  // load everything via DBus
953  if ( opt_fgcolor != NULL )
954  iface->setInputData("fgcolor", opt_fgcolor);
955  if ( opt_bgcolor != NULL )
956  iface->setInputData("bgcolor", opt_bgcolor);
957  if ( opt_dpi > 0 )
958  iface->setInputData("dpi", QString::null, opt_dpi);
959  if (opt_mathmode != NULL)
960  iface->setInputData("mathmode", QString::fromLocal8Bit(opt_mathmode));
961  if (opt_preamble != NULL)
962  iface->setInputData("preamble", QString::fromLocal8Bit(opt_preamble));
963  // load latex after preamble, so that the interface doesn't prompt to include missing packages
964  if ( ! latexinput.isNull() )
965  iface->setInputData("latex", latexinput);
966  if (opt_outlinefonts >= 0)
968  if (opt_lborderoffset != -1)
970  if (opt_tborderoffset != -1)
972  if (opt_rborderoffset != -1)
974  if (opt_bborderoffset != -1)
976  if (opt_tempdir != NULL)
978  if (opt_latex != NULL)
980  if (opt_dvips != NULL)
982  if (opt_gs != NULL)
984  if (opt_epstopdf != NULL)
986  // will actually save only if output is non empty.
987  if (!opt_noeval || opt_output) {
989  }
990  // and import KLF files if wanted
991  QStringList flist;
992  for (int k = 0; klf_args[k] != NULL; ++k)
993  flist << QString::fromLocal8Bit(klf_args[k]);
994  iface->openFiles(flist);
995  main_cleanup();
996  return 0;
997  }
998 #endif
999 
1000  if ( ! opt_quiet )
1001  fprintf(stderr, "KLatexFormula Version %s by Philippe Faist (c) 2005-2011\n"
1002  "Licensed under the terms of the GNU Public License GPL\n\n",
1003  KLF_VERSION_STRING);
1004 
1005  klfDbgT("$$About to load config$$");
1006 
1007  // now load default config
1008  klfconfig.loadDefaults(); // must be called before 'readFromConfig'
1011 
1012  klfDbgT("$$About to main_load_extra_resources$$");
1014 
1015  klfDbgT("$$About to main_reload_translations$$");
1017 
1022 
1023  klfDbgT("$$About to create lib factories$$");
1024 
1025  // initialize and register some library resource engine + view factories
1026  (void)new KLFLibBasicWidgetFactory(qApp);
1027  (void)new KLFLibDBEngineFactory(qApp);
1028  (void)new KLFLibLegacyEngineFactory(qApp);
1029  (void)new KLFLibDefaultViewFactory(qApp);
1030 
1031  klfDbgT( "$$START LOADING$$" ) ;
1032 
1033  KLFMainWin mainWin;
1034 
1037 
1038  mainWin.refreshWindowSizes();
1039 
1040  if (!opt_skip_plugins)
1041  main_load_plugins(&app, &mainWin);
1042 
1043  mainWin.show();
1044 
1045  mainWin.startupFinished();
1046 
1047  klfDbgT( "$$END LOADING$$" ) ;
1048 
1049 #if defined(KLF_USE_DBUS)
1050  new KLFDBusAppAdaptor(&app, &mainWin);
1052  dbusconn.registerService("org.klatexformula.KLatexFormula");
1053  dbusconn.registerObject("/MainApplication", &app);
1055  dbusconn.registerObject("/MainWindow/KLFMainWin", &mainWin, QDBusConnection::ExportAllContents
1056  | QDBusConnection::ExportChildObjects);
1057 #endif
1058 
1059  // parse command-line given actions
1060 
1061  // consistency check warning
1062  if (opt_output && latexinput.isEmpty()) {
1063  qWarning("%s", qPrintable(QObject::tr("Can't use --output without any input")));
1064  }
1065 
1066  if ( ! latexinput.isNull() )
1067  mainWin.slotSetLatex(latexinput);
1068 
1069  if ( opt_fgcolor != NULL ) {
1071  }
1072  if ( opt_bgcolor != NULL ) {
1074  }
1075  if ( opt_dpi > 0 ) {
1076  mainWin.slotSetDPI(opt_dpi);
1077  }
1078  if (opt_mathmode != NULL) {
1080  }
1081  if (opt_preamble != NULL) {
1082  qDebug("opt_preamble != NULL, gui mode, preamble=%s", opt_preamble);
1084  }
1085  if (opt_outlinefonts >= 0)
1087  if (opt_lborderoffset != -1)
1089  if (opt_tborderoffset != -1)
1091  if (opt_rborderoffset != -1)
1093  if (opt_bborderoffset != -1)
1095  if (opt_tempdir != NULL)
1097  if (opt_latex != NULL)
1099  if (opt_dvips != NULL)
1101  if (opt_gs != NULL)
1103  if (opt_epstopdf != NULL)
1105 
1106  if (!opt_noeval && opt_output) {
1107  // will actually save only if output is non empty.
1110  }
1111 
1112 
1113  // IMPORT .klf (or other) files passed as arguments
1114  QStringList flist;
1115  for (int k = 0; klf_args[k] != NULL; ++k)
1116  flist << QString::fromLocal8Bit(klf_args[k]);
1117 
1118  QMetaObject::invokeMethod(&mainWin, "openFiles", Qt::QueuedConnection, Q_ARG(QStringList, flist));
1119 
1120  app.setQuitOnLastWindowClosed(false);
1121  int r = app.exec();
1122  main_cleanup();
1123  klfDbg("application has quit; we have cleaned up main(), ready to return. code="<<r) ;
1124  // and exit.
1125  // DO NOT CALL ::exit() as this prevents KLFMainWin's destructor from being called.
1126  // This includes not calling main_exit().
1127  return r;
1128 
1129  } else {
1130  // NON-INTERACTIVE (BATCH MODE, no X11)
1131 
1132  // Create the QCoreApplication
1134 
1135  // main_get_input relies on a Q[Core]Application
1137 
1138  main_setup_app(&app);
1139 
1140  // now load default config
1141  klfconfig.loadDefaults(); // must be called before 'readFromConfig'
1144 
1146 
1148 
1149  // show version number ?
1150  if ( opt_version_requested ) {
1151  /* Remember: the format here should NOT change from one version to another, so that it
1152  * can be parsed eg. by scripts if needed. */
1154  version_string.replace(QLatin1String("%k"), QLatin1String(KLF_VERSION_STRING));
1155  version_string.replace(QLatin1String("%q"), QLatin1String(qVersion()));
1156  version_string.replace(QLatin1String("%%"), QLatin1String("%"));
1157  fprintf(opt_version_fp, "%s\n", qPrintable(version_string));
1158  main_exit(0);
1159  }
1160 
1161  // show program help ?
1162  if ( opt_help_requested ) {
1163  QFile cmdlHelpFile(klfFindTranslatedDataFile(":/data/cmdl-help", ".txt"));
1164  if (!cmdlHelpFile.open(QIODevice::ReadOnly)) {
1165  qWarning()<<KLF_FUNC_NAME<<": Can't access command-line-help file :/data/cmdl-help.txt!";
1166  main_exit(-1);
1167  }
1168  QString helpData = QString::fromUtf8(cmdlHelpFile.readAll());
1169  fprintf(opt_help_fp, "%s", helpData.toLocal8Bit().constData());
1170  main_exit(0);
1171  }
1172 
1173  if ( ! opt_quiet )
1174  fprintf(stderr, "KLatexFormula Version %s by Philippe Faist (c) 2005-2011\n"
1175  "Licensed under the terms of the GNU Public License GPL\n\n",
1176  KLF_VERSION_STRING);
1177 
1178  if ( opt_daemonize ) {
1179  qWarning()<<qPrintable(QObject::tr("The option --daemonize can only be used in interactive mode."));
1180  }
1181 
1182  // warn for ignored arguments
1183  for (int kl = 0; klf_args[kl] != NULL; ++kl)
1184  qWarning()<<qPrintable(QObject::tr("[Non-Interactive Mode] Ignoring additional command-line argument: %1")
1185  .arg(klf_args[kl]));
1186 
1187 
1188  // now process required actions.
1189  KLFBackend::klfInput input;
1190  KLFBackend::klfSettings settings;
1191  KLFBackend::klfOutput klfoutput;
1192 
1193  if ( (opt_input == NULL || !strlen(opt_input)) &&
1194  (opt_latexinput == NULL || !strlen(opt_latexinput)) ) {
1195  // read from stdin by default
1196  opt_input = strdup("-");
1198  }
1199 
1200  input.latex = latexinput;
1201 
1202  if (opt_mathmode != NULL) {
1204  } else {
1205  input.mathmode = "\\[ ... \\]";
1206  }
1207 
1208  if (opt_preamble != NULL) {
1210  } else {
1211  input.preamble = "";
1212  }
1213 
1214  if ( ! opt_fgcolor ) {
1215  opt_fgcolor = strdup("#000000");
1217  }
1218  QColor fgcolor;
1219  fgcolor.setNamedColor(opt_fgcolor);
1220  input.fg_color = fgcolor.rgb();
1221  if ( ! opt_bgcolor ) {
1222  opt_bgcolor = strdup("-");
1224  }
1225  QColor bgcolor;
1226  if (!strcmp(opt_bgcolor, "-"))
1227  bgcolor.setRgb(255, 255, 255, 0); // white transparent
1228  else
1229  bgcolor.setNamedColor(opt_bgcolor);
1230  input.bg_color = bgcolor.rgba();
1231 
1232  input.dpi = (opt_dpi > 0) ? opt_dpi : 1200;
1233 
1234  settings.outlineFonts = true;
1235  if (opt_outlinefonts >= 0)
1236  settings.outlineFonts = (bool)opt_outlinefonts;
1237  settings.lborderoffset = settings.tborderoffset
1238  = settings.rborderoffset = settings.bborderoffset = 1;
1239  if (opt_lborderoffset != -1)
1240  settings.lborderoffset = opt_lborderoffset;
1241  if (opt_tborderoffset != -1)
1242  settings.tborderoffset = opt_tborderoffset;
1243  if (opt_rborderoffset != -1)
1244  settings.rborderoffset = opt_rborderoffset;
1245  if (opt_bborderoffset != -1)
1246  settings.bborderoffset = opt_bborderoffset;
1252 
1253  if (opt_tempdir != NULL)
1255  if (opt_latex != NULL)
1257  if (opt_dvips != NULL)
1259  if (opt_gs != NULL)
1260  settings.gsexec = QString::fromLocal8Bit(opt_gs);
1261  if (opt_epstopdf != NULL)
1263 
1264  klfoutput = KLFBackend::getLatexFormula(input, settings);
1265 
1266  if (klfoutput.status != 0) {
1267  // error occurred
1268 
1269  if ( ! opt_quiet )
1270  fprintf(stderr, "%s\n", klfoutput.errorstr.toLocal8Bit().constData());
1271 
1272  main_exit(klfoutput.status);
1273  }
1274 
1276  QString format = QString::fromLocal8Bit(opt_format).trimmed().toUpper();
1277  main_save(klfoutput, output, format);
1278 
1279  main_exit( 0 );
1280  }
1281 
1282  main_exit( 0 );
1283 }
1284 
1285 
1286 // PARSE COMMAND-LINE OPTIONS
1287 
1288 FILE *main_msg_get_fp_arg(const char *arg)
1289 {
1290  FILE *fp = NULL;
1291  if (arg != NULL) {
1292  if (arg[0] == '&') { // file descriptor number
1293  int fd = atoi(&arg[1]);
1294  if (fd > 0)
1295  fp = fdopen(fd, "a");
1296  if (fd <= 0 || fp == NULL) {
1297  qWarning("Failed to open file descriptor %d.", fd);
1298  return stderr;
1299  }
1300  return fp;
1301  }
1302  if (!strcmp(arg, "-")) { // stdout
1303  return stdout;
1304  }
1305  // file name
1306  fp = fopen(arg, "a");
1307  if (fp == NULL) {
1308  qWarning("Failed to open file `%s' to print help message.", arg);
1309  return stderr;
1310  }
1311  return fp;
1312  }
1313  return stderr;
1314 }
1315 
1316 static bool __klf_parse_bool_arg(const char * arg, bool defaultvalue)
1317 {
1318  if (arg == NULL)
1319  return defaultvalue;
1320 
1321  QRegExp booltruerx = QRegExp("^\\s*on|y(es)?|1|t(rue)?\\s*", Qt::CaseInsensitive);
1322  QRegExp boolfalserx = QRegExp("^\\s*off|n(o)?|0|f(alse)?\\s*", Qt::CaseInsensitive);
1323 
1324  if ( booltruerx.exactMatch(arg) )
1325  return true;
1326  if ( boolfalserx.exactMatch(arg) )
1327  return false;
1328 
1329  qWarning()<<KLF_FUNC_NAME<<": Can't parse boolean argument: "<<QString(arg);
1330  opt_error.has_error = true;
1331  opt_error.retcode = -1;
1332 
1333  return defaultvalue;
1334 }
1335 
1336 void main_parse_options(int argc, char *argv[])
1337 {
1338  // argument processing
1339  int c;
1340  char *arg = NULL;
1341 
1342  // prepare fake command-line options as will be seen by Q[Core]Application
1343  qt_argc = 1;
1344  qt_argv[0] = argv[0];
1345  qt_argv[1] = NULL;
1346 
1347  // build getopt_long short option list
1348  char klfcmdl_optstring[1024];
1349  int k, j;
1350  for (k = 0, j = 0; klfcmdl_optlist[k].name != NULL; ++k) {
1351  if (klfcmdl_optlist[k].val < 127) { // has short option char
1352  klfcmdl_optstring[j++] = klfcmdl_optlist[k].val;
1353  if (klfcmdl_optlist[k].has_arg)
1354  klfcmdl_optstring[j++] = ':';
1355  }
1356  }
1357  klfcmdl_optstring[j] = '\0'; // terminate C string
1358 
1359  // loop for each option
1360  for (;;) {
1361  // get an option from command line
1362  c = getopt_long(argc, argv, klfcmdl_optstring, klfcmdl_optlist, NULL);
1363  if (c == -1)
1364  break;
1365 
1366  arg = NULL;
1367  if (optarg != NULL) {
1368  if (opt_base64arg) {
1369  // this argument is to be decoded from base64
1370  //
1371  // note that here QByteArray can function without a Q[Core]Application
1372  // (officially? this is just suggested by the fact that they mention it
1373  // explicitely for QString:
1374  // http://doc.trolltech.com/4.4/qcoreapplication.html#details)
1375  QByteArray decoded = QByteArray::fromBase64(optarg);
1376  arg = strdup(decoded.constData());
1377  } else {
1378  arg = strdup(optarg);
1379  }
1381  }
1382  // immediately reset this flag, as it applies to the argument of the next option
1383  // only (which we have just retrieved and possibly decoded)
1384  opt_base64arg = false;
1385 
1386  switch (c) {
1387  case OPT_INTERACTIVE:
1388  opt_interactive = 1;
1389  break;
1390  case OPT_INPUT:
1391  if (opt_interactive == -1) opt_interactive = 0;
1392  opt_input = arg;
1393  break;
1394  case OPT_LATEXINPUT:
1395  if (opt_interactive == -1) opt_interactive = 0;
1396  opt_latexinput = arg;
1397  break;
1398  case OPT_PASTE_CLIPBOARD:
1399  if (opt_interactive <= 0) {
1400  if (opt_interactive == 0)
1401  qWarning("%s", qPrintable(QObject::tr("--paste-clipboard requires interactive mode. Switching.")));
1402  opt_interactive = 1;
1403  }
1404  opt_paste = 1;
1405  break;
1406  case OPT_PASTE_SELECTION:
1407  if (opt_interactive <= 0) {
1408  if (opt_interactive == 0)
1409  qWarning("%s", qPrintable(QObject::tr("--paste-selection requires interactive mode. Switching.")));
1410  opt_interactive = 1;
1411  }
1412  opt_paste = 2;
1413  break;
1414  case OPT_NOEVAL:
1415  opt_noeval = true;
1416  break;
1417  case OPT_BASE64ARG:
1418  opt_base64arg = true;
1419  break;
1420  case OPT_OUTPUT:
1421  opt_output = arg;
1422  break;
1423  case OPT_FORMAT:
1424  opt_format = arg;
1425  break;
1426  case OPT_FGCOLOR:
1427  opt_fgcolor = arg;
1428  break;
1429  case OPT_BGCOLOR:
1430  opt_bgcolor = arg;
1431  break;
1432  case OPT_DPI:
1433  opt_dpi = atoi(arg);
1434  break;
1435  case OPT_MATHMODE:
1436  opt_mathmode = arg;
1437  break;
1438  case OPT_PREAMBLE:
1439 #if defined(Q_WS_MAC)
1440  // NASTY WORKAROUND FOR a mysterious -psn_**** option passed to the application
1441  // when opened using the apple 'open' command-line utility, and thus when the
1442  // application is launched via an icon..
1443  if ( !strncmp(arg, "sn_", 3) )
1444  break;
1445 #endif
1446  opt_preamble = arg;
1447  break;
1448  case OPT_QUIET:
1449  opt_quiet = __klf_parse_bool_arg(arg, true);
1450  break;
1451  case OPT_REDIRECT_DEBUG:
1452  opt_redirect_debug = arg;
1453  break;
1454  case OPT_DAEMONIZE:
1455  opt_daemonize = true;
1456  break;
1458  opt_dbus_export_mainwin = true;
1459  break;
1460  case OPT_SKIP_PLUGINS:
1461  // default value 'true' (default value if option is given)
1463  break;
1464  case OPT_OUTLINEFONTS:
1466  break;
1467  case OPT_LBORDEROFFSET:
1468  opt_lborderoffset = atoi(arg);
1469  break;
1470  case OPT_TBORDEROFFSET:
1471  opt_tborderoffset = atoi(arg);
1472  break;
1473  case OPT_RBORDEROFFSET:
1474  opt_rborderoffset = atoi(arg);
1475  break;
1476  case OPT_BBORDEROFFSET:
1477  opt_bborderoffset = atoi(arg);
1478  break;
1479  case OPT_TEMPDIR:
1480  opt_tempdir = arg;
1481  break;
1482  case OPT_LATEX:
1483  opt_latex = arg;
1484  break;
1485  case OPT_DVIPS:
1486  opt_dvips = arg;
1487  break;
1488  case OPT_GS:
1489  opt_gs = arg;
1490  break;
1491  case OPT_EPSTOPDF:
1492  opt_epstopdf = arg;
1493  break;
1494  case OPT_HELP:
1496  opt_help_requested = true;
1497  break;
1498  case OPT_VERSION:
1499  if (arg != NULL) {
1500  char *colonptr = strchr(arg, ':');
1501  if (colonptr != NULL) {
1502  *colonptr = '\0';
1503  opt_version_format = colonptr+1;
1504  }
1505  }
1507  opt_version_requested = true;
1508  break;
1509  case OPT_QTOPT:
1510  qt_argv[qt_argc] = arg;
1511  qt_argc++;
1512  break;
1513  default:
1514  opt_error.has_error = true;
1515  opt_error.retcode = c;
1516  return;
1517  }
1518  }
1519 
1520  qt_argv[qt_argc] = NULL;
1521 
1522  // possibly pointing on NULL if no extra arguments
1523  klf_args = & argv[optind];
1524 
1526  opt_interactive = 0;
1527 
1528  if (opt_interactive == -1) {
1529  // interactive (open GUI) by default
1530  opt_interactive = 1;
1531  }
1532 
1533  // Constistency checks
1534  if (opt_noeval && !opt_interactive) {
1535  qWarning("%s", qPrintable(QObject::tr("--noeval is relevant only in interactive mode.")));
1536  opt_noeval = false;
1537  }
1538  if (opt_noeval && opt_output) {
1539  qWarning("%s", qPrintable(QObject::tr("--noeval may not be used when --output is present.")));
1540  opt_noeval = false;
1541  }
1542  if (opt_interactive && opt_format && !opt_output) {
1543  qWarning("%s", qPrintable(QObject::tr("Ignoring --format without --output.")));
1544  opt_format = NULL;
1545  }
1546 
1547  return;
1548 }
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:788
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:1316
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:1336
#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:1288
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
setDesktopSettingsAware(bool on)
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:403
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)
void dumpDir(const QDir &, int=0)
Definition: main.cpp:474
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:560
bool useSystemAppFont
Definition: klfconfig.h:178
Definition: main.cpp:173
void main_load_extra_resources()
Definition: main.cpp:477
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:345
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:721
absoluteFilePath(const QString &fileName)
char * opt_strdup_free_list[64]
Definition: main.cpp:134
void main_setup_app(QCoreApplication *a)
Definition: main.cpp:750
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:165
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:561
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:566
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.7