summaryrefslogtreecommitdiff
path: root/vcl/os2/source
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/os2/source')
-rw-r--r--vcl/os2/source/app/makefile.mk59
-rw-r--r--vcl/os2/source/app/printf.c284
-rw-r--r--vcl/os2/source/app/salinfo.cxx182
-rw-r--r--vcl/os2/source/app/salinst.cxx863
-rw-r--r--vcl/os2/source/app/sallang.cxx117
-rw-r--r--vcl/os2/source/app/salshl.cxx123
-rw-r--r--vcl/os2/source/app/saltimer.cxx140
-rw-r--r--vcl/os2/source/gdi/makefile.mk56
-rw-r--r--vcl/os2/source/gdi/os2layout.cxx1056
-rw-r--r--vcl/os2/source/gdi/salbmp.cxx737
-rw-r--r--vcl/os2/source/gdi/salgdi.cxx1044
-rw-r--r--vcl/os2/source/gdi/salgdi2.cxx786
-rw-r--r--vcl/os2/source/gdi/salgdi3.cxx1769
-rw-r--r--vcl/os2/source/gdi/salprn.cxx1833
-rw-r--r--vcl/os2/source/gdi/salvd.cxx200
-rw-r--r--vcl/os2/source/src/airbrush.ptrbin0 -> 2106 bytes
-rwxr-xr-xvcl/os2/source/src/ase.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asn.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asne.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asns.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asnswe.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asnw.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/ass.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asse.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/assw.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/asw.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/aswe.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/chain.ptrbin0 -> 16 bytes
-rw-r--r--vcl/os2/source/src/chainnot.ptrbin0 -> 16 bytes
-rw-r--r--vcl/os2/source/src/chart.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/copydata.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/copydlnk.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/copyf.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/copyf2.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/copyflnk.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/crook.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/crop.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/cross.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/darc.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/data.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dbezier.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dcapt.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dcirccut.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dconnect.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dellipse.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/detectiv.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dfree.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dline.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dpie.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dpolygon.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/drect.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/dtext.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/fill.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/hand.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/help.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/hshear.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/hsizebar.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/hsplit.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/linkdata.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/linkf.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/magnify.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/makefile.mk111
-rw-r--r--vcl/os2/source/src/mirror.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/move.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/movebw.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/movedata.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/movedlnk.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/movef.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/movef2.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/moveflnk.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/movept.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/nullptr.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/pen.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/pivotcol.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/pivotfld.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/pivotrow.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/pntbrsh.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/src/refhand.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/rotate.ptrbin0 -> 1191 bytes
-rw-r--r--vcl/os2/source/src/salsrc.rc108
-rw-r--r--vcl/os2/source/src/sd.icobin0 -> 3344 bytes
-rw-r--r--vcl/os2/source/src/sd2.icobin0 -> 5604 bytes
-rw-r--r--vcl/os2/source/src/tblsele.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/src/tblsels.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/src/tblselse.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/src/tblselsw.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/src/tblselw.ptrbin0 -> 2106 bytes
-rwxr-xr-xvcl/os2/source/src/timemove.ptrbin0 -> 1190 bytes
-rwxr-xr-xvcl/os2/source/src/timesize.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/vshear.ptrbin0 -> 1201 bytes
-rw-r--r--vcl/os2/source/src/vsizebar.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/vsplit.ptrbin0 -> 1190 bytes
-rw-r--r--vcl/os2/source/src/vtext.ptrbin0 -> 2106 bytes
-rw-r--r--vcl/os2/source/window/makefile53
-rw-r--r--vcl/os2/source/window/makefile.mk47
-rw-r--r--vcl/os2/source/window/salframe.cxx3774
-rw-r--r--vcl/os2/source/window/salmenu.cxx132
-rw-r--r--vcl/os2/source/window/salobj.cxx568
98 files changed, 14042 insertions, 0 deletions
diff --git a/vcl/os2/source/app/makefile.mk b/vcl/os2/source/app/makefile.mk
new file mode 100644
index 000000000000..80aeb7f568fb
--- /dev/null
+++ b/vcl/os2/source/app/makefile.mk
@@ -0,0 +1,59 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=SV
+TARGET=salapp
+
+# --- Settings -----------------------------------------------------
+
+#.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+#.INCLUDE : sv.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+
+# --- Files --------------------------------------------------------
+
+YD00_CXXFILES=\
+ salshl.cxx \
+ salinst.cxx \
+ sallang.cxx \
+ saltimer.cxx \
+ salsys.cxx
+
+SLOFILES= $(SLO)$/salshl.obj \
+ $(SLO)$/printf.obj \
+ $(SLO)$/salinfo.obj \
+ $(SLO)$/salinst.obj \
+ $(SLO)$/sallang.obj \
+ $(SLO)$/saltimer.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/os2/source/app/printf.c b/vcl/os2/source/app/printf.c
new file mode 100644
index 000000000000..7cfcf4efc559
--- /dev/null
+++ b/vcl/os2/source/app/printf.c
@@ -0,0 +1,284 @@
+/* ----------------------------------------------------------------- */
+/* PRINTF: diverts PRINTF calls to an OS/2 Named Queue */
+/* Copyright (c) IBM Corporation, 1991, 1992 */
+/* ----------------------------------------------------------------- */
+/* This version for OS/2 2.x, 32-bit programs. Mike Cowlishaw */
+/* */
+/* This routine, when linked into an .EXE instead of the usual C */
+/* runtime, sends the edited result string to a named queue (if */
+/* it exists). If the queue does not exist, then all printf data */
+/* are discarded (ignored). */
+/* */
+/* The result string is accumulated until a line feed (LF) character */
+/* is received; the whole line is then sent to the queue. Lines are */
+/* automatically broken at a set (tailorable) length, if necessary. */
+/* */
+/* This routine may be tailored by altering the #defines at the */
+/* top: */
+/* */
+/* PRINTFID - An ID string that is prefixed to each line of */
+/* data before being sent to the queue. This */
+/* can be any string, or the null string. */
+/* PRINTFMAXLEN - Maximum length of string that can be formatted */
+/* in a single call. */
+/* Results are unpredictable if this length is */
+/* exceeded. Default is 250. */
+/* PRINTFLINELEN - Maximum length of a line that will be sent. */
+/* This excludes the prefix and its blank. If the */
+/* calls to printf cause a line to be generated */
+/* that is longer than this, the line will be */
+/* broken at this point. */
+/* PRINTFTHREADS - Maximum number of threads expected. This may */
+/* need to be increased if the process limitation */
+/* is removed, or you can save a little storage */
+/* by decreasing it. PRINTFs from threads larger */
+/* than this number are ignored. */
+/* PRINTFQNAME - The name of the public queue that the result */
+/* is to be sent to. Normally '\QUEUES\PRINTF32'. */
+/* Note that the \QUEUES\ part is required. */
+/* */
+/* Returns: */
+/* n: Count of data characters, if successfully received */
+/* 0: If no queue existed (i.e., no server) */
+/* <0: An error occurred (e.g., out of memory) */
+/* */
+/* Restrictions: */
+/* 1. Total length of data (length of PRINTFID, + PRINTFMAXLEN) */
+/* must be less than 32K-1. */
+/* 2. This has only been tested under IBM C Set/2 compiler. It */
+/* may need modification for other compilers. */
+/* 3. This version uses a static array to point to the per-thread */
+/* data. The code could be made read-only by hanging this */
+/* array (and the other static information) off a system-owned */
+/* anchor of some kind. */
+/* 4. To use PRINTF within other than the main thread in a */
+/* program, that thread must be started with _beginthread */
+/* (not DosCreateThread). This restriction is a consequence of */
+/* the use of C library routines (sprintf) in PRINTF, and may */
+/* not apply to all compilers. */
+/* 5. If the last PRINTF done by a thread does not end in '\n' */
+/* then the final part-line may be lost, or appear later. */
+/* */
+/* Protocol: */
+/* PRINTF writes its data to the named queue using the following */
+/* protocol: */
+/* Address -- Holds the address of the string to be sent. This */
+/* is a 0-terminated string) starting at offset 0. */
+/* Length -- The length of the data, including terminator. */
+/* A negative length indicates a BELL in the data. */
+/* Request -- Timestamp (when queue was written) in C long */
+/* integer format (as returned by time()). */
+/* This may be 0L if not required. */
+/* */
+/* Notes: */
+/* 1. PMPRINTF uses a queue and shared memory messages because: */
+/* (a) It makes collection at the receiving end very easy. */
+/* (b) I wanted to experiment with queues and shared memory. */
+/* This make not be the most cost-effective method. */
+/* 2. Typical IBM C Set/2 compiler invocation: */
+/* icc /c /Gm /O+ /Q /J /Kabgop */
+/* If you get linking errors (duplicate symbols, etc.), try */
+/* recompiling PRINTF.C with the same options as you use for */
+/* your main program. */
+/* 3. PRINTF sends the timestamp across the queue as a GMT long */
+/* integer, the result from a call to the C function time(). */
+/* This will only be correct if the environment variable TZ has */
+/* been set (e.g., TZ=EST5EDT), or you are in the same time */
+/* zone as the default for your compiler. */
+/* For more information, see the tzset() function description */
+/* in your C compiler manual. */
+
+/* ----- Customization variables ----- */
+#define PRINTFID ""
+#define PRINTFMAXLEN 300
+#define PRINTFLINELEN 100
+#define PRINTFTHREADS 54
+#define PRINTFQNAME "\\QUEUES\\PRINTF32"
+
+/* ----- Includes and externals ----- */
+#include <stdlib.h> /* standard C functions */
+#include <stddef.h> /* .. */
+#include <string.h> /* .. */
+#include <time.h> /* .. */
+#include <stdarg.h> /* .. */
+#include <stdio.h> /* (needed to pick up real name) */
+#define INCL_DOS /* Operating system definitions */
+#include <os2.h> /* For OS/2 functions */
+
+#define max(a,b) (a>b ? a : b)
+
+/* ----- Local defines ----- */
+#define PRINTFIDSIZE sizeof(PRINTFID)
+#define PRINTFMAXBUF PRINTFIDSIZE+PRINTFLINELEN
+
+/* ----- Per-thread output buffer and current indices into line ---- */
+struct perthread {
+ LONG lineindex; /* where next char */
+ LONG tidemark; /* rightmost char */
+ int bell; /* TRUE if line has bell */
+ UCHAR line[PRINTFMAXBUF]; /* accumulator */
+ };
+
+/* ----- Local static variables ----- */
+static ULONG ourpid=0; /* our process ID */
+static ULONG servepid=0; /* process IDs of the server */
+static HQUEUE qhandle=0; /* handle for the queue */
+static struct perthread *tps[PRINTFTHREADS+1]; /* -> per-thread data */
+
+/* ----- Local subroutine ----- */
+static int printf_(struct perthread *);
+
+/* ----------------------------------------------------------------- */
+/* The "printf" function. Note this has a variable number of */
+/* arguments. */
+/* ----------------------------------------------------------------- */
+int debug_printf(const char *f, ...)
+ {
+ TIB *ptib; /* process/thread id structures */
+ PIB *ppib; /* .. */
+ TID ourtid; /* thread ID */
+ struct perthread *tp; /* pointer to per-thread data */
+ int rc; /* returncode */
+ ULONG urc; /* returncode */
+
+ urc=DosOpenQueue(&servepid, &qhandle, PRINTFQNAME); /* Open the Q */
+ /* Non-0 RC means Q does not exist or cannot be opened */
+ if (urc==343) return 0; /* queue does not exist, so quit */
+ if (urc!=0) return -1; /* report any other error */
+
+ /* First determine our thread ID (and hence get access to the */
+ /* correct per-thread data. If the per-thread data has not been */
+ /* allocated, then allocate it now. It is never freed, once */
+ /* allocated, as PRINTF is not notified of end-of-thread. */
+ DosGetInfoBlocks(&ptib,&ppib); /* get process/thread info */
+ ourtid=ptib->tib_ptib2->tib2_ultid; /* .. and copy TID */
+ if (ourtid>PRINTFTHREADS) /* too many threads .. */
+ return 0; /* .. so quit, quietly */
+ tp=tps[ourtid]; /* copy to local pointer */
+ if (tp==NULL) { /* uninitialized (NULL=0) */
+ /* allocate a per-thread structure */
+ tp=(struct perthread *)malloc(sizeof(struct perthread));
+ if (tp==NULL) return -1; /* out of memory -- return error */
+ tps[ourtid]=tp; /* save for future calls */
+ strcpy(tp->line,PRINTFID); /* initialize: line.. */
+ tp->lineindex=PRINTFIDSIZE-1; /* ..where next char */
+ tp->tidemark =PRINTFIDSIZE-2; /* ..rightmost char */
+ tp->bell=FALSE; /* ..if line has bell */
+ if (ourpid==0) ourpid=ppib->pib_ulpid; /* save PID for all to use */
+ }
+
+ { /* Block for declarations -- only needed if queue exists, etc. */
+ LONG count; /* count of characters formatted */
+ UCHAR buffer[PRINTFMAXLEN+1]; /* formatting area */
+ LONG i, newind; /* work */
+ UCHAR ch; /* .. */
+ va_list argptr; /* -> variable argument list */
+
+ va_start(argptr, f); /* get pointer to argument list */
+ count=vsprintf(buffer, f, argptr);
+ va_end(argptr); /* done with variable arguments */
+
+ if (count<0) return count-1000;/* bad start */
+
+ if (count>PRINTFMAXLEN) {
+ /* Disaster -- we are probably "dead", but just in case we */
+ /* are not, carry on with truncated data. */
+ count=PRINTFMAXLEN;
+ }
+ buffer[count]='\0'; /* ensure terminated */
+ /* OK, ready to go with the data now in BUFFER */
+ /* We copy from the formatted string to the output (line) buffer, */
+ /* taking note of certain control characters and sending a line */
+ /* the queue whenever we see a LF control, or when the line */
+ /* fills (causing a forced break). */
+ for (i=0; ; i++) {
+ ch=buffer[i]; if (!ch) break;
+ switch(ch) {
+ case '\r': /* carriage return */
+ tp->lineindex=PRINTFIDSIZE-1; /* back to start of line */
+ break;
+ case '\n': /* new line */
+ case '\f': /* form feed */
+ rc=printf_(tp); /* print a line */
+ if (rc!=0) return rc; /* error */
+ break;
+ case '\t': /* tab */
+ newind=tp->lineindex-PRINTFIDSIZE+1; /* offset into data */
+ newind=tp->lineindex+5-newind%5; /* new index requested */
+ if (newind>=PRINTFMAXBUF) newind=PRINTFMAXBUF; /* clamp */
+ for (; tp->lineindex<newind; tp->lineindex++) {
+ if (tp->lineindex>tp->tidemark) { /* beyond current end */
+ tp->line[tp->lineindex]=' '; /* add space */
+ tp->tidemark=tp->lineindex;
+ }
+ }
+ break;
+ case '\v': /* vertical tab */
+ /* ignore it */
+ break;
+ case '\b': /* backspace */
+ tp->lineindex=max(tp->lineindex-1,PRINTFIDSIZE);
+ break;
+ case '\a': /* alert (bell) */
+ tp->bell=TRUE;
+ break;
+ default: /* ordinary character */
+ tp->line[tp->lineindex]=ch;
+ if (tp->lineindex>tp->tidemark) /* is rightmost.. */
+ tp->tidemark=tp->lineindex;
+ tp->lineindex++; /* step for next */
+ } /* switch */
+ if (tp->lineindex>=PRINTFMAXBUF) {
+ rc=printf_(tp); /* print a line */
+ if (rc!=0) return rc; /* error */
+ }
+
+ } /* copy loop */
+ return count; /* all formatted data processed */
+ } /* block */
+ } /* printf */
+
+/* ----- printf_(tp) -- Local subroutine to send a line ------------ */
+/* A line has been completed (or overflowed): write it to the queue. */
+int printf_(struct perthread *tp) /* pointer to per-thread data */
+ {
+ ULONG urc; /* unsigned returncode */
+ PSZ pszTo, pszFrom; /* character pointers */
+ PVOID addr; /* address of output data */
+ long size; /* total size of output data */
+ time_t timenow; /* holds current time */
+
+ tp->line[tp->tidemark+1]='\0'; /* add terminator */
+ size=tp->tidemark+2; /* total length of data */
+
+ /* Get some shared memory that can be given away */
+ urc=DosAllocSharedMem(&addr, NULL, (unsigned)size,
+ OBJ_GIVEABLE|PAG_WRITE|PAG_COMMIT);
+ if (urc!=0) return -2; /* error */
+
+ pszTo=addr; /* copy for clarity */
+ pszFrom=&(tp->line[0]); /* pointer to source */
+ strcpy(pszTo,pszFrom); /* copy the string to shared memory */
+
+ if (ourpid!=servepid) { /* (no giveaway needed if to self) */
+ urc=DosGiveSharedMem(addr, servepid, PAG_READ); /* give access */
+ if (urc!=0) return -3;} /* error */
+
+ /* Write the selector, size, and timestamp to the queue */
+ if (tp->bell) size=-size; /* BELL passed by negation */
+ time(&timenow); /* optional - else use 0 */
+ urc=DosWriteQueue(qhandle, /* handle */
+ (unsigned)timenow, /* 'request' (timestamp) */
+ (unsigned)size, /* 'length' (length/bell) */
+ addr, /* 'address' (address) */
+ 0); /* priority (FIFO if enabled) */
+ if (urc!=0) return -4; /* error */
+ if (ourpid!=servepid) { /* if given away.. */
+ urc=DosFreeMem(addr); /* .. *we* are done with it */
+ if (urc!=0) return -5;} /* error */
+ /* Reset the line buffer and indices */
+ tp->lineindex=PRINTFIDSIZE-1; /* where next char */
+ tp->tidemark =PRINTFIDSIZE-2; /* rightmost char */
+ tp->bell =FALSE; /* true if line has bell */
+ return 0; /* success! */
+ } /* printf_ */
diff --git a/vcl/os2/source/app/salinfo.cxx b/vcl/os2/source/app/salinfo.cxx
new file mode 100644
index 000000000000..e48aacd4c521
--- /dev/null
+++ b/vcl/os2/source/app/salinfo.cxx
@@ -0,0 +1,182 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_PM
+#define INCL_DOS
+#define INCL_GPI
+#include <svpm.h>
+
+#include <tools/string.hxx>
+#include <salsys.h>
+#include <salframe.h>
+#include <salinst.h>
+#include "saldata.hxx"
+#include <tools/debug.hxx>
+#include <vcl/svdata.hxx>
+#include <rtl/ustrbuf.hxx>
+#include "vcl/window.hxx"
+
+#ifndef _SV_SALGTYPE_HXX
+//#include <salgtype.hxx>
+#endif
+
+#define CHAR_POINTER(THE_OUSTRING) ::rtl::OUStringToOString (THE_OUSTRING, RTL_TEXTENCODING_UTF8).pData->buffer
+
+class Os2SalSystem : public SalSystem
+{
+public:
+ Os2SalSystem() {}
+ virtual ~Os2SalSystem();
+
+ virtual unsigned int GetDisplayScreenCount();
+ virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen );
+ //virtual bool GetSalSystemDisplayInfo( DisplayInfo& rInfo );
+
+ virtual bool IsMultiDisplay();
+ virtual unsigned int GetDefaultDisplayNumber();
+ virtual Rectangle GetDisplayWorkAreaPosSizePixel( unsigned int nScreen );
+ virtual rtl::OUString GetScreenName( unsigned int nScreen );
+
+ virtual int ShowNativeMessageBox( const String& rTitle,
+ const String& rMessage,
+ int nButtonCombination,
+ int nDefaultButton);
+};
+
+SalSystem* Os2SalInstance::CreateSalSystem()
+{
+ return new Os2SalSystem();
+}
+
+Os2SalSystem::~Os2SalSystem()
+{
+}
+
+// -----------------------------------------------------------------------
+#if 0
+bool Os2SalSystem::GetSalSystemDisplayInfo( DisplayInfo& rInfo )
+{
+ HDC hDC;
+ if( hDC = WinQueryWindowDC(HWND_DESKTOP) )
+ {
+ LONG bitCount;
+ DevQueryCaps(hDC, CAPS_COLOR_BITCOUNT, CAPS_COLOR_BITCOUNT, &bitCount);
+ rInfo.nWidth = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
+ rInfo.nHeight = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
+ rInfo.nDepth = bitCount;
+ return true;
+ }
+ else
+ return false;
+}
+#endif
+
+unsigned int Os2SalSystem::GetDisplayScreenCount()
+{
+ return 1;
+}
+
+Rectangle Os2SalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen )
+{
+ Rectangle aRet;
+ aRet = Rectangle( Point(), Point( WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ),
+ WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) ) );
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+/* We have to map the button identifier to the identifier used by the Os232
+ Platform SDK to specify the default button for the MessageBox API.
+ The first dimension is the button combination, the second dimension
+ is the button identifier.
+*/
+static int DEFAULT_BTN_MAPPING_TABLE[][8] =
+{
+ // Undefined OK CANCEL ABORT RETRY IGNORE YES NO
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK_CANCEL
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //ABORT_RETRY_IGNO
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO_CANCEL
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO
+ { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 } //RETRY_CANCEL
+};
+
+static int COMBI_BTN_MAPPING_TABLE[] =
+{
+ MB_OK, MB_OKCANCEL, MB_ABORTRETRYIGNORE, MB_YESNO, MB_YESNOCANCEL, MB_RETRYCANCEL
+};
+
+int Os2SalSystem::ShowNativeMessageBox(const String& rTitle, const String& rMessage, int nButtonCombination, int nDefaultButton)
+{
+ DBG_ASSERT( nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
+ nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
+ nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
+ nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, "Invalid arguments!" );
+
+ int nFlags = MB_APPLMODAL | MB_WARNING | COMBI_BTN_MAPPING_TABLE[nButtonCombination];
+
+ if (nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
+ nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
+ nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
+ nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO)
+ nFlags |= DEFAULT_BTN_MAPPING_TABLE[nButtonCombination][nDefaultButton];
+
+ //#107209 hide the splash screen if active
+ ImplSVData* pSVData = ImplGetSVData();
+ if (pSVData->mpIntroWindow)
+ pSVData->mpIntroWindow->Hide();
+
+ return WinMessageBox(
+ HWND_DESKTOP, HWND_DESKTOP,
+ (PSZ)CHAR_POINTER(rMessage),
+ (PSZ)CHAR_POINTER(rTitle),
+ 0, nFlags);
+}
+
+
+unsigned int Os2SalSystem::GetDefaultDisplayNumber()
+{
+ return 0;
+}
+
+bool Os2SalSystem::IsMultiDisplay()
+{
+ return false;
+}
+
+Rectangle Os2SalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen )
+{
+ return GetDisplayScreenPosSizePixel( nScreen );
+}
+
+rtl::OUString Os2SalSystem::GetScreenName( unsigned int nScreen )
+{
+ rtl::OUStringBuffer aBuf( 32 );
+ aBuf.appendAscii( "VirtualScreen " );
+ aBuf.append( sal_Int32(nScreen) );
+ return aBuf.makeStringAndClear();
+}
diff --git a/vcl/os2/source/app/salinst.cxx b/vcl/os2/source/app/salinst.cxx
new file mode 100644
index 000000000000..b08a9769ccf4
--- /dev/null
+++ b/vcl/os2/source/app/salinst.cxx
@@ -0,0 +1,863 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSPROCESS
+
+#include <string.h>
+#include <svpm.h>
+#include <process.h>
+
+#define _SV_SALINST_CXX
+
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+#include <tools/debug.hxx>
+
+#ifndef _SV_SALIDS_HRC
+#include <salids.hrc>
+#endif
+#include <vcl/salatype.hxx>
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salframe.h>
+#include <salobj.h>
+#include <saltimer.h>
+#include <salbmp.h>
+#include <vcl/salimestatus.hxx>
+#include <vcl/timer.hxx>
+#include <tools/solarmutex.hxx>
+
+// =======================================================================
+
+void SalAbort( const XubString& rErrorText )
+{
+ ImplFreeSalGDI();
+
+ if( !rErrorText.Len() )
+ fprintf( stderr, "Application Error " );
+ else
+ fprintf( stderr, "%s ",
+ ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
+ abort();
+}
+
+// =======================================================================
+
+ULONG GetCurrentThreadId()
+{
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks( &pptib, &pppib );
+ return pptib->tib_ptib2->tib2_ultid;
+}
+
+// =======================================================================
+
+MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 );
+
+// =======================================================================
+
+class SalYieldMutex : public vos::OMutex
+{
+public:
+ Os2SalInstance* mpInstData;
+ ULONG mnCount;
+ ULONG mnThreadId;
+
+public:
+ SalYieldMutex( Os2SalInstance* pInstData );
+
+ virtual void SAL_CALL acquire();
+ virtual void SAL_CALL release();
+ virtual sal_Bool SAL_CALL tryToAcquire();
+
+ ULONG GetAcquireCount( ULONG nThreadId );
+};
+
+// -----------------------------------------------------------------------
+
+SalYieldMutex::SalYieldMutex( Os2SalInstance* pInstData )
+{
+ mpInstData = pInstData;
+ mnCount = 0;
+ mnThreadId = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SalYieldMutex::acquire()
+{
+ OMutex::acquire();
+ mnCount++;
+ mnThreadId = GetCurrentThreadId();
+}
+
+// -----------------------------------------------------------------------
+
+void SalYieldMutex::release()
+{
+ ULONG nThreadId = GetCurrentThreadId();
+ if ( mnThreadId != nThreadId )
+ OMutex::release();
+ else
+ {
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mnAppThreadId != nThreadId )
+ {
+ if ( mnCount == 1 )
+ {
+ mpInstData->mpSalWaitMutex->acquire();
+ if ( mpInstData->mnYieldWaitCount )
+ WinPostMsg( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
+ mnThreadId = 0;
+ mnCount--;
+ OMutex::release();
+ mpInstData->mpSalWaitMutex->release();
+ }
+ else
+ {
+ mnCount--;
+ OMutex::release();
+ }
+ }
+ else
+ {
+ if ( mnCount == 1 )
+ mnThreadId = 0;
+ mnCount--;
+ OMutex::release();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SalYieldMutex::tryToAcquire()
+{
+ if ( OMutex::tryToAcquire() )
+ {
+ mnCount++;
+ mnThreadId = GetCurrentThreadId();
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId )
+{
+ if ( nThreadId == mnThreadId )
+ return mnCount;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexAcquireWithWait()
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return;
+
+ // If we are the main thread, then we must wait with wait, because
+ // in if we don't reschedule, then we create deadlocks if a Windows
+ // Function is called from another thread. If we arn't the main thread,
+ // than we call qcquire directly.
+ ULONG nThreadId = GetCurrentThreadId();
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mnAppThreadId == nThreadId )
+ {
+ // Wenn wir den Mutex nicht bekommen, muessen wir solange
+ // warten, bis wir Ihn bekommen
+ BOOL bAcquire = FALSE;
+ do
+ {
+ if ( pInst->mpSalYieldMutex->tryToAcquire() )
+ bAcquire = TRUE;
+ else
+ {
+ pInst->mpSalWaitMutex->acquire();
+ if ( pInst->mpSalYieldMutex->tryToAcquire() )
+ {
+ bAcquire = TRUE;
+ pInst->mpSalWaitMutex->release();
+ }
+ else
+ {
+ pInst->mnYieldWaitCount++;
+ pInst->mpSalWaitMutex->release();
+ QMSG aTmpMsg;
+ WinGetMsg( pSalData->mhAB, &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
+ pInst->mnYieldWaitCount--;
+ if ( pInst->mnYieldWaitCount )
+ WinPostMsg( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0 , 0 );
+ }
+ }
+ }
+ while ( !bAcquire );
+ }
+ else
+ pInst->mpSalYieldMutex->acquire();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplSalYieldMutexTryToAcquire()
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ return pInst->mpSalYieldMutex->tryToAcquire();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexAcquire()
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->acquire();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalYieldMutexRelease()
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->release();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ImplSalReleaseYieldMutex()
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return 0;
+
+ SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
+ ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
+ ULONG n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+
+ return nCount;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalAcquireYieldMutex( ULONG nCount )
+{
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( !pInst )
+ return;
+
+ SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex;
+ while ( nCount )
+ {
+ pYieldMutex->acquire();
+ nCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+
+void ImplDbgTestSolarMutex()
+{
+ SalData* pSalData = GetSalData();
+ ULONG nCurThreadId = GetCurrentThreadId();
+ if ( pSalData->mnAppThreadId != nCurThreadId )
+ {
+ if ( pSalData->mpFirstInstance )
+ {
+ SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
+ if ( pYieldMutex->mnThreadId != nCurThreadId )
+ {
+ DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" );
+ }
+ }
+ }
+ else
+ {
+ if ( pSalData->mpFirstInstance )
+ {
+ SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
+ if ( pYieldMutex->mnThreadId != nCurThreadId )
+ {
+ DBG_ERROR( "SolarMutex not locked in the main thread" );
+ }
+ }
+ }
+}
+
+#endif
+
+// =======================================================================
+
+void InitSalData()
+{
+ SalData* pSalData = new SalData;
+ memset( pSalData, 0, sizeof( SalData ) );
+ SetSalData( pSalData );
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitSalData()
+{
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mpFontMetrics )
+ delete pSalData->mpFontMetrics;
+ delete pSalData;
+ SetSalData( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalMain()
+{
+ PPIB pib;
+ PTIB tib;
+ HAB hAB;
+ HMQ hMQ;
+ SalData* pData = GetAppSalData();
+#if OSL_DEBUG_LEVEL>0
+printf("InitSalMain\n");
+#endif
+
+ // morph application to PM
+ DosGetInfoBlocks(&tib, &pib);
+ // Change flag from VIO to PM:
+ if (pib->pib_ultype==2) pib->pib_ultype = 3;
+
+ // create anchor block
+ hAB = WinInitialize( 0 );
+ if ( !hAB )
+ return;
+
+ // create message queue
+ hMQ = WinCreateMsgQueue( hAB, 60 );
+ if ( !hMQ )
+ {
+ WinTerminate( hAB );
+ return;
+ }
+
+ if ( pData ) // Im AppServer NULL
+ {
+ // Ankerblock und Messagequeue merken
+ pData->mhAB = hAB;
+ pData->mhMQ = hMQ;
+ }
+
+}
+
+void DeInitSalMain()
+{
+#if OSL_DEBUG_LEVEL>0
+printf("DeInitSalMain\n");
+#endif
+
+ SalData* pData = GetAppSalData();
+ // destroy message queue and anchor block
+ WinDestroyMsgQueue( pData->mhMQ );
+ WinTerminate( pData->mhAB );
+
+}
+
+// -----------------------------------------------------------------------
+
+SalInstance* CreateSalInstance()
+{
+ SalData* pSalData = GetSalData();
+
+ // determine the os2 version
+ ULONG nMayor;
+ ULONG nMinor;
+ DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MAJOR, &nMayor, sizeof( nMayor ) );
+ DosQuerySysInfo( QSV_VERSION_MINOR, QSV_VERSION_MINOR, &nMinor, sizeof( nMinor ) );
+ aSalShlData.mnVersion = (USHORT)(nMayor*10 + nMinor);
+
+ pSalData->mnAppThreadId = GetCurrentThreadId();
+
+ // register frame class
+ if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_FRAME_CLASSNAME,
+ (PFNWP)SalFrameWndProc, CS_MOVENOTIFY /* 17/08 CS_HITTEST | CS_MOVENOTIFY */,
+ SAL_FRAME_WNDEXTRA ) )
+ {
+ return NULL;
+ }
+ // register subframe class
+ if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_SUBFRAME_CLASSNAME,
+ (PFNWP)SalFrameWndProc, CS_SAVEBITS| CS_MOVENOTIFY,
+ SAL_FRAME_WNDEXTRA ) )
+ {
+ return NULL;
+ }
+ // register object class
+ if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_COM_CLASSNAME,
+ (PFNWP)SalComWndProc, 0, 0 ))
+ {
+ return NULL;
+ }
+
+ HWND hComWnd = WinCreateWindow( HWND_OBJECT, (PCSZ)SAL_COM_CLASSNAME,
+ (PCSZ)"", 0, 0, 0, 0, 0,
+ HWND_OBJECT, HWND_TOP,
+ 222, NULL, NULL);
+ if ( !hComWnd )
+ return NULL;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("CreateSalInstance hComWnd %x\n", hComWnd);
+#endif
+ Os2SalInstance* pInst = new Os2SalInstance;
+
+ // init instance (only one instance in this version !!!)
+ pSalData->mpFirstInstance = pInst;
+ pInst->mhAB = pSalData->mhAB;
+ pInst->mhMQ = pSalData->mhMQ;
+ pInst->mnArgc = pSalData->mnArgc;
+ pInst->mpArgv = pSalData->mpArgv;
+ pInst->mhComWnd = hComWnd;
+
+ // AppIcon ermitteln
+ ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, pInst->mhAppIcon);
+
+ // init static GDI Data
+ ImplInitSalGDI();
+
+ return pInst;
+}
+
+// -----------------------------------------------------------------------
+
+void DestroySalInstance( SalInstance* pInst )
+{
+ SalData* pSalData = GetSalData();
+
+ // (only one instance in this version !!!)
+ ImplFreeSalGDI();
+
+#ifdef ENABLE_IME
+ // IME-Daten freigeben
+ if ( pSalData->mpIMEData )
+ ImplReleaseSALIMEData();
+#endif
+
+ // reset instance
+ if ( pSalData->mpFirstInstance == pInst )
+ pSalData->mpFirstInstance = NULL;
+
+ delete pInst;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalInstance::Os2SalInstance()
+{
+ mhComWnd = 0;
+ mpSalYieldMutex = new SalYieldMutex( this );
+ mpSalWaitMutex = new vos::OMutex;
+ mnYieldWaitCount = 0;
+ mpSalYieldMutex->acquire();
+ ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalInstance::~Os2SalInstance()
+{
+ ::tools::SolarMutex::SetSolarMutex( 0 );
+ mpSalYieldMutex->release();
+ delete mpSalYieldMutex;
+ delete mpSalWaitMutex;
+ WinDestroyWindow( mhComWnd);
+}
+
+// -----------------------------------------------------------------------
+
+vos::IMutex* Os2SalInstance::GetYieldMutex()
+{
+ return mpSalYieldMutex;
+}
+// -----------------------------------------------------------------------
+
+ULONG Os2SalInstance::ReleaseYieldMutex()
+{
+ return ImplSalReleaseYieldMutex();
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::AcquireYieldMutex( ULONG nCount )
+{
+ ImplSalAcquireYieldMutex( nCount );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
+{
+ QMSG aMsg;
+ bool bWasMsg = false, bOneEvent = false;
+ bool bQuit = false;
+
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
+ do
+ {
+ if ( WinPeekMsg( pInst->mhAB, &aMsg, 0, 0, 0, PM_REMOVE ) )
+ {
+ WinDispatchMsg( pInst->mhAB, &aMsg );
+ bOneEvent = bWasMsg = true;
+ if (aMsg.msg == WM_QUIT)
+ bQuit = true;
+ }
+ else
+ bOneEvent = false;
+ } while( --nMaxEvents && bOneEvent );
+
+ if ( bWait && ! bWasMsg )
+ {
+ if ( WinGetMsg( pInst->mhAB, &aMsg, 0, 0, 0 ) )
+ WinDispatchMsg( pInst->mhAB, &aMsg );
+ else
+ bQuit = true;
+ }
+
+ if (bQuit)
+ {
+ ImplSalYieldMutexAcquireWithWait();
+ Os2SalFrame* pFrame = GetSalData()->mpFirstFrame;
+ if ( pFrame )
+ {
+ if (pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 ))
+ WinCancelShutdown( pFrame->mhAB, FALSE );
+ }
+ ImplSalYieldMutexRelease();
+ }
+
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ SalData* pSalData = GetSalData();
+ ULONG nCurThreadId = GetCurrentThreadId();
+ ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
+ ULONG n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+ if ( pSalData->mnAppThreadId != nCurThreadId )
+ {
+ // #97739# A SendMessage call blocks until the called thread (here: the main thread)
+ // returns. During a yield however, messages are processed in the main thread that might
+ // result in a new message loop due to opening a dialog. Thus, SendMessage would not
+ // return which will block this thread!
+ // Solution: just give up the time slice and hope that messages are processed
+ // by the main thread anyway (where all windows are created)
+ // If the mainthread is not currently handling messages, then our SendMessage would
+ // also do nothing, so this seems to be reasonable.
+
+ // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
+ if( ImplGetSVData()->maAppData.mnModalMode )
+ DosSleep(1);
+ else
+ WinSendMsg( mhComWnd, SAL_MSG_THREADYIELD, (MPARAM)bWait, (MPARAM)bHandleAllCurrentEvents );
+
+ n = nCount;
+ while ( n )
+ {
+ pYieldMutex->acquire();
+ n--;
+ }
+ }
+ else
+ {
+ ImplSalYield( bWait, bHandleAllCurrentEvents );
+
+ n = nCount;
+ while ( n )
+ {
+ ImplSalYieldMutexAcquireWithWait();
+ n--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ //debug_printf( "SalComWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
+
+ switch ( nMsg )
+ {
+ case SAL_MSG_PRINTABORTJOB:
+ //ImplSalPrinterAbortJobAsync( (HDC)wParam );
+ break;
+ case SAL_MSG_THREADYIELD:
+ ImplSalYield( (bool)nMP1, (bool) nMP2);
+ return 0;
+ // If we get this message, because another GetMessage() call
+ // has recieved this message, we must post this message to
+ // us again, because in the other case we wait forever.
+ case SAL_MSG_RELEASEWAITYIELD:
+ {
+ Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
+ if ( pInst && pInst->mnYieldWaitCount )
+ WinPostMsg( hWnd, SAL_MSG_RELEASEWAITYIELD, nMP1, nMP2 );
+ }
+ return 0;
+ case SAL_MSG_STARTTIMER:
+ ImplSalStartTimer( (ULONG)nMP2, FALSE);
+ return 0;
+ case SAL_MSG_CREATEFRAME:
+ return (MRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)nMP2, (ULONG)nMP1 );
+ case SAL_MSG_DESTROYFRAME:
+ delete (SalFrame*)nMP2;
+ return 0;
+ case SAL_MSG_DESTROYHWND:
+ //We only destroy the native window here. We do NOT destroy the SalFrame contained
+ //in the structure (GetWindowPtr()).
+ if (WinDestroyWindow((HWND)nMP2) == 0)
+ {
+ OSL_ENSURE(0, "DestroyWindow failed!");
+ //Failure: We remove the SalFrame from the window structure. So we avoid that
+ // the window structure may contain an invalid pointer, once the SalFrame is deleted.
+ SetWindowPtr((HWND)nMP2, 0);
+ }
+ return 0;
+ case SAL_MSG_CREATEOBJECT:
+ return (MRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (Os2SalFrame*)(ULONG)nMP2 );
+ case SAL_MSG_DESTROYOBJECT:
+ delete (SalObject*)nMP2;
+ return 0;
+ case SAL_MSG_CREATESOUND:
+ //return (MRESULT)((Os2SalSound*)nMP2)->ImplCreate();
+ return 0;
+ case SAL_MSG_DESTROYSOUND:
+ //((Os2SalSound*)nMP2)->ImplDestroy();
+ return 0;
+ case SAL_MSG_POSTTIMER:
+ SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, (ULONG)nMP2 );
+ break;
+ case WM_TIMER:
+ SalTimerProc( hWnd, 0, 0, 0 );
+ break;
+ }
+
+ return WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalInstance::AnyInput( USHORT nType )
+{
+ SalData* pSalData = GetSalData();
+ QMSG aQMSG;
+
+ if ( (nType & (INPUT_ANY)) == INPUT_ANY )
+ {
+ // Any Input
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) )
+ return TRUE;
+ }
+ else
+ {
+ if ( nType & INPUT_MOUSE )
+ {
+ // Test auf Mouseinput
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
+ WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE ) )
+ return TRUE;
+ }
+
+ if ( nType & INPUT_KEYBOARD )
+ {
+ // Test auf Keyinput
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
+ WM_CHAR, WM_CHAR, PM_NOREMOVE ) )
+ return !(SHORT1FROMMP( aQMSG.mp1 ) & KC_KEYUP);
+ }
+
+ if ( nType & INPUT_PAINT )
+ {
+ // Test auf Paintinput
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
+ WM_PAINT, WM_PAINT, PM_NOREMOVE ) )
+ return TRUE;
+ }
+
+ if ( nType & INPUT_TIMER )
+ {
+ // Test auf Timerinput
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
+ WM_TIMER, WM_TIMER, PM_NOREMOVE ) )
+ return TRUE;
+ }
+
+ if ( nType & INPUT_OTHER )
+ {
+ // Test auf sonstigen Input
+ if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) )
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* Os2SalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
+{
+ // Um auf Main-Thread umzuschalten
+ return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)pSystemParentData->hWnd );
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* Os2SalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
+{
+ // Um auf Main-Thread umzuschalten
+ HWND mhWndClient;
+//31/05/06 YD use client as owner(parent) so positioning will not need to
+// take care of borders and captions
+ if ( pParent )
+ mhWndClient = static_cast<Os2SalFrame*>(pParent)->mhWndClient;
+ else
+ mhWndClient = 0;
+ return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)mhWndClient );
+}
+
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DestroyFrame( SalFrame* pFrame )
+{
+ WinSendMsg( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (MPARAM)pFrame );
+}
+
+// -----------------------------------------------------------------------
+
+SalObject* Os2SalInstance::CreateObject( SalFrame* pParent,
+ SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
+ BOOL /*bShow*/ )
+{
+ // Um auf Main-Thread umzuschalten
+ return (SalObject*)WinSendMsg( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (MPARAM)pParent );
+}
+
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DestroyObject( SalObject* pObject )
+{
+ WinSendMsg( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (MPARAM)pObject );
+}
+
+// -----------------------------------------------------------------------
+
+void* Os2SalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
+{
+ rReturnedBytes = 1;
+ rReturnedType = AsciiCString;
+ return (void*) "";
+}
+
+void Os2SalInstance::AddToRecentDocumentList(const rtl::OUString& /*rFileUrl*/, const rtl::OUString& /*rMimeType*/)
+{
+}
+
+// -----------------------------------------------------------------------
+
+SalTimer* Os2SalInstance::CreateSalTimer()
+{
+ return new Os2SalTimer();
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* Os2SalInstance::CreateSalBitmap()
+{
+ return new Os2SalBitmap();
+}
+
+// -----------------------------------------------------------------------
+
+class Os2ImeStatus : public SalI18NImeStatus
+{
+ public:
+ Os2ImeStatus() {}
+ virtual ~Os2ImeStatus() {}
+
+ // asks whether there is a status window available
+ // to toggle into menubar
+ virtual bool canToggle() { return false; }
+ virtual void toggle() {}
+};
+
+SalI18NImeStatus* Os2SalInstance::CreateI18NImeStatus()
+{
+ return new Os2ImeStatus();
+}
+
+// -----------------------------------------------------------------------
+
+const ::rtl::OUString& SalGetDesktopEnvironment()
+{
+ static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "OS/2" ) );
+ return aDesktopEnvironment;
+}
+
+SalSession* Os2SalInstance::CreateSalSession()
+{
+ return NULL;
+}
+
diff --git a/vcl/os2/source/app/sallang.cxx b/vcl/os2/source/app/sallang.cxx
new file mode 100644
index 000000000000..f23705077ac3
--- /dev/null
+++ b/vcl/os2/source/app/sallang.cxx
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SALLANG_HXX
+#include <sallang.hxx>
+#endif
+
+// =======================================================================
+
+// -----------------------------------------------------------------------
+// English (US/UK/AUS/CAN/NZ/EIRE/SAFRICA/JAMAICA/CARRIBEAN)
+static const wchar_t* aImplLangEnglishTab[LSTR_COUNT] =
+{
+ L"Shift", // LSTR_KEY_SHIFT
+ L"Ctrl", // LSTR_KEY_CTRL
+ L"Alt", // LSTR_KEY_ALT
+ L"Up", // LSTR_KEY_UP
+ L"Down", // LSTR_KEY_DOWN
+ L"Left", // LSTR_KEY_LEFT
+ L"Right", // LSTR_KEY_RIGHT
+ L"Home", // LSTR_KEY_HOME
+ L"End", // LSTR_KEY_END
+ L"PageUp", // LSTR_KEY_PAGEUP
+ L"PageDown", // LSTR_KEY_PAGEDOWN
+ L"Enter", // LSTR_KEY_RETURN
+ L"Esc", // LSTR_KEY_ESC
+ L"Tab", // LSTR_KEY_TAB
+ L"Backspace", // LSTR_KEY_BACKSPACE
+ L"Space", // LSTR_KEY_SPACE
+ L"Insert", // LSTR_KEY_INSERT
+ L"Del", // LSTR_KEY_DELETE
+};
+
+// =======================================================================
+
+const sal_Unicode** ImplGetLangTab( LanguageType eLang )
+{
+ // Sprachtabelle ermitteln
+ const wchar_t** pLangTab;
+ //switch ( International::GetNeutralLanguage( eLang ) )
+ switch ( eLang )
+ {
+#if 0
+ case LANGUAGE_DANISH:
+ pLangTab = aImplLangDanishTab;
+ break;
+
+ case LANGUAGE_DUTCH:
+ case LANGUAGE_DUTCH_BELGIAN:
+ pLangTab = aImplLangDutchTab;
+ break;
+
+ case LANGUAGE_FINNISH:
+ pLangTab = aImplLangFinnishTab;
+ break;
+
+ case LANGUAGE_FRENCH:
+ pLangTab = aImplLangFrenchTab;
+ break;
+
+ case LANGUAGE_GERMAN:
+ pLangTab = aImplLangGermanTab;
+ break;
+
+ case LANGUAGE_ITALIAN:
+ pLangTab = aImplLangItalianTab;
+ break;
+
+ case LANGUAGE_NORWEGIAN:
+ case LANGUAGE_NORWEGIAN_BOKMAL:
+ pLangTab = aImplLangNorwegianTab;
+ break;
+
+ case LANGUAGE_PORTUGUESE:
+ case LANGUAGE_PORTUGUESE_BRAZILIAN:
+ pLangTab = aImplLangPortugueseTab;
+ break;
+
+ case LANGUAGE_SPANISH:
+ pLangTab = aImplLangSpanishTab;
+ break;
+
+ case LANGUAGE_SWEDISH:
+ pLangTab = aImplLangSwedishTab;
+ break;
+#endif
+ default:
+ pLangTab = aImplLangEnglishTab;
+ break;
+ }
+
+ return (const sal_Unicode**)pLangTab;
+}
diff --git a/vcl/os2/source/app/salshl.cxx b/vcl/os2/source/app/salshl.cxx
new file mode 100644
index 000000000000..637ddd748f33
--- /dev/null
+++ b/vcl/os2/source/app/salshl.cxx
@@ -0,0 +1,123 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svpm.h>
+
+#define _SV_SALSHL_CXX
+#include <saldata.hxx>
+#include <tools/debug.hxx>
+
+// =======================================================================
+
+SalShlData aSalShlData;
+
+HMODULE ImplGetModule(void);
+static HMODULE mhMod = ImplGetModule();
+
+// =======================================================================
+
+APIRET APIENTRY DosQueryModFromEIP (HMODULE *phMod, ULONG *pObjNum,
+ ULONG BuffLen, PCHAR pBuff, ULONG *pOffset, ULONG Address);
+
+HMODULE ImplGetModule(void)
+{
+ HMODULE hMod;
+ ULONG ObjNum;
+ CHAR Buff[2*_MAX_PATH];
+ ULONG Offset;
+ APIRET rc;
+
+ // get module handle (and name)
+ rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, &Offset, (ULONG)ImplGetModule);
+ if (rc)
+ return NULL;
+ // return module handle
+ aSalShlData.mhMod = hMod;
+ return hMod;
+}
+
+// =======================================================================
+
+HPOINTER ImplLoadSalCursor( int nId )
+{
+ DBG_ASSERT( aSalShlData.mhMod, "no DLL instance handle" );
+
+ HPOINTER hPointer = WinLoadPointer( HWND_DESKTOP, aSalShlData.mhMod, nId );
+
+ DBG_ASSERT( hPointer, "pointer not found in sal resource" );
+#if OSL_DEBUG_LEVEL>0
+ if (!hPointer)
+ debug_printf( "ImplLoadSalCursor: pointer %d not found in sal resource\n", nId);
+#endif
+ return hPointer;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplLoadSalIcon( int nId, HPOINTER& rIcon)
+{
+ DBG_ASSERT( aSalShlData.mhMod, "no DLL instance handle" );
+
+ SalData* pSalData = GetSalData();
+
+ // check the cache first
+ SalIcon *pSalIcon = pSalData->mpFirstIcon;
+ while( pSalIcon )
+ {
+ if( pSalIcon->nId != nId )
+ pSalIcon = pSalIcon->pNext;
+ else
+ {
+ rIcon = pSalIcon->hIcon;
+ return (rIcon != 0);
+ }
+ }
+
+ // Try at first to load the icons from the application exe file
+ rIcon = WinLoadPointer( HWND_DESKTOP, NULL, nId );
+ if ( !rIcon )
+ {
+ // If the application don't provide these icons, then we try
+ // to load the icon from the VCL resource
+ rIcon = WinLoadPointer( HWND_DESKTOP, aSalShlData.mhMod, nId );
+ }
+
+ if( rIcon )
+ {
+ // add to icon cache
+ pSalIcon = new SalIcon();
+ pSalIcon->nId = nId;
+ pSalIcon->hIcon = rIcon;
+ pSalIcon->pNext = pSalData->mpFirstIcon;
+ pSalData->mpFirstIcon = pSalIcon;
+ }
+
+ return (rIcon != 0);
+}
+
+// =======================================================================
+
diff --git a/vcl/os2/source/app/saltimer.cxx b/vcl/os2/source/app/saltimer.cxx
new file mode 100644
index 000000000000..bcdeec94ef25
--- /dev/null
+++ b/vcl/os2/source/app/saltimer.cxx
@@ -0,0 +1,140 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svpm.h>
+
+#define _SV_SALTIMER_CXX
+#include <saldata.hxx>
+#include <saltimer.h>
+#include <salinst.h>
+
+// =======================================================================
+
+// Maximale Periode
+#define MAX_SYSPERIOD 65533
+#define IDTIMER 10
+
+// =======================================================================
+
+void ImplSalStartTimer( ULONG nMS, BOOL bMutex )
+{
+ SalData* pSalData = GetSalData();
+
+ // Periode darf nicht zu gross sein, da OS2 2.11 mit USHORT arbeitet
+ // Remenber the time of the timer
+ pSalData->mnTimerMS = nMS;
+ if ( !bMutex )
+ pSalData->mnTimerOrgMS = nMS;
+
+ // Periode darf nicht zu gross sein, da Windows mit USHORT arbeitet
+ if ( nMS > MAX_SYSPERIOD )
+ nMS = MAX_SYSPERIOD;
+
+ // Gibt es einen Timer, dann zerstoren
+ if ( pSalData->mnTimerId )
+ WinStopTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, pSalData->mnTimerId );
+
+ // Make a new timer with new period
+ pSalData->mnTimerId = WinStartTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, IDTIMER, nMS );
+ pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalTimer::~Os2SalTimer()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalTimer::Start( ULONG nMS )
+{
+ // Um auf Main-Thread umzuschalten
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mpFirstInstance )
+ {
+ if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
+ WinPostMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (MPARAM)nMS );
+ else
+ WinSendMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (MPARAM)nMS );
+ }
+ else
+ ImplSalStartTimer( nMS, FALSE);
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalTimer::Stop()
+{
+ SalData* pSalData = GetSalData();
+
+ // Exitstiert ein Timer, dann diesen zerstoeren
+ if ( pSalData->mnTimerId ) {
+ WinStopTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, pSalData->mnTimerId );
+ pSalData->mnTimerId = 0;
+ pSalData->mnNextTimerTime = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SalTimerProc( HWND, UINT, UINT nId, ULONG )
+{
+ SalData* pSalData = GetSalData();
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Test for MouseLeave
+ SalTestMouseLeave();
+
+ bool bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE);
+ if ( pSVData->mpSalTimer && ! bRecursive )
+ {
+ // Try to aquire the mutex. If we don't get the mutex then we
+ // try this a short time later again.
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE);
+ if ( pSVData->mpSalTimer && ! bRecursive )
+ {
+ pSalData->mbInTimerProc = TRUE;
+ pSVData->mpSalTimer->CallCallback();
+ pSalData->mbInTimerProc = FALSE;
+ ImplSalYieldMutexRelease();
+
+ // Run the timer in the correct time, if we start this
+ // with a small timeout, because we don't get the mutex
+ if ( pSalData->mnTimerId &&
+ (pSalData->mnTimerMS != pSalData->mnTimerOrgMS) )
+ ImplSalStartTimer( pSalData->mnTimerOrgMS, FALSE );
+ }
+ }
+ else
+ ImplSalStartTimer( 10, TRUE );
+ }
+
+}
+
diff --git a/vcl/os2/source/gdi/makefile.mk b/vcl/os2/source/gdi/makefile.mk
new file mode 100644
index 000000000000..b411c1eb2ce2
--- /dev/null
+++ b/vcl/os2/source/gdi/makefile.mk
@@ -0,0 +1,56 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=SV
+TARGET=salgdi
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+YD00_CXXFILES= salgdi.cxx \
+ salgdi2.cxx \
+ salgdi3.cxx \
+ salvd.cxx \
+ salprn.cxx \
+ salbmp.cxx
+
+SLOFILES= $(SLO)$/salgdi.obj \
+ $(SLO)$/salgdi2.obj \
+ $(SLO)$/salgdi3.obj \
+ $(SLO)$/salvd.obj \
+ $(SLO)$/salprn.obj \
+ $(SLO)$/salbmp.obj \
+ $(SLO)$/os2layout.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/os2/source/gdi/os2layout.cxx b/vcl/os2/source/gdi/os2layout.cxx
new file mode 100644
index 000000000000..924770c86869
--- /dev/null
+++ b/vcl/os2/source/gdi/os2layout.cxx
@@ -0,0 +1,1056 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <tools/svwin.h>
+
+#include <rtl/ustring.hxx>
+#include <osl/module.h>
+#include <salgdi.h>
+#include <saldata.hxx>
+#include <vcl/sallayout.hxx>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+#include <cstdio>
+#include <malloc.h>
+
+#ifdef GCP_KERN_HACK
+ #include <algorithm>
+#endif // GCP_KERN_HACK
+
+// for GetMirroredChar
+#include <vcl/svapp.hxx>
+
+#include <hash_map>
+typedef std::hash_map<int,int> IntMap;
+
+#define DROPPED_OUTGLYPH 0xFFFF
+
+using namespace rtl;
+
+// =======================================================================
+
+// OS/2 specific physical font instance
+class ImplOs2FontEntry : public ImplFontEntry
+{
+public:
+ ImplOs2FontEntry( ImplFontSelectData& );
+ ~ImplOs2FontEntry();
+
+private:
+ // TODO: also add HFONT??? Watch out for issues with too many active fonts...
+
+#ifdef GCP_KERN_HACK
+public:
+ bool HasKernData() const;
+ void SetKernData( int, const KERNINGPAIRS* );
+ int GetKerning( sal_Unicode, sal_Unicode ) const;
+private:
+ KERNINGPAIRS* mpKerningPairs;
+ int mnKerningPairs;
+#endif // GCP_KERN_HACK
+
+public:
+ int GetCachedGlyphWidth( int nCharCode ) const;
+ void CacheGlyphWidth( int nCharCode, int nCharWidth );
+private:
+ IntMap maWidthMap;
+};
+
+// -----------------------------------------------------------------------
+
+inline void ImplOs2FontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth )
+{
+ maWidthMap[ nCharCode ] = nCharWidth;
+}
+
+inline int ImplOs2FontEntry::GetCachedGlyphWidth( int nCharCode ) const
+{
+ IntMap::const_iterator it = maWidthMap.find( nCharCode );
+ if( it == maWidthMap.end() )
+ return -1;
+ return it->second;
+}
+
+// =======================================================================
+
+class Os2Layout : public SalLayout
+{
+public:
+ Os2Layout( HDC, const ImplOs2FontData&, ImplOs2FontEntry& );
+ virtual void InitFont() const;
+ void SetFontScale( float f ) { mfFontScale = f; }
+ float GetFontScale() const { return mfFontScale; }
+
+protected:
+ HPS mhPS; // OS2 device handle
+ FATTRS mhFont;
+ int mnBaseAdv; // x-offset relative to Layout origin
+ float mfFontScale; // allows metrics emulation of huge font sizes
+
+ const ImplOs2FontData& mrOs2FontData;
+ ImplOs2FontEntry& mrOs2FontEntry;
+};
+
+// =======================================================================
+
+class Os2SalLayout : public Os2Layout
+{
+public:
+ Os2SalLayout( HPS, BYTE nCharSet, const ImplOs2FontData&, ImplOs2FontEntry& );
+ virtual ~Os2SalLayout();
+
+ virtual bool LayoutText( ImplLayoutArgs& );
+ virtual void AdjustLayout( ImplLayoutArgs& );
+ virtual void DrawText( SalGraphics& ) const;
+
+ virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
+ sal_Int32* pGlyphAdvances, int* pCharIndexes ) const;
+
+ virtual long FillDXArray( long* pDXArray ) const;
+ virtual int GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const;
+ virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const;
+
+ // for glyph+font+script fallback
+ virtual void MoveGlyph( int nStart, long nNewXPos );
+ virtual void DropGlyph( int nStart );
+ virtual void Simplify( bool bIsBase );
+
+protected:
+ void Justify( long nNewWidth );
+ void ApplyDXArray( const ImplLayoutArgs& );
+
+protected:
+
+private:
+ int mnGlyphCount;
+ int mnCharCount;
+ sal_Unicode* mpOutGlyphs;
+ int* mpGlyphAdvances; // if possible this is shared with mpGlyphAdvances[]
+ int* mpGlyphOrigAdvs;
+ int* mpCharWidths; // map rel char pos to char width
+ int* mpChars2Glyphs; // map rel char pos to abs glyph pos
+ int* mpGlyphs2Chars; // map abs glyph pos to abs char pos
+ bool* mpGlyphRTLFlags; // BiDi status for glyphs: true=>RTL
+ mutable long mnWidth;
+ bool mbDisableGlyphs;
+
+ int mnNotdefWidth;
+ BYTE mnCharSet;
+
+};
+
+// =======================================================================
+
+Os2Layout::Os2Layout( HPS hPS, const ImplOs2FontData& rWFD, ImplOs2FontEntry& rWFE )
+: mhPS( hPS ),
+ mnBaseAdv( 0 ),
+ mfFontScale( 1.0 ),
+ mrOs2FontData( rWFD ),
+ mrOs2FontEntry( rWFE )
+{
+ BOOL fSuccess;
+ fSuccess = Ft2QueryLogicalFont( mhPS, LCID_BASE, NULL, &mhFont, sizeof(FATTRS));
+}
+
+// -----------------------------------------------------------------------
+
+void Os2Layout::InitFont() const
+{
+ // select fallback level 0 font
+ APIRET rc = Ft2CreateLogFont( mhPS, NULL, LCID_BASE, (PFATTRS)&mhFont);
+}
+
+// =======================================================================
+
+Os2SalLayout::Os2SalLayout( HPS hPS, BYTE nCharSet,
+ const ImplOs2FontData& rOs2FontData, ImplOs2FontEntry& rOs2FontEntry )
+: Os2Layout( hPS, rOs2FontData, rOs2FontEntry ),
+ mnGlyphCount( 0 ),
+ mnCharCount( 0 ),
+ mpOutGlyphs( NULL ),
+ mpGlyphAdvances( NULL ),
+ mpGlyphOrigAdvs( NULL ),
+ mpCharWidths( NULL ),
+ mpChars2Glyphs( NULL ),
+ mpGlyphs2Chars( NULL ),
+ mpGlyphRTLFlags( NULL ),
+ mnWidth( 0 ),
+ mnNotdefWidth( -1 ),
+ mnCharSet( nCharSet ),
+ mbDisableGlyphs( false )
+{
+ mbDisableGlyphs = true;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalLayout::~Os2SalLayout()
+{
+ delete[] mpGlyphRTLFlags;
+ delete[] mpGlyphs2Chars;
+ delete[] mpChars2Glyphs;
+ if( mpCharWidths != mpGlyphAdvances )
+ delete[] mpCharWidths;
+ delete[] mpGlyphOrigAdvs;
+ delete[] mpGlyphAdvances;
+ delete[] mpOutGlyphs;
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalLayout::LayoutText( ImplLayoutArgs& rArgs )
+{
+ // prepare layout
+ // TODO: fix case when recyclying old Os2SalLayout object
+ mbDisableGlyphs |= ((rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) != 0);
+ mnCharCount = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
+
+ if( !mbDisableGlyphs )
+ {
+ // Win32 glyph APIs have serious problems with vertical layout
+ // => workaround is to use the unicode methods then
+ if( rArgs.mnFlags & SAL_LAYOUT_VERTICAL )
+ mbDisableGlyphs = true;
+ else
+ // use cached value from font face
+ mbDisableGlyphs = mrOs2FontData.IsGlyphApiDisabled();
+ }
+
+ // TODO: use a cached value for bDisableAsianKern from upper layers
+#if 0
+ if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN )
+ {
+ TEXTMETRICA aTextMetricA;
+ if( ::GetTextMetricsA( mhDC, &aTextMetricA )
+ && !(aTextMetricA.tmPitchAndFamily & TMPF_FIXED_PITCH) )
+ rArgs.mnFlags &= ~SAL_LAYOUT_KERNING_ASIAN;
+ }
+#endif
+
+ // layout text
+ int i, j;
+
+ mnGlyphCount = 0;
+ bool bVertical = (rArgs.mnFlags & SAL_LAYOUT_VERTICAL) != 0;
+
+ // count the number of chars to process if no RTL run
+ rArgs.ResetPos();
+ bool bHasRTL = false;
+ while( rArgs.GetNextRun( &i, &j, &bHasRTL ) && !bHasRTL )
+ mnGlyphCount += j - i;
+
+ // if there are RTL runs we need room to remember individual BiDi flags
+ if( bHasRTL )
+ {
+ mpGlyphRTLFlags = new bool[ mnCharCount ];
+ for( i = 0; i < mnCharCount; ++i )
+ mpGlyphRTLFlags[i] = false;
+ }
+
+ // rewrite the logical string if needed to prepare for the API calls
+ const sal_Unicode* pBidiStr = rArgs.mpStr + rArgs.mnMinCharPos;
+ if( (mnGlyphCount != mnCharCount) || bVertical )
+ {
+ // we need to rewrite the pBidiStr when any of
+ // - BiDirectional layout
+ // - vertical layout
+ // - partial runs (e.g. with control chars or for glyph fallback)
+ // are involved
+ sal_Unicode* pRewrittenStr = (sal_Unicode*)alloca( mnCharCount * sizeof(sal_Unicode) );
+ pBidiStr = pRewrittenStr;
+
+ // note: glyph to char mapping is relative to first character
+ mpChars2Glyphs = new int[ mnCharCount ];
+ mpGlyphs2Chars = new int[ mnCharCount ];
+ for( i = 0; i < mnCharCount; ++i )
+ mpChars2Glyphs[i] = mpGlyphs2Chars[i] = -1;
+
+ mnGlyphCount = 0;
+ rArgs.ResetPos();
+ bool bIsRTL = false;
+ while( rArgs.GetNextRun( &i, &j, &bIsRTL ) )
+ {
+ do
+ {
+ // get the next leftmost character in this run
+ int nCharPos = bIsRTL ? --j : i++;
+ sal_Unicode cChar = rArgs.mpStr[ nCharPos ];
+
+ // in the RTL case mirror the character and remember its RTL status
+ if( bIsRTL )
+ {
+ cChar = ::GetMirroredChar( cChar );
+ mpGlyphRTLFlags[ mnGlyphCount ] = true;
+ }
+
+ // for vertical writing use vertical alternatives
+ if( bVertical )
+ {
+ sal_Unicode cVert = ::GetVerticalChar( cChar );
+ if( cVert )
+ cChar = cVert;
+ }
+
+ // rewrite the original string
+ // update the mappings between original and rewritten string
+ pRewrittenStr[ mnGlyphCount ] = cChar;
+ mpGlyphs2Chars[ mnGlyphCount ] = nCharPos;
+ mpChars2Glyphs[ nCharPos - rArgs.mnMinCharPos ] = mnGlyphCount;
+ ++mnGlyphCount;
+ } while( i < j );
+ }
+ }
+
+ mpOutGlyphs = new sal_Unicode[ mnGlyphCount ];
+ mpGlyphAdvances = new int[ mnGlyphCount ];
+
+ if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_PAIRS | SAL_LAYOUT_KERNING_ASIAN) )
+ mpGlyphOrigAdvs = new int[ mnGlyphCount ];
+
+#ifndef GCP_KERN_HACK
+ DWORD nGcpOption = 0;
+ // enable kerning if requested
+ if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS )
+ nGcpOption |= GCP_USEKERNING;
+#endif // GCP_KERN_HACK
+
+ LONG lLcid = Ft2QueryCharSet( mhPS);
+
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpOutGlyphs[i] = pBidiStr[ i ];
+ mnWidth = 0;
+ for( i = 0; i < mnGlyphCount; ++i )
+ {
+ const sal_Unicode* pCodes = &pBidiStr[i];
+ // check for surrogate pairs
+ if( (pCodes[0] & 0xFC00) == 0xDC00 )
+ continue;
+ bool bSurrogate = ((pCodes[0] & 0xFC00) == 0xD800);
+
+ // get the width of the corresponding code point
+ int nCharCode = pCodes[0];
+ if( bSurrogate )
+ nCharCode = 0x10000 + ((pCodes[0] & 0x03FF) << 10) + (pCodes[1] & 0x03FF);
+ int nGlyphWidth = mrOs2FontEntry.GetCachedGlyphWidth( nCharCode );
+ if( nGlyphWidth == -1 )
+ {
+ if (!Ft2QueryStringWidthW( mhPS, (LPWSTR)&pCodes[0], 1, (LONG*)&nGlyphWidth))
+ nGlyphWidth = 0;
+ mrOs2FontEntry.CacheGlyphWidth( nCharCode, nGlyphWidth );
+ }
+ mpGlyphAdvances[ i ] = nGlyphWidth;
+ mnWidth += nGlyphWidth;
+
+ // remaining codes of surrogate pair get a zero width
+ if( bSurrogate )
+ mpGlyphAdvances[ i+1 ] = 0;
+
+ // check with the font face if glyph fallback is needed
+ if( mrOs2FontData.HasChar( nCharCode ) )
+ continue;
+ // Type1 charmaps are not complete (or buggy), use FT2 to check again
+ if (Ft2FontSupportsUnicodeChar( mhPS, lLcid, TRUE, nCharCode))
+ continue;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalLayout::LayoutText font does not support unicode char\n");
+#endif
+ // request glyph fallback at this position in the string
+ bool bRTL = mpGlyphRTLFlags ? mpGlyphRTLFlags[i] : false;
+ int nCharPos = mpGlyphs2Chars ? mpGlyphs2Chars[i]: i + rArgs.mnMinCharPos;
+ rArgs.NeedFallback( nCharPos, bRTL );
+ if( bSurrogate )
+ rArgs.NeedFallback( nCharPos+1, bRTL );
+
+ if( rArgs.mnFlags & SAL_LAYOUT_FOR_FALLBACK )
+ {
+ // when we already are layouting for glyph fallback
+ // then a new unresolved glyph is not interesting
+ mnNotdefWidth = 0;
+ mpOutGlyphs[i] = DROPPED_OUTGLYPH;
+ if( mbDisableGlyphs && bSurrogate )
+ mpOutGlyphs[i+1] = DROPPED_OUTGLYPH;
+ }
+ else
+ {
+ if( mnNotdefWidth < 0 )
+ {
+ // get the width of the NotDef glyph
+ LONG aExtent;
+ mnNotdefWidth = 0;
+ if (Ft2QueryStringWidthW( mhPS, (LPWSTR)&rArgs.mpStr[ nCharPos ], 1, &aExtent))
+ mnNotdefWidth = aExtent;
+ }
+ // use a better NotDef glyph
+ if( !mbDisableGlyphs )
+ mpOutGlyphs[i] = 0;
+ }
+
+ // replace the current glyph with the NotDef glyph
+ mnWidth += mnNotdefWidth - mpGlyphAdvances[i];
+ mpGlyphAdvances[i] = mnNotdefWidth;
+ if( mpGlyphOrigAdvs )
+ mpGlyphOrigAdvs[i] = mnNotdefWidth;
+ }
+
+#ifdef GCP_KERN_HACK
+ // apply kerning if the layout engine has not yet done it
+ if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_ASIAN|SAL_LAYOUT_KERNING_PAIRS) )
+ {
+#else // GCP_KERN_HACK
+ // apply just asian kerning
+ if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN )
+ {
+ if( !(rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) )
+#endif // GCP_KERN_HACK
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpGlyphOrigAdvs[i] = mpGlyphAdvances[i];
+
+ // #99658# also apply asian kerning on the substring border
+ int nLen = mnGlyphCount;
+ if( rArgs.mnMinCharPos + nLen < rArgs.mnLength )
+ ++nLen;
+ for( i = 1; i < nLen; ++i )
+ {
+#ifdef GCP_KERN_HACK
+ if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS )
+ {
+ int nKernAmount = mrOs2FontEntry.GetKerning( pBidiStr[i-1], pBidiStr[i] );
+ mpGlyphAdvances[ i-1 ] += nKernAmount;
+ mnWidth += nKernAmount;
+ }
+ else if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN )
+#endif // GCP_KERN_HACK
+
+ if( (0x3000 == (0xFF00 & pBidiStr[i-1]))
+ && (0x3000 == (0xFF00 & pBidiStr[i])) )
+ {
+ long nKernFirst = +CalcAsianKerning( pBidiStr[i-1], true, bVertical );
+ long nKernNext = -CalcAsianKerning( pBidiStr[i], false, bVertical );
+
+ long nDelta = (nKernFirst < nKernNext) ? nKernFirst : nKernNext;
+ if( nDelta<0 && nKernFirst!=0 && nKernNext!=0 )
+ {
+ nDelta = (nDelta * mpGlyphAdvances[i-1] + 2) / 4;
+ mpGlyphAdvances[i-1] += nDelta;
+ mnWidth += nDelta;
+ }
+ }
+ }
+ }
+
+ // calculate virtual char widths
+ if( !mpGlyphs2Chars )
+ mpCharWidths = mpGlyphAdvances;
+ else
+ {
+ mpCharWidths = new int[ mnCharCount ];
+ for( i = 0; i < mnCharCount; ++i )
+ mpCharWidths[ i ] = 0;
+ for( i = 0; i < mnGlyphCount; ++i )
+ {
+ int j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos;
+ if( j >= 0 )
+ mpCharWidths[ j ] += mpGlyphAdvances[ i ];
+ }
+ }
+
+ // scale layout metrics if needed
+ if( mfFontScale != 1.0 )
+ {
+ mnWidth *= mfFontScale;
+ mnBaseAdv *= mfFontScale;
+ for( i = 0; i < mnCharCount; ++i )
+ mpCharWidths[ i ] *= mfFontScale;
+ if( mpGlyphAdvances != mpCharWidths )
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpGlyphAdvances[ i ] *= mfFontScale;
+ if( mpGlyphOrigAdvs && (mpGlyphOrigAdvs != mpGlyphAdvances) )
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpGlyphOrigAdvs[ i ] *= mfFontScale;
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------
+
+int Os2SalLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int& nStart,
+ sal_Int32* pGlyphAdvances, int* pCharIndexes ) const
+{
+ // return zero if no more glyph found
+ if( nStart >= mnGlyphCount )
+ return 0;
+
+ // calculate glyph position relative to layout base
+ // TODO: avoid for nStart!=0 case by reusing rPos
+ long nXOffset = mnBaseAdv;
+ for( int i = 0; i < nStart; ++i )
+ nXOffset += mpGlyphAdvances[ i ];
+
+ // calculate absolute position in pixel units
+ Point aRelativePos( nXOffset, 0 );
+ rPos = GetDrawPosition( aRelativePos );
+
+ int nCount = 0;
+ while( nCount < nLen )
+ {
+ // update return values {nGlyphIndex,nCharPos,nGlyphAdvance}
+ long nGlyphIndex = mpOutGlyphs[ nStart ];
+ if( mbDisableGlyphs )
+ {
+ if( mnLayoutFlags & SAL_LAYOUT_VERTICAL )
+ {
+ sal_Unicode cChar = (sal_Unicode)(nGlyphIndex & GF_IDXMASK);
+#ifdef GNG_VERT_HACK
+ if( mrOs2FontData.HasGSUBstitutions( mhPS )
+ && mrOs2FontData.IsGSUBstituted( cChar ) )
+ nGlyphIndex |= GF_ROTL | GF_GSUB;
+ else
+#endif // GNG_VERT_HACK
+ {
+ nGlyphIndex |= GetVerticalFlags( cChar );
+ if( !(nGlyphIndex & GF_ROTMASK) )
+ nGlyphIndex |= GF_VERT;
+ }
+ }
+ nGlyphIndex |= GF_ISCHAR;
+ }
+ ++nCount;
+ *(pGlyphs++) = nGlyphIndex;
+ if( pGlyphAdvances )
+ *(pGlyphAdvances++) = mpGlyphAdvances[ nStart ];
+ if( pCharIndexes )
+ {
+ int nCharPos;
+ if( !mpGlyphs2Chars )
+ nCharPos = nStart + mnMinCharPos;
+ else
+ nCharPos = mpGlyphs2Chars[nStart];
+ *(pCharIndexes++) = nCharPos;
+ }
+
+ // stop at last glyph
+ if( ++nStart >= mnGlyphCount )
+ break;
+
+ // stop when next x-position is unexpected
+ if( !pGlyphAdvances && mpGlyphOrigAdvs )
+ if( mpGlyphAdvances[nStart-1] != mpGlyphOrigAdvs[nStart-1] )
+ break;
+ }
+
+ return nCount;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::DrawText( SalGraphics& rGraphics ) const
+{
+ if( mnGlyphCount <= 0 )
+ return;
+
+ Point aPos = GetDrawPosition( Point( mnBaseAdv, 0 ) );
+ POINTL aPt;
+ APIRET rc;
+
+ aPt.x = aPos.X();
+ aPt.y = static_cast<Os2SalGraphics&>(rGraphics).mnHeight - aPos.Y();
+
+ // ft2lib doesn't work with printer hps, so we fallback to codepage printing
+ // until cp1200 support will work.
+ if (static_cast<Os2SalGraphics&>(rGraphics).mbPrinter) {
+ // convert to codepage
+ ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() );
+ // gliph size is not recalculated, so it could be wrong!
+ rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
+ &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(),
+ (LONG*)mpGlyphAdvances, 0);
+ } else {
+ // try unicode rendering to screen
+ rc = Ft2CharStringPosAtW( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
+ &aPt, NULL, CHS_VECTOR, mnGlyphCount, (LPWSTR)mpOutGlyphs,
+ (LONG*)mpGlyphAdvances, 0);
+ if (rc == GPI_ERROR) {
+ // if *W fails, convert to codepage and use *A (fallback to GPI into ft2)
+ ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() );
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("Os2SalLayout::DrawText HPS %08x PosAtW failed '%s'!\n",static_cast<Os2SalGraphics&>(rGraphics).mhPS,str.GetBuffer());
+#endif
+ // gliph size is not recalculated, so it could be wrong!
+ rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
+ &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(),
+ (LONG*)mpGlyphAdvances, 0);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Os2SalLayout::FillDXArray( long* pDXArray ) const
+{
+ if( !mnWidth )
+ {
+ long mnWidth = mnBaseAdv;
+ for( int i = 0; i < mnGlyphCount; ++i )
+ mnWidth += mpGlyphAdvances[ i ];
+ }
+
+ if( pDXArray != NULL )
+ {
+ for( int i = 0; i < mnCharCount; ++i )
+ pDXArray[ i ] = mpCharWidths[ i ];
+ }
+
+ return mnWidth;
+}
+
+// -----------------------------------------------------------------------
+
+int Os2SalLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const
+// NOTE: the nFactor is used to prevent rounding errors for small nCharExtra values
+{
+ if( mnWidth )
+ if( (mnWidth * nFactor + mnCharCount * nCharExtra) <= nMaxWidth )
+ return STRING_LEN;
+
+ long nExtraWidth = mnBaseAdv * nFactor;
+ for( int n = 0; n < mnCharCount; ++n )
+ {
+ // skip unused characters
+ if( mpChars2Glyphs && (mpChars2Glyphs[n] < 0) )
+ continue;
+ // add char widths until max
+ nExtraWidth += mpCharWidths[ n ] * nFactor;
+ if( nExtraWidth >= nMaxWidth )
+ return (mnMinCharPos + n);
+ nExtraWidth += nCharExtra;
+ }
+
+ return STRING_LEN;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::GetCaretPositions( int nMaxIdx, long* pCaretXArray ) const
+{
+ long nXPos = mnBaseAdv;
+
+ if( !mpGlyphs2Chars )
+ {
+ for( int i = 0; i < nMaxIdx; i += 2 )
+ {
+ pCaretXArray[ i ] = nXPos;
+ nXPos += mpGlyphAdvances[ i>>1 ];
+ pCaretXArray[ i+1 ] = nXPos;
+ }
+ }
+ else
+ {
+ int i;
+ for( i = 0; i < nMaxIdx; ++i )
+ pCaretXArray[ i ] = -1;
+
+ // assign glyph positions to character positions
+ for( i = 0; i < mnGlyphCount; ++i )
+ {
+ int nCurrIdx = mpGlyphs2Chars[ i ] - mnMinCharPos;
+ long nXRight = nXPos + mpCharWidths[ nCurrIdx ];
+ nCurrIdx *= 2;
+ if( !(mpGlyphRTLFlags && mpGlyphRTLFlags[i]) )
+ {
+ // normal positions for LTR case
+ pCaretXArray[ nCurrIdx ] = nXPos;
+ pCaretXArray[ nCurrIdx+1 ] = nXRight;
+ }
+ else
+ {
+ // reverse positions for RTL case
+ pCaretXArray[ nCurrIdx ] = nXRight;
+ pCaretXArray[ nCurrIdx+1 ] = nXPos;
+ }
+ nXPos += mpGlyphAdvances[ i ];
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::Justify( long nNewWidth )
+{
+ long nOldWidth = mnWidth;
+ mnWidth = nNewWidth;
+
+ if( mnGlyphCount <= 0 )
+ return;
+
+ if( nNewWidth == nOldWidth )
+ return;
+
+ // the rightmost glyph cannot be stretched
+ const int nRight = mnGlyphCount - 1;
+ nOldWidth -= mpGlyphAdvances[ nRight ];
+ nNewWidth -= mpGlyphAdvances[ nRight ];
+
+ // count stretchable glyphs
+ int nStretchable = 0, i;
+ for( i = 0; i < nRight; ++i )
+ if( mpGlyphAdvances[i] >= 0 )
+ ++nStretchable;
+
+ // stretch these glyphs
+ int nDiffWidth = nNewWidth - nOldWidth;
+ for( i = 0; (i < nRight) && (nStretchable > 0); ++i )
+ {
+ if( mpGlyphAdvances[i] <= 0 )
+ continue;
+ int nDeltaWidth = nDiffWidth / nStretchable;
+ mpGlyphAdvances[i] += nDeltaWidth;
+ --nStretchable;
+ nDiffWidth -= nDeltaWidth;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
+{
+ SalLayout::AdjustLayout( rArgs );
+
+ // adjust positions if requested
+ if( rArgs.mpDXArray )
+ ApplyDXArray( rArgs );
+ else if( rArgs.mnLayoutWidth )
+ Justify( rArgs.mnLayoutWidth );
+ else
+ return;
+
+ // recalculate virtual char widths if they were changed
+ if( mpCharWidths != mpGlyphAdvances )
+ {
+ int i;
+ if( !mpGlyphs2Chars )
+ {
+ // standard LTR case
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpCharWidths[ i ] = mpGlyphAdvances[ i ];
+ }
+ else
+ {
+ // BiDi or complex case
+ for( i = 0; i < mnCharCount; ++i )
+ mpCharWidths[ i ] = 0;
+ for( i = 0; i < mnGlyphCount; ++i )
+ {
+ int j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos;
+ if( j >= 0 )
+ mpCharWidths[ j ] += mpGlyphAdvances[ i ];
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::ApplyDXArray( const ImplLayoutArgs& rArgs )
+{
+ // try to avoid disturbance of text flow for LSB rounding case;
+ const long* pDXArray = rArgs.mpDXArray;
+
+ int i = 0;
+ long nOldWidth = mnBaseAdv;
+ for(; i < mnCharCount; ++i )
+ {
+ int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i];
+ if( j >= 0 )
+ {
+ nOldWidth += mpGlyphAdvances[ j ];
+ int nDiff = nOldWidth - pDXArray[ i ];
+
+ // disabled because of #104768#
+ // works great for static text, but problems when typing
+ // if( nDiff>+1 || nDiff<-1 )
+ // only bother with changing anything when something moved
+ if( nDiff != 0 )
+ break;
+ }
+ }
+ if( i >= mnCharCount )
+ return;
+
+ if( !mpGlyphOrigAdvs )
+ {
+ mpGlyphOrigAdvs = new int[ mnGlyphCount ];
+ for( i = 0; i < mnGlyphCount; ++i )
+ mpGlyphOrigAdvs[ i ] = mpGlyphAdvances[ i ];
+ }
+
+ mnWidth = mnBaseAdv;
+ for( i = 0; i < mnCharCount; ++i )
+ {
+ int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i];
+ if( j >= 0 )
+ mpGlyphAdvances[j] = pDXArray[i] - mnWidth;
+ mnWidth = pDXArray[i];
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::MoveGlyph( int nStart, long nNewXPos )
+{
+ if( nStart > mnGlyphCount )
+ return;
+
+ // calculate the current x-position of the requested glyph
+ // TODO: cache absolute positions
+ int nXPos = mnBaseAdv;
+ for( int i = 0; i < nStart; ++i )
+ nXPos += mpGlyphAdvances[i];
+
+ // calculate the difference to the current glyph position
+ int nDelta = nNewXPos - nXPos;
+
+ // adjust the width of the layout if it was already cached
+ if( mnWidth )
+ mnWidth += nDelta;
+
+ // depending on whether the requested glyph is leftmost in the layout
+ // adjust either the layout's or the requested glyph's relative position
+ if( nStart > 0 )
+ mpGlyphAdvances[ nStart-1 ] += nDelta;
+ else
+ mnBaseAdv += nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::DropGlyph( int nStart )
+{
+ mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalLayout::Simplify( bool bIsBase )
+{
+ // return early if no glyph has been dropped
+ int i = mnGlyphCount;
+ while( (--i >= 0) && (mpOutGlyphs[ i ] != DROPPED_OUTGLYPH) );
+ if( i < 0 )
+ return;
+
+ // convert the layout to a sparse layout if it is not already
+ if( !mpGlyphs2Chars )
+ {
+ mpGlyphs2Chars = new int[ mnGlyphCount ];
+ mpCharWidths = new int[ mnCharCount ];
+ // assertion: mnGlyphCount == mnCharCount
+ for( int k = 0; k < mnGlyphCount; ++k )
+ {
+ mpGlyphs2Chars[ k ] = mnMinCharPos + k;
+ mpCharWidths[ k ] = mpGlyphAdvances[ k ];
+ }
+ }
+
+ // remove dropped glyphs that are rightmost in the layout
+ for( i = mnGlyphCount; --i >= 0; )
+ {
+ if( mpOutGlyphs[ i ] != DROPPED_OUTGLYPH )
+ break;
+ if( mnWidth )
+ mnWidth -= mpGlyphAdvances[ i ];
+ int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos;
+ if( nRelCharPos >= 0 )
+ mpCharWidths[ nRelCharPos ] = 0;
+ }
+ mnGlyphCount = i + 1;
+
+ // keep original glyph widths around
+ if( !mpGlyphOrigAdvs )
+ {
+ mpGlyphOrigAdvs = new int[ mnGlyphCount ];
+ for( int k = 0; k < mnGlyphCount; ++k )
+ mpGlyphOrigAdvs[ k ] = mpGlyphAdvances[ k ];
+ }
+
+ // remove dropped glyphs inside the layout
+ int nNewGC = 0;
+ for( i = 0; i < mnGlyphCount; ++i )
+ {
+ if( mpOutGlyphs[ i ] == DROPPED_OUTGLYPH )
+ {
+ // adjust relative position to last valid glyph
+ int nDroppedWidth = mpGlyphAdvances[ i ];
+ mpGlyphAdvances[ i ] = 0;
+ if( nNewGC > 0 )
+ mpGlyphAdvances[ nNewGC-1 ] += nDroppedWidth;
+ else
+ mnBaseAdv += nDroppedWidth;
+
+ // zero the virtual char width for the char that has a fallback
+ int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos;
+ if( nRelCharPos >= 0 )
+ mpCharWidths[ nRelCharPos ] = 0;
+ }
+ else
+ {
+ if( nNewGC != i )
+ {
+ // rearrange the glyph array to get rid of the dropped glyph
+ mpOutGlyphs[ nNewGC ] = mpOutGlyphs[ i ];
+ mpGlyphAdvances[ nNewGC ] = mpGlyphAdvances[ i ];
+ mpGlyphOrigAdvs[ nNewGC ] = mpGlyphOrigAdvs[ i ];
+ mpGlyphs2Chars[ nNewGC ] = mpGlyphs2Chars[ i ];
+ }
+ ++nNewGC;
+ }
+ }
+
+ mnGlyphCount = nNewGC;
+ if( mnGlyphCount <= 0 )
+ mnWidth = mnBaseAdv = 0;
+}
+
+// =======================================================================
+
+SalLayout* Os2SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
+{
+ Os2SalLayout* pLayout = NULL;
+ DBG_ASSERT( mpOs2FontEntry[nFallbackLevel], "WinSalGraphics mpWinFontEntry==NULL");
+
+ const ImplOs2FontData& rFontFace = *mpOs2FontData[ nFallbackLevel ];
+ ImplOs2FontEntry& rFontInstance = *mpOs2FontEntry[ nFallbackLevel ];
+
+ {
+#ifdef GCP_KERN_HACK
+ if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) && !rFontInstance.HasKernData() )
+ {
+ // TODO: directly cache kerning info in the rFontInstance
+ // TODO: get rid of kerning methods+data in WinSalGraphics object
+ GetKernPairs( 0, NULL );
+ rFontInstance.SetKernData( mnFontKernPairCount, mpFontKernPairs );
+ }
+#endif // GCP_KERN_HACK
+
+ //BYTE eCharSet = ANSI_CHARSET;
+ //if( mpLogFont )
+ // eCharSet = mpLogFont->lfCharSet;
+ pLayout = new Os2SalLayout( mhPS, 0, rFontFace, rFontInstance );
+ }
+
+ if( mfFontScale != 1.0 )
+ pLayout->SetFontScale( mfFontScale );
+
+ return pLayout;
+}
+
+// =======================================================================
+
+ImplOs2FontEntry::ImplOs2FontEntry( ImplFontSelectData& rFSD )
+: ImplFontEntry( rFSD ),
+ maWidthMap( 512 )
+#ifdef GCP_KERN_HACK
+ ,mpKerningPairs( NULL )
+ ,mnKerningPairs( -1 )
+#endif // GCP_KERN_HACK
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplOs2FontEntry::~ImplOs2FontEntry()
+{
+#ifdef GCP_KERN_HACK
+ delete[] mpKerningPairs;
+#endif // GCP_KERN_HACK
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef GCP_KERN_HACK
+bool ImplOs2FontEntry::HasKernData() const
+{
+ return (mnKerningPairs >= 0);
+}
+
+// -----------------------------------------------------------------------
+
+void ImplOs2FontEntry::SetKernData( int nPairCount, const KERNINGPAIRS* pPairData )
+{
+ mnKerningPairs = nPairCount;
+ mpKerningPairs = new KERNINGPAIRS[ mnKerningPairs ];
+ ::memcpy( mpKerningPairs, (const void*)pPairData, nPairCount*sizeof(KERNINGPAIRS) );
+}
+
+// -----------------------------------------------------------------------
+
+int ImplOs2FontEntry::GetKerning( sal_Unicode cLeft, sal_Unicode cRight ) const
+{
+ int nKernAmount = 0;
+ if( mpKerningPairs )
+ {
+ const KERNINGPAIRS aRefPair = { cLeft, cRight, 0 };
+ const KERNINGPAIRS* pFirstPair = mpKerningPairs;
+ const KERNINGPAIRS* pEndPair = mpKerningPairs + mnKerningPairs;
+ const KERNINGPAIRS* pPair = std::lower_bound( pFirstPair,
+ pEndPair, aRefPair, ImplCmpKernData );
+ if( (pPair != pEndPair)
+ && (pPair->sFirstChar == aRefPair.sFirstChar)
+ && (pPair->sSecondChar == aRefPair.sSecondChar) )
+ nKernAmount = pPair->lKerningAmount;
+ }
+
+ return nKernAmount;
+}
+#endif // GCP_KERN_HACK
+
+// =======================================================================
+
+ImplFontData* ImplOs2FontData::Clone() const
+{
+ if( mpUnicodeMap )
+ mpUnicodeMap->AddReference();
+ ImplFontData* pClone = new ImplOs2FontData( *this );
+ return pClone;
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontEntry* ImplOs2FontData::CreateFontInstance( ImplFontSelectData& rFSD ) const
+{
+ //debug_printf("ImplOs2FontData::CreateFontInstance\n");
+ ImplFontEntry* pEntry = new ImplOs2FontEntry( rFSD );
+ return pEntry;
+}
+
+// =======================================================================
+
diff --git a/vcl/os2/source/gdi/salbmp.cxx b/vcl/os2/source/gdi/salbmp.cxx
new file mode 100644
index 000000000000..3d8f86ddcd1e
--- /dev/null
+++ b/vcl/os2/source/gdi/salbmp.cxx
@@ -0,0 +1,737 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svpm.h>
+
+#define _SV_SALBMP_CXX
+#include <rtl/alloc.h>
+#include <vcl/salbtype.hxx>
+#include <salgdi.h>
+#include <saldata.hxx>
+#include <salbmp.h>
+#include <vcl/bitmap.hxx> // for BitmapSystemData
+#include <string.h>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+// -----------
+// - Inlines -
+// -----------
+
+inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex )
+{
+ BYTE& rByte = pScanline[ nX >> 1 ];
+
+ ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) :
+ ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) );
+}
+
+// -------------
+// - Os2SalBitmap -
+// -------------
+
+Os2SalBitmap::Os2SalBitmap() :
+ mhDIB ( 0 ),
+ mhDIB1Subst ( 0 ),
+ mhDDB ( 0 ),
+ mnBitCount ( 0 )
+{
+}
+
+// ------------------------------------------------------------------
+
+Os2SalBitmap::~Os2SalBitmap()
+{
+ Destroy();
+}
+
+// ------------------------------------------------------------------
+
+bool Os2SalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
+{
+ BOOL bRet = TRUE;
+
+ if( bDIB )
+ mhDIB = (HANDLE) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
+ else
+ mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
+
+ if( mhDIB )
+ {
+ // bitmap-header is the beginning of memory block
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) mhDIB;
+
+ maSize = Size( pBIH->cx, pBIH->cy );
+ mnBitCount = pBIH->cBitCount;
+
+ if( mnBitCount )
+ mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
+ }
+ else if( mhDDB )
+ {
+ BITMAPINFOHEADER2 aDDBInfoHeader;
+
+ aDDBInfoHeader.cbFix = sizeof( aDDBInfoHeader );
+
+ if( GpiQueryBitmapInfoHeader( mhDDB, &aDDBInfoHeader ) )
+ {
+ maSize = Size( aDDBInfoHeader.cx, aDDBInfoHeader.cy );
+ mnBitCount = aDDBInfoHeader.cPlanes * aDDBInfoHeader.cBitCount;
+
+ if( mnBitCount )
+ {
+ mnBitCount = ( mnBitCount <= 1 ) ? 1 :
+ ( mnBitCount <= 4 ) ? 4 :
+ ( mnBitCount <= 8 ) ? 8 : 24;
+ }
+ }
+ else
+ {
+ mhDDB = 0;
+ bRet = FALSE;
+ }
+
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+bool Os2SalBitmap::Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
+{
+ bool bRet = FALSE;
+
+ mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
+
+ if( mhDIB )
+ {
+ maSize = rSize;
+ mnBitCount = nBitCount;
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+bool Os2SalBitmap::Create( const SalBitmap& rSSalBitmap )
+{
+ bool bRet = FALSE;
+ const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
+
+ if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB )
+ {
+ HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB,
+ rSalBitmap.mhDIB != 0 );
+
+ if( hNewHdl )
+ {
+ if( rSalBitmap.mhDIB )
+ mhDIB = (HANDLE) hNewHdl;
+ else if( rSalBitmap.mhDDB )
+ mhDDB = (HBITMAP) hNewHdl;
+
+ maSize = rSalBitmap.maSize;
+ mnBitCount = rSalBitmap.mnBitCount;
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
+{
+ bool bRet = FALSE;
+ const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp);
+ Os2SalGraphics* pGraphics = static_cast<Os2SalGraphics*>(pSGraphics);
+
+ if( rSalBmp.mhDIB )
+ {
+ HPS hPS = pGraphics->mhPS;
+ HBITMAP hNewDDB;
+ BITMAPINFOHEADER2 aInfoHeader;
+ const Size aSize( rSalBmp.GetSize() );
+ long nFormat[ 2 ];
+
+ memset( &aInfoHeader, 0, sizeof( aInfoHeader ) );
+ aInfoHeader.cbFix = 16;
+ aInfoHeader.cx = aSize.Width();
+ aInfoHeader.cy = aSize.Height();
+
+ GpiQueryDeviceBitmapFormats( hPS, 2L, (PLONG) &nFormat );
+ aInfoHeader.cPlanes = nFormat[ 0 ];
+ aInfoHeader.cBitCount = nFormat[ 1 ];
+
+ // ! wegen Postscript-Treiber
+ if( !aInfoHeader.cBitCount )
+ aInfoHeader.cBitCount = 24;
+ else if( ( aInfoHeader.cPlanes == 1 ) && ( aInfoHeader.cBitCount == 1 ) )
+ aInfoHeader.cBitCount = 4;
+
+ // BitCount == 1 ist wegen aller moeglichen Treiberfehler nicht moeglich
+ if( rSalBmp.GetBitCount() == 1 )
+ {
+ HANDLE hTmp = ImplCreateDIB4FromDIB1( rSalBmp.mhDIB );
+ PBYTE pBits = (PBYTE) hTmp + *(ULONG*) hTmp + ImplGetDIBColorCount( hTmp ) * sizeof( RGB2 );
+
+ hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) hTmp );
+ rtl_freeMemory( (void*)hTmp );
+ }
+ else
+ {
+ PBYTE pBits = (PBYTE) rSalBmp.mhDIB + *(ULONG*) rSalBmp.mhDIB + ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGB2 );
+ hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) rSalBmp.mhDIB );
+ }
+
+ aInfoHeader.cbFix = sizeof( aInfoHeader );
+
+ if( hNewDDB && GpiQueryBitmapInfoHeader( hNewDDB, &aInfoHeader ) )
+ {
+ mhDDB = hNewDDB;
+ maSize = Size( aInfoHeader.cx, aInfoHeader.cy );
+ mnBitCount = aInfoHeader.cPlanes * aInfoHeader.cBitCount;
+
+ if( mnBitCount )
+ {
+ mnBitCount = ( mnBitCount <= 1 ) ? 1 :
+ ( mnBitCount <= 4 ) ? 4 :
+ ( mnBitCount <= 8 ) ? 8 : 24;
+ }
+
+ bRet = TRUE;
+ }
+ else if( hNewDDB )
+ GpiDeleteBitmap( hNewDDB );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, USHORT nNewBitCount )
+{
+ bool bRet = FALSE;
+ const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp);
+
+ if( rSalBmp.mhDDB )
+ {
+ mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
+
+ if( mhDIB )
+ {
+ // bitmap-header is the beginning of memory block
+ PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB;
+ const int nLines = (int) rSalBmp.maSize.Height();
+ PBYTE pBits = (PBYTE) pBI + *(ULONG*) pBI + ImplGetDIBColorCount( mhDIB ) * sizeof( RGB2 );
+ SIZEL aSizeL = { rSalBmp.maSize.Width(), nLines };
+ HAB hAB = GetSalData()->mhAB;
+ DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+ HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ HBITMAP hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, rSalBmp.mhDDB );
+
+ if( GpiQueryBitmapBits( hMemPS, 0, nLines, pBits, pBI ) == nLines )
+ {
+ maSize = rSalBmp.maSize;
+ mnBitCount = nNewBitCount;
+ bRet = TRUE;
+ }
+ else
+ {
+ rtl_freeMemory( (void*)mhDIB );
+ mhDIB = 0;
+ }
+
+ Ft2SetBitmap( hMemPS, hMemOld );
+ Ft2DestroyPS( hMemPS );
+ DevCloseDC( hMemDC );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+void Os2SalBitmap::Destroy()
+{
+ if( mhDIB )
+ rtl_freeMemory( (void*)mhDIB );
+ else if( mhDDB )
+ GpiDeleteBitmap( mhDDB );
+
+ if( mhDIB1Subst )
+ {
+ rtl_freeMemory( (void*)mhDIB1Subst );
+ mhDIB1Subst = NULL;
+ }
+
+ maSize = Size();
+ mnBitCount = 0;
+}
+
+// ------------------------------------------------------------------
+
+void Os2SalBitmap::ImplReplacehDIB1Subst( HANDLE hDIB1Subst )
+{
+ if( mhDIB1Subst )
+ rtl_freeMemory( (void*)mhDIB1Subst );
+
+ mhDIB1Subst = hDIB1Subst;
+}
+
+// ------------------------------------------------------------------
+
+USHORT Os2SalBitmap::ImplGetDIBColorCount( HANDLE hDIB )
+{
+ USHORT nColors = 0;
+
+ if( hDIB )
+ {
+ // bitmap infos can be found at the beginning of the memory
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hDIB;
+
+ if( pBIH->cBitCount <= 8 )
+ {
+ if( pBIH->cclrUsed )
+ nColors = (USHORT) pBIH->cclrUsed;
+ else
+ nColors = 1 << pBIH->cBitCount;
+ }
+ }
+
+ return nColors;
+}
+
+// ------------------------------------------------------------------
+
+HANDLE Os2SalBitmap::ImplCreateDIB( const Size& rSize, USHORT nBits, const BitmapPalette& rPal )
+{
+ DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24, "Unsupported BitCount!" );
+
+ HANDLE hDIB = 0;
+
+ if ( rSize.Width() && rSize.Height() && ( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24 ) )
+ {
+ const ULONG nImageSize = AlignedWidth4Bytes( nBits * rSize.Width() ) * rSize.Height();
+ const USHORT nColors = ( nBits <= 8 ) ? ( 1 << nBits ) : 0;
+
+ hDIB = (HANDLE) rtl_allocateZeroMemory( sizeof( BITMAPINFOHEADER2 ) + nColors * sizeof( RGB2 ) + nImageSize );
+
+ if( hDIB )
+ {
+ // bitmap infos can be found at the beginning of the memory
+ PBITMAPINFO2 pBI = (PBITMAPINFO2) hDIB;
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI;
+
+ pBIH->cbFix = sizeof( BITMAPINFOHEADER2 );
+ pBIH->cx = rSize.Width();
+ pBIH->cy = rSize.Height();
+ pBIH->cPlanes = 1;
+ pBIH->cBitCount = nBits;
+ pBIH->ulCompression = BCA_UNCOMP; // BI_RGB;
+ pBIH->cbImage = nImageSize;
+ pBIH->cxResolution = 0;
+ pBIH->cyResolution = 0;
+ pBIH->cclrUsed = 0;
+ pBIH->cclrImportant = 0;
+
+ // Rest auf 0 setzen
+ memset( (PBYTE) &pBIH->usUnits, 0, (PBYTE) pBI->argbColor - (PBYTE) &pBIH->usUnits );
+
+ if( nColors )
+ {
+ const USHORT nMinCount = Min( nColors, rPal.GetEntryCount() );
+
+ if( nMinCount )
+ memcpy( pBI->argbColor, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGB2 ) );
+ }
+ }
+ }
+
+ return hDIB;
+}
+
+// ------------------------------------------------------------------
+
+HANDLE Os2SalBitmap::ImplCreateDIB4FromDIB1( HANDLE hDIB1 )
+{
+ PBITMAPINFO2 pBI = (PBITMAPINFO2) hDIB1;
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI;
+ PBYTE pBits = (PBYTE) pBI + *(ULONG*) pBIH + Os2SalBitmap::ImplGetDIBColorCount( hDIB1 ) * sizeof( RGB2 );
+ ULONG nWidth = pBIH->cx, nHeight = pBIH->cy;
+ ULONG nAligned = AlignedWidth4Bytes( nWidth );
+ ULONG nAligned4 = AlignedWidth4Bytes( nWidth << 2 );
+ ULONG nSize4 = sizeof( BITMAPINFOHEADER2 ) + ( sizeof( RGB2 ) << 4 ) + nAligned4 * nHeight;
+ PBYTE pDIB4 = (PBYTE) rtl_allocateZeroMemory( nSize4 );
+ PBITMAPINFO2 pBI4 = (PBITMAPINFO2) pDIB4;
+ PBITMAPINFOHEADER2 pBIH4 = (PBITMAPINFOHEADER2) pBI4;
+ BYTE aMap[ 4 ] = { 0x00, 0x01, 0x10, 0x11 };
+
+ memset( pBIH4, 0, sizeof( BITMAPINFOHEADER2 ) );
+ pBIH4->cbFix = sizeof( BITMAPINFOHEADER2 );
+ pBIH4->cx = nWidth;
+ pBIH4->cy = nHeight;
+ pBIH4->cPlanes = 1;
+ pBIH4->cBitCount = 4;
+
+ // die ersten beiden Eintraege der 1Bit-Farbtabelle kopieren
+ memcpy( pBI4->argbColor, pBI->argbColor, sizeof( RGB2 ) << 1 );
+
+ PBYTE pBits4 = (PBYTE) pBI4 + *(ULONG*) pBIH4 + ( sizeof( RGB2 ) << 4 );
+
+ // 4Bit-DIB-Bilddaten setzen
+ for( ULONG nY = 0UL; nY < nHeight; nY++ )
+ {
+ PBYTE pTmp = pBits; pBits += nAligned;
+ PBYTE pTmp4 = pBits4; pBits4 += nAligned4;
+
+ for( ULONG nX = 0UL; nX < nWidth; nX += 8UL )
+ {
+ *pTmp4++ = aMap[ ( *pTmp >> 6 ) & 3 ];
+ *pTmp4++ = aMap[ ( *pTmp >> 4 ) & 3 ];
+ *pTmp4++ = aMap[ ( *pTmp >> 2 ) & 3 ];
+ *pTmp4++ = aMap[ *pTmp++ & 3 ];
+ }
+ }
+
+ return (HANDLE) pDIB4;
+}
+
+// ------------------------------------------------------------------
+
+HANDLE Os2SalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, BOOL bDIB )
+{
+ HANDLE hCopy = 0;
+
+ if( bDIB && hHdl )
+ {
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hHdl;
+ const ULONG nSize = sizeof( BITMAPINFOHEADER2 )
+ + ImplGetDIBColorCount( hHdl ) * sizeof( RGB2 ) +
+ ( pBIH->cbImage ? pBIH->cbImage : AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) );
+
+ BYTE* pCopy = (BYTE*)rtl_allocateZeroMemory( nSize );
+ memcpy( pCopy, (BYTE*) hHdl, nSize );
+ hCopy = (HANDLE) pCopy;
+ }
+ else if( hHdl )
+ {
+ HAB hAB = GetSalData()->mhAB;
+ HDC hSrcMemDC;
+ HDC hDestMemDC;
+ HPS hSrcMemPS;
+ HPS hDestMemPS;
+ HBITMAP hCopyBitmap;
+ BITMAPINFOHEADER2 aInfoHeader;
+ DEVOPENSTRUC aDevOpenStruc;
+ SIZEL size;
+
+ aInfoHeader.cbFix = sizeof( BITMAPINFOHEADER2 );
+ GpiQueryBitmapInfoHeader( hHdl, &aInfoHeader );
+ size.cx = aInfoHeader.cx;
+ size.cy = aInfoHeader.cy;
+
+ // Memory DCs erzeugen
+ aDevOpenStruc.pszLogAddress = 0;
+ aDevOpenStruc.pszDriverName = (PSZ)"DISPLAY";
+
+ hSrcMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ hDestMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+
+ // Memory PSs erzeugen
+ hSrcMemPS = Ft2CreatePS( hAB, hSrcMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ hDestMemPS = Ft2CreatePS( hAB, hDestMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+
+ Ft2SetBitmap( hSrcMemPS, hHdl );
+
+ if( !hHdl )
+ {
+ memset( &aInfoHeader, 0, sizeof( BITMAPINFOHEADER2 ) );
+ aInfoHeader.cbFix = sizeof( BITMAPINFOHEADER2 );
+ aInfoHeader.cx = 0;
+ aInfoHeader.cy = 0;
+ aInfoHeader.cPlanes = 1;
+ aInfoHeader.cBitCount = 1;
+ }
+
+ hCopy = GpiCreateBitmap( hDestMemPS, &aInfoHeader, 0, NULL, NULL );
+ Ft2SetBitmap( hDestMemPS, hCopy );
+
+ POINTL pts[3];
+
+ pts[0].x = 0;
+ pts[0].y = 0;
+ pts[1].x = size.cx;
+ pts[1].y = size.cy;
+ pts[2].x = 0;
+ pts[2].y = 0;
+
+ GpiBitBlt( hDestMemPS, hSrcMemPS, 3, pts, ROP_SRCCOPY, BBO_IGNORE );
+
+ Ft2SetBitmap( hSrcMemPS, (HBITMAP)0L);
+ Ft2SetBitmap( hDestMemPS, (HBITMAP)0L);
+ Ft2Associate( hSrcMemPS, NULLHANDLE );
+ Ft2Associate( hDestMemPS, NULLHANDLE );
+ Ft2DestroyPS( hSrcMemPS );
+ Ft2DestroyPS( hDestMemPS );
+ DevCloseDC( hSrcMemDC );
+ DevCloseDC( hDestMemDC );
+ }
+
+ return hCopy;
+}
+
+// ------------------------------------------------------------------
+
+BitmapBuffer* Os2SalBitmap::AcquireBuffer( bool bReadOnly )
+{
+ BitmapBuffer* pBuffer = NULL;
+
+ if( mhDIB )
+ {
+ // bitmap infos can be found at the beginning of the memory
+ PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB;
+ PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI;
+
+ if( ( pBIH->ulCompression == BCA_RLE4 ) || ( pBIH->ulCompression == BCA_RLE8 ) )
+ {
+ Size aSizePix( pBIH->cx, pBIH->cy );
+ HANDLE hNewDIB = ImplCreateDIB( aSizePix, pBIH->cBitCount, BitmapPalette() );
+
+ if( hNewDIB )
+ {
+ // bitmap infos can be found at the beginning of the memory
+ PBITMAPINFO2 pNewBI = (PBITMAPINFO2) hNewDIB;
+ PBITMAPINFOHEADER2 pNewBIH = (PBITMAPINFOHEADER2) pNewBI;
+ const USHORT nColorCount = ImplGetDIBColorCount( hNewDIB );
+ const ULONG nOffset = *(ULONG*) pBI + nColorCount * sizeof( RGB2 );
+ BYTE* pOldBits = (BYTE*) pBI + nOffset;
+ BYTE* pNewBits = (BYTE*) pNewBI + nOffset;
+
+ memcpy( pNewBI, pBI, nOffset );
+ pNewBIH->ulCompression = 0;
+ ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->ulCompression == BCA_RLE4 );
+
+ rtl_freeMemory( (void*)mhDIB );
+
+ mhDIB = hNewDIB;
+ pBI = pNewBI;
+ pBIH = pNewBIH;
+ }
+ }
+
+ if( pBIH->cPlanes == 1 )
+ {
+ pBuffer = new BitmapBuffer;
+
+ pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
+ ( pBIH->cBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
+ pBIH->cBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
+ pBIH->cBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
+ pBIH->cBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
+ pBIH->cBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
+ pBIH->cBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
+
+ if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
+ {
+ pBuffer->mnWidth = maSize.Width();
+ pBuffer->mnHeight = maSize.Height();
+ pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->cBitCount );
+ pBuffer->mnBitCount = (USHORT) pBIH->cBitCount;
+
+ if( pBuffer->mnBitCount <= 8 )
+ {
+ const USHORT nPalCount = ImplGetDIBColorCount( mhDIB );
+
+ pBuffer->maPalette.SetEntryCount( nPalCount );
+
+ if( nPalCount )
+ memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->argbColor, nPalCount * sizeof( RGB2 ) );
+
+ pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI + nPalCount * sizeof( RGB2 );
+ }
+ else
+ pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI;
+ }
+ else
+ {
+ delete pBuffer;
+ pBuffer = NULL;
+ }
+ }
+ }
+
+ if( pBuffer && mhDIB1Subst )
+ {
+ rtl_freeMemory( (void*)mhDIB1Subst );
+ mhDIB1Subst = 0;
+ }
+
+ return pBuffer;
+}
+
+// ------------------------------------------------------------------
+
+void Os2SalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
+{
+ if( pBuffer )
+ {
+ if( mhDIB )
+ {
+ if( !bReadOnly && !!pBuffer->maPalette )
+ {
+ // bitmap infos can be found at the beginning of the memory
+ PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB;
+ const USHORT nCount = pBuffer->maPalette.GetEntryCount();
+
+ if( nCount )
+ memcpy( pBI->argbColor, pBuffer->maPalette.ImplGetColorBuffer(), nCount * sizeof( RGB2 ) );
+ }
+ }
+
+ delete pBuffer;
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Os2SalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
+ const Size& rSizePixel, BOOL bRLE4 )
+{
+ HPBYTE pRLE = (HPBYTE) pSrcBuf;
+ HPBYTE pDIB = (HPBYTE) pDstBuf;
+ HPBYTE pRow = (HPBYTE) pDstBuf;
+ ULONG nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
+ HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
+ ULONG nCountByte;
+ ULONG nRunByte;
+ ULONG nX = 0;
+ ULONG i;
+ BYTE cTmp;
+ BOOL bEndDecoding = FALSE;
+
+ if( pRLE && pDIB )
+ {
+ do
+ {
+ if( !( nCountByte = *pRLE++ ) )
+ {
+ nRunByte = *pRLE++;
+
+ if( nRunByte > 2UL )
+ {
+ if( bRLE4 )
+ {
+ nCountByte = nRunByte >> 1UL;
+
+ for( i = 0; i < nCountByte; i++ )
+ {
+ cTmp = *pRLE++;
+ ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
+ ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
+ }
+
+ if( nRunByte & 1 )
+ ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
+
+ if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
+ pRLE++;
+ }
+ else
+ {
+ memcpy( &pDIB[ nX ], pRLE, nRunByte );
+ pRLE += nRunByte;
+ nX += nRunByte;
+
+ if( nRunByte & 1 )
+ pRLE++;
+ }
+ }
+ else if( !nRunByte )
+ {
+ pDIB = ( pRow += nWidthAl );
+ nX = 0UL;
+ }
+ else if( nRunByte == 1 )
+ bEndDecoding = TRUE;
+ else
+ {
+ nX += *pRLE++;
+ pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
+ }
+ }
+ else
+ {
+ cTmp = *pRLE++;
+
+ if( bRLE4 )
+ {
+ nRunByte = nCountByte >> 1;
+
+ for( i = 0; i < nRunByte; i++ )
+ {
+ ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
+ ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
+ }
+
+ if( nCountByte & 1 )
+ ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
+ }
+ else
+ {
+ for( i = 0; i < nCountByte; i++ )
+ pDIB[ nX++ ] = cTmp;
+ }
+ }
+ }
+ while( !bEndDecoding && ( pDIB <= pLast ) );
+ }
+}
+
+bool Os2SalBitmap::GetSystemData( BitmapSystemData& rData )
+{
+ bool bRet = false;
+ if( mhDIB || mhDDB )
+ {
+ bRet = true;
+ rData.pDIB = (void*)mhDIB;
+ rData.pDDB = (void*)mhDDB;
+ }
+ return bRet;
+}
diff --git a/vcl/os2/source/gdi/salgdi.cxx b/vcl/os2/source/gdi/salgdi.cxx
new file mode 100644
index 000000000000..dff1557170fb
--- /dev/null
+++ b/vcl/os2/source/gdi/salgdi.cxx
@@ -0,0 +1,1044 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <svpm.h>
+
+#define _SV_SALGDI_CXX
+#include <tools/debug.hxx>
+#include <saldata.hxx>
+#include <salgdi.h>
+#include <tools/debug.hxx>
+#include <salframe.h>
+#include <tools/poly.hxx>
+#ifndef _RTL_STRINGBUF_HXX
+#include <rtl/strbuf.hxx>
+#endif
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+// ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern
+#define SAL_PRINTER_CLIPPATH 1
+// #define SAL_PRINTER_POLYPATH 1
+
+// =======================================================================
+
+void ImplInitSalGDI()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFreeSalGDI()
+{
+ SalData* pSalData = GetSalData();
+
+ // delete icon cache
+ SalIcon* pIcon = pSalData->mpFirstIcon;
+ while( pIcon )
+ {
+ SalIcon* pTmp = pIcon->pNext;
+ WinDestroyPointer( pIcon->hIcon );
+ delete pIcon;
+ pIcon = pTmp;
+ }
+
+}
+
+// =======================================================================
+
+void ImplSalInitGraphics( Os2SalGraphics* pData )
+{
+ GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalDeInitGraphics( Os2SalGraphics* pData )
+{
+}
+
+// =======================================================================
+
+Os2SalGraphics::Os2SalGraphics()
+{
+ for( int i = 0; i < MAX_FALLBACK; ++i )
+ {
+ mhFonts[ i ] = 0;
+ mpOs2FontData[ i ] = NULL;
+ mpOs2FontEntry[ i ] = NULL;
+ }
+
+ mfFontScale = 1.0;
+
+ mhPS = 0;
+ mhDC = 0;
+ mbLine = FALSE;
+ mbFill = FALSE;
+ mbXORMode = FALSE;
+ mnFontMetricCount = 0;
+ mpFontMetrics = NULL;
+ mpClipRectlAry = NULL;
+
+ mhDefFont = 0;
+ mpFontKernPairs = NULL;
+ mnFontKernPairCount = 0;
+ mbFontKernInit = FALSE;
+
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalGraphics::~Os2SalGraphics()
+{
+ Ft2DeleteSetId( mhPS, LCID_BASE);
+
+ if ( mpFontMetrics )
+ delete mpFontMetrics;
+
+ if ( mpFontKernPairs )
+ delete mpFontKernPairs;
+
+}
+
+// -----------------------------------------------------------------------
+
+static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
+{
+ SalColor nSalColor;
+
+ switch( nROPColor )
+ {
+ case SAL_ROP_0:
+ nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
+ break;
+
+ case SAL_ROP_1:
+ case SAL_ROP_INVERT:
+ nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
+ break;
+ }
+
+ return nSalColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::GetResolution( long& rDPIX, long& rDPIY )
+{
+ // since OOo asks for DPI, I will query FONT_RES, which seems to be
+ // more correct than _RESOLUTION fields (on my wide screen lcd)
+ // and does not require conversion
+ DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &rDPIX );
+ DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &rDPIY );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Os2SalGraphics::GetBitCount()
+{
+ LONG nBitCount;
+ DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount );
+ return (USHORT)nBitCount;
+}
+
+// -----------------------------------------------------------------------
+
+long Os2SalGraphics::GetGraphicsWidth() const
+{
+ if( mhWnd )
+ {
+ Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd );
+ if( pFrame )
+ {
+ if( pFrame->maGeometry.nWidth )
+ return pFrame->maGeometry.nWidth;
+ else
+ {
+ // TODO: perhaps not needed, maGeometry should always be up-to-date
+ RECTL aRect;
+ WinQueryWindowRect( mhWnd, &aRect );
+ return aRect.xRight;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::ResetClipRegion()
+{
+#ifdef SAL_PRINTER_CLIPPATH
+ if ( mbPrinter )
+ GpiSetClipPath( mhPS, 0, SCP_RESET );
+ else
+#endif
+ {
+ HRGN hOldRegion;
+
+ GpiSetClipRegion( mhPS, NULL, &hOldRegion );
+ if ( hOldRegion )
+ GpiDestroyRegion( mhPS, hOldRegion );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::BeginSetClipRegion( ULONG nCount )
+{
+ mpClipRectlAry = new RECTL[ nCount ];
+ mnClipElementCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalGraphics::unionClipRegion( long nX, long nY, long nWidth, long nHeight )
+{
+ RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ];
+ pClipRect->xLeft = nX;
+ pClipRect->yTop = mnHeight - nY;
+ pClipRect->xRight = nX + nWidth;
+ pClipRect->yBottom = mnHeight - (nY + nHeight);
+ mnClipElementCount++;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon& )
+{
+ // TODO: implement and advertise OutDevSupport_B2DClip support
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::EndSetClipRegion()
+{
+#ifdef SAL_PRINTER_CLIPPATH
+ if ( mbPrinter )
+ {
+ GpiSetClipPath( mhPS, 0, SCP_RESET );
+ GpiBeginPath( mhPS, 1L );
+
+ for( int i = 0; i < mnClipElementCount; i++ )
+ {
+ POINTL aPt;
+ RECTL* pClipRect = &mpClipRectlAry[ i ];
+
+ aPt.x = pClipRect->xLeft;
+ aPt.y = pClipRect->yTop-1;
+ Ft2Move( mhPS, &aPt );
+
+ aPt.x = pClipRect->xRight-1;
+ aPt.y = pClipRect->yBottom;
+
+ Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
+ }
+
+ GpiEndPath( mhPS );
+ GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND );
+ }
+ else
+#endif
+ {
+ HRGN hClipRegion = GpiCreateRegion( mhPS,
+ mnClipElementCount,
+ mpClipRectlAry );
+ HRGN hOldRegion;
+
+ GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion );
+ if( hOldRegion )
+ GpiDestroyRegion( mhPS, hOldRegion );
+ }
+
+ delete [] mpClipRectlAry;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetLineColor()
+{
+ // don't draw line!
+ mbLine = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetLineColor( SalColor nSalColor )
+{
+ LINEBUNDLE lb;
+
+ // set color
+ lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
+ SALCOLOR_GREEN( nSalColor ),
+ SALCOLOR_BLUE( nSalColor ) );
+
+ Ft2SetAttrs( mhPS,
+ PRIM_LINE,
+ LBB_COLOR,
+ 0,
+ &lb );
+
+ // draw line!
+ mbLine = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetFillColor()
+{
+ // don't fill area!
+ mbFill = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetFillColor( SalColor nSalColor )
+{
+ AREABUNDLE ab;
+
+ // set color
+ ab.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
+ SALCOLOR_GREEN( nSalColor ),
+ SALCOLOR_BLUE( nSalColor ) );
+
+ Ft2SetAttrs( mhPS,
+ PRIM_AREA,
+ ABB_COLOR,
+ 0,
+ &ab );
+
+ // fill area!
+ mbFill = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetXORMode( bool bSet, bool )
+{
+ mbXORMode = bSet;
+ LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT;
+
+ // set mix mode for lines
+ LINEBUNDLE lb;
+ lb.usMixMode = nMixMode;
+ Ft2SetAttrs( mhPS,
+ PRIM_LINE,
+ LBB_MIX_MODE,
+ 0,
+ &lb );
+
+ // set mix mode for areas
+ AREABUNDLE ab;
+ ab.usMixMode = nMixMode;
+ Ft2SetAttrs( mhPS,
+ PRIM_AREA,
+ ABB_MIX_MODE,
+ 0,
+ &ab );
+
+ // set mix mode for text
+ CHARBUNDLE cb;
+ cb.usMixMode = nMixMode;
+ Ft2SetAttrs( mhPS,
+ PRIM_CHAR,
+ CBB_MIX_MODE,
+ 0,
+ &cb );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor )
+{
+ SetLineColor( ImplGetROPSalColor( nROPColor ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor )
+{
+ SetFillColor( ImplGetROPSalColor( nROPColor ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawPixel( long nX, long nY )
+{
+ POINTL aPt;
+
+ aPt.x = nX;
+ aPt.y = TY( nY );
+
+ // set color
+ Ft2SetPel( mhPS, &aPt );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
+{
+ // save old color
+ LINEBUNDLE oldLb;
+ GpiQueryAttrs( mhPS,
+ PRIM_LINE,
+ LBB_COLOR,
+ &oldLb );
+
+ // set new color
+ LINEBUNDLE lb;
+ lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
+ SALCOLOR_GREEN( nSalColor ),
+ SALCOLOR_BLUE( nSalColor ) );
+ Ft2SetAttrs( mhPS,
+ PRIM_LINE,
+ LBB_COLOR,
+ 0,
+ &lb );
+
+ // set color of pixel
+ POINTL aPt;
+ aPt.x = nX;
+ aPt.y = TY( nY );
+ Ft2SetPel( mhPS, &aPt );
+
+ // restore old color
+ Ft2SetAttrs( mhPS,
+ PRIM_LINE,
+ LBB_COLOR,
+ 0,
+ &oldLb );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
+{
+ // OS2 zeichnet den Endpunkt mit
+ POINTL aPt;
+ aPt.x = nX1;
+ aPt.y = TY( nY1 );
+ Ft2Move( mhPS, &aPt );
+ aPt.x = nX2;
+ aPt.y = TY( nY2 );
+ GpiLine( mhPS, &aPt );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
+{
+ POINTL aPt;
+ long lControl;
+
+ if ( mbFill )
+ {
+ if ( mbLine )
+ lControl = DRO_OUTLINEFILL;
+ else
+ lControl = DRO_FILL;
+ }
+ else
+ {
+ if ( mbLine )
+ lControl = DRO_OUTLINE;
+ else
+ return;
+ }
+
+ aPt.x = nX;
+ aPt.y = TY( nY );
+ Ft2Move( mhPS, &aPt );
+ aPt.x = nX + nWidth - 1;
+ aPt.y = TY( nY + nHeight - 1 );
+ Ft2Box( mhPS, lControl, &aPt, 0, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawPolyLine( ULONG nPoints, const SalPoint* pPtAry )
+{
+ // convert all points to sys orientation
+ POINTL* pOS2PtAry = new POINTL[ nPoints ];
+ POINTL* pTempOS2PtAry = pOS2PtAry;
+ const SalPoint* pTempPtAry = pPtAry;
+ ULONG nTempPoints = nPoints;
+ long nHeight = mnHeight - 1;
+
+ while( nTempPoints-- )
+ {
+ (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
+ (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
+ pTempOS2PtAry++;
+ pTempPtAry++;
+ }
+
+ Ft2Move( mhPS, pOS2PtAry );
+ GpiPolyLine( mhPS, nPoints, pOS2PtAry );
+ delete [] pOS2PtAry;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawPolygon( ULONG nPoints, const SalPoint* pPtAry )
+{
+ PM_POLYGON aPolygon;
+
+ // create polygon
+ aPolygon.aPointl = new POINTL[ nPoints ];
+ aPolygon.ulPoints = nPoints;
+
+ // convert all points to sys orientation
+ POINTL* pTempOS2PtAry = aPolygon.aPointl;
+ const SalPoint* pTempPtAry = pPtAry;
+ ULONG nTempPoints = nPoints;
+ long nHeight = mnHeight - 1;
+
+ while( nTempPoints-- )
+ {
+ (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
+ (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
+ pTempOS2PtAry++;
+ pTempPtAry++;
+ }
+
+ // Innenleben zeichnen
+ if ( mbFill )
+ {
+#ifdef SAL_PRINTER_POLYPATH
+ if ( mbPrinter )
+ {
+ Ft2BeginPath( mhPS, 1 );
+ Ft2Move( mhPS, aPolygon.aPointl );
+ Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
+ Ft2EndPath( mhPS );
+ Ft2FillPath( mhPS, 1, 0 );
+
+ if ( mbLine )
+ {
+ Ft2Move( mhPS, aPolygon.aPointl );
+ Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
+ }
+ }
+ else
+#endif
+ {
+ ULONG nOptions = POLYGON_ALTERNATE;
+
+ if ( mbLine )
+ nOptions |= POLYGON_BOUNDARY;
+ else
+ nOptions |= POLYGON_NOBOUNDARY;
+
+ Ft2Move( mhPS, aPolygon.aPointl );
+ GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL );
+ }
+ }
+ else
+ {
+ if ( mbLine )
+ {
+ Ft2Move( mhPS, aPolygon.aPointl );
+ GpiPolyLine( mhPS, nPoints, aPolygon.aPointl );
+ }
+ }
+
+ delete [] aPolygon.aPointl;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawPolyPolygon( ULONG nPoly, const ULONG* pPoints,
+ PCONSTSALPOINT* pPtAry )
+{
+ ULONG i;
+ long nHeight = mnHeight - 1;
+ PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ];
+
+ for( i = 0; i < nPoly; i++ )
+ {
+ const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ];
+
+ // create polygon
+ ULONG nTempPoints = pPoints[ i ];
+ POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ];
+
+ // convert all points to sys orientation
+ aPolygonAry[ i ].ulPoints = nTempPoints;
+ aPolygonAry[ i ].aPointl = pTempOS2PtAry;
+
+ while( nTempPoints-- )
+ {
+ (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
+ (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
+ pTempOS2PtAry++;
+ pTempPtAry++;
+ }
+ }
+
+ // Innenleben zeichnen
+ if ( mbFill )
+ {
+#ifdef SAL_PRINTER_POLYPATH
+ if ( mbPrinter )
+ {
+ Ft2BeginPath( mhPS, 1 );
+ for ( i = 0; i < nPoly; i++ )
+ {
+ Ft2Move( mhPS, aPolygonAry[i].aPointl );
+ Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl );
+ }
+ Ft2EndPath( mhPS );
+ Ft2FillPath( mhPS, 1, 0 );
+ }
+ else
+#endif
+ {
+ ULONG nOptions = POLYGON_ALTERNATE;
+
+ if ( mbLine )
+ nOptions |= POLYGON_BOUNDARY;
+ else
+ nOptions |= POLYGON_NOBOUNDARY;
+
+ Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl );
+ GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL );
+ }
+ }
+ else
+ {
+ if ( mbLine )
+ {
+ for( i = 0; i < nPoly; i++ )
+ {
+ Ft2Move( mhPS, aPolygonAry[ i ].aPointl );
+ GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl );
+ }
+ }
+ }
+
+ // cleanup
+ for( i = 0; i < nPoly; i++ )
+ delete [] aPolygonAry[ i ].aPointl;
+ delete [] aPolygonAry;
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
+{
+ // TODO: implement and advertise OutDevSupport_B2DDraw support
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::drawPolyLine(
+ const basegfx::B2DPolygon& /*rPolygon*/,
+ double /*fTransparency*/,
+ const basegfx::B2DVector& /*rLineWidths*/,
+ basegfx::B2DLineJoin /*eLineJoin*/)
+{
+ // TODO: implement
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Os2SalGraphics::drawPolyLineBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Os2SalGraphics::drawPolygonBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Os2SalGraphics::drawPolyPolygonBezier( ULONG nPoly, const ULONG* pPoints,
+ const SalPoint* const* pPtAry, const BYTE* const* pFlgAry )
+{
+ return sal_False;
+}
+
+// =======================================================================
+
+// MAXIMUM BUFSIZE EQ 0xFFFF
+#define POSTSCRIPT_BUFSIZE 0x4000
+// we only try to get the BoundingBox in the first 4096 bytes
+#define POSTSCRIPT_BOUNDINGSEARCH 0x1000
+
+static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, ULONG nComp, ULONG nSize )
+{
+ while ( nComp-- >= nSize )
+ {
+ ULONG i;
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
+ break;
+ }
+ if ( i == nSize )
+ return pSource;
+ pSource++;
+ }
+ return NULL;
+}
+
+
+static BOOL ImplGetBoundingBox( double* nNumb, BYTE* pSource, ULONG nSize )
+{
+ BOOL bRetValue = FALSE;
+ BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 );
+ if ( pDest )
+ {
+ nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
+ pDest += 14;
+
+ int nSizeLeft = nSize - ( pDest - pSource );
+ if ( nSizeLeft > 100 )
+ nSizeLeft = 100; // only 100 bytes following the bounding box will be checked
+
+ int i;
+ for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
+ {
+ int nDivision = 1;
+ BOOL bDivision = FALSE;
+ BOOL bNegative = FALSE;
+ BOOL bValid = TRUE;
+
+ while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
+ BYTE nByte = *pDest;
+ while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
+ {
+ switch ( nByte )
+ {
+ case '.' :
+ if ( bDivision )
+ bValid = FALSE;
+ else
+ bDivision = TRUE;
+ break;
+ case '-' :
+ bNegative = TRUE;
+ break;
+ default :
+ if ( ( nByte < '0' ) || ( nByte > '9' ) )
+ nSizeLeft = 1; // error parsing the bounding box values
+ else if ( bValid )
+ {
+ if ( bDivision )
+ nDivision*=10;
+ nNumb[i] *= 10;
+ nNumb[i] += nByte - '0';
+ }
+ break;
+ }
+ nSizeLeft--;
+ nByte = *(++pDest);
+ }
+ if ( bNegative )
+ nNumb[i] = -nNumb[i];
+ if ( bDivision && ( nDivision != 1 ) )
+ nNumb[i] /= nDivision;
+ }
+ if ( i == 4 )
+ bRetValue = TRUE;
+ }
+ return bRetValue;
+}
+
+#if 0
+static void ImplWriteDouble( BYTE** pBuf, double nNumber )
+{
+// *pBuf += sprintf( (char*)*pBuf, "%f", nNumber );
+
+ if ( nNumber < 0 )
+ {
+ *(*pBuf)++ = (BYTE)'-';
+ nNumber = -nNumber;
+ }
+ ULONG nTemp = (ULONG)nNumber;
+ const String aNumber1( nTemp );
+ ULONG nLen = aNumber1.Len();
+
+ for ( USHORT n = 0; n < nLen; n++ )
+ *(*pBuf)++ = aNumber1[ n ];
+
+ nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 );
+ if ( nTemp )
+ {
+ *(*pBuf)++ = (BYTE)'.';
+ const String aNumber2( nTemp );
+
+ ULONG nLen = aNumber2.Len();
+ if ( nLen < 8 )
+ {
+ for ( n = 0; n < ( 5 - nLen ); n++ )
+ {
+ *(*pBuf)++ = (BYTE)'0';
+ }
+ }
+ for ( USHORT n = 0; n < nLen; n++ )
+ {
+ *(*pBuf)++ = aNumber2[ n ];
+ }
+ }
+ *(*pBuf)++ = ' ';
+}
+#endif
+
+inline void ImplWriteString( BYTE** pBuf, const char* sString )
+{
+ strcpy( (char*)*pBuf, sString );
+ *pBuf += strlen( sString );
+}
+
+BOOL Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize )
+{
+ if ( !mbPrinter )
+ return FALSE;
+
+ BOOL bRet = FALSE;
+ LONG nLong = 0;
+ if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) &&
+ (CAPS_TECH_POSTSCRIPT == nLong)) )
+ return FALSE;
+
+ BYTE* pBuf = new BYTE[ POSTSCRIPT_BUFSIZE ];
+ double nBoundingBox[4];
+
+ if ( pBuf && ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) )
+ {
+ LONG pOS2DXAry[4]; // hack -> print always 2 white space
+ POINTL aPt;
+ aPt.x = 0;
+ aPt.y = 0;
+ PCH pStr = (PCH) " ";
+ for( long i = 0; i < 4; i++ )
+ pOS2DXAry[i] = i;
+ Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] );
+
+ OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
+
+ // reserve place for a USHORT
+ aBuf.append( "aa" );
+
+ // #107797# Write out EPS encapsulation header
+ // ----------------------------------------------------------------------------------
+
+ // directly taken from the PLRM 3.0, p. 726. Note:
+ // this will definitely cause problems when
+ // recursively creating and embedding PostScript files
+ // in OOo, since we use statically-named variables
+ // here (namely, b4_Inc_state_salWin, dict_count_salWin and
+ // op_count_salWin). Currently, I have no idea on how to
+ // work around that, except from scanning and
+ // interpreting the EPS for unused identifiers.
+
+ // append the real text
+ aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
+ "/dict_count_salWin countdictstack def\n"
+ "/op_count_salWin count 1 sub def\n"
+ "userdict begin\n"
+ "/showpage {} def\n"
+ "0 setgray 0 setlinecap\n"
+ "1 setlinewidth 0 setlinejoin\n"
+ "10 setmiterlimit [] 0 setdash newpath\n"
+ "/languagelevel where\n"
+ "{\n"
+ " pop languagelevel\n"
+ " 1 ne\n"
+ " {\n"
+ " false setstrokeadjust false setoverprint\n"
+ " } if\n"
+ "} if\n\n" );
+
+#if 0
+ // #i10737# Apply clipping manually
+ // ----------------------------------------------------------------------------------
+
+ // Windows seems to ignore any clipping at the HDC,
+ // when followed by a POSTSCRIPT_PASSTHROUGH
+
+ // Check whether we've got a clipping, consisting of
+ // exactly one rect (other cases should be, but aren't
+ // handled currently)
+
+ // TODO: Handle more than one rectangle here (take
+ // care, the buffer can handle only POSTSCRIPT_BUFSIZE
+ // characters!)
+ if ( mhRegion != 0 &&
+ mpStdClipRgnData != NULL &&
+ mpClipRgnData == mpStdClipRgnData &&
+ mpClipRgnData->rdh.nCount == 1 )
+ {
+ RECT* pRect = &(mpClipRgnData->rdh.rcBound);
+
+ aBuf.append( "\nnewpath\n" );
+ aBuf.append( pRect->left );
+ aBuf.append( " " );
+ aBuf.append( pRect->top );
+ aBuf.append( " moveto\n" );
+ aBuf.append( pRect->right );
+ aBuf.append( " " );
+ aBuf.append( pRect->top );
+ aBuf.append( " lineto\n" );
+ aBuf.append( pRect->right );
+ aBuf.append( " " );
+ aBuf.append( pRect->bottom );
+ aBuf.append( " lineto\n" );
+ aBuf.append( pRect->left );
+ aBuf.append( " " );
+ aBuf.append( pRect->bottom );
+ aBuf.append( " lineto\n"
+ "closepath\n"
+ "clip\n"
+ "newpath\n" );
+ }
+#endif
+
+ // #107797# Write out buffer
+ // ----------------------------------------------------------------------------------
+ *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
+ //Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
+ DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
+ (PBYTE)aBuf.getStr(), 0, NULL );
+
+ double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
+ double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) );
+
+ // reserve a USHORT again
+ aBuf.setLength( 2 );
+ aBuf.append( "\n\n[" );
+ aBuf.append( dM11 );
+ aBuf.append( " 0 0 " );
+ aBuf.append( dM22 );
+ aBuf.append( ' ' );
+ aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
+ aBuf.append( ' ' );
+ aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
+ aBuf.append( "] concat\n"
+ "%%BeginDocument:\n" );
+ *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
+ DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
+ (PBYTE)aBuf.getStr(), 0, NULL );
+#if 0
+ BYTE* pTemp = pBuf;
+ ImplWriteString( &pTemp, "save\n[ " );
+ ImplWriteDouble( &pTemp, dM11 );
+ ImplWriteDouble( &pTemp, 0 );
+ ImplWriteDouble( &pTemp, 0 );
+ ImplWriteDouble( &pTemp, dM22 );
+ ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) );
+ ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) );
+ ImplWriteString( &pTemp, "] concat /showpage {} def\n" );
+
+ if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf,
+ (PBYTE)pBuf, 0, NULL ) == DEV_OK )
+#endif //
+ {
+ UINT32 nToDo = nSize;
+ UINT32 nDoNow;
+ bRet = TRUE;
+ while( nToDo && bRet )
+ {
+ nDoNow = 0x4000;
+ if ( nToDo < nDoNow )
+ nDoNow = nToDo;
+
+ if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PBYTE)pPtr + nSize - nToDo,
+ 0, NULL ) == -1 )
+ bRet = FALSE;
+ nToDo -= nDoNow;
+ }
+
+ if ( bRet )
+ {
+ strcpy ( (char*)pBuf, "\nrestore\n" );
+ if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PBYTE)pBuf,
+ 0, NULL ) == DEV_OK ) bRet = TRUE;
+ }
+
+ // #107797# Write out EPS encapsulation footer
+ // ----------------------------------------------------------------------------------
+ // reserve a USHORT again
+ aBuf.setLength( 2 );
+ aBuf.append( "%%EndDocument\n"
+ "count op_count_salWin sub {pop} repeat\n"
+ "countdictstack dict_count_salWin sub {end} repeat\n"
+ "b4_Inc_state_salWin restore\n\n" );
+ *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
+ DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
+ (PBYTE)aBuf.getStr(), 0, NULL );
+ bRet = TRUE;
+
+ }
+ }
+ delete [] pBuf;
+ return bRet;
+}
+
+/*
+ * IsNativeControlSupported()
+ *
+ * Returns TRUE if the platform supports native
+ * drawing of the control defined by nPart
+ */
+BOOL Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
+{
+ return( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+SystemGraphicsData Os2SalGraphics::GetGraphicsData() const
+{
+ SystemGraphicsData aRes;
+ aRes.nSize = sizeof(aRes);
+#if 0
+ aRes.hDC = mhDC;
+#endif
+ return aRes;
+}
+
+// -----------------------------------------------------------------------
diff --git a/vcl/os2/source/gdi/salgdi2.cxx b/vcl/os2/source/gdi/salgdi2.cxx
new file mode 100644
index 000000000000..37621ee1f6a8
--- /dev/null
+++ b/vcl/os2/source/gdi/salgdi2.cxx
@@ -0,0 +1,786 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <svpm.h>
+
+#define _SV_SALGDI2_CXX
+#include <salbmp.h>
+#include <saldata.hxx>
+#ifndef _SV_SALIDS_HRC
+#include <salids.hrc>
+#endif
+#include <salgdi.h>
+#include <salvd.h>
+#include <vcl/salbtype.hxx>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+BOOL bFastTransparent = FALSE;
+
+// -----------
+// - Defines -
+// -----------
+
+#define RGBCOLOR( r, g, b ) ((ULONG)(((BYTE)(b)|((USHORT)(g)<<8))|(((ULONG)(BYTE)(r))<<16)))
+#define TY( y ) (mnHeight-(y)-1)
+
+// ---------------
+// - SalGraphics -
+// ---------------
+
+bool Os2SalGraphics::supportsOperation( OutDevSupportType ) const
+{
+ return false;
+}
+
+
+void Os2SalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics )
+{
+ HPS hSrcPS;
+ POINTL thePoints[4];
+ long nSrcHeight;
+
+ if ( pSrcGraphics )
+ {
+ //hSrcPS = pSrcGraphics->mhPS;
+ //nSrcHeight = pSrcGraphics->mnHeight;
+ hSrcPS = static_cast<Os2SalGraphics*>(pSrcGraphics)->mhPS;
+ nSrcHeight = static_cast<Os2SalGraphics*>(pSrcGraphics)->mnHeight;
+ }
+ else
+ {
+ hSrcPS = mhPS;
+ nSrcHeight = mnHeight;
+ }
+
+ // lower-left corner of target
+ thePoints[0].x = pPosAry->mnDestX;
+ thePoints[0].y = TY( pPosAry->mnDestY + pPosAry->mnDestHeight - 1 );
+
+ // upper-right corner of target
+ thePoints[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth;
+ thePoints[1].y = TY( pPosAry->mnDestY - 1 );
+
+ // lower-left corner of source
+ thePoints[2].x = pPosAry->mnSrcX;
+ thePoints[2].y = nSrcHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
+
+ if ( ( pPosAry->mnDestWidth != pPosAry->mnSrcWidth ) || ( pPosAry->mnDestHeight != pPosAry->mnSrcHeight ) )
+ {
+ // upper-right corner of Source
+ thePoints[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
+ thePoints[3].y = nSrcHeight - pPosAry->mnSrcY + pPosAry->mnSrcHeight;
+
+ GpiBitBlt( mhPS, hSrcPS, 4, thePoints,
+ mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
+ }
+ else
+ {
+ GpiBitBlt( mhPS, hSrcPS, 3, thePoints,
+ mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::copyArea( long nDestX, long nDestY,
+ long nSrcX, long nSrcY,
+ long nSrcWidth, long nSrcHeight,
+ USHORT nFlags )
+{
+ POINTL thePoints[3];
+
+ // lower-left corner of target
+ thePoints[0].x = nDestX;
+ thePoints[0].y = TY( nDestY + nSrcHeight - 1 );
+
+ // upper-right corner of target
+ thePoints[1].x = nDestX + nSrcWidth;
+ thePoints[1].y = TY( nDestY - 1 );
+
+ // lower-left corner of source
+ thePoints[2].x = nSrcX;
+ thePoints[2].y = TY( nSrcY + nSrcHeight - 1);
+
+ if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow )
+ {
+ // Overlap-Bereich berechnen und invalidieren
+ Point aVCLSrcPos( nSrcX, nSrcY );
+ Size aVCLSrcSize( nSrcWidth, nSrcHeight );
+ Rectangle aVCLSrcRect( aVCLSrcPos, aVCLSrcSize );
+ Rectangle aVCLClipRect;
+ SWP aSWP;
+
+ WinQueryWindowPos( mhWnd, &aSWP );
+ aVCLClipRect.Right() = aSWP.cx-1;
+ aVCLClipRect.Bottom() = aSWP.cy-1;
+ if ( !aVCLSrcRect.Intersection( aVCLClipRect ).IsEmpty() )
+ {
+ RECTL aSrcRect;
+ RECTL aTempRect;
+ HRGN hInvalidateRgn;
+ HRGN hTempRgn;
+ HWND hWnd;
+ long nRgnType;
+
+ long nVCLScrHeight = aVCLSrcRect.GetHeight();
+ aSrcRect.xLeft = aVCLSrcRect.Left();
+ aSrcRect.yBottom = TY( aVCLSrcRect.Top()+nVCLScrHeight-1 );
+ aSrcRect.xRight = aSrcRect.xLeft+aVCLSrcRect.GetWidth();
+ aSrcRect.yTop = aSrcRect.yBottom+nVCLScrHeight;
+
+ // Rechteck in Screen-Koordinaaten umrechnen
+ POINTL aPt;
+ long nScreenDX = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
+ long nScreenDY = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
+ aPt.x = 0;
+ aPt.y = 0;
+ WinMapWindowPoints( mhWnd, HWND_DESKTOP, &aPt, 1 );
+ aSrcRect.xLeft += aPt.x;
+ aSrcRect.yTop += aPt.y;
+ aSrcRect.xRight += aPt.x;
+ aSrcRect.yBottom += aPt.y;
+ hInvalidateRgn = 0;
+ // Bereiche ausserhalb des sichtbaren Bereiches berechnen
+ if ( aSrcRect.xLeft < 0 )
+ {
+ if ( !hInvalidateRgn )
+ hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ aTempRect.xLeft = -31999;
+ aTempRect.yBottom = 0;
+ aTempRect.xRight = 0;
+ aTempRect.yTop = 31999;
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
+ GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ }
+ if ( aSrcRect.yBottom < 0 )
+ {
+ if ( !hInvalidateRgn )
+ hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ aTempRect.xLeft = 0;
+ aTempRect.yBottom = -31999;
+ aTempRect.xRight = 31999;
+ aTempRect.yTop = 0;
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
+ GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ }
+ if ( aSrcRect.xRight > nScreenDX )
+ {
+ if ( !hInvalidateRgn )
+ hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ aTempRect.xLeft = nScreenDX;
+ aTempRect.yBottom = 0;
+ aTempRect.xRight = 31999;
+ aTempRect.yTop = 31999;
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
+ GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ }
+ if ( aSrcRect.yTop > nScreenDY )
+ {
+ if ( !hInvalidateRgn )
+ hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ aTempRect.xLeft = 0;
+ aTempRect.yBottom = nScreenDY;
+ aTempRect.xRight = 31999;
+ aTempRect.yTop = 31999;
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
+ GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ }
+
+ // Bereiche die von anderen Fenstern ueberlagert werden berechnen
+ // Calculate areas that are overlapped by other windows
+ HWND hWndParent = WinQueryWindow( mhWnd, QW_PARENT );
+ hWnd = WinQueryWindow( HWND_DESKTOP, QW_TOP );
+ aVCLSrcRect = Rectangle( aSrcRect.xLeft, aSrcRect.yBottom, aSrcRect.xRight, aSrcRect.yTop );
+ while ( hWnd )
+ {
+ if ( hWnd == hWndParent )
+ break;
+ if ( WinIsWindowVisible( hWnd ) )
+ {
+ WinQueryWindowPos( hWnd, &aSWP );
+ if ( !(aSWP.fl & SWP_MINIMIZE) )
+ {
+ aVCLClipRect = Rectangle( Point( aSWP.x, aSWP.y ), Size( aSWP.cx, aSWP.cy ) );
+ if ( aVCLSrcRect.IsOver( aVCLClipRect ) )
+ {
+ if ( !hInvalidateRgn )
+ hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ aTempRect.xLeft = aSWP.x;
+ aTempRect.yBottom = aSWP.y;
+ aTempRect.xRight = aTempRect.xLeft+aSWP.cx;
+ aTempRect.yTop = aTempRect.yBottom+aSWP.cy;
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
+ GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ }
+ }
+ }
+ hWnd = WinQueryWindow( hWnd, QW_NEXT );
+ }
+
+ if ( hInvalidateRgn )
+ {
+ hTempRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
+ nRgnType = GpiCombineRegion( mhPS, hInvalidateRgn, hTempRgn, hInvalidateRgn, CRGN_DIFF );
+ GpiDestroyRegion( mhPS, hTempRgn );
+ if ( (nRgnType != RGN_ERROR) && (nRgnType != RGN_NULL) )
+ {
+ long nOffX = (nDestX-nSrcX);
+ long nOffY = (nSrcY-nDestY);
+ aPt.x = nOffX-aPt.x;
+ aPt.y = nOffY-aPt.y;
+ GpiOffsetRegion( mhPS, hInvalidateRgn, &aPt );
+ WinInvalidateRegion( mhWnd, hInvalidateRgn, TRUE );
+ // Hier loesen wir nur ein Update aus, wenn es der
+ // MainThread ist, damit es beim Bearbeiten der
+ // Paint-Message keinen Deadlock gibt, da der
+ // SolarMutex durch diesen Thread schon gelockt ist
+ SalData* pSalData = GetSalData();
+ ULONG nCurThreadId = GetCurrentThreadId();
+ if ( pSalData->mnAppThreadId == nCurThreadId )
+ WinUpdateWindow( mhWnd );
+ }
+ GpiDestroyRegion( mhPS, hInvalidateRgn );
+ }
+ }
+ }
+
+ GpiBitBlt( mhPS, mhPS, 3, thePoints,
+ ROP_SRCCOPY, BBO_IGNORE );
+
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDrawBitmap( HPS hPS, long nScreenHeight,
+ const SalTwoRect* pPosAry, const Os2SalBitmap& rSalBitmap,
+ BOOL bPrinter, int nDrawMode )
+{
+ if( hPS )
+ {
+ HANDLE hDrawDIB;
+ HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB();
+ Os2SalBitmap* pTmpSalBmp = NULL;
+ BOOL bPrintDDB = ( bPrinter && hDrawDDB );
+ BOOL bDrawDDB1 = ( ( rSalBitmap.GetBitCount() == 1 ) && hDrawDDB );
+
+ if( bPrintDDB || bDrawDDB1 )
+ {
+ pTmpSalBmp = new Os2SalBitmap;
+ pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() );
+ hDrawDIB = pTmpSalBmp->ImplGethDIB();
+ }
+ else
+ hDrawDIB = rSalBitmap.ImplGethDIB();
+
+ if( hDrawDIB )
+ {
+ HANDLE hSubst = rSalBitmap.ImplGethDIB1Subst();
+ POINTL pts[ 4 ];
+ BITMAPINFO2* pBI = (BITMAPINFO2*) hDrawDIB;
+ BITMAPINFOHEADER2* pBIH = (BITMAPINFOHEADER2*) pBI;
+ const long nHeight = pBIH->cy;
+ long nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGB2 );
+ BYTE* pBits = (BYTE*) pBI + nInfoSize;
+
+ pts[0].x = pPosAry->mnDestX;
+ pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight;
+ pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1;
+ pts[1].y = nScreenHeight - pPosAry->mnDestY - 1;
+
+ pts[2].x = pPosAry->mnSrcX;
+ pts[2].y = nHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
+ pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
+ pts[3].y = nHeight - pPosAry->mnSrcY;
+
+ // if we've got a 1Bit DIB, we create a 4Bit substitute
+ if( ( pBIH->cBitCount == 1 ) && !hSubst )
+ {
+ // create 4Bit substitute
+ hSubst = Os2SalBitmap::ImplCreateDIB4FromDIB1( hDrawDIB );
+
+ // replace substitute only, if it is no temporary SalBitmap
+ if( !( bPrintDDB || bDrawDDB1 ) )
+ ( (Os2SalBitmap&) rSalBitmap ).ImplReplacehDIB1Subst( hSubst );
+ }
+
+ if( hSubst )
+ {
+ pBI = (BITMAPINFO2*) hSubst;
+ pBIH = (BITMAPINFOHEADER2*) pBI;
+ nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hSubst ) * sizeof( RGB2 );
+ pBits = (BYTE*) pBI + nInfoSize;
+ }
+
+ if( bPrinter )
+ {
+ BYTE* pDummy;
+
+ // expand 8Bit-DIB's to 24Bit-DIB's, because some printer drivers
+ // have problems to print these DIB's (strange)
+ if( pBIH->cBitCount == 8 && pBIH->ulCompression == BCA_UNCOMP )
+ {
+ const long nWidth = pBIH->cx;
+ const long nHeight = pBIH->cy;
+ const long nWidthAl8 = AlignedWidth4Bytes( nWidth * 8 );
+ const long nWidthAl24 = AlignedWidth4Bytes( nWidth * 24 );
+ const long nNewImageSize = nHeight * nWidthAl24;
+ BITMAPINFOHEADER2* pNewInfo;
+
+ pDummy = new BYTE[ sizeof( BITMAPINFO2 ) + nNewImageSize ];
+ memset( pDummy, 0, sizeof( BITMAPINFO2 ) );
+
+ pNewInfo = (BITMAPINFOHEADER2*) pDummy;
+ pNewInfo->cbFix = sizeof( BITMAPINFOHEADER2 );
+ pNewInfo->cx = nWidth;
+ pNewInfo->cy = nHeight;
+ pNewInfo->cPlanes = 1;
+ pNewInfo->cBitCount = 24;
+ pNewInfo->ulCompression = BCA_UNCOMP;
+ pNewInfo->cbImage = nNewImageSize;
+
+ BYTE* pBitsSrc = (BYTE*) pBIH + nInfoSize;
+ BYTE* pBitsDst = pDummy + sizeof( BITMAPINFO2 );
+
+ for( long nY = 0UL; nY < nHeight; nY++ )
+ {
+ BYTE* pSrcLine = pBitsSrc + nY * nWidthAl8;
+ BYTE* pDstLine = pBitsDst + nY * nWidthAl24;
+
+ for( long nX = 0UL; nX < nWidth; nX++ )
+ {
+ const RGB2& rQuad = pBI->argbColor[ *pSrcLine++ ];
+
+ *pDstLine++ = rQuad.bBlue;
+ *pDstLine++ = rQuad.bGreen;
+ *pDstLine++ = rQuad.bRed;
+ }
+ }
+
+ nInfoSize = sizeof( BITMAPINFO2 );
+ }
+ else
+ {
+ const long nImageSize = ( pBIH->cbImage ? pBIH->cbImage : ( pBIH->cy * AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) ) );
+ const long nTotalSize = nInfoSize + nImageSize;
+
+ pDummy = new BYTE[ nTotalSize ];
+ memcpy( pDummy, pBI, nTotalSize );
+ }
+
+ GpiDrawBits( hPS, pDummy + nInfoSize, (BITMAPINFO2*) pDummy, 4L, pts, nDrawMode, BBO_IGNORE );
+ delete[] pDummy;
+ }
+ else
+ GpiDrawBits( hPS, pBits, pBI, 4L, pts, nDrawMode, BBO_IGNORE );
+ }
+ else if( hDrawDDB && !bPrintDDB )
+ {
+ POINTL pts[ 4 ];
+
+ pts[0].x = pPosAry->mnDestX;
+ pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight;
+ pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1;
+ pts[1].y = nScreenHeight - pPosAry->mnDestY - 1;
+
+ pts[2].x = pPosAry->mnSrcX;
+ pts[2].y = rSalBitmap.GetSize().Height() - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
+ pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
+ pts[3].y = rSalBitmap.GetSize().Height() - pPosAry->mnSrcY;
+
+ GpiWCBitBlt( hPS, hDrawDDB, 4L, pts, nDrawMode, BBO_IGNORE );
+/*
+ HPS hDrawPS = ImplGetCachedPS( CACHED_HPS_DRAW, hDrawDDB );
+ Ft2BitBlt( hPS, hDrawPS, 4, pts, nDrawMode, BBO_IGNORE );
+ ImplReleaseCachedPS( CACHED_HPS_DRAW );
+*/
+ }
+
+ if( bPrintDDB || bDrawDDB1 )
+ delete pTmpSalBmp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
+ const SalBitmap& rSalBitmap )
+{
+ ImplDrawBitmap( mhPS, mnHeight,
+ pPosAry, static_cast<const Os2SalBitmap&>(rSalBitmap),
+ mbPrinter,
+ mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
+ const SalBitmap& rSalBitmap,
+ SalColor nTransparentColor )
+{
+ DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
+ //const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
+ // an FM: kann erst einmal unberuecksichtigt bleiben
+ drawBitmap( pPosAry, rSalBitmap );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
+ const SalBitmap& rSSalBitmap,
+ const SalBitmap& rSTransparentBitmap )
+{
+ DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
+
+ const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
+ const Os2SalBitmap& rTransparentBitmap = static_cast<const Os2SalBitmap&>(rSTransparentBitmap);
+
+ if( bFastTransparent )
+ {
+ ImplDrawBitmap( mhPS, mnHeight, pPosAry, rTransparentBitmap, FALSE, ROP_SRCAND );
+ ImplDrawBitmap( mhPS, mnHeight, pPosAry, rSalBitmap, FALSE, ROP_SRCPAINT );
+ }
+ else
+ {
+ SalTwoRect aPosAry = *pPosAry;
+ int nDstX = (int) aPosAry.mnDestX;
+ int nDstY = (int) aPosAry.mnDestY;
+ int nDstWidth = (int) aPosAry.mnDestWidth;
+ int nDstHeight = (int) aPosAry.mnDestHeight;
+ HAB hAB = GetSalData()->mhAB;
+ HPS hPS = mhPS;
+ DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+ SIZEL aSizeL = { nDstWidth, nDstHeight };
+ POINTL aPtL[ 3 ];
+
+ HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ HBITMAP hMemBitmap = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDstWidth, nDstHeight, 0 );
+ HBITMAP hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, hMemBitmap );
+ HDC hMaskDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ HPS hMaskPS = Ft2CreatePS( hAB, hMaskDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ HBITMAP hMaskBitmap = ImplCreateVirDevBitmap( hMaskDC, hMaskPS, nDstWidth, nDstHeight, 0 );
+ HBITMAP hMaskOld = (HBITMAP) Ft2SetBitmap( hMaskPS, hMaskBitmap );
+/*
+ HPS hMemPS = ImplGetCachedPS( CACHED_HPS_1, 0 );
+ HPS hMaskPS = ImplGetCachedPS( CACHED_HPS_2, 0 );
+*/
+ aPosAry.mnDestX = aPosAry.mnDestY = 0L;
+
+ aPtL[ 0 ].x = 0;
+ aPtL[ 0 ].y = 0;
+ aPtL[ 1 ].x = nDstWidth;
+ aPtL[ 1 ].y = nDstHeight;
+ aPtL[ 2 ].x = nDstX;
+ aPtL[ 2 ].y = TY( nDstY + nDstHeight - 1 );
+
+ GpiBitBlt( hMemPS, hPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE );
+ ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rTransparentBitmap, FALSE, ROP_SRCCOPY );
+
+ aPtL[ 2 ].x = 0;
+ aPtL[ 2 ].y = 0;
+
+ GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCAND, BBO_IGNORE );
+ ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rSalBitmap, FALSE, ROP_SRCERASE );
+ GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCPAINT, BBO_IGNORE );
+
+ aPtL[ 0 ].x = nDstX;
+ aPtL[ 0 ].y = TY( nDstY + nDstHeight - 1 );
+ aPtL[ 1 ].x = nDstX + nDstWidth;
+ aPtL[ 1 ].y = TY( nDstY - 1 );
+
+ GpiBitBlt( hPS, hMemPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE );
+
+ Ft2SetBitmap( hMaskPS, hMaskOld );
+ Ft2DestroyPS( hMaskPS );
+ DevCloseDC( hMaskDC );
+ GpiDeleteBitmap( hMaskBitmap );
+
+ Ft2SetBitmap( hMemPS, hMemOld );
+ Ft2DestroyPS( hMemPS );
+ DevCloseDC( hMemDC );
+ GpiDeleteBitmap( hMemBitmap );
+
+/*
+ ImplReleaseCachedPS( CACHED_HPS_1 );
+ ImplReleaseCachedPS( CACHED_HPS_2 );
+*/
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
+ const SalBitmap& rSrcBitmap,
+ const SalBitmap& rAlphaBmp )
+{
+ // TODO(P3) implement alpha blending
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
+ long nHeight, sal_uInt8 nTransparency )
+{
+ // TODO(P3) implement alpha blending
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::drawMask( const SalTwoRect* pPosAry,
+ const SalBitmap& rSSalBitmap,
+ SalColor nMaskColor )
+{
+ DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
+
+ const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
+
+ SalTwoRect aPosAry = *pPosAry;
+ HPS hPS = mhPS;
+ IMAGEBUNDLE aBundle, aOldBundle;
+ AREABUNDLE aAreaBundle, aOldAreaBundle;
+ const ULONG nColor = RGBCOLOR( SALCOLOR_RED( nMaskColor ),
+ SALCOLOR_GREEN( nMaskColor ),
+ SALCOLOR_BLUE( nMaskColor ) );
+
+ GpiQueryAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, &aOldBundle );
+ aBundle.lColor = RGBCOLOR( 0, 0, 0 );
+ aBundle.lBackColor = RGBCOLOR( 0xFF, 0xFF, 0xFF );
+ Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aBundle );
+
+ GpiQueryAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
+ ABB_MIX_MODE | ABB_BACK_MIX_MODE, &aOldAreaBundle );
+ aAreaBundle.lColor = nColor;
+ aAreaBundle.lBackColor = nColor;
+ aAreaBundle.usSymbol = PATSYM_SOLID;
+ aAreaBundle.usMixMode = FM_OVERPAINT;
+ aAreaBundle.usBackMixMode = BM_OVERPAINT;
+ Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
+ ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aAreaBundle );
+
+ ImplDrawBitmap( hPS, mnHeight, &aPosAry, rSalBitmap, FALSE, 0x00B8L );
+
+ Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aOldBundle );
+ Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
+ ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aOldAreaBundle );
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* Os2SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
+{
+ HAB hAB = GetSalData()->mhAB;
+ SIZEL size = { nDX, nDY };
+ Os2SalBitmap* pSalBitmap = NULL;
+
+ // create device context (at this time allways display compatible)
+ DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+ HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ HBITMAP hMemBmp = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDX, nDY, 0 );
+ HBITMAP hMemOld = Ft2SetBitmap( hMemPS, hMemBmp );
+
+ // creation successfull?
+ if( hMemDC && hMemPS && hMemBmp )
+ {
+ POINTL thePoints[ 3 ];
+
+ // lower-left corner of target
+ thePoints[ 0 ].x = 0;
+ thePoints[ 0 ].y = 0;
+
+ // upper-right corner of target
+ thePoints[ 1 ].x = nDX;
+ thePoints[ 1 ].y = nDY;
+
+ // lower-left corner of source
+ thePoints[ 2 ].x = nX;
+ thePoints[ 2 ].y = TY( nY + nDY - 1 );
+
+ long lHits = GpiBitBlt( hMemPS, mhPS, 3, thePoints,
+ mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
+
+ if( hMemPS )
+ {
+ Ft2SetBitmap( hMemPS, hMemOld );
+ Ft2DestroyPS( hMemPS );
+ }
+
+ if( hMemDC )
+ DevCloseDC( hMemDC );
+
+ if( lHits == GPI_OK )
+ {
+ pSalBitmap = new Os2SalBitmap;
+
+ if( !pSalBitmap->Create( hMemBmp, FALSE, FALSE ) )
+ {
+ delete pSalBitmap;
+ pSalBitmap = NULL;
+ }
+ }
+ }
+
+ if( !pSalBitmap )
+ GpiDeleteBitmap( hMemBmp );
+
+ // return pointer to SAL-Bitmap
+ return pSalBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+SalColor Os2SalGraphics::getPixel( long nX, long nY )
+{
+ POINTL aPt = { nX, TY( nY ) };
+ LONG nColor = Ft2QueryPel( mhPS, &aPt );
+
+ return MAKE_SALCOLOR( (BYTE) ( nColor >> 16 ), (BYTE) ( nColor >> 8 ), (BYTE) nColor );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
+{
+ if( nFlags & SAL_INVERT_TRACKFRAME )
+ {
+ // save old vylues
+ LINEBUNDLE oldLb;
+ LINEBUNDLE lb;
+ GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb );
+
+ // set linetype to short dash
+ lb.lColor = RGBCOLOR( 255, 255, 255 );
+ lb.usMixMode = FM_XOR;
+ lb.usType = LINETYPE_ALTERNATE;
+ Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb );
+
+ // draw inverted box
+ POINTL aPt;
+
+ aPt.x = nX;
+ aPt.y = TY( nY );
+
+ Ft2Move( mhPS, &aPt );
+
+ aPt.x = nX + nWidth - 1;
+ aPt.y = TY( nY + nHeight - 1 );
+
+ Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
+
+ // restore old values
+ Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb );
+
+ }
+ else
+ {
+ // save old values
+ AREABUNDLE oldAb;
+ AREABUNDLE ab;
+
+ GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb );
+
+ // set fill color to black
+ ab.lColor = RGBCOLOR( 255, 255, 255 );
+ ab.usMixMode = FM_XOR;
+ ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID;
+ Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab );
+
+ // draw inverted box
+ POINTL aPt;
+
+ aPt.x = nX;
+ aPt.y = TY( nY );
+
+ Ft2Move( mhPS, &aPt );
+
+ aPt.x = nX + nWidth - 1;
+ aPt.y = TY( nY + nHeight - 1 );
+
+ Ft2Box( mhPS, DRO_FILL, &aPt, 0, 0 );
+
+ // restore old values
+ Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nFlags )
+{
+ if( nFlags & SAL_INVERT_TRACKFRAME )
+ {
+ // save old vylues
+ LINEBUNDLE oldLb;
+ LINEBUNDLE lb;
+ GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb );
+
+ // set linetype to short dash
+ lb.lColor = RGBCOLOR( 255, 255, 255 );
+ lb.usMixMode = FM_XOR;
+ lb.usType = LINETYPE_ALTERNATE;
+ Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb );
+
+ // Draw Polyline
+ drawPolyLine( nPoints, pPtAry );
+
+ // restore old values
+ Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb );
+ }
+ else
+ {
+ // save old values
+ AREABUNDLE oldAb;
+ AREABUNDLE ab;
+
+ GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb );
+
+ // set fill color to black
+ ab.lColor = RGBCOLOR( 255, 255, 255 );
+ ab.usMixMode = FM_XOR;
+ ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID;
+ Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab );
+
+ // Draw Polyline
+ drawPolygon( nPoints, pPtAry );
+
+ // restore old values
+ Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb );
+ }
+}
+
diff --git a/vcl/os2/source/gdi/salgdi3.cxx b/vcl/os2/source/gdi/salgdi3.cxx
new file mode 100644
index 000000000000..e25e68ee5a4c
--- /dev/null
+++ b/vcl/os2/source/gdi/salgdi3.cxx
@@ -0,0 +1,1769 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_GRE_STRINGS
+#define INCL_GPI
+#define INCL_DOS
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <svpm.h>
+
+#define _SV_SALGDI3_CXX
+#include <tools/svwin.h>
+#include <rtl/tencinfo.h>
+#ifndef _OSL_FILE_HXX
+#include <osl/file.hxx>
+#endif
+#ifndef _OSL_THREAD_HXX
+#include <osl/thread.hxx>
+#endif
+#ifndef _OSL_PROCESS_HXX
+#include <osl/process.h>
+#endif
+#include <vcl/svapp.hxx>
+#include <saldata.hxx>
+#include <salgdi.h>
+#include <vcl/font.hxx>
+#include <vcl/sallayout.hxx>
+#include <tools/poly.hxx>
+#include <tools/debug.hxx>
+#include <rtl/textcvt.h>
+#include <tools/debug.hxx>
+#include <saldata.hxx>
+#include <salgdi.h>
+#ifndef _SV_OUTFONT_HXX
+#include <vcl/outfont.hxx>
+#endif
+#include <sallayout.h>
+#include <tools/poly.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+#include "sft.hxx"
+
+#ifdef GCP_KERN_HACK
+#include <algorithm>
+#endif
+
+using namespace vcl;
+
+// -----------
+// - Inlines -
+// -----------
+
+
+inline W32FIXED FixedFromDouble( double d )
+{
+ const long l = (long) ( d * 65536. );
+ return *(W32FIXED*) &l;
+}
+
+// -----------------------------------------------------------------------
+
+inline int IntTimes256FromFixed(W32FIXED f)
+{
+ int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8);
+ return nFixedTimes256;
+}
+
+// -----------
+// - Defines -
+// -----------
+
+// this is a special codepage code, used to identify OS/2 symbol font.
+#define SYMBOL_CHARSET 65400
+
+// =======================================================================
+
+UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen = STRING_LEN)
+{
+ return UniString( pStr, nLen, gsl_getSystemTextEncoding(),
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
+}
+
+// =======================================================================
+
+static USHORT ImplSalToCharSet( CharSet eCharSet )
+{
+ // !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0
+ // !!! zurueckgegeben werden, solange die DBCS-Charsets nicht
+ // !!! durchgereicht werden
+
+ switch ( eCharSet )
+ {
+ case RTL_TEXTENCODING_IBM_437:
+ return 437;
+
+ case RTL_TEXTENCODING_IBM_850:
+ return 850;
+
+ case RTL_TEXTENCODING_IBM_860:
+ return 860;
+
+ case RTL_TEXTENCODING_IBM_861:
+ return 861;
+
+ case RTL_TEXTENCODING_IBM_863:
+ return 863;
+
+ case RTL_TEXTENCODING_IBM_865:
+ return 865;
+ case RTL_TEXTENCODING_MS_1252:
+ return 1004;
+ case RTL_TEXTENCODING_SYMBOL:
+ return 65400;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static CharSet ImplCharSetToSal( USHORT usCodePage )
+{
+ switch ( usCodePage )
+ {
+ case 437:
+ return RTL_TEXTENCODING_IBM_437;
+
+ case 850:
+ return RTL_TEXTENCODING_IBM_850;
+
+ case 860:
+ return RTL_TEXTENCODING_IBM_860;
+
+ case 861:
+ return RTL_TEXTENCODING_IBM_861;
+
+ case 863:
+ return RTL_TEXTENCODING_IBM_863;
+
+ case 865:
+ return RTL_TEXTENCODING_IBM_865;
+ case 1004:
+ return RTL_TEXTENCODING_MS_1252;
+ case 65400:
+ return RTL_TEXTENCODING_SYMBOL;
+ }
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+static FontFamily ImplFamilyToSal( BYTE bFamilyType )
+{
+ switch ( bFamilyType )
+ {
+ case 4:
+ return FAMILY_DECORATIVE;
+ case 3:
+ return FAMILY_SCRIPT;
+ }
+
+ return FAMILY_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+static FontWeight ImplWeightToSal( USHORT nWeight )
+{
+ // Falls sich jemand an die alte Doku gehalten hat
+ if ( nWeight > 999 )
+ nWeight /= 1000;
+
+ switch ( nWeight )
+ {
+ case 1:
+ return WEIGHT_THIN;
+
+ case 2:
+ return WEIGHT_ULTRALIGHT;
+
+ case 3:
+ return WEIGHT_LIGHT;
+
+ case 4:
+ return WEIGHT_SEMILIGHT;
+
+ case 5:
+ return WEIGHT_NORMAL;
+
+ case 6:
+ return WEIGHT_SEMIBOLD;
+
+ case 7:
+ return WEIGHT_BOLD;
+
+ case 8:
+ return WEIGHT_ULTRABOLD;
+
+ case 9:
+ return WEIGHT_BLACK;
+ }
+
+ return WEIGHT_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+static UniString ImpStyleNameToSal( const char* pFamilyName,
+ const char* pFaceName,
+ USHORT nLen )
+{
+ if ( !nLen )
+ nLen = strlen(pFamilyName);
+
+ // strip FamilyName from FaceName
+ if ( strncmp( pFamilyName, pFaceName, nLen ) == 0 )
+ {
+ USHORT nFaceLen = (USHORT)strlen( pFaceName+nLen );
+ // Ist Facename laenger, schneiden wir den FamilyName ab
+ if ( nFaceLen > 1 )
+ return UniString( pFaceName+(nLen+1), gsl_getSystemTextEncoding());
+ else
+ return UniString();
+ }
+ else
+ return UniString( pFaceName, gsl_getSystemTextEncoding());
+}
+
+// -----------------------------------------------------------------------
+
+inline FontPitch ImplLogPitchToSal( BYTE fsType )
+{
+ if ( fsType & FM_TYPE_FIXED )
+ return PITCH_FIXED;
+ else
+ return PITCH_VARIABLE;
+}
+
+// -----------------------------------------------------------------------
+
+inline BYTE ImplPitchToWin( FontPitch ePitch )
+{
+ if ( ePitch == PITCH_FIXED )
+ return FM_TYPE_FIXED;
+ //else if ( ePitch == PITCH_VARIABLE )
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static ImplDevFontAttributes Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric)
+{
+ ImplDevFontAttributes aDFA;
+
+ // get font face attributes
+ aDFA.meFamily = ImplFamilyToSal( pFontMetric->panose.bFamilyType);
+ aDFA.meWidthType = WIDTH_DONTKNOW;
+ aDFA.meWeight = ImplWeightToSal( pFontMetric->usWeightClass);
+ aDFA.meItalic = (pFontMetric->fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
+ aDFA.mePitch = ImplLogPitchToSal( pFontMetric->fsType );
+ aDFA.mbSymbolFlag = (pFontMetric->usCodePage == SYMBOL_CHARSET);
+
+ // get the font face name
+ // the maName field stores the font name without the style, so under OS/2
+ // we must use the family name
+ aDFA.maName = UniString( pFontMetric->szFamilyname, gsl_getSystemTextEncoding());
+
+ aDFA.maStyleName = ImpStyleNameToSal( pFontMetric->szFamilyname,
+ pFontMetric->szFacename,
+ strlen( pFontMetric->szFamilyname) );
+
+ // get device specific font attributes
+ aDFA.mbOrientation = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
+ aDFA.mbDevice = (pFontMetric->fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
+
+ aDFA.mbEmbeddable = false;
+ aDFA.mbSubsettable = false;
+ DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFamilyname);
+ if( fontType == FT2_FONTTYPE_TRUETYPE && !aDFA.mbDevice)
+ aDFA.mbSubsettable = true;
+ // for now we can only embed Type1 fonts
+ if( fontType == FT2_FONTTYPE_TYPE1 )
+ aDFA.mbEmbeddable = true;
+
+ // heuristics for font quality
+ // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
+ // - subsetting > embedding > none
+ aDFA.mnQuality = 0;
+ if( fontType == FT2_FONTTYPE_TRUETYPE )
+ aDFA.mnQuality += 50;
+ if( aDFA.mbSubsettable )
+ aDFA.mnQuality += 200;
+ else if( aDFA.mbEmbeddable )
+ aDFA.mnQuality += 100;
+
+ // #i38665# prefer Type1 versions of the standard postscript fonts
+ if( aDFA.mbEmbeddable )
+ {
+ if( aDFA.maName.EqualsAscii( "AvantGarde" )
+ || aDFA.maName.EqualsAscii( "Bookman" )
+ || aDFA.maName.EqualsAscii( "Courier" )
+ || aDFA.maName.EqualsAscii( "Helvetica" )
+ || aDFA.maName.EqualsAscii( "NewCenturySchlbk" )
+ || aDFA.maName.EqualsAscii( "Palatino" )
+ || aDFA.maName.EqualsAscii( "Symbol" )
+ || aDFA.maName.EqualsAscii( "Times" )
+ || aDFA.maName.EqualsAscii( "ZapfChancery" )
+ || aDFA.maName.EqualsAscii( "ZapfDingbats" ) )
+ aDFA.mnQuality += 500;
+ }
+
+ aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW;
+ aDFA.meAntiAlias = ANTIALIAS_DONTKNOW;
+
+ // TODO: add alias names
+
+ return aDFA;
+}
+
+// =======================================================================
+
+// -----------------------------------------------------------------------
+
+// =======================================================================
+
+ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric,
+ int nHeight, BYTE nPitchAndFamily )
+: ImplFontData( Os2Font2DevFontAttributes(_pFontMetric), 0 ),
+ pFontMetric( _pFontMetric ),
+ meOs2CharSet( _pFontMetric->usCodePage),
+ mnPitchAndFamily( nPitchAndFamily ),
+ mpFontCharSets( NULL ),
+ mpUnicodeMap( NULL ),
+ mbDisableGlyphApi( false ),
+ mbHasKoreanRange( false ),
+ mbHasCJKSupport( false ),
+ mbAliasSymbolsLow( false ),
+ mbAliasSymbolsHigh( false ),
+ mnId( 0 )
+{
+ SetBitmapSize( 0, nHeight );
+}
+
+// -----------------------------------------------------------------------
+
+ImplOs2FontData::~ImplOs2FontData()
+{
+ delete[] mpFontCharSets;
+
+ if( mpUnicodeMap )
+ mpUnicodeMap->DeReference();
+}
+
+// -----------------------------------------------------------------------
+
+sal_IntPtr ImplOs2FontData::GetFontId() const
+{
+ return mnId;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplOs2FontData::UpdateFromHPS( HPS hPS ) const
+{
+ // short circuit if already initialized
+ if( mpUnicodeMap != NULL )
+ return;
+
+ ReadCmapTable( hPS );
+ ReadOs2Table( hPS );
+
+ // even if the font works some fonts have problems with the glyph API
+ // => the heuristic below tries to figure out which fonts have the problem
+ DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFacename);
+ if( fontType != FT2_FONTTYPE_TRUETYPE
+ && (pFontMetric->fsDefn & FM_DEFN_GENERIC) == 0)
+ mbDisableGlyphApi = true;
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef GNG_VERT_HACK
+bool ImplOs2FontData::HasGSUBstitutions( HPS hPS ) const
+{
+ if( !mbGsubRead )
+ ReadGsubTable( hPS );
+ return !maGsubTable.empty();
+}
+
+// -----------------------------------------------------------------------
+
+bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar ) const
+{
+ return( maGsubTable.find( cChar ) != maGsubTable.end() );
+}
+#endif // GNG_VERT_HACK
+
+// -----------------------------------------------------------------------
+
+ImplFontCharMap* ImplOs2FontData::GetImplFontCharMap() const
+{
+ mpUnicodeMap->AddReference();
+ return mpUnicodeMap;
+}
+
+// -----------------------------------------------------------------------
+
+static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
+static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);}
+static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));}
+static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
+
+void ImplOs2FontData::ReadOs2Table( HPS hPS ) const
+{
+ const DWORD Os2Tag = CalcTag( "OS/2" );
+ DWORD nLength = Ft2GetFontData( hPS, Os2Tag, 0, NULL, 0 );
+ if( (nLength == FT2_ERROR) || !nLength )
+ return;
+ std::vector<unsigned char> aOS2map( nLength );
+ unsigned char* pOS2map = &aOS2map[0];
+ DWORD nRC = Ft2GetFontData( hPS, Os2Tag, 0, pOS2map, nLength );
+ sal_uInt32 nVersion = GetUShort( pOS2map );
+ if ( nVersion >= 0x0001 && nLength >= 58 )
+ {
+ // We need at least version 0x0001 (TrueType rev 1.66)
+ // to have access to the needed struct members.
+ sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 );
+ sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 );
+ sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 );
+ sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 );
+
+ // Check for CJK capabilities of the current font
+ mbHasCJKSupport = (ulUnicodeRange2 & 0x2fff0000)
+ | (ulUnicodeRange3 & 0x00000001);
+ mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000)
+ | (ulUnicodeRange2 & 0x01100000);
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+#ifdef GNG_VERT_HACK
+void ImplOs2FontData::ReadGsubTable( HPS hPS ) const
+{
+ mbGsubRead = true;
+
+ // check the existence of a GSUB table
+ const DWORD GsubTag = CalcTag( "GSUB" );
+ DWORD nRC = Ft2GetFontData( hPS, GsubTag, 0, NULL, 0 );
+ if( (nRC == FT2_ERROR) || !nRC )
+ return;
+
+ // TODO: directly read the GSUB table instead of going through sft
+
+ // get raw font file data
+ DWORD nFontSize = Ft2GetFontData( hPS, 0, 0, NULL, 0 );
+ if( nFontSize == FT2_ERROR )
+ return;
+ std::vector<char> aRawFont( nFontSize+1 );
+ aRawFont[ nFontSize ] = 0;
+ DWORD nFontSize2 = Ft2GetFontData( hPS, 0, 0, (void*)&aRawFont[0], nFontSize );
+ if( nFontSize != nFontSize2 )
+ return;
+
+ // open font file
+ sal_uInt32 nFaceNum = 0;
+ if( !aRawFont[0] ) // TTC candidate
+ nFaceNum = ~0U; // indicate "TTC font extracts only"
+
+ TrueTypeFont* pTTFont = NULL;
+ ::OpenTTFontBuffer( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
+ if( !pTTFont )
+ return;
+
+ // add vertically substituted characters to list
+ static const sal_Unicode aGSUBCandidates[] = {
+ 0x0020, 0x0080, // ASCII
+ 0x2000, 0x2600, // misc
+ 0x3000, 0x3100, // CJK punctutation
+ 0x3300, 0x3400, // squared words
+ 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
+ 0 };
+
+ for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
+ for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
+ if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
+ maGsubTable.insert( cChar ); // insert GSUBbed unicodes
+
+ CloseTTFont( pTTFont );
+
+#if 0
+ TrueTypeFont* pTTFont = NULL;
+ ::OpenTTFont( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
+ if( !pTTFont )
+ return;
+
+ // add vertically substituted characters to list
+ static const sal_Unicode aGSUBCandidates[] = {
+ 0x0020, 0x0080, // ASCII
+ 0x2000, 0x2600, // misc
+ 0x3000, 0x3100, // CJK punctutation
+ 0x3300, 0x3400, // squared words
+ 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
+ 0 };
+
+ for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
+ for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
+ if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
+ maGsubTable.insert( cChar ); // insert GSUBbed unicodes
+
+ CloseTTFont( pTTFont );
+#endif
+}
+#endif // GNG_VERT_HACK
+
+// -----------------------------------------------------------------------
+
+void ImplOs2FontData::ReadCmapTable( HPS hPS ) const
+{
+ CmapResult aResult;
+ aResult.mnPairCount = 0;
+ aResult.mbSymbolic = (meOs2CharSet == SYMBOL_CHARSET);
+ aResult.mbRecoded = true;
+
+ // get the CMAP table from the font which is selected into the DC
+ const DWORD CmapTag = CalcTag( "cmap" );
+ DWORD nRC = Ft2GetFontData( hPS, CmapTag, 0, NULL, 0 );
+ // read the CMAP table if available
+ if( nRC != FT2_ERROR )
+ {
+ const int nLength = nRC;
+ std::vector<unsigned char> aCmap( nLength );
+ unsigned char* pCmap = &aCmap[0];
+ nRC = Ft2GetFontData( hPS, CmapTag, 0, pCmap, nLength );
+ // parse the CMAP table
+ if( nRC == nLength )
+ ParseCMAP( pCmap, nLength, aResult );
+ } else {
+ // we need to define at least a simple charmap, otherwise this font
+ // will be mapped to default charmap, and OOo doesn't accept the
+ // system font to match the default charmap
+ aResult.mnPairCount = 1;
+ // ImplFontCharMap destructor will free this memory
+ aResult.mpPairCodes = new sal_uInt32[ 2 * aResult.mnPairCount ];
+ aResult.mpPairCodes[0] = 0x0020;
+ aResult.mpPairCodes[1] = 0x00FF;
+ aResult.mpStartGlyphs = NULL;
+ }
+
+ mbDisableGlyphApi |= aResult.mbRecoded;
+
+ if( aResult.mnPairCount > 0 )
+ mpUnicodeMap = new ImplFontCharMap( aResult.mnPairCount,
+ aResult.mpPairCodes, aResult.mpStartGlyphs );
+ else
+ mpUnicodeMap = ImplFontCharMap::GetDefaultMap();
+}
+
+// =======================================================================
+
+void Os2SalGraphics::SetTextColor( SalColor nSalColor )
+{
+ CHARBUNDLE cb;
+
+ cb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
+ SALCOLOR_GREEN( nSalColor ),
+ SALCOLOR_BLUE( nSalColor ) );
+
+ // set default color attributes
+ Ft2SetAttrs( mhPS,
+ PRIM_CHAR,
+ CBB_COLOR,
+ 0,
+ &cb );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Os2SalGraphics::ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int nFallbackLevel)
+{
+
+#if OSL_DEBUG_LEVEL>10
+ debug_printf( "Os2SalGraphics::ImplDoSetFont\n");
+#endif
+
+ ImplOs2FontData* pFontData = (ImplOs2FontData*)i_pFont->mpFontData;
+ PFONTMETRICS pFontMetric = NULL;
+ FATTRS aFAttrs;
+ BOOL bOutline = FALSE;
+ APIRET rc;
+
+ memset( &aFAttrs, 0, sizeof( FATTRS ) );
+ aFAttrs.usRecordLength = sizeof( FATTRS );
+
+ aFAttrs.lMaxBaselineExt = i_pFont->mnHeight;
+ aFAttrs.lAveCharWidth = i_pFont->mnWidth;
+
+ // do we have a pointer to the FONTMETRICS of the selected font? -> use it!
+ if ( pFontData )
+ {
+ pFontMetric = pFontData->GetFontMetrics();
+
+ bOutline = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
+
+ // use match&registry fields to get correct match
+ aFAttrs.lMatch = pFontMetric->lMatch;
+ aFAttrs.idRegistry = pFontMetric->idRegistry;
+ aFAttrs.usCodePage = pFontMetric->usCodePage;
+
+ if ( bOutline )
+ {
+ aFAttrs.fsFontUse |= FATTR_FONTUSE_OUTLINE;
+ if ( i_pFont->mnOrientation )
+ aFAttrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
+ }
+ else
+ {
+ aFAttrs.lMaxBaselineExt = pFontMetric->lMaxBaselineExt;
+ aFAttrs.lAveCharWidth = pFontMetric->lAveCharWidth;
+ }
+
+ }
+
+ // use family name for outline fonts
+ if ( mbPrinter ) {
+ // use font face name for printers because otherwise ft2lib will fail
+ // to select the correct font for GPI (ticket#117)
+ strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
+ } else if ( !pFontMetric) {
+ // use OOo name if fontmetrics not available!
+ ByteString aName( i_pFont->maName.GetToken( 0 ), gsl_getSystemTextEncoding());
+ strncpy( (char*)(aFAttrs.szFacename), aName.GetBuffer(), sizeof( aFAttrs.szFacename ) );
+ } else if ( bOutline) {
+ // use fontmetric family name for outline fonts
+ strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFamilyname, sizeof( aFAttrs.szFacename ) );
+ } else {
+ // use real font face name for bitmaps (WarpSans only)
+ strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
+ }
+
+ if ( i_pFont->meItalic != ITALIC_NONE )
+ aFAttrs.fsSelection |= FATTR_SEL_ITALIC;
+ if ( i_pFont->meWeight > WEIGHT_MEDIUM )
+ aFAttrs.fsSelection |= FATTR_SEL_BOLD;
+
+#if OSL_DEBUG_LEVEL>1
+ if (pFontMetric->szFacename[0] == 'A') {
+ debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS, pFontMetric->lMatch);
+ debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS, pFontMetric->szFacename);
+ debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS, aFAttrs.szFacename);
+ }
+#endif
+
+ Ft2DeleteSetId( mhPS, nFallbackLevel + LCID_BASE);
+ if ( (rc=Ft2CreateLogFont( mhPS, NULL, nFallbackLevel + LCID_BASE, &aFAttrs)) == GPI_ERROR ) {
+#if OSL_DEBUG_LEVEL>1
+ ERRORID nLastError = WinGetLastError( GetSalData()->mhAB );
+ debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS, nLastError );
+#endif
+ return SAL_SETFONT_REMOVEANDMATCHNEW;
+ }
+
+ CHARBUNDLE aBundle;
+
+ ULONG nAttrsDefault = 0;
+ ULONG nAttrs = CBB_SET;
+ aBundle.usSet = nFallbackLevel + LCID_BASE;
+
+ if ( bOutline )
+ {
+ nAttrs |= CBB_BOX;
+ aBundle.sizfxCell.cy = MAKEFIXED( i_pFont->mnHeight, 0 );
+
+ if ( !i_pFont->mnWidth )
+ {
+ LONG nXFontRes;
+ LONG nYFontRes;
+ LONG nHeight;
+
+ // Auf die Aufloesung achten, damit das Ergebnis auch auf
+ // Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet
+ // werden, da auf meinem OS2 beispielsweise als
+ // Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck-
+ // gegeben wird
+ GetResolution( nXFontRes, nYFontRes );
+ nHeight = i_pFont->mnHeight;
+ nHeight *= nXFontRes;
+ nHeight += nYFontRes/2;
+ nHeight /= nYFontRes;
+ aBundle.sizfxCell.cx = MAKEFIXED( nHeight, 0 );
+ }
+ else
+ aBundle.sizfxCell.cx = MAKEFIXED( i_pFont->mnWidth, 0 );
+ }
+
+ // set orientation for outlinefonts
+ if ( i_pFont->mnOrientation )
+ {
+ if ( bOutline )
+ {
+ nAttrs |= CBB_ANGLE;
+ double alpha = (double)(i_pFont->mnOrientation);
+ alpha *= 0.0017453292; // *PI / 1800
+ mnOrientationY = (long) (1000.0 * sin( alpha ));
+ mnOrientationX = (long) (1000.0 * cos( alpha ));
+ aBundle.ptlAngle.x = mnOrientationX;
+ aBundle.ptlAngle.y = mnOrientationY;
+ }
+ else
+ {
+ mnOrientationX = 1;
+ mnOrientationY = 0;
+ nAttrs |= CBB_ANGLE;
+ aBundle.ptlAngle.x = 1;
+ aBundle.ptlAngle.y = 0;
+ }
+ }
+ else
+ {
+ mnOrientationX = 1;
+ mnOrientationY = 0;
+ nAttrs |= CBB_ANGLE;
+ aBundle.ptlAngle.x = 1;
+ aBundle.ptlAngle.y = 0;
+ }
+
+ rc = Ft2SetAttrs( mhPS, PRIM_CHAR, nAttrs, nAttrsDefault, &aBundle );
+
+#if OSL_DEBUG_LEVEL>1
+ FONTMETRICS aOS2Metric = {0};
+ Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
+#endif
+
+ return 0;
+}
+
+
+USHORT Os2SalGraphics::SetFont( ImplFontSelectData* pFont, int nFallbackLevel )
+{
+
+ // return early if there is no new font
+ if( !pFont )
+ {
+#if 0
+ // deselect still active font
+ if( mhDefFont )
+ Ft2SetCharSet( mhPS, mhDefFont );
+ // release no longer referenced font handles
+ for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
+ {
+ if( mhFonts[i] )
+ Ft2DeleteSetId( mhPS, mhFonts[i] );
+ mhFonts[ i ] = 0;
+ }
+#endif
+ mhDefFont = 0;
+ return 0;
+ }
+
+#if OSL_DEBUG_LEVEL>10
+ debug_printf( "Os2SalGraphics::SetFont\n");
+#endif
+
+ DBG_ASSERT( pFont->mpFontData, "WinSalGraphics mpFontData==NULL");
+ mpOs2FontEntry[ nFallbackLevel ] = reinterpret_cast<ImplOs2FontEntry*>( pFont->mpFontEntry );
+ mpOs2FontData[ nFallbackLevel ] = static_cast<const ImplOs2FontData*>( pFont->mpFontData );
+
+ ImplDoSetFont( pFont, mfFontScale, nFallbackLevel);
+
+ if( !mhDefFont )
+ {
+ // keep default font
+ mhDefFont = nFallbackLevel + LCID_BASE;
+ }
+ else
+ {
+ // release no longer referenced font handles
+ for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
+ {
+ if( mhFonts[i] )
+ {
+#if 0
+ Ft2DeleteSetId( mhPS, mhFonts[i] );
+#endif
+ mhFonts[i] = 0;
+ }
+ }
+ }
+
+ // store new font in correct layer
+ mhFonts[ nFallbackLevel ] = nFallbackLevel + LCID_BASE;
+
+ // now the font is live => update font face
+ if( mpOs2FontData[ nFallbackLevel ] )
+ mpOs2FontData[ nFallbackLevel ]->UpdateFromHPS( mhPS );
+
+ if( !nFallbackLevel )
+ {
+ mbFontKernInit = TRUE;
+ if ( mpFontKernPairs )
+ {
+ delete[] mpFontKernPairs;
+ mpFontKernPairs = NULL;
+ }
+ mnFontKernPairCount = 0;
+ }
+
+ // some printers have higher internal resolution, so their
+ // text output would be different from what we calculated
+ // => suggest DrawTextArray to workaround this problem
+ if ( mbPrinter )
+ return SAL_SETFONT_USEDRAWTEXTARRAY;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::GetFontMetric( ImplFontMetricData* pMetric )
+{
+ FONTMETRICS aOS2Metric;
+ Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
+
+#if OSL_DEBUG_LEVEL>1
+ debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS);
+ if (aOS2Metric.szFacename[0] == 'A') {
+ debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS, aOS2Metric.szFacename);
+ debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS, aOS2Metric.lMatch);
+ }
+#endif
+
+ pMetric->maName = UniString( aOS2Metric.szFamilyname, gsl_getSystemTextEncoding());
+ pMetric->maStyleName = ImpStyleNameToSal( aOS2Metric.szFamilyname,
+ aOS2Metric.szFacename,
+ strlen( aOS2Metric.szFamilyname ) );
+
+ // device independent font attributes
+ pMetric->meFamily = ImplFamilyToSal( aOS2Metric.panose.bFamilyType);
+ pMetric->mbSymbolFlag = (aOS2Metric.usCodePage == SYMBOL_CHARSET);
+ pMetric->meWeight = ImplWeightToSal( aOS2Metric.usWeightClass );
+ pMetric->mePitch = ImplLogPitchToSal( aOS2Metric.fsType );
+ pMetric->meItalic = (aOS2Metric.fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
+ pMetric->mnSlant = 0;
+
+ // device dependend font attributes
+ pMetric->mbDevice = (aOS2Metric.fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
+ pMetric->mbScalableFont = (aOS2Metric.fsDefn & FM_DEFN_OUTLINE) ? true : false;
+ if( pMetric->mbScalableFont )
+ {
+ // check if there are kern pairs
+ // TODO: does this work with GPOS kerning?
+ pMetric->mbKernableFont = (aOS2Metric.sKerningPairs > 0);
+ }
+ else
+ {
+ // bitmap fonts cannot be rotated directly
+ pMetric->mnOrientation = 0;
+ // bitmap fonts have no kerning
+ pMetric->mbKernableFont = false;
+ }
+
+ // transformation dependend font metrics
+ if ( aOS2Metric.fsDefn & FM_DEFN_OUTLINE )
+ {
+ pMetric->mnWidth = aOS2Metric.lEmInc;
+ }
+ else
+ {
+ pMetric->mnWidth = aOS2Metric.lAveCharWidth;
+ pMetric->mnOrientation = 0;
+ }
+ pMetric->mnIntLeading = aOS2Metric.lInternalLeading;
+ pMetric->mnExtLeading = aOS2Metric.lExternalLeading;
+ pMetric->mnAscent = aOS2Metric.lMaxAscender;
+ pMetric->mnDescent = aOS2Metric.lMaxDescender;
+
+ // #107888# improved metric compatibility for Asian fonts...
+ // TODO: assess workaround below for CWS >= extleading
+ // TODO: evaluate use of aWinMetric.sTypo* members for CJK
+ if( mpOs2FontData[0] && mpOs2FontData[0]->SupportsCJK() )
+ {
+ pMetric->mnIntLeading += pMetric->mnExtLeading;
+
+ // #109280# The line height for Asian fonts is too small.
+ // Therefore we add half of the external leading to the
+ // ascent, the other half is added to the descent.
+ const long nHalfTmpExtLeading = pMetric->mnExtLeading / 2;
+ const long nOtherHalfTmpExtLeading = pMetric->mnExtLeading - nHalfTmpExtLeading;
+
+ // #110641# external leading for Asian fonts.
+ // The factor 0.3 has been confirmed with experiments.
+ long nCJKExtLeading = static_cast<long>(0.30 * (pMetric->mnAscent + pMetric->mnDescent));
+ nCJKExtLeading -= pMetric->mnExtLeading;
+ pMetric->mnExtLeading = (nCJKExtLeading > 0) ? nCJKExtLeading : 0;
+
+ pMetric->mnAscent += nHalfTmpExtLeading;
+ pMetric->mnDescent += nOtherHalfTmpExtLeading;
+
+ // #109280# HACK korean only: increase descent for wavelines and impr
+ // YD win9x only
+ }
+
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Os2SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs )
+{
+ DBG_ASSERT( sizeof( KERNINGPAIRS ) == sizeof( ImplKernPairData ),
+ "Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" );
+
+ if ( mbFontKernInit )
+ {
+ if( mpFontKernPairs )
+ {
+ delete[] mpFontKernPairs;
+ mpFontKernPairs = NULL;
+ }
+ mnFontKernPairCount = 0;
+
+ {
+ KERNINGPAIRS* pPairs = NULL;
+ FONTMETRICS aOS2Metric;
+ Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
+ int nCount = aOS2Metric.sKerningPairs;
+ if( nCount )
+ {
+#ifdef GCP_KERN_HACK
+ pPairs = new KERNINGPAIRS[ nCount+1 ];
+ mpFontKernPairs = pPairs;
+ mnFontKernPairCount = nCount;
+ Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
+#else // GCP_KERN_HACK
+ pPairs = (KERNINGPAIRS*)pKernPairs;
+ nCount = (nCount < nPairs) ? nCount : nPairs;
+ Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
+ return nCount;
+#endif // GCP_KERN_HACK
+ }
+ }
+
+ mbFontKernInit = FALSE;
+
+ std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData );
+ }
+
+ if( !pKernPairs )
+ return mnFontKernPairCount;
+ else if( mpFontKernPairs )
+ {
+ if ( nPairs < mnFontKernPairCount )
+ nPairs = mnFontKernPairCount;
+ memcpy( pKernPairs, mpFontKernPairs,
+ nPairs*sizeof( ImplKernPairData ) );
+ return nPairs;
+ }
+
+ return 0;
+}
+
+
+// -----------------------------------------------------------------------
+
+static ImplFontCharMap* pOs2DefaultImplFontCharMap = NULL;
+static const sal_uInt32 pOs2DefaultRangeCodes[] = {0x0020,0x00FF};
+
+ImplFontCharMap* Os2SalGraphics::GetImplFontCharMap() const
+{
+ if( !mpOs2FontData[0] )
+ return ImplFontCharMap::GetDefaultMap();
+ return mpOs2FontData[0]->GetImplFontCharMap();
+}
+
+// -----------------------------------------------------------------------
+
+bool Os2SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
+ const String& rFontFileURL, const String& rFontName )
+{
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalGraphics::AddTempDevFont\n");
+#endif
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalGraphics::GetDevFontList( ImplDevFontList* pList )
+{
+ PFONTMETRICS pFontMetrics;
+ ULONG nFontMetricCount;
+ SalData* pSalData;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalGraphics::GetDevFontList\n");
+#endif
+
+ // install OpenSymbol
+ HMODULE hMod;
+ ULONG ObjNum, Offset, rc;
+ CHAR Buff[2*_MAX_PATH];
+ char drive[_MAX_DRIVE], dir[_MAX_DIR];
+ char fname[_MAX_FNAME], ext[_MAX_EXT];
+ // get module handle (and name)
+ rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff,
+ &Offset, (ULONG)ImplSalGetUniString);
+ DosQueryModuleName(hMod, sizeof(Buff), Buff);
+ // replace module path with font path
+ char* slash = strrchr( Buff, '\\');
+ *slash = '\0';
+ slash = strrchr( Buff, '\\');
+ *slash = '\0';
+ strcat( Buff, "\\SHARE\\FONTS\\TRUETYPE\\OPENS___.TTF");
+ rc = GpiLoadPublicFonts( GetSalData()->mhAB, Buff);
+
+ if ( !mbPrinter )
+ {
+ // Bei Bildschirm-Devices cachen wir die Liste global, da
+ // dies im unabhaengigen Teil auch so gemacht wird und wir
+ // ansonsten auf geloeschten Systemdaten arbeiten koennten
+ pSalData = GetSalData();
+ nFontMetricCount = pSalData->mnFontMetricCount;
+ pFontMetrics = pSalData->mpFontMetrics;
+ // Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu
+ if ( pFontMetrics )
+ {
+ delete pFontMetrics;
+ pFontMetrics = NULL;
+ nFontMetricCount = 0;
+ }
+ }
+ else
+ {
+ nFontMetricCount = mnFontMetricCount;
+ pFontMetrics = mpFontMetrics;
+ }
+
+ // do we have to create the cached font list first?
+ if ( !pFontMetrics )
+ {
+ // query the number of fonts available
+ LONG nTemp = 0;
+ nFontMetricCount = Ft2QueryFonts( mhPS,
+ QF_PUBLIC | QF_PRIVATE,
+ NULL, &nTemp,
+ sizeof( FONTMETRICS ), NULL );
+
+ // procede only if at least one is available!
+ if ( nFontMetricCount )
+ {
+ // allocate memory for font list
+ pFontMetrics = new FONTMETRICS[nFontMetricCount];
+
+ // query font list
+ Ft2QueryFonts( mhPS,
+ QF_PUBLIC | QF_PRIVATE,
+ NULL,
+ (PLONG)&nFontMetricCount,
+ (LONG) sizeof( FONTMETRICS ),
+ pFontMetrics );
+ }
+
+ if ( !mbPrinter )
+ {
+ pSalData->mnFontMetricCount = nFontMetricCount;
+ pSalData->mpFontMetrics = pFontMetrics;
+ }
+ else
+ {
+ mnFontMetricCount = nFontMetricCount;
+ mpFontMetrics = pFontMetrics;
+ }
+ }
+
+ // copy data from the font list
+ for( ULONG i = 0; i < nFontMetricCount; i++ )
+ {
+ PFONTMETRICS pFontMetric = &pFontMetrics[i];
+
+ // skip font starting with '@', this is an alias internally
+ // used by truetype engine.
+ if (pFontMetric->szFacename[0] == '@')
+ continue;
+
+ // skip bitmap fonts (but keep WarpSans)
+ if ( (pFontMetric->fsDefn & FM_DEFN_OUTLINE) == 0
+ && strncmp( pFontMetric->szFacename, "WarpSans", 8) )
+ // Font nicht aufnehmen
+ continue;
+
+ // replace '-' in facename with ' ' (for ft2lib)
+ char* dash = pFontMetric->szFacename;
+ while( (dash=strchr( dash, '-')))
+ *dash++ = ' ';
+
+ // create new font list element
+ ImplOs2FontData* pData = new ImplOs2FontData( pFontMetric, 0, 0 );
+
+ // add font list element to font list
+ pList->Add( pData );
+
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+void Os2SalGraphics::GetDevFontSubstList( OutputDevice* pOutDev )
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& rRect )
+{
+ // use unity matrix
+ MAT2 aMat;
+ aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
+ aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
+
+ UINT nGGOFlags = GGO_METRICS;
+ if( !(nIndex & GF_ISCHAR) )
+ nGGOFlags |= GGO_GLYPH_INDEX;
+ nIndex &= GF_IDXMASK;
+
+ GLYPHMETRICS aGM;
+ DWORD nSize = FT2_ERROR;
+ nSize = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGM, 0, NULL, &aMat );
+ if( nSize == FT2_ERROR )
+ return false;
+
+ rRect = Rectangle( Point( +aGM.gmptGlyphOrigin.x, -aGM.gmptGlyphOrigin.y ),
+ Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) );
+ rRect.Left() = static_cast<int>( mfFontScale * rRect.Left() );
+ rRect.Right() = static_cast<int>( mfFontScale * rRect.Right() );
+ rRect.Top() = static_cast<int>( mfFontScale * rRect.Top() );
+ rRect.Bottom() = static_cast<int>( mfFontScale * rRect.Bottom() );
+ return true;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB2DPolyPoly )
+{
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalGraphics::GetGlyphOutline\n");
+#endif
+ rB2DPolyPoly.clear();
+
+ BOOL bRet = FALSE;
+
+ // use unity matrix
+ MAT2 aMat;
+ aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
+ aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
+
+ UINT nGGOFlags = GGO_NATIVE;
+ if( !(nIndex & GF_ISCHAR) )
+ nGGOFlags |= GGO_GLYPH_INDEX;
+ nIndex &= GF_IDXMASK;
+
+ GLYPHMETRICS aGlyphMetrics;
+ DWORD nSize1 = FT2_ERROR;
+ nSize1 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGlyphMetrics, 0, NULL, &aMat );
+
+ if( !nSize1 ) // blank glyphs are ok
+ bRet = TRUE;
+ else if( nSize1 != FT2_ERROR )
+ {
+ BYTE* pData = new BYTE[ nSize1 ];
+ ULONG nTotalCount = 0;
+ DWORD nSize2;
+ nSize2 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags,
+ &aGlyphMetrics, nSize1, pData, &aMat );
+
+ if( nSize1 == nSize2 )
+ {
+ bRet = TRUE;
+
+ int nPtSize = 512;
+ Point* pPoints = new Point[ nPtSize ];
+ BYTE* pFlags = new BYTE[ nPtSize ];
+
+ TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData;
+ while( (BYTE*)pHeader < pData+nSize2 )
+ {
+ // only outline data is interesting
+ if( pHeader->dwType != TT_POLYGON_TYPE )
+ break;
+
+ // get start point; next start points are end points
+ // of previous segment
+ int nPnt = 0;
+
+ long nX = IntTimes256FromFixed( pHeader->pfxStart.x );
+ long nY = IntTimes256FromFixed( pHeader->pfxStart.y );
+ pPoints[ nPnt ] = Point( nX, nY );
+ pFlags[ nPnt++ ] = POLY_NORMAL;
+
+ bool bHasOfflinePoints = false;
+ TTPOLYCURVE* pCurve = (TTPOLYCURVE*)( pHeader + 1 );
+ pHeader = (TTPOLYGONHEADER*)( (BYTE*)pHeader + pHeader->cb );
+ while( (BYTE*)pCurve < (BYTE*)pHeader )
+ {
+ int nNeededSize = nPnt + 16 + 3 * pCurve->cpfx;
+ if( nPtSize < nNeededSize )
+ {
+ Point* pOldPoints = pPoints;
+ BYTE* pOldFlags = pFlags;
+ nPtSize = 2 * nNeededSize;
+ pPoints = new Point[ nPtSize ];
+ pFlags = new BYTE[ nPtSize ];
+ for( int i = 0; i < nPnt; ++i )
+ {
+ pPoints[ i ] = pOldPoints[ i ];
+ pFlags[ i ] = pOldFlags[ i ];
+ }
+ delete[] pOldPoints;
+ delete[] pOldFlags;
+ }
+
+ int i = 0;
+ if( TT_PRIM_LINE == pCurve->wType )
+ {
+ while( i < pCurve->cpfx )
+ {
+ nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
+ nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
+ ++i;
+ pPoints[ nPnt ] = Point( nX, nY );
+ pFlags[ nPnt ] = POLY_NORMAL;
+ ++nPnt;
+ }
+ }
+ else if( TT_PRIM_QSPLINE == pCurve->wType )
+ {
+ bHasOfflinePoints = true;
+ while( i < pCurve->cpfx )
+ {
+ // get control point of quadratic bezier spline
+ nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
+ nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
+ ++i;
+ Point aControlP( nX, nY );
+
+ // calculate first cubic control point
+ // P0 = 1/3 * (PBeg + 2 * PQControl)
+ nX = pPoints[ nPnt-1 ].X() + 2 * aControlP.X();
+ nY = pPoints[ nPnt-1 ].Y() + 2 * aControlP.Y();
+ pPoints[ nPnt+0 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
+ pFlags[ nPnt+0 ] = POLY_CONTROL;
+
+ // calculate endpoint of segment
+ nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
+ nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
+
+ if ( i+1 >= pCurve->cpfx )
+ {
+ // endpoint is either last point in segment => advance
+ ++i;
+ }
+ else
+ {
+ // or endpoint is the middle of two control points
+ nX += IntTimes256FromFixed( pCurve->apfx[ i-1 ].x );
+ nY += IntTimes256FromFixed( pCurve->apfx[ i-1 ].y );
+ nX = (nX + 1) / 2;
+ nY = (nY + 1) / 2;
+ // no need to advance, because the current point
+ // is the control point in next bezier spline
+ }
+
+ pPoints[ nPnt+2 ] = Point( nX, nY );
+ pFlags[ nPnt+2 ] = POLY_NORMAL;
+
+ // calculate second cubic control point
+ // P1 = 1/3 * (PEnd + 2 * PQControl)
+ nX = pPoints[ nPnt+2 ].X() + 2 * aControlP.X();
+ nY = pPoints[ nPnt+2 ].Y() + 2 * aControlP.Y();
+ pPoints[ nPnt+1 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
+ pFlags[ nPnt+1 ] = POLY_CONTROL;
+
+ nPnt += 3;
+ }
+ }
+
+ // next curve segment
+ pCurve = (TTPOLYCURVE*)&pCurve->apfx[ i ];
+ }
+
+ // end point is start point for closed contour
+ // disabled, because Polygon class closes the contour itself
+ // pPoints[nPnt++] = pPoints[0];
+ // #i35928#
+ // Added again, but add only when not yet closed
+ if(pPoints[nPnt - 1] != pPoints[0])
+ {
+ if( bHasOfflinePoints )
+ pFlags[nPnt] = pFlags[0];
+
+ pPoints[nPnt++] = pPoints[0];
+ }
+
+ // convert y-coordinates W32 -> VCL
+ for( int i = 0; i < nPnt; ++i )
+ pPoints[i].Y() = -pPoints[i].Y();
+
+ // insert into polypolygon
+ Polygon aPoly( nPnt, pPoints, (bHasOfflinePoints ? pFlags : NULL) );
+ // convert to B2DPolyPolygon
+ // TODO: get rid of the intermediate PolyPolygon
+ rB2DPolyPoly.append( aPoly.getB2DPolygon() );
+ }
+
+ delete[] pPoints;
+ delete[] pFlags;
+ }
+
+ delete[] pData;
+ }
+
+ // rescaling needed for the PolyPolygon conversion
+ if( rB2DPolyPoly.count() )
+ {
+ const double fFactor((1.0/256) * mfFontScale);
+ rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor));
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+// TODO: Replace this class with boost::scoped_array
+class ScopedCharArray
+{
+public:
+ inline explicit ScopedCharArray(char * pArray): m_pArray(pArray) {}
+
+ inline ~ScopedCharArray() { delete[] m_pArray; }
+
+ inline char * get() const { return m_pArray; }
+
+private:
+ char * m_pArray;
+};
+
+class ScopedFont
+{
+public:
+ explicit ScopedFont(Os2SalGraphics & rData);
+
+ ~ScopedFont();
+
+private:
+ Os2SalGraphics & m_rData;
+ ULONG m_hOrigFont;
+};
+
+ScopedFont::ScopedFont(Os2SalGraphics & rData): m_rData(rData)
+{
+#if 0
+ m_hOrigFont = m_rData.mhFonts[0];
+ m_rData.mhFonts[0] = 0; // avoid deletion of current font
+#endif
+}
+
+ScopedFont::~ScopedFont()
+{
+#if 0
+ if( m_hOrigFont )
+ {
+ // restore original font, destroy temporary font
+ HFONT hTempFont = m_rData.mhFonts[0];
+ m_rData.mhFonts[0] = m_hOrigFont;
+ SelectObject( m_rData.mhDC, m_hOrigFont );
+ DeleteObject( hTempFont );
+ }
+#endif
+}
+
+class ScopedTrueTypeFont
+{
+public:
+ inline ScopedTrueTypeFont(): m_pFont(0) {}
+
+ ~ScopedTrueTypeFont();
+
+ int open(void * pBuffer, sal_uInt32 nLen, sal_uInt32 nFaceNum);
+
+ inline TrueTypeFont * get() const { return m_pFont; }
+
+private:
+ TrueTypeFont * m_pFont;
+};
+
+ScopedTrueTypeFont::~ScopedTrueTypeFont()
+{
+ if (m_pFont != 0)
+ CloseTTFont(m_pFont);
+}
+
+int ScopedTrueTypeFont::open(void * pBuffer, sal_uInt32 nLen,
+ sal_uInt32 nFaceNum)
+{
+ OSL_ENSURE(m_pFont == 0, "already open");
+ return OpenTTFontBuffer(pBuffer, nLen, nFaceNum, &m_pFont);
+}
+
+BOOL Os2SalGraphics::CreateFontSubset( const rtl::OUString& rToFile,
+ const ImplFontData* pFont, long* pGlyphIDs, sal_uInt8* pEncoding,
+ sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo )
+{
+ // create matching ImplFontSelectData
+ // we need just enough to get to the font file data
+ // use height=1000 for easier debugging (to match psprint's font units)
+ ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
+
+ // TODO: much better solution: move SetFont and restoration of old font to caller
+ ScopedFont aOldFont(*this);
+ SetFont( &aIFSD, 0 );
+
+#if OSL_DEBUG_LEVEL > 100
+ // get font metrics
+ TEXTMETRICA aWinMetric;
+ if( !::GetTextMetricsA( mhDC, &aWinMetric ) )
+ return FALSE;
+
+ DBG_ASSERT( !(aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "cannot subset device font" );
+ DBG_ASSERT( aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE, "can only subset TT font" );
+#endif
+
+ // get raw font file data
+ DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
+ if( nFontSize1 == FT2_ERROR )
+ return FALSE;
+ ScopedCharArray xRawFontData(new char[ nFontSize1 ]);
+ DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 );
+ if( nFontSize1 != nFontSize2 )
+ return FALSE;
+
+ // open font file
+ sal_uInt32 nFaceNum = 0;
+ if( !*xRawFontData.get() ) // TTC candidate
+ nFaceNum = ~0U; // indicate "TTC font extracts only"
+
+ ScopedTrueTypeFont aSftTTF;
+ int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum );
+ if( nRC != SF_OK )
+ return FALSE;
+
+ TTGlobalFontInfo aTTInfo;
+ ::GetTTGlobalFontInfo( aSftTTF.get(), &aTTInfo );
+ rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TRUETYPE;
+ rInfo.m_aPSName = ImplSalGetUniString( aTTInfo.psname );
+ rInfo.m_nAscent = +aTTInfo.winAscent;
+ rInfo.m_nDescent = -aTTInfo.winDescent;
+ rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ),
+ Point( aTTInfo.xMax, aTTInfo.yMax ) );
+ rInfo.m_nCapHeight = aTTInfo.yMax; // Well ...
+
+ // subset glyphs and get their properties
+ // take care that subset fonts require the NotDef glyph in pos 0
+ int nOrigCount = nGlyphCount;
+ USHORT aShortIDs[ 256 ];
+ sal_uInt8 aTempEncs[ 256 ];
+
+ int nNotDef=-1, i;
+ for( i = 0; i < nGlyphCount; ++i )
+ {
+ aTempEncs[i] = pEncoding[i];
+ sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
+ if( pGlyphIDs[i] & GF_ISCHAR )
+ {
+ bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0;
+ nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
+ if( nGlyphIdx == 0 && pFont->IsSymbolFont() )
+ {
+ // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX
+ nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
+ nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 );
+ nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
+ }
+ }
+ aShortIDs[i] = static_cast<USHORT>( nGlyphIdx );
+ if( !nGlyphIdx )
+ if( nNotDef < 0 )
+ nNotDef = i; // first NotDef glyph found
+ }
+
+ if( nNotDef != 0 )
+ {
+ // add fake NotDef glyph if needed
+ if( nNotDef < 0 )
+ nNotDef = nGlyphCount++;
+
+ // NotDef glyph must be in pos 0 => swap glyphids
+ aShortIDs[ nNotDef ] = aShortIDs[0];
+ aTempEncs[ nNotDef ] = aTempEncs[0];
+ aShortIDs[0] = 0;
+ aTempEncs[0] = 0;
+ }
+ DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" );
+
+ // fill pWidth array
+ TTSimpleGlyphMetrics* pMetrics =
+ ::GetTTSimpleGlyphMetrics( aSftTTF.get(), aShortIDs, nGlyphCount, aIFSD.mbVertical );
+ if( !pMetrics )
+ return FALSE;
+ sal_uInt16 nNotDefAdv = pMetrics[0].adv;
+ pMetrics[0].adv = pMetrics[nNotDef].adv;
+ pMetrics[nNotDef].adv = nNotDefAdv;
+ for( i = 0; i < nOrigCount; ++i )
+ pGlyphWidths[i] = pMetrics[i].adv;
+ free( pMetrics );
+
+ // write subset into destination file
+ rtl::OUString aSysPath;
+ if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) )
+ return FALSE;
+ rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding();
+ ByteString aToFile( rtl::OUStringToOString( aSysPath, aThreadEncoding ) );
+ nRC = ::CreateTTFromTTGlyphs( aSftTTF.get(), aToFile.GetBuffer(), aShortIDs,
+ aTempEncs, nGlyphCount, 0, NULL, 0 );
+ return nRC == SF_OK;
+}
+
+//--------------------------------------------------------------------------
+
+const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData* pFont,
+ const sal_Ucs* pUnicodes, sal_Int32* pCharWidths,
+ FontSubsetInfo& rInfo, long* pDataLen )
+{
+ // create matching ImplFontSelectData
+ // we need just enough to get to the font file data
+ ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
+
+ // TODO: much better solution: move SetFont and restoration of old font to caller
+ ScopedFont aOldFont(*this);
+ SetFont( &aIFSD, 0 );
+
+ // get the raw font file data
+ DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
+ if( nFontSize1 == FT2_ERROR || nFontSize1 <= 0 )
+ return NULL;
+ *pDataLen = nFontSize1;
+ void* pData = reinterpret_cast<void*>(new char[ nFontSize1 ]);
+ DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, pData, nFontSize1 );
+ if( nFontSize1 != nFontSize2 )
+ *pDataLen = 0;
+
+ // get important font properties
+ FONTMETRICS aOS2Metric;
+ if (Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ) == GPI_ERROR)
+ *pDataLen = 0;
+ rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TYPE1;
+ rInfo.m_aPSName = ImplSalGetUniString( aOS2Metric.szFacename );
+ rInfo.m_nAscent = +aOS2Metric.lMaxAscender;
+ rInfo.m_nDescent = -aOS2Metric.lMaxDescender;
+ rInfo.m_aFontBBox = Rectangle( Point( 0, -aOS2Metric.lMaxDescender ),
+ Point( aOS2Metric.lMaxCharInc, aOS2Metric.lMaxAscender+aOS2Metric.lExternalLeading ) );
+ rInfo.m_nCapHeight = aOS2Metric.lMaxAscender; // Well ...
+
+ // get individual character widths
+ for( int i = 0; i < 256; ++i )
+ {
+ LONG nCharWidth = 0;
+ const sal_Ucs cChar = pUnicodes[i];
+ if( !Ft2QueryStringWidthW( mhPS, (LPWSTR)&cChar, 1, &nCharWidth ) )
+ *pDataLen = 0;
+ pCharWidths[i] = nCharWidth;
+ }
+
+ if( !*pDataLen )
+ {
+ FreeEmbedFontData( pData, nFontSize1 );
+ pData = NULL;
+ }
+
+ return pData;
+}
+
+//--------------------------------------------------------------------------
+
+void Os2SalGraphics::FreeEmbedFontData( const void* pData, long /*nLen*/ )
+{
+ delete[] reinterpret_cast<char*>(const_cast<void*>(pData));
+}
+
+const Ucs2SIntMap* Os2SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
+{
+ // TODO: even for builtin fonts we get here... why?
+ if( !pFont->IsEmbeddable() )
+ return NULL;
+
+ // fill the encoding vector
+ Ucs2SIntMap& rMap = *new Ucs2SIntMap;
+#if 0
+ // TODO: get correct encoding vector
+ ImplWinFontData* pWinFontData = reinterpret_cast<ImplWinFontData*>(pFont);
+
+ GLYPHSET aGlyphSet;
+ aGlyphSet.cbThis = sizeof(aGlyphSet);
+ DWORD aW = ::GetFontUnicodeRanges( mhDC, &aGlyphSet);
+#else
+ for( sal_Unicode i = 32; i < 256; ++i )
+ rMap[i] = i;
+ if( pNonEncoded )
+ *pNonEncoded = NULL;
+#endif
+
+ return &rMap;
+}
+
+//--------------------------------------------------------------------------
+
+void Os2SalGraphics::GetGlyphWidths( const ImplFontData* pFont,
+ bool bVertical,
+ Int32Vector& rWidths,
+ Ucs2UIntMap& rUnicodeEnc )
+{
+ // create matching ImplFontSelectData
+ // we need just enough to get to the font file data
+ ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
+
+ // TODO: much better solution: move SetFont and restoration of old font to caller
+ ScopedFont aOldFont(*this);
+
+ float fScale = 0.0;
+ ImplDoSetFont( &aIFSD, fScale, 0);
+
+ if( pFont->IsSubsettable() )
+ {
+ // get raw font file data
+ DWORD nFontSize1 = ::Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
+ if( nFontSize1 == FT2_ERROR )
+ return;
+ ScopedCharArray xRawFontData(new char[ nFontSize1 ]);
+ DWORD nFontSize2 = ::Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 );
+ if( nFontSize1 != nFontSize2 )
+ return;
+
+ // open font file
+ sal_uInt32 nFaceNum = 0;
+ if( !*xRawFontData.get() ) // TTC candidate
+ nFaceNum = ~0U; // indicate "TTC font extracts only"
+
+ ScopedTrueTypeFont aSftTTF;
+ int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum );
+ if( nRC != SF_OK )
+ return;
+
+ int nGlyphs = GetTTGlyphCount( aSftTTF.get() );
+ if( nGlyphs > 0 )
+ {
+ rWidths.resize(nGlyphs);
+ std::vector<sal_uInt16> aGlyphIds(nGlyphs);
+ for( int i = 0; i < nGlyphs; i++ )
+ aGlyphIds[i] = sal_uInt16(i);
+ TTSimpleGlyphMetrics* pMetrics = ::GetTTSimpleGlyphMetrics( aSftTTF.get(),
+ &aGlyphIds[0],
+ nGlyphs,
+ bVertical ? 1 : 0 );
+ if( pMetrics )
+ {
+ for( int i = 0; i< nGlyphs; i++ )
+ rWidths[i] = pMetrics[i].adv;
+ free( pMetrics );
+ rUnicodeEnc.clear();
+ }
+ const ImplOs2FontData* pWinFont = static_cast<const ImplOs2FontData*>(pFont);
+ ImplFontCharMap* pMap = pWinFont->GetImplFontCharMap();
+ DBG_ASSERT( pMap && pMap->GetCharCount(), "no map" );
+
+ int nCharCount = pMap->GetCharCount();
+ sal_uInt32 nChar = pMap->GetFirstChar();
+ for( int i = 0; i < nCharCount; i++ )
+ {
+ if( nChar < 0x00010000 )
+ {
+ sal_uInt16 nGlyph = ::MapChar( aSftTTF.get(),
+ static_cast<sal_uInt16>(nChar),
+ bVertical ? 1 : 0 );
+ if( nGlyph )
+ rUnicodeEnc[ static_cast<sal_Unicode>(nChar) ] = nGlyph;
+ }
+ nChar = pMap->GetNextChar( nChar );
+ }
+ }
+ }
+ else if( pFont->IsEmbeddable() )
+ {
+ // get individual character widths
+ rWidths.clear();
+ rUnicodeEnc.clear();
+ rWidths.reserve( 224 );
+ for( sal_Unicode i = 32; i < 256; ++i )
+ {
+ int nCharWidth = 0;
+ if( Ft2QueryStringWidthW( mhPS, (LPWSTR)&i, 1, (LONG*)&nCharWidth ) )
+ {
+ rUnicodeEnc[ i ] = rWidths.size();
+ rWidths.push_back( nCharWidth );
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void Os2SalGraphics::DrawServerFontLayout( const ServerFontLayout& )
+{}
+
+//--------------------------------------------------------------------------
+
+SystemFontData Os2SalGraphics::GetSysFontData( int nFallbacklevel ) const
+{
+ SystemFontData aSysFontData;
+
+ if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
+ if (nFallbacklevel < 0 ) nFallbacklevel = 0;
+
+ aSysFontData.nSize = sizeof( SystemFontData );
+ aSysFontData.hFont = mhFonts[nFallbacklevel];
+ aSysFontData.bFakeBold = false;
+ aSysFontData.bFakeItalic = false;
+ aSysFontData.bAntialias = true;
+ aSysFontData.bVerticalCharacterType = false;
+
+ return aSysFontData;
+}
+
+//--------------------------------------------------------------------------
diff --git a/vcl/os2/source/gdi/salprn.cxx b/vcl/os2/source/gdi/salprn.cxx
new file mode 100644
index 000000000000..1aef34631f2e
--- /dev/null
+++ b/vcl/os2/source/gdi/salprn.cxx
@@ -0,0 +1,1833 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// use this define to disable the DJP support
+// #define NO_DJP
+
+#define INCL_DOSMODULEMGR
+#define INCL_DEV
+#define INCL_SPL
+#define INCL_SPLERRORS
+#define INCL_SPLDOSPRINT
+#define INCL_DEVDJP
+
+#define INCL_GPI
+#define INCL_DOSSEMAPHORES
+#define INCL_PM
+#include <svpm.h>
+#include <pmdjp.h>
+
+#include <string.h>
+
+#define _SV_SALPRN_CXX
+#include <tools/debug.hxx>
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salgdi.h>
+#include <salframe.h>
+#include <vcl/salptype.hxx>
+#include <salprn.h>
+#include <vcl/print.h>
+#include <vcl/jobset.h>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+// =======================================================================
+
+// -----------------------
+// - struct ImplFormInfo -
+// -----------------------
+
+struct ImplFormInfo
+{
+ long mnPaperWidth;
+ long mnPaperHeight;
+#ifndef NO_DJP
+ DJPT_PAPERSIZE mnId;
+#endif
+};
+
+// =======================================================================
+
+// -----------------------
+// - struct ImplTrayInfo -
+// -----------------------
+
+struct ImplTrayInfo
+{
+ CHAR maName[32];
+ CHAR maDisplayName[64];
+ DJPT_TRAYTYPE mnId;
+
+ ImplTrayInfo( const char* pTrayName,
+ const char* pTrayDisplayName )
+ {
+ strcpy( maName, pTrayName);
+ strcpy( maDisplayName, pTrayDisplayName);
+ }
+};
+
+// =======================================================================
+
+struct ImplQueueSalSysData
+{
+ ByteString maPrinterName; // pszPrinters
+ ByteString maName; // pszName bzw. LogAddress
+ ByteString maOrgDriverName; // pszDriverName (maDriverName.maDeviceName)
+ ByteString maDriverName; // pszDriverName bis .
+ ByteString maDeviceName; // pszDriverName nach .
+ PDRIVDATA mpDrivData;
+
+ ImplQueueSalSysData( const ByteString& rPrinterName,
+ const ByteString& rName,
+ const ByteString& rDriverName,
+ const ByteString& rDeviceName,
+ const ByteString& rOrgDriverName,
+ PDRIVDATA pDrivData );
+ ~ImplQueueSalSysData();
+};
+
+// -----------------------------------------------------------------------
+
+ImplQueueSalSysData::ImplQueueSalSysData( const ByteString& rPrinterName,
+ const ByteString& rName,
+ const ByteString& rOrgDriverName,
+ const ByteString& rDriverName,
+ const ByteString& rDeviceName,
+ PDRIVDATA pDrivData ) :
+ maPrinterName( rPrinterName ),
+ maName( rName ),
+ maOrgDriverName( rName ),
+ maDriverName( rDriverName ),
+ maDeviceName( rDeviceName )
+{
+ if ( pDrivData )
+ {
+ mpDrivData = (PDRIVDATA)new BYTE[pDrivData->cb];
+ memcpy( mpDrivData, pDrivData, pDrivData->cb );
+ }
+ else
+ mpDrivData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplQueueSalSysData::~ImplQueueSalSysData()
+{
+ delete mpDrivData;
+}
+
+// =======================================================================
+
+static ULONG ImplPMQueueStatusToSal( USHORT nPMStatus )
+{
+ ULONG nStatus = 0;
+ if ( nPMStatus & PRQ3_PAUSED )
+ nStatus |= QUEUE_STATUS_PAUSED;
+ if ( nPMStatus & PRQ3_PENDING )
+ nStatus |= QUEUE_STATUS_PENDING_DELETION;
+ if ( !nStatus )
+ nStatus |= QUEUE_STATUS_READY;
+ return nStatus;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
+{
+ APIRET rc;
+ ULONG nNeeded;
+ ULONG nReturned;
+ ULONG nTotal;
+
+ // query needed size of the buffer for the QueueInfo
+ rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
+ if( nNeeded == 0 )
+ return;
+
+ // create the buffer for the QueueInfo
+ PCHAR pQueueData = new CHAR[nNeeded];
+
+ // query QueueInfos
+ rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
+
+ PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData;
+ for ( int i = 0; i < nReturned; i++ )
+ {
+ // create entry for the QueueInfo array
+ SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+
+ ByteString aOrgDriverName( pPrqInfo->pszDriverName);
+ ByteString aName( pPrqInfo->pszName);
+ pInfo->maDriver = ::rtl::OStringToOUString (aOrgDriverName, gsl_getSystemTextEncoding());
+ pInfo->maPrinterName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding());
+ pInfo->maLocation = ::rtl::OStringToOUString (aName, gsl_getSystemTextEncoding());
+ pInfo->mnStatus = ImplPMQueueStatusToSal( pPrqInfo->fsStatus );
+ pInfo->mnJobs = pPrqInfo->cJobs;
+ // pInfo->maComment = !!!
+
+ // Feststellen, ob Name doppelt
+ PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData;
+ for ( int j = 0; j < nReturned; j++ )
+ {
+ // Wenn Name doppelt, erweitern wir diesen um die Location
+ if ( (j != i) &&
+ (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) )
+ {
+ pInfo->maPrinterName += ';';
+ pInfo->maPrinterName += pInfo->maLocation;
+ }
+ pTempPrqInfo++;
+ }
+
+ // pszDriver in DriverName (bis .) und DeviceName (nach .) aufsplitten
+ PSZ pDriverName;
+ PSZ pDeviceName;
+ if ( (pDriverName = strchr( pPrqInfo->pszDriverName, '.' )) != 0 )
+ {
+ *pDriverName = 0;
+ pDeviceName = pDriverName + 1;
+ }
+ else
+ pDeviceName = NULL;
+
+ // Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit
+ // ein memcmp vom JobSetup auch funktioniert
+ if ( pPrqInfo->pDriverData &&
+ (pPrqInfo->pDriverData->cb >= sizeof( pPrqInfo->pDriverData )) )
+ {
+ int nDeviceNameLen = strlen( pPrqInfo->pDriverData->szDeviceName );
+ memset( pPrqInfo->pDriverData->szDeviceName+nDeviceNameLen,
+ 0,
+ sizeof( pPrqInfo->pDriverData->szDeviceName )-nDeviceNameLen );
+ }
+
+ // save driver data and driver names
+ ByteString aPrinterName( pPrqInfo->pszPrinters);
+ ByteString aDriverName( pPrqInfo->pszDriverName);
+ ByteString aDeviceName;
+ if ( pDeviceName )
+ aDeviceName = pDeviceName;
+ pInfo->mpSysData = new ImplQueueSalSysData( aPrinterName, aName,
+ aOrgDriverName,
+ aDriverName, aDeviceName,
+ pPrqInfo->pDriverData );
+
+ // add queue to the list
+ pList->Add( pInfo );
+
+ // increment to next element of the QueueInfo array
+ pPrqInfo++;
+ }
+
+ delete [] pQueueData;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
+{
+ APIRET rc;
+ ULONG nNeeded;
+ ULONG nReturned;
+ ULONG nTotal;
+
+ // query needed size of the buffer for the QueueInfo
+ rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
+ if( nNeeded == 0 )
+ return;
+
+ // create the buffer for the QueueInfo
+ PCHAR pQueueData = new CHAR[nNeeded];
+
+ // query QueueInfos
+ rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
+
+ PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData;
+ for ( int i = 0; i < nReturned; i++ )
+ {
+ ImplQueueSalSysData* pSysData = (ImplQueueSalSysData*)(pInfo->mpSysData);
+ if ( pSysData->maPrinterName.Equals( pPrqInfo->pszPrinters ) &&
+ pSysData->maName.Equals( pPrqInfo->pszName ) &&
+ pSysData->maOrgDriverName.Equals( pPrqInfo->pszDriverName ) )
+ {
+ pInfo->mnStatus = ImplPMQueueStatusToSal( pPrqInfo->fsStatus );
+ pInfo->mnJobs = pPrqInfo->cJobs;
+ break;
+ }
+
+ // increment to next element of the QueueInfo array
+ pPrqInfo++;
+ }
+
+ delete [] pQueueData;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
+{
+ delete ((ImplQueueSalSysData*)(pInfo->mpSysData));
+ delete pInfo;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Os2SalInstance::GetDefaultPrinter()
+{
+ APIRET rc;
+ ULONG nNeeded;
+ ULONG nReturned;
+ ULONG nTotal;
+ char szQueueName[255];
+ XubString aDefaultName;
+
+ // query default queue
+ if ( !PrfQueryProfileString( HINI_PROFILE, SPL_INI_SPOOLER, "QUEUE", 0, szQueueName, sizeof( szQueueName ) ) )
+ return aDefaultName;
+
+ // extract first queue name
+ PSZ pStr;
+ if ( (pStr = strchr( szQueueName, ';' )) != 0 )
+ *pStr = 0;
+
+ // query needed size of the buffer for the QueueInfo
+ rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL );
+ if ( nNeeded == 0 )
+ return aDefaultName;
+
+ // create the buffer for the QueueInfo
+ PCHAR pQueueData = new CHAR[ nNeeded ];
+
+ // query QueueInfos
+ rc = SplEnumQueue ((PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL );
+
+ // find printer name for default queue
+ PPRQINFO3 pPrqInfo = (PPRQINFO3) pQueueData;
+ for ( int i = 0; i < nReturned; i++ )
+ {
+ if ( strcmp( pPrqInfo->pszName, szQueueName ) == 0 )
+ {
+ aDefaultName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding());
+
+ // Feststellen, ob Name doppelt
+ PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData;
+ for ( int j = 0; j < nReturned; j++ )
+ {
+ // Wenn Name doppelt, erweitern wir diesen um die Location
+ if ( (j != i) &&
+ (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) )
+ {
+ String pszName( ::rtl::OStringToOUString (pPrqInfo->pszName, gsl_getSystemTextEncoding()));
+ aDefaultName += ';';
+ aDefaultName += pszName;
+ }
+ pTempPrqInfo++;
+ }
+ break;
+ }
+
+ // increment to next element of the QueueInfo array
+ pPrqInfo++;
+ }
+
+ delete [] pQueueData;
+
+ return aDefaultName;
+}
+
+// =======================================================================
+
+static void* ImplAllocPrnMemory( size_t n )
+{
+ return calloc( n, 1);
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplFreePrnMemory( void* p )
+{
+ free( p );
+}
+
+// -----------------------------------------------------------------------
+
+static PDRIVDATA ImplPrnDrivData( const ImplJobSetup* pSetupData )
+{
+ // Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf
+ // unseren Daten arbeiten, da es durch Konfigurationsprobleme
+ // sein kann, das der Druckertreiber bei uns Daten ueberschreibt.
+ // Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw.
+ // sind dadurch leichter zu finden
+
+ if ( !pSetupData->mpDriverData )
+ return NULL;
+
+ DBG_ASSERT( ((PDRIVDATA)(pSetupData->mpDriverData))->cb == pSetupData->mnDriverDataLen,
+ "ImplPrnDrivData() - SetupDataLen != DriverDataLen" );
+
+ PDRIVDATA pDrivData = (PDRIVDATA)ImplAllocPrnMemory( pSetupData->mnDriverDataLen );
+ memcpy( pDrivData, pSetupData->mpDriverData, pSetupData->mnDriverDataLen );
+ return pDrivData;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplUpdateSetupData( const PDRIVDATA pDrivData, ImplJobSetup* pSetupData )
+{
+ // Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf
+ // unseren Daten arbeiten, da es durch Konfigurationsprobleme
+ // sein kann, das der Druckertreiber bei uns Daten ueberschreibt.
+ // Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw.
+ // sind dadurch leichter zu finden
+
+ if ( !pDrivData || !pDrivData->cb )
+ {
+ if ( pSetupData->mpDriverData )
+ rtl_freeMemory( pSetupData->mpDriverData );
+ pSetupData->mpDriverData = NULL;
+ pSetupData->mnDriverDataLen = 0;
+ }
+ else
+ {
+ // Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit
+ // ein memcmp vom JobSetup auch funktioniert
+ if ( pDrivData->cb >= sizeof( pDrivData ) )
+ {
+ int nDeviceNameLen = strlen( pDrivData->szDeviceName );
+ memset( pDrivData->szDeviceName+nDeviceNameLen,
+ 0,
+ sizeof( pDrivData->szDeviceName )-nDeviceNameLen );
+ }
+
+ if ( pSetupData->mpDriverData )
+ {
+ if ( pSetupData->mnDriverDataLen != pDrivData->cb )
+ rtl_freeMemory( pSetupData->mpDriverData );
+ pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb);
+ }
+ else
+ pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb);
+ pSetupData->mnDriverDataLen = pDrivData->cb;
+ memcpy( pSetupData->mpDriverData, pDrivData, pDrivData->cb );
+ }
+
+ if ( pDrivData )
+ ImplFreePrnMemory( pDrivData );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplPaperSizeEqual( long nPaperWidth1, long nPaperHeight1,
+ long nPaperWidth2, long nPaperHeight2 )
+{
+ return (((nPaperWidth1 >= nPaperWidth2-1) && (nPaperWidth1 <= nPaperWidth2+1)) &&
+ ((nPaperHeight1 >= nPaperHeight2-1) && (nPaperHeight1 <= nPaperHeight2+1)));
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplIsDriverDJPEnabled( HDC hDC )
+{
+#ifdef NO_DJP
+ return FALSE;
+#else
+ // Ueber OS2-Ini kann DJP disablte werden
+ if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_USEDJP, 1 ) )
+ return FALSE;
+
+ // Testen, ob DJP-Interface am Drucker vorhanden
+ LONG lQuery;
+ APIRET rc;
+
+ lQuery = DEVESC_QUERYSIZE;
+ rc = DevEscape( hDC,
+ DEVESC_QUERYESCSUPPORT,
+ sizeof( lQuery ),
+ (PBYTE)&lQuery,
+ 0,
+ (PBYTE)NULL );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ lQuery = DEVESC_QUERYJOBPROPERTIES;
+ rc = DevEscape( hDC,
+ DEVESC_QUERYESCSUPPORT,
+ sizeof( lQuery ),
+ (PBYTE)&lQuery,
+ 0,
+ (PBYTE)NULL );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ lQuery = DEVESC_SETJOBPROPERTIES;
+ rc = DevEscape( hDC,
+ DEVESC_QUERYESCSUPPORT,
+ sizeof( lQuery ),
+ (PBYTE)&lQuery,
+ 0,
+ (PBYTE)NULL );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplFormatInputList( PDJP_ITEM pDJP, PQUERYTUPLE pTuple )
+{
+ // Loop through the query elements
+ BOOL fContinue = TRUE;
+ do
+ {
+ pDJP->cb = sizeof (DJP_ITEM);
+ pDJP->ulProperty = pTuple->ulProperty;
+ pDJP->lType = pTuple->lType;
+ pDJP->ulNumReturned = 0;
+ pDJP->ulValue = DJP_NONE;
+
+ // at EOL?
+ fContinue = DJP_NONE != pTuple->ulProperty;
+
+ // Move to next item structure and tuplet
+ pDJP++;
+ pTuple++;
+ }
+ while ( fContinue );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplFreeFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter )
+{
+ if ( pOs2SalInfoPrinter->mnFormCount )
+ {
+ for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnFormCount; i++ )
+ delete pOs2SalInfoPrinter->mpFormArray[i];
+ delete [] pOs2SalInfoPrinter->mpFormArray;
+ pOs2SalInfoPrinter->mnFormCount = 0;
+ }
+
+ if ( pOs2SalInfoPrinter->mnTrayCount )
+ {
+ for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnTrayCount; i++ )
+ delete pOs2SalInfoPrinter->mpTrayArray[i];
+ delete [] pOs2SalInfoPrinter->mpTrayArray;
+ pOs2SalInfoPrinter->mnTrayCount = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter, const ImplJobSetup* pSetupData )
+{
+ ImplFreeFormAndTrayList( pOs2SalInfoPrinter );
+
+ LONG alQuery[] =
+ {
+ 0, 0, // First two members of QUERYSIZE
+ DJP_CJ_FORM, DJP_ALL,
+ DJP_CJ_TRAYNAME, DJP_ALL,
+ DJP_NONE, DJP_NONE // EOL marker
+ };
+
+ APIRET rc;
+ PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery;
+ PBYTE pBuffer = NULL;
+ LONG nAlloc = 0;
+ PDRIVDATA pCopyDrivData = ImplPrnDrivData( pSetupData );
+ LONG nDrivDataSize = pCopyDrivData->cb;
+ PBYTE pDrivData = (PBYTE)pCopyDrivData;
+
+ // find out how many bytes to allocate
+ pQuerySize->cb = sizeof( alQuery );
+ rc = DevEscape( pOs2SalInfoPrinter->mhDC,
+ DEVESC_QUERYSIZE,
+ sizeof( alQuery ),
+ (PBYTE)pQuerySize,
+ &nDrivDataSize,
+ pDrivData );
+ if ( DEV_OK != rc )
+ {
+ ImplFreePrnMemory( pCopyDrivData );
+ return;
+ }
+
+ // allocate the memory
+ nAlloc = pQuerySize->ulSizeNeeded;
+ pBuffer = (PBYTE)new BYTE[nAlloc];
+
+ // set up the input
+ PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
+ ImplFormatInputList( pDJP, pQuerySize->aTuples );
+
+ // do it!
+ rc = DevEscape( pOs2SalInfoPrinter->mhDC,
+ DEVESC_QUERYJOBPROPERTIES,
+ nAlloc,
+ pBuffer,
+ &nDrivDataSize,
+ pDrivData );
+ ImplFreePrnMemory( pCopyDrivData );
+
+ if ( (DEV_OK == rc) || (DEV_WARNING == rc) )
+ {
+ // Loop through the query elements
+ PQUERYTUPLE pTuple = pQuerySize->aTuples;
+ while ( DJP_NONE != pTuple->ulProperty )
+ {
+ if ( pDJP->ulProperty == DJP_CJ_FORM )
+ {
+ if ( pDJP->ulNumReturned )
+ {
+ PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM );
+
+ pOs2SalInfoPrinter->mnFormCount = pDJP->ulNumReturned;
+ pOs2SalInfoPrinter->mpFormArray = new PIMPLFORMINFO[pOs2SalInfoPrinter->mnFormCount];
+ for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ )
+ {
+ ImplFormInfo* pInfo = new ImplFormInfo;
+ pInfo->mnPaperWidth = pElm->hcInfo.cx;
+ pInfo->mnPaperHeight = pElm->hcInfo.cy;
+ pInfo->mnId = pElm->djppsFormID;
+ pOs2SalInfoPrinter->mpFormArray[i] = pInfo;
+ }
+ }
+ }
+ else if ( pDJP->ulProperty == DJP_CJ_TRAYNAME )
+ {
+ if ( pDJP->ulNumReturned )
+ {
+ PDJPT_TRAYNAME pElm = DJP_ELEMENTP( *pDJP, DJPT_TRAYNAME );
+
+ pOs2SalInfoPrinter->mnTrayCount = pDJP->ulNumReturned;
+ pOs2SalInfoPrinter->mpTrayArray = new PIMPLTRAYINFO[pOs2SalInfoPrinter->mnTrayCount];
+ for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ )
+ {
+ ImplTrayInfo* pInfo = new ImplTrayInfo( pElm->szTrayname, pElm->szDisplayTrayname );
+ pInfo->mnId = pElm->djpttTrayID;
+ pOs2SalInfoPrinter->mpTrayArray[i] = pInfo;
+ }
+ }
+ }
+
+ pDJP = DJP_NEXT_STRUCTP( pDJP );
+ pTuple++;
+ }
+ }
+
+ delete [] pBuffer;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplGetCurrentSettings( Os2SalInfoPrinter* pOs2SalInfoPrinter, ImplJobSetup* pSetupData )
+{
+ // Um den aktuellen Tray zu ermitteln, brauchen wir auch die Listen dazu
+ if ( !pOs2SalInfoPrinter->mnFormCount )
+ ImplGetFormAndTrayList( pOs2SalInfoPrinter, pSetupData );
+
+ LONG alQuery[] =
+ {
+ 0, 0, // First two members of QUERYSIZE
+ DJP_SJ_ORIENTATION, DJP_CURRENT,
+ DJP_CJ_FORM, DJP_CURRENT,
+ DJP_NONE, DJP_NONE // EOL marker
+ };
+
+ APIRET rc;
+ PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery;
+ PBYTE pBuffer = NULL;
+ LONG nAlloc = 0;
+ PDRIVDATA pCopyDrivData = ImplPrnDrivData( pSetupData );
+ LONG nDrivDataSize = pCopyDrivData->cb;
+ PBYTE pDrivData = (PBYTE)pCopyDrivData;
+ BOOL bResult;
+
+ // find out how many bytes to allocate
+ pQuerySize->cb = sizeof( alQuery );
+ rc = DevEscape( pOs2SalInfoPrinter->mhDC,
+ DEVESC_QUERYSIZE,
+ sizeof( alQuery ),
+ (PBYTE)pQuerySize,
+ &nDrivDataSize,
+ pDrivData );
+ if ( DEV_OK != rc )
+ {
+ ImplFreePrnMemory( pCopyDrivData );
+ return FALSE;
+ }
+
+ // allocate the memory
+ nAlloc = pQuerySize->ulSizeNeeded;
+ pBuffer = (PBYTE)new BYTE[nAlloc];
+
+ // set up the input
+ PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
+ ImplFormatInputList( pDJP, pQuerySize->aTuples );
+
+ rc = DevEscape( pOs2SalInfoPrinter->mhDC,
+ DEVESC_QUERYJOBPROPERTIES,
+ nAlloc,
+ pBuffer,
+ &nDrivDataSize,
+ pDrivData );
+ if ( (DEV_OK == rc) || (DEV_WARNING == rc) )
+ {
+ // aktuelle Setup-Daten uebernehmen
+ ImplUpdateSetupData( pCopyDrivData, pSetupData );
+
+ // Loop through the query elements
+ PQUERYTUPLE pTuple = pQuerySize->aTuples;
+ while ( DJP_NONE != pTuple->ulProperty )
+ {
+ if ( pDJP->ulProperty == DJP_SJ_ORIENTATION )
+ {
+ if ( pDJP->ulNumReturned )
+ {
+ PDJPT_ORIENTATION pElm = DJP_ELEMENTP( *pDJP, DJPT_ORIENTATION );
+ if ( (DJP_ORI_PORTRAIT == *pElm) || (DJP_ORI_REV_PORTRAIT == *pElm) )
+ pSetupData->meOrientation = ORIENTATION_PORTRAIT;
+ else
+ pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
+ }
+ }
+ else if ( pDJP->ulProperty == DJP_CJ_FORM )
+ {
+ if ( pDJP->ulNumReturned )
+ {
+ PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM );
+
+ pSetupData->mnPaperWidth = pElm->hcInfo.cx*100;
+ pSetupData->mnPaperHeight = pElm->hcInfo.cy*100;
+ switch( pElm->djppsFormID )
+ {
+ case DJP_PSI_A3:
+ pSetupData->mePaperFormat = PAPER_A3;
+ break;
+
+ case DJP_PSI_A4:
+ pSetupData->mePaperFormat = PAPER_A4;
+ break;
+
+ case DJP_PSI_A5:
+ pSetupData->mePaperFormat = PAPER_A5;
+ break;
+
+ case DJP_PSI_B4:
+ pSetupData->mePaperFormat = PAPER_B4;
+ break;
+
+ case DJP_PSI_B5:
+ pSetupData->mePaperFormat = PAPER_B5;
+ break;
+
+ case DJP_PSI_LETTER:
+ pSetupData->mePaperFormat = PAPER_LETTER;
+ break;
+
+ case DJP_PSI_LEGAL:
+ pSetupData->mePaperFormat = PAPER_LEGAL;
+ break;
+
+ case DJP_PSI_TABLOID:
+ pSetupData->mePaperFormat = PAPER_TABLOID;
+ break;
+
+ default:
+ pSetupData->mePaperFormat = PAPER_USER;
+ break;
+ }
+
+ // Wir suchen zuerst ueber den Namen/Id und dann ueber die Id
+ BOOL bTrayFound = FALSE;
+ USHORT j;
+ for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ )
+ {
+ if ( (pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID) &&
+ (pOs2SalInfoPrinter->mpTrayArray[j]->maName == pElm->szTrayname) )
+ {
+ pSetupData->mnPaperBin = j;
+ bTrayFound = TRUE;
+ break;
+ }
+ }
+ if ( !bTrayFound )
+ {
+ for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ )
+ {
+ if ( pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID )
+ {
+ pSetupData->mnPaperBin = j;
+ bTrayFound = TRUE;
+ break;
+ }
+ }
+ }
+ // Wenn wir Ihn immer noch nicht gefunden haben, setzen
+ // wir ihn auf DontKnow
+ if ( !bTrayFound )
+ pSetupData->mnPaperBin = 0xFFFF;
+ }
+ }
+
+ pDJP = DJP_NEXT_STRUCTP( pDJP );
+ pTuple++;
+ }
+
+ bResult = TRUE;
+ }
+ else
+ {
+ ImplFreePrnMemory( pCopyDrivData );
+ bResult = FALSE;
+ }
+
+ delete [] pBuffer;
+
+ return bResult;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplSetOrientation( HDC hPrinterDC, PDRIVDATA pDriverData,
+ Orientation eOrientation )
+{
+ LONG alQuery[] =
+ {
+ 0, 0, // First two members of QUERYSIZE
+ DJP_SJ_ORIENTATION, DJP_CURRENT,
+ DJP_NONE, DJP_NONE // EOL marker
+ };
+
+ APIRET rc;
+ PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery;
+ PBYTE pBuffer = NULL;
+ LONG nAlloc = 0;
+ LONG nDrivDataSize = pDriverData->cb;
+
+ // find out how many bytes to allocate
+ pQuerySize->cb = sizeof( alQuery );
+ rc = DevEscape( hPrinterDC,
+ DEVESC_QUERYSIZE,
+ sizeof( alQuery ),
+ (PBYTE)pQuerySize,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ // allocate the memory
+ nAlloc = pQuerySize->ulSizeNeeded;
+ pBuffer = (PBYTE)new BYTE[nAlloc];
+
+ // set up the input
+ PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
+ ImplFormatInputList( pDJP, pQuerySize->aTuples );
+
+ pDJP->cb = sizeof( DJP_ITEM );
+ pDJP->ulProperty = DJP_SJ_ORIENTATION;
+ pDJP->lType = DJP_CURRENT;
+ pDJP->ulValue = (eOrientation == ORIENTATION_PORTRAIT)
+ ? DJP_ORI_PORTRAIT
+ : DJP_ORI_LANDSCAPE;
+
+ // do it!
+ rc = DevEscape( hPrinterDC,
+ DEVESC_SETJOBPROPERTIES,
+ nAlloc,
+ pBuffer,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+
+ delete [] pBuffer;
+
+ return ((DEV_OK == rc) || (DEV_WARNING == rc));
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplSetPaperSize( HDC hPrinterDC, PDRIVDATA pDriverData,
+ DJPT_PAPERSIZE nOS2PaperFormat )
+{
+ LONG alQuery[] =
+ {
+ 0, 0, // First two members of QUERYSIZE
+ DJP_SJ_PAPERSIZE, DJP_CURRENT,
+ DJP_NONE, DJP_NONE // EOL marker
+ };
+
+ APIRET rc;
+ PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery;
+ PBYTE pBuffer = NULL;
+ LONG nAlloc = 0;
+ LONG nDrivDataSize = pDriverData->cb;
+
+ // find out how many bytes to allocate
+ pQuerySize->cb = sizeof( alQuery );
+ rc = DevEscape( hPrinterDC,
+ DEVESC_QUERYSIZE,
+ sizeof( alQuery ),
+ (PBYTE)pQuerySize,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ // allocate the memory
+ nAlloc = pQuerySize->ulSizeNeeded;
+ pBuffer = (PBYTE)new BYTE[nAlloc];
+
+ // set up the input
+ PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
+ PDJP_ITEM pStartDJP = pDJP;
+ ImplFormatInputList( pDJP, pQuerySize->aTuples );
+
+ // Neue Daten zuweisen
+ pDJP->cb = sizeof( DJP_ITEM );
+ pDJP->ulProperty = DJP_SJ_PAPERSIZE;
+ pDJP->lType = DJP_CURRENT;
+ pDJP->ulValue = nOS2PaperFormat;
+
+ // und setzen
+ rc = DevEscape( hPrinterDC,
+ DEVESC_SETJOBPROPERTIES,
+ nAlloc,
+ pBuffer,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+
+ delete [] pBuffer;
+
+ return ((DEV_OK == rc) || (DEV_WARNING == rc));
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplSetPaperBin( HDC hPrinterDC, PDRIVDATA pDriverData,
+ ImplTrayInfo* pTrayInfo )
+{
+ LONG alQuery[] =
+ {
+ 0, 0, // First two members of QUERYSIZE
+ DJP_SJ_TRAYTYPE, DJP_CURRENT,
+ DJP_NONE, DJP_NONE // EOL marker
+ };
+
+ APIRET rc;
+ PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery;
+ PBYTE pBuffer = NULL;
+ LONG nAlloc = 0;
+ LONG nDrivDataSize = pDriverData->cb;
+
+ // find out how many bytes to allocate
+ pQuerySize->cb = sizeof( alQuery );
+ rc = DevEscape( hPrinterDC,
+ DEVESC_QUERYSIZE,
+ sizeof( alQuery ),
+ (PBYTE)pQuerySize,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ // allocate the memory
+ nAlloc = pQuerySize->ulSizeNeeded;
+ pBuffer = (PBYTE)new BYTE[nAlloc];
+
+ // set up the input
+ PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer;
+ ImplFormatInputList( pDJP, pQuerySize->aTuples );
+
+ // Neue Daten zuweisen
+ pDJP->cb = sizeof( DJP_ITEM );
+ pDJP->ulProperty = DJP_SJ_TRAYTYPE;
+ pDJP->lType = DJP_CURRENT;
+ pDJP->ulValue = pTrayInfo->mnId;
+
+ // und setzen
+ rc = DevEscape( hPrinterDC,
+ DEVESC_SETJOBPROPERTIES,
+ nAlloc,
+ pBuffer,
+ &nDrivDataSize,
+ (PBYTE)pDriverData );
+
+ delete [] pBuffer;
+
+ return ((DEV_OK == rc) || (DEV_WARNING == rc));
+}
+
+// =======================================================================
+
+static BOOL ImplSalCreateInfoPrn( Os2SalInfoPrinter* pPrinter, PDRIVDATA pDriverData,
+ HDC& rDC, HPS& rPS )
+{
+ SalData* pSalData = GetSalData();
+
+ // create info context
+ DEVOPENSTRUC devOpenStruc;
+ memset( &devOpenStruc, 0, sizeof( devOpenStruc ) );
+ devOpenStruc.pszLogAddress = (char*)pPrinter->maName.GetBuffer();
+ devOpenStruc.pszDriverName = (char*)pPrinter->maDriverName.GetBuffer();
+ devOpenStruc.pdriv = pDriverData;
+ devOpenStruc.pszDataType = "PM_Q_STD";
+
+ HDC hDC = DevOpenDC( pSalData->mhAB, OD_INFO, "*",
+ 4, (PDEVOPENDATA)&devOpenStruc, (HDC)NULL);
+ if ( !hDC )
+ return FALSE;
+
+ // create presentation space
+ SIZEL sizel;
+ sizel.cx = 0;
+ sizel.cy = 0;
+ HPS hPS = Ft2CreatePS( pSalData->mhAB, hDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS );
+ if ( !hPS )
+ {
+ DevCloseDC( hDC );
+ return FALSE;
+ }
+
+ rDC = hDC;
+ rPS = hPS;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalDestroyInfoPrn( Os2SalInfoPrinter* pPrinter )
+{
+ ImplSalDeInitGraphics( pPrinter->mpGraphics);
+ Ft2Associate( pPrinter->mhPS, 0 );
+ Ft2DestroyPS( pPrinter->mhPS );
+ DevCloseDC( pPrinter->mhDC );
+}
+
+// =======================================================================
+
+SalInfoPrinter* Os2SalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
+ ImplJobSetup* pSetupData )
+{
+ ImplQueueSalSysData* pSysQueueData = (ImplQueueSalSysData*)(pQueueInfo->mpSysData);
+ Os2SalInfoPrinter* pPrinter = new Os2SalInfoPrinter;
+ pPrinter->maPrinterName = pSysQueueData->maPrinterName;
+ pPrinter->maName = pSysQueueData->maName;
+ pPrinter->maDriverName = pSysQueueData->maDriverName;
+ pPrinter->maDeviceName = pSysQueueData->maDeviceName;
+
+ // Nur Setup-Daten uebernehmen, wenn Treiber und Laenge der Treiberdaten
+ // uebereinstimmt
+ PDRIVDATA pDriverData;
+ BOOL bUpdateDriverData;
+ if ( pSetupData->mpDriverData && pSysQueueData->mpDrivData &&
+ (pSetupData->mnSystem == JOBSETUP_SYSTEM_OS2) &&
+ (pSetupData->mnDriverDataLen == pSysQueueData->mpDrivData->cb) &&
+ (strcmp( ((PDRIVDATA)pSetupData->mpDriverData)->szDeviceName,
+ pSysQueueData->mpDrivData->szDeviceName ) == 0) )
+ {
+ pDriverData = PDRIVDATA( pSetupData->mpDriverData );
+ bUpdateDriverData = FALSE;
+ }
+ else
+ {
+ pDriverData = pSysQueueData->mpDrivData;
+ bUpdateDriverData = TRUE;
+ }
+ if ( pDriverData )
+ pPrinter->maJobSetupDeviceName = pDriverData->szDeviceName;
+
+ if ( !ImplSalCreateInfoPrn( pPrinter, pDriverData,
+ pPrinter->mhDC,
+ pPrinter->mhPS ) )
+ {
+ delete pPrinter;
+ return NULL;
+ }
+
+ // create graphics object for output
+ Os2SalGraphics* pGraphics = new Os2SalGraphics;
+ pGraphics->mhDC = pPrinter->mhDC;
+ pGraphics->mhPS = pPrinter->mhPS;
+ pGraphics->mhWnd = 0;
+ pGraphics->mbPrinter = TRUE;
+ pGraphics->mbVirDev = FALSE;
+ pGraphics->mbWindow = FALSE;
+ pGraphics->mbScreen = FALSE;
+
+ ImplSalInitGraphics( pGraphics );
+ pPrinter->mpGraphics = pGraphics;
+
+ // check printer driver for DJP support
+ pPrinter->mbDJPSupported = ImplIsDriverDJPEnabled( pPrinter->mhDC );
+
+ if ( bUpdateDriverData )
+ {
+ if ( pSetupData->mpDriverData )
+ rtl_freeMemory( pSetupData->mpDriverData);
+ pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDriverData->cb);
+ memcpy( pSetupData->mpDriverData, pDriverData, pDriverData->cb );
+ pSetupData->mnDriverDataLen = pDriverData->cb;
+ }
+
+ // retrieve current settings from printer driver and store them to system independend data!
+ if ( pPrinter->mbDJPSupported )
+ ImplGetCurrentSettings( pPrinter, pSetupData );
+ pSetupData->mnSystem = JOBSETUP_SYSTEM_OS2;
+
+ return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
+{
+ delete pPrinter;
+}
+
+// =======================================================================
+
+Os2SalInfoPrinter::Os2SalInfoPrinter()
+{
+ mhDC = 0;
+ mhPS = 0;
+ mpGraphics = NULL;
+ mbGraphics = FALSE;
+ mbDJPSupported = FALSE;
+ mnFormCount = 0;
+ mpFormArray = NULL;
+ mnTrayCount = 0;
+ mpTrayArray = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalInfoPrinter::~Os2SalInfoPrinter()
+{
+ if ( mpGraphics )
+ {
+ ImplSalDestroyInfoPrn( this );
+ delete mpGraphics;
+ }
+
+ ImplFreeFormAndTrayList( this );
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* Os2SalInfoPrinter::GetGraphics()
+{
+ if ( mbGraphics )
+ return NULL;
+
+ if ( mpGraphics )
+ mbGraphics = TRUE;
+
+ return mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInfoPrinter::ReleaseGraphics( SalGraphics* )
+{
+ mbGraphics = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData )
+{
+ PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData );
+ if ( !pDrivData )
+ return FALSE;
+
+ APIRET rc = DevPostDeviceModes( GetSalData()->mhAB, pDrivData,
+ maDriverName.GetBuffer(),
+ maDeviceName.GetBuffer(),
+ maPrinterName.GetBuffer(),
+ DPDM_POSTJOBPROP );
+ if ( rc == DEV_OK )
+ {
+ ImplUpdateSetupData( pDrivData, pSetupData );
+
+ // update DC and PS
+ HDC hDC;
+ HPS hPS;
+ if ( !ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) )
+ return FALSE;
+
+ // Alten Printer DC/PS zerstoeren
+ ImplSalDestroyInfoPrn( this );
+
+ // Neue Daten setzen und initialisieren
+ mhDC = hDC;
+ mhPS = hPS;
+ mpGraphics->mhDC = mhDC;
+ mpGraphics->mhPS = mhPS;
+ ImplSalInitGraphics( mpGraphics );
+
+ // retrieve current settings from printer driver and store them to system independend data!
+ ImplFreeFormAndTrayList( this );
+ if ( mbDJPSupported )
+ ImplGetCurrentSettings( this, pSetupData );
+
+ return TRUE;
+ }
+ else
+ {
+ ImplFreePrnMemory( pDrivData );
+ return FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
+{
+ // Wir koennen nur Treiberdaten von OS2 setzen
+ if ( pSetupData->mnSystem != JOBSETUP_SYSTEM_OS2 )
+ return FALSE;
+
+ PDRIVDATA pNewDrivData = (PDRIVDATA)(pSetupData->mpDriverData);
+ if ( !pNewDrivData )
+ return FALSE;
+
+ // Testen, ob Printerdaten fuer den gleichen Printer uebergeben werden,
+ // da einige Treiber zu Abstuerzen neigen, wenn Daten von einem anderen
+ // Printer gesetzt werden
+ if ( !maJobSetupDeviceName.Equals( pNewDrivData->szDeviceName ))
+ return FALSE;
+
+ // update DC and PS
+ HDC hDC;
+ HPS hPS;
+ if ( !ImplSalCreateInfoPrn( this, pNewDrivData, hDC, hPS ) )
+ return FALSE;
+
+ // Alten Printer DC/PS zerstoeren
+ ImplSalDestroyInfoPrn( this );
+
+ // Neue Daten setzen und initialisieren
+ mhDC = hDC;
+ mhPS = hPS;
+ mpGraphics->mhDC = mhDC;
+ mpGraphics->mhPS = mhPS;
+ ImplSalInitGraphics( mpGraphics );
+
+ // retrieve current settings from printer driver and store them to system independend data!
+ ImplFreeFormAndTrayList( this );
+ if ( mbDJPSupported )
+ ImplGetCurrentSettings( this, pSetupData );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalInfoPrinter::SetData( ULONG nFlags, ImplJobSetup* pSetupData )
+{
+ // needs DJP support
+ if ( !mbDJPSupported )
+ return FALSE;
+
+ PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData );
+
+ if ( !pDrivData )
+ return FALSE;
+
+ BOOL bOK = FALSE;
+
+ // set orientation
+ if ( nFlags & SAL_JOBSET_ORIENTATION )
+ {
+ if ( ImplSetOrientation( mhDC, pDrivData, pSetupData->meOrientation ) )
+ bOK = TRUE;
+ }
+
+ // set paper size
+ if ( nFlags & SAL_JOBSET_PAPERSIZE )
+ {
+ // Papierformat ermitteln
+ DJPT_PAPERSIZE nOS2PaperFormat;
+ switch ( pSetupData->mePaperFormat )
+ {
+ case PAPER_A3:
+ nOS2PaperFormat = DJP_PSI_A3;
+ break;
+
+ case PAPER_A4:
+ nOS2PaperFormat = DJP_PSI_A4;
+ break;
+
+ case PAPER_A5:
+ nOS2PaperFormat = DJP_PSI_A5;
+ break;
+
+ case PAPER_B4:
+ nOS2PaperFormat = DJP_PSI_B4;
+ break;
+
+ case PAPER_B5:
+ nOS2PaperFormat = DJP_PSI_B5;
+ break;
+
+ case PAPER_LETTER:
+ nOS2PaperFormat = DJP_PSI_LETTER;
+ break;
+
+ case PAPER_LEGAL:
+ nOS2PaperFormat = DJP_PSI_LEGAL;
+ break;
+
+ case PAPER_TABLOID:
+ nOS2PaperFormat = DJP_PSI_TABLOID;
+ break;
+
+ default:
+ {
+ nOS2PaperFormat = DJP_PSI_NONE;
+ // OS2 rechnet in Millimetern
+ long nPaperWidth = pSetupData->mnPaperWidth / 100;
+ long nPaperHeight = pSetupData->mnPaperHeight / 100;
+ // Ansonsten ueber die Papiergroesse suchen
+ for( int i = 0; i < mnFormCount; i++ )
+ {
+ ImplFormInfo* pFormInfo = mpFormArray[i];
+ if ( ImplPaperSizeEqual( nPaperWidth, nPaperHeight,
+ pFormInfo->mnPaperWidth, pFormInfo->mnPaperHeight ) )
+ {
+ nOS2PaperFormat = pFormInfo->mnId;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ if ( nOS2PaperFormat != DJP_PSI_NONE )
+ {
+ if ( ImplSetPaperSize( mhDC, pDrivData, nOS2PaperFormat ) )
+ bOK = TRUE;
+ }
+ }
+
+ // set paper tray
+ if ( (nFlags & SAL_JOBSET_PAPERBIN) && (pSetupData->mnPaperBin < mnTrayCount) )
+ {
+ if ( ImplSetPaperBin( mhDC, pDrivData,
+ mpTrayArray[pSetupData->mnPaperBin] ) )
+ bOK = TRUE;
+ }
+
+ if ( bOK )
+ {
+ ImplUpdateSetupData( pDrivData, pSetupData );
+
+ // query current driver settings
+ ImplFreeFormAndTrayList( this );
+ if ( ImplGetCurrentSettings( this, pSetupData ) )
+ {
+ // update DC and PS
+ HDC hDC;
+ HPS hPS;
+ if ( ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) )
+ {
+ // Alten Printer DC/PS zerstoeren
+ ImplSalDestroyInfoPrn( this );
+
+ // Neue Daten setzen und initialisieren
+ mhDC = hDC;
+ mhPS = hPS;
+ mpGraphics->mhDC = mhDC;
+ mpGraphics->mhPS = mhPS;
+ ImplSalInitGraphics( mpGraphics );
+ }
+ else
+ bOK = FALSE;
+ }
+ else
+ bOK = FALSE;
+ }
+
+ return bOK;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Os2SalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup )
+{
+ if ( !mbDJPSupported )
+ return 1;
+
+ // init paperbinlist if empty
+ if ( !mnTrayCount )
+ ImplGetFormAndTrayList( this, pJobSetup );
+
+ // Wir haben immer einen PaperTray und wenn, das eben einen ohne
+ // Namen
+ if ( !mnTrayCount )
+ return 1;
+ else
+ return mnTrayCount;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Os2SalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup,
+ ULONG nPaperBin )
+{
+ XubString aPaperBinName;
+
+ if ( mbDJPSupported )
+ {
+ // init paperbinlist if empty
+ if ( !mnTrayCount )
+ ImplGetFormAndTrayList( this, pJobSetup );
+
+ if ( nPaperBin < mnTrayCount )
+ aPaperBinName = ::rtl::OStringToOUString (mpTrayArray[nPaperBin]->maDisplayName, gsl_getSystemTextEncoding());
+ }
+
+ return aPaperBinName;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Os2SalInfoPrinter::GetCapabilities( const ImplJobSetup*, USHORT nType )
+{
+ switch ( nType )
+ {
+ case PRINTER_CAPABILITIES_SUPPORTDIALOG:
+ return TRUE;
+ case PRINTER_CAPABILITIES_COPIES:
+ return 0xFFFF;
+ case PRINTER_CAPABILITIES_COLLATECOPIES:
+ return 0;
+ case PRINTER_CAPABILITIES_SETORIENTATION:
+ case PRINTER_CAPABILITIES_SETPAPERBIN:
+ case PRINTER_CAPABILITIES_SETPAPERSIZE:
+ case PRINTER_CAPABILITIES_SETPAPER:
+ return mbDJPSupported;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInfoPrinter::GetPageInfo( const ImplJobSetup*,
+ long& rOutWidth, long& rOutHeight,
+ long& rPageOffX, long& rPageOffY,
+ long& rPageWidth, long& rPageHeight )
+{
+ HDC hDC = mhDC;
+
+ // search current form
+ HCINFO aInfo;
+ int nForms = DevQueryHardcopyCaps( hDC, 0, 0, &aInfo );
+ for( int i = 0; i < nForms; i++ )
+ {
+ if ( DevQueryHardcopyCaps( hDC, i, 1, &aInfo ) >= 0 )
+ {
+ if ( aInfo.flAttributes & HCAPS_CURRENT )
+ {
+ // query resolution
+ long nXResolution;
+ long nYResolution;
+ DevQueryCaps( hDC, CAPS_HORIZONTAL_RESOLUTION, 1, &nXResolution );
+ DevQueryCaps( hDC, CAPS_VERTICAL_RESOLUTION, 1, &nYResolution );
+ rPageOffX = aInfo.xLeftClip * nXResolution / 1000;
+ rPageOffY = (aInfo.cy-aInfo.yTopClip) * nYResolution / 1000;
+ rPageWidth = aInfo.cx * nXResolution / 1000;
+ rPageHeight = aInfo.cy * nYResolution / 1000;
+ rOutWidth = aInfo.xPels;
+ rOutHeight = aInfo.yPels;
+ return;
+ }
+ }
+ }
+
+ // use device caps if no form selected/found
+ long lCapsWidth = 0;
+ long lCapsHeight = 0;
+ DevQueryCaps( hDC, CAPS_WIDTH, 1L, &lCapsWidth );
+ DevQueryCaps( hDC, CAPS_HEIGHT, 1L, &lCapsHeight );
+ rPageOffX = 0;
+ rPageOffY = 0;
+ rOutWidth = lCapsWidth;
+ rOutHeight = lCapsHeight;
+ rPageWidth = rOutWidth;
+ rPageHeight = rOutHeight;
+}
+
+// =======================================================================
+
+static BOOL ImplIsDriverPrintDJPEnabled( HDC hDC )
+{
+#ifdef NO_DJP
+ return FALSE;
+#else
+ // Ueber OS2-Ini kann DJP disablte werden
+ if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTDJP, 1 ) )
+ return FALSE;
+
+ // Testen, ob DJP-Interface am Drucker vorhanden
+ LONG lQuery;
+ APIRET rc;
+
+ lQuery = DEVESC_QUERYSIZE;
+ rc = DevEscape( hDC,
+ DEVESC_QUERYESCSUPPORT,
+ sizeof( lQuery ),
+ (PBYTE)&lQuery,
+ 0,
+ (PBYTE)NULL );
+ if ( DEV_OK != rc )
+ return FALSE;
+
+ return TRUE;
+#endif
+}
+
+// =======================================================================
+
+SalPrinter* Os2SalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
+{
+ Os2SalPrinter* pPrinter = new Os2SalPrinter;
+ pPrinter->mpInfoPrinter = static_cast<Os2SalInfoPrinter*>(pInfoPrinter);
+ return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DestroyPrinter( SalPrinter* pPrinter )
+{
+ delete pPrinter;
+}
+
+// =======================================================================
+
+Os2SalPrinter::Os2SalPrinter()
+{
+ mhDC = 0;
+ mhPS = 0;
+ mpGraphics = NULL;
+ mbAbort = FALSE;
+ mbPrintDJPSupported = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalPrinter::~Os2SalPrinter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalPrinter::StartJob( const XubString* pFileName,
+ const XubString& rJobName,
+ const XubString& rAppName,
+ ULONG nCopies,
+ bool bCollate,
+ bool bDirect,
+ ImplJobSetup* pSetupData )
+{
+ DEVOPENSTRUC aDevOpenStruc;
+ LONG lType;
+ APIRET rc;
+
+ // prepare queue information
+ memset( &aDevOpenStruc, 0, sizeof( aDevOpenStruc ) );
+ aDevOpenStruc.pszDriverName = (PSZ)(mpInfoPrinter->maDriverName.GetBuffer());
+
+ // print into file?
+ if ( pFileName )
+ {
+ aDevOpenStruc.pszLogAddress = (PSZ)pFileName->GetBuffer();
+ aDevOpenStruc.pszDataType = "PM_Q_RAW";
+ lType = OD_DIRECT;
+ }
+ else
+ {
+ aDevOpenStruc.pszLogAddress = (PSZ)(mpInfoPrinter->maName.GetBuffer());
+ if ( PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTRAW, 0 ) )
+ aDevOpenStruc.pszDataType = "PM_Q_RAW";
+ else
+ aDevOpenStruc.pszDataType = "PM_Q_STD";
+ lType = OD_QUEUED;
+ }
+
+#if 0 // YD FIXME
+ // Set comment (AppName nur bis zum 1. Space-Zeichen nehmen)
+ const xub_Unicode* pComment = rAppName;
+ USHORT nCommentLen = 0;
+ memset( maCommentBuf, 0, sizeof( maCommentBuf ) );
+ while ( (nCommentLen < 32) &&
+ (((*pComment >= 'a') && (*pComment <= 'z')) ||
+ ((*pComment >= 'A') && (*pComment <= 'Z')) ||
+ ((*pComment >= '0') && (*pComment <= '9')) ||
+ (*pComment == '-')))
+ {
+ maCommentBuf[nCommentLen] = (char)(*pComment);
+ nCommentLen++;
+ pComment++;
+ }
+ aDevOpenStruc.pszComment = (PSZ)maCommentBuf;
+#endif
+ ByteString jobName( rJobName, gsl_getSystemTextEncoding());
+ aDevOpenStruc.pszComment = (PSZ)jobName.GetBuffer();
+
+ // Kopien
+ if ( nCopies > 1 )
+ {
+ // OS2 kann maximal 999 Kopien
+ if ( nCopies > 999 )
+ nCopies = 999;
+ sprintf( maCopyBuf, "COP=%d", nCopies);
+ aDevOpenStruc.pszQueueProcParams = (PSZ)maCopyBuf;
+ }
+
+ // open device context
+ SalData* pSalData = GetSalData();
+ HAB hAB = pSalData->mhAB;
+ aDevOpenStruc.pdriv = (PDRIVDATA)pSetupData->mpDriverData;
+ mhDC = DevOpenDC( hAB,
+ lType,
+ "*",
+ 7,
+ (PDEVOPENDATA)&aDevOpenStruc,
+ 0 );
+ if ( mhDC == 0 )
+ {
+ ERRORID nLastError = WinGetLastError( hAB );
+ if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT )
+ mnError = SAL_PRINTER_ERROR_ABORT;
+ else
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return FALSE;
+ }
+
+ // open presentation space
+ SIZEL sizel;
+ sizel.cx = 0;
+ sizel.cy = 0;
+ mhPS = Ft2CreatePS( hAB, mhDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS );
+ if ( !mhPS )
+ {
+ DevCloseDC( mhDC );
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return NULL;
+ }
+
+ // Can we print with DJP
+ mbPrintDJPSupported = ImplIsDriverPrintDJPEnabled( mhDC );
+
+ // JobName ermitteln und Job starten
+ PSZ pszJobName = NULL;
+ int nJobNameLen = 0;
+ if ( jobName.Len() > 0 )
+ {
+ pszJobName = (PSZ)jobName.GetBuffer();
+ nJobNameLen = jobName.Len();
+ }
+ rc = DevEscape( mhDC,
+ DEVESC_STARTDOC,
+ nJobNameLen, (PBYTE)pszJobName,
+ 0, (PBYTE)NULL );
+
+ if ( rc != DEV_OK )
+ {
+ ERRORID nLastError = WinGetLastError( hAB );
+ if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT )
+ mnError = SAL_PRINTER_ERROR_ABORT;
+ else
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ Ft2Associate( mhPS, NULL );
+ Ft2DestroyPS( mhPS );
+ DevCloseDC( mhDC );
+ return FALSE;
+ }
+
+ // init for first page
+ mbFirstPage = TRUE;
+ mnError = 0;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalPrinter::EndJob()
+{
+ APIRET rc;
+ rc = DevEscape( mhDC,
+ DEVESC_ENDDOC,
+ 0, NULL,
+ 0, NULL);
+
+ // destroy presentation space and device context
+ Ft2Associate( mhPS, NULL );
+ Ft2DestroyPS( mhPS );
+ DevCloseDC( mhDC );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalPrinter::AbortJob()
+{
+ APIRET rc;
+
+ rc = DevEscape( mhDC,
+ DEVESC_ABORTDOC,
+ 0, NULL,
+ 0, NULL );
+
+ // destroy SalGraphics
+ if ( mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ delete mpGraphics;
+ mpGraphics = NULL;
+ }
+
+ // destroy presentation space and device context
+ Ft2Associate( mhPS, NULL );
+ Ft2DestroyPS( mhPS );
+ DevCloseDC( mhDC );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* Os2SalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobSetup )
+{
+ APIRET rc;
+
+ if ( mbFirstPage )
+ mbFirstPage = FALSE;
+ else
+ {
+ PBYTE pJobData;
+ LONG nJobDataSize;
+ LONG nEscape;
+ if ( mbPrintDJPSupported && bNewJobSetup )
+ {
+ nEscape = DEVESC_NEWFRAME_WPROP;
+ nJobDataSize = ((PDRIVDATA)(pSetupData->mpDriverData))->cb;
+ pJobData = (PBYTE)(pSetupData->mpDriverData);
+ }
+ else
+ {
+ nEscape = DEVESC_NEWFRAME;
+ nJobDataSize = 0;
+ pJobData = NULL;
+ }
+ rc = DevEscape( mhDC,
+ nEscape,
+ 0, NULL,
+ &nJobDataSize, pJobData );
+
+ if ( rc != DEV_OK )
+ {
+ DevEscape( mhDC, DEVESC_ENDDOC, 0, NULL, 0, NULL);
+ Ft2Associate( mhPS, NULL );
+ Ft2DestroyPS( mhPS );
+ DevCloseDC( mhDC );
+ mnError = SAL_PRINTER_ERROR_GENERALERROR;
+ return NULL;
+ }
+ }
+
+ // create SalGraphics with copy of hPS
+ Os2SalGraphics* pGraphics = new Os2SalGraphics;
+ pGraphics->mhDC = mhDC;
+ pGraphics->mhPS = mhPS;
+ pGraphics->mhWnd = 0;
+ pGraphics->mbPrinter = TRUE;
+ pGraphics->mbVirDev = FALSE;
+ pGraphics->mbWindow = FALSE;
+ pGraphics->mbScreen = FALSE;
+ pGraphics->mnHeight = 0;
+ // search current form for actual page height
+ HCINFO aInfo;
+ int nForms = DevQueryHardcopyCaps( mhDC, 0, 0, &aInfo );
+ for( int i = 0; i < nForms; i++ )
+ {
+ if ( DevQueryHardcopyCaps( mhDC, i, 1, &aInfo ) >= 0 )
+ {
+ if ( aInfo.flAttributes & HCAPS_CURRENT )
+ pGraphics->mnHeight = aInfo.yPels;
+ }
+ }
+ // use device caps if no form selected/found
+ if ( !pGraphics->mnHeight )
+ DevQueryCaps( mhDC, CAPS_HEIGHT, 1L, &pGraphics->mnHeight );
+
+ ImplSalInitGraphics( pGraphics );
+ mpGraphics = pGraphics;
+
+ return pGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalPrinter::EndPage()
+{
+ if ( mpGraphics )
+ {
+ // destroy SalGraphics
+ ImplSalDeInitGraphics( mpGraphics );
+ delete mpGraphics;
+ mpGraphics = NULL;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Os2SalPrinter::GetErrorCode()
+{
+ return mnError;
+}
+
+void Os2SalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
+{
+ printf("Os2SalInfoPrinter::InitPaperFormats\n");
+}
+int Os2SalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
+{
+ printf("Os2SalInfoPrinter::GetLandscapeAngle\n");
+ return 0;
+}
+
diff --git a/vcl/os2/source/gdi/salvd.cxx b/vcl/os2/source/gdi/salvd.cxx
new file mode 100644
index 000000000000..4e53782be8ea
--- /dev/null
+++ b/vcl/os2/source/gdi/salvd.cxx
@@ -0,0 +1,200 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#include <svpm.h>
+
+#define _SV_SALVD_CXX
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salgdi.h>
+#include <salvd.h>
+
+#ifndef __H_FT2LIB
+#include <wingdi.h>
+#include <ft2lib.h>
+#endif
+
+// =======================================================================
+
+HBITMAP ImplCreateVirDevBitmap( HDC hDC, HPS hPS, long nDX, long nDY,
+ USHORT nBitCount )
+{
+ if( !nBitCount )
+ {
+ LONG nDevBitCount;
+ DevQueryCaps( hDC, CAPS_COLOR_BITCOUNT, 1, &nDevBitCount );
+ nBitCount = nDevBitCount;
+ }
+
+ LONG nPlanes;
+ DevQueryCaps( hDC, CAPS_COLOR_PLANES, 1, &nPlanes );
+
+ // entsprechende Bitmap zum OutputDevice erzeugen
+ HBITMAP hBitmap;
+ BITMAPINFOHEADER2 aBitmapInfo;
+ memset( &aBitmapInfo, 0, sizeof( BITMAPINFOHEADER2 ) );
+ aBitmapInfo.cbFix = sizeof( BITMAPINFOHEADER2 );
+ aBitmapInfo.cx = nDX;
+ aBitmapInfo.cy = nDY;
+ aBitmapInfo.cPlanes = nPlanes;
+ aBitmapInfo.cBitCount = (nBitCount < 4) ? 4 : nBitCount;
+ hBitmap = GpiCreateBitmap( hPS, &aBitmapInfo, 0, NULL, NULL );
+ return hBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+SalVirtualDevice* Os2SalInstance::CreateVirtualDevice( SalGraphics* pSGraphics,
+ long nDX, long nDY,
+ USHORT nBitCount,
+ const SystemGraphicsData* pData )
+{
+ Os2SalGraphics* pGraphics = static_cast<Os2SalGraphics*>(pSGraphics);
+ HAB hAB = GetSalData()->mhAB;
+ SIZEL size;
+
+ // create device context (at this time allways display compatible)
+ DEVOPENSTRUC aDevOpenStruc = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+ HDC hDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5, (PDEVOPENDATA)&aDevOpenStruc, 0 );
+ if ( !hDC )
+ return NULL;
+
+ // create presentation space
+ size.cx = nDX;
+ size.cy = nDY;
+ HPS hPS = Ft2CreatePS( hAB, hDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
+ if ( !hPS )
+ {
+ DevCloseDC( hDC );
+ return NULL;
+ }
+
+ // create bitmap for the virtual device
+ HBITMAP hBmp = ImplCreateVirDevBitmap( hDC, hPS, nDX, nDY, nBitCount );
+ if ( !hBmp )
+ {
+ Ft2DestroyPS( hPS );
+ DevCloseDC( hDC );
+ return NULL;
+ }
+
+ // init data
+ Os2SalVirtualDevice* pVDev = new Os2SalVirtualDevice;
+ Os2SalGraphics* pVirGraphics = new Os2SalGraphics;
+
+ pVirGraphics->mhDC = hDC;
+ pVirGraphics->mhPS = hPS;
+ pVirGraphics->mhWnd = 0;
+ pVirGraphics->mnHeight = nDY;
+ pVirGraphics->mbPrinter = FALSE;
+ pVirGraphics->mbVirDev = TRUE;
+ pVirGraphics->mbWindow = FALSE;
+ pVirGraphics->mbScreen = pGraphics->mbScreen;
+ ImplSalInitGraphics( pVirGraphics );
+
+ pVDev->mhDC = hDC;
+ pVDev->mhPS = hPS;
+ pVDev->mhBmp = hBmp;
+ pVDev->mhDefBmp = Ft2SetBitmap( hPS, hBmp );
+ pVDev->mpGraphics = pVirGraphics;
+ pVDev->mnBitCount = nBitCount;
+ pVDev->mbGraphics = FALSE;
+ return pVDev;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
+{
+ delete pDevice;
+}
+
+// =======================================================================
+
+Os2SalVirtualDevice::Os2SalVirtualDevice()
+{
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalVirtualDevice::~Os2SalVirtualDevice()
+{
+ ImplSalDeInitGraphics( mpGraphics );
+
+ Ft2SetBitmap( mpGraphics->mhPS, mhDefBmp );
+ GpiDeleteBitmap( mhBmp );
+ Ft2DestroyPS( mpGraphics->mhPS );
+ DevCloseDC( mpGraphics->mhDC );
+ delete mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* Os2SalVirtualDevice::GetGraphics()
+{
+ if ( mbGraphics )
+ return NULL;
+
+ if ( mpGraphics )
+ mbGraphics = TRUE;
+
+ return mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalVirtualDevice::ReleaseGraphics( SalGraphics* )
+{
+ mbGraphics = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalVirtualDevice::SetSize( long nDX, long nDY )
+{
+ HBITMAP hNewBmp = ImplCreateVirDevBitmap( mhDC,
+ mhPS, nDX, nDY,
+ mnBitCount );
+ if ( hNewBmp )
+ {
+ Ft2SetBitmap( mhPS, hNewBmp );
+ GpiDeleteBitmap( mhBmp );
+ mhBmp = hNewBmp;
+ mpGraphics->mnHeight = nDY;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void Os2SalVirtualDevice::GetSize( long& rWidth, long& rHeight )
+{
+ DevQueryCaps( mpGraphics->mhDC, CAPS_WIDTH, CAPS_WIDTH, (LONG*)rWidth );
+ DevQueryCaps( mpGraphics->mhDC, CAPS_HEIGHT, CAPS_HEIGHT, (LONG*)rHeight );
+}
diff --git a/vcl/os2/source/src/airbrush.ptr b/vcl/os2/source/src/airbrush.ptr
new file mode 100644
index 000000000000..89a99d763d94
--- /dev/null
+++ b/vcl/os2/source/src/airbrush.ptr
Binary files differ
diff --git a/vcl/os2/source/src/ase.ptr b/vcl/os2/source/src/ase.ptr
new file mode 100755
index 000000000000..1f6c4e764901
--- /dev/null
+++ b/vcl/os2/source/src/ase.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asn.ptr b/vcl/os2/source/src/asn.ptr
new file mode 100755
index 000000000000..b526c17a83e0
--- /dev/null
+++ b/vcl/os2/source/src/asn.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asne.ptr b/vcl/os2/source/src/asne.ptr
new file mode 100755
index 000000000000..4ed44679918f
--- /dev/null
+++ b/vcl/os2/source/src/asne.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asns.ptr b/vcl/os2/source/src/asns.ptr
new file mode 100755
index 000000000000..12395e641b4f
--- /dev/null
+++ b/vcl/os2/source/src/asns.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asnswe.ptr b/vcl/os2/source/src/asnswe.ptr
new file mode 100755
index 000000000000..46f1f790b474
--- /dev/null
+++ b/vcl/os2/source/src/asnswe.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asnw.ptr b/vcl/os2/source/src/asnw.ptr
new file mode 100755
index 000000000000..d934c3b69a79
--- /dev/null
+++ b/vcl/os2/source/src/asnw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/ass.ptr b/vcl/os2/source/src/ass.ptr
new file mode 100755
index 000000000000..059ce40126cd
--- /dev/null
+++ b/vcl/os2/source/src/ass.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asse.ptr b/vcl/os2/source/src/asse.ptr
new file mode 100755
index 000000000000..78a1f7ff5c64
--- /dev/null
+++ b/vcl/os2/source/src/asse.ptr
Binary files differ
diff --git a/vcl/os2/source/src/assw.ptr b/vcl/os2/source/src/assw.ptr
new file mode 100755
index 000000000000..5adf85360e30
--- /dev/null
+++ b/vcl/os2/source/src/assw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/asw.ptr b/vcl/os2/source/src/asw.ptr
new file mode 100755
index 000000000000..160a775abe22
--- /dev/null
+++ b/vcl/os2/source/src/asw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/aswe.ptr b/vcl/os2/source/src/aswe.ptr
new file mode 100755
index 000000000000..b4e6580c560d
--- /dev/null
+++ b/vcl/os2/source/src/aswe.ptr
Binary files differ
diff --git a/vcl/os2/source/src/chain.ptr b/vcl/os2/source/src/chain.ptr
new file mode 100644
index 000000000000..0e248b324daa
--- /dev/null
+++ b/vcl/os2/source/src/chain.ptr
Binary files differ
diff --git a/vcl/os2/source/src/chainnot.ptr b/vcl/os2/source/src/chainnot.ptr
new file mode 100644
index 000000000000..0e248b324daa
--- /dev/null
+++ b/vcl/os2/source/src/chainnot.ptr
Binary files differ
diff --git a/vcl/os2/source/src/chart.ptr b/vcl/os2/source/src/chart.ptr
new file mode 100644
index 000000000000..66c685d111c7
--- /dev/null
+++ b/vcl/os2/source/src/chart.ptr
Binary files differ
diff --git a/vcl/os2/source/src/copydata.ptr b/vcl/os2/source/src/copydata.ptr
new file mode 100644
index 000000000000..e7e7ccd17e41
--- /dev/null
+++ b/vcl/os2/source/src/copydata.ptr
Binary files differ
diff --git a/vcl/os2/source/src/copydlnk.ptr b/vcl/os2/source/src/copydlnk.ptr
new file mode 100644
index 000000000000..acbf27b3462e
--- /dev/null
+++ b/vcl/os2/source/src/copydlnk.ptr
Binary files differ
diff --git a/vcl/os2/source/src/copyf.ptr b/vcl/os2/source/src/copyf.ptr
new file mode 100644
index 000000000000..8ebcbded233b
--- /dev/null
+++ b/vcl/os2/source/src/copyf.ptr
Binary files differ
diff --git a/vcl/os2/source/src/copyf2.ptr b/vcl/os2/source/src/copyf2.ptr
new file mode 100644
index 000000000000..dcfa6c089c10
--- /dev/null
+++ b/vcl/os2/source/src/copyf2.ptr
Binary files differ
diff --git a/vcl/os2/source/src/copyflnk.ptr b/vcl/os2/source/src/copyflnk.ptr
new file mode 100644
index 000000000000..3bd6e9d4706e
--- /dev/null
+++ b/vcl/os2/source/src/copyflnk.ptr
Binary files differ
diff --git a/vcl/os2/source/src/crook.ptr b/vcl/os2/source/src/crook.ptr
new file mode 100644
index 000000000000..0b639614ddb3
--- /dev/null
+++ b/vcl/os2/source/src/crook.ptr
Binary files differ
diff --git a/vcl/os2/source/src/crop.ptr b/vcl/os2/source/src/crop.ptr
new file mode 100644
index 000000000000..076e522e1b7f
--- /dev/null
+++ b/vcl/os2/source/src/crop.ptr
Binary files differ
diff --git a/vcl/os2/source/src/cross.ptr b/vcl/os2/source/src/cross.ptr
new file mode 100644
index 000000000000..1a2cd8dae5f6
--- /dev/null
+++ b/vcl/os2/source/src/cross.ptr
Binary files differ
diff --git a/vcl/os2/source/src/darc.ptr b/vcl/os2/source/src/darc.ptr
new file mode 100644
index 000000000000..eba024e6a09a
--- /dev/null
+++ b/vcl/os2/source/src/darc.ptr
Binary files differ
diff --git a/vcl/os2/source/src/data.ptr b/vcl/os2/source/src/data.ptr
new file mode 100644
index 000000000000..4c3c9eeb5e7a
--- /dev/null
+++ b/vcl/os2/source/src/data.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dbezier.ptr b/vcl/os2/source/src/dbezier.ptr
new file mode 100644
index 000000000000..8972b0007c13
--- /dev/null
+++ b/vcl/os2/source/src/dbezier.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dcapt.ptr b/vcl/os2/source/src/dcapt.ptr
new file mode 100644
index 000000000000..b04b21bad1a7
--- /dev/null
+++ b/vcl/os2/source/src/dcapt.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dcirccut.ptr b/vcl/os2/source/src/dcirccut.ptr
new file mode 100644
index 000000000000..936b337ebcc7
--- /dev/null
+++ b/vcl/os2/source/src/dcirccut.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dconnect.ptr b/vcl/os2/source/src/dconnect.ptr
new file mode 100644
index 000000000000..f8bc2cf454aa
--- /dev/null
+++ b/vcl/os2/source/src/dconnect.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dellipse.ptr b/vcl/os2/source/src/dellipse.ptr
new file mode 100644
index 000000000000..388bc2f2b00c
--- /dev/null
+++ b/vcl/os2/source/src/dellipse.ptr
Binary files differ
diff --git a/vcl/os2/source/src/detectiv.ptr b/vcl/os2/source/src/detectiv.ptr
new file mode 100644
index 000000000000..44ca1546a93b
--- /dev/null
+++ b/vcl/os2/source/src/detectiv.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dfree.ptr b/vcl/os2/source/src/dfree.ptr
new file mode 100644
index 000000000000..52d95d814d98
--- /dev/null
+++ b/vcl/os2/source/src/dfree.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dline.ptr b/vcl/os2/source/src/dline.ptr
new file mode 100644
index 000000000000..e7b80ae56735
--- /dev/null
+++ b/vcl/os2/source/src/dline.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dpie.ptr b/vcl/os2/source/src/dpie.ptr
new file mode 100644
index 000000000000..abd68b899f3a
--- /dev/null
+++ b/vcl/os2/source/src/dpie.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dpolygon.ptr b/vcl/os2/source/src/dpolygon.ptr
new file mode 100644
index 000000000000..94fa158b4186
--- /dev/null
+++ b/vcl/os2/source/src/dpolygon.ptr
Binary files differ
diff --git a/vcl/os2/source/src/drect.ptr b/vcl/os2/source/src/drect.ptr
new file mode 100644
index 000000000000..3ec044f267d6
--- /dev/null
+++ b/vcl/os2/source/src/drect.ptr
Binary files differ
diff --git a/vcl/os2/source/src/dtext.ptr b/vcl/os2/source/src/dtext.ptr
new file mode 100644
index 000000000000..8c221303b0b6
--- /dev/null
+++ b/vcl/os2/source/src/dtext.ptr
Binary files differ
diff --git a/vcl/os2/source/src/fill.ptr b/vcl/os2/source/src/fill.ptr
new file mode 100644
index 000000000000..e7247a6d107b
--- /dev/null
+++ b/vcl/os2/source/src/fill.ptr
Binary files differ
diff --git a/vcl/os2/source/src/hand.ptr b/vcl/os2/source/src/hand.ptr
new file mode 100644
index 000000000000..b1d65c7f19d0
--- /dev/null
+++ b/vcl/os2/source/src/hand.ptr
Binary files differ
diff --git a/vcl/os2/source/src/help.ptr b/vcl/os2/source/src/help.ptr
new file mode 100644
index 000000000000..3df4d88bddc4
--- /dev/null
+++ b/vcl/os2/source/src/help.ptr
Binary files differ
diff --git a/vcl/os2/source/src/hshear.ptr b/vcl/os2/source/src/hshear.ptr
new file mode 100644
index 000000000000..76bbebba5865
--- /dev/null
+++ b/vcl/os2/source/src/hshear.ptr
Binary files differ
diff --git a/vcl/os2/source/src/hsizebar.ptr b/vcl/os2/source/src/hsizebar.ptr
new file mode 100644
index 000000000000..9b78ff9ee9a9
--- /dev/null
+++ b/vcl/os2/source/src/hsizebar.ptr
Binary files differ
diff --git a/vcl/os2/source/src/hsplit.ptr b/vcl/os2/source/src/hsplit.ptr
new file mode 100644
index 000000000000..62f3b590a414
--- /dev/null
+++ b/vcl/os2/source/src/hsplit.ptr
Binary files differ
diff --git a/vcl/os2/source/src/linkdata.ptr b/vcl/os2/source/src/linkdata.ptr
new file mode 100644
index 000000000000..e5e6ace59be3
--- /dev/null
+++ b/vcl/os2/source/src/linkdata.ptr
Binary files differ
diff --git a/vcl/os2/source/src/linkf.ptr b/vcl/os2/source/src/linkf.ptr
new file mode 100644
index 000000000000..62bf7e739e32
--- /dev/null
+++ b/vcl/os2/source/src/linkf.ptr
Binary files differ
diff --git a/vcl/os2/source/src/magnify.ptr b/vcl/os2/source/src/magnify.ptr
new file mode 100644
index 000000000000..1d9a0c149ebd
--- /dev/null
+++ b/vcl/os2/source/src/magnify.ptr
Binary files differ
diff --git a/vcl/os2/source/src/makefile.mk b/vcl/os2/source/src/makefile.mk
new file mode 100644
index 000000000000..1dba7496be65
--- /dev/null
+++ b/vcl/os2/source/src/makefile.mk
@@ -0,0 +1,111 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=vcl
+TARGET=salsrc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# --- Files --------------------------------------------------------
+
+RCDEPN= nullptr.ptr \
+ help.ptr \
+ cross.ptr \
+ move.ptr \
+ hsplit.ptr \
+ vsplit.ptr \
+ hsizebar.ptr \
+ vsizebar.ptr \
+ hand.ptr \
+ refhand.ptr \
+ pen.ptr \
+ magnify.ptr \
+ fill.ptr \
+ rotate.ptr \
+ hshear.ptr \
+ vshear.ptr \
+ mirror.ptr \
+ crook.ptr \
+ crop.ptr \
+ movept.ptr \
+ movebw.ptr \
+ movedata.ptr \
+ copydata.ptr \
+ linkdata.ptr \
+ movedlnk.ptr \
+ copydlnk.ptr \
+ movef.ptr \
+ copyf.ptr \
+ linkf.ptr \
+ moveflnk.ptr \
+ copyflnk.ptr \
+ movef2.ptr \
+ copyf2.ptr \
+ dline.ptr \
+ drect.ptr \
+ dpolygon.ptr \
+ dbezier.ptr \
+ darc.ptr \
+ dpie.ptr \
+ dcirccut.ptr \
+ dellipse.ptr \
+ dfree.ptr \
+ dconnect.ptr \
+ dtext.ptr \
+ dcapt.ptr \
+ chart.ptr \
+ detectiv.ptr \
+ pivotcol.ptr \
+ pivotrow.ptr \
+ pivotfld.ptr \
+ chain.ptr \
+ chainnot.ptr \
+ timemove.ptr \
+ timesize.ptr \
+ asn.ptr \
+ ass.ptr \
+ asw.ptr \
+ ase.ptr \
+ asnw.ptr \
+ asne.ptr \
+ assw.ptr \
+ asse.ptr \
+ asns.ptr \
+ aswe.ptr \
+ asnswe.ptr \
+ sd.ico
+
+RCFILES= salsrc.rc
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/os2/source/src/mirror.ptr b/vcl/os2/source/src/mirror.ptr
new file mode 100644
index 000000000000..9135331048c9
--- /dev/null
+++ b/vcl/os2/source/src/mirror.ptr
Binary files differ
diff --git a/vcl/os2/source/src/move.ptr b/vcl/os2/source/src/move.ptr
new file mode 100644
index 000000000000..6b5a11d31219
--- /dev/null
+++ b/vcl/os2/source/src/move.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movebw.ptr b/vcl/os2/source/src/movebw.ptr
new file mode 100644
index 000000000000..e766b885db0a
--- /dev/null
+++ b/vcl/os2/source/src/movebw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movedata.ptr b/vcl/os2/source/src/movedata.ptr
new file mode 100644
index 000000000000..689f38da772f
--- /dev/null
+++ b/vcl/os2/source/src/movedata.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movedlnk.ptr b/vcl/os2/source/src/movedlnk.ptr
new file mode 100644
index 000000000000..d533e7135ad0
--- /dev/null
+++ b/vcl/os2/source/src/movedlnk.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movef.ptr b/vcl/os2/source/src/movef.ptr
new file mode 100644
index 000000000000..e9fabda359c8
--- /dev/null
+++ b/vcl/os2/source/src/movef.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movef2.ptr b/vcl/os2/source/src/movef2.ptr
new file mode 100644
index 000000000000..9940890840cb
--- /dev/null
+++ b/vcl/os2/source/src/movef2.ptr
Binary files differ
diff --git a/vcl/os2/source/src/moveflnk.ptr b/vcl/os2/source/src/moveflnk.ptr
new file mode 100644
index 000000000000..d651491ad001
--- /dev/null
+++ b/vcl/os2/source/src/moveflnk.ptr
Binary files differ
diff --git a/vcl/os2/source/src/movept.ptr b/vcl/os2/source/src/movept.ptr
new file mode 100644
index 000000000000..d34332dd89e5
--- /dev/null
+++ b/vcl/os2/source/src/movept.ptr
Binary files differ
diff --git a/vcl/os2/source/src/nullptr.ptr b/vcl/os2/source/src/nullptr.ptr
new file mode 100644
index 000000000000..f8b0f784ba7a
--- /dev/null
+++ b/vcl/os2/source/src/nullptr.ptr
Binary files differ
diff --git a/vcl/os2/source/src/pen.ptr b/vcl/os2/source/src/pen.ptr
new file mode 100644
index 000000000000..3b4495697597
--- /dev/null
+++ b/vcl/os2/source/src/pen.ptr
Binary files differ
diff --git a/vcl/os2/source/src/pivotcol.ptr b/vcl/os2/source/src/pivotcol.ptr
new file mode 100644
index 000000000000..369fdeebf2d0
--- /dev/null
+++ b/vcl/os2/source/src/pivotcol.ptr
Binary files differ
diff --git a/vcl/os2/source/src/pivotfld.ptr b/vcl/os2/source/src/pivotfld.ptr
new file mode 100644
index 000000000000..047c45a711df
--- /dev/null
+++ b/vcl/os2/source/src/pivotfld.ptr
Binary files differ
diff --git a/vcl/os2/source/src/pivotrow.ptr b/vcl/os2/source/src/pivotrow.ptr
new file mode 100644
index 000000000000..e66e752e51d0
--- /dev/null
+++ b/vcl/os2/source/src/pivotrow.ptr
Binary files differ
diff --git a/vcl/os2/source/src/pntbrsh.ptr b/vcl/os2/source/src/pntbrsh.ptr
new file mode 100644
index 000000000000..506965e6b52d
--- /dev/null
+++ b/vcl/os2/source/src/pntbrsh.ptr
Binary files differ
diff --git a/vcl/os2/source/src/refhand.ptr b/vcl/os2/source/src/refhand.ptr
new file mode 100644
index 000000000000..33d613134cb5
--- /dev/null
+++ b/vcl/os2/source/src/refhand.ptr
Binary files differ
diff --git a/vcl/os2/source/src/rotate.ptr b/vcl/os2/source/src/rotate.ptr
new file mode 100644
index 000000000000..622b05346cfc
--- /dev/null
+++ b/vcl/os2/source/src/rotate.ptr
Binary files differ
diff --git a/vcl/os2/source/src/salsrc.rc b/vcl/os2/source/src/salsrc.rc
new file mode 100644
index 000000000000..6e3b40c76da0
--- /dev/null
+++ b/vcl/os2/source/src/salsrc.rc
@@ -0,0 +1,108 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SV_SALIDS_HRC
+#include <salids.hrc>
+#endif
+
+POINTER SAL_RESID_POINTER_NULL NULLPTR.PTR
+POINTER SAL_RESID_POINTER_HELP HELP.PTR
+POINTER SAL_RESID_POINTER_CROSS CROSS.PTR
+POINTER SAL_RESID_POINTER_MOVE MOVE.PTR
+POINTER SAL_RESID_POINTER_HSPLIT HSPLIT.PTR
+POINTER SAL_RESID_POINTER_VSPLIT VSPLIT.PTR
+POINTER SAL_RESID_POINTER_HSIZEBAR HSIZEBAR.PTR
+POINTER SAL_RESID_POINTER_VSIZEBAR VSIZEBAR.PTR
+POINTER SAL_RESID_POINTER_HAND HAND.PTR
+POINTER SAL_RESID_POINTER_REFHAND REFHAND.PTR
+POINTER SAL_RESID_POINTER_PEN PEN.PTR
+POINTER SAL_RESID_POINTER_MAGNIFY MAGNIFY.PTR
+POINTER SAL_RESID_POINTER_FILL FILL.PTR
+POINTER SAL_RESID_POINTER_ROTATE ROTATE.PTR
+POINTER SAL_RESID_POINTER_HSHEAR HSHEAR.PTR
+POINTER SAL_RESID_POINTER_VSHEAR VSHEAR.PTR
+POINTER SAL_RESID_POINTER_MIRROR MIRROR.PTR
+POINTER SAL_RESID_POINTER_CROOK CROOK.PTR
+POINTER SAL_RESID_POINTER_CROP CROP.PTR
+POINTER SAL_RESID_POINTER_MOVEPOINT MOVEPT.PTR
+POINTER SAL_RESID_POINTER_MOVEBEZIERWEIGHT MOVEBW.PTR
+POINTER SAL_RESID_POINTER_MOVEDATA MOVEDATA.PTR
+POINTER SAL_RESID_POINTER_COPYDATA COPYDATA.PTR
+POINTER SAL_RESID_POINTER_LINKDATA LINKDATA.PTR
+POINTER SAL_RESID_POINTER_MOVEDATALINK MOVEDLNK.PTR
+POINTER SAL_RESID_POINTER_COPYDATALINK COPYDLNK.PTR
+POINTER SAL_RESID_POINTER_MOVEFILE MOVEF.PTR
+POINTER SAL_RESID_POINTER_COPYFILE COPYF.PTR
+POINTER SAL_RESID_POINTER_LINKFILE LINKF.PTR
+POINTER SAL_RESID_POINTER_MOVEFILELINK MOVEFLNK.PTR
+POINTER SAL_RESID_POINTER_COPYFILELINK COPYFLNK.PTR
+POINTER SAL_RESID_POINTER_MOVEFILES MOVEF2.PTR
+POINTER SAL_RESID_POINTER_COPYFILES COPYF2.PTR
+POINTER SAL_RESID_POINTER_DRAW_LINE DLINE.PTR
+POINTER SAL_RESID_POINTER_DRAW_RECT DRECT.PTR
+POINTER SAL_RESID_POINTER_DRAW_POLYGON DPOLYGON.PTR
+POINTER SAL_RESID_POINTER_DRAW_BEZIER DBEZIER.PTR
+POINTER SAL_RESID_POINTER_DRAW_ARC DARC.PTR
+POINTER SAL_RESID_POINTER_DRAW_PIE DPIE.PTR
+POINTER SAL_RESID_POINTER_DRAW_CIRCLECUT DCIRCCUT.PTR
+POINTER SAL_RESID_POINTER_DRAW_ELLIPSE DELLIPSE.PTR
+POINTER SAL_RESID_POINTER_DRAW_FREEHAND DFREE.PTR
+POINTER SAL_RESID_POINTER_DRAW_CONNECT DCONNECT.PTR
+POINTER SAL_RESID_POINTER_DRAW_TEXT DTEXT.PTR
+POINTER SAL_RESID_POINTER_DRAW_CAPTION DCAPT.PTR
+POINTER SAL_RESID_POINTER_CHART CHART.PTR
+POINTER SAL_RESID_POINTER_DETECTIVE DETECTIV.PTR
+POINTER SAL_RESID_POINTER_PIVOT_COL PIVOTCOL.PTR
+POINTER SAL_RESID_POINTER_PIVOT_ROW PIVOTROW.PTR
+POINTER SAL_RESID_POINTER_PIVOT_FIELD PIVOTFLD.PTR
+POINTER SAL_RESID_POINTER_CHAIN CHAIN.PTR
+POINTER SAL_RESID_POINTER_CHAIN_NOTALLOWED CHAINNOT.PTR
+POINTER SAL_RESID_POINTER_TIMEEVENT_MOVE TIMEMOVE.PTR
+POINTER SAL_RESID_POINTER_TIMEEVENT_SIZE TIMESIZE.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_N ASN.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_S ASS.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_W ASW.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_E ASE.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_NW ASNW.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_NE ASNE.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_SW ASSW.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_SE ASSE.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_NS ASNS.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_WE ASWE.PTR
+POINTER SAL_RESID_POINTER_AUTOSCROLL_NSWE ASNSWE.PTR
+
+POINTER SAL_RESID_POINTER_AIRBRUSH AIRBRUSH.PTR
+POINTER SAL_RESID_POINTER_TEXT_VERTICAL VTEXT.PTR
+POINTER SAL_RESID_POINTER_TAB_SELECT_S TBLSELS.PTR
+POINTER SAL_RESID_POINTER_TAB_SELECT_E TBLSELE.PTR
+POINTER SAL_RESID_POINTER_TAB_SELECT_SE TBLSELSE.PTR
+POINTER SAL_RESID_POINTER_TAB_SELECT_W TBLSELW.PTR
+POINTER SAL_RESID_POINTER_TAB_SELECT_SW TBLSELSW.PTR
+POINTER SAL_RESID_POINTER_PAINTBRUSH PNTBRSH.PTR
+
+ICON SAL_RESID_ICON_DEFAULT SD2.ICO
+
diff --git a/vcl/os2/source/src/sd.ico b/vcl/os2/source/src/sd.ico
new file mode 100644
index 000000000000..22cb33630b85
--- /dev/null
+++ b/vcl/os2/source/src/sd.ico
Binary files differ
diff --git a/vcl/os2/source/src/sd2.ico b/vcl/os2/source/src/sd2.ico
new file mode 100644
index 000000000000..f7edd4524bc1
--- /dev/null
+++ b/vcl/os2/source/src/sd2.ico
Binary files differ
diff --git a/vcl/os2/source/src/tblsele.ptr b/vcl/os2/source/src/tblsele.ptr
new file mode 100644
index 000000000000..627c2f61662b
--- /dev/null
+++ b/vcl/os2/source/src/tblsele.ptr
Binary files differ
diff --git a/vcl/os2/source/src/tblsels.ptr b/vcl/os2/source/src/tblsels.ptr
new file mode 100644
index 000000000000..3553c0d1f5ae
--- /dev/null
+++ b/vcl/os2/source/src/tblsels.ptr
Binary files differ
diff --git a/vcl/os2/source/src/tblselse.ptr b/vcl/os2/source/src/tblselse.ptr
new file mode 100644
index 000000000000..355e5105f58f
--- /dev/null
+++ b/vcl/os2/source/src/tblselse.ptr
Binary files differ
diff --git a/vcl/os2/source/src/tblselsw.ptr b/vcl/os2/source/src/tblselsw.ptr
new file mode 100644
index 000000000000..435dec00c3e1
--- /dev/null
+++ b/vcl/os2/source/src/tblselsw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/tblselw.ptr b/vcl/os2/source/src/tblselw.ptr
new file mode 100644
index 000000000000..de64ad06d6a2
--- /dev/null
+++ b/vcl/os2/source/src/tblselw.ptr
Binary files differ
diff --git a/vcl/os2/source/src/timemove.ptr b/vcl/os2/source/src/timemove.ptr
new file mode 100755
index 000000000000..a9298cee867b
--- /dev/null
+++ b/vcl/os2/source/src/timemove.ptr
Binary files differ
diff --git a/vcl/os2/source/src/timesize.ptr b/vcl/os2/source/src/timesize.ptr
new file mode 100755
index 000000000000..e543c1ff790c
--- /dev/null
+++ b/vcl/os2/source/src/timesize.ptr
Binary files differ
diff --git a/vcl/os2/source/src/vshear.ptr b/vcl/os2/source/src/vshear.ptr
new file mode 100644
index 000000000000..f335d5ea949b
--- /dev/null
+++ b/vcl/os2/source/src/vshear.ptr
Binary files differ
diff --git a/vcl/os2/source/src/vsizebar.ptr b/vcl/os2/source/src/vsizebar.ptr
new file mode 100644
index 000000000000..b238889c594c
--- /dev/null
+++ b/vcl/os2/source/src/vsizebar.ptr
Binary files differ
diff --git a/vcl/os2/source/src/vsplit.ptr b/vcl/os2/source/src/vsplit.ptr
new file mode 100644
index 000000000000..662d760b0b2f
--- /dev/null
+++ b/vcl/os2/source/src/vsplit.ptr
Binary files differ
diff --git a/vcl/os2/source/src/vtext.ptr b/vcl/os2/source/src/vtext.ptr
new file mode 100644
index 000000000000..a7f9901bdf68
--- /dev/null
+++ b/vcl/os2/source/src/vtext.ptr
Binary files differ
diff --git a/vcl/os2/source/window/makefile b/vcl/os2/source/window/makefile
new file mode 100644
index 000000000000..e9aba563d9e8
--- /dev/null
+++ b/vcl/os2/source/window/makefile
@@ -0,0 +1,53 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..\..\..
+
+PRJNAME=SV
+TARGET=salwin
+
+# --- Settings -----------------------------------------------------
+
+!INCLUDE <svpre.mak>
+!INCLUDE <settings.mak>
+!INCLUDE <sv.mak>
+
+!IF "$(COM)"=="ICC"
+ENVCFLAGS=$(ENVCFLAGS) -D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
+!ENDIF
+
+# --- Files --------------------------------------------------------
+
+CXXFILES= salframe.cxx \
+ salobj.cxx
+
+SLOFILES= $(SLO)\salframe.obj \
+ $(SLO)\salobj.obj
+
+# --- Targets ------------------------------------------------------
+
+!INCLUDE <target.mak>
diff --git a/vcl/os2/source/window/makefile.mk b/vcl/os2/source/window/makefile.mk
new file mode 100644
index 000000000000..f4a6ad0cb870
--- /dev/null
+++ b/vcl/os2/source/window/makefile.mk
@@ -0,0 +1,47 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=SV
+TARGET=salwin
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES__YD= salframe.cxx \
+ salobj.cxx
+
+SLOFILES= $(SLO)$/salframe.obj \
+ $(SLO)$/salobj.obj $(SLO)$/salmenu.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/os2/source/window/salframe.cxx b/vcl/os2/source/window/salframe.cxx
new file mode 100644
index 000000000000..f3314c725255
--- /dev/null
+++ b/vcl/os2/source/window/salframe.cxx
@@ -0,0 +1,3774 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#define INCL_DOS
+#define INCL_PM
+#define INCL_WIN
+#include <svpm.h>
+
+// =======================================================================
+
+#define _SV_SALFRAME_CXX
+
+#ifndef DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#define private public
+
+#ifndef _SV_SALLANG_HXX
+#include <sallang.hxx>
+#endif
+#ifndef _SV_SALIDS_HRC
+#include <salids.hrc>
+#endif
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salgdi.h>
+#include <salframe.h>
+#include <vcl/timer.hxx>
+#include <vcl/settings.hxx>
+#ifndef _SV_KEYCOES_HXX
+#include <vcl/keycodes.hxx>
+#endif
+#include <saltimer.h>
+
+#if OSL_DEBUG_LEVEL>10
+extern "C" int debug_printf(const char *f, ...);
+
+static BOOL _bCapture;
+
+#else
+#define debug_printf( ...) { 1; }
+#endif
+
+// =======================================================================
+
+HPOINTER ImplLoadPointer( ULONG nId );
+
+static void SetMaximizedFrameGeometry( HWND hWnd, Os2SalFrame* pFrame );
+static void UpdateFrameGeometry( HWND hWnd, Os2SalFrame* pFrame );
+static void ImplSalCalcFrameSize( HWND hWnd,
+ LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY );
+static void ImplSalCalcFrameSize( const Os2SalFrame* pFrame,
+ LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY );
+MRESULT EXPENTRY SalFrameSubClassWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 );
+
+// =======================================================================
+
+static LanguageType eImplKeyboardLanguage = LANGUAGE_DONTKNOW;
+BOOL Os2SalFrame::mbInReparent = FALSE;
+ULONG Os2SalFrame::mnInputLang = 0;
+
+// =======================================================================
+
+// define a new flag
+#define SWP_CENTER (SWP_NOAUTOCLOSE<<4)
+#define SWP_SHOWMAXIMIZED (SWP_ACTIVATE | SWP_SHOW | SWP_MAXIMIZE)
+#define SWP_SHOWMINIMIZED (SWP_ACTIVATE | SWP_SHOW | SWP_MINIMIZE)
+#define SWP_SHOWNORMAL (SWP_ACTIVATE | SWP_SHOW | SWP_RESTORE)
+
+static LONG nScreenHeight = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN);
+static LONG nScreenWidth = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
+
+BOOL APIENTRY _WinQueryWindowRect( HWND hwnd, PRECTL prclDest)
+{
+ BOOL rc = WinQueryWindowRect( hwnd, prclDest);
+ ULONG tmp = prclDest->yBottom;
+ prclDest->yBottom = prclDest->yTop;
+ prclDest->yTop = tmp;
+ return rc;
+}
+
+BOOL APIENTRY _WinQueryPointerPos (HWND hwndDesktop, PPOINTL pptl)
+{
+ BOOL rc = WinQueryPointerPos( hwndDesktop, pptl);
+ pptl->y = nScreenHeight - pptl->y;
+ return rc;
+}
+
+BOOL APIENTRY _WinQueryWindowPos( Os2SalFrame* pFrame, PSWP pswp)
+{
+ SWP swpOwner;
+ BOOL rc = WinQueryWindowPos( pFrame->mhWndFrame, pswp);
+
+#if OSL_DEBUG_LEVEL>1
+ debug_printf( "> WinQueryWindowPos hwnd %x at %d,%d (%dx%d)\n",
+ pFrame->mhWndFrame, pswp->x, pswp->y, pswp->cx, pswp->cy);
+#endif
+
+ Os2SalFrame* pParentFrame = pFrame->mpParentFrame;
+
+ //YD adjust to owner coordinates
+ if ( pParentFrame )
+ {
+ POINTL ptlOwner = {0};
+
+ // coords are relative to screen, map to parent frame client area
+ ptlOwner.x = pswp->x;
+ ptlOwner.y = pswp->y;
+ WinMapWindowPoints( HWND_DESKTOP, pParentFrame->mhWndClient, &ptlOwner, 1);
+ pswp->x = ptlOwner.x;
+ pswp->y = ptlOwner.y;
+ // get parent client area size
+ WinQueryWindowPos( pParentFrame->mhWndClient, &swpOwner);
+ } else
+ {
+ // no owner info, use DESKTOP????
+ swpOwner.cx = nScreenWidth;
+ swpOwner.cy = nScreenHeight;
+ }
+
+ // invert Y coordinate
+ pswp->y = swpOwner.cy - (pswp->y + pswp->cy);
+
+#if OSL_DEBUG_LEVEL>1
+ debug_printf( "< WinQueryWindowPos hwnd %x at %d,%d (%dx%d)\n",
+ pFrame->mhWndFrame, pswp->x, pswp->y, pswp->cx, pswp->cy);
+#endif
+ return rc;
+}
+
+BOOL APIENTRY _WinSetWindowPos( Os2SalFrame* pFrame, HWND hwndInsertBehind, LONG x, LONG y,
+ LONG cx, LONG cy, ULONG fl)
+{
+ SWP swpOwner = {0};
+ POINTL ptlOwner = {0};
+ HWND hParent = NULL;
+
+#if OSL_DEBUG_LEVEL>1
+ debug_printf( ">WinSetWindowPos hwnd %x at %d,%d (%dx%d) fl 0x%08x\n",
+ pFrame->mhWndFrame, x, y, cx, cy, fl);
+#endif
+
+ // first resize window if requested
+ if ( (fl & SWP_SIZE) ) {
+ ULONG flag = SWP_SIZE;
+ LONG nX = 0, nY = 0;
+ LONG frameFrameX, frameFrameY, frameCaptionY;
+
+ ImplSalCalcFrameSize( pFrame, frameFrameX, frameFrameY, frameCaptionY );
+ // if we change y size, we need to move the window down
+ // because os2 window origin is lower left corner
+ if (pFrame->maGeometry.nHeight != cy) {
+ SWP aSWP;
+ WinQueryWindowPos( pFrame->mhWndFrame, &aSWP);
+ nX = aSWP.x;
+ nY = aSWP.y - (cy + 2*frameFrameY + frameCaptionY - aSWP.cy);
+ flag |= SWP_MOVE;
+ }
+ WinSetWindowPos( pFrame->mhWndFrame, NULL, nX, nY,
+ cx+2*frameFrameX, cy+2*frameFrameY+frameCaptionY, flag);
+ fl = fl & ~SWP_SIZE;
+ }
+ else // otherwise get current size
+ {
+ SWP swp = {0};
+ WinQueryWindowPos( pFrame->mhWndClient, &swp);
+ cx = swp.cx;
+ cy = swp.cy;
+ }
+
+ // get parent window handle
+ Os2SalFrame* pParentFrame = pFrame->mpParentFrame;
+
+ // use desktop if parent is not defined
+ hParent = pParentFrame ? pParentFrame->mhWndClient : HWND_DESKTOP;
+ // if parent is not visible, use desktop as reference
+ hParent = WinIsWindowVisible( hParent) ? hParent : HWND_DESKTOP;
+
+ WinQueryWindowPos( hParent, &swpOwner);
+
+ //YD adjust to owner coordinates only when moving and not centering
+ //if (!(fl & SWP_CENTER) && (fl & SWP_MOVE))
+ if ((fl & SWP_MOVE))
+ {
+
+ // if SWP_CENTER is specified, change position to parent center
+ if (fl & SWP_CENTER) {
+ ptlOwner.x = (swpOwner.cx - cx) / 2;
+ ptlOwner.y = (swpOwner.cy - cy) / 2;
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "_WinSetWindowPos SWP_CENTER\n");
+#endif
+ fl = fl & ~SWP_CENTER;
+ } else {
+ // coords are relative to parent frame client area, map to screen
+ // map Y to OS/2 system coordinates
+ ptlOwner.x = x;
+ ptlOwner.y = swpOwner.cy - (y + cy);
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "_WinSetWindowPos owner 0x%x at %d,%d (%dx%d) OS2\n",
+ hParent, ptlOwner.x, ptlOwner.y, swpOwner.cx, swpOwner.cy);
+#endif
+ }
+ // map from client area to screen
+ WinMapWindowPoints( hParent, HWND_DESKTOP, &ptlOwner, 1);
+ x = ptlOwner.x;
+ y = ptlOwner.y;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "_WinSetWindowPos owner 0x%x at %d,%d (%dx%d) MAPPED OS2\n",
+ hParent, ptlOwner.x, ptlOwner.y, swpOwner.cx, swpOwner.cy);
+#endif
+ }
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "<WinSetWindowPos hwnd %x at %d,%d (%dx%d) fl=%x\n",
+ pFrame->mhWndFrame, x, y, cx, cy, fl);
+#endif
+ return WinSetWindowPos( pFrame->mhWndFrame, hwndInsertBehind, x, y, 0, 0, fl);
+}
+
+// =======================================================================
+
+#if OSL_DEBUG_LEVEL > 0
+static void dumpWindowInfo( char* fnc, HWND hwnd)
+{
+ SWP aSWP;
+ HWND hwnd2;
+ char szTitle[256];
+
+#if 0
+ _WinQueryWindowPos( hwnd, &aSWP );
+ strcpy(szTitle,"");
+ WinQueryWindowText(hwnd, sizeof(szTitle), szTitle);
+ debug_printf( "%s: window %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd,
+ aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
+ hwnd2 = WinQueryWindow(hwnd, QW_PARENT);
+ _WinQueryWindowPos( hwnd2, &aSWP );
+ strcpy(szTitle,"");
+ WinQueryWindowText(hwnd2, sizeof(szTitle), szTitle);
+ debug_printf( "%s: parent %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd2,
+ aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
+ hwnd2 = WinQueryWindow(hwnd, QW_OWNER);
+ _WinQueryWindowPos( hwnd2, &aSWP );
+ strcpy(szTitle,"");
+ WinQueryWindowText(hwnd2, sizeof(szTitle), szTitle);
+ debug_printf( "%s: owner %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd2,
+ aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
+#endif
+}
+#endif
+
+// =======================================================================
+
+#ifdef ENABLE_IME
+
+struct ImplSalIMEProc
+{
+ ULONG nOrd;
+ PFN* pProc;
+};
+
+#define SAL_IME_PROC_COUNT 12
+
+// -----------------------------------------------------------------------
+
+static SalIMEData* GetSalIMEData()
+{
+ SalData* pSalData = GetSalData();
+
+ if ( !pSalData->mbIMEInit )
+ {
+ pSalData->mbIMEInit = TRUE;
+
+ HMODULE hMod = 0;
+ if ( 0 == DosLoadModule( NULL, 0, "OS2IM", &hMod ) )
+ {
+ SalIMEData* pIMEData = new SalIMEData;
+ BOOL bError = FALSE;
+ ImplSalIMEProc aProcAry[SAL_IME_PROC_COUNT] =
+ {
+ { 101, (PFN*)&(pIMEData->mpAssocIME) },
+ { 104, (PFN*)&(pIMEData->mpGetIME) },
+ { 106, (PFN*)&(pIMEData->mpReleaseIME) },
+ { 117, (PFN*)&(pIMEData->mpSetConversionFont) },
+ { 144, (PFN*)&(pIMEData->mpSetConversionFontSize) },
+ { 118, (PFN*)&(pIMEData->mpGetConversionString) },
+ { 122, (PFN*)&(pIMEData->mpGetResultString) },
+ { 115, (PFN*)&(pIMEData->mpSetCandidateWin) },
+ { 130, (PFN*)&(pIMEData->mpQueryIMEProperty) },
+ { 131, (PFN*)&(pIMEData->mpRequestIME) },
+ { 128, (PFN*)&(pIMEData->mpSetIMEMode) },
+ { 127, (PFN*)&(pIMEData->mpQueryIMEMode) }
+ };
+
+ pIMEData->mhModIME = hMod;
+ for ( USHORT i = 0; i < SAL_IME_PROC_COUNT; i++ )
+ {
+ if ( 0 != DosQueryProcAddr( pIMEData->mhModIME, aProcAry[i].nOrd, 0, aProcAry[i].pProc ) )
+ {
+ bError = TRUE;
+ break;
+ }
+ }
+
+ if ( bError )
+ {
+ DosFreeModule( pIMEData->mhModIME );
+ delete pIMEData;
+ }
+ else
+ pSalData->mpIMEData = pIMEData;
+ }
+ }
+
+ return pSalData->mpIMEData;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplReleaseSALIMEData()
+{
+ SalData* pSalData = GetSalData();
+
+ if ( pSalData->mpIMEData )
+ {
+ DosFreeModule( pSalData->mpIMEData->mhModIME );
+ delete pSalData->mpIMEData;
+ }
+}
+
+#endif
+
+// =======================================================================
+
+static void ImplSaveFrameState( Os2SalFrame* pFrame )
+{
+ // Position, Groesse und Status fuer GetWindowState() merken
+ if ( !pFrame->mbFullScreen )
+ {
+ SWP aSWP;
+ BOOL bVisible = WinIsWindowVisible( pFrame->mhWndFrame);
+
+ // Query actual state (maState uses screen coords)
+ WinQueryWindowPos( pFrame->mhWndFrame, &aSWP );
+
+ if ( aSWP.fl & SWP_MINIMIZE )
+ {
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::GetWindowState %08x SAL_FRAMESTATE_MINIMIZED\n",
+ pFrame->mhWndFrame);
+#endif
+ pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
+ if ( bVisible )
+ pFrame->mnShowState = SWP_SHOWMAXIMIZED;
+ }
+ else if ( aSWP.fl & SWP_MAXIMIZE )
+ {
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::GetWindowState %08x SAL_FRAMESTATE_MAXIMIZED\n",
+ pFrame->mhWndFrame);
+#endif
+ pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
+ pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
+ if ( bVisible )
+ pFrame->mnShowState = SWP_SHOWMINIMIZED;
+ pFrame->mbRestoreMaximize = TRUE;
+ }
+ else
+ {
+ LONG nFrameX, nFrameY, nCaptionY;
+ ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );
+ // to be consistent with Unix, the frame state is without(!) decoration
+ long nTopDeco = nFrameY + nCaptionY;
+ long nLeftDeco = nFrameX;
+ long nBottomDeco = nFrameY;
+ long nRightDeco = nFrameX;
+
+ pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
+ // subtract decoration, store screen coords
+ pFrame->maState.mnX = aSWP.x+nLeftDeco;
+ pFrame->maState.mnY = nScreenHeight - (aSWP.y+aSWP.cy)+nTopDeco;
+ pFrame->maState.mnWidth = aSWP.cx-nLeftDeco-nRightDeco;
+ pFrame->maState.mnHeight = aSWP.cy-nTopDeco-nBottomDeco;
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::GetWindowState %08x (%dx%d) at %d,%d VCL\n",
+ pFrame->mhWndFrame,
+ pFrame->maState.mnWidth,pFrame->maState.mnHeight,pFrame->maState.mnX,pFrame->maState.mnY);
+#endif
+ if ( bVisible )
+ pFrame->mnShowState = SWP_SHOWNORMAL;
+ pFrame->mbRestoreMaximize = FALSE;
+ //debug_printf( "ImplSaveFrameState: window %08x at %d,%d (size %dx%d)\n",
+ // pFrame->mhWndFrame,
+ // pFrame->maState.mnX, pFrame->maState.mnY, pFrame->maState.mnWidth, pFrame->maState.mnHeight);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ImplSalCallbackDummy( void*, SalFrame*, USHORT, const void* )
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalCalcFrameSize( HWND hWnd,
+ LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY )
+{
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( !pFrame )
+ return;
+ return ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );
+}
+
+static void ImplSalCalcFrameSize( const Os2SalFrame* pFrame,
+ LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY )
+{
+ if ( pFrame->mbSizeBorder )
+ {
+ nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXSIZEBORDER );
+ nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER );
+ }
+ else if ( pFrame->mbFixBorder )
+ {
+ nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXDLGFRAME );
+ nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME );
+ }
+ else if ( pFrame->mbBorder )
+ {
+ nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXBORDER );
+ nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER );
+ }
+ else
+ {
+ nFrameX = 0;
+ nFrameY = 0;
+ }
+ if ( pFrame->mbCaption )
+ nCaptionY = WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR );
+ else
+ nCaptionY = 0;
+
+#if OSL_DEBUG_LEVEL>0
+ //if (_bCapture)
+ debug_printf("ImplSalCalcFrameSize 0x%08x x=%d y=%d t=%d\n", pFrame->mhWndFrame, nFrameX, nFrameY, nCaptionY);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalCalcFullScreenSize( const Os2SalFrame* pFrame,
+ LONG& rX, LONG& rY, LONG& rDX, LONG& rDY )
+{
+ // set window to screen size
+ LONG nFrameX, nFrameY, nCaptionY;
+ LONG rScreenDX = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
+ LONG rScreenDY = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
+
+ // Framegroessen berechnen
+ ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );
+
+ rX = -nFrameX;
+ rY = -(nFrameY+nCaptionY);
+ rDX = rScreenDX+(nFrameX*2);
+ rDY = rScreenDY+(nFrameY*2)+nCaptionY;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalFrameFullScreenPos( Os2SalFrame* pFrame, BOOL bAlways = FALSE )
+{
+ SWP aSWP;
+ _WinQueryWindowPos( pFrame, &aSWP );
+ if ( bAlways || !(aSWP.fl & SWP_MINIMIZE) )
+ {
+ // set window to screen size
+ LONG nX;
+ LONG nY;
+ LONG nWidth;
+ LONG nHeight;
+ ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
+ _WinSetWindowPos( pFrame, 0,
+ nX, nY, nWidth, nHeight,
+ SWP_MOVE | SWP_SIZE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+// Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
+#define KEY_TAB_SIZE (VK_ENDDRAG+1)
+
+static USHORT aImplTranslateKeyTab[KEY_TAB_SIZE] =
+{
+ // StarView-Code System-Code Index
+ 0, // 0x00
+ 0, // VK_BUTTON1 0x01
+ 0, // VK_BUTTON2 0x02
+ 0, // VK_BUTTON3 0x03
+ 0, // VK_BREAK 0x04
+ KEY_BACKSPACE, // VK_BACKSPACE 0x05
+ KEY_TAB, // VK_TAB 0x06
+ KEY_TAB, // VK_BACKTAB 0x07
+ KEY_RETURN, // VK_NEWLINE 0x08
+ 0, // VK_SHIFT 0x09
+ 0, // VK_CTRL 0x0A
+ 0, // VK_ALT 0x0B
+ 0, // VK_ALTGRAF 0x0C
+ 0, // VK_PAUSE 0x0D
+ 0, // VK_CAPSLOCK 0x0E
+ KEY_ESCAPE, // VK_ESC 0x0F
+ KEY_SPACE, // VK_SPACE 0x10
+ KEY_PAGEUP, // VK_PAGEUP 0x11
+ KEY_PAGEDOWN, // VK_PAGEDOWN 0x12
+ KEY_END, // VK_END 0x13
+ KEY_HOME, // VK_HOME 0x14
+ KEY_LEFT, // VK_LEFT 0x15
+ KEY_UP, // VK_UP 0x16
+ KEY_RIGHT, // VK_RIGHT 0x17
+ KEY_DOWN, // VK_DOWN 0x18
+ 0, // VK_PRINTSCRN 0x19
+ KEY_INSERT, // VK_INSERT 0x1A
+ KEY_DELETE, // VK_DELETE 0x1B
+ 0, // VK_SCRLLOCK 0x1C
+ 0, // VK_NUMLOCK 0x1D
+ KEY_RETURN, // VK_ENTER 0x1E
+ 0, // VK_SYSRQ 0x1F
+ KEY_F1, // VK_F1 0x20
+ KEY_F2, // VK_F2 0x21
+ KEY_F3, // VK_F3 0x22
+ KEY_F4, // VK_F4 0x23
+ KEY_F5, // VK_F5 0x24
+ KEY_F6, // VK_F6 0x25
+ KEY_F7, // VK_F7 0x26
+ KEY_F8, // VK_F8 0x27
+ KEY_F9, // VK_F9 0x28
+ KEY_F10, // VK_F10 0x29
+ KEY_F11, // VK_F11 0x2A
+ KEY_F12, // VK_F12 0x2B
+ KEY_F13, // VK_F13 0x2C
+ KEY_F14, // VK_F14 0x2D
+ KEY_F15, // VK_F15 0x2E
+ KEY_F16, // VK_F16 0x2F
+ KEY_F17, // VK_F17 0x30
+ KEY_F18, // VK_F18 0x31
+ KEY_F19, // VK_F19 0x32
+ KEY_F20, // VK_F20 0x33
+ KEY_F21, // VK_F21 0x34
+ KEY_F22, // VK_F22 0x35
+ KEY_F23, // VK_F23 0x36
+ KEY_F24, // VK_F24 0x37
+ 0 // VK_ENDDRAG 0x38
+};
+
+// =======================================================================
+
+SalFrame* ImplSalCreateFrame( Os2SalInstance* pInst, HWND hWndParent, ULONG nSalFrameStyle )
+{
+ SalData* pSalData = GetSalData();
+ Os2SalFrame* pFrame = new Os2SalFrame;
+ HWND hWndFrame;
+ HWND hWndClient;
+ ULONG nFrameFlags = FCF_NOBYTEALIGN | FCF_SCREENALIGN;
+ ULONG nFrameStyle = 0;
+ ULONG nClientStyle = WS_CLIPSIBLINGS;
+ BOOL bSubFrame = FALSE;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf(">ImplSalCreateFrame hWndParent 0x%x, nSalFrameStyle 0x%x\n", hWndParent, nSalFrameStyle);
+#endif
+
+ if ( hWndParent )
+ {
+ bSubFrame = TRUE;
+ pFrame->mbNoIcon = TRUE;
+ }
+
+ // determine creation data (bei Moveable nehmen wir DLG-Border, damit
+ // es besser aussieht)
+ if ( nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE )
+ nFrameFlags |= FCF_CLOSEBUTTON;
+
+ if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) {
+ pFrame->mbCaption = TRUE;
+ nFrameStyle = WS_ANIMATE;
+ nFrameFlags |= FCF_SYSMENU | FCF_TITLEBAR | FCF_DLGBORDER;
+ if ( !hWndParent )
+ nFrameFlags |= FCF_MINBUTTON;
+
+ if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
+ {
+ pFrame->mbSizeBorder = TRUE;
+ nFrameFlags |= FCF_SIZEBORDER;
+ if ( !hWndParent )
+ nFrameFlags |= FCF_MAXBUTTON;
+ }
+ else
+ pFrame->mbFixBorder = TRUE;
+
+ // add task list style if not a tool window
+ if ( !(nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW) ) {
+ nFrameFlags |= FCF_TASKLIST;
+ }
+ }
+
+ if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW )
+ {
+ pFrame->mbNoIcon = TRUE;
+ // YD gives small caption -> nExSysStyle |= WS_EX_TOOLWINDOW;
+ }
+
+ if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
+ {
+ //nExSysStyle |= WS_EX_TOOLWINDOW;
+ pFrame->mbFloatWin = TRUE;
+ }
+ //if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP )
+ // nExSysStyle |= WS_EX_TOPMOST;
+
+ // init frame data
+ pFrame->mnStyle = nSalFrameStyle;
+
+ // determine show style
+ pFrame->mnShowState = SWP_SHOWNORMAL;
+
+ // create frame
+ //YD FIXME this is a potential bug with multiple threads and cuncurrent
+ //window creation, because this field is accessed in
+ //WM_CREATE to get window data,
+ pSalData->mpCreateFrame = pFrame;
+
+ //YD FIXME if SAL_FRAME_CHILD is specified, use hWndParent as parent handle...
+ hWndFrame = WinCreateStdWindow( HWND_DESKTOP, nFrameStyle, &nFrameFlags,
+ (PSZ)(bSubFrame ? SAL_SUBFRAME_CLASSNAME : SAL_FRAME_CLASSNAME),
+ NULL,
+ nClientStyle, 0, 0, &hWndClient );
+ debug_printf("ImplSalCreateFrame hWndParent 0x%x, hWndFrame 0x%x, hWndClient 0x%x\n", hWndParent, hWndFrame, hWndClient);
+ if ( !hWndFrame )
+ {
+ delete pFrame;
+ return NULL;
+ }
+
+ // Parent setzen (Owner)
+ if ( hWndParent != 0 && hWndParent != HWND_DESKTOP )
+ WinSetOwner( hWndFrame, hWndParent );
+
+ Os2SalFrame* pParentFrame = GetWindowPtr( hWndParent );
+ if ( pParentFrame )
+ pFrame->mpParentFrame = pParentFrame;
+
+ // Icon setzen (YD win32 does it in the class registration)
+ if ( nFrameFlags & FCF_MINBUTTON )
+ WinSendMsg( hWndFrame, WM_SETICON, (MPARAM)pInst->mhAppIcon, (MPARAM)0 );
+
+ // If we have an Window with an Caption Bar and without
+ // an MaximizeBox, we change the SystemMenu
+ if ( (nFrameFlags & (FCF_TITLEBAR | FCF_MAXBUTTON)) == (FCF_TITLEBAR) )
+ {
+ HWND hSysMenu = WinWindowFromID( hWndFrame, FID_SYSMENU );
+ if ( hSysMenu )
+ {
+ if ( !(nFrameFlags & (FCF_MINBUTTON | FCF_MAXBUTTON)) )
+ WinEnableMenuItem(hSysMenu, SC_RESTORE, FALSE);
+ if ( !(nFrameFlags & FCF_MINBUTTON) )
+ WinEnableMenuItem(hSysMenu, SC_MINIMIZE, FALSE);
+ if ( !(nFrameFlags & FCF_MAXBUTTON) )
+ WinEnableMenuItem(hSysMenu, SC_MAXIMIZE, FALSE);
+ if ( !(nFrameFlags & FCF_SIZEBORDER) )
+ WinEnableMenuItem(hSysMenu, SC_SIZE, FALSE);
+ }
+ }
+ if ( (nFrameFlags & FCF_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) )
+ {
+ HWND hSysMenu = WinWindowFromID( hWndFrame, FID_SYSMENU );
+ if ( hSysMenu )
+ {
+ WinEnableMenuItem(hSysMenu, SC_CLOSE, FALSE);
+ }
+ }
+
+ // ticket#124 subclass frame window: we need to intercept TRACK message
+ aSalShlData.mpFrameProc = WinSubclassWindow( hWndFrame, SalFrameSubClassWndProc);
+
+ // init OS/2 frame data
+ pFrame->mhAB = pInst->mhAB;
+
+ // YD 18/08 under OS/2, invisible frames have size 0,0 at 0,0, so
+ // we need to set an initial size/position manually
+ SWP aSWP;
+ memset( &aSWP, 0, sizeof( aSWP ) );
+ WinQueryTaskSizePos( pInst->mhAB, 0, &aSWP );
+ WinSetWindowPos( hWndFrame, NULL, aSWP.x, aSWP.y, aSWP.cx, aSWP.cy,
+ SWP_MOVE | SWP_SIZE);
+
+#ifdef ENABLE_IME
+ // Input-Context einstellen
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ pFrame->mhIMEContext = 0;
+ if ( 0 != pIMEData->mpAssocIME( hWndClient, pFrame->mhIMEContext, &pFrame->mhDefIMEContext ) )
+ pFrame->mhDefIMEContext = 0;
+ }
+ else
+ {
+ pFrame->mhIMEContext = 0;
+ pFrame->mhDefIMEContext = 0;
+ }
+#endif
+
+ RECTL rectl;
+ _WinQueryWindowRect( hWndClient, &rectl );
+ pFrame->mnWidth = rectl.xRight;
+ pFrame->mnHeight = rectl.yBottom;
+ debug_printf( "ImplSalCreateFrame %dx%d\n", pFrame->mnWidth, pFrame->mnHeight);
+ ImplSaveFrameState( pFrame );
+ pFrame->mbDefPos = TRUE;
+
+ UpdateFrameGeometry( hWndFrame, pFrame );
+
+ if( pFrame->mnShowState == SWP_SHOWMAXIMIZED )
+ {
+ // #96084 set a useful internal window size because
+ // the window will not be maximized (and the size updated) before show()
+ SetMaximizedFrameGeometry( hWndFrame, pFrame );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ dumpWindowInfo( "<ImplSalCreateFrame (exit)", hWndFrame);
+#endif
+
+ return pFrame;
+}
+
+// =======================================================================
+
+Os2SalFrame::Os2SalFrame()
+{
+ SalData* pSalData = GetSalData();
+
+ mbGraphics = NULL;
+ mhPointer = WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, FALSE );
+ mpGraphics = NULL;
+ mpInst = NULL;
+ mbFullScreen = FALSE;
+ mbAllwayOnTop = FALSE;
+ mbVisible = FALSE;
+ mbMinHide = FALSE;
+ mbInShow = FALSE;
+ mbRestoreMaximize = FALSE;
+ mbInMoveMsg = FALSE;
+ mbInSizeMsg = FALSE;
+ mbDefPos = TRUE;
+ mbOverwriteState = TRUE;
+ mbHandleIME = FALSE;
+ mbConversionMode = FALSE;
+ mbCandidateMode = FALSE;
+ mbCaption = FALSE;
+ //mhDefIMEContext = 0;
+ mpGraphics = NULL;
+ mnShowState = SWP_SHOWNORMAL;
+ mnWidth = 0;
+ mnHeight = 0;
+ mnMinWidth = 0;
+ mnMinHeight = 0;
+ mnMaxWidth = SHRT_MAX;
+ mnMaxHeight = SHRT_MAX;
+ mnInputLang = 0;
+ mnKeyboardHandle = 0;
+ mbGraphics = FALSE;
+ mbCaption = FALSE;
+ mbBorder = FALSE;
+ mbFixBorder = FALSE;
+ mbSizeBorder = FALSE;
+ mbFullScreen = FALSE;
+ //mbPresentation = FALSE;
+ mbInShow = FALSE;
+ mbRestoreMaximize = FALSE;
+ mbInMoveMsg = FALSE;
+ mbInSizeMsg = FALSE;
+ //mbFullScreenToolWin = FALSE;
+ mbDefPos = TRUE;
+ mbOverwriteState = TRUE;
+ //mbIME = FALSE;
+ mbHandleIME = FALSE;
+ //mbSpezIME = FALSE;
+ //mbAtCursorIME = FALSE;
+ mbCandidateMode = FALSE;
+ mbFloatWin = FALSE;
+ mbNoIcon = FALSE;
+ //mSelectedhMenu = 0;
+ //mLastActivatedhMenu = 0;
+ mpParentFrame = NULL;
+
+ memset( &maState, 0, sizeof( SalFrameState ) );
+ maSysData.nSize = sizeof( SystemEnvData );
+ memset( &maGeometry, 0, sizeof( maGeometry ) );
+
+ // insert frame in framelist
+ mpNextFrame = pSalData->mpFirstFrame;
+ pSalData->mpFirstFrame = this;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalFrame::~Os2SalFrame()
+{
+ SalData* pSalData = GetSalData();
+
+ // destroy DC
+ if ( mpGraphics )
+ {
+ ImplSalDeInitGraphics( mpGraphics );
+ WinReleasePS( mpGraphics->mhPS );
+ delete mpGraphics;
+ }
+
+ // destroy system frame
+ WinDestroyWindow( mhWndFrame );
+
+ // remove frame from framelist
+ if ( this == pSalData->mpFirstFrame )
+ pSalData->mpFirstFrame = mpNextFrame;
+ else
+ {
+ Os2SalFrame* pTempFrame = pSalData->mpFirstFrame;
+ while ( pTempFrame->mpNextFrame != this )
+ pTempFrame = pTempFrame->mpNextFrame;
+
+ pTempFrame->mpNextFrame = mpNextFrame;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static HDC ImplWinGetDC( HWND hWnd )
+{
+ HDC hDC = WinQueryWindowDC( hWnd );
+ if ( !hDC )
+ hDC = WinOpenWindowDC( hWnd );
+ return hDC;
+}
+
+// -----------------------------------------------------------------------
+
+SalGraphics* Os2SalFrame::GetGraphics()
+{
+ if ( mbGraphics )
+ return NULL;
+
+ if ( !mpGraphics )
+ {
+ SalData* pSalData = GetSalData();
+ mpGraphics = new Os2SalGraphics;
+ mpGraphics->mhPS = WinGetPS( mhWndClient );
+ mpGraphics->mhDC = ImplWinGetDC( mhWndClient );
+ mpGraphics->mhWnd = mhWndClient;
+ mpGraphics->mnHeight = mnHeight;
+ mpGraphics->mbPrinter = FALSE;
+ mpGraphics->mbVirDev = FALSE;
+ mpGraphics->mbWindow = TRUE;
+ mpGraphics->mbScreen = TRUE;
+ ImplSalInitGraphics( mpGraphics );
+ mbGraphics = TRUE;
+ }
+ else
+ mbGraphics = TRUE;
+
+ return mpGraphics;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::ReleaseGraphics( SalGraphics* )
+{
+ mbGraphics = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalFrame::PostEvent( void* pData )
+{
+ return (BOOL)WinPostMsg( mhWndClient, SAL_MSG_USEREVENT, 0, (MPARAM)pData );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetTitle( const XubString& rTitle )
+{
+ // set window title
+ ByteString title( rTitle, gsl_getSystemTextEncoding() );
+ debug_printf("Os2SalFrame::SetTitle %x '%s'\n", mhWndFrame, title.GetBuffer() );
+ WinSetWindowText( mhWndFrame, title.GetBuffer() );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetIcon( USHORT nIcon )
+{
+ debug_printf("Os2SalFrame::SetIcon\n");
+
+ // If we have a window without an Icon (for example a dialog), ignore this call
+ if ( mbNoIcon )
+ return;
+
+ // 0 means default (class) icon
+ HPOINTER hIcon = NULL;
+ if ( !nIcon )
+ nIcon = 1;
+
+ ImplLoadSalIcon( nIcon, hIcon );
+
+ DBG_ASSERT( hIcon , "Os2SalFrame::SetIcon(): Could not load icon !" );
+
+ // Icon setzen
+ WinSendMsg( mhWndFrame, WM_SETICON, (MPARAM)hIcon, (MPARAM)0 );
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* Os2SalFrame::GetParent() const
+{
+ //debug_printf("Os2SalFrame::GetParent\n");
+ return GetWindowPtr( WinQueryWindow(mhWndFrame, QW_OWNER) );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSalShow( HWND hWnd, ULONG bVisible, ULONG bNoActivate )
+{
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( !pFrame )
+ return;
+
+ if ( bVisible )
+ {
+ pFrame->mbDefPos = FALSE;
+ pFrame->mbOverwriteState = TRUE;
+ pFrame->mbInShow = TRUE;
+
+#if OSL_DEBUG_LEVEL > 0
+ debug_printf( "ImplSalShow hwnd %x visible flag %d, no activate: flag %d\n", hWnd, bVisible, bNoActivate);
+#endif
+
+ if( bNoActivate )
+ WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_SHOW);
+ else
+ WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, pFrame->mnShowState);
+
+ pFrame->mbInShow = FALSE;
+
+ // Direct Paint only, if we get the SolarMutx
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ WinUpdateWindow( hWnd );
+ ImplSalYieldMutexRelease();
+ }
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 0
+ debug_printf( "ImplSalShow hwnd %x HIDE\n");
+#endif
+ WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_HIDE);
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+
+void Os2SalFrame::SetExtendedFrameStyle( SalExtStyle nExtStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::Show( BOOL bVisible, BOOL bNoActivate )
+{
+ // Post this Message to the window, because this only works
+ // in the thread of the window, which has create this window.
+ // We post this message to avoid deadlocks
+ if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
+ WinPostMsg( mhWndFrame, SAL_MSG_SHOW, (MPARAM)bVisible, (MPARAM)bNoActivate );
+ else
+ ImplSalShow( mhWndFrame, bVisible, bNoActivate );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::Enable( BOOL bEnable )
+{
+ WinEnableWindow( mhWndFrame, bEnable );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetMinClientSize( long nWidth, long nHeight )
+{
+ debug_printf("Os2SalFrame::SetMinClientSize\n");
+ mnMinWidth = nWidth;
+ mnMinHeight = nHeight;
+}
+
+void Os2SalFrame::SetMaxClientSize( long nWidth, long nHeight )
+{
+ debug_printf("Os2SalFrame::SetMaxClientSize\n");
+ mnMaxWidth = nWidth;
+ mnMaxHeight = nHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ // calculation frame size
+ USHORT nEvent = 0;
+ ULONG nPosFlags = 0;
+
+#if OSL_DEBUG_LEVEL > 0
+ //dumpWindowInfo( "-Os2SalFrame::SetPosSize", mhWndFrame);
+ debug_printf( ">Os2SalFrame::SetPosSize go to %d,%d (%dx%d) VCL\n",nX,nY,nWidth,nHeight);
+#endif
+
+ SWP aSWP;
+ _WinQueryWindowPos( this, &aSWP );
+ BOOL bVisible = WinIsWindowVisible( mhWndFrame );
+ if ( !bVisible )
+ {
+ if ( mbFloatWin )
+ mnShowState = SWP_SHOW;
+ else
+ mnShowState = SWP_SHOWNORMAL;
+ }
+ else
+ {
+ if ( (aSWP.fl & SWP_MINIMIZE) || (aSWP.fl & SWP_MAXIMIZE) )
+ WinSetWindowPos(mhWndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE );
+ }
+
+ if ( (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) ) {
+ nPosFlags |= SWP_MOVE;
+#if OSL_DEBUG_LEVEL > 0
+ debug_printf( "-Os2SalFrame::SetPosSize MOVE to %d,%d\n", nX, nY);
+#endif
+ //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" );
+ nEvent = SALEVENT_MOVE;
+ }
+
+ if ( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) ) {
+ nPosFlags |= SWP_SIZE;
+#if OSL_DEBUG_LEVEL > 0
+ debug_printf( "-Os2SalFrame::SetPosSize SIZE to %d,%d\n", nWidth,nHeight);
+#endif
+ nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
+ }
+
+ // Default-Position, dann zentrieren, ansonsten Position beibehalten
+ if ( mbDefPos && !(nPosFlags & SWP_MOVE))
+ {
+ // calculate bottom left corner of frame
+ mbDefPos = FALSE;
+ nPosFlags |= SWP_MOVE | SWP_CENTER;
+ nEvent = SALEVENT_MOVERESIZE;
+#if OSL_DEBUG_LEVEL > 10
+ debug_printf( "-Os2SalFrame::SetPosSize CENTER\n");
+ debug_printf( "-Os2SalFrame::SetPosSize default position to %d,%d\n", nX, nY);
+#endif
+ }
+
+ // Adjust Window in the screen
+ BOOL bCheckOffScreen = TRUE;
+
+ // but don't do this for floaters or ownerdraw windows that are currently moved interactively
+ if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
+ bCheckOffScreen = FALSE;
+
+ if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
+ {
+ // may be the window is currently being moved (mouse is captured), then no check is required
+ if( mhWndClient == WinQueryCapture( HWND_DESKTOP) )
+ bCheckOffScreen = FALSE;
+ else
+ bCheckOffScreen = TRUE;
+ }
+
+ if( bCheckOffScreen )
+ {
+ if ( nX+nWidth > nScreenWidth )
+ nX = nScreenWidth - nWidth;
+ if ( nY+nHeight > nScreenHeight )
+ nY = nScreenHeight - nHeight;
+ if ( nX < 0 )
+ nX = 0;
+ if ( nY < 0 )
+ nY = 0;
+ }
+
+ // bring floating windows always to top
+ // do not change zorder, otherwise tooltips will bring main window to top (ticket:14)
+ //if( (mnStyle & SAL_FRAME_STYLE_FLOAT) )
+ // nPosFlags |= SWP_ZORDER; // do not change z-order
+
+ // set new position
+ _WinSetWindowPos( this, HWND_TOP, nX, nY, nWidth, nHeight, nPosFlags); // | SWP_RESTORE
+
+ UpdateFrameGeometry( mhWndFrame, this );
+
+ // Notification -- really ???
+ if( nEvent )
+ CallCallback( nEvent, NULL );
+
+#if OSL_DEBUG_LEVEL > 0
+ dumpWindowInfo( "<Os2SalFrame::SetPosSize (exit)", mhWndFrame);
+#endif
+
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetParent( SalFrame* pNewParent )
+{
+ APIRET rc;
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::SetParent mhWndFrame 0x%08x to 0x%08x\n",
+ static_cast<Os2SalFrame*>(this)->mhWndFrame,
+ static_cast<Os2SalFrame*>(pNewParent)->mhWndClient);
+#endif
+ Os2SalFrame::mbInReparent = TRUE;
+ //rc = WinSetParent(static_cast<Os2SalFrame*>(this)->mhWndFrame,
+ // static_cast<Os2SalFrame*>(pNewParent)->mhWndClient, TRUE);
+ rc = WinSetOwner(static_cast<Os2SalFrame*>(this)->mhWndFrame,
+ static_cast<Os2SalFrame*>(pNewParent)->mhWndClient);
+ mpParentFrame = static_cast<Os2SalFrame*>(pNewParent);
+ Os2SalFrame::mbInReparent = FALSE;
+}
+
+bool Os2SalFrame::SetPluginParent( SystemParentData* pNewParent )
+{
+ APIRET rc;
+ if ( pNewParent->hWnd == 0 )
+ {
+ pNewParent->hWnd = HWND_DESKTOP;
+ }
+
+ Os2SalFrame::mbInReparent = TRUE;
+ rc = WinSetOwner(static_cast<Os2SalFrame*>(this)->mhWndFrame,
+ pNewParent->hWnd);
+ Os2SalFrame::mbInReparent = FALSE;
+ return true;
+}
+
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::GetWorkArea( RECTL &rRect )
+{
+ rRect.xLeft = rRect.yTop = 0;
+ rRect.xRight = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN )-1;
+ rRect.yBottom = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN )-1;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::GetWorkArea( Rectangle &rRect )
+{
+ RECTL aRect;
+ GetWorkArea( aRect);
+ rRect.nLeft = aRect.xLeft;
+ rRect.nRight = aRect.xRight; // win -1;
+ rRect.nTop = aRect.yTop;
+ rRect.nBottom = aRect.yBottom; // win -1;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::GetClientSize( long& rWidth, long& rHeight )
+{
+ rWidth = maGeometry.nWidth;
+ rHeight = maGeometry.nHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetWindowState( const SalFrameState* pState )
+{
+ LONG nX;
+ LONG nY;
+ LONG nWidth;
+ LONG nHeight;
+ ULONG nPosSize = 0;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::SetWindowState\n");
+ debug_printf("Os2SalFrame::SetWindowState %08x (%dx%d) at %d,%d VCL\n",
+ mhWndFrame,
+ pState->mnWidth,pState->mnHeight,pState->mnX,pState->mnY);
+#endif
+
+ BOOL bVisible = WinIsWindowVisible( mhWndFrame );
+
+ // get screen coordinates
+ SWP aSWP;
+ WinQueryWindowPos( mhWndFrame, &aSWP );
+ LONG nFrameX, nFrameY, nCaptionY;
+ ImplSalCalcFrameSize( this, nFrameX, nFrameY, nCaptionY );
+
+ long nTopDeco = nFrameY + nCaptionY;
+ long nLeftDeco = nFrameX;
+ long nBottomDeco = nFrameY;
+ long nRightDeco = nFrameX;
+
+ // Fenster-Position/Groesse in den Bildschirm einpassen
+ if ((pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
+ nPosSize |= SWP_MOVE;
+ if ((pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
+ nPosSize |= SWP_SIZE;
+
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
+ nX = (int)pState->mnX - nLeftDeco;
+ else
+ nX = aSWP.x;
+
+ // keep Y inverted since height is still unknown, will invert later
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
+ nY = (int)pState->mnY - nTopDeco;
+ else
+ nY = nScreenHeight - (aSWP.y+aSWP.cy);
+
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
+ nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
+ else
+ nWidth = aSWP.cx;
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
+ nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
+ else
+ nHeight = aSWP.cy;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::SetWindowState (%dx%d) at %d,%d\n", nWidth,nHeight,nX,nY);
+#endif
+
+ // Adjust Window in the screen:
+ // if it does not fit into the screen do nothing, ie default pos/size will be used
+ // if there is an overlap with the screen border move the window while keeping its size
+
+ //if( nWidth > nScreenWidth || nHeight > nScreenHeight )
+ // nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);
+
+ if ( nX+nWidth > nScreenWidth )
+ nX = (nScreenWidth) - nWidth;
+ if ( nY+nHeight > nScreenHeight )
+ nY = (nScreenHeight) - nHeight;
+ if ( nX < 0 )
+ nX = 0;
+ if ( nY < 0 )
+ nY = 0;
+
+ // Restore-Position setzen
+ SWP aPlacement;
+ WinQueryWindowPos( mhWndFrame, &aPlacement );
+
+ // Status setzen
+ bVisible = WinIsWindowVisible( mhWndFrame);
+ BOOL bUpdateHiddenFramePos = FALSE;
+ if ( !bVisible )
+ {
+ aPlacement.fl = SWP_HIDE;
+
+ if ( mbOverwriteState )
+ {
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
+ {
+ if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
+ mnShowState = SWP_SHOWMINIMIZED;
+ else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
+ {
+ mnShowState = SWP_SHOWMAXIMIZED;
+ bUpdateHiddenFramePos = TRUE;
+ }
+ else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
+ mnShowState = SWP_SHOWNORMAL;
+ }
+ }
+ }
+ else
+ {
+ if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
+ {
+ if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
+ {
+ //if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
+ // aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
+ aPlacement.fl = SWP_SHOWMINIMIZED;
+ }
+ else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
+ aPlacement.fl = SWP_SHOWMAXIMIZED;
+ else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
+ aPlacement.fl = SWP_RESTORE;
+ }
+ }
+
+ // Wenn Fenster nicht minimiert/maximiert ist oder nicht optisch
+ // umgesetzt werden muss, dann SetWindowPos() benutzen, da
+ // SetWindowPlacement() die TaskBar mit einrechnet
+ if ( !(aPlacement.fl & SWP_MINIMIZE)
+ && !( aPlacement.fl & SWP_MAXIMIZE )
+ && (!bVisible || (aPlacement.fl == SWP_RESTORE)) )
+ {
+ if( bUpdateHiddenFramePos )
+ {
+ // #96084 set a useful internal window size because
+ // the window will not be maximized (and the size updated) before show()
+ SetMaximizedFrameGeometry( mhWndFrame, this );
+ }
+ else
+ WinSetWindowPos( mhWndFrame, 0, nX,
+ nScreenHeight - (nY+nHeight), nWidth, nHeight, nPosSize);
+ }
+ else
+ {
+ if( (nPosSize & (SWP_MOVE|SWP_SIZE)) )
+ {
+ aPlacement.x = nX;
+ aPlacement.y = nScreenHeight-(nY+nHeight);
+ aPlacement.cx = nWidth;
+ aPlacement.cy = nHeight;
+ }
+ WinSetWindowPos( mhWndFrame, 0, aPlacement.x, aPlacement.y,
+ aPlacement.cx, aPlacement.cy, aPlacement.fl );
+ }
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("Os2SalFrame::SetWindowState DONE\n");
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalFrame::GetWindowState( SalFrameState* pState )
+{
+ if ( maState.mnWidth && maState.mnHeight )
+ {
+ *pState = maState;
+ // #94144# allow Minimize again, should be masked out when read from configuration
+ // 91625 - Don't save minimize
+ //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
+ if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
+ pState->mnState |= SAL_FRAMESTATE_NORMAL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetScreenNumber( unsigned int nNewScreen )
+{
+#if 0
+ WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
+ if( pSys )
+ {
+ const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
+ pSys->getMonitors();
+ size_t nMon = rMonitors.size();
+ if( nNewScreen < nMon )
+ {
+ Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
+ Point aCurPos( maGeometry.nX, maGeometry.nY );
+ for( size_t i = 0; i < nMon; i++ )
+ {
+ if( rMonitors[i].m_aArea.IsInside( aCurPos ) )
+ {
+ aOldMonPos = rMonitors[i].m_aArea.TopLeft();
+ break;
+ }
+ }
+ mnDisplay = nNewScreen;
+ maGeometry.nScreenNumber = nNewScreen;
+ SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()),
+ aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()),
+ 0, 0,
+ SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
+ }
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+// native menu implementation - currently empty
+void Os2SalFrame::DrawMenuBar()
+{
+}
+
+void Os2SalFrame::SetMenu( SalMenu* pSalMenu )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay )
+{
+ if ( mbFullScreen == bFullScreen )
+ return;
+
+ mbFullScreen = bFullScreen;
+ if ( bFullScreen )
+ {
+ // save old position
+ memset( &maFullScreenRect, 0, sizeof( SWP ) );
+ _WinQueryWindowPos( this, &maFullScreenRect );
+
+ // set window to screen size
+ ImplSalFrameFullScreenPos( this, TRUE );
+ }
+ else
+ {
+ _WinSetWindowPos( this,
+ 0,
+ maFullScreenRect.x, maFullScreenRect.y,
+ maFullScreenRect.cx, maFullScreenRect.cy,
+ SWP_MOVE | SWP_SIZE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::StartPresentation( BOOL bStart )
+{
+ // SysSetObjectData("<WP_DESKTOP>","Autolockup=no"); oder OS2.INI: PM_Lockup
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetAlwaysOnTop( BOOL bOnTop )
+{
+ mbAllwayOnTop = bOnTop;
+#if 0
+ HWND hWnd;
+ if ( bOnTop )
+ hWnd = HWND_TOPMOST;
+ else
+ hWnd = HWND_NOTOPMOST;
+ SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
+#endif
+}
+
+
+// -----------------------------------------------------------------------
+
+static void ImplSalToTop( HWND hWnd, ULONG nFlags )
+{
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("ImplSalToTop hWnd %08x, nFlags %x\n", hWnd, nFlags);
+#endif
+
+ // if window is minimized, first restore it
+ SWP aSWP;
+ WinQueryWindowPos( hWnd, &aSWP );
+ if ( aSWP.fl & SWP_MINIMIZE )
+ WinSetWindowPos( hWnd, NULL, 0, 0, 0, 0, SWP_RESTORE );
+
+ if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
+ WinSetWindowPos( pFrame->mhWndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE | SWP_ZORDER);
+
+ if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
+ {
+ ULONG nStyle;
+ if ( pFrame->mbRestoreMaximize )
+ nStyle = SWP_MAXIMIZE;
+ else
+ nStyle = SWP_RESTORE;
+
+ WinSetWindowPos( pFrame->mhWndFrame, NULL, 0, 0, 0, 0, nStyle );
+ }
+ WinSetFocus( HWND_DESKTOP, pFrame->mhWndClient );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::ToTop( USHORT nFlags )
+{
+ nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS; // this flag is not needed on win32
+ // Post this Message to the window, because this only works
+ // in the thread of the window, which has create this window.
+ // We post this message to avoid deadlocks
+ if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
+ WinPostMsg( mhWndFrame, SAL_MSG_TOTOP, (MPARAM)nFlags, 0 );
+ else
+ ImplSalToTop( mhWndFrame, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetPointer( PointerStyle ePointerStyle )
+{
+ struct ImplPtrData
+ {
+ HPOINTER mhPointer;
+ ULONG mnSysId;
+ ULONG mnOwnId;
+ };
+
+ static ImplPtrData aImplPtrTab[POINTER_COUNT] =
+ {
+ { 0, SPTR_ARROW, 0 }, // POINTER_ARROW
+ { 0, 0, SAL_RESID_POINTER_NULL }, // POINTER_NULL
+ { 0, SPTR_WAIT, 0 }, // POINTER_WAIT
+ { 0, SPTR_TEXT, 0 }, // POINTER_BEAM
+ { 0, 0, SAL_RESID_POINTER_HELP }, // POINTER_HELP
+ { 0, 0, SAL_RESID_POINTER_CROSS }, // POINTER_CROSS
+ { 0, 0, SAL_RESID_POINTER_MOVE }, // POINTER_MOVE
+ { 0, SPTR_SIZENS, 0 }, // POINTER_NSIZE
+ { 0, SPTR_SIZENS, 0 }, // POINTER_SSIZE
+ { 0, SPTR_SIZEWE, 0 }, // POINTER_WSIZE
+ { 0, SPTR_SIZEWE, 0 }, // POINTER_ESIZE
+ { 0, SPTR_SIZENWSE, 0 }, // POINTER_NWSIZE
+ { 0, SPTR_SIZENESW, 0 }, // POINTER_NESIZE
+ { 0, SPTR_SIZENESW, 0 }, // POINTER_SWSIZE
+ { 0, SPTR_SIZENWSE, 0 }, // POINTER_SESIZE
+ { 0, SPTR_SIZENS, 0 }, // POINTER_WINDOW_NSIZE
+ { 0, SPTR_SIZENS, 0 }, // POINTER_WINDOW_SSIZE
+ { 0, SPTR_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE
+ { 0, SPTR_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE
+ { 0, SPTR_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE
+ { 0, SPTR_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE
+ { 0, SPTR_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE
+ { 0, SPTR_SIZENWSE, 0 }, // POINTER_WINDOW_SESIZE
+ { 0, 0, SAL_RESID_POINTER_HSPLIT }, // POINTER_HSPLIT
+ { 0, 0, SAL_RESID_POINTER_VSPLIT }, // POINTER_VSPLIT
+ { 0, 0, SAL_RESID_POINTER_HSIZEBAR }, // POINTER_HSIZEBAR
+ { 0, 0, SAL_RESID_POINTER_VSIZEBAR }, // POINTER_VSIZEBAR
+ { 0, 0, SAL_RESID_POINTER_HAND }, // POINTER_HAND
+ { 0, 0, SAL_RESID_POINTER_REFHAND }, // POINTER_REFHAND
+ { 0, 0, SAL_RESID_POINTER_PEN }, // POINTER_PEN
+ { 0, 0, SAL_RESID_POINTER_MAGNIFY }, // POINTER_MAGNIFY
+ { 0, 0, SAL_RESID_POINTER_FILL }, // POINTER_FILL
+ { 0, 0, SAL_RESID_POINTER_ROTATE }, // POINTER_ROTATE
+ { 0, 0, SAL_RESID_POINTER_HSHEAR }, // POINTER_HSHEAR
+ { 0, 0, SAL_RESID_POINTER_VSHEAR }, // POINTER_VSHEAR
+ { 0, 0, SAL_RESID_POINTER_MIRROR }, // POINTER_MIRROR
+ { 0, 0, SAL_RESID_POINTER_CROOK }, // POINTER_CROOK
+ { 0, 0, SAL_RESID_POINTER_CROP }, // POINTER_CROP
+ { 0, 0, SAL_RESID_POINTER_MOVEPOINT }, // POINTER_MOVEPOINT
+ { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT }, // POINTER_MOVEBEZIERWEIGHT
+ { 0, 0, SAL_RESID_POINTER_MOVEDATA }, // POINTER_MOVEDATA
+ { 0, 0, SAL_RESID_POINTER_COPYDATA }, // POINTER_COPYDATA
+ { 0, 0, SAL_RESID_POINTER_LINKDATA }, // POINTER_LINKDATA
+ { 0, 0, SAL_RESID_POINTER_MOVEDATALINK }, // POINTER_MOVEDATALINK
+ { 0, 0, SAL_RESID_POINTER_COPYDATALINK }, // POINTER_COPYDATALINK
+ { 0, 0, SAL_RESID_POINTER_MOVEFILE }, // POINTER_MOVEFILE
+ { 0, 0, SAL_RESID_POINTER_COPYFILE }, // POINTER_COPYFILE
+ { 0, 0, SAL_RESID_POINTER_LINKFILE }, // POINTER_LINKFILE
+ { 0, 0, SAL_RESID_POINTER_MOVEFILELINK }, // POINTER_MOVEFILELINK
+ { 0, 0, SAL_RESID_POINTER_COPYFILELINK }, // POINTER_COPYFILELINK
+ { 0, 0, SAL_RESID_POINTER_MOVEFILES }, // POINTER_MOVEFILES
+ { 0, 0, SAL_RESID_POINTER_COPYFILES }, // POINTER_COPYFILES
+ { 0, SPTR_ILLEGAL, 0 }, // POINTER_NOTALLOWED
+ { 0, 0, SAL_RESID_POINTER_DRAW_LINE }, // POINTER_DRAW_LINE
+ { 0, 0, SAL_RESID_POINTER_DRAW_RECT }, // POINTER_DRAW_RECT
+ { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON }, // POINTER_DRAW_POLYGON
+ { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER }, // POINTER_DRAW_BEZIER
+ { 0, 0, SAL_RESID_POINTER_DRAW_ARC }, // POINTER_DRAW_ARC
+ { 0, 0, SAL_RESID_POINTER_DRAW_PIE }, // POINTER_DRAW_PIE
+ { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT }, // POINTER_DRAW_CIRCLECUT
+ { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE }, // POINTER_DRAW_ELLIPSE
+ { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND }, // POINTER_DRAW_FREEHAND
+ { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT }, // POINTER_DRAW_CONNECT
+ { 0, 0, SAL_RESID_POINTER_DRAW_TEXT }, // POINTER_DRAW_TEXT
+ { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION }, // POINTER_DRAW_CAPTION
+ { 0, 0, SAL_RESID_POINTER_CHART }, // POINTER_CHART
+ { 0, 0, SAL_RESID_POINTER_DETECTIVE }, // POINTER_DETECTIVE
+ { 0, 0, SAL_RESID_POINTER_PIVOT_COL }, // POINTER_PIVOT_COL
+ { 0, 0, SAL_RESID_POINTER_PIVOT_ROW }, // POINTER_PIVOT_ROW
+ { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD }, // POINTER_PIVOT_FIELD
+ { 0, 0, SAL_RESID_POINTER_CHAIN }, // POINTER_CHAIN
+ { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED }, // POINTER_CHAIN_NOTALLOWED
+ { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE }, // POINTER_TIMEEVENT_MOVE
+ { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE }, // POINTER_TIMEEVENT_SIZE
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N }, // POINTER_AUTOSCROLL_N
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S }, // POINTER_AUTOSCROLL_S
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W }, // POINTER_AUTOSCROLL_W
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E }, // POINTER_AUTOSCROLL_E
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW }, // POINTER_AUTOSCROLL_NW
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE }, // POINTER_AUTOSCROLL_NE
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW }, // POINTER_AUTOSCROLL_SW
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE }, // POINTER_AUTOSCROLL_SE
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS }, // POINTER_AUTOSCROLL_NS
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE }, // POINTER_AUTOSCROLL_WE
+ { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE }, // POINTER_AUTOSCROLL_NSWE
+ { 0, 0, SAL_RESID_POINTER_AIRBRUSH }, // POINTER_AIRBRUSH
+ { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL }, // POINTER_TEXT_VERTICAL
+ { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE }, // POINTER_PIVOT_DELETE
+
+ // --> FME 2004-07-30 #i32329# Enhanced table selection
+ { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S }, // POINTER_TAB_SELECT_S
+ { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E }, // POINTER_TAB_SELECT_E
+ { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE }, // POINTER_TAB_SELECT_SE
+ { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W }, // POINTER_TAB_SELECT_W
+ { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW }, // POINTER_TAB_SELECT_SW
+ // <--
+
+ // --> FME 2004-08-16 #i20119# Paintbrush tool
+ { 0, 0, SAL_RESID_POINTER_PAINTBRUSH } // POINTER_PAINTBRUSH
+ // <--
+ };
+
+#if POINTER_COUNT != 94
+#error New Pointer must be defined!
+#endif
+
+ //debug_printf("Os2SalFrame::SetPointer\n");
+
+ // Mousepointer loaded ?
+ if ( !aImplPtrTab[ePointerStyle].mhPointer )
+ {
+ if ( aImplPtrTab[ePointerStyle].mnOwnId )
+ aImplPtrTab[ePointerStyle].mhPointer = ImplLoadSalCursor( (ULONG)aImplPtrTab[ePointerStyle].mnOwnId );
+ else
+ aImplPtrTab[ePointerStyle].mhPointer = WinQuerySysPointer( HWND_DESKTOP, aImplPtrTab[ePointerStyle].mnSysId, FALSE );
+ }
+ if (aImplPtrTab[ePointerStyle].mhPointer == 0) {
+ debug_printf( "SetPointer ePointerStyle %d unknown\n", ePointerStyle);
+ aImplPtrTab[ePointerStyle].mhPointer = SPTR_ICONERROR;
+ }
+
+ // Unterscheidet sich der Mauspointer, dann den neuen setzen
+ if ( mhPointer != aImplPtrTab[ePointerStyle].mhPointer )
+ {
+ mhPointer = aImplPtrTab[ePointerStyle].mhPointer;
+ WinSetPointer( HWND_DESKTOP, mhPointer );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::CaptureMouse( BOOL bCapture )
+{
+#if OSL_DEBUG_LEVEL>10
+ _bCapture=bCapture;
+ debug_printf("Os2SalFrame::CaptureMouse bCapture %d\n", bCapture);
+#endif
+ if ( bCapture )
+ WinSetCapture( HWND_DESKTOP, mhWndClient );
+ else
+ WinSetCapture( HWND_DESKTOP, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetPointerPos( long nX, long nY )
+{
+ POINTL aPt;
+ aPt.x = nX;
+ aPt.y = mnHeight - nY - 1; // convert sal coords to sys
+ WinMapWindowPoints( mhWndClient, HWND_DESKTOP, &aPt, 1 );
+ WinSetPointerPos( HWND_DESKTOP, aPt.x, aPt.y );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::Flush()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::Sync()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetInputContext( SalInputContext* pContext )
+{
+#ifdef ENABLE_IME
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ HWND hWnd = mhWndClient;
+ HIMI hIMI = 0;
+ pIMEData->mpGetIME( hWnd, &hIMI );
+ if ( hIMI )
+ {
+ ULONG nInputMode;
+ ULONG nConversionMode;
+ if ( 0 == pIMEData->mpQueryIMEMode( hIMI, &nInputMode, &nConversionMode ) )
+ {
+ if ( pContext->mnOptions & SAL_INPUTCONTEXT_TEXT )
+ {
+ nInputMode &= ~IMI_IM_IME_DISABLE;
+ if ( pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT_OFF )
+ nInputMode &= ~IMI_IM_IME_ON;
+// !!! Da derzeit ueber das OS2-IME-UI der IME-Mode nicht einschaltbar ist !!!
+// if ( SAL_INPUTCONTEXT_EXTTEXTINPUT_ON )
+ nInputMode |= IMI_IM_IME_ON;
+ }
+ else
+ nInputMode |= IMI_IM_IME_DISABLE;
+ pIMEData->mpSetIMEMode( hIMI, nInputMode, nConversionMode );
+ }
+
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+ }
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+#if 0
+void Os2SalFrame::UpdateExtTextInputArea()
+{
+#ifdef ENABLE_IME
+#endif
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::EndExtTextInput( USHORT nFlags )
+{
+#ifdef ENABLE_IME
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ HWND hWnd = mhWndClient;
+ HIMI hIMI = 0;
+ pIMEData->mpGetIME( hWnd, &hIMI );
+ if ( hIMI )
+ {
+ ULONG nIndex;
+ if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
+ nIndex = CNV_COMPLETE;
+ else
+ nIndex = CNV_CANCEL;
+
+ pIMEData->mpRequestIME( hIMI, REQ_CONVERSIONSTRING, nIndex, 0 );
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+ }
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+XubString Os2SalFrame::GetKeyName( USHORT nCode )
+{
+ if ( eImplKeyboardLanguage == LANGUAGE_DONTKNOW )
+ eImplKeyboardLanguage = MsLangId::getSystemLanguage();
+
+ XubString aKeyCode;
+ XubString aCode;
+ const sal_Unicode** pLangTab = ImplGetLangTab( eImplKeyboardLanguage );
+
+ if ( nCode & KEY_SHIFT )
+ aKeyCode = pLangTab[LSTR_KEY_SHIFT];
+
+ if ( nCode & KEY_MOD1 )
+ {
+ if ( aKeyCode.Len() == 0 )
+ aKeyCode = pLangTab[LSTR_KEY_CTRL];
+ else
+ {
+ aKeyCode += '+';
+ aKeyCode += pLangTab[LSTR_KEY_CTRL];
+ }
+ }
+
+ if ( nCode & KEY_MOD2 )
+ {
+ if ( aKeyCode.Len() == 0 )
+ aKeyCode = pLangTab[LSTR_KEY_ALT];
+ else
+ {
+ aKeyCode += '+';
+ aKeyCode += pLangTab[LSTR_KEY_ALT];
+ }
+ }
+
+ USHORT nKeyCode = nCode & 0x0FFF;
+ if ( (nKeyCode >= KEY_0) && (nKeyCode <= KEY_9) )
+ aCode = sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_0));
+ else if ( (nKeyCode >= KEY_A) && (nKeyCode <= KEY_Z) )
+ aCode = sal::static_int_cast<sal_Char>('A' + (nKeyCode - KEY_A));
+ else if ( (nKeyCode >= KEY_F1) && (nKeyCode <= KEY_F26) )
+ {
+ aCode += 'F';
+ if ( (nKeyCode >= KEY_F1) && (nKeyCode <= KEY_F9) )
+ {
+ aCode += sal::static_int_cast<sal_Char>('1' + (nKeyCode - KEY_F1));
+ }
+ else if ( (nKeyCode >= KEY_F10) && (nKeyCode <= KEY_F19) )
+ {
+ aCode += '1';
+ aCode += sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_F10));
+ }
+ else
+ {
+ aCode += '2';
+ aCode += sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_F20));
+ }
+ }
+ else
+ {
+ switch ( nKeyCode )
+ {
+ case KEY_DOWN:
+ aCode = pLangTab[LSTR_KEY_DOWN];
+ break;
+ case KEY_UP:
+ aCode = pLangTab[LSTR_KEY_UP];
+ break;
+ case KEY_LEFT:
+ aCode = pLangTab[LSTR_KEY_LEFT];
+ break;
+ case KEY_RIGHT:
+ aCode = pLangTab[LSTR_KEY_RIGHT];
+ break;
+ case KEY_HOME:
+ aCode = pLangTab[LSTR_KEY_HOME];
+ break;
+ case KEY_END:
+ aCode = pLangTab[LSTR_KEY_END];
+ break;
+ case KEY_PAGEUP:
+ aCode = pLangTab[LSTR_KEY_PAGEUP];
+ break;
+ case KEY_PAGEDOWN:
+ aCode = pLangTab[LSTR_KEY_PAGEDOWN];
+ break;
+ case KEY_RETURN:
+ aCode = pLangTab[LSTR_KEY_RETURN];
+ break;
+ case KEY_ESCAPE:
+ aCode = pLangTab[LSTR_KEY_ESC];
+ break;
+ case KEY_TAB:
+ aCode = pLangTab[LSTR_KEY_TAB];
+ break;
+ case KEY_BACKSPACE:
+ aCode = pLangTab[LSTR_KEY_BACKSPACE];
+ break;
+ case KEY_SPACE:
+ aCode = pLangTab[LSTR_KEY_SPACE];
+ break;
+ case KEY_INSERT:
+ aCode = pLangTab[LSTR_KEY_INSERT];
+ break;
+ case KEY_DELETE:
+ aCode = pLangTab[LSTR_KEY_DELETE];
+ break;
+
+ case KEY_ADD:
+ aCode += '+';
+ break;
+ case KEY_SUBTRACT:
+ aCode += '-';
+ break;
+ case KEY_MULTIPLY:
+ aCode += '*';
+ break;
+ case KEY_DIVIDE:
+ aCode += '/';
+ break;
+ case KEY_POINT:
+ aCode += '.';
+ break;
+ case KEY_COMMA:
+ aCode += ',';
+ break;
+ case KEY_LESS:
+ aCode += '<';
+ break;
+ case KEY_GREATER:
+ aCode += '>';
+ break;
+ case KEY_EQUAL:
+ aCode += '=';
+ break;
+ }
+ }
+
+ if ( aCode.Len() )
+ {
+ if ( aKeyCode.Len() == 0 )
+ aKeyCode = aCode;
+ else
+ {
+ aKeyCode += '+';
+ aKeyCode += aCode;
+ }
+ }
+
+ return aKeyCode;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Os2SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
+{
+ return GetKeyName( nKeyCode );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplOS2ColorToSal( long nOS2Color )
+{
+ return MAKE_SALCOLOR( (BYTE)( nOS2Color>>16), (BYTE)(nOS2Color>>8), (BYTE)nOS2Color );
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplMouseSysValueToSAL( int iSysValue, USHORT& rCode, USHORT& rClicks, BOOL& rDown )
+{
+ LONG lValue = WinQuerySysValue( HWND_DESKTOP, iSysValue );
+
+ rCode = 0;
+ rClicks = 1;
+ rDown = TRUE;
+
+ switch ( lValue & 0xFFFF )
+ {
+ case WM_BUTTON1UP:
+ case WM_BUTTON1CLICK:
+ rCode = MOUSE_LEFT;
+ rDown = FALSE;
+ break;
+ case WM_BUTTON1DOWN:
+ case WM_BUTTON1MOTIONSTART:
+ rCode = MOUSE_LEFT;
+ break;
+ case WM_BUTTON1DBLCLK:
+ rCode = MOUSE_LEFT;
+ rClicks = 2;
+ break;
+
+ case WM_BUTTON2UP:
+ case WM_BUTTON2CLICK:
+ rCode = MOUSE_RIGHT;
+ rDown = FALSE;
+ break;
+ case WM_BUTTON2DOWN:
+ case WM_BUTTON2MOTIONSTART:
+ rCode = MOUSE_RIGHT;
+ break;
+ case WM_BUTTON2DBLCLK:
+ rCode = MOUSE_RIGHT;
+ rClicks = 2;
+ break;
+
+ case WM_BUTTON3UP:
+ case WM_BUTTON3CLICK:
+ rCode = MOUSE_MIDDLE;
+ rDown = FALSE;
+ break;
+ case WM_BUTTON3DOWN:
+ case WM_BUTTON3MOTIONSTART:
+ rCode = MOUSE_MIDDLE;
+ break;
+ case WM_BUTTON3DBLCLK:
+ rCode = MOUSE_MIDDLE;
+ rClicks = 2;
+ break;
+ }
+
+ if ( !rCode )
+ return FALSE;
+
+ lValue = (lValue & 0xFFFF0000) >> 16;
+ if ( lValue != 0xFFFF )
+ {
+ if ( lValue & KC_SHIFT )
+ rCode |= KEY_SHIFT;
+ if ( lValue & KC_CTRL )
+ rCode |= KEY_MOD1;
+ if ( lValue & KC_ALT )
+ rCode |= KEY_MOD2;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplSalIsSameColor( const Color& rColor1, const Color& rColor2 )
+{
+ ULONG nWrong = 0;
+ nWrong += Abs( (short)rColor1.GetRed()-(short)rColor2.GetRed() );
+ nWrong += Abs( (short)rColor1.GetGreen()-(short)rColor2.GetGreen() );
+ nWrong += Abs( (short)rColor1.GetBlue()-(short)rColor2.GetBlue() );
+ return (nWrong < 30);
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplOS2NameFontToVCLFont( const char* pFontName, Font& rFont )
+{
+ char aNumBuf[10];
+ int nNumBufLen = 0;
+
+ while ( *pFontName && (*pFontName != '.') &&
+ (nNumBufLen < sizeof(aNumBuf)-1) )
+ {
+ aNumBuf[nNumBufLen] = *pFontName;
+ nNumBufLen++;
+ pFontName++;
+ }
+ aNumBuf[nNumBufLen] = '\0';
+
+ pFontName++;
+ while ( *pFontName == ' ' )
+ pFontName++;
+
+ int nFontHeight = atoi( aNumBuf );
+ int nFontNameLen = strlen( pFontName );
+ if ( nFontHeight && nFontNameLen )
+ {
+ rFont.SetFamily( FAMILY_DONTKNOW );
+ rFont.SetWeight( WEIGHT_NORMAL );
+ rFont.SetItalic( ITALIC_NONE );
+ // search for a style embedded in the name, e.g. 'WarpSans Bold'
+ // because we need to split the style from the family name
+ if (strstr( pFontName, " Bold")
+ || strstr( pFontName, " Italic")
+ || strstr( pFontName, "-Normal"))
+ {
+ char* fontName = strdup( pFontName);
+ char* style = strstr( fontName, " Bold");
+ if (style)
+ rFont.SetWeight( WEIGHT_BOLD );
+
+ if (!style)
+ style = strstr( fontName, " Italic");
+ if (style)
+ rFont.SetItalic( ITALIC_NORMAL );
+
+ if (!style)
+ style = strstr( fontName, "-Normal");
+ // store style, skip whitespace char
+ rFont.SetStyleName( ::rtl::OStringToOUString ( style+1, gsl_getSystemTextEncoding()) );
+ // truncate name
+ *style = 0;
+ // store family name
+ rFont.SetName( ::rtl::OStringToOUString ( fontName, gsl_getSystemTextEncoding()) );
+ free( fontName);
+ }
+ else
+ {
+ rFont.SetName( ::rtl::OStringToOUString (pFontName, gsl_getSystemTextEncoding()) );
+ rFont.SetStyleName( ::rtl::OStringToOUString ("", gsl_getSystemTextEncoding()) );
+ }
+
+ rFont.SetSize( Size( 0, nFontHeight ) );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::UpdateSettings( AllSettings& rSettings )
+{
+ static char aControlPanel[] = "PM_ControlPanel";
+ static char aSystemFonts[] = "PM_SystemFonts";
+ char aDummyStr[] = "";
+
+ // --- Mouse setting ---
+ USHORT nCode;
+ USHORT nClicks;
+ BOOL bDown;
+ MouseSettings aMouseSettings = rSettings.GetMouseSettings();
+ aMouseSettings.SetDoubleClickTime( WinQuerySysValue( HWND_DESKTOP, SV_DBLCLKTIME ) );
+ if ( ImplMouseSysValueToSAL( SV_BEGINDRAG, nCode, nClicks, bDown ) )
+ aMouseSettings.SetStartDragCode( nCode );
+ if ( ImplMouseSysValueToSAL( SV_CONTEXTMENU, nCode, nClicks, bDown ) )
+ {
+ aMouseSettings.SetContextMenuCode( nCode );
+ aMouseSettings.SetContextMenuClicks( nClicks );
+ aMouseSettings.SetContextMenuDown( bDown );
+ }
+ aMouseSettings.SetButtonStartRepeat( WinQuerySysValue( HWND_DESKTOP, SV_FIRSTSCROLLRATE ) );
+ aMouseSettings.SetButtonRepeat( WinQuerySysValue( HWND_DESKTOP, SV_SCROLLRATE ) );
+ rSettings.SetMouseSettings( aMouseSettings );
+
+ // --- Style settings ---
+ StyleSettings aStyleSettings = rSettings.GetStyleSettings();
+ BOOL bCompBorder = (aStyleSettings.GetOptions() & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE)) == 0;
+
+ // General settings
+ LONG nDisplayTime = PrfQueryProfileInt( HINI_PROFILE, (PSZ)aControlPanel, (PSZ)"LogoDisplayTime", -1 );
+ ULONG nSalDisplayTime;
+ if ( nDisplayTime < 0 )
+ nSalDisplayTime = LOGO_DISPLAYTIME_STARTTIME;
+ else if ( !nDisplayTime )
+ nSalDisplayTime = LOGO_DISPLAYTIME_NOLOGO;
+ else
+ nSalDisplayTime = (ULONG)nDisplayTime;
+ aStyleSettings.SetLogoDisplayTime( nSalDisplayTime );
+
+ aStyleSettings.SetCursorBlinkTime( WinQuerySysValue( HWND_DESKTOP, SV_CURSORRATE ) );
+ ULONG nDragFullOptions = aStyleSettings.GetDragFullOptions();
+ if ( WinQuerySysValue( HWND_DESKTOP, SV_DYNAMICDRAG ) )
+ nDragFullOptions |= DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
+ else
+ nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
+ aStyleSettings.SetDragFullOptions( nDragFullOptions );
+
+ // Size settings
+ aStyleSettings.SetScrollBarSize( WinQuerySysValue( HWND_DESKTOP, SV_CYHSCROLL ) );
+ if ( bCompBorder )
+ {
+ aStyleSettings.SetTitleHeight( WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) );
+ }
+
+ // Color settings
+ if ( bCompBorder )
+ {
+ aStyleSettings.SetFaceColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0 ) ) );
+ aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
+ aStyleSettings.SetLightColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0 ) ) );
+ aStyleSettings.SetLightBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0 ) ) );
+ aStyleSettings.SetShadowColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONDARK, 0 ) ) );
+ aStyleSettings.SetDarkShadowColor( Color( COL_BLACK ) );
+ aStyleSettings.SetDialogColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0 ) ) );
+ aStyleSettings.SetButtonTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
+ aStyleSettings.SetActiveColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVETITLE, 0 ) ) );
+ aStyleSettings.SetActiveTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVETITLETEXT, 0 ) ) );
+ aStyleSettings.SetActiveBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVEBORDER, 0 ) ) );
+ aStyleSettings.SetDeactiveColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVETITLE, 0 ) ) );
+ aStyleSettings.SetDeactiveTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVETITLETEXT, 0 ) ) );
+ aStyleSettings.SetDeactiveBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVEBORDER, 0 ) ) );
+ aStyleSettings.SetMenuColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENU, 0 ) ) );
+ aStyleSettings.SetMenuTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
+ aStyleSettings.SetMenuBarTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
+ }
+ aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
+ aStyleSettings.SetRadioCheckTextColor( aStyleSettings.GetButtonTextColor() );
+ aStyleSettings.SetGroupTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOWSTATICTEXT, 0 ) ) );
+ aStyleSettings.SetLabelTextColor( aStyleSettings.GetGroupTextColor() );
+ aStyleSettings.SetInfoTextColor( aStyleSettings.GetGroupTextColor() );
+ aStyleSettings.SetWindowColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOW, 0 ) ) );
+ aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
+ aStyleSettings.SetWindowTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOWTEXT, 0 ) ) );
+ aStyleSettings.SetFieldColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ENTRYFIELD, 0 ) ) );
+ aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
+ aStyleSettings.SetDisableColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUDISABLEDTEXT, 0 ) ) );
+ aStyleSettings.SetHighlightColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_HILITEBACKGROUND, 0 ) ) );
+ aStyleSettings.SetHighlightTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_HILITEFOREGROUND, 0 ) ) );
+ Color aMenuHighColor = ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUHILITEBGND, 0 ) );
+ if ( ImplSalIsSameColor( aMenuHighColor, aStyleSettings.GetMenuColor() ) )
+ {
+ if ( bCompBorder )
+ {
+ aStyleSettings.SetMenuHighlightColor( Color( COL_BLUE ) );
+ aStyleSettings.SetMenuHighlightTextColor( Color( COL_WHITE ) );
+ }
+ }
+ else
+ {
+ aStyleSettings.SetMenuHighlightColor( aMenuHighColor );
+ aStyleSettings.SetMenuHighlightTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUHILITE, 0 ) ) );
+ }
+ // Checked-Color berechnen
+ Color aColor1 = aStyleSettings.GetFaceColor();
+ Color aColor2 = aStyleSettings.GetLightColor();
+ BYTE nRed = (BYTE)(((USHORT)aColor1.GetRed() + (USHORT)aColor2.GetRed())/2);
+ BYTE nGreen = (BYTE)(((USHORT)aColor1.GetGreen() + (USHORT)aColor2.GetGreen())/2);
+ BYTE nBlue = (BYTE)(((USHORT)aColor1.GetBlue() + (USHORT)aColor2.GetBlue())/2);
+ aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
+
+ // Fonts updaten
+ Font aFont;
+ char aFontNameBuf[255];
+ aFont = aStyleSettings.GetMenuFont();
+ if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"Menus", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
+ {
+ if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) ) {
+#if 0
+ // Add Workplace Sans if not already listed
+ if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
+ {
+ XubString aFontName = aFont.GetName();
+ aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
+ aFont.SetName( aFontName );
+ aFont.SetSize( Size( 0, 9 ) );
+ }
+#endif
+ aStyleSettings.SetMenuFont( aFont );
+ }
+ }
+ aFont = aStyleSettings.GetIconFont();
+ if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"IconText", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
+ {
+ if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
+ aStyleSettings.SetIconFont( aFont );
+ }
+ aFont = aStyleSettings.GetTitleFont();
+ if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"WindowTitles", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
+ {
+ if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
+ {
+ // Add Workplace Sans if not already listed
+ if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
+ {
+ XubString aFontName = aFont.GetName();
+ aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
+ aFont.SetName( aFontName );
+ aFont.SetSize( Size( 0, 9 ) );
+ aFont.SetWeight( WEIGHT_BOLD );
+ aFont.SetItalic( ITALIC_NONE );
+ }
+ aStyleSettings.SetTitleFont( aFont );
+ aStyleSettings.SetFloatTitleFont( aFont );
+ }
+ }
+ aFont = aStyleSettings.GetAppFont();
+ if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"WindowText", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
+ {
+ if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
+ {
+ Font aHelpFont = aFont;
+ aHelpFont.SetName( (sal_Unicode*)L"Helv;WarpSans" );
+ aHelpFont.SetSize( Size( 0, 8 ) );
+ aHelpFont.SetWeight( WEIGHT_NORMAL );
+ aHelpFont.SetItalic( ITALIC_NONE );
+ aStyleSettings.SetHelpFont( aHelpFont );
+
+ // Add Workplace Sans if not already listed
+ if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
+ {
+ XubString aFontName = aFont.GetName();
+ aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
+ aFont.SetName( aFontName );
+ aFont.SetSize( Size( 0, 9 ) );
+ }
+ aStyleSettings.SetAppFont( aFont );
+ aStyleSettings.SetToolFont( aFont );
+ aStyleSettings.SetLabelFont( aFont );
+ aStyleSettings.SetInfoFont( aFont );
+ aStyleSettings.SetRadioCheckFont( aFont );
+ aStyleSettings.SetPushButtonFont( aFont );
+ aStyleSettings.SetFieldFont( aFont );
+ aStyleSettings.SetGroupFont( aFont );
+ }
+ }
+
+ rSettings.SetStyleSettings( aStyleSettings );
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* Os2SalFrame::SnapShot()
+{
+debug_printf("Os2SalFrame::SnapShot\n");
+return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+const SystemEnvData* Os2SalFrame::GetSystemData() const
+{
+ return &maSysData;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::Beep( SoundType eSoundType )
+{
+ static ULONG aImplSoundTab[5] =
+ {
+ WA_NOTE, // SOUND_DEFAULT
+ WA_NOTE, // SOUND_INFO
+ WA_WARNING, // SOUND_WARNING
+ WA_ERROR, // SOUND_ERROR
+ WA_NOTE // SOUND_QUERY
+ };
+
+#if 0
+#if SOUND_COUNT != 5
+#error New Sound must be defined!
+#endif
+#endif
+
+ debug_printf("Os2SalFrame::Beep %d\n", eSoundType);
+ WinAlarm( HWND_DESKTOP, aImplSoundTab[eSoundType] );
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame::SalPointerState Os2SalFrame::GetPointerState()
+{
+ SalPointerState aState;
+ aState.mnState = 0;
+
+ // MausModus feststellen und setzen
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON1 ) & 0x8000 )
+ aState.mnState |= MOUSE_LEFT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON2 ) & 0x8000 )
+ aState.mnState |= MOUSE_RIGHT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON3 ) & 0x8000 )
+ aState.mnState |= MOUSE_MIDDLE;
+ // Modifier-Tasten setzen
+ if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
+ aState.mnState |= KEY_SHIFT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
+ aState.mnState |= KEY_MOD1;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
+ aState.mnState |= KEY_MOD2;
+
+ POINTL pt;
+ _WinQueryPointerPos( HWND_DESKTOP, &pt );
+
+ aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
+ return aState;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::SetBackgroundBitmap( SalBitmap* )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SalTestMouseLeave()
+{
+ SalData* pSalData = GetSalData();
+
+ if ( pSalData->mhWantLeaveMsg && !::WinQueryCapture( HWND_DESKTOP ) )
+ {
+ POINTL aPt;
+ WinQueryPointerPos( HWND_DESKTOP, &aPt );
+ if ( pSalData->mhWantLeaveMsg != WinWindowFromPoint( HWND_DESKTOP, &aPt, TRUE ) )
+ WinSendMsg( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MPFROM2SHORT( aPt.x, aPt.y ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleMouseMsg( HWND hWnd,
+ UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
+{
+ SalMouseEvent aMouseEvt;
+ long nRet;
+ USHORT nEvent;
+ BOOL bCall = TRUE;
+ USHORT nFlags = SHORT2FROMMP( nMP2 );
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( !pFrame )
+ return 0;
+
+ aMouseEvt.mnX = (short)SHORT1FROMMP( nMP1 );
+ aMouseEvt.mnY = pFrame->mnHeight - (short)SHORT2FROMMP( nMP1 ) - 1;
+ aMouseEvt.mnCode = 0;
+ aMouseEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+
+ // MausModus feststellen und setzen
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON1 ) & 0x8000 )
+ aMouseEvt.mnCode |= MOUSE_LEFT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON2 ) & 0x8000 )
+ aMouseEvt.mnCode |= MOUSE_RIGHT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON3 ) & 0x8000 )
+ aMouseEvt.mnCode |= MOUSE_MIDDLE;
+ // Modifier-Tasten setzen
+ if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
+ aMouseEvt.mnCode |= KEY_SHIFT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
+ aMouseEvt.mnCode |= KEY_MOD1;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
+ aMouseEvt.mnCode |= KEY_MOD2;
+
+ switch ( nMsg )
+ {
+ case WM_MOUSEMOVE:
+ {
+ SalData* pSalData = GetSalData();
+
+ // Da bei Druecken von Modifier-Tasten die MouseEvents
+ // nicht zusammengefast werden (da diese durch KeyEvents
+ // unterbrochen werden), machen wir dieses hier selber
+ if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
+ {
+ QMSG aTempMsg;
+ if ( WinPeekMsg( pSalData->mhAB, &aTempMsg,
+ pFrame->mhWndClient,
+ WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE ) )
+ {
+ if ( (aTempMsg.msg == WM_MOUSEMOVE) &&
+ (aTempMsg.mp2 == nMP2) )
+ return 1;
+ }
+ }
+
+ // Test for MouseLeave
+ if ( pSalData->mhWantLeaveMsg &&
+ (pSalData->mhWantLeaveMsg != pFrame->mhWndClient) )
+ {
+ POINTL aMousePoint;
+ WinQueryMsgPos( pFrame->mhAB, &aMousePoint );
+ WinSendMsg( pSalData->mhWantLeaveMsg,
+ SAL_MSG_MOUSELEAVE,
+ 0, MPFROM2SHORT( aMousePoint.x, aMousePoint.y ) );
+ }
+ pSalData->mhWantLeaveMsg = pFrame->mhWndClient;
+ // Start MouseLeave-Timer
+ if ( !pSalData->mpMouseLeaveTimer )
+ {
+ pSalData->mpMouseLeaveTimer = new AutoTimer;
+ pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
+ pSalData->mpMouseLeaveTimer->Start();
+ // We dont need to set a timeout handler, because we test
+ // for mouseleave in the timeout callback
+ }
+ aMouseEvt.mnButton = 0;
+ nEvent = SALEVENT_MOUSEMOVE;
+ }
+ break;
+
+ case SAL_MSG_MOUSELEAVE:
+ {
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mhWantLeaveMsg == pFrame->mhWndClient )
+ {
+ pSalData->mhWantLeaveMsg = 0;
+ if ( pSalData->mpMouseLeaveTimer )
+ {
+ delete pSalData->mpMouseLeaveTimer;
+ pSalData->mpMouseLeaveTimer = NULL;
+ }
+
+ // Mouse-Coordinaates are relativ to the screen
+ POINTL aPt;
+ aPt.x = (short)SHORT1FROMMP( nMP2 );
+ aPt.y = (short)SHORT2FROMMP( nMP2 );
+ WinMapWindowPoints( HWND_DESKTOP, pFrame->mhWndClient, &aPt, 1 );
+ aPt.y = pFrame->mnHeight - aPt.y - 1;
+ aMouseEvt.mnX = aPt.x;
+ aMouseEvt.mnY = aPt.y;
+ aMouseEvt.mnButton = 0;
+ nEvent = SALEVENT_MOUSELEAVE;
+ }
+ else
+ bCall = FALSE;
+ }
+ break;
+
+ case WM_BUTTON1DBLCLK:
+ case WM_BUTTON1DOWN:
+ aMouseEvt.mnButton = MOUSE_LEFT;
+ nEvent = SALEVENT_MOUSEBUTTONDOWN;
+ break;
+
+ case WM_BUTTON2DBLCLK:
+ case WM_BUTTON2DOWN:
+ aMouseEvt.mnButton = MOUSE_RIGHT;
+ nEvent = SALEVENT_MOUSEBUTTONDOWN;
+ break;
+
+ case WM_BUTTON3DBLCLK:
+ case WM_BUTTON3DOWN:
+ aMouseEvt.mnButton = MOUSE_MIDDLE;
+ nEvent = SALEVENT_MOUSEBUTTONDOWN;
+ break;
+
+ case WM_BUTTON1UP:
+ aMouseEvt.mnButton = MOUSE_LEFT;
+ nEvent = SALEVENT_MOUSEBUTTONUP;
+ break;
+
+ case WM_BUTTON2UP:
+ aMouseEvt.mnButton = MOUSE_RIGHT;
+ nEvent = SALEVENT_MOUSEBUTTONUP;
+ break;
+
+ case WM_BUTTON3UP:
+ aMouseEvt.mnButton = MOUSE_MIDDLE;
+ nEvent = SALEVENT_MOUSEBUTTONUP;
+ break;
+ }
+
+ // check if this window was destroyed - this might happen if we are the help window
+ // and sent a mouse leave message to the application which killed the help window, ie ourself
+ if( !WinIsWindow( pFrame->mhAB, hWnd ) )
+ return 0;
+
+#if OSL_DEBUG_LEVEL>10
+ //if (_bCapture)
+ debug_printf("ImplHandleMouseMsg mouse %d,%d\n",aMouseEvt.mnX,aMouseEvt.mnY);
+#endif
+
+ if ( bCall )
+ {
+ if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
+ WinUpdateWindow( pFrame->mhWndClient );
+
+ // --- RTL --- (mirror mouse pos)
+ //if( Application::GetSettings().GetLayoutRTL() )
+ // aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
+
+ nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
+ if ( nMsg == WM_MOUSEMOVE )
+ {
+ WinSetPointer( HWND_DESKTOP, pFrame->mhPointer );
+ nRet = TRUE;
+ }
+ }
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
+{
+
+ ImplSalYieldMutexAcquireWithWait();
+
+ long nRet = 0;
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+
+ // Mouse-Coordinaates are relativ to the screen
+ POINTL aPt;
+ WinQueryMsgPos( pFrame->mhAB, &aPt );
+ WinMapWindowPoints( HWND_DESKTOP, pFrame->mhWndClient, &aPt, 1 );
+ aPt.y = pFrame->mnHeight - aPt.y - 1;
+
+ SalWheelMouseEvent aWheelEvt;
+ aWheelEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+ aWheelEvt.mnX = aPt.x;
+ aWheelEvt.mnY = aPt.y;
+ aWheelEvt.mnCode = 0;
+ bool bNeg = (SHORT2FROMMP(nMP2) == SB_LINEDOWN || SHORT2FROMMP(nMP2) == SB_PAGEDOWN );
+ aWheelEvt.mnDelta = bNeg ? -120 : 120;
+ aWheelEvt.mnNotchDelta = bNeg ? -1 : 1;
+ if (SHORT2FROMMP(nMP2) == SB_PAGEUP || SHORT2FROMMP(nMP2) == SB_PAGEDOWN)
+ aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
+ else
+ aWheelEvt.mnScrollLines = 1;
+
+ if( nMsg == WM_HSCROLL )
+ aWheelEvt.mbHorz = TRUE;
+
+ // Modifier-Tasten setzen
+ if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
+ aWheelEvt.mnCode |= KEY_SHIFT;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
+ aWheelEvt.mnCode |= KEY_MOD1;
+ if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
+ aWheelEvt.mnCode |= KEY_MOD2;
+
+ nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
+ }
+
+ ImplSalYieldMutexRelease();
+
+ return nRet;
+}
+
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplSalGetKeyCode( Os2SalFrame* pFrame, MPARAM aMP1, MPARAM aMP2 )
+{
+ USHORT nKeyFlags = SHORT1FROMMP( aMP1 );
+ UCHAR nCharCode = (UCHAR)SHORT1FROMMP( aMP2 );
+ USHORT nKeyCode = (UCHAR)SHORT2FROMMP( aMP2 );
+ UCHAR nScanCode = (UCHAR)CHAR4FROMMP( aMP1 );
+ USHORT rSVCode = 0;
+
+ // Ist virtueller KeyCode gesetzt und befindet sich der KeyCode in der
+ // Tabelle, dann mappen
+ if ( (nKeyFlags & KC_VIRTUALKEY) && (nKeyCode < KEY_TAB_SIZE) )
+ rSVCode = aImplTranslateKeyTab[nKeyCode];
+
+ // Wenn kein KeyCode ermittelt werden konnte, versuchen wir aus dem
+ // CharCode einen zu erzeugen
+ if ( !rSVCode && nCharCode )
+ {
+ // Bei 0-9, a-z und A-Z auch KeyCode setzen
+ if ( (nCharCode >= '0') && (nCharCode <= '9') && (!rSVCode || !(nKeyFlags & KC_SHIFT)) )
+ rSVCode = KEYGROUP_NUM + (nCharCode-'0');
+ else if ( (nCharCode >= 'a') && (nCharCode <= 'z') )
+ rSVCode = KEYGROUP_ALPHA + (nCharCode-'a');
+ else if ( (nCharCode >= 'A') && (nCharCode <= 'Z') )
+ rSVCode = KEYGROUP_ALPHA + (nCharCode-'A');
+ else
+ {
+ switch ( nCharCode )
+ {
+ case '+':
+ rSVCode = KEY_ADD;
+ break;
+ case '-':
+ rSVCode = KEY_SUBTRACT;
+ break;
+ case '*':
+ rSVCode = KEY_MULTIPLY;
+ break;
+ case '/':
+ rSVCode = KEY_DIVIDE;
+ break;
+ case '.':
+ rSVCode = KEY_POINT;
+ break;
+ case ',':
+ rSVCode = KEY_COMMA;
+ break;
+ case '<':
+ rSVCode = KEY_LESS;
+ break;
+ case '>':
+ rSVCode = KEY_GREATER;
+ break;
+ case '=':
+ rSVCode = KEY_EQUAL;
+ break;
+ }
+ }
+ }
+
+ // "Numlock-Hack": we want to get correct keycodes from the numpad
+ if ( (nCharCode >= '0') && (nCharCode <= '9') && !(nKeyFlags & KC_SHIFT) )
+ rSVCode = KEYGROUP_NUM + (nCharCode-'0');
+ if ( nCharCode == ',' )
+ rSVCode = KEY_COMMA;
+ if ( nCharCode == '.' )
+ rSVCode = KEY_POINT;
+
+ return rSVCode;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplUpdateInputLang( Os2SalFrame* pFrame )
+{
+ BOOL bLanguageChange = FALSE;
+ ULONG nLang = 0;
+ APIRET rc;
+ UconvObject uconv_object = NULL;
+ LocaleObject locale_object = NULL;
+ UniChar *pinfo_item;
+
+ // we do not support change of input language while working,
+ // so exit if already defined (mnInputLang is a static class field)
+ if (pFrame->mnInputLang)
+ return;
+
+ // get current locale
+ rc = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locale_object);
+ // get Win32 locale id and sublanguage (hex uni string)
+ rc = UniQueryLocaleItem(locale_object, LOCI_xWinLocale, &pinfo_item);
+ // convert uni string to integer
+ rc = UniStrtoul(locale_object, pinfo_item, &pinfo_item, 16, &nLang);
+ rc = UniFreeMem(pinfo_item);
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("ImplUpdateInputLang nLang %04x\n", nLang);
+ char char_buffer[256];
+ rc = UniCreateUconvObject((UniChar *)L"", &uconv_object);
+ rc = UniQueryLocaleItem(locale_object, LOCI_sKeyboard, &pinfo_item);
+ rc = UniStrFromUcs(uconv_object, char_buffer, pinfo_item, sizeof(char_buffer));
+ debug_printf("Keyboard name is: %s\n", char_buffer );
+ rc = UniFreeMem(pinfo_item);
+#endif
+ rc = UniFreeLocaleObject(locale_object);
+
+ // keep input lang up-to-date
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("ImplUpdateInputLang pFrame %08x lang changed from %d to %d\n",
+ pFrame, pFrame->mnInputLang, nLang);
+#endif
+ pFrame->mnInputLang = nLang;
+}
+
+
+static sal_Unicode ImplGetCharCode( Os2SalFrame* pFrame, USHORT nKeyFlags,
+ sal_Char nCharCode, UCHAR nScanCode )
+{
+ ImplUpdateInputLang( pFrame );
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("ImplGetCharCode nCharCode %c, %04x\n", nCharCode, nCharCode);
+#endif
+ return OUString( &nCharCode, 1, gsl_getSystemTextEncoding()).toChar();
+}
+
+// -----------------------------------------------------------------------
+
+LanguageType Os2SalFrame::GetInputLanguage()
+{
+ if( !mnInputLang )
+ ImplUpdateInputLang( this );
+
+ if( !mnInputLang )
+ return LANGUAGE_DONTKNOW;
+ else
+ return (LanguageType) mnInputLang;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Os2SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
+{
+ // not supported yet
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_Unicode ImplConvertKey( Os2SalFrame* pFrame, MPARAM aMP1, MPARAM aMP2 )
+{
+ USHORT nKeyFlags = SHORT1FROMMP( aMP1 );
+ UCHAR nCharCode = (UCHAR)SHORT1FROMMP( aMP2 );
+ USHORT nKeyCode = (UCHAR)SHORT2FROMMP( aMP2 );
+ UCHAR nScanCode = (UCHAR)CHAR4FROMMP( aMP1 );
+ sal_Unicode rSVCharCode = 0;
+
+ // Ist Character-Code gesetzt
+ // !!! Bei CTRL/ALT ist KC_CHAR nicht gesetzt, jedoch moechten wir
+ // !!! dann auch einen CharCode und machen die Behandlung deshalb
+ // !!! selber
+ if ( (nKeyFlags & KC_CHAR) || (nKeyFlags & KC_CTRL) || (nKeyFlags & KC_ALT) )
+ rSVCharCode = ImplGetCharCode( pFrame, nKeyFlags, nCharCode, nScanCode);
+
+ // ret unicode
+ return rSVCharCode;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleKeyMsg( HWND hWnd,
+ UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
+{
+ static USHORT nLastOS2KeyChar = 0;
+ static sal_Unicode nLastChar = 0;
+ USHORT nRepeat = CHAR3FROMMP( nMP1 ) - 1;
+ SHORT nFlags = SHORT1FROMMP( nMP1 );
+ USHORT nModCode = 0;
+ USHORT nSVCode = 0;
+ USHORT nOS2KeyCode = (UCHAR)SHORT2FROMMP( nMP2 );
+ sal_Unicode nSVCharCode = 0;
+ long nRet = 0;
+
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( !pFrame )
+ return 0;
+
+ // determine modifiers
+ if ( nFlags & KC_SHIFT )
+ nModCode |= KEY_SHIFT;
+ if ( nFlags & KC_CTRL )
+ nModCode |= KEY_MOD1;
+ if ( nFlags & KC_ALT )
+ nModCode |= KEY_MOD2;
+
+ // Bei Shift, Control und Alt schicken wir einen KeyModChange-Event
+ if ( (nOS2KeyCode == VK_SHIFT) || (nOS2KeyCode == VK_CTRL) ||
+ (nOS2KeyCode == VK_ALT) || (nOS2KeyCode == VK_ALTGRAF) )
+ {
+ SalKeyModEvent aModEvt;
+ aModEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+ aModEvt.mnCode = nModCode;
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("SALEVENT_KEYMODCHANGE\n");
+#endif
+ nRet = pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
+ }
+ else
+ {
+ nSVCode = ImplSalGetKeyCode( pFrame, nMP1, nMP2 );
+ nSVCharCode = ImplConvertKey( pFrame, nMP1, nMP2 );
+#if OSL_DEBUG_LEVEL>10
+ debug_printf("nSVCode %04x nSVCharCode %04x\n",nSVCode,nSVCharCode );
+#endif
+
+ // Fuer Java muessen wir bei KeyUp einen CharCode liefern
+ if ( nFlags & KC_KEYUP )
+ {
+ if ( !nSVCharCode )
+ {
+ if ( nLastOS2KeyChar == nOS2KeyCode )
+ {
+ nSVCharCode = nLastChar;
+ nLastOS2KeyChar = 0;
+ nLastChar = 0;
+ }
+ }
+ else
+ {
+ nLastOS2KeyChar = 0;
+ nLastChar = 0;
+ }
+ }
+ else
+ {
+ nLastOS2KeyChar = nOS2KeyCode;
+ nLastChar = nSVCharCode;
+ }
+
+ if ( nSVCode || nSVCharCode )
+ {
+ SalKeyEvent aKeyEvt;
+ aKeyEvt.mnCode = nSVCode;
+ aKeyEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+ aKeyEvt.mnCode |= nModCode;
+ aKeyEvt.mnCharCode = nSVCharCode;
+ aKeyEvt.mnRepeat = nRepeat;
+
+#if OSL_DEBUG_LEVEL>10
+ debug_printf( (nFlags & KC_KEYUP) ? "SALEVENT_KEYUP\n" : "SALEVENT_KEYINPUT\n");
+#endif
+ nRet = pFrame->CallCallback( (nFlags & KC_KEYUP) ? SALEVENT_KEYUP : SALEVENT_KEYINPUT,
+ &aKeyEvt );
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static bool ImplHandlePaintMsg( HWND hWnd )
+{
+ BOOL bMutex = FALSE;
+
+ if ( ImplSalYieldMutexTryToAcquire() )
+ bMutex = TRUE;
+
+ // if we don't get the mutex, we can also change the clip region,
+ // because other threads doesn't use the mutex from the main
+ // thread --> see GetGraphics()
+
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
+ // Paint-Region anliegt
+ if ( WinQueryUpdateRect( hWnd, NULL ) )
+ {
+ // Call BeginPaint/EndPaint to query the rect and send
+ // this Notofication to rect
+ HPS hPS;
+ RECTL aUpdateRect;
+ hPS = WinBeginPaint( hWnd, NULLHANDLE, &aUpdateRect );
+ WinEndPaint( hPS );
+
+ // Paint
+ if ( bMutex )
+ {
+ SalPaintEvent aPEvt( aUpdateRect.xLeft, pFrame->mnHeight - aUpdateRect.yTop, aUpdateRect.xRight- aUpdateRect.xLeft, aUpdateRect.yTop - aUpdateRect.yBottom );
+
+ pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
+ }
+ else
+ {
+ RECTL* pRect = new RECTL;
+ WinCopyRect( pFrame->mhAB, pRect, &aUpdateRect );
+ WinPostMsg( hWnd, SAL_MSG_POSTPAINT, (MPARAM)pRect, 0 );
+ }
+ }
+ }
+
+ if ( bMutex )
+ ImplSalYieldMutexRelease();
+
+ return bMutex ? true : false;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandlePaintMsg2( HWND hWnd, RECTL* pRect )
+{
+ // Paint
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ SalPaintEvent aPEvt( pRect->xLeft, pFrame->mnHeight - pRect->yTop, pRect->xRight - pRect->xLeft, pRect->yTop - pRect->yBottom );
+ pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
+ }
+ ImplSalYieldMutexRelease();
+ delete pRect;
+ }
+ else
+ WinPostMsg( hWnd, SAL_MSG_POSTPAINT, (MPARAM)pRect, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+static void SetMaximizedFrameGeometry( HWND hWnd, Os2SalFrame* pFrame )
+{
+ // calculate and set frame geometry of a maximized window - useful if the window is still hidden
+
+ RECTL aRect;
+ pFrame->GetWorkArea( aRect);
+
+ // a maximized window has no other borders than the caption
+ pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
+ pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) : 0;
+
+ aRect.yTop += pFrame->maGeometry.nTopDecoration;
+ pFrame->maGeometry.nX = aRect.xLeft;
+ pFrame->maGeometry.nY = aRect.yBottom;
+ pFrame->maGeometry.nWidth = aRect.xRight - aRect.xLeft + 1;
+ pFrame->maGeometry.nHeight = aRect.yBottom - aRect.yTop + 1;
+}
+
+static void UpdateFrameGeometry( HWND hWnd, Os2SalFrame* pFrame )
+{
+ if( !pFrame )
+ return;
+
+ //SalFrame has a
+ //maGeometry member that holds absolute screen positions (and needs to be
+ //updated if the window is moved by the way).
+
+ // reset data
+ memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
+
+ SWP swp;
+ LONG nFrameX, nFrameY, nCaptionY;
+
+ // get frame size
+ WinQueryWindowPos(pFrame->mhWndFrame, &swp);
+ if (swp.fl & SWP_MINIMIZE)
+ return;
+
+ // map from client area to screen
+ ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY);
+ pFrame->maGeometry.nTopDecoration = nFrameY + nCaptionY;
+ pFrame->maGeometry.nLeftDecoration = nFrameX;
+ pFrame->maGeometry.nRightDecoration = nFrameX;
+ pFrame->maGeometry.nBottomDecoration = nFrameY;
+
+ // position of client area, not of frame corner!
+ pFrame->maGeometry.nX = swp.x + nFrameX;
+ pFrame->maGeometry.nY = nScreenHeight - (swp.y + swp.cy) + nFrameY + nCaptionY;
+
+ int nWidth = swp.cx - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
+ int nHeight = swp.cy - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
+
+ // clamp to zero
+ pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
+ pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "UpdateFrameGeometry: hwnd %x, frame %x at %d,%d (%dx%d)\n",
+ hWnd, pFrame->mhWndFrame,
+ pFrame->maGeometry.nX, pFrame->maGeometry.nY,
+ pFrame->maGeometry.nWidth,pFrame->maGeometry.nHeight);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleMoveMsg( HWND hWnd)
+{
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ UpdateFrameGeometry( hWnd, pFrame );
+
+ if ( WinIsWindowVisible( hWnd ))
+ pFrame->mbDefPos = FALSE;
+
+ // Gegen moegliche Rekursionen sichern
+ if ( !pFrame->mbInMoveMsg )
+ {
+ // Fenster im FullScreenModus wieder einpassen
+ pFrame->mbInMoveMsg = TRUE;
+ if ( pFrame->mbFullScreen )
+ ImplSalFrameFullScreenPos( pFrame );
+ pFrame->mbInMoveMsg = FALSE;
+ }
+
+ // Status merken
+ ImplSaveFrameState( pFrame );
+
+ // Call Hdl
+ //#93851 if we call this handler, VCL floating windows are not updated correctly
+ //ImplCallMoveHdl( hWnd );
+
+ }
+
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSizeMsg( HWND hWnd, MPARAM nMP2 )
+{
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ UpdateFrameGeometry( hWnd, pFrame );
+ pFrame->mbDefPos = FALSE;
+ pFrame->mnWidth = (short)SHORT1FROMMP( nMP2 );
+ pFrame->mnHeight = (short)SHORT2FROMMP( nMP2 );
+ if ( pFrame->mpGraphics )
+ pFrame->mpGraphics->mnHeight = (int)SHORT2FROMMP(nMP2);
+ // Status merken
+ ImplSaveFrameState( pFrame );
+ pFrame->CallCallback( SALEVENT_RESIZE, 0 );
+ if ( WinIsWindowVisible( pFrame->mhWndFrame ) && !pFrame->mbInShow )
+ WinUpdateWindow( pFrame->mhWndClient );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleFocusMsg( Os2SalFrame* pFrame, MPARAM nMP2 )
+{
+if ( pFrame && !Os2SalFrame::mbInReparent )
+{
+ if ( SHORT1FROMMP( nMP2 ) )
+ {
+ if ( WinIsWindowVisible( pFrame->mhWndFrame ) && !pFrame->mbInShow )
+ WinUpdateWindow( pFrame->mhWndClient );
+ return pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
+ }
+ else
+ {
+ return pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
+ }
+}
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleCloseMsg( HWND hWnd )
+{
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ pFrame->CallCallback( SALEVENT_CLOSE, 0 );
+ }
+
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, WM_CLOSE, 0, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplHandleUserEvent( HWND hWnd, MPARAM nMP2 )
+{
+ ImplSalYieldMutexAcquireWithWait();
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+ if ( pFrame )
+ {
+ pFrame->CallCallback( SALEVENT_USEREVENT, (void*)nMP2 );
+ }
+ ImplSalYieldMutexRelease();
+}
+
+// -----------------------------------------------------------------------
+
+static int SalImplHandleProcessMenu( Os2SalFrame* pFrame, ULONG nMsg, MPARAM nMP1, MPARAM nMP2)
+{
+ long nRet = 0;
+debug_printf("SalImplHandleProcessMenu\n");
+#if 0
+ DWORD err=0;
+ if( !HIWORD(wParam) )
+ {
+ // Menu command
+ WORD nId = LOWORD(wParam);
+ if( nId ) // zero for separators
+ {
+ SalMenuEvent aMenuEvt;
+ aMenuEvt.mnId = nId;
+ WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
+ if( pSalMenuItem )
+ aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
+ else
+ aMenuEvt.mpMenu = NULL;
+
+ nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
+ }
+ }
+#endif
+ //return (nRet != 0);
+ return (nRet == 0);
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleInputLangChange( HWND hWnd )
+{
+ ImplSalYieldMutexAcquireWithWait();
+
+ // Feststellen, ob wir IME unterstuetzen
+ Os2SalFrame* pFrame = GetWindowPtr( hWnd );
+#if 0
+ if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
+ {
+ HWND hWnd = pFrame->mhWnd;
+ HKL hKL = (HKL)lParam;
+ UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
+
+ pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
+ pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
+ pFrame->mbHandleIME = !pFrame->mbSpezIME;
+ }
+#endif
+
+ // trigger input language and codepage update
+ UINT nLang = pFrame->mnInputLang;
+ ImplUpdateInputLang( pFrame );
+ debug_printf("ImplHandleInputLangChange new language 0x%04x\n",pFrame->mnInputLang);
+
+ // notify change
+ if( nLang != pFrame->mnInputLang )
+ pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );
+
+ ImplSalYieldMutexRelease();
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef ENABLE_IME
+
+static long ImplHandleIMEStartConversion( Os2SalFrame* pFrame )
+{
+ long nRet = FALSE;
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ HWND hWnd = pFrame->mhWndClient;
+ HIMI hIMI = 0;
+ pIMEData->mpGetIME( hWnd, &hIMI );
+ if ( hIMI )
+ {
+ ULONG nProp;
+ if ( 0 != pIMEData->mpQueryIMEProperty( hIMI, QIP_PROPERTY, &nProp ) )
+ pFrame->mbHandleIME = FALSE;
+ else
+ {
+ pFrame->mbHandleIME = !(nProp & PRP_SPECIALUI);
+
+ }
+ if ( pFrame->mbHandleIME )
+ {
+/* Windows-Code, der noch nicht angepasst wurde !!!
+ // Cursor-Position ermitteln und aus der die Default-Position fuer
+ // das Composition-Fenster berechnen
+ SalCursorPosEvent aCursorPosEvt;
+ pFrame->CallCallback( pFrame->mpInst, pFrame,
+ SALEVENT_CURSORPOS, (void*)&aCursorPosEvt );
+ COMPOSITIONFORM aForm;
+ memset( &aForm, 0, sizeof( aForm ) );
+ if ( !aCursorPosEvt.mnWidth || !aCursorPosEvt.mnHeight )
+ aForm.dwStyle |= CFS_DEFAULT;
+ else
+ {
+ aForm.dwStyle |= CFS_POINT;
+ aForm.ptCurrentPos.x = aCursorPosEvt.mnX;
+ aForm.ptCurrentPos.y = aCursorPosEvt.mnY;
+ }
+ ImmSetCompositionWindow( hIMC, &aForm );
+
+ // Den InputContect-Font ermitteln und diesem dem Composition-Fenster
+ // bekannt machen
+*/
+
+ pFrame->mbConversionMode = TRUE;
+ pFrame->CallCallback( SALEVENT_STARTEXTTEXTINPUT, (void*)NULL );
+ nRet = TRUE;
+ }
+
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleIMEConversion( Os2SalFrame* pFrame, MPARAM nMP2Param )
+{
+ long nRet = FALSE;
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ HWND hWnd = pFrame->mhWndClient;
+ HIMI hIMI = 0;
+ ULONG nMP2 = (ULONG)nMP2Param;
+ pIMEData->mpGetIME( hWnd, &hIMI );
+ if ( hIMI )
+ {
+ if ( nMP2 & (IMR_RESULT_RESULTSTRING |
+ IMR_CONV_CONVERSIONSTRING | IMR_CONV_CONVERSIONATTR |
+ IMR_CONV_CURSORPOS | IMR_CONV_CURSORATTR) )
+ {
+ SalExtTextInputEvent aEvt;
+ aEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+ aEvt.mpTextAttr = NULL;
+ aEvt.mnCursorPos = 0;
+ aEvt.mnDeltaStart = 0;
+ aEvt.mbOnlyCursor = FALSE;
+ aEvt.mbCursorVisible = TRUE;
+
+ ULONG nBufLen = 0;
+ xub_Unicode* pBuf = NULL;
+ ULONG nAttrBufLen = 0;
+ PM_BYTE* pAttrBuf = NULL;
+ BOOL bLastCursor = FALSE;
+ if ( nMP2 & IMR_RESULT_RESULTSTRING )
+ {
+ pIMEData->mpGetResultString( hIMI, IMR_RESULT_RESULTSTRING, 0, &nBufLen );
+ if ( nBufLen > 0 )
+ {
+ pBuf = new xub_Unicode[nBufLen];
+ pIMEData->mpGetResultString( hIMI, IMR_RESULT_RESULTSTRING, pBuf, &nBufLen );
+ }
+
+ bLastCursor = TRUE;
+ aEvt.mbCursorVisible = TRUE;
+ }
+ else if ( nMP2 & (IMR_CONV_CONVERSIONSTRING | IMR_CONV_CONVERSIONATTR |
+ IMR_CONV_CURSORPOS | IMR_CONV_CURSORATTR) )
+ {
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, 0, &nBufLen );
+ if ( nBufLen > 0 )
+ {
+ pBuf = new xub_Unicode[nBufLen];
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, pBuf, &nBufLen );
+ }
+
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONATTR, 0, &nAttrBufLen );
+ if ( nAttrBufLen > 0 )
+ {
+ pAttrBuf = new PM_BYTE[nAttrBufLen];
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONATTR, pAttrBuf, &nAttrBufLen );
+ }
+
+/* !!! Wir bekommen derzeit nur falsche Daten, deshalb zeigen wir derzeit
+ !!! auch keine Cursor an
+ ULONG nTempBufLen;
+ ULONG nCursorPos = 0;
+ ULONG nCursorAttr = 0;
+ ULONG nChangePos = 0;
+ nTempBufLen = sizeof( ULONG );
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORPOS, &nCursorPos, &nTempBufLen );
+ nTempBufLen = sizeof( ULONG );
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORATTR, &nCursorAttr, &nTempBufLen );
+ nTempBufLen = sizeof( ULONG );
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CHANGESTART, &nChangePos, &nTempBufLen );
+
+ aEvt.mnCursorPos = nCursorPos;
+ aEvt.mnDeltaStart = nChangePos;
+ if ( nCursorAttr & CP_CURSORATTR_INVISIBLE )
+ aEvt.mbCursorVisible = FALSE;
+*/
+ aEvt.mnCursorPos = 0;
+ aEvt.mnDeltaStart = 0;
+ aEvt.mbCursorVisible = FALSE;
+
+ if ( (nMP2 == IMR_CONV_CURSORPOS) ||
+ (nMP2 == IMR_CONV_CURSORATTR) )
+ aEvt.mbOnlyCursor = TRUE;
+ }
+
+ USHORT* pSalAttrAry = NULL;
+ if ( pBuf )
+ {
+ aEvt.maText = XubString( pBuf, (USHORT)nBufLen );
+ delete [] pBuf;
+ if ( pAttrBuf )
+ {
+ USHORT nTextLen = aEvt.maText.Len();
+ if ( nTextLen )
+ {
+ pSalAttrAry = new USHORT[nTextLen];
+ memset( pSalAttrAry, 0, nTextLen*sizeof( USHORT ) );
+ for ( USHORT i = 0; (i < nTextLen) && (i < nAttrBufLen); i++ )
+ {
+ PM_BYTE nOS2Attr = pAttrBuf[i];
+ USHORT nSalAttr;
+ if ( nOS2Attr == CP_ATTR_TARGET_CONVERTED )
+ nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETCONVERTED | SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
+ else if ( nOS2Attr == CP_ATTR_CONVERTED )
+ nSalAttr = SAL_EXTTEXTINPUT_ATTR_CONVERTED | SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
+ else if ( nOS2Attr == CP_ATTR_TARGET_NOTCONVERTED )
+ nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETNOTCONVERTED | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
+ else if ( nOS2Attr == CP_ATTR_INPUT_ERROR )
+ nSalAttr = SAL_EXTTEXTINPUT_ATTR_INPUTERROR | SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
+ else /* ( nOS2Attr == CP_ATTR_INPUT ) */
+ nSalAttr = SAL_EXTTEXTINPUT_ATTR_INPUT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
+ pSalAttrAry[i] = nSalAttr;
+ }
+ aEvt.mpTextAttr = pSalAttrAry;
+ }
+ delete [] pAttrBuf;
+ }
+ if ( bLastCursor )
+ aEvt.mnCursorPos = aEvt.maText.Len();
+ }
+
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+
+ // Handler rufen und wenn wir ein Attribute-Array haben, danach
+ // wieder zerstoeren
+ pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
+ if ( pSalAttrAry )
+ delete [] pSalAttrAry;
+ }
+ else
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+ }
+
+ nRet = TRUE;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleIMEEndConversion( Os2SalFrame* pFrame )
+{
+ pFrame->mbConversionMode = FALSE;
+ pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleIMEOpenCandidate( Os2SalFrame* pFrame )
+{
+ pFrame->mbCandidateMode = TRUE;
+
+ long nRet = FALSE;
+ SalIMEData* pIMEData = GetSalIMEData();
+ if ( pIMEData )
+ {
+ HWND hWnd = pFrame->mhWndClient;
+ HIMI hIMI = 0;
+ pIMEData->mpGetIME( hWnd, &hIMI );
+ if ( hIMI )
+ {
+ ULONG nBufLen = 0;
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, 0, &nBufLen );
+ if ( nBufLen > 0 )
+ {
+/* !!! Wir bekommen derzeit nur falsche Daten steht der Cursor immer bei 0
+ ULONG nTempBufLen = sizeof( ULONG );
+ ULONG nCursorPos = 0;
+ pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORPOS, &nCursorPos, &nTempBufLen );
+*/
+ ULONG nCursorPos = 0;
+
+ SalExtTextInputPosEvent aEvt;
+ aEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
+ aEvt.mnFirstPos = nCursorPos;
+ aEvt.mnChars = nBufLen-nCursorPos;
+ aEvt.mpPosAry = new SalExtCharPos[aEvt.mnChars];
+ memset( aEvt.mpPosAry, 0, aEvt.mnChars*sizeof(SalExtCharPos) );
+
+ pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aEvt );
+
+ long nMinLeft = aEvt.mpPosAry[0].mnX;
+ long nMinTop = aEvt.mpPosAry[0].mnY;
+ long nMaxBottom = aEvt.mpPosAry[0].mnY+aEvt.mpPosAry[0].mnHeight;
+ long nMaxRight = nMinLeft;
+ USHORT i = 0;
+ while ( i < aEvt.mnChars )
+ {
+ // Solange wir uns auf der gleichen Zeile bewegen,
+ // ermitteln wir die Rechteck-Grenzen
+ if ( !aEvt.mpPosAry[i].mnHeight ||
+ (aEvt.mpPosAry[i].mnY < nMaxBottom-1) )
+ {
+ if ( aEvt.mpPosAry[i].mnX < nMinLeft )
+ nMinLeft = aEvt.mpPosAry[i].mnX;
+ if ( aEvt.mpPosAry[i].mnX+aEvt.mpPosAry[0].mnWidth > nMaxRight )
+ nMaxRight = aEvt.mpPosAry[i].mnX+aEvt.mpPosAry[0].mnWidth;
+ if ( aEvt.mpPosAry[i].mnY < nMinTop )
+ nMinTop = aEvt.mpPosAry[i].mnY;
+ i++;
+ }
+ else
+ break;
+ }
+
+ CANDIDATEPOS aForm;
+ aForm.ulIndex = 0;
+ aForm.ulStyle = CPS_EXCLUDE;
+ aForm.ptCurrentPos.x = aEvt.mpPosAry[0].mnX;
+ aForm.ptCurrentPos.y = pFrame->mnHeight - (nMaxBottom+1) - 1;
+ aForm.rcArea.xLeft = nMinLeft;
+ aForm.rcArea.yBottom = pFrame->mnHeight - nMaxBottom - 1;
+ aForm.rcArea.xRight = nMaxRight+1;
+ aForm.rcArea.yTop = pFrame->mnHeight - nMinTop - 1;
+ pIMEData->mpSetCandidateWin( hIMI, &aForm );
+
+ delete aEvt.mpPosAry;
+ }
+
+ pIMEData->mpReleaseIME( hWnd, hIMI );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplHandleIMECloseCandidate( Os2SalFrame* pFrame )
+{
+ pFrame->mbCandidateMode = FALSE;
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalFrameWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( hWnd );
+ MRESULT nRet = (MRESULT)0;
+ BOOL bDef = TRUE;
+ bool bCheckTimers= false;
+
+#if OSL_DEBUG_LEVEL>10
+ if (nMsg!=WM_TIMER && nMsg!=WM_MOUSEMOVE)
+ debug_printf( "SalFrameWndProc hWnd 0x%x nMsg 0x%x\n", hWnd, nMsg);
+#endif
+
+ switch( nMsg )
+ {
+ case WM_MOUSEMOVE:
+ case WM_BUTTON1DOWN:
+ case WM_BUTTON2DOWN:
+ case WM_BUTTON3DOWN:
+ case WM_BUTTON1DBLCLK:
+ case WM_BUTTON2DBLCLK:
+ case WM_BUTTON3DBLCLK:
+ case WM_BUTTON1UP:
+ case WM_BUTTON2UP:
+ case WM_BUTTON3UP:
+ case SAL_MSG_MOUSELEAVE:
+ // ButtonUp/Down nie an die WinDefWindowProc weiterleiten, weil sonst
+ // die Message an den Owner weitergeleitet wird
+ ImplSalYieldMutexAcquireWithWait();
+ bDef = !ImplHandleMouseMsg( hWnd, nMsg, nMP1, nMP2 );
+ ImplSalYieldMutexRelease();
+ break;
+
+ case WM_CHAR:
+ if ( pFrame->mbConversionMode )
+ bDef = FALSE;
+ else
+ bDef = !ImplHandleKeyMsg( hWnd, nMsg, nMP1, nMP2 );
+ break;
+
+ case WM_ERASEBACKGROUND:
+ nRet = (MRESULT)FALSE;
+ bDef = FALSE;
+ break;
+
+ case WM_PAINT:
+ bCheckTimers = ImplHandlePaintMsg( hWnd );
+ bDef = FALSE;
+ break;
+ case SAL_MSG_POSTPAINT:
+ ImplHandlePaintMsg2( hWnd, (RECTL*)nMP1 );
+ bCheckTimers = true;
+ bDef = FALSE;
+ break;
+
+ case WM_MOVE:
+ case SAL_MSG_POSTMOVE:
+ ImplHandleMoveMsg( hWnd );
+ bDef = FALSE;
+ break;
+
+ case WM_SIZE:
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ ImplHandleSizeMsg( hWnd, nMP2 );
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SAL_MSG_POSTSIZE, nMP1, nMP2 );
+ break;
+ case SAL_MSG_POSTSIZE:
+ ImplHandleSizeMsg( hWnd, nMP2 );
+ break;
+ case WM_MINMAXFRAME:
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ PSWP pswp = (PSWP) nMP1;
+ ImplHandleSizeMsg( hWnd, MPFROM2SHORT( pswp->cx, pswp->cy) );
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SAL_MSG_POSTSIZE, 0, nMP2 );
+ break;
+
+ case WM_CALCVALIDRECTS:
+ return (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
+
+ case WM_SETFOCUS:
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ ImplHandleFocusMsg( pFrame, nMP2 );
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SAL_MSG_POSTFOCUS, 0, nMP2 );
+ break;
+ case SAL_MSG_POSTFOCUS:
+ ImplHandleFocusMsg( pFrame, nMP2 );
+ break;
+
+ case WM_TRANSLATEACCEL:
+ {
+ // Da uns OS/2 zu viele Tasten abfaegnt, unternehmen wir etwas,
+ // damit wir Shift+F1, Shift+F10 und Shift+Enter bekommen
+ PQMSG pMsg = (PQMSG)nMP1;
+ USHORT nKeyFlags = SHORT1FROMMP( pMsg->mp1 );
+ USHORT nKeyCode = (UCHAR)SHORT2FROMMP( pMsg->mp2 );
+
+ if ( !(nKeyFlags & KC_KEYUP) && (nKeyFlags & KC_VIRTUALKEY) &&
+ (nKeyFlags & KC_SHIFT) && (nKeyCode != VK_ESC) )
+ return (MRESULT)FALSE;
+
+ if ( nKeyCode == VK_F1 )
+ return (MRESULT)FALSE;
+ }
+ break;
+
+ case WM_CREATE:
+ {
+ HWND hWndFrame = WinQueryWindow(hWnd, QW_PARENT);
+ if (hWndFrame == 0)
+ debug_printf(" WARNING NULL FRAME!!\n");
+ SalData* pSalData = GetSalData();
+ // Window-Instanz am Windowhandle speichern
+ pFrame = pSalData->mpCreateFrame;
+ pSalData->mpCreateFrame = NULL;
+ SetWindowPtr( hWnd, pFrame );
+ SetWindowPtr( hWndFrame, pFrame);
+ // HWND schon hier setzen, da schon auf den Instanzdaten
+ // gearbeitet werden kann, wenn Messages waehrend
+ // CreateWindow() gesendet werden
+ pFrame->mhWndClient = hWnd;
+ pFrame->mhWndFrame = hWndFrame;
+ pFrame->maSysData.hWnd = hWnd;
+ }
+ break;
+
+ case WM_CLOSE:
+ ImplHandleCloseMsg( hWnd );
+ bDef = FALSE;
+ break;
+
+ case WM_SYSVALUECHANGED:
+ if ( pFrame->mbFullScreen )
+ ImplSalFrameFullScreenPos( pFrame );
+ // kein break, da der Rest auch noch verarbeitet werden soll
+ case PL_ALTERED:
+ case WM_SYSCOLORCHANGE:
+ ImplSalYieldMutexAcquire();
+ pFrame->CallCallback( SALEVENT_SETTINGSCHANGED, 0 );
+ ImplSalYieldMutexRelease();
+ break;
+
+ case SAL_MSG_USEREVENT:
+ ImplHandleUserEvent( hWnd, nMP2 );
+ bDef = FALSE;
+ break;
+ case SAL_MSG_TOTOP:
+ ImplSalToTop( hWnd, (ULONG)nMP1 );
+ bDef = FALSE;
+ break;
+ case SAL_MSG_SHOW:
+ ImplSalShow( hWnd, (ULONG)nMP1, (ULONG)nMP2 );
+ bDef = FALSE;
+ break;
+
+ case WM_KBDLAYERCHANGED:
+ debug_printf("hWnd 0x%08x WM_KBDLAYERCHANGED\n", hWnd);
+ ImplHandleInputLangChange( hWnd );
+ break;
+
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ ImplHandleWheelMsg( hWnd, nMsg, nMP1, nMP2 );
+ bDef = FALSE;
+ break;
+
+ case WM_COMMAND:
+ case SAL_MSG_SYSPROCESSMENU:
+ if ( SalImplHandleProcessMenu( pFrame, nMsg, nMP1, nMP2 ) )
+ {
+ bDef = FALSE;
+ nRet = (MRESULT)1;
+ }
+ break;
+
+#ifdef ENABLE_IME
+ case WM_IMEREQUEST:
+ if ( (ULONG)nMP1 == IMR_CONVRESULT )
+ {
+ if ( pFrame->mbHandleIME )
+ {
+ // Nur im Conversionmodus akzeptieren wir den IME-Input
+ if ( pFrame->mbConversionMode )
+ {
+ ImplSalYieldMutexAcquire();
+ if ( ImplHandleIMEConversion( pFrame, nMP2 ) )
+ {
+ bDef = FALSE;
+ nRet = (MRESULT)TRUE;
+ }
+ ImplSalYieldMutexRelease();
+ }
+ }
+ }
+ else if ( (ULONG)nMP1 == IMR_CANDIDATE )
+ {
+ if ( pFrame->mbHandleIME )
+ {
+ ImplSalYieldMutexAcquire();
+ if ( (ULONG)nMP2 & IMR_CANDIDATE_SHOW )
+ ImplHandleIMEOpenCandidate( pFrame );
+ else if ( (ULONG)nMP2 & IMR_CANDIDATE_HIDE )
+ ImplHandleIMECloseCandidate( pFrame );
+ ImplSalYieldMutexRelease();
+ }
+ }
+ break;
+
+ case WM_IMENOTIFY:
+ if ( (ULONG)nMP1 == IMN_STARTCONVERSION )
+ {
+ ImplSalYieldMutexAcquire();
+ if ( ImplHandleIMEStartConversion( pFrame ) )
+ {
+ bDef = FALSE;
+ nRet = (MRESULT)TRUE;
+ }
+ ImplSalYieldMutexRelease();
+ }
+ else if ( (ULONG)nMP1 == IMN_ENDCONVERSION )
+ {
+ if ( pFrame->mbHandleIME )
+ {
+ ImplSalYieldMutexAcquire();
+ if ( ImplHandleIMEEndConversion( pFrame ) )
+ {
+ bDef = FALSE;
+ nRet = (MRESULT)TRUE;
+ }
+ ImplSalYieldMutexRelease();
+ }
+ }
+ break;
+#endif
+ }
+
+ if( bCheckTimers )
+ {
+ SalData* pSalData = GetSalData();
+ if( pSalData->mnNextTimerTime )
+ {
+ ULONG nCurTime;
+ DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PVOID)&nCurTime, sizeof(ULONG));
+ if( pSalData->mnNextTimerTime < nCurTime )
+ {
+ QMSG aMsg;
+ if (!WinPeekMsg( pFrame->mhAB, &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE ) )
+ WinPostMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, (MPARAM)nCurTime );
+ }
+ }
+ }
+
+ if ( bDef )
+ nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalFrame::ResetClipRegion()
+{
+}
+
+void Os2SalFrame::BeginSetClipRegion( ULONG )
+{
+}
+
+void Os2SalFrame::UnionClipRegion( long, long, long, long )
+{
+}
+
+void Os2SalFrame::EndSetClipRegion()
+{
+}
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalFrameSubClassWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ MRESULT mReturn = 0L;
+
+ // ticket#124 min size of 132 px is too much
+ if (nMsg == WM_QUERYTRACKINFO) {
+ PTRACKINFO pti;
+ // first, let PM initialize TRACKINFO
+ mReturn = aSalShlData.mpFrameProc( hWnd, nMsg, nMP1, nMP2 );
+ // now change default min size
+ pti = (PTRACKINFO) nMP2;
+ pti->ptlMinTrackSize.x = 64L;
+ // now return to PM
+ return mReturn;
+ }
+
+ return aSalShlData.mpFrameProc( hWnd, nMsg, nMP1, nMP2 );
+}
+
+// -----------------------------------------------------------------------
diff --git a/vcl/os2/source/window/salmenu.cxx b/vcl/os2/source/window/salmenu.cxx
new file mode 100644
index 000000000000..339ab5dbfadb
--- /dev/null
+++ b/vcl/os2/source/window/salmenu.cxx
@@ -0,0 +1,132 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_DOS
+#define INCL_PM
+#define INCL_WIN
+#include <svpm.h>
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salmenu.h>
+
+
+// =======================================================================
+
+// Os2SalInst factory methods
+
+SalMenu* Os2SalInstance::CreateMenu( BOOL bMenuBar )
+{
+ return NULL; // no support for native menues
+}
+
+void Os2SalInstance::DestroyMenu( SalMenu* pSalMenu )
+{
+ delete pSalMenu;
+}
+
+
+SalMenuItem* Os2SalInstance::CreateMenuItem( const SalItemParams* pItemData )
+{
+ return NULL; // no support for native menues
+}
+
+void Os2SalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem )
+{
+ delete pSalMenuItem;
+}
+
+
+// =======================================================================
+
+
+/*
+ * Os2SalMenu
+ */
+
+
+Os2SalMenu::~Os2SalMenu()
+{
+}
+
+BOOL Os2SalMenu::VisibleMenuBar()
+{
+ return FALSE;
+}
+
+void Os2SalMenu::SetFrame( const SalFrame *pFrame )
+{
+}
+
+void Os2SalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
+{
+}
+
+void Os2SalMenu::RemoveItem( unsigned nPos )
+{
+}
+
+void Os2SalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
+{
+}
+
+void Os2SalMenu::CheckItem( unsigned nPos, BOOL bCheck )
+{
+}
+
+void Os2SalMenu::EnableItem( unsigned nPos, BOOL bEnable )
+{
+}
+
+void Os2SalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage )
+{
+}
+
+void Os2SalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText )
+{
+}
+
+void Os2SalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& rKeyName )
+{
+}
+
+void Os2SalMenu::GetSystemMenuData( SystemMenuData* pData )
+{
+}
+
+// =======================================================================
+
+/*
+ * SalMenuItem
+ */
+
+
+Os2SalMenuItem::~Os2SalMenuItem()
+{
+}
+
+// -------------------------------------------------------------------
+
diff --git a/vcl/os2/source/window/salobj.cxx b/vcl/os2/source/window/salobj.cxx
new file mode 100644
index 000000000000..85ed1a606d08
--- /dev/null
+++ b/vcl/os2/source/window/salobj.cxx
@@ -0,0 +1,568 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <svpm.h>
+
+#define _SV_SALOBJ_CXX
+#include <saldata.hxx>
+#include <salinst.h>
+#include <salframe.h>
+#include <salobj.h>
+
+// =======================================================================
+
+static BOOL ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild )
+{
+ if ( hWndParent == hWndChild )
+ return TRUE;
+
+ HWND hTempWnd = WinQueryWindow( hWndChild, QW_PARENT );
+ while ( hTempWnd )
+ {
+ if ( hTempWnd == hWndParent )
+ return TRUE;
+ hTempWnd = WinQueryWindow( hTempWnd, QW_PARENT );
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static Os2SalObject* ImplFindOs2SalObject( HWND hWndChild )
+{
+ SalData* pSalData = GetSalData();
+ Os2SalObject* pObject = pSalData->mpFirstObject;
+ while ( pObject )
+ {
+ if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) )
+ return pObject;
+
+ pObject = pObject->mpNextObject;
+ }
+
+ return NULL;
+}
+
+// =======================================================================
+
+BOOL EXPENTRY SalSysMsgProc( HAB /* hAB */, QMSG* pMsg, ULONG /* fs */ )
+{
+ if ( (pMsg->msg == WM_BUTTON1DOWN) ||
+ (pMsg->msg == WM_BUTTON2DOWN) ||
+ (pMsg->msg == WM_BUTTON3DOWN) )
+ {
+ SalData* pSalData = GetSalData();
+ Os2SalObject* pObject = ImplFindOs2SalObject( pMsg->hwnd );
+ if ( pObject )
+ WinPostMsg( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 );
+ }
+
+ // Focus fangen wir hier nicht ab, da wir erstmal davon ausgehen,
+ // das unser Os2SalObject-Fenster immer eine WM_FOCUSCHANGE-Message
+ // bekommt.
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalSysObjWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ Os2SalObject* pSysObj;
+ MRESULT nRet = 0;
+ int bDef = TRUE;
+
+#if OSL_DEBUG_LEVEL>0
+ debug_printf( "SalSysObjWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
+#endif
+
+ switch( nMsg )
+ {
+ case WM_ERASEBACKGROUND:
+ nRet = (MRESULT)FALSE;
+ bDef = FALSE;
+ break;
+ case WM_PAINT:
+ {
+ HPS hPS;
+ RECTL aRect;
+ hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
+ WinEndPaint( hPS );
+ bDef = FALSE;
+ }
+ bDef = FALSE;
+ break;
+
+ case WM_BUTTON1DOWN:
+ case WM_BUTTON2DOWN:
+ case WM_BUTTON3DOWN:
+ case SALOBJ_MSG_TOTOP:
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ pSysObj = GetSalObjWindowPtr( hWnd );
+ pSysObj->mpProc( pSysObj->mpInst, pSysObj,
+ SALOBJ_EVENT_TOTOP, 0 );
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
+ break;
+
+ case WM_FOCUSCHANGE:
+ case SALOBJ_MSG_POSTFOCUS:
+ if ( ImplSalYieldMutexTryToAcquire() )
+ {
+ pSysObj = GetSalObjWindowPtr( hWnd );
+ if ( SHORT1FROMMP( nMP2 ) )
+ {
+ pSysObj->mhLastFocusWnd = WinQueryFocus( HWND_DESKTOP );
+ pSysObj->mpProc( pSysObj->mpInst, pSysObj,
+ SALOBJ_EVENT_GETFOCUS, 0 );
+ }
+ else
+ {
+ HWND hWndFocus = HWNDFROMMP( nMP1 );
+ if ( !hWndFocus || !ImplIsSysWindowOrChild( hWnd, hWndFocus ) )
+ {
+ pSysObj->mpProc( pSysObj->mpInst, pSysObj,
+ SALOBJ_EVENT_LOSEFOCUS, 0 );
+ }
+ }
+ ImplSalYieldMutexRelease();
+ }
+ else
+ WinPostMsg( hWnd, SALOBJ_MSG_POSTFOCUS, nMP1, nMP2 );
+ break;
+
+ case WM_SIZE:
+ {
+ pSysObj = GetSalObjWindowPtr( hWnd );
+ pSysObj->mnHeight = (short)SHORT2FROMMP( nMP2 );
+ WinSetWindowPos( pSysObj->mhWndChild, 0,
+ 0, 0,
+ (short)SHORT1FROMMP( nMP2 ), (short)SHORT2FROMMP( nMP2 ),
+ SWP_SIZE | SWP_MOVE );
+ bDef = FALSE;
+ }
+ break;
+
+ case WM_CREATE:
+ {
+ // Window-Instanz am Windowhandle speichern
+ CREATESTRUCT* pStruct = (CREATESTRUCT*)nMP2;
+ pSysObj = (Os2SalObject*)pStruct->pPresParams;
+ SetSalObjWindowPtr( hWnd, pSysObj );
+ bDef = FALSE;
+ }
+ break;
+ }
+
+ if ( bDef )
+ nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ MRESULT nRet = 0;
+ int bDef = TRUE;
+
+ debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
+
+ switch( nMsg )
+ {
+ case WM_ERASEBACKGROUND:
+ // Wegen PlugIn's loeschen wir erstmal den Hintergrund
+/*
+ nRet = (MRESULT)FALSE;
+ bDef = FALSE;
+*/
+ break;
+ case WM_PAINT:
+ {
+ HPS hPS;
+ RECTL aRect;
+ hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
+ WinEndPaint( hPS );
+ bDef = FALSE;
+ }
+ break;
+ }
+
+ if ( bDef )
+ nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg,
+ MPARAM nMP1, MPARAM nMP2 )
+{
+ MRESULT nRet = 0;
+ int bDef = TRUE;
+
+ debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
+
+ switch( nMsg )
+ {
+ case WM_MOUSEMOVE:
+ case WM_BUTTON1DOWN:
+ case WM_BUTTON2DOWN:
+ case WM_BUTTON3DOWN:
+ case WM_BUTTON1DBLCLK:
+ case WM_BUTTON2DBLCLK:
+ case WM_BUTTON3DBLCLK:
+ case WM_BUTTON1UP:
+ case WM_BUTTON2UP:
+ case WM_BUTTON3UP:
+ {
+ // Alle Events an den Frame weiterreichen, da diese Bereiche
+ // dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten
+ // entsprechend umgerechnet werden
+ HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster
+ hWndParent = WinQueryWindow( hWndParent, QW_PARENT );
+ short nX = (short)SHORT1FROMMP( nMP1 );
+ short nY = (short)SHORT2FROMMP( nMP1 );
+ POINTL aPos;
+ aPos.x = nX;
+ aPos.y = nY;
+ WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 );
+ nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y );
+ bDef = FALSE;
+ nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 );
+ }
+ break;
+
+ case WM_HITTEST:
+ // Damit im disablten Zustand die MouseKlicks immer noch
+ // an den Frame geschickt werden
+ // Dieser Code reicht leider nicht aus, deshalb wir unter
+ // OS2 immer das Child-Fenster disablen, im Gegensatz
+ // zu Windows, wo immer der Parent disablte wird, da
+ // sich das Fenster evtl. anders Darstellen koennte,
+ // wenn es disablte wird. Da dieser Fall uns bisher
+ // nicht bekannt ist, ignorieren wir das.
+ nRet = HT_NORMAL;
+ bDef = FALSE;
+ break;
+
+ case WM_ERASEBACKGROUND:
+ nRet = (MRESULT)FALSE;
+ bDef = FALSE;
+ break;
+ case WM_PAINT:
+ {
+ HPS hPS;
+ RECTL aRect;
+ hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
+ WinEndPaint( hPS );
+ bDef = FALSE;
+ }
+ break;
+ }
+
+ if ( bDef )
+ nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
+ return nRet;
+}
+
+// =======================================================================
+
+void ImplDestroyAllClipWindows( HWND hWndLast )
+{
+ if ( hWndLast == HWND_TOP )
+ return;
+
+ HWND hWndPrev;
+ while ( hWndLast )
+ {
+ hWndPrev = WinQueryWindow( hWndLast, QW_PREV );
+ WinDestroyWindow( hWndLast );
+ hWndLast = hWndPrev;
+ }
+}
+
+// =======================================================================
+
+SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent )
+{
+ SalData* pSalData = GetSalData();
+
+ if ( !pSalData->mbObjClassInit )
+ {
+ if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME,
+ (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY,
+ SAL_OBJECT_WNDEXTRA ) )
+ {
+ if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME,
+ (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) )
+ {
+ if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME,
+ (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) )
+ pSalData->mbObjClassInit = TRUE;
+ }
+ }
+ }
+
+ if ( pSalData->mbObjClassInit )
+ {
+ Os2SalObject* pObject = new Os2SalObject;
+ HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "",
+ 0,
+ 0, 0, 0, 0,
+ pParent->mhWndClient, HWND_TOP,
+ 0, NULL, (void*)pObject );
+ HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "",
+ WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
+ 0, 0, 0, 0,
+ hWnd, HWND_TOP,
+ 0, NULL, NULL );
+
+ if ( !hWndChild )
+ {
+ if ( hWnd )
+ WinDestroyWindow( hWnd );
+ delete pObject;
+ return NULL;
+ }
+
+ if ( hWnd )
+ {
+ debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild);
+ debug_printf("ImplSalCreateObject hWnd %x\n", hWnd);
+ pObject->mhWnd = hWnd;
+ pObject->mhWndChild = hWndChild;
+ pObject->maSysData.hWnd = hWndChild;
+ return pObject;
+ }
+ }
+
+ return NULL;
+}
+
+// =======================================================================
+
+long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* )
+{
+ return 0;
+}
+
+// =======================================================================
+
+Os2SalObject::Os2SalObject()
+{
+ SalData* pSalData = GetSalData();
+
+ mhLastClipWnd = HWND_TOP;
+
+ mhWnd = 0;
+ mhWndChild = 0;
+ mhLastFocusWnd = 0;
+ maSysData.nSize = sizeof( SystemEnvData );
+ mnHeight = 0;
+ mpInst = NULL;
+ mpProc = ImplSalObjCallbackDummy;
+
+ // Hook installieren, wenn es das erste Os2SalObject ist
+ if ( !pSalData->mpFirstObject )
+ {
+ WinSetHook( pSalData->mhAB, pSalData->mhMQ,
+ HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
+ }
+
+ // Insert object in objectlist
+ mpNextObject = pSalData->mpFirstObject;
+ pSalData->mpFirstObject = this;
+}
+
+// -----------------------------------------------------------------------
+
+Os2SalObject::~Os2SalObject()
+{
+ SalData* pSalData = GetSalData();
+
+ // remove frame from framelist
+ if ( this == pSalData->mpFirstObject )
+ {
+ pSalData->mpFirstObject = mpNextObject;
+
+ // Wenn letztes Os2SalObject, dann Hook wieder entfernen
+ if ( !pSalData->mpFirstObject )
+ {
+ WinReleaseHook( pSalData->mhAB, pSalData->mhMQ,
+ HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
+ }
+ }
+ else
+ {
+ Os2SalObject* pTempObject = pSalData->mpFirstObject;
+ while ( pTempObject->mpNextObject != this )
+ pTempObject = pTempObject->mpNextObject;
+
+ pTempObject->mpNextObject = mpNextObject;
+ }
+
+ // Cache-Daten zerstoeren
+ ImplDestroyAllClipWindows( mhLastClipWnd );
+
+ if ( mhWndChild )
+ WinDestroyWindow( mhWndChild );
+ if ( mhWnd )
+ WinDestroyWindow( mhWnd );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::ResetClipRegion()
+{
+ ImplDestroyAllClipWindows( mhLastClipWnd );
+ mhLastClipWnd = HWND_TOP;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Os2SalObject::GetClipRegionType()
+{
+ return SAL_OBJECT_CLIP_EXCLUDERECTS;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::BeginSetClipRegion( ULONG nRectCount )
+{
+ mhOldLastClipWnd = mhLastClipWnd;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
+{
+ HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "",
+ WS_VISIBLE,
+ nX, mnHeight-(nY+nHeight), nWidth, nHeight,
+ mhWnd, mhLastClipWnd,
+ 0, NULL, NULL );
+ debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd);
+ mhLastClipWnd = hClipWnd;
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::EndSetClipRegion()
+{
+ ImplDestroyAllClipWindows( mhOldLastClipWnd );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
+{
+ ULONG nStyle = 0;
+ BOOL bVisible = WinIsWindowVisible( mhWnd );
+ if ( bVisible )
+ {
+ WinShowWindow( mhWnd, FALSE );
+ nStyle |= SWP_SHOW;
+ }
+ SWP aParentSWP;
+ WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP );
+ WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight,
+ SWP_MOVE | SWP_SIZE | nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::Show( BOOL bVisible )
+{
+ WinShowWindow( mhWnd, bVisible );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::Enable( BOOL bEnable )
+{
+ // Im Gegensatz zu Windows disablen wir das Childfenster,
+ // da ansonsten unser Clippen nicht mehr funktioniert, da
+ // wir keine Events mehr bekommen. Dadurch kann sich evtl.
+ // das Fenster anders darstellen, was wir eigentlich nicht
+ // wollen. Aber da uns bisher kein Fall bekannt ist,
+ // ignorieren wir dies. Ansonsten muss ein Fenster dazwischen
+ // gezogen werden oder getestet werden, wie wir die
+ // Maustransparenz erreichen, wenn mhWnd
+ // disablte wird.
+ WinEnableWindow( mhWndChild, bEnable );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::GrabFocus()
+{
+ if ( mhLastFocusWnd &&
+ WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) &&
+ ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
+ WinSetFocus( HWND_DESKTOP, mhLastFocusWnd );
+ else
+ WinSetFocus( HWND_DESKTOP, mhWndChild );
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::SetBackground()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Os2SalObject::SetBackground( SalColor nSalColor )
+{
+}
+
+// -----------------------------------------------------------------------
+
+const SystemChildData* Os2SalObject::GetSystemData() const
+{
+ return &maSysData;
+}
+
+// -----------------------------------------------------------------------
+#if 0
+void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc )
+{
+ mpInst = pInst;
+ if ( pProc )
+ mpProc = pProc;
+ else
+ mpProc = ImplSalObjCallbackDummy;
+}
+#endif
+