Index: vcl/source/window/window.cxx =================================================================== RCS file: /cvs/gsl/vcl/source/window/window.cxx,v retrieving revision 1.228 retrieving revision 1.228.34.1 diff -u -p -u -p -r1.228 -r1.228.34.1 --- vcl/source/window/window.cxx 9 Feb 2006 17:13:00 -0000 1.228 +++ vcl/source/window/window.cxx 16 Mar 2006 17:37:18 -0000 1.228.34.1 @@ -176,6 +176,9 @@ #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEROLE_HPP_ #include #endif +#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATOR_HPP_ +#include +#endif #include #include @@ -6435,7 +6438,19 @@ void Window::Show( BOOL bVisible, USHORT ImplSVData* pSVData = ImplGetSVData(); // #106431#, hide SplashScreen if( pSVData->mpIntroWindow && !ImplIsWindowOrChild( pSVData->mpIntroWindow ) ) - pSVData->mpIntroWindow->Hide(); + { + bVisible = sal_True; + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bVisible; + Reference rSplashScreen = + Reference( + comphelper::getProcessServiceFactory()->createInstanceWithArguments( + OUString::createFromAscii( "com.sun.star.office.SplashScreen" ), + aSeq ), UNO_QUERY); + + if ( rSplashScreen.is() ) + rSplashScreen->end(); + } //DBG_ASSERT( !mpWindowImpl->mbSuppressAccessibilityEvents, "Window::Show() - Frame reactivated"); mpWindowImpl->mbSuppressAccessibilityEvents = FALSE; Index: scp2/source/ooo/file_ooo.scp =================================================================== RCS file: /cvs/installation/scp2/source/ooo/file_ooo.scp,v retrieving revision 1.144 retrieving revision 1.144.8.1 diff -u -p -u -p -r1.144 -r1.144.8.1 --- scp2/source/ooo/file_ooo.scp 8 Mar 2006 14:15:39 -0000 1.144 +++ scp2/source/ooo/file_ooo.scp 16 Mar 2006 17:06:40 -0000 1.144.8.1 @@ -338,6 +338,15 @@ File gid_File_Bin_Soffice_Bin Name = "soffice.bin"; End +#if defined(UNX) && defined(ENABLE_GTK) +File gid_File_Bin_QStart_Bin + BIN_FILE_BODY; + Dir = gid_Dir_Program; + Styles = (PACKED, PATCH); + Name = "ooqstart"; +End +#endif + #ifdef UNX File gid_File_Bin_Open_Url Index: desktop/prj/build.lst =================================================================== RCS file: /cvs/framework/desktop/prj/build.lst,v retrieving revision 1.33 retrieving revision 1.33.4.1 diff -u -p -u -p -r1.33 -r1.33.4.1 --- desktop/prj/build.lst 7 Mar 2006 09:44:17 -0000 1.33 +++ desktop/prj/build.lst 16 Mar 2006 17:06:41 -0000 1.33.4.1 @@ -14,6 +14,7 @@ dt desktop\win32\source\setup nmake - dt desktop\win32\source\officeloader nmake - w dt_officeloader NULL dt desktop\win32\source\applauncher nmake - w dt_applauncher NULL dt desktop\win32\source\applauncher\ooo nmake - w dt_applauncher_ooo dt_applauncher.w NULL +dt desktop\unx\source nmake - u dt_uwrapper NULL dt desktop\source\pagein nmake - u dt_pagein NULL dt desktop\source\pkgchk nmake - all dt_pkgchk dt_dp_misc dt_app NULL dt desktop\source\pkgchk\msi nmake - w dt_pkgchk_msi dt_pkgchk NULL @@ -31,4 +32,4 @@ dt desktop\source\deployment\registry\co dt desktop\scripts nmake - u dt_scripts NULL dt desktop\macosx\source nmake - u dt_macosx_bundle NULL dt desktop\macosx\source\misc nmake - u dt_misc_macosxrc NULL -dt desktop\util nmake - all dt_util dt_app dt_so_comp dt_spl dt_wrapper.w dt_officeloader.w dt_migr dt_macosx_bundle.u NULL +dt desktop\util nmake - all dt_util dt_app dt_so_comp dt_spl dt_uwrapper.u dt_wrapper.w dt_officeloader.w dt_migr dt_macosx_bundle.u NULL Index: desktop/prj/d.lst =================================================================== RCS file: /cvs/framework/desktop/prj/d.lst,v retrieving revision 1.45 retrieving revision 1.45.4.1 diff -u -p -u -p -r1.45 -r1.45.4.1 --- desktop/prj/d.lst 7 Mar 2006 09:44:29 -0000 1.45 +++ desktop/prj/d.lst 16 Mar 2006 17:06:41 -0000 1.45.4.1 @@ -7,6 +7,7 @@ mkdir: %_DEST%\bin%_EXT%\remote2 ..\%__SRC%\bin\soffice.bin %_DEST%\bin%_EXT%\soffice.bin ..\%__SRC%\bin\officeloader.exe %_DEST%\bin%_EXT%\soffice.exe ..\%__SRC%\bin\soffice %_DEST%\bin%_EXT%\soffice.bin +..\%__SRC%\bin\ooqstart %_DEST%\bin%_EXT%\ooqstart ..\%__SRC%\bin\soffice_oo.exe %_DEST%\bin%_EXT%\soffice_oo.exe ..\%__SRC%\bin\soffice_so.exe %_DEST%\bin%_EXT%\soffice_so.exe Index: desktop/source/app/app.cxx =================================================================== RCS file: /cvs/framework/desktop/source/app/app.cxx,v retrieving revision 1.188 retrieving revision 1.188.50.1 diff -u -p -u -p -r1.188 -r1.188.50.1 --- desktop/source/app/app.cxx 27 Jan 2006 16:20:05 -0000 1.188 +++ desktop/source/app/app.cxx 16 Mar 2006 17:38:47 -0000 1.188.50.1 @@ -1393,6 +1393,7 @@ void Desktop::Main() OpenSplashScreen(); RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" ); + SetSplashScreenProgress(10); { UserInstall::UserInstallError instErr_fin = UserInstall::finalize(); if ( instErr_fin != UserInstall::E_None) @@ -1403,7 +1404,7 @@ void Desktop::Main() } // refresh path information utl::Bootstrap::reloadData(); - SetSplashScreenProgress(25); + SetSplashScreenProgress(20); } Reference< XMultiServiceFactory > xSMgr = @@ -1416,7 +1417,7 @@ void Desktop::Main() { RegisterServices( xSMgr ); - //SetSplashScreenProgress(15); + SetSplashScreenProgress(25); #ifndef UNX if ( pCmdLineArgs->IsHelp() ) { @@ -1456,7 +1457,7 @@ void Desktop::Main() // Read the common configuration items for optimization purpose if ( !InitializeConfiguration() ) return; - //SetSplashScreenProgress(20); + SetSplashScreenProgress(30); // set static variable to enabled/disable crash reporter retrieveCrashReporterState(); @@ -1517,10 +1518,10 @@ void Desktop::Main() #endif SetDisplayName( aTitle ); -// SetSplashScreenProgress(30); + SetSplashScreenProgress(35); RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" ); pPathOptions = new SvtPathOptions; -// SetSplashScreenProgress(40); + SetSplashScreenProgress(40); // pLanguageOptions = new SvtLanguageOptions(sal_True); // SetSplashScreenProgress(45); RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" ); @@ -1600,7 +1601,7 @@ void Desktop::Main() OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); if (xDesktopFrame.is()) { -// SetSplashScreenProgress(60); + SetSplashScreenProgress(60); Reference< XFrame > xBackingFrame; Reference< ::com::sun::star::awt::XWindow > xContainerWindow; @@ -1616,7 +1617,7 @@ void Desktop::Main() Reference< XController > xBackingComp( xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), UNO_QUERY); -// SetSplashScreenProgress(80); + SetSplashScreenProgress(80); if (xBackingComp.is()) { Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); @@ -1659,7 +1660,7 @@ void Desktop::Main() return; } */ -// SetSplashScreenProgress(55); + SetSplashScreenProgress(55); SvtFontSubstConfig().Apply(); @@ -1668,7 +1669,7 @@ void Desktop::Main() aAppearanceCfg.SetApplicationDefaults( this ); SvtAccessibilityOptions aOptions; aOptions.SetVCLSettings(); -// SetSplashScreenProgress(60); + SetSplashScreenProgress(60); Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) ); @@ -1691,7 +1692,7 @@ void Desktop::Main() // use system window dialogs Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG ); -// SetSplashScreenProgress(80); + SetSplashScreenProgress(80); if ( !bTerminateRequested && !pCmdLineArgs->IsInvisible() ) InitializeQuickstartMode( xSMgr ); Index: desktop/source/app/cmdlineargs.cxx =================================================================== RCS file: /cvs/framework/desktop/source/app/cmdlineargs.cxx,v retrieving revision 1.28 retrieving revision 1.28.62.1 diff -u -p -u -p -r1.28 -r1.28.62.1 --- desktop/source/app/cmdlineargs.cxx 8 Sep 2005 17:05:40 -0000 1.28 +++ desktop/source/app/cmdlineargs.cxx 16 Mar 2006 17:31:02 -0000 1.28.62.1 @@ -412,6 +412,11 @@ sal_Bool CommandLineArgs::InterpretComma SetBoolParam_Impl( CMD_BOOLPARAM_HELPMATH, sal_True ); return sal_True; } + else if ( aArgStr.Copy(0, 13).EqualsIgnoreCaseAscii( "-splash-pipe=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_SPLASHPIPE, aArgStr.Copy( 13 ) ); + return sal_True; + } else if ( aArgStr.Copy(0, 8).EqualsIgnoreCaseAscii( "-accept=" )) { AddStringListParam_Impl( CMD_STRINGPARAM_ACCEPT, aArgStr.Copy( 8 ) ); @@ -861,7 +866,9 @@ sal_Bool CommandLineArgs::IsEmptyOrAccep { osl::MutexGuard aMutexGuard( m_aMutex ); - return m_bEmpty || ( ( m_nArgumentCount == 1 ) && ( m_aStrParams[ CMD_STRINGPARAM_ACCEPT ].getLength() ) ); + return m_bEmpty || + ( ( m_nArgumentCount == 1 ) && ( m_aStrParams[ CMD_STRINGPARAM_SPLASHPIPE ].getLength() ) ) || + ( ( m_nArgumentCount == 1 ) && ( m_aStrParams[ CMD_STRINGPARAM_ACCEPT ].getLength() ) ); } } // namespace desktop Index: desktop/source/app/cmdlineargs.hxx =================================================================== RCS file: /cvs/framework/desktop/source/app/cmdlineargs.hxx,v retrieving revision 1.22 retrieving revision 1.22.62.1 diff -u -p -u -p -r1.22 -r1.22.62.1 --- desktop/source/app/cmdlineargs.hxx 8 Sep 2005 17:06:04 -0000 1.22 +++ desktop/source/app/cmdlineargs.hxx 16 Mar 2006 17:31:02 -0000 1.22.62.1 @@ -89,6 +89,7 @@ class CommandLineArgs enum StringParam // must be zero based! { CMD_STRINGPARAM_PORTAL, + CMD_STRINGPARAM_SPLASHPIPE, CMD_STRINGPARAM_ACCEPT, CMD_STRINGPARAM_UNACCEPT, CMD_STRINGPARAM_USERDIR, Index: desktop/source/splash/splash.cxx =================================================================== RCS file: /cvs/framework/desktop/source/splash/splash.cxx,v retrieving revision 1.17 retrieving revision 1.17.52.2 diff -u -p -u -p -r1.17 -r1.17.52.2 --- desktop/source/splash/splash.cxx 27 Jan 2006 16:22:01 -0000 1.17 +++ desktop/source/splash/splash.cxx 16 Mar 2006 17:37:19 -0000 1.17.52.2 @@ -82,11 +82,37 @@ SplashScreen::SplashScreen(const Referen , _yoffset(18) , _barheight(-1) , _barspace(2) + , _bVisible( FALSE ) + , _outFd(NULL) { _rFactory = rSMgr; - loadConfig(); +#ifdef UNX + ::vos::OStartupInfo aInfo; +#define PIPE_ARG "-splash-pipe=" + for (sal_uInt32 i = 0; i < aInfo.getCommandArgCount(); i++) + { + rtl::OUString aArg; + if (aInfo.getCommandArg (i, aArg)) + break; + if (aArg.matchIgnoreAsciiCaseAsciiL (PIPE_ARG, sizeof (PIPE_ARG) - 1, 0)) + { + OUString aNum = aArg.copy (sizeof (PIPE_ARG) - 1); + int fd = aNum.toInt32(); + _outFd = fdopen (fd, "w"); +/* fprintf (stderr, "Got argument '-splash-pipe=%d ('%s') (%p)\n", + fd, (const sal_Char *)rtl::OUStringToOString (aNum, RTL_TEXTENCODING_UTF8), + _outFd); */ + } + } +#endif + + if (!doRender()) + return; + + loadConfig(); initBitmap(); + Size aSize = _aIntroBmp.GetSizePixel(); SetOutputSizePixel( aSize ); _vdev.SetOutputSizePixel( aSize ); @@ -139,10 +165,18 @@ SplashScreen::SplashScreen(const Referen SplashScreen::~SplashScreen() { + if (!doRender()) + return; Application::RemoveEventListener( LINK( this, SplashScreen, AppEventListenerHdl ) ); - Hide(); + if (_bVisible) Hide(); +#ifdef UNX + if (!doRender()) { + fclose (_outFd); + _outFd = NULL; + } +#endif } void SAL_CALL SplashScreen::start(const OUString& aText, sal_Int32 nRange) @@ -161,6 +195,13 @@ void SAL_CALL SplashScreen::end() _iProgress = _iMax; updateStatus(); if (_bVisible) Hide(); +#ifdef UNX + if (!doRender()) { +/* fprintf (stderr, "SplashScreen::end()\n"); */ + fprintf (_outFd, "end\n"); + fflush (_outFd); + } +#endif } void SAL_CALL SplashScreen::reset() throw (RuntimeException) @@ -185,6 +226,13 @@ void SAL_CALL SplashScreen::setValue(sal RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue ); ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); +#ifdef UNX + if (!doRender()) + { + fprintf (_outFd, "%d%%\n", nValue); + fflush (_outFd); + } +#endif if (_bVisible) { Show(); if (nValue >= _iMax) _iProgress = _iMax; @@ -199,7 +247,7 @@ SplashScreen::initialize( const ::com::s throw (RuntimeException) { ::osl::ClearableMutexGuard aGuard( _aMutex ); - if (aArguments.getLength() > 0) + if (aArguments.getLength() > 0 && doRender()) aArguments[0] >>= _bVisible; } Index: desktop/source/splash/splash.hxx =================================================================== RCS file: /cvs/framework/desktop/source/splash/splash.hxx,v retrieving revision 1.9 retrieving revision 1.9.62.1 diff -u -p -u -p -r1.9 -r1.9.62.1 --- desktop/source/splash/splash.hxx 8 Sep 2005 17:50:08 -0000 1.9 +++ desktop/source/splash/splash.hxx 16 Mar 2006 17:06:41 -0000 1.9.62.1 @@ -33,6 +33,8 @@ * ************************************************************************/ +#include + #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ #include #endif @@ -113,9 +115,12 @@ private: sal_Bool _bPaintBitmap; sal_Bool _bPaintProgress; sal_Bool _bVisible; + FILE *_outFd; long _height, _width, _tlx, _tly, _barwidth; long _barheight, _barspace; const long _xoffset, _yoffset; + + bool doRender() { return _outFd == NULL; }; public: static const char* interfaces[]; Index: desktop/unx/source/makefile.mk =================================================================== RCS file: desktop/unx/source/makefile.mk diff -N desktop/unx/source/makefile.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ desktop/unx/source/makefile.mk 16 Mar 2006 17:27:52 -0000 1.1.2.1 @@ -0,0 +1,32 @@ +PRJ=..$/.. +PRJNAME=desktop +TARGET=ooqstart + +NO_DEFAULT_STL=TRUE + +.INCLUDE : settings.mk + +.IF "$(ENABLE_GTK)" != "TRUE" +dummy: + @echo "Nothing to build. GUIBASE == $(GUIBASE), WITH_WIDGETSET == $(WITH_WIDGETSET)" + +.ELSE # we need glib... + +PKGCONFIG_MODULES=glib-2.0 +.INCLUDE: pkg_config.mk + +CFLAGS+= $(PKGCONFIG_CFLAGS) +STDLIB= + +APP1TARGET = $(TARGET) +APP1OBJS = $(OBJ)$/splashx.obj $(OBJ)$/start.obj +APP1NOSAL = TRUE +APP1LIBSALCPPRT= +APP1CODETYPE = C +APP1STDLIBS = $(PKGCONFIG_LIBS) -lX11 + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk Index: desktop/unx/source/splashx.c =================================================================== RCS file: desktop/unx/source/splashx.c diff -N desktop/unx/source/splashx.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ desktop/unx/source/splashx.c 16 Mar 2006 17:27:52 -0000 1.1.2.1 @@ -0,0 +1,528 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile$ + * + * $Revision$ + * + * last change: $Author$ $Date$ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "splashx.h" + +#define WINDOW_WIDTH 440 +#define WINDOW_HEIGHT 299 + +#define PROGRESS_XOFFSET 12 +#define PROGRESS_YOFFSET 18 +#define PROGRESS_BARSPACE 2 + +static Display *display = NULL; +static int screen; +static int depth; +static Visual *visual = NULL; + +static int width = WINDOW_WIDTH; +static int height = WINDOW_HEIGHT; + +static Colormap color_map; +static Window win; +static GC gc; + +typedef struct { + unsigned char b, g, r; +} color_t; +static color_t *bitmap = NULL; + +#define BMP_HEADER_LEN 14 +#define WIN_INFO_LEN 40 + +#define UINT8( x ) ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + +#define UINT16( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) ) + +#define UINT32( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[2] ) ) << 16 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[3] ) ) << 24 ) ) + +#define MAX( x, y ) ( ( (x) > (y) )? (x): (y) ) + +#define LOAD_FAILURE( msg ) \ + { \ + fprintf( stderr, "%s: " msg, filename ); \ + close( fd ); \ + return 0; \ + } + +// Load the specified Windows 24bit BMP to 'bitmap' +// Return: 1 - success, 0 - failure +int splash_load_bmp( char *filename ) +{ + int fd = open( filename, O_RDONLY ); + if ( fd < 0 ) + return 0; + + char file_header[ BMP_HEADER_LEN ]; + + if ( read( fd, file_header, BMP_HEADER_LEN ) != BMP_HEADER_LEN || file_header[0] != 'B' || file_header[1] != 'M' ) + LOAD_FAILURE( "Not a bitmap.\n" ); + + int file_size = UINT32( file_header + 2 ); + + char info_header[ WIN_INFO_LEN ]; + if ( read( fd, info_header, 4 ) != 4 ) + LOAD_FAILURE( "Unable to read the header.\n" ); + + int header_size = UINT32( info_header ); + if ( header_size != WIN_INFO_LEN ) + LOAD_FAILURE( "Not a Windows bitmap.\n" ); + + if ( read( fd, info_header + 4, WIN_INFO_LEN - 4 ) != WIN_INFO_LEN - 4 ) + LOAD_FAILURE( "The header ended too early.\n" ); + + width = UINT32( info_header + 4 ); + height = UINT32( info_header + 8 ); + + int bits = UINT16( info_header + 14 ); + int compression = UINT16( info_header + 16 ); + + if ( bits != 24 ) + LOAD_FAILURE( "Just 24 bpp bitmaps are supported.\n" ); + + if ( compression != 0 ) + LOAD_FAILURE( "Just uncompressed bitmaps are supported.\n" ); + + size_t bitmap_size = width * height * 3; + bitmap = malloc( bitmap_size ); + if ( bitmap == NULL ) + LOAD_FAILURE( "Cannot allocate memory for the data.\n" ); + + int y; + size_t line_size = width * 3; + color_t *line = bitmap + ( height - 1 ) * width; + for ( y = height; y > 0; --y, line -= width ) + { + if ( read( fd, line, line_size ) != line_size ) + LOAD_FAILURE( "Cannot read the bitmap data.\n" ); + } + + close( fd ); + return 1; +} + +// Universal shift: bits >= 0 - left, otherwise right +#define SHIFT( x, bits ) ( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) ) + +// Position of the highest bit (more or less integer log2) +inline int HIGHEST_BIT( unsigned long x ) +{ + int i = 0; + for ( ; x; ++i ) + x >>= 1; + + return i; +} + +// Number of bits set to 1 +inline int BITS( unsigned long x ) +{ + int i = 0; + for ( ; x; x >>= 1 ) + if ( x & 1UL ) + ++i; + + return i; +} + +// Set 'bitmap' as the background of our 'win' window +static void create_pixmap() +{ + if ( !bitmap ) + return; + + Pixmap pixmap = XCreatePixmap( display, win, width, height, depth ); + + unsigned long value_mask = 0; + XGCValues values; + GC pixmap_gc = XCreateGC( display, pixmap, value_mask, &values ); + + if ( visual->class == TrueColor ) + { + unsigned long red_mask = visual->red_mask; + unsigned long green_mask = visual->green_mask; + unsigned long blue_mask = visual->blue_mask; + + unsigned long red_delta_mask = ( 1UL << ( 8 - BITS( red_mask ) ) ) - 1; + unsigned long green_delta_mask = ( 1UL << ( 8 - BITS( green_mask ) ) ) - 1; + unsigned long blue_delta_mask = ( 1UL << ( 8 - BITS( blue_mask ) ) ) - 1; + + int red_shift = HIGHEST_BIT( red_mask ) - 8; + int green_shift = HIGHEST_BIT( green_mask ) - 8; + int blue_shift = HIGHEST_BIT( blue_mask ) - 8; + + XImage *image = XCreateImage( display, visual, depth, ZPixmap, + 0, NULL, width, height, 32, 0 ); + + int bytes_per_line = image->bytes_per_line; + int bpp = image->bits_per_pixel; + int byte_order = image->byte_order; + int machine_byte_order = ( __BYTE_ORDER == __LITTLE_ENDIAN )? LSBFirst: MSBFirst; + + if ( __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN ) + { + fprintf( stderr, "Unsupported machine endianity.\n" ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } + + char *data = malloc( height * bytes_per_line ); + image->data = data; + + // The following dithers & converts the color_t color to one + // acceptable for the visual +#define COPY_IN_OUT( code ) \ + { \ + int x, y; \ + for ( y = 0; y < height; ++y ) \ + { \ + unsigned long red_delta = 0, green_delta = 0, blue_delta = 0; \ + for ( x = 0; x < width; ++x, ++in ) \ + { \ + unsigned long red = in->r + red_delta; \ + unsigned long green = in->g + green_delta; \ + unsigned long blue = in->b + blue_delta; \ + red_delta = red & red_delta_mask; \ + green_delta = green & green_delta_mask; \ + blue_delta = blue & blue_delta_mask; \ + if ( red > 255 ) \ + red = 255; \ + if ( green > 255 ) \ + green = 255; \ + if ( blue > 255 ) \ + blue = 255; \ + unsigned long pixel = \ + ( SHIFT( red, red_shift ) & red_mask ) | \ + ( SHIFT( green, green_shift ) & green_mask ) | \ + ( SHIFT( blue, blue_shift ) & blue_mask ); \ + code \ + } \ + } \ + } + + color_t *in = bitmap; + char *out = data; + + if ( bpp == 32 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( *( (uint32_t *)out ) = (uint32_t)pixel; out += 4; ) + else + COPY_IN_OUT( uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 3 ) = *( (uint8_t *)(&tmp) ); + out += 4; ) + } + else if ( bpp == 24 ) + { + if ( machine_byte_order == byte_order && byte_order == LSBFirst ) + COPY_IN_OUT( *( (color_t *)out ) = *( (color_t *)( &pixel ) ); out += 3; ) + if ( machine_byte_order == byte_order && byte_order == MSBFirst ) + COPY_IN_OUT( uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 3 ); + out += 3; ) + else + COPY_IN_OUT( uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + out += 3; ) + } + else if ( bpp == 16 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( *( (uint16_t *)out ) = (uint16_t)pixel; out += 2; ) + else + COPY_IN_OUT( uint16_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) ); + out += 2; ); + } + else if ( bpp == 8 ) + { + COPY_IN_OUT( *( (uint8_t *)out ) = (uint8_t)pixel; ++out; ) + } + else + { + fprintf( stderr, "Unsupported depth: %d bits per pixel.\n", bpp ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } + +#undef COPY_IN_OUT + + XPutImage( display, pixmap, pixmap_gc, image, 0, 0, 0, 0, width, height ); + XDestroyImage( image ); + } + else //if ( depth == 1 || visual->class == DirectColor ) + { + // FIXME Something like the following, but faster ;-) - XDrawPoint is not + // a good idea... + int x, y; + for ( y = 0; y < height; ++y ) + { + color_t *color = bitmap + y * width; + + int delta = 0; + for ( x = 0; x < width; ++x, ++color ) + { + int rnd = (int)( ( (long)( random() - RAND_MAX/2 ) * 32000 )/RAND_MAX ); + int luminance = delta + rnd + 299 * (int)color->r + 587 * (int)color->g + 114 * (int)color->b; + + if ( luminance < 128000 ) + { + XSetForeground( display, pixmap_gc, BlackPixel( display, screen ) ); + delta = luminance; + } + else + { + XSetForeground( display, pixmap_gc, WhitePixel( display, screen ) ); + delta = luminance - 255000; + } + + XDrawPoint( display, pixmap, pixmap_gc, x, y ); + } + } + } + + XSetWindowBackgroundPixmap( display, win, pixmap ); + + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); +} + +// The old method of hiding the window decorations +static void suppress_decorations_motif() +{ + struct { + unsigned long flags, functions, decorations; + long input_mode; + unsigned long status; + } mwmhints; + + Atom a = XInternAtom( display, "_MOTIF_WM_HINTS", False ); + + mwmhints.flags = 15; // functions, decorations, input_mode, status + mwmhints.functions = 2; // ? + mwmhints.decorations = 0; + mwmhints.input_mode = 0; + + XChangeProperty( display, win, a, a, 32, + PropModeReplace, (unsigned char*)&mwmhints, 5 ); +} + +// This is a splash, set it as such. +// If it fails, just hide the decorations... +static void suppress_decorations() +{ + Atom atom_type = XInternAtom( display, "_NET_WM_WINDOW_TYPE", True ); + Atom atom_splash = XInternAtom( display, "_NET_WM_WINDOW_TYPE_SPLASH", True ); + + if ( atom_type != None && atom_splash != None ) + XChangeProperty( display, win, atom_type, XA_ATOM, 32, + PropModeReplace, (unsigned char*)&atom_splash, 1 ); + //else + suppress_decorations_motif(); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed +} + +// Create the window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ) +{ + char *display_name = NULL; + int i; + for ( i = 0; i < argc; i++ ) + { + if ( !strcmp( argv[i], "-display" ) || !strcmp( argv[i], "--display" ) ) + display_name = ( i + 1 < argc )? argv[i+1]: NULL; + } + + if ( !display_name ) + display_name = getenv( "DISPLAY" ); + + // init display + display = XOpenDisplay( display_name ); + if ( !display ) + { + fprintf( stderr, "Failed to open display\n" ); + return 0; + } + + // create the window + screen = DefaultScreen( display ); + depth = DefaultDepth( display, screen ); + color_map = DefaultColormap( display, screen ); + visual = DefaultVisual( display, screen ); + + Window root_win = RootWindow( display, screen ); + int display_width = DisplayWidth( display, screen ); + int display_height = DisplayHeight( display, screen ); + + win = XCreateSimpleWindow( display, root_win, + ( display_width - width ) / 2, ( display_height - height ) / 2, + width, height, 0, + BlackPixel( display, screen ), BlackPixel( display, screen ) ); + + XSetWindowColormap( display, win, color_map ); + + // FIXME Do we want an own colormap for 8bpp displays? + + // not resizable, no decorations, etc. + unsigned long value_mask = 0; + XGCValues values; + gc = XCreateGC( display, win, value_mask, &values ); + + XSizeHints size_hints; + size_hints.flags = PPosition | PSize | PMinSize | PMaxSize; + size_hints.min_width = width; + size_hints.max_width = width; + size_hints.min_height = height; + size_hints.max_height = height; + + char *name = "OpenOffice.org"; + char *icon = "icon"; // FIXME + + XSetStandardProperties( display, win, name, icon, None, + 0, 0, &size_hints ); + + // the actual work + suppress_decorations(); + create_pixmap(); + + // show it + XSelectInput( display, win, 0 ); + XMapWindow( display, win ); + + return 1; +} + +// Re-draw & rocess the events +// Just throwing them away - we do not need anything more... +static void process_events() +{ + XEvent xev; + int num_events; + + XFlush( display ); + num_events = XPending( display ); + while ( num_events > 0 ) + { + num_events--; + XNextEvent( display, &xev ); + //process_event(xev); + } +} + +// Draw the progress +void splash_draw_progress( int progress ) +{ + // values taken from desktop/source/splash/splash.cxx + static int tlx = 212; + static int tly = 216; + static int barwidth = 263; + static int barheight = 8; + static int barspace = PROGRESS_BARSPACE; + static int initialized = 0; + if ( !initialized ) + { + if ( width <= 500) + { + barwidth = width - (2 * PROGRESS_XOFFSET); + barheight = 6; + tlx = PROGRESS_XOFFSET; + tly = height - PROGRESS_YOFFSET; + } + initialized = 1; + } + + // sanity + if ( progress < 0 ) + progress = 0; + if ( progress > 100 ) + progress = 100; + + // draw progress... + int length = ( progress * barwidth / 100 ) - ( 2 * barspace ); + if (length < 0) + length = 0; + + // border + XSetForeground( display, gc, WhitePixel( display, screen ) ); + XDrawRectangle( display, win, gc, + tlx, tly, + barwidth, barheight ); + + // progress bar + XSetForeground( display, gc, WhitePixel( display, screen ) ); + XFillRectangle( display, win, gc, + tlx + barspace, tly + barspace, + length + 1, barheight - 2*barspace + 1 ); + + // pending events + process_events(); +} + +// Close the window & cleanup +void splash_close_window() +{ + XCloseDisplay( display ); + + free( bitmap ); + bitmap = NULL; +} Index: desktop/unx/source/splashx.h =================================================================== RCS file: desktop/unx/source/splashx.h diff -N desktop/unx/source/splashx.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ desktop/unx/source/splashx.h 16 Mar 2006 17:27:52 -0000 1.1.2.1 @@ -0,0 +1,58 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile$ + * + * $Revision$ + * + * last change: $Author$ $Date$ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _SPLASHX_H +#define _SPLASHX_H + +// Load the specified Windows 24bit BMP we can have as a background of the +// splash. +// +// Note: Must be called before the create_window(), otherwise there will be no +// image in the splash, just black rectangle. +// +// Return: 1 - success, 0 - failure (non-existing, etc.) +int splash_load_bmp( char *filename ); + +// Create the splash window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ); + +// Destroy the splash window +void splash_close_window(); + +// Update the progress bar +void splash_draw_progress( int progress ); + +#endif // _SPLASHX_H Index: desktop/unx/source/start.c =================================================================== RCS file: desktop/unx/source/start.c diff -N desktop/unx/source/start.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ desktop/unx/source/start.c 16 Mar 2006 17:29:08 -0000 1.1.2.2 @@ -0,0 +1,496 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile$ + * + * $Revision$ + * + * last change: $Author$ $Date$ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PIPEDEFAULTPATH "/tmp" +#define PIPEALTERNATEPATH "/var/tmp" + +static char * +read_path_and_chomp (const char *app) +{ + int len; + char buffer[PATH_MAX]; + + /* Readlink on argv[0] to point to the install path */ + if ((len = readlink (app, buffer, sizeof(buffer))) < 0) + return NULL; + buffer[MIN(len, 4095)] = '\0'; + + return g_path_get_dirname (buffer); +} + +static char * +get_app_path (const char *app_exec) +{ + if (app_exec[0] != '/') + g_error ("%s must be called with an absolute path\n", app_exec); + + return g_path_get_dirname (app_exec); +} + +/* OO.o likes to find real paths, unwinding symlinks etc. */ +static char * +get_real_app_path (const char *app_path) +{ + char *path, *bin_path; + + path = g_strdup (app_path); + + /* Hack for use with linkoo: follow soffice.bin + if it is a symlink */ + bin_path = g_strconcat (app_path, "/soffice.bin", NULL); + if (g_file_test (bin_path, G_FILE_TEST_IS_SYMLINK)) + { + g_free (path); + path = read_path_and_chomp (bin_path); + } + g_free (bin_path); + + /* Nasty - but OO.o likes to call realpath too ... */ + char *real_path = (char *)g_malloc (PATH_MAX + 1); + realpath (path, real_path); + real_path[PATH_MAX] = '\0'; + g_free (path); + + return real_path; +} + +static char * +get_pipe_path (const char *app_path) +{ + char *pipe_path; + char *real_app_path; + char *terminated_path; + const char *base_path; + + real_app_path = get_real_app_path (app_path); + terminated_path = g_strconcat (real_app_path, "/", NULL); + + if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) + base_path = PIPEDEFAULTPATH; + else + base_path = PIPEALTERNATEPATH; + + pipe_path = g_strdup_printf ( + "%s/OSL_PIPE_%u_SingleOfficeIPC_%d-%x", base_path, (int)getuid(), + SUPD, g_str_hash (terminated_path)); + +/* fprintf (stderr, "pipe path is '%s' from '%s'\n", pipe_path, real_app_path); */ + + g_free (terminated_path); + g_free (real_app_path); + + return pipe_path; +} + +static int +connect_pipe (const char *pipe_path) +{ + int fd; + size_t len; + struct sockaddr_un addr; + + memset(&addr, 0, sizeof(addr)); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return fd; + + fcntl (fd, F_SETFD, FD_CLOEXEC); + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, pipe_path, sizeof(addr.sun_path)); + +/* cut / paste from osl's pipe.c */ +#if defined(FREEBSD) + len = SUN_LEN(&addr); +#else + len = sizeof(addr); +#endif + + if (connect (fd, (struct sockaddr *)&addr, len) < 0) + return -1; + + return fd; +} + +static gboolean +send_args (int fd, GPtrArray *args, const char *cwd) +{ + int i, len; + GString *arg_str = g_string_new (""); + + for (i = 1; i < args->len; i++) + { + g_string_append (arg_str, (char *)args->pdata[i]); + g_string_append_c (arg_str, '|'); + } + +#ifdef DEBUG + fprintf (stderr, "Pass args: '%s'\n", arg_str->str); +#endif + len = arg_str->len + 1; + + return write (fd, arg_str->str, len) == len; +} + +typedef struct { + gboolean finish; + gboolean error; + int percent; +} StatusClosure; + +static gboolean +status_pipe_update (GIOChannel * source, + GIOCondition condition, + StatusClosure *cl) +{ + gboolean retval = TRUE; + +#ifdef DEBUG + fprintf (stderr, "Status pipe update (0x%x)\n", (int) condition); +#endif + + if ((int)condition & (G_IO_IN | G_IO_PRI)) + { + int percent; + GString *str = g_string_new (""); + switch (g_io_channel_read_line_string (source, str, NULL, NULL)) { + case G_IO_STATUS_ERROR: + cl->error = TRUE; + /* drop through */ + case G_IO_STATUS_EOF: + retval = FALSE; + break; + default: + /* pipe lifecycle is odd - HUP only for remote process death */ + if (!g_ascii_strncasecmp (str->str, "end", 3)) + retval = FALSE; + if (sscanf (str->str, "%d%%", &percent)) + cl->percent = percent; + break; + } + g_string_free (str, TRUE); + } + + if ((int)condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR)) + { + cl->error = TRUE; + retval = FALSE; + } + + if (!retval) + cl->finish = TRUE; + + return retval; +} + +static void +load_splash_image (const char *image_path) +{ + char *path; + int success; + +// path = g_strconcat (image_path, "/intro-nld.bmp", NULL); +// success = splash_load_bmp (path); +// g_free (path); +// if (success) +// return; + + path = g_strconcat (image_path, "/intro.bmp", NULL); + success = splash_load_bmp (path); + g_free (path); +} + +static void +show_splash (GIOChannel *status_channel) +{ + StatusClosure cl; + + /* setup closure */ + cl.finish = FALSE; + cl.error = FALSE; + cl.percent = 0; + + /* setup status listener ... */ + g_io_add_watch (status_channel, + (GIOCondition)(G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_NVAL | G_IO_ERR), + (GIOFunc) status_pipe_update, (gpointer) &cl); + +#ifdef DEBUG + g_warning ("Start main loop...\n"); +#endif + while (!cl.finish) + { + splash_draw_progress (cl.percent); + if ( g_main_context_pending (g_main_context_default ()) ) + g_main_context_iteration (g_main_context_default (), TRUE); + else + usleep (20000); + } + + if (cl.error) + g_warning ("Unknown error forking main binary / abnormal early exit ..."); + + g_io_channel_shutdown (status_channel, FALSE, NULL); + g_io_channel_unref (status_channel); +} + +typedef struct { + int pipe_fd; + int clone_fd; +} ChildClosure; + +static void +child_setup (gpointer user_data) +{ + ChildClosure *cl = (ChildClosure *)user_data; + if (cl->pipe_fd >= 0) + close (cl->pipe_fd); + close (cl->clone_fd); +} + +static void +system_checks (void) +{ +#ifdef LINUX + /* check proc is mounted - lots of things fail otherwise */ + if (!g_file_test ("/proc/version", G_FILE_TEST_EXISTS)) + g_warning ("/proc not mounted - OO.o is unlikely to work well if at all"); +#endif +} + +static gboolean +fork_app (const char *app_path, GPtrArray *args, int pipe_fd, + GIOChannel **status_channel) +{ + int status_pipe[2]; + gboolean spawn_success; + GError *error = NULL; + char *splash_pipe_arg; + ChildClosure *cl = g_new (ChildClosure, 1); + GIOChannel *status; + + system_checks (); + + args->pdata[0] = (gpointer)g_strconcat (app_path, "/soffice", NULL); + + /* create pipe */ + if (pipe (status_pipe) < 0) + g_error ("no file handles\n"); + + status = g_io_channel_unix_new (status_pipe[0]); + g_io_channel_set_encoding (status, NULL, NULL); + + splash_pipe_arg = g_strdup_printf ("-splash-pipe=%d", status_pipe[1]); +#ifdef DEBUG + fprintf ( stderr, "Pass splash pipe arg: '%s'\n", splash_pipe_arg); +#endif + g_ptr_array_add (args, splash_pipe_arg); + +#ifdef DEBUG + fprintf (stderr, "Fork app '%s' in '%s'\n", (char *)args->pdata[0], app_path); +#endif + cl->pipe_fd = pipe_fd; + cl->clone_fd = status_pipe[0]; + spawn_success = g_spawn_async + (app_path, (char **)args->pdata, NULL, + G_SPAWN_LEAVE_DESCRIPTORS_OPEN, + (GSpawnChildSetupFunc) child_setup, + (gpointer) cl, + NULL, /* child_pid */ + &error); + close (status_pipe[1]); + + if (!spawn_success) + fprintf (stderr, "Error forking '%s/%s': '%s'\n", + app_path, "/soffice", + error ? error->message : ""); + + *status_channel = status; + + return spawn_success; +} + +static char * +convert_path (const char *arg, const char *cwd_str, gboolean not_filename) +{ + if (arg[0] == '-' || not_filename) + return g_strdup (arg); + + if (strstr (arg, "://")) /* is URI */ + return g_strdup (arg); + + if (arg[0] == '/') /* absolute path */ + return g_strdup (arg); + + if (!strncmp (arg, "slot:", 5)) /* a slot */ + return g_strdup (arg); + + /* prepend cwd ... */ + return g_strconcat (cwd_str, "/", arg, NULL); +} + +static gboolean +arg_check (const char *arg, const char *cmp_with) +{ + if (arg[0] == '-') + arg++; + else + return FALSE; + if (arg[0] == '-') /* tolerate -- prefixes etc. */ + arg++; + return !g_ascii_strcasecmp (arg, cmp_with); +} + +static GPtrArray * +setup_args (int argc, char **argv, const char *cwd_str, + gboolean *inhibit_splash) +{ + int i; + gboolean have_non_option = FALSE; + gboolean next_arg_not_filename = FALSE; + GPtrArray *args = g_ptr_array_sized_new (argc + 8); + + *inhibit_splash = FALSE; + + for (i = 0; i < argc; i++) + { + char *converted; + + if (i) + converted = convert_path (argv[i], cwd_str, next_arg_not_filename); + else + converted = g_strdup (argv[i]); + g_ptr_array_add (args, converted); + + if (!i) + continue; + + if (argv[i][0] != '-') + have_non_option = TRUE; + + else if (arg_check (argv[i], "nologo") || + arg_check (argv[i], "headless") || + arg_check (argv[i], "invisible")) + *inhibit_splash = TRUE; + + else if (arg_check (argv[i], "-pt")) + next_arg_not_filename = TRUE; + } + + /* It's necessary to append eg. -writer for writer. */ + if (!have_non_option) + { + const char *extra_arg = g_getenv ("OOO_EXTRA_ARG"); + if (!extra_arg) + g_error ("Missing default argument in OOO_EXTRA_ARG"); + if (extra_arg[0] != '\0') + g_ptr_array_add (args, g_strdup (extra_arg)); + } + + return args; +} + +int main (int argc, char **argv) +{ + int fd; + gboolean inhibit_splash; + GIOChannel *status_channel = NULL; + gboolean sent_args = FALSE; + char *app_path, *pipe_path; + GPtrArray *args; + char cwd_str[PATH_MAX]; + + /* turn SIGPIPE into an error */ + signal (SIGPIPE, SIG_IGN); + if (!getcwd (cwd_str, sizeof (cwd_str))) + g_error ("can't get cwd"); + cwd_str[sizeof(cwd_str)-1] = '\0'; + + args = setup_args (argc, argv, cwd_str, &inhibit_splash); + + app_path = get_app_path (argv[0]); + if (!app_path) + g_error ("Pathalogical failure: can't read app link\n"); + + load_splash_image (app_path); + + pipe_path = get_pipe_path (app_path); + + if ((fd = connect_pipe (pipe_path)) >= 0) + sent_args = send_args (fd, args, cwd_str); +#ifdef DEBUG + else + fprintf (stderr, "Failed to connect to pipe '%s'\n", pipe_path); +#endif + + if (!sent_args) + { + if (!inhibit_splash) + { + if (splash_create_window (argc, argv)) + splash_draw_progress (0); + else + inhibit_splash = TRUE; + } + + if (! fork_app (app_path, args, fd, &status_channel)) + return 1; + + if (!inhibit_splash) + { + show_splash (status_channel); + splash_close_window (); + } + } + + g_ptr_array_foreach (args, (GFunc)g_free, NULL); + g_ptr_array_free (args, TRUE); + g_free (app_path); + + return 0; +}