home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / lyx_main.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  14KB  |  504 lines

  1. /* This file is part of
  2. * ======================================================
  3. *           LyX, The Document Processor
  4. *      
  5. *        Copyright (C) 1995 Matthias Ettrich
  6. *           Copyright (C) 1995-1998 The LyX Team.
  7. *
  8. *======================================================*/
  9.  
  10. #include <config.h>
  11.  
  12. //     $Id: lyx_main.C,v 1.1.1.1 1998/04/23 16:02:51 larsbj Exp $    
  13. #ifdef __GNUG__
  14. #pragma implementation "lyx_main.h"
  15. #pragma implementation "path.h"
  16. #endif
  17.  
  18. #if !defined(lint) && !defined(WITH_WARNINGS)
  19. static char vcid[] = "$Id: lyx_main.C,v 1.1.1.1 1998/04/23 16:02:51 larsbj Exp $";
  20. #endif /* lint */
  21.  
  22. #include <stdlib.h>
  23. #include <signal.h>
  24.  
  25. #include "version.h"
  26. #include "lyx_main.h"
  27. #include "lyx_gui.h"
  28. #include "lyxrc.h"
  29. #include "path.h"
  30. #include "bufferlist.h"
  31. #include "error.h"
  32. #include "FileInfo.h"
  33. #include "lastfiles.h"
  34. #include "intl.h"
  35. #include "lyxserver.h"
  36. #include "layout.h"
  37.  
  38. extern void LoadLyXFile(LString const &);
  39.  
  40. LString system_lyxdir;
  41. LString build_lyxdir;
  42. LString system_tempdir;
  43. LString user_lyxdir;    // Default $HOME/.lyx
  44.  
  45. // Should this be kept global? Asger says Yes.
  46. Error lyxerr;
  47.  
  48. LastFiles *lastfiles;
  49. LyXRC *lyxrc;
  50.  
  51. // This is the global bufferlist object
  52. BufferList bufferlist;
  53.  
  54. LyXServer *lyxserver = 0;
  55. // this should be static, but I need it in buffer.C
  56. bool finished = false;    // flag, that we are quitting the program
  57.  
  58. // convenient to have it here.
  59. kb_keymap *toplevel_keymap;
  60.  
  61. LyX::LyX(int *argc, char *argv[])
  62. {
  63.     // Prevent crash with --help
  64.     lyxGUI = 0;
  65.     lastfiles = 0;
  66.  
  67.     // Here we need to parse the command line. At least
  68.     // we need to parse for "-dbg" and "-help"
  69.     bool gui = easyParse(argc, argv);
  70.  
  71.     // Global bindings (this must be done as early as possible.) (Lgb)
  72.     toplevel_keymap = new kb_keymap;
  73.  
  74.     lyxerr.debug("Initializing lyxrc");
  75.     lyxrc = new LyXRC;
  76.  
  77.     // Make the GUI object, and let it take care of the
  78.     // command line arguments that concerns it.
  79.     lyxerr.debug("Initializing LyXGUI...");
  80.     lyxGUI = new LyXGUI(this, argc, argv, gui);
  81.     lyxerr.debug("Initializing LyXGUI...done");
  82.  
  83.     // Initialization of LyX (reads lyxrc and more)
  84.     lyxerr.debug("Initializing LyX::init...");
  85.     init(argc, argv);
  86.     lyxerr.debug("Initializing LyX::init...done");
  87.  
  88.     lyxGUI->init();
  89.  
  90.     // Load the files specified in the command line.
  91.     // Now the GUI and LyX have taken care of their arguments, so
  92.     // the only thing left on the command line should be
  93.     // filenames.
  94.     if ((*argc)==2) 
  95.         lyxerr.debug("Opening document...");
  96.     else if ((*argc)>2)
  97.         lyxerr.debug("Opening documents...");
  98.  
  99.     Buffer *last_loaded = NULL;
  100.  
  101.     for (int argi = (*argc) - 1; argi >= 1; argi--) {
  102.         Buffer * loadb = bufferlist.loadLyXFile(argv[argi]);
  103.         if (loadb != 0) {
  104.             last_loaded = loadb;
  105.         }
  106.     }
  107.  
  108.     if (last_loaded != NULL) {
  109.         lyxerr.debug("Yes we loaded some files.");
  110.         lyxGUI->regBuf(last_loaded);
  111.     }
  112.     
  113.     // Let the ball begin...
  114.     lyxGUI->runTime();
  115. }
  116.  
  117.  
  118. // A destructor is always necessary  (asierra-970604)
  119. LyX::~LyX()
  120. {
  121.     if (lastfiles)
  122.         delete lastfiles;
  123.  
  124.     if (lyxGUI)
  125.         delete lyxGUI;
  126. }
  127.  
  128.  
  129. void error_handler(int err_sig);
  130.  
  131. void LyX::init(int */*argc*/, char **argv)
  132. {
  133.     // Install the signal handlers
  134.     struct sigaction act;
  135.     act.sa_handler = error_handler;
  136.     //act.sa_mask = 0;
  137.     act.sa_flags = SA_RESETHAND;
  138.     sigaction(SIGHUP, &act, NULL);
  139.     sigaction(SIGFPE, &act, NULL);
  140.     sigaction(SIGSEGV, &act, NULL);
  141.     sigaction(SIGINT, &act, NULL);
  142.     sigaction(SIGTERM, &act, NULL);
  143.  
  144.     //
  145.     // Determine path of binary
  146.     //
  147.  
  148.     LString binpath = argv[0];
  149.     binpath.subst('\\','/');
  150.     LString binname = OnlyFilename(argv[0]);
  151.     // Sorry for system specific code. (SMiyata)
  152.     if (binname.suffixIs(".exe")) binname.substring(0,binname.length()-5);
  153.     
  154.     binpath = ExpandPath(binpath); // This expands ./ and ~/
  155.     
  156.     if (!AbsolutePath(binpath)) {
  157.         LString binsearchpath = getEnvPath("PATH");
  158.         binsearchpath += ";."; // This will make "src/lyx" work always :-)
  159.         binpath = FileOpenSearch(binsearchpath, argv[0]);
  160.     }
  161.     
  162.     binpath = MakeAbsPath(OnlyPath(binpath));
  163.  
  164.     if (binpath.empty()) {
  165.         lyxerr.print(_("Warning: could not determine path of binary."));
  166.         lyxerr.print(_("If you have problems, try starting LyX with an absolute path."));
  167.     }
  168.     lyxerr.debug("Path of binary: " + binpath);
  169.  
  170.     //
  171.     // Determine system directory.
  172.     //
  173.  
  174.     // Directories are searched in this order:
  175.     // 1) -sysdir command line parameter
  176.     // 2) LYX_DIR_12 environment variable
  177.     // 3) Maybe <path of binary>/TOP_SRCDIR/lib
  178.     // 4) <path of binary>/../share/<name of binary>/
  179.     // 5) hardcoded lyx_dir
  180.     // The directory is checked for the presence of the file
  181.     // "chkconfig.ltx", and if that is present, the directory
  182.     // is accepted as the system directory.
  183.     // If no chkconfig.ltx file is found, a warning is given,
  184.     // and the hardcoded lyx_dir is used.
  185.  
  186.     // If we had a command line switch, system_lyxdir is already set
  187.     LString searchpath = MakeAbsPath(system_lyxdir) + ';';
  188.  
  189.     // LYX_DIR_12 environment variable
  190.     LString lyxdir = getEnvPath("LYX_DIR_12");
  191.     
  192.     if (!lyxdir.empty()) {
  193.         lyxerr.debug("LYX_DIR_12: " + lyxdir, Error::INIT);
  194.         searchpath += lyxdir + ';';
  195.     }
  196.  
  197.     // <path of binary>/TOP_SRCDIR/lib
  198.     build_lyxdir = MakeAbsPath("../lib", binpath);
  199.     if (!FileSearch(build_lyxdir, "lyxrc.defaults").empty()) {
  200.         searchpath += MakeAbsPath(AddPath(TOP_SRCDIR, "lib"),
  201.                       binpath) + ';';
  202.         lyxerr.debug("Checking whether LyX is run in "
  203.                   "place... yes", Error::INIT);
  204.     } else {
  205.         lyxerr.debug("Checking whether LyX is run in place... no",
  206.                   Error::INIT);
  207.         build_lyxdir.erase();
  208.     }
  209.       
  210.     // Path of binary/../share/name of binary/
  211.     searchpath += NormalizePath(binpath + "../share/" + 
  212.               OnlyFilename(binname)) + ';';
  213.  
  214.     // Hardcoded dir
  215.     searchpath += LYX_DIR;
  216.  
  217.     // If debugging, show complete search path
  218.     lyxerr.debug("System directory search path: "+searchpath, Error::INIT);
  219.  
  220.     LString const filename = "chkconfig.ltx";
  221.     LString temp = FileOpenSearch(searchpath, filename, LString());
  222.     system_lyxdir = OnlyPath(temp);
  223.  
  224.     // Reduce "path/../path" stuff out of system directory
  225.     system_lyxdir = NormalizePath(system_lyxdir);
  226.  
  227.     bool path_shown = false;
  228.  
  229.     // Warn if environment variable is set, but unusable
  230.     if (!lyxdir.empty()) {
  231.         if (system_lyxdir != NormalizePath(lyxdir)) {
  232.             lyxerr.print(_("LYX_DIR_12 environment variable no good."));
  233.             lyxerr.print(_("System directory set to: ") 
  234.                      + system_lyxdir);
  235.             path_shown = true;
  236.         }
  237.     }
  238.  
  239.     // Warn the user if we couldn't find "chkconfig.ltx"
  240.     if (system_lyxdir.empty()) {
  241.         lyxerr.print(_("LyX Warning! Couldn't determine system directory."));
  242.         lyxerr.print(_("Try the '-sysdir' command line parameter or"));
  243.         lyxerr.print(_("set the environment variable LYX_DIR_12 to the "
  244.                   "LyX system directory"));
  245.         lyxerr.print(_("containing the file `chkconfig.ltx'."));
  246.         if (!path_shown)
  247.             lyxerr.print(_("Using built-in default ") 
  248.                      + LString(LYX_DIR) + _(" but expect problems."));
  249.         else
  250.             lyxerr.print(_("Expect problems."));
  251.         system_lyxdir = LYX_DIR;
  252.         path_shown = true;
  253.     }
  254.  
  255.     // Report the system directory if debugging is on
  256.     if (!path_shown)
  257.         lyxerr.debug("System directory: '" + system_lyxdir + '\'', 
  258.                   Error::INIT);
  259.  
  260.     //
  261.     // Determine user lyx-dir
  262.     //
  263.     
  264.     user_lyxdir = AddPath(getEnvPath("HOME"), LString(".")+LYX_NAME);
  265.     lyxerr.debug("User LyX directory: '" 
  266.              + user_lyxdir + "'", Error::INIT);
  267.  
  268.     // Check that user LyX directory is ok.
  269.     queryUserLyXDir();
  270.  
  271.     //
  272.     // Load the layouts first
  273.     //
  274.  
  275.     lyxerr.debug("Reading layouts...", Error::INIT);
  276.     LyXSetStyle();
  277.  
  278.     //
  279.     // Shine up lyxrc defaults
  280.     //
  281.  
  282.     // Default template path: system_dir/templates
  283.     if (lyxrc->template_path.empty()){
  284.         lyxrc->template_path = AddPath(system_lyxdir, "templates");
  285.     }
  286.    
  287.     // Default lastfiles file: $HOME/.lyx/lastfiles
  288.     if (lyxrc->lastfiles.empty()){
  289.         lyxrc->lastfiles = AddName(user_lyxdir, "lastfiles");
  290.     }
  291.  
  292.     // Calculate screen dpi as average of x-DPI and y-DPI:
  293.     Screen * scr=(DefaultScreenOfDisplay(fl_get_display()));
  294.     lyxrc->dpi = ((HeightOfScreen(scr)* 25.4 / HeightMMOfScreen(scr)) +
  295.               (WidthOfScreen(scr)* 25.4 / WidthMMOfScreen(scr))) / 2;
  296.     lyxerr.debug(LString("DPI setting detected to be ") + 
  297.               int(lyxrc->dpi+0.5));
  298.  
  299.     //
  300.     // Read configuration files
  301.     //
  302.  
  303.     ReadRcFile("lyxrc.defaults");
  304.     ReadRcFile("lyxrc");
  305.  
  306.     if (lyxerr.debugging(Error::LYXRC)) {
  307.         lyxrc->Print();
  308.     }
  309.  
  310.     // Create temp directory    
  311.     system_tempdir = CreateLyXTmpDir(lyxrc->tempdir_path);
  312.     if (lyxerr.debugging(Error::INIT)) {
  313.         lyxerr.print("LyX tmp dir: `" + system_tempdir + '\'');
  314.     }
  315.  
  316.     // load the lastfiles mini-database
  317.     lyxerr.debug("Reading lastfiles `" + lyxrc->lastfiles + "'...", 
  318.               Error::INIT);
  319.     lastfiles = new LastFiles(lyxrc->lastfiles, 
  320.                   lyxrc->check_lastfiles,
  321.                   lyxrc->num_lastfiles);
  322.  
  323.     // start up the lyxserver. (is this a bit early?) (Lgb)
  324.     // 0.12 this will be way to early, we need the GUI to be initialized
  325.     // first, so move it for now.
  326.     // lyxserver = new LyXServer;
  327. }
  328.  
  329.  
  330. // This one is not allowed to use anything on the main form, since that
  331. // one does not exist yet. (Asger)
  332. void LyX::queryUserLyXDir()
  333. {
  334.     // Does user directory exist?
  335.     FileInfo fileInfo(user_lyxdir);
  336.     if (fileInfo.isOK() && fileInfo.isDir()) {
  337.         return;
  338.     }
  339.  
  340.     // Nope
  341.     if (!AskQuestion(_("You don't have a personal LyX directory."),
  342.              _("It is needed to keep your own configuration."),
  343.              _("Should I try to set it up for you (recommended)?"))) {
  344.         lyxerr.print(_("Running without personal LyX directory."));
  345.         // No, let's use $HOME instead.
  346.         user_lyxdir = getEnvPath("HOME");
  347.         return;
  348.     }
  349.  
  350.     // Tell the user what is going on
  351.     lyxerr.print(_("LyX: Creating directory ") + user_lyxdir + _(" and running configure..."));
  352.  
  353.     // Create directory structure
  354.     if (!createDirectory(user_lyxdir, 0755)) {
  355.         // Failed, let's use $HOME instead.
  356.         user_lyxdir = getEnvPath("HOME");
  357.         lyxerr.print(_("Failed. Will use ") + user_lyxdir + _(" instead."));
  358.         return;
  359.     }
  360.  
  361.     // Run configure in user lyx directory
  362.     //PathPush(user_lyxdir);
  363.     Path p(user_lyxdir);
  364.     system(AddName(system_lyxdir,"configure").c_str());
  365.     //PathPop();
  366.     lyxerr.print(LString("LyX: ") + _("Done!"));
  367. }
  368.  
  369.  
  370. // Read the rc file `name'
  371. void LyX::ReadRcFile(LString const & name)
  372. {
  373.     lyxerr.debug("About to read "+name+"...", Error::INIT);
  374.     
  375.     LString lyxrc_path = LibFileSearch(LString(), name);
  376.     if (!lyxrc_path.empty()){
  377.             lyxerr.debug("Found "+name+" in " + lyxrc_path, Error::INIT);
  378.         if (lyxrc->Read(lyxrc_path) < 0) { 
  379.                 WriteAlert(_("LyX Warning!"), 
  380.                    _("Error while reading ")+lyxrc_path+".",
  381.                    _("Using built-in defaults."));
  382.         }
  383.     } else
  384.           lyxerr.debug("Could not find "+name, Error::INIT);
  385. }
  386.  
  387.  
  388. // Give command line help
  389. void commandLineHelp()
  390. {
  391.     fprintf(stdout,
  392.         _("LyX " LYX_VERSION " of " LYX_RELEASE ".\n"
  393.           "Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
  394.           "Command line switches (case sensitive):\n"
  395.           "   -help           summarize LyX usage\n"
  396.           "   -sysdir x       try to set system directory to x\n"
  397.           "   -width x        set the width of the main window\n"
  398.           "   -height y       set the height of the main window\n"
  399.           "   -xpos x         set the x position of the main window\n"
  400.           "   -ypos y         set the y position of the main window\n"
  401.           "   -dbg feature[,feature]...\n"
  402.           "                   select the features to debug.\n"
  403.           "                   Type `lyx -dbg' to see the list of features\n"
  404.           "   -Reverse        swaps foreground & background colors\n"
  405.           "   -Mono           runs LyX in black and white mode\n"
  406.           "   -FastSelection  use a fast routine for drawing selections\n"
  407.           "Check the LyX man page for more options.\n"));
  408. }
  409.  
  410.  
  411. bool LyX::easyParse(int *argc, char *argv[])
  412. {
  413.     bool gui = true;
  414.     for(int i=1; i < *argc; i++) {
  415.         LString arg = argv[i];
  416.         // Check for -dbg int
  417.         if (arg == "-dbg") {
  418.             if (i+1 < *argc) {
  419.                 lyxerr.setDebugLevel(argv[i+1]);
  420.  
  421.                 // Now, remove these two arguments by shifting
  422.                 // the following two places down.
  423.                 (*argc) -= 2;
  424.                 for (int j=i; j < (*argc); j++)
  425.                     argv[j] = argv[j+2];
  426.                 i--; // After shift, check this number again.
  427.             } else {
  428.                 lyxerr.print(_("List of supported debug flags:\n"));
  429.                 lyxerr.showTags();
  430.                 exit(0);
  431.             }
  432.         } 
  433.         // Check for "-sysdir"
  434.         else if (arg == "-sysdir") {
  435.             if (i+1 < *argc) {
  436.                 system_lyxdir = argv[i+1];
  437.  
  438.                 // Now, remove these two arguments by shifting
  439.                 // the following two places down.
  440.                 (*argc) -= 2;
  441.                 for (int j=i; j < (*argc); j++)
  442.                     argv[j] = argv[j+2];
  443.                 i--; // After shift, check this number again.
  444.             } else
  445.                 lyxerr.print(_("Missing directory for -sysdir switch!"));
  446.         // Check for --help or -help
  447.         } else if (arg == "--help" || arg == "-help") {
  448.             commandLineHelp();
  449.             exit(0);
  450.         } 
  451.         // Check for "-nw": No window
  452.         else if (arg == "-nw") {
  453.             gui = false;
  454.         }
  455.     }
  456.     return gui;
  457. }
  458.  
  459.  
  460. void error_handler(int err_sig)
  461. {
  462.     switch (err_sig) {
  463.     case SIGHUP:
  464.         fprintf(stderr, "\nlyx: SIGHUP signal caught\n");
  465.         break;
  466.     case SIGINT:
  467.         // no comments
  468.         break;
  469.     case SIGFPE:
  470.         fprintf(stderr, "\nlyx: SIGFPE signal caught\n");
  471.         break;
  472.     case SIGSEGV:
  473.         fprintf(stderr, "\nlyx: SIGSEGV signal caught\n");
  474.         fprintf(stderr,
  475.             "Sorry, you have found a bug in LyX."
  476.             " If possible, please read 'Known bugs'\n"
  477.             "under the Help menu and then send us "
  478.             "a full bug report. Thanks!\n");
  479.         break;
  480.     case SIGTERM:
  481.         // no comments
  482.         break;
  483.     }
  484.    
  485.     // Deinstall the signal handlers
  486.     struct sigaction act;
  487.     act.sa_handler = SIG_DFL;
  488.     //act.sa_mask = 0;
  489.     act.sa_flags = 0;
  490.     sigaction(SIGHUP, &act, NULL);
  491.     sigaction(SIGINT, &act, NULL);
  492.     sigaction(SIGFPE, &act, NULL);
  493.     sigaction(SIGSEGV, &act, NULL);
  494.     sigaction(SIGTERM, &act, NULL);
  495.  
  496.     bufferlist.emergencyWriteAll();
  497.  
  498.     lyxerr.print("Bye.");
  499.     if(err_sig!=SIGHUP && (getenv("LYXDEBUG") || err_sig == SIGSEGV))
  500.         abort();
  501.     exit(0);
  502. }
  503.