LCOV - code coverage report
Current view: top level - fontforgeexe - startui.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 54 540 10.0 %
Date: 2017-08-04 Functions: 1 21 4.8 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : 
      28             : #include "ffglib.h"
      29             : 
      30             : #include <fontforge-config.h>
      31             : #include "autosave.h"
      32             : #include "bitmapchar.h"
      33             : #include "clipnoui.h"
      34             : #include "encoding.h"
      35             : #include "fontforgeui.h"
      36             : #include "lookups.h"
      37             : #include "start.h"
      38             : 
      39             : #ifndef _NO_LIBUNICODENAMES
      40             : #include <libunicodenames.h>      /* need to open a database when we start */
      41             : extern uninm_names_db names_db; /* Unicode character names and annotations database */
      42             : extern uninm_blocks_db blocks_db;
      43             : #endif
      44             : #include <gfile.h>
      45             : #include <gresource.h>
      46             : #include <ustring.h>
      47             : #include <ltdl.h>
      48             : #include <time.h>
      49             : #include <sys/time.h>
      50             : #include <locale.h>
      51             : #include <unistd.h>
      52             : #include <dynamic.h>
      53             : #include <stdlib.h>               /* getenv,setenv */
      54             : #include <sys/stat.h>
      55             : #include <sys/types.h>
      56             : #include "../gdraw/hotkeys.h"
      57             : #include "gutils/prefs.h"
      58             : 
      59             : 
      60             : #define GTimer GTimer_GTK
      61             : #include <glib.h>
      62             : #include <glib-object.h>
      63             : #undef GTimer
      64             : 
      65             : #ifdef __Mac
      66             : extern void setup_cocoa_app();
      67             : #endif
      68             : 
      69             : #ifdef _NO_LIBPNG
      70             : #  define PNGLIBNAME    "libpng"
      71             : #else
      72             : #  include <png.h>                /* for version number to find up shared image name */
      73             : #  if !defined(PNG_LIBPNG_VER_MAJOR) || (PNG_LIBPNG_VER_MAJOR==1 && PNG_LIBPNG_VER_MINOR<2)
      74             : #    define PNGLIBNAME  "libpng"
      75             : #  else
      76             : #    define xstr(s) str(s)
      77             : #    define str(s) #s
      78             : #    define PNGLIBNAME  "libpng" xstr(PNG_LIBPNG_VER_MAJOR) xstr(PNG_LIBPNG_VER_MINOR)
      79             : #  endif
      80             : #endif
      81             : #ifdef __Mac
      82             : #  include <carbon.h>
      83             : /* For reasons obscure to me RunApplicationEventLoop is not defined in */
      84             : /*  the mac header files if we are in 64 bit mode. Strangely it seems to */
      85             : /*  be in the libraries and functional */
      86             : /*
      87             :  * It was found in Dec 2014 that using RunApplicationEventLoop() could induce strange
      88             :  * and extremely frustrating pausing issues on osx. The main generic event handling
      89             :  * seems to work just fine, so there doesn't seem to be a need for this specialized
      90             :  * Application Event Loop.
      91             :  * 
      92             :  * See this issue bringing back Breakpad usage and the issues linked in comments 2,3
      93             :  * by adrientetar:
      94             :  * https://github.com/fontforge/fontforge/issues/2120
      95             :  */
      96             : //#  if __LP64__
      97             : //extern void RunApplicationEventLoop(void);
      98             : //#  endif
      99             : #endif
     100             : 
     101             : #if defined(__MINGW32__)
     102             : #include <windows.h>
     103             : #define sleep(n) Sleep(1000 * (n))
     104             : #endif
     105             : 
     106             : #include "collabclientui.h"
     107             : #include "scripting.h"
     108             : 
     109             : extern int AutoSaveFrequency;
     110             : int splash = 1;
     111             : static int localsplash;
     112             : static int unique = 0;
     113             : 
     114             : /**
     115             :  * In osx versions prior to 10.9.x a special -psn_ flag was supplied
     116             :  * when fontforge was run by osx in some cases. For opening an sfd
     117             :  * file from finder we need to register the openWith event in order to
     118             :  * get the name of the file to open. So it makes sense to always
     119             :  * register for Apple events on OSX so that we can get those file
     120             :  * names as they come through.
     121             :  */
     122             : #if defined(__Mac)
     123             :     static int listen_to_apple_events = true; // This was once true, but Apple broke it.
     124             : #else
     125             :     static int listen_to_apple_events = false;
     126             : #endif
     127             : static bool ProcessPythonInitFiles = 1;
     128             : 
     129           0 : static void _dousage(void) {
     130           0 :     printf( "fontforge [options] [fontfiles]\n" );
     131           0 :     printf( "\t-new\t\t\t (creates a new font)\n" );
     132           0 :     printf( "\t-last\t\t\t (loads the last sfd file closed)\n" );
     133             : #if HANYANG
     134             :     printf( "\t-newkorean\t\t (creates a new korean font)\n" );
     135             : #endif
     136           0 :     printf( "\t-recover none|auto|inquire|clean (control error recovery)\n" );
     137           0 :     printf( "\t-allglyphs\t\t (load all glyphs in the 'glyf' table\n\t\t\t of a truetype collection)\n" );
     138           0 :     printf( "\t-nosplash\t\t (no splash screen)\n" );
     139           0 :     printf( "\t-quiet\t\t\t (don't print non-essential information to stderr)\n" );
     140           0 :     printf( "\t-unique\t\t\t (if a fontforge is already running open\n\t\t\t all arguments in it and have this process exit)\n" );
     141           0 :     printf( "\t-display display-name\t (sets the X display)\n" );
     142           0 :     printf( "\t-depth val\t\t (sets the display depth if possible)\n" );
     143           0 :     printf( "\t-vc val\t\t\t (sets the visual class if possible)\n" );
     144           0 :     printf( "\t-cmap current|copy|private\t (sets the type of colormap)\n" );
     145           0 :     printf( "\t-dontopenxdevices\t (in case that fails)\n" );
     146           0 :     printf( "\t-sync\t\t\t (syncs the display, debugging)\n" );
     147           0 :     printf( "\t-keyboard ibm|mac|sun|ppc  (generates appropriate hotkeys in menus)\n" );
     148             : #if MyMemory
     149             :     printf( "\t-memory\t\t\t (turns on memory checks, debugging)\n" );
     150             : #endif
     151             : #ifndef _NO_LIBCAIRO
     152           0 :     printf( "\t-usecairo=yes|no  Use (or not) the cairo library for drawing\n" );
     153             : #endif
     154           0 :     printf( "\t-help\t\t\t (displays this message, and exits)\n" );
     155           0 :     printf( "\t-docs\t\t\t (displays this message, invokes a browser)\n\t\t\t\t (Using the BROWSER environment variable)\n" );
     156           0 :     printf( "\t-version\t\t (prints the version of fontforge and exits)\n" );
     157           0 :     printf( "\t-library-status\t (prints information about optional libraries\n\t\t\t\t and exits)\n" );
     158             : #ifndef _NO_PYTHON
     159           0 :     printf( "\t-lang=py\t\t use python for scripts (may precede -script)\n" );
     160             : #endif
     161             : #ifndef _NO_FFSCRIPT
     162           0 :     printf( "\t-lang=ff\t\t use fontforge's legacy scripting language\n" );
     163             : #endif
     164           0 :     printf( "\t-script scriptfile\t (executes scriptfile)\n" );
     165           0 :     printf( "\t\tmust be the first option (or follow -lang).\n" );
     166           0 :     printf( "\t\tAll others passed to scriptfile.\n" );
     167           0 :     printf( "\t-dry scriptfile\t\t (syntax checks scriptfile)\n" );
     168           0 :     printf( "\t\tmust be the first option. All others passed to scriptfile.\n" );
     169           0 :     printf( "\t\tOnly for fontforge's own scripting language, not python.\n" );
     170           0 :     printf( "\t-c script-string\t (executes argument as scripting cmds)\n" );
     171           0 :     printf( "\t\tmust be the first option. All others passed to the script.\n" );
     172           0 :     printf( "\n" );
     173           0 :     printf( "FontForge will read postscript (pfa, pfb, ps, cid), opentype (otf),\n" );
     174           0 :     printf( "\ttruetype (ttf,ttc), macintosh resource fonts (dfont,bin,hqx),\n" );
     175           0 :     printf( "\tand bdf and pcf fonts. It will also read its own format --\n" );
     176           0 :     printf( "\tsfd files.\n" );
     177           0 :     printf( "If no fontfiles are specified (and -new is not either and there's nothing\n" );
     178           0 :     printf( "\tto recover) then fontforge will produce an open font dlg.\n" );
     179           0 :     printf( "If a scriptfile is specified then FontForge will not open the X display\n" );
     180           0 :     printf( "\tnor will it process any additional arguments. It will execute the\n" );
     181           0 :     printf( "\tscriptfile and give it any remaining arguments\n" );
     182           0 :     printf( "If the first argument is an executable filename, and that file's first\n" );
     183           0 :     printf( "\tline contains \"fontforge\" then it will be treated as a scriptfile.\n\n" );
     184           0 :     printf( "For more information see:\n\thttp://fontforge.sourceforge.net/\n" );
     185           0 :     printf( "Send bug reports to:\tfontforge-devel@lists.sourceforge.net\n" );
     186           0 : }
     187             : 
     188           0 : static void dousage(void) {
     189           0 :     _dousage();
     190           0 : exit(0);
     191             : }
     192             : 
     193           0 : static void dohelp(void) {
     194           0 :     _dousage();
     195           0 :     help("overview.html");
     196           0 : exit(0);
     197             : }
     198             : 
     199             : struct delayed_event {
     200             :     void *data;
     201             :     void (*func)(void *);
     202             : };
     203             : 
     204           0 : static void BuildCharHook(GDisplay *gd) {
     205           0 :     GWidgetCreateInsChar();
     206           0 : }
     207             : 
     208           0 : static void InsCharHook(GDisplay *gd,unichar_t ch) {
     209           0 :     GInsCharSetChar(ch);
     210           0 : }
     211             : 
     212             : extern GImage splashimage;
     213             : static GWindow splashw;
     214             : static GTimer *autosave_timer, *splasht;
     215             : static GFont *splash_font, *splash_italic;
     216             : static int as,fh, linecnt;
     217             : static unichar_t msg[470];
     218             : static unichar_t *lines[30], *is, *ie;
     219             : 
     220           0 : void ShowAboutScreen(void) {
     221             :     static int first=1;
     222             : 
     223           0 :     if ( first ) {
     224           0 :         GDrawResize(splashw,splashimage.u.image->width,splashimage.u.image->height+linecnt*fh);
     225           0 :         first = false;
     226             :     }
     227           0 :     if ( splasht!=NULL )
     228           0 :         GDrawCancelTimer(splasht);
     229           0 :     splasht=NULL;
     230           0 :     GDrawSetVisible(splashw,true);
     231           0 : }
     232             : 
     233           0 : static void SplashLayout() {
     234             :     unichar_t *start, *pt, *lastspace;
     235             :     extern const char *source_modtime_str;
     236             :     extern const char *source_version_str;
     237             : 
     238           0 :     uc_strcpy(msg, "When my father finished his book on Renaissance printing (The Craft of Printing and the Publication of Shakespeare's Works) he told me that I would have to write the chapter on computer typography. This is my attempt to do so.");
     239             : 
     240           0 :     GDrawSetFont(splashw,splash_font);
     241           0 :     linecnt = 0;
     242           0 :     lines[linecnt++] = msg-1;
     243           0 :     for ( start = msg; *start!='\0'; start = pt ) {
     244           0 :         lastspace = NULL;
     245           0 :         for ( pt=start; ; ++pt ) {
     246           0 :             if ( *pt==' ' || *pt=='\0' ) {
     247           0 :                 if ( GDrawGetTextWidth(splashw,start,pt-start)<splashimage.u.image->width-10 )
     248           0 :                     lastspace = pt;
     249             :                 else
     250           0 :         break;
     251           0 :                 if ( *pt=='\0' )
     252           0 :         break;
     253             :             }
     254           0 :         }
     255           0 :         if ( lastspace!=NULL )
     256           0 :             pt = lastspace;
     257           0 :         lines[linecnt++] = pt;
     258           0 :         if ( *pt ) ++pt;
     259             :     }
     260           0 :     uc_strcpy(pt, " FontForge used to be named PfaEdit.");
     261             : 
     262           0 :     pt += u_strlen(pt);
     263           0 :     lines[linecnt++] = pt;
     264           0 :     uc_strcpy(pt,"  git hash: ");
     265           0 :     pt += u_strlen(pt);
     266           0 :     lines[linecnt++] = pt;
     267           0 :     uc_strcat(pt, " ");
     268           0 :     uc_strcat(pt, FONTFORGE_GIT_VERSION);
     269             : 
     270           0 :     pt += u_strlen(pt);
     271           0 :     lines[linecnt++] = pt;
     272           0 :     uc_strcpy(pt,"  Version: ");
     273           0 :     uc_strcat(pt,FONTFORGE_MODTIME_STR);
     274             : 
     275           0 :     pt += u_strlen(pt);
     276           0 :     lines[linecnt++] = pt;
     277           0 :     uc_strcat(pt,"           (");
     278           0 :     uc_strcat(pt,FONTFORGE_MODTIME_STR);
     279           0 :     uc_strcat(pt,"-ML");
     280             : #ifdef FREETYPE_HAS_DEBUGGER
     281             :     uc_strcat(pt,"-TtfDb");
     282             : #endif
     283             : #ifdef _NO_PYTHON
     284             :     uc_strcat(pt,"-NoPython");
     285             : #endif
     286             : #ifdef FONTFORGE_CONFIG_USE_DOUBLE
     287           0 :     uc_strcat(pt,"-D");
     288             : #endif
     289           0 :     uc_strcat(pt,")");
     290           0 :     pt += u_strlen(pt);
     291           0 :     lines[linecnt++] = pt;
     292           0 :     uc_strcpy(pt,"  Lib Version: ");
     293           0 :     uc_strcat(pt,FONTFORGE_MODTIME_STR);
     294           0 :     lines[linecnt++] = pt+u_strlen(pt);
     295           0 :     lines[linecnt] = NULL;
     296           0 :     is = u_strchr(msg,'(');
     297           0 :     ie = u_strchr(msg,')');
     298           0 : }
     299             : 
     300           0 : void DelayEvent(void (*func)(void *), void *data) {
     301           0 :     struct delayed_event *info = calloc(1,sizeof(struct delayed_event));
     302             : 
     303           0 :     info->data = data;
     304           0 :     info->func = func;
     305           0 :     GDrawRequestTimer(splashw,100,0,info);
     306           0 : }
     307             : 
     308           0 : static void DoDelayedEvents(GEvent *event) {
     309           0 :     GTimer *t = event->u.timer.timer;
     310           0 :     struct delayed_event *info = (struct delayed_event *) (event->u.timer.userdata);
     311             : 
     312           0 :     if ( info!=NULL ) {
     313           0 :         (info->func)(info->data);
     314           0 :         free(info);
     315             :     }
     316           0 :     GDrawCancelTimer(t);
     317           0 : }
     318             : 
     319             : struct argsstruct {
     320             :     int next;
     321             :     int argc;
     322             :     char **argv;
     323             :     int any;
     324             : };
     325             : 
     326           0 : static void SendNextArg(struct argsstruct *args) {
     327             :     int i;
     328             :     char *msg;
     329             :     static GTimer *timeout;
     330             : 
     331           0 :     if ( timeout!=NULL ) {
     332           0 :         GDrawCancelTimer(timeout);
     333           0 :         timeout = NULL;
     334             :     }
     335             : 
     336           0 :     for ( i=args->next; i<args->argc; ++i ) {
     337           0 :         if ( *args->argv[i]!='-' ||
     338           0 :                 strcmp(args->argv[i],"-quit")==0 || strcmp(args->argv[i],"--quit")==0 ||
     339           0 :                 strcmp(args->argv[i],"-new")==0 || strcmp(args->argv[i],"--new")==0 )
     340             :     break;
     341             :     }
     342           0 :     if ( i>=args->argc ) {
     343           0 :         if ( args->any )
     344           0 : exit(0);                /* Sent everything */
     345           0 :         msg = "-open";
     346             :     } else
     347           0 :         msg = args->argv[i];
     348           0 :     args->next = i+1;
     349           0 :     args->any  = true;
     350             : 
     351           0 :     GDrawGrabSelection(splashw,sn_user1);
     352           0 :     GDrawAddSelectionType(splashw,sn_user1,"STRING",
     353           0 :             copy(msg),strlen(msg),1,
     354             :             NULL,NULL);
     355             : 
     356             :         /* If we just sent the other fontforge a request to die, it will never*/
     357             :         /*  take the selection back. So we should just die quietly */
     358             :         /*  But we can't die instantly, or it will never get our death threat */
     359             :         /*  (it won't have a chance to ask us for the selection if we're dead)*/
     360           0 :     timeout = GDrawRequestTimer(splashw,1000,0,NULL);
     361           0 : }
     362             : 
     363             : /* When we want to send filenames to another running fontforge we want a */
     364             : /*  different event handler. We won't have a splash window in that case, */
     365             : /*  just an invisible utility window on which we perform a little selection */
     366             : /*  dance */
     367           0 : static int request_e_h(GWindow gw, GEvent *event) {
     368             : 
     369           0 :     if ( event->type == et_selclear ) {
     370           0 :         SendNextArg( GDrawGetUserData(gw));
     371           0 :     } else if ( event->type == et_timer )
     372           0 : exit( 0 );
     373             : 
     374           0 : return( true );
     375             : }
     376             : 
     377           0 : static void PingOtherFontForge(int argc, char **argv) {
     378             :     struct argsstruct args;
     379             : 
     380           0 :     args.next = 1;
     381           0 :     args.argc = argc;
     382           0 :     args.argv = argv;
     383           0 :     args.any  = false;
     384           0 :     GDrawSetUserData(splashw,&args);
     385           0 :     SendNextArg(&args);
     386           0 :     GDrawEventLoop(NULL);
     387           0 : exit( 0 );              /* But the event loop should never return */
     388             : }
     389             : 
     390           0 : static void start_splash_screen(void){
     391           0 :     GDrawSetVisible(splashw,true);
     392           0 :     GDrawSync(NULL);
     393           0 :     GDrawProcessPendingEvents(NULL);
     394           0 :     GDrawProcessPendingEvents(NULL);
     395           0 :     splasht = GDrawRequestTimer(splashw,1000,1000,NULL);
     396             : 
     397           0 :     localsplash = false;
     398           0 : }
     399             : 
     400             : #if defined(__Mac)
     401             : static FILE *logfile;
     402             : 
     403             : /* These are the four apple events to which we currently respond */
     404             : static pascal OSErr OpenApplicationAE( const AppleEvent * theAppleEvent,
     405             :         AppleEvent * reply, SInt32 handlerRefcon) {
     406             :  fprintf( logfile, "OPENAPP event received.\n" ); fflush( logfile );
     407             :     if ( localsplash )
     408             :         start_splash_screen();
     409             :     system( "DYLD_LIBRARY_PATH=\"\"; osascript -e 'tell application \"X11\" to activate'" );
     410             :     if ( fv_list==NULL )
     411             :         _FVMenuOpen(NULL);
     412             :  fprintf( logfile, " event processed %d.\n", noErr ); fflush( logfile );
     413             : return( noErr );
     414             : }
     415             : 
     416             : static pascal OSErr ReopenApplicationAE( const AppleEvent * theAppleEvent,
     417             :         AppleEvent * reply, SInt32 handlerRefcon) {
     418             :  fprintf( logfile, "ReOPEN event received.\n" ); fflush( logfile );
     419             :     if ( localsplash )
     420             :         start_splash_screen();
     421             :     system( "DYLD_LIBRARY_PATH=\"\"; osascript -e 'tell application \"X11\" to activate'" );
     422             :     if ( fv_list==NULL )
     423             :         _FVMenuOpen(NULL);
     424             :  fprintf( logfile, " event processed %d.\n", noErr ); fflush( logfile );
     425             : return( noErr );
     426             : }
     427             : 
     428             : static pascal OSErr ShowPreferencesAE( const AppleEvent * theAppleEvent,
     429             :         AppleEvent * reply, SInt32 handlerRefcon) {
     430             :  fprintf( logfile, "PREFS event received.\n" ); fflush( logfile );
     431             :     if ( localsplash )
     432             :         start_splash_screen();
     433             :     system( "DYLD_LIBRARY_PATH=\"\"; osascript -e 'tell application \"X11\" to activate'" );
     434             :     DoPrefs();
     435             :  fprintf( logfile, " event processed %d.\n", noErr ); fflush( logfile );
     436             : return( noErr );
     437             : }
     438             : 
     439             : static pascal OSErr OpenDocumentsAE( const AppleEvent * theAppleEvent,
     440             :         AppleEvent * reply, SInt32 handlerRefcon) {
     441             :     AEDescList  docList;
     442             :     FSRef       theFSRef;
     443             :     long        index;
     444             :     long        count = 0;
     445             :     OSErr       err;
     446             :     char        buffer[2048];
     447             : 
     448             :  fprintf( logfile, "OPEN event received.\n" ); fflush( logfile );
     449             :     if ( localsplash )
     450             :         start_splash_screen();
     451             : 
     452             :     err = AEGetParamDesc(theAppleEvent, keyDirectObject,
     453             :                          typeAEList, &docList);
     454             :     err = AECountItems(&docList, &count);
     455             :     for(index = 1; index <= count; index++) {
     456             :         err = AEGetNthPtr(&docList, index, typeFSRef,
     457             :                         NULL, NULL, &theFSRef,
     458             :                         sizeof(theFSRef), NULL);// 4
     459             :         err = FSRefMakePath(&theFSRef,(unsigned char *) buffer,sizeof(buffer));
     460             :         ViewPostScriptFont(buffer,0);
     461             :  fprintf( logfile, " file: %s\n", buffer );
     462             :     }
     463             :     system( "DYLD_LIBRARY_PATH=\"\"; osascript -e 'tell application \"X11\" to activate'" );
     464             :     AEDisposeDesc(&docList);
     465             :  fprintf( logfile, " event processed %d.\n", err ); fflush( logfile );
     466             : 
     467             : return( err );
     468             : }
     469             : 
     470             : static void AttachErrorCode(AppleEvent *event,OSStatus err) {
     471             :     OSStatus returnVal;
     472             : 
     473             :     if ( event==NULL )
     474             : return;
     475             : 
     476             :     if (event->descriptorType != typeNull) {
     477             :         /* Check there isn't already an error attached */
     478             :         returnVal = AESizeOfParam(event, keyErrorNumber, NULL, NULL);
     479             :         if (returnVal != noErr ) {      /* Add success if no previous error */
     480             :             AEPutParamPtr(event, keyErrorNumber,
     481             :                         typeSInt32, &err, sizeof(err));
     482             :         }
     483             :     }
     484             : }
     485             : 
     486             : static AppleEvent *quit_event = NULL;
     487             : static void we_are_dead(void) {
     488             :     AttachErrorCode(quit_event,noErr);
     489             :     /* Send the reply (I hope) */
     490             :     AESendMessage(quit_event,NULL, kAENoReply, kAEDefaultTimeout);
     491             :     AEDisposeDesc(quit_event);
     492             :     /* fall off the end of the world and die */
     493             :  fprintf( logfile, " event succeded.\n"); fflush( logfile );
     494             : }
     495             : 
     496             : static pascal OSErr QuitApplicationAE( const AppleEvent * theAppleEvent,
     497             :         AppleEvent * reply, SInt32 handlerRefcon) {
     498             :     static int first_time = true;
     499             : 
     500             :  fprintf( logfile, "QUIT event received.\n" ); fflush( logfile );
     501             :     quit_event = reply;
     502             :     if ( first_time ) {
     503             :         atexit( we_are_dead );
     504             :         first_time = false;
     505             :     }
     506             :     MenuExit(NULL,NULL,NULL);
     507             :     /* if we get here, they canceled the quit, so we return a failure */
     508             :     quit_event = NULL;
     509             :  fprintf( logfile, " event failed %d.\n", errAEEventFailed ); fflush( logfile );
     510             : return(errAEEventFailed);
     511             : }
     512             : 
     513             : /* Install event handlers for the Apple Events we care about */
     514             : static  OSErr install_apple_event_handlers(void) {
     515             :     OSErr       err;
     516             : 
     517             :     err     = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
     518             :                 NewAEEventHandlerUPP(OpenApplicationAE), 0, false);
     519             :     require_noerr(err, CantInstallAppleEventHandler);
     520             : 
     521             :     err     = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication,
     522             :                 NewAEEventHandlerUPP(ReopenApplicationAE), 0, false);
     523             :     require_noerr(err, CantInstallAppleEventHandler);
     524             : 
     525             :     err     = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
     526             :                 NewAEEventHandlerUPP(OpenDocumentsAE), 0, false);
     527             :     require_noerr(err, CantInstallAppleEventHandler);
     528             : 
     529             :     err     = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
     530             :                 NewAEEventHandlerUPP(QuitApplicationAE), 0, false);
     531             :     require_noerr(err, CantInstallAppleEventHandler);
     532             : 
     533             :     err     = AEInstallEventHandler(kCoreEventClass, kAEShowPreferences,
     534             :                 NewAEEventHandlerUPP(ShowPreferencesAE), 0, false);
     535             :     require_noerr(err, CantInstallAppleEventHandler);
     536             : 
     537             :  /* some debugging code, for now */
     538             :  if ( getenv("HOME")!=NULL ) {
     539             :   char buffer[1024];
     540             :   sprintf( buffer, "%s/.FontForge-LogFile.txt", getenv("HOME"));
     541             :   logfile = fopen("/tmp/LogFile.txt","w");
     542             :  }
     543             :  if ( logfile==NULL )
     544             :   logfile = stderr;
     545             : 
     546             : CantInstallAppleEventHandler:
     547             :     return err;
     548             : 
     549             : }
     550             : 
     551             : static pascal void DoRealStuff(EventLoopTimerRef timer,void *ignored_data) {
     552             :     GDrawProcessPendingEvents(NULL);
     553             :     MacServiceReadFDs();
     554             : }
     555             : 
     556             : static void install_mac_timer(void) {
     557             :     EventLoopTimerRef timer;
     558             : 
     559             :     InstallEventLoopTimer(GetMainEventLoop(),
     560             :             .001*kEventDurationSecond,.001*kEventDurationSecond,
     561             :             NewEventLoopTimerUPP(DoRealStuff), NULL,
     562             :             &timer);
     563             : }
     564             : #endif
     565             : 
     566           0 : static int splash_e_h(GWindow gw, GEvent *event) {
     567             :     static int splash_cnt;
     568             :     GRect old;
     569             :     int i, y, x;
     570             :     static char *foolishness[] = {
     571             : /* GT: These strings are for fun. If they are offensive or incomprehensible */
     572             : /* GT: simply translate them as something dull like: "FontForge" */
     573             : /* GT: This is a spoof of political slogans, designed to point out how foolish they are */
     574             :             N_("A free press discriminates\nagainst the illiterate."),
     575             :             N_("A free press discriminates\nagainst the illiterate."),
     576             : /* GT: This is a pun on the old latin drinking song "Gaudeamus igature!" */
     577             :             N_("Gaudeamus Ligature!"),
     578             :             N_("Gaudeamus Ligature!"),
     579             : /* GT: Spoof on the bible */
     580             :             N_("In the beginning was the letter..."),
     581             : /* GT: Some wit at MIT came up with this ("ontology recapitulates phylogony" is the original) */
     582             :             N_("fontology recapitulates file-ogeny")
     583             :     };
     584             : 
     585           0 :     switch ( event->type ) {
     586             :       case et_create:
     587           0 :         GDrawGrabSelection(gw,sn_user1);
     588           0 :       break;
     589             :       case et_expose:
     590           0 :         GDrawPushClip(gw,&event->u.expose.rect,&old);
     591           0 :         GDrawDrawImage(gw,&splashimage,NULL,0,0);
     592           0 :         GDrawSetFont(gw,splash_font);
     593           0 :         y = splashimage.u.image->height + as + fh/2;
     594           0 :         for ( i=1; i<linecnt; ++i ) {
     595           0 :             if ( is>=lines[i-1]+1 && is<lines[i] ) {
     596           0 :                 x = 8+GDrawDrawText(gw,8,y,lines[i-1]+1,is-lines[i-1]-1,0x000000);
     597           0 :                 GDrawSetFont(gw,splash_italic);
     598           0 :                 GDrawDrawText(gw,x,y,is,lines[i]-is,0x000000);
     599           0 :             } else if ( ie>=lines[i-1]+1 && ie<lines[i] ) {
     600           0 :                 x = 8+GDrawDrawText(gw,8,y,lines[i-1]+1,ie-lines[i-1]-1,0x000000);
     601           0 :                 GDrawSetFont(gw,splash_font);
     602           0 :                 GDrawDrawText(gw,x,y,ie,lines[i]-ie,0x000000);
     603             :             } else
     604           0 :                 GDrawDrawText(gw,8,y,lines[i-1]+1,lines[i]-lines[i-1]-1,0x000000);
     605           0 :             y += fh;
     606             :         }
     607           0 :         GDrawPopClip(gw,&old);
     608           0 :       break;
     609             :       case et_map:
     610           0 :         splash_cnt = 0;
     611           0 :       break;
     612             :       case et_timer:
     613           0 :         if ( event->u.timer.timer==autosave_timer ) {
     614           0 :             DoAutoSaves();
     615           0 :         } else if ( event->u.timer.timer==splasht ) {
     616           0 :             if ( ++splash_cnt==1 )
     617           0 :                 GDrawResize(gw,splashimage.u.image->width,splashimage.u.image->height-30);
     618           0 :             else if ( splash_cnt==2 )
     619           0 :                 GDrawResize(gw,splashimage.u.image->width,splashimage.u.image->height);
     620           0 :             else if ( splash_cnt>=7 ) {
     621           0 :                 GGadgetEndPopup();
     622           0 :                 GDrawSetVisible(gw,false);
     623           0 :                 GDrawCancelTimer(splasht);
     624           0 :                 splasht = NULL;
     625             :             }
     626             :         } else {
     627           0 :             DoDelayedEvents(event);
     628             :         }
     629           0 :       break;
     630             :       case et_char:
     631             :       case et_mousedown:
     632             :       case et_close:
     633           0 :         GGadgetEndPopup();
     634           0 :         GDrawSetVisible(gw,false);
     635           0 :       break;
     636             :       case et_mousemove:
     637           0 :         GGadgetPreparePopup8(gw,_(foolishness[rand()%(sizeof(foolishness)/sizeof(foolishness[0]))]) );
     638           0 :       break;
     639             :       case et_selclear:
     640             :         /* If this happens, it means someone wants to send us a message with a*/
     641             :         /*  filename to open. So we need to ask for it, process it, and then  */
     642             :         /*  take the selection back again */
     643           0 :         if ( event->u.selclear.sel == sn_user1 ) {
     644             :             int len;
     645             :             char *arg;
     646           0 :             arg = GDrawRequestSelection(splashw,sn_user1,"STRING",&len);
     647           0 :             if ( arg==NULL )
     648           0 : return( true );
     649           0 :             if ( strcmp(arg,"-new")==0 || strcmp(arg,"--new")==0 )
     650           0 :                 FontNew();
     651           0 :             else if ( strcmp(arg,"-open")==0 || strcmp(arg,"--open")==0 )
     652           0 :                 _FVMenuOpen(NULL);
     653           0 :             else if ( strcmp(arg,"-quit")==0 || strcmp(arg,"--quit")==0 )
     654           0 :                 MenuExit(NULL,NULL,NULL);
     655             :             else
     656           0 :                 ViewPostScriptFont(arg,0);
     657           0 :             free(arg);
     658           0 :             GDrawGrabSelection(splashw,sn_user1);
     659             :         }
     660           0 :       break;
     661             :       case et_destroy:
     662           0 :         IError("Who killed the splash screen?");
     663           0 :       break;
     664             :     }
     665           0 : return( true );
     666             : }
     667             : 
     668           0 : static void  AddR(char *program_name, char *window_name, char *cmndline_val) {
     669             : /* Add this command line value to this GUI resource.                    */
     670             : /* These are the command line options expected when using this routine: */
     671             : /*      -depth, -vc,-cmap or -colormap,-dontopenxdevices, -keyboard     */
     672             :     char *full;
     673           0 :     if ((full = malloc(strlen(window_name)+strlen(cmndline_val)+4))!=NULL) {
     674           0 :         strcpy(full,window_name);
     675           0 :         strcat(full,": ");
     676           0 :         strcat(full,cmndline_val);
     677           0 :         GResourceAddResourceString(full,program_name);
     678           0 :         free(full);
     679             :     }
     680           0 : }
     681             : 
     682           0 : static int ReopenLastFonts(void) {
     683             :     char buffer[1024];
     684           0 :     char *ffdir = getFontForgeUserDir(Config);
     685             :     FILE *old;
     686           0 :     int any = 0;
     687             : 
     688           0 :     if ( ffdir==NULL ) return false;
     689             : 
     690           0 :     sprintf( buffer, "%s/FontsOpenAtLastQuit", ffdir );
     691           0 :     old = fopen(buffer,"r");
     692           0 :     if ( old==NULL ) {
     693           0 :         free(ffdir);
     694           0 :         return false;
     695             :     }
     696           0 :     while ( fgets(buffer,sizeof(buffer),old)!=NULL ) {
     697           0 :     if ( ViewPostScriptFont(g_strchomp(buffer),0)!=0 )
     698           0 :         any = 1;
     699             :     }
     700           0 :     fclose(old);
     701           0 :     free(ffdir);
     702           0 :     return any;
     703             : }
     704             : 
     705             : #if defined(__Mac)
     706             : /* Read a property from the x11 properties files */
     707             : /* At the moment we want to know if we get the command key, or if the menubar */
     708             : /*    eats it */
     709             : static int get_mac_x11_prop(char *keystr) {
     710             :     CFPropertyListRef ret;
     711             :     CFStringRef key, appID;
     712             :     int val;
     713             : 
     714             :     appID = CFStringCreateWithBytes(NULL,(uint8 *) "com.apple.x11",strlen("com.apple.x11"), kCFStringEncodingISOLatin1, 0);
     715             :     key   = CFStringCreateWithBytes(NULL,(uint8 *) keystr,strlen(keystr), kCFStringEncodingISOLatin1, 0);
     716             :     ret = CFPreferencesCopyAppValue(key,appID);
     717             :     if ( ret==NULL ) {
     718             :         /* Sigh. Apple uses a different preference file under 10.5.6 I really */
     719             :         /*  wish they'd stop making stupid, unnecessary changes */
     720             :         appID = CFStringCreateWithBytes(NULL,(uint8 *) "org.x.X11",strlen("org.x.X11"), kCFStringEncodingISOLatin1, 0);
     721             :         ret = CFPreferencesCopyAppValue(key,appID);
     722             :     }
     723             :     if ( ret==NULL )
     724             : return( -1 );
     725             :     if ( CFGetTypeID(ret)!=CFBooleanGetTypeID())
     726             : return( -2 );
     727             :     val = CFBooleanGetValue(ret);
     728             :     CFRelease(ret);
     729             : return( val );
     730             : }
     731             : 
     732             : static int uses_local_x(int argc,char **argv) {
     733             :     int i;
     734             :     char *arg;
     735             : 
     736             :     for ( i=1; i<argc; ++i ) {
     737             :         arg = argv[i];
     738             :         if ( *arg=='-' ) {
     739             :             if ( arg[0]=='-' && arg[1]=='-' && arg[2]!='\0')
     740             :                 ++arg;
     741             :             if ( strcmp(arg,"-display")==0 )
     742             : return( i+1<argc && strcmp(argv[i+1],":0")!=0 && strcmp(argv[i+1],":0.0")!=0? 2 : 0 );
     743             :             if ( strcmp(argv[i],"-c")==0 )
     744             : return( false );                /* we use a script string, no x display at all */
     745             :             if ( strcmp(arg,"-script")==0 )
     746             : return( false );                /* we use a script, no x display at all */
     747             :             if ( strcmp(argv[i],"-")==0 )
     748             : return( false );                /* script on stdin */
     749             :         } else {
     750             :             /* Is this argument a script file ? */
     751             :             FILE *temp = fopen(argv[i],"r");
     752             :             char buffer[200];
     753             :             if ( temp==NULL )
     754             : return( true );                 /* not a script file, so need local local X */
     755             :             buffer[0] = '\0';
     756             :             fgets(buffer,sizeof(buffer),temp);
     757             :             fclose(temp);
     758             :             if ( buffer[0]=='#' && buffer[1]=='!' &&
     759             :                     (strstr(buffer,"pfaedit")!=NULL || strstr(buffer,"fontforge")!=NULL )) {
     760             : return( false );                /* is a script file, so no need for X */
     761             : 
     762             : return( true );                 /* not a script, so needs X */
     763             :             }
     764             :         }
     765             :     }
     766             : return( true );
     767             : }
     768             : #endif
     769             : 
     770             : 
     771             : #if defined(__Mac)
     772             : static int hasquit( int argc, char **argv ) {
     773             :     int i;
     774             : 
     775             :     for ( i=1; i<argc; ++i )
     776             :         if ( strcmp(argv[i],"-quit")==0 || strcmp(argv[i],"--quit")==0 )
     777             : return( true );
     778             : 
     779             : return( false );
     780             : }
     781             : #endif
     782             : 
     783           0 : static void GrokNavigationMask(void) {
     784             :     extern int navigation_mask;
     785             : 
     786           0 :     navigation_mask = GMenuItemParseMask(H_("NavigationMask|None"));
     787           0 : }
     788             : 
     789             : /**
     790             :  * Create the directory basedir/dirname with the given mode.
     791             :  * Silently ignore any errors that might happen.
     792             :  */
     793           0 : static void ffensuredir( const char* basedir, const char* dirname, mode_t mode ) {
     794           0 :     const int buffersz = PATH_MAX;
     795           0 :     char buffer[buffersz+1];
     796             : 
     797           0 :     snprintf(buffer,buffersz,"%s/%s", basedir, dirname );
     798             :     // ignore errors, this is just to help the user aftre all.
     799           0 :     mkdir( buffer, mode );
     800           0 : }
     801             : 
     802           0 : static void ensureDotFontForgeIsSetup() {
     803           0 :     char *basedir = getFontForgeUserDir(Config);
     804           0 :     if ( !basedir ) {
     805           0 :         return;
     806             :     }
     807           0 :     ffensuredir( basedir, "",       S_IRWXU );
     808           0 :     ffensuredir( basedir, "python", S_IRWXU );
     809           0 :     free(basedir);
     810             : }
     811             : 
     812           0 : static void DoAutoRecoveryPostRecover_PromptUserGraphically(SplineFont *sf)
     813             : {
     814             :     /* Ask user to save-as file */
     815             :     char *buts[4];
     816           0 :     buts[0] = _("_OK");
     817           0 :     buts[1] = 0;
     818           0 :     gwwv_ask( _("Recovery Complete"),(const char **) buts,0,1,_("Your file %s has been recovered.\nYou must now Save your file to continue working on it."), sf->filename );
     819           0 :     _FVMenuSaveAs( (FontView*)sf->fv );
     820           0 : }
     821             : 
     822             : #if defined(__MINGW32__) && !defined(_NO_LIBCAIRO)
     823             : /**
     824             :  * \brief Load fonts from the specified folder for the UI to use.
     825             :  * This should only be used if Cairo is used on Windows, which defaults to the
     826             :  * Win32 font backend.
     827             :  * This is an ANSI version, so files which contain characters outside of the
     828             :  * user's locale will fail to be loaded.
     829             :  * \param prefix The folder to read fonts from. Currently the pixmaps folder
     830             :  *               and the folder 'ui-fonts' in the FontForge preferences folder.
     831             :  */
     832             : static void WinLoadUserFonts(const char *prefix) {
     833             :     HANDLE fileHandle;
     834             :     WIN32_FIND_DATA fileData;
     835             :     char path[MAX_PATH], *ext;
     836             :     HRESULT ret;
     837             :     int i;
     838             : 
     839             :     if (prefix == NULL) {
     840             :         return;
     841             :     }
     842             :     ret = snprintf(path, MAX_PATH, "%s/*.???", prefix);
     843             :     if (ret <= 0 || ret >= MAX_PATH) {
     844             :         return;
     845             :     }
     846             : 
     847             :     fileHandle = FindFirstFileA(path, &fileData);
     848             :     if (fileHandle != INVALID_HANDLE_VALUE) do {
     849             :         ext = strrchr(fileData.cFileName, '.');
     850             :         if (!ext || (strcasecmp(ext, ".ttf") && strcasecmp(ext, ".ttc") &&
     851             :                      strcasecmp(ext,".otf")))
     852             :         {
     853             :             continue;
     854             :         }
     855             :         ret = snprintf(path, MAX_PATH, "%s/%s", prefix, fileData.cFileName);
     856             :         if (ret > 0 && ret < MAX_PATH) {
     857             :             //printf("WIN32-FONT-TEST: %s\n", path);
     858             :             ret = AddFontResourceExA(path, FR_PRIVATE, NULL);
     859             :             //if (ret > 0) {
     860             :             //    printf("\tLOADED FONT OK!\n");
     861             :             //}
     862             :         }
     863             :     } while (FindNextFileA(fileHandle, &fileData) != 0);
     864             : }
     865             : #endif
     866             : 
     867             : 
     868          40 : int fontforge_main( int argc, char **argv ) {
     869             :     extern const char *source_modtime_str;
     870             :     extern const char *source_version_str;
     871          40 :     const char *load_prefs = getenv("FONTFORGE_LOADPREFS");
     872             :     int i;
     873          40 :     int recover=2;
     874             :     int any;
     875          40 :     int next_recent=0;
     876             :     GRect pos;
     877             :     GWindowAttrs wattrs;
     878          40 :     char *display = NULL;
     879             :     FontRequest rq;
     880             :     int ds, ld;
     881          40 :     int openflags=0;
     882          40 :     int doopen=0, quit_request=0;
     883          40 :     bool use_cairo = true;
     884             : 
     885             : #if !(GLIB_CHECK_VERSION(2, 35, 0))
     886             :     g_type_init();
     887             : #endif
     888             : 
     889             :     /* Must be done before we cache the current directory */
     890             :     /* Change to HOME dir if specified on the commandline */
     891         408 :     for ( i=1; i<argc; ++i ) {
     892         368 :         char *pt = argv[i];
     893         368 :         if ( pt[0]=='-' && pt[1]=='-' ) ++pt;
     894         368 :         if (strcmp(pt,"-home")==0 || strncmp(pt,"-psn_",5)==0) {
     895             :             /* OK, I don't know what _-psn_ means, but to GW it means */
     896             :             /* we've been started on the mac from the FontForge.app   */
     897             :             /* structure, and the current directory is (shudder) "/"  */
     898           0 :             if (getenv("HOME")!=NULL) chdir(getenv("HOME"));
     899           0 :             break;      /* Done - Unnecessary to check more arguments */
     900             :         }
     901         368 :         if (strcmp(pt,"-quiet")==0)
     902           0 :             quiet = 1;
     903             :     }
     904             : 
     905          40 :     if (!quiet) {
     906          40 :         fprintf( stderr, "Copyright (c) 2000-2014 by George Williams. See AUTHORS for Contributors.\n" );
     907          40 :         fprintf( stderr, " License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n" );
     908          40 :         fprintf( stderr, " with many parts BSD <http://fontforge.org/license.html>. Please read LICENSE.\n" );
     909          40 :         fprintf( stderr, " Based on sources from %s"
     910             :                 "-ML"
     911             : #ifdef FREETYPE_HAS_DEBUGGER
     912             :                 "-TtfDb"
     913             : #endif
     914             : #ifdef _NO_PYTHON
     915             :                 "-NoPython"
     916             : #endif
     917             : #ifdef FONTFORGE_CONFIG_USE_DOUBLE
     918             :                 "-D"
     919             : #endif
     920             :                 ".\n",
     921             :                 FONTFORGE_MODTIME_STR );
     922          40 :         fprintf( stderr, " Based on source from git with hash: %s\n", FONTFORGE_GIT_VERSION );
     923             :     }
     924             : 
     925             : #if defined(__Mac)
     926             :     /* Start X if they haven't already done so. Well... try anyway */
     927             :     /* Must be before we change DYLD_LIBRARY_PATH or X won't start */
     928             :     /* (osascript depends on a libjpeg which isn't found if we look in /sw/lib first */
     929             :     int local_x = uses_local_x(argc,argv);
     930             :     if ( local_x==1 && getenv("DISPLAY")==NULL ) {
     931             :         /* Don't start X if we're just going to quit. */
     932             :         /* if X exists, it isn't needed. If X doesn't exist it's wrong */
     933             :         if ( !hasquit(argc,argv)) {
     934             :             /* This sequence is supposed to bring up an app without a window */
     935             :             /*  but X still opens an xterm */
     936             :             system( "osascript -e 'tell application \"X11\" to launch'" );
     937             :             system( "osascript -e 'tell application \"X11\" to activate'" );
     938             :         }
     939             :         setenv("DISPLAY",":0.0",0);
     940             :     } else if ( local_x==1 && *getenv("DISPLAY")!='/' && strcmp(getenv("DISPLAY"),":0.0")!=0 && strcmp(getenv("DISPLAY"),":0")!=0 )
     941             :         /* 10.5.7 uses a named socket or something "/tmp/launch-01ftWX:0" */
     942             :         local_x = 0;
     943             : #endif
     944             : 
     945             : #if defined(__MINGW32__)
     946             :     if( getenv("DISPLAY")==NULL ) {
     947             :         putenv("DISPLAY=127.0.0.1:0.0");
     948             :     }
     949             :     if( getenv("LC_ALL")==NULL ){
     950             :         char lang[8];
     951             :         char env[32];
     952             :         if( GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, 8) > 0 ){
     953             :             strcpy(env, "LC_ALL=");
     954             :             strcat(env, lang);
     955             :             putenv(env);
     956             :         }
     957             :     }
     958             : #endif
     959             : 
     960          40 :     FF_SetUiInterface(&gdraw_ui_interface);
     961          40 :     FF_SetPrefsInterface(&gdraw_prefs_interface);
     962          40 :     FF_SetSCInterface(&gdraw_sc_interface);
     963          40 :     FF_SetCVInterface(&gdraw_cv_interface);
     964          40 :     FF_SetBCInterface(&gdraw_bc_interface);
     965          40 :     FF_SetFVInterface(&gdraw_fv_interface);
     966          40 :     FF_SetFIInterface(&gdraw_fi_interface);
     967          40 :     FF_SetMVInterface(&gdraw_mv_interface);
     968          40 :     FF_SetClipInterface(&gdraw_clip_interface);
     969             : #ifndef _NO_PYTHON
     970          40 :     PythonUI_Init();
     971             : #endif
     972             : 
     973          40 :     FindProgDir(argv[0]);
     974          40 :     InitSimpleStuff();
     975             : 
     976             : #if defined(__MINGW32__)
     977             :     {
     978             :         char path[MAX_PATH];
     979             :         unsigned int len = GetModuleFileNameA(NULL, path, MAX_PATH);
     980             :         path[len] = '\0';
     981             :         
     982             :         //The '.exe' must be removed as resources presumes it's not there.
     983             :         GResourceSetProg(GFileRemoveExtension(GFileNormalizePath(path)));
     984             :     }
     985             : #else
     986          40 :     GResourceSetProg(argv[0]);
     987             : #endif
     988             : 
     989             : #if defined(__Mac)
     990             :     /* The mac seems to default to the "C" locale, LANG and LC_MESSAGES are not*/
     991             :     /*  defined. This means that gettext will not bother to look up any message*/
     992             :     /*  files -- even if we have a "C" or "POSIX" entry in the locale diretory */
     993             :     /* Now if X11 gives us the command key, I want to force a rebinding to use */
     994             :     /*  Cmd rather than Control key -- more mac-like. But I can't do that if   */
     995             :     /*  there is no locale. So I force a locale if there is none specified */
     996             :     /* I force the US English locale, because that's the what the messages are */
     997             :     /*  by default so I'm changing as little as I can. I think. */
     998             :     /* Now the locale command will treat a LANG which is "" as undefined, but */
     999             :     /*  gettext will not. So I don't bother to check for null strings or "C"  */
    1000             :     /*  or "POSIX". If they've mucked with the locale perhaps they know what  */
    1001             :     /*  they are doing */
    1002             :     {
    1003             :         int did_keybindings = 0;
    1004             :         int useCommandKey = get_mac_x11_prop("enable_key_equivalents") <= 0;
    1005             : 
    1006             :         if ( local_x && useCommandKey ) {
    1007             :             hotkeySystemSetCanUseMacCommand( 1 );
    1008             : 
    1009             :             /* Ok, we get the command key */
    1010             :             if ( getenv("LANG")==NULL && getenv("LC_MESSAGES")==NULL ) {
    1011             :                 setenv("LC_MESSAGES","en_US.UTF-8",0);
    1012             :             }
    1013             :             /* Can we find a set of keybindings designed for the mac with cmd key? */
    1014             :             bind_textdomain_codeset("Mac-FontForge-MenuShortCuts","UTF-8");
    1015             :             bindtextdomain("Mac-FontForge-MenuShortCuts", getLocaleDir());
    1016             :             if ( *dgettext("Mac-FontForge-MenuShortCuts","Flag0x10+")!='F' ) {
    1017             :                 GMenuSetShortcutDomain("Mac-FontForge-MenuShortCuts");
    1018             :                 did_keybindings = 1;
    1019             :             }
    1020             :         }
    1021             :         if ( !did_keybindings ) {
    1022             :             /* Nope. we can't. Fall back to the normal stuff */
    1023             : #endif
    1024          40 :             GMenuSetShortcutDomain("FontForge-MenuShortCuts");
    1025          40 :             bind_textdomain_codeset("FontForge-MenuShortCuts","UTF-8");
    1026          40 :             bindtextdomain("FontForge-MenuShortCuts", getLocaleDir());
    1027             : #if defined(__Mac)
    1028             :         }
    1029             :     }
    1030             : #endif
    1031          40 :     bind_textdomain_codeset("FontForge","UTF-8");
    1032          40 :     bindtextdomain("FontForge", getLocaleDir());
    1033          40 :     textdomain("FontForge");
    1034          40 :     GResourceUseGetText();
    1035             :     {
    1036             :         char shareDir[PATH_MAX];
    1037          40 :         char* sd = getShareDir();
    1038          40 :         strncpy( shareDir, sd, PATH_MAX );
    1039          40 :     shareDir[PATH_MAX-1] = '\0';
    1040          40 :         if(!sd) {
    1041           0 :             strcpy( shareDir, SHAREDIR );
    1042             :         }
    1043             : 
    1044             :         char path[PATH_MAX];
    1045          40 :         snprintf(path, PATH_MAX, "%s%s", shareDir, "/pixmaps" );
    1046          40 :         GGadgetSetImageDir( path );
    1047             : 
    1048          40 :         snprintf(path, PATH_MAX, "%s%s", shareDir, "/resources/fontforge.resource" );
    1049          40 :         GResourceAddResourceFile(path, GResourceProgramName,false);
    1050             :     }
    1051          40 :     hotkeysLoad();
    1052             : //    loadPrefsFiles();
    1053          40 :     Prefs_LoadDefaultPreferences();
    1054             : 
    1055          40 :     if ( load_prefs!=NULL && strcasecmp(load_prefs,"Always")==0 )
    1056           0 :         LoadPrefs();
    1057          40 :     if ( default_encoding==NULL )
    1058          40 :         default_encoding=FindOrMakeEncoding("ISO8859-1");
    1059          40 :     if ( default_encoding==NULL )
    1060           0 :         default_encoding=&custom;   /* In case iconv is broken */
    1061             : 
    1062             :     // This no longer starts embedded Python unless control passes to the Python executors,
    1063             :     // which exit independently rather than returning here.
    1064          40 :     CheckIsScript(argc,argv); /* Will run the script and exit if it is a script */
    1065             :                                         /* If there is no UI, there is always a script */
    1066             :                                         /*  and we will never return from the above */
    1067           0 :     if ( load_prefs==NULL ||
    1068           0 :             (strcasecmp(load_prefs,"Always")!=0 &&    /* Already loaded */
    1069           0 :              strcasecmp(load_prefs,"Never")!=0 ))
    1070           0 :         LoadPrefs();
    1071           0 :     GrokNavigationMask();
    1072           0 :     for ( i=1; i<argc; ++i ) {
    1073           0 :         char *pt = argv[i];
    1074           0 :         if ( pt[0]=='-' && pt[1]=='-' )
    1075           0 :             ++pt;
    1076           0 :         if ( strcmp(pt,"-sync")==0 )
    1077           0 :             GResourceAddResourceString("Gdraw.Synchronize: true",argv[0]);
    1078           0 :         else if ( strcmp(pt,"-depth")==0 && i<argc-1 )
    1079           0 :             AddR(argv[0],"Gdraw.Depth", argv[++i]);
    1080           0 :         else if ( strcmp(pt,"-vc")==0 && i<argc-1 )
    1081           0 :             AddR(argv[0],"Gdraw.VisualClass", argv[++i]);
    1082           0 :         else if ( (strcmp(pt,"-cmap")==0 || strcmp(pt,"-colormap")==0) && i<argc-1 )
    1083           0 :             AddR(argv[0],"Gdraw.Colormap", argv[++i]);
    1084           0 :         else if ( (strcmp(pt,"-dontopenxdevices")==0) )
    1085           0 :             AddR(argv[0],"Gdraw.DontOpenXDevices", "true");
    1086           0 :         else if ( strcmp(pt,"-keyboard")==0 && i<argc-1 )
    1087           0 :             AddR(argv[0],"Gdraw.Keyboard", argv[++i]);
    1088           0 :         else if ( strcmp(pt,"-display")==0 && i<argc-1 )
    1089           0 :             display = argv[++i];
    1090             : # if MyMemory
    1091             :         else if ( strcmp(pt,"-memory")==0 )
    1092             :             __malloc_debug(5);
    1093             : # endif
    1094           0 :         else if ( strncmp(pt,"-usecairo",strlen("-usecairo"))==0 ) {
    1095           0 :             if ( strcmp(pt,"-usecairo=no")==0 )
    1096           0 :                 use_cairo = false;
    1097             :             else
    1098           0 :                 use_cairo = true;
    1099           0 :             GDrawEnableCairo(use_cairo);
    1100           0 :         } else if ( strcmp(pt,"-nosplash")==0 )
    1101           0 :             splash = 0;
    1102           0 :         else if ( strcmp(pt,"-quiet")==0 )
    1103             :             /* already checked for this earlier, no need to do it again */;
    1104           0 :         else if ( strcmp(pt,"-unique")==0 )
    1105           0 :             unique = 1;
    1106           0 :         else if ( strcmp(pt,"-forceuihidden")==0 )
    1107           0 :             cmdlinearg_forceUIHidden = 0;
    1108           0 :         else if ( strcmp(pt,"-recover")==0 && i<argc-1 ) {
    1109           0 :             ++i;
    1110           0 :             if ( strcmp(argv[i],"none")==0 )
    1111           0 :                 recover=0;
    1112           0 :             else if ( strcmp(argv[i],"clean")==0 )
    1113           0 :                 recover= -1;
    1114           0 :             else if ( strcmp(argv[i],"auto")==0 )
    1115           0 :                 recover= 1;
    1116           0 :             else if ( strcmp(argv[i],"inquire")==0 )
    1117           0 :                 recover= 2;
    1118             :             else {
    1119           0 :                 fprintf( stderr, "Invalid argument to -recover, must be none, auto, inquire or clean\n" );
    1120           0 :                 dousage();
    1121             :             }
    1122           0 :         } else if ( strcmp(pt,"-recover=none")==0 ) {
    1123           0 :             recover = 0;
    1124           0 :         } else if ( strcmp(pt,"-recover=clean")==0 ) {
    1125           0 :             recover = -1;
    1126           0 :         } else if ( strcmp(pt,"-recover=auto")==0 ) {
    1127           0 :             recover = 1;
    1128           0 :         } else if ( strcmp(pt,"-recover=inquire")==0 ) {
    1129           0 :             recover = 2;
    1130           0 :         } else if ( strcmp(pt,"-docs")==0 )
    1131           0 :             dohelp();
    1132           0 :         else if ( strcmp(pt,"-help")==0 )
    1133           0 :             dousage();
    1134           0 :         else if ( strcmp(pt,"-version")==0 || strcmp(pt,"-v")==0 || strcmp(pt,"-V")==0 )
    1135           0 :             doversion(FONTFORGE_MODTIME_STR);
    1136           0 :         else if ( strcmp(pt,"-quit")==0 )
    1137           0 :             quit_request = true;
    1138           0 :         else if ( strcmp(pt,"-home")==0 )
    1139             :             /* already did a chdir earlier, don't need to do it again */;
    1140             : #if defined(__Mac)
    1141             :         else if ( strncmp(pt,"-psn_",5)==0 ) {
    1142             :             /* OK, I don't know what _-psn_ means, but to GW it means */
    1143             :             /* we've been started on the mac from the FontForge.app   */
    1144             :             /* structure, and the current directory was (shudder) "/" */
    1145             :             /* (however, we changed to HOME earlier in main routine). */
    1146             :             unique = 1;
    1147             :             listen_to_apple_events = true; // This has been problematic on Mavericks and later.
    1148             :         }
    1149             : #endif
    1150             :     }
    1151             : 
    1152           0 :     ensureDotFontForgeIsSetup();
    1153             : #if defined(__MINGW32__) && !defined(_NO_LIBCAIRO)
    1154             :     //Load any custom fonts for the user interface
    1155             :     if (use_cairo) {
    1156             :         char *system_load = getGResourceProgramDir();
    1157             :         char *user_load = getFontForgeUserDir(Data);
    1158             :         char lbuf[MAX_PATH];
    1159             :         int lret;
    1160             : 
    1161             :         if (system_load != NULL) {
    1162             :             //Follow the FontConfig APPSHAREFONTDIR location
    1163             :             lret = snprintf(lbuf, MAX_PATH, "%s/../share/fonts", system_load);
    1164             :             if (lret > 0 && lret < MAX_PATH) {
    1165             :                 WinLoadUserFonts(lbuf);
    1166             :             }
    1167             :         }
    1168             :         if (user_load != NULL) {
    1169             :             lret = snprintf(lbuf, MAX_PATH, "%s/%s", user_load, "ui-fonts");
    1170             :             if (lret > 0 && lret < MAX_PATH) {
    1171             :                 WinLoadUserFonts(lbuf);
    1172             :             }
    1173             :             free(user_load);
    1174             :         }
    1175             :     }
    1176             : #endif
    1177           0 :     InitImageCache(); // This is in gtextinfo.c. It zeroes imagecache for us.
    1178           0 :     atexit(&ClearImageCache); // We register the destructor, which is also in gtextinfo.c.
    1179           0 :     GDrawCreateDisplays(display,argv[0]);
    1180           0 :     atexit(&GDrawDestroyDisplays); // We register the destructor so that it runs even if we call exit without finishing this function.
    1181           0 :     default_background = GDrawGetDefaultBackground(screen_display);
    1182           0 :     InitToolIconClut(default_background);
    1183           0 :     InitToolIcons();
    1184           0 :     InitCursors();
    1185             : 
    1186             :     /**
    1187             :      * we have to do a quick sniff of argv[] here to see if the user
    1188             :      * wanted to skip loading these python init files.
    1189             :      */
    1190           0 :     for ( i=1; i<argc; ++i ) {
    1191           0 :         char *pt = argv[i];
    1192             : 
    1193           0 :         if ( !strcmp(pt,"-SkipPythonInitFiles")) {
    1194           0 :             ProcessPythonInitFiles = 0;
    1195             :         }
    1196             :     }
    1197             :     
    1198             : #ifndef _NO_PYTHON
    1199             : /*# ifndef GWW_TEST*/
    1200           0 :     FontForge_InitializeEmbeddedPython(); /* !!!!!! debug (valgrind doesn't like python) */
    1201             : /*# endif*/
    1202             : #endif
    1203             : 
    1204             : #ifndef _NO_PYTHON
    1205           0 :     if( ProcessPythonInitFiles )
    1206           0 :         PyFF_ProcessInitFiles();
    1207             : #endif
    1208             : 
    1209             :     /* the splash screen used not to have a title bar (wam_nodecor) */
    1210             :     /*  but I found I needed to know how much the window manager moved */
    1211             :     /*  the window around, which I can determine if I have a positioned */
    1212             :     /*  decorated window created at the begining */
    1213             :     /* Actually I don't care any more */
    1214           0 :     wattrs.mask = wam_events|wam_cursor|wam_bordwidth|wam_backcol|wam_positioned|wam_utf8_wtitle|wam_isdlg;
    1215           0 :     wattrs.event_masks = ~(1<<et_charup);
    1216           0 :     wattrs.positioned = 1;
    1217           0 :     wattrs.cursor = ct_pointer;
    1218           0 :     wattrs.utf8_window_title = "FontForge";
    1219           0 :     wattrs.border_width = 2;
    1220           0 :     wattrs.background_color = 0xffffff;
    1221           0 :     wattrs.is_dlg = !listen_to_apple_events;
    1222           0 :     pos.x = pos.y = 200;
    1223           0 :     pos.width = splashimage.u.image->width;
    1224           0 :     pos.height = splashimage.u.image->height-56;             /* 54 */
    1225           0 :     GDrawBindSelection(NULL,sn_user1,"FontForge");
    1226           0 :     if ( unique && GDrawSelectionOwned(NULL,sn_user1)) {
    1227             :         /* Different event handler, not a dialog */
    1228           0 :         wattrs.is_dlg = false;
    1229           0 :         splashw = GDrawCreateTopWindow(NULL,&pos,request_e_h,NULL,&wattrs);
    1230           0 :         PingOtherFontForge(argc,argv);
    1231             :     } else {
    1232           0 :         if ( quit_request )
    1233           0 : exit( 0 );
    1234           0 :         splashw = GDrawCreateTopWindow(NULL,&pos,splash_e_h,NULL,&wattrs);
    1235             :     }
    1236             : 
    1237           0 :     memset(&rq,0,sizeof(rq));
    1238           0 :     rq.utf8_family_name = SERIF_UI_FAMILIES;
    1239           0 :     rq.point_size = 12;
    1240           0 :     rq.weight = 400;
    1241           0 :     splash_font = GDrawInstanciateFont(NULL,&rq);
    1242           0 :     splash_font = GResourceFindFont("Splash.Font",splash_font);
    1243           0 :     GDrawDecomposeFont(splash_font, &rq);
    1244           0 :     rq.style = fs_italic;
    1245           0 :     splash_italic = GDrawInstanciateFont(NULL,&rq);
    1246           0 :     splash_italic = GResourceFindFont("Splash.ItalicFont",splash_italic);
    1247           0 :     GDrawSetFont(splashw,splash_font);
    1248             : 
    1249           0 :     SplashLayout();
    1250           0 :     localsplash = splash;
    1251             : 
    1252           0 :    if ( localsplash && !listen_to_apple_events )
    1253           0 :         start_splash_screen();
    1254             : 
    1255             :     //
    1256             :     // The below call will initialize the fontconfig cache if required.
    1257             :     // That can take a while the first time it happens.
    1258             :     //
    1259           0 :    GDrawWindowFontMetrics(splashw,splash_font,&as,&ds,&ld);
    1260           0 :    fh = as+ds+ld;
    1261             : 
    1262           0 :     if ( AutoSaveFrequency>0 )
    1263           0 :         autosave_timer=GDrawRequestTimer(splashw,2*AutoSaveFrequency*1000,AutoSaveFrequency*1000,NULL);
    1264             : 
    1265           0 :     GDrawProcessPendingEvents(NULL);
    1266           0 :     GDrawSetBuildCharHooks(BuildCharHook,InsCharHook);
    1267             : 
    1268           0 :     any = 0;
    1269           0 :     if ( recover==-1 )
    1270           0 :         CleanAutoRecovery();
    1271           0 :     else if ( recover )
    1272           0 :         any = DoAutoRecoveryExtended( recover-1 );
    1273             :                         
    1274           0 :     openflags = 0;
    1275           0 :     for ( i=1; i<argc; ++i ) {
    1276             :         char buffer[1025];
    1277           0 :         char *pt = argv[i];
    1278             : 
    1279           0 :         GDrawProcessPendingEvents(NULL);
    1280           0 :         if ( pt[0]=='-' && pt[1]=='-' && pt[2]!='\0')
    1281           0 :             ++pt;
    1282           0 :         if ( strcmp(pt,"-new")==0 ) {
    1283           0 :             FontNew();
    1284           0 :             any = 1;
    1285             : #  if HANYANG
    1286             :         } else if ( strcmp(pt,"-newkorean")==0 ) {
    1287             :             MenuNewComposition(NULL,NULL,NULL);
    1288             :             any = 1;
    1289             : #  endif
    1290           0 :         } else if ( !strcmp(pt,"-SkipPythonInitFiles")) {
    1291             :             // already handled above.
    1292           0 :         } else if ( strcmp(pt,"-last")==0 ) {
    1293           0 :             if ( next_recent<RECENT_MAX && RecentFiles[next_recent]!=NULL )
    1294           0 :                 if ( ViewPostScriptFont(RecentFiles[next_recent++],openflags))
    1295           0 :                     any = 1;
    1296           0 :         } else if ( strcmp(pt,"-sync")==0 || strcmp(pt,"-memory")==0 ||
    1297           0 :                     strcmp(pt,"-nosplash")==0 || strcmp(pt,"-recover=none")==0 ||
    1298           0 :                     strcmp(pt,"-recover=clean")==0 || strcmp(pt,"-recover=auto")==0 ||
    1299           0 :                     strcmp(pt,"-dontopenxdevices")==0 || strcmp(pt,"-unique")==0 ||
    1300           0 :                     strncmp(pt,"-usecairo",strlen("-usecairo"))==0 ||
    1301           0 :                     strcmp(pt,"-home")==0 || strcmp(pt,"-quiet")==0
    1302           0 :                     || strcmp(pt,"-forceuihidden")==0 )
    1303             :             /* Already done, needed to be before display opened */;
    1304           0 :         else if ( strncmp(pt,"-psn_",5)==0 )
    1305             :             /* Already done */;
    1306           0 :         else if ( (strcmp(pt,"-depth")==0 || strcmp(pt,"-vc")==0 ||
    1307           0 :                     strcmp(pt,"-cmap")==0 || strcmp(pt,"-colormap")==0 ||
    1308           0 :                     strcmp(pt,"-keyboard")==0 ||
    1309           0 :                     strcmp(pt,"-display")==0 || strcmp(pt,"-recover")==0 ) &&
    1310           0 :                 i<argc-1 )
    1311           0 :             ++i; /* Already done, needed to be before display opened */
    1312           0 :         else if ( strcmp(pt,"-allglyphs")==0 )
    1313           0 :             openflags |= of_all_glyphs_in_ttc;
    1314           0 :         else if ( strcmp(pt,"-open")==0 )
    1315           0 :             doopen = true;
    1316             :         else {
    1317           0 :             printf("else argv[i]:%s\n", argv[i] );
    1318           0 :             if ( strstr(argv[i],"://")!=NULL ) {              /* Assume an absolute URL */
    1319           0 :                 strncpy(buffer,argv[i],sizeof(buffer));
    1320           0 :                 buffer[sizeof(buffer)-1]= '\0';
    1321             :             } else
    1322           0 :                 GFileGetAbsoluteName(argv[i],buffer,sizeof(buffer));
    1323           0 :             if ( GFileIsDir(buffer) || (strstr(buffer,"://")!=NULL && buffer[strlen(buffer)-1]=='/')) {
    1324             :                 char *fname;
    1325           0 :                 fname = malloc(strlen(buffer)+strlen("/glyphs/contents.plist")+1);
    1326           0 :                 strcpy(fname,buffer); strcat(fname,"/glyphs/contents.plist");
    1327           0 :                 if ( GFileExists(fname)) {
    1328             :                     /* It's probably a Unified Font Object directory */
    1329           0 :                     free(fname);
    1330           0 :                     if ( ViewPostScriptFont(buffer,openflags) )
    1331           0 :                         any = 1;
    1332             :                 } else {
    1333           0 :                     strcpy(fname,buffer); strcat(fname,"/font.props");
    1334           0 :                     if ( GFileExists(fname)) {
    1335             :                         /* It's probably a sf dir collection */
    1336           0 :                         free(fname);
    1337           0 :                         if ( ViewPostScriptFont(buffer,openflags) )
    1338           0 :                             any = 1;
    1339             :                     } else {
    1340           0 :                         free(fname);
    1341           0 :                         if ( buffer[strlen(buffer)-1]!='/' ) {
    1342             :                             /* If dirname doesn't end in "/" we'll be looking in parent dir */
    1343           0 :                             buffer[strlen(buffer)+1]='\0';
    1344           0 :                             buffer[strlen(buffer)] = '/';
    1345             :                         }
    1346           0 :                         fname = GetPostScriptFontName(buffer,false);
    1347           0 :                         if ( fname!=NULL )
    1348           0 :                             ViewPostScriptFont(fname,openflags);
    1349           0 :                         any = 1;        /* Even if we didn't get a font, don't bring up dlg again */
    1350           0 :                         free(fname);
    1351             :                     }
    1352             :                 }
    1353           0 :             } else if ( ViewPostScriptFont(buffer,openflags)!=0 )
    1354           0 :                 any = 1;
    1355             :         }
    1356             :     }
    1357           0 :     if ( !any && !doopen )
    1358           0 :         any = ReopenLastFonts();
    1359             : 
    1360           0 :     collabclient_ensureClientBeacon();
    1361           0 :     collabclient_sniffForLocalServer();
    1362             : #ifndef _NO_PYTHON
    1363           0 :     PythonUI_namedpipe_Init();
    1364             : #endif
    1365             : 
    1366             : #if defined(__Mac)
    1367             :     if ( listen_to_apple_events ) {
    1368             :         install_apple_event_handlers();
    1369             :         install_mac_timer();
    1370             :         setup_cocoa_app();
    1371             : 
    1372             :         
    1373             :         // WARNING: See declaration of RunApplicationEventLoop() above as to
    1374             :         // why you might not want to call that function anymore.
    1375             :         // RunApplicationEventLoop();
    1376             :         
    1377             :     } else
    1378             : #endif
    1379           0 :     if ( doopen || !any )
    1380           0 :         _FVMenuOpen(NULL);
    1381           0 :     GDrawEventLoop(NULL);
    1382           0 :     GDrawDestroyDisplays();
    1383             : 
    1384             : #ifndef _NO_PYTHON
    1385             : /*# ifndef GWW_TEST*/
    1386           0 :     FontForge_FinalizeEmbeddedPython(); /* !!!!!! debug (valgrind doesn't like python) */
    1387             : /*# endif*/
    1388             : #endif
    1389             : 
    1390             :     // These free menu translations, mostly.
    1391           0 :     BitmapViewFinishNonStatic();
    1392           0 :     MetricsViewFinishNonStatic();
    1393           0 :     CharViewFinishNonStatic();
    1394           0 :     FontViewFinishNonStatic();
    1395             : 
    1396           0 :     ClearImageCache(); // This frees the contents of imagecache.
    1397           0 :     hotkeysSave();
    1398           0 :     LastFonts_Save();
    1399             : 
    1400             : #ifndef _NO_LIBUNICODENAMES
    1401             :     uninm_names_db_close(names_db);     /* close this database before exiting */
    1402             :     uninm_blocks_db_close(blocks_db);
    1403             : #endif
    1404             : 
    1405           0 :     lt_dlexit();
    1406             : 
    1407           0 : return( 0 );
    1408             : }

Generated by: LCOV version 1.10