diff options
Diffstat (limited to 'vcl/unx/source/app')
-rw-r--r-- | vcl/unx/source/app/i18n_cb.cxx | 547 | ||||
-rw-r--r-- | vcl/unx/source/app/i18n_ic.cxx | 686 | ||||
-rw-r--r-- | vcl/unx/source/app/i18n_im.cxx | 332 | ||||
-rw-r--r-- | vcl/unx/source/app/i18n_wrp.cxx | 293 | ||||
-rw-r--r-- | vcl/unx/source/app/i18n_xkb.cxx | 195 | ||||
-rw-r--r-- | vcl/unx/source/app/keysymnames.cxx | 545 | ||||
-rw-r--r-- | vcl/unx/source/app/makefile.mk | 142 | ||||
-rw-r--r-- | vcl/unx/source/app/saldata.cxx | 854 | ||||
-rw-r--r-- | vcl/unx/source/app/saldisp.cxx | 3653 | ||||
-rw-r--r-- | vcl/unx/source/app/salinst.cxx | 346 | ||||
-rw-r--r-- | vcl/unx/source/app/salsys.cxx | 200 | ||||
-rw-r--r-- | vcl/unx/source/app/saltimer.cxx | 129 | ||||
-rw-r--r-- | vcl/unx/source/app/sm.cxx | 347 | ||||
-rw-r--r-- | vcl/unx/source/app/soicon.cxx | 502 |
14 files changed, 8771 insertions, 0 deletions
diff --git a/vcl/unx/source/app/i18n_cb.cxx b/vcl/unx/source/app/i18n_cb.cxx new file mode 100644 index 000000000000..434b356054fd --- /dev/null +++ b/vcl/unx/source/app/i18n_cb.cxx @@ -0,0 +1,547 @@ +/************************************************************************* + * + * $RCSfile: i18n_cb.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): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> +#ifdef SOLARIS +#include <alloca.h> +#endif +#include <prex.h> +#include <X11/Xlocale.h> +#include <X11/Xlib.h> +#include <postx.h> + +#include <salunx.h> +#include "XIM.h" + +#ifndef _SAL_I18N_CALLBACK_HXX +#include "i18n_cb.hxx" +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif + +// ------------------------------------------------------------------------- +// +// i. preedit start callback +// +// ------------------------------------------------------------------------- + +int +PreeditStartCallback ( XIC ic, XPointer client_data, XPointer call_data ) +{ + #define PREEDIT_BUFSZ 16 + + preedit_data_t* pPreeditData = (preedit_data_t*)client_data; + + if ( pPreeditData->eState == ePreeditStatusActivationRequired ) + { + pPreeditData->eState = ePreeditStatusActive; + + pPreeditData->aText.pUnicodeBuffer = + (sal_Unicode*)malloc(PREEDIT_BUFSZ * sizeof(sal_Unicode)); + pPreeditData->aText.pCharStyle = + (XIMFeedback*)malloc(PREEDIT_BUFSZ * sizeof(XIMFeedback)); + pPreeditData->aText.nCursorPos = 0; + pPreeditData->aText.nLength = 0; + pPreeditData->aText.nSize = PREEDIT_BUFSZ; + + pPreeditData->pFrame->maFrameData.Call(SALEVENT_STARTEXTTEXTINPUT, + (void*)NULL ); + } + + return -1; +} + +// ------------------------------------------------------------------------- +// +// ii. preedit done callback +// +// ------------------------------------------------------------------------- + +void +PreeditDoneCallback ( XIC ic, XPointer client_data, XPointer call_data ) +{ + preedit_data_t* pPreeditData = (preedit_data_t*)client_data; + + if (pPreeditData->eState == ePreeditStatusActive ) + pPreeditData->pFrame->maFrameData.Call( + SALEVENT_ENDEXTTEXTINPUT, (void*)NULL ); + pPreeditData->eState = ePreeditStatusStartPending; + + if ( pPreeditData->aText.pUnicodeBuffer != NULL ) + { + free (pPreeditData->aText.pUnicodeBuffer); + pPreeditData->aText.pUnicodeBuffer = NULL; + } + if ( pPreeditData->aText.pCharStyle != NULL ) + { + free (pPreeditData->aText.pCharStyle); + pPreeditData->aText.pCharStyle = NULL; + } +} + +// ------------------------------------------------------------------------- +// +// iii. preedit draw callback +// +// ------------------------------------------------------------------------- + +// +// Handle deletion of text in a preedit_draw_callback +// from and howmuch are guaranteed to be nonnegative +// + +void +Preedit_DeleteText(preedit_text_t *ptext, int from, int howmuch) +{ + int to = from + howmuch; + + if (to == ptext->nLength) + { + // delete from the end of the text + ptext->nLength = from; + } + else + if (to < ptext->nLength) + { + // cut out of the middle of the text + memmove( (void*)(ptext->pUnicodeBuffer + from), + (void*)(ptext->pUnicodeBuffer + to), + (ptext->nLength - to) * sizeof(sal_Unicode)); + memmove( (void*)(ptext->pCharStyle + from), + (void*)(ptext->pCharStyle + to), + (ptext->nLength - to) * sizeof(sal_Unicode)); + ptext->nLength -= howmuch; + } + else + // if ( to > pText->nLength ) + { + // XXX this indicates an error, are we out of sync ? + fprintf(stderr, "Preedit_DeleteText( from=%i to=%i length=%i )\n", + from, to, ptext->nLength ); + fprintf (stderr, "\t XXX internal error, out of sync XXX\n"); + + ptext->nLength = from; + } + + // NULL-terminate the string + ptext->pUnicodeBuffer[ptext->nLength] = (sal_Unicode)0; +} + +// reallocate the textbuffer with sufficiently large size 2^x +// nnewlimit is presupposed to be larger than ptext->size +void +enlarge_buffer ( preedit_text_t *ptext, int nnewlimit ) +{ + size_t nnewsize = ptext->nSize; + + while ( nnewsize <= nnewlimit ) + nnewsize *= 2; + + ptext->nSize = nnewsize; + ptext->pUnicodeBuffer = (sal_Unicode*)realloc((void*)ptext->pUnicodeBuffer, + nnewsize * sizeof(sal_Unicode)); + ptext->pCharStyle = (XIMFeedback*)realloc((void*)ptext->pCharStyle, + nnewsize * sizeof(XIMFeedback)); +} + +// +// Handle insertion of text in a preedit_draw_callback +// string field of XIMText struct is guaranteed to be != NULL +// + +void +Preedit_InsertText(preedit_text_t *pText, XIMText *pInsertText, int where, + Bool isMultilingual) +{ + sal_Unicode *pInsertTextString; + int nInsertTextLength = 0; + XIMFeedback *pInsertTextCharStyle = pInsertText->feedback; + + nInsertTextLength = pInsertText->length; + + if (isMultilingual) + { + XIMUnicodeText *pUniText = (XIMUnicodeText*)pInsertText; + pInsertTextString = pUniText->string.utf16_char; + } + else + { + // can't handle wchar_t strings, so convert to multibyte chars first + char *pMBString; + size_t nMBLength; + if (pInsertText->encoding_is_wchar) + { + wchar_t *pWCString = pInsertText->string.wide_char; + size_t nBytes = wcstombs ( NULL, pWCString, 1024 /* dont care */); + pMBString = (char*)alloca( nBytes + 1 ); + nMBLength = wcstombs ( pMBString, pWCString, nBytes + 1); + } + else + { + pMBString = pInsertText->string.multi_byte; + nMBLength = strlen(pMBString); // xxx + } + + // convert multibyte chars to unicode + rtl_TextEncoding nEncoding = gsl_getSystemTextEncoding(); + + if (nEncoding != RTL_TEXTENCODING_UNICODE) + { + rtl_TextToUnicodeConverter aConverter = + rtl_createTextToUnicodeConverter( nEncoding ); + rtl_TextToUnicodeContext aContext = + rtl_createTextToUnicodeContext(aConverter); + + sal_Size nBufferSize = nInsertTextLength * 2; + + pInsertTextString = (sal_Unicode*)alloca(nBufferSize); + + sal_uInt32 nConversionInfo; + sal_Size nConvertedChars; + + sal_Size nSize = + rtl_convertTextToUnicode( aConverter, aContext, + pMBString, nMBLength, + pInsertTextString, nBufferSize, + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE + | RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE, + &nConversionInfo, &nConvertedChars ); + + rtl_destroyTextToUnicodeContext(aConverter, aContext); + rtl_destroyTextToUnicodeConverter(aConverter); + + } + else + { + pInsertTextString = (sal_Unicode*)pMBString; + } + } + + // enlarge target text-buffer if necessary + if (pText->nSize <= (pText->nLength + nInsertTextLength)) + enlarge_buffer(pText, pText->nLength + nInsertTextLength); + + // insert text: displace old mem and put new bytes in + int from = where; + int to = where + nInsertTextLength; + int howmany = pText->nLength - where; + + memmove((void*)(pText->pUnicodeBuffer + to), + (void*)(pText->pUnicodeBuffer + from), + howmany * sizeof(sal_Unicode)); + memmove((void*)(pText->pCharStyle + to), + (void*)(pText->pCharStyle + from), + howmany * sizeof(XIMFeedback)); + + to = from; + howmany = nInsertTextLength; + + memcpy((void*)(pText->pUnicodeBuffer + to), (void*)pInsertTextString, + howmany * sizeof(sal_Unicode)); + memcpy((void*)(pText->pCharStyle + to), (void*)pInsertTextCharStyle, + howmany * sizeof(XIMFeedback)); + + pText->nLength += howmany; + + // NULL-terminate the string + pText->pUnicodeBuffer[pText->nLength] = (sal_Unicode)0; +} + +// +// Handle the change of attributes in a preedit_draw_callback +// +void +Preedit_UpdateAttributes ( preedit_text_t* ptext, XIMFeedback* feedback, + int from, int amount ) +{ + if ( (from + amount) > ptext->nLength ) + { + // XXX this indicates an error, are we out of sync ? + fprintf (stderr, "Preedit_UpdateAttributes( %i + %i > %i )\n", + from, amount, ptext->nLength ); + fprintf (stderr, "\t XXX internal error, out of sync XXX\n"); + + return; + } + + memcpy ( ptext->pCharStyle + from, + feedback, amount * sizeof(XIMFeedback) ); +} + +// Convert the XIM feedback values into appropriate VCL +// SAL_EXTTEXTINPUT_ATTR values +// returns an allocate list of attributes, which must be freed by caller +USHORT* +Preedit_FeedbackToSAL ( XIMFeedback* pfeedback, int nlength ) +{ + USHORT *psalattr; + USHORT nval; + USHORT noldval = 0; + XIMFeedback nfeedback; + + // only work with reasonable length + if (nlength > 0) + psalattr = (USHORT*)malloc(nlength * sizeof(USHORT)); + else + return (USHORT*)NULL; + + for (int npos = 0; npos < nlength; npos++) + { + nval = 0; + nfeedback = pfeedback[npos]; + + // means to use the feedback of the previous char + if (nfeedback == 0) + { + nval = noldval; + } + // convert feedback to attributes + else + { + if (nfeedback & XIMReverse) + nval |= SAL_EXTTEXTINPUT_ATTR_REDTEXT; + if (nfeedback & XIMUnderline) + nval |= SAL_EXTTEXTINPUT_ATTR_UNDERLINE; + if (nfeedback & XIMHighlight) + nval |= SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT; + if (nfeedback & XIMPrimary) + nval |= SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE; + if (nfeedback & XIMSecondary) + nval |= SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE; + if (nfeedback & XIMTertiary) // same as 2ery + nval |= SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE; + + #if 0 // visibility feedback not supported now + if ( (nfeedback & XIMVisibleToForward) + || (nfeedback & XIMVisibleToBackward) + || (nfeedback & XIMVisibleCenter) ) + { } + #endif + } + // copy in list + psalattr[npos] = nval; + noldval = nval; + } + // return list of sal attributes + return psalattr; +} + +void +PreeditDrawCallback(XIC ic, XPointer client_data, + XIMPreeditDrawCallbackStruct *call_data) +{ + preedit_data_t* pPreeditData = (preedit_data_t*)client_data; + + // if there's nothing to change then change nothing + if ( (call_data->text == NULL) && (call_data->chg_length == 0) ) + return; + + if ( pPreeditData->eState == ePreeditStatusStartPending ) + pPreeditData->eState = ePreeditStatusActivationRequired; + PreeditStartCallback( ic, client_data, NULL ); + + // Edit the internal textbuffer as indicated by the call_data, + // chg_first and chg_length are guaranteed to be nonnegative + + // handle text deletion + if (call_data->text == NULL) + { + Preedit_DeleteText(&(pPreeditData->aText), + call_data->chg_first, call_data->chg_length ); + } + else + { + // handle text insertion + if ( (call_data->chg_length == 0) + && (call_data->text->string.wide_char != NULL)) + { + Preedit_InsertText(&(pPreeditData->aText), call_data->text, + call_data->chg_first, pPreeditData->bIsMultilingual); + } + else + // handle text replacement by deletion and insertion of text, + // not smart, just good enough + if ( (call_data->chg_length != 0) + && (call_data->text->string.wide_char != NULL)) + { + Preedit_DeleteText(&(pPreeditData->aText), + call_data->chg_first, call_data->chg_length); + Preedit_InsertText(&(pPreeditData->aText), call_data->text, + call_data->chg_first, pPreeditData->bIsMultilingual); + } + else + // not really a text update, only attributes are concerned + if ( (call_data->chg_length != 0) + && (call_data->text->string.wide_char == NULL)) + { + Preedit_UpdateAttributes(&(pPreeditData->aText), + call_data->text->feedback, + call_data->chg_first, call_data->chg_length); + } + } + + // + // build the SalExtTextInputEvent and send it up + // + + SalExtTextInputEvent aTextEvent; + + aTextEvent.mnTime = 0; + aTextEvent.mpTextAttr = Preedit_FeedbackToSAL( + pPreeditData->aText.pCharStyle, pPreeditData->aText.nLength); + aTextEvent.mnCursorPos = call_data->caret; + aTextEvent.maText = pPreeditData->aText.pUnicodeBuffer; + aTextEvent.mbCursorVisible = True; + aTextEvent.mnDeltaStart = 0; // call_data->chg_first; + aTextEvent.mbOnlyCursor = False; + + if ( pPreeditData->eState == ePreeditStatusActive ) + pPreeditData->pFrame->maFrameData.Call(SALEVENT_EXTTEXTINPUT, + (void*)&aTextEvent); + if (aTextEvent.mpTextAttr) + free((void*)aTextEvent.mpTextAttr); +} + +// ------------------------------------------------------------------------- +// +// iv. preedit caret callback +// +// ------------------------------------------------------------------------- + +void +PreeditCaretCallback ( XIC ic, XPointer client_data, + XIMPreeditCaretCallbackStruct *call_data ) +{ + // XXX PreeditCaretCallback is pure debug code for now + char *direction = "?"; + char *style = "?"; + + switch ( call_data->style ) + { + case XIMIsInvisible: style = "Invisible"; break; + case XIMIsPrimary: style = "Primary"; break; + case XIMIsSecondary: style = "Secondary"; break; + } + switch ( call_data->direction ) + { + case XIMForwardChar: direction = "Forward char"; break; + case XIMBackwardChar: direction = "Backward char"; break; + case XIMForwardWord: direction = "Forward word"; break; + case XIMBackwardWord: direction = "Backward word"; break; + case XIMCaretUp: direction = "Caret up"; break; + case XIMCaretDown: direction = "Caret down"; break; + case XIMNextLine: direction = "Next line"; break; + case XIMPreviousLine: direction = "Previous line"; break; + case XIMLineStart: direction = "Line start"; break; + case XIMLineEnd: direction = "Line end"; break; + case XIMAbsolutePosition: direction = "Absolute"; break; + case XIMDontChange: direction = "Dont change"; break; + } + + fprintf (stderr, "PreeditCaretCallback( ic=%i, client=%i,\n", + (unsigned int)ic, (unsigned int)client_data ); + fprintf (stderr, "\t position=%i, direction=\"%s\", style=\"%s\" )\n", + call_data->position, direction, style ); + + // XXX +} + +// ----------------------------------------------------------------------- +// +// v. commit string callback: convert an extended text input (iiimp ... ) +// into an ordinary key-event +// +// ----------------------------------------------------------------------- + +int +CommitStringCallback( XIC ic, XPointer client_data, XPointer call_data ) +{ + preedit_data_t* pPreeditData = (preedit_data_t*)client_data; + + XIMUnicodeText *cbtext = (XIMUnicodeText *)call_data; + sal_Unicode *p_unicode_data = (sal_Unicode*)cbtext->string.utf16_char; + p_unicode_data[cbtext->length] = (sal_Unicode)0; + + if ( pPreeditData->eState == ePreeditStatusActive ) + PreeditDoneCallback( ic, client_data, call_data ); + + pPreeditData->pFrame->maFrameData.Call( SALEVENT_STARTEXTTEXTINPUT, + (void*)NULL ); + + SalExtTextInputEvent aTextEvent; + + aTextEvent.mnTime = 0; + aTextEvent.mpTextAttr = 0; + aTextEvent.mnCursorPos = cbtext->length; + aTextEvent.maText = p_unicode_data; + aTextEvent.mbCursorVisible = True; + aTextEvent.mnDeltaStart = 0; + aTextEvent.mbOnlyCursor = False; + + pPreeditData->pFrame->maFrameData.Call( SALEVENT_EXTTEXTINPUT, + (void*)&aTextEvent); + pPreeditData->pFrame->maFrameData.Call( SALEVENT_ENDEXTTEXTINPUT, + (void*)NULL ); + + return 0; +} + diff --git a/vcl/unx/source/app/i18n_ic.cxx b/vcl/unx/source/app/i18n_ic.cxx new file mode 100644 index 000000000000..4e2f34b77d22 --- /dev/null +++ b/vcl/unx/source/app/i18n_ic.cxx @@ -0,0 +1,686 @@ +/************************************************************************* + * + * $RCSfile: i18n_ic.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): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> +#include <alloca.h> + +#include <prex.h> +#include <X11/Xlocale.h> +#include <X11/Xlib.h> +#include <postx.h> + +#include <salunx.h> + +#include <XIM.h> + +#ifndef _SAL_I18N_INPUTCONTEXT_HXX +#include "i18n_ic.hxx" +#endif +#ifndef _SAL_I18N_INPUTMETHOD_HXX +#include "i18n_im.hxx" +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif + +// --------------------------------------------------------------------------- +// +// Constructor / Destructor, the InputContext is bound to the SalFrame, as it +// needs the shell window as a focus window +// +// ---------------------------------------------------------------------------- + +SalI18N_InputContext::~SalI18N_InputContext() +{ + if ( maContext != NULL ) + XDestroyIC( maContext ); + if ( mpAttributes != NULL ) + XFree( mpAttributes ); + if ( mpStatusAttributes != NULL ) + XFree( mpStatusAttributes ); + if ( mpPreeditAttributes != NULL ) + XFree( mpPreeditAttributes ); + #ifdef SOLARIS + if ( mpFontSet != NULL ) + XFreeFontSet( mpDisplay, mpFontSet ); + #endif +} + +#ifdef DEBUG + +// ---------------------------------------------------------------------------- +// debug routines, that keep track of fonts we've chosen in a fontset +// ---------------------------------------------------------------------------- + +// report which fonts are missing for the requested +// basefont and which fonts are actually selected + +static void +v_print_missing_fonts( char **pp_list, int n_listsz, const char *p_pattern ) +{ + if ( !(n_listsz > 0) || (pp_list == NULL) || (p_pattern == NULL) ) + return; + + for (int i = 0; i < n_listsz; i++ ) + fprintf(stderr, "missing charset@%s:\"%s\"\n", p_pattern, pp_list[i] ); +} + +static void +v_print_chosen_fonts( XFontSet a_fontset ) +{ + if ( a_fontset == 0 ) + return; + + char *p_locale_name; + XFontStruct **pp_font_struct_list; + char **pp_font_name_list; + int n_listsz; + + p_locale_name = XLocaleOfFontSet( a_fontset ); + n_listsz = XFontsOfFontSet( a_fontset, + &pp_font_struct_list, + &pp_font_name_list ); + for ( int i = 0; i < n_listsz; i++ ) + { + fprintf( stderr, "font@%s:\"%s\"\n", + p_locale_name, pp_font_name_list[i] ); + } +} + +#endif // DEBUG + +// Wrapper for XCreateFontSet to create a default font set +static XFontSet +p_create_fontset( Display *p_display ) +{ + // a fontset, as there is no valid default for russian and all other + // eastern european locales in solaris 8 + const char *p_base_font[] = { + "-*-application-medium-r-*-sans-12-*", + "-*-application-*-r-*-*-12-*", + "-*-*-*-r-*-*-12-*", + "-*" }; + char **pp_missing_charset_list = NULL; + int n_missing_charset_count = 0; + char *p_def_string = NULL; + + XFontSet a_fontset; + + for (int i = 0; i < (sizeof(p_base_font) / sizeof(char*)); i++ ) + { + a_fontset = XCreateFontSet( p_display, p_base_font[i], + &pp_missing_charset_list, + &n_missing_charset_count, &p_def_string); + #ifdef DEBUG + v_print_missing_fonts ( pp_missing_charset_list, + n_missing_charset_count, p_base_font[i] ); + #endif + + if ( a_fontset != 0 ) + break; + } + + #ifdef DEBUG + v_print_chosen_fonts( a_fontset ); + #endif + + return a_fontset; +} + +// ---------------------------------------------------------------------------- +// convenience routine to add items to a XVaNestedList +// ---------------------------------------------------------------------------- + +static XVaNestedList +XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value ) +{ + XVaNestedList a_dstlist; + + // if ( value == NULL ) + // return a_srclist; + + if ( a_srclist == NULL ) + { + a_dstlist = XVaCreateNestedList( + 0, + name, value, + 0 ); + } + else + { + a_dstlist = XVaCreateNestedList( + 0, + XNVaNestedList, a_srclist, + name, value, + 0 ); + } + + return a_dstlist != NULL ? a_dstlist : a_srclist ; +} + +// --------------------------------------------------------------------------- +// +// Constructor for a InputContext (IC) +// +// ---------------------------------------------------------------------------- + +SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) : + mbUseable( True ), + maContext( (XIC)NULL ), + mpAttributes( NULL ), + mpStatusAttributes( NULL ), + mpPreeditAttributes( NULL ), + #ifdef SOLARIS + mpFontSet( NULL ), + #endif + mnStatusStyle( 0 ), + mnPreeditStyle( 0 ), + mnSupportedPreeditStyle( XIMPreeditCallbacks | + XIMPreeditNothing | XIMPreeditNone + /* | XIMPreeditCallbacks + | XIMPreeditArea + | XIMPreeditPosition */ ), + mnSupportedStatusStyle( // XIMStatusCallbacks | + XIMStatusNothing | XIMStatusNone + /* | XIMStatusCallbacks + | XIMStatusArea */ ) +{ + SalI18N_InputMethod *pInputMethod; + pInputMethod = pFrame->maFrameData.GetDisplay()->GetInputMethod(); + mbMultiLingual = pInputMethod->IsMultiLingual(); + + if ( pInputMethod->UseMethod() + && SupportInputMethodStyle( pInputMethod->GetSupportedStyles() ) ) + { + XLIB_Window aClientWindow= pFrame->maFrameData.GetShellWindow(); + XLIB_Window aFocusWindow= pFrame->maFrameData.GetWindow(); + Display *pDisplay = XDisplayOfIM( pInputMethod->GetMethod() ); + + // for status callbacks and commit string callbacks + maClientData.bIsMultilingual = mbMultiLingual; + maClientData.eState = ePreeditStatusStartPending; + maClientData.pFrame = pFrame; + maClientData.aText.pUnicodeBuffer = NULL; + maClientData.aText.pCharStyle = NULL; + maClientData.aText.nCursorPos = 0; + maClientData.aText.nLength = 0; + maClientData.aText.nSize = 0; + + // set status attributes + // only none and nothing are supported which do not need special + // arguments, area and position are just hacks, preedit callback + // does work but cannot be connected without unicode/multibyte + // support of independent vcl layer + + switch ( mnStatusStyle ) + { + case XIMStatusArea: + { + XRectangle *pStatusArea = new XRectangle; + pStatusArea->x = 0; + pStatusArea->y = 64; + pStatusArea->width = 256; + pStatusArea->height = 64; + + mpStatusAttributes = XVaCreateNestedList ( + 0, + XNAreaNeeded, pStatusArea, + XNArea, pStatusArea, + 0 ); + + break; + } + + case XIMStatusNone: + case XIMStatusNothing: + default: + + break; + } + + // + // set preedit attributes + // + + switch ( mnPreeditStyle ) + { + case XIMPreeditCallbacks: + + maPreeditCaretCallback.callback = (XIMProc)PreeditCaretCallback; + maPreeditStartCallback.callback = (XIMProc)PreeditStartCallback; + maPreeditDoneCallback.callback = (XIMProc)PreeditDoneCallback; + maPreeditDrawCallback.callback = (XIMProc)PreeditDrawCallback; + maPreeditCaretCallback.client_data = (XPointer)&maClientData; + maPreeditStartCallback.client_data = (XPointer)&maClientData; + maPreeditDoneCallback.client_data = (XPointer)&maClientData; + maPreeditDrawCallback.client_data = (XPointer)&maClientData; + + mpPreeditAttributes = XVaCreateNestedList ( + 0, + XNPreeditStartCallback, &maPreeditStartCallback, + XNPreeditDoneCallback, &maPreeditDoneCallback, + XNPreeditDrawCallback, &maPreeditDrawCallback, + XNPreeditCaretCallback, &maPreeditCaretCallback, + 0 ); + + break; + + case XIMPreeditPosition: + case XIMPreeditArea: + { + XRectangle *pPreeditArea = new XRectangle; + XPoint *pSpotLocation = new XPoint; + + pSpotLocation->x = 16; + pSpotLocation->y = 32; + + pPreeditArea->x = 0; + pPreeditArea->y = 0; + pPreeditArea->width = 256; + pPreeditArea->height = 64; + + mpPreeditAttributes = XVaCreateNestedList ( + 0, + XNArea, pPreeditArea, + XNSpotLocation, pSpotLocation, + 0 ); + + break; + } + + case XIMPreeditNone: + case XIMPreeditNothing: + default: + + break; + } + + // Create the InputContext by given it exact the information it + // deserves, because inappropriate attributes + // let XCreateIC fail on Solaris (eg. for C locale) + + mpAttributes = XVaCreateNestedList( + 0, + XNFocusWindow, aFocusWindow, + XNClientWindow, aClientWindow, + XNInputStyle, mnPreeditStyle | mnStatusStyle, + 0 ); + + #ifdef SOLARIS + mpDisplay = pDisplay; + if ( 0 && (mpFontSet = p_create_fontset(mpDisplay)) != NULL ) + { + mpStatusAttributes = XVaAddToNestedList( mpStatusAttributes, + XNFontSet, (XPointer)mpFontSet ); + mpPreeditAttributes = XVaAddToNestedList( mpPreeditAttributes, + XNFontSet, (XPointer)mpFontSet ); + } + #endif + if ( mnPreeditStyle != XIMPreeditNone ) + { + #ifdef LINUX + if ( mpPreeditAttributes != NULL ) + #endif + mpAttributes = XVaAddToNestedList( mpAttributes, + XNPreeditAttributes, (XPointer)mpPreeditAttributes ); + } + if ( mnStatusStyle != XIMStatusNone ) + { + #ifdef LINUX + if ( mpStatusAttributes != NULL ) + #endif + mpAttributes = XVaAddToNestedList( mpAttributes, + XNStatusAttributes, (XPointer)mpStatusAttributes ); + } + maContext = XCreateIC( pInputMethod->GetMethod(), + XNVaNestedList, mpAttributes, + NULL ); + } + + if ( maContext == NULL ) + { + #ifdef DEBUG + fprintf(stderr, "input context creation failed\n"); + #endif + + mbUseable = False; + mbMultiLingual = False; + + if ( mpAttributes != NULL ) + XFree( mpAttributes ); + if ( mpStatusAttributes != NULL ) + XFree( mpStatusAttributes ); + if ( mpPreeditAttributes != NULL ) + XFree( mpPreeditAttributes ); + } + + if ( maContext != NULL && mbMultiLingual ) + { + maCommitStringCallback.callback = (XIMProc)::CommitStringCallback; + maCommitStringCallback.client_data = (XPointer)&maClientData; + XSetICValues( maContext, + XNCommitStringCallback, &maCommitStringCallback, + NULL ); + } + +} + +// --------------------------------------------------------------------------- +// +// In Solaris 8 the status window does not unmap if the frame unmapps, so +// unmap it the hard way +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::Unmap() +{ + if ( maContext != NULL ) + { + XDestroyIC( maContext ); + maContext = NULL; + } +} + +void +SalI18N_InputContext::Map( SalFrame *pFrame ) +{ + if ( (maContext == NULL) && mbUseable) + { + SalI18N_InputMethod *pInputMethod; + pInputMethod = pFrame->maFrameData.GetDisplay()->GetInputMethod(); + + maContext = XCreateIC( pInputMethod->GetMethod(), + XNVaNestedList, mpAttributes, + NULL ); + if ( maContext != NULL && mbMultiLingual ) + XSetICValues( maContext, + XNCommitStringCallback, &maCommitStringCallback, + NULL ); + SetICFocus(); + } +} + +// --------------------------------------------------------------------------- +// +// make sure, the input method gets all the X-Events it needs, this is only +// called once on each frame, it relys on a valid maContext +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow ) +{ + unsigned long nIMEventMask; + XWindowAttributes aWindowAttributes; + + if ( mbUseable ) + { + Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) ); + + XGetWindowAttributes( pDisplay, aFocusWindow, + &aWindowAttributes ); + XGetICValues ( maContext, + XNFilterEvents, &nIMEventMask, + NULL); + nIMEventMask |= aWindowAttributes.your_event_mask; + XSelectInput ( pDisplay, aFocusWindow, nIMEventMask ); + } +} + +// --------------------------------------------------------------------------- +// +// tune the styles provided by the input method with the supported one +// +// --------------------------------------------------------------------------- + +unsigned int +SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle ) const +{ + struct StyleWeightingT { + const XIMStyle nStyle; + const unsigned int nWeight; + }; + + StyleWeightingT const *pWeightPtr; + const StyleWeightingT pWeight[] = { + { XIMPreeditCallbacks, 0x10000000 }, + { XIMPreeditPosition, 0x02000000 }, + { XIMPreeditArea, 0x01000000 }, + { XIMPreeditNothing, 0x00100000 }, + { XIMPreeditNone, 0x00010000 }, + { XIMStatusCallbacks, 0x1000 }, + { XIMStatusArea, 0x0100 }, + { XIMStatusNothing, 0x0010 }, + { XIMStatusNone, 0x0001 }, + { 0, 0x0 } + }; + + int nWeight = 0; + for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ ) + { + if ( (pWeightPtr->nStyle & nStyle) != 0 ) + nWeight += pWeightPtr->nWeight; + } + return nWeight; +} + +Bool +SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const +{ + if ( (nStyle & mnSupportedPreeditStyle) + && (nStyle & mnSupportedStatusStyle) ) + { + return True; + } + return False; +} + +Bool +SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles ) +{ + int nBestScore = 0; + int nActualScore = 0; + + mnPreeditStyle = 0; + mnStatusStyle = 0; + + if ( pIMStyles != NULL ) + { + // check whether the XIM supports one of the desired styles + // only a single preedit and a single status style must occure + // in a inpuut method style. Hideki said so, so i trust him + for ( int nStyle = 0; nStyle < pIMStyles->count_styles; nStyle++ ) + { + XIMStyle nProvidedStyle = pIMStyles->supported_styles[ nStyle ]; + if ( IsSupportedIMStyle(nProvidedStyle) ) + { + nActualScore = GetWeightingOfIMStyle( nProvidedStyle ); + if ( nActualScore >= nBestScore ) + { + nBestScore = nActualScore; + mnPreeditStyle = nProvidedStyle & mnSupportedPreeditStyle; + mnStatusStyle = nProvidedStyle & mnSupportedStatusStyle; + } + } + } + } + + #ifdef DEBUG + char pBuf[ 128 ]; + fprintf( stderr, "selected inputmethod style = %s\n", + GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) ); + #endif + + return (mnPreeditStyle != 0) && (mnStatusStyle != 0) ; +} + +int +SalI18N_InputContext::CommitStringCallback( sal_Unicode* pText, sal_Size nLength ) +{ + XIMUnicodeText call_data; + + call_data.string.utf16_char = pText; + call_data.length = nLength; + call_data.annotations = NULL; + call_data.count_annotations = 0; + call_data.feedback = NULL; + + return ::CommitStringCallback( maContext, + (XPointer)&maClientData, (XPointer)&call_data ); +} + +// --------------------------------------------------------------------------- +// +// set and unset the focus for the Input Context +// the context may be NULL despite it is useable if the framewindow is +// in unmapped state +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::SetICFocus() +{ + if ( mbUseable && (maContext != NULL) ) + XSetICFocus( maContext ); +} + +void +SalI18N_InputContext::UnsetICFocus() +{ + if ( mbUseable && (maContext != NULL) ) + XUnsetICFocus( maContext ); +} + +// --------------------------------------------------------------------------- +// +// not used, multi byte input method only +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::EndExtTextInput( USHORT nFlags ) +{ + if ( mbUseable && (maContext != NULL) ) + { + char *pPendingChars = XmbResetIC( maContext ); + + // text is unicode + if ( (pPendingChars != NULL) + && (nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE) ) + { + XIMUnicodeText aPendingText; + int nLen; + sal_Unicode* pPtr; + rtl_TextEncoding nEncoding = gsl_getSystemTextEncoding(); + + // buffer is already unicode + if ( mbMultiLingual || nEncoding == RTL_TEXTENCODING_UNICODE ) + { + pPtr = (sal_Unicode*)pPendingChars; + for ( nLen = 0; pPtr[ nLen ] != (sal_Unicode)0; nLen++ ) + ; + } + // else convert buffer to unicode + else + { + for ( nLen = 0; pPendingChars[ nLen ] != (char)0; nLen++ ) + ; + + // create text converter + rtl_TextToUnicodeConverter aConverter = + rtl_createTextToUnicodeConverter( nEncoding ); + rtl_TextToUnicodeContext aContext = + rtl_createTextToUnicodeContext( aConverter ); + + sal_Size nBufferSize = nLen * 2; + sal_uInt32 nConversionInfo; + sal_Size nConvertedChars; + + pPtr = (sal_Unicode*) alloca( nBufferSize ); + + // convert to single byte text stream + nLen = rtl_convertTextToUnicode( + aConverter, aContext, (char*)pPendingChars, + nLen, pPtr, nBufferSize, + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE + | RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE, + &nConversionInfo, &nConvertedChars ); + + // destroy converter + rtl_destroyTextToUnicodeContext( aConverter, aContext ); + rtl_destroyTextToUnicodeConverter( aConverter ); + } + aPendingText.length = nLen; + aPendingText.string.utf16_char = pPtr; + + ::CommitStringCallback( maContext, + (XPointer)&maClientData, (XPointer)&aPendingText ); + } + if ( pPendingChars != NULL ) + XFree ( (void*)pPendingChars ); + } +} + + diff --git a/vcl/unx/source/app/i18n_im.cxx b/vcl/unx/source/app/i18n_im.cxx new file mode 100644 index 000000000000..04c1f9b24ca2 --- /dev/null +++ b/vcl/unx/source/app/i18n_im.cxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * $RCSfile: i18n_im.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): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> + +#include <prex.h> +#include <X11/Xlocale.h> +#include <X11/Xlib.h> +#include <XIM.h> +#include <postx.h> + +#include <salunx.h> + +#ifndef _SAL_I18N_INPUTMETHOD_HXX +#include "i18n_im.hxx" +#endif + +// ------------------------------------------------------------------------- +// +// locale handling +// +// ------------------------------------------------------------------------- + +// Locale handling of the operating system layer + +static char* +SetSystemLocale( const char* p_inlocale ) +{ + char *p_outlocale; + if ( (p_outlocale = setlocale(LC_ALL, p_inlocale)) == NULL ) + { + fprintf( stderr, + "I18N: Operating system doesn't support locale \"%s\"\n", + p_inlocale ); + } + + return p_outlocale; +} + +static Bool +IsPosixLocale( const char* p_locale ) +{ + if ( p_locale == NULL ) + return False; + if ( (p_locale[ 0 ] == 'C') && (p_locale[ 1 ] == '\0') ) + return True; + if ( strncmp(p_locale, "POSIX", sizeof("POSIX")) == 0 ) + return True; + + return False; +} + +// Locale handling of the X Window System layer + +static Bool +IsXWindowCompatibleLocale( const char* p_locale ) +{ + if ( p_locale == NULL ) + return False; + + if ( !XSupportsLocale() ) + { + if ( p_locale != NULL ) + fprintf (stderr, + "I18N: X Window System doesn't support locale \"%s\"\n", + p_locale ); + return False; + } + return True; +} + +// Locale setting for the Input Method +// allways provide a fallback, even if it means falling back to the +// portable POSIX "C" locale + +Bool +SalI18N_InputMethod::SetLocale( const char* pLocale ) +{ + // check whether we want an Input Method engine, if we don't we + // do not need to set the locale + if ( mbUseable ) + { + char *locale; + + // check whether the operating system supports the LANG + if ( (locale = SetSystemLocale( pLocale )) == NULL ) + { + if ( (locale = SetSystemLocale( "C" )) == NULL ) + mbUseable = False; + } + + // check whether the XWindow system supports the LANG + if ( !IsXWindowCompatibleLocale(locale) ) + { + if ( !IsPosixLocale(locale) ) + { + locale = SetSystemLocale( "C" ); + if ( !IsXWindowCompatibleLocale(locale) ) + mbUseable = False; + } + else + { + mbUseable = False; + } + } + + // must not fail if mbUseable since XSupportsLocale() asserts success + if ( mbUseable && XSetLocaleModifiers("") == NULL ) + { + fprintf (stderr, "I18N: Can't set X modifiers for locale \"%s\"\n", + locale); + mbUseable = False; + } + } + + return mbUseable; +} + +// ------------------------------------------------------------------------ +// +// Constructor / Destructor / Initialisation +// +// ------------------------------------------------------------------------ + +SalI18N_InputMethod::SalI18N_InputMethod( ) : maMethod( (XIM)NULL ), + mpStyles( (XIMStyles*)NULL ), + mbUseable( bUseInputMethodDefault ), + mbMultiLingual( False ) +{ + const char *pUseInputMethod = getenv( "SAL_USEINPUTMETHOD" ); + if ( pUseInputMethod != NULL ) + mbUseable = pUseInputMethod[0] != '\0' ; +} + +SalI18N_InputMethod::~SalI18N_InputMethod() +{ + if ( mpStyles != NULL ) + XFree( mpStyles ); + if ( maMethod != NULL ) + XCloseIM ( maMethod ); +} + +// +// XXX +// debug routine: lets have a look at the provided method styles +// + +#ifdef DEBUG + +extern "C" char* +GetMethodName( XIMStyle nStyle, char *pBuf, int nBufSize) +{ + struct StyleName { + const XIMStyle nStyle; + const char *pName; + const int nNameLen; + }; + + StyleName *pDescPtr; + static const StyleName pDescription[] = { + { XIMPreeditArea, "PreeditArea ", sizeof("PreeditArea ") }, + { XIMPreeditCallbacks, "PreeditCallbacks ",sizeof("PreeditCallbacks ")}, + { XIMPreeditPosition, "PreeditPosition ", sizeof("PreeditPosition ") }, + { XIMPreeditNothing, "PreeditNothing ", sizeof("PreeditNothing ") }, + { XIMPreeditNone, "PreeditNone ", sizeof("PreeditNone ") }, + { XIMStatusArea, "StatusArea ", sizeof("StatusArea ") }, + { XIMStatusCallbacks, "StatusCallbacks ", sizeof("StatusCallbacks ") }, + { XIMStatusNothing, "StatusNothing ", sizeof("StatusNothing ") }, + { XIMStatusNone, "StatusNone ", sizeof("StatusNone ") }, + { 0, "NULL", 0 } + }; + + if ( nBufSize > 0 ) + pBuf[0] = '\0'; + + char *pBufPtr = pBuf; + for ( pDescPtr = const_cast<StyleName*>(pDescription); pDescPtr->nStyle != 0; pDescPtr++ ) + { + int nSize = pDescPtr->nNameLen - 1; + if ( (nStyle & pDescPtr->nStyle) && (nBufSize > nSize) ) + { + strncpy( pBufPtr, pDescPtr->pName, nSize + 1); + pBufPtr += nSize; + nBufSize -= nSize; + } + } + + return pBuf; +} + +extern "C" void +PrintInputStyle( XIMStyles *pStyle ) +{ + char pBuf[ 128 ]; + int nBuf = sizeof( pBuf ); + + if ( pStyle == NULL ) + fprintf( stderr, "no input method styles\n"); + else + for ( int nStyle = 0; nStyle < pStyle->count_styles; nStyle++ ) + { + fprintf( stderr, "style #%i = %s\n", nStyle, + GetMethodName(pStyle->supported_styles[nStyle], pBuf, nBuf) ); + } +} + +#endif + +// +// this is the real constructing routine, since locale setting has to be done +// prior to xopendisplay, the xopenim call has to be delayed +// + +Bool +SalI18N_InputMethod::CreateMethod ( Display *pDisplay ) +{ + if ( mbUseable ) + { + if ( getenv("USE_XOPENIM") == NULL ) + { + mbMultiLingual = True; // set ml-input flag to create input-method + maMethod = XvaOpenIM(pDisplay, NULL, NULL, NULL, + XNMultiLingualInput, mbMultiLingual, /* dummy */ + 0); + // get ml-input flag from input-method + if ( maMethod == (XIM)NULL ) + mbMultiLingual = False; + else + if ( XGetIMValues(maMethod, + XNMultiLingualInput, &mbMultiLingual, NULL ) != NULL ) + mbMultiLingual = False; + } + else + { + maMethod = XOpenIM(pDisplay, NULL, NULL, NULL); + mbMultiLingual = False; + } + + if ( maMethod != (XIM)NULL ) + { + if ( XGetIMValues(maMethod, XNQueryInputStyle, &mpStyles, NULL) + != NULL) + mbUseable = False; + #ifdef DEBUG + fprintf(stderr, "Creating %s-Lingual InputMethod\n", + mbMultiLingual ? "Multi" : "Mono" ); + PrintInputStyle( mpStyles ); + #endif + } + else + { + mbUseable = False; + } + } + + #ifdef DEBUG + if ( !mbUseable ) + fprintf(stderr, "input method creation failed\n"); + #endif + + return mbUseable; +} + +// +// give IM the opportunity to look at the event, and possibly hide it +// + +Bool +SalI18N_InputMethod::FilterEvent( XEvent *pEvent ) +{ + return mbUseable && (Bool)XFilterEvent( pEvent, None ); +} + + diff --git a/vcl/unx/source/app/i18n_wrp.cxx b/vcl/unx/source/app/i18n_wrp.cxx new file mode 100644 index 000000000000..4ad92b28d3cb --- /dev/null +++ b/vcl/unx/source/app/i18n_wrp.cxx @@ -0,0 +1,293 @@ +/************************************************************************* + * + * $RCSfile: i18n_wrp.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): _______________________________________ + * + * + ************************************************************************/ + +struct XIMArg +{ + char *name; + char *value; +}; + +#if !defined(LINUX) +#include <varargs.h> +#else +#include <stdarg.h> +#endif +#include <string.h> +#include <dlfcn.h> +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include "XIM.h" + + +#ifdef SOLARIS +#define XIIIMP_PATH "/usr/openwin/lib/locale/common/xiiimp.so.2" +#else /* Linux */ +#define XIIIMP_PATH "/usr/lib/im/xiiimp.so.2" +#endif + +/* global variables */ +static void *g_dlmodule = 0; + +extern "C" { +typedef XIM (*OpenFunction)(Display*, XrmDatabase, char*, char*, XIMArg*); +} + +static OpenFunction g_open_im = (OpenFunction)NULL; + +/* utility function to transform vararg list into an array of XIMArg */ + +int +XvaCountArgs( XIMArg *pInArgs ) +{ + int nArgs = 0; + char *pName, *pValue; + + while ( (pName = pInArgs->name) != NULL ) + { + pValue = pInArgs->value; + + if ( strcmp(pName, XNVaNestedList) == 0 ) + { + nArgs += XvaCountArgs( (XIMArg*)pValue ); + } + else + { + nArgs += 1; + } + pInArgs++; + } + + return nArgs; +} + +int +XvaCountArgs( va_list pInArgs ) +{ + int nArgs = 0; + char *pName, *pValue; + + while ( (pName = va_arg(pInArgs, char*)) != NULL) + { + pValue = va_arg(pInArgs, char*); + + if ( strcmp(pName, XNVaNestedList) == 0 ) + { + nArgs += XvaCountArgs( (XIMArg*)pValue ); + } + else + { + nArgs += 1; + } + } + + return nArgs; +} + +XIMArg* +XvaGetArgs( XIMArg *pInArgs, XIMArg *pOutArgs ) +{ + char *pName, *pValue; + + while ( (pName = pInArgs->name) != NULL ) + { + pValue = pInArgs->value; + + if ( strcmp(pName, XNVaNestedList) == 0 ) + { + pOutArgs = XvaGetArgs( (XIMArg*)pValue, pOutArgs ); + } + else + { + pOutArgs->name = pName; + pOutArgs->value = pValue; + pOutArgs++; + } + pInArgs++; + } + + return pOutArgs; +} + +void +XvaGetArgs( va_list pInArgs, XIMArg *pOutArgs ) +{ + char *pName, *pValue; + + while ((pName = va_arg(pInArgs, char*)) != NULL) + { + pValue = va_arg(pInArgs, char*); + + if ( strcmp(pName, XNVaNestedList) == 0 ) + { + pOutArgs = XvaGetArgs( (XIMArg*)pValue, pOutArgs ); + } + else + { + pOutArgs->name = pName; + pOutArgs->value = pValue; + pOutArgs++; + } + } + + pOutArgs->name = NULL; + pOutArgs->value = NULL; +} + + +/* Puplic functions */ + +#ifdef __cplusplus +extern "C" +#endif +XIM +XvaOpenIM(Display *display, XrmDatabase rdb, + char *res_name, char *res_class, ...) +{ + XIM xim = (XIM)0; + va_list variable; + int total_count = 0; + + /* + * so count the stuff dangling here + */ + + #ifdef LINUX + va_start(variable, res_class); + #else + va_start(variable); + #endif + total_count = XvaCountArgs(variable); + va_end(variable); + + if (total_count > 0) + { + /* call a new open IM method */ + + XIMArg* args = (XIMArg*)Xmalloc( (total_count + 1) * sizeof(XIMArg) ); + + /* + * now package it up so we can set it along + */ + #ifdef LINUX + va_start(variable, res_class); + #else + va_start(variable); + #endif + XvaGetArgs( variable, args ); + va_end(variable); + + if (!g_dlmodule) + { + g_dlmodule = dlopen(XIIIMP_PATH, RTLD_LAZY); + if (!g_dlmodule) + goto legacy_XIM; + + g_open_im = (OpenFunction)(long)dlsym(g_dlmodule, "__XOpenIM"); + if (!g_open_im) + goto legacy_XIM; + + xim = (*g_open_im)(display, (XrmDatabase)rdb, + (char*)res_name, (char *)res_class, (XIMArg*)args); + } + else + { + goto legacy_XIM; + } + } + + legacy_XIM: + + if (!xim) + xim = XOpenIM(display, rdb, res_name, res_class); + + return xim; +} + +/* + * Close the connection to the input manager, and free the XIM structure + */ + +Status +XvaCloseIM(XIM im) +{ + Status s; + #if 0 + XCloseIM(im); + s = (im->methods->close)(im); /* we can use the same close module */ + #endif + + if (!g_dlmodule) + { + /* assuming one XvaOpenIM call */ + dlclose(g_dlmodule); + g_dlmodule = (void*)0; + g_open_im = (OpenFunction)NULL; + } + #if 0 + if (im) + Xfree((char *)im); + #endif + + return (s); +} + + + diff --git a/vcl/unx/source/app/i18n_xkb.cxx b/vcl/unx/source/app/i18n_xkb.cxx new file mode 100644 index 000000000000..b57abd09acc4 --- /dev/null +++ b/vcl/unx/source/app/i18n_xkb.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * $RCSfile: i18n_xkb.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): _______________________________________ + * + * + ************************************************************************/ + + +#include <stdio.h> + +#if defined(LINUX) // should really check for xfree86 or for X11R6.1 and higher +#define __XKeyboardExtension__ 1 +#else +#define __XKeyboardExtension__ 0 +#endif + +#include <prex.h> +#include <X11/X.h> +#if __XKeyboardExtension__ +#include <X11/XKBlib.h> +#endif +#include <postx.h> + +#ifndef _SAL_I18N_XKBDEXTENSION_HXX +#include "i18n_xkb.hxx" +#endif + +SalI18N_KeyboardExtension::SalI18N_KeyboardExtension( Display *pDisplay ) + : mbUseExtension( (sal_Bool)__XKeyboardExtension__ ), + mnDefaultGroup( 0 ) +{ + #if __XKeyboardExtension__ + + mpDisplay = pDisplay; + + // allow user to set the default keyboard group idx or to disable the usage + // of x keyboard extension at all: + // setenv SAL_XKEYBOARDGROUP disables keyboard extension + // setenv SAL_XKEYBOARDGROUP 2 sets the keyboard group index to 2 + // keyboard group index must be in [1,4], may be specified in hex or decimal + static char *pUseKeyboardExtension = getenv( "SAL_XKEYBOARDGROUP" ); + if ( pUseKeyboardExtension != NULL ) + { + mbUseExtension = pUseKeyboardExtension[0] != '\0' ; + if ( mbUseExtension ) + mnDefaultGroup = strtol( pUseKeyboardExtension, NULL, 0 ); + if ( mnDefaultGroup > XkbMaxKbdGroup ) + mnDefaultGroup = 0; + } + + // query XServer support for XKB Extension, + // do not call XQueryExtension() / XInitExtension() due to possible version + // clashes ! + if ( mbUseExtension ) + { + int nMajorExtOpcode; + int nExtMajorVersion = XkbMajorVersion; + int nExtMinorVersion = XkbMinorVersion; + + mbUseExtension = (sal_Bool)XkbQueryExtension( mpDisplay, + &nMajorExtOpcode, (int*)&mnEventBase, (int*)&mnErrorBase, + &nExtMajorVersion, &nExtMinorVersion ); + } + + // query notification for changes of the keyboard group + if ( mbUseExtension ) + { + #define XkbGroupMask ( XkbGroupStateMask | XkbGroupBaseMask \ + | XkbGroupLatchMask | XkbGroupLockMask ) + + mbUseExtension = XkbSelectEventDetails( mpDisplay, + XkbUseCoreKbd, XkbStateNotify, XkbGroupMask, XkbGroupMask ); + } + + // query initial keyboard group + if ( mbUseExtension ) + { + XkbStateRec aStateRecord; + XkbGetState( mpDisplay, XkbUseCoreKbd, &aStateRecord ); + mnGroup = aStateRecord.group; + } + + #endif // __XKeyboardExtension__ +} + +void +SalI18N_KeyboardExtension::Dispatch( XEvent *pEvent ) +{ + #if __XKeyboardExtension__ + + // must the event be handled? + if ( !mbUseExtension + || (pEvent->type != mnEventBase) ) + return; + + // only handle state notify events for now, and only interested + // in group details + sal_uInt32 nXKBType = ((XkbAnyEvent*)pEvent)->xkb_type; + switch ( nXKBType ) + { + case XkbStateNotify: + + mnGroup = ((XkbStateNotifyEvent*)pEvent)->group; + break; + + default: + + #ifdef DEBUG + fprintf(stderr, "Got unrequested XkbAnyEvent %#x/%i\n", + nXKBType, nXKBType ); + #endif + break; + } + + #endif // __XKeyboardExtension__ +} + +sal_uInt32 +SalI18N_KeyboardExtension::LookupKeysymInGroup( sal_uInt32 nKeyCode, + sal_uInt32 nShiftState, + sal_uInt32 nGroup ) const +{ + #if __XKeyboardExtension__ + + if ( !mbUseExtension ) + return NoSymbol; + + nShiftState &= ShiftMask; + + KeySym nKeySymbol; + nKeySymbol = XkbKeycodeToKeysym( mpDisplay, nKeyCode, nGroup, nShiftState ); + return nKeySymbol; + + #else + + return NoSymbol; + + #endif // __XKeyboardExtension__ +} + + diff --git a/vcl/unx/source/app/keysymnames.cxx b/vcl/unx/source/app/keysymnames.cxx new file mode 100644 index 000000000000..e08804ff371e --- /dev/null +++ b/vcl/unx/source/app/keysymnames.cxx @@ -0,0 +1,545 @@ +/************************************************************************* + * + * $RCSfile: keysymnames.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): _______________________________________ + * + * + ************************************************************************/ + +#ifndef SOLARIS +#include <prex.h> +#include <X11/XKBlib.h> +#include <postx.h> +#endif + +#include <saldisp.hxx> +#include <X11/keysym.h> + +#ifdef SOLARIS +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/kbio.h> +#include <sys/kbd.h> +#include <stdio.h> +#include <fcntl.h> +#include <deflt.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#ifndef KB_USB // compile with too old headers +#define KB_USB 6 +#endif +#endif + +namespace vcl_sal { + + struct KeysymNameReplacement + { + KeySym aSymbol; + const char* pName; + }; + + struct KeyboardReplacements + { + const char* pKeyboardName; + const KeysymNameReplacement* pReplacements; + int nReplacements; + rtl_TextEncoding nEncoding; + }; + + static const struct KeysymNameReplacement aImplReplacements_German[] = + { + { XK_Control_L, "Strg" }, + { XK_Control_R, "Strg" }, + { XK_Shift_L, "Umschalt" }, + { XK_Shift_R, "Umschalt" }, + { XK_Alt_L, "Alt" }, + { XK_Alt_R, "Alt Gr" }, + { XK_Page_Up, "Bild auf" }, + { XK_Page_Down, "Bild ab" }, + { XK_End, "Ende" }, + { XK_Home, "Pos 1" }, + { XK_Insert, "Einfg" }, + { XK_Delete, "Entf" }, + { XK_Escape, "Esc" }, + { XK_Right, "Rechts" }, + { XK_Left, "Links" }, + { XK_Up, "Oben" }, + { XK_Down, "Unten" }, + { XK_BackSpace, "Rückschritt" }, + { XK_Return, "Eingabe" }, + { XK_slash, "Schrägstrich" }, + { XK_space, "Leertaste" } + }; + + static const struct KeysymNameReplacement aImplReplacements_French[] = + { + { XK_Shift_L, "Maj" }, + { XK_Shift_R, "Maj" }, + { XK_Page_Up, "Pg. Préc" }, + { XK_Page_Down, "Pg. Suiv" }, + { XK_End, "Fin" }, + { XK_Home, "Origine" }, + { XK_Insert, "Insérer" }, + { XK_Delete, "Suppr" }, + { XK_Escape, "Esc" }, + { XK_Right, "Droite" }, + { XK_Left, "Gauche" }, + { XK_Up, "Haut" }, + { XK_Down, "Bas" }, + { XK_BackSpace, "Ret. Arr" }, + { XK_Return, "Retour" }, + { XK_KP_Enter, "Entrée" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Italian[] = + { + { XK_Shift_L, "Maiusc" }, + { XK_Shift_R, "Maiusc" }, + { XK_Page_Up, "PgSu" }, + { XK_Page_Down, "PgGiu" }, + { XK_End, "Fine" }, + { XK_Insert, "Ins" }, + { XK_Delete, "Canc" }, + { XK_Escape, "Esc" }, + { XK_Right, "A destra" }, + { XK_Left, "A sinistra" }, + { XK_Up, "Sposta verso l'alto" }, + { XK_Down, "Sposta verso il basso" }, + { XK_BackSpace, "Backspace" }, + { XK_Return, "Invio" }, + { XK_space, "Spaziatrice" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Dutch[] = + { + { XK_Page_Up, "PageUp" }, + { XK_Page_Down, "PageDown" }, + { XK_Escape, "Esc" }, + { XK_Right, "Rechts" }, + { XK_Left, "Links" }, + { XK_Up, "Boven" }, + { XK_Down, "Onder" }, + { XK_BackSpace, "Backspace" }, + { XK_Return, "Return" }, + { XK_space, "Spatiebalk" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Norwegian[] = + { + { XK_Shift_L, "Skift" }, + { XK_Shift_R, "Skift" }, + { XK_Page_Up, "PageUp" }, + { XK_Page_Down, "PageDown" }, + { XK_Escape, "Esc" }, + { XK_Right, "Hyre" }, + { XK_Left, "Venstre" }, + { XK_Up, "Opp" }, + { XK_Down, "Ned" }, + { XK_BackSpace, "Tilbake" }, + { XK_Return, "Enter" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Swedish[] = + { + { XK_Shift_L, "Skift" }, + { XK_Shift_R, "Skift" }, + { XK_Page_Up, "PageUp" }, + { XK_Page_Down, "PageDown" }, + { XK_Escape, "Esc" }, + { XK_Right, "Höger" }, + { XK_Left, "Vänster" }, + { XK_Up, "Up" }, + { XK_Down, "Ned" }, + { XK_BackSpace, "Backsteg" }, + { XK_Return, "Retur" }, + { XK_space, "Blank" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Portuguese[] = + { + { XK_Page_Up, "PageUp" }, + { XK_Page_Down, "PageDown" }, + { XK_Escape, "Esc" }, + { XK_Right, "Direita" }, + { XK_Left, "Esquerda" }, + { XK_Up, "Acima" }, + { XK_Down, "Abaixo" }, + { XK_BackSpace, "Rückschritt" }, + { XK_Return, "Eingabe" }, + { XK_slash, "Schrägstrich" } + }; + + static const struct KeysymNameReplacement aImplReplacements_Spanish[] = + { + { XK_Shift_L, "Mayos" }, + { XK_Shift_R, "Mayos" }, + { XK_Page_Up, "RePág" }, + { XK_Page_Down, "AvPág" }, + { XK_End, "Fin" }, + { XK_Home, "Inicio" }, + { XK_Delete, "Supr" }, + { XK_Escape, "Esc" }, + { XK_Right, "Hacia la derecha" }, + { XK_Left, "Hacia la izquierda" }, + { XK_Up, "Hacia arriba" }, + { XK_Down, "Hacia abajo" }, + { XK_BackSpace, "Ret" }, + { XK_Return, "Entrada" }, + { XK_space, "Espacio" }, + { XK_KP_Enter, "Intro" } + }; + + static const struct KeyboardReplacements aKeyboards[] = + { +#ifdef SOLARIS + { "Germany5", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Germany4", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "France5", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "France6", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "France_x86", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italy5", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italy5-Hobo", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italy4", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italy6", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italy_x86", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Netherland4", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Netherland5", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Netherland5-Hobo", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Netherland6", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Netherland_x86", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norway5", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norway5-Hobo", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norway4", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norway6", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norway_x86", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portugal5", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portugal5-Hobo", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portugal4", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portugal6", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portugal_x86", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spain5", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spain5-Hobo", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spain4", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spain6", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spain_x86", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Sweden5", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Sweden5-Hobo", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Sweden4", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Sweden6", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Sweden_x86", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, +#endif + { "German", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "French", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Norwegian", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Swedish", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Portuguese", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Spanish", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]), RTL_TEXTENCODING_ISO_8859_1 }, + { "Italian", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]), RTL_TEXTENCODING_ISO_8859_1 } + }; + + String getKeysymReplacementName( const char* pKeyboard, KeySym nSymbol ) + { + for( int n = 0; n < sizeof(aKeyboards)/sizeof(aKeyboards[0]); n++ ) + { + if( ! strcasecmp( pKeyboard, aKeyboards[n].pKeyboardName ) ) + { + const struct KeysymNameReplacement* pRepl = aKeyboards[n].pReplacements; + for( int m = aKeyboards[n].nReplacements ; m ; ) + { + if( nSymbol == pRepl[--m].aSymbol ) + return String( pRepl[m].pName, aKeyboards[n].nEncoding ); + } + } + } + return String(); + } + +} + +#ifdef SOLARIS +typedef struct { + int n_layout; + const char* p_description; +} keyboard_layout; + +static const keyboard_layout type0_layout[] = +{ + { 0, "US4" }, + { -1, NULL } +}; + +static const keyboard_layout type3_layout[] = +{ + { 0, "US3" }, + { -1, NULL } +}; + +static const keyboard_layout type4_layout[] = +{ + { 0, "US4" }, + { 1, "US4" }, + { 2, "FranceBelg4" }, + { 3, "Canada4" }, + { 4, "Denmark4" }, + { 5, "Germany4" }, + { 6, "Italy4" }, + { 7, "Netherland4" }, + { 8, "Norway4" }, + { 9, "Portugal4" }, + { 10, "SpainLatAm4" }, + { 11, "SwedenFin4" }, + { 12, "Switzer_Fr4" }, + { 13, "Switzer_Ge4" }, + { 14, "UK4" }, + { 16, "Korea4" }, + { 17, "Taiwan4" }, + { 19, "US101A_PC" }, + { 19, "US101A_Sun" }, + { 32, "Japan4" }, + { 33, "US5" }, + { 34, "US_UNIX5" }, + { 35, "France5" }, + { 36, "Denmark5" }, + { 37, "Germany5" }, + { 38, "Italy5" }, + { 39, "Netherland5" }, + { 40, "Norway5" }, + { 41, "Portugal5" }, + { 42, "Spain5" }, + { 43, "Sweden5" }, + { 44, "Switzer_Fr5" }, + { 45, "Switzer_Ge5" }, + { 46, "UK5" }, + { 47, "Korea5" }, + { 48, "Taiwan5" }, + { 49, "Japan5" }, + { 50, "Canada_Fr5" }, + { 51, "Hungary5" }, + { 52, "Poland5" }, + { 53, "Czech5" }, + { 54, "Russia5" }, + { 55, "Latvia5" }, + { 56, "Turkey5" }, + { 57, "Greece5" }, + { 58, "Estonia5" }, + { 59, "Lithuania5" }, + { 63, "Canada_Fr5_TBITS5" }, + { 80, "US5_Hobo" }, + { 81, "US_UNIX5_Hobo" }, + { 82, "France5_Hobo" }, + { 83, "Denmark5_Hobo" }, + { 84, "Germany5_Hobo" }, + { 85, "Italy5_Hobo" }, + { 86, "Netherland5_Hobo" }, + { 87, "Norway5_Hobo" }, + { 88, "Portugal5_Hobo" }, + { 89, "Spain5_Hobo" }, + { 90, "Sweden5_Hobo" }, + { 91, "Switzer_Fr5_Hobo" }, + { 92, "Switzer_Ge5_Hobo" }, + { 93, "UK5_Hobo" }, + { 94, "Korea5_Hobo" }, + { 95, "Taiwan5_Hobo" }, + { 96, "Japan5_Hobo" }, + { 97, "Canada_Fr5_Hobo" }, + { -1, NULL } +}; + +static const keyboard_layout type101_layout[] = +{ + { 0, "US101A_x86" }, + { 1, "US101A_x86" }, + { 34, "J3100_x86" }, + { 35, "France_x86" }, + { 36, "Denmark_x86" }, + { 37, "Germany_x86" }, + { 38, "Italy_x86" }, + { 39, "Netherland_x86" }, + { 40, "Norway_x86" }, + { 41, "Portugal_x86" }, + { 42, "Spain_x86" }, + { 43, "Sweden_x86" }, + { 44, "Switzer_Fr_x86" }, + { 45, "Switzer_Ge_x86" }, + { 46, "UK_x86" }, + { 47, "Korea_x86" }, + { 48, "Taiwan_x86" }, + { 49, "Japan_x86" }, + { 50, "Canada_Fr2_x86" }, + { 51, "Hungary_x86" }, + { 52, "Poland_x86" }, + { 53, "Czech_x86" }, + { 54, "Russia_x86" }, + { 55, "Latvia_x86" }, + { 56, "Turkey_x86" }, + { 57, "Greece_x86" }, + { 59, "Lithuania_x86" }, + { 1001, "MS_US101A_x86" }, + { -1, NULL } +}; + +static const keyboard_layout type6_layout[] = +{ + { 0, "US6" }, + { 6, "Denmark6" }, + { 7, "Finnish6" }, + { 8, "France6" }, + { 9, "Germany6" }, + { 14, "Italy6" }, + { 15, "Japan6" }, + { 16, "Korea6" }, + { 18, "Netherland6" }, + { 19, "Norway6" }, + { 22, "Portugal6" }, + { 25, "Spain6" }, + { 26, "Sweden6" }, + { 27, "Switzer_Fr6" }, + { 28, "Switzer_Ge6" }, + { 30, "Taiwan6" }, + { 32, "UK6" }, + { 33, "US6" }, + { -1, NULL } +}; +#endif + + +#ifdef DEBUG +#include <stdio.h> +#endif + +const char* SalDisplay::GetKeyboardName( BOOL bRefresh ) +{ + if( bRefresh || ! m_aKeyboardName.Len() ) + { +#ifdef SOLARIS + if( IsLocal() ) + { + int kbd = open( "/dev/kbd", O_RDONLY ); + if( kbd >= 0 ) + { + int kbd_type = 0; + if( ! ioctl( kbd, KIOCTYPE, &kbd_type ) ) + { + int kbd_layout = 0; + if( ! ioctl( kbd, KIOCLAYOUT, &kbd_layout ) ) + { + const keyboard_layout *p_layout = NULL; + switch( kbd_type ) + { + case KB_KLUNK: p_layout = type0_layout; break; + case KB_SUN3: p_layout = type3_layout; break; + case KB_SUN4: p_layout = type4_layout; break; + case KB_USB: p_layout = type6_layout; break; + case KB_PC: p_layout = type101_layout; break; + } + + if( p_layout ) + { + while( p_layout->n_layout != -1 ) + { + if ( p_layout->n_layout == kbd_layout ) + { + m_aKeyboardName = p_layout->p_description; + break; + } + p_layout++; + } + } + } + } + } + } +#else + int opcode, event, error; + int major = XkbMajorVersion, minor = XkbMinorVersion; + if( ! m_aKeyboardName.Len() && + XSalIsDisplay( GetDisplay() ) && + XkbQueryExtension( GetDisplay(), &opcode, &event,&error, &major, &minor ) ) + { + XkbDescPtr pXkbDesc = NULL; + // try X keyboard extension + if( pXkbDesc = XkbGetKeyboard( GetDisplay(), XkbAllComponentsMask, XkbUseCoreKbd ) ) + { + const char* pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->groups[0] ); + m_aKeyboardName = pAtom; + XFree( (void*)pAtom ); + +#ifdef DEBUG +#define PRINT_ATOM( x ) { if( pXkbDesc->names->x ) { pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->x ); fprintf( stderr, "%s: %s\n", #x, pAtom ); XFree( (void*)pAtom ); } else fprintf( stderr, "%s: <nil>\n", #x ); } + + PRINT_ATOM( keycodes ); + PRINT_ATOM( geometry ); + PRINT_ATOM( symbols ); + PRINT_ATOM( types ); + PRINT_ATOM( compat ); + PRINT_ATOM( phys_symbols ); + + int i; + for( i = 0; i < XkbNumVirtualMods; i++ ) + PRINT_ATOM( vmods[i] ); + for( i = 0; i < XkbNumIndicators; i++ ) + PRINT_ATOM( indicators[i] ); + for( i = 0; i < XkbNumKbdGroups; i++ ) + PRINT_ATOM( groups[i] ); +#endif + XkbFreeKeyboard( pXkbDesc, 0, True ); + } + } +#endif + } + return m_aKeyboardName.GetBuffer(); +} diff --git a/vcl/unx/source/app/makefile.mk b/vcl/unx/source/app/makefile.mk new file mode 100644 index 000000000000..c532bcd1a836 --- /dev/null +++ b/vcl/unx/source/app/makefile.mk @@ -0,0 +1,142 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,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): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salapp +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +.IF "$(OS)"=="MACOSX" + +dummy: + @echo "Nothing to build for Mac OS X" + +.ELSE # "$(OS)"=="MACOSX" + +.IF "$(remote)"=="" +OBJFILES=\ + $(OBJ)$/salmain.obj + +SLOFILES=\ + $(SLO)$/i18n_cb.obj \ + $(SLO)$/i18n_ic.obj \ + $(SLO)$/i18n_im.obj \ + $(SLO)$/i18n_xkb.obj \ + $(SLO)$/i18n_wrp.obj \ + $(SLO)$/salmain.obj \ + $(SLO)$/saldata.obj \ + $(SLO)$/saltimer.obj \ + $(SLO)$/saldisp.obj \ + $(SLO)$/salinst.obj \ + $(SLO)$/salsound2.obj \ + $(SLO)$/audioconvert.obj \ + $(SLO)$/osssound.obj \ + $(SLO)$/devaudiosound.obj \ + $(SLO)$/rptpsound.obj \ + $(SLO)$/nassound.obj \ + $(SLO)$/salsys.obj \ + $(SLO)$/soicon.obj \ + $(SLO)$/sm.obj \ + $(SLO)$/stacktrace.obj \ + $(SLO)$/keysymnames.obj + +.IF "$(OS)$(CPU)" == "SOLARISS" +.IF "$(COM)"!="GCC" +SLOFILES+=$(SLO)$/getfpsols.obj +.ENDIF # "$(COM)"!="GCC" +.ELIF "$(OS)$(CPU)" == "SOLARISI" +SLOFILES+=$(SLO)$/getfpsoli.obj +.ENDIF + +.ELSE +SLOFILES=\ + $(SLO)$/salmain.obj +.ENDIF + +.IF "$(remote)"!="" +EXCEPTIONSFILES=$(SLO)$/salmain.obj \ + $(OBJ)$/salmain.obj +.ENDIF + +.ENDIF # "$(OS)"=="MACOSX" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.INCLUDE : $(PRJ)$/util$/target.pmk + +$(SLO)$/getfpsols.obj: getfpsols.s + CC -c -o $(SLO)$/getfpsols.o getfpsols.s && touch $(SLO)$/getfpsols.obj + +$(SLO)$/getfpsoli.obj: getfpsoli.s + CC -c -o $(SLO)$/getfpsoli.o getfpsoli.s && touch $(SLO)$/getfpsoli.obj + 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; +} + diff --git a/vcl/unx/source/app/saldisp.cxx b/vcl/unx/source/app/saldisp.cxx new file mode 100644 index 000000000000..5c7ca51b0a6b --- /dev/null +++ b/vcl/unx/source/app/saldisp.cxx @@ -0,0 +1,3653 @@ +/************************************************************************* + * + * $RCSfile: saldisp.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_SALDISP_CXX + +#define SAL_XT + +// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <sys/time.h> +#include <pthread.h> +#include <unistd.h> +#include <ctype.h> +#include <string.h> + +#ifdef __SunOS_5_5_1 +extern "C" { int gethostname(char*,int); } +#endif + +#include <prex.h> +#include <X11/cursorfont.h> +#include "nodrop_curs.h" +#include "nodrop_mask.h" +#include "wait_curs.h" +#include "wait_mask.h" +#include "hsplit_curs.h" +#include "hsplit_mask.h" +#include "vsplit_curs.h" +#include "vsplit_mask.h" +#include "neswsize_curs.h" +#include "neswsize_mask.h" +#include "nwsesize_curs.h" +#include "nwsesize_mask.h" +#include "magnify_curs.h" +#include "magnify_mask.h" +#include "rotate_curs.h" +#include "rotate_mask.h" +#include "hshear_curs.h" +#include "hshear_mask.h" +#include "vshear_curs.h" +#include "vshear_mask.h" +#include "drawline_curs.h" +#include "drawline_mask.h" +#include "drawrect_curs.h" +#include "drawrect_mask.h" +#include "drawpolygon_curs.h" +#include "drawpolygon_mask.h" +#include "drawbezier_curs.h" +#include "drawbezier_mask.h" +#include "drawarc_curs.h" +#include "drawarc_mask.h" +#include "drawpie_curs.h" +#include "drawpie_mask.h" +#include "drawcirclecut_curs.h" +#include "drawcirclecut_mask.h" +#include "drawellipse_curs.h" +#include "drawellipse_mask.h" +#include "drawconnect_curs.h" +#include "drawconnect_mask.h" +#include "drawtext_curs.h" +#include "drawtext_mask.h" +#include "mirror_curs.h" +#include "mirror_mask.h" +#include "crook_curs.h" +#include "crook_mask.h" +#include "crop_curs.h" +#include "crop_mask.h" +#include "move_curs.h" +#include "move_mask.h" +#include "movepoint_curs.h" +#include "movepoint_mask.h" +#include "movebezierweight_curs.h" +#include "movebezierweight_mask.h" +#include "drawfreehand_curs.h" +#include "drawfreehand_mask.h" +#include "drawcaption_curs.h" +#include "drawcaption_mask.h" +#include "movedata_curs.h" +#include "movedata_mask.h" +#include "copydata_curs.h" +#include "copydata_mask.h" +#include "linkdata_curs.h" +#include "linkdata_mask.h" +#include "movedlnk_curs.h" +#include "movedlnk_mask.h" +#include "copydlnk_curs.h" +#include "copydlnk_mask.h" +#include "movefile_curs.h" +#include "movefile_mask.h" +#include "copyfile_curs.h" +#include "copyfile_mask.h" +#include "linkfile_curs.h" +#include "linkfile_mask.h" +#include "moveflnk_curs.h" +#include "moveflnk_mask.h" +#include "copyflnk_curs.h" +#include "copyflnk_mask.h" +#include "movefiles_curs.h" +#include "movefiles_mask.h" +#include "copyfiles_curs.h" +#include "copyfiles_mask.h" + +#include "chart_curs.h" +#include "chart_mask.h" +#include "detective_curs.h" +#include "detective_mask.h" +#include "pivotcol_curs.h" +#include "pivotcol_mask.h" +#include "pivotfld_curs.h" +#include "pivotfld_mask.h" +#include "pivotrow_curs.h" +#include "pivotrow_mask.h" + +#include "chain_curs.h" +#include "chain_mask.h" +#include "chainnot_curs.h" +#include "chainnot_mask.h" + +#include "timemove_curs.h" +#include "timemove_mask.h" +#include "timesize_curs.h" +#include "timesize_mask.h" + +#include "ase_curs.h" +#include "ase_mask.h" +#include "asn_curs.h" +#include "asn_mask.h" +#include "asne_curs.h" +#include "asne_mask.h" +#include "asns_curs.h" +#include "asns_mask.h" +#include "asnswe_curs.h" +#include "asnswe_mask.h" +#include "asnw_curs.h" +#include "asnw_mask.h" +#include "ass_curs.h" +#include "ass_mask.h" +#include "asse_curs.h" +#include "asse_mask.h" +#include "assw_curs.h" +#include "assw_mask.h" +#include "asw_curs.h" +#include "asw_mask.h" +#include "aswe_curs.h" +#include "aswe_mask.h" +#include "null_curs.h" +#include "null_mask.h" + +#include "airbrush_curs.h" +#include "airbrush_mask.h" +#include "fill_curs.h" +#include "fill_mask.h" + +#include "invert50.h" +#if !(defined S390 || defined AIX) +#include <X11/extensions/XShm.h> +#endif +#include <X11/keysym.h> + +#ifdef USE_XMU +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/SysUtil.h> +#endif +#include <X11/Xatom.h> +#include <postx.h> + +#include <salunx.h> + +#ifndef _SAL_I18N_INPUTMETHOD_HXX +#include "i18n_im.hxx" +#endif +#ifndef _SAL_I18N_XKBDEXTENSION_HXX +#include "i18n_xkb.hxx" +#endif + +#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_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_KEYCODES_HXX +#include <keycodes.hxx> +#endif +#ifndef _SV_SALBTYPE_HXX +#include <salbtype.hxx> +#endif +#ifndef _SV_SALBMP_HXX +#include <salbmp.hxx> +#endif +#ifndef _SV_SALSYS_HXX +#include <salsys.hxx> +#endif +#ifndef _SV_DTINT_HXX +#include <dtint.hxx> +#endif +#ifndef _SV_SALOGL_HXX +#include <salogl.hxx> +#endif +#ifndef _OSL_THREADMUTEX_H_ +#include <osl/mutex.h> +#endif +#ifndef _SV_SALOBJ_HXX +#include <salobj.hxx> +#endif +#ifndef _VCL_SM_HXX +#include <sm.hxx> +#endif + +#include <osl/socket.h> +#include <rtl/ustring> + +// -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#define PSEUDOCOLOR12 +#define PSEUDOCOLOR8 +#define TRUECOLOR24 +#define TRUECOLOR16 +#define TRUECOLOR15 +#define TRUECOLOR12 +#define TRUECOLOR8 + +#define SALCOLOR_WHITE MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) +#define SALCOLOR_BLACK MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) + +// -=-= Prototyps =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +EXTERN_C int XShmGetEventBase( Display* ); + +// -=-= static variables -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +static const char* const VisualClassName[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +static const char* const AtomStrings[] = +{ + "WM_PROTOCOLS", // window manager + "WM_STATE", + "WM_DELETE_WINDOW", + "WM_SAVE_YOURSELF", + "WM_COMMAND", + + "SAL_QUITEVENT", // client message events + "SAL_USEREVENT", +}; + +static const char* const EventNames[] = +{ + NULL, + NULL, + "KeyPress", + "KeyRelease", + "ButtonPress", + "ButtonRelease", + "MotionNotify", + "EnterNotify", + "LeaveNotify", + "FocusIn", + "FocusOut", + "KeymapNotify", + "Expose", + "GraphicsExpose", + "NoExpose", + "VisibilityNotify", + "CreateNotify", + "DestroyNotify", + "UnmapNotify", + "MapNotify", + "MapRequest", + "ReparentNotify", + "ConfigureNotify", + "ConfigureRequest", + "GravityNotify", + "ResizeRequest", + "CirculateNotify", + "CirculateRequest", + "PropertyNotify", + "SelectionClear", + "SelectionRequest", + "SelectionNotify", + "ColormapNotify", + "ClientMessage", + "MappingNotify" +}; + +static UINT32 nIn___, nOut___; + +// -=-= global inline =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +inline const char *Null( const char *p ) { return p ? p : ""; } +inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); } +inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); } + +#ifdef USE_XMU +final inline const char *GetAtomName( Display *d, Atom a ) +{ return Null( XmuGetAtomName( d, a ) ); } +#else +final inline const char *GetAtomName( Display *d, Atom a ) +{ return Null( XGetAtomName( d, a ) ); } +#endif + +final inline double Hypothenuse( long w, long h ) +{ return sqrt( (w*w)+(h*h) ); } + +final inline int ColorDiff( int r, int g, int b ) +{ return (r*r)+(g*g)+(b*b); } + +final inline int ColorDiff( SalColor c1, int r, int g, int b ) +{ return ColorDiff( (int)SALCOLOR_RED (c1)-r, + (int)SALCOLOR_GREEN(c1)-g, + (int)SALCOLOR_BLUE (c1)-b ); } + +// -=-= global functions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +static int sal_Shift( Pixel nMask ) +{ + int i = 24; + if( nMask < 0x00010000 ) { nMask <<= 16; i -= 16; } + if( nMask < 0x01000000 ) { nMask <<= 8; i -= 8; } + if( nMask < 0x10000000 ) { nMask <<= 4; i -= 4; } + if( nMask < 0x40000000 ) { nMask <<= 2; i -= 2; } + if( nMask < 0x80000000 ) { nMask <<= 1; i -= 1; } + return i; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +static BOOL sal_GetVisualInfo( Display *pDisplay, XID nVID, XVisualInfo &rVI ) +{ + int nInfos; + XVisualInfo aTemplate; + XVisualInfo*pInfos; + + aTemplate.visualid = nVID; + + pInfos = XGetVisualInfo( pDisplay, VisualIDMask, &aTemplate, &nInfos ); + if( !pInfos ) + return FALSE; + + rVI = *pInfos; + XFree( pInfos ); + + DBG_ASSERT( rVI.visualid == nVID, + "sal_GetVisualInfo: could not get correct visual by visualId" ) + return TRUE; +} + +// --------------------------------------------------------------------------- + +// check wether displaystring is in format N.M or N. or just N +// with N and M beeing natural numbers +static BOOL +sal_IsDisplayNumber( const char *pDisplayString ) +{ + if ( ! isdigit(*pDisplayString) ) + return FALSE; + while ( isdigit(*(++pDisplayString)) ) + ; /* do nothing */ + + if ( *pDisplayString == '.' ) + { + while ( isdigit(*(++pDisplayString)) ) + ; /* do nothing */ + } + + return (*pDisplayString == '\0'); +} + +// check whether host1 and host2 point to the same ip address +static BOOL +sal_EqualHosts( const ::rtl::OUString& Host1, const ::rtl::OUString& Host2) +{ + oslSocketAddr pHostAddr1; + oslSocketAddr pHostAddr2; + BOOL bEqualAddress; + + if ( Host1.toChar() >= '0' && Host1.toChar() <= '9' ) + pHostAddr1 = osl_createInetSocketAddr( Host1.pData, 0 ); + else + pHostAddr1 = osl_resolveHostname( Host1.pData ); + + if ( Host2.toChar() >= '0' && Host2.toChar() <= '9' ) + pHostAddr2 = osl_createInetSocketAddr( Host2.pData, 0 ); + else + pHostAddr2 = osl_resolveHostname( Host2.pData ); + + bEqualAddress = osl_isEqualSocketAddr( pHostAddr1, pHostAddr2 ) ? TRUE : FALSE; + + osl_destroySocketAddr( pHostAddr1 ); + osl_destroySocketAddr( pHostAddr2 ); + + return bEqualAddress; +} + +static BOOL +sal_IsLocalDisplay( Display *pDisplay ) +{ + const char *pDisplayString = DisplayString( pDisplay ); + + // no string, no idea + if ( pDisplayString == NULL || pDisplayString[ 0 ] == '\0') + return FALSE; + + // check for ":x.y" + if ( pDisplayString[ 0 ] == ':' ) + return sal_IsDisplayNumber( pDisplayString + 1 ); + + // check for fixed token which all mean localhost:x.y + const char pLocal[] = "localhost:"; + const int nLocalLen = sizeof(pLocal) - 1; + if ( strncmp(pDisplayString, pLocal, nLocalLen) == 0 ) + return sal_IsDisplayNumber( pDisplayString + nLocalLen ); + + const char pUnix[] = "unix:"; + const int nUnixLen = sizeof(pUnix) - 1; + if ( strncmp(pDisplayString, pUnix, nUnixLen) == 0 ) + return sal_IsDisplayNumber( pDisplayString + nUnixLen ); + + const char pLoopback[] = "127.0.0.1:"; + const int nLoopbackLen= sizeof(pLoopback) - 1; + if ( strncmp(pDisplayString, pLoopback, nLoopbackLen) == 0 ) + return sal_IsDisplayNumber( pDisplayString + nLoopbackLen ); + + // compare local hostname to displaystring, both may be ip address or + // hostname + BOOL bEqual = FALSE; + char *pDisplayHost = strdup( pDisplayString ); + char *pPtr = strrchr( pDisplayHost, ':' ); + + if( pPtr != NULL ) + { + ::rtl::OUString aLocalHostname; + if( osl_getLocalHostname( &aLocalHostname.pData ) == osl_Socket_Ok) + { + *pPtr = '\0'; + ::rtl::OUString aDisplayHostname( pDisplayHost, strlen( pDisplayHost ), gsl_getSystemTextEncoding() ); + bEqual = sal_EqualHosts( aLocalHostname, aDisplayHostname ); + bEqual = bEqual && sal_IsDisplayNumber( pPtr + 1 ); + } + } + free( pDisplayHost ); + + return bEqual; +} + +// --------------------------------------------------------------------------- +// IsLocal means soffice is running on the same host as the xserver +// since it is not called very often and sal_IsLocalDisplay() is relative +// expensive bLocal_ is initialized on first call + +BOOL SalDisplay::IsLocal() +{ + if ( ! mbLocalIsValid ) + { + bLocal_ = sal_IsLocalDisplay( pDisp_ ); + mbLocalIsValid = TRUE; + } + return (BOOL)bLocal_; +} + +// --------------------------------------------------------------------------- +extern "C" srv_vendor_t +sal_GetServerVendor( Display *p_display ) +{ + typedef struct { + srv_vendor_t e_vendor; // vendor as enum + char *p_name; // vendor name as returned by VendorString() + unsigned int n_len; // number of chars to compare + } vendor_t; + + const vendor_t p_vendorlist[] = { + { vendor_xfree, "The XFree86 Project, Inc", 13 }, + { vendor_sun, "Sun Microsystems, Inc.", 10 }, + { vendor_attachmate, "Attachmate Corporation", 10 }, + { vendor_excursion, + "DECWINDOWS DigitalEquipmentCorporation, eXcursion", 42 }, + { vendor_hp, "Hewlett-Packard Company", 17 }, + { vendor_hummingbird, "Hummingbird Communications Ltd.", 11 }, + { vendor_ibm, "International Business Machines", 24 }, + { vendor_sgi, "Silicon Graphics", 9 }, + { vendor_sco, "The Santa Cruz Operation", 16 }, + { vendor_xinside, "X Inside Inc.", 10 }, + // allways the last entry: vendor_none to indicate eol + { vendor_none, NULL, 0 }, + }; + + // handle xprinter separately, since it doesn´t implement ServerVendor() + if ( ! XSalIsDisplay( p_display ) ) + return vendor_xprinter; + + // handle regular server vendors + char *p_name = ServerVendor( p_display ); + vendor_t *p_vendor; + for (p_vendor = const_cast<vendor_t*>(p_vendorlist); p_vendor->e_vendor != vendor_none; p_vendor++) + { + if ( strncmp (p_name, p_vendor->p_name, p_vendor->n_len) == 0 ) + return p_vendor->e_vendor; + } + + // vendor not found in list + return vendor_unknown; +} + +// -=-= SalDisplay -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final BOOL SalDisplay::BestVisual( Display *pDisplay, + int nScreen, + XVisualInfo &rVI ) +{ + VisualID nDefVID = XVisualIDFromVisual( DefaultVisual( pDisplay, nScreen ) ); + VisualID nVID = 0; + char *pVID = getenv( "SAL_VISUAL" ); + if( pVID ) + sscanf( pVID, "%li", &nVID ); + + if( nVID && sal_GetVisualInfo( pDisplay, nVID, rVI ) ) + return rVI.visualid == nDefVID; + + XVisualInfo aVI; + // get all visuals + int nVisuals; + XVisualInfo* pVInfos = XGetVisualInfo( pDisplay, VisualNoMask, + &aVI, &nVisuals ); + // pVInfos should contain at least one visual, otherwise + // we're in trouble + int* pWeight = new int[ nVisuals ]; + int i; + for( i = 0; i < nVisuals; i++ ) + { + BOOL bUsable = FALSE; + int nTrueColor = 1; + + if ( pVInfos[i].screen != nScreen ) + { + bUsable = FALSE; + } + else + if( pVInfos[i].c_class == TrueColor ) + { + nTrueColor = 2048; + if( pVInfos[i].depth == 24 ) + bUsable = TRUE; +#ifdef TRUECOLOR8 + else if( pVInfos[i].depth == 8 ) + { + nTrueColor = -1; // strongly discourage 8 bit true color + bUsable = TRUE; + } +#endif +#ifdef TRUECOLOR15 + else if( pVInfos[i].depth == 15 ) + bUsable = TRUE; +#endif +#ifdef TRUECOLOR16 + else if( pVInfos[i].depth == 16 ) + bUsable = TRUE; +#endif +#ifdef TRUECOLOR32 + else if( pVInfos[i].depth == 32 ) + { + nTrueColor = 256; + // we do not have use for an alpha channel + // better use a 24 or 16 bit truecolor visual if possible + bUsable = TRUE; + } +#endif + } + else if( pVInfos[i].c_class == PseudoColor ) + { + if( pVInfos[i].depth <= 8 ) + bUsable = TRUE; +#ifdef PSEUDOCOLOR12 + else if( pVInfos[i].depth == 12 ) + bUsable = TRUE; +#endif + } + pWeight[ i ] = bUsable ? nTrueColor*pVInfos[i].depth : -1024; + pWeight[ i ] -= pVInfos[ i ].visualid; + } + + SalOpenGL::MakeVisualWeights( pDisplay, pVInfos, pWeight, nVisuals ); + + int nBestVisual = 0; + int nBestWeight = -1024; + for( i = 0; i < nVisuals; i++ ) + { + if( pWeight[ i ] > nBestWeight ) + { + nBestWeight = pWeight[ i ]; + nBestVisual = i; + } + } + + rVI = pVInfos[ nBestVisual ]; + + XFree( pVInfos ); + return rVI.visualid == nDefVID; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +final SalDisplay::SalDisplay( Widget w ) +{ + SalData *pSalData = GetSalData(); + + if( !pSalData->GetDefDisp() ) + pSalData->SetDefDisp( this ); + if( !pSalData->GetCurDisp() ) + pSalData->SetCurDisp( this ); + + pXLib_ = pSalData->GetLib(); + pDisp_ = XtDisplay( w ); + nScreen_ = DefaultScreen( pDisp_ ); + hShell_ = w; + hComposite_ = XtVaCreateManagedWidget( + "ShellComposite", + SAL_COMPOSITE_WIDGET, + hShell_, + NULL ); + + Visual *pVisual = NULL; + Colormap hColMap = None; + Arg aArgs[10]; + + XtSetArg( aArgs[0], XtNvisual, &pVisual ); + XtSetArg( aArgs[1], XtNcolormap, &hColMap ); + + XtGetValues( hShell_, aArgs, 2 ); + if( !pVisual ) + pVisual = DefaultVisual( pDisp_, nScreen_ ); + if (!hColMap) + hColMap = DefaultColormap( pDisp_, nScreen_ ); + if( !IsDisplay() && !hColMap) + hColMap = 1; // trick for XPrinter + + XVisualInfo aXVI; + sal_GetVisualInfo( pDisp_, XVisualIDFromVisual( pVisual ), aXVI ); + + Init( hColMap, &aXVI ); +} + +final SalDisplay::SalDisplay( Display *display, Visual *pVisual, + Colormap aColMap ) : pDisp_( display ) +{ + SalData *pSalData = GetSalData(); + XVisualInfo aXVI; + + if( !pSalData->GetDefDisp() ) + pSalData->SetDefDisp( this ); + if( !pSalData->GetCurDisp() ) + pSalData->SetCurDisp( this ); + + pXLib_ = XSalIsDisplay( pDisp_ ) ? pSalData->GetLib() : NULL; + nScreen_ = DefaultScreen( pDisp_ ); + + if (!aColMap) + aColMap = DefaultColormap( display, nScreen_ ); + if( !IsDisplay() && !aColMap) + aColMap = 1; // trick for XPrinter + if (!pVisual) + pVisual = DefaultVisual( pDisp_, nScreen_ ); + + sal_GetVisualInfo( pDisp_, XVisualIDFromVisual( pVisual ), aXVI ); + Init( aColMap, &aXVI ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final SalDisplay::~SalDisplay( ) +{ + SalData *pSalData = GetSalData(); + + SalBitmap::ImplDestroyCache(); + DestroyFontCache(); + + if( IsDisplay() ) + { + osl_destroyMutex( hEventGuard_ ); + + XDestroyWindow( pDisp_, hRefWindow_ ); + if( pMonoGC_ != pCopyGC_ ) + XFreeGC( pDisp_, pMonoGC_ ); + XFreeGC( pDisp_, pCopyGC_ ); + XFreeGC( pDisp_, pAndInvertedGC_ ); + XFreeGC( pDisp_, pAndGC_ ); + XFreeGC( pDisp_, pOrGC_ ); + XFreeGC( pDisp_, pStippleGC_ ); + XFreePixmap( pDisp_, hInvert50_ ); + + hEventGuard_ = (oslMutex)ILLEGAL_POINTER; + hRefWindow_ = (XLIB_Window)ILLEGAL_POINTER; + pMonoGC_ = (GC)ILLEGAL_POINTER; + pCopyGC_ = (GC)ILLEGAL_POINTER; + pAndInvertedGC_ = (GC)ILLEGAL_POINTER; + pAndGC_ = (GC)ILLEGAL_POINTER; + pOrGC_ = (GC)ILLEGAL_POINTER; + pStippleGC_ = (GC)ILLEGAL_POINTER; + hInvert50_ = None; + + for( size_t i = 0; i < POINTER_COUNT; i++ ) + { + XFreeCursor( pDisp_, aPointerCache_[i] ); +#ifdef DBG_UTIL + aPointerCache_[i] = None; +#endif + } + + if( hComposite_ ) + XtDestroyWidget( hComposite_ ); + if( hShell_ ) + XtDestroyWidget( hShell_ ); + + pXLib_->Remove( ConnectionNumber( pDisp_ ) ); + + delete mpInputMethod; + delete mpKbdExtension; + XtCloseDisplay( pDisp_ ); + } + + pDisp_ = (Display*)ILLEGAL_POINTER; + + pSalData->Remove( this ); + + // free colormap before modifying pVisual_ + xColor_.Clear(); + + delete pICCCM_; + delete pVisual_; + + if( pRootVisual_ != pVisual_ ) + delete pRootVisual_; + + pICCCM_ = (SalICCCM*)ILLEGAL_POINTER; + pVisual_ = (SalVisual*)ILLEGAL_POINTER; + pRootVisual_ = (SalVisual*)ILLEGAL_POINTER; + + if( pSalData->GetDefDisp() == this ) + pSalData->SetDefDisp( NULL ); + if( pSalData->GetCurDisp() == this ) + pSalData->SetCurDisp( NULL ); +} + +static int DisplayHasEvent( int fd, SalDisplay *pDisplay ) +{ + DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, + "wrong fd in DisplayHasEvent" ) + return pDisplay->IsDisplay() && pDisplay->IsEvent(); +} +static int DisplayQueue( int fd, SalDisplay *pDisplay ) +{ + DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, + "wrong fd in DisplayHasEvent" ) + return XEventsQueued( pDisplay->GetDisplay(), + QueuedAfterReading ); +} +static int DisplayYield( int fd, SalDisplay *pDisplay ) +{ + DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, + "wrong fd in DisplayHasEvent" ) + pDisplay->Yield( TRUE ); + return TRUE; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final void SalDisplay::Init( Colormap hXColmap, const XVisualInfo* pXVI ) +{ + GetSalData()->Insert( this ); + + for( size_t i = 0; i < POINTER_COUNT; i++ ) + aPointerCache_[i] = None; + + eWindowManager_ = otherwm; + nProperties_ = PROPERTY_DEFAULT; + nStateOfYield_ = 0; + nStateOfSendEvent_ = 0; + hEventGuard_ = NULL; + pEventQueue_ = NULL; + pDispatchStack_ = NULL; + pFontCache_ = NULL; + mpFontList = (XlfdStorage*)NULL; + mpFactory = (AttributeProvider*)NULL; + mpCvtCache = NULL; + pCapture_ = NULL; + pVisual_ = new SalVisual( pXVI ); + aSize_ = Size( DisplayWidth ( pDisp_, nScreen_ ), + DisplayHeight( pDisp_, nScreen_ ) ); + aResolution_ = + Pair( DPI( aSize_.Width(), DisplayWidthMM ( pDisp_, nScreen_ ) ), + DPI( aSize_.Height(), DisplayHeightMM( pDisp_, nScreen_ ) ) ); + + nMaxRequestSize_ = XExtendedMaxRequestSize( pDisp_ ) * 4; + if( !nMaxRequestSize_ ) + nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4; + + SetServerVendor(); + SalBitmap::ImplCreateCache(); + + if( IsDisplay() ) + { + hEventGuard_ = osl_createMutex(); + + pXLib_->Insert( ConnectionNumber( pDisp_ ), + this, + (YieldFunc) DisplayHasEvent, + (YieldFunc) DisplayQueue, + (YieldFunc) DisplayYield ); + + pICCCM_ = new SalICCCM( this ); + pScreen_ = ScreenOfDisplay( pDisp_, nScreen_ ); + hRootWindow_ = RootWindowOfScreen( pScreen_ ); + + // we are interested in create and destroy notify events + // for salsystem + if( hRootWindow_ != None ) + XSelectInput( pDisp_, hRootWindow_, SubstructureNotifyMask ); + + bLocal_ = FALSE; /* dont care, initialize later by + calling SalDisplay::IsLocal() */ + mbLocalIsValid = FALSE; /* bLocal_ is not yet initialized */ + + // - - - - - - - - - - Visuals - - - - - - - - - - - - - - - + Visual *pRootVisual = DefaultVisual( pDisp_, nScreen_ ); + // if( pRootVisual != pXVI->visual ) + if( pRootVisual->visualid != pVisual_->GetVisualId() ) + { + XVisualInfo aXVI; + sal_GetVisualInfo( pDisp_, pRootVisual->visualid, aXVI ); + pRootVisual_ = new SalVisual( &aXVI ); + } + else + pRootVisual_ = pVisual_; + + // start session management + SessionManagerClient::open(); + + // - - - - - - - - - - Reference Window/Default Drawable - - + XSetWindowAttributes aXWAttributes; + aXWAttributes.border_pixel = 0; + aXWAttributes.background_pixel = 0; + aXWAttributes.colormap = hXColmap; + hRefWindow_ = XCreateWindow( pDisp_, + hRootWindow_, + 0,0, 16,16, 0, + pVisual_->GetDepth(), + InputOutput, + pVisual_->GetVisual(), + CWBorderPixel|CWBackPixel|CWColormap, + &aXWAttributes ); + + // set client leader and session id + char* pSessionID = SessionManagerClient::getSessionID(); + if( hRefWindow_ ) + { + if( pSessionID ) + { + XChangeProperty( pDisp_, + hRefWindow_, + XInternAtom( pDisp_, "SM_CLIENT_ID", False ), + XA_STRING, + 8, + PropModeReplace, + (unsigned char*)pSessionID, + strlen( pSessionID ) + ); + } + // client leader must have WM_CLIENT_LEADER pointing to itself + + XChangeProperty( pDisp_, + hRefWindow_, + XInternAtom( pDisp_, "WM_CLIENT_LEADER", False ), + XA_WINDOW, + 32, + PropModeReplace, + (unsigned char*)&hRefWindow_, + 1 + + ); + + ByteString aExec( SessionManagerClient::getExecName(), gsl_getSystemTextEncoding() ); + char* argv[2]; + argv[0] = "/bin/sh"; + argv[1] = const_cast<char*>(aExec.GetBuffer()); + XSetCommand( pDisp_, hRefWindow_, argv, 2 ); + } + + // - - - - - - - - - - Synchronize - - - - - - - - - - - - - + if( getenv( "SAL_SYNCHRONIZE" ) ) + XSynchronize( pDisp_, True ); + + // - - - - - - - - - - Window Manager - - - - - - - - - - - + const char *pWM = getenv( "SAL_WM" ); + if( pWM ) + sscanf( pWM, "%li", &eWindowManager_ ); + else if( XInternAtom( pDisp_, "_SGI_TELL_WM", True ) ) + eWindowManager_ = _4Dwm; + else if( XInternAtom( pDisp_, "KWM_RUNNING", True ) ) + eWindowManager_ = mwm; // naja, eigentlich kwm ... + else if( XInternAtom( pDisp_, "_OL_WIN_ATTR", True ) ) + eWindowManager_ = olwm; + + // - - - - - - - - - - Properties - - - - - - - - - - - - - + const char *pProperties = getenv( "SAL_PROPERTIES" ); + if( pProperties ) + sscanf( pProperties, "%li", &nProperties_ ); + else + { +#if defined DBG_UTIL || defined SUN || defined LINUX + nProperties_ |= PROPERTY_FEATURE_Maximize; +#endif + // Server Bugs & Properties + if( GetServerVendor() == vendor_excursion ) + { + nProperties_ |= PROPERTY_BUG_Stipple; + nProperties_ |= PROPERTY_BUG_DrawLine; + nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; + } + else + if( GetServerVendor() == vendor_attachmate ) + { + nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel; + } + else + if( GetServerVendor() == vendor_ibm ) + { + nProperties_ |= PROPERTY_BUG_XA_FAMILY_NAME_nil; + + if( otherwm == eWindowManager_ ) eWindowManager_ = mwm; + } + else + if( GetServerVendor() == vendor_xfree ) + { + nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor; +#ifdef ARM32 // ??? Server! nicht Client ??? + nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; +#endif +#ifdef LINUX + // otherwm and olwm are a kind of default, which are not detected + // carefully. if we are running linux (i.e. not netbsd) on an xfree + // display, fvwm is most probable the wm to choose, confusing with mwm + // doesn't harm. #57791# start maximized if possible + if( (otherwm == eWindowManager_) + || (olwm == eWindowManager_ )) + { + eWindowManager_ = fvwm; // ??? + nProperties_ |= PROPERTY_FEATURE_Maximize; + } +#else + if( otherwm == eWindowManager_ ) eWindowManager_ = winmgr; +#endif +#if defined SOLARIS && defined SPARC + nProperties_ |= PROPERTY_BUG_Bitmap_Bit_Order; + // solaris xlib seems to have problems with putting images + // in correct bit order to xfree 8 bit displays +#endif + } + else + if( GetServerVendor() == vendor_sun ) + { + // nicht alle! (bekannt: nur Sparc II CG3, CG6?) + nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; + + // Fehler im Sun-Solaris X86 Server ! + if (ImageByteOrder(GetDisplay()) == LSBFirst) + { + nProperties_ |= PROPERTY_BUG_Tile; + nProperties_ |= PROPERTY_SUPPORT_3ButtonMouse; + } + else // MSBFirst Sun-Solaris Sparc Server + { + // XCopyPlane reverts black and white for 1bit bitmaps + // only sun, only 8bit pseudocolor target + if ( (pVisual_->GetDepth() == 8) + && (pVisual_->GetClass() == PseudoColor)) + nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel; + // Fehler in Solaris 2.5.1 + if (VendorRelease ( GetDisplay() ) < 3600) + nProperties_ |= PROPERTY_BUG_FillPolygon_Tile; + } + + if( otherwm == eWindowManager_ ) + if( XInternAtom( pDisp_, "_MOTIF_WM_INFO", True ) ) + eWindowManager_ = dtwm; + else + eWindowManager_ = olwm; + } + else + if( GetServerVendor() == vendor_sco ) + { + if( otherwm == eWindowManager_ ) eWindowManager_ = pmwm; + } + else + if( GetServerVendor() == vendor_sgi ) + { + if( pVisual_->GetDepth() > 8 && pVisual_->GetDepth() <= 16 ) + nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor; + nProperties_ |= PROPERTY_SUPPORT_XSetClipMask; + + if( otherwm == eWindowManager_ ) eWindowManager_ = _4Dwm; + } + else + if( GetServerVendor() == vendor_hp ) + { + if( otherwm == eWindowManager_ ) eWindowManager_ = dtwm; + } + else + if( GetServerVendor() == vendor_hummingbird ) + { + if (pVisual_->GetDepth() == 24) + nProperties_ |= PROPERTY_BUG_CopyArea_OnlySmallSlices; + } + + if( otherwm == eWindowManager_ ) + { + if( !XInternAtom( pDisp_, "_MOTIF_WM_INFO", True ) ) + eWindowManager_ = olwm; + // ??? + } + + if( winmgr == eWindowManager_ ) + { + nProperties_ &= ~PROPERTY_SUPPORT_WM_SetPos; + nProperties_ &= ~PROPERTY_SUPPORT_WM_Screen; + nProperties_ |= PROPERTY_FEATURE_Maximize; + } + else if( dtwm == eWindowManager_ ) + { + nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos; + } + else if( pmwm == eWindowManager_ ) + { + nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos; + } + } + + // - - - - - - - - - - Shared Images - - - - - - - - - - - - +#if defined _XSHM_H_ // && defined DBG_UTIL + // SharedMem wird nur noch ueber SalProperties enabled + // wegen Bugs #47289 und #46512 + + if( ( nProperties_ & PROPERTY_FEATURE_SharedMemory ) + && ( *DisplayString( pDisp_ ) == ':' + || !strncmp( DisplayString( pDisp_ ), "localhost:", 10 )) + ) + { + int nMinor, nMajor; + Bool bPixmaps; + + nSharedImages_ = XShmQueryVersion( pDisp_, + &nMajor, + &nMinor, + &bPixmaps ) + ? 0x80000000 : 0; + } + else + nSharedImages_ = 0; +#else + nSharedImages_ = 0; +#endif + // - - - - - - - - - - Images - - - - - - - - - - - - - - - + nImageDepths_ = 0x00000000; + int nCount, *pDepths = XListDepths( pDisp_, nScreen_, &nCount ); + if( pDepths ) + { + for( int i = 0; i < nCount; i++ ) + nImageDepths_ |= 1 << (pDepths[i]-1); + XFree( pDepths ); + } + } + else + { + pICCCM_ = NULL; + pScreen_ = NULL; + hRootWindow_ = None; + pRootVisual_ = pVisual_; +#ifdef DBG_UTIL + hRefWindow_ = (XLIB_Window)ILLEGAL_POINTER; +#endif + hInvert50_ = None; + bLocal_ = TRUE; /* always true for xprinter */ + mbLocalIsValid = TRUE; /* yes bLocal_ is initialized */ + nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; //XPrinter doesnt + nSharedImages_ = 0; + nImageDepths_ = 0xFFFFFFFF; + } + + // - - - - - - - - - - Images - - - - - - - - - - - - - - - + // 0x8080C889 + nImageDepths_ &= (1<<(32-1)) + |(1<<(24-1)) + |(1<<(16-1)) + |(1<<(15-1)) + |(1<<(12-1)) + |(1<<(8-1)) + |(1<<(4-1)) + |(1<<(1-1)); + + xColor_ = new SalColormap( this, hXColmap ); + + // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - - + XGCValues values; + values.graphics_exposures = True; + values.fill_style = FillOpaqueStippled; + values.background = (1<<pVisual_->GetDepth())-1; + values.foreground = 0; + + pCopyGC_ = XCreateGC( pDisp_, + hRefWindow_, + GCGraphicsExposures + | GCForeground + | GCBackground, + &values ); + pAndInvertedGC_ = XCreateGC( pDisp_, + hRefWindow_, + GCGraphicsExposures + | GCForeground + | GCBackground, + &values ); + pAndGC_ = XCreateGC( pDisp_, + hRefWindow_, + GCGraphicsExposures + | GCForeground + | GCBackground, + &values ); + pOrGC_ = XCreateGC( pDisp_, + hRefWindow_, + GCGraphicsExposures + | GCForeground + | GCBackground, + &values ); + pStippleGC_ = XCreateGC( pDisp_, + hRefWindow_, + GCGraphicsExposures + | GCFillStyle + | GCForeground + | GCBackground, + &values ); + + XSetFunction( pDisp_, pAndInvertedGC_, GXandInverted ); + XSetFunction( pDisp_, pAndGC_, GXand ); + // #44556# PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop + //XSetFunction( pDisp_, pOrGC_, GXor ); + XSetFunction( pDisp_, pOrGC_, GXxor ); + + if( 1 == pVisual_->GetDepth() ) // irgendwer dreht immer + { + XSetFunction( pDisp_, pCopyGC_, GXcopyInverted ); + pMonoGC_ = pCopyGC_; + } + else + { + Pixmap hPixmap = XCreatePixmap( pDisp_, hRefWindow_, 1, 1, 1 ); + pMonoGC_ = XCreateGC( pDisp_, + hPixmap, + GCGraphicsExposures, + &values ); + XFreePixmap( pDisp_, hPixmap ); + } + + if( IsDisplay() ) + { + hInvert50_ = XCreateBitmapFromData( pDisp_, + hRefWindow_, + invert50_bits, + invert50_width, + invert50_height ); + + // - - - - - - - - - - Sound - - - - - - - - - - - - - - - - + + nBeepVolume_ = 0; + + // - - - - - - - - - - Fonts - - - - - - - - - - - - - - - - + + const char *pFontPath = getenv( "SAL_FONTPATH" ); + if( pFontPath ) + AddFontPath( ByteString( pFontPath ) ); + + // - - - - - - - - - - Keyboardmapping - - - - - - - - - - - + + ModifierMapping(); + + // - - - - - - - - - - ShellWidget - - - - - - - - - - - - - + + + if( !XtWindow( hShell_ ) ) + { + Position w, h; + Arg aArgs[10]; + + XtSetArg( aArgs[0], XtNwidth, &w ); + XtSetArg( aArgs[1], XtNheight, &h ); + XtGetValues( hShell_, aArgs, 2 ); + + if( !w || !h ) + { + if( GetProperties() & PROPERTY_FEATURE_Maximize ) + { + XtSetArg( aArgs[0], XtNwidth, aSize_.Width() ); + XtSetArg( aArgs[1], XtNheight, aSize_.Height() ); + } + else + { + XtSetArg( aArgs[0], XtNwidth, 500 ); + XtSetArg( aArgs[1], XtNheight, 400 ); + } + XtSetValues( hShell_, aArgs, 2 ); + } + + // X-Window erzeugen + XtSetMappedWhenManaged( hShell_, FALSE ); + XtRealizeWidget( hShell_ ); + } + if( !XtWindow( hComposite_ ) ) + XtRealizeWidget( hComposite_ ); + } +#ifdef DBG_UTIL + PrintInfo(); +#endif + +#ifdef DEBUG + fprintf( stderr, "Keyboard name: %s\n", GetKeyboardName() ); + String aConvert = GetKeyNameFromKeySym( XK_Control_L ); + fprintf( stderr, "Control: %s\n", aConvert.Len() ? ByteString( aConvert, gsl_getSystemTextEncoding() ).GetBuffer() : "<nil>" ); + aConvert = GetKeyNameFromKeySym( XK_Shift_L ); + fprintf( stderr, "Shift: %s\n", aConvert.Len() ? ByteString( aConvert, gsl_getSystemTextEncoding() ).GetBuffer() : "<nil>" ); + aConvert = GetKeyNameFromKeySym( XK_Alt_L ); + fprintf( stderr, "Alt: %s\n", aConvert.Len() ? ByteString( aConvert, gsl_getSystemTextEncoding() ).GetBuffer() : "<nil>" ); + aConvert = GetKeyNameFromKeySym( XK_Alt_R ); + fprintf( stderr, "AltGr: %s\n", aConvert.Len() ? ByteString( aConvert, gsl_getSystemTextEncoding() ).GetBuffer() : "<nil>" ); +#endif +} + +/*---------------------------- + keep track of windows that are sized in ::Init but repositioned + by the window-mgr. If they are not resized by SalFrame::Set[Pos]Size + then SalFrameData::HandleReparentEvent takes a look at it, to prevent it + from beeing moved outside the screen + ------------------------------*/ + +static unsigned int nRefWindow = 0; + +void +MarkWindowAsBadPositioned( unsigned int nWindow ) +{ + nRefWindow = nWindow; +} + +void +MarkWindowAsGoodPositioned( unsigned int nWindow ) +{ + if ( nRefWindow == nWindow ) + nRefWindow = 0; +} + +Boolean +WindowNeedGoodPosition( unsigned int nWindow ) +{ + return (Boolean) nWindow == nRefWindow; +} + +// Sound +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +beta void SalDisplay::Beep() const +{ + XBell( pDisp_, nBeepVolume_ ); +} + +// Keyboard +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +String SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym ) const +{ + String aRet; + if( !nKeySym ) + aRet = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "???" ) ); + else + { + aRet = ::vcl_sal::getKeysymReplacementName( const_cast<SalDisplay*>(this)->GetKeyboardName(), nKeySym ); + if( ! aRet.Len() ) + { + const char *pString = XKeysymToString( nKeySym ); + int n = strlen( pString ); + if( n > 2 && pString[n-2] == '_' ) + aRet = String( pString, n-2, RTL_TEXTENCODING_ISO_8859_1 ); + else + aRet = String( pString, n, RTL_TEXTENCODING_ISO_8859_1 ); + } + } + return aRet; +} + +inline KeySym sal_XModifier2Keysym( Display *pDisplay, + XModifierKeymap *pXModMap, + int n ) +{ + return XKeycodeToKeysym( pDisplay, + pXModMap->modifiermap[n*pXModMap->max_keypermod], + 0 ); +} + +final void SalDisplay::ModifierMapping() +{ + XModifierKeymap *pXModMap = XGetModifierMapping( pDisp_ ); + + bNumLockFromXS_ = True; + nShiftKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ShiftMapIndex ); + nCtrlKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ControlMapIndex ); + nMod1KeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, Mod1MapIndex ); + + // Auf Sun-Servern und SCO-Severn beruecksichtigt XLookupString + // nicht den NumLock Modifier. + if( (GetServerVendor() == vendor_sun) + || (GetServerVendor() == vendor_sco) ) + { + XLIB_KeyCode aNumLock = XKeysymToKeycode( pDisp_, XK_Num_Lock ); + + if( aNumLock ) for( int i = ShiftMapIndex; i <= Mod5MapIndex; i++ ) + { + if( pXModMap->modifiermap[i*pXModMap->max_keypermod] == aNumLock ) + { + bNumLockFromXS_ = False; + nNumLockIndex_ = i; + nNumLockMask_ = 1<<i; + break; + } + } + } + + XFreeModifiermap( pXModMap ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final XubString SalDisplay::GetKeyName( USHORT nKeyCode ) const +{ + String aStrMap; + + if( nKeyCode & KEY_MOD2 ) + { + aStrMap += GetKeyNameFromKeySym( nMod1KeySym_ ); + } + if( nKeyCode & KEY_MOD1 ) + { + if( aStrMap.Len() ) + aStrMap += '+'; + aStrMap += GetKeyNameFromKeySym( nCtrlKeySym_ ); + } + if( nKeyCode & KEY_SHIFT ) + { + if( aStrMap.Len() ) + aStrMap += '+'; + aStrMap += GetKeyNameFromKeySym( nShiftKeySym_ ); + } + nKeyCode &= 0x0FFF; + + KeySym nKeySym = 0; + + if( KEY_0 <= nKeyCode && nKeyCode <= KEY_9 ) + nKeySym = XK_0 + (nKeyCode - KEY_0); + else if( KEY_A <= nKeyCode && nKeyCode <= KEY_Z ) + nKeySym = XK_A + (nKeyCode - KEY_A); + else if( KEY_F1 <= nKeyCode && nKeyCode <= KEY_F26 ) // Existiert die Taste + nKeySym = XK_F1 + (nKeyCode - KEY_F1); + else switch( nKeyCode ) + { + case KEY_DOWN: + nKeySym = XK_Down; + break; + case KEY_UP: + nKeySym = XK_Up; + break; + case KEY_LEFT: + nKeySym = XK_Left; + break; + case KEY_RIGHT: + nKeySym = XK_Right; + break; + case KEY_HOME: + nKeySym = XK_Home; + break; + case KEY_END: + nKeySym = XK_End; + break; + case KEY_PAGEUP: + nKeySym = XK_Prior; + break; + case KEY_PAGEDOWN: + nKeySym = XK_Next; + break; + case KEY_RETURN: + nKeySym = XK_Return; + break; + case KEY_ESCAPE: + nKeySym = XK_Escape; + break; + case KEY_TAB: + nKeySym = XK_Tab; + break; + case KEY_BACKSPACE: + nKeySym = XK_BackSpace; + break; + case KEY_SPACE: + nKeySym = XK_space; + break; + case KEY_INSERT: + nKeySym = XK_Insert; + break; + case KEY_DELETE: + nKeySym = XK_Delete; + break; + case KEY_OPEN: + nKeySym = XK_L7; + break; + case KEY_CUT: + nKeySym = XK_L10; + break; + case KEY_COPY: + nKeySym = XK_L6; + break; + case KEY_PASTE: + nKeySym = XK_L8; + break; + case KEY_UNDO: + nKeySym = XK_L4; // XK_Undo; ??? + break; + case KEY_REPEAT: +// nKeySym = XK_L2; // XK_Redo; ??? + nKeySym = XK_Redo; + break; + case KEY_FIND: + nKeySym = XK_L9; // XK_Find; ??? + break; + case KEY_PROPERTIES: + nKeySym = XK_L3; + break; + case KEY_FRONT: + nKeySym = XK_L5; + break; + + case KEY_ADD: + nKeySym = XK_plus; + break; + case KEY_SUBTRACT: + nKeySym = XK_minus; + break; + case KEY_MULTIPLY: + nKeySym = XK_asterisk; + break; + case KEY_DIVIDE: + nKeySym = XK_slash; + break; + case KEY_POINT: + nKeySym = XK_period; + break; + case KEY_COMMA: + nKeySym = XK_comma; + break; + case KEY_LESS: + nKeySym = XK_less; + break; + case KEY_GREATER: + nKeySym = XK_greater; + break; + case KEY_EQUAL: + nKeySym = XK_equal; + break; + case KEY_FRONT+1: // KEY_HELP + nKeySym = XK_F1; // XK_Help; ??? + break; + + default: + nKeySym = 0; + break; + } + + if( nKeySym ) + { + if( aStrMap.Len() ) + aStrMap += '+'; + aStrMap += GetKeyNameFromKeySym( nKeySym ); + } + + return aStrMap; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#ifndef IsISOKey +#define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00)) +#endif + +final USHORT SalDisplay::GetKeyCode( KeySym keysym, char*pcPrintable ) const +{ + USHORT nKey = 0; + + if( XK_a <= keysym && XK_z >= keysym ) + nKey = (USHORT)(KEY_A + (keysym - XK_a)); + else if( XK_A <= keysym && XK_Z >= keysym ) + nKey = (USHORT)(KEY_A + (keysym - XK_A)); + else if( XK_0 <= keysym && XK_9 >= keysym ) + nKey = (USHORT)(KEY_0 + (keysym - XK_0)); + else if( IsModifierKey( keysym ) ) + nop; + else if( IsKeypadKey( keysym ) ) + { + if( (keysym >= XK_KP_0) && (keysym <= XK_KP_9) ) + { + nKey = (USHORT)(KEY_0 + (keysym - XK_KP_0)); + *pcPrintable = '0' + nKey - KEY_0; + } + else if( IsPFKey( keysym ) ) + nKey = (USHORT)(KEY_F1 + (keysym - XK_KP_F1)); + else switch( keysym ) + { + case XK_KP_Space: + nKey = KEY_SPACE; + *pcPrintable = ' '; + break; + case XK_KP_Tab: + nKey = KEY_TAB; + break; + case XK_KP_Enter: + nKey = KEY_RETURN; + break; + case XK_KP_Begin: + case XK_KP_Home: + nKey = KEY_HOME; + break; + case XK_KP_Left: + nKey = KEY_LEFT; + break; + case XK_KP_Up: + nKey = KEY_UP; + break; + case XK_KP_Right: + nKey = KEY_RIGHT; + break; + case XK_KP_Down: + nKey = KEY_DOWN; + break; + case XK_KP_Prior: // XK_KP_Page_Up + nKey = KEY_PAGEUP; + break; + case XK_KP_Next: // XK_KP_Page_Down + nKey = KEY_PAGEDOWN; + break; + case XK_KP_End: + nKey = KEY_END; + break; + case XK_KP_Insert: + nKey = KEY_INSERT; + break; + case XK_KP_Delete: + nKey = KEY_DELETE; + break; + case XK_KP_Equal: + nKey = KEY_EQUAL; + *pcPrintable = '='; + break; + case XK_KP_Multiply: + nKey = KEY_MULTIPLY; + *pcPrintable = '*'; + break; + case XK_KP_Add: + nKey = KEY_ADD; + *pcPrintable = '+'; + break; + case XK_KP_Separator: + nKey = KEY_COMMA; // ??? + *pcPrintable = ','; + break; + case XK_KP_Subtract: + nKey = KEY_SUBTRACT; + *pcPrintable = '-'; + break; + case XK_KP_Decimal: + nKey = KEY_POINT; + *pcPrintable = '.'; + break; + case XK_KP_Divide: + nKey = KEY_DIVIDE; + *pcPrintable = '/'; + break; + } + } + else if( IsFunctionKey( keysym ) ) + { + if( bNumLockFromXS_ ) + { + if( keysym >= XK_F1 && keysym <= XK_F26 ) + nKey = (USHORT)(KEY_F1 + keysym - XK_F1); + } + else switch( keysym ) + { +#if 1 // Sun schaltet mit "Alt Graph"/XK_Mode_switch um + // - - - - - Sun X-Server Tastatur ohne Cursorblock ??? - - - +#if 0 // Sal supports F1 - F26 + case XK_R1: // XK_F21: + nKey = KEY_F21; // KEY_PRINT/KEY_SYSREQ + break; + case XK_R2: // XK_F22: + nKey = KEY_F22; // KEY_SCROLLLOCK + break; + case XK_R3: // XK_F23: + nKey = KEY_F23; // KEY_PAUSE/KEY_BREAK + break; + case XK_R4: // XK_F24: + nKey = KEY_F24; // KEY_EQUAL + break; + case XK_R5: // XK_F25: + nKey = KEY_F25; // KEY_DIVIDE + break; + case XK_R6: // XK_F26: + nKey = KEY_F26; // KEY_MULTIPLY + break; +#endif + case XK_R7: // XK_F27: + nKey = KEY_HOME; + break; + case XK_R8: // XK_F28: + nKey = KEY_UP; + break; + case XK_R9: // XK_F29: + nKey = KEY_PAGEUP; + break; + case XK_R10: // XK_F30: + nKey = KEY_LEFT; + break; + case XK_R11: // XK_F31: + nKey = 0; // KEY_F31 + break; + case XK_R12: // XK_F32: + nKey = KEY_RIGHT; + break; + case XK_R13: // XK_F33: + nKey = KEY_END; + break; + case XK_R14: // XK_F34: + nKey = KEY_DOWN; + break; + case XK_R15: // XK_F35: + nKey = KEY_PAGEDOWN; + break; + // - - - - - Sun X-Server Tastatur ??? - - - - - - - - - - - - + case XK_L1: // XK_F11: + nKey = KEY_F11; // KEY_CANCEL + break; + case XK_L2: // XK_F12: + if ( GetServerVendor() == vendor_sun ) + nKey = KEY_REPEAT; + else + nKey = KEY_F12; + break; + case XK_L3: // XK_F13: + nKey = KEY_PROPERTIES; // KEY_F13 + break; + case XK_L4: // XK_F14: + nKey = KEY_UNDO; // KEY_F14 + break; + case XK_L5: // XK_F15: + nKey = KEY_F15; // KEY_FRONT + break; + case XK_L6: // XK_F16: + nKey = KEY_COPY; // KEY_F16 + break; + case XK_L7: // XK_F17: + nKey = KEY_F17; // KEY_OPEN + break; + case XK_L8: // XK_F18: + nKey = KEY_PASTE; // KEY_F18 + break; + case XK_L9: // XK_F19: + nKey = KEY_F19; // KEY_FIND + break; + case XK_L10: // XK_F20: + nKey = KEY_CUT; // KEY_F20 + break; +#endif + default: + if( keysym >= XK_F1 && keysym <= XK_F26 ) + nKey = (USHORT)(KEY_F1 + keysym - XK_F1); + break; + } + } + else if( IsCursorKey( keysym ) ) + { + switch( keysym ) + { + case XK_Begin: + case XK_Home: + nKey = KEY_HOME; + break; + case XK_Left: + nKey = KEY_LEFT; + break; + case XK_Up: + nKey = KEY_UP; + break; + case XK_Right: + nKey = KEY_RIGHT; + break; + case XK_Down: + nKey = KEY_DOWN; + break; + case XK_Prior: // XK_Page_Up + nKey = KEY_PAGEUP; + break; + case XK_Next: // XK_Page_Down + nKey = KEY_PAGEDOWN; + break; + case XK_End: + nKey = KEY_END; + break; + } + } + else if( IsMiscFunctionKey( keysym ) ) + { + switch( keysym ) + { + case XK_Insert: + nKey = KEY_INSERT; + break; + case XK_Redo: + nKey = KEY_REPEAT; + break; + case XK_Undo: + nKey = KEY_UNDO; + break; + case XK_Find: + nKey = KEY_FIND; + break; + case XK_Help: + nKey = KEY_FRONT+1; // KEY_HELP + nKey = KEY_F1; + break; + case XK_Menu: + nKey = KEY_F10; + break; +#if 0 + case XK_Break: + case XK_Select: + case XK_Execute: + case XK_Print: + case XK_Cancel: +#endif + } + } + else if( IsISOKey( keysym ) ) // XK_ISO_ + { + switch( keysym ) + { + case 0xFE20: // XK_ISO_Left_Tab: + nKey = KEY_TAB; + break; + } + } + else switch( keysym ) + { + case XK_Return: + nKey = KEY_RETURN; + break; + case XK_BackSpace: + nKey = KEY_BACKSPACE; + break; + case XK_Delete: + nKey = KEY_DELETE; + break; + case XK_space: + nKey = KEY_SPACE; + break; + case XK_Tab: + nKey = KEY_TAB; + break; + case XK_Escape: + nKey = KEY_ESCAPE; + break; + case XK_plus: + nKey = KEY_ADD; + break; + case XK_minus: + nKey = KEY_SUBTRACT; + break; + case XK_asterisk: + nKey = KEY_MULTIPLY; + break; + case XK_slash: + nKey = KEY_DIVIDE; + break; + case XK_period: + nKey = KEY_POINT; + break; + case XK_comma: + nKey = KEY_COMMA; + break; + case XK_less: + nKey = KEY_LESS; + break; + case XK_greater: + nKey = KEY_GREATER; + break; + case XK_equal: + nKey = KEY_EQUAL; + break; +// case XK_Linefeed: +// *pcPrintable = '\n'; +// break; + // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000 + case 0x1000FF02: // apXK_Copy + nKey = KEY_COPY; + break; + case 0x1000FF03: // apXK_Cut + nKey = KEY_CUT; + break; + case 0x1000FF04: // apXK_Paste + nKey = KEY_PASTE; + break; + case 0x1000FF14: // apXK_Repeat + nKey = KEY_REPEAT; + break; + // Exit, Save + // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000 + case 0x1000FF00: + nKey = KEY_DELETE; + break; + // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000 + case 0x1000FF73: // hpXK_DeleteChar + nKey = KEY_DELETE; + break; + case 0x1000FF74: // hpXK_BackTab + case 0x1000FF75: // hpXK_KP_BackTab + nKey = KEY_TAB; + break; + // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - - + // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004 + case 0x1004FF02: // osfXK_Copy + nKey = KEY_COPY; + break; + case 0x1004FF03: // osfXK_Cut + nKey = KEY_CUT; + break; + case 0x1004FF04: // osfXK_Paste + nKey = KEY_PASTE; + break; + case 0x1004FF07: // osfXK_BackTab + nKey = KEY_TAB; + break; + case 0x1004FF08: // osfXK_BackSpace + nKey = KEY_BACKSPACE; + break; + case 0x1004FF1B: // osfXK_Escape + nKey = KEY_ESCAPE; + break; + // Up, Down, Left, Right, PageUp, PageDown + // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - - + // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007 + // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - - + // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005 + case 0x1005FF10: // SunXK_F36 + nKey = KEY_F11; + break; + case 0x1005FF11: // SunXK_F37 + nKey = KEY_F12; + break; + case 0x1005FF70: // SunXK_Props + nKey = KEY_PROPERTIES; + break; + case 0x1005FF71: // SunXK_Front + nKey = KEY_FRONT; + break; + case 0x1005FF72: // SunXK_Copy + nKey = KEY_COPY; + break; + case 0x1005FF73: // SunXK_Open + nKey = KEY_OPEN; + break; + case 0x1005FF74: // SunXK_Paste + nKey = KEY_PASTE; + break; + case 0x1005FF75: // SunXK_Cut + nKey = KEY_CUT; + break; + } + return nKey; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final KeySym SalDisplay::GetKeySym( XKeyEvent *pEvent, + unsigned char *pPrintable, + int *pLen, + Status *pStatusReturn, + XIC aInputContext ) const +{ + KeySym nKeySym; + memset( pPrintable, 0, *pLen ); + + if ( (aInputContext == 0) || (pEvent->type == KeyRelease) ) + { + XComposeStatus nStatus; + *pLen = XLookupString( pEvent, (char*)pPrintable, 1, + &nKeySym, &nStatus ); + } + else + { + *pStatusReturn = 0; + // not really sufficient for multibyte lookup: cannot handle more + // than one byte in sprintable, cannot handle conversion error + *pLen = XmbLookupString( aInputContext, + pEvent, (char*)pPrintable, *pLen - 1, &nKeySym, pStatusReturn ); + + // Lookup the string again, now with appropriate size + if ( *pStatusReturn == XBufferOverflow ) + { + pPrintable[ 0 ] = (char)0; + return 0; + } + + switch ( *pStatusReturn ) + { + case XBufferOverflow: + /* unhandled error */ + break; + case XLookupNone: + /* unhandled error */ + break; + case XLookupKeySym: + /* #72223# this is a strange one: on exceed sometimes + * no printable is returned for the first char entered, + * just to retry lookup solves the problem. The problem + * is not yet fully understood, so restrict 2nd lookup + * to 7bit ascii chars */ + if ( (XK_space <= nKeySym) && (XK_asciitilde >= nKeySym) ) + { + *pLen = 1; + pPrintable[ 0 ] = (char)nKeySym; + } + break; + case XLookupBoth: + case XLookupChars: + + /* nothing to, char allready in pPrintable */ + break; + } + } + + if( !bNumLockFromXS_ + && (IsCursorKey(nKeySym) + || IsFunctionKey(nKeySym) + || IsKeypadKey(nKeySym) + || XK_Delete == nKeySym ) ) + { + // Bei einigen X-Servern muss man bei den Keypadtasten + // schon sehr genau hinschauen. ZB. Solaris XServer: + // 2, 4, 6, 8 werden als Cursorkeys klassifiziert (Up, Down, Left, Right + // 1, 3, 5, 9 werden als Functionkeys klassifiziert (F27,F29,F33,F35) + // 0 als Keypadkey und der Dezimalpunkt gar nicht (KP_Insert) + KeySym nNewKeySym = XLookupKeysym( pEvent, nNumLockIndex_ ); +// fprintf( stderr, "Key%s: sym=%x state=%x code=%d new=%x\n", +// KeyRelease == pEvent->type ? "Release" : "Press", +// nKeySym, pEvent->state, pEvent->keycode, nNewKeySym ); + if( nNewKeySym != NoSymbol ) + nKeySym = nNewKeySym; + } +// else +// fprintf( stderr, "Key%s: sym=%x state=%x code=%d\n", +// KeyRelease == pEvent->type ? "Release" : "Press", +// nKeySym, pEvent->state, pEvent->keycode ); + + return nKeySym; +} + +// Pointer +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#define MAKE_BITMAP( name ) \ + XCreateBitmapFromData( pDisp_, \ + DefaultRootWindow( pDisp_ ), \ + name##_bits, \ + name##_width, \ + name##_height ) + +#define MAKE_CURSOR( name ) \ + aCursBitmap = MAKE_BITMAP( name##curs ); \ + aMaskBitmap = MAKE_BITMAP( name##mask ); \ + nXHot = name##curs_x_hot; \ + nYHot = name##curs_y_hot + +final XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle ) +{ + if( ePointerStyle > POINTER_COUNT ) + return NULL; + + XLIB_Cursor &aCur = aPointerCache_[ePointerStyle]; + + if( aCur != None ) + return aCur; + + Pixmap aCursBitmap, aMaskBitmap; + unsigned int nXHot, nYHot; + + switch( ePointerStyle ) + { + case POINTER_NULL: + MAKE_CURSOR( null ); + break; + case POINTER_ARROW: + aCur = XCreateFontCursor( pDisp_, XC_top_left_arrow ); + break; + case POINTER_WAIT: + MAKE_CURSOR( wait_ ); + break; + case POINTER_TEXT: // Mouse Pointer ist ein "I" Beam + aCur = XCreateFontCursor( pDisp_, XC_xterm ); + break; + case POINTER_HELP: + aCur = XCreateFontCursor( pDisp_, XC_question_arrow ); + break; + case POINTER_CROSS: // Mouse Pointer ist ein Kreuz + aCur = XCreateFontCursor( pDisp_, XC_crosshair ); + break; + case POINTER_NSIZE: + aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); + break; + case POINTER_SSIZE: + aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); + break; + case POINTER_WSIZE: + aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); + break; + case POINTER_ESIZE: + aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); + break; + case POINTER_WINDOW_NSIZE: + aCur = XCreateFontCursor( pDisp_, XC_top_tee ); + break; + case POINTER_WINDOW_SSIZE: + aCur = XCreateFontCursor( pDisp_, XC_bottom_tee ); + break; + case POINTER_WINDOW_WSIZE: + aCur = XCreateFontCursor( pDisp_, XC_left_tee ); + break; + case POINTER_WINDOW_ESIZE: + aCur = XCreateFontCursor( pDisp_, XC_right_tee ); + break; + case POINTER_NWSIZE: + MAKE_CURSOR( nwsesize_ ); + break; + case POINTER_NESIZE: + MAKE_CURSOR( neswsize_ ); + break; + case POINTER_SWSIZE: + MAKE_CURSOR( neswsize_ ); + break; + case POINTER_SESIZE: + MAKE_CURSOR( nwsesize_ ); + break; + case POINTER_WINDOW_NWSIZE: + aCur = XCreateFontCursor( pDisp_, XC_top_left_corner ); + break; + case POINTER_WINDOW_NESIZE: + aCur = XCreateFontCursor( pDisp_, XC_top_right_corner ); + break; + case POINTER_WINDOW_SWSIZE: + aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner ); + break; + case POINTER_WINDOW_SESIZE: + aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner ); + break; + case POINTER_HSPLIT: + MAKE_CURSOR( hsplit_ ); + break; + case POINTER_VSPLIT: + MAKE_CURSOR( vsplit_ ); + break; + case POINTER_HSIZEBAR: + aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); // ??? + break; + case POINTER_VSIZEBAR: + aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); // ??? + break; + case POINTER_REFHAND: + aCur = XCreateFontCursor( pDisp_, XC_hand1 ); + break; + case POINTER_HAND: + aCur = XCreateFontCursor( pDisp_, XC_hand2 ); + break; + case POINTER_MAGNIFY: + MAKE_CURSOR( magnify_ ); + break; + case POINTER_FILL: + MAKE_CURSOR( fill_ ); + break; + case POINTER_MOVE: + MAKE_CURSOR( move_ ); + break; + case POINTER_MOVEDATA: + MAKE_CURSOR( movedata_ ); + break; + case POINTER_COPYDATA: + MAKE_CURSOR( copydata_ ); + break; + case POINTER_MOVEFILE: + MAKE_CURSOR( movefile_ ); + break; + case POINTER_COPYFILE: + MAKE_CURSOR( copyfile_ ); + break; + case POINTER_MOVEFILES: + MAKE_CURSOR( movefiles_ ); + break; + case POINTER_COPYFILES: + MAKE_CURSOR( copyfiles_ ); + break; + case POINTER_NOTALLOWED: + MAKE_CURSOR( nodrop_ ); + break; + case POINTER_ROTATE: + MAKE_CURSOR( rotate_ ); + break; + case POINTER_HSHEAR: + MAKE_CURSOR( hshear_ ); + break; + case POINTER_VSHEAR: + MAKE_CURSOR( vshear_ ); + break; + case POINTER_DRAW_LINE: + MAKE_CURSOR( drawline_ ); + break; + case POINTER_DRAW_RECT: + MAKE_CURSOR( drawrect_ ); + break; + case POINTER_DRAW_POLYGON: + MAKE_CURSOR( drawpolygon_ ); + break; + case POINTER_DRAW_BEZIER: + MAKE_CURSOR( drawbezier_ ); + break; + case POINTER_DRAW_ARC: + MAKE_CURSOR( drawarc_ ); + break; + case POINTER_DRAW_PIE: + MAKE_CURSOR( drawpie_ ); + break; + case POINTER_DRAW_CIRCLECUT: + MAKE_CURSOR( drawcirclecut_ ); + break; + case POINTER_DRAW_ELLIPSE: + MAKE_CURSOR( drawellipse_ ); + break; + case POINTER_DRAW_CONNECT: + MAKE_CURSOR( drawconnect_ ); + break; + case POINTER_DRAW_TEXT: + MAKE_CURSOR( drawtext_ ); + break; + case POINTER_MIRROR: + MAKE_CURSOR( mirror_ ); + break; + case POINTER_CROOK: + MAKE_CURSOR( crook_ ); + break; + case POINTER_CROP: + MAKE_CURSOR( crop_ ); + break; + case POINTER_MOVEPOINT: + MAKE_CURSOR( movepoint_ ); + break; + case POINTER_MOVEBEZIERWEIGHT: + MAKE_CURSOR( movebezierweight_ ); + break; + case POINTER_DRAW_FREEHAND: + MAKE_CURSOR( drawfreehand_ ); + break; + case POINTER_DRAW_CAPTION: + MAKE_CURSOR( drawcaption_ ); + break; + case POINTER_PEN: // Mouse Pointer ist ein Stift + aCur = XCreateFontCursor( pDisp_, XC_pencil ); + break; + case POINTER_LINKDATA: + MAKE_CURSOR( linkdata_ ); + break; + case POINTER_MOVEDATALINK: + MAKE_CURSOR( movedlnk_ ); + break; + case POINTER_COPYDATALINK: + MAKE_CURSOR( copydlnk_ ); + break; + case POINTER_LINKFILE: + MAKE_CURSOR( linkfile_ ); + break; + case POINTER_MOVEFILELINK: + MAKE_CURSOR( moveflnk_ ); + break; + case POINTER_COPYFILELINK: + MAKE_CURSOR( copyflnk_ ); + break; + case POINTER_CHART: + MAKE_CURSOR( chart_ ); + break; + case POINTER_DETECTIVE: + MAKE_CURSOR( detective_ ); + break; + case POINTER_PIVOT_COL: + MAKE_CURSOR( pivotcol_ ); + break; + case POINTER_PIVOT_ROW: + MAKE_CURSOR( pivotrow_ ); + break; + case POINTER_PIVOT_FIELD: + MAKE_CURSOR( pivotfld_ ); + break; + case POINTER_CHAIN: + MAKE_CURSOR( chain_ ); + break; + case POINTER_CHAIN_NOTALLOWED: + MAKE_CURSOR( chainnot_ ); + break; + case POINTER_TIMEEVENT_MOVE: + MAKE_CURSOR( timemove_ ); + break; + case POINTER_TIMEEVENT_SIZE: + MAKE_CURSOR( timesize_ ); + break; + case POINTER_AUTOSCROLL_N: + MAKE_CURSOR(asn_ ); + break; + case POINTER_AUTOSCROLL_S: + MAKE_CURSOR( ass_ ); + break; + case POINTER_AUTOSCROLL_W: + MAKE_CURSOR( asw_ ); + break; + case POINTER_AUTOSCROLL_E: + MAKE_CURSOR( ase_ ); + break; + case POINTER_AUTOSCROLL_NW: + MAKE_CURSOR( asnw_ ); + break; + case POINTER_AUTOSCROLL_NE: + MAKE_CURSOR( asne_ ); + break; + case POINTER_AUTOSCROLL_SW: + MAKE_CURSOR( assw_ ); + break; + case POINTER_AUTOSCROLL_SE: + MAKE_CURSOR( asse_ ); + break; + case POINTER_AUTOSCROLL_NS: + MAKE_CURSOR( asns_ ); + break; + case POINTER_AUTOSCROLL_WE: + MAKE_CURSOR( aswe_ ); + break; + case POINTER_AUTOSCROLL_NSWE: + MAKE_CURSOR( asnswe_ ); + break; + case POINTER_AIRBRUSH: + MAKE_CURSOR( airbrush_ ); + break; + default: + DBG_ERROR("pointer not implemented"); + aCur = XCreateFontCursor( pDisp_, XC_arrow ); + break; + } + + if( None == aCur ) + { + XColor aBlack, aWhite, aDummy; + Colormap hColormap = xColor_->GetXColormap(); + + XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy ); + XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy ); + + aCur = XCreatePixmapCursor( pDisp_, + aCursBitmap, aMaskBitmap, + &aBlack, &aWhite, + nXHot, nYHot ); + + XFreePixmap( pDisp_, aCursBitmap ); + XFreePixmap( pDisp_, aMaskBitmap ); + } + + return aCur; +} + +int SalDisplay::CaptureMouse( SalFrameData *pCapture ) +{ + if( !pCapture ) + { + pCapture_ = NULL; + XUngrabPointer( GetDisplay(), CurrentTime ); + XFlush( GetDisplay() ); + return 0; + } + + if( pCapture_ ) + //pCapture_->CaptureMouse( FALSE ); + pCapture_ = NULL; + + int ret = XGrabPointer( GetDisplay(), + pCapture->GetWindow(), + False, + PointerMotionMask| ButtonPressMask|ButtonReleaseMask, + GrabModeAsync, + GrabModeAsync, + None, + pCapture->GetCursor(), + CurrentTime ); + + if( ret != GrabSuccess ) + { + DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n"); + return -1; + } + + pCapture_ = pCapture; + return 1; +} + +// Fonts +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +static BOOL +sal_IsValidFontpath( const ByteString &rFontPath, + const srv_vendor_t eServerVendor ) +{ + // filter fontpath with ':unscaled' attribute for server other + // than xfree (e.g.: /opt/Office51/fonts/75dpi:unscaled) + + const char aAttr[] = ":unscaled"; + const USHORT nAttrLen = sizeof( aAttr ) - 1; + USHORT nAttrPos; + + nAttrPos = rFontPath.Search( aAttr, 0 ); + if ( nAttrPos == (rFontPath.Len() - nAttrLen) ) + return (eServerVendor == vendor_xfree); + + return TRUE; +} + +final void SalDisplay::AddFontPath( const ByteString &rPath ) const +{ + const char cSeparator = ';' ; + + if( rPath.Len() + && (GetServerVendor() != vendor_excursion) + && (GetServerVendor() != vendor_hummingbird) ) + { + USHORT nCount = rPath.GetTokenCount( cSeparator ); + int i; + int nPaths = 0; + char **pOldFontPath = XGetFontPath( pDisp_, &nPaths ); + int nOriginalPaths = nPaths; + char **pNewFontPath = new char*[nPaths+nCount]; + BOOL bOld = pXLib_->GetIgnoreXErrors(); + + for( i = 0; i < nPaths; i++ ) + pNewFontPath[i] = pOldFontPath[i]; + + for( USHORT nNew = 0; nNew < nCount; nNew++ ) + { + ByteString aPathName = rPath.GetToken( nNew, cSeparator ); + + if( aPathName.Len() ) + { + for( i = 0; i < nPaths; i++ ) + if( !strcmp( pNewFontPath[i], aPathName.GetBuffer() ) ) + break; + + if ( (i == nPaths) + && sal_IsValidFontpath(aPathName, GetServerVendor()) ) + { + pNewFontPath[nPaths] = new char[aPathName.Len()+1]; + strcpy( pNewFontPath[nPaths++], aPathName.GetBuffer() ); + pXLib_->SetIgnoreXErrors( TRUE ); // reset WasXError + + XSetFontPath( pDisp_, pNewFontPath, nPaths ); + XSync( pDisp_, False ); + if( pXLib_->WasXError() ) + delete pNewFontPath[--nPaths]; + } + } + } + + while( nPaths-- > nOriginalPaths ) + delete pNewFontPath[ nPaths ]; + + delete pNewFontPath; + XFreeFontPath( pOldFontPath ); + + + pXLib_->SetIgnoreXErrors( bOld ); + } +} + +// Events +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final void SalDisplay::Remove( XEvent *pEvent ) +{ +} + +final void SalDisplay::SendEvent( Atom aEvent, + void *pData, + XLIB_Window hReceiver ) const +{ + UINT32 aData[5]; + +#if __SIZEOFLONG > 4 + aData[0] = (UINT32)((long)pData & 0xffffffff); + aData[1] = (UINT32)((long)pData >> 32); +#else + aData[0] = (UINT32)(long)pData; + aData[1] = NULL; +#endif + aData[2] = NULL; +#ifndef DBG_UTIL + aData[3] = NULL; + aData[4] = NULL; +#else + aData[3] = ++nIn___; + aData[4] = nOut___; +#endif + SendEvent( aEvent, aData, hReceiver ); +} + +final void SalDisplay::SendEvent( Atom aEvent, + UINT32 *Data, + XLIB_Window hReceiver ) const +{ +#define pClient (&(aClient.xclient)) + XEvent aClient; + + if( !hReceiver ) + hReceiver = GetWindow(); + + pClient->type = ClientMessage; + pClient->display = pDisp_; + pClient->window = hReceiver; + pClient->message_type = aEvent; + pClient->format = 32; + + if( Data ) for( int i = 0; i < 5; i++ ) + pClient->data.l[i] = Data[i]; + + if( osl_acquireMutex( hEventGuard_ ) ) + { + pClient->send_event = 2; + if( pEventQueue_ ) + { + SalXEvent *pEvent = pEventQueue_; + while( pEvent->pNext_ ) + pEvent = pEvent->pNext_; + + pEvent->pNext_ = new SalXEvent; + pEvent->pNext_->event_ = aClient; + pEvent->pNext_->pNext_ = NULL; + } + else + { + ((SalDisplay*)this)->pEventQueue_ = new SalXEvent; + pEventQueue_->event_ = aClient; + pEventQueue_->pNext_ = NULL; + } + + osl_releaseMutex( hEventGuard_ ); + } + else + DBG_ASSERT( 1, "SalDisplay::SendEvent !acquireMutex\n" ); +#undef pClient +} + +final BOOL SalDisplay::IsEvent() +{ + if( pEventQueue_ ) + return TRUE; + + if( XEventsQueued( pDisp_, QueuedAlready ) ) + return TRUE; + + XFlush( pDisp_ ); + return FALSE; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +final void SalDisplay::Yield( BOOL bWait ) +{ + SalXEvent aEvent; + while( !nStateOfYield_ ) + { + if( pEventQueue_ ) + { + nStateOfYield_ = 5; + if( osl_acquireMutex( hEventGuard_ ) ) + { + nStateOfYield_ = 6; + + SalXEvent *pEvent = pEventQueue_; + + pEventQueue_ = pEventQueue_->pNext_; + + osl_releaseMutex( hEventGuard_ ); + + aEvent.event_ = pEvent->event_; + + delete pEvent; + + break; + } + else + DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" ); + } + + nStateOfYield_ = 1; + + DBG_ASSERT( XtAppPending( pXLib_->GetAppContext() ), "no pending event" ); + SalData *pSalData = GetSalData(); + SalYieldMutex* pSalInstYieldMutex = + pSalData->pFirstInstance_->maInstData.mpSalYieldMutex; + + DBG_ASSERT( pSalInstYieldMutex->GetThreadId() == + NAMESPACE_VOS(OThread)::getCurrentIdentifier(), + "will crash soon since solar mutex not locked in SalDisplay::Yield" ); + + // note: alternate input is dispatched by XtAppNextEvent + XtAppNextEvent( pXLib_->GetAppContext(), &aEvent.event_ ); + } + + nStateOfYield_ = 0; + + BOOL bIgnoreXErrors = pXLib_->GetIgnoreXErrors(); + + aEvent.pNext_ = pDispatchStack_; + pDispatchStack_ = &aEvent; + + Dispatch( &aEvent.event_ ); + + pDispatchStack_ = aEvent.pNext_; + +#ifdef DBG_UTIL + if( pXLib_->WasXError() ) + { + XFlush( pDisp_ ); + PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent.event_ ); + } +#endif + + pXLib_->SetIgnoreXErrors( bIgnoreXErrors ); +} + +final long SalDisplay::Dispatch( XEvent *pEvent ) +{ + if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease ) + { + XLIB_Window aWindow = pEvent->xkey.window; + SalFrame* pFrame = NULL; + for( pFrame = GetSalData()->pFirstFrame_; + pFrame + && pFrame->maFrameData.GetWindow() != aWindow + && pFrame->maFrameData.GetShellWindow() != aWindow; + pFrame = pFrame->maFrameData.GetNextFrame() ) + ; + if( pFrame ) + if ( mpInputMethod->FilterEvent( pEvent ) ) + return 0; + } + else + if ( mpInputMethod->FilterEvent( pEvent ) ) + return 0; + + DtIntegrator::HandleXEvent( pEvent ); + + switch( pEvent->type ) + { + case MotionNotify: + while( XCheckWindowEvent( pEvent->xany.display, + pEvent->xany.window, + ButtonMotionMask, + pEvent ) ) + nop; + break; + + case MappingNotify: + if( MappingKeyboard == pEvent->xmapping.request ) + XRefreshKeyboardMapping( &pEvent->xmapping ); + else if( MappingModifier == pEvent->xmapping.request ) + ModifierMapping(); + break; + + default: + + if ( GetKbdExtension()->UseExtension() + && GetKbdExtension()->GetEventBase() == pEvent->type ) + { + GetKbdExtension()->Dispatch( pEvent ); + return 1; + } + +#ifdef _XSHM_H_ + { + BOOL bPrevious = pXLib_->GetIgnoreXErrors(); + pXLib_->SetIgnoreXErrors( TRUE ); + if( pEvent->type == XShmGetEventBase( pDisp_ ) + ShmCompletion ) + { + Remove( pEvent ); + return 1; + } + pXLib_->SetIgnoreXErrors( bPrevious ); + } +#endif + break; + } + + SalFrame *pFrame = GetSalData()->pFirstFrame_; + + while( pFrame ) + { + if( pFrame->maFrameData.GetWindow() == pEvent->xany.window || + pFrame->maFrameData.GetShellWindow() == pEvent->xany.window ) + { + return pFrame->maFrameData.Dispatch( pEvent ); + } + if( pFrame->maFrameData.GetForeignParent() == pEvent->xany.window || + pFrame->maFrameData.GetForeignTopLevelWindow() == pEvent->xany.window ) + { + pFrame->maFrameData.Dispatch( pEvent ); + break; + } + pFrame = pFrame->maFrameData.GetNextFrame(); // not allways NULL + } + + // dispatch to Xt + XtDispatchEvent( pEvent ); + + // dispatch to salobjects + SalObjectData::Dispatch( pEvent ); + + return 0; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final void SalDisplay::PrintEvent( const ByteString &rComment, + XEvent *pEvent ) const +{ + if( pEvent->type <= MappingNotify ) + { + fprintf( stderr, "[%s] %s s=%d w=%ld\n", + rComment.GetBuffer(), + EventNames[pEvent->type], + pEvent->xany.send_event, + pEvent->xany.window ); + + switch( pEvent->type ) + { + case XLIB_KeyPress: + case KeyRelease: + fprintf( stderr, "\t\ts=%d c=%d\n", + pEvent->xkey.state, + pEvent->xkey.keycode ); + break; + + case ButtonPress: + case ButtonRelease: + fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n", + pEvent->xbutton.state, + pEvent->xbutton.button, + pEvent->xbutton.x, + pEvent->xbutton.y, + pEvent->xbutton.x_root, + pEvent->xbutton.y_root ); + break; + + case MotionNotify: + fprintf( stderr, "\t\ts=%d x=%d y=%d\n", + pEvent->xmotion.state, + pEvent->xmotion.x, + pEvent->xmotion.y ); + break; + + case EnterNotify: + case LeaveNotify: + fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n", + pEvent->xcrossing.mode, + pEvent->xcrossing.focus, + pEvent->xcrossing.x, + pEvent->xcrossing.y ); + break; + + case FocusIn: + case FocusOut: + fprintf( stderr, "\t\tm=%d d=%d\n", + pEvent->xfocus.mode, + pEvent->xfocus.detail ); + break; + + case Expose: + case GraphicsExpose: + fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n", + pEvent->xexpose.count, + pEvent->xexpose.width, + pEvent->xexpose.height, + pEvent->xexpose.x, + pEvent->xexpose.y ); + break; + + case VisibilityNotify: + fprintf( stderr, "\t\ts=%d\n", + pEvent->xvisibility.state ); + break; + + case CreateNotify: + case DestroyNotify: + break; + + case MapNotify: + case UnmapNotify: + break; + + case ReparentNotify: + fprintf( stderr, "\t\tp=%d x=%d y=%d\n", + pEvent->xreparent.parent, + pEvent->xreparent.x, + pEvent->xreparent.y ); + break; + + case ConfigureNotify: + fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n", + pEvent->xconfigure.border_width, + pEvent->xconfigure.width, + pEvent->xconfigure.height, + pEvent->xconfigure.x, + pEvent->xconfigure.y ); + break; + + case PropertyNotify: + fprintf( stderr, "\t\ta=%s (0x%X)\n", + GetAtomName( pDisp_, pEvent->xproperty.atom ), + pEvent->xproperty.atom ); + break; + + case ColormapNotify: + fprintf( stderr, "\t\tc=%ld n=%d s=%d\n", + pEvent->xcolormap.colormap, + pEvent->xcolormap.c_new, + pEvent->xcolormap.state ); + break; + + case ClientMessage: + fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n", + GetAtomName( pDisp_, pEvent->xclient.message_type ), + pEvent->xclient.message_type, + pEvent->xclient.format, + pEvent->xclient.data.l[0], + pEvent->xclient.data.l[1], + pEvent->xclient.data.l[2], + pEvent->xclient.data.l[3], + pEvent->xclient.data.l[4] ); + break; + + case MappingNotify: + fprintf( stderr, "\t\tr=%sd\n", + MappingModifier == pEvent->xmapping.request + ? "MappingModifier" + : MappingKeyboard == pEvent->xmapping.request + ? "MappingKeyboard" + : "MappingPointer" ); + + break; + } + } +#ifdef _XSHM_H_ + else if( pEvent->type == XShmGetEventBase( pDisp_ ) + ShmCompletion ) + { +#define pCompletionEvent ((XShmCompletionEvent*)pEvent) + fprintf( stderr, "[%s] %s s=%d d=%ld\n", + rComment.GetBuffer(), + "ShmCompletion", + pCompletionEvent->send_event, + pCompletionEvent->drawable ); + + fprintf( stderr, "\t\tc=%d.%d s=%ld o=%ld\n", + pCompletionEvent->major_code, + pCompletionEvent->minor_code, + pCompletionEvent->shmseg, + pCompletionEvent->offset ); +#undef pCompletionEvent + } +#endif + else + fprintf( stderr, "[%s] %d s=%d w=%ld\n", + rComment.GetBuffer(), + pEvent->type, + pEvent->xany.send_event, + pEvent->xany.window ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void SalDisplay::PrintInfo() const +{ + if( IsDisplay() ) + { + fprintf( stderr, "\n" ); + fprintf( stderr, "Environment\n" ); + fprintf( stderr, "\t$XENVIRONMENT \t\"%s\"\n", + GetEnv( "XENVIRONMENT" ) ); + fprintf( stderr, "\t$DISPLAY \t\"%s\"\n", + GetEnv( "DISPLAY" ) ); + fprintf( stderr, "\t$SAL_VISUAL \t\"%s\"\n", + GetEnv( "SAL_VISUAL" ) ); + fprintf( stderr, "\t$SAL_FONTPATH \t\"%s\"\n", + GetEnv( "SAL_FONTPATH" ) ); + fprintf( stderr, "\t$SAL_NOSEGV \t\"%s\"\n", + GetEnv( "SAL_NOSEGV" ) ); + fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n", + GetEnv( "SAL_IGNOREXERRORS" ) ); + fprintf( stderr, "\t$SAL_PROPERTIES \t\"%s\"\n", + GetEnv( "SAL_PROPERTIES" ) ); + fprintf( stderr, "\t$SAL_WM \t\"%s\"\n", + GetEnv( "SAL_WM" ) ); + fprintf( stderr, "\t$SAL_SYNCHRONIZE \t\"%s\"\n", + GetEnv( "SAL_SYNCHRONIZE" ) ); + fprintf( stderr, "\t$XPPATH \t\"%s\"\n", + GetEnv( "XPPATH" ) ); + + char sHostname[ 120 ]; +# ifdef USE_XMU + XmuGetHostname( sHostname, 120 ); +# else + gethostname (sHostname, 120 ); +# endif + fprintf( stderr, "Client\n" ); + fprintf( stderr, "\tHost \t\"%s\"\n", + sHostname ); + + fprintf( stderr, "Display\n" ); + fprintf( stderr, "\tHost \t\"%s\"\n", + DisplayString(pDisp_) ); + fprintf( stderr, "\tVendor (Release) \t\"%s (%d)\"\n", + ServerVendor(pDisp_), VendorRelease(pDisp_) ); + fprintf( stderr, "\tProtocol \t%d.%d\n", + ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) ); + fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n", + nScreen_, ScreenCount(pDisp_), DefaultScreen(pDisp_) ); + fprintf( stderr, "\tshift ctrl alt \t%s (0x%X) %s (0x%X) %s (0x%X)\n", + KeyStr( nShiftKeySym_ ), nShiftKeySym_, + KeyStr( nCtrlKeySym_ ), nCtrlKeySym_, + KeyStr( nMod1KeySym_ ), nMod1KeySym_ ); + if( XExtendedMaxRequestSize(pDisp_) * 4 ) + fprintf( stderr, "\tXMaxRequestSize \t%ld %ld [bytes]\n", + XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 ); + if( GetProperties() != PROPERTY_DEFAULT ) + fprintf( stderr, "\tProperties \t0x%lX\n", GetProperties() ); + if( eWindowManager_ != otherwm ) + fprintf( stderr, "\tWindowmanager \t%d\n", eWindowManager_ ); + } + fprintf( stderr, "Screen\n" ); + fprintf( stderr, "\tResolution/Size \t%d*%d %d*%d %.1lf\"\n", + aResolution_.A(), aResolution_.B(), + aSize_.Width(), aSize_.Height(), + Hypothenuse( DisplayWidthMM ( pDisp_, nScreen_ ), + DisplayHeightMM( pDisp_, nScreen_ ) ) / 25.4 ); + fprintf( stderr, "\tBlack&White \t%lu %lu\n", + xColor_->GetBlackPixel(), xColor_->GetWhitePixel() ); + fprintf( stderr, "\tRGB \t0x%lx 0x%lx 0x%lx\n", + pVisual_->red_mask, pVisual_->green_mask, pVisual_->blue_mask ); + fprintf( stderr, "\tVisual \t%d-bit %s ID=0x%x\n", + pVisual_->GetDepth(), + VisualClassName[ pVisual_->GetClass() ], + pVisual_->GetVisualId() ); + if( pVisual_ != pRootVisual_ ) + fprintf( stderr, "\tRoot visual \t%d-bit %s ID=0x%x\n", + pRootVisual_->GetDepth(), + VisualClassName[ pRootVisual_->GetClass() ], + pRootVisual_->GetVisualId() ); + fprintf( stderr, "\tImages (Shared) \t0x%lx (%lx)\n", + nImageDepths_, nSharedImages_ ); + + if( nStateOfYield_ || nStateOfSendEvent_ ) + { + fprintf( stderr, "Thread/Signal\n" ); + fprintf( stderr, "\tNextEvent \t%d\n", nStateOfYield_ ); + fprintf( stderr, "\tSendEvent \t%d\n", nStateOfSendEvent_ ); + } + if( pDispatchStack_ ) + { + fprintf( stderr, "Event\n" ); + SalXEvent *pEvent = pDispatchStack_; + while( pEvent ) + { + PrintEvent( "\t\x08\x08", &pEvent->event_ ); + pEvent = pEvent->pNext_; + } + } +} + +// -=-= SalICCCM -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final +SalICCCM::SalICCCM( SalDisplay *pDisplay ) +{ + Display *display = pDisplay->GetDisplay(); + + for( int i = 0; i < capacityof( AtomStrings ); i++ ) + (&aWM_Protocols_)[i] = XInternAtom( display, AtomStrings[i], False ); +} + +// -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +SalVisual::SalVisual( const XVisualInfo* pXVI ) +{ + *(XVisualInfo*)this = *pXVI; + if( GetClass() == TrueColor ) + { + nRedShift_ = sal_Shift( red_mask ); + nGreenShift_ = sal_Shift( green_mask ); + nBlueShift_ = sal_Shift( blue_mask ); + + if( GetDepth() == 24 ) + if( red_mask == 0xFF0000 ) + if( green_mask == 0xFF00 ) + if( blue_mask == 0xFF ) + eRGBMode_ = RGB; + else + eRGBMode_ = other; + else if( blue_mask == 0xFF00 ) + if( green_mask == 0xFF ) + eRGBMode_ = RBG; + else + eRGBMode_ = other; + else + eRGBMode_ = other; + else if( green_mask == 0xFF0000 ) + if( red_mask == 0xFF00 ) + if( blue_mask == 0xFF ) + eRGBMode_ = GRB; + else + eRGBMode_ = other; + else if( blue_mask == 0xFF00 ) + if( red_mask == 0xFF ) + eRGBMode_ = GBR; + else + eRGBMode_ = other; + else + eRGBMode_ = other; + else if( blue_mask == 0xFF0000 ) + if( red_mask == 0xFF00 ) + if( green_mask == 0xFF ) + eRGBMode_ = BRG; + else + eRGBMode_ = other; + else if( green_mask == 0xFF00 ) + if( red_mask == 0xFF ) + eRGBMode_ = BGR; + else + eRGBMode_ = other; + else + eRGBMode_ = other; + else + eRGBMode_ = other; + else + eRGBMode_ = other; + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +SalVisual::~SalVisual() +{ + if( -1 == screen && -1 == visualid ) delete visual; +} + +// Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors +// fuer die 6 XXXA ist das nicht reversibel +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF + +#define SALCOLOR RGB +#define SALCOLORREVERSE BGR + +BOOL SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 ) +{ + int n; + + switch( GetMode() ) + { + case other: + return FALSE; + break; + case SALCOLOR: + break; + case SALCOLORREVERSE: + case RBG: + case BRG: + case GBR: + case GRB: + return Convert( n0, n1, n2 ); + break; + case RGBA: + n = n0; + n0 = n1; + n1 = n2; + n2 = n3; + n3 = n; + break; + case BGRA: + case RBGA: + case BRGA: + case GBRA: + case GRBA: + default: + fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); + abort(); + break; + } + return TRUE; +} + +BOOL SalVisual::Convert( int &n0, int &n1, int &n2 ) +{ + int n; + + switch( GetMode() ) + { + case other: + return FALSE; + break; + case SALCOLOR: + break; + case RBG: + n = n0; + n0 = n1; + n1 = n; + break; + case GRB: + n = n1; + n1 = n2; + n2 = n; + break; + case SALCOLORREVERSE: + n = n0; + n0 = n2; + n2 = n; + break; + case BRG: + n = n0; + n0 = n1; + n1 = n2; + n2 = n; + break; + case GBR: + n = n2; + n2 = n1; + n1 = n0; + n0 = n; + break; + default: + fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); + abort(); + break; + } + return TRUE; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final SalColor SalVisual::GetTCColor( Pixel nPixel ) const +{ + if( SALCOLOR == eRGBMode_ ) + return (SalColor)nPixel; + + if( SALCOLORREVERSE == eRGBMode_ ) + return MAKE_SALCOLOR( (nPixel & 0x0000FF), + (nPixel & 0x00FF00) >> 8, + (nPixel & 0xFF0000) >> 16); + + Pixel r = nPixel & red_mask; + Pixel g = nPixel & green_mask; + Pixel b = nPixel & blue_mask; + + if( other != eRGBMode_ ) // 8+8+8=24 + return MAKE_SALCOLOR( r >> nRedShift_, + g >> nGreenShift_, + b >> nBlueShift_ ); + + if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_; + if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_; + if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_; + + return MAKE_SALCOLOR( r, g, b ); +} + +final Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const +{ + if( SALCOLOR == eRGBMode_ ) + return (Pixel)nSalColor; + + Pixel r = (Pixel)SALCOLOR_RED( nSalColor ); + Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor ); + Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor ); + + if( SALCOLORREVERSE == eRGBMode_ ) + return (b << 16) | (g << 8) | (r); + + if( other != eRGBMode_ ) // 8+8+8=24 + return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_); + + if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_; + if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_; + if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_; + + return (r&red_mask) | (g&green_mask) | (b&blue_mask); +} + +// -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final SalColormap::SalColormap( SalDisplay *pDisplay, Colormap hColormap ) + : pDisplay_( pDisplay ), + hColormap_( hColormap ), + pPalette_( NULL ), + pLookupTable_( NULL ) +{ + pVisual_ = pDisplay_->GetVisual(); + + if( pVisual_ == pDisplay_->GetRootVisual() ) + { + nBlackPixel_ = BlackPixel( pDisplay_->GetDisplay(), + pDisplay_->GetScreenNumber() ); + nWhitePixel_ = WhitePixel( pDisplay_->GetDisplay(), + pDisplay_->GetScreenNumber() ); + } + else + { + XColor aColor; + + GetXPixel( aColor, 0x00, 0x00, 0x00 ); + nBlackPixel_ = aColor.pixel; + + GetXPixel( aColor, 0xFF, 0xFF, 0xFF ); + nWhitePixel_ = aColor.pixel; + } + + nUsed_ = 1 << pVisual_->GetDepth(); + + if( pVisual_->GetClass() == PseudoColor ) + { + XColor aColor; + int r, g, b; + + // black, white, gray, ~gray = 4 + GetXPixels( aColor, 0xC0, 0xC0, 0xC0 ); + + // light colors: 3 * 2 = 6 +// GetXPixels( aColor, 0x00, 0x00, 0x00 ); + GetXPixels( aColor, 0x00, 0x00, 0xFF ); + GetXPixels( aColor, 0x00, 0xFF, 0x00 ); + GetXPixels( aColor, 0x00, 0xFF, 0xFF ); +// GetXPixels( aColor, 0xFF, 0x00, 0x00 ); +// GetXPixels( aColor, 0xFF, 0x00, 0xFF ); +// GetXPixels( aColor, 0xFF, 0xFF, 0x00 ); +// GetXPixels( aColor, 0xFF, 0xFF, 0xFF ); + + // standard colors: 7 * 2 = 14 +// GetXPixels( aColor, 0x00, 0x00, 0x00 ); + GetXPixels( aColor, 0x00, 0x00, 0x80 ); + GetXPixels( aColor, 0x00, 0x80, 0x00 ); + GetXPixels( aColor, 0x00, 0x80, 0x80 ); + GetXPixels( aColor, 0x80, 0x00, 0x00 ); + GetXPixels( aColor, 0x80, 0x00, 0x80 ); + GetXPixels( aColor, 0x80, 0x80, 0x00 ); + GetXPixels( aColor, 0x80, 0x80, 0x80 ); + GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7 + + // cube: 6*6*6 - 8 = 208 + for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF + for( g = 0; g < 0x100; g += 0x33 ) + for( b = 0; b < 0x100; b += 0x33 ) + GetXPixels( aColor, r, g, b ); + + // gray: 16 - 6 = 10 + for( g = 0x11; g < 0xFF; g += 0x11 ) + GetXPixels( aColor, g, g, g ); + + // green: 16 - 6 = 10 + for( g = 0x11; g < 0xFF; g += 0x11 ) + GetXPixels( aColor, 0, g, 0 ); + + // red: 16 - 6 = 10 + for( r = 0x11; r < 0xFF; r += 0x11 ) + GetXPixels( aColor, r, 0, 0 ); + + // blue: 16 - 6 = 10 + for( b = 0x11; b < 0xFF; b += 0x11 ) + GetXPixels( aColor, 0, 0, b ); + } +} + +// PseudoColor +final SalColormap::SalColormap( const BitmapPalette &rPalette ) + : pDisplay_( GetSalData()->GetCurDisp() ), + hColormap_( None ), + pVisual_( NULL ), + nUsed_( rPalette.GetEntryCount() ), + nBlackPixel_( 0xFFFFFFFF ), + nWhitePixel_( 0xFFFFFFFF ), + pLookupTable_( NULL ) +{ + pPalette_ = new SalColor[nUsed_]; + + for( int i = 0; i < nUsed_; i++ ) + { + const BitmapColor &rColor = rPalette[i]; + pPalette_[i] = MAKE_SALCOLOR( rColor.GetRed(), + rColor.GetGreen(), + rColor.GetBlue() ); + if( nBlackPixel_ == 0xFFFFFFFF && SALCOLOR_BLACK == pPalette_[i] ) + nBlackPixel_ = i; + else if( nWhitePixel_ == 0xFFFFFFFF && SALCOLOR_WHITE == pPalette_[i] ) + nWhitePixel_ = i; + } +} + +// MonoChrome +final SalColormap::SalColormap() + : pDisplay_( GetSalData()->GetCurDisp() ), + hColormap_( None ), + pVisual_( NULL ), + nUsed_( 2 ), + nBlackPixel_( 0 ), + nWhitePixel_( 1 ), + pLookupTable_( NULL ) +{ + pPalette_ = new SalColor[nUsed_]; + + pPalette_[nBlackPixel_] = SALCOLOR_BLACK; + pPalette_[nWhitePixel_] = SALCOLOR_WHITE; +} + +// TrueColor +final SalColormap::SalColormap( USHORT nDepth ) + : pDisplay_( GetSalData()->GetCurDisp() ), + hColormap_( None ), + pPalette_( NULL ), + nUsed_( 1 << nDepth ), + nWhitePixel_( (1 << nDepth) - 1 ), + nBlackPixel_( 0x00000000 ), + pLookupTable_( NULL ) + +{ + SalVisual *pVisual = pDisplay_->GetVisual(); + + if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth ) + pVisual_ = pVisual; + else + { + XVisualInfo aVI; + + if( !XMatchVisualInfo( pDisplay_->GetDisplay(), + pDisplay_->GetScreenNumber(), + nDepth, + TrueColor, + &aVI ) ) + { + aVI.visual = new Visual(); + aVI.visualid = (VisualID)-1; + aVI.screen = -1; + aVI.depth = nDepth; + aVI.c_class = TrueColor; + if( 24 == nDepth ) // 888 + { + aVI.red_mask = 0xFF0000; + aVI.green_mask = 0x00FF00; + aVI.blue_mask = 0x0000FF; + } + else if( 16 == nDepth ) // 565 + { + aVI.red_mask = 0x00F800; + aVI.green_mask = 0x0007E0; + aVI.blue_mask = 0x00001F; + } + else if( 15 == nDepth ) // 555 + { + aVI.red_mask = 0x007C00; + aVI.green_mask = 0x0003E0; + aVI.blue_mask = 0x00001F; + } + else if( 12 == nDepth ) // 444 + { + aVI.red_mask = 0x000F00; + aVI.green_mask = 0x0000F0; + aVI.blue_mask = 0x00000F; + } + else if( 8 == nDepth ) // 332 + { + aVI.red_mask = 0x0000E0; + aVI.green_mask = 0x00001C; + aVI.blue_mask = 0x000003; + } + else + { + aVI.red_mask = 0x000000; + aVI.green_mask = 0x000000; + aVI.blue_mask = 0x000000; + } + aVI.colormap_size = 0; + aVI.bits_per_rgb = 8; + + aVI.visual->ext_data = NULL; + aVI.visual->visualid = aVI.visualid; + aVI.visual->c_class = aVI.c_class; + aVI.visual->red_mask = aVI.red_mask; + aVI.visual->green_mask = aVI.green_mask; + aVI.visual->blue_mask = aVI.blue_mask; + aVI.visual->bits_per_rgb = aVI.bits_per_rgb; + aVI.visual->map_entries = aVI.colormap_size; + } + + pVisual_ = new SalVisual( &aVI ); + } +} + +final SalColormap::~SalColormap() +{ + if( hColormap_ + && pDisplay_->IsDisplay() + && hColormap_ != DefaultColormap( GetXDisplay(), pDisplay_->GetScreenNumber() ) ) + XFreeColormap( GetXDisplay(), hColormap_ ); + delete pPalette_; + delete pLookupTable_; + if( pVisual_ != pDisplay_->GetVisual() ) + delete pVisual_; + +#ifdef DBG_UTIL + hColormap_ = (Colormap)ILLEGAL_POINTER; + pDisplay_ = (SalDisplay*)ILLEGAL_POINTER; + pPalette_ = (SalColor*)ILLEGAL_POINTER; + pLookupTable_ = (USHORT*)ILLEGAL_POINTER; + pVisual_ = (SalVisual*)ILLEGAL_POINTER; +#endif +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final void SalColormap::SetPalette( const BitmapPalette &rPalette ) +{ + if( this != &GetSalData()->GetCurDisp()->GetColormap() ) + { + nBlackPixel_ = 0xFFFFFFFF; + nWhitePixel_ = 0xFFFFFFFF; + } + + if( rPalette.GetEntryCount() > nUsed_ ) + { + nBlackPixel_ = 0xFFFFFFFF; + nWhitePixel_ = 0xFFFFFFFF; + delete pPalette_; + pPalette_ = new SalColor[rPalette.GetEntryCount()]; + nUsed_ = rPalette.GetEntryCount(); + } + + for( int i = 0; i < rPalette.GetEntryCount(); i++ ) + { + const BitmapColor &rColor = rPalette[i]; + pPalette_[i] = MAKE_SALCOLOR( rColor.GetRed(), + rColor.GetGreen(), + rColor.GetBlue() ); + if( nBlackPixel_ == 0xFFFFFFFF && SALCOLOR_BLACK == pPalette_[i] ) + nBlackPixel_ = i; + else if( nWhitePixel_ == 0xFFFFFFFF && SALCOLOR_WHITE == pPalette_[i] ) + nWhitePixel_ = i; + } +} + +final void SalColormap::GetPalette() +{ + Pixel i; + + pPalette_ = new SalColor[nUsed_]; + + XColor *aColor = new XColor[nUsed_]; + + for( i = 0; i < nUsed_; i++ ) + { + aColor[i].red = aColor[i].green = aColor[i].blue = 0; + aColor[i].pixel = i; + } + + XQueryColors( pDisplay_->GetDisplay(), hColormap_, aColor, nUsed_ ); + + for( i = 0; i < nUsed_; i++ ) + { + pPalette_[i] = MAKE_SALCOLOR( aColor[i].red >> 8, + aColor[i].green >> 8, + aColor[i].blue >> 8 ); + } + + delete aColor; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final static USHORT sal_Lookup( SalColor *pPalette, + int r, int g, int b, + Pixel nUsed ) +{ + USHORT nPixel = 0; + int nBest = ColorDiff( pPalette[0], r, g, b ); + + for( USHORT i = 1; i < nUsed; i++ ) + { + int n = ColorDiff( pPalette[i], r, g, b ); + + if( n < nBest ) + { + if( !n ) + return i; + + nPixel = i; + nBest = n; + } + } + return nPixel; +} + +final void SalColormap::GetLookupTable() +{ + USHORT *p = pLookupTable_ = new USHORT[16*16*16]; + + for( int r = 0; r < 256; r += 17 ) + for( int g = 0; g < 256; g += 17 ) + for( int b = 0; b < 256; b += 17 ) + *p++ = sal_Lookup( pPalette_, r, g, b, nUsed_ ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final SalColor SalColormap::GetColor( Pixel nPixel ) const +{ + if( nBlackPixel_ == nPixel ) return SALCOLOR_BLACK; + if( nWhitePixel_ == nPixel ) return SALCOLOR_WHITE; + + if( pVisual_ ) + { + if( pVisual_->GetClass() == TrueColor ) + return pVisual_->GetTCColor( nPixel ); + + if( !pPalette_ + && ( hColormap_ || XSalIsPrinter( GetXDisplay() ) ) +#ifdef PSEUDOCOLOR12 + && pVisual_->GetDepth() <= 12 +#else + && pVisual_->GetDepth() <= 8 +#endif + && pVisual_->GetClass() == PseudoColor ) + ((SalColormap*)this)->GetPalette(); + } + + if( pPalette_ && nPixel < nUsed_ ) + return pPalette_[nPixel]; + + if( !hColormap_ && !XSalIsPrinter( GetXDisplay() ) ) + { + DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" ); + return nPixel; + } + + // DirectColor, StaticColor, StaticGray, GrayScale + XColor aColor; + + aColor.pixel = nPixel; + + XQueryColor( pDisplay_->GetDisplay(), hColormap_, &aColor ); + + return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 ); +} + +final inline BOOL SalColormap::GetXPixel( XColor &rColor, + int r, + int g, + int b ) const +{ + rColor.red = r * 257; + rColor.green = g * 257; + rColor.blue = b * 257; + return XAllocColor( GetXDisplay(), hColormap_, &rColor ); +} + +final BOOL SalColormap::GetXPixels( XColor &rColor, + int r, + int g, + int b ) const +{ + if( !GetXPixel( rColor, r, g, b ) ) + return FALSE; + if( rColor.pixel & 1 ) + return TRUE; + return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF ); +} + +final Pixel SalColormap::GetPixel( SalColor nSalColor ) const +{ + if( 0xFFFFFFFF == nSalColor ) return 0; + if( SALCOLOR_BLACK == nSalColor ) return nBlackPixel_; + if( SALCOLOR_WHITE == nSalColor ) return nWhitePixel_; + + if( pVisual_ && pVisual_->GetClass() == TrueColor ) + return pVisual_->GetTCPixel( nSalColor ); + + if( !pLookupTable_ ) + { + if( !pPalette_ + && ( hColormap_ || XSalIsPrinter( GetXDisplay() ) ) + && pVisual_ +#ifdef PSEUDOCOLOR12 + && pVisual_->GetDepth() <= 12 +#else + && pVisual_->GetDepth() <= 8 +#endif + && pVisual_->GetClass() == PseudoColor ) // what else ??? + ((SalColormap*)this)->GetPalette(); + + if( pPalette_ ) + for( Pixel i = 0; i < nUsed_; i++ ) + if( pPalette_[i] == nSalColor ) + return i; + + if( hColormap_ || XSalIsPrinter( GetXDisplay() ) ) + { + // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor) + XColor aColor; + + if( GetXPixel( aColor, + SALCOLOR_RED ( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE ( nSalColor ) ) ) + { + if( pPalette_ && !pPalette_[aColor.pixel] ) + { + pPalette_[aColor.pixel] = nSalColor; + + if( !(aColor.pixel & 1) && !pPalette_[aColor.pixel+1] ) + { + XColor aInversColor; + + SalColor nInversColor = nSalColor ^ 0xFFFFFF; + + GetXPixel( aInversColor, + SALCOLOR_RED ( nInversColor ), + SALCOLOR_GREEN( nInversColor ), + SALCOLOR_BLUE ( nInversColor ) ); + + if( !pPalette_[aInversColor.pixel] ) + pPalette_[aInversColor.pixel] = nInversColor; +#ifdef DBG_UTIL + else + fprintf( stderr, "SalColormap::GetPixel() 0x06lx=%d 0x06lx=%d\n", + nSalColor, aColor.pixel, + nInversColor, aInversColor.pixel); +#endif + } + } + + return aColor.pixel; + } + +#ifdef DBG_UTIL + fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n", + nSalColor ); +#endif + } + + if( !pPalette_ ) + { + fprintf( stderr, "SalColormap::GetPixel() !pPalette_ %lx\n", + nSalColor); + return nSalColor; + } + + ((SalColormap*)this)->GetLookupTable(); + } + + // Colormatching ueber Palette + USHORT r = SALCOLOR_RED ( nSalColor ); + USHORT g = SALCOLOR_GREEN( nSalColor ); + USHORT b = SALCOLOR_BLUE ( nSalColor ); + return pLookupTable_[ (((r+8)/17) << 8) + + (((g+8)/17) << 4) + + ((b+8)/17) ]; +} + diff --git a/vcl/unx/source/app/salinst.cxx b/vcl/unx/source/app/salinst.cxx new file mode 100644 index 000000000000..374ab09a94df --- /dev/null +++ b/vcl/unx/source/app/salinst.cxx @@ -0,0 +1,346 @@ +/************************************************************************* + * + * $RCSfile: salinst.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_SALINST_CXX + +// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <salunx.h> + +#ifndef _VOS_MUTEX_HXX +#include <vos/mutex.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALWTYPE_HXX +#include <salwtype.hxx> +#endif +#ifndef _SV_SALATYPE_HXX +#include <salatype.hxx> +#endif +#ifndef _SV_DTINT_HXX +#include <dtint.hxx> +#endif +#ifndef _SV_SALPRN_H +#include <salprn.h> +#endif +#ifndef _VCL_SALCONFIG_HXX +#include <salconfig.hxx> +#endif + +// -=-= C++ globals =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void SalAbort( const XubString& rErrorText ) +{ + if( !rErrorText.Len() ) + fprintf( stderr, "Application Error" ); + else + fprintf( stderr, ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() ); + abort(); +} + + +// ------------------------------------------------------------------------- +// +// SalYieldMutex +// +// ------------------------------------------------------------------------- + +SalYieldMutex::SalYieldMutex() +{ + mnCount = 0; + mnThreadId = 0; +} + +void SalYieldMutex::acquire() +{ + OMutex::acquire(); + mnThreadId = NAMESPACE_VOS(OThread)::getCurrentIdentifier(); + mnCount++; +} + +void SalYieldMutex::release() +{ + if ( mnThreadId == NAMESPACE_VOS(OThread)::getCurrentIdentifier() ) + { + if ( mnCount == 1 ) + mnThreadId = 0; + mnCount--; + } + OMutex::release(); +} + +sal_Bool SalYieldMutex::tryToAcquire() +{ + if ( OMutex::tryToAcquire() ) + { + mnThreadId = NAMESPACE_VOS(OThread)::getCurrentIdentifier(); + mnCount++; + return True; + } + else + return False; +} + +//---------------------------------------------------------------------------- + +final void InitSalData() +{ + SalData *pSalData = new SalData; + SetSalData( pSalData ); +} + +final void DeInitSalData() +{ + SalData *pSalData = GetSalData(); + delete pSalData; + SetSalData( NULL ); +} + +final void SetFilterCallback( void* pCallback, void* pInst ) +{ + SalData* pSalData = GetSalData(); + + pSalData->pFirstInstance_->maInstData.mpFilterCallback = pCallback; + pSalData->pFirstInstance_->maInstData.mpFilterInst = pInst; +} + +final SalInstance *CreateSalInstance() +{ + SalData *pSalData = GetSalData(); + SalInstance *pInst = new SalInstance; + + // init instance (only one instance in this version !!!) + pSalData->pFirstInstance_ = pInst; + + StartPrinterListening(); + + return pInst; +} + +final void DestroySalInstance( SalInstance *pInst ) +{ + SalData *pSalData = GetSalData(); + + // reset instance (only one instance in this version !!!) + if( pSalData->pFirstInstance_ == pInst ) + { + StopPrinterListening(); + pSalData->pFirstInstance_ = NULL; + ::vcl_sal::XpDefaults::release(); + } + + delete pInst; +} + +// -=-= SalInstance =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final SalInstance::SalInstance() +{ + maInstData.mpFilterCallback = NULL; + maInstData.mpFilterInst = NULL; + maInstData.mpSalYieldMutex = new SalYieldMutex; + maInstData.mpSalYieldMutex->acquire(); +} + +final SalInstance::~SalInstance() +{ +// #75711# - java is running + maInstData.mpSalYieldMutex->release(); + delete maInstData.mpSalYieldMutex; +} + + +// -------------------------------------------------------- +// AnyInput from sv/mow/source/app/svapp.cxx + +struct PredicateReturn +{ + USHORT nType; + BOOL bRet; +}; + +Bool ImplPredicateEvent( Display *, XEvent *pEvent, char *pData ) +{ + PredicateReturn *pPre = (PredicateReturn *)pData; + + if ( pPre->bRet ) + return False; + + USHORT nType; + + switch( pEvent->type ) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + nType = INPUT_MOUSE; + break; + + case XLIB_KeyPress: + //case KeyRelease: + nType = INPUT_KEYBOARD; + break; + case Expose: + case GraphicsExpose: + case NoExpose: + nType = INPUT_PAINT; + break; + default: + nType = 0; + } + + if ( nType & pPre->nType || ( ! nType && pPre->nType & INPUT_OTHER ) ) + pPre->bRet = TRUE; + + return False; +} + + +alpha BOOL SalInstance::AnyInput(USHORT nType) +{ + SalData *pSalData = GetSalData(); + Display *pDisplay = pSalData->GetDefDisp()->GetDisplay(); + + // XtInputMask nMask = XtAppPending( SVData().GetAppContext() ); + // if( nMask ) + if (XPending(pDisplay) ) + { + // if ( INPUT_TIMER & nType && XtIMTimer & nMask ) + // return TRUE; + // else + { + PredicateReturn aInput; + XEvent aEvent; + + aInput.bRet = FALSE; + aInput.nType = nType; + + XCheckIfEvent(pDisplay, &aEvent, ImplPredicateEvent, + (char *)&aInput ); + + return aInput.bRet; + } + } + return FALSE ; +} + +#ifdef _VOS_NO_NAMESPACE +IMutex* SalInstance::GetYieldMutex() +#else +vos::IMutex* SalInstance::GetYieldMutex() +#endif +{ + return maInstData.mpSalYieldMutex; +} + +// ----------------------------------------------------------------------- + +ULONG SalInstance::ReleaseYieldMutex() +{ + SalYieldMutex* pYieldMutex = maInstData.mpSalYieldMutex; + if ( pYieldMutex->GetThreadId() == + NAMESPACE_VOS(OThread)::getCurrentIdentifier() ) + { + ULONG nCount = pYieldMutex->GetAcquireCount(); + ULONG n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + + return nCount; + } + else + return 0; +} + +// ----------------------------------------------------------------------- + +void SalInstance::AcquireYieldMutex( ULONG nCount ) +{ + SalYieldMutex* pYieldMutex = maInstData.mpSalYieldMutex; + while ( nCount ) + { + pYieldMutex->acquire(); + nCount--; + } +} + +final void SalInstance::Yield( BOOL bWait ) +{ GetSalData()->GetLib()->Yield( bWait ); } + diff --git a/vcl/unx/source/app/salsys.cxx b/vcl/unx/source/app/salsys.cxx new file mode 100644 index 000000000000..47f855ce365a --- /dev/null +++ b/vcl/unx/source/app/salsys.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * $RCSfile: salsys.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_SALSYS_CXX + +#include <cstdio> +#include <string> + +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALSYS_HXX +#include <salsys.hxx> +#endif +#ifndef _SV_DTINT_HXX +#include <dtint.hxx> +#endif +#include <salframe.hxx> + +#include <strhelper.hxx> +#include <stacktrace.hxx> + + +void SalSystemData::CreateDtIntegrator( SalFrame* pNewFrame ) +{ + if( pNewFrame ) + { + if( m_pDtIntegrator && m_pDtIntegrator->GetDisplay() != + pNewFrame->maFrameData.GetDisplay()->GetDisplay() ) + { + m_pDtIntegrator->Release(); + m_pDtIntegrator = 0; + } + if( ! m_pDtIntegrator ) + { + m_pDtIntegrator = DtIntegrator::CreateDtIntegrator( pNewFrame ); + m_pDtIntegrator->Acquire(); + } + } +} + +void SalSystemData::SetSalDisplay( SalDisplay *pSalDisplay ) +{ + m_pSalDisplay = pSalDisplay; +} + +SalSystemData::~SalSystemData() +{ + if( m_pDtIntegrator ) + m_pDtIntegrator->Release(); +} + + +// ----------------------------------------------------------------------- + +SalSystem* SalInstance::CreateSystem() +{ + return new SalSystem(); +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroySystem( SalSystem* pSystem ) +{ + delete pSystem; +} + +// ======================================================================= + +SalSystem::SalSystem() +{ + maSystemData.m_pSalDisplay = 0; + maSystemData.m_pDtIntegrator = 0; +} + +// ----------------------------------------------------------------------- + +SalSystem::~SalSystem() +{ +} + +// ----------------------------------------------------------------------- + +BOOL SalSystem::StartProcess( SalFrame* pFrame, const String& rFileName, + const String& rParam, + const String& rWorkingDirectory ) +{ + maSystemData.CreateDtIntegrator( pFrame ); + + XubString aFileName( '\"' ); + aFileName += rFileName; + aFileName += '\"'; + + // StartProcess is desktop specific + return maSystemData.m_pDtIntegrator-> + StartProcess( aFileName, + const_cast<XubString&>(rParam), + const_cast<XubString&>(rWorkingDirectory) ); +} + +// ----------------------------------------------------------------------- + +BOOL SalSystem::AddRecentDoc( SalFrame* pFrame, const XubString& rFileName ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +String SalSystem::GetSummarySystemInfos( ULONG nFlags ) +{ + sal_PostMortem aPostMortem; + + /* + * unimplemented flags: + * SALSYSTEM_GETSYSTEMINFO_MODULES + * SALSYSTEM_GETSYSTEMINFO_MOUSEINFO + * SALSYSTEM_GETSYSTEMINFO_SYSTEMDIRS + * SALSYSTEM_GETSYSTEMINFO_LOCALVOLUMES + */ + + ByteString aRet; + if( nFlags & SALSYSTEM_GETSYSTEMINFO_SYSTEMVERSION ) + aRet += aPostMortem.getSystemInfo(); + if( nFlags & SALSYSTEM_GETSYSTEMINFO_CPUTYPE ) + aRet += aPostMortem.getProcessorInfo(); + if( nFlags & SALSYSTEM_GETSYSTEMINFO_MEMORYINFO ) + aRet += aPostMortem.getMemoryInfo(); + if( nFlags & SALSYSTEM_GETSYSTEMINFO_STACK ) + aRet += aPostMortem.getStackTrace(); + if( nFlags & SALSYSTEM_GETSYSTEMINFO_GRAPHICSSYSTEM ) + aRet += aPostMortem.getGraphicsSystem(); + +#ifdef DEBUG + fprintf( stderr, "SalSystem::GetSummarySystemInfos() =\n%s", aRet.GetBuffer() ); +#endif + return String( aRet, RTL_TEXTENCODING_ISO_8859_1 ); +} + diff --git a/vcl/unx/source/app/saltimer.cxx b/vcl/unx/source/app/saltimer.cxx new file mode 100644 index 000000000000..754d0509de66 --- /dev/null +++ b/vcl/unx/source/app/saltimer.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * $RCSfile: saltimer.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_SALTIMER_CXX + +// -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include <stdio.h> +#include <sys/time.h> +#include <sys/times.h> +#include <time.h> +#include <unistd.h> + +#include <salunx.h> + +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif +#ifndef _SV_SALTIMER_HXX +#include <saltimer.hxx> +#endif + +// -=-= SalData =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final void SalData::Timeout() const +{ + if( pTimerProc_ ) + pTimerProc_(); +} + +// -=-= SalXLib =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +final inline void SalXLib::StopTimer() +{ + Timeout_.tv_sec = 0; + Timeout_.tv_usec = 0; + nTimeoutMS_ = 0; +} + +final inline void SalXLib::StartTimer( ULONG nMS ) +{ + gettimeofday( &Timeout_, NULL ); + + nTimeoutMS_ = nMS; + Timeout_.tv_sec += nTimeoutMS_ / 1000; + Timeout_.tv_usec += nTimeoutMS_ ? (nTimeoutMS_ % 1000) * 1000 : 500; + if( Timeout_.tv_usec > 1000000 ) + { + Timeout_.tv_sec++; + Timeout_.tv_usec -= 1000000; + } +} + +// -=-= SalTimer -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +/* static */ final void SalTimer::SetCallback( SALTIMERPROC pProc ) +{ GetSalData()->SetCallback( pProc ); } + + +/* static */ final void SalTimer::Stop() +{ + GetSalData()->GetLib()->StopTimer(); +} + +/* static */ final void SalTimer::Start( ULONG nMS ) +{ + GetSalData()->GetLib()->StartTimer( nMS ); +} + diff --git a/vcl/unx/source/app/sm.cxx b/vcl/unx/source/app/sm.cxx new file mode 100644 index 000000000000..b6552ac490bc --- /dev/null +++ b/vcl/unx/source/app/sm.cxx @@ -0,0 +1,347 @@ +/************************************************************************* + * + * $RCSfile: sm.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): _______________________________________ + * + * + ************************************************************************/ +#include <unistd.h> +#include <stdio.h> + +#include <vos/process.hxx> +#include <vos/security.hxx> + +#ifndef _VCL_SM_HXX +#include <sm.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif +#ifndef _SV_CONFIG_HXX +#include <config.hxx> +#endif + +//#define USE_SM_EXTENSION + +BOOL ICEConnectionObserver::bIsWatching = FALSE; +SmcConn SessionManagerClient::aSmcConnection = NULL; +char* SessionManagerClient::pClientID = NULL; + +static SmProp* pSmProps = NULL; +static SmProp** ppSmProps = NULL; +static int nSmProps = 0; + +static void BuildSmPropertyList() +{ + if( ! pSmProps ) + { + ByteString aExec( SessionManagerClient::getExecName(), gsl_getSystemTextEncoding() ); + + nSmProps = 4; + pSmProps = new SmProp[ nSmProps ]; + + pSmProps[ 0 ].name = "SmCloneCommand"; + pSmProps[ 0 ].type = "SmLISTofARRAY8"; + pSmProps[ 0 ].num_vals = 1; + pSmProps[ 0 ].vals = new SmPropValue; + pSmProps[ 0 ].vals->length = aExec.Len(); + pSmProps[ 0 ].vals->value = strdup( aExec.GetBuffer() ); + + pSmProps[ 1 ].name = "SmProgram"; + pSmProps[ 1 ].type = "SmARRAY8"; + pSmProps[ 1 ].num_vals = 1; + pSmProps[ 1 ].vals = new SmPropValue; + pSmProps[ 1 ].vals->length = aExec.Len(); + pSmProps[ 1 ].vals->value = strdup( aExec.GetBuffer() ); + + pSmProps[ 2 ].name = "SmRestartCommand"; + pSmProps[ 2 ].type = "SmLISTofARRAY8"; + pSmProps[ 2 ].num_vals = 1; + pSmProps[ 2 ].vals = new SmPropValue; + pSmProps[ 2 ].vals->length = aExec.Len(); + pSmProps[ 2 ].vals->value = strdup( aExec.GetBuffer() ); + + NAMESPACE_VOS(OSecurity) aSecurity; + ::rtl::OUString aUserName; + aSecurity.getUserName( aUserName ); + ::rtl::OString aUser( ::rtl::OUStringToOString( aUserName, gsl_getSystemTextEncoding() ) ); + + pSmProps[ 3 ].name = "SmUserID"; + pSmProps[ 3 ].type = "SmARRAY8"; + pSmProps[ 3 ].num_vals = 1; + pSmProps[ 3 ].vals = new SmPropValue; + pSmProps[ 3 ].vals->value = strdup( aUser.getStr() ); + pSmProps[ 3 ].vals->length = strlen( (char *)pSmProps[ 3 ].vals->value ); + + ppSmProps = new SmProp*[ nSmProps ]; + for( int i = 0; i < nSmProps; i++ ) + ppSmProps[ i ] = &pSmProps[i]; + } +} + + +void SessionManagerClient::SaveYourselfProc( + SmcConn connection, + SmPointer client_data, + int save_type, + Bool shutdown, + int interact_style, + Bool fast + ) +{ + BuildSmPropertyList(); +#ifdef USE_SM_EXTENSION + SmcSetProperties( aSmcConnection, nSmProps, ppSmProps ); + SmcSaveYourselfDone( aSmcConnection, True ); +#endif +} + +void SessionManagerClient::DieProc( + SmcConn connection, + SmPointer client_data + ) +{ +#ifdef USE_SM_EXTENSION + SmcCloseConnection( connection, 0, NULL ); +#endif + if( connection == aSmcConnection ) + aSmcConnection = NULL; +} + +void SessionManagerClient::SaveCompleteProc( + SmcConn connection, + SmPointer client_data + ) +{ +} + +void SessionManagerClient::ShutdownCanceledProc( + SmcConn connection, + SmPointer client_data ) +{ +} + +void SessionManagerClient::open() +{ + static SmcCallbacks aCallbacks; + +#ifdef USE_SM_EXTENSION + // erst scharf schalten wenn getestet + + // this is the way Xt does it, so we can too + if( ! aSmcConnection && getenv( "SESSION_MANAGER" ) ) + { + char aErrBuf[1024]; + String aFilename( getenv( "HOME" ) ); + aFilename += "/.so_lastSessionID"; + + ICEConnectionObserver::activate(); + + aCallbacks.save_yourself.callback = SaveYourselfProc; + aCallbacks.save_yourself.client_data = NULL; + aCallbacks.die.callback = DieProc; + aCallbacks.die.client_data = NULL; + aCallbacks.save_complete.callback = SaveCompleteProc; + aCallbacks.save_complete.client_data = NULL; + aCallbacks.shutdown_cancelled.callback = ShutdownCanceledProc; + aCallbacks.shutdown_cancelled.client_data = NULL; + aSmcConnection = SmcOpenConnection( NULL, + NULL, + SmProtoMajor, + SmProtoMinor, + SmcSaveYourselfProcMask | + SmcDieProcMask | + SmcSaveCompleteProcMask | + SmcShutdownCancelledProcMask , + &aCallbacks, + getPreviousSessionID(), + &pClientID, + sizeof( aErrBuf ), + aErrBuf ); +#if defined DEBUG || defined DBG_UTIL + if( ! aSmcConnection ) + fprintf( stderr, "SmcOpenConnection failed: %s\n", aErrBuf ); +#endif + setPreviousSessionID( pClientID ); + } +#endif +} + +void SessionManagerClient::close() +{ + if( aSmcConnection ) + { +#ifdef USE_SM_EXTENSION + SmcCloseConnection( aSmcConnection, 0, NULL ); +#endif + aSmcConnection = NULL; + ICEConnectionObserver::deactivate(); + } +} + + +String SessionManagerClient::getExecName() +{ + static NAMESPACE_VOS( OStartupInfo ) aStartupInfo; + + ::rtl::OUString aExec; + aStartupInfo.getExecutableFile( aExec ); + + int nPos = aExec.search( ::rtl::OUString::createFromAscii( ".bin" ) ); + if( nPos != -1 ) + aExec = aExec.copy( 0, nPos ); + return aExec; +} + + +char* SessionManagerClient::getPreviousSessionID() +{ + static char aID[1024]; + + String aFilename( getenv( "HOME" ), gsl_getSystemTextEncoding() ); + aFilename.AppendAscii( "/.sosessions" ); + + ByteString aExec( getExecName(), gsl_getSystemTextEncoding() ); + aExec = aExec.GetToken( aExec.GetTokenCount( '/' )-1, '/' ); + + Config aConfig( aFilename ); + aConfig.SetGroup( "Sessions" ); + ByteString aSessionID = aConfig.ReadKey( aExec ); + if( aSessionID.Len() ) + { + strncpy( aID, aSessionID.GetBuffer(), sizeof( aID ) ); + return aID; + } + return NULL; +} + +void SessionManagerClient::setPreviousSessionID( const ByteString& rID ) +{ + static char aID[1024]; + + String aFilename( getenv( "HOME" ), gsl_getSystemTextEncoding() ); + aFilename.AppendAscii( "/.sosessions" ); + + ByteString aExec( getExecName(), gsl_getSystemTextEncoding() ); + aExec = aExec.GetToken( aExec.GetTokenCount( '/' )-1, '/' ); + + Config aConfig( aFilename ); + aConfig.SetGroup( "Sessions" ); + aConfig.WriteKey( aExec, rID ); +} + +void ICEConnectionObserver::activate() +{ + if( ! bIsWatching ) + { + bIsWatching = TRUE; +#ifdef USE_SM_EXTENSION + IceAddConnectionWatch( ICEWatchProc, NULL ); +#endif + } +} + +void ICEConnectionObserver::deactivate() +{ + if( bIsWatching ) + { + bIsWatching = FALSE; +#ifdef USE_SM_EXTENSION + IceRemoveConnectionWatch( ICEWatchProc, NULL ); +#endif + } +} + +void ICEConnectionObserver::ICEWatchProc( + IceConn connection, + IcePointer client_data, + Bool opening, + IcePointer* watch_data + ) +{ +#ifdef USE_SM_EXTENSION + if( opening ) + GetSalData()->GetLib()->Insert( IceConnectionNumber( connection ), + connection, + (YieldFunc)Pending, + (YieldFunc)Queued, + (YieldFunc)HandleEvents ); + else + GetSalData()->GetLib()->Remove( IceConnectionNumber( connection ) ); +#endif +} + +int ICEConnectionObserver::Pending( int fd, void* data ) +{ + return 1; +} + +int ICEConnectionObserver::Queued( int fd, void* data ) +{ + return 1; +} + +int ICEConnectionObserver::HandleEvents( int fd, void* data ) +{ +#ifdef USE_SM_EXTENSION + IceProcessMessages( (IceConn)data, NULL, NULL ); +#endif + return 0; +} + diff --git a/vcl/unx/source/app/soicon.cxx b/vcl/unx/source/app/soicon.cxx new file mode 100644 index 000000000000..caf8c6797156 --- /dev/null +++ b/vcl/unx/source/app/soicon.cxx @@ -0,0 +1,502 @@ +/************************************************************************* + * + * $RCSfile: soicon.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_SOICON_CXX + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include <salunx.h> + +#ifndef _SV_SALDISP_HXX +#include <saldisp.hxx> +#endif +#ifndef _SV_SALBMP_HXX +#include <salbmp.hxx> +#endif +#ifndef _SV_SALBTYPE_HXX +#include <salbtype.hxx> +#endif +#ifndef _SV_IMPBMP_HXX +#include <impbmp.hxx> +#endif +#ifndef _SV_BITMAP_HXX +#include <bitmap.hxx> +#endif +#ifndef _SV_BITMAP_HXX +#include <bitmapex.hxx> +#endif +#ifndef _SV_GRAPH_HXX +#include <graph.hxx> +#endif +#ifndef _SV_CVTGRF_HXX +#include <cvtgrf.hxx> +#endif +#ifndef _SV_STRHELPER_HXX +#include <strhelper.hxx> +#endif + +#include <tools/stream.hxx> +#include <tools/string.hxx> + + +#include "so.xpm" + +static Pixmap aAppPixmap = 0, aAppMask = 0; + +static void ConvertXpm( SalDisplay* pDisplay ) +{ + int nWidth, nHeight, nColors, nCharsPerPixel; + XColor *pColors; + char *pColorAlias; + int nElement = 0,nColor = 0,i,nX,nY; + char pColorName[16], pComName[16],pColorString[256]; + BOOL bTransparent = FALSE; + + sscanf( xpmdata[ nElement++ ], "%d%d%d%d", &nWidth, &nHeight, + &nColors, &nCharsPerPixel ); +#if defined DBG_UTIL || defined DEBUG + fprintf( stderr, "ConvertXpm: converting width = %d height = %d ncolors = %d chars_per_pixel = %d\n", nWidth, nHeight, nColors, nCharsPerPixel ); +#endif + nColor = 0; + pColors = new XColor[ nColors ]; + pColorAlias = new char[ nColors * nCharsPerPixel ]; + while( nElement <= nColors ) + { + sscanf( xpmdata[ nElement++ ],"%s %s %s", + pColorName, pComName, pColorString); + if( strncmp( pColorString, "None", 4 ) ) + { + XAllocNamedColor( pDisplay->GetDisplay(), + DefaultColormap( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ), + pColorString, &pColors[nColor], &pColors[nColor] ); + strncpy( &pColorAlias[nColor*nCharsPerPixel], + pColorName, nCharsPerPixel ); + nColor++; + } + } + nColors = nColor+1; + + aAppPixmap = XCreatePixmap( pDisplay->GetDisplay(), + pDisplay->GetRootWindow(), + nWidth, nHeight, + pDisplay->GetRootVisual()->GetDepth() ); + XSetForeground( pDisplay->GetDisplay(), + DefaultGC( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ), + BlackPixel( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ) ); + XFillRectangle( pDisplay->GetDisplay(), aAppPixmap, + DefaultGC( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ), + 0,0,nWidth,nHeight ); + + aAppMask = XCreatePixmap( pDisplay->GetDisplay(), + pDisplay->GetRootWindow(), + nWidth, nHeight, 1 ); + + XGCValues aValues; + aValues.function = GXset; + aValues.foreground = 0xffffffff; + GC aMonoGC = XCreateGC( pDisplay->GetDisplay(), aAppMask, + GCFunction|GCForeground, &aValues ); + + XFillRectangle( pDisplay->GetDisplay(), aAppMask, aMonoGC, + 0,0, nWidth, nHeight ); + aValues.function = GXclear; + XChangeGC( pDisplay->GetDisplay(), aMonoGC, GCFunction, &aValues ); + + for( nY=0; nY < nHeight; nY++ ) + { + char *pRun = xpmdata[ nElement+nY ]; + for( nX=0; nX < nWidth; nX++ ) + { + // get color number + nColor = 0; + while( nColor < nColors && + strncmp( pRun, &pColorAlias[nColor*nCharsPerPixel], + nCharsPerPixel ) ) + nColor++; + if( nColor < nColors ) + { + XSetForeground( pDisplay->GetDisplay(), + DefaultGC( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ), + pColors[ nColor ].pixel ); + XDrawPoint( pDisplay->GetDisplay(), + aAppPixmap, + DefaultGC( pDisplay->GetDisplay(), + pDisplay->GetScreenNumber() ), + nX, nY ); + + } + else + { + bTransparent = TRUE; + XDrawPoint( pDisplay->GetDisplay(), + aAppMask, aMonoGC, nX, nY ); + } + pRun += nCharsPerPixel; + } + } + delete pColors; + delete pColorAlias; + XFreeGC( pDisplay->GetDisplay(), aMonoGC ); + + if( ! bTransparent ) + { +#if defined DBG_UTIL || defined DEBUG + fprintf( stderr, "ConvertXpm: keine Transparenz -> keine Maske\n" ); +#endif + XFreePixmap( pDisplay->GetDisplay(), aAppMask ); + aAppMask = 0; + } +} + +Pixmap GetAppIconPixmap( SalDisplay *pDisplay ) +{ + if( ! aAppPixmap ) + ConvertXpm( pDisplay ); + return aAppPixmap; +} + +Pixmap GetAppIconMask( SalDisplay *pDisplay ) +{ + if( ! aAppPixmap ) + ConvertXpm( pDisplay ); + return aAppMask; +} + +static void NextLine( SvStream& rFile, ByteString& rLine, BOOL bXpm2Mode ) +{ + if( bXpm2Mode ) + { + rFile.ReadLine( rLine ); + } + else + { + do + { + rFile.ReadLine( rLine ); + rLine = rLine.GetToken( 1, '"' ); + if( rLine.Len() ) + rLine = rLine.GetToken( 0, '"' ); + } while( ! ( rLine.Len() || rFile.IsEof() ) ); + } +} + +BOOL ReadXBMFile( Display* pDisplay, const String& rFile, SalBitmap*& rpBmp ) +{ + SvFileStream aFile( rFile, STREAM_READ ); + int nBytes = 0; + int nWidth= -1, nHeight=-1; + BOOL bSuccess = FALSE; + + rpBmp = NULL; + + // read in bitmap file ( cause XReadBitmapFileData not present + // in Solaris 2.5.1) + if( ! aFile.IsOpen() ) + return FALSE; + + ByteString aLine; + + while( ( nWidth < 0 || nHeight < 0 ) && ! aFile.IsEof() ) + { + aFile.ReadLine( aLine ); + aLine = WhitespaceToSpace( aLine ); + + if( aLine.GetChar(0) == '#' ) + { + if( aLine.Search( "_width" ) != STRING_NOTFOUND ) + nWidth = aLine.GetToken( ' ', 2 ).ToInt32(); + else if( aLine.Search( "_height" ) != STRING_NOTFOUND ) + nHeight = aLine.GetToken( ' ', 2 ).ToInt32(); + } + } + + if( nWidth <= 0 || nHeight <= 0 ) + return FALSE; + + BitmapPalette aPal( 2 ); + const Size aSize( nWidth, nHeight ); + + aPal[ 0 ] = BitmapColor( 0, 0, 0 ); + aPal[ 1 ] = BitmapColor( 0xff, 0xff, 0xff ); + + rpBmp = new SalBitmap; + rpBmp->Create( aSize, 1, aPal ); + + BitmapBuffer* pBmpBuf = rpBmp->AcquireBuffer( FALSE ); + BYTE* pBmpScan = pBmpBuf->mpBits + ( nHeight - 1 ) * pBmpBuf->mnScanlineSize; + long nX = 0, nY = 0; + + aFile.Seek( 0L ); + + do + { + int nPos; + + aFile.ReadLine( aLine ); + aLine.ToUpperAscii(); + + while( ( ( nPos = aLine.Search( "0X" ) ) != STRING_NOTFOUND ) && ( nY < nHeight ) ) + { + BYTE cData = 0; + + for( int i = 0; i < 2; i++ ) + { + cData *= 16; + char c = aLine.GetChar( nPos + 2 + i); + + if( c >= '0' && c <= '9' ) + cData += (unsigned char)( c - '0' ); + else if( c >= 'A' && c <= 'F' ) + cData += (unsigned char)( c - 'A' + 10 ); + } + + *pBmpScan++ += ( ( cData & 1 ) << 7 ) | ( ( cData & 2 ) << 5 ) | + ( ( cData & 4 ) << 3 ) | ( ( cData & 8 ) << 1 ) | + ( ( cData & 16 ) >> 1 ) | ( ( cData & 32 ) >> 3 ) | + ( ( cData & 64 ) >> 5 ) | ( ( cData& 128 ) >> 7 ); + + if( ( nX += 8 ) >= nWidth ) + nX = 0, pBmpScan = pBmpBuf->mpBits + ( nHeight - ++nY - 1 ) * pBmpBuf->mnScanlineSize; + + aLine.Erase( 0, nPos + 5 ); + } + } + while( !aFile.IsEof() && ( nY < nHeight ) ); + + rpBmp->ReleaseBuffer( pBmpBuf, FALSE ); + + return TRUE; +} + +//------------------------------------------------------------------------------ + +BOOL ReadXPMFile( Display* pDisplay, const String& rFile, + SalBitmap*& rpBmp, SalBitmap*& rpMsk ) +{ + SvFileStream aFile( rFile, STREAM_READ ); + ByteString aColorName, aColorString, aLine; + int nWidth, nHeight, nColors, nCharsPerPixel; + int nElement = 0,nColor = 0, i, nX, nY; + UINT8* pColorTable; + char* pColorAlias; + BOOL bTransparent = FALSE; + BOOL bXpm2Mode = FALSE; + + rpBmp = rpMsk = NULL; + + if( ! aFile.IsOpen() ) + return FALSE; + + aFile.ReadLine( aLine ); + aLine = WhitespaceToSpace( aLine ); + + if( aLine.CompareTo( "! XPM", 5 ) == COMPARE_EQUAL ) + bXpm2Mode = TRUE; + else + { + bXpm2Mode = FALSE; + aFile.Seek( 0L ); + } + + NextLine( aFile, aLine, bXpm2Mode ); + + nWidth = GetCommandLineToken( 0, aLine ).ToInt32(); + nHeight = GetCommandLineToken( 1, aLine ).ToInt32(); + nColors = GetCommandLineToken( 2, aLine ).ToInt32(); + nCharsPerPixel = GetCommandLineToken( 3, aLine ).ToInt32(); + + if( nWidth == 0 || nHeight == 0 || nColors == 0 || nCharsPerPixel == 0 ) + { + // not really an xpm despite the name => try to load it via GraphicConverter + aFile.Seek( 0L ); + Graphic aGraphic; + GraphicConverter::Import( aFile, aGraphic ); + + BitmapEx aBitmapEx( aGraphic.GetBitmapEx() ); + + if( aBitmapEx.GetSizePixel().Width() == 0 || aBitmapEx.GetSizePixel().Height() == 0 ) + return FALSE; + + const Bitmap aBmp( aBitmapEx.GetBitmap() ); + const Bitmap aMsk( aBitmapEx.GetMask() ); + + if( !!aBmp ) + { + rpBmp = new SalBitmap; + rpBmp->Create( *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap() ); + } + + if( !!aMsk ) + { + rpMsk = new SalBitmap; + rpMsk->Create( *aMsk.ImplGetImpBitmap()->ImplGetSalBitmap() ); + } + + return TRUE; + } + + nColor = 0; + pColorTable = new UINT8[ (nColors+1) * 3 ]; + pColorAlias = new char[ nColors * nCharsPerPixel ]; + XColor aExactColor; + aExactColor.flags = DoRed | DoGreen | DoBlue; + while( nColors ) + { + NextLine( aFile, aLine, bXpm2Mode ); + // might be a space as color variable + aColorName = aLine.Copy( 0, nCharsPerPixel ); + aLine.Erase( 0, nCharsPerPixel ); + aLine = WhitespaceToSpace( aLine ); + + int nPos = aLine.Search( " c " ); + if( nPos == STRING_NOTFOUND && aLine.CompareIgnoreCaseToAscii( "c ", 2 ) == COMPARE_EQUAL ) + nPos = 2; + else + nPos += 3; + aColorString = aLine.Copy( nPos ); + + if( aColorString.CompareIgnoreCaseToAscii( "none", 4 ) != COMPARE_EQUAL ) + { + XParseColor( pDisplay, + DefaultColormap( pDisplay, + DefaultScreen( pDisplay ) ), + aColorString.GetBuffer(), + &aExactColor ); + pColorTable[ nColor * 3 +2 ] = (UINT8)(aExactColor.red / 256 ); + pColorTable[ nColor * 3 +1 ] = (UINT8)(aExactColor.green / 256 ); + pColorTable[ nColor * 3 ] = (UINT8)(aExactColor.blue / 256 ); + strncpy( pColorAlias + nColor*nCharsPerPixel, + aColorName.GetBuffer(), nCharsPerPixel ); + nColor++; + } + nColors--; + } + pColorTable[ 3*nColor ] = pColorTable[ 3*nColor+1 ] = + pColorTable[ 3*nColor+2 ] = 0; + nColors = nColor; + + // read SalBitmap's + BitmapPalette aPal( 2 ); + const Size aSize( nWidth, nHeight ); + + aPal[ 0 ] = BitmapColor( 0, 0, 0 ); + aPal[ 1 ] = BitmapColor( 0xff, 0xff, 0xff ); + + rpBmp = new SalBitmap; + rpBmp->Create( aSize, 24, aPal ); + BitmapBuffer* pBmpBuf = rpBmp->AcquireBuffer( FALSE ); + + rpMsk = new SalBitmap; + rpMsk->Create( aSize, 1, aPal ); + BitmapBuffer* pMskBuf = rpMsk->AcquireBuffer( FALSE ); + + for( nY=0; nY < nHeight; nY++ ) + { + NextLine( aFile, aLine, bXpm2Mode ); + + const char* pRun = aLine.GetBuffer(); + BYTE* pBmpScan = pBmpBuf->mpBits + pBmpBuf->mnScanlineSize * ( nHeight - nY - 1 ); + BYTE* pMskScan = pMskBuf->mpBits + pMskBuf->mnScanlineSize * ( nHeight - nY - 1 ); + UINT8 nMaskByte = 0; + + for( nX = 0; nX < nWidth; nX++ ) + { + // get color number + for( nColor=0; nColor < nColors; nColor++ ) + { + if( ! strncmp( pRun, pColorAlias + nColor*nCharsPerPixel, + nCharsPerPixel ) ) + break; + } + + long nIndex = nColor * 3; + + *pBmpScan++ = pColorTable[ nIndex++ ]; + *pBmpScan++ = pColorTable[ nIndex++ ]; + *pBmpScan++ = pColorTable[ nIndex ]; + + if( nColor == nColors ) + nMaskByte |= ( 1 << ( 7 - ( nX & 7 ) ) ); + + pRun += nCharsPerPixel; + + if( ( ( nX & 7 ) == 7 ) || ( nX == nWidth - 1 ) ) + { + *pMskScan++ = nMaskByte; + nMaskByte = 0; + } + } + } + + rpBmp->ReleaseBuffer( pBmpBuf, FALSE ); + rpMsk->ReleaseBuffer( pMskBuf, FALSE ); + delete[] pColorTable; + delete[] pColorAlias; + + return TRUE; +} |