1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <string.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 35 #include "osl/module.hxx" 36 #include "tools/solarmutex.hxx" 37 #include "vos/mutex.hxx" 38 39 40 #include "unx/salunx.h" 41 #include "unx/saldata.hxx" 42 #include "unx/saldisp.hxx" 43 #include "unx/salinst.h" 44 #include "unx/salframe.h" 45 #include "unx/dtint.hxx" 46 #include "unx/salprn.h" 47 #include "unx/sm.hxx" 48 49 #include "vcl/apptypes.hxx" 50 #include "vcl/helper.hxx" 51 52 #include "salwtype.hxx" 53 54 // ------------------------------------------------------------------------- 55 // 56 // SalYieldMutex 57 // 58 // ------------------------------------------------------------------------- 59 60 SalYieldMutex::SalYieldMutex() 61 { 62 mnCount = 0; 63 mnThreadId = 0; 64 ::tools::SolarMutex::SetSolarMutex( this ); 65 } 66 67 void SalYieldMutex::acquire() 68 { 69 OMutex::acquire(); 70 mnThreadId = vos::OThread::getCurrentIdentifier(); 71 mnCount++; 72 } 73 74 void SalYieldMutex::release() 75 { 76 if ( mnThreadId == vos::OThread::getCurrentIdentifier() ) 77 { 78 if ( mnCount == 1 ) 79 mnThreadId = 0; 80 mnCount--; 81 } 82 OMutex::release(); 83 } 84 85 sal_Bool SalYieldMutex::tryToAcquire() 86 { 87 if ( OMutex::tryToAcquire() ) 88 { 89 mnThreadId = vos::OThread::getCurrentIdentifier(); 90 mnCount++; 91 return True; 92 } 93 else 94 return False; 95 } 96 97 //---------------------------------------------------------------------------- 98 99 // -=-= SalInstance =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 100 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 101 102 // plugin factory function 103 extern "C" 104 { 105 VCLPLUG_GEN_PUBLIC SalInstance* create_SalInstance() 106 { 107 /* #i92121# workaround deadlocks in the X11 implementation 108 */ 109 static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" ); 110 /* #i90094# 111 from now on we know that an X connection will be 112 established, so protect X against itself 113 */ 114 if( ! ( pNoXInitThreads && *pNoXInitThreads ) ) 115 XInitThreads(); 116 117 X11SalInstance* pInstance = new X11SalInstance( new SalYieldMutex() ); 118 119 // initialize SalData 120 X11SalData *pSalData = new X11SalData; 121 SetSalData( pSalData ); 122 pSalData->m_pInstance = pInstance; 123 pSalData->Init(); 124 125 return pInstance; 126 } 127 } 128 129 X11SalInstance::~X11SalInstance() 130 { 131 // close session management 132 SessionManagerClient::close(); 133 134 // dispose SalDisplay list from SalData 135 // would be done in a static destructor else which is 136 // a little late 137 138 X11SalData *pSalData = GetX11SalData(); 139 pSalData->deInitNWF(); 140 delete pSalData; 141 SetSalData( NULL ); 142 143 ::tools::SolarMutex::SetSolarMutex( 0 ); 144 delete mpSalYieldMutex; 145 } 146 147 148 // -------------------------------------------------------- 149 // AnyInput from sv/mow/source/app/svapp.cxx 150 151 struct PredicateReturn 152 { 153 sal_uInt16 nType; 154 sal_Bool bRet; 155 }; 156 157 extern "C" { 158 Bool ImplPredicateEvent( Display *, XEvent *pEvent, char *pData ) 159 { 160 PredicateReturn *pPre = (PredicateReturn *)pData; 161 162 if ( pPre->bRet ) 163 return False; 164 165 sal_uInt16 nType; 166 167 switch( pEvent->type ) 168 { 169 case ButtonPress: 170 case ButtonRelease: 171 case MotionNotify: 172 case EnterNotify: 173 case LeaveNotify: 174 nType = INPUT_MOUSE; 175 break; 176 177 case XLIB_KeyPress: 178 //case KeyRelease: 179 nType = INPUT_KEYBOARD; 180 break; 181 case Expose: 182 case GraphicsExpose: 183 case NoExpose: 184 nType = INPUT_PAINT; 185 break; 186 default: 187 nType = 0; 188 } 189 190 if ( (nType & pPre->nType) || ( ! nType && (pPre->nType & INPUT_OTHER) ) ) 191 pPre->bRet = sal_True; 192 193 return False; 194 } 195 } 196 197 bool X11SalInstance::AnyInput(sal_uInt16 nType) 198 { 199 X11SalData *pSalData = GetX11SalData(); 200 Display *pDisplay = pSalData->GetDisplay()->GetDisplay(); 201 sal_Bool bRet = sal_False; 202 203 if( (nType & INPUT_TIMER) && 204 pSalData->GetDisplay()->GetXLib()->CheckTimeout( false ) ) 205 { 206 bRet = sal_True; 207 } 208 else if (XPending(pDisplay) ) 209 { 210 PredicateReturn aInput; 211 XEvent aEvent; 212 213 aInput.bRet = sal_False; 214 aInput.nType = nType; 215 216 XCheckIfEvent(pDisplay, &aEvent, ImplPredicateEvent, 217 (char *)&aInput ); 218 219 bRet = aInput.bRet; 220 } 221 return bRet; 222 } 223 224 vos::IMutex* X11SalInstance::GetYieldMutex() 225 { 226 return mpSalYieldMutex; 227 } 228 229 // ----------------------------------------------------------------------- 230 231 sal_uLong X11SalInstance::ReleaseYieldMutex() 232 { 233 SalYieldMutex* pYieldMutex = mpSalYieldMutex; 234 if ( pYieldMutex->GetThreadId() == 235 vos::OThread::getCurrentIdentifier() ) 236 { 237 sal_uLong nCount = pYieldMutex->GetAcquireCount(); 238 sal_uLong n = nCount; 239 while ( n ) 240 { 241 pYieldMutex->release(); 242 n--; 243 } 244 245 return nCount; 246 } 247 else 248 return 0; 249 } 250 251 // ----------------------------------------------------------------------- 252 253 void X11SalInstance::AcquireYieldMutex( sal_uLong nCount ) 254 { 255 SalYieldMutex* pYieldMutex = mpSalYieldMutex; 256 while ( nCount ) 257 { 258 pYieldMutex->acquire(); 259 nCount--; 260 } 261 } 262 263 // ----------------------------------------------------------------------- 264 265 bool X11SalInstance::CheckYieldMutex() 266 { 267 bool bRet = true; 268 269 SalYieldMutex* pYieldMutex = mpSalYieldMutex; 270 if ( pYieldMutex->GetThreadId() != 271 vos::OThread::getCurrentIdentifier() ) 272 { 273 bRet = false; 274 } 275 276 return bRet; 277 } 278 279 // ----------------------------------------------------------------------- 280 281 void X11SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) 282 { GetX11SalData()->GetLib()->Yield( bWait, bHandleAllCurrentEvents ); } 283 284 void* X11SalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) 285 { 286 static const char* pDisplay = getenv( "DISPLAY" ); 287 rReturnedType = AsciiCString; 288 rReturnedBytes = pDisplay ? strlen( pDisplay )+1 : 1; 289 return pDisplay ? (void*)pDisplay : (void*)""; 290 } 291 292 SalFrame *X11SalInstance::CreateFrame( SalFrame *pParent, sal_uLong nSalFrameStyle ) 293 { 294 SalFrame *pFrame = new X11SalFrame( pParent, nSalFrameStyle ); 295 296 return pFrame; 297 } 298 299 SalFrame* X11SalInstance::CreateChildFrame( SystemParentData* pParentData, sal_uLong nStyle ) 300 { 301 SalFrame* pFrame = new X11SalFrame( NULL, nStyle, pParentData ); 302 303 return pFrame; 304 } 305 306 void X11SalInstance::DestroyFrame( SalFrame* pFrame ) 307 { 308 delete pFrame; 309 } 310 311 static void getServerDirectories( std::list< rtl::OString >& o_rFontPaths ) 312 { 313 #ifdef LINUX 314 /* 315 * chkfontpath exists on some (RH derived) Linux distributions 316 */ 317 static const char* pCommands[] = { 318 "/usr/sbin/chkfontpath 2>/dev/null", "chkfontpath 2>/dev/null" 319 }; 320 ::std::list< ByteString > aLines; 321 322 for( unsigned int i = 0; i < sizeof(pCommands)/sizeof(pCommands[0]); i++ ) 323 { 324 FILE* pPipe = popen( pCommands[i], "r" ); 325 aLines.clear(); 326 if( pPipe ) 327 { 328 char line[1024]; 329 char* pSearch; 330 while( fgets( line, sizeof(line), pPipe ) ) 331 { 332 int nLen = strlen( line ); 333 if( line[nLen-1] == '\n' ) 334 line[nLen-1] = 0; 335 pSearch = strstr( line, ": " ); 336 if( pSearch ) 337 aLines.push_back( pSearch+2 ); 338 } 339 if( ! pclose( pPipe ) ) 340 break; 341 } 342 } 343 344 for( ::std::list< ByteString >::iterator it = aLines.begin(); it != aLines.end(); ++it ) 345 { 346 if( ! access( it->GetBuffer(), F_OK ) ) 347 { 348 o_rFontPaths.push_back( *it ); 349 #if OSL_DEBUG_LEVEL > 1 350 fprintf( stderr, "adding fs dir %s\n", it->GetBuffer() ); 351 #endif 352 } 353 } 354 #else 355 (void)o_rFontPaths; 356 #endif 357 } 358 359 360 361 void X11SalInstance::FillFontPathList( std::list< rtl::OString >& o_rFontPaths ) 362 { 363 Display *pDisplay = GetX11SalData()->GetDisplay()->GetDisplay(); 364 365 DBG_ASSERT( pDisplay, "No Display !" ); 366 if( pDisplay ) 367 { 368 // get font paths to look for fonts 369 int nPaths = 0, i; 370 char** pPaths = XGetFontPath( pDisplay, &nPaths ); 371 372 bool bServerDirs = false; 373 for( i = 0; i < nPaths; i++ ) 374 { 375 OString aPath( pPaths[i] ); 376 sal_Int32 nPos = 0; 377 if( ! bServerDirs 378 && ( nPos = aPath.indexOf( ':' ) ) > 0 379 && ( !aPath.copy(nPos).equals( ":unscaled" ) ) ) 380 { 381 bServerDirs = true; 382 getServerDirectories( o_rFontPaths ); 383 } 384 else 385 { 386 psp::normPath( aPath ); 387 o_rFontPaths.push_back( aPath ); 388 } 389 } 390 391 if( nPaths ) 392 XFreeFontPath( pPaths ); 393 } 394 395 // insert some standard directories 396 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/TrueType" ); 397 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/Type1" ); 398 o_rFontPaths.push_back( "/usr/openwin/lib/X11/fonts/Type1/sun" ); 399 o_rFontPaths.push_back( "/usr/X11R6/lib/X11/fonts/truetype" ); 400 o_rFontPaths.push_back( "/usr/X11R6/lib/X11/fonts/Type1" ); 401 402 #ifdef SOLARIS 403 /* cde specials, from /usr/dt/bin/Xsession: here are the good fonts, 404 the OWfontpath file may contain as well multiple lines as a comma 405 separated list of fonts in each line. to make it even more weird 406 environment variables are allowed as well */ 407 408 const char* lang = getenv("LANG"); 409 if ( lang != NULL ) 410 { 411 String aOpenWinDir( String::CreateFromAscii( "/usr/openwin/lib/locale/" ) ); 412 aOpenWinDir.AppendAscii( lang ); 413 aOpenWinDir.AppendAscii( "/OWfontpath" ); 414 415 SvFileStream aStream( aOpenWinDir, STREAM_READ ); 416 417 // TODO: replace environment variables 418 while( aStream.IsOpen() && ! aStream.IsEof() ) 419 { 420 ByteString aLine; 421 aStream.ReadLine( aLine ); 422 // need an OString for normpath 423 OString aNLine( aLine ); 424 psp::normPath( aNLine ); 425 aLine = aNLine; 426 // try to avoid bad fonts in some cases 427 static bool bAvoid = (strncasecmp( lang, "ar", 2 ) == 0) || (strncasecmp( lang, "he", 2 ) == 0) || strncasecmp( lang, "iw", 2 ) == 0 || (strncasecmp( lang, "hi", 2 ) == 0); 428 if( bAvoid && aLine.Search( "iso_8859" ) != STRING_NOTFOUND ) 429 continue; 430 o_rFontPaths.push_back( aLine ); 431 } 432 } 433 #endif /* SOLARIS */ 434 } 435 436 extern "C" { static void SAL_CALL thisModule() {} } 437 438 void X11SalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& rMimeType) 439 { 440 const rtl::OUString SYM_ADD_TO_RECENTLY_USED_FILE_LIST(RTL_CONSTASCII_USTRINGPARAM("add_to_recently_used_file_list")); 441 const rtl::OUString LIB_RECENT_FILE(RTL_CONSTASCII_USTRINGPARAM("librecentfile.so")); 442 typedef void (*PFUNC_ADD_TO_RECENTLY_USED_LIST)(const rtl::OUString&, const rtl::OUString&); 443 444 PFUNC_ADD_TO_RECENTLY_USED_LIST add_to_recently_used_file_list = 0; 445 446 osl::Module module; 447 module.loadRelative( &thisModule, LIB_RECENT_FILE ); 448 if (module.is()) 449 add_to_recently_used_file_list = (PFUNC_ADD_TO_RECENTLY_USED_LIST)module.getFunctionSymbol(SYM_ADD_TO_RECENTLY_USED_FILE_LIST); 450 if (add_to_recently_used_file_list) 451 add_to_recently_used_file_list(rFileUrl, rMimeType); 452 } 453