summaryrefslogtreecommitdiff
path: root/vcl/unx/source/app/saldata.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/source/app/saldata.cxx')
-rw-r--r--vcl/unx/source/app/saldata.cxx854
1 files changed, 854 insertions, 0 deletions
diff --git a/vcl/unx/source/app/saldata.cxx b/vcl/unx/source/app/saldata.cxx
new file mode 100644
index 000000000000..4519e75fd56f
--- /dev/null
+++ b/vcl/unx/source/app/saldata.cxx
@@ -0,0 +1,854 @@
+/*************************************************************************
+ *
+ * $RCSfile: saldata.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:42 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SALDATA_CXX
+
+#ifdef USE_XTOOLKIT
+# define SAL_XT
+#endif
+
+// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/resource.h>
+#ifdef SUN
+#include <sys/systeminfo.h>
+#endif
+#ifdef AIX
+#include <strings.h>
+#endif
+
+#include <prex.h>
+#include <X11/Shell.h>
+#include <X11/Xproto.h>
+#include <postx.h>
+
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+
+#include <salunx.h>
+
+#ifndef _SV_SALDISP_HXX
+#include <saldisp.hxx>
+#endif
+#ifndef _SV_SALDATA_HXX
+#include <saldata.hxx>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _OSL_SIGNAL_H_
+#include <osl/signal.h>
+#endif
+#ifndef _OSL_THREAD_H_
+#include <osl/thread.h>
+#endif
+#ifndef _OSL_PROCESS_H_
+#include <osl/process.h>
+#endif
+
+#include <tools/debug.hxx>
+
+#ifndef _SAL_I18N_INPUTMETHOD_HXX
+#include "i18n_im.hxx"
+#endif
+#ifndef _SAL_I18N_XKBDEXTENSION_HXX
+#include "i18n_xkb.hxx"
+#endif
+
+// -=-= <signal.h> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#ifndef UNX
+#ifndef SIGBUS
+#define SIGBUS 10
+#endif
+#ifndef SIGSEGV
+#define SIGSEGV 11
+#endif
+#ifndef SIGIOT
+#define SIGIOT SIGABRT
+#endif
+#endif
+
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+static const struct timeval noyield = { 0, 0 };
+static const struct timeval yield = { 0, 10000 };
+static const struct fd_set ZeroFDS = { 0 };
+static const char* XRequest[] = {
+ // see /usr/lib/X11/XErrorDB, /usr/openwin/lib/XErrorDB ...
+ NULL,
+ "X_CreateWindow",
+ "X_ChangeWindowAttributes",
+ "X_GetWindowAttributes",
+ "X_DestroyWindow",
+ "X_DestroySubwindows",
+ "X_ChangeSaveSet",
+ "X_ReparentWindow",
+ "X_MapWindow",
+ "X_MapSubwindows",
+ "X_UnmapWindow",
+ "X_UnmapSubwindows",
+ "X_ConfigureWindow",
+ "X_CirculateWindow",
+ "X_GetGeometry",
+ "X_QueryTree",
+ "X_InternAtom",
+ "X_GetAtomName",
+ "X_ChangeProperty",
+ "X_DeleteProperty",
+ "X_GetProperty",
+ "X_ListProperties",
+ "X_SetSelectionOwner",
+ "X_GetSelectionOwner",
+ "X_ConvertSelection",
+ "X_SendEvent",
+ "X_GrabPointer",
+ "X_UngrabPointer",
+ "X_GrabButton",
+ "X_UngrabButton",
+ "X_ChangeActivePointerGrab",
+ "X_GrabKeyboard",
+ "X_UngrabKeyboard",
+ "X_GrabKey",
+ "X_UngrabKey",
+ "X_AllowEvents",
+ "X_GrabServer",
+ "X_UngrabServer",
+ "X_QueryPointer",
+ "X_GetMotionEvents",
+ "X_TranslateCoords",
+ "X_WarpPointer",
+ "X_SetInputFocus",
+ "X_GetInputFocus",
+ "X_QueryKeymap",
+ "X_OpenFont",
+ "X_CloseFont",
+ "X_QueryFont",
+ "X_QueryTextExtents",
+ "X_ListFonts",
+ "X_ListFontsWithInfo",
+ "X_SetFontPath",
+ "X_GetFontPath",
+ "X_CreatePixmap",
+ "X_FreePixmap",
+ "X_CreateGC",
+ "X_ChangeGC",
+ "X_CopyGC",
+ "X_SetDashes",
+ "X_SetClipRectangles",
+ "X_FreeGC",
+ "X_ClearArea",
+ "X_CopyArea",
+ "X_CopyPlane",
+ "X_PolyPoint",
+ "X_PolyLine",
+ "X_PolySegment",
+ "X_PolyRectangle",
+ "X_PolyArc",
+ "X_FillPoly",
+ "X_PolyFillRectangle",
+ "X_PolyFillArc",
+ "X_PutImage",
+ "X_GetImage",
+ "X_PolyText8",
+ "X_PolyText16",
+ "X_ImageText8",
+ "X_ImageText16",
+ "X_CreateColormap",
+ "X_FreeColormap",
+ "X_CopyColormapAndFree",
+ "X_InstallColormap",
+ "X_UninstallColormap",
+ "X_ListInstalledColormaps",
+ "X_AllocColor",
+ "X_AllocNamedColor",
+ "X_AllocColorCells",
+ "X_AllocColorPlanes",
+ "X_FreeColors",
+ "X_StoreColors",
+ "X_StoreNamedColor",
+ "X_QueryColors",
+ "X_LookupColor",
+ "X_CreateCursor",
+ "X_CreateGlyphCursor",
+ "X_FreeCursor",
+ "X_RecolorCursor",
+ "X_QueryBestSize",
+ "X_QueryExtension",
+ "X_ListExtensions",
+ "X_ChangeKeyboardMapping",
+ "X_GetKeyboardMapping",
+ "X_ChangeKeyboardControl",
+ "X_GetKeyboardControl",
+ "X_Bell",
+ "X_ChangePointerControl",
+ "X_GetPointerControl",
+ "X_SetScreenSaver",
+ "X_GetScreenSaver",
+ "X_ChangeHosts",
+ "X_ListHosts",
+ "X_SetAccessControl",
+ "X_SetCloseDownMode",
+ "X_KillClient",
+ "X_RotateProperties",
+ "X_ForceScreenSaver",
+ "X_SetPointerMapping",
+ "X_GetPointerMapping",
+ "X_SetModifierMapping",
+ "X_GetModifierMapping",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "X_NoOperation"
+};
+
+BEGIN_C
+// -=-= C statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+static oslSignalAction SalSignalHdl (void* pData, oslSignalInfo* pInfo)
+{
+ ULONG nException = 0;
+
+ switch (pInfo->Signal)
+ {
+ case osl_Signal_System :
+ return osl_Signal_ActCallNextHdl;
+ case osl_Signal_Terminate :
+ if (!GetSalData()->Close())
+ return osl_Signal_ActIgnore;
+ break;
+ case osl_Signal_User :
+ return osl_Signal_ActCallNextHdl;
+ default: break;
+ }
+
+ return osl_Signal_ActAbortApp;
+}
+
+
+final static int sal_XErrorHdl( Display *pDisplay, XErrorEvent *pEvent )
+{
+ GetSalData()->XError( pDisplay, pEvent );
+ return 0;
+}
+
+final static int sal_XIOErrorHdl( Display *pDisplay )
+{
+ SalData *pSalData = GetSalData();
+ SalDisplay *pSalDisplay = pSalData->GetDisplay( pDisplay );
+ if ( pDisplay && pSalDisplay->IsDisplay() )
+ pSalData->GetLib()->Remove( ConnectionNumber( pDisplay ) );
+
+ oslSignalAction eToDo = osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL);
+ // einen XIOError kann man nicht ignorieren. Die Connection ist
+ // zusammengebrochen, hier kann man nur noch halbwegs sinnvoll runterfahren
+
+ fprintf( stderr, "X IO Error\n" );
+ fflush( stdout );
+ fflush( stderr );
+ exit(0);
+ return 0;
+}
+
+final static void sal_XtErrorHdl( XLIB_String sMsg )
+{
+#ifdef DBG_UTIL
+ fprintf( stderr, "X Toolkit Error: %s\n", sMsg );
+#endif
+ fflush( stdout );
+ fflush( stderr );
+ abort();
+}
+
+final static void sal_XtWarningHdl( XLIB_String sMsg )
+{
+#ifdef DBG_UTIL
+ fprintf( stderr, "X Toolkit Warning: %s\n", sMsg );
+ fflush( stdout );
+ fflush( stderr );
+#endif
+}
+
+END_C
+
+// -=-= SalData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <pthread.h>
+
+final SalData::SalData()
+{
+ argv_ = 0;
+ argc_ = 0;
+
+ pTimerProc_ = 0;
+
+ memset( sig_, 0, sizeof( sig_ ) ); // SIG_DFL
+ bNoExceptions_ = !!getenv( "SAL_NOSEGV" );
+
+ pXLib_ = new SalXLib();
+ pDefDisp_ = 0;
+ pCurDisp_ = 0;
+
+ hMainThread_ = pthread_self();
+
+ pFirstInstance_ = NULL;
+ pFirstFrame_ = NULL;
+}
+
+final SalData::~SalData()
+{
+ delete pXLib_;
+}
+
+final long SalData::Close() const
+{
+ signal( SIGTERM, sig_[SIGTERM] );
+ if( !pFirstFrame_ )
+ return 1;
+
+ SalFrame *pFrame = pFirstFrame_;
+ while( pFrame )
+ {
+ if( !pFrame->maFrameData.Close() )
+ return 0;
+ pFrame = pFrame->maFrameData.GetNextFrame();
+ }
+ return 1;
+}
+
+final long SalData::ShutDown() const
+{
+ if( !pFirstFrame_ )
+ return 1;
+
+ SalFrame *pFrame = pFirstFrame_;
+ while( pFrame )
+ {
+ if( !pFrame->maFrameData.ShutDown() )
+ return 0;
+ pFrame = pFrame->maFrameData.GetNextFrame();
+ }
+ return 1;
+}
+
+final XubString SalData::GetCommandLineParam( USHORT nParam ) const
+{
+ if( !nParam ) { return aBinaryPath_; }
+ if( nParam >= argc_ ) return String();
+ return String( argv_[nParam], gsl_getSystemTextEncoding() );
+}
+
+final SalDisplay *SalData::GetDisplay( Display *pDisplay )
+{
+ SalDisplay *pSalDisplay = SalDisplays_.First();
+ while( pSalDisplay && pSalDisplay->GetDisplay() != pDisplay )
+ pSalDisplay = SalDisplays_.Next();
+ return pSalDisplay;
+}
+
+void SalData::Init( int *pArgc, char *ppArgv[] )
+{
+ // Pfad zum Executable bestimmen
+ char aFilePath[ PATH_MAX ];
+ ::rtl::OUString aPath;
+ osl_getExecutableFile( &aPath.pData );
+
+ aBinaryPath_ = aPath;
+
+ pXLib_->Init( pArgc, ppArgv );
+
+ argc_ = *pArgc;
+ argv_ = ppArgv;
+}
+
+
+// -=-= SalXLib =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+final SalXLib::SalXLib()
+{
+ pApplicationContext_ = NULL;
+ Timeout_.tv_sec = 0;
+ Timeout_.tv_usec = 0;
+ nTimeoutMS_ = 0;
+ bWasXError_ = FALSE;
+ bIgnoreXErrors_ = !!getenv( "SAL_IGNOREXERRORS" );
+ nStateOfYield_ = 0;
+ nFDs_ = 0;
+ pReadFDS_ = new fd_set;
+ pExceptionFDS_ = new fd_set;
+ FD_ZERO( pReadFDS_ );
+ FD_ZERO( pExceptionFDS_ );
+}
+
+final SalXLib::~SalXLib()
+{
+ delete pReadFDS_;
+ delete pExceptionFDS_;
+
+// completetly disabled Bug Nr. #47319 -> segv while using xsuntransport=shmem
+// #ifdef SAL_XT
+// XtDestroyApplicationContext( pApplicationContext_ );
+// #endif
+}
+
+static char sDISPLAY___[30];
+final void SalXLib::Init( int *pArgc, char *ppArgv[] )
+{
+ SalData *pSalData = GetSalData();
+ SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
+
+ pInputMethod->SetLocale();
+
+ if( !getenv( "DISPLAY" ) )
+ putenv( "DISPLAY=:0" );
+
+ XtSetLanguageProc( NULL, NULL, NULL );
+ XtToolkitInitialize();
+ XrmInitialize();
+ pApplicationContext_ = XtCreateApplicationContext();
+
+ Display *pDisp = XtOpenDisplay( pApplicationContext_,
+ NULL,
+ NULL,
+ "VCL",
+ NULL,
+ 0,
+ pArgc,
+ ppArgv );
+
+ if( !pDisp )
+ {
+ char *pDisplayString = getenv ("DISPLAY");
+
+ fprintf( stderr, "%s: cannot open display \"%s\"\n",
+ ppArgv[0],
+ pDisplayString ? pDisplayString : ":0.0" );
+ fprintf( stderr, "Please check your \"DISPLAY\" environment variable, as well as the permissions to access that display ");
+ fprintf( stderr, "(See \"man X\" resp. \"man xhost\" for details)\n");
+ fflush ( stderr );
+ exit (0);
+ }
+
+ XVisualInfo aVI;
+ Colormap aColMap;
+ int nScreen = DefaultScreen( pDisp );
+
+ if( SalDisplay::BestVisual( pDisp, nScreen, aVI ) ) // DefaultVisual
+ aColMap = DefaultColormap( pDisp, nScreen );
+ else
+ aColMap = XCreateColormap( pDisp,
+ RootWindow( pDisp, nScreen ),
+ aVI.visual,
+ AllocNone );
+
+ Arg aArgs[10];
+ int nArgs = 0;
+ XtSetArg( aArgs[nArgs], XtNvisual, aVI.visual ); nArgs++;
+ XtSetArg( aArgs[nArgs], XtNdepth, aVI.depth ); nArgs++;
+ XtSetArg( aArgs[nArgs], XtNcolormap, aColMap ); nArgs++;
+
+ Widget wInitWidget = XtAppCreateShell( NULL,
+ "SAL",
+ applicationShellWidgetClass,
+ pDisp,
+ aArgs, nArgs );
+
+
+ XSetIOErrorHandler ( (XIOErrorHandler)sal_XIOErrorHdl );
+ XSetErrorHandler ( (XErrorHandler)sal_XErrorHdl );
+
+ XtAppSetErrorHandler ( GetAppContext(),
+ (XtErrorHandler)sal_XtErrorHdl );
+ XtAppSetWarningHandler( GetAppContext(),
+ (XtErrorHandler)sal_XtWarningHdl );
+
+ SalDisplay *pSalDisplay = new SalDisplay( wInitWidget );
+
+ pInputMethod->CreateMethod( pDisp );
+ pSalDisplay->SetInputMethod( pInputMethod );
+
+ sal_Bool bOldErrorSetting = GetIgnoreXErrors();
+ SetIgnoreXErrors( True );
+ SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
+ XSync( pDisp, False );
+
+ pKbdExtension->UseExtension( ! WasXError() );
+ SetIgnoreXErrors( bOldErrorSetting );
+
+ pSalDisplay->SetKbdExtension( pKbdExtension );
+
+#if 0 // ! USE_XTOOLKIT
+
+ SalDisplay *pSalDisplay = new SalDisplay( pDisp, aVI.visual, aColMap );
+
+#endif
+}
+
+extern "C" {
+void EmitFontpathWarning( void )
+{
+ static Bool bOnce = False;
+ if ( !bOnce )
+ {
+ bOnce = True;
+ fprintf( stderr, "Please verify your fontpath settings\n"
+ "\t(See \"man xset\" for details"
+ " or ask your system administrator)\n" );
+ }
+}
+
+} /* extern "C" */
+
+final void SalXLib::XError( Display *pDisplay, XErrorEvent *pEvent )
+{
+ char msg[ 120 ];
+
+ if( ! bIgnoreXErrors_ )
+ {
+#if defined DEBUG || defined DBG_UTIL
+ XGetErrorText( pDisplay, pEvent->error_code, msg, sizeof( msg ) );
+ fprintf( stderr, "X-Error: %s\n", msg );
+ if( pEvent->request_code > capacityof( XRequest ) )
+ fprintf( stderr, "\tMajor opcode: %d (Shm?)\n", pEvent->request_code );
+ else if( XRequest[pEvent->request_code] )
+ fprintf( stderr, "\tMajor opcode: %d (%s)\n",
+ pEvent->request_code, XRequest[pEvent->request_code] );
+ else
+ fprintf( stderr, "\tMajor opcode: %d (BadRequest?)\n", pEvent->request_code );
+ fprintf( stderr, "\tResource ID: 0x%lx\n",
+ pEvent->resourceid );
+ fprintf( stderr, "\tSerial No: %ld (%ld)\n",
+ pEvent->serial, LastKnownRequestProcessed(pDisplay) );
+
+ fflush( stdout );
+ fflush( stderr );
+#endif
+
+ oslSignalAction eToDo = osl_raiseSignal (OSL_SIGNAL_USER_X11SUBSYSTEMERROR, NULL);
+ switch (eToDo)
+ {
+ case osl_Signal_ActIgnore :
+ return;
+ case osl_Signal_ActAbortApp :
+ abort();
+ case osl_Signal_ActKillApp :
+ exit(0);
+ case osl_Signal_ActCallNextHdl :
+ break;
+ default :
+ break;
+ }
+
+ if ( (pEvent->error_code == BadAlloc)
+ && (pEvent->request_code == X_OpenFont) )
+ {
+ static Bool bOnce = False;
+ if ( !bOnce )
+ {
+ fprintf(stderr, "X-Error occured in a request for X_OpenFont\n");
+ EmitFontpathWarning();
+
+ bOnce = True ;
+ }
+ }
+ else
+ {
+ abort();
+ }
+ }
+
+ bWasXError_ = TRUE;
+}
+
+#define MAX_NUM_DESCRIPTORS 128
+
+struct YieldEntry
+{
+ YieldEntry* next; // pointer to next entry
+ int fd; // file descriptor for reading
+ void* data; // data for predicate and callback
+ YieldFunc pending; // predicate (determins pending events)
+ YieldFunc queued; // read and queue up events
+ YieldFunc handle; // handle pending events
+
+ inline int HasPendingEvent() const { return pending( fd, data ); }
+ inline int IsEventQueued() const { return queued( fd, data ); }
+ inline void HandleNextEvent() const { handle( fd, data ); }
+};
+
+#define MAX_NUM_DESCRIPTORS 128
+
+static YieldEntry yieldTable[ MAX_NUM_DESCRIPTORS ];
+
+void SalXLib::Insert( int nFD, void* data,
+ YieldFunc pending,
+ YieldFunc queued,
+ YieldFunc handle )
+{
+ DBG_ASSERT( nFD, "can not insert stdin descriptor" )
+ DBG_ASSERT( !yieldTable[nFD].fd, "SalXLib::Insert fd twice" )
+
+ yieldTable[nFD].fd = nFD;
+ yieldTable[nFD].data = data;
+ yieldTable[nFD].pending = pending;
+ yieldTable[nFD].queued = queued;
+ yieldTable[nFD].handle = handle;
+
+ FD_SET( nFD, pReadFDS_ );
+ FD_SET( nFD, pExceptionFDS_ );
+
+ if( nFD >= nFDs_ )
+ nFDs_ = nFD + 1;
+}
+
+void SalXLib::Remove( int nFD )
+{
+ FD_CLR( nFD, pReadFDS_ );
+ FD_CLR( nFD, pExceptionFDS_ );
+
+ yieldTable[nFD].fd = 0;
+
+ if ( nFD == nFDs_ )
+ {
+ for ( nFD = nFDs_ - 1;
+ nFD >= 0 && !yieldTable[nFD].fd;
+ nFD-- );
+
+ nFDs_ = nFD + 1;
+ }
+}
+
+class YieldMutexReleaser
+{
+ ULONG m_nYieldCount;
+ SalYieldMutex* m_pSalInstYieldMutex;
+public:
+ YieldMutexReleaser();
+ ~YieldMutexReleaser();
+};
+
+YieldMutexReleaser::YieldMutexReleaser()
+{
+ SalData *pSalData = GetSalData();
+ m_pSalInstYieldMutex =
+ pSalData->pFirstInstance_->maInstData.mpSalYieldMutex;
+
+ ULONG i;
+ if ( m_pSalInstYieldMutex->GetThreadId() ==
+ NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ m_nYieldCount = m_pSalInstYieldMutex->GetAcquireCount();
+ for ( i = 0; i < m_nYieldCount; i++ )
+ m_pSalInstYieldMutex->release();
+ }
+ else
+ m_nYieldCount = 0;
+}
+
+YieldMutexReleaser::~YieldMutexReleaser()
+{
+ // Yield-Semaphore wieder holen
+ while ( m_nYieldCount )
+ {
+ m_pSalInstYieldMutex->acquire();
+ m_nYieldCount--;
+ }
+}
+
+final void SalXLib::Yield( BOOL bWait )
+{
+ fd_set ReadFDS;
+ fd_set ExceptionFDS;
+ int nFound = 0;
+
+ nStateOfYield_ = 0; // is not 0 if we are recursive called
+
+ // first look for queued events
+ for ( int nFD = 0; nFD < nFDs_; nFD++ )
+ {
+ YieldEntry* pEntry = &(yieldTable[nFD]);
+ if ( pEntry->fd )
+ {
+ DBG_ASSERT( nFD == pEntry->fd, "wrong fd in Yield()" );
+
+ if ( pEntry->HasPendingEvent() )
+ {
+ pEntry->HandleNextEvent();
+ // #63862# da jetzt alle user-events ueber die interne
+ // queue kommen, wird die Kontrolle analog zum select
+ // gesteuerten Zweig einmal bei bWait abgegeben
+ YieldMutexReleaser aReleaser;
+ if ( bWait )
+ osl_yieldThread();
+ return;
+ }
+ }
+ }
+
+ // next select with or without timeout according to bWait
+
+ ReadFDS = *pReadFDS_;
+ ExceptionFDS = *pExceptionFDS_;
+
+ struct timeval Timeout;
+ Timeout = bWait ? yield : noyield;
+
+ nStateOfYield_ = 1;
+
+ {
+ // Yield-Semaphore freigeben
+ YieldMutexReleaser aReleaser;
+ if( bWait )
+ osl_yieldThread();
+#if defined (HPUX) && defined (CMA_UX)
+ nFound = select( nFDs_, (int*)&ReadFDS, (int*)NULL,
+ (int*)&ExceptionFDS, &Timeout );
+#else
+ nFound = select( nFDs_, &ReadFDS, NULL, &ExceptionFDS, &Timeout );
+#endif
+ }
+ if( nFound < 0 ) // error
+ {
+#ifdef DBG_UTIL
+ fprintf( stderr, "SalXLib::Yield s=%d e=%d f=%d\n",
+ nStateOfYield_, errno, nFound );
+#endif
+ nStateOfYield_ = 0;
+ if( EINTR == errno )
+ {
+ errno = 0;
+ }
+ }
+
+ // check for timeouts
+ if( Timeout_.tv_sec ) // timer is started
+ {
+ gettimeofday( &Timeout, NULL );
+
+ if( Timeout >= Timeout_ )
+ {
+ Timeout_ = Timeout + nTimeoutMS_;
+ GetSalData()->Timeout();
+ }
+ }
+
+ // handle events
+ if( nFound > 0 )
+ {
+ // now we are in the protected section !
+ // recall select if we have acquired fd's, ready for reading,
+
+ struct timeval noTimeout = { 0, 0 };
+ nFound = select( nFDs_, &ReadFDS, NULL,
+ &ExceptionFDS, &noTimeout );
+
+ // someone-else has done the job for us
+ if (nFound == 0)
+ {
+ nStateOfYield_ = 0;
+ //if ( !pthread_equal (pthread_self(),
+ // pSalData->GetMainThread()))
+ return;
+ }
+
+ for ( int nFD = 0; nFD < nFDs_; nFD++ )
+ {
+ YieldEntry* pEntry = &(yieldTable[nFD]);
+ if ( pEntry->fd )
+ {
+ if ( FD_ISSET( nFD, &ExceptionFDS ) ) {
+#if defined DEBUG
+ fprintf( stderr, "SalXLib::Yield exception\n" );
+#endif
+ nFound--;
+ }
+ if ( FD_ISSET( nFD, &ReadFDS ) )
+ {
+ nStateOfYield_ = 3;
+ if ( pEntry->IsEventQueued() )
+ {
+ nStateOfYield_ = 4;
+ pEntry->HandleNextEvent();
+ // if a recursive call has done the job
+ // so abort here
+ if ( nStateOfYield_ != 4 )
+ break;
+ }
+ nFound--;
+ }
+ }
+ }
+ }
+ nStateOfYield_ = 0;
+}
+