summaryrefslogtreecommitdiff
path: root/vcl/unx/source/app
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/source/app')
-rw-r--r--vcl/unx/source/app/i18n_cb.cxx547
-rw-r--r--vcl/unx/source/app/i18n_ic.cxx686
-rw-r--r--vcl/unx/source/app/i18n_im.cxx332
-rw-r--r--vcl/unx/source/app/i18n_wrp.cxx293
-rw-r--r--vcl/unx/source/app/i18n_xkb.cxx195
-rw-r--r--vcl/unx/source/app/keysymnames.cxx545
-rw-r--r--vcl/unx/source/app/makefile.mk142
-rw-r--r--vcl/unx/source/app/saldata.cxx854
-rw-r--r--vcl/unx/source/app/saldisp.cxx3653
-rw-r--r--vcl/unx/source/app/salinst.cxx346
-rw-r--r--vcl/unx/source/app/salsys.cxx200
-rw-r--r--vcl/unx/source/app/saltimer.cxx129
-rw-r--r--vcl/unx/source/app/sm.cxx347
-rw-r--r--vcl/unx/source/app/soicon.cxx502
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;
+}