summaryrefslogtreecommitdiff
path: root/vcl/source
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source')
-rw-r--r--vcl/source/app/dbggui.cxx1884
-rw-r--r--vcl/source/app/help.cxx686
-rw-r--r--vcl/source/app/idlemgr.cxx191
-rw-r--r--vcl/source/app/makefile.mk123
-rw-r--r--vcl/source/app/settings.cxx1857
-rw-r--r--vcl/source/app/sound.cxx361
-rw-r--r--vcl/source/app/stdtext.cxx104
-rw-r--r--vcl/source/app/svapp.cxx1770
-rw-r--r--vcl/source/app/svdata.cxx237
-rw-r--r--vcl/source/app/svmain.cxx714
-rw-r--r--vcl/source/app/timer.cxx490
-rw-r--r--vcl/source/app/unohelp.cxx275
-rw-r--r--vcl/source/control/button.cxx3010
-rw-r--r--vcl/source/control/combobox.cxx1242
-rw-r--r--vcl/source/control/ctrl.cxx155
-rw-r--r--vcl/source/control/edit.cxx2200
-rw-r--r--vcl/source/control/field.cxx2330
-rw-r--r--vcl/source/control/field2.cxx3245
-rw-r--r--vcl/source/control/fixbrd.cxx255
-rw-r--r--vcl/source/control/fixed.cxx1051
-rw-r--r--vcl/source/control/group.cxx349
-rw-r--r--vcl/source/control/ilstbox.cxx2387
-rw-r--r--vcl/source/control/imgctrl.cxx95
-rw-r--r--vcl/source/control/longcurr.cxx873
-rw-r--r--vcl/source/control/lstbox.cxx1242
-rw-r--r--vcl/source/control/makefile.mk119
-rw-r--r--vcl/source/control/menubtn.cxx285
-rw-r--r--vcl/source/control/morebtn.cxx266
-rw-r--r--vcl/source/control/scrbar.cxx1245
-rw-r--r--vcl/source/control/slider.cxx1024
-rw-r--r--vcl/source/control/spinbtn.cxx313
-rw-r--r--vcl/source/control/spinfld.cxx791
-rw-r--r--vcl/source/control/tabctrl.cxx1772
-rw-r--r--vcl/source/gdi/alpha.cxx353
-rw-r--r--vcl/source/gdi/animate.cxx992
-rw-r--r--vcl/source/gdi/bitmap.cxx1980
-rw-r--r--vcl/source/gdi/bitmap2.cxx1269
-rw-r--r--vcl/source/gdi/bitmap3.cxx2248
-rw-r--r--vcl/source/gdi/bitmap4.cxx953
-rw-r--r--vcl/source/gdi/bitmapex.cxx690
-rw-r--r--vcl/source/gdi/bmpacc.cxx448
-rw-r--r--vcl/source/gdi/bmpacc2.cxx353
-rw-r--r--vcl/source/gdi/bmpacc3.cxx351
-rw-r--r--vcl/source/gdi/cvtgrf.cxx232
-rw-r--r--vcl/source/gdi/cvtsvm.cxx2106
-rw-r--r--vcl/source/gdi/font.cxx625
-rw-r--r--vcl/source/gdi/gdimtf.cxx1724
-rw-r--r--vcl/source/gdi/gfxlink.cxx450
-rw-r--r--vcl/source/gdi/gradient.cxx386
-rw-r--r--vcl/source/gdi/graph.cxx832
-rw-r--r--vcl/source/gdi/hatch.cxx262
-rw-r--r--vcl/source/gdi/image.cxx1521
-rw-r--r--vcl/source/gdi/imgcons.cxx593
-rw-r--r--vcl/source/gdi/impanmvw.cxx392
-rw-r--r--vcl/source/gdi/impanmvw.hxx130
-rw-r--r--vcl/source/gdi/impbmp.cxx309
-rw-r--r--vcl/source/gdi/impgraph.cxx1571
-rw-r--r--vcl/source/gdi/impimage.cxx744
-rw-r--r--vcl/source/gdi/implncvt.cxx605
-rw-r--r--vcl/source/gdi/implncvt.hxx113
-rw-r--r--vcl/source/gdi/impprn.cxx256
-rw-r--r--vcl/source/gdi/impvect.cxx1267
-rw-r--r--vcl/source/gdi/impvect.hxx101
-rw-r--r--vcl/source/gdi/jobset.cxx415
-rw-r--r--vcl/source/gdi/lineinfo.cxx300
-rw-r--r--vcl/source/gdi/makefile.mk156
-rw-r--r--vcl/source/gdi/mapmod.cxx356
-rw-r--r--vcl/source/gdi/metaact.cxx3434
-rw-r--r--vcl/source/gdi/metric.cxx142
-rw-r--r--vcl/source/gdi/octree.cxx419
-rw-r--r--vcl/source/gdi/opengl.cxx1714
-rw-r--r--vcl/source/gdi/outdev.cxx1927
-rw-r--r--vcl/source/gdi/outdev2.cxx1928
-rw-r--r--vcl/source/gdi/outdev3.cxx6326
-rw-r--r--vcl/source/gdi/outdev4.cxx1634
-rw-r--r--vcl/source/gdi/outdev5.cxx430
-rw-r--r--vcl/source/gdi/outdev6.cxx1043
-rw-r--r--vcl/source/gdi/outmap.cxx2106
-rw-r--r--vcl/source/gdi/polyscan.cxx389
-rw-r--r--vcl/source/gdi/print.cxx1979
-rw-r--r--vcl/source/gdi/print2.cxx543
-rw-r--r--vcl/source/gdi/regband.cxx785
-rw-r--r--vcl/source/gdi/region.cxx2458
-rw-r--r--vcl/source/gdi/salmisc.cxx497
-rw-r--r--vcl/source/gdi/svcompat.cxx117
-rw-r--r--vcl/source/gdi/virdev.cxx442
-rw-r--r--vcl/source/gdi/wall.cxx616
-rw-r--r--vcl/source/helper/evntpost.cxx96
-rw-r--r--vcl/source/helper/makefile.mk100
-rw-r--r--vcl/source/helper/threadex.cxx130
-rw-r--r--vcl/source/src/btntext.src290
-rw-r--r--vcl/source/src/helptext.src367
-rw-r--r--vcl/source/src/images.src167
-rw-r--r--vcl/source/src/makefile.mk106
-rw-r--r--vcl/source/src/menu.src284
-rw-r--r--vcl/source/src/stdtext.src91
-rw-r--r--vcl/source/window/accel.cxx775
-rw-r--r--vcl/source/window/accmgr.cxx318
-rw-r--r--vcl/source/window/brdwin.cxx3808
-rw-r--r--vcl/source/window/btndlg.cxx584
-rw-r--r--vcl/source/window/cursor.cxx449
-rw-r--r--vcl/source/window/decoview.cxx1297
-rw-r--r--vcl/source/window/dialog.cxx847
-rw-r--r--vcl/source/window/dlgctrl.cxx968
-rw-r--r--vcl/source/window/dockwin.cxx857
-rw-r--r--vcl/source/window/floatwin.cxx748
-rw-r--r--vcl/source/window/keycod.cxx276
-rw-r--r--vcl/source/window/makefile.mk139
-rw-r--r--vcl/source/window/menu.cxx3444
-rw-r--r--vcl/source/window/mnemonic.cxx260
-rw-r--r--vcl/source/window/msgbox.cxx548
-rw-r--r--vcl/source/window/scrwnd.cxx420
-rw-r--r--vcl/source/window/scrwnd.hxx124
-rw-r--r--vcl/source/window/seleng.cxx506
-rw-r--r--vcl/source/window/split.cxx365
-rw-r--r--vcl/source/window/splitwin.cxx3647
-rw-r--r--vcl/source/window/status.cxx1411
-rw-r--r--vcl/source/window/syschild.cxx221
-rw-r--r--vcl/source/window/syswin.cxx389
-rw-r--r--vcl/source/window/tabdlg.cxx315
-rw-r--r--vcl/source/window/tabpage.cxx182
-rw-r--r--vcl/source/window/toolbox.cxx4176
-rw-r--r--vcl/source/window/toolbox2.cxx1401
-rw-r--r--vcl/source/window/window.cxx6539
-rw-r--r--vcl/source/window/window2.cxx1384
-rw-r--r--vcl/source/window/winproc.cxx2151
-rw-r--r--vcl/source/window/wrkwin.cxx424
127 files changed, 127557 insertions, 0 deletions
diff --git a/vcl/source/app/dbggui.cxx b/vcl/source/app/dbggui.cxx
new file mode 100644
index 000000000000..024f3cdd5191
--- /dev/null
+++ b/vcl/source/app/dbggui.cxx
@@ -0,0 +1,1884 @@
+/*************************************************************************
+ *
+ * $RCSfile: dbggui.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#pragma hdrstop
+
+#ifdef DBG_UTIL
+
+#define _SV_DBGGUI_CXX
+
+#include "svdata.hxx"
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <svsys.h>
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_LSTBOX_HXX
+#include <lstbox.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_EDIT_HXX
+#include <edit.hxx>
+#endif
+#ifndef _SV_FIXED_HXX
+#include <fixed.hxx>
+#endif
+#ifndef _SV_GROUP_HXX
+#include <group.hxx>
+#endif
+#ifndef _SV_FIELD_HXX
+#include <field.hxx>
+#endif
+#ifndef _SV_MSGBOX_HXX
+#include <msgbox.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_SYSTEM_HXX
+#include <system.hxx>
+#endif
+
+#ifndef _SV_DBGGUI_HXX
+#include <dbggui.hxx>
+#endif
+
+// =======================================================================
+
+static sal_Char* pDbgHelpText[] =
+{
+"Object Test\n",
+"------------------------------------------\n",
+"\n",
+"--- Macros ---\n",
+"DBG_NAME( aName )\n",
+"Definiert die Verwaltungsdaten fuer eine Klasse. Dieses Makro darf nur in "
+"einem Source-File mit dem gleichen Namen benutzt werden.\n",
+"\n",
+"DBG_NAMEEX( aName )\n",
+"Wie DBG_NAME, nur fuer weitere Source-Files.\n",
+"\n",
+"DBG_CTOR( aName, fTest )\n",
+"Muss in allen Konstruktoren einer Klasse benutzt werden (auch beim "
+"CopyCtor). Als erster Paramter muss der registrierte Name (am besten der "
+"Klassenname) uebergeben werden und als zweiter Parameter die Testfunktion "
+"oder 0.\n",
+"\n",
+"DBG_DTOR( aName, fTest )\n",
+"Muss im Destruktor der Klasse benutzt werden. Als erster Paramter muss "
+"der registrierte Name uebergeben werden und als zweiter Parameter die "
+"Testfunktion oder 0.\n",
+"\n",
+"DBG_CHKTHIS( aName, fTest )\n",
+"Kann in Methoden einer Klasse benutzt werden, wo die Konstruktoren und "
+"der Destruktor der Klasse mit den entsprechenden Makros ausgestattet sind. "
+"Als erster Paramter muss der registrierte Name uebergeben werden und als "
+"zweiter Parameter die Testfunktion oder 0.\n",
+"\n",
+"DBG_CHKOBJ( pObj, aName, fTest )\n",
+"Kann auf Instanzen einer Klasse angewendet werden, wo die Konstruktoren und "
+"der Destruktor der Klasse mit den entsprechenden Makros ausgestattet sind. "
+"Als erster Paramter muss die Adresse des zu testenden Objects uebergeben "
+"werden, als zweiter Parameter der registrierte Name und als dritter "
+"Parameter die Testfunktion oder 0.\n",
+"\n",
+"Damit die Makros Wirkung haben, muss DBG_UTIL defniert sein.\n",
+"\n",
+#ifndef CFRONT
+"--- Optionen ---\n",
+"This\n",
+"Es wird auf gueltigen This-Pointer getestet. Dadurch kann man erreichen, "
+"das bei allen Objekten die damit ausgestattet sind, geprueft wird, ob "
+"mit einem existierenden Objekt gearbeitet wird. Dadurch findet man zum "
+"Beispiel schneller Fehler durch falsche Mehrfachvererbung, Alignment oder "
+"Compilerfehler. Da fast alle Standard-Klassen von SV (String, List, Pen, "
+"Brush, Polygon, ...) mit DBG_CHKTHIS() ausgestattet sind, werden viele "
+"Fehler gefunden, jedoch kostet dadurch dieser Test auch entsprechend viel "
+"Performence.\n",
+"\n",
+"Function\n",
+"Wenn eine Funktion bei den Macros uebergeben wird, wird sie gerufen.\n",
+"\n",
+"Exit\n",
+"This- und Func-Test wird auch beim Funktionsaustritt durchgefuehrt.\n",
+"\n",
+"Report\n",
+"Am Programmende wird die Anzahl der angelegten Objekte ausgegeben. "
+"Da alle wichtigen SV-Klassen zumindest mit DBG_CTOR()/DBG_DTOR() "
+"ausgestattet sind, kann man damit feststellen, ob man die sogenannten "
+"Resource-Leaks hat (Systemobjekte, die nicht freigegeben werden). Dazu "
+"gehoehren OutputDevice, Window, VirtualDevice, Printer und Menu. Achtung: "
+"Dtor-Aufrufe von statischen Objekten werden nicht beruecksichtigt. Deshalb "
+"bleiben bei jedem SV-Programm auch 2 Strings und eine Bitmap nach.\n",
+"\n",
+"Trace\n",
+"Erzeugung, Zerstoerung und Benutzung der mit DBG_XTOR ausgestatteten "
+"Objekte wird protokoliert.\n",
+"\n",
+"\n",
+"Memory Test\n",
+"------------------------------------------\n",
+"\n",
+"--- Macros ---\n",
+"DBG_MEMTEST()\n",
+"Fuehrt die eingestellten Memory Tests durch.\n",
+"\n",
+"DBG_MEMTEST_PTR( p )\n",
+"Fuehrt die eingestellten Memory Tests durch und zusaetzlich wird der "
+"uebergebene Pointer auf Gueltigkeit geprueft, wenn Pointer Test an ist.\n",
+"\n",
+"--- Optionen ---\n",
+"Initilize\n",
+"Allokierter Speicher wird mit 0x77 und freier oder freigegebener Speicher "
+"wird mit 0x33 initialisiert. Diese Option kostet (fast) keine Performence "
+"und sollte deshalb waehrend der Entwicklung fast immer an sein. Denn "
+"dadurch erreicht man auch, das Abstuerze oefters reproduzierbarer "
+"auftreten.\n",
+"\n",
+"Overwrite\n",
+"Es wird getestet, ob vor/hinter die Bloecke geschrieben wird. Vor und "
+"hinter dem Block wird der Speicher mit 0x55 initialisiert. Diese Option "
+"kostet Performence, sollte jedoch auch mal eingesetzt werden um die "
+"haeufigsten Speicherueberschreiber (+-1-Fehler) zu testen. Diese Option "
+"sollte auch eingeschaltet werden, wenn das Programm im new oder "
+"delete-Operator abstuerzt.\n",
+"\n",
+"Free\n",
+"Es wird getestet, ob freier Speicher ueberschrieben wird. Diese Option "
+"kostet eine ganze Menge Performence und sollte deshalb nur gelegentlich "
+"eingesetzt werden um Speicherueberschreiber zu testen. Diese Option "
+"sollte evt. auch eingeschaltet werden, wenn das Programm im new oder "
+"delete-Operator abstuerzt.\n",
+"\n",
+"Pointer\n",
+"Bei delete und DBG_MEMTEST_PTR() wird der Zeiger getestet, ob er auch mit "
+"new oder SvMemAlloc() angelegt wurde. Wenn diese Option eingeschaltet ist, "
+"werden Fehler wie doppeltes delete und delete auf Stack-Objekte oder "
+"ungueltige Zeiger gefunden. Diese Option kostet Performence und sollte "
+"deshalb nicht immer eingeschaltet sein. Jedoch sollte auch ab und zu mit "
+"dieser Option getestet werden, da der Memory-Manager nicht immer bei delete "
+"und ungueltigem Zeiger abstuerzt. Diese Option sollte auch eingeschaltet "
+"werden, wenn das Programm im new oder delete-Operator abstuerzt.\n",
+"\n",
+"Report\n",
+"Am Programmende wird eine kleine Statistik und der nicht freigegebene "
+"Speicher ausgegeben. Achtung: Speicher der von globalen Objekten noch "
+"freigegeben wird, taucht auch in der Leak-Liste auf.\n",
+"\n",
+"Trace\n",
+"Allokation und Freigeben von Speicher wird protokoliert.\n",
+"\n",
+"Leak-Report\n",
+"Gibt unter WNT beim Programmende eine Liste der Memory-Leaks mit "
+"Stack-Trace aus. Dabei werden nur Bloecke beruecksichtigt, die innerhalb "
+"von Application::Execute() angelegt und freigegeben werden. Wenn diese "
+"Option und Overwrite gesetzt ist, wird bei einem Speicherueberschreiber "
+"auch noch versucht den Stack auszugeben, wo der Block angelegt wurde. "
+"Diese Ausgabe erfolgt erst nach Ausgabe der Fehlermeldung in die "
+"Log-Datei.\n"
+"\n",
+"New/Delete\n",
+"Memory-Tests werden auf den gesammten Speicher bei jedem new/delete "
+"durchgefuhert. Achtung: Diese Option macht die Programme sehr langsam "
+"und sollte nur eingeschaltet werden, wenn ein Speicherueberschreiber "
+"eingegrenzt werden soll. Ansonsten reicht es, die einzelnen Optionen "
+"einzuschalten, da (kein Leak vorrausgesetzt) jeder zu erkennende "
+"Speicherueberschreiber waehrend der Laufzeit eines Programms gefunden "
+"werden sollte.\n",
+"\n",
+"Object Test\n",
+"Memory-Tests werden auf den gesammten Speicher bei jedem Object-Test "
+"durchgefuhert. Achtung: Diese Option macht die Programme sehr langsam "
+"und sollte nur eingeschaltet werden, wenn ein Speicherueberschreiber "
+"eingegrenzt werden soll. Ansonsten reicht es, die einzelnen Optionen "
+"einzuschalten, da (kein Leak vorrausgesetzt) jeder zu erkennende "
+"Speicherueberschreiber waehrend der Laufzeit eines Programms gefunden "
+"werden sollte.\n",
+"\n",
+"SysAlloc\n",
+"Wenn dieses Flag gesetzt ist, wird Speicher mit direkten Systemfunktionen"
+"angefordert und der Memory-Manager von SV umgangen. Dadurch ist es moeglich"
+"leistungsfaehigere Memory-Test-Tools einzusetzen. Es ist jedoch darauf zu"
+"achten, das nicht auf jedem System die Memory-Funktionen vom Compiler"
+"gerufen werden, sondern die Systemfunktionen. Dadurch ist man unter"
+"Windows 16-Bit auf ca. 4000 news begrenzt und unter OS2 werden immer"
+"4096 KB Bloecke angefordert.\n",
+"\n",
+"Windows 16-Bit und Debug-Tests\n",
+"Achtung: Wenn Memory-Tests an sind (ausser Initilize) wird niemals "
+"(auch nicht bei >= 64 KB) Speicher mit Offset 0 zurueckgeben. Falls man "
+"darauf angewiesen ist, muessen die Tests mit 32-Bit-Versionen der "
+"Programme durchgefuehrt werden. Teilweise reicht es aber auch schon aus, "
+"wenn man statt 64 KB nur 64 KB - 64-Bytes anlegt, da es dann nicht zu "
+"einem Segmentueberlauf kommt.\n",
+"Ausserdem sollten die Memory- genauso wie die Object-Tests nur dann "
+"eingesetzt werden, wenn nur eine SV-Applikation gleichzeitig laeuft. "
+"Ansonsten kann es zu unkontrolierten Fehlern kommen. Hier hilft dann auch "
+"nur ein ausweichen auf 32-Bit-Programme."
+"\n",
+"\n",
+"\nWeitere Test's und Makros\n",
+"------------------------------------------\n",
+"\n",
+"Profiling\n",
+"DBG_PROFSTART() / DBG_PROFSTOP() / DBG_PROFCONTINUE() / DBG_PROFPAUSE() "
+"werden ausgewertet und beim Programmende wird die Anzahl der Durchlaeufe "
+"und die dazu benoetigte Zeit (inklusive der Childaufrufe) in "
+"Millisekunden ausgegeben. Diese Macros koennen dann eingesetzt werden, wenn "
+"die gleichen Funktionsablaeufe ueber die gesammte Entwicklungszeit "
+"beobachtet werden sollen, wie zum Beispiel die Startup-Zeiten. Bei den "
+"Makros muss der registrierte Name uebergeben werden, der mit DBG_NAME() "
+"registriert wurde.\n",
+"\n",
+"Resourcen\n",
+"Bei Resource-Fehlern gibt es einen Fehler-Dialog, bevor der "
+"Exception-Handler gerufen wird.\n",
+"\n",
+"Dialog\n",
+"Es werden FixedTexte, CheckBoxen, TriStateBoxen und RadioButtons mit "
+"einer anderen Hintergrundfarbe versehen, damit man feststellen kann, wie "
+"Gross die Controls sind. Ausserdem wird getestet, ob sich Controls "
+"ueberschneiden, die Tabreihenfolge in Ordnung ist und die Mnemonischen "
+"Zeichen ordentlich vergeben wurden. Bei Dialogen wird auch angemahnt, "
+"wenn kein DefPushButton oder kein OK-/CancelButton vorhanden ist. "
+"Diese Tests sind nicht 100% (es wird evt. zuviel angemahnt) und "
+"erfuellen auch keine Garantie, das alle Problemfaelle festgestellt "
+"werden, da zum Beispiel nur initial und dann nur die sichtbaren Controls "
+"getestet werden. Es werden somit keine Fehler gefunden, die waehrend der "
+"Benutzung des Dialoges auftreten.\n",
+"\n",
+"Bold AppFont\n",
+"Es wird der Applikationsfont auf Fett gesetzt, damit man feststellen kann, "
+"ob der Platz fuer die Texte auf anderen Systemen oder bei anderer "
+"Systemeinstellung ausreicht. Denn bei schmalen Fonts werden die Dialoge "
+"kuenstlich breiter gemacht, da diese ansonsten zu schmal aussehen.\n",
+"\n",
+"Trace-Ausgaben\n",
+"DBG_TRACE() kann verwendet werden, wenn man TRACE-Ausgaben haben moechte. "
+"DBG_TRACEFILE() gibt zu der Meldung auch noch die Datei und die Zeilennummer "
+"aus, an der das Makro steht. DBG_TRACE1() bis DBG_TRACE5() koennen "
+"verwendet werden, wenn man eine formatierte Ausgabe (printf-Formatstring) "
+"haben moechte. Die Trace-Ausgaben werden aktiviert, in dem man in der "
+"DropDown-ListBox eine entsprechende Ausgabe waehlt.\n"
+"\n",
+"Warnings\n",
+"DBG_WARNING() kann verwendet werden, wenn man Warnungen ausgeben moechte. "
+"DBG_WARNINGFILE() gibt zu der Warnung auch noch die Datei und die "
+"Zeilennummer aus, an der das Makro steht. DBG_WARNING1() bis DBG_WARNING5() "
+"koennen verwendet werden, wenn man eine formatierte Ausgabe "
+"(printf-Formatstring) haben moechte. Wenn man die Warnung von einer "
+"Bedingung abhaengig machen moechte, kann man DBG_ASSERTWARNING() "
+"benutzen. Die Warning wird ausgegeben, wenn die Bedingung nicht erfuellt "
+"wurde. Als erster Parameter muss die zu testende Bedingung und als zweiter "
+"Parameter die auszugebene Meldung uebergeben werden. Die Warnungen werden "
+"aktiviert, in dem man in der DropDown-ListBox eine entsprechende Ausgabe "
+"waehlt. Wenn None gewaehlt ist, wird auch die Bedingung bei "
+"DBG_ASSERTWARNING() nicht ausgewertet.\n",
+"\n",
+"Errors\n",
+"DBG_ERROR() kann verwendet werden, wenn man Fehlermeldungen ausgeben "
+"moechte. DBG_ERRORFILE() gibt zu dem Fehler auch noch die Datei und die "
+"Zeilennummer aus, an der das Makro steht. DBG_ERROR1() bis DBG_ERROR5() "
+"koennen verwendet werden, wenn man eine formatierte Ausgabe "
+"(printf-Formatstring) haben moechte. Wenn man die Fehlerausgabe von einer "
+"Bedingung abhaengig machen moechte, kann man DBG_ASSERT() benutzen. Der "
+"Fehler wird ausgegeben, wenn die Bedingung nicht erfuellt wurde. Als erster "
+"Parameter muss die zu testende Bedingung und als zweiter Parameter die "
+"auszugebene Meldung uebergeben werden. Die Fehlermeldungen werden "
+"aktiviert, in dem man in der DropDown-ListBox eine entsprechende Ausgabe "
+"waehlt. Wenn None gewaehlt ist, wird auch die Bedingung bei "
+"DBG_ASSERT() nicht ausgewertet.\n",
+"\n",
+"\n",
+"Output\n",
+"------------------------------------------\n",
+"\n",
+"Overwrite - CheckBox\n",
+"Bei jedem neuen Programmstart wird das Log-File ueberschrieben, wenn "
+"eine Ausgabe stattgefunden hat.\n",
+"\n",
+"Include-ObjectTest-Filter\n",
+"Es werden nur die Klassen bei Object-Test ausgewertet, die einen der "
+"angegebenen Filter enthalten. Die Filter werden mit ';' getrennt und "
+"sind casesensitiv. Wildcards werden nicht unterstuetzt. Wenn kein Text "
+"angegeben wird, ist der Filter nicht aktiv.\n",
+"\n",
+"Exclude-ObjectTest-Filter\n",
+"Es werden die Klassen bei Object-Test ausgewertet, die einen der "
+"angegebenen Filter nicht enthalten. Die Filter werden mit ';' getrennt "
+"und sind casesensitiv. Wildcards werden nicht unterstuetzt. Wenn kein "
+"Text angegeben wird, ist der Filter nicht aktiv.\n",
+"\n",
+"Include-Filter\n",
+"Es werden nur die Texte ausgegeben, die einen der angegebenen Filter "
+"enthalten. Die Filter werden mit ';' getrennt und sind casesensitiv. "
+"Wildcards werden nicht unterstuetzt. Der Filter gilt fuer alle Ausgaben "
+"(jedoch nicht fuer Errors). Wenn kein Text angegeben wird, ist der Filter "
+"nicht aktiv.\n",
+"\n",
+"Exclude-Filter\n",
+"Es werden nur die Texte ausgegeben, die einen der angegebenen Filter "
+"nicht enthalten. Die Filter werden mit ';' getrennt und sind casesensitiv. "
+"Wildcards werden nicht unterstuetzt. Der Filter gilt fuer alle Ausgaben "
+"(jedoch nicht fuer Errors). Wenn kein Text angegeben wird, ist der Filter "
+"nicht aktiv.\n",
+"\n",
+"Ausserdem kann eingestellt werden, wohin die Daten ausgegeben werden "
+"sollen:\n",
+"\n",
+"None\n",
+"Ausgabe wird unterdrueckt.\n",
+"\n",
+"File\n",
+"Ausgabe ins Debug-File. Dateiname kann im Editfeld eingegeben werden.\n",
+"\n",
+"Window\n",
+"Ausgabe in ein kleines Debug-Window. Die Fenstergroesse wird gespeichert, "
+"wenn man den Debug-Dialog mit OK beendet und das Fenster sichtbar ist.\n",
+"\n",
+"Shell\n",
+"Ausgabe in ein Debug-System (Windows Debug-Window) wenn vorhanden oder "
+"unter Unix ins Shell-Fenster. Ansonsten das gleiche wie Window.\n",
+"\n",
+"MessageBox\n",
+"Ausgabe in MessageBox. In dieser hat man dann die Auswahl, ob das Programm "
+"fortgesetzt, beendet (Application::Abort) oder mit CoreDump abgebrochen "
+"werden soll. Da eine MessageBox weitere Event-Verarbeitung zulaest koennen "
+"jeweils weitere Fehler zum Beispiel durch Paints, Activate/Deactivate, "
+"GetFocus/LoseFocus die Ausgabe der Meldung oder weitere und falsche "
+"Fehler und Meldungen ausloesen. Deshalb sollte bei Problemen die Meldungen "
+"evt. auch in ein File/Debugger geleitet werden um die (richtigen) Fehlermeldungen "
+"zu erhalten.\n",
+"\n",
+"TestTool\n",
+"Wenn das TestTool laeuft, werden die Meldungen in das TestTool umgeleitet.\n",
+"\n",
+"Debugger\n",
+"Versucht den Debugger zu aktivieren und dort die Meldung auszugeben, "
+"so das man im Debugger dann immer auch den dazugehoerenden Stacktrace "
+"erhaellt.\n",
+"\n",
+"CoreDump\n",
+"Erzeugt einen Absturz\n",
+"\n",
+"\n",
+"Einstellungen\n",
+"------------------------------------------\n",
+"\n",
+"Wo standardmaessig das INI-File und LOG-File gelesen und geschrieben "
+"wird, kann folgendermassen eingestellt werden:\n",
+"\n",
+"WIN/WNT (WIN.INI, Gruppe SV, Default: dbgsv.ini und dbgsv.log):\n",
+"INI: dbgsv\n",
+"LOG: dbgsvlog\n",
+"\n",
+"OS2 (OS2.INI, Application SV, Default: dbgsv.ini und dbgsv.log):\n",
+"INI: DBGSV\n",
+"LOG: DBGSVLOG\n",
+"\n",
+"UNIX (Environment-Variable, Default: .dbgsv.init und dbgsv.log):\n",
+"INI: DBGSV_INIT\n",
+"LOG: DBGSV_LOG\n",
+"\n",
+"MAC (Default: dbgsv.ini und dbgsv.log):\n",
+"INI: keine Moeglichkeit\n",
+"LOG: nur Debug-Dialogeinstellung\n",
+"\n",
+"Es muss jeweils Pfad und Dateiname angegeben werden. Der Name der "
+"Log-Datei, der im Debug-Dialog eintragen wurde, hat immer vorrang.\n",
+"\n",
+"\n",
+"Beispiel\n",
+"------------------------------------------\n",
+"\n",
+"DBG_NAME( String );\n",
+"\n",
+"#ifdef DBG_UTIL\n",
+"const sal_Char* DbgCheckString( const void* pString )\n",
+"{\n",
+" String* p = (String*)pString;\n",
+"\n",
+" if ( p->mpData->maStr[p->mpData->mnLen] != 0 )\n",
+" return \"String damaged: aStr[nLen] != 0\";\n",
+"\n",
+" return NULL;\n",
+"}\n",
+"#endif\n",
+"\n",
+"String::String()\n",
+"{\n",
+" DBG_CTOR( String, DbgCheckString );\n",
+" // ...\n",
+"}\n",
+"\n",
+"String::~String()\n",
+"{\n",
+" DBG_DTOR( String, DbgCheckString );\n",
+" //...\n",
+"}\n",
+"\n",
+"char& String::operator [] ( USHORT nIndex )\n",
+"{\n",
+" DBG_CHKTHIS( String, DbgCheckString );\n",
+" DBG_ASSERT( nIndex <= pData->nLen, \"String::[] : nIndex > Len\" );\n",
+"\n",
+" //...\n",
+"}\n",
+"\n",
+"USHORT String::Search( const String& rStr, USHORT nIndex ) const\n",
+"{\n",
+" DBG_CHKTHIS( String, DbgCheckString );\n",
+" DBG_CHKOBJ( &rStr, String, DbgCheckString );\n",
+"\n",
+" //...\n",
+"}",
+"\n",
+#endif
+NULL
+};
+
+// =======================================================================
+
+// -------------
+// - DbgWindow -
+// -------------
+
+#define DBGWIN_MAXLINES 100
+
+class DbgWindow : public WorkWindow
+{
+private:
+ ListBox maLstBox;
+
+public:
+ DbgWindow();
+
+ virtual BOOL Close();
+ virtual void Resize();
+ void InsertLine( const XubString& rLine );
+ void Update() { WorkWindow::Update(); maLstBox.Update(); }
+};
+
+// -----------------
+// - DbgInfoDialog -
+// -----------------
+
+class DbgInfoDialog : public ModalDialog
+{
+private:
+ ListBox maListBox;
+ OKButton maOKButton;
+ BOOL mbHelpText;
+
+public:
+ DbgInfoDialog( Window* pParent, BOOL bHelpText = FALSE );
+
+ void SetInfoText( const XubString& rStr );
+};
+
+// -------------
+// - DbgDialog -
+// -------------
+
+class DbgDialog : public ModalDialog
+{
+private:
+ CheckBox maXtorThis;
+ CheckBox maXtorFunc;
+ CheckBox maXtorExit;
+ CheckBox maXtorReport;
+ CheckBox maXtorTrace;
+ GroupBox maBox1;
+
+ CheckBox maMemInit;
+ CheckBox maMemOverwrite;
+ CheckBox maMemOverwriteFree;
+ CheckBox maMemPtr;
+ CheckBox maMemReport;
+ CheckBox maMemTrace;
+ CheckBox maMemLeakReport;
+ CheckBox maMemNewDel;
+ CheckBox maMemXtor;
+ CheckBox maMemSysAlloc;
+ GroupBox maBox2;
+
+ CheckBox maProf;
+ CheckBox maRes;
+ CheckBox maDialog;
+ CheckBox maBoldAppFont;
+ GroupBox maBox3;
+
+ Edit maDebugName;
+ CheckBox maOverwrite;
+ FixedText maInclClassText;
+ Edit maInclClassFilter;
+ FixedText maExclClassText;
+ Edit maExclClassFilter;
+ FixedText maInclText;
+ Edit maInclFilter;
+ FixedText maExclText;
+ Edit maExclFilter;
+ FixedText maTraceText;
+ ListBox maTraceBox;
+ FixedText maWarningText;
+ ListBox maWarningBox;
+ FixedText maErrorText;
+ ListBox maErrorBox;
+ GroupBox maBox4;
+
+ OKButton maOKButton;
+ CancelButton maCancelButton;
+ PushButton maInfoButton;
+ HelpButton maHelpButton;
+ USHORT mnErrorOff;
+
+public:
+ DbgDialog();
+
+ DECL_LINK( ClickHdl, Button* );
+ void RequestHelp( const HelpEvent& rHEvt );
+};
+
+// =======================================================================
+
+static sal_Char aDbgInfoBuf[12288];
+static sal_Char aDbgOutBuf[DBG_BUF_MAXLEN];
+
+// =======================================================================
+
+DbgWindow::DbgWindow() :
+ WorkWindow( NULL, WB_STDWORK ),
+ maLstBox( this, WB_AUTOHSCROLL )
+{
+ DbgData* pData = DbgGetData();
+
+ maLstBox.Show();
+ maLstBox.SetPosPixel( Point( 0, 0 ) );
+
+ SetOutputSizePixel( Size( 250, 400 ) );
+ if ( pData->aDbgWinState )
+ {
+ ByteString aState( pData->aDbgWinState );
+ SetWindowState( aState );
+ }
+
+ SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "StarView Debug Window" ) ) );
+ Show();
+ Update();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DbgWindow::Close()
+{
+ delete this;
+ ImplGetSVData()->maWinData.mpDbgWin = NULL;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgWindow::Resize()
+{
+ maLstBox.SetSizePixel( GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void DbgWindow::InsertLine( const XubString& rLine )
+{
+ XubString aStr = rLine;
+ aStr.ConvertLineEnd( LINEEND_LF );
+ xub_StrLen nPos = aStr.Search( _LF );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
+ maLstBox.RemoveEntry( 0 );
+ maLstBox.InsertEntry( aStr.Copy( 0, nPos ) );
+ aStr.Erase( 0, nPos+1 );
+ nPos = aStr.Search( _LF );
+ }
+ if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
+ maLstBox.RemoveEntry( 0 );
+ maLstBox.InsertEntry( aStr );
+ maLstBox.SetTopEntry( DBGWIN_MAXLINES-1 );
+ maLstBox.Update();
+}
+
+// =======================================================================
+
+DbgDialog::DbgDialog() :
+ ModalDialog( Application::GetAppWindow(), WB_STDMODAL | WB_SYSTEMWINDOW ),
+ maXtorThis( this ),
+ maXtorFunc( this ),
+ maXtorExit( this ),
+ maXtorReport( this ),
+ maXtorTrace( this ),
+ maBox1( this ),
+ maMemInit( this ),
+ maMemOverwrite( this ),
+ maMemOverwriteFree( this ),
+ maMemPtr( this ),
+ maMemReport( this ),
+ maMemTrace( this ),
+ maMemLeakReport( this ),
+ maMemNewDel( this ),
+ maMemXtor( this ),
+ maMemSysAlloc( this ),
+ maBox2( this ),
+ maProf( this ),
+ maRes( this ),
+ maDialog( this ),
+ maBoldAppFont( this ),
+ maBox3( this ),
+ maDebugName( this ),
+ maOverwrite( this ),
+ maInclClassText( this ),
+ maInclClassFilter( this ),
+ maExclClassText( this ),
+ maExclClassFilter( this ),
+ maInclText( this ),
+ maInclFilter( this ),
+ maExclText( this ),
+ maExclFilter( this ),
+ maTraceText( this ),
+ maTraceBox( this, WB_DROPDOWN ),
+ maWarningText( this ),
+ maWarningBox( this, WB_DROPDOWN ),
+ maErrorText( this ),
+ maErrorBox( this, WB_DROPDOWN ),
+ maBox4( this ),
+ maOKButton( this, WB_DEFBUTTON ),
+ maCancelButton( this ),
+ maInfoButton( this ),
+ maHelpButton( this )
+{
+ DbgData* pData = DbgGetData();
+ MapMode aAppMap( MAP_APPFONT );
+ Size aButtonSize = LogicToPixel( Size( 60, 12 ), aAppMap );
+
+ {
+ maXtorThis.Show();
+ maXtorThis.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "T~his" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_XTOR_THIS )
+ maXtorThis.Check( TRUE );
+ maXtorThis.SetPosSizePixel( LogicToPixel( Point( 10, 15 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maXtorFunc.Show();
+ maXtorFunc.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Function" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_XTOR_FUNC )
+ maXtorFunc.Check( TRUE );
+ maXtorFunc.SetPosSizePixel( LogicToPixel( Point( 75, 15 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maXtorExit.Show();
+ maXtorExit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "E~xit" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_XTOR_EXIT )
+ maXtorExit.Check( TRUE );
+ maXtorExit.SetPosSizePixel( LogicToPixel( Point( 140, 15 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maXtorReport.Show();
+ maXtorReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_XTOR_REPORT )
+ maXtorReport.Check( TRUE );
+ maXtorReport.SetPosSizePixel( LogicToPixel( Point( 205, 15 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maXtorTrace.Show();
+ maXtorTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_XTOR_TRACE )
+ maXtorTrace.Check( TRUE );
+ maXtorTrace.SetPosSizePixel( LogicToPixel( Point( 270, 15 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maBox1.Show();
+ maBox1.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Object Tests" ) ) );
+ maBox1.SetPosSizePixel( LogicToPixel( Point( 5, 5 ), aAppMap ),
+ LogicToPixel( Size( 330, 30 ), aAppMap ) );
+ }
+
+ {
+ maMemInit.Show();
+ maMemInit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Initilize" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_INIT )
+ maMemInit.Check( TRUE );
+ maMemInit.SetPosSizePixel( LogicToPixel( Point( 10, 50 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemOverwrite.Show();
+ maMemOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Overwrite" )) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITE )
+ maMemOverwrite.Check( TRUE );
+ maMemOverwrite.SetPosSizePixel( LogicToPixel( Point( 75, 50 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemOverwriteFree.Show();
+ maMemOverwriteFree.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Free" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITEFREE )
+ maMemOverwriteFree.Check( TRUE );
+ maMemOverwriteFree.SetPosSizePixel( LogicToPixel( Point( 140, 50 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemPtr.Show();
+ maMemPtr.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Pointer" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_POINTER )
+ maMemPtr.Check( TRUE );
+ maMemPtr.SetPosSizePixel( LogicToPixel( Point( 205, 50 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemReport.Show();
+ maMemReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_REPORT )
+ maMemReport.Check( TRUE );
+ maMemReport.SetPosSizePixel( LogicToPixel( Point( 270, 50 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemTrace.Show();
+ maMemTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_TRACE )
+ maMemTrace.Check( TRUE );
+ maMemTrace.SetPosSizePixel( LogicToPixel( Point( 10, 65 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemLeakReport.Show();
+ maMemLeakReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Leak-Report" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_LEAKREPORT )
+ maMemLeakReport.Check( TRUE );
+ maMemLeakReport.SetPosSizePixel( LogicToPixel( Point( 75, 65 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemNewDel.Show();
+ maMemNewDel.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~New/Delete" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_NEWDEL )
+ maMemNewDel.Check( TRUE );
+ maMemNewDel.SetPosSizePixel( LogicToPixel( Point( 140, 65 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemXtor.Show();
+ maMemXtor.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Ob~ject Test" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_XTOR )
+ maMemXtor.Check( TRUE );
+ maMemXtor.SetPosSizePixel( LogicToPixel( Point( 205, 65 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maMemSysAlloc.Show();
+ maMemSysAlloc.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "System ~Alloc" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_MEM_SYSALLOC )
+ {
+ maMemSysAlloc.Check( TRUE );
+ ClickHdl( &maMemSysAlloc );
+ }
+ maMemSysAlloc.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
+ maMemSysAlloc.SetPosSizePixel( LogicToPixel( Point( 270, 65 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maBox2.Show();
+ maBox2.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Memory Tests" ) ) );
+ maBox2.SetPosSizePixel( LogicToPixel( Point( 5, 40 ), aAppMap ),
+ LogicToPixel( Size( 330, 40 ), aAppMap ) );
+ }
+
+ {
+ maProf.Show();
+ maProf.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Profiling" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_PROFILING )
+ maProf.Check( TRUE );
+ maProf.SetPosSizePixel( LogicToPixel( Point( 10, 95 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maRes.Show();
+ maRes.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Resourcen" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_RESOURCE )
+ maRes.Check( TRUE );
+ maRes.SetPosSizePixel( LogicToPixel( Point( 75, 95 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maDialog.Show();
+ maDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Dialog" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_DIALOG )
+ maDialog.Check( TRUE );
+ maDialog.SetPosSizePixel( LogicToPixel( Point( 140, 95 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maBoldAppFont.Show();
+ maBoldAppFont.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Bold AppFont" ) ) );
+ if ( pData->nTestFlags & DBG_TEST_BOLDAPPFONT )
+ maBoldAppFont.Check( TRUE );
+ maBoldAppFont.SetPosSizePixel( LogicToPixel( Point( 205, 95 ), aAppMap ),
+ aButtonSize );
+ maBoldAppFont.SaveValue();
+ }
+
+ {
+ maBox3.Show();
+ maBox3.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Test Options" ) ) );
+ maBox3.SetPosSizePixel( LogicToPixel( Point( 5, 85 ), aAppMap ),
+ LogicToPixel( Size( 330, 30 ), aAppMap ) );
+ }
+
+ {
+ maDebugName.Show();
+ maDebugName.SetText( XubString( pData->aDebugName, RTL_TEXTENCODING_UTF8 ) );
+ maDebugName.SetMaxTextLen( sizeof( pData->aDebugName ) );
+ maDebugName.SetPosSizePixel( LogicToPixel( Point( 10, 130 ), aAppMap ),
+ LogicToPixel( Size( 185, 14 ), aAppMap ) );
+ }
+
+ {
+ maOverwrite.Show();
+ maOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Overwrite ~File" ) ) );
+ if ( pData->bOverwrite )
+ maOverwrite.Check( TRUE );
+ maOverwrite.SetPosSizePixel( LogicToPixel( Point( 205, 130 ), aAppMap ),
+ aButtonSize );
+ }
+
+ {
+ maInclClassText.Show();
+ maInclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-ObjectTest-Filter" ) ) );
+ maInclClassText.SetPosSizePixel( LogicToPixel( Point( 10, 150 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maInclClassFilter.Show();
+ maInclClassFilter.SetText( XubString( pData->aInclClassFilter, RTL_TEXTENCODING_UTF8 ) );
+ maInclClassFilter.SetMaxTextLen( sizeof( pData->aInclClassFilter ) );
+ maInclClassFilter.SetPosSizePixel( LogicToPixel( Point( 10, 160 ), aAppMap ),
+ LogicToPixel( Size( 95, 14 ), aAppMap ) );
+ }
+
+ {
+ maExclClassText.Show();
+ maExclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-ObjectTest-Filter" ) ) );
+ maExclClassText.SetPosSizePixel( LogicToPixel( Point( 115, 150 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maExclClassFilter.Show();
+ maExclClassFilter.SetText( XubString( pData->aExclClassFilter, RTL_TEXTENCODING_UTF8 ) );
+ maExclClassFilter.SetMaxTextLen( sizeof( pData->aExclClassFilter ) );
+ maExclClassFilter.SetPosSizePixel( LogicToPixel( Point( 115, 160 ), aAppMap ),
+ LogicToPixel( Size( 95, 14 ), aAppMap ) );
+ }
+
+ {
+ maInclText.Show();
+ maInclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-Filter" ) ) );
+ maInclText.SetPosSizePixel( LogicToPixel( Point( 10, 180 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maInclFilter.Show();
+ maInclFilter.SetText( XubString( pData->aInclFilter, RTL_TEXTENCODING_UTF8 ) );
+ maInclFilter.SetMaxTextLen( sizeof( pData->aInclFilter ) );
+ maInclFilter.SetPosSizePixel( LogicToPixel( Point( 10, 190 ), aAppMap ),
+ LogicToPixel( Size( 95, 14 ), aAppMap ) );
+ }
+
+ {
+ maExclText.Show();
+ maExclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-Filter" ) ) );
+ maExclText.SetPosSizePixel( LogicToPixel( Point( 115, 180 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maExclFilter.Show();
+ maExclFilter.SetText( XubString( pData->aExclFilter, RTL_TEXTENCODING_UTF8 ) );
+ maExclFilter.SetMaxTextLen( sizeof( pData->aExclFilter ) );
+ maExclFilter.SetPosSizePixel( LogicToPixel( Point( 115, 190 ), aAppMap ),
+ LogicToPixel( Size( 95, 14 ), aAppMap ) );
+ }
+
+ {
+ maTraceText.Show();
+ maTraceText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
+ maTraceText.SetPosSizePixel( LogicToPixel( Point( 10, 210 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
+ maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) );
+ maTraceBox.SelectEntryPos( (USHORT)pData->nTraceOut );
+ maTraceBox.Show();
+ maTraceBox.SetPosSizePixel( LogicToPixel( Point( 10, 220 ), aAppMap ),
+ LogicToPixel( Size( 95, 80 ), aAppMap ) );
+ }
+
+ {
+ maWarningText.Show();
+ maWarningText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Warning" ) ) );
+ maWarningText.SetPosSizePixel( LogicToPixel( Point( 115, 210 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
+ maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) );
+ maWarningBox.SelectEntryPos( (USHORT)pData->nWarningOut );
+ maWarningBox.Show();
+ maWarningBox.SetPosSizePixel( LogicToPixel( Point( 115, 220 ), aAppMap ),
+ LogicToPixel( Size( 95, 80 ), aAppMap ) );
+ }
+
+ {
+ maErrorText.Show();
+ maErrorText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Error" ) ) );
+ maErrorText.SetPosSizePixel( LogicToPixel( Point( 220, 210 ), aAppMap ),
+ LogicToPixel( Size( 95, 9 ), aAppMap ) );
+ }
+
+ {
+ if ( DbgIsAllErrorOut() )
+ {
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
+ mnErrorOff = 0;
+ }
+ else
+ mnErrorOff = 4;
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
+ maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) );
+ maErrorBox.SelectEntryPos( (USHORT)pData->nErrorOut-mnErrorOff );
+ maErrorBox.Show();
+ maErrorBox.SetPosSizePixel( LogicToPixel( Point( 220, 220 ), aAppMap ),
+ LogicToPixel( Size( 95, 80 ), aAppMap ) );
+ }
+
+ {
+ maBox4.Show();
+ maBox4.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Output" ) ) );
+ maBox4.SetPosSizePixel( LogicToPixel( Point( 5, 120 ), aAppMap ),
+ LogicToPixel( Size( 330, 120 ), aAppMap ) );
+ }
+
+ {
+ maOKButton.Show();
+ maOKButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
+ maOKButton.SetPosSizePixel( LogicToPixel( Point( 10, 245 ), aAppMap ),
+ LogicToPixel( Size( 50, 15 ), aAppMap ) );
+ }
+ {
+ maCancelButton.Show();
+ maCancelButton.SetPosSizePixel( LogicToPixel( Point( 70, 245 ), aAppMap ),
+ LogicToPixel( Size( 50, 15 ), aAppMap ) );
+ }
+ {
+ maInfoButton.Show();
+ maInfoButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
+ maInfoButton.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Info..." ) ) );
+ maInfoButton.SetPosSizePixel( LogicToPixel( Point( 130, 245 ), aAppMap ),
+ LogicToPixel( Size( 50, 15 ), aAppMap ) );
+ }
+ {
+ maHelpButton.Show();
+ maHelpButton.SetPosSizePixel( LogicToPixel( Point( 190, 245 ), aAppMap ),
+ LogicToPixel( Size( 50, 15 ), aAppMap ) );
+ }
+
+ {
+#ifdef REMOTE_APPSERVER
+ SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL Debug Options (Server)" ) ) );
+#else
+ SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL Debug Options" ) ) );
+#endif
+ SetOutputSizePixel( LogicToPixel( Size( 340, 265 ), aAppMap ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( DbgDialog, ClickHdl, Button*, pButton )
+{
+ if ( pButton == &maOKButton )
+ {
+ DbgData aData;
+
+ memcpy( &aData, DbgGetData(), sizeof( DbgData ) );
+ aData.nTestFlags = 0;
+
+ aData.nTraceOut = maTraceBox.GetSelectEntryPos();
+ aData.nWarningOut = maWarningBox.GetSelectEntryPos();
+ aData.nErrorOut = maErrorBox.GetSelectEntryPos()+mnErrorOff;
+
+ strncpy( aData.aDebugName, ByteString( maDebugName.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aDebugName ) );
+ strncpy( aData.aInclClassFilter, ByteString( maInclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclClassFilter ) );
+ strncpy( aData.aExclClassFilter, ByteString( maExclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclClassFilter ) );
+ strncpy( aData.aInclFilter, ByteString( maInclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclFilter ) );
+ strncpy( aData.aExclFilter, ByteString( maExclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclFilter ) );
+ aData.aDebugName[sizeof( aData.aDebugName )-1] = '\0';
+ aData.aInclClassFilter[sizeof( aData.aInclClassFilter )-1] = '\0';
+ aData.aExclClassFilter[sizeof( aData.aExclClassFilter )-1] = '\0';
+ aData.aInclFilter[sizeof( aData.aInclFilter )-1] = '\0';
+ aData.aExclFilter[sizeof( aData.aExclFilter )-1] = '\0';
+
+ if ( maOverwrite.IsChecked() )
+ aData.bOverwrite = TRUE;
+ else
+ aData.bOverwrite = FALSE;
+
+ if ( maXtorThis.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_XTOR_THIS;
+
+ if ( maXtorFunc.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_XTOR_FUNC;
+
+ if ( maXtorExit.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_XTOR_EXIT;
+
+ if ( maXtorReport.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_XTOR_REPORT;
+
+ if ( maXtorTrace.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_XTOR_TRACE;
+
+ if ( maMemInit.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_INIT;
+
+ if ( maMemOverwrite.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_OVERWRITE;
+
+ if ( maMemOverwriteFree.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_OVERWRITEFREE;
+
+ if ( maMemPtr.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_POINTER;
+
+ if ( maMemReport.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_REPORT;
+
+ if ( maMemTrace.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_TRACE;
+
+ if ( maMemLeakReport.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_LEAKREPORT;
+
+ if ( maMemNewDel.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_NEWDEL;
+
+ if ( maMemXtor.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_XTOR;
+
+ if ( maMemSysAlloc.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_MEM_SYSALLOC;
+
+ if ( maProf.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_PROFILING;
+
+ if ( maRes.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_RESOURCE;
+
+ if ( maDialog.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_DIALOG;
+
+ if ( maBoldAppFont.IsChecked() )
+ aData.nTestFlags |= DBG_TEST_BOLDAPPFONT;
+
+ // Fensterposition mit abspeichern
+ DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
+ if ( pDbgWindow )
+ {
+ ByteString aState = pDbgWindow->GetWindowState();
+ if ( aState.Len() < sizeof( aData.aDbgWinState ) )
+ memcpy( aData.aDbgWinState, aState.GetBuffer(), aState.Len() );
+ }
+
+ // Daten speichern
+ DbgSaveData( aData );
+
+ // Umschalten der Laufzeitwerte
+ DBG_INSTOUTTRACE( aData.nTraceOut );
+ DBG_INSTOUTWARNING( aData.nWarningOut );
+ DBG_INSTOUTERROR( aData.nErrorOut );
+
+ DbgData* pData = DbgGetData();
+ pData->nTestFlags &= ~(DBG_TEST_XTOR_TRACE | DBG_TEST_MEM_INIT | DBG_TEST_RESOURCE | DBG_TEST_DIALOG | DBG_TEST_BOLDAPPFONT);
+ pData->nTestFlags |= aData.nTestFlags & (DBG_TEST_XTOR_TRACE | DBG_TEST_MEM_INIT | DBG_TEST_RESOURCE | DBG_TEST_DIALOG | DBG_TEST_BOLDAPPFONT);
+ strcpy( pData->aInclClassFilter, aData.aInclClassFilter );
+ strcpy( pData->aExclClassFilter, aData.aExclClassFilter );
+ strcpy( pData->aInclFilter, aData.aInclFilter );
+ strcpy( pData->aExclFilter, aData.aExclFilter );
+ if ( maBoldAppFont.GetSavedValue() != maBoldAppFont.IsChecked() )
+ {
+ AllSettings aSettings = Application::GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ Font aFont = aStyleSettings.GetAppFont();
+ if ( maBoldAppFont.IsChecked() )
+ aFont.SetWeight( WEIGHT_BOLD );
+ else
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aStyleSettings.SetAppFont( aFont );
+ aSettings.SetStyleSettings( aStyleSettings );
+ Application::SetSettings( aSettings );
+ }
+ EndDialog( TRUE );
+ }
+ else if ( pButton == &maInfoButton )
+ {
+ DbgInfoDialog aInfoDialog( this );
+ aDbgInfoBuf[0] = '\0';
+ DbgMemInfo( aDbgInfoBuf );
+ DbgXtorInfo( aDbgInfoBuf );
+ XubString aInfoText( aDbgInfoBuf, RTL_TEXTENCODING_UTF8 );
+ aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug InfoReport" ) ) );
+ aInfoDialog.SetInfoText( aInfoText );
+ aInfoDialog.Execute();
+ }
+ else if ( pButton == &maMemSysAlloc )
+ {
+ BOOL bEnable = maMemSysAlloc.IsChecked() == 0;
+ maMemInit.Enable( bEnable );
+ maMemOverwrite.Enable( bEnable );
+ maMemOverwriteFree.Enable( bEnable );
+ maMemPtr.Enable( bEnable );
+ maMemReport.Enable( bEnable );
+ maMemTrace.Enable( bEnable );
+ maMemLeakReport.Enable( bEnable );
+ maMemNewDel.Enable( bEnable );
+ maMemXtor.Enable( bEnable );
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgDialog::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & HELPMODE_CONTEXT )
+ {
+ DbgInfoDialog aInfoDialog( this, TRUE );
+ XubString aHelpText;
+ sal_Char** pHelpStrs = pDbgHelpText;
+ while ( *pHelpStrs )
+ {
+ aHelpText.AppendAscii( *pHelpStrs );
+ pHelpStrs++;
+ }
+ aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug Hilfe" ) ) );
+ aInfoDialog.SetInfoText( aHelpText );
+ aInfoDialog.Execute();
+ }
+}
+
+// =======================================================================
+
+DbgInfoDialog::DbgInfoDialog( Window* pParent, BOOL bHelpText ) :
+ ModalDialog( pParent, WB_STDMODAL ),
+ maListBox( this, WB_BORDER | WB_AUTOHSCROLL ),
+ maOKButton( this, WB_DEFBUTTON )
+{
+ mbHelpText = bHelpText;
+
+ if ( !bHelpText )
+ {
+ Font aFont = System::GetStandardFont( STDFONT_FIXED );
+ aFont.SetHeight( 8 );
+ aFont.SetPitch( PITCH_FIXED );
+ maListBox.SetControlFont( aFont );
+ }
+ maListBox.SetPosSizePixel( Point( 5, 5 ), Size( 630, 380 ) );
+ maListBox.Show();
+
+ maOKButton.SetPosSizePixel( Point( 290, 390 ), Size( 60, 25 ) );
+ maOKButton.Show();
+
+ SetOutputSizePixel( Size( 640, 420 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void DbgInfoDialog::SetInfoText( const XubString& rStr )
+{
+ maListBox.SetUpdateMode( FALSE );
+ maListBox.Clear();
+ XubString aStr = rStr;
+ aStr.ConvertLineEnd( LINEEND_LF );
+ USHORT nIndex = 0;
+ USHORT nFoundIndex;
+ do
+ {
+ nFoundIndex = aStr.Search( _LF, nIndex );
+ XubString aTextParagraph = aStr.Copy( nIndex, nFoundIndex-nIndex );
+ if ( mbHelpText )
+ {
+ long nMaxWidth = maListBox.GetOutputSizePixel().Width()-30;
+ USHORT nLastIndex = 0;
+ USHORT nIndex = aTextParagraph.Search( ' ' );
+ while ( nIndex != STRING_NOTFOUND )
+ {
+ if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
+ {
+ if ( !nLastIndex )
+ nLastIndex = nIndex+1;
+ XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex );
+ aTextParagraph.Erase( 0, nLastIndex );
+ maListBox.InsertEntry( aTempStr );
+ nLastIndex = 0;
+ }
+ else
+ nLastIndex = nIndex+1;
+ nIndex = aTextParagraph.Search( ' ', nLastIndex );
+ }
+
+ if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
+ {
+ if ( !nLastIndex )
+ nLastIndex = nIndex+1;
+ XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex );
+ aTextParagraph.Erase( 0, nLastIndex );
+ maListBox.InsertEntry( aTempStr );
+ }
+ }
+ maListBox.InsertEntry( aTextParagraph );
+ nIndex = nFoundIndex+1;
+ }
+ while ( nFoundIndex != STRING_NOTFOUND );
+ maListBox.SetUpdateMode( TRUE );
+}
+
+// =======================================================================
+
+void DbgDialogTest( Window* pWindow )
+{
+ BOOL aAccelBuf[65536];
+ USHORT nChildCount = pWindow->GetChildCount();
+ Window* pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ Window* pChild;
+ Point aTabPos;
+
+ if ( !pGetChild )
+ return;
+
+ Rectangle* pRectAry = (Rectangle*)new long[(sizeof(Rectangle)*nChildCount)/sizeof(long)];
+ memset( aAccelBuf, 0, sizeof( aAccelBuf ) );
+ memset( pRectAry, 0, sizeof(Rectangle)*nChildCount );
+
+ if ( pWindow->IsDialog() )
+ {
+ BOOL bOKCancelButton = FALSE;
+ BOOL bDefPushButton = FALSE;
+ BOOL bButton = FALSE;
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+
+ if ( pChild->ImplIsPushButton() )
+ {
+ bButton = TRUE;
+ if ( (pChild->GetType() == WINDOW_OKBUTTON) || (pChild->GetType() == WINDOW_CANCELBUTTON) )
+ bOKCancelButton = TRUE;
+ if ( pChild->GetStyle() & WB_DEFBUTTON )
+ bDefPushButton = TRUE;
+ }
+
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+
+ if ( bButton )
+ {
+ if ( !bOKCancelButton )
+ DbgError( "Dialogs should have a OK- or CancelButton" );
+ if ( !bDefPushButton )
+ DbgError( "Dialogs should have a Button with WB_DEFBUTTON" );
+ }
+ }
+
+ USHORT i = 0;
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+
+ if ( (pChild->GetType() != WINDOW_TABCONTROL) &&
+ (pChild->GetType() != WINDOW_TABPAGE) &&
+ (pChild->GetType() != WINDOW_GROUPBOX) )
+ {
+ XubString aText = pChild->GetText();
+ USHORT nAccelPos;
+ xub_Unicode cAccel = 0;
+ if ( aText.Len() )
+ {
+ nAccelPos = aText.Search( '~' );
+ if ( nAccelPos != STRING_NOTFOUND )
+ {
+ const International& rIntn = Application::GetSettings().GetInternational();
+ XubString aUpperText = rIntn.Upper( aText );
+ cAccel = aUpperText.GetChar( nAccelPos+1 );
+ if ( pChild->IsVisible() )
+ {
+ if ( aAccelBuf[cAccel] )
+ DbgOutTypef( DBG_OUT_ERROR, "Double mnemonic char: %c", cAccel );
+ else
+ aAccelBuf[cAccel] = TRUE;
+ }
+ }
+ }
+
+ if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_CHECKBOX) ||
+ (pChild->GetType() == WINDOW_TRISTATEBOX) ||
+ (pChild->GetType() == WINDOW_PUSHBUTTON) )
+ {
+ if ( !cAccel && aText.Len() && !aText.EqualsAscii( "..." ) )
+ {
+ const char* pClass;
+ if ( pChild->GetType() == WINDOW_RADIOBUTTON )
+ pClass = "RadioButton";
+ else if ( pChild->GetType() == WINDOW_IMAGERADIOBUTTON )
+ pClass = "ImageRadioButton";
+ else if ( pChild->GetType() == WINDOW_CHECKBOX )
+ pClass = "CheckBox";
+ else if ( pChild->GetType() == WINDOW_TRISTATEBOX )
+ pClass = "TriStateBox";
+ else if ( pChild->GetType() == WINDOW_PUSHBUTTON )
+ pClass = "PushButton";
+ else
+ pClass = "Dontknow";
+ DbgOutTypef( DBG_OUT_ERROR,
+ "%s should have a mnemonic char (~): %s",
+ pClass,
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ }
+
+ if ( pChild->GetType() == WINDOW_FIXEDTEXT )
+ {
+ if ( (pChild->GetSizePixel().Height() >= pChild->GetTextHeight()*2) &&
+ !(pChild->GetStyle() & WB_WORDBREAK) )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "FixedText greater than one line, but WordBreak is not set: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+
+ if ( (i+1 < nChildCount) && aText.Len() )
+ {
+ Window* pTempChild = pGetChild->GetWindow( WINDOW_NEXT )->ImplGetWindow();
+ if ( (pTempChild->GetType() == WINDOW_EDIT) ||
+ (pTempChild->GetType() == WINDOW_MULTILINEEDIT) ||
+ (pTempChild->GetType() == WINDOW_SPINFIELD) ||
+ (pTempChild->GetType() == WINDOW_PATTERNFIELD) ||
+ (pTempChild->GetType() == WINDOW_NUMERICFIELD) ||
+ (pTempChild->GetType() == WINDOW_METRICFIELD) ||
+ (pTempChild->GetType() == WINDOW_CURRENCYFIELD) ||
+ (pTempChild->GetType() == WINDOW_DATEFIELD) ||
+ (pTempChild->GetType() == WINDOW_TIMEFIELD) ||
+ (pTempChild->GetType() == WINDOW_LISTBOX) ||
+ (pTempChild->GetType() == WINDOW_MULTILISTBOX) ||
+ (pTempChild->GetType() == WINDOW_COMBOBOX) ||
+ (pTempChild->GetType() == WINDOW_PATTERNBOX) ||
+ (pTempChild->GetType() == WINDOW_NUMERICBOX) ||
+ (pTempChild->GetType() == WINDOW_METRICBOX) ||
+ (pTempChild->GetType() == WINDOW_CURRENCYBOX) ||
+ (pTempChild->GetType() == WINDOW_DATEBOX) ||
+ (pTempChild->GetType() == WINDOW_TIMEBOX) )
+ {
+ if ( !cAccel )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "Labels befor Fields (Edit,ListBox,...) should have a mnemonic char (~): %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ if ( !pTempChild->IsEnabled() && pChild->IsEnabled() )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "Labels befor Fields (Edit,ListBox,...) should be disabled, when the field is disabled: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ }
+ }
+ }
+
+ if ( pChild->GetType() == WINDOW_MULTILINEEDIT )
+ {
+ if ( !(pChild->GetStyle() & WB_IGNORETAB) )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "MultiLineEdits in Dialogs should have the Style WB_IGNORETAB: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ }
+
+ if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_CHECKBOX) ||
+ (pChild->GetType() == WINDOW_TRISTATEBOX) ||
+ (pChild->GetType() == WINDOW_FIXEDTEXT) )
+ {
+ pChild->SetBackground( Wallpaper( Color( COL_LIGHTGREEN ) ) );
+ }
+
+ if ( pChild->IsVisible() )
+ {
+ BOOL bMaxWarning = FALSE;
+ if ( pChild->GetType() == WINDOW_NUMERICFIELD )
+ {
+ NumericField* pField = (NumericField*)pChild;
+ if ( pField->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_METRICFIELD )
+ {
+ MetricField* pField = (MetricField*)pChild;
+ if ( pField->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_CURRENCYFIELD )
+ {
+ CurrencyField* pField = (CurrencyField*)pChild;
+ if ( pField->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_TIMEFIELD )
+ {
+ TimeField* pField = (TimeField*)pChild;
+ if ( pField->GetMax() == Time( 23, 59, 59, 99 ) )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_DATEFIELD )
+ {
+ DateField* pField = (DateField*)pChild;
+ if ( pField->GetMax() == Date( 31, 12, 9999 ) )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_NUMERICBOX )
+ {
+ NumericBox* pBox = (NumericBox*)pChild;
+ if ( pBox->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_METRICBOX )
+ {
+ MetricBox* pBox = (MetricBox*)pChild;
+ if ( pBox->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_CURRENCYBOX )
+ {
+ CurrencyBox* pBox = (CurrencyBox*)pChild;
+ if ( pBox->GetMax() == LONG_MAX )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_TIMEBOX )
+ {
+ TimeBox* pBox = (TimeBox*)pChild;
+ if ( pBox->GetMax() == Time( 23, 59, 59, 99 ) )
+ bMaxWarning = TRUE;
+ }
+ else if ( pChild->GetType() == WINDOW_DATEBOX )
+ {
+ DateBox* pBox = (DateBox*)pChild;
+ if ( pBox->GetMax() == Date( 31, 12, 9999 ) )
+ bMaxWarning = TRUE;
+ }
+ if ( bMaxWarning )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "No Max-Value is set: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+
+ if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_CHECKBOX) ||
+ (pChild->GetType() == WINDOW_TRISTATEBOX) ||
+ (pChild->GetType() == WINDOW_PUSHBUTTON) ||
+ (pChild->GetType() == WINDOW_OKBUTTON) ||
+ (pChild->GetType() == WINDOW_CANCELBUTTON) ||
+ (pChild->GetType() == WINDOW_HELPBUTTON) ||
+ (pChild->GetType() == WINDOW_IMAGEBUTTON) ||
+ (pChild->GetType() == WINDOW_FIXEDTEXT) ||
+ (pChild->GetType() == WINDOW_EDIT) ||
+ (pChild->GetType() == WINDOW_MULTILINEEDIT) ||
+ (pChild->GetType() == WINDOW_SPINFIELD) ||
+ (pChild->GetType() == WINDOW_PATTERNFIELD) ||
+ (pChild->GetType() == WINDOW_NUMERICFIELD) ||
+ (pChild->GetType() == WINDOW_METRICFIELD) ||
+ (pChild->GetType() == WINDOW_CURRENCYFIELD) ||
+ (pChild->GetType() == WINDOW_DATEFIELD) ||
+ (pChild->GetType() == WINDOW_TIMEFIELD) ||
+ (pChild->GetType() == WINDOW_LISTBOX) ||
+ (pChild->GetType() == WINDOW_MULTILISTBOX) ||
+ (pChild->GetType() == WINDOW_COMBOBOX) ||
+ (pChild->GetType() == WINDOW_PATTERNBOX) ||
+ (pChild->GetType() == WINDOW_NUMERICBOX) ||
+ (pChild->GetType() == WINDOW_METRICBOX) ||
+ (pChild->GetType() == WINDOW_CURRENCYBOX) ||
+ (pChild->GetType() == WINDOW_DATEBOX) ||
+ (pChild->GetType() == WINDOW_TIMEBOX) )
+ {
+ Point aNewPos = pChild->GetPosPixel();
+ Rectangle aChildRect( aNewPos, pChild->GetSizePixel() );
+
+ if ( cAccel || (pChild->GetStyle() & WB_TABSTOP) ||
+ (pChild->GetType() == WINDOW_RADIOBUTTON) ||
+ (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) )
+ {
+ if ( (aNewPos.X() <= aTabPos.X()) && (aNewPos.Y() <= aTabPos.Y()) )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "Possible wrong childorder for dialogcontrol: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ aTabPos = aNewPos;
+ }
+
+ for ( USHORT j = 0; j < i; j++ )
+ {
+ if ( ((pRectAry[j].Right() != 0) || (pRectAry[j].Bottom() != 0)) &&
+ aChildRect.IsOver( pRectAry[j] ) )
+ {
+ DbgOutTypef( DBG_OUT_ERROR,
+ "Window overlaps with sibling window: %s",
+ ByteString( aText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
+ }
+ }
+ pRectAry[i] = aChildRect;
+ }
+ }
+ }
+
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ i++;
+ }
+
+ delete pRectAry;
+}
+
+// =======================================================================
+
+void DbgPrintMsgBox( const char* pLine )
+{
+ if ( Application::IsDialogCancelEnabled() )
+ {
+#if defined( WNT )
+ if ( GetSystemMetrics( SM_DEBUG ) )
+ {
+ strcpy( aDbgOutBuf, pLine );
+ strcat( aDbgOutBuf, "\r\n" );
+ OutputDebugString( aDbgOutBuf );
+ return;
+ }
+#endif
+#ifdef UNX
+ fprintf( stderr, "%s\n", pLine );
+ return;
+#else
+ DbgPrintFile( pLine );
+ return;
+#endif
+ }
+
+ strcpy( aDbgOutBuf, pLine );
+ strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=core dump)" );
+
+ // Tracking beenden und Mouse freigeben, damit die Boxen nicht haengen
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ if ( pSVData->maWinData.mpCaptureWin )
+ pSVData->maWinData.mpCaptureWin->ReleaseMouse();
+
+#ifndef REMOTE_APPSERVER
+#if defined( WNT )
+ BOOL bOldCallTimer = pSVData->mbNoCallTimer;
+ pSVData->mbNoCallTimer = TRUE;
+ short nRet = (short)MessageBox( 0, (LPSTR)aDbgOutBuf, "Debug Output",
+ MB_TASKMODAL | MB_YESNOCANCEL |
+ MB_DEFBUTTON2 | MB_ICONSTOP );
+ MessageBeep( MB_ICONHAND );
+ pSVData->mbNoCallTimer = bOldCallTimer;
+ switch ( nRet )
+ {
+ case IDYES:
+ nRet = RET_YES;
+ break;
+ case IDNO:
+ nRet = RET_NO;
+ break;
+ case IDCANCEL:
+ nRet = RET_CANCEL;
+ break;
+ }
+#elif defined( OS2 )
+ BOOL bOldCallTimer = pSVData->mbNoCallTimer;
+ pSVData->mbNoCallTimer = TRUE;
+ PM_ULONG nRet = WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
+ (PSZ)aDbgOutBuf, (PSZ)"Debug Output", 0,
+ MB_APPLMODAL | MB_MOVEABLE |
+ MB_YESNOCANCEL | MB_DEFBUTTON2 |
+ MB_ERROR );
+ pSVData->mbNoCallTimer = bOldCallTimer;
+ switch ( nRet )
+ {
+ case MBID_YES:
+ nRet = RET_YES;
+ break;
+ case MBID_NO:
+ nRet = RET_NO;
+ break;
+ case MBID_CANCEL:
+ nRet = RET_CANCEL;
+ break;
+ }
+#else
+ USHORT nOldMode = Application::GetSystemWindowMode();
+ Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
+ ErrorBox aBox( Application::GetAppWindow(), WB_YES_NO_CANCEL | WB_DEF_NO,
+ UniString( aDbgOutBuf, RTL_TEXTENCODING_UTF8 ) );
+ aBox.SetText( String( RTL_CONSTASCII_USTRINGPARAM("Debug Output") ) );
+ Application::SetSystemWindowMode( nOldMode );
+ short nRet = aBox.Execute();
+#endif
+#else
+ USHORT nOldMode = Application::GetSystemWindowMode();
+ Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
+ ErrorBox aBox( Application::GetAppWindow(), WB_YES_NO_CANCEL | WB_DEF_NO,
+ UniString( aDbgOutBuf, RTL_TEXTENCODING_UTF8 ) );
+ aBox.SetText( String( RTL_CONSTASCII_USTRINGPARAM("Debug Output (Server)") ) );
+ Application::SetSystemWindowMode( nOldMode );
+ short nRet = aBox.Execute();
+#endif
+
+ if ( nRet == RET_YES )
+ GetpApp()->Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug-Utilities-Error" ) ) );
+ else if ( nRet == RET_CANCEL )
+ DbgCoreDump();
+}
+
+// -----------------------------------------------------------------------
+
+void DbgPrintWindow( const char* pLine )
+{
+ static BOOL bIn = FALSE;
+
+ // keine rekursiven Traces
+ if ( bIn )
+ return;
+ bIn = TRUE;
+
+ DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
+ if ( !pDbgWindow )
+ {
+ pDbgWindow = new DbgWindow;
+ ImplGetSVData()->maWinData.mpDbgWin = pDbgWindow;
+ }
+
+ pDbgWindow->InsertLine( XubString( pLine, RTL_TEXTENCODING_UTF8 ) );
+
+ bIn = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgPrintShell( const char* pLine )
+{
+#if defined( WNT )
+ if ( GetSystemMetrics( SM_DEBUG ) )
+ {
+ strcpy( aDbgOutBuf, pLine );
+ strcat( aDbgOutBuf, "\r\n" );
+ OutputDebugString( aDbgOutBuf );
+ return;
+ }
+#endif
+#ifdef UNX
+ fprintf( stderr, "%s\n", pLine );
+ return;
+#endif
+
+ DbgPrintWindow( pLine );
+}
+
+// =======================================================================
+
+#if defined( REMOTE_APPSERVER ) || defined( WNT ) || defined( OS2 )
+void ImplDbgTestSolarMutex();
+#endif
+
+// =======================================================================
+
+void DbgGUIInit()
+{
+ DbgSetPrintMsgBox( DbgPrintMsgBox );
+ DbgSetPrintWindow( DbgPrintWindow );
+ DbgSetPrintShell( DbgPrintShell );
+#if defined( REMOTE_APPSERVER ) || defined( WNT ) || defined( OS2 )
+ DbgSetTestSolarMutex( ImplDbgTestSolarMutex );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void DbgGUIDeInit()
+{
+ DbgSetPrintMsgBox( NULL );
+ DbgSetPrintWindow( NULL );
+ DbgSetPrintShell( NULL );
+#if defined( REMOTE_APPSERVER ) || defined( WNT ) || defined( OS2 )
+ DbgSetTestSolarMutex( NULL );
+#endif
+
+ DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
+ if ( pDbgWindow )
+ delete pDbgWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void DbgGUIStart()
+{
+ DbgData* pData = DbgGetData();
+
+ if ( pData )
+ {
+ DbgDialog* pDialog = new DbgDialog;
+ // Fuer den Debug-Dialog schalten wir Dialogtests aus
+ ULONG nOldFlags = pData->nTestFlags;
+ pData->nTestFlags &= ~DBG_TEST_DIALOG;
+ if ( !pDialog->Execute() )
+ pData->nTestFlags |= (nOldFlags & DBG_TEST_DIALOG);
+ delete pDialog;
+ }
+ else
+ {
+ ErrorBox( 0, WB_OK,
+ XubString( RTL_CONSTASCII_USTRINGPARAM( "TOOLS Library has no Debug-Routines" ) ) ).Execute();
+ }
+}
+
+#endif // DBG_UTIL
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
new file mode 100644
index 000000000000..91343819c168
--- /dev/null
+++ b/vcl/source/app/help.cxx
@@ -0,0 +1,686 @@
+/*************************************************************************
+ *
+ * $RCSfile: help.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_HELP_CXX
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_HELPWIN_HXX
+#include <helpwin.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define HELPWINSTYLE_QUICK 0
+#define HELPWINSTYLE_BALLOON 1
+
+#define HELPTEXTMARGIN_QUICK 3
+#define HELPTEXTMARGIN_BALLOON 6
+
+#define HELPDELAY_NORMAL 1
+#define HELPDELAY_SHORT 2
+#define HELPDELAY_NONE 3
+
+// =======================================================================
+
+Help::Help()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::Start( ULONG )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::Start( const XubString& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Help::GetHelpText( ULONG nHelpId )
+{
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void Help::EnableContextHelp()
+{
+ ImplGetSVData()->maHelpData.mbContextHelp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::DisableContextHelp()
+{
+ ImplGetSVData()->maHelpData.mbContextHelp = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::IsContextHelpEnabled()
+{
+ return ImplGetSVData()->maHelpData.mbContextHelp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::StartContextHelp()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maHelpData.mbContextHelp )
+ {
+ Window* pWindow = pSVData->maWinData.mpFocusWin;
+ if ( pWindow )
+ {
+ Point aMousePos = pWindow->OutputToScreenPixel( pWindow->GetPointerPosPixel() );
+ HelpEvent aHelpEvent( aMousePos, HELPMODE_CONTEXT );
+ pWindow->RequestHelp( aHelpEvent );
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::EnableExtHelp()
+{
+ ImplGetSVData()->maHelpData.mbExtHelp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::DisableExtHelp()
+{
+ ImplGetSVData()->maHelpData.mbExtHelp = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::IsExtHelpEnabled()
+{
+ return ImplGetSVData()->maHelpData.mbExtHelp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::StartExtHelp()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maHelpData.mbExtHelp && !pSVData->maHelpData.mbExtHelpMode )
+ {
+ pSVData->maHelpData.mbExtHelpMode = TRUE;
+ pSVData->maHelpData.mbOldBalloonMode = pSVData->maHelpData.mbBalloonHelp;
+ pSVData->maHelpData.mbBalloonHelp = TRUE;
+ if ( pSVData->maWinData.mpAppWin )
+ pSVData->maWinData.mpAppWin->ImplGenerateMouseMove();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::EndExtHelp()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maHelpData.mbExtHelp && pSVData->maHelpData.mbExtHelpMode )
+ {
+ pSVData->maHelpData.mbExtHelpMode = FALSE;
+ pSVData->maHelpData.mbBalloonHelp = pSVData->maHelpData.mbOldBalloonMode;
+ if ( pSVData->maWinData.mpAppWin )
+ pSVData->maWinData.mpAppWin->ImplGenerateMouseMove();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::IsExtHelpActive()
+{
+ return ImplGetSVData()->maHelpData.mbExtHelpMode;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::EnableBalloonHelp()
+{
+ ImplGetSVData()->maHelpData.mbBalloonHelp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::DisableBalloonHelp()
+{
+ ImplGetSVData()->maHelpData.mbBalloonHelp = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::IsBalloonHelpEnabled()
+{
+ return ImplGetSVData()->maHelpData.mbBalloonHelp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::ShowBalloon( Window* pParent,
+ const Point& rScreenPos,
+ const XubString& rHelpText )
+{
+ ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0,
+ rHelpText, ImplGetSVEmptyStr(), rScreenPos );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::ShowBalloon( Window* pParent,
+ const Point& rScreenPos, const Rectangle& rRect,
+ const XubString& rHelpText )
+{
+ ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0,
+ rHelpText, ImplGetSVEmptyStr(), rScreenPos, &rRect );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::EnableQuickHelp()
+{
+ ImplGetSVData()->maHelpData.mbQuickHelp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::DisableQuickHelp()
+{
+ ImplGetSVData()->maHelpData.mbQuickHelp = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::IsQuickHelpEnabled()
+{
+ return ImplGetSVData()->maHelpData.mbQuickHelp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Help::ShowQuickHelp( Window* pParent,
+ const Rectangle& rScreenRect,
+ const XubString& rHelpText,
+ const XubString& rLongHelpText,
+ USHORT nStyle )
+{
+ ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle,
+ rHelpText, rLongHelpText,
+ pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Help::ShowTip( Window* pParent, const Rectangle& rRect,
+ const XubString& rText, USHORT nStyle )
+{
+ USHORT nHelpWinStyle = HELPWINSTYLE_QUICK;
+ HelpTextWindow* pHelpWin = new HelpTextWindow( pParent, rText, nHelpWinStyle, nStyle );
+
+ Size aSz = pHelpWin->CalcOutSize();
+ pHelpWin->SetOutputSizePixel( aSz );
+ ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle,
+ pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rRect );
+ pHelpWin->ShowHelp( HELPDELAY_NONE );
+ return (ULONG)pHelpWin;
+}
+
+// -----------------------------------------------------------------------
+
+void Help::HideTip( ULONG nId )
+{
+ HelpTextWindow* pHelpWin = (HelpTextWindow*)nId;
+ Window* pFrameWindow = pHelpWin->ImplGetFrameWindow();
+ pHelpWin->Hide();
+ // Update ausloesen, damit ein Paint sofort ausgeloest wird, da
+ // wir den Hintergrund nicht sichern
+ pFrameWindow->ImplUpdateAll();
+ delete pHelpWin;
+}
+
+// =======================================================================
+
+HelpTextWindow::HelpTextWindow( Window* pParent, const XubString& rText, USHORT nHelpWinStyle, USHORT nStyle ) :
+ FloatingWindow( pParent->ImplGetFrameWindow(), 0 ),
+ maHelpText( rText )
+{
+ ImplSetMouseTransparent( TRUE );
+ mnHelpWinStyle = nHelpWinStyle;
+ mnStyle = nStyle;
+
+ EnableAlwaysOnTop();
+ EnableSaveBackground();
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetPointFont( rStyleSettings.GetHelpFont() );
+ SetTextColor( rStyleSettings.GetHelpTextColor() );
+ SetTextAlign( ALIGN_TOP );
+ SetBackground( Wallpaper( rStyleSettings.GetHelpColor() ) );
+ SetLineColor( COL_BLACK );
+ SetFillColor();
+
+ if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
+ {
+ Size aSize;
+ aSize.Height() = GetTextHeight();
+ if ( mnStyle & QUICKHELP_CTRLTEXT )
+ aSize.Width() = GetCtrlTextWidth( maHelpText );
+ else
+ aSize.Width() = GetTextWidth( maHelpText );
+ maTextRect = Rectangle( Point( HELPTEXTMARGIN_QUICK, HELPTEXTMARGIN_QUICK ), aSize );
+ }
+ else // HELPWINSTYLE_BALLOON
+ {
+ Point aTmpPoint;
+ USHORT nCharsInLine = 35 + ((maHelpText.Len()/100)*5);
+ XubString aXXX;
+ aXXX.Fill( nCharsInLine, 'x' ); // Durchschnittliche Breite, damit nicht jedes Fenster anders.
+ long nWidth = GetTextWidth( aXXX );
+ Size aTmpSize( nWidth, 0x7FFFFFFF );
+ Rectangle aTry1( aTmpPoint, aTmpSize );
+ USHORT nDrawFlags = TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK |
+ TEXT_DRAW_LEFT | TEXT_DRAW_TOP;
+ if ( mnStyle & QUICKHELP_CTRLTEXT )
+ nDrawFlags |= TEXT_DRAW_MNEMONIC;
+ Rectangle aTextRect = GetTextRect( aTry1, maHelpText, nDrawFlags );
+
+ // Spaeter mal eine geeignete Breite ermitteln...
+ maTextRect = aTextRect;
+
+ // Sicherheitsabstand...
+ maTextRect.SetPos( Point( HELPTEXTMARGIN_BALLOON, HELPTEXTMARGIN_BALLOON ) );
+ }
+
+ const HelpSettings& rHelpSettings = GetSettings().GetHelpSettings();
+ maShowTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
+ maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
+ maHideTimer.SetTimeout( rHelpSettings.GetTipTimeout() );
+}
+
+// -----------------------------------------------------------------------
+
+HelpTextWindow::~HelpTextWindow()
+{
+ maShowTimer.Stop();
+ maHideTimer.Stop();
+
+ if ( maStatusText.Len() )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpApp->HideHelpStatusText();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HelpTextWindow::ImplShow()
+{
+ if ( maStatusText.Len() )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpApp->ShowHelpStatusText( maStatusText );
+ }
+ Show();
+ Update();
+}
+
+// -----------------------------------------------------------------------
+
+void HelpTextWindow::Paint( const Rectangle& )
+{
+ // Border zeichen
+ // .....
+
+ if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
+ {
+ if ( mnStyle & QUICKHELP_CTRLTEXT )
+ DrawCtrlText( maTextRect.TopLeft(), maHelpText );
+ else
+ DrawText( maTextRect.TopLeft(), maHelpText );
+ }
+ else // HELPWINSTYLE_BALLOON
+ {
+ USHORT nDrawFlags = TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK|
+ TEXT_DRAW_LEFT|TEXT_DRAW_TOP;
+ if ( mnStyle & QUICKHELP_CTRLTEXT )
+ nDrawFlags |= TEXT_DRAW_MNEMONIC;
+ DrawText( maTextRect, maHelpText, nDrawFlags );
+ }
+
+ // Umrandung
+ Size aSz = GetOutputSizePixel();
+ DrawRect( Rectangle( Point(), aSz ) );
+ if ( mnHelpWinStyle == HELPWINSTYLE_BALLOON )
+ {
+ aSz.Width() -= 2;
+ aSz.Height() -= 2;
+ Color aColor( GetLineColor() );
+ SetLineColor( ( COL_GRAY ) );
+ DrawRect( Rectangle( Point( 1, 1 ), aSz ) );
+ SetLineColor( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HelpTextWindow::ShowHelp( USHORT nDelayMode )
+{
+ ULONG nTimeout = 0;
+ if ( nDelayMode != HELPDELAY_NONE )
+ {
+ // Im ExtendedHelp-Fall die Hilfe schneller anzeigen
+ if ( ImplGetSVData()->maHelpData.mbExtHelpMode )
+ nTimeout = 15;
+ else
+ {
+ const HelpSettings& rHelpSettings = GetSettings().GetHelpSettings();
+ if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
+ nTimeout = rHelpSettings.GetTipDelay();
+ else
+ nTimeout = rHelpSettings.GetBalloonDelay();
+ }
+
+ if ( nDelayMode == HELPDELAY_SHORT )
+ nTimeout /= 3;
+ }
+
+ maShowTimer.SetTimeout( nTimeout );
+ maShowTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( HelpTextWindow, TimerHdl, Timer*, pTimer)
+{
+ if ( pTimer == &maShowTimer )
+ {
+ ImplShow();
+ if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
+ {
+ // Auto-Hide nicht bei einem Tip-Fenster (ShowTip)
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( this == pSVData->maHelpData.mpHelpWin )
+ maHideTimer.Start();
+ }
+ }
+ else
+ {
+ Hide();
+ ImplDestroyHelpWindow();
+ }
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+Size HelpTextWindow::CalcOutSize() const
+{
+ Size aSz = maTextRect.GetSize();
+ aSz.Width() += 2*maTextRect.Left();
+ aSz.Height() += 2*maTextRect.Top();
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+void HelpTextWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ // Nur damit nicht von Window::RequestHelp() ein
+ // ShowQuickHelp/ShowBalloonHelp am HelpTextWindow aufgerufen wird.
+}
+
+// =======================================================================
+
+
+void ImplShowHelpWindow( Window* pParent, USHORT nHelpWinStyle, USHORT nStyle,
+ const XubString& rHelpText, const XubString& rStatusText,
+ const Point& rScreenPos, const Rectangle* pHelpArea )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin;
+ USHORT nDelayMode = HELPDELAY_NORMAL;
+ if ( pHelpWin )
+ {
+ DBG_ASSERT( pHelpWin != pParent, "HelpInHelp ?!" );
+
+ if ( ( pHelpWin->GetHelpText() != rHelpText ) ||
+ ( pHelpWin->GetWinStyle() != nHelpWinStyle ) ||
+ ( pHelpArea && ( pHelpWin->GetHelpArea() != *pHelpArea ) ) )
+ {
+ // Fenster wegnehmen wenn kein HelpText oder anderer HelpText oder
+ // anderer Modus.
+ if ( pHelpWin->IsVisible() )
+ nDelayMode = HELPDELAY_SHORT; // Wenn schon vorher Quick-Hilfe, dann jetzt auch schnell
+ pHelpWin = NULL;
+ ImplDestroyHelpWindow();
+ }
+ else if ( !pHelpWin->IsVisible() )
+ {
+ // Dann die Position der Maus annaehren...
+ ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
+ }
+ }
+
+ if ( !pHelpWin && rHelpText.Len() )
+ {
+ DBG_ASSERT( !pHelpWin, "Noch ein HelpWin ?!" );
+ pHelpWin = new HelpTextWindow( pParent, rHelpText, nHelpWinStyle, nStyle );
+ pSVData->maHelpData.mpHelpWin = pHelpWin;
+ pHelpWin->SetStatusText( rStatusText );
+ if ( pHelpArea )
+ pHelpWin->SetHelpArea( *pHelpArea );
+
+// Positionieren...
+ Size aSz = pHelpWin->CalcOutSize();
+ pHelpWin->SetOutputSizePixel( aSz );
+ ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
+ // Wenn nicht aus Window::RequestHelp, dann ohne Delay...
+ if ( !pSVData->maHelpData.mbRequestingHelp )
+ nDelayMode = HELPDELAY_NONE;
+ pHelpWin->ShowHelp( nDelayMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDestroyHelpWindow( BOOL bUpdate )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin;
+ if ( pHelpWin )
+ {
+ pSVData->maHelpData.mpHelpWin = NULL;
+ pHelpWin->Hide();
+ if ( bUpdate )
+ {
+ // Update ausloesen, damit ein Paint sofort ausgeloest wird, da
+ // wir den Hintergrund nicht sichern
+ Window* pFrameWindow = pHelpWin->ImplGetFrameWindow();
+ pFrameWindow->ImplUpdateAll();
+ }
+ delete pHelpWin;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSetHelpWindowPos( Window* pHelpWin, USHORT nHelpWinStyle, USHORT nStyle,
+ const Point& rPos, const Rectangle* pHelpArea )
+{
+ Point aPos = rPos;
+ Size aSz = pHelpWin->GetSizePixel();
+ Rectangle aScreenRect = pHelpWin->ImplGetFrameWindow()->GetDesktopRectPixel();
+ if ( nHelpWinStyle == HELPWINSTYLE_QUICK )
+ {
+ if ( !(nStyle & QUICKHELP_NOAUTOPOS) )
+ {
+ long nScreenHeight = aScreenRect.GetHeight();
+ aPos.X() -= 4;
+ if ( aPos.Y() > aScreenRect.Top()+nScreenHeight-(nScreenHeight/4) )
+ aPos.Y() -= aSz.Height()+4;
+ else
+ aPos.Y() += 21;
+ }
+ }
+ else
+ {
+ // Wenn es die Maus-Position ist, dann Fenster leicht versetzt
+ // anzeigen, damit MousePointer nicht das Hilfe-Fenster verdeckt
+ if ( aPos == pHelpWin->OutputToScreenPixel( pHelpWin->GetPointerPosPixel() ) )
+ {
+ aPos.X() += 12;
+ aPos.Y() += 16;
+ }
+ }
+
+ if ( nStyle & QUICKHELP_NOAUTOPOS )
+ {
+ if ( pHelpArea )
+ {
+ // Welche Position vom Rechteck?
+ aPos = pHelpArea->Center();
+
+ if ( nStyle & QUICKHELP_LEFT )
+ aPos.X() = pHelpArea->Left();
+ else if ( nStyle & QUICKHELP_RIGHT )
+ aPos.X() = pHelpArea->Right();
+
+ if ( nStyle & QUICKHELP_TOP )
+ aPos.Y() = pHelpArea->Top();
+ else if ( nStyle & QUICKHELP_BOTTOM )
+ aPos.Y() = pHelpArea->Bottom();
+ }
+
+ // Welche Richtung?
+ if ( nStyle & QUICKHELP_LEFT )
+ ;
+ else if ( nStyle & QUICKHELP_RIGHT )
+ aPos.X() -= aSz.Width();
+ else
+ aPos.X() -= aSz.Width()/2;
+
+ if ( nStyle & QUICKHELP_TOP )
+ ;
+ else if ( nStyle & QUICKHELP_BOTTOM )
+ aPos.Y() -= aSz.Height();
+ else
+ aPos.Y() -= aSz.Height()/2;
+ }
+
+ if ( aPos.X() < aScreenRect.Left() )
+ aPos.X() = aScreenRect.Left();
+ else if ( ( aPos.X() + aSz.Width() ) > aScreenRect.Right() )
+ aPos.X() = aScreenRect.Right() - aSz.Width();
+ if ( aPos.Y() < aScreenRect.Top() )
+ aPos.Y() = aScreenRect.Top();
+ else if ( ( aPos.Y() + aSz.Height() ) > aScreenRect.Bottom() )
+ aPos.Y() = aScreenRect.Bottom() - aSz.Height();
+
+ pHelpWin->SetPosPixel( aPos );
+}
diff --git a/vcl/source/app/idlemgr.cxx b/vcl/source/app/idlemgr.cxx
new file mode 100644
index 000000000000..e597d2680c1a
--- /dev/null
+++ b/vcl/source/app/idlemgr.cxx
@@ -0,0 +1,191 @@
+/*************************************************************************
+ *
+ * $RCSfile: idlemgr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IDLEMGR_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+
+#ifndef _SV_IDLEMGR_HXX
+#include <idlemgr.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// =======================================================================
+
+struct ImplIdleData
+{
+ Link maIdleHdl;
+ USHORT mnPriority;
+ BOOL mbTimeout;
+};
+
+DECLARE_LIST( ImplIdleList, ImplIdleData* );
+
+#define IMPL_IDLETIMEOUT 350
+
+// =======================================================================
+
+ImplIdleMgr::ImplIdleMgr()
+{
+ mpIdleList = new ImplIdleList( 8, 8, 8 );
+
+ maTimer.SetTimeout( IMPL_IDLETIMEOUT );
+ maTimer.SetTimeoutHdl( LINK( this, ImplIdleMgr, TimeoutHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+ImplIdleMgr::~ImplIdleMgr()
+{
+ // Liste loeschen
+ ImplIdleData* pIdleData = mpIdleList->First();
+ while ( pIdleData )
+ {
+ delete pIdleData;
+ pIdleData = mpIdleList->Next();
+ }
+
+ delete mpIdleList;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplIdleMgr::InsertIdleHdl( const Link& rLink, USHORT nPriority )
+{
+ ULONG nPos = LIST_APPEND;
+ ImplIdleData* pIdleData = mpIdleList->First();
+ while ( pIdleData )
+ {
+ // Wenn Link schon existiert, dann gebe FALSE zurueck
+ if ( pIdleData->maIdleHdl == rLink )
+ return FALSE;
+
+ // Nach Prioritaet sortieren
+ if ( nPriority <= pIdleData->mnPriority )
+ nPos = mpIdleList->GetCurPos();
+
+ // Schleife nicht beenden, da noch
+ // geprueft werden muss, ob sich der Link
+ // schon in der Liste befindet
+
+ pIdleData = mpIdleList->Next();
+ }
+
+ pIdleData = new ImplIdleData;
+ pIdleData->maIdleHdl = rLink;
+ pIdleData->mnPriority = nPriority;
+ pIdleData->mbTimeout = FALSE;
+ mpIdleList->Insert( pIdleData, nPos );
+
+ // Wenn Timer noch nicht gestartet ist, dann starten
+ if ( !maTimer.IsActive() )
+ maTimer.Start();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplIdleMgr::RemoveIdleHdl( const Link& rLink )
+{
+ ImplIdleData* pIdleData = mpIdleList->First();
+ while ( pIdleData )
+ {
+ if ( pIdleData->maIdleHdl == rLink )
+ {
+ mpIdleList->Remove();
+ delete pIdleData;
+ break;
+ }
+
+ pIdleData = mpIdleList->Next();
+ }
+
+ // keine Handdler mehr da
+ if ( !mpIdleList->Count() )
+ maTimer.Stop();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplIdleMgr, TimeoutHdl, Timer*, EMPTYARG )
+{
+ ImplIdleData* pIdleData = mpIdleList->First();
+ while ( pIdleData )
+ {
+ if ( !pIdleData->mbTimeout )
+ {
+ pIdleData->mbTimeout = TRUE;
+ pIdleData->maIdleHdl.Call( GetpApp() );
+ // Kann im Handler entfernt worden sein
+ if ( mpIdleList->GetPos( pIdleData ) != LIST_ENTRY_NOTFOUND )
+ pIdleData->mbTimeout = FALSE;
+ }
+
+ pIdleData = mpIdleList->Next();
+ }
+
+ return 0;
+}
diff --git a/vcl/source/app/makefile.mk b/vcl/source/app/makefile.mk
new file mode 100644
index 000000000000..ef981b4c4c1c
--- /dev/null
+++ b/vcl/source/app/makefile.mk
@@ -0,0 +1,123 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=app
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+CDEFS+=-DDLLSUFFIX=$(DLLSUFFIX)
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/access.obj \
+ $(SLO)$/config.obj \
+ $(SLO)$/dbggui.obj \
+ $(SLO)$/help.obj \
+ $(SLO)$/idlemgr.obj \
+ $(SLO)$/oldsv.obj \
+ $(SLO)$/resary.obj \
+ $(SLO)$/resmgr.obj \
+ $(SLO)$/settings.obj \
+ $(SLO)$/sound.obj \
+ $(SLO)$/stdtext.obj \
+ $(SLO)$/svapp.obj \
+ $(SLO)$/svdata.obj \
+ $(SLO)$/svmain.obj \
+ $(SLO)$/system.obj \
+ $(SLO)$/timer.obj \
+ $(SLO)$/unohelp.obj
+
+.IF "$(remote)"!=""
+EXCEPTIONSFILES= \
+ $(SLO)$/svapp.obj \
+ $(SLO)$/access.obj \
+ $(SLO)$/config.obj \
+ $(SLO)$/oldsv.obj \
+ $(SLO)$/help.obj \
+ $(SLO)$/resmgr.obj \
+ $(SLO)$/sound.obj \
+ $(SLO)$/svapp.obj \
+ $(SLO)$/svmain.obj \
+ $(SLO)$/system.obj \
+ $(SLO)$/idlemgr.obj \
+ $(SLO)$/timer.obj \
+ $(SLO)$/unohelp.obj
+.ELSE
+EXCEPTIONSFILES= $(SLO)$/svapp.obj \
+EXCEPTIONSFILES= $(SLO)$/unohelp.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
+
diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx
new file mode 100644
index 000000000000..663a2fe387f5
--- /dev/null
+++ b/vcl/source/app/settings.cxx
@@ -0,0 +1,1857 @@
+/*************************************************************************
+ *
+ * $RCSfile: settings.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SETTINGS_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+
+#ifndef _ISOLANG_HXX
+#include <tools/isolang.hxx>
+#endif
+
+#pragma hdrstop
+
+BOOL ImplCompareLocales( const ::com::sun::star::lang::Locale& L1, const ::com::sun::star::lang::Locale& L2 )
+{
+ return ( ( L1.Language == L2.Language ) &&
+ ( L1.Country == L2.Country ) &&
+ ( L1.Variant == L2.Variant ) );
+}
+
+// =======================================================================
+
+DBG_NAME( AllSettings );
+
+// =======================================================================
+
+#define STDSYS_STYLE (STYLE_OPTION_SCROLLARROW | \
+ STYLE_OPTION_SPINARROW | \
+ STYLE_OPTION_SPINUPDOWN | \
+ STYLE_OPTION_NOMNEMONICS)
+
+// =======================================================================
+
+ImplMachineData::ImplMachineData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+ mnScreenOptions = 0;
+ mnPrintOptions = 0;
+ mnScreenRasterFontDeviation = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMachineData::ImplMachineData( const ImplMachineData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+ mnScreenOptions = rData.mnScreenOptions;
+ mnPrintOptions = rData.mnPrintOptions;
+ mnScreenRasterFontDeviation = rData.mnScreenRasterFontDeviation;
+}
+
+// -----------------------------------------------------------------------
+
+MachineSettings::MachineSettings()
+{
+ mpData = new ImplMachineData();
+}
+
+// -----------------------------------------------------------------------
+
+MachineSettings::MachineSettings( const MachineSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MachineSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+MachineSettings::~MachineSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const MachineSettings& MachineSettings::operator =( const MachineSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MachineSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void MachineSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplMachineData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MachineSettings::operator ==( const MachineSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) &&
+ (mpData->mnScreenOptions == rSet.mpData->mnScreenOptions) &&
+ (mpData->mnPrintOptions == rSet.mpData->mnPrintOptions) &&
+ (mpData->mnScreenRasterFontDeviation == rSet.mpData->mnScreenRasterFontDeviation) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, MachineSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const MachineSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplMouseData::ImplMouseData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+ mnDoubleClkTime = 500;
+ mnDoubleClkWidth = 2;
+ mnDoubleClkHeight = 2;
+ mnStartDragWidth = 2;
+ mnStartDragHeight = 2;
+ mnStartDragCode = MOUSE_LEFT;
+ mnDragMoveCode = 0;
+ mnDragCopyCode = KEY_MOD1;
+ mnDragLinkCode = KEY_SHIFT | KEY_MOD1;
+ mnContextMenuCode = MOUSE_RIGHT;
+ mnContextMenuClicks = 1;
+ mbContextMenuDown = FALSE;
+ mnScrollRepeat = 100;
+ mnButtonStartRepeat = 370;
+ mnButtonRepeat = 90;
+ mnActionDelay = 250;
+ mnMenuDelay = 150;
+ mnFollow = MOUSE_FOLLOW_MENU | MOUSE_FOLLOW_DDLIST;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMouseData::ImplMouseData( const ImplMouseData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+ mnDoubleClkTime = rData.mnDoubleClkTime;
+ mnDoubleClkWidth = rData.mnDoubleClkWidth;
+ mnDoubleClkHeight = rData.mnDoubleClkHeight;
+ mnStartDragWidth = rData.mnStartDragWidth;
+ mnStartDragHeight = rData.mnStartDragHeight;
+ mnStartDragCode = rData.mnStartDragCode;
+ mnDragMoveCode = rData.mnDragMoveCode;
+ mnDragCopyCode = rData.mnDragCopyCode;
+ mnDragLinkCode = rData.mnDragLinkCode;
+ mnContextMenuCode = rData.mnContextMenuCode;
+ mnContextMenuClicks = rData.mnContextMenuClicks;
+ mbContextMenuDown = rData.mbContextMenuDown;
+ mnScrollRepeat = rData.mnScrollRepeat;
+ mnButtonStartRepeat = rData.mnButtonStartRepeat;
+ mnButtonRepeat = rData.mnButtonRepeat;
+ mnActionDelay = rData.mnActionDelay;
+ mnMenuDelay = rData.mnMenuDelay;
+ mnFollow = rData.mnFollow;
+}
+
+// -----------------------------------------------------------------------
+
+MouseSettings::MouseSettings()
+{
+ mpData = new ImplMouseData();
+}
+
+// -----------------------------------------------------------------------
+
+MouseSettings::MouseSettings( const MouseSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MouseSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+MouseSettings::~MouseSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const MouseSettings& MouseSettings::operator =( const MouseSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MouseSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void MouseSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplMouseData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MouseSettings::operator ==( const MouseSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) &&
+ (mpData->mnDoubleClkTime == rSet.mpData->mnDoubleClkTime) &&
+ (mpData->mnDoubleClkWidth == rSet.mpData->mnDoubleClkWidth) &&
+ (mpData->mnDoubleClkHeight == rSet.mpData->mnDoubleClkHeight) &&
+ (mpData->mnStartDragWidth == rSet.mpData->mnStartDragWidth) &&
+ (mpData->mnStartDragHeight == rSet.mpData->mnStartDragHeight) &&
+ (mpData->mnStartDragCode == rSet.mpData->mnStartDragCode) &&
+ (mpData->mnDragMoveCode == rSet.mpData->mnDragMoveCode) &&
+ (mpData->mnDragCopyCode == rSet.mpData->mnDragCopyCode) &&
+ (mpData->mnDragLinkCode == rSet.mpData->mnDragLinkCode) &&
+ (mpData->mnContextMenuCode == rSet.mpData->mnContextMenuCode) &&
+ (mpData->mnContextMenuClicks == rSet.mpData->mnContextMenuClicks) &&
+ (mpData->mbContextMenuDown == rSet.mpData->mbContextMenuDown) &&
+ (mpData->mnScrollRepeat == rSet.mpData->mnScrollRepeat) &&
+ (mpData->mnButtonStartRepeat == rSet.mpData->mnButtonStartRepeat) &&
+ (mpData->mnButtonRepeat == rSet.mpData->mnButtonRepeat) &&
+ (mpData->mnActionDelay == rSet.mpData->mnActionDelay) &&
+ (mpData->mnMenuDelay == rSet.mpData->mnMenuDelay) &&
+ (mpData->mnFollow == rSet.mpData->mnFollow) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, MouseSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const MouseSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplKeyboardData::ImplKeyboardData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplKeyboardData::ImplKeyboardData( const ImplKeyboardData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+}
+
+// -----------------------------------------------------------------------
+
+KeyboardSettings::KeyboardSettings()
+{
+ mpData = new ImplKeyboardData();
+}
+
+// -----------------------------------------------------------------------
+
+KeyboardSettings::KeyboardSettings( const KeyboardSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "KeyboardSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+KeyboardSettings::~KeyboardSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const KeyboardSettings& KeyboardSettings::operator =( const KeyboardSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "KeyboardSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void KeyboardSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplKeyboardData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL KeyboardSettings::operator ==( const KeyboardSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, KeyboardSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const KeyboardSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplStyleData::ImplStyleData()
+{
+ mnRefCount = 1;
+ mnScrollBarSize = 16;
+ mnSplitSize = 3;
+ mnSpinSize = 16;
+ mnIconHorzSpace = 50;
+ mnIconVertSpace = 40;
+ mnCursorSize = 2;
+#ifdef REMOTE_APPSERVER
+ mnCursorBlinkTime = STYLE_CURSOR_NOBLINKTIME;
+#else
+ mnCursorBlinkTime = 500;
+#endif
+ mnScreenZoom = 100;
+ mnScreenFontZoom = 100;
+ mnRadioButtonStyle = 0;
+ mnCheckBoxStyle = 0;
+ mnPushButtonStyle = 0;
+ mnTabControlStyle = 0;
+ mnLogoDisplayTime = LOGO_DISPLAYTIME_STARTTIME;
+ mnDragFullOptions = 0;
+ mnAnimationOptions = 0;
+ mnSelectionOptions = 0;
+ mnOptions = 0;
+
+ SetStandardStyles();
+}
+
+// -----------------------------------------------------------------------
+
+ImplStyleData::ImplStyleData( const ImplStyleData& rData ) :
+ maFaceColor( rData.maFaceColor ),
+ maCheckedColor( rData.maCheckedColor ),
+ maLightColor( rData.maLightColor ),
+ maLightBorderColor( rData.maLightBorderColor ),
+ maShadowColor( rData.maShadowColor ),
+ maDarkShadowColor( rData.maDarkShadowColor ),
+ maButtonTextColor( rData.maButtonTextColor ),
+ maRadioCheckTextColor( rData.maRadioCheckTextColor ),
+ maGroupTextColor( rData.maGroupTextColor ),
+ maLabelTextColor( rData.maLabelTextColor ),
+ maInfoTextColor( rData.maInfoTextColor ),
+ maWindowColor( rData.maWindowColor ),
+ maWindowTextColor( rData.maWindowTextColor ),
+ maDialogColor( rData.maDialogColor ),
+ maDialogTextColor( rData.maDialogTextColor ),
+ maWorkspaceColor( rData.maWorkspaceColor ),
+ maFieldColor( rData.maFieldColor ),
+ maFieldTextColor( rData.maFieldTextColor ),
+ maActiveColor( rData.maActiveColor ),
+ maActiveColor2( rData.maActiveColor2 ),
+ maActiveTextColor( rData.maActiveTextColor ),
+ maActiveBorderColor( rData.maActiveBorderColor ),
+ maDeactiveColor( rData.maDeactiveColor ),
+ maDeactiveColor2( rData.maDeactiveColor2 ),
+ maDeactiveTextColor( rData.maDeactiveTextColor ),
+ maDeactiveBorderColor( rData.maDeactiveBorderColor ),
+ maMenuColor( rData.maMenuColor ),
+ maMenuTextColor( rData.maMenuTextColor ),
+ maMenuHighlightColor( rData.maMenuHighlightColor ),
+ maMenuHighlightTextColor( rData.maMenuHighlightTextColor ),
+ maHighlightColor( rData.maHighlightColor ),
+ maHighlightTextColor( rData.maHighlightTextColor ),
+ maDisableColor( rData.maDisableColor ),
+ maHelpColor( rData.maHelpColor ),
+ maHelpTextColor( rData.maHelpTextColor ),
+ maLinkColor( rData.maLinkColor ),
+ maVisitedLinkColor( rData.maLinkColor ),
+ maHighlightLinkColor( rData.maLinkColor ),
+ maAppFont( rData.maAppFont ),
+ maHelpFont( rData.maAppFont ),
+ maTitleFont( rData.maTitleFont ),
+ maFloatTitleFont( rData.maFloatTitleFont ),
+ maMenuFont( rData.maMenuFont ),
+ maToolFont( rData.maToolFont ),
+ maGroupFont( rData.maGroupFont ),
+ maLabelFont( rData.maLabelFont ),
+ maInfoFont( rData.maInfoFont ),
+ maRadioCheckFont( rData.maRadioCheckFont ),
+ maPushButtonFont( rData.maPushButtonFont ),
+ maFieldFont( rData.maFieldFont ),
+ maIconFont( rData.maIconFont )
+{
+ mnRefCount = 1;
+ mnBorderSize = rData.mnBorderSize;
+ mnTitleHeight = rData.mnTitleHeight;
+ mnFloatTitleHeight = rData.mnFloatTitleHeight;
+ mnTearOffTitleHeight = rData.mnTearOffTitleHeight;
+ mnMenuBarHeight = rData.mnMenuBarHeight;
+ mnScrollBarSize = rData.mnScrollBarSize;
+ mnSplitSize = rData.mnSplitSize;
+ mnSpinSize = rData.mnSpinSize;
+ mnIconHorzSpace = rData.mnIconHorzSpace;
+ mnIconVertSpace = rData.mnIconVertSpace;
+ mnCursorSize = rData.mnCursorSize;
+ mnCursorBlinkTime = rData.mnCursorBlinkTime;
+ mnScreenZoom = rData.mnScreenZoom;
+ mnScreenFontZoom = rData.mnScreenFontZoom;
+ mnRadioButtonStyle = rData.mnRadioButtonStyle;
+ mnCheckBoxStyle = rData.mnCheckBoxStyle;
+ mnPushButtonStyle = rData.mnPushButtonStyle;
+ mnTabControlStyle = rData.mnTabControlStyle;
+ mnLogoDisplayTime = rData.mnLogoDisplayTime;
+ mnDragFullOptions = rData.mnDragFullOptions;
+ mnAnimationOptions = rData.mnAnimationOptions;
+ mnSelectionOptions = rData.mnSelectionOptions;
+ mnOptions = rData.mnOptions;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStyleData::SetStandardStyles()
+{
+ Font aStdFont( FAMILY_SWISS, Size( 0, 8 ) );
+ aStdFont.SetCharSet( gsl_getSystemTextEncoding() );
+ aStdFont.SetWeight( WEIGHT_NORMAL );
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "MS Sans Serif;Geneva;Helv;WarpSans;Tahoma;Arial Unicode MS;Dialog;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+ maAppFont = aStdFont;
+ maHelpFont = aStdFont;
+ maMenuFont = aStdFont;
+ maToolFont = aStdFont;
+ maGroupFont = aStdFont;
+ maLabelFont = aStdFont;
+ maInfoFont = aStdFont;
+ maRadioCheckFont = aStdFont;
+ maPushButtonFont = aStdFont;
+ maFieldFont = aStdFont;
+ maIconFont = aStdFont;
+ maFloatTitleFont = aStdFont;
+ aStdFont.SetWeight( WEIGHT_BOLD );
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "MS Sans Serif;Charcoal;Chicago;Geneva;Helv;WarpSans;Tahoma;Arial Unicode MS;Dialog;Lucida;Helvetica;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+ maTitleFont = aStdFont;
+
+ maFaceColor = Color( COL_LIGHTGRAY );
+ maCheckedColor = Color( 0xCC, 0xCC, 0xCC );
+ maLightColor = Color( COL_WHITE );
+ maLightBorderColor = Color( COL_LIGHTGRAY );
+ maShadowColor = Color( COL_GRAY );
+ maDarkShadowColor = Color( COL_BLACK );
+ maButtonTextColor = Color( COL_BLACK );
+ maRadioCheckTextColor = Color( COL_BLACK );
+ maGroupTextColor = Color( COL_BLACK );
+ maLabelTextColor = Color( COL_BLACK );
+ maInfoTextColor = Color( COL_BLACK );
+ maWindowColor = Color( COL_WHITE );
+ maWindowTextColor = Color( COL_BLACK );
+ maDialogColor = Color( COL_LIGHTGRAY );
+ maDialogTextColor = Color( COL_BLACK );
+ maWorkspaceColor = Color( COL_GRAY );
+ maFieldColor = Color( COL_WHITE );
+ maFieldTextColor = Color( COL_BLACK );
+ maActiveColor = Color( COL_BLUE );
+ maActiveColor2 = Color( COL_BLACK );
+ maActiveTextColor = Color( COL_WHITE );
+ maActiveBorderColor = Color( COL_LIGHTGRAY );
+ maDeactiveColor = Color( COL_GRAY );
+ maDeactiveColor2 = Color( COL_BLACK );
+ maDeactiveTextColor = Color( COL_LIGHTGRAY );
+ maDeactiveBorderColor = Color( COL_LIGHTGRAY );
+ maMenuColor = Color( COL_LIGHTGRAY );
+ maMenuTextColor = Color( COL_BLACK );
+ maMenuHighlightColor = Color( COL_BLUE );
+ maMenuHighlightTextColor = Color( COL_WHITE );
+ maHighlightColor = Color( COL_BLUE );
+ maHighlightTextColor = Color( COL_WHITE );
+ maDisableColor = Color( COL_GRAY );
+ maHelpColor = Color( 0xFF, 0xFF, 0xE0 );
+ maHelpTextColor = Color( COL_BLACK );
+ maLinkColor = Color( COL_BLUE );
+ maVisitedLinkColor = Color( COL_RED );
+ maHighlightLinkColor = Color( COL_LIGHTBLUE );
+
+ mnRadioButtonStyle &= ~STYLE_RADIOBUTTON_STYLE;
+ mnCheckBoxStyle &= ~STYLE_CHECKBOX_STYLE;
+ mnPushButtonStyle &= ~STYLE_PUSHBUTTON_STYLE;
+ mnTabControlStyle = 0;
+
+ mnOptions &= ~(STYLE_OPTION_SYSTEMSTYLE | STDSYS_STYLE);
+ mnBorderSize = 1;
+ mnTitleHeight = 18;
+ mnFloatTitleHeight = 13;
+ mnTearOffTitleHeight = 8;
+ mnMenuBarHeight = 14;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStyleData::SetStandardWinStyles()
+{
+ SetStandardStyles();
+
+ mnRadioButtonStyle &= ~STYLE_RADIOBUTTON_STYLE;
+ mnRadioButtonStyle |= STYLE_RADIOBUTTON_WIN;
+ mnCheckBoxStyle &= ~STYLE_CHECKBOX_STYLE;
+ mnCheckBoxStyle |= STYLE_CHECKBOX_WIN;
+ mnPushButtonStyle &= ~STYLE_PUSHBUTTON_STYLE;
+ mnPushButtonStyle |= STYLE_PUSHBUTTON_WIN;
+ mnTabControlStyle = 0;
+
+ mnOptions &= ~(STYLE_OPTION_SYSTEMSTYLE | STDSYS_STYLE);
+ mnOptions |= STYLE_OPTION_WINSTYLE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStyleData::SetStandardOS2Styles()
+{
+ Font aStdFont( FAMILY_SWISS, Size( 0, 9 ) );
+ aStdFont.SetCharSet( gsl_getSystemTextEncoding() );
+ aStdFont.SetWeight( WEIGHT_NORMAL );
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "WarpSans;MS Sans Serif;Geneva;Helv;Tahoma;Arial Unicode MS;Dialog;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+ maAppFont = aStdFont;
+ maHelpFont = aStdFont;
+ maToolFont = aStdFont;
+ maGroupFont = aStdFont;
+ maLabelFont = aStdFont;
+ maInfoFont = aStdFont;
+ maRadioCheckFont = aStdFont;
+ maPushButtonFont = aStdFont;
+ maFieldFont = aStdFont;
+ maIconFont = aStdFont;
+ maFloatTitleFont = aStdFont;
+ aStdFont.SetWeight( WEIGHT_BOLD );
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "WarpSans;MS Sans Serif;Charcoal;Chicago;Geneva;Helv;Tahoma;Arial Unicode MS;Dialog;Lucida;Helvetica;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+ maMenuFont = aStdFont;
+ maTitleFont = aStdFont;
+
+ maFaceColor = Color( COL_LIGHTGRAY );
+ maCheckedColor = Color( 0xCC, 0xCC, 0xCC );
+ maLightColor = Color( COL_WHITE );
+ maLightBorderColor = Color( COL_LIGHTGRAY );
+ maShadowColor = Color( COL_GRAY );
+ maDarkShadowColor = Color( COL_BLACK );
+ maButtonTextColor = Color( COL_BLACK );
+ maRadioCheckTextColor = Color( COL_BLACK );
+ maGroupTextColor = Color( COL_BLACK );
+ maLabelTextColor = Color( COL_BLACK );
+ maInfoTextColor = Color( COL_BLACK );
+ maWindowColor = Color( COL_WHITE );
+ maWindowTextColor = Color( COL_BLACK );
+ maDialogColor = Color( COL_LIGHTGRAY );
+ maDialogTextColor = Color( COL_BLACK );
+ maWorkspaceColor = Color( COL_GRAY );
+ maFieldColor = Color( COL_WHITE );
+ maFieldTextColor = Color( COL_BLACK );
+ maActiveColor = Color( COL_BLUE );
+ maActiveColor2 = Color( COL_BLACK );
+ maActiveTextColor = Color( COL_WHITE );
+ maActiveBorderColor = Color( COL_LIGHTGRAY );
+ maDeactiveColor = Color( COL_GRAY );
+ maDeactiveColor2 = Color( COL_BLACK );
+ maDeactiveTextColor = Color( COL_LIGHTGRAY );
+ maDeactiveBorderColor = Color( COL_LIGHTGRAY );
+ maMenuColor = Color( COL_LIGHTGRAY );
+ maMenuTextColor = Color( COL_BLACK );
+ maMenuHighlightColor = Color( COL_BLUE );
+ maMenuHighlightTextColor = Color( COL_WHITE );
+ maHighlightColor = Color( COL_GRAY );
+ maHighlightTextColor = Color( COL_WHITE );
+ maDisableColor = Color( COL_GRAY );
+ maHelpColor = Color( 0xFF, 0xFF, 0xE0 );
+ maHelpTextColor = Color( COL_BLACK );
+
+ mnRadioButtonStyle &= ~STYLE_RADIOBUTTON_STYLE;
+ mnRadioButtonStyle |= STYLE_RADIOBUTTON_OS2;
+ mnCheckBoxStyle &= ~STYLE_CHECKBOX_STYLE;
+ mnCheckBoxStyle |= STYLE_CHECKBOX_OS2;
+ mnPushButtonStyle &= ~STYLE_PUSHBUTTON_STYLE;
+ mnPushButtonStyle |= STYLE_PUSHBUTTON_OS2;
+ mnTabControlStyle = STYLE_TABCONTROL_SINGLELINE |
+ STYLE_TABCONTROL_COLOR;
+
+ mnOptions &= ~(STYLE_OPTION_SYSTEMSTYLE | STDSYS_STYLE);
+ mnOptions |= STYLE_OPTION_OS2STYLE | STYLE_OPTION_SPINARROW;
+ mnBorderSize = 1;
+ mnTitleHeight = 18;
+ mnFloatTitleHeight = 13;
+ mnTearOffTitleHeight = 8;
+ mnMenuBarHeight = 14;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStyleData::SetStandardMacStyles()
+{
+ Font aStdFont( FAMILY_SWISS, Size( 0, 8 ) );
+ aStdFont.SetCharSet( gsl_getSystemTextEncoding() );
+ aStdFont.SetWeight( WEIGHT_NORMAL );
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "Geneva;MS Sans Serif;Helv;Tahoma;Arial Unicode MS;WarpSans;Dialog;Lucida;Helvetica;Charcoal;Chicago;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+ maAppFont = aStdFont;
+ maHelpFont = aStdFont;
+ maToolFont = aStdFont;
+ maPushButtonFont = aStdFont;
+ maGroupFont = aStdFont;
+ maLabelFont = aStdFont;
+ maInfoFont = aStdFont;
+ maRadioCheckFont = aStdFont;
+ maFieldFont = aStdFont;
+ maIconFont = aStdFont;
+ maFloatTitleFont = aStdFont;
+ aStdFont.SetName( XubString( RTL_CONSTASCII_USTRINGPARAM( "Charcoal;Chicago;Geneva;MS Sans Serif;Helv;Tahoma;Arial Unicode MS;WarpSans;Dialog;Lucida;Helvetica;MS Sans Serif;Arial;Times;Times New Roman;Interface System" ) ) );
+// aStdFont.SetWeight( WEIGHT_BOLD );
+ maMenuFont = aStdFont;
+ maTitleFont = aStdFont;
+// maPushButtonFont = aStdFont;
+// maGroupFont = aStdFont;
+// maLabelFont = aStdFont;
+
+ maFaceColor = Color( COL_LIGHTGRAY );
+ maCheckedColor = Color( 0x99, 0x99, 0x99 );
+ maLightColor = Color( COL_WHITE );
+ maLightBorderColor = Color( COL_LIGHTGRAY );
+ maShadowColor = Color( COL_GRAY );
+ maDarkShadowColor = Color( COL_BLACK );
+ maButtonTextColor = Color( COL_BLACK );
+ maRadioCheckTextColor = Color( COL_BLACK );
+ maGroupTextColor = Color( COL_BLACK );
+ maLabelTextColor = Color( COL_BLACK );
+ maInfoTextColor = Color( COL_BLACK );
+ maWindowColor = Color( COL_WHITE );
+ maWindowTextColor = Color( COL_BLACK );
+ maDialogColor = Color( COL_LIGHTGRAY );
+ maDialogTextColor = Color( COL_BLACK );
+ maWorkspaceColor = Color( COL_GRAY );
+ maFieldColor = Color( COL_WHITE );
+ maFieldTextColor = Color( COL_BLACK );
+ maActiveColor = Color( COL_LIGHTGRAY );
+ maActiveColor2 = Color( COL_LIGHTGRAY );
+ maActiveTextColor = Color( COL_BLACK );
+ maActiveBorderColor = Color( COL_LIGHTGRAY );
+ maDeactiveColor = Color( COL_LIGHTGRAY );
+ maDeactiveColor2 = Color( COL_LIGHTGRAY );
+ maDeactiveTextColor = Color( COL_GRAY );
+ maDeactiveBorderColor = Color( COL_LIGHTGRAY );
+ maMenuColor = Color( COL_LIGHTGRAY );
+ maMenuTextColor = Color( COL_BLACK );
+ maMenuHighlightColor = Color( COL_BLUE );
+ maMenuHighlightTextColor = Color( COL_WHITE );
+ maHighlightColor = Color( COL_BLUE );
+ maHighlightTextColor = Color( COL_WHITE );
+ maDisableColor = Color( COL_GRAY );
+ maHelpColor = Color( 0xFF, 0xFF, 0xE0 );
+ maHelpTextColor = Color( COL_BLACK );
+
+ mnRadioButtonStyle &= ~STYLE_RADIOBUTTON_STYLE;
+ mnRadioButtonStyle |= STYLE_RADIOBUTTON_MAC;
+ mnCheckBoxStyle &= ~STYLE_CHECKBOX_STYLE;
+ mnCheckBoxStyle |= STYLE_CHECKBOX_MAC;
+ mnPushButtonStyle &= ~STYLE_PUSHBUTTON_STYLE;
+ mnPushButtonStyle |= STYLE_PUSHBUTTON_MAC;
+ mnTabControlStyle = 0;
+
+ mnOptions &= ~(STYLE_OPTION_SYSTEMSTYLE | STDSYS_STYLE);
+ mnOptions |= STYLE_OPTION_MACSTYLE | STYLE_OPTION_NOMNEMONICS | STYLE_OPTION_SPINUPDOWN;
+ mnBorderSize = 2;
+ mnTitleHeight = 16;
+ mnFloatTitleHeight = 12;
+ mnTearOffTitleHeight = 7;
+ mnMenuBarHeight = 14;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStyleData::SetStandardUnixStyles()
+{
+ SetStandardStyles();
+
+ maActiveColor = Color( 182, 77, 121 );
+ maActiveColor2 = Color( 182, 77, 121 );
+ maActiveTextColor = Color( COL_WHITE );
+ maActiveBorderColor = Color( 182, 77, 121 );
+ maDeactiveColor = Color( 174, 178, 199 );
+ maDeactiveColor2 = Color( 174, 178, 199 );
+ maDeactiveTextColor = Color( COL_BLACK );
+ maDeactiveBorderColor = Color( 174, 178, 199 );
+
+ mnRadioButtonStyle &= ~STYLE_RADIOBUTTON_STYLE;
+ mnRadioButtonStyle |= STYLE_RADIOBUTTON_UNIX;
+ mnCheckBoxStyle &= ~STYLE_CHECKBOX_STYLE;
+ mnCheckBoxStyle |= STYLE_CHECKBOX_UNIX;
+ mnPushButtonStyle &= ~STYLE_PUSHBUTTON_STYLE;
+ mnPushButtonStyle |= STYLE_PUSHBUTTON_UNIX;
+ mnTabControlStyle = 0;
+
+ mnOptions &= ~(STYLE_OPTION_SYSTEMSTYLE | STDSYS_STYLE);
+ mnOptions |= STYLE_OPTION_UNIXSTYLE;
+
+ mnBorderSize = 3;
+}
+
+// -----------------------------------------------------------------------
+
+StyleSettings::StyleSettings()
+{
+ mpData = new ImplStyleData();
+}
+
+// -----------------------------------------------------------------------
+
+StyleSettings::StyleSettings( const StyleSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "StyleSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+StyleSettings::~StyleSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::Set3DColors( const Color& rColor )
+{
+ CopyData();
+ mpData->maFaceColor = rColor;
+ mpData->maLightBorderColor = rColor;
+ mpData->maDarkShadowColor = Color( COL_BLACK );
+ if ( rColor != Color( COL_LIGHTGRAY ) )
+ {
+ mpData->maLightColor = rColor;
+ mpData->maShadowColor = rColor;
+ mpData->maLightColor.IncreaseLuminance( 64 );
+ mpData->maShadowColor.DecreaseLuminance( 64 );
+ ULONG nRed = mpData->maLightColor.GetRed();
+ ULONG nGreen = mpData->maLightColor.GetGreen();
+ ULONG nBlue = mpData->maLightColor.GetBlue();
+ nRed += (ULONG)(mpData->maShadowColor.GetRed());
+ nGreen += (ULONG)(mpData->maShadowColor.GetGreen());
+ nBlue += (ULONG)(mpData->maShadowColor.GetBlue());
+ mpData->maCheckedColor = Color( (BYTE)(nRed/2), (BYTE)(nGreen/2), (BYTE)(nBlue/2) );
+ }
+ else
+ {
+ mpData->maCheckedColor = Color( 0x99, 0x99, 0x99 );
+ mpData->maLightColor = Color( COL_WHITE );
+ mpData->maShadowColor = Color( COL_GRAY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::SetStandardStyles()
+{
+ CopyData();
+ mpData->SetStandardStyles();
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::SetStandardWinStyles()
+{
+ CopyData();
+ mpData->SetStandardWinStyles();
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::SetStandardOS2Styles()
+{
+ CopyData();
+ mpData->SetStandardOS2Styles();
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::SetStandardMacStyles()
+{
+ CopyData();
+ mpData->SetStandardMacStyles();
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::SetStandardUnixStyles()
+{
+ CopyData();
+ mpData->SetStandardUnixStyles();
+}
+
+// -----------------------------------------------------------------------
+
+const StyleSettings& StyleSettings::operator =( const StyleSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "StyleSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void StyleSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplStyleData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL StyleSettings::operator ==( const StyleSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) &&
+ (mpData->mnLogoDisplayTime == rSet.mpData->mnLogoDisplayTime) &&
+ (mpData->mnDragFullOptions == rSet.mpData->mnDragFullOptions) &&
+ (mpData->mnAnimationOptions == rSet.mpData->mnAnimationOptions) &&
+ (mpData->mnSelectionOptions == rSet.mpData->mnSelectionOptions) &&
+ (mpData->mnCursorSize == rSet.mpData->mnCursorSize) &&
+ (mpData->mnCursorBlinkTime == rSet.mpData->mnCursorBlinkTime) &&
+ (mpData->mnBorderSize == rSet.mpData->mnBorderSize) &&
+ (mpData->mnTitleHeight == rSet.mpData->mnTitleHeight) &&
+ (mpData->mnFloatTitleHeight == rSet.mpData->mnFloatTitleHeight) &&
+ (mpData->mnTearOffTitleHeight == rSet.mpData->mnTearOffTitleHeight) &&
+ (mpData->mnMenuBarHeight == rSet.mpData->mnMenuBarHeight) &&
+ (mpData->mnScrollBarSize == rSet.mpData->mnScrollBarSize) &&
+ (mpData->mnSplitSize == rSet.mpData->mnSplitSize) &&
+ (mpData->mnSpinSize == rSet.mpData->mnSpinSize) &&
+ (mpData->mnIconHorzSpace == rSet.mpData->mnIconHorzSpace) &&
+ (mpData->mnIconVertSpace == rSet.mpData->mnIconVertSpace) &&
+ (mpData->mnScreenZoom == rSet.mpData->mnScreenZoom) &&
+ (mpData->mnScreenFontZoom == rSet.mpData->mnScreenFontZoom) &&
+ (mpData->mnRadioButtonStyle == rSet.mpData->mnRadioButtonStyle) &&
+ (mpData->mnCheckBoxStyle == rSet.mpData->mnCheckBoxStyle) &&
+ (mpData->mnPushButtonStyle == rSet.mpData->mnPushButtonStyle) &&
+ (mpData->mnTabControlStyle == rSet.mpData->mnTabControlStyle) &&
+ (mpData->maFaceColor == rSet.mpData->maFaceColor) &&
+ (mpData->maCheckedColor == rSet.mpData->maCheckedColor) &&
+ (mpData->maLightColor == rSet.mpData->maLightColor) &&
+ (mpData->maLightBorderColor == rSet.mpData->maLightBorderColor) &&
+ (mpData->maShadowColor == rSet.mpData->maShadowColor) &&
+ (mpData->maDarkShadowColor == rSet.mpData->maDarkShadowColor) &&
+ (mpData->maButtonTextColor == rSet.mpData->maButtonTextColor) &&
+ (mpData->maRadioCheckTextColor == rSet.mpData->maRadioCheckTextColor) &&
+ (mpData->maGroupTextColor == rSet.mpData->maGroupTextColor) &&
+ (mpData->maLabelTextColor == rSet.mpData->maLabelTextColor) &&
+ (mpData->maInfoTextColor == rSet.mpData->maInfoTextColor) &&
+ (mpData->maWindowColor == rSet.mpData->maWindowColor) &&
+ (mpData->maWindowTextColor == rSet.mpData->maWindowTextColor) &&
+ (mpData->maDialogColor == rSet.mpData->maDialogColor) &&
+ (mpData->maDialogTextColor == rSet.mpData->maDialogTextColor) &&
+ (mpData->maWorkspaceColor == rSet.mpData->maWorkspaceColor) &&
+ (mpData->maFieldColor == rSet.mpData->maFieldColor) &&
+ (mpData->maFieldTextColor == rSet.mpData->maFieldTextColor) &&
+ (mpData->maActiveColor == rSet.mpData->maActiveColor) &&
+ (mpData->maActiveColor2 == rSet.mpData->maActiveColor2) &&
+ (mpData->maActiveTextColor == rSet.mpData->maActiveTextColor) &&
+ (mpData->maActiveBorderColor == rSet.mpData->maActiveBorderColor) &&
+ (mpData->maDeactiveColor == rSet.mpData->maDeactiveColor) &&
+ (mpData->maDeactiveColor2 == rSet.mpData->maDeactiveColor2) &&
+ (mpData->maDeactiveTextColor == rSet.mpData->maDeactiveTextColor) &&
+ (mpData->maDeactiveBorderColor == rSet.mpData->maDeactiveBorderColor) &&
+ (mpData->maMenuColor == rSet.mpData->maMenuColor) &&
+ (mpData->maMenuTextColor == rSet.mpData->maMenuTextColor) &&
+ (mpData->maMenuHighlightColor == rSet.mpData->maMenuHighlightColor) &&
+ (mpData->maMenuHighlightTextColor == rSet.mpData->maMenuHighlightTextColor) &&
+ (mpData->maHighlightColor == rSet.mpData->maHighlightColor) &&
+ (mpData->maHighlightTextColor == rSet.mpData->maHighlightTextColor) &&
+ (mpData->maDisableColor == rSet.mpData->maDisableColor) &&
+ (mpData->maHelpColor == rSet.mpData->maHelpColor) &&
+ (mpData->maHelpTextColor == rSet.mpData->maHelpTextColor) &&
+ (mpData->maLinkColor == rSet.mpData->maLinkColor) &&
+ (mpData->maVisitedLinkColor == rSet.mpData->maVisitedLinkColor) &&
+ (mpData->maHighlightLinkColor == rSet.mpData->maHighlightLinkColor) &&
+ (mpData->maAppFont == rSet.mpData->maAppFont) &&
+ (mpData->maHelpFont == rSet.mpData->maHelpFont) &&
+ (mpData->maTitleFont == rSet.mpData->maTitleFont) &&
+ (mpData->maFloatTitleFont == rSet.mpData->maFloatTitleFont) &&
+ (mpData->maMenuFont == rSet.mpData->maMenuFont) &&
+ (mpData->maToolFont == rSet.mpData->maToolFont) &&
+ (mpData->maGroupFont == rSet.mpData->maGroupFont) &&
+ (mpData->maLabelFont == rSet.mpData->maLabelFont) &&
+ (mpData->maInfoFont == rSet.mpData->maInfoFont) &&
+ (mpData->maRadioCheckFont == rSet.mpData->maRadioCheckFont) &&
+ (mpData->maPushButtonFont == rSet.mpData->maPushButtonFont) &&
+ (mpData->maFieldFont == rSet.mpData->maFieldFont) &&
+ (mpData->maIconFont == rSet.mpData->maIconFont) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, StyleSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const StyleSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplMiscData::ImplMiscData()
+{
+ mnRefCount = 1;
+ mnTwoDigitYearStart = 1930;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMiscData::ImplMiscData( const ImplMiscData& rData )
+{
+ mnRefCount = 1;
+ mnTwoDigitYearStart = rData.mnTwoDigitYearStart;
+}
+
+// -----------------------------------------------------------------------
+
+MiscSettings::MiscSettings()
+{
+ mpData = new ImplMiscData();
+}
+
+// -----------------------------------------------------------------------
+
+MiscSettings::MiscSettings( const MiscSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MiscSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+MiscSettings::~MiscSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const MiscSettings& MiscSettings::operator =( const MiscSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "MiscSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void MiscSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplMiscData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MiscSettings::operator ==( const MiscSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnTwoDigitYearStart == rSet.mpData->mnTwoDigitYearStart ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, MiscSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const MiscSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplSoundData::ImplSoundData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplSoundData::ImplSoundData( const ImplSoundData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+}
+
+// -----------------------------------------------------------------------
+
+SoundSettings::SoundSettings()
+{
+ mpData = new ImplSoundData();
+}
+
+// -----------------------------------------------------------------------
+
+SoundSettings::SoundSettings( const SoundSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "SoundSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+SoundSettings::~SoundSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const SoundSettings& SoundSettings::operator =( const SoundSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "SoundSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void SoundSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplSoundData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SoundSettings::operator ==( const SoundSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, SoundSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const SoundSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplNotificationData::ImplNotificationData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplNotificationData::ImplNotificationData( const ImplNotificationData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+}
+
+// -----------------------------------------------------------------------
+
+NotificationSettings::NotificationSettings()
+{
+ mpData = new ImplNotificationData();
+}
+
+// -----------------------------------------------------------------------
+
+NotificationSettings::NotificationSettings( const NotificationSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "NotificationSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+NotificationSettings::~NotificationSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const NotificationSettings& NotificationSettings::operator =( const NotificationSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "NotificationSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void NotificationSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplNotificationData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL NotificationSettings::operator ==( const NotificationSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, NotificationSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const NotificationSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplHelpData::ImplHelpData()
+{
+ mnRefCount = 1;
+ mnOptions = 0;
+ mnTipDelay = 500;
+ mnTipTimeout = 3000;
+ mnBalloonDelay = 1500;
+}
+
+// -----------------------------------------------------------------------
+
+ImplHelpData::ImplHelpData( const ImplHelpData& rData )
+{
+ mnRefCount = 1;
+ mnOptions = rData.mnOptions;
+ mnTipDelay = rData.mnTipDelay;
+ mnTipTimeout = rData.mnTipTimeout;
+ mnBalloonDelay = rData.mnBalloonDelay;
+}
+
+// -----------------------------------------------------------------------
+
+HelpSettings::HelpSettings()
+{
+ mpData = new ImplHelpData();
+}
+
+// -----------------------------------------------------------------------
+
+HelpSettings::HelpSettings( const HelpSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "HelpSettings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+HelpSettings::~HelpSettings()
+{
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const HelpSettings& HelpSettings::operator =( const HelpSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "HelpSettings: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void HelpSettings::CopyData()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplHelpData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL HelpSettings::operator ==( const HelpSettings& rSet ) const
+{
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->mnOptions == rSet.mpData->mnOptions ) &&
+ (mpData->mnTipDelay == rSet.mpData->mnTipDelay ) &&
+ (mpData->mnTipTimeout == rSet.mpData->mnTipTimeout ) &&
+ (mpData->mnBalloonDelay == rSet.mpData->mnBalloonDelay ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, HelpSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const HelpSettings& rSet )
+{
+ return rOStream;
+}
+
+// =======================================================================
+
+ImplAllSettingsData::ImplAllSettingsData()
+{
+ mnRefCount = 1;
+ mnSystemUpdate = SETTINGS_ALLSETTINGS;
+ mnWindowUpdate = SETTINGS_ALLSETTINGS;
+}
+
+// -----------------------------------------------------------------------
+
+ImplAllSettingsData::ImplAllSettingsData( const ImplAllSettingsData& rData ) :
+ maMouseSettings( rData.maMouseSettings ),
+ maKeyboardSettings( rData.maKeyboardSettings ),
+ maStyleSettings( rData.maStyleSettings ),
+ maMiscSettings( rData.maMiscSettings ),
+ maSoundSettings( rData.maSoundSettings ),
+ maNotificationSettings( rData.maNotificationSettings ),
+ maHelpSettings( rData.maHelpSettings ),
+ maInternational( rData.maInternational )
+{
+ mnRefCount = 1;
+ mnSystemUpdate = rData.mnSystemUpdate;
+ mnWindowUpdate = rData.mnWindowUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+AllSettings::AllSettings()
+{
+ DBG_CTOR( AllSettings, NULL );
+
+ mpData = new ImplAllSettingsData();
+}
+
+// -----------------------------------------------------------------------
+
+AllSettings::AllSettings( const AllSettings& rSet )
+{
+ DBG_CTOR( AllSettings, NULL );
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "Settings: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpData = rSet.mpData;
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+AllSettings::~AllSettings()
+{
+ DBG_DTOR( AllSettings, NULL );
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+const AllSettings& AllSettings::operator =( const AllSettings& rSet )
+{
+ DBG_ASSERT( rSet.mpData->mnRefCount < 0xFFFE, "AllSettings: RefCount overflow" );
+ DBG_CHKTHIS( AllSettings, NULL );
+ DBG_CHKOBJ( &rSet, AllSettings, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rSet.mpData->mnRefCount++;
+
+ // Daten loeschen, wenn letzte Referenz
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+
+ mpData = rSet.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void AllSettings::CopyData()
+{
+ DBG_CHKTHIS( AllSettings, NULL );
+
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplAllSettingsData( *mpData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ULONG AllSettings::Update( ULONG nFlags, const AllSettings& rSet )
+{
+ DBG_CHKTHIS( AllSettings, NULL );
+ DBG_CHKOBJ( &rSet, AllSettings, NULL );
+
+ ULONG nChangeFlags = 0;
+
+ if ( nFlags & SETTINGS_MACHINE )
+ {
+ if ( mpData->maMachineSettings != rSet.mpData->maMachineSettings )
+ {
+ CopyData();
+ mpData->maMachineSettings = rSet.mpData->maMachineSettings;
+ nChangeFlags |= SETTINGS_MACHINE;
+ }
+ }
+
+ if ( nFlags & SETTINGS_MOUSE )
+ {
+ if ( mpData->maMouseSettings != rSet.mpData->maMouseSettings )
+ {
+ CopyData();
+ mpData->maMouseSettings = rSet.mpData->maMouseSettings;
+ nChangeFlags |= SETTINGS_MOUSE;
+ }
+ }
+
+ if ( nFlags & SETTINGS_KEYBOARD )
+ {
+ if ( mpData->maKeyboardSettings != rSet.mpData->maKeyboardSettings )
+ {
+ CopyData();
+ mpData->maKeyboardSettings = rSet.mpData->maKeyboardSettings;
+ nChangeFlags |= SETTINGS_KEYBOARD;
+ }
+ }
+
+ if ( nFlags & SETTINGS_STYLE )
+ {
+ if ( mpData->maStyleSettings != rSet.mpData->maStyleSettings )
+ {
+ CopyData();
+ mpData->maStyleSettings = rSet.mpData->maStyleSettings;
+ nChangeFlags |= SETTINGS_STYLE;
+ }
+ }
+
+ if ( nFlags & SETTINGS_MISC )
+ {
+ if ( mpData->maMiscSettings != rSet.mpData->maMiscSettings )
+ {
+ CopyData();
+ mpData->maMiscSettings = rSet.mpData->maMiscSettings;
+ nChangeFlags |= SETTINGS_MISC;
+ }
+ }
+
+ if ( nFlags & SETTINGS_SOUND )
+ {
+ if ( mpData->maSoundSettings != rSet.mpData->maSoundSettings )
+ {
+ CopyData();
+ mpData->maSoundSettings = rSet.mpData->maSoundSettings;
+ nChangeFlags |= SETTINGS_SOUND;
+ }
+ }
+
+ if ( nFlags & SETTINGS_NOTIFICATION )
+ {
+ if ( mpData->maNotificationSettings != rSet.mpData->maNotificationSettings )
+ {
+ CopyData();
+ mpData->maNotificationSettings = rSet.mpData->maNotificationSettings;
+ nChangeFlags |= SETTINGS_NOTIFICATION;
+ }
+ }
+
+ if ( nFlags & SETTINGS_HELP )
+ {
+ if ( mpData->maHelpSettings != rSet.mpData->maHelpSettings )
+ {
+ CopyData();
+ mpData->maHelpSettings = rSet.mpData->maHelpSettings;
+ nChangeFlags |= SETTINGS_HELP;
+ }
+ }
+
+ if ( nFlags & SETTINGS_INTERNATIONAL )
+ {
+ if ( mpData->maInternational != rSet.mpData->maInternational )
+ {
+ CopyData();
+ mpData->maInternational = rSet.mpData->maInternational;
+ nChangeFlags |= SETTINGS_INTERNATIONAL;
+ // Will be calculated in GetLocale();
+ mpData->maLocale = ::com::sun::star::lang::Locale();
+ }
+
+ // Da System-International-Klassen intern in der
+ // International-Klasse automatisch bei Systemaenderungen geaendert
+ // werden, wird der Status innerhalb einer System-International-
+ // Aenderung anders ermittelt, da ansonsten die App nicht
+ // mitbekommt, das sich etwas geaendert hat
+ if ( (mpData->maInternational.GetLanguage() == LANGUAGE_SYSTEM) ||
+ (mpData->maInternational.GetFormatLanguage() == LANGUAGE_SYSTEM) )
+ {
+ if ( ImplGetSVData()->maAppData.mbIntnChanged )
+ nChangeFlags |= SETTINGS_INTERNATIONAL;
+ }
+ }
+
+ if ( nFlags & SETTINGS_LOCALE )
+ {
+ if ( !ImplCompareLocales( mpData->maLocale, rSet.mpData->maLocale ) )
+ {
+ CopyData();
+ mpData->maLocale = rSet.mpData->maLocale;
+ nChangeFlags |= SETTINGS_LOCALE;
+ }
+ }
+
+ return nChangeFlags;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG AllSettings::GetChangeFlags( const AllSettings& rSet ) const
+{
+ DBG_CHKTHIS( AllSettings, NULL );
+ DBG_CHKOBJ( &rSet, AllSettings, NULL );
+
+ ULONG nChangeFlags = 0;
+
+ if ( mpData->maMachineSettings != rSet.mpData->maMachineSettings )
+ nChangeFlags |= SETTINGS_MACHINE;
+
+ if ( mpData->maMouseSettings != rSet.mpData->maMouseSettings )
+ nChangeFlags |= SETTINGS_MOUSE;
+
+ if ( mpData->maKeyboardSettings != rSet.mpData->maKeyboardSettings )
+ nChangeFlags |= SETTINGS_KEYBOARD;
+
+ if ( mpData->maStyleSettings != rSet.mpData->maStyleSettings )
+ nChangeFlags |= SETTINGS_STYLE;
+
+ if ( mpData->maMiscSettings != rSet.mpData->maMiscSettings )
+ nChangeFlags |= SETTINGS_MISC;
+
+ if ( mpData->maSoundSettings != rSet.mpData->maSoundSettings )
+ nChangeFlags |= SETTINGS_SOUND;
+
+ if ( mpData->maNotificationSettings != rSet.mpData->maNotificationSettings )
+ nChangeFlags |= SETTINGS_NOTIFICATION;
+
+ if ( mpData->maHelpSettings != rSet.mpData->maHelpSettings )
+ nChangeFlags |= SETTINGS_HELP;
+
+ if ( mpData->maInternational != rSet.mpData->maInternational )
+ nChangeFlags |= SETTINGS_INTERNATIONAL;
+
+ // Da System-International-Klassen intern in der
+ // International-Klasse automatisch bei Systemaenderungen geaendert
+ // werden, wird der Status innerhalb einer System-International-
+ // Aenderung anders ermittelt, da ansonsten die App nicht
+ // mitbekommt, das sich etwas geaendert hat
+ if ( (mpData->maInternational.GetLanguage() == LANGUAGE_SYSTEM) ||
+ (mpData->maInternational.GetFormatLanguage() == LANGUAGE_SYSTEM) )
+ {
+ if ( ImplGetSVData()->maAppData.mbIntnChanged )
+ nChangeFlags |= SETTINGS_INTERNATIONAL;
+ }
+
+ return nChangeFlags;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL AllSettings::operator ==( const AllSettings& rSet ) const
+{
+ DBG_CHKTHIS( AllSettings, NULL );
+ DBG_CHKOBJ( &rSet, AllSettings, NULL );
+
+ if ( mpData == rSet.mpData )
+ return TRUE;
+
+ if ( (mpData->maMachineSettings == rSet.mpData->maMachineSettings) &&
+ (mpData->maMouseSettings == rSet.mpData->maMouseSettings) &&
+ (mpData->maKeyboardSettings == rSet.mpData->maKeyboardSettings) &&
+ (mpData->maStyleSettings == rSet.mpData->maStyleSettings) &&
+ (mpData->maMiscSettings == rSet.mpData->maMiscSettings) &&
+ (mpData->maSoundSettings == rSet.mpData->maSoundSettings) &&
+ (mpData->maNotificationSettings == rSet.mpData->maNotificationSettings) &&
+ (mpData->maHelpSettings == rSet.mpData->maHelpSettings) &&
+ (mpData->maInternational == rSet.mpData->maInternational) &&
+ (mpData->mnSystemUpdate == rSet.mpData->mnSystemUpdate) &&
+ (mpData->mnWindowUpdate == rSet.mpData->mnWindowUpdate) )
+ {
+ // special treatment for Locale, because maLocale is only
+ // initialized after first call of GetLocale().
+ ::com::sun::star::lang::Locale aEmptyLocale;
+ if ( ( ImplCompareLocales( mpData->maLocale, aEmptyLocale ) && ImplCompareLocales( rSet.mpData->maLocale, aEmptyLocale ) )
+ || ImplCompareLocales( GetLocale(), rSet.GetLocale() ) )
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+const ::com::sun::star::lang::Locale& AllSettings::GetLocale() const
+{
+ if ( !mpData->maLocale.Language.getLength() )
+ {
+ String aLanguage, aCountry;
+ ConvertLanguageToIsoNames( mpData->maInternational.GetLanguage(), aLanguage, aCountry );
+ ((AllSettings*)this)->mpData->maLocale.Language = aLanguage;
+ ((AllSettings*)this)->mpData->maLocale.Country = aCountry;
+ }
+ return mpData->maLocale;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, AllSettings& rSet )
+{
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const AllSettings& rSet )
+{
+ return rOStream;
+}
diff --git a/vcl/source/app/sound.cxx b/vcl/source/app/sound.cxx
new file mode 100644
index 000000000000..c055f95fdd50
--- /dev/null
+++ b/vcl/source/app/sound.cxx
@@ -0,0 +1,361 @@
+/*************************************************************************
+ *
+ * $RCSfile: sound.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SOUND_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALSOUND_HXX
+#include <salsound.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include <rmwindow.hxx>
+#include <rmsound.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _NEW_HXX
+#include <tools/new.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SALSOUND_HXX
+#include <salsound.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+
+#pragma hdrstop
+
+// ----------------------
+// - SalSound-Callback -
+// ----------------------
+
+#ifndef REMOTE_APPSERVER
+
+void SalSoundProc( void* pInst, SoundNotification eNotification, ULONG nError )
+{
+ ( (Sound*) pInst )->ImplNotify( eNotification, nError );
+}
+
+#endif
+
+// ---------
+// - Sound -
+// ---------
+
+Sound::Sound( Window* pWindow ) :
+ mpWindow ( pWindow ),
+ mpSoundData ( NULL ),
+ mnDataLen ( 0UL ),
+ mnSoundLen ( 0UL ),
+ mnStartTime ( 0UL ),
+ mnPlayTime ( SOUND_PLAYALL ),
+ mnErrorCode ( 0UL ),
+ meNotification ( SOUND_NOTIFY_SUCCESS ),
+ mbPlaying ( FALSE ),
+ mbLoopMode ( FALSE )
+{
+#ifndef REMOTE_APPSERVER
+
+ mpSound = new SalSound;
+ mpSound->Create();
+
+ if( mpSound->IsValid() )
+ mpSound->SetNotifyProc( this, SalSoundProc );
+
+#else
+
+ mpSound = new RMSound;
+ mpSound->Create( this );
+
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Sound::~Sound()
+{
+ if( mpSoundData )
+ SvMemFree( mpSoundData );
+
+ delete mpSound;
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::ImplNotify( SoundNotification eNotification, ULONG nError )
+{
+ meNotification = eNotification;
+ mbPlaying = FALSE;
+
+ if( SOUND_NOTIFY_ERROR == meNotification )
+ mnErrorCode = nError;
+
+ Notify();
+
+ if( maNotifyHdl.IsSet() )
+ maNotifyHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::Notify()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Sound::SetSoundName( const XubString& rSoundName )
+{
+ BOOL bRet;
+
+ if( !rSoundName.Len() )
+ {
+ mnDataLen = 0UL;
+ mnSoundLen = 0UL;
+ mnStartTime = 0UL;
+ mnPlayTime = SOUND_PLAYALL;
+ mnErrorCode = 0UL;
+ meNotification = SOUND_NOTIFY_SUCCESS;
+ mbPlaying = FALSE;
+ mbLoopMode = FALSE;
+ bRet = TRUE;
+
+#ifdef REMOTE_APPSERVER
+ if( mpSoundData )
+ {
+ SvMemFree( mpSoundData );
+ mpSoundData = NULL;
+ }
+
+ // if IFace is init., destroy it and create a new one
+ if( maSoundName.Len() )
+ {
+ delete mpSound;
+ mpSound = new RMSound;
+ mpSound->Create( this );
+ }
+#else
+ mpSound->Init( NULL, rSoundName, mnSoundLen );
+#endif
+ }
+ else if( mpSound->IsValid() )
+ bRet = mpSound->Init( NULL, rSoundName, mnSoundLen );
+ else
+ bRet = FALSE;
+
+ maSoundName = rSoundName;
+
+ // if sound could not be initialized, but we've gotten _no_
+ // notification ==> create common error notification
+ if( !bRet && !mnErrorCode )
+ ImplNotify( SOUND_NOTIFY_ERROR, SOUNDERR_GENERAL_ERROR );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Sound::SetSoundData( const BYTE* pSoundData, ULONG nDataLen )
+{
+ BOOL bRet;
+
+ if( mpSoundData )
+ SvMemFree( mpSoundData );
+
+ mpSoundData = (BYTE*) SvMemAlloc( mnDataLen = nDataLen );
+ HMEMCPY( mpSoundData, pSoundData, nDataLen );
+
+ if( mpSound->IsValid() )
+ bRet = mpSound->Init( NULL, mpSoundData, mnDataLen, mnSoundLen );
+ else
+ bRet = FALSE;
+
+ // if sound could not be initialized, but we've gotten _no_
+ // notification ==> create common error notification
+ if( !bRet && !mnErrorCode )
+ ImplNotify( SOUND_NOTIFY_ERROR, SOUNDERR_GENERAL_ERROR );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::SetStartTime( ULONG nStartTime )
+{
+ mnStartTime = nStartTime;
+
+#ifdef REMOTE_APPSERVER
+ mpSound->SetStartTime( nStartTime );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::SetPlayTime( ULONG nPlayTime )
+{
+ mnPlayTime = nPlayTime;
+
+#ifdef REMOTE_APPSERVER
+ mpSound->SetStartTime( nPlayTime );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::SetLoopMode( BOOL bLoop )
+{
+ mbLoopMode = bLoop;
+
+#ifdef REMOTE_APPSERVER
+ mpSound->SetStartTime( bLoop );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::ClearError()
+{
+ mnErrorCode = 0;
+
+#ifdef REMOTE_APPSERVER
+ mpSound->ClearError();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::Play()
+{
+ BOOL bRet;
+
+ if( mpSound->IsValid() && !mnErrorCode )
+ {
+#ifndef REMOTE_APPSERVER
+ mpSound->Play( mnStartTime, mnPlayTime, mbLoopMode );
+#else
+ mpSound->Play();
+#endif
+
+ mbPlaying = TRUE;
+ }
+ else
+ bRet = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::Stop()
+{
+ mbPlaying = FALSE;
+
+ if( mpSound->IsValid() )
+ mpSound->Stop();
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::Pause()
+{
+ mbPlaying = FALSE;
+
+ if( mpSound->IsValid() )
+ mpSound->Pause();
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::Beep( SoundType eType, Window* pWindow )
+{
+ if( !pWindow )
+ ImplGetDefaultWindow()->ImplGetFrame()->Beep( eType );
+ else
+ pWindow->ImplGetFrame()->Beep( eType );
+}
+
+// -----------------------------------------------------------------------
+
+void Sound::SetSoundPath( const XubString& rSoundPath )
+{
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& Sound::GetSoundPath()
+{
+ return ImplGetSVEmptyStr();
+}
diff --git a/vcl/source/app/stdtext.cxx b/vcl/source/app/stdtext.cxx
new file mode 100644
index 000000000000..8eafc26e474f
--- /dev/null
+++ b/vcl/source/app/stdtext.cxx
@@ -0,0 +1,104 @@
+/*************************************************************************
+ *
+ * $RCSfile: stdtext.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_STDTEXT_CXX
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_MSGBOX_HXX
+#include <msgbox.hxx>
+#endif
+#ifndef _VCL_STDTEXT_HXX
+#include <stdtext.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+XubString GetStandardText( USHORT nStdText )
+{
+ XubString aText( ResId( nStdText-STANDARD_TEXT_FIRST+SV_STDTEXT_FIRST, ImplGetResMgr() ) );
+ return aText;
+}
+
+// =======================================================================
+
+void ShowServiceNotAvailableError( Window* pParent,
+ const XubString& rServiceName, BOOL bError )
+{
+ XubString aText( GetStandardText( STANDARD_TEXT_SERVICE_NOT_AVAILABLE ) );
+ aText.SearchAndReplaceAscii( "%s", rServiceName );
+ if ( bError )
+ {
+ ErrorBox aBox( pParent, WB_OK | WB_DEF_OK, aText );
+ aBox.Execute();
+ }
+ else
+ {
+ WarningBox aBox( pParent, WB_OK | WB_DEF_OK, aText );
+ aBox.Execute();
+ }
+}
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
new file mode 100644
index 000000000000..459653156f73
--- /dev/null
+++ b/vcl/source/app/svapp.cxx
@@ -0,0 +1,1770 @@
+/*************************************************************************
+ *
+ * $RCSfile: svapp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_APP_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include "rvp.hxx"
+#include <rmwindow.hxx>
+#include <rmevents.hxx>
+#include <vos/thread.hxx>
+#include <unobrok.hxx>
+#ifndef _SV_MSGBOX_HXX
+#include <msgbox.hxx>
+#endif
+#endif
+
+#ifndef _VOS_PROCESS_HXX
+#include <vos/process.hxx>
+#endif
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+
+#if defined( WIN ) || defined( WNT ) || defined( OS2 )
+#ifndef _DLL_HXX
+#include <tools/dll.hxx>
+#endif
+#endif
+#ifndef _TOOLS_H
+#include <tools/tools.h>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _ACCMGR_HXX
+#include <accmgr.hxx>
+#endif
+#ifndef _SV_KEYCOD_HXX
+#include <keycod.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDATA_HXX
+#include <windata.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_IDLEMGR_HXX
+#include <idlemgr.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _VCL_UNOWRAP_HXX
+#include <unowrap.hxx>
+#endif
+
+#include <com/sun/star/awt/XToolkit.hpp>
+
+// #include <usr/refl.hxx>
+class Reflection;
+
+#pragma hdrstop
+
+// =======================================================================
+
+// --------------
+// - ImplHotKey -
+// --------------
+
+struct ImplHotKey
+{
+ ImplHotKey* mpNext;
+ void* mpUserData;
+ KeyCode maKeyCode;
+ Link maLink;
+};
+
+// =======================================================================
+
+// -----------------
+// - ImplEventHook -
+// -----------------
+
+struct ImplEventHook
+{
+ ImplEventHook* mpNext;
+ void* mpUserData;
+ VCLEventHookProc mpProc;
+};
+
+// =======================================================================
+
+Application* GetpApp()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData )
+ return NULL;
+ return pSVData->mpApp;
+}
+
+// -----------------------------------------------------------------------
+
+Application::Application()
+{
+ ImplInitSVData();
+ ImplGetSVData()->mpApp = this;
+#ifndef REMOTE_APPSERVER
+ InitSalData();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Application::~Application()
+{
+ ImplDeInitSVData();
+#ifndef REMOTE_APPSERVER
+ DeInitSalData();
+#endif
+ ImplGetSVData()->mpApp = NULL;
+ ImplDestroySVData();
+ GlobalDeInitTools();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::InitAppRes( const ResId& rResId )
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::QueryExit()
+{
+ WorkWindow* pAppWin = ImplGetSVData()->maWinData.mpAppWin;
+
+ // Aufruf des Close-Handlers des Applikationsfensters
+ if ( pAppWin )
+ return pAppWin->Close();
+ else
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::UserEvent( ULONG, void* )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::ShowStatusText( const XubString& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::ShowHelpStatusText( const XubString& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::ActivateExtHelp()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::DeactivateExtHelp()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::HideStatusText()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::HideHelpStatusText()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::FocusChanged()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::DataChanged( const DataChangedEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Application::GetCommandLineParamCount()
+{
+ NAMESPACE_VOS( OStartupInfo ) aStartInfo;
+ return (USHORT)aStartInfo.getCommandArgCount();
+}
+
+// -----------------------------------------------------------------------
+
+XubString Application::GetCommandLineParam( USHORT nParam )
+{
+ NAMESPACE_VOS( OStartupInfo ) aStartInfo;
+ NAMESPACE_RTL( OUString ) aParam;
+ aStartInfo.getCommandArg( nParam, aParam );
+ return XubString( aParam );
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& Application::GetAppFileName()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ DBG_ASSERT( pSVData->maAppData.mpAppFileName, "AppFileName vor SVMain ?!" );
+ if ( pSVData->maAppData.mpAppFileName )
+ return *pSVData->maAppData.mpAppFileName;
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Application::Exception( USHORT nError )
+{
+ switch ( nError & EXC_MAJORTYPE )
+ {
+ // Bei System machen wir nichts und lassen dem System den
+ // vortritt
+ case EXC_SYSTEM:
+ return 0;
+
+ case EXC_DISPLAY:
+ case EXC_REMOTE:
+ return 0;
+
+#ifdef DBG_UTIL
+ case EXC_RSCNOTLOADED:
+ Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "Resource not loaded" ) ) );
+ break;
+ case EXC_SYSOBJNOTCREATED:
+ Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "System Object not created" ) ) );
+ break;
+ default:
+ Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "Unknown Error" ) ) );
+ break;
+#else
+ default:
+ Abort( ImplGetSVEmptyStr() );
+ break;
+#endif
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::Abort( const XubString& rErrorText )
+{
+#ifndef REMOTE_APPSERVER
+ SalAbort( rErrorText );
+#else
+ ErrorBox aErrorBox( NULL, WB_OK, rErrorText );
+ aErrorBox.Execute();
+ exit(-1);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+ImplRemoteYieldMutex::ImplRemoteYieldMutex()
+{
+ mnCount = 0;
+ mnMainThreadId = NAMESPACE_VOS(OThread)::getCurrentIdentifier();
+ mnThreadId = 0;
+}
+
+void SAL_CALL ImplRemoteYieldMutex::acquire()
+{
+ OMutex::acquire();
+ mnThreadId = NAMESPACE_VOS(OThread)::getCurrentIdentifier();
+ mnCount++;
+}
+
+void SAL_CALL ImplRemoteYieldMutex::release()
+{
+ if ( mnThreadId == NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ if ( mnCount == 1 )
+ mnThreadId = 0;
+ mnCount--;
+ }
+ OMutex::release();
+}
+
+sal_Bool SAL_CALL ImplRemoteYieldMutex::tryToAcquire()
+{
+ if ( OMutex::tryToAcquire() )
+ {
+ mnThreadId = NAMESPACE_VOS(OThread)::getCurrentIdentifier();
+ mnCount++;
+ return True;
+ }
+ else
+ return False;
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+
+void ImplDbgTestSolarMutex()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maAppData.mpSolarMutex->GetMainThreadId() !=
+ NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ if ( pSVData->maAppData.mpSolarMutex->GetThreadId() !=
+ NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" );
+ }
+ }
+ else
+ {
+ if ( pSVData->maAppData.mpSolarMutex->GetThreadId() !=
+ NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ DBG_ERROR( "SolarMutex not locked in the main thread" );
+ }
+ }
+}
+
+#endif
+
+
+NAMESPACE_VOS(OThreadData)* getThreadLocalEnvironment();
+
+static void ImplRemoteDispatch( BOOL bWait )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Yield-Semaphore freigeben
+ ULONG nAcquireCount;
+ ULONG i;
+ if ( pSVData->maAppData.mpSolarMutex->GetThreadId() ==
+ ::vos::OThread::getCurrentIdentifier() )
+ {
+ nAcquireCount = pSVData->maAppData.mpSolarMutex->GetAcquireCount();
+ for ( i = 0; i < nAcquireCount; i++ )
+ pSVData->maAppData.mpSolarMutex->release();
+ }
+ else
+ nAcquireCount = 0;
+
+ RmEvent* pEvent = pSVData->mpRmEventQueue->GetNextEvent( bWait );
+
+ // Yield-Semaphore wieder holen
+ while ( nAcquireCount )
+ {
+ pSVData->maAppData.mpSolarMutex->acquire();
+ nAcquireCount--;
+ }
+
+ if ( pEvent )
+ ImplDispatchEvent( (ExtRmEvent*)pEvent );
+ else
+ ::vos::OThread::yield();
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+void Application::Execute()
+{
+ DBG_STARTAPPEXECUTE();
+
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mbInAppExecute = TRUE;
+
+ while ( !pSVData->maAppData.mbAppQuit )
+ Application::Yield();
+
+ pSVData->maAppData.mbInAppExecute = FALSE;
+
+ DBG_ENDAPPEXECUTE();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::Reschedule()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Restliche Timer abarbeitet
+ while ( pSVData->mbNotAllTimerCalled )
+ ImplTimerCallbackProc();
+
+ pSVData->maAppData.mnDispatchLevel++;
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->Yield( FALSE );
+#else
+ ImplRemoteDispatch( FALSE );
+#endif
+ pSVData->maAppData.mnDispatchLevel--;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::Yield()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Restliche Timer abarbeitet
+ while ( pSVData->mbNotAllTimerCalled )
+ ImplTimerCallbackProc();
+
+ // Wenn Application schon beendet wurde, warten wir nicht mehr auf
+ // Messages, sondern verarbeiten nur noch welche, wenn noch welche
+ // vorliegen
+ pSVData->maAppData.mnDispatchLevel++;
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->Yield( !pSVData->maAppData.mbAppQuit );
+#else
+ ImplRemoteDispatch( TRUE );
+#endif
+ pSVData->maAppData.mnDispatchLevel--;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_STATIC_LINK( ImplSVAppData, ImplQuitMsg, void*, EMPTYARG )
+{
+ ImplGetSVData()->maAppData.mbAppQuit = TRUE;
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::Quit()
+{
+ Application::PostUserEvent( STATIC_LINK( NULL, ImplSVAppData, ImplQuitMsg ) );
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef _VOS_NO_NAMESPACE
+IMutex& Application::GetSolarMutex()
+#else
+vos::IMutex& Application::GetSolarMutex()
+#endif
+{
+#ifndef REMOTE_APPSERVER
+ ImplSVData* pSVData = ImplGetSVData();
+ return *(pSVData->mpDefInst->GetYieldMutex());
+#else
+ return *(ImplGetSVData()->maAppData.mpSolarMutex);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef _VOS_NO_NAMESPACE
+OThread::TThreadIdentifier Application::GetMainThreadIdentifier()
+#else
+vos::OThread::TThreadIdentifier Application::GetMainThreadIdentifier()
+#endif
+{
+ return ImplGetSVData()->mnMainThreadId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::ReleaseSolarMutex()
+{
+#ifndef REMOTE_APPSERVER
+ ImplSVData* pSVData = ImplGetSVData();
+ return pSVData->mpDefInst->ReleaseYieldMutex();
+#else
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Wenn wir gelockt haben, dann freigeben
+ if ( pSVData->maAppData.mpSolarMutex->GetThreadId() ==
+ NAMESPACE_VOS(OThread)::getCurrentIdentifier() )
+ {
+ ULONG nCount = pSVData->maAppData.mpSolarMutex->GetAcquireCount();
+ ULONG n = nCount;
+ while ( n )
+ {
+ pSVData->maAppData.mpSolarMutex->release();
+ n--;
+ }
+
+ return nCount;
+ }
+ else
+ return 0;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Application::AcquireSolarMutex( ULONG nCount )
+{
+#ifndef REMOTE_APPSERVER
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpDefInst->AcquireYieldMutex( nCount );
+#else
+ ImplSVData* pSVData = ImplGetSVData();
+ while ( nCount )
+ {
+ pSVData->maAppData.mpSolarMutex->acquire();
+ nCount--;
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsInMain()
+{
+ return ImplGetSVData()->maAppData.mbInAppMain;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsInExecute()
+{
+ return ImplGetSVData()->maAppData.mbInAppExecute;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsShutDown()
+{
+ return ImplGetSVData()->maAppData.mbAppQuit;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsInModalMode()
+{
+ return (ImplGetSVData()->maAppData.mnModalMode != 0);
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Application::GetDispatchLevel()
+{
+ return ImplGetSVData()->maAppData.mnDispatchLevel;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::AnyInput( USHORT nType )
+{
+#ifndef REMOTE_APPSERVER
+ return SalInstance::AnyInput( nType );
+#else
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if( ( nType & ( INPUT_ANY ) ) == ( INPUT_ANY ) )
+ {
+ return( pSVData->mpRmEventQueue->HasMouseEvent() ||
+ pSVData->mpRmEventQueue->HasKeyEvent() ||
+ pSVData->mpRmEventQueue->HasPaintEvent() ||
+ pSVData->mpRmEventQueue->HasTimerEvent() ||
+ pSVData->mpRmEventQueue->HasOtherEvent() );
+ }
+ else if( ( nType & ( INPUT_MOUSEANDKEYBOARD ) ) == ( INPUT_MOUSEANDKEYBOARD ) )
+ {
+ return( pSVData->mpRmEventQueue->HasMouseEvent() ||
+ pSVData->mpRmEventQueue->HasKeyEvent() );
+ }
+ else
+ {
+ if( nType & INPUT_MOUSE )
+ return pSVData->mpRmEventQueue->HasMouseEvent();
+
+ if( nType & INPUT_KEYBOARD )
+ return pSVData->mpRmEventQueue->HasKeyEvent();
+
+ if( nType & INPUT_PAINT )
+ return pSVData->mpRmEventQueue->HasPaintEvent();
+
+ if( nType & INPUT_TIMER )
+ return pSVData->mpRmEventQueue->HasTimerEvent();
+
+ if( nType & INPUT_OTHER )
+ return pSVData->mpRmEventQueue->HasOtherEvent();
+ }
+
+ return FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::GetLastInputInterval()
+{
+ return (Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime);
+}
+
+// -----------------------------------------------------------------------
+
+extern int nImplSysDialog;
+
+BOOL Application::IsUICaptured()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ // Wenn Mouse gecaptured, oder im TrackingModus oder im Auswahlmodus
+ // eines FloatingWindows (wie Menus, Aufklapp-ToolBoxen) soll kein
+ // weiteres Fenster aufgezogen werden
+ if ( pSVData->maWinData.mpCaptureWin || pSVData->maWinData.mpTrackWin ||
+ pSVData->maWinData.mpFirstFloat || DragManager::GetDragManager() ||
+ nImplSysDialog )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsUserActive( USHORT nTest )
+{
+ if ( nTest & (USERACTIVE_MOUSEDRAG | USERACTIVE_INPUT) )
+ {
+ if ( IsUICaptured() )
+ return TRUE;
+ }
+
+ if ( nTest & USERACTIVE_INPUT )
+ {
+ if ( GetLastInputInterval() < 500 )
+ return TRUE;
+
+ if ( AnyInput( INPUT_KEYBOARD ) )
+ return TRUE;
+ }
+
+ if ( nTest & USERACTIVE_MODALDIALOG )
+ {
+ if ( ImplGetSVData()->maAppData.mnModalDialog )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SystemSettingsChanging( AllSettings& rSettings,
+ Window* pFrame )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Application::MergeSystemSettings( AllSettings& rSettings )
+{
+#ifndef REMOTE_APPSERVER
+ ImplGetDefaultWindow()->ImplGetFrame()->UpdateSettings( rSettings );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetSettings( const AllSettings& rSettings )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maAppData.mpSettings )
+ {
+ pSVData->maAppData.mpSettings = new AllSettings();
+ *pSVData->maAppData.mpSettings = rSettings;
+ }
+ else
+ {
+ AllSettings aOldSettings = *pSVData->maAppData.mpSettings;
+ *pSVData->maAppData.mpSettings = rSettings;
+ ULONG nChangeFlags = aOldSettings.GetChangeFlags( *pSVData->maAppData.mpSettings );
+ if ( nChangeFlags )
+ {
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
+ GetpApp()->DataChanged( aDCEvt );
+
+ // Update all windows
+ Window* pFirstFrame = pSVData->maWinData.mpFirstFrame;
+ // Daten, die neu berechnet werden muessen, zuruecksetzen
+ long nOldDPIX;
+ long nOldDPIY;
+ if ( pFirstFrame )
+ {
+ nOldDPIX = pFirstFrame->mnDPIX;
+ nOldDPIY = pFirstFrame->mnDPIY;
+ pSVData->maGDIData.mnAppFontX = 0;
+ }
+ Window* pFrame = pFirstFrame;
+ while ( pFrame )
+ {
+ // AppFont-Cache-Daten zuruecksetzen
+ pFrame->mpFrameData->meMapUnit = MAP_PIXEL;
+
+ // UpdateSettings am ClientWindow aufrufen, damit
+ // die Daten nicht doppelt geupdatet werden
+ Window* pClientWin = pFrame;
+ while ( pClientWin->ImplGetClientWindow() )
+ pClientWin = pClientWin->ImplGetClientWindow();
+ pClientWin->UpdateSettings( rSettings, TRUE );
+
+ Window* pTempWin = pFrame->mpFrameData->mpFirstOverlap;
+ while ( pTempWin )
+ {
+ // UpdateSettings am ClientWindow aufrufen, damit
+ // die Daten nicht doppelt geupdatet werden
+ pClientWin = pTempWin;
+ while ( pClientWin->ImplGetClientWindow() )
+ pClientWin = pClientWin->ImplGetClientWindow();
+ pClientWin->UpdateSettings( rSettings, TRUE );
+ pTempWin = pTempWin->mpNextOverlap;
+ }
+
+ pFrame = pFrame->mpFrameData->mpNextFrame;
+ }
+
+ // Wenn sich die DPI-Aufloesung fuer Screen-Ausgaben
+ // geaendert hat, setzen wir auch bei allen
+ // Screen-Kompatiblen VirDev's die neue Aufloesung
+ pFirstFrame = pSVData->maWinData.mpFirstFrame;
+ if ( pFirstFrame )
+ {
+ if ( (pFirstFrame->mnDPIX != nOldDPIX) ||
+ (pFirstFrame->mnDPIY != nOldDPIY) )
+ {
+ VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
+ while ( pVirDev )
+ {
+ if ( pVirDev->mbScreenComp &&
+ (pVirDev->mnDPIX == nOldDPIX) &&
+ (pVirDev->mnDPIY == nOldDPIY) )
+ {
+ pVirDev->mnDPIX = pFirstFrame->mnDPIX;
+ pVirDev->mnDPIY = pFirstFrame->mnDPIY;
+ if ( pVirDev->IsMapMode() )
+ {
+ MapMode aMapMode = pVirDev->GetMapMode();
+ pVirDev->SetMapMode();
+ pVirDev->SetMapMode( aMapMode );
+ }
+ }
+
+ pVirDev = pVirDev->mpNext;
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const AllSettings& Application::GetSettings()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maAppData.mpSettings )
+ pSVData->maAppData.mpSettings = new AllSettings();
+ return *(pSVData->maAppData.mpSettings);
+}
+
+// -----------------------------------------------------------------------
+
+void Application::NotifyAllWindows( DataChangedEvent& rDCEvt )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pFrame = pSVData->maWinData.mpFirstFrame;
+ while ( pFrame )
+ {
+ pFrame->NotifyAllChilds( rDCEvt );
+
+ Window* pSysWin = pFrame->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ pSysWin->NotifyAllChilds( rDCEvt );
+ pSysWin = pSysWin->mpNextOverlap;
+ }
+
+ pFrame = pFrame->mpFrameData->mpNextFrame;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::PostUserEvent( ULONG nEvent, void* pEventData )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, nEvent, pEventData );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::PostUserEvent( const Link& rLink, void* pCaller )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, rLink, pCaller );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::PostUserEvent( ULONG& rEventId, ULONG nEvent, void* pEventData )
+{
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = nEvent;
+ pSVEvent->mpData = pEventData;
+ pSVEvent->mpLink = NULL;
+ pSVEvent->mpWindow = NULL;
+ pSVEvent->mbCall = TRUE;
+ rEventId = (ULONG)pSVEvent;
+#ifndef REMOTE_APPSERVER
+ if ( ImplGetDefaultWindow()->ImplGetFrame()->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ delete pSVEvent;
+ return FALSE;
+ }
+#else
+ ExtRmEvent* pEvt = new ExtRmEvent( RMEVENT_USEREVENT, NULL, pSVEvent );
+ ImplPostEvent( pEvt );
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::PostUserEvent( ULONG& rEventId, const Link& rLink, void* pCaller )
+{
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = 0;
+ pSVEvent->mpData = pCaller;
+ pSVEvent->mpLink = new Link( rLink );
+ pSVEvent->mpWindow = NULL;
+ pSVEvent->mbCall = TRUE;
+ rEventId = (ULONG)pSVEvent;
+#ifndef REMOTE_APPSERVER
+ if ( ImplGetDefaultWindow()->ImplGetFrame()->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ delete pSVEvent;
+ return FALSE;
+ }
+#else
+ ExtRmEvent* pEvt = new ExtRmEvent( RMEVENT_USEREVENT, NULL, pSVEvent );
+ ImplPostEvent( pEvt );
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveUserEvent( ULONG nUserEvent )
+{
+ ImplSVEvent* pSVEvent = (ImplSVEvent*)nUserEvent;
+
+ DBG_ASSERT( !pSVEvent->mpWindow,
+ "Application::RemoveUserEvent(): Event is send to a window" );
+ DBG_ASSERT( pSVEvent->mbCall,
+ "Application::RemoveUserEvent(): Event is already removed" );
+
+ if ( pSVEvent->mpWindow )
+ {
+ pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
+ pSVEvent->mpWindow = NULL;
+ }
+
+ pSVEvent->mbCall = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::InsertIdleHdl( const Link& rLink, USHORT nPrio )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Falls er noch nicht existiert, dann anlegen
+ if ( !pSVData->maAppData.mpIdleMgr )
+ pSVData->maAppData.mpIdleMgr = new ImplIdleMgr;
+
+ return pSVData->maAppData.mpIdleMgr->InsertIdleHdl( rLink, nPrio );
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveIdleHdl( const Link& rLink )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maAppData.mpIdleMgr )
+ pSVData->maAppData.mpIdleMgr->RemoveIdleHdl( rLink );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow* Application::GetAppWindow()
+{
+ return ImplGetSVData()->maWinData.mpAppWin;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Application::GetFocusWindow()
+{
+ return ImplGetSVData()->maWinData.mpFocusWin;
+}
+
+// -----------------------------------------------------------------------
+
+OutputDevice* Application::GetDefaultDevice()
+{
+ return ImplGetDefaultWindow();
+}
+
+// -----------------------------------------------------------------------
+
+Window* Application::GetFirstTopLevelWindow()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ return pSVData->maWinData.mpFirstFrame;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Application::GetNextTopLevelWindow( Window* pWindow )
+{
+ return pWindow->mpFrameData->mpNextFrame;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetAppName( const XubString& rUniqueName )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Falls er noch nicht existiert, dann anlegen
+ if ( !pSVData->maAppData.mpAppName )
+ pSVData->maAppData.mpAppName = new XubString( rUniqueName );
+ else
+ *(pSVData->maAppData.mpAppName) = rUniqueName;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Application::GetAppName()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maAppData.mpAppName )
+ return *(pSVData->maAppData.mpAppName);
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetDisplayName( const UniString& rName )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Falls er noch nicht existiert, dann anlegen
+ if ( !pSVData->maAppData.mpDisplayName )
+ pSVData->maAppData.mpDisplayName = new UniString( rName );
+ else
+ *(pSVData->maAppData.mpDisplayName) = rName;
+}
+
+// -----------------------------------------------------------------------
+
+UniString Application::GetDisplayName()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maAppData.mpDisplayName )
+ return *(pSVData->maAppData.mpDisplayName);
+ else if ( pSVData->maWinData.mpAppWin )
+ return pSVData->maWinData.mpAppWin->GetText();
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::InsertAccel( Accelerator* pAccel )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maAppData.mpAccelMgr )
+ pSVData->maAppData.mpAccelMgr = new ImplAccelManager();
+ return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveAccel( Accelerator* pAccel )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maAppData.mpAccelMgr )
+ pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void Application::FlushAccel()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maAppData.mpAccelMgr )
+ pSVData->maAppData.mpAccelMgr->FlushAccel();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetHelp( Help* pHelp )
+{
+ ImplGetSVData()->maAppData.mpHelp = pHelp;
+}
+
+// -----------------------------------------------------------------------
+
+Help* Application::GetHelp()
+{
+ return ImplGetSVData()->maAppData.mpHelp;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::EnableAutoHelpId( BOOL bEnabled )
+{
+ ImplGetSVData()->maHelpData.mbAutoHelpId = bEnabled;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsAutoHelpIdEnabled()
+{
+ return ImplGetSVData()->maHelpData.mbAutoHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::EnableAutoMnemonic( BOOL bEnabled )
+{
+ ImplGetSVData()->maAppData.mbAutoMnemonics = bEnabled;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsAutoMnemonicEnabled()
+{
+ return ImplGetSVData()->maAppData.mbAutoMnemonics;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetDialogScaleX( short nScale )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mnDialogScaleX = nScale;
+ pSVData->maGDIData.mnAppFontX = pSVData->maGDIData.mnRealAppFontX;
+ if ( nScale )
+ pSVData->maGDIData.mnAppFontX += (pSVData->maGDIData.mnAppFontX*nScale)/100;
+}
+
+// -----------------------------------------------------------------------
+
+short Application::GetDialogScaleX()
+{
+ return ImplGetSVData()->maAppData.mnDialogScaleX;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetDefDialogParent( Window* pWindow )
+{
+ ImplGetSVData()->maWinData.mpDefDialogParent = pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Application::GetDefDialogParent()
+{
+ return ImplGetSVData()->maWinData.mpDefDialogParent;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::EnableDialogCancel( BOOL bDialogCancel )
+{
+ ImplGetSVData()->maAppData.mbDialogCancel = bDialogCancel;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsDialogCancelEnabled()
+{
+ return ImplGetSVData()->maAppData.mbDialogCancel;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetSystemWindowMode( USHORT nMode )
+{
+ ImplGetSVData()->maAppData.mnSysWinMode = nMode;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Application::GetSystemWindowMode()
+{
+ return ImplGetSVData()->maAppData.mnSysWinMode;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetResourcePath( const XubString& rPath )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Falls er noch nicht existiert, dann anlegen
+ if ( !pSVData->maAppData.mpResPath )
+ pSVData->maAppData.mpResPath = new XubString( rPath );
+ else
+ *(pSVData->maAppData.mpResPath) = rPath;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& Application::GetResourcePath()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maAppData.mpResPath )
+ return *(pSVData->maAppData.mpResPath);
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::EnterMultiThread( BOOL bEnter )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+#if defined( WIN ) || defined( WNT ) || defined( OS2 )
+ ::EnterMultiThread( bEnter );
+#endif
+
+ if ( bEnter )
+ {
+ pSVData->mnThreadCount++;
+
+#ifndef REMOTE_APPSERVER
+ // Unser DefaultWindow muss vor einem Thread-Starten erzeugt werden,
+ // damit dieses im Hauptthread laeuft
+ ImplGetDefaultWindow();
+#endif
+ }
+ else
+ pSVData->mnThreadCount--;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsMultiThread()
+{
+ return (ImplGetSVData()->mnThreadCount != 0);
+}
+
+// -----------------------------------------------------------------------
+
+UniqueItemId Application::CreateUniqueId()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maAppData.mpUniqueIdCont )
+ pSVData->maAppData.mpUniqueIdCont = new UniqueIdContainer( UNIQUEID_SV_BEGIN );
+ return pSVData->maAppData.mpUniqueIdCont->CreateId();
+}
+
+// -----------------------------------------------------------------------
+
+SystemInfoType Application::GetClientSystem()
+{
+#ifndef REMOTE_APPSERVER
+ return GetServerSystem();
+#else
+ static SystemInfoType nImplClientSystemInfo = 0;
+ if ( !nImplClientSystemInfo )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->mxStatus.is() )
+ nImplClientSystemInfo = (SystemInfoType)pSVData->mxStatus->GetSystemType();
+ }
+
+ return nImplClientSystemInfo;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+SystemInfoType Application::GetServerSystem()
+{
+#if defined( WIN )
+ return SYSTEMINFO_SYSTEM_WINDOWS | SYSTEMINFO_SYSTEMBASE_DOS;
+#elif defined( WNT )
+ return SYSTEMINFO_SYSTEM_WINDOWS | SYSTEMINFO_SYSTEMBASE_NT;
+#elif defined( OS2 )
+ return SYSTEMINFO_SYSTEM_OS2;
+#elif defined( MAC )
+ return SYSTEMINFO_SYSTEM_MAC;
+#elif defined( UNX )
+#if defined( LINUX )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_LINUX;
+#elif defined( SOLARIS )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_SOLARIS;
+#elif defined( SCO )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_SCO;
+#elif defined( NETBSD )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_NETBSD;
+#elif defined( AIX )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_AIX;
+#elif defined( IRIX )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_IRIX;
+#elif defined( HPUX )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_HPUX;
+#elif defined( FREEBSD )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_FREEBSD;
+#elif defined( MACOSX )
+ return SYSTEMINFO_SYSTEM_UNIX | SYSTEMINFO_SYSTEMBASE_MACOSX;
+#else
+#error Unknown Unix-System, new SystemBase must be defined!
+#endif
+#else
+#error Unknown System, new System must be defined!
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::IsRemoteServer()
+{
+#ifndef REMOTE_APPSERVER
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void* Application::GetRemoteEnvironment()
+{
+#ifndef REMOTE_APPSERVER
+ return NULL;
+#else
+ return ImplGetSVData()->mhRemoteEnv;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > Application::GetVCLToolkit()
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > xT;
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ xT = pWrapper->GetVCLToolkit();
+ return xT;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RegisterUnoServices()
+{
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ pWrapper->RegisterUnoServices();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetUnoWrapper( UnoWrapperBase* pWrapper )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ DBG_ASSERT( !pSVData->mpUnoWrapper, "SetUnoWrapper: Wrapper allready exists" );
+ pSVData->mpUnoWrapper = pWrapper;
+}
+
+// -----------------------------------------------------------------------
+
+UnoWrapperBase* Application::GetUnoWrapper()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ return pSVData->mpUnoWrapper;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetFilterHdl( const Link& rLink )
+{
+ ImplGetSVData()->maGDIData.mpGrfConverter->SetFilterHdl( rLink );
+}
+
+// -----------------------------------------------------------------------
+
+const Link& Application::GetFilterHdl()
+{
+ return ImplGetSVData()->maGDIData.mpGrfConverter->GetFilterHdl();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::AccessNotify( const AccessNotification& rNotification )
+{
+ GetFirstAccessHdl().Call( (void*) &rNotification );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Application::GenerateAccessEvent( ULONG nAccessEvent,
+ long nData1,
+ long nData2,
+ long nData3 )
+{
+ BOOL bRet = FALSE;
+
+ switch( nAccessEvent )
+ {
+ case( ACCESS_EVENT_DLGCONTROLS ):
+ {
+ if( IsInModalMode() )
+ {
+ Window* pDlgWin = GetFocusWindow();
+ BOOL bFound = FALSE;
+
+ // find modal dialog
+ while( pDlgWin && !bFound )
+ {
+ switch( pDlgWin->GetType() )
+ {
+ case( WINDOW_MESSBOX ):
+ case( WINDOW_INFOBOX ):
+ case( WINDOW_WARNINGBOX ):
+ case( WINDOW_ERRORBOX ):
+ case( WINDOW_QUERYBOX ):
+ case( WINDOW_MODALDIALOG ):
+ case( WINDOW_PATHDIALOG ):
+ case( WINDOW_FILEDIALOG ):
+ case( WINDOW_PRINTERSETUPDIALOG ):
+ case( WINDOW_PRINTDIALOG ):
+ case( WINDOW_COLORDIALOG ):
+ case( WINDOW_FONTDIALOG ):
+ case( WINDOW_TABDIALOG ):
+ case( WINDOW_BUTTONDIALOG ):
+ bFound = TRUE;
+ break;
+
+ default:
+ pDlgWin = pDlgWin->GetWindow( WINDOW_PARENT );
+ break;
+ }
+ }
+
+ if( pDlgWin )
+ {
+ AccessNotify( AccessNotification( ACCESS_EVENT_DLGCONTROLS, pDlgWin ) );
+ bRet = TRUE;
+ }
+ }
+ }
+ break;
+
+ case( ACCESS_EVENT_KEY ):
+ AccessNotify( AccessNotification( ACCESS_EVENT_KEY, nData1, nData2, nData3 ) );
+ break;
+
+ default:
+ break;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::AddAccessHdl( const Link& rLink )
+{
+ if( !ImplGetSVData()->maAppData.mpAccessList )
+ ImplGetSVData()->maAppData.mpAccessList = new List;
+
+ List* pList = ImplGetSVData()->maAppData.mpAccessList;
+ BOOL bInserted = FALSE;
+
+ for( void* pLink = pList->First(); pLink; pLink = pList->Next() )
+ {
+ if( *(Link*) pLink == rLink )
+ {
+ bInserted = TRUE;
+ break;
+ }
+ }
+
+ if( !bInserted )
+ {
+ ImplGetSVData()->maAppData.mnAccessCount++;
+ pList->Insert( new Link( rLink ), LIST_APPEND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveAccessHdl( const Link& rLink )
+{
+ List* pList = ImplGetSVData()->maAppData.mpAccessList;
+
+ if( pList )
+ {
+ for( void* pLink = pList->First(); pLink; pLink = pList->Next() )
+ {
+ if( *(Link*) pLink == rLink )
+ {
+ ImplGetSVData()->maAppData.mnAccessCount--;
+ delete (Link*) pList->Remove( pLink );
+ break;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Application::GetAccessHdlCount()
+{
+ return ImplGetSVData()->maAppData.mnAccessCount;
+}
+
+// -----------------------------------------------------------------------
+
+Link Application::GetFirstAccessHdl()
+{
+ List* pList = ImplGetSVData()->maAppData.mpAccessList;
+
+ if( pList && pList->Count() )
+ return *(Link*) pList->First();
+ else
+ return Link();
+}
+
+// -----------------------------------------------------------------------
+
+void Application::CallNextAccessHdl( AccessNotification* pData )
+{
+ List* pList = ImplGetSVData()->maAppData.mpAccessList;
+
+ if( pList )
+ {
+ Link* pNext = (Link*) pList->Next();
+
+ if( pNext )
+ pNext->Call( pData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplCallHotKey( const KeyCode& rKeyCode )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
+ while ( pHotKeyData )
+ {
+ if ( pHotKeyData->maKeyCode.IsDefinedKeyCodeEqual( rKeyCode ) )
+ {
+ pHotKeyData->maLink.Call( pHotKeyData->mpUserData );
+ return TRUE;
+ }
+
+ pHotKeyData = pHotKeyData->mpNext;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFreeHotKeyData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplHotKey* pTempHotKeyData;
+ ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
+ while ( pHotKeyData )
+ {
+ pTempHotKeyData = pHotKeyData->mpNext;
+ delete pHotKeyData;
+ pHotKeyData = pTempHotKeyData;
+ }
+
+ pSVData->maAppData.mpFirstHotKey = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::AddHotKey( const KeyCode& rKeyCode, const Link& rLink, void* pData )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplHotKey* pHotKeyData = new ImplHotKey;
+ pHotKeyData->mpUserData = pData;
+ pHotKeyData->maKeyCode = rKeyCode;
+ pHotKeyData->maLink = rLink;
+ pHotKeyData->mpNext = pSVData->maAppData.mpFirstHotKey;
+ pSVData->maAppData.mpFirstHotKey = pHotKeyData;
+ return (ULONG)pHotKeyData;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveHotKey( ULONG nId )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplHotKey* pFindHotKeyData = (ImplHotKey*)nId;
+ ImplHotKey* pPrevHotKeyData = NULL;
+ ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
+ while ( pHotKeyData )
+ {
+ if ( pHotKeyData == pFindHotKeyData )
+ {
+ if ( pPrevHotKeyData )
+ pPrevHotKeyData->mpNext = pFindHotKeyData->mpNext;
+ else
+ pSVData->maAppData.mpFirstHotKey = pFindHotKeyData->mpNext;
+ delete pFindHotKeyData;
+ break;
+ }
+
+ pPrevHotKeyData = pHotKeyData;
+ pHotKeyData = pHotKeyData->mpNext;
+ }
+
+ DBG_ASSERT( pHotKeyData, "Application::RemoveHotKey() - HotKey is not added" );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFreeEventHookData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplEventHook* pTempEventHookData;
+ ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
+ while ( pEventHookData )
+ {
+ pTempEventHookData = pEventHookData->mpNext;
+ delete pEventHookData;
+ pEventHookData = pTempEventHookData;
+ }
+
+ pSVData->maAppData.mpFirstEventHook = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Application::AddEventHook( VCLEventHookProc pProc, void* pData )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplEventHook* pEventHookData = new ImplEventHook;
+ pEventHookData->mpUserData = pData;
+ pEventHookData->mpProc = pProc;
+ pEventHookData->mpNext = pSVData->maAppData.mpFirstEventHook;
+ pSVData->maAppData.mpFirstEventHook = pEventHookData;
+ return (ULONG)pEventHookData;
+}
+
+// -----------------------------------------------------------------------
+
+void Application::RemoveEventHook( ULONG nId )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplEventHook* pFindEventHookData = (ImplEventHook*)nId;
+ ImplEventHook* pPrevEventHookData = NULL;
+ ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
+ while ( pEventHookData )
+ {
+ if ( pEventHookData == pFindEventHookData )
+ {
+ if ( pPrevEventHookData )
+ pPrevEventHookData->mpNext = pFindEventHookData->mpNext;
+ else
+ pSVData->maAppData.mpFirstEventHook = pFindEventHookData->mpNext;
+ delete pFindEventHookData;
+ break;
+ }
+
+ pPrevEventHookData = pEventHookData;
+ pEventHookData = pEventHookData->mpNext;
+ }
+
+ DBG_ASSERT( pEventHookData, "Application::RemoveEventHook() - EventHook is not added" );
+}
+
+// -----------------------------------------------------------------------
+
+long Application::CallEventHooks( NotifyEvent& rEvt )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ long nRet = 0;
+ ImplEventHook* pTempEventHookData;
+ ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
+ while ( pEventHookData )
+ {
+ pTempEventHookData = pEventHookData->mpNext;
+ nRet = pEventHookData->mpProc( rEvt, pEventHookData->mpUserData );
+ if ( nRet )
+ break;
+ pEventHookData = pTempEventHookData;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+long Application::CallPreNotify( NotifyEvent& rEvt )
+{
+ return ImplCallPreNotify( rEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long Application::CallEvent( NotifyEvent& rEvt )
+{
+ return ImplCallEvent( rEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Application::SetAppInternational( const International& rIntn )
+{
+ AllSettings aSettings = GetSettings();
+ aSettings.SetInternational( rIntn );
+ SetSettings( aSettings );
+}
+
+// -----------------------------------------------------------------------
+
+const International& Application::GetAppInternational()
+{
+ return GetSettings().GetInternational();
+}
+
+// =======================================================================
+
+void InitVCL()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitVCL()
+{
+}
diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
new file mode 100644
index 000000000000..7b7e1c38b2ed
--- /dev/null
+++ b/vcl/source/app/svdata.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * $RCSfile: svdata.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#define _SV_SVDATA_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#endif
+
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#define private public
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+
+#ifndef _VCL_UNOWRAP_HXX
+#include <unowrap.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+// static Empty-SV-String
+static XubString aImplSVEmptyStr;
+XubString& rImplSVEmptyStr = aImplSVEmptyStr;
+#ifdef ENABLEUNICODE
+static ByteString aImplSVEmptyByteStr;
+ByteString& rImplSVEmptyByteStr = aImplSVEmptyByteStr;
+#endif
+
+#ifndef WIN
+ImplSVData private_aImplSVData;
+// static SV-Data
+ImplSVData* pImplSVData = &private_aImplSVData;
+#endif
+
+// static SharedLib SV-Data
+ImplSVShlData aImplSVShlData;
+
+// =======================================================================
+
+void ImplInitSVData()
+{
+#ifndef WIN
+ ImplSVData* pSVData = pImplSVData;
+ ImplSVData** ppSVData = (ImplSVData**)GetAppData( SHL_SV );
+ *ppSVData = &private_aImplSVData;
+#else
+ // alloc global instance data
+ ImplSVData* pSVData = new ImplSVData;
+ ImplSVData** ppSVData = (ImplSVData**)GetAppData( SHL_SV );
+ *ppSVData = pSVData;
+#endif
+
+ // init global sharedlib data
+ // ...
+
+ // init global instance data
+ memset( pSVData, 0, sizeof( ImplSVData ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDeInitSVData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // delete global instance data
+
+ if ( pSVData->mpUnoWrapper )
+ {
+ pSVData->mpUnoWrapper->Destroy();
+ pSVData->mpUnoWrapper = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDestroySVData()
+{
+ ImplSVData** ppSVData = (ImplSVData**)GetAppData( SHL_SV );
+ ImplSVData* pSVData = *ppSVData;
+#ifdef WIN
+ delete pSVData;
+#endif
+
+ // delete global sharedlib data
+ // ...
+
+ *ppSVData = NULL;
+#ifndef WIN
+ pImplSVData = NULL;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Window* ImplGetDefaultWindow()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpAppWin )
+ return pSVData->maWinData.mpAppWin;
+
+ if ( !pSVData->mpDefaultWin )
+ {
+ DBG_WARNING( "ImplGetDefaultWindow(): No AppWindow" );
+ Application::GetSolarMutex().acquire();
+ pSVData->mpDefaultWin = new WorkWindow( 0, 0 );
+ Application::GetSolarMutex().release();
+ }
+
+ return pSVData->mpDefaultWin;
+}
+
+// -----------------------------------------------------------------------
+
+#define VCL_CREATERESMGR_NAME( Name ) #Name MAKE_NUMSTR( SUPD )
+#define VCL_CREATERESMGR( Name ) ResMgr::CreateResMgr( VCL_CREATERESMGR_NAME( Name ) )
+
+ResMgr* ImplGetResMgr()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->mpResMgr )
+ pSVData->mpResMgr = VCL_CREATERESMGR( vcl );
+ return pSVData->mpResMgr;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+Window* ImplFindWindow( const SalFrame* pFrame, Point& rSalFramePos )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pFrameWindow = pSVData->maWinData.mpFirstFrame;
+ while ( pFrameWindow )
+ {
+ if ( pFrameWindow->ImplGetFrame() == pFrame )
+ {
+ Window* pWindow = pFrameWindow->ImplFindWindow( rSalFramePos );
+ if ( !pWindow )
+ pWindow = pFrameWindow->ImplGetWindow();
+ rSalFramePos = pWindow->ImplFrameToOutput( rSalFramePos );
+ return pWindow;
+ }
+ pFrameWindow = pFrameWindow->mpFrameData->mpNextFrame;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
new file mode 100644
index 000000000000..2b7d389a5aeb
--- /dev/null
+++ b/vcl/source/app/svmain.cxx
@@ -0,0 +1,714 @@
+/*************************************************************************
+ *
+ * $RCSfile: svmain.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SVMAIN_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALSOUND_HXX
+#include <salsound.hxx>
+#endif
+#ifndef _SV_SALOGL_HXX
+#include <salogl.hxx>
+#endif
+#ifndef _SV_SALWTYPE_HXX
+#include <salwtype.hxx>
+#endif
+#ifndef _OSL_UTIL_H
+#include <osl/util.h>
+#endif
+#ifndef _VOS_SIGNAL_HXX
+#include <vos/signal.hxx>
+#endif
+#ifndef _VOS_CHANNEL_HXX
+#include <vos/channel.hxx>
+#endif
+#ifndef _VOS_SOCKET_HXX
+#include <vos/socket.hxx>
+#endif
+#ifndef _TOOLS_H
+#include <tools/tools.h>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _UNIQID_HXX
+#include <tools/unqid.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_DBGGUI_HXX
+#include <dbggui.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#ifndef _SV_RESMGR_HXX
+#include <resmgr.hxx>
+#endif
+#ifndef _SV_ACCMGR_HXX
+#include <accmgr.hxx>
+#endif
+#ifndef _SV_IDLEMGR_HXX
+#include <idlemgr.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+// HACK: Only for Exception-Hack
+#ifndef _SV_SYSEXCHG_HXX
+#include <sysexchg.hxx>
+#endif
+
+#include <vos/process.hxx>
+#include <osl/file.hxx>
+
+#ifdef REMOTE_APPSERVER
+#include <config.hxx>
+#include <ooffice.hxx>
+#include <rversion.h>
+#include <xevthdl.hxx>
+#include <rmevents.hxx>
+#include <rmprint.hxx>
+#include <outdev.h>
+#include <vos/mutex.hxx>
+#include <vos/timer.hxx>
+#include <unobrok.hxx>
+#include "rvp.hxx"
+#include <atom.hxx>
+
+#include <cppuhelper/servicefactory.hxx>
+#include <unotools/processfactory.hxx>
+#include <unotools/regpathhelper.hxx>
+
+#include <com/sun/star/portal/client/XRmStatus.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::portal::client;
+using namespace ::cppu;
+using namespace ::rtl;
+
+#ifdef UNX
+class SalData
+{
+ void Init (int *pIPointer, char *pCPointer[] );
+};
+void SalData::Init (int *pIPointer, char *pCPointer[] )
+{};
+#endif /* UNX */
+
+#endif /* REMOTE_APPSERVER */
+
+#pragma hdrstop
+
+// =======================================================================
+
+class ImplVCLExceptionHandler : public ::vos::OSignalHandler
+{
+public:
+ virtual ::vos::OSignalHandler::TSignalAction SAL_CALL signal( ::vos::OSignalHandler::TSignalInfo* pInfo );
+};
+
+// -----------------------------------------------------------------------
+
+::vos::OSignalHandler::TSignalAction SAL_CALL ImplVCLExceptionHandler::signal( ::vos::OSignalHandler::TSignalInfo* pInfo )
+{
+ static BOOL bIn = FALSE;
+
+ // Wenn wir nocheinmal abstuerzen, verabschieden wir uns gleich
+ if ( !bIn )
+ {
+ USHORT nVCLException = 0;
+
+ // UAE
+ if ( (pInfo->Signal == TSignal_AccessViolation) ||
+ (pInfo->Signal == TSignal_IntegerDivideByZero) ||
+ (pInfo->Signal == TSignal_FloatDivideByZero) ||
+ (pInfo->Signal == TSignal_DebugBreak) )
+ nVCLException = EXC_SYSTEM;
+
+ // RC
+ if ((pInfo->Signal == TSignal_SignalUser) &&
+ (pInfo->UserSignal == OSL_SIGNAL_USER_RESOURCEFAILURE) )
+ nVCLException = EXC_RSCNOTLOADED;
+
+ // DISPLAY-Unix
+ if ((pInfo->Signal == TSignal_SignalUser) &&
+ (pInfo->UserSignal == OSL_SIGNAL_USER_X11SUBSYSTEMERROR) )
+ nVCLException = EXC_DISPLAY;
+
+ // Remote-Client
+ if ((pInfo->Signal == TSignal_SignalUser) &&
+ (pInfo->UserSignal == OSL_SIGNAL_USER_RVPCONNECTIONERROR) )
+ nVCLException = EXC_REMOTE;
+
+ if ( nVCLException )
+ {
+ bIn = TRUE;
+ // Timer nicht mehr anhalten, da ansonsten die UAE-Box
+ // auch nicht mehr gepaintet wird
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->mpApp )
+ {
+ USHORT nOldMode = Application::GetSystemWindowMode();
+ Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
+ pSVData->mpApp->Exception( nVCLException );
+ Application::SetSystemWindowMode( nOldMode );
+ }
+ bIn = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ return NAMESPACE_VOS(OSignalHandler)::TAction_CallNextHandler;
+#else
+ return NAMESPACE_VOS(OSignalHandler)::TAction_KillApplication;
+#endif
+ }
+ }
+
+ return NAMESPACE_VOS(OSignalHandler)::TAction_CallNextHandler;
+}
+
+BOOL SVMain()
+{
+ osl_setSUPD( SUPD );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+
+ DBG_ASSERT( pSVData->mpApp, "no instance of class Application" );
+
+ // SV bei den Tools anmelden
+ InitTools();
+
+ // Main-Thread-Id merken
+ pSVData->mnMainThreadId = ::vos::OThread::getCurrentIdentifier();
+
+ NAMESPACE_VOS( OStartupInfo ) aStartInfo;
+ NAMESPACE_RTL( OUString ) aExeFileName;
+
+#ifdef REMOTE_APPSERVER
+ // create a readonly applicat rdb.
+ // NOTE : This is a hack, a servicemanager is needed before SFX, so
+ // there is created one with the readonly registry. There
+ // now exists 2 Servicemanager
+
+ Application::EnterMultiThread( TRUE );
+
+ Reference< XMultiServiceFactory > rSMgr = createServiceFactory();
+ Reference< XInterface > x = rSMgr->createInstance(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.registry.SimpleRegistry" ) ) );
+ Reference< XSimpleRegistry > rSimple( x , UNO_QUERY );
+ rSimple->open( ::utl::getPathToSystemRegistry() , sal_True , sal_False );
+ if( rSimple->isValid() )
+ {
+ Reference < XInitialization > rInit( rSMgr , UNO_QUERY );
+ Any a;
+ a <<= rSimple;
+ Sequence< Any > seq( &a , 1 );
+ rInit->initialize( seq );
+ }
+ // servicemanager up -> copy user installation
+ Any aAny;
+ Reference <XInterface> xRef = rSMgr->createInstanceWithArguments(
+ OUString::createFromAscii( "com.sun.star.portal.InstallUser" ),
+ Sequence<Any>( &aAny, 1 ) );
+
+
+ // OSL_ENSURE( 0 , "Office is waiting ....\n" );
+
+
+// sal_Bool bStandAloneMode = sal_False;
+// sal_Bool bStartDesktop = sal_True;
+
+ OUString conDcp;
+
+ // Anderes Flag setzen, wenn der Server von Hand gestartet wird...
+ USHORT nArgs = Application::GetCommandLineParamCount();
+ for( USHORT n = 0; n < nArgs; n++ )
+ {
+ XubString aParam = Application::GetCommandLineParam( n );
+ if ( (aParam.GetChar( 0 ) == '/') || (aParam.GetChar( 0 ) == '-') )
+ {
+ aParam.SetChar( 0 , (sal_Unicode)'-' );
+ if ( aParam.EqualsIgnoreCaseAscii( "-appserver" ) )
+ ; //bStandAloneMode = sal_True;
+
+ else if ( aParam.EqualsIgnoreCaseAscii( "-bean" ) )
+ ; //bStartDesktop = sal_False;
+
+ else if(aParam.Copy(0, 8).EqualsIgnoreCaseAscii("-accept="))
+ {
+// ++ n;
+// conDcp = Application::GetCommandLineParam(n);
+ conDcp = aParam.Copy(8);
+
+#ifdef DEBUG
+ OString tmp = OUStringToOString(conDcp, RTL_TEXTENCODING_ASCII_US);
+ OSL_TRACE("svmain.cxx: -accept with %s", tmp.getStr());
+#endif
+ }
+ }
+ }
+
+// ::vos::OThread *pUnoBroker = 0;
+
+// if (bStandAloneMode)
+// {
+ Config aCfg( UniString::CreateFromAscii( "remote.ini" ) );
+ aCfg.SetGroup( ByteString("Remote" ) );
+ ByteString s = aCfg.ReadKey( "ROffice" );
+ OUString aROffice = OUString::createFromAscii( s.GetBuffer() );
+ aROffice.trim();
+ if ( ! aROffice.getLength() )
+ aROffice = OUString(
+ RTL_CONSTASCII_USTRINGPARAM("socket,host=localhost,port=8125;urp;"));
+
+
+ if(conDcp.getLength() > 0)
+ aROffice = conDcp;
+
+ // create condition now to avoid race
+ pSVData->mpStartUpCond = new NAMESPACE_VOS(OCondition);
+
+ pSVData->mpUserInfo = new UserOnPrintServer;
+
+ // accept incoming connections
+ if(!vcl_accept::accept(aROffice, rSMgr))
+ return sal_False;
+
+// pUnoBroker = new vcl_AcceptorThread(
+// rSMgr ,
+// NULL, /*rInitialObject ,*/
+// aROffice );
+// }
+// else
+// pUnoBroker = new UnoBrokerThread( rSMgr , NULL /*rInitialObject*/);
+
+
+ pSVData->mpRmEventQueue = new RmEventQueue;
+ pSVData->mpRemotePrinterList = new RemotePrinterList( rSMgr );
+ pSVData->mpWindowObjectMutex = new VOS_NAMESPACE(OMutex,vos);
+ pSVData->maAppData.mpSolarMutex = new ImplRemoteYieldMutex;
+
+ pSVData->maGDIData.mpScreenFontList = new ImplDevFontList;
+ pSVData->maGDIData.mpScreenFontCache = new ImplFontCache( FALSE );
+
+
+// pUnoBroker->create();
+ pSVData->mpStartUpCond->wait();
+ delete pSVData->mpStartUpCond;
+ pSVData->mpStartUpCond = NULL;
+
+ if( pSVData->mxClientFactory.is() )
+ {
+ pSVData->mpAtoms = new ::vcl::AtomClient(
+ Reference< ::com::sun::star::portal::client::XAtomServer >(
+ pSVData->mxClientFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "ClientAtomServer.stardiv.de" ) ) ), UNO_QUERY ) );
+
+ Reference< XInterface > rX = pSVData->mxClientFactory->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "OfficeStatus.stardiv.de" ) ) );
+
+ pSVData->mxStatus = Reference < ::com::sun::star::portal::client::XRmStatus > ( rX , UNO_QUERY );
+ if( pSVData->mxStatus->GetRemoteVersion() != REMOTE_VCLVERSION )
+ {
+ pSVData->mxStatus->ShowError(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong Office-Version")), 0 );
+ pSVData->mxStatus->Quit();
+ return sal_False;
+ }
+ }
+ else
+ {
+ return sal_False;
+ }
+
+ // add client printers
+ REF( NMSP_CLIENT::XRmPrinterEnvironment ) xClientPrinterEnvironment(
+ pSVData->mxClientFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OfficePrinterEnvironment.stardiv.de" ) ) ), NMSP_UNO::UNO_QUERY );
+ if( xClientPrinterEnvironment.is() )
+ {
+ ::rtl::OUString aDefPrinter = xClientPrinterEnvironment->GetDefaultPrinterName();
+ NMSP_UNO::Sequence< ::rtl::OUString > aPrinters;
+ xClientPrinterEnvironment->GetPrinterNames( aPrinters );
+ int nPrinters = aPrinters.getLength();
+ if( nPrinters )
+ {
+ while( nPrinters-- )
+ {
+ ImplAddRemotePrinter(
+ aPrinters.getConstArray()[nPrinters],
+ String::CreateFromAscii( RVP_CLIENT_SERVER_NAME ),
+ aDefPrinter == aPrinters.getConstArray()[nPrinters] ? TRUE : FALSE,
+ FALSE
+ );
+ }
+ }
+ }
+
+ // add printers on print servers
+ ::rtl::OUString aValue;
+ if( aStartInfo.getEnvironment( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SOFFICE_PRINTER_URL" ) ), aValue ) ==
+ NAMESPACE_VOS( OStartupInfo ) :: E_None )
+ {
+ String aPrinterEnv = aValue;
+ if( aPrinterEnv.Len() > 0 )
+ {
+ USHORT nPrinters = aPrinterEnv.GetTokenCount( ';' );
+ for ( USHORT n = 0; n < nPrinters; n++ )
+ {
+ String aPrinterInfo = aPrinterEnv.GetToken( n, ';' );
+
+ String aServer = aPrinterInfo.GetToken( 0, '@' );
+ String aPrinter = aPrinterInfo.GetToken( 1, '@' );
+ BOOL bSetDef = aPrinterInfo.GetToken( 2, '@' ).EqualsAscii( "1" );
+ ImplAddRemotePrinter( aPrinter, aServer, bSetDef, FALSE );
+ }
+ }
+ }
+
+ pSVData->maAppData.mpSolarMutex->acquire();
+
+
+#endif
+
+ // Sal initialisieren
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst = CreateSalInstance();
+ if ( !pSVData->mpDefInst )
+ return FALSE;
+#endif
+
+ // Den AppFileName gleich holen und absolut machen, bevor das
+ // WorkingDirectory sich aendert...
+ aStartInfo.getExecutableFile( aExeFileName );
+
+ // convert path to native file format
+ rtl::OUString aNativeFileName;
+ osl::FileBase::getSystemPathFromNormalizedPath(aExeFileName, aNativeFileName);
+
+ pSVData->maAppData.mpAppFileName = new String( aNativeFileName );
+
+ // Initialize global data
+ pSVData->maGDIData.mpScreenFontList = new ImplDevFontList;
+ pSVData->maGDIData.mpScreenFontCache = new ImplFontCache( FALSE );
+ pSVData->maGDIData.mpGrfConverter = new GraphicConverter;
+
+ // Exception-Handler setzen
+ // HACK: Hier SystemExchange initialisieren, damit Exception-Handler unter Windows funktioniert
+ CreateSystemExchange();
+ ImplVCLExceptionHandler aExceptionHandler;
+
+ // Debug-Daten initialisieren
+ DBGGUI_INIT();
+
+ // Application-Main rufen
+ pSVData->maAppData.mbInAppMain = TRUE;
+ pSVData->mpApp->Main();
+ pSVData->maAppData.mbInAppMain = FALSE;
+
+ // Debug Daten zuruecksetzen
+ DBGGUI_DEINIT();
+
+// #ifdef REMOTE_APPSERVER
+// if( pUnoBroker )
+// pUnoBroker->terminate();
+// #endif
+
+ // Access list
+ List* pList = pSVData->maAppData.mpAccessList;
+ if( pList )
+ {
+ for( void* pLink = pList->First(); pLink; pLink = pList->Next() )
+ delete (Link*) pLink;
+ delete pList;
+ pSVData->maAppData.mpAccessList = NULL;
+ }
+
+ // globale daten wieder freigeben
+#ifndef REMOTE_APPSERVER
+ SalSound::Release();
+ SalOpenGL::Release();
+#endif
+
+ // free global data
+ delete pSVData->maGDIData.mpGrfConverter;
+
+ if ( pSVData->maAppData.mpIdleMgr )
+ delete pSVData->maAppData.mpIdleMgr;
+ ImplDeInitTimer();
+
+ if ( pSVData->maWinData.mpMsgBoxImgList )
+ {
+ delete pSVData->maWinData.mpMsgBoxImgList;
+ pSVData->maWinData.mpMsgBoxImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpCheckImgList )
+ {
+ delete pSVData->maCtrlData.mpCheckImgList;
+ pSVData->maCtrlData.mpCheckImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpRadioImgList )
+ {
+ delete pSVData->maCtrlData.mpRadioImgList;
+ pSVData->maCtrlData.mpRadioImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpPinImgList )
+ {
+ delete pSVData->maCtrlData.mpPinImgList;
+ pSVData->maCtrlData.mpPinImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpSplitHPinImgList )
+ {
+ delete pSVData->maCtrlData.mpSplitHPinImgList;
+ pSVData->maCtrlData.mpSplitHPinImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpSplitVPinImgList )
+ {
+ delete pSVData->maCtrlData.mpSplitVPinImgList;
+ pSVData->maCtrlData.mpSplitVPinImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpSplitHArwImgList )
+ {
+ delete pSVData->maCtrlData.mpSplitHArwImgList;
+ pSVData->maCtrlData.mpSplitHArwImgList = NULL;
+ }
+ if ( pSVData->maCtrlData.mpSplitVArwImgList )
+ {
+ delete pSVData->maCtrlData.mpSplitVArwImgList;
+ pSVData->maCtrlData.mpSplitVArwImgList = NULL;
+ }
+ if ( pSVData->mpDefaultWin )
+ {
+ delete pSVData->mpDefaultWin;
+ pSVData->mpDefaultWin = NULL;
+ }
+ if ( pSVData->mpResMgr )
+ {
+ delete pSVData->mpResMgr;
+ pSVData->mpResMgr = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pSVData->mpUserInfo )
+ {
+ try
+ {
+ delete pSVData->mpUserInfo;
+ }
+ catch(...)
+ {
+ }
+ pSVData->mpUserInfo = NULL;
+ }
+ if( pSVData->mpRemotePrinterList )
+ {
+ try
+ {
+ delete pSVData->mpRemotePrinterList;
+ }
+ catch(...)
+ {
+ }
+ pSVData->mpRemotePrinterList = NULL;
+ }
+ if( pSVData->mxClientFactory.is() )
+ {
+ try
+ {
+ pSVData->mxClientFactory = Reference < XMultiServiceFactory >();
+ }
+ catch(...)
+ {
+ }
+ }
+
+ if( pSVData->mxMultiFactory.is() )
+ {
+ try
+ {
+ pSVData->mxMultiFactory.clear();
+ }
+ catch(...)
+ {
+ }
+
+ }
+ CORmStarOffice::eraseRemoteCaches();
+ if( pSVData->mxStatus.is() )
+ {
+ try
+ {
+ pSVData->mxStatus->Quit();
+ pSVData->mxStatus = Reference < ::com::sun::star::portal::client::XRmStatus >();
+ }
+ catch(...)
+ {
+ }
+
+ }
+
+ pSVData->maAppData.mpSolarMutex->release();
+ delete pSVData->maAppData.mpSolarMutex;
+ pSVData->maAppData.mpSolarMutex = NULL;
+ pSVData->mpOTimer->release();
+ pSVData->mpOTimer = NULL;
+ delete pSVData->mpRmEventQueue;
+ pSVData->mpRmEventQueue = NULL;
+ delete pSVData->mpWindowObjectMutex;
+ pSVData->mpWindowObjectMutex = NULL;
+
+ if ( pSVData->mpKeyNames )
+ {
+ for( String* pObj = pSVData->mpKeyNames->First(); pObj; pObj = pSVData->mpKeyNames->Next() )
+ delete pObj;
+ delete pSVData->mpKeyNames;
+ }
+ delete pSVData->mpAtoms;
+#endif
+
+ if ( pSVData->maAppData.mpSettings )
+ {
+ delete pSVData->maAppData.mpSettings;
+ pSVData->maAppData.mpSettings = NULL;
+ }
+ if ( pSVData->maAppData.mpAccelMgr )
+ {
+ delete pSVData->maAppData.mpAccelMgr;
+ pSVData->maAppData.mpAccelMgr = NULL;
+ }
+ if ( pSVData->maAppData.mpUniqueIdCont )
+ {
+ delete pSVData->maAppData.mpUniqueIdCont;
+ pSVData->maAppData.mpUniqueIdCont = NULL;
+ }
+ if ( pSVData->maAppData.mpAppFileName )
+ {
+ delete pSVData->maAppData.mpAppFileName;
+ pSVData->maAppData.mpAppFileName = NULL;
+ }
+ if ( pSVData->maAppData.mpAppName )
+ {
+ delete pSVData->maAppData.mpAppName;
+ pSVData->maAppData.mpAppName = NULL;
+ }
+ if ( pSVData->maAppData.mpDisplayName )
+ {
+ delete pSVData->maAppData.mpDisplayName;
+ pSVData->maAppData.mpDisplayName = NULL;
+ }
+ if ( pSVData->maAppData.mpResPath )
+ {
+ delete pSVData->maAppData.mpResPath;
+ pSVData->maAppData.mpResPath = NULL;
+ }
+
+ if ( pSVData->maAppData.mpFirstHotKey )
+ ImplFreeHotKeyData();
+ if ( pSVData->maAppData.mpFirstEventHook )
+ ImplFreeEventHookData();
+
+ ImplDeletePrnQueueList();
+ delete pSVData->maGDIData.mpScreenFontList;
+ pSVData->maGDIData.mpScreenFontList = NULL;
+ delete pSVData->maGDIData.mpScreenFontCache;
+ pSVData->maGDIData.mpScreenFontCache = NULL;
+ ImplFreeOutDevFontData();
+
+ ResMgr::DestroyAllResMgr();
+
+ // Sal deinitialisieren
+#ifndef REMOTE_APPSERVER
+ DestroySalInstance( pSVData->mpDefInst );
+#endif
+
+ DeInitTools();
+
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
new file mode 100644
index 000000000000..78235032e919
--- /dev/null
+++ b/vcl/source/app/timer.cxx
@@ -0,0 +1,490 @@
+/*************************************************************************
+ *
+ * $RCSfile: timer.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TIMER_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALTIMER_HXX
+#include <saltimer.hxx>
+#endif
+#else
+#include <rmevents.hxx>
+#endif
+
+#ifndef _TIME_HXX
+#include <tools/time.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+#define protected public
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#undef protected
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define MAX_TIMER_PERIOD ((ULONG)0xFFFFFFFF)
+
+// ---------------------
+// - TimeManager-Types -
+// ---------------------
+
+struct ImplTimerData
+{
+ ImplTimerData* mpNext; // Pointer to the next Instance
+ Timer* mpSVTimer; // Pointer to SV Timer instance
+ ULONG mnUpdateTime; // Last Update Time
+ ULONG mnTimerUpdate; // TimerCallbackProcs on stack
+ BOOL mbDelete; // Wurde Timer waehren Update() geloescht
+ BOOL mbInTimeout; // Befinden wir uns im Timeout-Handler
+};
+
+// =======================================================================
+
+void ImplDeInitTimer()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
+
+ if ( pTimerData )
+ {
+ do
+ {
+ ImplTimerData* pTempTimerData = pTimerData;
+ if ( pTimerData->mpSVTimer )
+ {
+ pTimerData->mpSVTimer->mbActive = FALSE;
+ pTimerData->mpSVTimer->mpTimerData = NULL;
+ }
+ pTimerData = pTimerData->mpNext;
+ delete pTempTimerData;
+ }
+ while ( pTimerData );
+
+ pSVData->mpFirstTimerData = NULL;
+ pSVData->mnTimerPeriod = 0;
+#ifndef REMOTE_APPSERVER
+ SalTimer::Stop();
+#else
+ if ( pSVData->mpOTimer )
+ pSVData->mpOTimer->StopTimer();
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplStartTimer( ImplSVData* pSVData, ULONG nMS )
+{
+ if ( !nMS )
+ nMS = 1;
+
+#ifndef REMOTE_APPSERVER
+ if ( nMS != pSVData->mnTimerPeriod )
+ {
+ pSVData->mnTimerPeriod = nMS;
+ SalTimer::Start( nMS );
+ }
+#else
+ pSVData->mnTimerPeriod = nMS;
+ if ( !pSVData->mpOTimer )
+ {
+ pSVData->mpOTimer = new VclOTimer;
+ pSVData->mpOTimer->acquire();
+ }
+ else
+ pSVData->mpOTimer->StopTimer();
+ pSVData->mpOTimer->setRemainingTime( nMS, 0 );
+ pSVData->mpOTimer->StartTimer();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTimerCallbackProc()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplTimerData* pTimerData;
+ ImplTimerData* pPrevTimerData;
+ ULONG nMinPeriod = MAX_TIMER_PERIOD;
+ ULONG nDeltaTime;
+ ULONG nTime = Time::GetSystemTicks();
+
+ if ( pSVData->mbNoCallTimer )
+ return;
+
+ pSVData->mnTimerUpdate++;
+ pSVData->mbNotAllTimerCalled = TRUE;
+
+ // Suche Timer raus, wo der Timeout-Handler gerufen werden muss
+ pTimerData = pSVData->mpFirstTimerData;
+ while ( pTimerData )
+ {
+ // Wenn Timer noch nicht neu ist und noch nicht geloescht wurde
+ // und er sich nicht im Timeout-Handler befindet,
+ // dann den Handler rufen, wenn die Zeit abgelaufen ist
+ if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
+ !pTimerData->mbDelete && !pTimerData->mbInTimeout )
+ {
+ // Zeit abgelaufen
+ if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
+ {
+ // Neue Updatezeit setzen
+ pTimerData->mnUpdateTime = nTime;
+
+ // kein AutoTimer, dann anhalten
+ if ( !pTimerData->mpSVTimer->mbAuto )
+ {
+ pTimerData->mpSVTimer->mbActive = FALSE;
+ pTimerData->mbDelete = TRUE;
+ }
+
+ // call Timeout
+ pTimerData->mbInTimeout = TRUE;
+ pTimerData->mpSVTimer->Timeout();
+ pTimerData->mbInTimeout = FALSE;
+ }
+ }
+
+ pTimerData = pTimerData->mpNext;
+ }
+
+ // Neue Zeit ermitteln
+ ULONG nNewTime = Time::GetSystemTicks();
+ pPrevTimerData = NULL;
+ pTimerData = pSVData->mpFirstTimerData;
+ while ( pTimerData )
+ {
+ // Befindet sich Timer noch im Timeout-Handler, dann ignorieren
+ if ( pTimerData->mbInTimeout )
+ {
+ pPrevTimerData = pTimerData;
+ pTimerData = pTimerData->mpNext;
+ }
+ // Wurde Timer zwischenzeitlich zerstoert ?
+ else if ( pTimerData->mbDelete )
+ {
+ if ( pPrevTimerData )
+ pPrevTimerData->mpNext = pTimerData->mpNext;
+ else
+ pSVData->mpFirstTimerData = pTimerData->mpNext;
+ if ( pTimerData->mpSVTimer )
+ pTimerData->mpSVTimer->mpTimerData = NULL;
+ ImplTimerData* pTempTimerData = pTimerData;
+ pTimerData = pTimerData->mpNext;
+ delete pTempTimerData;
+ }
+ else
+ {
+ pTimerData->mnTimerUpdate = 0;
+ // kleinste Zeitspanne ermitteln
+ if ( pTimerData->mnUpdateTime == nTime )
+ {
+ nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
+ if ( nDeltaTime < nMinPeriod )
+ nMinPeriod = nDeltaTime;
+ }
+ else
+ {
+ nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
+ if ( nDeltaTime < nNewTime )
+ nMinPeriod = 1;
+ else
+ {
+ nDeltaTime -= nNewTime;
+ if ( nDeltaTime < nMinPeriod )
+ nMinPeriod = nDeltaTime;
+ }
+ }
+ pPrevTimerData = pTimerData;
+ pTimerData = pTimerData->mpNext;
+ }
+ }
+
+ // Wenn keine Timer mehr existieren, dann Clock loeschen
+ if ( !pSVData->mpFirstTimerData )
+ {
+#ifndef REMOTE_APPSERVER
+ SalTimer::Stop();
+#else
+ if ( pSVData->mpOTimer )
+ pSVData->mpOTimer->StopTimer();
+#endif
+ pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
+ }
+ else
+ ImplStartTimer( pSVData, nMinPeriod );
+
+ pSVData->mnTimerUpdate--;
+ pSVData->mbNotAllTimerCalled = FALSE;
+}
+
+// =======================================================================
+
+#ifdef REMOTE_APPSERVER
+
+VclOTimer::VclOTimer() :
+ maTimeoutHdl( LINK( this, VclOTimer, Timeout ) )
+{
+ mbSend = FALSE;
+}
+
+void SAL_CALL VclOTimer::onShot()
+{
+ stop(); // start wird durch ImplTimerCallbackProc() gerufen
+ if ( !mbSend )
+ {
+ mbSend = TRUE;
+ if ( !Application::PostUserEvent( maTimeoutHdl ) )
+ {
+ mbSend = FALSE;
+ start();
+ }
+ }
+}
+
+IMPL_LINK( VclOTimer, Timeout, void*, EMPTYARG )
+{
+ mbSend = FALSE;
+ ImplTimerCallbackProc();
+ return 0;
+}
+
+void VclOTimer::StartTimer()
+{
+ start();
+}
+
+void VclOTimer::StopTimer()
+{
+ stop();
+}
+
+#endif
+
+// =======================================================================
+
+Timer::Timer()
+{
+ mpTimerData = NULL;
+ mnTimeout = 1;
+ mbAuto = FALSE;
+ mbActive = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Timer::Timer( const Timer& rTimer )
+{
+ mpTimerData = NULL;
+ mnTimeout = rTimer.mnTimeout;
+ mbAuto = FALSE;
+ mbActive = FALSE;
+ maTimeoutHdl = rTimer.maTimeoutHdl;
+
+ if ( rTimer.IsActive() )
+ Start();
+}
+
+// -----------------------------------------------------------------------
+
+Timer::~Timer()
+{
+ if ( mpTimerData )
+ {
+ mpTimerData->mbDelete = TRUE;
+ mpTimerData->mpSVTimer = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Timer::Timeout()
+{
+ maTimeoutHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Timer::SetTimeout( ULONG nNewTimeout )
+{
+ mnTimeout = nNewTimeout;
+
+ // Wenn Timer aktiv, dann Clock erneuern
+ if ( mbActive )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
+ ImplStartTimer( pSVData, mnTimeout );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Timer::Start()
+{
+ mbActive = TRUE;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !mpTimerData )
+ {
+ if ( !pSVData->mpFirstTimerData )
+ {
+ pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
+#ifndef REMOTE_APPSERVER
+ SalTimer::SetCallback( ImplTimerCallbackProc );
+#endif
+ }
+
+ // insert timer and start
+ mpTimerData = new ImplTimerData;
+ mpTimerData->mpSVTimer = this;
+ mpTimerData->mnUpdateTime = Time::GetSystemTicks();
+ mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
+ mpTimerData->mbDelete = FALSE;
+ mpTimerData->mbInTimeout = FALSE;
+
+ // !!!!! Wegen SFX hinten einordnen !!!!!
+ ImplTimerData* pPrev = NULL;
+ ImplTimerData* pData = pSVData->mpFirstTimerData;
+ while ( pData )
+ {
+ pPrev = pData;
+ pData = pData->mpNext;
+ }
+ mpTimerData->mpNext = NULL;
+ if ( pPrev )
+ pPrev->mpNext = mpTimerData;
+ else
+ pSVData->mpFirstTimerData = mpTimerData;
+
+ if ( mnTimeout < pSVData->mnTimerPeriod )
+ ImplStartTimer( pSVData, mnTimeout );
+ }
+ else
+ {
+ mpTimerData->mnUpdateTime = Time::GetSystemTicks();
+ mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
+ mpTimerData->mbDelete = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Timer::Stop()
+{
+ mbActive = FALSE;
+
+ if ( mpTimerData )
+ mpTimerData->mbDelete = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Timer& Timer::operator=( const Timer& rTimer )
+{
+ if ( IsActive() )
+ Stop();
+
+ mbActive = FALSE;
+ mnTimeout = rTimer.mnTimeout;
+ maTimeoutHdl = rTimer.maTimeoutHdl;
+
+ if ( rTimer.IsActive() )
+ Start();
+
+ return *this;
+}
+
+// =======================================================================
+
+AutoTimer::AutoTimer()
+{
+ mbAuto = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
+{
+ mbAuto = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
+{
+ Timer::operator=( rTimer );
+ return *this;
+}
diff --git a/vcl/source/app/unohelp.cxx b/vcl/source/app/unohelp.cxx
new file mode 100644
index 000000000000..c01deefc4897
--- /dev/null
+++ b/vcl/source/app/unohelp.cxx
@@ -0,0 +1,275 @@
+/*************************************************************************
+ *
+ * $RCSfile: unohelp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#pragma hdrstop
+
+#include <unohelp.hxx>
+
+#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#endif
+
+#ifndef _UNOTOOLS_PROCESSFACTORY_HXX_
+#include <unotools/processfactory.hxx>
+#endif
+
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <cppuhelper/factory.hxx>
+
+#include <uno/environment.h>
+#include <uno/mapping.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/module.h>
+
+#ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
+#include <com/sun/star/text/XBreakIterator.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_XCHARACTERCLASSIFICATION_HPP_
+#include <com/sun/star/lang/XCharacterClassification.hpp>
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::rtl;
+
+#define DOSTRING( x ) #x
+#define STRING( x ) DOSTRING( x )
+
+#define DOCONCAT4( x, y, z, a ) x##y##z##a
+#define CONCAT4( x, y, z, a ) DOCONCAT4(x,y,z,a)
+#define DOCONCAT5( x, y, z, a, b ) x##y##z##a##b
+#define CONCAT5( x, y, z, a, b ) DOCONCAT5(x,y,z,a,b)
+
+#ifdef UNX
+#define LIBNAME(name) STRING(CONCAT5(lib,name,SUPD, DLLSUFFIX,.so))
+#else
+#define LIBNAME(name) STRING(CONCAT4( name, SUPD, DLLSUFFIX, .dll))
+#endif
+
+Reference< XSingleServiceFactory > ImplLoadLibComponentFactory(
+ const OUString & rLibName, const OUString & rImplName,
+ const Reference< XMultiServiceFactory > & xSF, const Reference< XRegistryKey > & xKey )
+{
+ Reference< XSingleServiceFactory > xRet;
+
+ oslModule lib = osl_loadModule( rLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
+ if (lib)
+ {
+ void * pSym;
+
+ // ========================= LATEST VERSION =========================
+ OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) );
+ if (pSym = osl_getSymbol( lib, aGetEnvName.pData ))
+ {
+ uno_Environment * pCurrentEnv = 0;
+ uno_Environment * pEnv = 0;
+ const sal_Char * pEnvTypeName = 0;
+ (*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv );
+
+ sal_Bool bNeedsMapping =
+ (pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME ));
+
+ OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
+
+ if (bNeedsMapping)
+ {
+ if (! pEnv)
+ uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 );
+ if (pEnv)
+ {
+ OUString aCppEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) );
+ uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 );
+ if (pCurrentEnv)
+ bNeedsMapping = (pEnv != pCurrentEnv);
+ }
+ }
+
+ OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETFACTORY) );
+ if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
+ {
+ OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
+
+ if (bNeedsMapping)
+ {
+ if (pEnv && pCurrentEnv)
+ {
+ Mapping aCurrent2Env( pCurrentEnv, pEnv );
+ Mapping aEnv2Current( pEnv, pCurrentEnv );
+
+ if (aCurrent2Env.is() && aEnv2Current.is())
+ {
+ void * pSMgr = aCurrent2Env.mapInterface(
+ xSF.get(), ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) );
+ void * pKey = aCurrent2Env.mapInterface(
+ xKey.get(), ::getCppuType( (const Reference< XRegistryKey > *)0 ) );
+
+ void * pSSF = (*((component_getFactoryFunc)pSym))(
+ aImplName.getStr(), pSMgr, pKey );
+
+ if (pKey)
+ (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey );
+ if (pSMgr)
+ (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr );
+
+ if (pSSF)
+ {
+ aEnv2Current.mapInterface(
+ reinterpret_cast< void ** >( &xRet ),
+ pSSF, ::getCppuType( (const Reference< XSingleServiceFactory > *)0 ) );
+ (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF );
+ }
+ }
+ }
+ }
+ else
+ {
+ XSingleServiceFactory * pRet = (XSingleServiceFactory *)
+ (*((component_getFactoryFunc)pSym))(
+ aImplName.getStr(), xSF.get(), xKey.get() );
+ if (pRet)
+ {
+ xRet = pRet;
+ pRet->release();
+ }
+ }
+ }
+
+ if (pEnv)
+ (*pEnv->release)( pEnv );
+ if (pCurrentEnv)
+ (*pCurrentEnv->release)( pCurrentEnv );
+ }
+
+
+ if (! xRet.is())
+ osl_unloadModule( lib );
+ }
+
+ return xRet;
+}
+
+uno::Reference < text::XBreakIterator > vcl::unohelper::CreateBreakIterator()
+{
+ uno::Reference < text::XBreakIterator > xB;
+ uno::Reference< lang::XMultiServiceFactory > xMSF = ::utl::getProcessServiceFactory();
+ if ( xMSF.is() )
+ {
+ uno::Reference < uno::XInterface > xI = xMSF->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.text.BreakIterator" ) );
+ if ( xI.is() )
+ {
+ uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< text::XBreakIterator >*)0) );
+ x >>= xB;
+ }
+ }
+ if( !xB.is() )
+ {
+ uno::Reference< lang::XSingleServiceFactory > xSSF = ImplLoadLibComponentFactory(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( LIBNAME( int ) ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.BreakIterator" ) ),
+ Reference< XMultiServiceFactory >(), Reference< XRegistryKey >() );
+
+ uno::Reference < uno::XInterface > xI = xSSF->createInstance();
+ if ( xI.is() )
+ {
+ uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< text::XBreakIterator >*)0) );
+ x >>= xB;
+ }
+ }
+ return xB;
+}
+
+uno::Reference < lang::XCharacterClassification > vcl::unohelper::CreateCharacterClassification()
+{
+ uno::Reference < lang::XCharacterClassification > xB;
+ uno::Reference< lang::XMultiServiceFactory > xMSF = ::utl::getProcessServiceFactory();
+ if ( xMSF.is() )
+ {
+ uno::Reference < uno::XInterface > xI = xMSF->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.lang.CharacterClassification" ) );
+ if ( xI.is() )
+ {
+ uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< lang::XCharacterClassification >*)0) );
+ x >>= xB;
+ }
+ }
+ if( !xB.is() )
+ {
+ uno::Reference< lang::XSingleServiceFactory > xSSF = ImplLoadLibComponentFactory(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( LIBNAME( int ) ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.lang.CharacterClassification" ) ),
+ Reference< XMultiServiceFactory >(), Reference< XRegistryKey >() );
+
+ uno::Reference < uno::XInterface > xI = xSSF->createInstance();
+ if ( xI.is() )
+ {
+ uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< lang::XCharacterClassification >*)0) );
+ x >>= xB;
+ }
+ }
+ return xB;
+}
+
+
+
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
new file mode 100644
index 000000000000..1ac338e26755
--- /dev/null
+++ b/vcl/source/control/button.cxx
@@ -0,0 +1,3010 @@
+/*************************************************************************
+ *
+ * $RCSfile: button.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BUTTON_CXX
+
+#include <tools/debug.hxx>
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_IAMGE_HXX
+#include <image.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_DIALOG_HXX
+#include <dialog.hxx>
+#endif
+#ifndef _SV_FIXED_HXX
+#include <fixed.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define PUSHBUTTON_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_WORDBREAK | WB_NOLABEL | \
+ WB_DEFBUTTON | WB_NOLIGHTBORDER | \
+ WB_RECTSTYLE | WB_SMALLSTYLE)
+#define RADIOBUTTON_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_WORDBREAK | WB_NOLABEL)
+#define CHECKBOX_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_WORDBREAK | WB_NOLABEL)
+
+// =======================================================================
+
+Button::Button( WindowType nType ) :
+ Control( nType )
+{
+}
+
+// -----------------------------------------------------------------------
+
+Button::Button( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_BUTTON )
+{
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Button::Button( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_BUTTON )
+{
+ rResId.SetRT( RSC_BUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle, NULL );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Button::Click()
+{
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+XubString Button::GetStandardText( StandardButtonType eButton )
+{
+ static USHORT aResIdAry[BUTTON_COUNT] =
+ {
+ SV_BUTTONTEXT_OK,
+ SV_BUTTONTEXT_CANCEL,
+ SV_BUTTONTEXT_YES,
+ SV_BUTTONTEXT_NO,
+ SV_BUTTONTEXT_RETRY,
+ SV_BUTTONTEXT_HELP,
+ SV_BUTTONTEXT_CLOSE,
+ SV_BUTTONTEXT_MORE
+ };
+
+ ResId aResId( aResIdAry[(USHORT)eButton], ImplGetResMgr() );
+ XubString aText( aResId );
+ return aText;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Button::GetStandardHelpText( StandardButtonType /* eButton */ )
+{
+ XubString aHelpText;
+ return aHelpText;
+}
+
+// =======================================================================
+
+void PushButton::ImplInitData()
+{
+ mbPushButton = TRUE;
+
+ meSymbol = SYMBOL_NOSYMBOL;
+ meImageAlign = IMAGEALIGN_TOP;
+ meState = STATE_NOCHECK;
+ meSaveValue = STATE_NOCHECK;
+ mnDDStyle = 0;
+ mnButtonState = 0;
+ mbPressed = FALSE;
+ mbInUserDraw = FALSE;
+ mpBitmapEx = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
+ Button::ImplInit( pParent, nStyle, NULL );
+
+ if ( nStyle & WB_NOLIGHTBORDER )
+ mnButtonState |= BUTTON_DRAW_NOLIGHTBORDER;
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits PushButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) &&
+ (!pPrevWindow ||
+ ((pPrevWindow->GetType() != WINDOW_PUSHBUTTON) &&
+ (pPrevWindow->GetType() != WINDOW_OKBUTTON) &&
+ (pPrevWindow->GetType() != WINDOW_CANCELBUTTON) &&
+ (pPrevWindow->GetType() != WINDOW_HELPBUTTON)) ) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetPushButtonFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetButtonTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ SetBackground();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplDrawPushButtonFrame( Window* pDev,
+ Rectangle& rRect, USHORT nStyle )
+{
+ if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) )
+ {
+ StyleSettings aStyleSettings = pDev->GetSettings().GetStyleSettings();
+ if ( pDev->IsControlBackground() )
+ aStyleSettings.Set3DColors( pDev->GetControlBackground() );
+
+ USHORT nPushButtonSysStyle = aStyleSettings.GetPushButtonStyle() & STYLE_PUSHBUTTON_STYLE;
+ if ( nPushButtonSysStyle == STYLE_PUSHBUTTON_MAC )
+ {
+ pDev->SetLineColor();
+ pDev->SetFillColor( aStyleSettings.GetFaceColor() );
+ pDev->DrawRect( rRect );
+
+ if ( (aStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (pDev->GetOutDevType() == OUTDEV_PRINTER) )
+ nStyle |= BUTTON_DRAW_MONO;
+
+ if ( nStyle & BUTTON_DRAW_DEFAULT )
+ {
+ if ( nStyle & BUTTON_DRAW_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( aStyleSettings.GetDarkShadowColor() );
+
+ pDev->DrawLine( Point( rRect.Left()+3, rRect.Top() ),
+ Point( rRect.Right()-3, rRect.Top() ) );
+ pDev->DrawLine( Point( rRect.Left()+3, rRect.Bottom() ),
+ Point( rRect.Right()-3, rRect.Bottom() ) );
+ pDev->DrawLine( Point( rRect.Left(), rRect.Top()+3 ),
+ Point( rRect.Left(), rRect.Bottom()-3 ) );
+ pDev->DrawLine( Point( rRect.Right(), rRect.Top()+3 ),
+ Point( rRect.Right(), rRect.Bottom()-3 ) );
+ pDev->DrawPixel( Point( rRect.Left()+2, rRect.Top()+1 ) );
+ pDev->DrawPixel( Point( rRect.Left()+1, rRect.Top()+2 ) );
+ pDev->DrawPixel( Point( rRect.Right()-2, rRect.Top()+1 ) );
+ pDev->DrawPixel( Point( rRect.Right()-1, rRect.Top()+2 ) );
+ pDev->DrawPixel( Point( rRect.Left()+2, rRect.Bottom()-1 ) );
+ pDev->DrawPixel( Point( rRect.Left()+1, rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-1 ) );
+ pDev->DrawPixel( Point( rRect.Right()-1, rRect.Bottom()-2 ) );
+
+ if ( nStyle & BUTTON_DRAW_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( aStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( rRect.Left()+3, rRect.Bottom()-1 ),
+ Point( rRect.Right()-3, rRect.Bottom()-1 ) );
+ pDev->DrawLine( Point( rRect.Right()-1, rRect.Top()+3 ),
+ Point( rRect.Right()-1, rRect.Bottom()-3 ) );
+ pDev->DrawPixel( Point( rRect.Right()-3, rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-3 ) );
+ }
+
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+
+ if ( nStyle & BUTTON_DRAW_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( aStyleSettings.GetDarkShadowColor() );
+
+ pDev->DrawLine( Point( rRect.Left()+2, rRect.Top() ),
+ Point( rRect.Right()-2, rRect.Top() ) );
+ pDev->DrawLine( Point( rRect.Left()+2, rRect.Bottom() ),
+ Point( rRect.Right()-2, rRect.Bottom() ) );
+ pDev->DrawLine( Point( rRect.Left(), rRect.Top()+2 ),
+ Point( rRect.Left(), rRect.Bottom()-2 ) );
+ pDev->DrawLine( Point( rRect.Right(), rRect.Top()+2 ),
+ Point( rRect.Right(), rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Left()+1, rRect.Top()+1 ) );
+ pDev->DrawPixel( Point( rRect.Right()-1, rRect.Top()+1 ) );
+ pDev->DrawPixel( Point( rRect.Left()+1, rRect.Bottom()-1 ) );
+ pDev->DrawPixel( Point( rRect.Right()-1, rRect.Bottom()-1 ) );
+
+ pDev->SetLineColor();
+ if ( nStyle & BUTTON_DRAW_CHECKED )
+ pDev->SetFillColor( aStyleSettings.GetCheckedColor() );
+ else
+ pDev->SetFillColor( aStyleSettings.GetFaceColor() );
+ pDev->DrawRect( Rectangle( rRect.Left()+2, rRect.Top()+2, rRect.Right()-2, rRect.Bottom()-2 ) );
+
+ if ( !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED)) )
+ {
+ if ( nStyle & BUTTON_DRAW_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( aStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( rRect.Left()+2, rRect.Bottom()-1 ),
+ Point( rRect.Right()-2, rRect.Bottom()-1 ) );
+ pDev->DrawLine( Point( rRect.Right()-1, rRect.Top()+2 ),
+ Point( rRect.Right()-1, rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Right()-2, rRect.Bottom()-2 ) );
+ pDev->SetLineColor( aStyleSettings.GetLightColor() );
+ }
+ else
+ pDev->SetLineColor( aStyleSettings.GetShadowColor() );
+
+ if ( !(nStyle & BUTTON_DRAW_MONO) )
+ {
+ pDev->DrawLine( Point( rRect.Left()+2, rRect.Top()+1 ),
+ Point( rRect.Right()-2, rRect.Top()+1 ) );
+ pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()+2 ),
+ Point( rRect.Left()+1, rRect.Bottom()-2 ) );
+ pDev->DrawPixel( Point( rRect.Top()+2, rRect.Right()+2 ) );
+ }
+
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()++;
+ rRect.Bottom()++;
+ }
+
+ return;
+ }
+ }
+
+ DecorationView aDecoView( pDev );
+ if ( pDev->IsControlBackground() )
+ {
+ AllSettings aSettings = pDev->GetSettings();
+ AllSettings aOldSettings = aSettings;
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ aStyleSettings.Set3DColors( pDev->GetControlBackground() );
+ aSettings.SetStyleSettings( aStyleSettings );
+ ((OutputDevice*)pDev)->SetSettings( aSettings );
+ rRect = aDecoView.DrawButton( rRect, nStyle );
+ ((OutputDevice*)pDev)->SetSettings( aOldSettings );
+ }
+ else
+ rRect = aDecoView.DrawButton( rRect, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL PushButton::ImplHitTestPushButton( Window* pDev,
+ const Point& rPos, USHORT nStyle )
+{
+ Point aTempPoint;
+ Rectangle aTestRect( aTempPoint, pDev->GetOutputSizePixel() );
+
+ if ( !(pDev->GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) )
+ {
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+
+ USHORT nPushButtonSysStyle = rStyleSettings.GetPushButtonStyle() & STYLE_PUSHBUTTON_STYLE;
+ if ( nPushButtonSysStyle == STYLE_PUSHBUTTON_MAC )
+ {
+ aTestRect.Left() += 2;
+ aTestRect.Top() += 2;
+ aTestRect.Right() -= 2;
+ aTestRect.Bottom() -= 2;
+ }
+ }
+
+ return aTestRect.IsInside( rPos );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT PushButton::ImplGetTextStyle() const
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ USHORT nTextStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_MULTILINE | TEXT_DRAW_ENDELLIPSIS;
+
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ nTextStyle |= TEXT_DRAW_MONO;
+ if ( GetStyle() & WB_WORDBREAK )
+ nTextStyle |= TEXT_DRAW_WORDBREAK;
+ if ( GetStyle() & WB_NOLABEL )
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ nTextStyle |= TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER;
+
+ return nTextStyle;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBtnDropDownArrow( OutputDevice* pDev,
+ long nX, long nY,
+ Color& rColor, BOOL bBlack )
+{
+ Color aOldLineColor = pDev->GetLineColor();
+ Color aOldFillColor = pDev->GetFillColor();
+
+ pDev->SetLineColor();
+ if ( bBlack )
+ pDev->SetFillColor( Color( COL_BLACK ) );
+ else
+ pDev->SetFillColor( rColor );
+ pDev->DrawRect( Rectangle( nX+0, nY+0, nX+6, nY+0 ) );
+ pDev->DrawRect( Rectangle( nX+1, nY+1, nX+5, nY+1 ) );
+ pDev->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) );
+ pDev->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
+ if ( bBlack )
+ {
+ pDev->SetFillColor( rColor );
+ pDev->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) );
+ pDev->DrawRect( Rectangle( nX+3, nY+2, nX+3, nY+2 ) );
+ }
+ pDev->SetLineColor( aOldLineColor );
+ pDev->SetFillColor( aOldFillColor );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplDrawPushButtonContent( OutputDevice* pDev, ULONG nDrawFlags,
+ const Rectangle& rRect, Rectangle& rTextRect )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aInRect = rRect;
+ Color aColor = rStyleSettings.GetButtonTextColor();
+ XubString aText = PushButton::GetText(); // PushButton:: wegen MoreButton
+ USHORT nTextStyle;
+ USHORT nStyle;
+
+ if ( nDrawFlags & WINDOW_DRAW_MONO )
+ aColor = Color( COL_BLACK );
+ else
+ {
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ }
+
+ rTextRect = aInRect;
+ if ( mnDDStyle == PUSHBUTTON_DROPDOWN_MENUBUTTON )
+ {
+ if ( aText.Len() )
+ {
+ // Symbol- und Textrect ermitteln
+ long nSymbolSize = pDev->GetTextHeight();
+ aInRect.Right() -= 5;
+ rTextRect.Left() += 2;
+ rTextRect.Right() = aInRect.Right()-nSymbolSize;
+ aInRect.Left() = rTextRect.Right();
+
+ nTextStyle = ImplGetTextStyle();
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ nTextStyle &= ~(TEXT_DRAW_RIGHT | TEXT_DRAW_CENTER);
+ nTextStyle |= TEXT_DRAW_LEFT;
+ rTextRect = pDev->GetTextRect( rTextRect, aText, nTextStyle );
+ pDev->SetTextColor( aColor );
+ pDev->DrawText( rTextRect, aText, nTextStyle );
+ }
+ else
+ ImplCalcSymbolRect( aInRect );
+
+ nStyle = 0;
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ }
+
+ DecorationView aDecoView( pDev );
+ aDecoView.DrawSymbol( aInRect, SYMBOL_SPIN_DOWN, aColor, nStyle );
+ }
+ else
+ {
+ if ( aText.Len() )
+ {
+ nTextStyle = ImplGetTextStyle();
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ rTextRect = pDev->GetTextRect( aInRect, aText, nTextStyle );
+ }
+
+ if ( IsSymbol() )
+ {
+ ImplCalcSymbolRect( aInRect );
+
+ nStyle = 0;
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ }
+
+ DecorationView aDecoView( pDev );
+ aDecoView.DrawSymbol( aInRect, meSymbol, aColor, nStyle );
+ }
+
+ if ( aText.Len() )
+ {
+ pDev->SetTextColor( aColor );
+ pDev->DrawText( rTextRect, aText, nTextStyle );
+ }
+
+ // Den Fall Text+Image erstmal ignoriert, TH ignoriert auch Text+Symbol
+ if ( IsImage() )
+ {
+ // Image zentrieren...
+ Size aImageSize( maImage.GetSizePixel() );
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+ if ( mpBitmapEx && ( pDev->GetOutDevType() == OUTDEV_PRINTER ) )
+ {
+ // Die Groesse richtet sich nach dem Bildschirm, soll auf
+ // dem Drucker genau so aussehen...
+ aImageSize = PixelToLogic( aImageSize, MAP_100TH_MM );
+ aImageSize = pDev->LogicToPixel( aImageSize, MAP_100TH_MM );
+ }
+
+ Point aImagePos( rRect.Left()+((aInRect.GetWidth()-aImageSize.Width())/2),
+ rRect.Top()+((aInRect.GetHeight()-aImageSize.Height())/2) );
+ nStyle = 0;
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nStyle |= IMAGE_DRAW_DISABLE;
+ }
+ if ( mpBitmapEx && ( pDev->GetOutDevType() == OUTDEV_PRINTER ) )
+ {
+ // Fuer die BitmapEx ueberlegt sich KA noch, wie man die disablete
+ // Darstellung hinbekommt...
+ aImageSize = pDev->PixelToLogic( aImageSize );
+ mpBitmapEx->Draw( pDev, aImagePos, aImageSize /*, nStyle*/ );
+ }
+ else
+ {
+ if ( IsZoom() )
+ pDev->DrawImage( aImagePos, aImageSize, maImage, nStyle );
+ else
+ pDev->DrawImage( aImagePos, maImage, nStyle );
+ }
+ }
+
+ if ( mnDDStyle == PUSHBUTTON_DROPDOWN_TOOLBOX )
+ {
+ BOOL bBlack = FALSE;
+ Color aArrowColor( COL_BLACK );
+ if ( !(nDrawFlags & WINDOW_DRAW_MONO) )
+ {
+ if ( !IsEnabled() )
+ aArrowColor = rStyleSettings.GetShadowColor();
+ else
+ {
+ aArrowColor = Color( COL_LIGHTGREEN );
+ bBlack = TRUE;
+ }
+ }
+
+ ImplDrawBtnDropDownArrow( pDev, aInRect.Right()-6, aInRect.Top()+1,
+ aArrowColor, bBlack );
+ }
+ }
+
+ UserDrawEvent aUDEvt( this, aInRect, 0 );
+ UserDraw( aUDEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplDrawPushButton()
+{
+ HideFocus();
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ USHORT nButtonStyle = mnButtonState;
+ Point aPoint;
+ Size aOutSz( GetOutputSizePixel() );
+ Rectangle aRect( aPoint, aOutSz );
+ Rectangle aInRect = aRect;
+ Rectangle aTextRect;
+
+ // Wenn Button gedrueckt gezeichnet werden soll, dann Pressed dazuordern
+ if ( mbPressed )
+ nButtonStyle |= BUTTON_DRAW_PRESSED;
+
+ // PushButtonFrame ausgeben
+ ImplDrawPushButtonFrame( this, aInRect, nButtonStyle );
+
+ // PushButton-Inhalt ausgeben
+ ImplDrawPushButtonContent( this, 0, aInRect, aTextRect );
+
+ maFocusRect = aTextRect;
+ maFocusRect.Left()--;
+ maFocusRect.Top()--;
+ maFocusRect.Right()++;
+ maFocusRect.Bottom()++;
+ if ( HasFocus() )
+ ShowFocus( maFocusRect );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::ImplSetDefButton( BOOL bSet )
+{
+ if ( bSet )
+ mnButtonState |= BUTTON_DRAW_DEFAULT;
+ else
+ mnButtonState &= ~BUTTON_DRAW_DEFAULT;
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL PushButton::ImplIsDefButton() const
+{
+ return (mnButtonState & BUTTON_DRAW_DEFAULT) != 0;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton::PushButton( WindowType nType ) :
+ Button( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+PushButton::PushButton( Window* pParent, WinBits nStyle ) :
+ Button( WINDOW_PUSHBUTTON )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+PushButton::PushButton( Window* pParent, const ResId& rResId ) :
+ Button( WINDOW_PUSHBUTTON )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_PUSHBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+PushButton::~PushButton()
+{
+ delete mpBitmapEx;
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() &&
+ ImplHitTestPushButton( this, rMEvt.GetPosPixel(), mnButtonState ) )
+ {
+ USHORT nTrackFlags = 0;
+
+ if ( GetStyle() & WB_REPEAT )
+ nTrackFlags |= STARTTRACK_BUTTONREPEAT;
+
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+ StartTracking( nTrackFlags );
+
+ if ( GetStyle() & WB_REPEAT )
+ Click();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
+ GrabFocus();
+
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( !(GetStyle() & WB_REPEAT) )
+ Click();
+ }
+ }
+ }
+ else
+ {
+ if ( ImplHitTestPushButton( this, rTEvt.GetMouseEvent().GetPosPixel(), mnButtonState ) )
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ if ( rTEvt.IsTrackingRepeat() && (GetStyle() & WB_REPEAT) )
+ Click();
+ }
+ else
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+ }
+ }
+ else
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( !aKeyCode.GetModifier() &&
+ ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
+ {
+ if ( !(mnButtonState & BUTTON_DRAW_PRESSED) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+ }
+
+ if ( GetStyle() & WB_REPEAT )
+ Click();
+ }
+ else if ( (mnButtonState & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+ }
+ else
+ Button::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::KeyUp( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( (mnButtonState & BUTTON_DRAW_PRESSED) &&
+ ((aKeyCode.GetCode() == KEY_RETURN) || (aKeyCode.GetCode() == KEY_SPACE)) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawPushButton();
+
+ if ( !(GetStyle() & WB_REPEAT) )
+ Click();
+ }
+ else
+ Button::KeyUp( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::Paint( const Rectangle& rRect )
+{
+ ImplDrawPushButton();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Rectangle aRect( aPos, aSize );
+ Rectangle aTextRect;
+ Font aFont = GetDrawPixelFont( pDev );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ DecorationView aDecoView( pDev );
+ USHORT nButtonStyle = 0;
+ if ( nFlags & WINDOW_DRAW_MONO )
+ nButtonStyle |= BUTTON_DRAW_MONO;
+ if ( IsChecked() )
+ nButtonStyle |= BUTTON_DRAW_CHECKED;
+ aRect = aDecoView.DrawButton( aRect, nButtonStyle );
+
+ ImplDrawPushButtonContent( pDev, nFlags, aRect, aTextRect );
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::GetFocus()
+{
+ ShowFocus( maFocusRect );
+ SetInputContext( InputContext( GetFont() ) );
+ Button::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::LoseFocus()
+{
+ EndSelection();
+ HideFocus();
+ Button::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::StateChanged( StateChangedType nType )
+{
+ Button::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_IMAGE) ||
+ (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_STATE) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ if ( nType == STATE_CHANGE_STATE )
+ Toggle();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( (GetPrevStyle() & PUSHBUTTON_VIEW_STYLE) !=
+ (GetStyle() & PUSHBUTTON_VIEW_STYLE) )
+ Invalidate();
+ }
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Button::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::Toggle()
+{
+ maToggleHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetSymbol( SymbolType eSymbol )
+{
+ if ( meSymbol != eSymbol )
+ {
+ meSymbol = eSymbol;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetImage( const Image& rImage )
+{
+ delete mpBitmapEx;
+ mpBitmapEx = NULL;
+ if ( rImage != maImage )
+ {
+ maImage = rImage;
+ meSymbol = SYMBOL_IMAGE;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetBitmap( const BitmapEx& rBmp )
+{
+ SetImage( rBmp );
+ DBG_ASSERT( !mpBitmapEx, "BitmapEx nach SetImage?!" );
+ mpBitmapEx = new BitmapEx( rBmp );
+}
+
+// -----------------------------------------------------------------------
+
+BitmapEx PushButton::GetBitmap() const
+{
+ BitmapEx aBmp;
+ if ( mpBitmapEx )
+ aBmp = *mpBitmapEx;
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetImageAlign( ImageAlign eAlign )
+{
+ if ( meImageAlign != eAlign )
+ {
+ meImageAlign = eAlign;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetDropDown( USHORT nStyle )
+{
+ if ( mnDDStyle != nStyle )
+ {
+ mnDDStyle = nStyle;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetState( TriState eState )
+{
+ if ( meState != eState )
+ {
+ meState = eState;
+ if ( meState == STATE_NOCHECK )
+ mnButtonState &= ~(BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW);
+ else if ( meState == STATE_CHECK )
+ {
+ mnButtonState &= ~BUTTON_DRAW_DONTKNOW;
+ mnButtonState |= BUTTON_DRAW_CHECKED;
+ }
+ else // STATE_DONTKNOW
+ {
+ mnButtonState &= ~BUTTON_DRAW_CHECKED;
+ mnButtonState |= BUTTON_DRAW_DONTKNOW;
+ }
+
+ StateChanged( STATE_CHANGE_STATE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::SetPressed( BOOL bPressed )
+{
+ if ( mbPressed != bPressed )
+ {
+ mbPressed = bPressed;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PushButton::EndSelection()
+{
+ EndTracking( ENDTRACK_CANCEL );
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ if ( !mbPressed )
+ ImplDrawPushButton();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size PushButton::CalcMinimumSize( long nMaxWidth ) const
+{
+ Size aSize;
+
+ if ( IsSymbol() )
+ aSize = Size( 12, 12 );
+ else if ( IsImage() )
+ aSize = maImage.GetSizePixel();
+ else if ( PushButton::GetText().Len() )
+ {
+ aSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
+ PushButton::GetText(), ImplGetTextStyle() ).GetSize();
+ }
+
+ return CalcWindowSize( aSize );
+}
+
+// =======================================================================
+
+void OKButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ PushButton::ImplInit( pParent, nStyle );
+
+ SetText( Button::GetStandardText( BUTTON_OK ) );
+ SetHelpText( Button::GetStandardHelpText( BUTTON_OK ) );
+}
+
+// -----------------------------------------------------------------------
+
+OKButton::OKButton( Window* pParent, WinBits nStyle ) :
+ PushButton( WINDOW_OKBUTTON )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+OKButton::OKButton( Window* pParent, const ResId& rResId ) :
+ PushButton( WINDOW_OKBUTTON )
+{
+ rResId.SetRT( RSC_OKBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void OKButton::Click()
+{
+ // Ist kein Link gesetzt, dann schliesse Parent
+ if ( !GetClickHdl() )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsSystemWindow() )
+ {
+ if ( pParent->IsDialog() )
+ {
+ // gegen rekursive Aufrufe schuetzen
+ if ( !((Dialog*)pParent)->IsInClose() )
+ {
+ if ( ((Dialog*)pParent)->IsInExecute() )
+ ((Dialog*)pParent)->EndDialog( TRUE );
+ else if ( pParent->GetStyle() & WB_CLOSEABLE )
+ ((Dialog*)pParent)->Close();
+ }
+ }
+ else
+ {
+ if ( pParent->GetStyle() & WB_CLOSEABLE )
+ ((SystemWindow*)pParent)->Close();
+ }
+ }
+ }
+ else
+ PushButton::Click();
+}
+
+// =======================================================================
+
+void CancelButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ PushButton::ImplInit( pParent, nStyle );
+
+ SetText( Button::GetStandardText( BUTTON_CANCEL ) );
+ SetHelpText( Button::GetStandardHelpText( BUTTON_CANCEL ) );
+}
+
+// -----------------------------------------------------------------------
+
+CancelButton::CancelButton( Window* pParent, WinBits nStyle ) :
+ PushButton( WINDOW_CANCELBUTTON )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+CancelButton::CancelButton( Window* pParent, const ResId& rResId ) :
+ PushButton( WINDOW_CANCELBUTTON )
+{
+ rResId.SetRT( RSC_CANCELBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void CancelButton::Click()
+{
+ // Ist kein Link gesetzt, dann schliesse Parent
+ if ( !GetClickHdl() )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsSystemWindow() )
+ {
+ if ( pParent->IsDialog() )
+ {
+ // gegen rekursive Aufrufe schuetzen
+ if ( !((Dialog*)pParent)->IsInClose() )
+ {
+ if ( ((Dialog*)pParent)->IsInExecute() )
+ ((Dialog*)pParent)->EndDialog( FALSE );
+ else if ( pParent->GetStyle() & WB_CLOSEABLE )
+ ((Dialog*)pParent)->Close();
+ }
+ }
+ else
+ {
+ if ( pParent->GetStyle() & WB_CLOSEABLE )
+ ((SystemWindow*)pParent)->Close();
+ }
+ }
+ }
+ else
+ PushButton::Click();
+}
+
+// =======================================================================
+
+void HelpButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ PushButton::ImplInit( pParent, nStyle | WB_NOPOINTERFOCUS );
+
+ SetText( Button::GetStandardText( BUTTON_HELP ) );
+ SetHelpText( Button::GetStandardHelpText( BUTTON_HELP ) );
+}
+
+// -----------------------------------------------------------------------
+
+HelpButton::HelpButton( Window* pParent, WinBits nStyle ) :
+ PushButton( WINDOW_HELPBUTTON )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+HelpButton::HelpButton( Window* pParent, const ResId& rResId ) :
+ PushButton( WINDOW_HELPBUTTON )
+{
+ rResId.SetRT( RSC_HELPBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void HelpButton::Click()
+{
+ // Ist kein Link gesetzt, loese Hilfe aus
+ if ( !GetClickHdl() )
+ {
+ Window* pFocusWin = Application::GetFocusWindow();
+ if ( !pFocusWin )
+ pFocusWin = this;
+
+ HelpEvent aEvt( pFocusWin->GetPointerPosPixel(), HELPMODE_CONTEXT );
+ pFocusWin->RequestHelp( aEvt );
+ }
+ else
+ PushButton::Click();
+}
+
+// =======================================================================
+
+void RadioButton::ImplInitData()
+{
+ mnButtonState = 0;
+ mbChecked = FALSE;
+ mbSaveValue = FALSE;
+ mbRadioCheck = TRUE;
+ mbStateChanged = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
+ Button::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits RadioButton::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) &&
+ (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_RADIOBUTTON)) )
+ nStyle |= WB_GROUP;
+ if ( !(nStyle & WB_NOTABSTOP) )
+ {
+ if ( IsChecked() )
+ nStyle |= WB_TABSTOP;
+ else
+ nStyle &= ~WB_TABSTOP;
+ }
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetRadioCheckFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetRadioCheckTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplDrawRadioButtonState()
+{
+ USHORT nStyle = 0;
+
+ // kein Image-RadioButton
+ if ( !maImage )
+ {
+ USHORT nStyle = mnButtonState;
+ if ( !IsEnabled() )
+ nStyle |= BUTTON_DRAW_DISABLED;
+ if ( mbChecked )
+ nStyle |= BUTTON_DRAW_CHECKED;
+ Image aImage = GetRadioImage( GetSettings(), nStyle );
+ if ( IsZoom() )
+ DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
+ else
+ DrawImage( maStateRect.TopLeft(), aImage );
+ }
+ else
+ {
+ HideFocus();
+
+ DecorationView aDecoView( this );
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aImageRect = maStateRect;
+ Size aImageSize = maImage.GetSizePixel();
+ BOOL bEnabled = IsEnabled();
+
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+
+ // Border und Selektionsstatus ausgeben
+ nStyle = FRAME_DRAW_DOUBLEIN;
+ aImageRect = aDecoView.DrawFrame( aImageRect, nStyle );
+ if ( (mnButtonState & BUTTON_DRAW_PRESSED) || !bEnabled )
+ SetFillColor( rStyleSettings.GetFaceColor() );
+ else
+ SetFillColor( rStyleSettings.GetFieldColor() );
+ SetLineColor();
+ DrawRect( aImageRect );
+
+ // Image ausgeben
+ nStyle = 0;
+ if ( !bEnabled )
+ nStyle |= IMAGE_DRAW_DISABLE;
+ Point aImagePos( aImageRect.TopLeft() );
+ aImagePos.X() += (aImageRect.GetWidth()-aImageSize.Width())/2;
+ aImagePos.Y() += (aImageRect.GetHeight()-aImageSize.Height())/2;
+ if ( IsZoom() )
+ DrawImage( aImagePos, aImageSize, maImage, nStyle );
+ else
+ DrawImage( aImagePos, maImage, nStyle );
+
+ aImageRect.Left()++;
+ aImageRect.Top()++;
+ aImageRect.Right()--;
+ aImageRect.Bottom()--;
+
+ maFocusRect = aImageRect;
+
+ if ( mbChecked )
+ {
+ SetLineColor( rStyleSettings.GetHighlightColor() );
+ SetFillColor();
+ if ( (aImageSize.Width() >= 20) || (aImageSize.Height() >= 20) )
+ {
+ aImageRect.Left()++;
+ aImageRect.Top()++;
+ aImageRect.Right()--;
+ aImageRect.Bottom()--;
+ }
+ DrawRect( aImageRect );
+ aImageRect.Left()++;
+ aImageRect.Top()++;
+ aImageRect.Right()--;
+ aImageRect.Bottom()--;
+ DrawRect( aImageRect );
+ }
+
+ if ( HasFocus() )
+ ShowFocus( maFocusRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize,
+ const Size& rImageSize, long nImageSep,
+ Rectangle& rStateRect,
+ Rectangle& rMouseRect,
+ Rectangle& rFocusRect )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ WinBits nWinStyle = GetStyle();
+ XubString aText( GetText() );
+ Rectangle aRect( rPos, rSize );
+
+ // kein Image-RadioButton
+ if ( !maImage )
+ {
+ if ( aText.Len() )
+ {
+ USHORT nTextStyle = FixedText::ImplGetTextStyle( nWinStyle );
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
+ (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ nTextStyle |= TEXT_DRAW_MONO;
+
+ aRect.Left() += rImageSize.Width()+nImageSep;
+ rMouseRect = pDev->GetTextRect( aRect, aText, nTextStyle );
+
+ pDev->DrawText( aRect, aText, nTextStyle );
+ rFocusRect = rMouseRect;
+ rFocusRect.Left()--;
+ rFocusRect.Right()++;
+
+ rMouseRect.Left() = rPos.X();
+ rStateRect.Left() = rPos.X();
+ rStateRect.Top() = rMouseRect.Top();
+ long nTextHeight = GetTextHeight();
+ if ( nTextHeight > rImageSize.Height() )
+ rStateRect.Top() += (nTextHeight-rImageSize.Height())/2;
+ rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
+ rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
+ if ( rStateRect.Bottom() > rMouseRect.Bottom() )
+ rMouseRect.Bottom() = rStateRect.Bottom();
+ }
+ else
+ {
+ if ( nWinStyle & WB_CENTER )
+ rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
+ else if ( nWinStyle & WB_RIGHT )
+ rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); //-1;
+ else
+ rStateRect.Left() = rPos.X(); //+1;
+ if ( nWinStyle & WB_VCENTER )
+ rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
+ else if ( nWinStyle & WB_BOTTOM )
+ rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); //-1;
+ else
+ rStateRect.Top() = rPos.Y(); //+1;
+ rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
+ rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
+ rMouseRect = rStateRect;
+ rFocusRect = Rectangle();
+/* und oben -1, da CalcSize() auch Focus-Rechteck nicht mit einrechnet,
+da im Writer ansonsten die Images noch weiter oben haengen
+ rFocusRect = rStateRect;
+ rFocusRect.Left()--;
+ rFocusRect.Top()--;
+ rFocusRect.Right()++;
+ rFocusRect.Bottom()++;
+*/
+ }
+ }
+ else
+ {
+ BOOL bTopImage = (nWinStyle & WB_TOP) != 0;
+ Size aImageSize = maImage.GetSizePixel();
+ Rectangle aImageRect( rPos, rSize );
+ long nTextHeight = pDev->GetTextHeight();
+ long nTextWidth = pDev->GetCtrlTextWidth( aText );
+
+ // Positionen und Groessen berechnen
+ if ( aText.Len() )
+ {
+ Size aTmpSize( (aImageSize.Width()+8), (aImageSize.Height()+8) );
+ if ( bTopImage )
+ {
+ aImageRect.Left() = (rSize.Width()-aTmpSize.Width())/2;
+ aImageRect.Top() = (rSize.Height()-(aTmpSize.Height()+nTextHeight+6))/2;
+ }
+ else
+ aImageRect.Top() = (rSize.Height()-aTmpSize.Height())/2;
+
+ aImageRect.Right() = aImageRect.Left()+aTmpSize.Width();
+ aImageRect.Bottom() = aImageRect.Top()+aTmpSize.Height();
+ }
+
+ // Text ausgeben
+ if ( aText.Len() )
+ {
+ Point aTxtPos = rPos;
+ if ( bTopImage )
+ {
+ aTxtPos.X() += (rSize.Width()-nTextWidth)/2;
+ aTxtPos.Y() += aImageRect.Bottom()+6;
+ }
+ else
+ {
+ aTxtPos.X() += aImageRect.Right()+8;
+ aTxtPos.Y() += (rSize.Height()-nTextHeight)/2;
+ }
+ pDev->DrawCtrlText( aTxtPos, aText );
+ }
+
+ rMouseRect = aImageRect;
+ rStateRect = aImageRect;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplDrawRadioButton()
+{
+ HideFocus();
+
+ Size aImageSize;
+ if ( !maImage )
+ aImageSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel();
+ else
+ aImageSize = maImage.GetSizePixel();
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+
+ ImplDraw( this, 0, Point(), GetOutputSizePixel(),
+ aImageSize, IMPL_SEP_BUTTON_IMAGE, maStateRect, maMouseRect, maFocusRect );
+
+ if ( !maImage )
+ {
+ if ( HasFocus() && !maFocusRect.IsEmpty() )
+ ShowFocus( maFocusRect );
+ }
+ ImplDrawRadioButtonState();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplUncheckAllOther()
+{
+ mnStyle |= WB_TABSTOP;
+
+ // Gruppe mit RadioButtons durchgehen und die gecheckten Buttons
+ Window* pWindow;
+ WinBits nStyle;
+ if ( !(GetStyle() & WB_GROUP) )
+ {
+ pWindow = GetWindow( WINDOW_PREV );
+ while ( pWindow )
+ {
+ nStyle = pWindow->GetStyle();
+
+ if ( pWindow->GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( ((RadioButton*)pWindow)->IsChecked() )
+ {
+ ImplDelData aDelData;
+ pWindow->ImplAddDel( &aDelData );
+ ((RadioButton*)pWindow)->SetState( FALSE );
+ if ( aDelData.IsDelete() )
+ return;
+ pWindow->ImplRemoveDel( &aDelData );
+ }
+ // Um falsch gesetzt WB_TABSTOPS immer zu entfernen, nicht
+ // innerhalb der if-Abfrage
+ pWindow->mnStyle &= ~WB_TABSTOP;
+ }
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ pWindow = pWindow->GetWindow( WINDOW_PREV );
+ }
+ }
+
+ pWindow = GetWindow( WINDOW_NEXT );
+ while ( pWindow )
+ {
+ nStyle = pWindow->GetStyle();
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ if ( pWindow->GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( ((RadioButton*)pWindow)->IsChecked() )
+ {
+ ImplDelData aDelData;
+ pWindow->ImplAddDel( &aDelData );
+ ((RadioButton*)pWindow)->SetState( FALSE );
+ if ( aDelData.IsDelete() )
+ return;
+ pWindow->ImplRemoveDel( &aDelData );
+ }
+ // Um falsch gesetzt WB_TABSTOPS immer zu entfernen, nicht
+ // innerhalb der if-Abfrage
+ pWindow->mnStyle &= ~WB_TABSTOP;
+ }
+
+ pWindow = pWindow->GetWindow( WINDOW_NEXT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplCallClick( BOOL bGrabFocus, USHORT nFocusFlags )
+{
+ mbStateChanged = !mbChecked;
+ mbChecked = TRUE;
+ mnStyle |= WB_TABSTOP;
+ ImplDrawRadioButtonState();
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ if ( mbRadioCheck )
+ ImplUncheckAllOther();
+ if ( aDelData.IsDelete() )
+ return;
+ if ( bGrabFocus )
+ ImplGrabFocus( nFocusFlags );
+ if ( aDelData.IsDelete() )
+ return;
+ if ( mbStateChanged )
+ Toggle();
+ if ( aDelData.IsDelete() )
+ return;
+ Click();
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+ mbStateChanged = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+RadioButton::RadioButton( Window* pParent, WinBits nStyle ) :
+ Button( WINDOW_RADIOBUTTON )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+RadioButton::RadioButton( Window* pParent, const ResId& rResId ) :
+ Button( WINDOW_RADIOBUTTON )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_RADIOBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::ImplLoadRes( const ResId& rResId )
+{
+ Button::ImplLoadRes( rResId );
+
+ //anderer Wert als Default ?
+ USHORT nChecked = ReadShortRes();
+ if ( nChecked )
+ SetState( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+RadioButton::~RadioButton()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ StartTracking();
+ return;
+ }
+
+ Button::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
+ GrabFocus();
+
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ ImplCallClick();
+ else
+ ImplDrawRadioButtonState();
+ }
+ }
+ else
+ {
+ if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
+ {
+ if ( !(mnButtonState & BUTTON_DRAW_PRESSED) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ }
+ }
+ else
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
+ {
+ if ( !(mnButtonState & BUTTON_DRAW_PRESSED) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ }
+ }
+ else if ( (mnButtonState & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ }
+ else
+ Button::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::KeyUp( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( (mnButtonState & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplCallClick();
+ }
+ else
+ Button::KeyUp( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Paint( const Rectangle& rRect )
+{
+ ImplDrawRadioButton();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ if ( !maImage )
+ {
+ MapMode aResMapMode( MAP_100TH_MM );
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
+ Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
+ Size aBrd2Size = pDev->LogicToPixel( Size( 60, 60 ), aResMapMode );
+ Font aFont = GetDrawPixelFont( pDev );
+ Rectangle aStateRect;
+ Rectangle aMouseRect;
+ Rectangle aFocusRect;
+
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+ aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
+ aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
+ aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
+ aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
+
+ if ( !aBrd1Size.Width() )
+ aBrd1Size.Width() = 1;
+ if ( !aBrd1Size.Height() )
+ aBrd1Size.Height() = 1;
+ if ( !aBrd2Size.Width() )
+ aBrd2Size.Width() = 1;
+ if ( !aBrd2Size.Height() )
+ aBrd2Size.Height() = 1;
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ ImplDraw( pDev, nFlags, aPos, aSize,
+ aImageSize, GetDrawPixel( pDev, IMPL_SEP_BUTTON_IMAGE ),
+ aStateRect, aMouseRect, aFocusRect );
+
+ Point aCenterPos = aStateRect.Center();
+ long nRadX = aImageSize.Width()/2;
+ long nRadY = aImageSize.Height()/2;
+
+ pDev->SetLineColor();
+ pDev->SetFillColor( Color( COL_BLACK ) );
+ pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
+ nRadX -= aBrd1Size.Width();
+ nRadY -= aBrd1Size.Height();
+ pDev->SetFillColor( Color( COL_WHITE ) );
+ pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
+ if ( mbChecked )
+ {
+ nRadX -= aBrd1Size.Width();
+ nRadY -= aBrd1Size.Height();
+ if ( !nRadX )
+ nRadX = 1;
+ if ( !nRadY )
+ nRadY = 1;
+ pDev->SetFillColor( Color( COL_BLACK ) );
+ pDev->DrawPolygon( Polygon( aCenterPos, nRadX, nRadY ) );
+ }
+
+ pDev->Pop();
+ }
+ else
+ {
+ DBG_ERROR( "RadioButton::Draw() - not implemented for RadioButton with Image" );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::GetFocus()
+{
+ ShowFocus( maFocusRect );
+ SetInputContext( InputContext( GetFont() ) );
+ Button::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::LoseFocus()
+{
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawRadioButtonState();
+ }
+
+ HideFocus();
+ Button::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::StateChanged( StateChangedType nType )
+{
+ Button::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_STATE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( HasPaintEvent() )
+ Invalidate( maStateRect );
+ else
+ ImplDrawRadioButtonState();
+ }
+ Toggle();
+ }
+ else if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_IMAGE) ||
+ (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
+
+ if ( (GetPrevStyle() & RADIOBUTTON_VIEW_STYLE) !=
+ (GetStyle() & RADIOBUTTON_VIEW_STYLE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Button::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Toggle()
+{
+ maToggleHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::SetImage( const Image& rImage )
+{
+ if ( rImage != maImage )
+ {
+ maImage = rImage;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::SetState( BOOL bCheck )
+{
+ // TabStop-Flag richtig mitfuehren
+ if ( bCheck )
+ mnStyle |= WB_TABSTOP;
+ else
+ mnStyle &= ~WB_TABSTOP;
+
+ if ( mbChecked != bCheck )
+ {
+ mbChecked = bCheck;
+ StateChanged( STATE_CHANGE_STATE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void RadioButton::Check( BOOL bCheck )
+{
+ // TabStop-Flag richtig mitfuehren
+ if ( bCheck )
+ mnStyle |= WB_TABSTOP;
+ else
+ mnStyle &= ~WB_TABSTOP;
+
+ if ( mbChecked != bCheck )
+ {
+ mbChecked = bCheck;
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ StateChanged( STATE_CHANGE_STATE );
+ if ( aDelData.IsDelete() )
+ return;
+ ImplRemoveDel( &aDelData );
+ if ( bCheck && mbRadioCheck )
+ ImplUncheckAllOther();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image RadioButton::GetRadioImage( const AllSettings& rSettings, USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
+ USHORT nStyle = rStyleSettings.GetRadioButtonStyle() & STYLE_RADIOBUTTON_STYLE;
+
+ if ( !pSVData->maCtrlData.mpRadioImgList ||
+ (pSVData->maCtrlData.mnRadioStyle != nStyle) ||
+ (pSVData->maCtrlData.mnLastRadioFColor != rStyleSettings.GetFaceColor().GetColor()) ||
+ (pSVData->maCtrlData.mnLastRadioWColor != rStyleSettings.GetWindowColor().GetColor()) ||
+ (pSVData->maCtrlData.mnLastRadioLColor != rStyleSettings.GetLightColor().GetColor()) )
+ {
+ if ( pSVData->maCtrlData.mpRadioImgList )
+ delete pSVData->maCtrlData.mpRadioImgList;
+
+ pSVData->maCtrlData.mnLastRadioFColor = rStyleSettings.GetFaceColor().GetColor();
+ pSVData->maCtrlData.mnLastRadioWColor = rStyleSettings.GetWindowColor().GetColor();
+ pSVData->maCtrlData.mnLastRadioLColor = rStyleSettings.GetLightColor().GetColor();
+
+ long aTempAry1[(6*sizeof(Color))/sizeof(long)];
+ long aTempAry2[(6*sizeof(Color))/sizeof(long)];
+ Color* pColorAry1 = (Color*)aTempAry1;
+ Color* pColorAry2 = (Color*)aTempAry2;
+ pColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 );
+ pColorAry1[1] = Color( 0xFF, 0xFF, 0x00 );
+ pColorAry1[2] = Color( 0xFF, 0xFF, 0xFF );
+ pColorAry1[3] = Color( 0x80, 0x80, 0x80 );
+ pColorAry1[4] = Color( 0x00, 0x00, 0x00 );
+ pColorAry1[5] = Color( 0x00, 0xFF, 0x00 );
+ pColorAry2[0] = rStyleSettings.GetFaceColor();
+ pColorAry2[1] = rStyleSettings.GetWindowColor();
+ pColorAry2[2] = rStyleSettings.GetLightColor();
+ pColorAry2[3] = rStyleSettings.GetShadowColor();
+ pColorAry2[4] = rStyleSettings.GetDarkShadowColor();
+ pColorAry2[5] = rStyleSettings.GetWindowTextColor();
+
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_RADIO+nStyle, ImplGetResMgr() ) );
+ aBmp.Replace( pColorAry1, pColorAry2, 6, NULL );
+ pSVData->maCtrlData.mpRadioImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 6 );
+ pSVData->maCtrlData.mnRadioStyle = nStyle;
+ }
+
+ USHORT nId;
+ if ( nFlags & BUTTON_DRAW_DISABLED )
+ {
+ if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 6;
+ else
+ nId = 5;
+ }
+ else if ( nFlags & BUTTON_DRAW_PRESSED )
+ {
+ if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 4;
+ else
+ nId = 3;
+ }
+ else
+ {
+ if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 2;
+ else
+ nId = 1;
+ }
+ return pSVData->maCtrlData.mpRadioImgList->GetImage( nId );
+}
+
+// -----------------------------------------------------------------------
+
+Size RadioButton::CalcMinimumSize( long nMaxWidth ) const
+{
+ Size aSize;
+ if ( !maImage )
+ aSize = GetRadioImage( GetSettings(), 0 ).GetSizePixel();
+ else
+ aSize = maImage.GetSizePixel();
+
+ XubString aText = GetText();
+ if ( aText.Len() )
+ {
+ Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
+ aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
+ aSize.Width() += IMPL_SEP_BUTTON_IMAGE;
+ aSize.Width() += aTextSize.Width();
+ if ( aSize.Height() < aTextSize.Height() )
+ aSize.Height() = aTextSize.Height();
+ }
+ else if ( !maImage )
+ {
+/* da ansonsten im Writer die Control zu weit oben haengen
+ aSize.Width() += 2;
+ aSize.Height() += 2;
+*/
+ }
+
+ return CalcWindowSize( aSize );
+}
+
+// =======================================================================
+
+void CheckBox::ImplInitData()
+{
+ mnButtonState = 0;
+ meState = STATE_NOCHECK;
+ meSaveValue = STATE_NOCHECK;
+ mbTriState = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( pParent->GetWindow( WINDOW_LASTCHILD ), nStyle );
+ Button::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits CheckBox::ImplInitStyle( const Window* pPrevWindow, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) &&
+ (!pPrevWindow || (pPrevWindow->GetType() != WINDOW_CHECKBOX)) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetRadioCheckFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetRadioCheckTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplLoadRes( const ResId& rResId )
+{
+ Button::ImplLoadRes( rResId );
+
+ if ( rResId.GetRT() != RSC_TRISTATEBOX )
+ {
+ USHORT nChecked = ReadShortRes();
+ //anderer Wert als Default ?
+ if( nChecked )
+ Check( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplDrawCheckBoxState()
+{
+ USHORT nStyle = mnButtonState;
+ if ( !IsEnabled() )
+ nStyle |= BUTTON_DRAW_DISABLED;
+ if ( meState == STATE_DONTKNOW )
+ nStyle |= BUTTON_DRAW_DONTKNOW;
+ else if ( meState == STATE_CHECK )
+ nStyle |= BUTTON_DRAW_CHECKED;
+ Image aImage = GetCheckImage( GetSettings(), nStyle );
+ if ( IsZoom() )
+ DrawImage( maStateRect.TopLeft(), maStateRect.GetSize(), aImage );
+ else
+ DrawImage( maStateRect.TopLeft(), aImage );
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize,
+ const Size& rImageSize, long nImageSep,
+ Rectangle& rStateRect,
+ Rectangle& rMouseRect,
+ Rectangle& rFocusRect )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ WinBits nWinStyle = GetStyle();
+ XubString aText( GetText() );
+ Rectangle aRect( rPos, rSize );
+
+ if ( aText.Len() )
+ {
+ USHORT nTextStyle = FixedText::ImplGetTextStyle( nWinStyle );
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
+ (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ nTextStyle |= TEXT_DRAW_MONO;
+
+ aRect.Left() += rImageSize.Width()+nImageSep;
+ rMouseRect = pDev->GetTextRect( aRect, aText, nTextStyle );
+
+ pDev->DrawText( aRect, aText, nTextStyle );
+ rFocusRect = rMouseRect;
+ rFocusRect.Left()--;
+ rFocusRect.Right()++;
+
+ rMouseRect.Left() = rPos.X();
+ rStateRect.Left() = rPos.X();
+ rStateRect.Top() = rMouseRect.Top();
+ long nTextHeight = GetTextHeight();
+ if ( nTextHeight > rImageSize.Height() )
+ rStateRect.Top() += (nTextHeight-rImageSize.Height())/2;
+ rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
+ rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
+ if ( rStateRect.Bottom() > rMouseRect.Bottom() )
+ rMouseRect.Bottom() = rStateRect.Bottom();
+ }
+ else
+ {
+ if ( nWinStyle & WB_CENTER )
+ rStateRect.Left() = rPos.X()+((rSize.Width()-rImageSize.Width())/2);
+ else if ( nWinStyle & WB_RIGHT )
+ rStateRect.Left() = rPos.X()+rSize.Width()-rImageSize.Width(); //-1;
+ else
+ rStateRect.Left() = rPos.X(); //+1;
+ if ( nWinStyle & WB_VCENTER )
+ rStateRect.Top() = rPos.Y()+((rSize.Height()-rImageSize.Height())/2);
+ else if ( nWinStyle & WB_BOTTOM )
+ rStateRect.Top() = rPos.Y()+rSize.Height()-rImageSize.Height(); //-1;
+ else
+ rStateRect.Top() = rPos.Y(); //+1;
+ rStateRect.Right() = rStateRect.Left()+rImageSize.Width()-1;
+ rStateRect.Bottom() = rStateRect.Top()+rImageSize.Height()-1;
+ rMouseRect = rStateRect;
+ rFocusRect = Rectangle();
+/* und oben -1, da CalcSize() auch Focus-Rechteck nicht mit einrechnet,
+da im Writer ansonsten die Images noch weiter oben haengen
+ rFocusRect = rStateRect;
+ rFocusRect.Left()--;
+ rFocusRect.Top()--;
+ rFocusRect.Right()++;
+ rFocusRect.Bottom()++;
+*/
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplDrawCheckBox()
+{
+ Size aImageSize = GetCheckImage( GetSettings(), 0 ).GetSizePixel();
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+
+ HideFocus();
+ ImplDraw( this, 0, Point(), GetOutputSizePixel(),
+ aImageSize, IMPL_SEP_BUTTON_IMAGE, maStateRect, maMouseRect, maFocusRect );
+ if ( HasFocus() && !maFocusRect.IsEmpty() )
+ ShowFocus( maFocusRect );
+ ImplDrawCheckBoxState();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::ImplCheck()
+{
+ TriState eNewState;
+ if ( meState == STATE_NOCHECK )
+ eNewState = STATE_CHECK;
+ else if ( !mbTriState )
+ eNewState = STATE_NOCHECK;
+ else if ( meState == STATE_CHECK )
+ eNewState = STATE_DONTKNOW;
+ else
+ eNewState = STATE_NOCHECK;
+ meState = eNewState;
+ ImplDrawCheckBoxState();
+ Toggle();
+ Click();
+}
+
+// -----------------------------------------------------------------------
+
+CheckBox::CheckBox( Window* pParent, WinBits nStyle ) :
+ Button( WINDOW_CHECKBOX )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+CheckBox::CheckBox( Window* pParent, const ResId& rResId ) :
+ Button( WINDOW_CHECKBOX )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_CHECKBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && maMouseRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ StartTracking();
+ return;
+ }
+
+ Button::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ if ( !(GetStyle() & WB_NOPOINTERFOCUS) && !rTEvt.IsTrackingCanceled() )
+ GrabFocus();
+
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ ImplCheck();
+ else
+ ImplDrawCheckBoxState();
+ }
+ }
+ else
+ {
+ if ( maMouseRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() ) )
+ {
+ if ( !(mnButtonState & BUTTON_DRAW_PRESSED) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ }
+ }
+ else
+ {
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( !aKeyCode.GetModifier() && (aKeyCode.GetCode() == KEY_SPACE) )
+ {
+ if ( !(mnButtonState & BUTTON_DRAW_PRESSED) )
+ {
+ mnButtonState |= BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ }
+ }
+ else if ( (mnButtonState & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_ESCAPE) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ }
+ else
+ Button::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::KeyUp( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ if ( (mnButtonState & BUTTON_DRAW_PRESSED) && (aKeyCode.GetCode() == KEY_SPACE) )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplCheck();
+ }
+ else
+ Button::KeyUp( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::Paint( const Rectangle& rRect )
+{
+ ImplDrawCheckBox();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ MapMode aResMapMode( MAP_100TH_MM );
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Size aImageSize = pDev->LogicToPixel( Size( 300, 300 ), aResMapMode );
+ Size aBrd1Size = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
+ Size aBrd2Size = pDev->LogicToPixel( Size( 30, 30 ), aResMapMode );
+ long nCheckWidth = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode ).Width();
+ Font aFont = GetDrawPixelFont( pDev );
+ Rectangle aStateRect;
+ Rectangle aMouseRect;
+ Rectangle aFocusRect;
+
+ aImageSize.Width() = CalcZoom( aImageSize.Width() );
+ aImageSize.Height() = CalcZoom( aImageSize.Height() );
+ aBrd1Size.Width() = CalcZoom( aBrd1Size.Width() );
+ aBrd1Size.Height() = CalcZoom( aBrd1Size.Height() );
+ aBrd2Size.Width() = CalcZoom( aBrd2Size.Width() );
+ aBrd2Size.Height() = CalcZoom( aBrd2Size.Height() );
+
+ if ( !aBrd1Size.Width() )
+ aBrd1Size.Width() = 1;
+ if ( !aBrd1Size.Height() )
+ aBrd1Size.Height() = 1;
+ if ( !aBrd2Size.Width() )
+ aBrd2Size.Width() = 1;
+ if ( !aBrd2Size.Height() )
+ aBrd2Size.Height() = 1;
+ if ( !nCheckWidth )
+ nCheckWidth = 1;
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ ImplDraw( pDev, nFlags, aPos, aSize,
+ aImageSize, GetDrawPixel( pDev, IMPL_SEP_BUTTON_IMAGE ),
+ aStateRect, aMouseRect, aFocusRect );
+
+ pDev->SetLineColor();
+ pDev->SetFillColor( Color( COL_BLACK ) );
+ pDev->DrawRect( aStateRect );
+ aStateRect.Left() += aBrd1Size.Width();
+ aStateRect.Top() += aBrd1Size.Height();
+ aStateRect.Right() -= aBrd1Size.Width();
+ aStateRect.Bottom() -= aBrd1Size.Height();
+ if ( meState == STATE_DONTKNOW )
+ pDev->SetFillColor( Color( COL_LIGHTGRAY ) );
+ else
+ pDev->SetFillColor( Color( COL_WHITE ) );
+ pDev->DrawRect( aStateRect );
+
+ if ( meState == STATE_CHECK )
+ {
+ aStateRect.Left() += aBrd2Size.Width();
+ aStateRect.Top() += aBrd2Size.Height();
+ aStateRect.Right() -= aBrd2Size.Width();
+ aStateRect.Bottom() -= aBrd2Size.Height();
+ Point aPos11( aStateRect.TopLeft() );
+ Point aPos12( aStateRect.BottomRight() );
+ Point aPos21( aStateRect.TopRight() );
+ Point aPos22( aStateRect.BottomLeft() );
+ Point aTempPos11( aPos11 );
+ Point aTempPos12( aPos12 );
+ Point aTempPos21( aPos21 );
+ Point aTempPos22( aPos22 );
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ long nDX = 0;
+ for ( long i = 0; i < nCheckWidth; i++ )
+ {
+ if ( !(i % 2) )
+ {
+ aTempPos11.X() = aPos11.X()+nDX;
+ aTempPos12.X() = aPos12.X()+nDX;
+ aTempPos21.X() = aPos21.X()+nDX;
+ aTempPos22.X() = aPos22.X()+nDX;
+ }
+ else
+ {
+ nDX++;
+ aTempPos11.X() = aPos11.X()-nDX;
+ aTempPos12.X() = aPos12.X()-nDX;
+ aTempPos21.X() = aPos21.X()-nDX;
+ aTempPos22.X() = aPos22.X()-nDX;
+ }
+ pDev->DrawLine( aTempPos11, aTempPos12 );
+ pDev->DrawLine( aTempPos21, aTempPos22 );
+ }
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::GetFocus()
+{
+ ShowFocus( maFocusRect );
+ SetInputContext( InputContext( GetFont() ) );
+ Button::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::LoseFocus()
+{
+ if ( mnButtonState & BUTTON_DRAW_PRESSED )
+ {
+ mnButtonState &= ~BUTTON_DRAW_PRESSED;
+ ImplDrawCheckBoxState();
+ }
+
+ HideFocus();
+ Button::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::StateChanged( StateChangedType nType )
+{
+ Button::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_STATE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( HasPaintEvent() )
+ Invalidate( maStateRect );
+ else
+ ImplDrawCheckBoxState();
+ }
+ Toggle();
+ }
+ else if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_IMAGE) ||
+ (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetWindow( WINDOW_PREV ), GetStyle() ) );
+
+ if ( (GetPrevStyle() & CHECKBOX_VIEW_STYLE) !=
+ (GetStyle() & CHECKBOX_VIEW_STYLE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Button::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::Toggle()
+{
+ maToggleHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::SetState( TriState eState )
+{
+ if ( !mbTriState && (eState == STATE_DONTKNOW) )
+ eState = STATE_NOCHECK;
+
+ if ( meState != eState )
+ {
+ meState = eState;
+ StateChanged( STATE_CHANGE_STATE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void CheckBox::EnableTriState( BOOL bTriState )
+{
+ if ( mbTriState != bTriState )
+ {
+ mbTriState = bTriState;
+
+ if ( !bTriState && (meState == STATE_DONTKNOW) )
+ SetState( STATE_NOCHECK );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image CheckBox::GetCheckImage( const AllSettings& rSettings, USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ const StyleSettings& rStyleSettings = rSettings.GetStyleSettings();
+ USHORT nStyle = rStyleSettings.GetCheckBoxStyle() & STYLE_CHECKBOX_STYLE;
+
+ if ( !pSVData->maCtrlData.mpCheckImgList ||
+ (pSVData->maCtrlData.mnCheckStyle != nStyle) ||
+ (pSVData->maCtrlData.mnLastCheckFColor != rStyleSettings.GetFaceColor().GetColor()) ||
+ (pSVData->maCtrlData.mnLastCheckWColor != rStyleSettings.GetWindowColor().GetColor()) ||
+ (pSVData->maCtrlData.mnLastCheckLColor != rStyleSettings.GetLightColor().GetColor()) )
+ {
+ if ( pSVData->maCtrlData.mpCheckImgList )
+ delete pSVData->maCtrlData.mpCheckImgList;
+
+ pSVData->maCtrlData.mnLastCheckFColor = rStyleSettings.GetFaceColor().GetColor();
+ pSVData->maCtrlData.mnLastCheckWColor = rStyleSettings.GetWindowColor().GetColor();
+ pSVData->maCtrlData.mnLastCheckLColor = rStyleSettings.GetLightColor().GetColor();
+
+ long aTempAry1[(6*sizeof(Color))/sizeof(long)];
+ long aTempAry2[(6*sizeof(Color))/sizeof(long)];
+ Color* pColorAry1 = (Color*)aTempAry1;
+ Color* pColorAry2 = (Color*)aTempAry2;
+ pColorAry1[0] = Color( 0xC0, 0xC0, 0xC0 );
+ pColorAry1[1] = Color( 0xFF, 0xFF, 0x00 );
+ pColorAry1[2] = Color( 0xFF, 0xFF, 0xFF );
+ pColorAry1[3] = Color( 0x80, 0x80, 0x80 );
+ pColorAry1[4] = Color( 0x00, 0x00, 0x00 );
+ pColorAry1[5] = Color( 0x00, 0xFF, 0x00 );
+ pColorAry2[0] = rStyleSettings.GetFaceColor();
+ pColorAry2[1] = rStyleSettings.GetWindowColor();
+ pColorAry2[2] = rStyleSettings.GetLightColor();
+ pColorAry2[3] = rStyleSettings.GetShadowColor();
+ pColorAry2[4] = rStyleSettings.GetDarkShadowColor();
+ pColorAry2[5] = rStyleSettings.GetWindowTextColor();
+
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_CHECK+nStyle, ImplGetResMgr() ) );
+ aBmp.Replace( pColorAry1, pColorAry2, 6, NULL );
+ pSVData->maCtrlData.mpCheckImgList = new ImageList( aBmp, 9 );
+ pSVData->maCtrlData.mnCheckStyle = nStyle;
+ }
+
+ USHORT nId;
+ if ( nFlags & BUTTON_DRAW_DISABLED )
+ {
+ if ( nFlags & BUTTON_DRAW_DONTKNOW )
+ nId = 9;
+ else if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 6;
+ else
+ nId = 5;
+ }
+ else if ( nFlags & BUTTON_DRAW_PRESSED )
+ {
+ if ( nFlags & BUTTON_DRAW_DONTKNOW )
+ nId = 8;
+ else if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 4;
+ else
+ nId = 3;
+ }
+ else
+ {
+ if ( nFlags & BUTTON_DRAW_DONTKNOW )
+ nId = 7;
+ else if ( nFlags & BUTTON_DRAW_CHECKED )
+ nId = 2;
+ else
+ nId = 1;
+ }
+ return pSVData->maCtrlData.mpCheckImgList->GetImage( nId );
+}
+
+// -----------------------------------------------------------------------
+
+Size CheckBox::CalcMinimumSize( long nMaxWidth ) const
+{
+ Size aSize = GetCheckImage( GetSettings(), 0 ).GetSizePixel();
+
+ XubString aText = GetText();
+ if ( aText.Len() )
+ {
+ Size aTextSize = GetTextRect( Rectangle( Point(), Size( nMaxWidth ? nMaxWidth : 0x7fffffff, 0x7fffffff ) ),
+ aText, FixedText::ImplGetTextStyle( GetStyle() ) ).GetSize();
+ aSize.Width() += IMPL_SEP_BUTTON_IMAGE;
+ aSize.Width() += aTextSize.Width();
+ if ( aSize.Height() < aTextSize.Height() )
+ aSize.Height() = aTextSize.Height();
+ }
+ else
+ {
+/* da ansonsten im Writer die Control zu weit oben haengen
+ aSize.Width() += 2;
+ aSize.Height() += 2;
+*/
+ }
+
+ return CalcWindowSize( aSize );
+}
+
+// =======================================================================
+
+ImageButton::ImageButton( WindowType nType ) :
+ PushButton( nType )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImageButton::ImageButton( Window* pParent, WinBits nStyle ) :
+ PushButton( pParent, nStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImageButton::ImageButton( Window* pParent, const ResId& rResId ) :
+ PushButton( pParent, rResId.SetRT( RSC_IMAGEBUTTON ) )
+{
+ USHORT nObjMask = ReadShortRes();
+
+ if ( RSC_IMAGEBUTTON_IMAGE & nObjMask )
+ {
+ SetImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes() ) ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+
+ if ( RSC_IMAGEBUTTON_SYMBOL & nObjMask )
+ SetSymbol( (SymbolType)ReadShortRes() );
+
+ if ( RSC_IMAGEBUTTON_STATE & nObjMask )
+ SetState( (TriState)ReadShortRes() );
+}
+
+// -----------------------------------------------------------------------
+
+ImageButton::~ImageButton()
+{
+}
+
+// =======================================================================
+
+ImageRadioButton::ImageRadioButton( Window* pParent, WinBits nStyle ) :
+ RadioButton( pParent, nStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImageRadioButton::ImageRadioButton( Window* pParent, const ResId& rResId ) :
+ RadioButton( pParent, rResId.SetRT( RSC_IMAGERADIOBUTTON ) )
+{
+ USHORT nObjMask = ReadShortRes();
+
+ if ( RSC_IMAGERADIOBUTTON_IMAGE & nObjMask )
+ {
+ SetImage( Image( ResId( (RSHEADER_TYPE*)GetClassRes() ) ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImageRadioButton::~ImageRadioButton()
+{
+}
+
+// =======================================================================
+
+TriStateBox::TriStateBox( Window* pParent, WinBits nStyle ) :
+ CheckBox( pParent, nStyle )
+{
+ EnableTriState( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+TriStateBox::TriStateBox( Window* pParent, const ResId& rResId ) :
+ CheckBox( pParent, rResId.SetRT( RSC_TRISTATEBOX ) )
+{
+ EnableTriState( TRUE );
+
+ USHORT nTriState = ReadShortRes();
+ USHORT bDisableTriState = ReadShortRes();
+ //anderer Wert als Default ?
+ if ( (TriState)nTriState != STATE_NOCHECK )
+ SetState( (TriState)nTriState );
+ if ( bDisableTriState )
+ EnableTriState( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+TriStateBox::~TriStateBox()
+{
+}
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
new file mode 100644
index 000000000000..1d5ab2dd8eab
--- /dev/null
+++ b/vcl/source/control/combobox.cxx
@@ -0,0 +1,1242 @@
+/*************************************************************************
+ *
+ * $RCSfile: combobox.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_COMBOBOX_CXX
+
+#ifndef _TOOLS_TABLE_HXX
+#include <tools/table.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_ILSTBOX_HXX
+#include <ilstbox.hxx>
+#endif
+#ifndef _SV_LSTBOX_H
+#include <lstbox.h>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_SUBEDIT_HXX
+#include <subedit.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_COMBOBOX_HXX
+#include <combobox.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+inline ULONG ImplCreateKey( USHORT nPos )
+{
+ // Key = Pos+1, wegen Pos 0
+ return nPos+1;
+}
+
+// -----------------------------------------------------------------------
+
+static void lcl_GetSelectedEntries( Table& rSelectedPos, const XubString& rText, xub_Unicode cTokenSep, const ImplEntryList* pEntryList )
+{
+ for( xub_StrLen n = rText.GetTokenCount( cTokenSep ); n; )
+ {
+ XubString aToken = rText.GetToken( --n, cTokenSep );
+ aToken.EraseLeadingAndTrailingChars( ' ' );
+ USHORT nPos = pEntryList->FindEntry( aToken );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ rSelectedPos.Insert( ImplCreateKey( nPos ), (void*)1L );
+ }
+}
+
+// =======================================================================
+
+ComboBox::ComboBox( WindowType nType ) :
+ Edit( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+ComboBox::ComboBox( Window* pParent, WinBits nStyle ) :
+ Edit( WINDOW_COMBOBOX )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ComboBox::ComboBox( Window* pParent, const ResId& rResId ) :
+ Edit( WINDOW_COMBOBOX )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_COMBOBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ComboBox::~ComboBox()
+{
+ SetSubEdit( NULL );
+ delete mpSubEdit;
+
+ delete mpImplLB;
+ mpImplLB = NULL;
+
+ delete mpFloatWin;
+ delete mpBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::ImplInitData()
+{
+ mpSubEdit = NULL;
+ mpBtn = NULL;
+ mpImplLB = NULL;
+ mpFloatWin = NULL;
+
+ mnDDHeight = 0;
+ mbDDAutoSize = TRUE;
+ mbSyntheticModify = FALSE;
+ mbMatchCase = FALSE;
+ mcMultiSep = ';';
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::ImplCalcEditHeight()
+{
+ long nLeft, nTop, nRight, nBottom;
+ GetBorder( nLeft, nTop, nRight, nBottom );
+ mnDDHeight = (USHORT)(mpSubEdit->GetTextHeight() + nTop + nBottom + 4);
+ if ( !IsDropDownBox() )
+ mnDDHeight += 4;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ ImplInitStyle( nStyle );
+
+ BOOL bNoBorder = ( nStyle & WB_NOBORDER ) ? TRUE : FALSE;
+ if ( !(nStyle & WB_DROPDOWN) )
+ {
+ nStyle &= ~WB_BORDER;
+ nStyle |= WB_NOBORDER;
+ }
+ else
+ {
+ if ( !bNoBorder )
+ nStyle |= WB_BORDER;
+ }
+
+ Edit::ImplInit( pParent, nStyle );
+ SetBackground();
+
+ // DropDown ?
+ WinBits nEditStyle = 0;
+ WinBits nListStyle = nStyle;
+ if( nStyle & WB_DROPDOWN )
+ {
+ mpFloatWin = new ImplListBoxFloatingWindow( this );
+ mpFloatWin->SetAutoWidth( TRUE );
+ mpFloatWin->SetPopupModeEndHdl( LINK( this, ComboBox, ImplPopupModeEndHdl ) );
+
+ mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
+ ImplInitDropDownButton( mpBtn );
+ mpBtn->SetMBDownHdl( LINK( this, ComboBox, ImplClickBtnHdl ) );
+ mpBtn->Show();
+
+ nEditStyle |= WB_NOBORDER;
+ nListStyle &= ~WB_BORDER;
+ nListStyle |= WB_NOBORDER;
+ }
+ else
+ {
+ if ( !bNoBorder )
+ {
+ nEditStyle |= WB_BORDER;
+ nListStyle &= ~WB_NOBORDER;
+ nListStyle |= WB_BORDER;
+ }
+ }
+
+ mpSubEdit = new Edit( this, nEditStyle );
+ SetSubEdit( mpSubEdit );
+ mpSubEdit->SetPosPixel( Point() );
+ EnableAutocomplete( TRUE );
+ mpSubEdit->Show();
+
+ Window* pLBParent = this;
+ if ( mpFloatWin )
+ pLBParent = mpFloatWin;
+ mpImplLB = new ImplListBox( pLBParent, nListStyle|WB_SIMPLEMODE );
+ mpImplLB->SetPosPixel( Point() );
+ mpImplLB->SetSelectHdl( LINK( this, ComboBox, ImplSelectHdl ) );
+ mpImplLB->SetCancelHdl( LINK( this, ComboBox, ImplCancelHdl ) );
+ mpImplLB->SetDoubleClickHdl( LINK( this, ComboBox, ImplDoubleClickHdl ) );
+ mpImplLB->SetUserDrawHdl( LINK( this, ComboBox, ImplUserDrawHdl ) );
+ mpImplLB->SetSelectionChangedHdl( LINK( this, ComboBox, ImplSelectionChangedHdl ) );
+ mpImplLB->Show();
+
+ if ( mpFloatWin )
+ mpFloatWin->SetImplListBox( mpImplLB );
+// else
+// mpImplLB->GetMainWindow()->AllowGrabFocus( TRUE );
+
+ ImplCalcEditHeight();
+
+ SetCompoundControl( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits ComboBox::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::ImplLoadRes( const ResId& rResId )
+{
+ Edit::ImplLoadRes( rResId );
+
+ USHORT nNumber = ReadShortRes();
+
+ if( nNumber )
+ {
+ for( USHORT i = 0; i < nNumber; i++ )
+ {
+ InsertEntry( ReadStringRes(), LISTBOX_APPEND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::EnableAutocomplete( BOOL bEnable, BOOL bMatchCase )
+{
+ mbMatchCase = bMatchCase;
+
+ if ( bEnable )
+ mpSubEdit->SetAutocompleteHdl( LINK( this, ComboBox, ImplAutocompleteHdl ) );
+ else
+ mpSubEdit->SetAutocompleteHdl( Link() );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ComboBox::IsAutocompleteEnabled() const
+{
+ return mpSubEdit->GetAutocompleteHdl().IsSet();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplClickBtnHdl, void*, EMPTYARG )
+{
+ mpSubEdit->GrabFocus();
+ if ( !mpImplLB->GetEntryList()->GetMRUCount() )
+ ImplUpdateFloatSelection();
+ else
+ mpImplLB->SelectEntry( 0 , TRUE );
+ mpBtn->SetPressed( TRUE );
+ mpFloatWin->StartFloat( TRUE );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplPopupModeEndHdl, void*, p )
+{
+ mpBtn->SetPressed( FALSE );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplAutocompleteHdl, Edit*, pEdit )
+{
+ Selection aSel = pEdit->GetSelection();
+ AutocompleteAction eAction = pEdit->GetAutocompleteAction();
+
+ // Wenn keine Selection vorhanden ist, wird bei Tab/Shift+Tab auch
+ // keine AutoCompletion durchgefuehrt, da man ansonsten nicht in
+ // das naechste Feld kommt und der Text wieder mit etwas AutoExpandiert
+ // wird, was man nicht haben moechte.
+ if ( aSel.Len() ||
+ ((eAction != AUTOCOMPLETE_TABFORWARD) && (eAction != AUTOCOMPLETE_TABBACKWARD)) )
+ {
+ XubString aFullText = pEdit->GetText();
+ XubString aStartText = aFullText.Copy( 0, (xub_StrLen)aSel.Max() );
+ USHORT nStart = mpImplLB->GetCurrentPos();
+
+ if ( nStart == LISTBOX_ENTRY_NOTFOUND )
+ nStart = 0;
+
+ BOOL bForward = TRUE;
+ if ( eAction == AUTOCOMPLETE_TABFORWARD )
+ nStart++;
+ else if ( eAction == AUTOCOMPLETE_TABBACKWARD )
+ {
+ bForward = FALSE;
+ nStart = nStart ? (nStart--) : mpImplLB->GetEntryList()->GetEntryCount()-1;
+ }
+ MatchMode eMatchMode = mbMatchCase ? MATCH_CASE : MATCH_BEST;
+ USHORT nPos = mpImplLB->GetEntryList()->FindEntry( aStartText, eMatchMode, aStartText.Len(), nStart, bForward );
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = mpImplLB->GetEntryList()->FindEntry( aStartText, eMatchMode, aStartText.Len(), bForward ? 0 : (mpImplLB->GetEntryList()->GetEntryCount()-1), bForward );
+
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ {
+ XubString aText = mpImplLB->GetEntryList()->GetEntryText( nPos );
+ Selection aSel( aText.Len(), aStartText.Len() );
+ pEdit->SetText( aText, aSel );
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplSelectHdl, void*, EMPTYARG )
+{
+ BOOL bPopup = IsInDropDown();
+ if ( bPopup && !mpImplLB->IsTravelSelect() &&
+ ( !IsMultiSelectionEnabled() || !mpImplLB->GetSelectModifier() ) )
+ {
+ mpFloatWin->EndPopupMode();
+ GrabFocus();
+ }
+
+ if ( mpImplLB->IsSelectionChanged() || bPopup )
+ {
+ XubString aText;
+ if ( IsMultiSelectionEnabled() )
+ {
+ aText = mpSubEdit->GetText();
+
+ // Alle Eintraege entfernen, zu denen es einen Entry gibt, der aber nicht selektiert ist.
+ xub_StrLen nIndex = 0;
+ while ( nIndex != STRING_NOTFOUND )
+ {
+ xub_StrLen nPrevIndex = nIndex;
+ XubString aToken = aText.GetToken( 0, mcMultiSep, nIndex );
+ xub_StrLen nTokenLen = aToken.Len();
+ aToken.EraseLeadingAndTrailingChars( ' ' );
+ USHORT nP = mpImplLB->GetEntryList()->FindEntry( aToken );
+ if ( (nP != LISTBOX_ENTRY_NOTFOUND) && (!mpImplLB->GetEntryList()->IsEntryPosSelected( nP )) )
+ {
+ aText.Erase( nPrevIndex, nTokenLen );
+ nIndex -= nTokenLen;
+ if ( (nPrevIndex < aText.Len()) && (aText.GetChar( nPrevIndex ) == mcMultiSep) )
+ {
+ aText.Erase( nPrevIndex, 1 );
+ nIndex--;
+ }
+ }
+ aText.EraseLeadingAndTrailingChars( ' ' );
+ }
+
+ // Fehlende Eintraege anhaengen...
+ Table aSelInText;
+ lcl_GetSelectedEntries( aSelInText, aText, mcMultiSep, mpImplLB->GetEntryList() );
+ USHORT nSelectedEntries = mpImplLB->GetEntryList()->GetSelectEntryCount();
+ for ( USHORT n = 0; n < nSelectedEntries; n++ )
+ {
+ USHORT nP = mpImplLB->GetEntryList()->GetSelectEntryPos( n );
+ if ( !aSelInText.IsKeyValid( ImplCreateKey( nP ) ) )
+ {
+ if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) != mcMultiSep) )
+ aText += mcMultiSep;
+ if ( aText.Len() )
+ aText += ' '; // etwas auflockern
+ aText += mpImplLB->GetEntryList()->GetEntryText( nP );
+ aText += mcMultiSep;
+ }
+ }
+ if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) == mcMultiSep) )
+ aText.Erase( aText.Len()-1, 1 );
+ }
+ else
+ {
+ aText = mpImplLB->GetEntryList()->GetSelectEntry( 0 );
+ }
+
+ mpSubEdit->SetText( aText );
+
+ Selection aNewSelection( 0, aText.Len() );
+ if ( IsMultiSelectionEnabled() )
+ aNewSelection.Min() = aText.Len();
+ mpSubEdit->SetSelection( aNewSelection );
+
+ mpSubEdit->SetModifyFlag();
+ mbSyntheticModify = TRUE;
+ Modify();
+ mbSyntheticModify = FALSE;
+ Select();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplCancelHdl, void*, EMPTYARG )
+{
+ if( IsInDropDown() )
+ mpFloatWin->EndPopupMode();
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplSelectionChangedHdl, void*, n )
+{
+ if ( !mpImplLB->IsTrackingSelect() )
+ {
+ USHORT nChanged = (USHORT)(ULONG)n;
+ if ( !mpSubEdit->IsReadOnly() && mpImplLB->GetEntryList()->IsEntryPosSelected( nChanged ) )
+ mpSubEdit->SetText( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplDoubleClickHdl, void*, EMPTYARG )
+{
+ DoubleClick();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::EnableAutoSize( BOOL bAuto )
+{
+ mbDDAutoSize = bAuto;
+ if ( mpFloatWin )
+ {
+ if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
+ mpFloatWin->SetDropDownLineCount( 5 );
+ else if ( !bAuto )
+ mpFloatWin->SetDropDownLineCount( 0 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetDropDownLineCount( USHORT nLines )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetDropDownLineCount( nLines );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetDropDownLineCount() const
+{
+ USHORT nLines = 0;
+ if ( mpFloatWin )
+ nLines = mpFloatWin->GetDropDownLineCount();
+ return nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
+ {
+ Size aPrefSz = mpFloatWin->GetPrefSize();
+ if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight > mnDDHeight ) )
+ aPrefSz.Height() = nHeight-mnDDHeight;
+ if ( nFlags & WINDOW_POSSIZE_WIDTH )
+ aPrefSz.Width() = nWidth;
+ mpFloatWin->SetPrefSize( aPrefSz );
+
+ if ( IsAutoSizeEnabled() )
+ nHeight = mnDDHeight;
+ }
+
+ Edit::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::Resize()
+{
+ Size aOutSz = GetOutputSizePixel();
+ if( IsDropDownBox() )
+ {
+ long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ nSBWidth = CalcZoom( nSBWidth );
+ mpSubEdit->SetSizePixel( Size( aOutSz.Width() - nSBWidth, aOutSz.Height() ) );
+ mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
+ }
+ else
+ {
+ mpSubEdit->SetSizePixel( Size( aOutSz.Width(), mnDDHeight ) );
+ mpImplLB->SetPosSizePixel( 0, mnDDHeight, aOutSz.Width(), aOutSz.Height() - mnDDHeight );
+ if ( GetText().Len() )
+ ImplUpdateFloatSelection();
+ }
+
+ // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten,
+ // weil KEY_PGUP/DOWN ausgewertet wird...
+ if ( mpFloatWin )
+ mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::StateChanged( StateChangedType nType )
+{
+ Edit::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_ENABLE ) || ( nType == STATE_CHANGE_READONLY ) )
+ {
+ mpImplLB->SetReadOnly( IsReadOnly() );
+ if ( mpBtn )
+ mpBtn->Enable( IsEnabled() && !IsReadOnly() );
+ }
+ else if ( nType == STATE_CHANGE_ENABLE )
+ {
+ mpSubEdit->Enable( IsEnabled() );
+ mpImplLB->Enable( IsEnabled() && !IsReadOnly() );
+ if ( mpBtn )
+ mpBtn->Enable( IsEnabled() && !IsReadOnly() );
+ Invalidate();
+ }
+ else if( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ mpImplLB->SetUpdateMode( IsUpdateMode() );
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ mpImplLB->SetZoom( GetZoom() );
+ mpSubEdit->SetZoom( GetZoom() );
+ ImplCalcEditHeight();
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ mpImplLB->SetControlFont( GetControlFont() );
+ mpSubEdit->SetControlFont( GetControlFont() );
+ ImplCalcEditHeight();
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ mpImplLB->SetControlForeground( GetControlForeground() );
+ mpSubEdit->SetControlForeground( GetControlForeground() );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ mpImplLB->SetControlBackground( GetControlBackground() );
+ mpSubEdit->SetControlBackground( GetControlBackground() );
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? TRUE : FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ if ( mpBtn )
+ {
+ mpBtn->SetSettings( GetSettings() );
+ ImplInitDropDownButton( mpBtn );
+ }
+ Resize();
+ mpImplLB->Resize(); // Wird nicht durch ComboBox::Resize() gerufen, wenn sich die ImplLB nicht aendert.
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ComboBox::PreNotify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+
+ if( ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) && ( rNEvt.GetWindow() == mpImplLB->GetMainWindow() ) )
+ {
+ mpSubEdit->GrabFocus();
+ }
+
+ return nDone ? nDone : Edit::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long ComboBox::Notify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpSubEdit )
+ && !IsReadOnly() )
+ {
+ KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
+ USHORT nKeyCode = aKeyEvt.GetKeyCode().GetCode();
+ switch( nKeyCode )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN:
+ {
+ ImplUpdateFloatSelection();
+ if( ( nKeyCode == KEY_DOWN ) && mpFloatWin && !mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ mpBtn->SetPressed( TRUE );
+ if ( mpImplLB->GetEntryList()->GetMRUCount() )
+ mpImplLB->SelectEntry( 0 , TRUE );
+ mpFloatWin->StartFloat( FALSE );
+ nDone = 1;
+ }
+ else if( ( nKeyCode == KEY_UP ) && mpFloatWin && mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ mpFloatWin->EndPopupMode();
+ nDone = 1;
+ }
+ else
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ break;
+
+ case KEY_RETURN:
+ {
+ if( ( rNEvt.GetWindow() == mpSubEdit ) && IsInDropDown() )
+ {
+ mpImplLB->ProcessKeyInput( aKeyEvt );
+ nDone = 1;
+ }
+ }
+ break;
+ }
+ }
+ else if ( (rNEvt.GetType() == EVENT_LOSEFOCUS) && mpFloatWin )
+ {
+ if( mpFloatWin->HasChildPathFocus() )
+ mpSubEdit->GrabFocus();
+ else if ( mpFloatWin->IsInPopupMode() && !HasChildPathFocus( TRUE ) )
+ mpFloatWin->EndPopupMode();
+ }
+ else if( (rNEvt.GetType() == EVENT_COMMAND) &&
+ (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
+ (rNEvt.GetWindow() == mpSubEdit) )
+ {
+ nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
+ }
+
+ return nDone ? nDone : Edit::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetText( const XubString& rStr )
+{
+ Edit::SetText( rStr );
+ ImplUpdateFloatSelection();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetText( const XubString& rStr, const Selection& rNewSelection )
+{
+ Edit::SetText( rStr, rNewSelection );
+ ImplUpdateFloatSelection();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::Modify()
+{
+ if ( !mbSyntheticModify )
+ ImplUpdateFloatSelection();
+
+ Edit::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::ImplUpdateFloatSelection()
+{
+ // Text in der ListBox in den sichtbaren Bereich bringen
+ mpImplLB->SetCallSelectionChangedHdl( FALSE );
+ if ( !IsMultiSelectionEnabled() )
+ {
+ XubString aSearchStr( mpSubEdit->GetText() );
+ USHORT nSelect = LISTBOX_ENTRY_NOTFOUND;
+ BOOL bSelect = TRUE;
+
+ if ( mpImplLB->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND )
+ {
+ XubString aCurrent = mpImplLB->GetEntryList()->GetEntryText( mpImplLB->GetCurrentPos() );
+ if ( aCurrent == aSearchStr )
+ nSelect = mpImplLB->GetCurrentPos();
+ }
+
+ if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpImplLB->GetEntryList()->FindEntry( aSearchStr, MATCH_CASE, STRING_LEN );
+ if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
+ {
+ nSelect = mpImplLB->GetEntryList()->FindEntry( aSearchStr, MATCH_BEST, aSearchStr.Len() );
+ bSelect = FALSE;
+ }
+
+ if( nSelect != LISTBOX_ENTRY_NOTFOUND )
+ {
+ if ( !mpImplLB->IsVisible( nSelect ) )
+ mpImplLB->SetTopEntry( nSelect );
+ mpImplLB->SelectEntry( nSelect, bSelect );
+ }
+ else
+ {
+ nSelect = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 );
+ if( nSelect != LISTBOX_ENTRY_NOTFOUND )
+ mpImplLB->SelectEntry( nSelect, FALSE );
+ mpImplLB->SetTopEntry( 0 );
+ mpImplLB->ResetCurrentPos();
+ }
+ }
+ else
+ {
+ Table aSelInText;
+ lcl_GetSelectedEntries( aSelInText, mpSubEdit->GetText(), mcMultiSep, mpImplLB->GetEntryList() );
+ for ( USHORT n = 0; n < mpImplLB->GetEntryList()->GetEntryCount(); n++ )
+ mpImplLB->SelectEntry( n, aSelInText.IsKeyValid( ImplCreateKey( n ) ) );
+ }
+ mpImplLB->SetCallSelectionChangedHdl( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::InsertEntry( const XubString& rStr, USHORT nPos )
+{
+ USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
+ nRealPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::InsertEntry( const XubString& rStr, const Image& rImage, USHORT nPos )
+{
+ USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
+ nRealPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::RemoveEntry( const XubString& rStr )
+{
+ RemoveEntry( GetEntryPos( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::RemoveEntry( USHORT nPos )
+{
+ mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::Clear()
+{
+ mpImplLB->Clear();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetEntryPos( const XubString& rStr ) const
+{
+ USHORT nPos = mpImplLB->GetEntryList()->FindEntry( rStr, MATCH_CASE, STRING_LEN, mpImplLB->GetEntryList()->GetMRUCount() );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetEntryPos( const void* pData ) const
+{
+ USHORT nPos = mpImplLB->GetEntryList()->FindEntry( pData );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+XubString ComboBox::GetEntry( USHORT nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetEntryCount() const
+{
+ return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ComboBox::IsTravelSelect() const
+{
+ return mpImplLB->IsTravelSelect();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ComboBox::IsInDropDown() const
+{
+ return mpFloatWin && mpFloatWin->IsInPopupMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::EnableMultiSelection( BOOL bMulti )
+{
+ mpImplLB->EnableMultiSelection( bMulti );
+ mpImplLB->SetMultiSelectionSimpleMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ComboBox::IsMultiSelectionEnabled() const
+{
+ return mpImplLB->IsMultiSelectionEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+long ComboBox::CalcWindowSizePixel( USHORT nLines ) const
+{
+ return mpImplLB->GetEntryHeight() * nLines;
+}
+
+// -----------------------------------------------------------------------
+
+Size ComboBox::CalcMinimumSize() const
+{
+ Size aSz;
+ if ( !IsDropDownBox() )
+ {
+ aSz = mpImplLB->CalcSize( mpImplLB->GetEntryList()->GetEntryCount() );
+ aSz.Height() += mnDDHeight;
+ }
+ else
+ {
+ aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
+ aSz.Width() = mpImplLB->GetMaxEntryWidth();
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ComboBox::CalcAdjustedSize( const Size& rPrefSize ) const
+{
+ Size aSz = rPrefSize;
+ long nLeft, nTop, nRight, nBottom;
+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
+ aSz.Height() -= nTop+nBottom;
+ if ( !IsDropDownBox() )
+ {
+ long nEntryHeight = CalcSize( 1, 1 ).Height();
+ long nLines = aSz.Height() / nEntryHeight;
+ if ( nLines < 1 )
+ nLines = 1;
+ aSz.Height() = nLines * nEntryHeight;
+ aSz.Height() += mnDDHeight;
+ }
+ else
+ {
+ aSz.Height() = mnDDHeight;
+ }
+ aSz.Height() += nTop+nBottom;
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ComboBox::CalcSize( USHORT nColumns, USHORT nLines ) const
+{
+ // ggf. werden ScrollBars eingeblendet
+ Size aMinSz = CalcMinimumSize();
+ Size aSz;
+
+ // Hoehe
+ if ( nLines )
+ {
+ if ( !IsDropDownBox() )
+ aSz.Height() = mpImplLB->CalcSize( nLines ).Height() + mnDDHeight;
+ else
+ aSz.Height() = mnDDHeight;
+ }
+ else
+ aSz.Height() = aMinSz.Height();
+
+ // Breite
+ if ( nColumns )
+ aSz.Width() = nColumns * GetTextWidth( UniString( 'X' ) );
+ else
+ aSz.Width() = aMinSz.Width();
+
+ if ( IsDropDownBox() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ if ( !IsDropDownBox() )
+ {
+ if ( aSz.Width() < aMinSz.Width() )
+ aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aSz.Height() < aMinSz.Height() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::GetMaxVisColumnsAndLines( USHORT& rnCols, USHORT& rnLines ) const
+{
+ long nCharWidth = GetTextWidth( UniString( 'x' ) );
+ if ( !IsDropDownBox() )
+ {
+ Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
+ rnCols = (USHORT)(aOutSz.Width()/nCharWidth);
+ rnLines = (USHORT)(aOutSz.Height()/mpImplLB->GetEntryHeight());
+ }
+ else
+ {
+ Size aOutSz = mpSubEdit->GetOutputSizePixel();
+ rnCols = (USHORT)(aOutSz.Width()/nCharWidth);
+ rnLines = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
+{
+ mpImplLB->GetMainWindow()->ImplInitSettings( TRUE, TRUE, TRUE );
+
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
+ OutDevType eOutDevType = pDev->GetOutDevType();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ pDev->SetTextFillColor();
+
+ // Border/Background
+ pDev->SetLineColor();
+ pDev->SetFillColor();
+ BOOL bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
+ BOOL bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
+ if ( bBorder || bBackground )
+ {
+ Rectangle aRect( aPos, aSize );
+ // aRect.Top() += nEditHeight;
+ if ( bBorder )
+ {
+ DecorationView aDecoView( pDev );
+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ if ( bBackground )
+ {
+ pDev->SetFillColor( GetControlBackground() );
+ pDev->DrawRect( aRect );
+ }
+ }
+
+ // Inhalt
+ if ( IsDropDownBox() )
+ {
+ mpSubEdit->Draw( pDev, aPos, aSize, nFlags );
+ // DD-Button ?
+ }
+ else
+ {
+ long nOnePixel = GetDrawPixel( pDev, 1 );
+ long nTextHeight = pDev->GetTextHeight();
+ long nEditHeight = nTextHeight + 6*nOnePixel;
+
+ mpSubEdit->Draw( pDev, aPos, Size( aSize.Width(), nEditHeight ), nFlags );
+
+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
+ {
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ }
+ else
+ {
+ if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ pDev->SetTextColor( rStyleSettings.GetDisableColor() );
+ }
+ else
+ {
+ pDev->SetTextColor( GetTextColor() );
+ }
+ }
+
+ Rectangle aClip( aPos, aSize );
+ pDev->IntersectClipRegion( aClip );
+ USHORT nLines = (USHORT) ( (aSize.Height()-nEditHeight) / nTextHeight );
+ if ( !nLines )
+ nLines = 1;
+ USHORT nTEntry = IsReallyVisible() ? mpImplLB->GetTopEntry() : 0;
+ for ( USHORT n = 0; n < nLines; n++ )
+ pDev->DrawText( Point( aPos.X() + 3*nOnePixel, aPos.Y() + n*nTextHeight + nEditHeight + nOnePixel ), mpImplLB->GetEntryList()->GetEntryText( n+nTEntry ) );
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ComboBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
+{
+ UserDraw( *pEvent );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetUserItemSize( const Size& rSz )
+{
+ mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
+}
+
+// -----------------------------------------------------------------------
+
+const Size& ComboBox::GetUserItemSize() const
+{
+ return mpImplLB->GetMainWindow()->GetUserItemSize();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::EnableUserDraw( BOOL bUserDraw )
+{
+ mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ComboBox::IsUserDrawEnabled() const
+{
+ return mpImplLB->GetMainWindow()->IsUserDrawEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+#if SUPD < 593
+void ComboBox::DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText )
+{
+ DBG_ASSERT( rEvt.GetDevice() == mpImplLB->GetMainWindow(), "DrawEntry?!" );
+ mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText );
+}
+#endif
+
+void ComboBox::DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos )
+{
+ DBG_ASSERT( rEvt.GetDevice() == mpImplLB->GetMainWindow(), "DrawEntry?!" );
+ mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetSeparatorPos( USHORT n )
+{
+ mpImplLB->SetSeparatorPos( n );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetSeparatorPos()
+{
+ mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetSeparatorPos() const
+{
+ return mpImplLB->GetSeparatorPos();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
+{
+ mpImplLB->SetMRUEntries( rEntries, cSep );
+}
+
+// -----------------------------------------------------------------------
+
+XubString ComboBox::GetMRUEntries( xub_Unicode cSep ) const
+{
+ return mpImplLB->GetMRUEntries( cSep );
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetMaxMRUCount( USHORT n )
+{
+ mpImplLB->SetMaxMRUCount( n );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ComboBox::GetMaxMRUCount() const
+{
+ return mpImplLB->GetMaxMRUCount();
+}
+
+// -----------------------------------------------------------------------
+
+void ComboBox::SetEntryData( USHORT nPos, void* pNewData )
+{
+ mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
+}
+
+// -----------------------------------------------------------------------
+
+void* ComboBox::GetEntryData( USHORT nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
new file mode 100644
index 000000000000..b325b75451bf
--- /dev/null
+++ b/vcl/source/control/ctrl.cxx
@@ -0,0 +1,155 @@
+/*************************************************************************
+ *
+ * $RCSfile: ctrl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CTRL_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_CTRL_HXX
+#include <ctrl.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void Control::ImplInitData()
+{
+ mbHasFocus = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Control::Control( WindowType nType ) :
+ Window( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Control::Control( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_CONTROL )
+{
+ ImplInitData();
+ Window::ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Control::Control( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_CONTROL )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_CONTROL );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle, NULL );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Control::GetFocus()
+{
+ Window::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Control::LoseFocus()
+{
+ Window::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+long Control::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ if ( !mbHasFocus )
+ {
+ mbHasFocus = TRUE;
+ maGetFocusHdl.Call( this );
+ }
+ }
+ else
+ {
+ if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ Window* pFocusWin = Application::GetFocusWindow();
+ if ( !pFocusWin || !ImplIsWindowOrChild( pFocusWin ) )
+ {
+ mbHasFocus = FALSE;
+ maLoseFocusHdl.Call( this );
+ }
+ }
+ }
+
+ return Window::Notify( rNEvt );
+}
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
new file mode 100644
index 000000000000..a93ef960b91b
--- /dev/null
+++ b/vcl/source/control/edit.cxx
@@ -0,0 +1,2200 @@
+/*************************************************************************
+ *
+ * $RCSfile: edit.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_EDIT_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_CLIP_HXX
+#include <clip.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+#ifndef _SV_TRANSFER_HXX
+#include <transfer.hxx>
+#endif
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _VCL_CMDEVT_H
+#include <cmdevt.h>
+#endif
+#ifndef _SV_SUBEDIT_HXX
+#include <subedit.hxx>
+#endif
+#ifndef _SV_EDIT_HXX
+#include <edit.hxx>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
+#include <com/sun/star/text/XBreakIterator.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_CHARACTERITERATORMODE_HPP_
+#include <com/sun/star/text/CharacterIteratorMode.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
+#include <com/sun/star/text/WordType.hpp>
+#endif
+
+#include <unohelp.hxx>
+
+
+#pragma hdrstop
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::rtl;
+
+// - Redo
+// - Bei Tracking-Cancel DefaultSelection wieder herstellen
+
+// =======================================================================
+
+static FncGetSpecialChars pImplFncGetSpecialChars = NULL;
+
+// =======================================================================
+
+#define EDIT_ALIGN_LEFT 1
+#define EDIT_ALIGN_CENTER 2
+#define EDIT_ALIGN_RIGHT 3
+
+#define EDIT_DEL_LEFT 1
+#define EDIT_DEL_RIGHT 2
+
+#define EDIT_DELMODE_SIMPLE 11
+#define EDIT_DELMODE_RESTOFWORD 12
+#define EDIT_DELMODE_RESTOFCONTENT 13
+
+// =======================================================================
+
+uno::Reference < text::XBreakIterator > ImplGetBreakIterator()
+{
+ static uno::Reference < text::XBreakIterator > xB;
+ if ( !xB.is() )
+ xB = vcl::unohelper::CreateBreakIterator();
+ return xB;
+}
+
+// =======================================================================
+
+struct DDInfo
+{
+ Cursor aCursor;
+ xub_StrLen nDropPos;
+ BOOL bStarterOfDD;
+ BOOL bDroppedInMe;
+ BOOL bVisCursor;
+
+ DDInfo()
+ {
+ aCursor.SetStyle( CURSOR_SHADOW );
+ nDropPos = 0;
+ bStarterOfDD = FALSE;
+ bDroppedInMe = FALSE;
+ bVisCursor = FALSE;
+ }
+};
+
+// =======================================================================
+
+struct Impl_IMEInfos
+{
+ USHORT* pAttribs;
+ xub_StrLen nPos;
+ xub_StrLen nLen;
+ BOOL bCursor;
+
+ Impl_IMEInfos( xub_StrLen nPos );
+ ~Impl_IMEInfos();
+
+ void CopyAttribs( const xub_StrLen* pA, xub_StrLen nL );
+ void DestroyAttribs();
+};
+
+// -----------------------------------------------------------------------
+
+Impl_IMEInfos::Impl_IMEInfos( xub_StrLen nP )
+{
+ nPos = nP;
+ nLen = 0;
+ bCursor = TRUE;
+ pAttribs = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Impl_IMEInfos::~Impl_IMEInfos()
+{
+ delete pAttribs;
+}
+
+// -----------------------------------------------------------------------
+
+void Impl_IMEInfos::CopyAttribs( const xub_StrLen* pA, xub_StrLen nL )
+{
+ nLen = nL;
+ delete pAttribs;
+ pAttribs = new USHORT[ nL ];
+ memcpy( pAttribs, pA, nL*sizeof(USHORT) );
+}
+
+// -----------------------------------------------------------------------
+
+void Impl_IMEInfos::DestroyAttribs()
+{
+ delete pAttribs;
+ pAttribs = NULL;
+}
+
+// =======================================================================
+
+Edit::Edit( WindowType nType ) :
+ Control( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Edit::Edit( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_EDIT )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Edit::Edit( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_EDIT )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_EDIT );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+Edit::~Edit()
+{
+ delete mpDDInfo;
+ Cursor* pCursor = GetCursor();
+ if ( pCursor )
+ {
+ SetCursor( NULL );
+ delete pCursor;
+ }
+
+ delete mpIMEInfos;
+
+ if ( mpUpdateDataTimer )
+ delete mpUpdateDataTimer;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplInitData()
+{
+ mpSubEdit = NULL;
+ mpUpdateDataTimer = NULL;
+ mnXOffset = 0;
+ mnAlign = EDIT_ALIGN_LEFT;
+ mnMaxTextLen = EDIT_NOLIMIT;
+ meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
+ mbModified = FALSE;
+ mbInternModified = FALSE;
+ mbReadOnly = FALSE;
+ mbInsertMode = TRUE;
+ mbClickedInSelection = FALSE;
+ mbActivePopup = FALSE;
+ mbIsSubEdit = FALSE;
+ mbInMBDown = FALSE;
+ mpDDInfo = NULL;
+ mpIMEInfos = NULL;
+ mcEchoChar = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ if ( !(nStyle & (WB_CENTER | WB_RIGHT)) )
+ nStyle |= WB_LEFT;
+
+ Control::ImplInit( pParent, nStyle, NULL );
+
+ mbReadOnly = (nStyle & WB_READONLY) != 0;
+
+ mnAlign = EDIT_ALIGN_LEFT;
+ if ( nStyle & WB_RIGHT )
+ mnAlign = EDIT_ALIGN_RIGHT;
+ else if ( nStyle & WB_CENTER )
+ mnAlign = EDIT_ALIGN_CENTER;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+ SetFillColor( rStyleSettings.GetFieldColor() );
+ SetCursor( new Cursor );
+
+ SetPointer( Pointer( POINTER_TEXT ) );
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits Edit::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Edit::IsCharInput( const KeyEvent& rKeyEvent )
+{
+ // In the future we must use new Unicode functions for this
+ xub_Unicode cCharCode = rKeyEvent.GetCharCode();
+ return ((cCharCode >= 32) && (cCharCode != 127) &&
+ !rKeyEvent.GetKeyCode().IsControlMod());
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplModified()
+{
+ mbModified = TRUE;
+ Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplInitSettings( BOOL bFont, BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetFieldFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bFont || bForeground )
+ {
+ Color aTextColor = rStyleSettings.GetFieldTextColor();
+ if ( IsControlForeground() )
+ aTextColor = GetControlForeground();
+ SetTextColor( aTextColor );
+ }
+
+ if ( bBackground )
+ {
+ if( IsControlBackground() )
+ {
+ SetBackground( GetControlBackground() );
+ SetFillColor( GetControlBackground() );
+ }
+ else
+ {
+ SetBackground( rStyleSettings.GetFieldColor() );
+ SetFillColor( rStyleSettings.GetFieldColor() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString Edit::ImplGetText() const
+{
+ if ( mcEchoChar || (GetStyle() & WB_PASSWORD) )
+ {
+ XubString aText;
+ xub_Unicode cEchoChar;
+ if ( mcEchoChar )
+ cEchoChar = mcEchoChar;
+ else
+ cEchoChar = '*';
+ aText.Fill( maText.Len(), cEchoChar );
+ return aText;
+ }
+ else
+ return maText;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplRepaint( xub_StrLen nStart, xub_StrLen nEnd )
+{
+ if ( !IsReallyVisible() )
+ return;
+
+ XubString aText = ImplGetText();
+ if ( nStart >= aText.Len() )
+ return;
+
+ if ( nEnd > aText.Len() )
+ nEnd = aText.Len();
+
+ Cursor* pCursor = GetCursor();
+ BOOL bVisCursor = pCursor ? pCursor->IsVisible() : FALSE;
+ if ( pCursor )
+ pCursor->Hide();
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if ( IsEnabled() )
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ else
+ SetTextColor( rStyleSettings.GetDisableColor() );
+
+ SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
+
+ // In der Hoehe zentrieren
+ long nH = GetOutputSize().Height();
+ long nTH = GetTextHeight();
+ Point aPos( mnXOffset, (nH-nTH)/2 );
+
+ BOOL bDrawSelection = maSelection.Len() && ( HasFocus() || ( GetStyle() & WB_NOHIDESELECTION ) || mbActivePopup );
+
+ if ( !bDrawSelection && !mpIMEInfos )
+ {
+ aPos.X() = GetTextWidth( aText, 0, nStart ) + mnXOffset;
+ DrawText( aPos, aText, nStart, nEnd - nStart );
+ }
+ else
+ {
+ Selection aTmpSel( maSelection );
+ aTmpSel.Justify();
+
+ xub_StrLen nIndex = nStart;
+ while ( nIndex < nEnd )
+ {
+ xub_StrLen nTmpEnd = nEnd;
+ USHORT nAttr = 0;
+ if ( mpIMEInfos && mpIMEInfos->pAttribs )
+ {
+ xub_StrLen nIMEEnd = mpIMEInfos->nPos+mpIMEInfos->nLen;
+ if ( (nIndex < mpIMEInfos->nPos) && (nTmpEnd > mpIMEInfos->nPos) )
+ {
+ nTmpEnd = mpIMEInfos->nPos;
+ }
+ else if ( (nIndex >= mpIMEInfos->nPos) && (nIndex < nIMEEnd) )
+ {
+ // Attributweise ausgeben...
+ nTmpEnd = nIndex + 1;
+ if ( (nIndex >= mpIMEInfos->nPos) && (nIndex < (mpIMEInfos->nPos+mpIMEInfos->nLen)) )
+ {
+ nAttr = mpIMEInfos->pAttribs[nIndex-mpIMEInfos->nPos];
+ xub_StrLen nMax = mpIMEInfos->nPos+mpIMEInfos->nLen;
+ while ( ( nTmpEnd < nMax ) && ( mpIMEInfos->pAttribs[ nTmpEnd - mpIMEInfos->nPos ] == nAttr ) )
+ nTmpEnd++;
+ }
+ }
+ }
+ else if ( bDrawSelection )
+ {
+ if ( ( nIndex < aTmpSel.Min() ) && ( nTmpEnd > aTmpSel.Min() ) )
+ nTmpEnd = (xub_StrLen)aTmpSel.Min();
+ else if ( ( nIndex >= aTmpSel.Min() ) && ( nIndex < aTmpSel.Max() ) && ( nTmpEnd > aTmpSel.Max() ) )
+ nTmpEnd = (xub_StrLen)aTmpSel.Max();
+ }
+
+ aPos.X() = GetTextWidth( aText, 0, nIndex ) + mnXOffset;
+ ImplInitSettings( mpIMEInfos ? TRUE : FALSE, TRUE, FALSE );
+ BOOL bSelected = bDrawSelection && ((xub_StrLen)aTmpSel.Min() <= nIndex ) && ((xub_StrLen)aTmpSel.Max() > nIndex );
+ if ( bSelected || ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT) )
+ {
+ SetTextColor( rStyleSettings.GetHighlightTextColor() );
+ SetTextFillColor( rStyleSettings.GetHighlightColor() );
+ }
+ else
+ {
+ SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
+ }
+
+ if ( nAttr )
+ {
+ Font aFont = GetFont();
+ if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
+ aFont.SetUnderline( UNDERLINE_SINGLE );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
+ aFont.SetUnderline( UNDERLINE_BOLD );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
+ aFont.SetUnderline( UNDERLINE_DOTTED );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
+ aFont.SetUnderline( UNDERLINE_DOTTED );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
+ {
+ aFont.SetUnderline( UNDERLINE_WAVE );
+ SetTextLineColor( Color( COL_LIGHTGRAY ) );
+ }
+ SetFont( aFont );
+
+ if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
+ SetTextColor( Color( COL_RED ) );
+ }
+ DrawText( aPos, aText, nIndex, nTmpEnd - nIndex );
+ nIndex = nTmpEnd;
+ }
+ }
+
+ if ( bVisCursor && ( !mpIMEInfos || mpIMEInfos->bCursor ) )
+ pCursor->Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplDelete( const Selection& rSelection, BYTE nDirection, BYTE nMode )
+{
+ XubString aText = ImplGetText();
+
+ // loeschen moeglich?
+ if ( !rSelection.Len() &&
+ (((rSelection.Min() == 0) && (nDirection == EDIT_DEL_LEFT)) ||
+ ((rSelection.Max() == aText.Len()) && (nDirection == EDIT_DEL_RIGHT))) )
+ return;
+
+ long nOldWidth = GetTextWidth( aText );
+ Selection aSelection( rSelection );
+ aSelection.Justify();
+
+ if ( !aSelection.Len() )
+ {
+ uno::Reference < text::XBreakIterator > xBI = ImplGetBreakIterator();
+ if ( nDirection == EDIT_DEL_LEFT )
+ {
+ if ( nMode == EDIT_DELMODE_RESTOFWORD )
+ {
+ text::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Min(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
+ if ( aBoundary.startPos == aSelection.Min() )
+ aBoundary = xBI->previousWord( maText, aSelection.Min(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ aSelection.Min() = aBoundary.startPos;
+ }
+ else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
+ {
+ aSelection.Min() = 0;
+ }
+ else
+ {
+ sal_Int32 nCount = 1;
+ aSelection.Min() = xBI->previousCharacters( maText, aSelection.Min(), GetSettings().GetLocale(), text::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
+ }
+ }
+ else
+ {
+ if ( nMode == EDIT_DELMODE_RESTOFWORD )
+ {
+ text::Boundary aBoundary = xBI->nextWord( maText, aSelection.Max(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ aSelection.Max() = aBoundary.startPos;
+ }
+ else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
+ {
+ aSelection.Max() = aText.Len();
+ }
+ else
+ {
+ sal_Int32 nCount = 1;
+ aSelection.Max() = xBI->nextCharacters( maText, aSelection.Max(), GetSettings().GetLocale(), text::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );;
+ }
+ }
+ }
+
+ maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
+ maSelection.Min() = aSelection.Min();
+ maSelection.Max() = aSelection.Min();
+ ImplAlignAndPaint( (xub_StrLen)aSelection.Min(), nOldWidth );
+ mbInternModified = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplInsertText( const XubString& rStr, const Selection* pNewSel )
+{
+ Selection aSelection( maSelection );
+ aSelection.Justify();
+
+ XubString aNewText( rStr );
+ aNewText.EraseAllChars( _LF );
+ aNewText.EraseAllChars( _CR );
+ aNewText.SearchAndReplaceAll( '\t', ' ' );
+
+ if ( (maText.Len() + aNewText.Len() - aSelection.Len()) > mnMaxTextLen )
+ return;
+
+ long nOldWidth = GetTextWidth( ImplGetText() );
+
+ if ( aSelection.Len() )
+ maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
+ else if ( !mbInsertMode && (aSelection.Max() < maText.Len()) )
+ maText.Erase( (xub_StrLen)aSelection.Max(), 1 );
+
+ if ( aNewText.Len() )
+ maText.Insert( aNewText, (xub_StrLen)aSelection.Min() );
+
+ if ( !pNewSel )
+ {
+ maSelection.Min() = aSelection.Min() + aNewText.Len();
+ maSelection.Max() = maSelection.Min();
+ }
+ else
+ {
+ maSelection = *pNewSel;
+ if ( maSelection.Min() > maText.Len() )
+ maSelection.Min() = maText.Len();
+ if ( maSelection.Max() > maText.Len() )
+ maSelection.Max() = maText.Len();
+ }
+
+ ImplAlignAndPaint( (xub_StrLen)aSelection.Min(), nOldWidth );
+ mbInternModified = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplSetText( const XubString& rText, const Selection* pNewSelection )
+{
+ // Der Text wird dadurch geloescht das der alte Text komplett 'selektiert'
+ // wird, dann InsertText, damit flackerfrei.
+ if ( (rText != maText) || (pNewSelection && (*pNewSelection != maSelection)) )
+ {
+ maSelection.Min() = 0;
+ maSelection.Max() = maText.Len();
+ if ( mnXOffset || HasPaintEvent() )
+ {
+ mnXOffset = 0;
+ maText = rText;
+
+ if ( pNewSelection )
+ ImplSetSelection( *pNewSelection, FALSE );
+
+ if ( mnXOffset && !pNewSelection )
+ maSelection.Max() = 0;
+
+ ImplAlign();
+ Invalidate();
+ }
+ else
+ ImplInsertText( rText, pNewSelection );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplClearBackground( long nXStart, long nXEnd )
+{
+ Point aTmpPoint;
+ Rectangle aRect( aTmpPoint, GetOutputSizePixel() );
+ aRect.Left() = nXStart;
+ aRect.Right() = nXEnd;
+
+ Cursor* pCursor = HasFocus() ? GetCursor() : NULL;
+
+ if ( pCursor )
+ pCursor->Hide();
+
+ Erase( aRect );
+
+ if ( pCursor )
+ pCursor->Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplShowCursor( BOOL bOnlyIfVisible )
+{
+ if ( !IsUpdateMode() || ( bOnlyIfVisible && !IsReallyVisible() ) )
+ return;
+
+ Cursor* pCursor = GetCursor();
+ XubString aText = ImplGetText();
+ long nTextWidth = GetTextWidth( aText, 0, (xub_StrLen)maSelection.Max() );
+
+ long nCursorWidth = 0;
+ if ( !mbInsertMode && !maSelection.Len() && (maSelection.Max() < aText.Len()) )
+ nCursorWidth = GetTextWidth( aText, (xub_StrLen)maSelection.Max(), 1 );
+ long nCursorPosX = nTextWidth + mnXOffset;
+
+ // Cursor muss im sichtbaren Bereich landen:
+ Size aOutSize = GetOutputSizePixel();
+ if ( (nCursorPosX < 0) || (nCursorPosX >= aOutSize.Width()) )
+ {
+ long nOldXOffset = mnXOffset;
+
+ if ( nCursorPosX < 0 )
+ {
+ mnXOffset = - nTextWidth;
+ long nMaxX = 0;
+ mnXOffset += aOutSize.Width() / 5;
+ if ( mnXOffset > nMaxX )
+ mnXOffset = nMaxX;
+ }
+ else
+ {
+ mnXOffset = aOutSize.Width() - nTextWidth;
+ // Etwas mehr?
+ if ( aOutSize.Width() < nTextWidth )
+ {
+ long nMaxNegX = aOutSize.Width() - GetTextWidth( aText );
+ mnXOffset -= aOutSize.Width() / 5;
+ if ( mnXOffset < nMaxNegX ) // beides negativ...
+ mnXOffset = nMaxNegX;
+ }
+ }
+
+ nCursorPosX = nTextWidth + mnXOffset;
+ if ( nCursorPosX == aOutSize.Width() ) // dann nicht sichtbar...
+ nCursorPosX--;
+
+ if ( mnXOffset != nOldXOffset )
+ ImplRepaint();
+ }
+
+ long nTextHeight = GetTextHeight();
+ long nCursorPosY = (aOutSize.Height()-nTextHeight) / 2;
+ pCursor->SetPos( Point( nCursorPosX, nCursorPosY ) );
+ pCursor->SetSize( Size( nCursorWidth, nTextHeight ) );
+ pCursor->Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplAlign()
+{
+ if ( mnAlign == EDIT_ALIGN_LEFT )
+ return;
+
+ long nTextWidth = GetTextWidth( ImplGetText() );
+ long nOutWidth = GetOutputSizePixel().Width();
+
+ if ( mnAlign == EDIT_ALIGN_RIGHT )
+ {
+ long nMinXOffset = nOutWidth - nTextWidth;
+ if ( mnXOffset < nMinXOffset )
+ mnXOffset = nMinXOffset;
+ }
+ else if( mnAlign == EDIT_ALIGN_CENTER )
+ {
+ // Mit Abfrage schoener, wenn gescrollt, dann aber nicht zentriert im gescrollten Zustand...
+// if ( nTextWidth < nOutWidth )
+ mnXOffset = (nOutWidth - nTextWidth) / 2;
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplAlignAndPaint( xub_StrLen nChangedFrom, long nOldWidth )
+{
+ long nNewWidth = GetTextWidth( ImplGetText() );
+ xub_StrLen nPaintStart = nChangedFrom;
+
+ ImplAlign();
+ if ( mnAlign == EDIT_ALIGN_LEFT )
+ {
+ if ( nOldWidth > nNewWidth )
+ ImplClearBackground( nNewWidth+mnXOffset, nOldWidth+mnXOffset );
+ }
+ else if ( mnAlign == EDIT_ALIGN_RIGHT )
+ {
+ nPaintStart = 0;
+ ImplClearBackground( GetOutputSizePixel().Width()-Max( nOldWidth, nNewWidth )-1, mnXOffset+1 );
+ }
+ else // EDIT_ALIGN_CENTER
+ {
+ nPaintStart = 0;
+ ImplClearBackground( 0, mnXOffset + 1 );
+ ImplClearBackground( mnXOffset+nNewWidth-1, GetOutputSizePixel().Width() );
+ }
+
+ ImplRepaint( nPaintStart, STRING_LEN );
+ ImplShowCursor();
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen Edit::ImplGetCharPos( const Point& rWindowPos )
+{
+ return GetTextBreak( ImplGetText(), rWindowPos.X() - mnXOffset );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplSetCursorPos( xub_StrLen nChar, BOOL bSelect )
+{
+ Selection aSelection( maSelection );
+ aSelection.Max() = nChar;
+ if ( !bSelect )
+ aSelection.Min() = aSelection.Max();
+ ImplSetSelection( aSelection );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ xub_StrLen nTextLength = ReadShortRes();
+ if ( nTextLength )
+ SetMaxTextLen( nTextLength );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( mpSubEdit )
+ {
+ Control::MouseButtonDown( rMEvt );
+ return;
+ }
+
+ xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() );
+ Selection aSelection( maSelection );
+ aSelection.Justify();
+
+ if ( rMEvt.GetClicks() < 4 )
+ {
+ mbClickedInSelection = FALSE;
+ if ( rMEvt.GetClicks() == 3 )
+ ImplSetSelection( Selection( 0, 0xFFFF ) );
+ else if ( rMEvt.GetClicks() == 2 )
+ {
+ uno::Reference < text::XBreakIterator > xBI = ImplGetBreakIterator();
+ text::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Max(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
+ ImplSetSelection( Selection( aBoundary.startPos, aBoundary.endPos ) );
+ }
+ else if ( !rMEvt.IsShift() && HasFocus() && aSelection.IsInside( nChar ) )
+ mbClickedInSelection = TRUE;
+ else if ( rMEvt.IsLeft() )
+ ImplSetCursorPos( nChar, rMEvt.IsShift() );
+
+ if ( !mbClickedInSelection && rMEvt.IsLeft() && ( rMEvt.GetClicks() == 1 ) )
+ StartTracking( STARTTRACK_SCROLLREPEAT );
+ }
+
+ mbInMBDown = TRUE; // Dann im GetFocus nicht alles selektieren
+ GrabFocus();
+ mbInMBDown = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if ( mbClickedInSelection && rMEvt.IsLeft() )
+ {
+ xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() );
+ ImplSetCursorPos( nChar, FALSE );
+ mbClickedInSelection = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mbClickedInSelection )
+ {
+ xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
+ ImplSetCursorPos( nChar, FALSE );
+ mbClickedInSelection = FALSE;
+ }
+ }
+ else
+ {
+ if( !mbClickedInSelection )
+ {
+ xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
+ ImplSetCursorPos( nChar, TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Edit::ImplHandleKeyEvent( const KeyEvent& rKEvt )
+{
+ BOOL bDone = FALSE;
+ USHORT nCode = rKEvt.GetKeyCode().GetCode();
+ KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
+
+ mbInternModified = FALSE;
+
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ switch ( eFunc )
+ {
+ case KEYFUNC_CUT:
+ {
+ if ( !mbReadOnly && maSelection.Len() && !(GetStyle() & WB_PASSWORD) )
+ {
+ Cut();
+ ImplModified();
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEYFUNC_COPY:
+ {
+ if ( !(GetStyle() & WB_PASSWORD) )
+ {
+ Copy();
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEYFUNC_PASTE:
+ {
+ if ( !mbReadOnly )
+ {
+ Paste();
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEYFUNC_UNDO:
+ {
+ if ( !mbReadOnly )
+ {
+ Undo();
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ default: // wird dann evtl. unten bearbeitet.
+ eFunc = KEYFUNC_DONTKNOW;
+ }
+ }
+
+ if ( eFunc == KEYFUNC_DONTKNOW )
+ {
+ switch ( nCode )
+ {
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ case KEY_HOME:
+ case KEY_END:
+ {
+ if ( !rKEvt.GetKeyCode().IsMod2() )
+ {
+ uno::Reference < text::XBreakIterator > xBI = ImplGetBreakIterator();
+
+ Selection aSel( maSelection );
+ BOOL bWord = rKEvt.GetKeyCode().IsMod1();
+ // Range wird in ImplSetSelection geprueft...
+ if ( ( nCode == KEY_LEFT ) && aSel.Max() )
+ {
+ if ( bWord )
+ {
+ text::Boundary aBoundary = xBI->getWordBoundary( maText, aSel.Max(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
+ if ( aBoundary.startPos == aSel.Max() )
+ aBoundary = xBI->previousWord( maText, aSel.Max(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ aSel.Max() = aBoundary.startPos;
+ }
+ else
+ {
+ sal_Int32 nCount = 1;
+ aSel.Max() = xBI->previousCharacters( maText, aSel.Max(), GetSettings().GetLocale(), text::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
+ }
+ }
+ else if ( ( nCode == KEY_RIGHT ) && ( aSel.Max() < maText.Len() ) )
+ {
+ if ( bWord )
+ {
+ text::Boundary aBoundary = xBI->nextWord( maText, aSel.Max(), GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ aSel.Max() = aBoundary.startPos;
+ }
+ else
+ {
+ sal_Int32 nCount = 1;
+ aSel.Max() = xBI->nextCharacters( maText, aSel.Max(), GetSettings().GetLocale(), text::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
+ }
+ }
+ else if ( nCode == KEY_HOME )
+ aSel.Max() = 0;
+ else if ( nCode == KEY_END )
+ aSel.Max() = 0xFFFF;
+
+ if ( !rKEvt.GetKeyCode().IsShift() )
+ aSel.Min() = aSel.Max();
+
+ ImplSetSelection( aSel );
+
+ if ( (nCode == KEY_END) && maAutocompleteHdl.IsSet() && !rKEvt.GetKeyCode().GetModifier() )
+ {
+ if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) )
+ {
+ meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
+ maAutocompleteHdl.Call( this );
+ }
+ }
+
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_BACKSPACE:
+ case KEY_DELETE:
+ {
+ if ( !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
+ {
+ BYTE nDel = (nCode == KEY_DELETE) ? EDIT_DEL_RIGHT : EDIT_DEL_LEFT;
+ BYTE nMode = rKEvt.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD : EDIT_DELMODE_SIMPLE;
+ if ( (nMode == EDIT_DELMODE_RESTOFWORD) && rKEvt.GetKeyCode().IsShift() )
+ nMode = EDIT_DELMODE_RESTOFCONTENT;
+ xub_StrLen nOldLen = maText.Len();
+ ImplDelete( maSelection, nDel, nMode );
+ if ( maText.Len() != nOldLen )
+ ImplModified();
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_INSERT:
+ {
+ if ( !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
+ {
+ SetInsertMode( !mbInsertMode );
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_TAB:
+ {
+ if ( !mbReadOnly && maAutocompleteHdl.IsSet() &&
+ maSelection.Min() && (maSelection.Min() == maText.Len()) &&
+ !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
+ {
+ // Kein Autocomplete wenn alles Selektiert oder Edit leer, weil dann
+ // keine vernuenftige Tab-Steuerung!
+ if ( rKEvt.GetKeyCode().IsShift() )
+ meAutocompleteAction = AUTOCOMPLETE_TABBACKWARD;
+ else
+ meAutocompleteAction = AUTOCOMPLETE_TABFORWARD;
+
+ maAutocompleteHdl.Call( this );
+
+ // Wurde nichts veraendert, dann TAB fuer DialogControl
+ if ( GetSelection().Len() )
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ default:
+ {
+ if ( IsCharInput( rKEvt ) )
+ {
+ bDone = TRUE; // Auch bei ReadOnly die Zeichen schlucken.
+ if ( !mbReadOnly )
+ {
+ ImplInsertText( rKEvt.GetCharCode() );
+ if ( maAutocompleteHdl.IsSet() )
+ {
+ if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) )
+ {
+ meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
+ maAutocompleteHdl.Call( this );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( !bDone && rKEvt.GetKeyCode().IsMod1() )
+ {
+ if ( nCode == KEY_A )
+ {
+ ImplSetSelection( Selection( 0, maText.Len() ) );
+ bDone = TRUE;
+ }
+ else if ( rKEvt.GetKeyCode().IsShift() && (nCode == KEY_S) )
+ {
+ if ( pImplFncGetSpecialChars )
+ {
+ Selection aSaveSel = GetSelection(); // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile...
+ XubString aChars = pImplFncGetSpecialChars( this, GetFont() );
+ SetSelection( aSaveSel );
+ if ( aChars.Len() )
+ {
+ ImplInsertText( aChars );
+ ImplModified();
+ }
+ bDone = TRUE;
+ }
+ }
+ }
+
+ if ( mbInternModified )
+ ImplModified();
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( mpSubEdit || !ImplHandleKeyEvent( rKEvt ) )
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Paint( const Rectangle& )
+{
+ if ( !mpSubEdit )
+ ImplRepaint();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Resize()
+{
+ if ( !mpSubEdit && IsReallyVisible() )
+ {
+ // Wegen vertikaler Zentrierung...
+ mnXOffset = 0;
+ ImplAlign();
+ Invalidate();
+ ImplShowCursor();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
+{
+ ImplInitSettings( TRUE, TRUE, TRUE );
+
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = GetDrawPixelFont( pDev );
+ OutDevType eOutDevType = pDev->GetOutDevType();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ pDev->SetTextFillColor();
+
+ // Border/Background
+ pDev->SetLineColor();
+ pDev->SetFillColor();
+ BOOL bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
+ BOOL bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
+ if ( bBorder || bBackground )
+ {
+ Rectangle aRect( aPos, aSize );
+ if ( bBorder )
+ {
+ DecorationView aDecoView( pDev );
+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ if ( bBackground )
+ {
+ pDev->SetFillColor( GetControlBackground() );
+ pDev->DrawRect( aRect );
+ }
+ }
+
+ // Inhalt
+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ {
+ if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ pDev->SetTextColor( rStyleSettings.GetDisableColor() );
+ }
+ else
+ {
+ pDev->SetTextColor( GetTextColor() );
+ }
+ }
+
+ XubString aText = ImplGetText();
+ long nTextHeight = pDev->GetTextHeight();
+ long nTextWidth = pDev->GetTextWidth( aText );
+ long nOnePixel = GetDrawPixel( pDev, 1 );
+ long nOffX = 3*nOnePixel;
+ long nOffY = (aSize.Height() - nTextHeight) / 2;
+
+ if ( GetStyle() & WB_CENTER )
+ {
+ aPos.X() += (aSize.Width() - nTextWidth) / 2;
+ nOffX = 0;
+ }
+ else if ( GetStyle() & WB_RIGHT )
+ {
+ aPos.X() += aSize.Width() - nTextWidth;
+ nOffX = -nOffX;
+ }
+
+ // Clipping?
+ if ( (nOffY < 0) ||
+ ((nOffY+nTextHeight) > aSize.Height()) ||
+ ((nOffX+nTextWidth) > aSize.Width()) )
+ {
+ Rectangle aClip( aPos, aSize );
+ if ( nTextHeight > aSize.Height() )
+ aClip.Bottom() += nTextHeight-aSize.Height()+1; // Damit HP-Drucker nicht 'weg-optimieren'
+ pDev->IntersectClipRegion( aClip );
+ }
+
+ pDev->DrawText( Point( aPos.X() + nOffX, aPos.Y() + nOffY ), aText );
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::GetFocus()
+{
+ if ( mpSubEdit )
+ mpSubEdit->ImplGrabFocus( GetGetFocusFlags() );
+ else if ( !mbActivePopup )
+ {
+ maUndoText = maText;
+
+ ULONG nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
+ if ( !( GetStyle() & (WB_NOHIDESELECTION|WB_READONLY) )
+ && ( GetGetFocusFlags() & (GETFOCUS_INIT|GETFOCUS_TAB|GETFOCUS_CURSOR|GETFOCUS_MNEMONIC) ) )
+ {
+ if ( nSelOptions & SELECTION_OPTION_SHOWFIRST )
+ {
+ maSelection.Min() = maText.Len();
+ maSelection.Max() = 0;
+ }
+ else
+ {
+ maSelection.Min() = 0;
+ maSelection.Max() = maText.Len();
+ }
+ }
+
+ ImplShowCursor();
+
+ if ( maSelection.Len() )
+ {
+ // Selektion malen
+ if ( !HasPaintEvent() )
+ ImplRepaint();
+ else
+ Invalidate();
+ }
+
+ SetInputContext( InputContext( GetFont(), TRUE ) );
+ }
+
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::LoseFocus()
+{
+ if ( !mpSubEdit )
+ {
+ if ( !mbActivePopup && !( GetStyle() & WB_NOHIDESELECTION ) && maSelection.Len() )
+ ImplRepaint(); // Selektion malen
+ }
+
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Command( const CommandEvent& rCEvt )
+{
+ if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) &&
+ !IsTracking() && maSelection.Len() &&
+ !(GetStyle() & WB_PASSWORD) &&
+ (!mpDDInfo || mpDDInfo->bStarterOfDD == FALSE) ) // Kein Mehrfach D&D
+ {
+ Selection aSel( maSelection );
+ aSel.Justify();
+
+ // Nur wenn Maus in der Selektion...
+ xub_StrLen nChar = ImplGetCharPos( rCEvt.GetMousePosPixel() );
+ if ( (nChar >= aSel.Min()) && (nChar < aSel.Max()) )
+ {
+ if ( !mpDDInfo )
+ mpDDInfo = new DDInfo;
+
+ mpDDInfo->bStarterOfDD = TRUE;
+
+ Region* pDDRegion = NULL;
+ Cursor* pCursor = GetCursor();
+ if ( pCursor )
+ pCursor->Hide();
+
+ SotDataObjectRef xData = new StringDataObject( GetSelected() );
+ if ( IsTracking() )
+ EndTracking(); // Vor D&D Tracking ausschalten
+ DropAction aAction = DragManager::ExecuteDrag( xData, DRAG_ALL );
+
+ if ( aAction == DROP_MOVE )
+ {
+ if ( mpDDInfo->bDroppedInMe )
+ {
+ if ( aSel.Max() > mpDDInfo->nDropPos )
+ {
+ long nLen = aSel.Len();
+ aSel.Min() += nLen;
+ aSel.Max() += nLen;
+ }
+ }
+ ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
+ ImplModified();
+ }
+
+ ImplHideDDCursor();
+ delete mpDDInfo;
+ mpDDInfo = 0;
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
+ {
+ PopupMenu* pPopup = Edit::CreatePopupMenu();
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_HIDEDISABLED )
+ pPopup->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES );
+
+ if ( !maSelection.Len() )
+ {
+ pPopup->EnableItem( SV_MENU_EDIT_CUT, FALSE );
+ pPopup->EnableItem( SV_MENU_EDIT_COPY, FALSE );
+ pPopup->EnableItem( SV_MENU_EDIT_DELETE, FALSE );
+ }
+
+ if ( IsReadOnly() )
+ {
+ pPopup->EnableItem( SV_MENU_EDIT_CUT, FALSE );
+ pPopup->EnableItem( SV_MENU_EDIT_PASTE, FALSE );
+ pPopup->EnableItem( SV_MENU_EDIT_DELETE, FALSE );
+ pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, FALSE );
+ }
+ else
+ {
+ // Paste nur, wenn Text im Clipboard
+ if ( !VclClipboard::HasFormat( FORMAT_STRING ) )
+ pPopup->EnableItem( SV_MENU_EDIT_PASTE, FALSE );
+ }
+
+ if ( maUndoText == maText )
+ pPopup->EnableItem( SV_MENU_EDIT_UNDO, FALSE );
+ if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
+ pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, FALSE );
+ if ( !pImplFncGetSpecialChars )
+ {
+ USHORT nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
+ pPopup->RemoveItem( nPos );
+ pPopup->RemoveItem( nPos-1 );
+ }
+
+ mbActivePopup = TRUE;
+ Selection aSaveSel = GetSelection(); // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile...
+ Point aPos = rCEvt.GetMousePosPixel();
+ if ( !rCEvt.IsMouseEvent() )
+ {
+ // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!!
+ Size aSize = GetOutputSizePixel();
+ aPos = Point( aSize.Width()/2, aSize.Height()/2 );
+ }
+ USHORT n = pPopup->Execute( this, aPos );
+ Edit::DeletePopupMenu( pPopup );
+ SetSelection( aSaveSel );
+ switch ( n )
+ {
+ case SV_MENU_EDIT_UNDO:
+ Undo();
+ ImplModified();
+ break;
+ case SV_MENU_EDIT_CUT:
+ Cut();
+ ImplModified();
+ break;
+ case SV_MENU_EDIT_COPY:
+ Copy();
+ break;
+ case SV_MENU_EDIT_PASTE:
+ Paste();
+ ImplModified();
+ break;
+ case SV_MENU_EDIT_DELETE:
+ DeleteSelected();
+ ImplModified();
+ break;
+ case SV_MENU_EDIT_SELECTALL:
+ ImplSetSelection( Selection( 0, maText.Len() ) );
+ break;
+ case SV_MENU_EDIT_INSERTSYMBOL:
+ {
+ XubString aChars = pImplFncGetSpecialChars( this, GetFont() );
+ SetSelection( aSaveSel );
+ if ( aChars.Len() )
+ {
+ ImplInsertText( aChars );
+ ImplModified();
+ }
+ }
+ break;
+ }
+ mbActivePopup = FALSE;
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_VOICE )
+ {
+ const CommandVoiceData* pData = rCEvt.GetVoiceData();
+ if ( pData->GetType() == VOICECOMMANDTYPE_DICTATION )
+ {
+ switch ( pData->GetCommand() )
+ {
+ case DICTATIONCOMMAND_UNKNOWN:
+ {
+ ReplaceSelected( pData->GetText() );
+ }
+ break;
+ case DICTATIONCOMMAND_LEFT:
+ {
+ ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_RIGHT:
+ {
+ ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_RIGHT, KEY_MOD1 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_UNDO:
+ {
+ Undo();
+ }
+ break;
+ case DICTATIONCOMMAND_DEL:
+ {
+ ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1|KEY_SHIFT ) ) );
+ DeleteSelected();
+ }
+ break;
+ }
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
+ {
+ DeleteSelected();
+ delete mpIMEInfos;
+ mpIMEInfos = new Impl_IMEInfos( (xub_StrLen)maSelection.Max() );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
+ {
+ delete mpIMEInfos;
+ mpIMEInfos = NULL;
+ // Font wieder ohne Attribute einstellen, wird jetzt im Repaint nicht
+ // mehr neu initialisiert
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
+ {
+ const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
+
+ maText.Erase( mpIMEInfos->nPos, mpIMEInfos->nLen );
+ maText.Insert( pData->GetText(), mpIMEInfos->nPos );
+
+ if ( pData->GetTextAttr() )
+ {
+ mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
+ mpIMEInfos->bCursor = pData->IsCursorVisible();
+ }
+ else
+ {
+ mpIMEInfos->DestroyAttribs();
+ }
+
+ Invalidate(); // Erstmal einfach zum Testen
+ xub_StrLen nCursorPos = mpIMEInfos->nPos + pData->GetCursorPos();
+ SetSelection( Selection( nCursorPos, nCursorPos ) );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUTPOS )
+ {
+ XubString aText( maText, mpIMEInfos->nPos, mpIMEInfos->nLen );
+ if ( aText.Len() )
+ {
+ const CommandExtTextInputPosData* pData = rCEvt.GetExtTextInputPosData();
+
+ xub_StrLen nChars = aText.Len();
+ Rectangle* pRects = new Rectangle[nChars];
+ long* pDXArr = new long[nChars];
+ long nTextHeight = GetTextHeight();
+ long nTop = (GetOutputSize().Height()-nTextHeight)/2;
+ long nBottom = nTop + nTextHeight;
+ long nX = mnXOffset;
+
+ GetTextArray( aText, pDXArr );
+ if ( mpIMEInfos->nPos )
+ nX += GetTextWidth( XubString( maText, 0, mpIMEInfos->nPos ) );
+
+ for ( xub_StrLen n = 0; n < nChars; n++ )
+ {
+ pRects[n].Top() = nTop;
+ pRects[n].Bottom() = nBottom;
+ pRects[n].Left() = nX + (n ? pDXArr[ n-1 ] : 0);
+ pRects[n].Right() = nX + pDXArr[n];
+ }
+ SetExtTextInputPos( 0, nChars, pRects );
+ delete pRects;
+ delete pDXArr;
+ }
+ else
+ SetExtTextInputPos( 0, 0, NULL );
+ }
+ else
+ Control::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( !mpSubEdit )
+ {
+ mnXOffset = 0; // Falls vorher GrabFocus, als Groesse noch falsch.
+ ImplAlign();
+ if ( !mpSubEdit )
+ ImplShowCursor( FALSE );
+ }
+ }
+ else if ( nType == STATE_CHANGE_ENABLE )
+ {
+ if ( !mpSubEdit )
+ {
+ // Es aendert sich nur die Textfarbe...
+ ImplRepaint( 0, 0xFFFF );
+ }
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ WinBits nStyle = ImplInitStyle( GetStyle() );
+ SetStyle( nStyle );
+
+ USHORT nOldAlign = mnAlign;
+ mnAlign = EDIT_ALIGN_LEFT;
+ if ( nStyle & WB_RIGHT )
+ mnAlign = EDIT_ALIGN_RIGHT;
+ else if ( nStyle & WB_CENTER )
+ mnAlign = EDIT_ALIGN_CENTER;
+ if ( maText.Len() && ( mnAlign != nOldAlign ) )
+ {
+ ImplAlign();
+ Invalidate();
+ }
+
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ if ( !mpSubEdit )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ ImplShowCursor( TRUE );
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ if ( !mpSubEdit )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ ImplShowCursor();
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ if ( !mpSubEdit )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ if ( !mpSubEdit )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+ }
+
+ Control::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ if ( !mpSubEdit )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ ImplShowCursor( TRUE );
+ Invalidate();
+ }
+ }
+
+ Control::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplShowDDCursor()
+{
+ if ( !mpDDInfo->bVisCursor )
+ {
+ long nTextWidth = GetTextWidth( maText, 0, mpDDInfo->nDropPos );
+ long nTextHeight = GetTextHeight();
+ Rectangle aCursorRect( Point( nTextWidth + mnXOffset, (GetOutputSize().Height()-nTextHeight)/2 ), Size( 2, nTextHeight ) );
+ mpDDInfo->aCursor.SetWindow( this );
+ mpDDInfo->aCursor.SetPos( aCursorRect.TopLeft() );
+ mpDDInfo->aCursor.SetSize( aCursorRect.GetSize() );
+ mpDDInfo->aCursor.Show();
+ mpDDInfo->bVisCursor = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplHideDDCursor()
+{
+ if ( mpDDInfo && mpDDInfo->bVisCursor )
+ {
+ mpDDInfo->aCursor.Hide();
+ mpDDInfo->bVisCursor = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Edit::QueryDrop( DropEvent& rDEvt )
+{
+ if ( rDEvt.IsLeaveWindow() )
+ {
+ ImplHideDDCursor();
+ return FALSE;
+ }
+
+ // Daten holen
+ SotDataObjectRef xDataObj = ((DropEvent&)rDEvt).GetData();
+ BOOL bString = xDataObj.Is() && NULL != xDataObj->GetTypeList().Get( FORMAT_STRING );
+
+ BOOL bDrop = FALSE;
+ if ( !mbReadOnly && bString &&
+ ( ( rDEvt.GetAction() == DROP_COPY ) || ( rDEvt.GetAction() == DROP_MOVE ) || ( rDEvt.GetAction() == DROP_LINK ) ) )
+ {
+ if ( !mpDDInfo )
+ mpDDInfo = new DDInfo;
+
+ Point aMousePos( rDEvt.GetPosPixel() );
+
+ xub_StrLen nPrevDropPos = mpDDInfo->nDropPos;
+ mpDDInfo->nDropPos = ImplGetCharPos( aMousePos );
+
+ Size aOutSize = GetOutputSizePixel();
+ if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
+ {
+ // Scrollen ?
+ }
+
+ Selection aSel( maSelection );
+ aSel.Justify();
+
+ // Nicht in Selektion droppen:
+ if ( aSel.IsInside( mpDDInfo->nDropPos ) )
+ {
+ ImplHideDDCursor();
+ return FALSE;
+ }
+
+ // Alten Cursor wegzeichnen...
+ if ( !mpDDInfo->bVisCursor || ( nPrevDropPos != mpDDInfo->nDropPos ) )
+ {
+ ImplHideDDCursor();
+ ImplShowDDCursor();
+ }
+ bDrop = TRUE;
+ }
+
+ return bDrop;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Edit::Drop( const DropEvent& rDEvt )
+{
+ mbInternModified = FALSE;
+
+ BOOL bDone = TRUE;
+ if ( !mbReadOnly && mpDDInfo )
+ {
+ ImplHideDDCursor();
+ Point aMousePos( rDEvt.GetPosPixel() );
+
+ Selection aSel( maSelection );
+ aSel.Justify();
+
+ if ( aSel.Len() && !mpDDInfo->bStarterOfDD )
+ ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
+
+ mpDDInfo->bDroppedInMe = TRUE;
+
+ aSel.Min() = mpDDInfo->nDropPos;
+ aSel.Max() = mpDDInfo->nDropPos;
+ ImplSetSelection( aSel );
+
+ // Daten holen
+ SotDataObjectRef xDataObj = ((DropEvent&)rDEvt).GetData();
+ SvData aData( FORMAT_STRING );
+ if( xDataObj->GetData( &aData ) )
+ {
+ XubString aStr;
+ aData.GetData( aStr );
+ ImplInsertText( aStr );
+ }
+
+ if ( !mpDDInfo->bStarterOfDD )
+ {
+ delete mpDDInfo;
+ mpDDInfo = 0;
+ }
+ }
+
+ if ( mbInternModified )
+ ImplModified();
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Modify()
+{
+ if ( mbIsSubEdit )
+ {
+ ((Edit*)GetParent())->Modify();
+ }
+ else
+ {
+ if ( mpUpdateDataTimer )
+ mpUpdateDataTimer->Start();
+
+ maModifyHdl.Call( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::UpdateData()
+{
+ maUpdateDataHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Edit, ImplUpdateDataHdl, Timer*, EMPTYARG )
+{
+ UpdateData();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::EnableUpdateData( ULONG nTimeout )
+{
+ if ( !nTimeout )
+ DisableUpdateData();
+ else
+ {
+ if ( !mpUpdateDataTimer )
+ {
+ mpUpdateDataTimer = new Timer;
+ mpUpdateDataTimer->SetTimeoutHdl( LINK( this, Edit, ImplUpdateDataHdl ) );
+ }
+
+ mpUpdateDataTimer->SetTimeout( nTimeout );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetEchoChar( xub_Unicode c )
+{
+ mcEchoChar = c;
+ if ( mpSubEdit )
+ mpSubEdit->SetEchoChar( c );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetReadOnly( BOOL bReadOnly )
+{
+ if ( mbReadOnly != bReadOnly )
+ {
+ mbReadOnly = bReadOnly;
+ if ( mpSubEdit )
+ mpSubEdit->SetReadOnly( bReadOnly );
+
+ StateChanged( STATE_CHANGE_READONLY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetAutocompleteHdl( const Link& rHdl )
+{
+ maAutocompleteHdl = rHdl;
+ if ( mpSubEdit )
+ mpSubEdit->SetAutocompleteHdl( rHdl );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetInsertMode( BOOL bInsert )
+{
+ if ( bInsert != mbInsertMode )
+ {
+ mbInsertMode = bInsert;
+ if ( mpSubEdit )
+ mpSubEdit->SetInsertMode( bInsert );
+ else
+ ImplShowCursor();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Edit::IsInsertMode() const
+{
+ if ( mpSubEdit )
+ return mpSubEdit->IsInsertMode();
+ else
+ return mbInsertMode;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetMaxTextLen( xub_StrLen nMaxLen )
+{
+ mnMaxTextLen = nMaxLen ? nMaxLen : EDIT_NOLIMIT;
+
+ if ( mpSubEdit )
+ mpSubEdit->SetMaxTextLen( nMaxLen );
+ else
+ {
+ if ( maText.Len() > nMaxLen )
+ ImplDelete( Selection( nMaxLen, maText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetSelection( const Selection& rSelection )
+{
+ // Wenn von aussen z.B. im MouseButtonDown die Selektion geaendert wird,
+ // soll nicht gleich ein Tracking() zuschlagen und die Selektion aendern.
+ if ( IsTracking() )
+ EndTracking();
+ else if ( mpSubEdit && mpSubEdit->IsTracking() )
+ mpSubEdit->EndTracking();
+
+ ImplSetSelection( rSelection );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ImplSetSelection( const Selection& rSelection, BOOL bPaint )
+{
+ if ( mpSubEdit )
+ mpSubEdit->ImplSetSelection( rSelection );
+ else
+ {
+ if ( rSelection != maSelection )
+ {
+ Selection aOld( maSelection );
+ Selection aNew( rSelection );
+
+ if ( aNew.Min() > maText.Len() )
+ aNew.Min() = maText.Len();
+ if ( aNew.Max() > maText.Len() )
+ aNew.Max() = maText.Len();
+ if ( aNew.Min() < 0 )
+ aNew.Min() = 0;
+ if ( aNew.Max() < 0 )
+ aNew.Max() = 0;
+
+ if ( aNew != maSelection )
+ {
+ maSelection = aNew;
+
+ if ( bPaint && ( aOld.Len() || aNew.Len() ) )
+ {
+ aOld.Justify();
+ aNew.Justify();
+ xub_StrLen nStart = (xub_StrLen)Min( aOld.Min(), aNew.Min() );
+ xub_StrLen nEnd = (xub_StrLen)Max( aOld.Max(), aNew.Max() );
+ ImplRepaint( nStart, nEnd );
+ }
+ ImplShowCursor();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const Selection& Edit::GetSelection() const
+{
+ if ( mpSubEdit )
+ return mpSubEdit->GetSelection();
+ else
+ return maSelection;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ReplaceSelected( const XubString& rStr )
+{
+ if ( mpSubEdit )
+ mpSubEdit->ReplaceSelected( rStr );
+ else
+ ImplInsertText( rStr );
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::DeleteSelected()
+{
+ if ( mpSubEdit )
+ mpSubEdit->DeleteSelected();
+ else
+ {
+ if ( maSelection.Len() )
+ ImplDelete( maSelection, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString Edit::GetSelected() const
+{
+ if ( mpSubEdit )
+ return mpSubEdit->GetSelected();
+ else
+ {
+ Selection aSelection( maSelection );
+ aSelection.Justify();
+ return maText.Copy( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Cut()
+{
+ if ( !(GetStyle() & WB_PASSWORD ) )
+ {
+ Copy();
+ ReplaceSelected( ImplGetSVEmptyStr() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Copy()
+{
+ if ( !(GetStyle() & WB_PASSWORD ) )
+ {
+ SotDataObjectRef xData = new StringDataObject( GetSelected() );
+ VclClipboard::Copy( xData );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Paste()
+{
+ // Daten holen
+ SotDataObjectRef xDataObj = VclClipboard::Paste();
+ SvData aData( FORMAT_STRING );
+ if( xDataObj.Is() && xDataObj->GetData( &aData ) )
+ {
+ XubString aStr;
+ aData.GetData( aStr );
+ ReplaceSelected( aStr );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::Undo()
+{
+ if ( mpSubEdit )
+ mpSubEdit->Undo();
+ else
+ {
+ XubString aText( maText );
+ ImplDelete( Selection( 0, aText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
+ ImplInsertText( maUndoText );
+ ImplSetSelection( Selection( 0, maUndoText.Len() ) );
+ maUndoText = aText;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetText( const XubString& rStr )
+{
+ if ( mpSubEdit )
+ mpSubEdit->SetText( rStr ); // Nicht direkt ImplSetText, falls SetText ueberladen
+ else
+ {
+ Selection aNewSel( 0, 0 ); // Damit nicht gescrollt wird
+ ImplSetText( rStr, &aNewSel );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetText( const XubString& rStr, const Selection& rSelection )
+{
+ if ( mpSubEdit )
+ mpSubEdit->SetText( rStr, rSelection );
+ else
+ ImplSetText( rStr, &rSelection );
+}
+
+// -----------------------------------------------------------------------
+
+XubString Edit::GetText() const
+{
+ if ( mpSubEdit )
+ return mpSubEdit->GetText();
+ else
+ return maText;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetModifyFlag()
+{
+ if ( mpSubEdit )
+ mpSubEdit->mbModified = TRUE;
+ else
+ mbModified = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::ClearModifyFlag()
+{
+ if ( mpSubEdit )
+ mpSubEdit->mbModified = FALSE;
+ else
+ mbModified = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetSubEdit( Edit* pEdit )
+{
+ mpSubEdit = pEdit;
+ if ( mpSubEdit )
+ {
+ SetPointer( POINTER_ARROW ); // Nur das SubEdit hat den BEAM...
+ mpSubEdit->mbIsSubEdit = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Edit::CalcMinimumSize() const
+{
+ Size aSz( GetTextWidth( GetText() ), GetTextHeight() );
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size Edit::CalcSize( xub_StrLen nChars ) const
+{
+ // Breite fuer n Zeichen, unabhaengig vom Inhalt.
+ // Funktioniert nur bei FixedFont richtig, sonst Mittelwert.
+ Size aSz( GetTextWidth( XubString( 'x' ) ), GetTextHeight() );
+ aSz.Width() *= nChars;
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen Edit::GetMaxVisChars() const
+{
+ const Window* pW = mpSubEdit ? mpSubEdit : this;
+ long nOutWidth = pW->GetOutputSizePixel().Width();
+ long nCharWidth = GetTextWidth( XubString( 'x' ) );
+ return nCharWidth ? (xub_StrLen)(nOutWidth/nCharWidth) : 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn )
+{
+ pImplFncGetSpecialChars = fn;
+}
+
+// -----------------------------------------------------------------------
+
+FncGetSpecialChars Edit::GetGetSpecialCharsFunction()
+{
+ return pImplFncGetSpecialChars;
+}
+
+// -----------------------------------------------------------------------
+
+PopupMenu* Edit::CreatePopupMenu()
+{
+ PopupMenu* pPopup = new PopupMenu( ResId( SV_RESID_MENU_EDIT, ImplGetResMgr() ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_UNDO, KeyCode( KEYFUNC_UNDO ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_CUT, KeyCode( KEYFUNC_CUT ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_COPY, KeyCode( KEYFUNC_COPY ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_PASTE, KeyCode( KEYFUNC_PASTE ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_DELETE, KeyCode( KEYFUNC_DELETE ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_SELECTALL, KeyCode( KEY_A, FALSE, TRUE, FALSE ) );
+ pPopup->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL, KeyCode( KEY_S, TRUE, TRUE, FALSE ) );
+ return pPopup;
+}
+
+// -----------------------------------------------------------------------
+
+void Edit::DeletePopupMenu( PopupMenu* pMenu )
+{
+ delete pMenu;
+}
+
+ImplSubEdit::ImplSubEdit( Edit* pParent, WinBits nStyle ) :
+ Edit( pParent, nStyle )
+{
+ pParent->SetSubEdit( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSubEdit::Modify()
+{
+ GetParent()->Modify();
+}
diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx
new file mode 100644
index 000000000000..42a30ffd1b5f
--- /dev/null
+++ b/vcl/source/control/field.cxx
@@ -0,0 +1,2330 @@
+/*************************************************************************
+ *
+ * $RCSfile: field.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_BIGINT
+#define _SV_FIELD_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _BIGINT_HXX
+#include <tools/bigint.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#include <field.hxx>
+#include <event.hxx>
+#include <svapp.hxx>
+#include <svdata.hxx>
+
+#pragma hdrstop
+
+// -----------------------------------------------------------------------
+
+#define FORMAT_NUMERIC 1
+#define FORMAT_METRIC 2
+#define FORMAT_CURRENCY 3
+
+// -----------------------------------------------------------------------
+
+static long ImplPower10( USHORT n )
+{
+ USHORT i;
+ long nValue = 1;
+
+ for ( i=0; i < n; i++ )
+ nValue *= 10;
+
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
+ BOOL bStrictFormat,
+ const International& rInter )
+{
+ if ( !bStrictFormat )
+ return FALSE;
+ else
+ {
+ xub_Unicode cChar = rKEvt.GetCharCode();
+ USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
+
+ if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
+ (nGroup == KEYGROUP_MISC) ||
+ ((cChar >= '0') && (cChar <= '9')) ||
+ (rInter.IsNumThousandSep() && (cChar == rInter.GetNumThousandSep())) ||
+ (cChar == rInter.GetNumDecimalSep()) ||
+ (cChar == '-') )
+ return FALSE;
+ else
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplNumericGetValue( const XubString& rStr, double& rValue,
+ USHORT nDecDigits, const International& rInter,
+ BOOL bCurrency = FALSE )
+{
+ XubString aStr = rStr;
+ XubString aStr1;
+ XubString aStr2;
+ BOOL bNegative = FALSE;
+ xub_StrLen nDecPos;
+ xub_StrLen i;
+
+ // Reaktion auf leeren String
+ if ( !rStr.Len() )
+ return FALSE;
+
+ // Fuehrende und nachfolgende Leerzeichen entfernen
+ aStr.EraseLeadingAndTrailingChars( ' ' );
+
+ // Position des Dezimalpunktes suchen
+ nDecPos = aStr.Search( rInter.GetNumDecimalSep() );
+ if ( nDecPos != STRING_NOTFOUND )
+ {
+ aStr1 = aStr.Copy( 0, nDecPos );
+ aStr2 = aStr.Copy( nDecPos+1 );
+ }
+ else
+ aStr1 = aStr;
+
+ // Negativ ?
+ if ( bCurrency )
+ {
+ if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') )
+ bNegative = TRUE;
+ if ( !bNegative )
+ {
+ for ( i=0; i < aStr.Len(); i++ )
+ {
+ if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
+ break;
+ else if ( aStr.GetChar( i ) == '-' )
+ {
+ bNegative = TRUE;
+ break;
+ }
+ }
+ }
+ if ( !bNegative && bCurrency && aStr.Len() )
+ {
+ USHORT nFormat = rInter.GetCurrNegativeFormat();
+ if ( (nFormat == 3) || (nFormat == 6) ||
+ (nFormat == 7) || (nFormat == 10) )
+ {
+ for ( i = (xub_StrLen)(aStr.Len()-1); i > 0; i++ )
+ {
+ if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
+ break;
+ else if ( aStr.GetChar( i ) == '-' )
+ {
+ bNegative = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( aStr1.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ }
+
+ // Alle unerwuenschten Zeichen rauswerfen
+ for ( i=0; i < aStr1.Len(); )
+ {
+ if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') )
+ i++;
+ else
+ aStr1.Erase( i, 1 );
+ }
+ for ( i=0; i < aStr2.Len(); )
+ {
+ if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') )
+ i++;
+ else
+ aStr2.Erase( i, 1 );
+ }
+
+ if ( !aStr1.Len() && !aStr2.Len() )
+ return FALSE;
+
+ if ( !aStr1.Len() )
+ aStr1.Insert( '0' );
+ if ( bNegative )
+ aStr1.Insert( '-', 0 );
+
+ // Nachkommateil zurechtstutzen und dabei runden
+ BOOL bRound = FALSE;
+ if ( aStr2.Len() > nDecDigits )
+ {
+ if ( aStr2.GetChar( nDecDigits ) >= '5' )
+ bRound = TRUE;
+ aStr2.Erase( nDecDigits );
+ }
+ if ( aStr2.Len() < nDecDigits )
+ aStr2.Expand( nDecDigits, '0' );
+
+ aStr = aStr1;
+ aStr += aStr2;
+
+ // Bereichsueberpruefung
+ double nValue = aStr.ToDouble();
+ if ( bRound )
+ {
+ if ( !bNegative )
+ nValue++;
+ else
+ nValue--;
+ }
+
+ rValue = nValue;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+FormatterBase::FormatterBase( Edit* pField )
+{
+ mpField = pField;
+ mpInternational = NULL;
+ mbReformat = FALSE;
+ mbStrictFormat = FALSE;
+ mbEmptyFieldValue = FALSE;
+ mbEmptyFieldValueEnabled = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+FormatterBase::~FormatterBase()
+{
+ delete mpInternational;
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::Reformat()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::ReformatAll()
+{
+ Reformat();
+};
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::SetStrictFormat( BOOL bStrict )
+{
+ if ( bStrict != mbStrictFormat )
+ {
+ mbStrictFormat = bStrict;
+ if ( mbStrictFormat )
+ ReformatAll();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::SetInternational( const International& rInternational )
+{
+ delete mpInternational;
+ mpInternational = new International( rInternational );
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+const International& FormatterBase::GetInternational() const
+{
+ if ( !mpInternational )
+ {
+ if ( mpField )
+ return mpField->GetSettings().GetInternational();
+ else
+ return Application::GetSettings().GetInternational();
+ }
+
+ return *mpInternational;
+}
+
+// -----------------------------------------------------------------------
+
+const AllSettings& FormatterBase::GetFieldSettings() const
+{
+ if ( mpField )
+ return mpField->GetSettings();
+ else
+ return Application::GetSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::SetFieldText( const XubString& rText, BOOL bKeepSelection )
+{
+ if ( mpField )
+ {
+ Selection aNewSelection( 0xFFFF, 0xFFFF );
+ if ( bKeepSelection )
+ aNewSelection = mpField->GetSelection();
+
+ ImplSetText( rText, &aNewSelection );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::ImplSetText( const XubString& rText, Selection* pNewSelection )
+{
+ if ( mpField )
+ {
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden,
+ // !!! warum SetText() intern bei gleichem Text nicht ImplSetSelection
+ // !!! aufruft, sondern etwas anders macht, denn sehr haeufig kommt
+ // !!! hier der gleiche Text an.
+
+ // ggf. bleibt der Text gleich, aber die Selektion wird geaendert...
+ BOOL bTextChanged = (mpField->GetText() != rText);
+
+ if ( pNewSelection )
+ mpField->SetText( rText, *pNewSelection );
+ else
+ {
+ Selection aSel = mpField->GetSelection();
+ aSel.Min() = aSel.Max();
+ mpField->SetText( rText, aSel );
+ }
+
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden,
+ // !!! warum hier der Modify-Handler gerufen wird !!!
+
+ // !!! MT-8.7.99: Erstmal auskommentiert, koentest recht haben,
+ // !!! Modify wird zu oft gerufen.
+// if ( MustBeReformatted() && bTextChanged )
+// mpField->Edit::Modify(); // Nur damit Modify-Hdl gerufen wird.
+
+ MarkToBeReformatted( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FormatterBase::SetEmptyFieldValue()
+{
+ if ( mpField )
+ mpField->SetText( ImplGetSVEmptyStr() );
+ mbEmptyFieldValue = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FormatterBase::IsEmptyFieldValue() const
+{
+ return (!mpField || !mpField->GetText().Len());
+}
+
+// -----------------------------------------------------------------------
+
+BOOL NumericFormatter::ImplNumericReformat( const XubString& rStr, double& rValue,
+ XubString& rOutStr )
+{
+ if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), GetInternational() ) )
+ return TRUE;
+ else
+ {
+ double nTempVal = rValue;
+ if ( nTempVal > mnMax )
+ nTempVal = mnMax;
+ else if ( nTempVal < mnMin )
+ nTempVal = mnMin;
+
+ if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
+ {
+ mnCorrectedValue = (long)nTempVal;
+ if ( !GetErrorHdl().Call( this ) )
+ {
+ mnCorrectedValue = 0;
+ return FALSE;
+ }
+ else
+ mnCorrectedValue = 0;
+ }
+
+ rOutStr = CreateFieldText( (long)nTempVal );
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::ImplInit()
+{
+ mnFieldValue = 0;
+ mnLastValue = 0;
+ mnMin = 0;
+ mnMax = 0x7FFFFFFF;
+ mnCorrectedValue = 0;
+ mnType = FORMAT_NUMERIC;
+
+ // Fuer Felder...
+ mnSpinSize = 1;
+ mnFirst = mnMin;
+ mnLast = mnMax;
+
+ SetDecimalDigits( 0 );
+}
+
+// -----------------------------------------------------------------------
+
+NumericFormatter::NumericFormatter()
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::ImplLoadRes( const ResId& rResId )
+{
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask;
+
+ nMask = pMgr->ReadShort();
+
+ if ( NUMERICFORMATTER_MIN & nMask )
+ mnMin = pMgr->ReadLong();
+
+ if ( NUMERICFORMATTER_MAX & nMask )
+ mnMax = pMgr->ReadLong();
+
+ if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
+ SetStrictFormat( (BOOL)pMgr->ReadShort() );
+
+ if ( NUMERICFORMATTER_I12 & nMask )
+ {
+ SetInternational( International( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+ if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
+ SetDecimalDigits( pMgr->ReadShort() );
+
+ if ( NUMERICFORMATTER_VALUE & nMask )
+ {
+ mnFieldValue = pMgr->ReadLong();
+ if ( mnFieldValue > mnMax )
+ mnFieldValue = mnMax;
+ else if ( mnFieldValue < mnMin )
+ mnFieldValue = mnMin;
+ mnLastValue = mnFieldValue;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+NumericFormatter::~NumericFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::SetMin( long nNewMin )
+{
+ mnMin = nNewMin;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::SetMax( long nNewMax )
+{
+ mnMax = nNewMax;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::SetDecimalDigits( USHORT nDigits )
+{
+ International aInter( GetInternational() );
+ aInter.SetCurrDigits( nDigits );
+ SetInternational( aInter );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT NumericFormatter::GetDecimalDigits() const
+{
+ return GetInternational().GetCurrDigits();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::SetValue( long nNewValue )
+{
+ SetUserValue( nNewValue );
+ mnFieldValue = mnLastValue;
+ ImplGetEmptyFieldValue() = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString NumericFormatter::CreateFieldText( long nValue ) const
+{
+ return GetInternational().GetNum( nValue, GetDecimalDigits() );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::ImplSetUserValue( long nNewValue, Selection* pNewSelection )
+{
+ if ( nNewValue > mnMax )
+ nNewValue = mnMax;
+ else if ( nNewValue < mnMin )
+ nNewValue = mnMin;
+ mnLastValue = nNewValue;
+
+ if ( GetField() )
+ ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::SetUserValue( long nNewValue )
+{
+ ImplSetUserValue( nNewValue );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericFormatter::GetValue() const
+{
+ if ( !GetField() )
+ return 0;
+
+ double nTempValue;
+
+ if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
+ GetDecimalDigits(), GetInternational() ) )
+ {
+ if ( nTempValue > mnMax )
+ nTempValue = mnMax;
+ else if ( nTempValue < mnMin )
+ nTempValue = mnMin;
+ return (long)nTempValue;
+ }
+ else
+ return mnLastValue;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL NumericFormatter::IsValueModified() const
+{
+ if ( ImplGetEmptyFieldValue() )
+ return !IsEmptyFieldValue();
+ else if ( GetValue() != mnFieldValue )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Fraction NumericFormatter::ConvertToFraction( long nValue )
+{
+ return Fraction( nValue, ImplPower10( GetDecimalDigits() ) );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericFormatter::ConvertToLong( const Fraction& rValue )
+{
+ Fraction aFract = rValue;
+ aFract *= Fraction( ImplPower10( GetDecimalDigits() ) );
+ return (long)aFract;
+}
+
+// -----------------------------------------------------------------------
+
+long NumericFormatter::Normalize( long nValue ) const
+{
+ return (nValue * ImplPower10( GetDecimalDigits() ) );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericFormatter::Denormalize( long nValue ) const
+{
+ long nFactor = ImplPower10( GetDecimalDigits() );
+ if( nValue < 0 )
+ return ((nValue-(nFactor/2)) / nFactor );
+ else
+ return ((nValue+(nFactor/2)) / nFactor );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
+ return;
+
+ XubString aStr;
+ double nTemp = mnLastValue;
+ BOOL bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr );
+ mnLastValue = (long)nTemp;
+ if ( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ ImplSetText( aStr );
+ else
+ SetValue( mnLastValue );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::FieldUp()
+{
+ long nValue = GetValue();
+ nValue += mnSpinSize;
+ if ( nValue > mnMax )
+ nValue = mnMax;
+
+ ImplNewFieldValue( nValue );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::FieldDown()
+{
+ long nValue = GetValue();
+ nValue -= mnSpinSize;
+ if ( nValue < mnMin )
+ nValue = mnMin;
+
+ ImplNewFieldValue( nValue );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::FieldFirst()
+{
+ ImplNewFieldValue( mnFirst );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::FieldLast()
+{
+ ImplNewFieldValue( mnLast );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericFormatter::ImplNewFieldValue( long nNewValue )
+{
+ if ( GetField() )
+ {
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden,
+ // !!! warum nicht bei ImplSetUserValue() geprueft wird, ob
+ // !!! sich der Wert aendert. Denn auch hier muesste dieses
+ // !!! gemacht werden, da ansonsten der Modify-Aufruf
+ // !!! nicht gemacht werden duerfte. Jedenfalls sollten die
+ // !!! Wege von ImplNewFieldValue, ImplSetUserValue und
+ // !!! ImplSetText ueberprueft und klarer gestalltet (mit Kommentar)
+ // !!! werden, damit wir mal wissen, was dort ablaeuft!!!
+
+ Selection aSelection = GetField()->GetSelection();
+ aSelection.Justify();
+ XubString aText = GetField()->GetText();
+ // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
+ if ( (xub_StrLen)aSelection.Max() == aText.Len() )
+ {
+ if ( !aSelection.Len() )
+ aSelection.Min() = SELECTION_MAX;
+ aSelection.Max() = SELECTION_MAX;
+ }
+
+ long nOldLastValue = mnLastValue;
+ ImplSetUserValue( nNewValue, &aSelection );
+ mnLastValue = nOldLastValue;
+
+ // Modify am Edit wird nur bei KeyInput gesetzt...
+ if ( GetField()->GetText() != aText )
+ {
+ GetField()->SetModifyFlag();
+ GetField()->Modify();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+NumericField::NumericField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+NumericField::NumericField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_NUMERICFIELD )
+{
+ rResId.SetRT( RSC_NUMERICFIELD );
+ WinBits nStyle = ImplInitRes( rResId ) ;
+ SpinField::ImplInit( pParent, nStyle );
+ SetField( this );
+ ImplLoadRes( rResId );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( NUMERICFIELD_FIRST & nMask )
+ mnFirst = ReadLongRes();
+
+ if ( NUMERICFIELD_LAST & nMask )
+ mnLast = ReadLongRes();
+
+ if ( NUMERICFIELD_SPINSIZE & nMask )
+ mnSpinSize = ReadLongRes();
+}
+
+// -----------------------------------------------------------------------
+
+NumericField::~NumericField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long NumericField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SpinField::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::Up()
+{
+ FieldUp();
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::Down()
+{
+ FieldDown();
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::First()
+{
+ FieldFirst();
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericField::Last()
+{
+ FieldLast();
+ SpinField::Last();
+}
+
+// -----------------------------------------------------------------------
+
+NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+NumericBox::NumericBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_NUMERICBOX )
+{
+ rResId.SetRT( RSC_NUMERICBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ComboBox::ImplInit( pParent, nStyle );
+ SetField( this );
+ ComboBox::ImplLoadRes( rResId );
+ NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+NumericBox::~NumericBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long NumericBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void NumericBox::ReformatAll()
+{
+ double nValue;
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplNumericReformat( GetEntry( i ), nValue, aStr );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ NumericFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericBox::InsertValue( long nValue, USHORT nPos )
+{
+ ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void NumericBox::RemoveValue( long nValue )
+{
+ ComboBox::RemoveEntry( CreateFieldText( nValue ) );
+}
+
+// -----------------------------------------------------------------------
+
+long NumericBox::GetValue( USHORT nPos ) const
+{
+ double nValue = 0;
+ ImplNumericGetValue( ComboBox::GetEntry( nPos ), nValue,
+ GetDecimalDigits(), GetInternational() );
+ return (long)nValue;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT NumericBox::GetValuePos( long nValue ) const
+{
+ return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
+ BOOL, const International& rInter )
+{
+ // Es gibt hier kein sinnvolles StrictFormat, also alle
+ // Zeichen erlauben
+ return ImplNumericProcessKeyInput( pEdit, rKEvt, FALSE, rInter );
+}
+
+// -----------------------------------------------------------------------
+
+static XubString ImplMetricGetUnitText( const XubString& rStr )
+{
+ // Einheitentext holen
+ XubString aStr;
+ for ( short i = rStr.Len()-1; i >= 0; i-- )
+ {
+ xub_Unicode c = rStr.GetChar( i );
+ if ( ((c >= 'A') && (c <= 'Z')) ||
+ ((c >= 'a') && (c <= 'z')) ||
+ (c == '\'') || (c == '\"') || (c == '%' ) )
+ aStr.Insert( c, 0 );
+ else
+ {
+ if ( aStr.Len() )
+ break;
+ }
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+static FieldUnit ImplMetricGetUnit( const XubString& rStr )
+{
+ XubString aStr = ImplMetricGetUnitText( rStr );
+ aStr.ToLowerAscii();
+
+ if ( aStr.EqualsAscii( "mm" ) ) // Milimeter
+ return FUNIT_MM;
+ else if ( aStr.EqualsAscii( "cm" ) ) // Centimeter
+ return FUNIT_CM;
+ else if ( aStr.EqualsAscii( "m" ) ) // Meter
+ return FUNIT_M;
+ else if ( aStr.EqualsAscii( "km" ) ) // Km
+ return FUNIT_KM;
+ else if ( aStr.EqualsAscii( "twip" ) ) // Twips
+ return FUNIT_TWIP;
+ else if ( aStr.EqualsAscii( "twips" ) ) // Twips
+ return FUNIT_TWIP;
+ else if ( aStr.EqualsAscii( "pt" ) ) // Point
+ return FUNIT_POINT;
+ else if ( aStr.EqualsAscii( "pi" ) ) // Pica
+ return FUNIT_PICA;
+ else if ( aStr.EqualsAscii( "\"" ) ) // Inch
+ return FUNIT_INCH;
+ else if ( aStr.EqualsAscii( "in" ) ) // Inch
+ return FUNIT_INCH;
+ else if ( aStr.EqualsAscii( "inch" ) ) // Inch
+ return FUNIT_INCH;
+ else if ( aStr.EqualsAscii( "'" ) ) // Foot
+ return FUNIT_FOOT;
+ else if ( aStr.EqualsAscii( "ft" ) ) // Foot
+ return FUNIT_FOOT;
+ else if ( aStr.EqualsAscii( "foot" ) ) // Foot
+ return FUNIT_FOOT;
+ else if ( aStr.EqualsAscii( "feet" ) ) // Foot
+ return FUNIT_FOOT;
+ else if ( aStr.EqualsAscii( "mile" ) ) // Mile
+ return FUNIT_MILE;
+ else if ( aStr.EqualsAscii( "miles" ) ) // Mile
+ return FUNIT_MILE;
+ else if ( aStr.EqualsAscii( "%" ) ) // Percent
+ return FUNIT_PERCENT;
+ else
+ return FUNIT_NONE;
+}
+
+#define K *1000L
+#define M *1000000L
+#define X *5280L
+
+static const long aImplFactor[FUNIT_MILE+1][FUNIT_MILE+1] =
+{ /*
+mm/100 mm cm m km twip point pica inch foot mile */
+{ 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
+{ 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
+{ 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X },
+{ 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X },
+{ 1, 1, 1, 1, 1, 0, 254, 254, 254, 254*12, 254*12 X },
+{ 1440,144 K,144 K,14400 K, 0, 1, 20, 240, 1440,1440*12,1440*12 X },
+{ 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X },
+{ 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X },
+{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X },
+{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X },
+{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 }
+};
+
+#undef X
+#undef M
+#undef K
+// twip in km 254/14400 M
+
+static FieldUnit eDefaultUnit = FUNIT_NONE;
+
+FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
+void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
+
+static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
+{
+ switch( meUnit )
+ {
+ case MAP_100TH_MM :
+ nDecDigits -= 2;
+ return FUNIT_MM;
+ case MAP_10TH_MM :
+ nDecDigits -= 1;
+ return FUNIT_MM;
+ case MAP_MM :
+ return FUNIT_MM;
+ case MAP_CM :
+ return FUNIT_CM;
+ case MAP_1000TH_INCH :
+ nDecDigits -= 3;
+ return FUNIT_INCH;
+ case MAP_100TH_INCH :
+ nDecDigits -= 2;
+ return FUNIT_INCH;
+ case MAP_10TH_INCH :
+ nDecDigits -= 1;
+ return FUNIT_INCH;
+ case MAP_INCH :
+ return FUNIT_INCH;
+ case MAP_POINT :
+ return FUNIT_POINT;
+ case MAP_TWIP :
+ return FUNIT_TWIP;
+ default:
+ DBG_ERROR( "default eInUnit" );
+ break;
+ }
+ return FUNIT_NONE;
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::ConvertValue( long nValue, long mnBaseValue, USHORT nDecDigits,
+ FieldUnit eInUnit, FieldUnit eOutUnit )
+{
+ return (long)ConvertDoubleValue( nValue, mnBaseValue, nDecDigits,
+ eInUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::ConvertValue( long nValue, USHORT nDigits,
+ MapUnit eInUnit, FieldUnit eOutUnit )
+{
+ return (long)ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::ConvertValue( long nValue, USHORT nDigits,
+ FieldUnit eInUnit, MapUnit eOutUnit )
+{
+ return (long)ConvertValue( nValue, nDigits, eInUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+double MetricField::ConvertDoubleValue( double nValue, long mnBaseValue, USHORT nDecDigits,
+ FieldUnit eInUnit, FieldUnit eOutUnit )
+{
+ if ( eInUnit != eOutUnit )
+ {
+ long nMult, nDiv;
+
+ if ( eInUnit == FUNIT_PERCENT )
+ {
+ if ( (mnBaseValue <= 0) || (nValue <= 0) )
+ return nValue;
+ nDiv = 100;
+ for ( USHORT i=0; i < nDecDigits; i++ )
+ nDiv *= 10;
+
+ nMult = mnBaseValue;
+ }
+ else if ( eOutUnit == FUNIT_PERCENT ||
+ eOutUnit == FUNIT_CUSTOM ||
+ eOutUnit == FUNIT_NONE ||
+ eInUnit == FUNIT_CUSTOM ||
+ eInUnit == FUNIT_NONE )
+ return nValue;
+ else
+ {
+ if ( eOutUnit == FUNIT_100TH_MM )
+ eOutUnit = FUNIT_NONE;
+ if ( eInUnit == FUNIT_100TH_MM )
+ eInUnit = FUNIT_NONE;
+
+ nDiv = aImplFactor[eInUnit][eOutUnit];
+ nMult = aImplFactor[eOutUnit][eInUnit];
+
+ DBG_ASSERT( nMult > 0, "illegal *" );
+ DBG_ASSERT( nDiv > 0, "illegal /" );
+ }
+
+ if ( nMult != 1 )
+ nValue *= nMult;
+ if ( nDiv != 1 )
+ {
+ nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
+ nValue /= nDiv;
+ }
+ }
+
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+double MetricField::ConvertDoubleValue( double nValue, USHORT nDigits,
+ MapUnit eInUnit, FieldUnit eOutUnit )
+{
+ if ( eOutUnit == FUNIT_PERCENT ||
+ eOutUnit == FUNIT_CUSTOM ||
+ eOutUnit == FUNIT_NONE ||
+ eInUnit == MAP_PIXEL ||
+ eInUnit == MAP_SYSFONT ||
+ eInUnit == MAP_APPFONT ||
+ eInUnit == MAP_RELATIVE )
+ {
+ DBG_ERROR( "invalid parameters" );
+ return nValue;
+ }
+
+ long nDecDigits = nDigits;
+ FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
+
+ if ( (long)nDecDigits < 0 )
+ {
+ while ( nDecDigits )
+ {
+ nValue += 5;
+ nValue /= 10;
+ nDecDigits++;
+ }
+ }
+ else
+ {
+ while ( nDecDigits )
+ {
+ nValue *= 10;
+ nDecDigits--;
+ }
+ }
+
+ if ( eFieldUnit != eOutUnit )
+ {
+ long nDiv = aImplFactor[eFieldUnit][eOutUnit];
+ long nMult = aImplFactor[eOutUnit][eFieldUnit];
+
+ if ( nMult != 1 )
+ nValue *= nMult;
+ if ( nDiv != 1 )
+ {
+ nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
+ nValue /= nDiv;
+ }
+ }
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+double MetricField::ConvertDoubleValue( double nValue, USHORT nDigits,
+ FieldUnit eInUnit, MapUnit eOutUnit )
+{
+ if ( eInUnit == FUNIT_PERCENT ||
+ eInUnit == FUNIT_CUSTOM ||
+ eInUnit == FUNIT_NONE ||
+ eOutUnit == MAP_PIXEL ||
+ eOutUnit == MAP_SYSFONT ||
+ eOutUnit == MAP_APPFONT ||
+ eOutUnit == MAP_RELATIVE )
+ {
+ DBG_ERROR( "invalid parameters" );
+ return nValue;
+ }
+
+ long nDecDigits = nDigits;
+ FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
+
+ if ( (long)nDecDigits < 0 )
+ {
+ while ( nDecDigits )
+ {
+ nValue *= 10;
+ nDecDigits++;
+ }
+ }
+ else
+ {
+ while ( nDecDigits )
+ {
+ nValue += 5;
+ nValue /= 10;
+ nDecDigits--;
+ }
+ }
+
+ if ( eFieldUnit != eInUnit )
+ {
+ long nDiv = aImplFactor[eInUnit][eFieldUnit];
+ long nMult = aImplFactor[eFieldUnit][eInUnit];
+
+ if( nMult != 1 )
+ nValue *= nMult;
+ if( nDiv != 1 )
+ {
+ nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
+ nValue /= nDiv;
+ }
+ }
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplMetricGetValue( const XubString& rStr, double& rValue, long nBaseValue,
+ USHORT nDecDigits,
+ const International& rInter, FieldUnit eUnit )
+{
+ // Zahlenwert holen
+ if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rInter ) )
+ return FALSE;
+
+ // Einheit rausfinden
+ FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
+
+ // Einheiten umrechnen
+ rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr )
+{
+ if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), GetInternational(), meUnit ) )
+ return TRUE;
+ else
+ {
+ double nTempVal = rValue;
+ if ( nTempVal > GetMax() )
+ nTempVal = GetMax();
+ else if ( nTempVal < GetMin())
+ nTempVal = GetMin();
+
+ if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
+ {
+ mnCorrectedValue = (long)nTempVal;
+ if ( !GetErrorHdl().Call( this ) )
+ {
+ mnCorrectedValue = 0;
+ return FALSE;
+ }
+ else
+ mnCorrectedValue = 0;
+ }
+
+ rOutStr = CreateFieldText( (long)nTempVal );
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void MetricFormatter::ImplInit()
+{
+ mnBaseValue = 0;
+ meUnit = MetricField::GetDefaultUnit();
+ mnType = FORMAT_METRIC;
+}
+
+// -----------------------------------------------------------------------
+
+MetricFormatter::MetricFormatter()
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::ImplLoadRes( const ResId& rResId )
+{
+ NumericFormatter::ImplLoadRes( rResId );
+
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask = pMgr->ReadShort();
+
+ if ( METRICFORMATTER_UNIT & nMask )
+ meUnit = (FieldUnit)pMgr->ReadShort();
+
+ if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
+ maCustomUnitText = pMgr->ReadString();
+}
+
+// -----------------------------------------------------------------------
+
+MetricFormatter::~MetricFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetUnit( FieldUnit eNewUnit )
+{
+ if ( eNewUnit == FUNIT_100TH_MM )
+ {
+ SetDecimalDigits( GetDecimalDigits() + 2 );
+ meUnit = FUNIT_MM;
+ }
+ else
+ meUnit = eNewUnit;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetCustomUnitText( const XubString& rStr )
+{
+ maCustomUnitText = rStr;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetValue( long nNewValue, FieldUnit eInUnit )
+{
+ SetUserValue( nNewValue, eInUnit );
+ mnFieldValue = mnLastValue;
+}
+
+// -----------------------------------------------------------------------
+
+XubString MetricFormatter::CreateFieldText( long nValue ) const
+{
+ XubString aStr = NumericFormatter::CreateFieldText( nValue );
+
+ // Einheit dranhaengen
+ switch ( meUnit )
+ {
+ case FUNIT_MM:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "mm" ) );
+ break;
+ case FUNIT_CM:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "cm" ) );
+ break;
+ case FUNIT_M:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "m" ) );
+ break;
+ case FUNIT_KM:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "km" ) );
+ break;
+ case FUNIT_TWIP:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "twips" ) );
+ break;
+ case FUNIT_POINT:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "pt" ) );
+ break;
+ case FUNIT_PICA:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "pi" ) );
+ break;
+ case FUNIT_INCH:
+ aStr.Append( '"' );
+ break;
+ case FUNIT_FOOT:
+ aStr.Append( '\'' );
+ break;
+ case FUNIT_MILE:
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "miles" ) );
+ break;
+ case FUNIT_CUSTOM:
+ aStr += maCustomUnitText;
+ break;
+ default:
+ break;
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetUserValue( long nNewValue, FieldUnit eInUnit )
+{
+ // Umrechnen auf eingestellte Einheiten
+ nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
+ NumericFormatter::SetUserValue( nNewValue );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricFormatter::GetValue( FieldUnit eOutUnit ) const
+{
+ if ( !GetField() )
+ return 0;
+
+ double nTempValue;
+ if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(),
+ GetInternational(), meUnit ) )
+ nTempValue = mnLastValue;
+
+ if ( nTempValue > mnMax )
+ nTempValue = mnMax;
+ else if ( nTempValue < mnMin )
+ nTempValue = mnMin;
+
+ // Umrechnen auf gewuenschte Einheiten
+ return MetricField::ConvertValue( (long)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetMin( long nNewMin, FieldUnit eInUnit )
+{
+ // Umrechnen auf gewuenschte Einheiten
+ NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit ) );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricFormatter::GetMin( FieldUnit eOutUnit ) const
+{
+ // Umrechnen auf gewuenschte Einheiten
+ return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
+ GetDecimalDigits(), meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetMax( long nNewMax, FieldUnit eInUnit )
+{
+ // Umrechnen auf gewuenschte Einheiten
+ NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit ) );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricFormatter::GetMax( FieldUnit eOutUnit ) const
+{
+ // Umrechnen auf gewuenschte Einheiten
+ return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
+ GetDecimalDigits(), meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::SetBaseValue( long nNewBase, FieldUnit eInUnit )
+{
+ mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
+{
+ // Umrechnen auf gewuenschte Einheiten
+ return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ XubString aText = GetField()->GetText();
+ if ( meUnit == FUNIT_CUSTOM )
+ maCurUnitText = ImplMetricGetUnitText( aText );
+
+ XubString aStr;
+ double nTemp = mnLastValue;
+ BOOL bOK = ImplMetricReformat( aText, nTemp, aStr );
+ mnLastValue = (long)nTemp;
+
+ if ( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ {
+ ImplSetText( aStr );
+ if ( meUnit == FUNIT_CUSTOM )
+ CustomConvert();
+ }
+ else
+ SetValue( mnLastValue );
+ maCurUnitText.Erase();
+}
+
+// -----------------------------------------------------------------------
+
+long MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
+{
+ // Umrechnen auf gewuenschte Einheiten
+ return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+MetricField::MetricField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+MetricField::MetricField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_METRICFIELD )
+{
+ rResId.SetRT( RSC_METRICFIELD );
+ WinBits nStyle = ImplInitRes( rResId ) ;
+ SpinField::ImplInit( pParent, nStyle );
+ SetField( this );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( METRICFIELD_FIRST & nMask )
+ mnFirst = ReadLongRes();
+
+ if ( METRICFIELD_LAST & nMask )
+ mnLast = ReadLongRes();
+
+ if ( METRICFIELD_SPINSIZE & nMask )
+ mnSpinSize = ReadLongRes();
+
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+MetricField::~MetricField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::SetFirst( long nNewFirst, FieldUnit eInUnit )
+{
+ // Umrechnen
+ nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+ mnFirst = nNewFirst;
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::GetFirst( FieldUnit eOutUnit ) const
+{
+ // Umrechnen
+ return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::SetLast( long nNewLast, FieldUnit eInUnit )
+{
+ // Umrechnen
+ nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+ mnLast = nNewLast;
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::GetLast( FieldUnit eOutUnit ) const
+{
+ // Umrechnen
+ return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SpinField::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::Up()
+{
+ FieldUp();
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::Down()
+{
+ FieldDown();
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::First()
+{
+ FieldFirst();
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::Last()
+{
+ FieldLast();
+ SpinField::Last();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricField::CustomConvert()
+{
+ maCustomConvertLink.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+MetricBox::MetricBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_METRICBOX )
+{
+ rResId.SetRT( RSC_METRICBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ComboBox::ImplInit( pParent, nStyle );
+ SetField( this );
+ Reformat();
+ ComboBox::ImplLoadRes( rResId );
+ MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+MetricBox::~MetricBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long MetricBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::ReformatAll()
+{
+ double nValue;
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplMetricReformat( GetEntry( i ), nValue, aStr );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ MetricFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::CustomConvert()
+{
+ maCustomConvertLink.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::InsertValue( long nValue, FieldUnit eInUnit, USHORT nPos )
+{
+ // Umrechnen auf eingestellte Einheiten
+ nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+ ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void MetricBox::RemoveValue( long nValue, FieldUnit eInUnit )
+{
+ // Umrechnen auf eingestellte Einheiten
+ nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+ ComboBox::RemoveEntry( CreateFieldText( nValue ) );
+}
+
+// -----------------------------------------------------------------------
+
+long MetricBox::GetValue( USHORT nPos, FieldUnit eOutUnit ) const
+{
+ double nValue = 0;
+ ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
+ GetDecimalDigits(), GetInternational(), meUnit );
+
+ // Umrechnen auf eingestellte Einheiten
+ long nRetValue = MetricField::ConvertValue( (long)nValue, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+
+ return nRetValue;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT MetricBox::GetValuePos( long nValue, FieldUnit eInUnit ) const
+{
+ // Umrechnen auf eingestellte Einheiten
+ nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
+ eInUnit, meUnit );
+ return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
+ BOOL, const International& rInter )
+{
+ // Es gibt hier kein sinnvolles StrictFormat, also alle
+ // Zeichen erlauben
+ return ImplNumericProcessKeyInput( pEdit, rKEvt, FALSE, rInter );
+}
+
+// -----------------------------------------------------------------------
+
+inline BOOL ImplCurrencyGetValue( const XubString& rStr, double& rValue,
+ USHORT nDecDigits, const International& rInter )
+{
+ // Zahlenwert holen
+ return ImplNumericGetValue( rStr, rValue, nDecDigits, rInter, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr,
+ XubString& rOutStr )
+{
+ double nValue;
+ if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), GetInternational(), TRUE ) )
+ return TRUE;
+ else
+ {
+ double nTempVal = nValue;
+ if ( nTempVal > GetMax() )
+ nTempVal = GetMax();
+ else if ( nTempVal < GetMin())
+ nTempVal = GetMin();
+
+ if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
+ {
+ mnCorrectedValue = (long)nTempVal;
+ if ( !GetErrorHdl().Call( this ) )
+ {
+ mnCorrectedValue = 0;
+ return FALSE;
+ }
+ else
+ mnCorrectedValue = 0;
+ }
+
+ rOutStr = GetInternational().GetCurr( (long)nTempVal );
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void CurrencyFormatter::ImplInit()
+{
+ mnType = FORMAT_CURRENCY;
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyFormatter::CurrencyFormatter()
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyFormatter::~CurrencyFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyFormatter::SetValue( long nNewValue )
+{
+ SetUserValue( nNewValue );
+ mnFieldValue = mnLastValue;
+ ImplGetEmptyFieldValue() = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString CurrencyFormatter::CreateFieldText( long nValue ) const
+{
+ return GetInternational().GetCurr( nValue, GetDecimalDigits() );
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyFormatter::GetValue() const
+{
+ if ( !GetField() )
+ return 0;
+
+ double nTempValue;
+ if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(),
+ GetInternational() ) )
+ {
+ if ( nTempValue > mnMax )
+ nTempValue = mnMax;
+ else if ( nTempValue < mnMin )
+ nTempValue = mnMin;
+ return (long)nTempValue;
+ }
+ else
+ return mnLastValue;
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ XubString aStr;
+ BOOL bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
+ if ( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ {
+ ImplSetText( aStr );
+ double nTemp = mnLastValue;
+ ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), GetInternational() );
+ mnLastValue = (long)nTemp;
+ }
+ else
+ SetValue( mnLastValue );
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_CURRENCYFIELD )
+{
+ rResId.SetRT( RSC_CURRENCYFIELD );
+ WinBits nStyle = ImplInitRes( rResId );
+ SpinField::ImplInit( pParent, nStyle);
+ SetField( this );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( CURRENCYFIELD_FIRST & nMask )
+ mnFirst = ReadLongRes();
+
+ if ( CURRENCYFIELD_LAST & nMask )
+ mnLast = ReadLongRes();
+
+ if ( CURRENCYFIELD_SPINSIZE & nMask )
+ mnSpinSize = ReadLongRes();
+
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyField::~CurrencyField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SpinField::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::Up()
+{
+ FieldUp();
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::Down()
+{
+ FieldDown();
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::First()
+{
+ FieldFirst();
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyField::Last()
+{
+ FieldLast();
+ SpinField::Last();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_CURRENCYBOX )
+{
+ rResId.SetRT( RSC_CURRENCYBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ComboBox::ImplInit( pParent, nStyle );
+ CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ SetField( this );
+ ComboBox::ImplLoadRes( rResId );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+CurrencyBox::~CurrencyBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyBox::ReformatAll()
+{
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplCurrencyReformat( GetEntry( i ), aStr );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ CurrencyFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyBox::InsertValue( long nValue, USHORT nPos )
+{
+ ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void CurrencyBox::RemoveValue( long nValue )
+{
+ ComboBox::RemoveEntry( CreateFieldText( nValue ) );
+}
+
+// -----------------------------------------------------------------------
+
+long CurrencyBox::GetValue( USHORT nPos ) const
+{
+ double nValue = 0;
+ ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue,
+ GetDecimalDigits(), GetInternational() );
+ return (long)nValue;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT CurrencyBox::GetValuePos( long nValue ) const
+{
+ return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
+}
diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx
new file mode 100644
index 000000000000..5a598c72e3cb
--- /dev/null
+++ b/vcl/source/control/field2.cxx
@@ -0,0 +1,3245 @@
+/*************************************************************************
+ *
+ * $RCSfile: field2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FIELD2_CXX
+
+#ifndef _TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <field.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_SYSTEM_HXX
+#include <system.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_FIELD_HXX
+#include <field.hxx>
+#endif
+
+#ifndef _ISOLANG_HXX
+#include <tools/isolang.hxx>
+#endif
+
+#include <unohelp.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+
+#ifndef _COM_SUN_STAR_LANG_XCHARACTERCLASSIFICATION_HPP_
+#include <com/sun/star/lang/XCharacterClassification.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_KCHARACTERTYPE_HPP_
+#include <com/sun/star/lang/KCharacterType.hpp>
+#endif
+
+#pragma hdrstop
+
+using namespace ::com::sun::star;
+
+// =======================================================================
+
+#define EDITMASK_LITERAL 'L'
+#define EDITMASK_ALPHA 'a'
+#define EDITMASK_UPPERALPHA 'A'
+#define EDITMASK_ALPHANUM 'c'
+#define EDITMASK_UPPERALPHANUM 'C'
+#define EDITMASK_NUM 'N'
+#define EDITMASK_NUMSPACE 'n'
+#define EDITMASK_ALLCHAR 'x'
+#define EDITMASK_UPPERALLCHAR 'X'
+
+
+
+const sal_Int32 nCharClassAlphaType =
+ ::com::sun::star::lang::KCharacterType::UPPER |
+ ::com::sun::star::lang::KCharacterType::LOWER |
+ ::com::sun::star::lang::KCharacterType::TITLE_CASE;
+
+const sal_Int32 nCharClassAlphaTypeMask =
+ nCharClassAlphaType |
+ ::com::sun::star::lang::KCharacterType::PRINTABLE |
+ ::com::sun::star::lang::KCharacterType::BASE_FORM;
+
+inline sal_Bool isAlphaType( sal_Int32 nType )
+{
+ return ((nType & nCharClassAlphaType) != 0) && (nType & ~(nCharClassAlphaTypeMask) == 0);
+}
+
+lang::Locale CreateLocale( const International& rInt )
+{
+ String aLanguage, aCountry;
+ ConvertLanguageToIsoNames( rInt.GetLanguage(), aLanguage, aCountry );
+ lang::Locale aLocale;
+ aLocale.Language = aLanguage;
+ aLocale.Country = aCountry;
+
+ return aLocale;
+}
+
+uno::Reference< lang::XCharacterClassification > ImplGetCharClass()
+{
+ static uno::Reference< lang::XCharacterClassification > xCharClass;
+ if ( !xCharClass.is() )
+ xCharClass = vcl::unohelper::CreateCharacterClassification();
+
+ return xCharClass;
+}
+
+
+// -----------------------------------------------------------------------
+
+static int ImplIsPatternChar( xub_Unicode cChar, sal_Char cEditMask )
+{
+ if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
+ {
+ if ( ((cChar < 'A') || (cChar > 'Z')) &&
+ ((cChar < 'a') || (cChar > 'z')) )
+ return FALSE;
+ }
+ else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
+ {
+ if ( ((cChar < 'A') || (cChar > 'Z')) &&
+ ((cChar < 'a') || (cChar > 'z')) &&
+ ((cChar < '0') || (cChar > '9')) )
+ return FALSE;
+ }
+ else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
+ {
+ if ( cChar < 32 )
+ return FALSE;
+ }
+ else if ( cEditMask == EDITMASK_NUM )
+ {
+ if ( (cChar < '0') || (cChar > '9') )
+ return FALSE;
+ }
+ else if ( cEditMask == EDITMASK_NUMSPACE )
+ {
+ if ( ((cChar < '0') || (cChar > '9')) && (cChar != ' ') )
+ return FALSE;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+static xub_Unicode ImplPatternChar( xub_Unicode cChar, sal_Char cEditMask )
+{
+ if ( ImplIsPatternChar( cChar, cEditMask ) )
+ {
+ if ( (cEditMask == EDITMASK_UPPERALPHA) ||
+ (cEditMask == EDITMASK_UPPERALPHANUM) )
+ {
+ if ( (cChar >= 'a') && (cChar <= 'z') )
+ cChar = (cChar - 'a') + 'A';
+ }
+ else if ( cEditMask == EDITMASK_UPPERALLCHAR )
+ {
+ cChar = ImplGetCharClass()->toUpper( String(cChar),0,1,Application::GetSettings().GetLocale() )[0];
+ }
+
+ return cChar;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static int ImplKommaPointCharEqual( xub_Unicode c1, xub_Unicode c2 )
+{
+ if ( c1 == c2 )
+ return TRUE;
+ else if ( ((c1 == '.') || (c1 == ',')) &&
+ ((c2 == '.') || (c2 == ',')) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static XubString ImplPatternReformat( const XubString& rStr,
+ const ByteString& rEditMask,
+ const XubString& rLiteralMask,
+ USHORT nFormatFlags )
+{
+ if ( !rEditMask.Len() )
+ return rStr;
+
+ XubString aStr = rStr;
+ XubString aOutStr = rLiteralMask;
+ xub_Unicode cTempChar;
+ xub_Unicode cChar;
+ xub_Unicode cLiteral;
+ sal_Char cMask;
+ xub_StrLen nStrIndex = 0;
+ xub_StrLen i = 0;
+ xub_StrLen n;
+
+ while ( i < rEditMask.Len() )
+ {
+ if ( nStrIndex >= aStr.Len() )
+ break;
+
+ cChar = aStr.GetChar(nStrIndex);
+ cLiteral = rLiteralMask.GetChar(i);
+ cMask = rEditMask.GetChar(i);
+
+ // Aktuelle Position ein Literal
+ if ( cMask == EDITMASK_LITERAL )
+ {
+ // Wenn es das Literal-Zeichen ist, uebernehmen, ansonsten
+ // ignorieren, da es das naechste gueltige Zeichen vom String
+ // sein kann
+ if ( ImplKommaPointCharEqual( cChar, cLiteral ) )
+ nStrIndex++;
+ else
+ {
+ // Ansonsten testen wir, ob es ein ungueltiges Zeichen ist.
+ // Dies ist dann der Fall, wenn es nicht in das Muster
+ // des naechsten nicht Literal-Zeichens passt
+ n = i+1;
+ while ( n < rEditMask.Len() )
+ {
+ if ( rEditMask.GetChar(n) != EDITMASK_LITERAL )
+ {
+ if ( !ImplIsPatternChar( cChar, rEditMask.GetChar(n) ) )
+ nStrIndex++;
+ break;
+ }
+
+ n++;
+ }
+ }
+ }
+ else
+ {
+ // Gueltiges Zeichen an der Stelle
+ cTempChar = ImplPatternChar( cChar, cMask );
+ if ( cTempChar )
+ {
+ // dann Zeichen uebernehmen
+ aOutStr.SetChar( i, cTempChar );
+ nStrIndex++;
+ }
+ else
+ {
+ // Wenn es das Literalzeichen ist, uebernehmen
+ if ( cLiteral == cChar )
+ nStrIndex++;
+ else
+ {
+ // Wenn das ungueltige Zeichen das naechste Literalzeichen
+ // sein kann, dann springen wir bis dahin vor, ansonten
+ // das Zeichen ignorieren
+ // Nur machen, wenn leere Literale erlaubt sind
+ if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
+ {
+ n = i;
+ while ( n < rEditMask.Len() )
+ {
+ if ( rEditMask.GetChar( n ) == EDITMASK_LITERAL )
+ {
+ if ( ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar( n ) ) )
+ i = n+1;
+
+ break;
+ }
+
+ n++;
+ }
+ }
+
+ nStrIndex++;
+ continue;
+ }
+ }
+ }
+
+ i++;
+ }
+
+ return aOutStr;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplPatternMaxPos( const XubString rStr, const ByteString& rEditMask,
+ USHORT nFormatFlags, BOOL bSameMask,
+ USHORT nCursorPos, USHORT& rPos )
+{
+
+ // Letzte Position darf nicht groesser als der enthaltene String sein
+ xub_StrLen nMaxPos = rStr.Len();
+
+ // Wenn keine leeren Literale erlaubt sind, auch Leerzeichen
+ // am Ende ignorieren
+ if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
+ {
+ while ( nMaxPos )
+ {
+ if ( (rEditMask.GetChar(nMaxPos-1) != EDITMASK_LITERAL) &&
+ (rStr.GetChar(nMaxPos-1) != ' ') )
+ break;
+ nMaxPos--;
+ }
+
+ // Wenn wir vor einem Literal stehen, dann solange weitersuchen,
+ // bis erste Stelle nach Literal
+ xub_StrLen nTempPos = nMaxPos;
+ while ( nTempPos < rEditMask.Len() )
+ {
+ if ( rEditMask.GetChar(nTempPos) != EDITMASK_LITERAL )
+ {
+ nMaxPos = nTempPos;
+ break;
+ }
+ nTempPos++;
+ }
+ }
+
+ if ( rPos > nMaxPos )
+ rPos = nMaxPos;
+ // Zeichen sollte nicht nach links wandern
+ if ( rPos < nCursorPos )
+ rPos = nCursorPos;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplPatternProcessStrictModify( Edit* pEdit,
+ const ByteString& rEditMask,
+ const XubString& rLiteralMask,
+ USHORT nFormatFlags, BOOL bSameMask )
+{
+ XubString aText = pEdit->GetText();
+
+ // Leerzeichen am Anfang entfernen
+ if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
+ {
+ xub_StrLen i = 0;
+ xub_StrLen nMaxLen = aText.Len();
+ while ( i < nMaxLen )
+ {
+ if ( (rEditMask.GetChar( i ) != EDITMASK_LITERAL) &&
+ (aText.GetChar( i ) != ' ') )
+ break;
+
+ i++;
+ }
+ // Alle Literalzeichen beibehalten
+ while ( i && (rEditMask.GetChar( i ) == EDITMASK_LITERAL) )
+ i--;
+ aText.Erase( 0, i );
+ }
+
+ XubString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
+ if ( aNewText != aText )
+ {
+ // Selection so anpassen, das diese wenn sie vorher am Ende
+ // stand, immer noch am Ende steht
+ Selection aSel = pEdit->GetSelection();
+ ULONG nMaxSel = Max( aSel.Min(), aSel.Max() );
+ if ( nMaxSel >= aText.Len() )
+ {
+ xub_StrLen nMaxPos = aNewText.Len();
+ ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, (xub_StrLen)nMaxSel, nMaxPos );
+ if ( aSel.Min() == aSel.Max() )
+ {
+ aSel.Min() = nMaxPos;
+ aSel.Max() = aSel.Min();
+ }
+ else if ( aSel.Min() > aSel.Max() )
+ aSel.Min() = nMaxPos;
+ else
+ aSel.Max() = nMaxPos;
+ }
+ pEdit->SetText( aNewText, aSel );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static xub_StrLen ImplPatternLeftPos( const ByteString& rEditMask, xub_StrLen nCursorPos )
+{
+ // Vorheriges Zeichen suchen, was kein Literal ist
+ xub_StrLen nNewPos = nCursorPos;
+ xub_StrLen nTempPos = nNewPos;
+ while ( nTempPos )
+ {
+ if ( rEditMask.GetChar(nTempPos-1) != EDITMASK_LITERAL )
+ {
+ nNewPos = nTempPos-1;
+ break;
+ }
+ nTempPos--;
+ }
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+static xub_StrLen ImplPatternRightPos( const XubString& rStr, const ByteString& rEditMask,
+ USHORT nFormatFlags, BOOL bSameMask,
+ xub_StrLen nCursorPos )
+{
+ // Naechstes Zeichen suchen, was kein Literal ist
+ xub_StrLen nNewPos = nCursorPos;
+ xub_StrLen nTempPos = nNewPos;
+ while ( nTempPos < rEditMask.Len() )
+ {
+ if ( rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL )
+ {
+ nNewPos = nTempPos+1;
+ break;
+ }
+ nTempPos++;
+ }
+ ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
+ const ByteString& rEditMask,
+ const XubString& rLiteralMask,
+ BOOL bStrictFormat,
+ USHORT nFormatFlags,
+ BOOL bSameMask,
+ BOOL& rbInKeyInput )
+{
+ if ( !rEditMask.Len() || !bStrictFormat )
+ return FALSE;
+
+ Selection aOldSel = pEdit->GetSelection();
+ KeyCode aCode = rKEvt.GetKeyCode();
+ xub_Unicode cChar = rKEvt.GetCharCode();
+ USHORT nKeyCode = aCode.GetCode();
+ BOOL bShift = aCode.IsShift();
+ xub_StrLen nCursorPos = (xub_StrLen)aOldSel.Max();
+ xub_StrLen nNewPos;
+ xub_StrLen nTempPos;
+
+ if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
+ {
+ if ( nKeyCode == KEY_LEFT )
+ {
+ Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
+ if ( bShift )
+ aSel.Min() = aOldSel.Min();
+ pEdit->SetSelection( aSel );
+ return TRUE;
+ }
+ else if ( nKeyCode == KEY_RIGHT )
+ {
+ // Hier nehmen wir Selectionsanfang als minimum, da falls durch
+ // Focus alles selektiert ist, ist eine kleine Position schon
+ // erlaubt.
+ Selection aSel( aOldSel );
+ aSel.Justify();
+ nCursorPos = (xub_StrLen)aSel.Min();
+ aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
+ if ( bShift )
+ aSel.Min() = aOldSel.Min();
+ else
+ aSel.Min() = aSel.Max();
+ pEdit->SetSelection( aSel );
+ return TRUE;
+ }
+ else if ( nKeyCode == KEY_HOME )
+ {
+ // Home ist Position des ersten nicht literalen Zeichens
+ nNewPos = 0;
+ while ( (nNewPos < rEditMask.Len()) &&
+ (rEditMask.GetChar(nNewPos) == EDITMASK_LITERAL) )
+ nNewPos++;
+ // Home sollte nicht nach rechts wandern
+ if ( nCursorPos < nNewPos )
+ nNewPos = nCursorPos;
+ Selection aSel( nNewPos );
+ if ( bShift )
+ aSel.Min() = aOldSel.Min();
+ pEdit->SetSelection( aSel );
+ return TRUE;
+ }
+ else if ( nKeyCode == KEY_END )
+ {
+ // End ist die Position des letzten nicht literalen Zeichens
+ nNewPos = rEditMask.Len();
+ while ( nNewPos &&
+ (rEditMask.GetChar(nNewPos-1) == EDITMASK_LITERAL) )
+ nNewPos--;
+ // Hier nehmen wir Selectionsanfang als minimum, da falls durch
+ // Focus alles selektiert ist, ist eine kleine Position schon
+ // erlaubt.
+ Selection aSel( aOldSel );
+ aSel.Justify();
+ nCursorPos = (xub_StrLen)aSel.Min();
+ ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
+ aSel.Max() = nNewPos;
+ if ( bShift )
+ aSel.Min() = aOldSel.Min();
+ else
+ aSel.Min() = aSel.Max();
+ pEdit->SetSelection( aSel );
+ return TRUE;
+ }
+ else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
+ {
+ XubString aStr( pEdit->GetText() );
+ XubString aOldStr = aStr;
+ Selection aSel = aOldSel;
+
+ aSel.Justify();
+ nNewPos = (xub_StrLen)aSel.Min();
+
+ // Wenn Selection, dann diese Loeschen
+ if ( aSel.Len() )
+ {
+ if ( bSameMask )
+ aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
+ else
+ {
+ XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
+ aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
+ }
+ }
+ else
+ {
+ if ( nKeyCode == KEY_BACKSPACE )
+ {
+ nTempPos = nNewPos;
+ nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
+ }
+ else
+ nTempPos = ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos );
+
+ if ( nNewPos != nTempPos )
+ {
+ if ( bSameMask )
+ {
+ if ( rEditMask.GetChar( nNewPos ) != EDITMASK_LITERAL )
+ aStr.Erase( nNewPos, 1 );
+ }
+ else
+ {
+ XubString aTempStr = rLiteralMask.Copy( nNewPos, 1 );
+ aStr.Replace( nNewPos, aTempStr.Len(), aTempStr );
+ }
+ }
+ }
+
+ if ( aOldStr != aStr )
+ {
+ if ( bSameMask )
+ aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
+ rbInKeyInput = TRUE;
+ pEdit->SetText( aStr, Selection( nNewPos ) );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ rbInKeyInput = FALSE;
+ }
+ else
+ pEdit->SetSelection( Selection( nNewPos ) );
+
+ return TRUE;
+ }
+ else if ( nKeyCode == KEY_INSERT )
+ {
+ // InsertModus kann man beim PatternField nur einstellen,
+ // wenn Maske an jeder Eingabeposition die gleiche
+ // ist
+ if ( !bSameMask )
+ {
+ Sound::Beep();
+ return TRUE;
+ }
+ }
+ }
+
+ if ( aCode.IsControlMod() || (cChar < 32) || (cChar == 127) )
+ return FALSE;
+
+ Selection aSel = aOldSel;
+ aSel.Justify();
+ nNewPos = (xub_StrLen)aSel.Min();
+
+ if ( nNewPos < rEditMask.Len() )
+ {
+ xub_Unicode cPattChar = ImplPatternChar( cChar, rEditMask.GetChar(nNewPos) );
+ if ( cPattChar )
+ cChar = cPattChar;
+ else
+ {
+ // Wenn kein gueltiges Zeichen, dann testen wir, ob der
+ // Anwender zum naechsten Literal springen wollte. Dies machen
+ // wir nur, wenn er hinter einem Zeichen steht, damit
+ // eingebene Literale die automatisch uebersprungenen wurden
+ // nicht dazu fuehren, das der Anwender dann da steht, wo
+ // er nicht stehen wollte.
+ if ( nNewPos &&
+ (rEditMask.GetChar(nNewPos-1) != EDITMASK_LITERAL) &&
+ !aSel.Len() )
+ {
+ // Naechstes Zeichen suchen, was kein Literal ist
+ nTempPos = nNewPos;
+ while ( nTempPos < rEditMask.Len() )
+ {
+ if ( rEditMask.GetChar(nTempPos) == EDITMASK_LITERAL )
+ {
+ // Gilt nur, wenn ein Literalzeichen vorhanden
+ if ( (rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL ) &&
+ ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar(nTempPos) ) )
+ {
+ nTempPos++;
+ ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
+ if ( nTempPos > nNewPos )
+ {
+ pEdit->SetSelection( Selection( nTempPos ) );
+ return TRUE;
+ }
+ }
+ break;
+ }
+ nTempPos++;
+ }
+ }
+
+ cChar = 0;
+ }
+ }
+ else
+ cChar = 0;
+ if ( cChar )
+ {
+ XubString aStr = pEdit->GetText();
+ BOOL bError = FALSE;
+ if ( bSameMask && pEdit->IsInsertMode() )
+ {
+ // Text um Spacezeichen und Literale am Ende kuerzen, bis zur
+ // aktuellen Position
+ xub_StrLen n = aStr.Len();
+ while ( n && (n > nNewPos) )
+ {
+ if ( (aStr.GetChar( n-1 ) != ' ') &&
+ ((n > rEditMask.Len()) || (rEditMask.GetChar(n-1) != EDITMASK_LITERAL)) )
+ break;
+
+ n--;
+ }
+ aStr.Erase( n );
+
+ if ( aSel.Len() )
+ aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
+
+ if ( aStr.Len() < rEditMask.Len() )
+ {
+ // String evtl. noch bis Cursor-Position erweitern
+ if ( aStr.Len() < nNewPos )
+ aStr += rLiteralMask.Copy( aStr.Len(), nNewPos-aStr.Len() );
+ if ( nNewPos < aStr.Len() )
+ aStr.Insert( cChar, nNewPos );
+ else if ( nNewPos < rEditMask.Len() )
+ aStr += cChar;
+ aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
+ }
+ else
+ bError = TRUE;
+ }
+ else
+ {
+ if ( aSel.Len() )
+ {
+ // Selection loeschen
+ XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
+ aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
+ }
+
+ if ( nNewPos < aStr.Len() )
+ aStr.SetChar( nNewPos, cChar );
+ else if ( nNewPos < rEditMask.Len() )
+ aStr += cChar;
+ }
+
+ if ( bError )
+ Sound::Beep();
+ else
+ {
+ rbInKeyInput = TRUE;
+ Selection aNewSel( ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos ) );
+ pEdit->SetText( aStr, aNewSel );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ rbInKeyInput = FALSE;
+ }
+ }
+ else
+ Sound::Beep();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::ImplSetMask( const ByteString& rEditMask,
+ const XubString& rLiteralMask )
+{
+ maEditMask = rEditMask;
+ maLiteralMask = rLiteralMask;
+ mbSameMask = TRUE;
+
+ if ( maEditMask.Len() != maLiteralMask.Len() )
+ {
+ if ( maEditMask.Len() < maLiteralMask.Len() )
+ maLiteralMask.Erase( maEditMask.Len() );
+ else
+ maLiteralMask.Expand( maEditMask.Len(), ' ' );
+ }
+
+ // StrictModus erlaubt nur Input-Mode, wenn als Maske nur
+ // gleiche Zeichen zugelassen werden und als Vorgabe nur
+ // Spacezeichen vorgegeben werden, die durch die Maske
+ // nicht zugelassen sind
+ xub_StrLen i = 0;
+ sal_Char c = 0;
+ while ( i < rEditMask.Len() )
+ {
+ sal_Char cTemp = rEditMask.GetChar( i );
+ if ( cTemp != EDITMASK_LITERAL )
+ {
+ if ( (cTemp == EDITMASK_ALLCHAR) ||
+ (cTemp == EDITMASK_UPPERALLCHAR) ||
+ (cTemp == EDITMASK_NUMSPACE) )
+ {
+ mbSameMask = FALSE;
+ break;
+ }
+ if ( i < rLiteralMask.Len() )
+ {
+ if ( rLiteralMask.GetChar( i ) != ' ' )
+ {
+ mbSameMask = FALSE;
+ break;
+ }
+ }
+ if ( !c )
+ c = cTemp;
+ if ( cTemp != c )
+ {
+ mbSameMask = FALSE;
+ break;
+ }
+ }
+ i++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+PatternFormatter::PatternFormatter()
+{
+ mnFormatFlags = 0;
+ mbSameMask = TRUE;
+ mbInPattKeyInput = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::ImplLoadRes( const ResId& rResId )
+{
+ ByteString aEditMask;
+ XubString aLiteralMask;
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask = pMgr->ReadShort();
+
+ if ( PATTERNFORMATTER_STRICTFORMAT & nMask )
+ SetStrictFormat( (BOOL)pMgr->ReadShort() );
+
+ if ( PATTERNFORMATTER_EDITMASK & nMask )
+ aEditMask = ByteString( pMgr->ReadString(), RTL_TEXTENCODING_ASCII_US );
+
+ if ( PATTERNFORMATTER_LITTERALMASK & nMask )
+ aLiteralMask = pMgr->ReadString();
+
+ if ( (PATTERNFORMATTER_EDITMASK | PATTERNFORMATTER_LITTERALMASK) & nMask )
+ ImplSetMask( aEditMask, aLiteralMask );
+}
+
+// -----------------------------------------------------------------------
+
+PatternFormatter::~PatternFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::SetMask( const ByteString& rEditMask,
+ const XubString& rLiteralMask )
+{
+ ImplSetMask( rEditMask, rLiteralMask );
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::SetString( const XubString& rStr )
+{
+ maFieldString = rStr;
+ if ( GetField() )
+ {
+ GetField()->SetText( rStr );
+ MarkToBeReformatted( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString PatternFormatter::GetString() const
+{
+ if ( !GetField() )
+ return ImplGetSVEmptyStr();
+ else
+ return ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::Reformat()
+{
+ if ( GetField() )
+ {
+ ImplSetText( ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags ) );
+ if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
+ GetField()->SetInsertMode( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void PatternFormatter::SelectFixedFont()
+{
+ if ( GetField() )
+ {
+ Font aFont = System::GetStandardFont( STDFONT_FIXED );
+ Font aControlFont;
+ aControlFont.SetName( aFont.GetName() );
+ aControlFont.SetFamily( aFont.GetFamily() );
+ aControlFont.SetPitch( aFont.GetPitch() );
+ GetField()->SetControlFont( aControlFont );
+ }
+}
+
+ // -----------------------------------------------------------------------
+
+PatternField::PatternField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+PatternField::PatternField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_PATTERNFIELD )
+{
+ rResId.SetRT( RSC_PATTERNFIELD );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ SetField( this );
+ SpinField::ImplLoadRes( rResId );
+ PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+PatternField::~PatternField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long PatternField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
+ IsStrictFormat(), GetFormatFlags(),
+ ImplIsSameMask(), ImplGetInPattKeyInput() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long PatternField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void PatternField::Modify()
+{
+ if ( !ImplGetInPattKeyInput() )
+ {
+ if ( IsStrictFormat() )
+ ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
+ else
+ MarkToBeReformatted( TRUE );
+ }
+
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+PatternBox::PatternBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+PatternBox::PatternBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_PATTERNBOX )
+{
+ rResId.SetRT( RSC_PATTERNBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+
+ SetField( this );
+ ComboBox::ImplLoadRes( rResId );
+ PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+PatternBox::~PatternBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long PatternBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
+ IsStrictFormat(), GetFormatFlags(),
+ ImplIsSameMask(), ImplGetInPattKeyInput() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long PatternBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void PatternBox::Modify()
+{
+ if ( !ImplGetInPattKeyInput() )
+ {
+ if ( IsStrictFormat() )
+ ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
+ else
+ MarkToBeReformatted( TRUE );
+ }
+
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void PatternBox::ReformatAll()
+{
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ PatternFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void PatternBox::InsertString( const XubString& rStr, USHORT nPos )
+{
+ ComboBox::InsertEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void PatternBox::RemoveString( const XubString& rStr )
+{
+ ComboBox::RemoveEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
+}
+
+// -----------------------------------------------------------------------
+
+XubString PatternBox::GetString( USHORT nPos ) const
+{
+ return ImplPatternReformat( ComboBox::GetEntry( nPos ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT PatternBox::GetStringPos( const XubString& rStr ) const
+{
+ return ComboBox::GetEntryPos( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
+}
+
+// =======================================================================
+
+static BOOL ImplNeed4DigitYear( USHORT nYear, const AllSettings& rSettings )
+{
+ USHORT nTwoDigitYearStart = rSettings.GetMiscSettings().GetTwoDigitYearStart();
+
+ // Wenn Jahr nicht im 2stelligen Grenzbereich liegt,
+ if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplCutDayFromString( XubString& rStr, const International& )
+{
+ // Nach Zahl suchen
+ while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ rStr.Erase( 0, 1 );
+ if ( !rStr.Len() )
+ return 0;
+ XubString aNumStr;
+ while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ {
+ aNumStr.Insert( rStr.GetChar( 0 ) );
+ rStr.Erase( 0, 1 );
+ }
+ return (USHORT)aNumStr.ToInt32();
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplCutMonthFromString( XubString& rStr, const International& rInter )
+{
+ USHORT nPos;
+
+ //Nach Monatsnamen suchen
+ for ( USHORT i=1; i <= 12; i++ )
+ {
+ const XubString& rMonthName = rInter.GetMonthText( i );
+ // Voller Monatsname ?
+ nPos = rStr.Search( rMonthName );
+ if ( nPos != STRING_NOTFOUND )
+ {
+ rStr.Erase( 0, nPos + rMonthName.Len() );
+ return i;
+ }
+ // Kurzer Monatsname ?
+ const XubString& rAbbrevMonthName = rInter.GetAbbrevMonthText( i );
+ nPos = rStr.Search( rAbbrevMonthName );
+ if ( nPos != STRING_NOTFOUND )
+ {
+ rStr.Erase( 0, nPos + rAbbrevMonthName.Len() );
+ return i;
+ }
+ }
+
+ // Nach Zahl suchen
+ while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ rStr.Erase( 0, 1 );
+ if ( !rStr.Len() )
+ return 0;
+ XubString aNumStr;
+ while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ {
+ aNumStr.Insert( rStr.GetChar( 0 ) );
+ rStr.Erase( 0, 1 );
+ }
+ return (USHORT)aNumStr.ToInt32();
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplCutYearFromString( XubString& rStr, const International& )
+{
+ // Nach Zahl suchen
+ while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ rStr.Erase( 0, 1 );
+ if ( !rStr.Len() )
+ return 0;
+ XubString aNumStr;
+ while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
+ {
+ aNumStr.Insert( rStr.GetChar( 0 ) );
+ aNumStr.Erase( 0, 1 );
+ }
+ return (USHORT)aNumStr.ToInt32();
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt,
+ BOOL bStrictFormat, BOOL bLongFormat,
+ const International& rInter )
+{
+ xub_Unicode cChar = rKEvt.GetCharCode();
+
+ if ( !bStrictFormat || bLongFormat )
+ return FALSE;
+ else
+ {
+ USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
+ if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
+ (nGroup == KEYGROUP_MISC)||
+ ((cChar >= '0') && (cChar <= '9')) ||
+ (cChar == rInter.GetDateSep()) )
+ return FALSE;
+ else
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplDateGetValue( const XubString& rStr, Date& rDate,
+ BOOL bLongFormat, const International& rInter,
+ const AllSettings& rSettings )
+{
+ XubString aStr = rStr;
+ BOOL bStrLongFormat = FALSE;
+ xub_StrLen nSep1Pos;
+ xub_StrLen nSep2Pos;
+ USHORT mnFirst;
+ USHORT nSecond;
+ USHORT nThird;
+ Date aDate( 0, 0, 0 );
+ DateFormat eDateFormat;
+
+ if ( !rStr.Len() )
+ return FALSE;
+
+ if ( bLongFormat )
+ eDateFormat = rInter.GetLongDateFormat();
+ else
+ eDateFormat = rInter.GetDateFormat();
+
+ // Sind da Buchstaben drin ?
+
+ bStrLongFormat = isAlphaType( ImplGetCharClass()->getStringType( aStr, 0, aStr.Len(), CreateLocale(rInter) ) );
+
+ // Bei enthaltenen Buchstaben gehen wir davon aus, das ein langes
+ // Datumsformat eingegeben wurde
+ if ( bStrLongFormat )
+ {
+ switch( eDateFormat )
+ {
+ case MDY:
+ mnFirst = ImplCutMonthFromString( aStr, rInter );
+ nSecond = ImplCutDayFromString( aStr, rInter );
+ nThird = ImplCutYearFromString( aStr, rInter );
+ break;
+ case DMY:
+ mnFirst = ImplCutDayFromString( aStr, rInter );
+ nSecond = ImplCutMonthFromString( aStr, rInter );
+ nThird = ImplCutYearFromString( aStr, rInter );
+ break;
+ case YMD:
+ default:
+ mnFirst = ImplCutYearFromString( aStr, rInter );
+ nSecond = ImplCutMonthFromString( aStr, rInter );
+ nThird = ImplCutDayFromString( aStr, rInter );
+ break;
+ }
+ }
+ else
+ {
+ // Nach Separatoren suchen
+ XubString aSepStr( RTL_CONSTASCII_USTRINGPARAM( ",.;:-/" ) );
+
+ // Die obigen Zeichen durch das Separatorzeichen ersetzen
+ for ( xub_StrLen i = 0; i < aSepStr.Len(); i++ )
+ {
+ if ( aSepStr.GetChar( i ) == rInter.GetDateSep() )
+ continue;
+ for ( xub_StrLen j = 0; j < aStr.Len(); j++ )
+ {
+ if ( aStr.GetChar( j ) == aSepStr.GetChar( i ) )
+ aStr.SetChar( j, rInter.GetDateSep() );
+ }
+ }
+
+ nSep1Pos = aStr.Search( rInter.GetDateSep() );
+ if ( nSep1Pos == STRING_NOTFOUND )
+ return FALSE;
+ nSep2Pos = aStr.Search( rInter.GetDateSep(), nSep1Pos+1 );
+
+ // Kein Jahr eingegeben ?
+ if ( nSep2Pos == STRING_NOTFOUND )
+ {
+ switch( eDateFormat )
+ {
+ case DMY:
+ case MDY:
+ nSep2Pos = aStr.Len();
+ aStr += rInter.GetDateSep();
+ aStr += aDate.GetYear();
+ break;
+ default:
+ case YMD:
+ {
+ nSep2Pos = nSep1Pos;
+ XubString aYearStr( aDate.GetYear() );
+ nSep2Pos = aYearStr.Len();
+ aStr.Insert( rInter.GetDateSep(), 0 );
+ aStr.Insert( aYearStr, 0 );
+ }
+ break;
+ }
+ }
+
+ mnFirst = (USHORT)aStr.Copy( 0, nSep1Pos ).ToInt32();
+ aStr.Erase( 0, nSep1Pos+1 );
+ nSecond = (USHORT)aStr.Copy( 0, nSep2Pos-nSep1Pos-1 ).ToInt32();
+ aStr.Erase( 0, nSep2Pos-nSep1Pos-1+1 );
+ nThird = (USHORT)aStr.ToInt32();
+ }
+
+ switch ( eDateFormat )
+ {
+ case MDY:
+ if ( !nSecond || !mnFirst )
+ return FALSE;
+ aDate = Date( nSecond, mnFirst, nThird );
+ break;
+ case DMY:
+ if ( !mnFirst || !nSecond )
+ return FALSE;
+ aDate = Date( mnFirst, nSecond, nThird );
+ break;
+ default:
+ case YMD:
+ if ( !nSecond || !nThird )
+ return FALSE;
+ aDate = Date( nThird, nSecond, mnFirst );
+ break;
+ }
+
+ DateFormatter::ExpandCentury( aDate, rSettings.GetMiscSettings().GetTwoDigitYearStart() );
+ if ( (aDate.GetDay() > 31) || (aDate.GetMonth() > 12) )
+ return FALSE;
+ if ( !aDate.IsValid() )
+ return FALSE;
+ rDate = aDate;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DateFormatter::ImplDateReformat( const XubString& rStr, XubString& rOutStr,
+ const AllSettings& rSettings )
+{
+ Date aDate( 0, 0, 0 );
+ if ( !ImplDateGetValue( rStr, aDate, mbLongFormat, GetInternational(), GetFieldSettings() ) )
+ return TRUE;
+
+ Date aTempDate = aDate;
+ if ( aTempDate > GetMax() )
+ aTempDate = GetMax();
+ else if ( aTempDate < GetMin() )
+ aTempDate = GetMin();
+
+ if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
+ {
+ maCorrectedDate = aTempDate;
+ if( !GetErrorHdl().Call( this ) )
+ {
+ maCorrectedDate = Date();
+ return FALSE;
+ }
+ else
+ maCorrectedDate = Date();
+ }
+
+ rOutStr = ImplGetDateAsText( aTempDate, rSettings );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString DateFormatter::ImplGetDateAsText( const Date& rDate,
+ const AllSettings& rSettings ) const
+{
+ XubString aDateAsText;
+
+ International aIntn = GetInternational();
+ BOOL b4DigitYear = ImplNeed4DigitYear( rDate.GetYear(), rSettings );
+ if ( mbLongFormat )
+ {
+ if ( b4DigitYear && !aIntn.IsLongDateCentury() )
+ aIntn.SetLongDateCentury( TRUE );
+ aDateAsText = aIntn.GetLongDate( rDate );
+ }
+ else
+ {
+ if ( b4DigitYear && !aIntn.IsDateCentury() )
+ aIntn.SetDateCentury( TRUE );
+ aDateAsText = aIntn.GetDate( rDate );
+ }
+
+ return aDateAsText;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDateIncrementDay( Date& rDate, BOOL bUp )
+{
+ DateFormatter::ExpandCentury( rDate );
+
+ if ( bUp )
+ {
+ if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
+ rDate++;
+ }
+ else
+ {
+ if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
+ rDate--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDateIncrementMonth( Date& rDate, BOOL bUp )
+{
+ DateFormatter::ExpandCentury( rDate );
+
+ USHORT nMonth = rDate.GetMonth();
+ USHORT nYear = rDate.GetYear();
+ if ( bUp )
+ {
+ if ( (nMonth == 12) && (nYear < 9999) )
+ {
+ rDate.SetMonth( 1 );
+ rDate.SetYear( nYear + 1 );
+ }
+ else
+ {
+ if ( nMonth < 12 )
+ rDate.SetMonth( nMonth + 1 );
+ }
+ }
+ else
+ {
+ if ( (nMonth == 1) && (nYear > 0) )
+ {
+ rDate.SetMonth( 12 );
+ rDate.SetYear( nYear - 1 );
+ }
+ else
+ {
+ if ( nMonth > 1 )
+ rDate.SetMonth( nMonth - 1 );
+ }
+ }
+
+ USHORT nDaysInMonth = rDate.GetDaysInMonth();
+ if ( rDate.GetDay() > nDaysInMonth )
+ rDate.SetDay( nDaysInMonth );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDateIncrementYear( Date& rDate, BOOL bUp )
+{
+ DateFormatter::ExpandCentury( rDate );
+
+ USHORT nYear = rDate.GetYear();
+ if ( bUp )
+ {
+ if ( nYear < 9999 )
+ rDate.SetYear( nYear + 1 );
+ }
+ else
+ {
+ if ( nYear > 0 )
+ rDate.SetYear( nYear - 1 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::ImplDateSpinArea( BOOL bUp )
+{
+ // Wenn alles selektiert ist, Tage hochzaehlen
+ if ( GetField() )
+ {
+ Date aDate( GetDate() );
+ Selection aSelection = GetField()->GetSelection();
+ aSelection.Justify();
+ XubString aText( GetText() );
+ if ( (xub_StrLen)aSelection.Len() == aText.Len() )
+ ImplDateIncrementDay( aDate, bUp );
+ else
+ {
+ xub_StrLen nDateArea = 0;
+
+ DateFormat eFormat;
+ if ( IsLongFormat() )
+ eFormat = GetInternational().GetLongDateFormat();
+ else
+ eFormat = GetInternational().GetDateFormat();
+
+ if ( !IsLongFormat() )
+ {
+ // Area suchen
+ xub_StrLen nPos = 0;
+ for ( xub_StrLen i = 1; i <= 3; i++ )
+ {
+ nPos = aText.Search( GetInternational().GetDateSep(), nPos );
+ if ( nPos >= (USHORT)aSelection.Max() )
+ {
+ nDateArea = i;
+ break;
+ }
+ else
+ nPos++;
+ }
+ }
+ else
+ nDateArea = 1;
+
+ switch( eFormat )
+ {
+ case MDY:
+ switch( nDateArea )
+ {
+ case 1: ImplDateIncrementMonth( aDate, bUp );
+ break;
+ case 2: ImplDateIncrementDay( aDate, bUp );
+ break;
+ case 3: ImplDateIncrementYear( aDate, bUp );
+ break;
+ }
+ break;
+ case DMY:
+ switch( nDateArea )
+ {
+ case 1: ImplDateIncrementDay( aDate, bUp );
+ break;
+ case 2: ImplDateIncrementMonth( aDate, bUp );
+ break;
+ case 3: ImplDateIncrementYear( aDate, bUp );
+ break;
+ }
+ break;
+ case YMD:
+ switch( nDateArea )
+ {
+ case 1: ImplDateIncrementYear( aDate, bUp );
+ break;
+ case 2: ImplDateIncrementMonth( aDate, bUp );
+ break;
+ case 3: ImplDateIncrementDay( aDate, bUp );
+ break;
+ }
+ break;
+ }
+ }
+
+ ImplNewFieldValue( aDate );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ImplInit()
+{
+ mbLongFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+DateFormatter::DateFormatter() :
+ maMin( 1, 1, 1900 ),
+ maMax( 31, 12, 2200 ),
+ maFieldDate( 0 ),
+ maLastDate( 0 )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ImplLoadRes( const ResId& )
+{
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask = pMgr->ReadShort();
+
+ if ( DATEFORMATTER_MIN & nMask )
+ {
+ maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
+ }
+ if ( DATEFORMATTER_MAX & nMask )
+ {
+ maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
+ }
+ if ( DATEFORMATTER_LONGFORMAT & nMask )
+ mbLongFormat = (BOOL)pMgr->ReadShort();
+
+ if ( DATEFORMATTER_STRICTFORMAT & nMask )
+ SetStrictFormat( (BOOL)pMgr->ReadShort() );
+
+ if ( DATEFORMATTER_I12 & nMask )
+ {
+ SetInternational( International( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
+ }
+ if ( DATEFORMATTER_VALUE & nMask )
+ {
+ maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
+ if ( maFieldDate > maMax )
+ maFieldDate = maMax;
+ if ( maFieldDate < maMin )
+ maFieldDate = maMin;
+ maLastDate = maFieldDate;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+DateFormatter::~DateFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ReformatAll()
+{
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetMin( const Date& rNewMin )
+{
+ maMin = rNewMin;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetMax( const Date& rNewMax )
+{
+ maMax = rNewMax;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetLongFormat( BOOL bLong )
+{
+ mbLongFormat = bLong;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetDate( const Date& rNewDate )
+{
+ SetUserDate( rNewDate );
+ maFieldDate = maLastDate;
+ maLastDate = GetDate();
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetUserDate( const Date& rNewDate )
+{
+ ImplSetUserDate( rNewDate );
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
+{
+ Date aNewDate = rNewDate;
+ if ( aNewDate > maMax )
+ aNewDate = maMax;
+ else if ( aNewDate < maMin )
+ aNewDate = maMin;
+ maLastDate = aNewDate;
+
+ if ( GetField() )
+ ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ImplNewFieldValue( const Date& rDate )
+{
+ if ( GetField() )
+ {
+ Selection aSelection = GetField()->GetSelection();
+ aSelection.Justify();
+ XubString aText = GetField()->GetText();
+ // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
+ if ( (xub_StrLen)aSelection.Max() == aText.Len() )
+ {
+ if ( !aSelection.Len() )
+ aSelection.Min() = SELECTION_MAX;
+ aSelection.Max() = SELECTION_MAX;
+ }
+
+ Date aOldLastDate = maLastDate;
+ ImplSetUserDate( rDate, &aSelection );
+ maLastDate = aOldLastDate;
+
+ // Modify am Edit wird nur bei KeyInput gesetzt...
+ if ( GetField()->GetText() != aText )
+ {
+ GetField()->SetModifyFlag();
+ GetField()->Modify();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Date DateFormatter::GetDate() const
+{
+ Date aDate( 0, 0, 0 );
+
+ if ( GetField() )
+ {
+ if ( ImplDateGetValue( GetField()->GetText(), aDate,
+ mbLongFormat, GetInternational(),
+ GetFieldSettings() ) )
+ {
+ if ( aDate > maMax )
+ aDate = maMax;
+ else if ( aDate < maMin )
+ aDate = maMin;
+ }
+ else
+ {
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
+ // !!! geklaert werden, warum dieses beim Datum gegenueber
+ // !!! allen anderen Feldern anders behandelt wird.
+ // !!! Siehe dazu Bug: 52304
+
+ if ( maLastDate.GetDate() )
+ aDate = maLastDate;
+ else if ( !IsEmptyFieldValueEnabled() )
+ aDate = Date();
+ }
+ }
+
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+Date DateFormatter::GetRealDate() const
+{
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte dieses auch einmal
+ // !!! fuer die Numeric-Klassen eingebaut werden.
+
+ Date aDate( 0, 0, 0 );
+
+ if ( GetField() )
+ {
+ ImplDateGetValue( GetField()->GetText(), aDate,
+ mbLongFormat, GetInternational(),
+ GetFieldSettings() );
+ }
+
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::SetEmptyDate()
+{
+ FormatterBase::SetEmptyFieldValue();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DateFormatter::IsEmptyDate() const
+{
+ BOOL bEmpty = FormatterBase::IsEmptyFieldValue();
+
+ if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
+ {
+ if ( !GetField()->GetText().Len() )
+ {
+ bEmpty = TRUE;
+ }
+ else if ( !maLastDate.GetDate() )
+ {
+ Date aDate;
+ bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate,
+ mbLongFormat, GetInternational(),
+ GetFieldSettings() );
+ }
+ }
+ return bEmpty;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DateFormatter::IsDateModified() const
+{
+ if ( ImplGetEmptyFieldValue() )
+ return !IsEmptyDate();
+ else if ( GetDate() != maFieldDate )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
+ return;
+
+ XubString aStr;
+ BOOL bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
+ if( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ {
+ ImplSetText( aStr );
+ ImplDateGetValue( aStr, maLastDate, mbLongFormat,
+ GetInternational(), GetFieldSettings() );
+ }
+ else
+ {
+ if ( maLastDate.GetDate() )
+ SetDate( maLastDate );
+ else if ( !IsEmptyFieldValueEnabled() )
+ SetDate( Date() );
+ else
+ {
+ ImplSetText( ImplGetSVEmptyStr() );
+ ImplGetEmptyFieldValue() = TRUE;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ExpandCentury( Date& rDate )
+{
+ ExpandCentury( rDate, Application::GetSettings().GetMiscSettings().GetTwoDigitYearStart() );
+}
+
+// -----------------------------------------------------------------------
+
+void DateFormatter::ExpandCentury( Date& rDate, USHORT nTwoDigitYearStart )
+{
+ USHORT nDateYear = rDate.GetYear();
+ if ( nDateYear < 100 )
+ {
+ USHORT nCentury = nTwoDigitYearStart / 100;
+ if ( nDateYear < (nTwoDigitYearStart % 100) )
+ nCentury++;
+ rDate.SetYear( nDateYear + (nCentury*100) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+DateField::DateField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle ),
+ maFirst( GetMin() ),
+ maLast( GetMax() )
+{
+ SetField( this );
+ SetText( GetInternational().GetDate( ImplGetFieldDate() ) );
+ Reformat();
+ ResetLastDate();
+}
+
+// -----------------------------------------------------------------------
+
+DateField::DateField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_DATEFIELD ),
+ maFirst( GetMin() ),
+ maLast( GetMax() )
+{
+ rResId.SetRT( RSC_DATEFIELD );
+ WinBits nStyle = ImplInitRes( rResId );
+ SpinField::ImplInit( pParent, nStyle );
+ SetField( this );
+ SetText( GetInternational().GetDate( ImplGetFieldDate() ) );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+
+ ResetLastDate();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( DATEFIELD_FIRST & nMask )
+ {
+ maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+ if ( DATEFIELD_LAST & nMask )
+ {
+ maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+DateField::~DateField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long DateField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsLongFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long DateField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() )
+ {
+ // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
+ // !!! geklaert werden, warum dieses beim Datum gegenueber
+ // !!! allen anderen Feldern anders behandelt wird.
+ // !!! Siehe dazu Bug: 52304
+
+ BOOL bTextLen = GetText().Len() != 0;
+ if ( bTextLen || !IsEmptyFieldValueEnabled() )
+ Reformat();
+ else if ( !bTextLen && IsEmptyFieldValueEnabled() )
+ {
+ ResetLastDate();
+ ImplGetEmptyFieldValue() = TRUE;
+ }
+ }
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SpinField::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & (SETTINGS_INTERNATIONAL | SETTINGS_MISC)) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::Up()
+{
+ ImplDateSpinArea( TRUE );
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::Down()
+{
+ ImplDateSpinArea( FALSE );
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::First()
+{
+ ImplNewFieldValue( maFirst );
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::Last()
+{
+ ImplNewFieldValue( maLast );
+ SpinField::Last();
+}
+
+// -----------------------------------------------------------------------
+
+void DateField::SetExtFormat( ExtDateFieldFormat eFormat )
+{
+ Date aDate = GetDate();
+ International aInt( Application::GetAppInternational() );
+
+ BOOL bLongFormat = FALSE; // immer bis auf XTDATEF_SYSTEM_LONG
+
+ switch ( eFormat )
+ {
+ case XTDATEF_SYSTEM_SHORT:
+ {
+ }
+ break;
+ case XTDATEF_SYSTEM_SHORT_YY:
+ {
+ aInt.SetDateCentury( FALSE );
+ }
+ break;
+ case XTDATEF_SYSTEM_SHORT_YYYY:
+ {
+ aInt.SetDateCentury( TRUE );
+ }
+ break;
+ case XTDATEF_SYSTEM_LONG:
+ {
+ bLongFormat = TRUE;
+ }
+ break;
+ case XTDATEF_SHORT_DDMMYY:
+ {
+ aInt.SetDateCentury( FALSE );
+ aInt.SetDateFormat( DMY );
+ }
+ break;
+ case XTDATEF_SHORT_MMDDYY:
+ {
+ aInt.SetDateCentury( FALSE );
+ aInt.SetDateFormat( MDY );
+ }
+ break;
+ case XTDATEF_SHORT_YYMMDD:
+ {
+ aInt.SetDateCentury( FALSE );
+ aInt.SetDateFormat( YMD );
+ }
+ break;
+ case XTDATEF_SHORT_DDMMYYYY:
+ {
+ aInt.SetDateCentury( TRUE );
+ aInt.SetDateFormat( DMY );
+ }
+ break;
+ case XTDATEF_SHORT_MMDDYYYY:
+ {
+ aInt.SetDateCentury( TRUE );
+ aInt.SetDateFormat( MDY );
+ }
+ break;
+ case XTDATEF_SHORT_YYYYMMDD:
+ {
+ aInt.SetDateCentury( TRUE );
+ aInt.SetDateFormat( YMD );
+ }
+ break;
+ case XTDATEF_SHORT_YYMMDD_DIN5008:
+ {
+ aInt.SetDateCentury( FALSE );
+ aInt.SetDateSep( '-' );
+ aInt.SetDateFormat( YMD );
+ }
+ break;
+ case XTDATEF_SHORT_YYYYMMDD_DIN5008:
+ {
+ aInt.SetDateCentury( TRUE );
+ aInt.SetDateSep( '-' );
+ aInt.SetDateFormat( YMD );
+ }
+ break;
+ default: DBG_ERROR( "ExtDateFieldFormat unknown!" );
+ }
+
+ SetInternational( aInt );
+ SetLongFormat( bLongFormat );
+ if ( GetField() && GetField()->GetText().Len() )
+ SetUserDate( aDate );
+}
+
+// -----------------------------------------------------------------------
+
+DateBox::DateBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ SetText( GetInternational().GetDate( ImplGetFieldDate() ) );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+DateBox::DateBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_DATEBOX )
+{
+ rResId.SetRT( RSC_DATEBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ComboBox::ImplInit( pParent, nStyle );
+ SetField( this );
+ SetText( GetInternational().GetDate( ImplGetFieldDate() ) );
+ ComboBox::ImplLoadRes( rResId );
+ DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ Reformat();
+
+ if ( !( nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+DateBox::~DateBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long DateBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsLongFormat(), GetInternational() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+long DateBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() )
+ {
+ BOOL bTextLen = GetText().Len() != 0;
+ if ( bTextLen || !IsEmptyFieldValueEnabled() )
+ Reformat();
+ else if ( !bTextLen && IsEmptyFieldValueEnabled() )
+ {
+ ResetLastDate();
+ ImplGetEmptyFieldValue() = TRUE;
+ }
+ }
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DateBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void DateBox::ReformatAll()
+{
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ DateFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void DateBox::InsertDate( const Date& rDate, USHORT nPos )
+{
+ Date aDate = rDate;
+ if ( aDate > GetMax() )
+ aDate = GetMax();
+ else if ( aDate < GetMin() )
+ aDate = GetMin();
+
+ ComboBox::InsertEntry( ImplGetDateAsText( aDate, GetFieldSettings() ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void DateBox::RemoveDate( const Date& rDate )
+{
+ ComboBox::RemoveEntry( ImplGetDateAsText( rDate, GetFieldSettings() ) );
+}
+
+// -----------------------------------------------------------------------
+
+Date DateBox::GetDate( USHORT nPos ) const
+{
+ Date aDate( 0, 0, 0 );
+ ImplDateGetValue( ComboBox::GetEntry( nPos ), aDate, IsLongFormat(),
+ GetInternational(), GetSettings() );
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT DateBox::GetDatePos( const Date& rDate ) const
+{
+ XubString aStr;
+ if ( IsLongFormat() )
+ aStr = GetInternational().GetLongDate( rDate );
+ else
+ aStr = GetInternational().GetDate( rDate );
+ return ComboBox::GetEntryPos( aStr );
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
+ BOOL bStrictFormat, BOOL bDuration,
+ TimeFieldFormat eFormat,
+ const International& rInter )
+{
+ xub_Unicode cChar = rKEvt.GetCharCode();
+
+ if ( !bStrictFormat )
+ return FALSE;
+ else
+ {
+ USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
+ if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
+ (nGroup == KEYGROUP_MISC) ||
+ ((cChar >= '0') && (cChar <= '9')) ||
+ (cChar == rInter.GetTimeSep()) ||
+ ((eFormat == TIMEF_100TH_SEC) && (cChar == rInter.GetTime100SecSep())) ||
+ ((eFormat == TIMEF_SEC_CS) && (cChar == rInter.GetTime100SecSep())) ||
+ (bDuration && (cChar == '-')) )
+ return FALSE;
+ else
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplTimeGetValue( const XubString& rStr, Time& rTime,
+ TimeFieldFormat eTimeFormat, BOOL bDuration,
+ const International& rInter )
+{
+ XubString aStr = rStr;
+ short nHour = 0;
+ short nMinute = 0;
+ short nSecond = 0;
+ short n100Sec = 0;
+ Time aTime( 0, 0, 0 );
+
+ if ( !rStr.Len() )
+ return FALSE;
+
+ // Nach Separatoren suchen
+ XubString aSepStr( RTL_CONSTASCII_USTRINGPARAM( ",.;:/" ) );
+ if ( !bDuration )
+ aSepStr.Append( '-' );
+
+ // Die obigen Zeichen durch das Separatorzeichen ersetzen
+ for ( xub_StrLen i = 0; i < aSepStr.Len(); i++ )
+ {
+ if ( aSepStr.GetChar( i ) == rInter.GetTimeSep() )
+ continue;
+ for ( xub_StrLen j = 0; j < aStr.Len(); j++ )
+ {
+ if ( aStr.GetChar( j ) == aSepStr.GetChar( i ) )
+ aStr.SetChar( j, rInter.GetTimeSep() );
+ }
+ }
+
+ BOOL bNegative = FALSE;
+ xub_StrLen nSepPos = aStr.Search( rInter.GetTimeSep() );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ if ( eTimeFormat != TIMEF_SEC_CS )
+ {
+ if ( nSepPos == STRING_NOTFOUND )
+ return FALSE;
+ nHour = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+
+ nSepPos = aStr.Search( rInter.GetTimeSep() );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ if ( nSepPos != STRING_NOTFOUND )
+ {
+ nMinute = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+
+ nSepPos = aStr.Search( rInter.GetTimeSep() );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ if ( nSepPos != STRING_NOTFOUND )
+ {
+ nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ n100Sec = (short)aStr.ToInt32();
+ }
+ else
+ nSecond = (short)aStr.ToInt32();
+ }
+ else
+ nMinute = (short)aStr.ToInt32();
+ }
+ else if ( nSepPos == STRING_NOTFOUND )
+ {
+ nSecond = (short)aStr.ToInt32();
+ nMinute += nSecond / 60;
+ nSecond %= 60;
+ nHour += nMinute / 60;
+ nMinute %= 60;
+ }
+ else
+ {
+ nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+
+ nSepPos = aStr.Search( rInter.GetTimeSep() );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ if ( nSepPos != STRING_NOTFOUND )
+ {
+ nMinute = nSecond;
+ nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+
+ nSepPos = aStr.Search( rInter.GetTimeSep() );
+ if ( aStr.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ if ( nSepPos != STRING_NOTFOUND )
+ {
+ nHour = nMinute;
+ nMinute = nSecond;
+ nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
+ aStr.Erase( 0, nSepPos+1 );
+ }
+ else
+ {
+ nHour += nMinute / 60;
+ nMinute %= 60;
+ }
+ }
+ else
+ {
+ nMinute += nSecond / 60;
+ nSecond %= 60;
+ nHour += nMinute / 60;
+ nMinute %= 60;
+ }
+ n100Sec = (short)aStr.ToInt32();
+
+ if ( n100Sec )
+ {
+ xub_StrLen nLen = 1; // mindestens eine Ziffer, weil sonst n100Sec==0
+
+ while ( aStr.GetChar(nLen) >= '0' && aStr.GetChar(nLen) <= '9' )
+ nLen++;
+
+ if ( nLen > 2 )
+ {
+ while( nLen > 3 )
+ {
+ n100Sec = n100Sec / 10;
+ nLen--;
+ }
+ // Rundung bei negativen Zahlen???
+ n100Sec = (n100Sec + 5) / 10;
+ }
+ else
+ {
+ while( nLen < 2 )
+ {
+ n100Sec = n100Sec * 10;
+ nLen++;
+ }
+ }
+ }
+ }
+
+ if ( (nMinute > 59) || (nSecond > 59) || (n100Sec > 100) )
+ return FALSE;
+
+ if ( eTimeFormat == TIMEF_NONE )
+ nSecond = n100Sec = 0;
+ else if ( eTimeFormat == TIMEF_SEC )
+ n100Sec = 0;
+
+ if ( !bDuration )
+ {
+ if ( bNegative || (nHour < 0) || (nMinute < 0) ||
+ (nSecond < 0) || (n100Sec < 0) )
+ return FALSE;
+
+ aStr.ToUpperAscii();
+ XubString aAM( rInter.GetTimeAM() );
+ XubString aPM( rInter.GetTimePM() );
+ aAM.ToUpperAscii();
+ aPM.ToUpperAscii();
+
+ if ( (aStr.Search( aPM ) != STRING_NOTFOUND) && (nHour < 12) )
+ nHour += 12;
+ if ( (aStr.Search( aAM ) != STRING_NOTFOUND) && (nHour == 12) )
+ nHour = 0;
+
+ aTime = Time( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond,
+ (USHORT)n100Sec );
+ }
+ else
+ {
+ if ( bNegative || (nHour < 0) || (nMinute < 0) ||
+ (nSecond < 0) || (n100Sec < 0) )
+ {
+ bNegative = TRUE;
+ nHour = nHour < 0 ? -nHour : nHour;
+ nMinute = nMinute < 0 ? -nMinute : nMinute;
+ nSecond = nSecond < 0 ? -nSecond : nSecond;
+ n100Sec = n100Sec < 0 ? -n100Sec : n100Sec;
+ }
+
+ aTime = Time( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond,
+ (USHORT)n100Sec );
+ if ( bNegative )
+ aTime = -aTime;
+ }
+
+ rTime = aTime;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TimeFormatter::ImplTimeReformat( const XubString& rStr, XubString& rOutStr )
+{
+ Time aTime( 0, 0, 0 );
+ if ( !ImplTimeGetValue( rStr, aTime, meFormat, mbDuration, GetInternational() ) )
+ return TRUE;
+
+ Time aTempTime = aTime;
+ if ( aTempTime > GetMax() )
+ aTempTime = GetMax() ;
+ else if ( aTempTime < GetMin() )
+ aTempTime = GetMin();
+
+ if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
+ {
+ maCorrectedTime = aTempTime;
+ if ( !GetErrorHdl().Call( this ) )
+ {
+ maCorrectedTime = Time();
+ return FALSE;
+ }
+ else
+ maCorrectedTime = Time();
+ }
+
+ BOOL bSecond = FALSE;
+ BOOL b100Sec = FALSE;
+ if ( meFormat != TIMEF_NONE )
+ bSecond = TRUE;
+ if ( meFormat == TIMEF_100TH_SEC )
+ b100Sec = TRUE;
+
+ if ( meFormat == TIMEF_SEC_CS )
+ {
+ ULONG n = aTempTime.GetHour() * 3600L;
+ n += aTempTime.GetMin() * 60L;
+ n += aTempTime.GetSec();
+ rOutStr = String::CreateFromInt32( n );
+ rOutStr += GetInternational().GetTime100SecSep();
+ if ( aTempTime.Get100Sec() < 10 )
+ rOutStr += '0';
+ rOutStr += String::CreateFromInt32( aTempTime.Get100Sec() );
+ }
+ else if ( mbDuration )
+ rOutStr = GetInternational().GetDuration( aTempTime, bSecond, b100Sec );
+ else
+ rOutStr = GetInternational().GetTime( aTempTime, bSecond, b100Sec );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::ImplTimeSpinArea( BOOL bUp )
+{
+ if ( GetField() )
+ {
+ xub_StrLen nTimeArea = 0;
+ xub_StrLen nPos;
+
+ Time aTime( GetTime() );
+ XubString aText( GetText() );
+ Selection aSelection( GetField()->GetSelection() );
+
+ // Area suchen
+ if ( meFormat != TIMEF_SEC_CS )
+ {
+ for ( xub_StrLen i = 1, nPos = 0; i <= 4; i++ )
+ {
+ xub_StrLen nPos1 = aText.Search( GetInternational().GetTimeSep(), nPos );
+ xub_StrLen nPos2 = aText.Search( GetInternational().GetTime100SecSep(), nPos );
+ nPos = nPos1 < nPos2 ? nPos1 : nPos2;
+ if ( nPos >= (xub_StrLen)aSelection.Max() )
+ {
+ nTimeArea = i;
+ break;
+ }
+ else
+ nPos++;
+ }
+ }
+ else
+ {
+ nPos = aText.Search( GetInternational().GetTime100SecSep() );
+ if ( nPos == STRING_NOTFOUND || nPos >= (xub_StrLen)aSelection.Max() )
+ nTimeArea = 3;
+ else
+ nTimeArea = 4;
+ }
+
+ if ( nTimeArea )
+ {
+ Time aAddTime( 0, 0, 0 );
+ if ( nTimeArea == 1 )
+ aAddTime = Time( 1, 0 );
+ else if ( nTimeArea == 2 )
+ aAddTime = Time( 0, 1 );
+ else if ( nTimeArea == 3 )
+ aAddTime = Time( 0, 0, 1 );
+ else if ( nTimeArea == 4 )
+ aAddTime = Time( 0, 0, 0, 1 );
+
+ if ( !bUp )
+ aAddTime = -aAddTime;
+
+ aTime += aAddTime;
+ if ( !mbDuration )
+ {
+ Time aAbsMaxTime( 23, 59, 59, 99 );
+ if ( aTime > aAbsMaxTime )
+ aTime = aAbsMaxTime;
+ Time aAbsMinTime( 0, 0 );
+ if ( aTime < aAbsMinTime )
+ aTime = aAbsMinTime;
+ }
+ ImplNewFieldValue( aTime );
+ }
+
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::ImplInit()
+{
+ meFormat = TIMEF_NONE;
+ mbDuration = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+TimeFormatter::TimeFormatter() :
+ maMin( 0, 0 ),
+ maMax( 23, 59, 59, 99 ),
+ maFieldTime( 0, 0 ),
+ maLastTime( 0, 0 )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::ImplLoadRes( const ResId& )
+{
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask = pMgr->ReadShort();
+
+ if ( TIMEFORMATTER_MIN & nMask )
+ {
+ SetMin( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+
+ if ( TIMEFORMATTER_MAX & nMask )
+ {
+ SetMax( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+
+ if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
+ meFormat = (TimeFieldFormat)pMgr->ReadShort();
+
+ if ( TIMEFORMATTER_DURATION & nMask )
+ mbDuration = (BOOL)pMgr->ReadShort();
+
+ if ( TIMEFORMATTER_STRICTFORMAT & nMask )
+ SetStrictFormat( (BOOL)pMgr->ReadShort() );
+
+ if ( TIMEFORMATTER_I12 & nMask )
+ {
+ SetInternational( International( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+
+ if ( TIMEFORMATTER_VALUE & nMask )
+ {
+ maFieldTime = Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ if ( maFieldTime > GetMax() )
+ maFieldTime = GetMax();
+ if ( maFieldTime < GetMin() )
+ maFieldTime = GetMin();
+ maLastTime = maFieldTime;
+
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TimeFormatter::~TimeFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::ReformatAll()
+{
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetMin( const Time& rNewMin )
+{
+ maMin = rNewMin;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetMax( const Time& rNewMax )
+{
+ maMax = rNewMax;
+ if ( !IsEmptyFieldValue() )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
+{
+ meFormat = eNewFormat;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetDuration( BOOL bNewDuration )
+{
+ mbDuration = bNewDuration;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetTime( const Time& rNewTime )
+{
+ SetUserTime( rNewTime );
+ maFieldTime = maLastTime;
+ ImplGetEmptyFieldValue() = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::ImplNewFieldValue( const Time& rTime )
+{
+ if ( GetField() )
+ {
+ Selection aSelection = GetField()->GetSelection();
+ aSelection.Justify();
+ XubString aText = GetField()->GetText();
+ // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
+ if ( (xub_StrLen)aSelection.Max() == aText.Len() )
+ {
+ if ( !aSelection.Len() )
+ aSelection.Min() = SELECTION_MAX;
+ aSelection.Max() = SELECTION_MAX;
+ }
+
+ Time aOldLastTime = maLastTime;
+ ImplSetUserTime( rTime, &aSelection );
+ maLastTime = aOldLastTime;
+
+ // Modify am Edit wird nur bei KeyInput gesetzt...
+ if ( GetField()->GetText() != aText )
+ {
+ GetField()->SetModifyFlag();
+ GetField()->Modify();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::ImplSetUserTime( const Time& rNewTime, Selection* pNewSelection )
+{
+ Time aNewTime = rNewTime;
+ if ( aNewTime > GetMax() )
+ aNewTime = GetMax();
+ else if ( aNewTime < GetMin() )
+ aNewTime = GetMin();
+ maLastTime = aNewTime;
+
+ if ( GetField() )
+ {
+ XubString aStr;
+ BOOL bSec = FALSE;
+ BOOL b100Sec = FALSE;
+ if ( meFormat != TIMEF_NONE )
+ bSec = TRUE;
+ if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS )
+ b100Sec = TRUE;
+ if ( meFormat == TIMEF_SEC_CS )
+ {
+ ULONG n = aNewTime.GetHour() * 3600L;
+ n += aNewTime.GetMin() * 60L;
+ n += aNewTime.GetSec();
+ aStr = String::CreateFromInt32( n );
+ aStr += GetInternational().GetTime100SecSep();
+ if ( aNewTime.Get100Sec() < 10 )
+ aStr += '0';
+ aStr += String::CreateFromInt32( aNewTime.Get100Sec() );
+ }
+ else if ( mbDuration )
+ aStr = GetInternational().GetDuration( aNewTime, bSec, b100Sec );
+ else
+ aStr = GetInternational().GetTime( aNewTime, bSec, b100Sec );
+
+ ImplSetText( aStr, pNewSelection );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::SetUserTime( const Time& rNewTime )
+{
+ ImplSetUserTime( rNewTime );
+}
+
+// -----------------------------------------------------------------------
+
+Time TimeFormatter::GetTime() const
+{
+ Time aTime( 0, 0, 0 );
+
+ if ( GetField() )
+ {
+ if ( ImplTimeGetValue( GetField()->GetText(), aTime,
+ meFormat, mbDuration, GetInternational() ) )
+ {
+ if ( aTime > GetMax() )
+ aTime = GetMax();
+ else if ( aTime < GetMin() )
+ aTime = GetMin();
+ }
+ else
+ aTime = maLastTime;
+ }
+
+ return aTime;
+}
+
+// -----------------------------------------------------------------------
+
+Time TimeFormatter::GetRealTime() const
+{
+ Time aTime( 0, 0, 0 );
+
+ if ( GetField() )
+ {
+ ImplTimeGetValue( GetField()->GetText(), aTime,
+ meFormat, mbDuration, GetInternational() );
+ }
+
+ return aTime;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TimeFormatter::IsTimeModified() const
+{
+ if ( ImplGetEmptyFieldValue() )
+ return !IsEmptyTime();
+ else if ( GetTime() != maFieldTime )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void TimeFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
+ return;
+
+ XubString aStr;
+ BOOL bOK = ImplTimeReformat( GetField()->GetText(), aStr );
+ if ( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ {
+ ImplSetText( aStr );
+ ImplTimeGetValue( aStr, maLastTime, meFormat, mbDuration, GetInternational() );
+ }
+ else
+ SetTime( maLastTime );
+}
+
+// -----------------------------------------------------------------------
+
+TimeField::TimeField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle ),
+ maFirst( GetMin() ),
+ maLast( GetMax() )
+{
+ SetField( this );
+ SetText( GetInternational().GetTime( maFieldTime, FALSE, FALSE ) );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+TimeField::TimeField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_TIMEFIELD ),
+ maFirst( GetMin() ),
+ maLast( GetMax() )
+{
+ rResId.SetRT( RSC_TIMEFIELD );
+ WinBits nStyle = ImplInitRes( rResId );
+ SpinField::ImplInit( pParent, nStyle );
+ SetField( this );
+ SetText( GetInternational().GetTime( maFieldTime, FALSE, FALSE ) );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( TIMEFIELD_FIRST & nMask )
+ {
+ maFirst = Time( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+ if ( TIMEFIELD_LAST & nMask )
+ {
+ maLast = Time( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+TimeField::~TimeField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long TimeField::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), mbDuration, meFormat, GetInternational() ) )
+ return 1;
+ }
+
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long TimeField::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SpinField::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::Up()
+{
+ ImplTimeSpinArea( TRUE );
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::Down()
+{
+ ImplTimeSpinArea( FALSE );
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::First()
+{
+ ImplNewFieldValue( maFirst );
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::Last()
+{
+ ImplNewFieldValue( maLast );
+ SpinField::Last();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
+{
+ Time aTime = GetTime();
+ International aInt( Application::GetAppInternational() );
+
+ switch ( eFormat )
+ {
+ case EXTTIMEF_24H_SHORT:
+ {
+ aInt.SetTimeFormat( HOUR_24 );
+ SetDuration( FALSE );
+ SetFormat( TIMEF_NONE );
+ }
+ break;
+ case EXTTIMEF_24H_LONG:
+ {
+ aInt.SetTimeFormat( HOUR_24 );
+ SetDuration( FALSE );
+ SetFormat( TIMEF_SEC );
+ }
+ break;
+ case EXTTIMEF_12H_SHORT:
+ {
+ aInt.SetTimeFormat( HOUR_12 );
+ SetDuration( FALSE );
+ SetFormat( TIMEF_NONE );
+ }
+ break;
+ case EXTTIMEF_12H_LONG:
+ {
+ aInt.SetTimeFormat( HOUR_12 );
+ SetDuration( FALSE );
+ SetFormat( TIMEF_SEC );
+ }
+ break;
+ case EXTTIMEF_DURATION_SHORT:
+ {
+ SetDuration( TRUE );
+ SetFormat( TIMEF_NONE );
+ }
+ break;
+ case EXTTIMEF_DURATION_LONG:
+ {
+ SetDuration( TRUE );
+ SetFormat( TIMEF_SEC );
+ }
+ break;
+ default: DBG_ERROR( "ExtTimeFieldFormat unknown!" );
+ }
+
+ SetInternational( aInt );
+ if ( GetField() && GetField()->GetText().Len() )
+ SetUserTime( aTime );
+}
+
+// -----------------------------------------------------------------------
+
+TimeBox::TimeBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ SetText( GetInternational().GetTime( maFieldTime, FALSE, FALSE ) );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+TimeBox::TimeBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_TIMEBOX )
+{
+ rResId.SetRT( RSC_TIMEBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ComboBox::ImplInit( pParent, nStyle );
+ SetField( this );
+ SetText( GetInternational().GetTime( maFieldTime, FALSE, FALSE ) );
+ ComboBox::ImplLoadRes( rResId );
+ TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+TimeBox::~TimeBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long TimeBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) &&
+ !rNEvt.GetKeyEvent()->GetKeyCode().IsControlMod() )
+ {
+ if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), mbDuration, meFormat, GetInternational() ) )
+ return 1;
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long TimeBox::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_GETFOCUS )
+ MarkToBeReformatted( FALSE );
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
+ Reformat();
+ }
+
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_INTERNATIONAL) )
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void TimeBox::ReformatAll()
+{
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplTimeReformat( GetEntry( i ), aStr );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ TimeFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void TimeBox::InsertTime( const Time& rTime, USHORT nPos )
+{
+ Time aTime = rTime;
+ if ( aTime > GetMax() )
+ aTime = GetMax();
+ else if ( aTime < GetMin() )
+ aTime = GetMin();
+
+ BOOL bSec = FALSE;
+ BOOL b100Sec = FALSE;
+ if ( meFormat == TIMEF_SEC )
+ bSec = TRUE;
+ if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS )
+ bSec = b100Sec = TRUE;
+ ComboBox::InsertEntry( GetInternational().GetTime( aTime, bSec, b100Sec ), nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void TimeBox::RemoveTime( const Time& rTime )
+{
+ BOOL bSec = FALSE;
+ BOOL b100Sec = FALSE;
+ if ( meFormat == TIMEF_SEC )
+ bSec = TRUE;
+ if ( meFormat == TIMEF_100TH_SEC || TIMEF_SEC_CS )
+ bSec = b100Sec = TRUE;
+ ComboBox::RemoveEntry( GetInternational().GetTime( rTime, bSec, b100Sec ) );
+}
+
+// -----------------------------------------------------------------------
+
+Time TimeBox::GetTime( USHORT nPos ) const
+{
+ Time aTime( 0, 0, 0 );
+ ImplTimeGetValue( ComboBox::GetEntry( nPos ), aTime,
+ meFormat, mbDuration, GetInternational() );
+ return aTime;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TimeBox::GetTimePos( const Time& rTime ) const
+{
+ BOOL bSec = FALSE;
+ BOOL b100Sec = FALSE;
+ if ( meFormat == TIMEF_SEC )
+ bSec = TRUE;
+ if ( meFormat == TIMEF_100TH_SEC || TIMEF_SEC_CS )
+ bSec = b100Sec = TRUE;
+ return ComboBox::GetEntryPos( GetInternational().GetTime( rTime, bSec, b100Sec ) );
+}
diff --git a/vcl/source/control/fixbrd.cxx b/vcl/source/control/fixbrd.cxx
new file mode 100644
index 000000000000..e7ca718c2537
--- /dev/null
+++ b/vcl/source/control/fixbrd.cxx
@@ -0,0 +1,255 @@
+/*************************************************************************
+ *
+ * $RCSfile: fixbrd.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FIXBRD_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_FIXBRD_HXX
+#include <fixbrd.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void FixedBorder::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mnType = FIXEDBORDER_TYPE_DOUBLEOUT;
+ mbTransparent = TRUE;
+
+ nStyle = ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FixedBorder::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::ImplInitSettings()
+{
+ Window* pParent = GetParent();
+ if ( (pParent->IsChildTransparentModeEnabled() ||
+ !(pParent->GetStyle() & WB_CLIPCHILDREN) ) &&
+ !IsControlBackground() && mbTransparent )
+ {
+ SetMouseTransparent( TRUE );
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ SetMouseTransparent( FALSE );
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FixedBorder::FixedBorder( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_FIXEDBORDER )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FixedBorder::FixedBorder( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_FIXEDBORDER )
+{
+ rResId.SetRT( RSC_CONTROL );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+FixedBorder::~FixedBorder()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aRect( rPos, rSize );
+ USHORT nBorderStyle = mnType;
+
+ if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
+ (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ nBorderStyle |= FRAME_DRAW_MONO;
+
+ DecorationView aDecoView( pDev );
+ aDecoView.DrawFrame( aRect, nBorderStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::Paint( const Rectangle& rRect )
+{
+ ImplDraw( this, 0, Point(), GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ ImplDraw( pDev, nFlags, aPos, aSize );
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::SetTransparent( BOOL bTransparent )
+{
+ if ( mbTransparent != bTransparent )
+ {
+ mbTransparent = bTransparent;
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBorder::SetBorderType( USHORT nType )
+{
+ if ( mnType != nType )
+ {
+ mnType = nType;
+ Invalidate();
+ }
+}
diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx
new file mode 100644
index 000000000000..54cab781ebe2
--- /dev/null
+++ b/vcl/source/control/fixed.cxx
@@ -0,0 +1,1051 @@
+/*************************************************************************
+ *
+ * $RCSfile: fixed.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FIXED_CXX
+
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_FIXED_HXX
+#include <fixed.hxx>
+#endif
+
+#include <rc.h>
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define FIXEDLINE_BORDER 12
+#define FIXEDLINE_TEXT_BORDER 2
+
+#define FIXEDTEXT_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_WORDBREAK | WB_NOLABEL | \
+ WB_INFO | WB_PATHELLIPSIS)
+#define FIXEDLINE_VIEW_STYLE (WB_3DLOOK | WB_NOLABEL)
+#define FIXEDBITMAP_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_SCALE)
+#define FIXEDIMAGE_VIEW_STYLE (WB_3DLOOK | \
+ WB_LEFT | WB_CENTER | WB_RIGHT | \
+ WB_TOP | WB_VCENTER | WB_BOTTOM | \
+ WB_SCALE)
+
+// =======================================================================
+
+static Point ImplCalcPos( WinBits nStyle, const Point& rPos,
+ const Size& rObjSize, const Size& rWinSize )
+{
+ long nX;
+ long nY;
+
+ if ( nStyle & WB_LEFT )
+ nX = 0;
+ else if ( nStyle & WB_RIGHT )
+ nX = rWinSize.Width()-rObjSize.Width();
+ else
+ nX = (rWinSize.Width()-rObjSize.Width())/2;
+
+ if ( nStyle & WB_TOP )
+ nY = 0;
+ else if ( nStyle & WB_BOTTOM )
+ nX = rWinSize.Height()-rObjSize.Height();
+ else
+ nY = (rWinSize.Height()-rObjSize.Height())/2;
+
+ if ( nStyle & WB_TOPLEFTVISIBLE )
+ {
+ if ( nX < 0 )
+ nX = 0;
+ if ( nY < 0 )
+ nY = 0;
+ }
+
+ Point aPos( nX+rPos.X(), nY+rPos.Y() );
+ return aPos;
+}
+
+// =======================================================================
+
+void FixedText::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FixedText::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont;
+ if ( GetStyle() & WB_INFO )
+ aFont = rStyleSettings.GetInfoFont();
+ else
+ aFont = rStyleSettings.GetLabelFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ {
+ if ( GetStyle() & WB_INFO )
+ aColor = rStyleSettings.GetInfoTextColor();
+ else
+ aColor = rStyleSettings.GetLabelTextColor();
+ }
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FixedText::FixedText( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_FIXEDTEXT )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FixedText::FixedText( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_FIXEDTEXT )
+{
+ rResId.SetRT( RSC_TEXT );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT FixedText::ImplGetTextStyle( WinBits nWinStyle )
+{
+ USHORT nTextStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_MULTILINE | TEXT_DRAW_ENDELLIPSIS;
+
+ if ( nWinStyle & WB_RIGHT )
+ nTextStyle |= TEXT_DRAW_RIGHT;
+ else if ( nWinStyle & WB_CENTER )
+ nTextStyle |= TEXT_DRAW_CENTER;
+ else
+ nTextStyle |= TEXT_DRAW_LEFT;
+ if ( nWinStyle & WB_BOTTOM )
+ nTextStyle |= TEXT_DRAW_BOTTOM;
+ else if ( nWinStyle & WB_VCENTER )
+ nTextStyle |= TEXT_DRAW_VCENTER;
+ else
+ nTextStyle |= TEXT_DRAW_TOP;
+ if ( nWinStyle & WB_WORDBREAK )
+ nTextStyle |= TEXT_DRAW_WORDBREAK;
+ if ( nWinStyle & WB_NOLABEL )
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+
+ return nTextStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ WinBits nWinStyle = GetStyle();
+ XubString aText( GetText() );
+ USHORT nTextStyle = FixedText::ImplGetTextStyle( nWinStyle );
+
+ if ( nWinStyle & WB_PATHELLIPSIS )
+ {
+ nTextStyle &= ~(TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK);
+ nTextStyle |= TEXT_DRAW_PATHELLIPSIS;
+ }
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
+ (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ nTextStyle |= TEXT_DRAW_MONO;
+
+ pDev->DrawText( Rectangle( rPos, rSize ), aText, nTextStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::Paint( const Rectangle& rRect )
+{
+ ImplDraw( this, 0, Point(), GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = GetDrawPixelFont( pDev );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ // Border
+ if ( !(nFlags & WINDOW_DRAW_NOBORDER) && (GetStyle() & WB_BORDER) )
+ {
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ pDev->SetFillColor();
+ pDev->DrawRect( Rectangle( aPos, aSize ) );
+ }
+
+ ImplDraw( pDev, nFlags, aPos, aSize );
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ if ( (GetPrevStyle() & FIXEDTEXT_VIEW_STYLE) !=
+ (GetStyle() & FIXEDTEXT_VIEW_STYLE) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedText::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size FixedText::CalcMinimumSize( long nMaxWidth ) const
+{
+ USHORT nStyle = ImplGetTextStyle( GetStyle() );
+ if ( !( GetStyle() & WB_NOLABEL ) )
+ nStyle |= TEXT_DRAW_MNEMONIC;
+
+ Size aSize = GetTextRect( Rectangle( Point(), Size( (nMaxWidth ? nMaxWidth : 0x7fffffff)-FIXEDLINE_BORDER, 0x7fffffff ) ),
+ GetText(), nStyle ).GetSize();
+
+ // GetTextRect verkraftet keinen leeren String:
+ if ( aSize.Width() < 0 )
+ aSize.Width() = 0;
+ if ( aSize.Height() <= 0 )
+ aSize.Height() = GetTextHeight();
+
+ return CalcWindowSize( aSize );
+}
+
+
+// =======================================================================
+
+void FixedLine::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FixedLine::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetGroupFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetGroupTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FixedLine::FixedLine( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_FIXEDLINE )
+{
+ ImplInit( pParent, nStyle );
+ SetSizePixel( Size( 2, 2 ) );
+}
+
+// -----------------------------------------------------------------------
+
+FixedLine::FixedLine( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_FIXEDLINE )
+{
+ rResId.SetRT( RSC_FIXEDLINE );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::Paint( const Rectangle& rRect )
+{
+ Size aOutSize = GetOutputSizePixel();
+ String aText = GetText();
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ WinBits nWinStyle = GetStyle();
+
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ SetLineColor( Color( COL_BLACK ) );
+ else
+ SetLineColor( rStyleSettings.GetShadowColor() );
+
+ if ( !aText.Len() || (nWinStyle & WB_VERT) )
+ {
+ long nX;
+ long nY;
+
+ if ( nWinStyle & WB_VERT )
+ {
+ nX = (aOutSize.Width()-1)/2;
+ DrawLine( Point( nX, 0 ), Point( nX, aOutSize.Height()-1 ) );
+ }
+ else
+ {
+ nY = (aOutSize.Height()-1)/2;
+ DrawLine( Point( 0, nY ), Point( aOutSize.Width()-1, nY ) );
+ }
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetLightColor() );
+ if ( nWinStyle & WB_VERT )
+ DrawLine( Point( nX+1, 0 ), Point( nX+1, aOutSize.Height()-1 ) );
+ else
+ DrawLine( Point( 0, nY+1 ), Point( aOutSize.Width()-1, nY+1 ) );
+ }
+ }
+ else
+ {
+ USHORT nStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER | TEXT_DRAW_ENDELLIPSIS;
+ Rectangle aRect( FIXEDLINE_BORDER, 0, aOutSize.Width()-FIXEDLINE_BORDER, aOutSize.Height() );
+
+ if ( !IsEnabled() )
+ nStyle |= TEXT_DRAW_DISABLE;
+ if ( GetStyle() & WB_NOLABEL )
+ nStyle &= ~TEXT_DRAW_MNEMONIC;
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ nStyle |= TEXT_DRAW_MONO;
+
+ aRect = GetTextRect( aRect, aText, nStyle );
+ long nTop = aRect.Top() + ((aRect.GetHeight()-1)/2);
+
+ DrawLine( Point( 0, nTop ), Point( aRect.Left()-FIXEDLINE_TEXT_BORDER, nTop ) );
+ DrawLine( Point( aRect.Right()+FIXEDLINE_TEXT_BORDER, nTop ), Point( aOutSize.Width()-1, nTop ) );
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( 0, nTop+1 ), Point( aRect.Left()-FIXEDLINE_TEXT_BORDER, nTop+1 ) );
+ DrawLine( Point( aRect.Right()+FIXEDLINE_TEXT_BORDER, nTop+1 ), Point( aOutSize.Width()-1, nTop+1 ) );
+ }
+
+ DrawText( aRect, aText, nStyle );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ if ( (GetPrevStyle() & FIXEDLINE_VIEW_STYLE) !=
+ (GetStyle() & FIXEDLINE_VIEW_STYLE) )
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_STYLE) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedLine::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// =======================================================================
+
+void FixedBitmap::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FixedBitmap::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::ImplInitSettings()
+{
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( RSC_FIXEDBITMAP_BITMAP & nObjMask )
+ {
+ maBitmap = Bitmap( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FixedBitmap::FixedBitmap( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_FIXEDBITMAP )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FixedBitmap::FixedBitmap( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_FIXEDBITMAP )
+{
+ rResId.SetRT( RSC_FIXEDBITMAP );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+FixedBitmap::~FixedBitmap()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::ImplDraw( OutputDevice* pDev, ULONG /* nDrawFlags */,
+ const Point& rPos, const Size& rSize )
+{
+ // Haben wir ueberhaupt eine Bitmap
+ if ( !(!maBitmap) )
+ {
+ if ( GetStyle() & WB_SCALE )
+ pDev->DrawBitmap( rPos, rSize, maBitmap );
+ else
+ {
+ Point aPos = ImplCalcPos( GetStyle(), rPos, maBitmap.GetSizePixel(), rSize );
+ pDev->DrawBitmap( aPos, maBitmap );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::Paint( const Rectangle& rRect )
+{
+ ImplDraw( this, 0, Point(), GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Rectangle aRect( aPos, aSize );
+
+ pDev->Push();
+ pDev->SetMapMode();
+
+ // Border
+ if ( !(nFlags & WINDOW_DRAW_NOBORDER) && (GetStyle() & WB_BORDER) )
+ {
+ DecorationView aDecoView( pDev );
+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ pDev->IntersectClipRegion( aRect );
+ ImplDraw( pDev, nFlags, aRect.TopLeft(), aRect.GetSize() );
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ if ( (GetPrevStyle() & FIXEDBITMAP_VIEW_STYLE) !=
+ (GetStyle() & FIXEDBITMAP_VIEW_STYLE) )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedBitmap::SetBitmap( const Bitmap& rBitmap )
+{
+ maBitmap = rBitmap;
+ StateChanged( STATE_CHANGE_DATA );
+}
+
+// =======================================================================
+
+void FixedImage::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ mbInUserDraw = FALSE;
+ Control::ImplInit( pParent, nStyle, NULL );
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FixedImage::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::ImplInitSettings()
+{
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( RSC_FIXEDIMAGE_IMAGE & nObjMask )
+ {
+ maImage = Image( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+FixedImage::FixedImage( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_FIXEDIMAGE )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FixedImage::FixedImage( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_FIXEDIMAGE )
+{
+ rResId.SetRT( RSC_FIXEDIMAGE );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+FixedImage::~FixedImage()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize )
+{
+ USHORT nStyle = 0;
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nStyle |= IMAGE_DRAW_DISABLE;
+ }
+
+ // Haben wir ueberhaupt ein Image
+ if ( !(!maImage) )
+ {
+ if ( GetStyle() & WB_SCALE )
+ pDev->DrawImage( rPos, rSize, maImage, nStyle );
+ else
+ {
+ Point aPos = ImplCalcPos( GetStyle(), rPos, maImage.GetSizePixel(), rSize );
+ pDev->DrawImage( aPos, maImage, nStyle );
+ }
+ }
+
+ mbInUserDraw = TRUE;
+ UserDrawEvent aUDEvt( pDev, Rectangle( rPos, rSize ), 0, nStyle );
+ UserDraw( aUDEvt );
+ mbInUserDraw = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::Paint( const Rectangle& rRect )
+{
+ ImplDraw( this, 0, Point(), GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Rectangle aRect( aPos, aSize );
+
+ pDev->Push();
+ pDev->SetMapMode();
+
+ // Border
+ if ( !(nFlags & WINDOW_DRAW_NOBORDER) && (GetStyle() & WB_BORDER) )
+ {
+ DecorationView aDecoView( pDev );
+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ pDev->IntersectClipRegion( aRect );
+ ImplDraw( pDev, nFlags, aRect.TopLeft(), aRect.GetSize() );
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_DATA) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ if ( (GetPrevStyle() & FIXEDIMAGE_VIEW_STYLE) !=
+ (GetStyle() & FIXEDIMAGE_VIEW_STYLE) )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FixedImage::SetImage( const Image& rImage )
+{
+ if ( rImage != maImage )
+ {
+ maImage = rImage;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Point FixedImage::CalcImagePos( const Point& rPos,
+ const Size& rObjSize, const Size& rWinSize )
+{
+ return ImplCalcPos( GetStyle(), rPos, rObjSize, rWinSize );
+}
diff --git a/vcl/source/control/group.cxx b/vcl/source/control/group.cxx
new file mode 100644
index 000000000000..2124a2cf6012
--- /dev/null
+++ b/vcl/source/control/group.cxx
@@ -0,0 +1,349 @@
+/*************************************************************************
+ *
+ * $RCSfile: group.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GROUP_CXX
+
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_GROUP_HXX
+#include <group.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define GROUP_BORDER 12
+#define GROUP_TEXT_BORDER 2
+
+#define GROUP_VIEW_STYLE (WB_3DLOOK | WB_NOLABEL)
+
+// =======================================================================
+
+void GroupBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+ SetMouseTransparent( TRUE );
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits GroupBox::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetGroupFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetGroupTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( (pParent->IsChildTransparentModeEnabled() ||
+ !(pParent->GetStyle() & WB_CLIPCHILDREN) ) &&
+ !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+GroupBox::GroupBox( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_GROUPBOX )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+GroupBox::GroupBox( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_GROUPBOX )
+{
+ rResId.SetRT( RSC_GROUPBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
+ const Point& rPos, const Size& rSize )
+{
+ long nTop;
+ long nTextOff;
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ XubString aText( GetText() );
+ Rectangle aRect( rPos, rSize );
+ USHORT nTextStyle = TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_MNEMONIC;
+
+ if ( GetStyle() & WB_NOLABEL )
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ if ( nDrawFlags & WINDOW_DRAW_NOMNEMONIC )
+ {
+ if ( nTextStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aText = GetNonMnemonicString( aText );
+ nTextStyle &= ~TEXT_DRAW_MNEMONIC;
+ }
+ }
+ if ( !(nDrawFlags & WINDOW_DRAW_NODISABLE) )
+ {
+ if ( !IsEnabled() )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ }
+ if ( (nDrawFlags & WINDOW_DRAW_MONO) ||
+ (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ nTextStyle |= TEXT_DRAW_MONO;
+ nDrawFlags |= WINDOW_DRAW_MONO;
+ }
+
+ if ( !aText.Len() )
+ {
+ nTop = rPos.Y();
+ nTextOff = 0;
+ }
+ else
+ {
+ aRect.Left() += GROUP_BORDER;
+ aRect.Right() -= GROUP_BORDER;
+ aRect = pDev->GetTextRect( aRect, aText, nTextStyle );
+ nTop = rPos.Y();
+ nTop += aRect.GetHeight() / 2;
+ nTextOff = GROUP_TEXT_BORDER;
+ }
+
+ if ( nDrawFlags & WINDOW_DRAW_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+
+ if ( !aText.Len() )
+ pDev->DrawLine( Point( rPos.X(), nTop ), Point( rPos.X()+rSize.Width()-2, nTop ) );
+ else
+ {
+ pDev->DrawLine( Point( rPos.X(), nTop ), Point( aRect.Left()-nTextOff, nTop ) );
+ pDev->DrawLine( Point( aRect.Right()+nTextOff, nTop ), Point( rPos.X()+rSize.Width()-2, nTop ) );
+ }
+ pDev->DrawLine( Point( rPos.X(), nTop ), Point( rPos.X(), rPos.Y()+rSize.Height()-2 ) );
+ pDev->DrawLine( Point( rPos.X(), rPos.Y()+rSize.Height()-2 ), Point( rPos.X()+rSize.Width()-2, rPos.Y()+rSize.Height()-2 ) );
+ pDev->DrawLine( Point( rPos.X()+rSize.Width()-2, rPos.Y()+rSize.Height()-2 ), Point( rPos.X()+rSize.Width()-2, nTop ) );
+
+ if ( !(nDrawFlags & WINDOW_DRAW_MONO) )
+ {
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ if ( !aText.Len() )
+ pDev->DrawLine( Point( rPos.X()+1, nTop+1 ), Point( rPos.X()+rSize.Width()-3, nTop+1 ) );
+ else
+ {
+ pDev->DrawLine( Point( rPos.X()+1, nTop+1 ), Point( aRect.Left()-nTextOff, nTop+1 ) );
+ pDev->DrawLine( Point( aRect.Right()+nTextOff, nTop+1 ), Point( rPos.X()+rSize.Width()-3, nTop+1 ) );
+ }
+ pDev->DrawLine( Point( rPos.X()+1, nTop+1 ), Point( rPos.X()+1, rPos.Y()+rSize.Height()-3 ) );
+ pDev->DrawLine( Point( rPos.X(), rPos.Y()+rSize.Height()-1 ), Point( rPos.X()+rSize.Width()-1, rPos.Y()+rSize.Height()-1 ) );
+ pDev->DrawLine( Point( rPos.X()+rSize.Width()-1, rPos.Y()+rSize.Height()-1 ), Point( rPos.X()+rSize.Width()-1, nTop ) );
+ }
+
+ pDev->DrawText( aRect, aText, nTextStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::Paint( const Rectangle& )
+{
+ ImplDraw( this, 0, Point(), GetOutputSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ ULONG nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = GetDrawPixelFont( pDev );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ ImplDraw( pDev, nFlags, aPos, aSize );
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( (nType == STATE_CHANGE_ENABLE) ||
+ (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_UPDATEMODE) )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ if ( (GetPrevStyle() & GROUP_VIEW_STYLE) !=
+ (GetStyle() & GROUP_VIEW_STYLE) )
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void GroupBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
diff --git a/vcl/source/control/ilstbox.cxx b/vcl/source/control/ilstbox.cxx
new file mode 100644
index 000000000000..3f1b977e7eab
--- /dev/null
+++ b/vcl/source/control/ilstbox.cxx
@@ -0,0 +1,2387 @@
+/*************************************************************************
+ *
+ * $RCSfile: ilstbox.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ILSTBOX_CXX
+
+#ifndef _TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SCRBAR_HXX
+#include <scrbar.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+
+#ifndef _SV_LSTBOX_H
+#include <lstbox.h>
+#endif
+#ifndef _SV_ILSTBOX_HXX
+#include <ilstbox.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void ImplInitFieldSettings( Window* pWin, BOOL bFont, BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetFieldFont();
+ if ( pWin->IsControlFont() )
+ aFont.Merge( pWin->GetControlFont() );
+ pWin->SetZoomedPointFont( aFont );
+ }
+
+ if ( bFont || bForeground )
+ {
+ Color aTextColor = rStyleSettings.GetFieldTextColor();
+ if ( pWin->IsControlForeground() )
+ aTextColor = pWin->GetControlForeground();
+ pWin->SetTextColor( aTextColor );
+ }
+
+ if ( bBackground )
+ {
+ if( pWin->IsControlBackground() )
+ pWin->SetBackground( pWin->GetControlBackground() );
+ else
+ pWin->SetBackground( rStyleSettings.GetFieldColor() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplInitDropDownButton( PushButton* pButton )
+{
+ if ( pButton->GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN )
+ pButton->SetSymbol( SYMBOL_SPIN_UPDOWN );
+ else
+ pButton->SetSymbol( SYMBOL_SPIN_DOWN );
+}
+
+// =======================================================================
+
+ImplEntryList::ImplEntryList()
+{
+ mnLastSelected = LISTBOX_ENTRY_NOTFOUND;
+ mnSelectionAnchor = LISTBOX_ENTRY_NOTFOUND;
+ mnImages = 0;
+ mbCallSelectionChangedHdl = TRUE;
+
+ mnMRUCount = 0;
+ mnMaxMRUCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplEntryList::~ImplEntryList()
+{
+ Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplEntryList::Clear()
+{
+ mnImages = 0;
+ for ( USHORT n = GetEntryCount(); n; )
+ {
+ ImplEntryType* pImplEntry = GetEntry( --n );
+ delete pImplEntry;
+ }
+ List::Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplEntryList::SelectEntry( USHORT nPos, BOOL bSelect )
+{
+ ImplEntryType* pImplEntry = GetEntry( nPos );
+ if ( pImplEntry && ( pImplEntry->mbIsSelected != bSelect ) )
+ {
+ pImplEntry->mbIsSelected = bSelect;
+ if ( mbCallSelectionChangedHdl )
+ maSelectionChangedHdl.Call( (void*)nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplEntryList::InsertEntry( USHORT nPos, ImplEntryType* pNewEntry, BOOL bSort )
+{
+ if ( !!pNewEntry->maImage )
+ mnImages++;
+
+ if ( !bSort || !Count() )
+ {
+ Insert( pNewEntry, nPos );
+ }
+ else
+ {
+ const XubString& rStr = pNewEntry->maStr;
+ ULONG nLow, nHigh, nMid;
+
+ nHigh = Count();
+
+ const International& rIntl = Application::GetSettings().GetInternational();
+ ImplEntryType* pTemp = GetEntry( (USHORT)(nHigh-1) );
+ StringCompare eComp = rIntl.Compare( rStr, pTemp->maStr );
+
+ // Schnelles Einfuegen bei sortierten Daten
+ if ( eComp != COMPARE_LESS )
+ {
+ Insert( pNewEntry, LIST_APPEND );
+ }
+ else
+ {
+ nLow = mnMRUCount;
+ pTemp = (ImplEntryType*)GetEntry( (USHORT)nLow );
+ eComp = rIntl.Compare( rStr, pTemp->maStr );
+ if ( eComp != COMPARE_GREATER )
+ {
+ Insert( pNewEntry, (ULONG)0 );
+ }
+ else
+ {
+ // Binaeres Suchen
+ nHigh--;
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ pTemp = (ImplEntryType*)GetObject( nMid );
+ eComp = rIntl.Compare( rStr, pTemp->maStr );
+
+ if ( eComp == COMPARE_LESS )
+ nHigh = nMid-1;
+ else
+ {
+ if ( eComp == COMPARE_GREATER )
+ nLow = nMid + 1;
+ else
+ break;
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( eComp != COMPARE_LESS )
+ nMid++;
+
+ Insert( pNewEntry, nMid );
+ }
+ }
+ }
+
+ return (USHORT)GetPos( pNewEntry );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplEntryList::RemoveEntry( USHORT nPos )
+{
+ ImplEntryType* pImplEntry = (ImplEntryType*)List::Remove( nPos );
+ if ( pImplEntry )
+ {
+ if ( !!pImplEntry->maImage )
+ mnImages--;
+
+ delete pImplEntry;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplEntryList::FindEntry( const XubString& rStr, MatchMode nMatchMode, USHORT nMatchLen, USHORT nStart, BOOL bForward ) const
+{
+ BOOL bEqual;
+ USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
+ USHORT nEntryCount = GetEntryCount();
+ if ( !bForward )
+ nStart++; // wird sofort dekrementiert
+ for ( USHORT n = nStart; bForward ? ( n < nEntryCount ) : n; )
+ {
+ if ( !bForward )
+ n--;
+
+ ImplEntryType* pImplEntry = GetEntry( n );
+ if ( nMatchMode == MATCH_CASE )
+ bEqual = pImplEntry->maStr.Equals( rStr, 0, nMatchLen );
+ else
+ bEqual = pImplEntry->maStr.EqualsIgnoreCaseAscii( rStr, 0, nMatchLen );
+ if ( bEqual )
+ {
+ // Wenn Case-Insensitiv matching, dann einen Eintrag bevorzugen,
+ // der trotzdem case-sensitiv matched.
+ if ( (nMatchMode == MATCH_CASE) ||
+ ((nMatchMode == MATCH_BEST) && (pImplEntry->maStr.Equals( rStr, 0, nMatchLen ))) )
+ {
+ nPos = n;
+ break;
+ }
+ else if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = n; // Bei Case-Insensitiv gewinnt der erste, wenn keiner 100%
+ }
+
+ if ( bForward )
+ n++;
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplEntryList::FindEntry( const void* pData ) const
+{
+ USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
+ for ( USHORT n = GetEntryCount(); n; )
+ {
+ ImplEntryType* pImplEntry = GetEntry( --n );
+ if ( pImplEntry->mpUserData == pData )
+ {
+ nPos = n;
+ break;
+ }
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+XubString ImplEntryList::GetEntryText( USHORT nPos ) const
+{
+ XubString aEntryText;
+ ImplEntryType* pImplEntry = GetEntry( nPos );
+ if ( pImplEntry )
+ aEntryText = pImplEntry->maStr;
+ return aEntryText;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplEntryList::HasEntryImage( USHORT nPos ) const
+{
+ BOOL bImage = FALSE;
+ ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos );
+ if ( pImplEntry )
+ bImage = !!pImplEntry->maImage;
+ return bImage;
+}
+
+// -----------------------------------------------------------------------
+
+Image ImplEntryList::GetEntryImage( USHORT nPos ) const
+{
+ Image aImage;
+ ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos );
+ if ( pImplEntry )
+ aImage = pImplEntry->maImage;
+ return aImage;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplEntryList::SetEntryData( USHORT nPos, void* pNewData )
+{
+ ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos );
+ if ( pImplEntry )
+ pImplEntry->mpUserData = pNewData;
+}
+
+// -----------------------------------------------------------------------
+
+void* ImplEntryList::GetEntryData( USHORT nPos ) const
+{
+ ImplEntryType* pImplEntry = (ImplEntryType*)List::GetObject( nPos );
+ return pImplEntry ? pImplEntry->mpUserData : NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplEntryList::GetSelectEntryCount() const
+{
+ USHORT nSelCount = 0;
+ for ( USHORT n = GetEntryCount(); n; )
+ {
+ ImplEntryType* pImplEntry = GetEntry( --n );
+ if ( pImplEntry->mbIsSelected )
+ nSelCount++;
+ }
+ return nSelCount;
+}
+
+// -----------------------------------------------------------------------
+
+XubString ImplEntryList::GetSelectEntry( USHORT nIndex ) const
+{
+ return GetEntryText( GetSelectEntryPos( nIndex ) );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplEntryList::GetSelectEntryPos( USHORT nIndex ) const
+{
+ USHORT nSelEntryPos = LISTBOX_ENTRY_NOTFOUND;
+ USHORT nSel = 0;
+ USHORT nEntryCount = GetEntryCount();
+
+ for ( USHORT n = 0; n < nEntryCount; n++ )
+ {
+ ImplEntryType* pImplEntry = GetEntry( n );
+ if ( pImplEntry->mbIsSelected )
+ {
+ if ( nSel == nIndex )
+ {
+ nSelEntryPos = n;
+ break;
+ }
+ nSel++;
+ }
+ }
+
+ return nSelEntryPos;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplEntryList::IsEntrySelected( const XubString& rStr ) const
+{
+ return IsEntryPosSelected( FindEntry( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplEntryList::IsEntryPosSelected( USHORT nIndex ) const
+{
+ ImplEntryType* pImplEntry = GetEntry( nIndex );
+ return pImplEntry ? pImplEntry->mbIsSelected : FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplEntryList::SetNoSelection()
+{
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT n = 0; n < nEntryCount; n++ )
+ SelectEntry( n, FALSE );
+}
+
+// =======================================================================
+
+ImplListBoxWindow::ImplListBoxWindow( Window* pParent, WinBits nWinStyle ) :
+ Control( pParent, 0 )
+{
+ mpEntryList = new ImplEntryList;
+
+ mnTop = 0;
+ mnLeft = 0;
+ mnBorder = 1;
+ mnSelectModifier = 0;
+ mnUserDrawEntry = LISTBOX_ENTRY_NOTFOUND;
+ mbTrack = FALSE;
+ mbImgsDiffSz = FALSE;
+ mbTravelSelect = FALSE;
+ mbTrackingSelect = FALSE;
+ mbSelectionChanged = FALSE;
+ mbMouseMoveSelect = FALSE;
+ mbMulti = FALSE;
+ mbGrabFocus = FALSE;
+ mbUserDrawEnabled = FALSE;
+ mbInUserDraw = FALSE;
+ mbReadOnly = FALSE;
+ mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE ) ? TRUE : FALSE;
+ mbSort = ( nWinStyle & WB_SORT ) ? TRUE : FALSE;
+
+ mnCurrentPos = LISTBOX_ENTRY_NOTFOUND;
+ mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
+ mnSeparatorPos = LISTBOX_ENTRY_NOTFOUND;
+
+ SetLineColor();
+ SetTextFillColor();
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
+
+ maSearchTimeout.SetTimeout( 500 );
+ maSearchTimeout.SetTimeoutHdl( LINK( this, ImplListBoxWindow, SearchStringTimeout ) );
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ ImplCalcMetrics();
+}
+
+// -----------------------------------------------------------------------
+
+ImplListBoxWindow::~ImplListBoxWindow()
+{
+ maSearchTimeout.Stop();
+ delete mpEntryList;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ImplInitSettings( BOOL bFont, BOOL bForeground, BOOL bBackground )
+{
+ ImplInitFieldSettings( this, bFont, bForeground, bBackground );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ImplCalcMetrics()
+{
+ mnMaxWidth = 0;
+ mnMaxTxtWidth = 0;
+ mnMaxImgWidth = 0;
+ mnMaxImgTxtWidth= 0;
+ mnMaxImgHeight = 0;
+
+ mnTextHeight = (USHORT)GetTextHeight();
+ mnMaxTxtHeight = mnTextHeight + mnBorder;
+ mnMaxHeight = mnMaxTxtHeight;
+
+ if ( maUserItemSize.Height() > mnMaxHeight )
+ mnMaxHeight = (USHORT) maUserItemSize.Height();
+ if ( maUserItemSize.Width() > mnMaxWidth )
+ mnMaxWidth= (USHORT) maUserItemSize.Width();
+
+ for ( USHORT n = mpEntryList->GetEntryCount(); n; )
+ {
+ const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( --n );
+ ImplCalcEntryMetrics( *pEntry, TRUE );
+ }
+
+ Size aSz( GetOutputSizePixel().Width(), mnMaxHeight );
+ maFocusRect.SetSize( aSz );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplListBoxWindow, SearchStringTimeout, Timer*, EMPTYARG )
+{
+ maSearchStr.Erase();
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::Clear()
+{
+ mpEntryList->Clear();
+
+ mnMaxHeight = mnMaxTxtHeight;
+ mnMaxWidth = 0;
+ mnMaxTxtWidth = 0;
+ mnMaxImgTxtWidth= 0;
+ mnMaxImgWidth = 0;
+ mnMaxImgHeight = 0;
+ mnTop = 0;
+ mnLeft = 0;
+ mbImgsDiffSz = FALSE;
+
+ Invalidate();
+}
+
+void ImplListBoxWindow::SetUserItemSize( const Size& rSz )
+{
+ maUserItemSize = rSz;
+ ImplCalcMetrics();
+}
+
+// -----------------------------------------------------------------------
+
+struct ImplEntryMetrics
+{
+ BOOL bText;
+ BOOL bImage;
+ USHORT nEntryWidth;
+ USHORT nEntryHeight;
+ USHORT nTextWidth;
+ USHORT nImgWidth;
+ USHORT nImgHeight;
+};
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ImplCalcEntryMetrics( const ImplEntryType& rEntry, BOOL bUpdateMetrics )
+{
+ // bUpdateMetrics: Wenn Entry groesser als Max-Wert, dann uebernehmen
+
+ // Diese Methode war mal auch fuer RemoveRentry gedacht, deshalb die
+ // ImplEntryMetrics-Struktur, damit die Werte zurueckgegeben werden.
+ // Jetzt werden die aktuellen Metriken aber doch immer angepasst, weil
+ // bei RemoveEntry einmal komplett durchgegangen wird.
+
+ ImplEntryMetrics aMetrics;
+ aMetrics.bText = rEntry.maStr.Len() ? TRUE : FALSE;
+ aMetrics.bImage = !!rEntry.maImage;
+ aMetrics.nEntryWidth = 0;
+ aMetrics.nEntryHeight = 0;
+ aMetrics.nTextWidth = 0;
+ aMetrics.nImgWidth = 0;
+ aMetrics.nImgHeight = 0;
+
+ if ( aMetrics.bText )
+ {
+ aMetrics.nTextWidth = (USHORT)GetTextWidth( rEntry.maStr );
+ if( bUpdateMetrics && ( aMetrics.nTextWidth > mnMaxTxtWidth ) )
+ mnMaxTxtWidth = aMetrics.nTextWidth;
+ aMetrics.nEntryWidth = mnMaxTxtWidth;
+ }
+ if ( aMetrics.bImage )
+ {
+ Size aImgSz = rEntry.maImage.GetSizePixel();
+ aMetrics.nImgWidth = (USHORT) CalcZoom( aImgSz.Width() );
+ aMetrics.nImgHeight = (USHORT) CalcZoom( aImgSz.Height() );
+
+ if ( bUpdateMetrics )
+ {
+ if( mnMaxImgWidth && ( aMetrics.nImgWidth != mnMaxImgWidth ) )
+ mbImgsDiffSz = TRUE;
+ else if ( mnMaxImgHeight && ( aMetrics.nImgHeight != mnMaxImgHeight ) )
+ mbImgsDiffSz = TRUE;
+
+ if( aMetrics.nImgWidth > mnMaxImgWidth )
+ mnMaxImgWidth = aMetrics.nImgWidth;
+ if( aMetrics.nImgHeight > mnMaxImgHeight )
+ mnMaxImgHeight = aMetrics.nImgHeight;
+
+ mnMaxImgTxtWidth = Max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
+ }
+ }
+ if ( IsUserDrawEnabled() || aMetrics.bImage )
+ {
+ aMetrics.nEntryWidth = Max( aMetrics.nImgWidth, (USHORT)maUserItemSize.Width() );
+ if ( aMetrics.bText )
+ aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
+ aMetrics.nEntryHeight = Max( mnMaxImgHeight, (USHORT)maUserItemSize.Height() ) + 2;
+ }
+
+ if ( bUpdateMetrics )
+ {
+ if ( aMetrics.nEntryWidth > mnMaxWidth )
+ mnMaxWidth = aMetrics.nEntryWidth;
+ if ( aMetrics.nEntryHeight > mnMaxHeight )
+ mnMaxHeight = aMetrics.nEntryHeight;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ImplCallSelect()
+{
+ if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() )
+ {
+ // Insert the selected entry as MRU, if not allready first MRU
+ USHORT nSelected = GetEntryList()->GetSelectEntryPos( 0 );
+ USHORT nMRUCount = GetEntryList()->GetMRUCount();
+ String aSelected = GetEntryList()->GetEntryText( nSelected );
+ USHORT nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected );
+ if ( nFirstMatchingEntryPos || !nMRUCount )
+ {
+ BOOL bSelectNewEntry = FALSE;
+ if ( nFirstMatchingEntryPos < nMRUCount )
+ {
+ RemoveEntry( nFirstMatchingEntryPos );
+ nMRUCount--;
+ if ( nFirstMatchingEntryPos == nSelected )
+ bSelectNewEntry = TRUE;
+ }
+ else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() )
+ {
+ RemoveEntry( nMRUCount - 1 );
+ nMRUCount--;
+ }
+
+ ImplEntryType* pNewEntry = new ImplEntryType( aSelected );
+ pNewEntry->mbIsSelected = bSelectNewEntry;
+ GetEntryList()->InsertEntry( 0, pNewEntry, FALSE );
+ GetEntryList()->SetMRUCount( ++nMRUCount );
+ SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
+ maMRUChangedHdl.Call( NULL );
+ }
+ }
+
+ maSelectHdl.Call( NULL );
+ mbSelectionChanged = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplListBoxWindow::InsertEntry( USHORT nPos, ImplEntryType* pNewEntry )
+{
+ USHORT nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, mbSort );
+
+ ImplCalcEntryMetrics( *pNewEntry, TRUE );
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::RemoveEntry( USHORT nPos )
+{
+ mpEntryList->RemoveEntry( nPos );
+ ImplCalcMetrics();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ mbMouseMoveSelect = FALSE; // Nur bis zum ersten MouseButtonDown
+
+ if ( !IsReadOnly() )
+ {
+ if( rMEvt.GetClicks() == 1 )
+ {
+ USHORT nSelect = (USHORT) ( ( rMEvt.GetPosPixel().Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop;
+ if( nSelect < mpEntryList->GetEntryCount() )
+ {
+ if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
+ mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 );
+ else
+ mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
+
+ mnCurrentPos = nSelect;
+ mbTrackingSelect = TRUE;
+ SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() );
+ mbTrackingSelect = FALSE;
+ if ( mbGrabFocus )
+ GrabFocus();
+
+ StartTracking( STARTTRACK_SCROLLREPEAT );
+ }
+ }
+ if( rMEvt.GetClicks() == 2 )
+ {
+ maDoubleClickHdl.Call( this );
+ }
+ }
+ else // if ( mbGrabFocus )
+ {
+ GrabFocus();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !mbMulti && mbMouseMoveSelect && mpEntryList->GetEntryCount() && !rMEvt.IsLeaveWindow() )
+ {
+ Point aPoint;
+ Rectangle aRect( aPoint, GetOutputSizePixel() );
+ if( aRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ USHORT nSelect = (USHORT) ( ( rMEvt.GetPosPixel().Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop;
+ nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) );
+ nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) );
+ if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() || ( nSelect != GetEntryList()->GetSelectEntryPos( 0 ) ) )
+ {
+ mbTrackingSelect = TRUE;
+ SelectEntries( nSelect, LET_TRACKING, FALSE, FALSE );
+ mbTrackingSelect = FALSE;
+ }
+
+ // Falls der DD-Button gedrueckt wurde und jemand mit gedrueckter
+ // Maustaste in die ListBox faehrt...
+ if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() )
+ {
+ if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
+ mnTrackingSaveSelection = GetEntryList()->GetSelectEntryPos( 0 );
+ else
+ mnTrackingSaveSelection = LISTBOX_ENTRY_NOTFOUND;
+ StartTracking( STARTTRACK_SCROLLREPEAT );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::SelectEntry( USHORT nPos, BOOL bSelect )
+{
+ if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect )
+ {
+ HideFocus();
+ if( bSelect )
+ {
+ if( !mbMulti )
+ {
+ // Selektierten Eintrag deselektieren
+ USHORT nDeselect = GetEntryList()->GetSelectEntryPos( 0 );
+ if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
+ {
+ //SelectEntryPos( nDeselect, FALSE );
+ GetEntryList()->SelectEntry( nDeselect, FALSE );
+ if ( IsUpdateMode() && IsReallyVisible() )
+ ImplPaint( nDeselect, TRUE );
+ }
+ }
+ mpEntryList->SelectEntry( nPos, TRUE );
+ mnCurrentPos = nPos;
+ if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
+ {
+ ImplPaint( nPos );
+ if ( !IsVisible( nPos ) )
+ SetTopEntry( nPos );
+ }
+ }
+ else
+ {
+ mpEntryList->SelectEntry( nPos, FALSE );
+ ImplPaint( nPos, TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplListBoxWindow::SelectEntries( USHORT nSelect, LB_EVENT_TYPE eLET, BOOL bShift, BOOL bCtrl )
+{
+ BOOL bFocusChanged = FALSE;
+ BOOL bSelectionChanged = FALSE;
+
+ if( IsEnabled() )
+ {
+ // Hier (Single-ListBox) kann nur ein Eintrag deselektiert werden
+ if( !mbMulti )
+ {
+ USHORT nDeselect = mpEntryList->GetSelectEntryPos( 0 );
+ if( nSelect != nDeselect )
+ {
+ SelectEntry( nSelect, TRUE );
+ mpEntryList->SetLastSelected( nSelect );
+ bFocusChanged = TRUE;
+ bSelectionChanged = TRUE;
+ }
+ }
+ // MultiListBox ohne Modifier
+ else if( mbSimpleMode && !bCtrl && !bShift )
+ {
+ USHORT nEntryCount = mpEntryList->GetEntryCount();
+ for ( USHORT nPos = 0; nPos < nEntryCount; nPos++ )
+ {
+ BOOL bSelect = nPos == nSelect;
+ if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect )
+ {
+ SelectEntry( nPos, bSelect );
+ bFocusChanged = TRUE;
+ bSelectionChanged = TRUE;
+ }
+ }
+ mpEntryList->SetLastSelected( nSelect );
+ mpEntryList->SetSelectionAnchor( nSelect );
+ }
+ // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode
+ else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) ) )
+ {
+ // Space fuer Selektionswechsel
+ if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) )
+ {
+ SelectEntry( nSelect, !mpEntryList->IsEntryPosSelected( nSelect ) );
+ mpEntryList->SetLastSelected( nSelect );
+ mpEntryList->SetSelectionAnchor( nSelect );
+ if ( !mpEntryList->IsEntryPosSelected( nSelect ) )
+ mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND );
+ bFocusChanged = TRUE;
+ bSelectionChanged = TRUE;
+ }
+ else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) ||
+ ( bShift && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) )
+ {
+ mnCurrentPos = nSelect;
+ bFocusChanged = TRUE;
+
+ USHORT nAnchor = mpEntryList->GetSelectionAnchor();
+ if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && ( mpEntryList->GetSelectEntryCount() ) )
+ {
+ nAnchor = mpEntryList->GetSelectEntryPos( mpEntryList->GetSelectEntryCount() - 1 );
+ }
+ if( nAnchor != LISTBOX_ENTRY_NOTFOUND )
+ {
+ // Alle Eintraege vom Anchor bis nSelect muessen selektiert sein
+ USHORT nStart = Min( nSelect, nAnchor );
+ USHORT nEnd = Max( nSelect, nAnchor );
+ for ( USHORT n = nStart; n <= nEnd; n++ )
+ {
+ if ( !mpEntryList->IsEntryPosSelected( n ) )
+ {
+ SelectEntry( n, TRUE );
+ bSelectionChanged = TRUE;
+ }
+ }
+
+ // Ggf. muss noch was deselektiert werden...
+ USHORT nLast = mpEntryList->GetLastSelected();
+ if ( nLast != LISTBOX_ENTRY_NOTFOUND )
+ {
+ if ( ( nLast > nSelect ) && ( nLast > nAnchor ) )
+ {
+ for ( USHORT n = nSelect+1; n <= nLast; n++ )
+ {
+ if ( mpEntryList->IsEntryPosSelected( n ) )
+ {
+ SelectEntry( n, FALSE );
+ bSelectionChanged = TRUE;
+ }
+ }
+ }
+ else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) )
+ {
+ for ( USHORT n = nLast; n < nSelect; n++ )
+ {
+ if ( mpEntryList->IsEntryPosSelected( n ) )
+ {
+ SelectEntry( n, FALSE );
+ bSelectionChanged = TRUE;
+ }
+ }
+ }
+ }
+ mpEntryList->SetLastSelected( nSelect );
+ }
+ }
+ else if( eLET != LET_TRACKING )
+ {
+ HideFocus();
+ ImplPaint( nSelect, TRUE );
+ bFocusChanged = TRUE;
+ }
+ }
+ else if( bShift )
+ {
+ bFocusChanged = TRUE;
+ }
+
+ if( bSelectionChanged )
+ mbSelectionChanged = TRUE;
+
+ if( bFocusChanged )
+ {
+ maFocusRect.SetPos( Point( 0, ( nSelect - mnTop ) * mnMaxHeight ) );
+ if( HasFocus() )
+ ShowFocus( maFocusRect );
+ }
+ }
+ return bSelectionChanged;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aPoint;
+ Rectangle aRect( aPoint, GetOutputSizePixel() );
+ BOOL bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() );
+
+ if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp
+ {
+ if ( bInside && !rTEvt.IsTrackingCanceled() )
+ {
+ mnSelectModifier = rTEvt.GetMouseEvent().GetModifier();
+ ImplCallSelect();
+ }
+ else
+ {
+ maCancelHdl.Call( NULL );
+ if ( !mbMulti )
+ {
+ mbTrackingSelect = TRUE;
+ SelectEntry( mnTrackingSaveSelection, TRUE );
+ mbTrackingSelect = FALSE;
+ if ( mnTrackingSaveSelection != LISTBOX_ENTRY_NOTFOUND )
+ {
+ maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) );
+ ShowFocus( maFocusRect );
+ }
+ }
+ }
+
+ mbTrack = FALSE;
+ }
+ else
+ {
+ BOOL bTrackOrQuickClick = mbTrack;
+ if( !mbTrack )
+ {
+ if ( bInside )
+ {
+ mbTrack = TRUE;
+ }
+
+ // Folgender Fall tritt nur auf, wenn man ganz kurz die Maustaste drueckt
+ if( rTEvt.IsTrackingEnded() && mbTrack )
+ {
+ bTrackOrQuickClick = TRUE;
+ mbTrack = FALSE;
+ }
+ }
+
+ if( bTrackOrQuickClick )
+ {
+ MouseEvent aMEvt = rTEvt.GetMouseEvent();
+ Point aPt( aMEvt.GetPosPixel() );
+ BOOL bShift = aMEvt.IsShift();
+ BOOL bCtrl = aMEvt.IsMod1();
+
+ USHORT nSelect = LISTBOX_ENTRY_NOTFOUND;
+ if( aPt.Y() < 0 )
+ {
+ nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0;
+ if( nSelect < mnTop )
+ SetTopEntry( mnTop-1 );
+ }
+ else if( aPt.Y() > GetOutputSizePixel().Height() )
+ {
+ nSelect = Min( (USHORT)(mnCurrentPos+1), (USHORT)(mpEntryList->GetEntryCount()-1) );
+ if( nSelect >= mnTop + mnMaxVisibleEntries )
+ SetTopEntry( mnTop+1 );
+ }
+ else
+ {
+ nSelect = (USHORT) ( ( aPt.Y() + mnBorder ) / mnMaxHeight ) + (USHORT) mnTop;
+ nSelect = Min( nSelect, (USHORT) ( mnTop + mnMaxVisibleEntries ) );
+ nSelect = Min( nSelect, (USHORT) ( mpEntryList->GetEntryCount() - 1 ) );
+ }
+
+ if ( bInside )
+ {
+ if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectEntryCount() )
+ {
+ mbTrackingSelect = TRUE;
+ SelectEntries( nSelect, LET_TRACKING, bShift, bCtrl );
+ mbTrackingSelect = FALSE;
+ }
+ }
+ else
+ {
+ if ( !mbMulti && GetEntryList()->GetSelectEntryCount() )
+ {
+ mbTrackingSelect = TRUE;
+ SelectEntry( GetEntryList()->GetSelectEntryPos( 0 ), FALSE );
+ mbTrackingSelect = FALSE;
+ }
+ }
+ mnCurrentPos = nSelect;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::KeyInput( const KeyEvent& rKEvt )
+{
+ if( !ProcessKeyInput( rKEvt ) )
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplListBoxWindow::ProcessKeyInput( const KeyEvent& rKEvt )
+{
+ // zu selektierender Eintrag
+ USHORT nSelect = LISTBOX_ENTRY_NOTFOUND;
+ LB_EVENT_TYPE eLET = LET_KEYMOVE;
+
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+ BOOL bShift = aKeyCode.IsShift();
+ BOOL bCtrl = aKeyCode.IsMod1();
+ BOOL bMod2 = aKeyCode.IsMod2();
+ BOOL bDone = FALSE;
+
+ switch( aKeyCode.GetCode() )
+ {
+ case KEY_UP:
+ {
+ if ( IsReadOnly() )
+ {
+ if ( GetTopEntry() )
+ SetTopEntry( GetTopEntry()-1 );
+ }
+ else if ( !bMod2 )
+ {
+ if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ else if ( mnCurrentPos )
+ nSelect = mnCurrentPos - 1;
+
+ if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) )
+ SetTopEntry( mnTop-1 );
+
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_DOWN:
+ {
+ if ( IsReadOnly() )
+ {
+ SetTopEntry( GetTopEntry()+1 );
+ }
+ else if ( !bMod2 )
+ {
+ if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
+ nSelect = mnCurrentPos+1;
+
+ if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= ( mnTop + mnMaxVisibleEntries ) ) )
+ SetTopEntry( mnTop+1 );
+
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_PAGEUP:
+ {
+ if ( IsReadOnly() )
+ {
+ SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ?
+ (mnTop-mnMaxVisibleEntries) : 0 );
+ }
+ else if ( !bCtrl && !bMod2 )
+ {
+ if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ else if ( mnCurrentPos )
+ {
+ if( mnCurrentPos == mnTop )
+ SetTopEntry( ( mnTop > mnMaxVisibleEntries ) ?
+ ( mnTop-mnMaxVisibleEntries+1 ) : 0 );
+ nSelect = mnTop;
+ }
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_PAGEDOWN:
+ {
+ if ( IsReadOnly() )
+ {
+ SetTopEntry( mnTop + mnMaxVisibleEntries );
+ }
+ else if ( !bCtrl && !bMod2 )
+ {
+ if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
+ {
+ USHORT nCount = mpEntryList->GetEntryCount();
+ USHORT nTmp = Min( mnMaxVisibleEntries, nCount );
+ nTmp += mnTop - 1;
+ if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 )
+ {
+ long nTmp2 = Min( (long)(nCount-mnMaxVisibleEntries), (long)((long)mnTop+(long)mnMaxVisibleEntries-1) );
+ nTmp2 = Max( (long)0 , nTmp2 );
+ nTmp = (USHORT)(nTmp2+(mnMaxVisibleEntries-1) );
+ SetTopEntry( (USHORT)nTmp2 );
+ }
+ nSelect = nTmp;
+ }
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_HOME:
+ {
+ if ( IsReadOnly() )
+ {
+ SetTopEntry( 0 );
+ }
+ else if ( !bCtrl && !bMod2 )
+ {
+ if ( mnCurrentPos )
+ {
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ if( mnTop != 0 )
+ SetTopEntry( 0 );
+
+ bDone = TRUE;
+ }
+ }
+ }
+ break;
+
+ case KEY_END:
+ {
+ if ( IsReadOnly() )
+ {
+ SetTopEntry( 0xFFFF );
+ }
+ else if ( !bCtrl && !bMod2 )
+ {
+ if( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND;
+ else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
+ {
+ USHORT nCount = mpEntryList->GetEntryCount();
+ nSelect = nCount - 1;
+ if( nCount > mnMaxVisibleEntries )
+ SetTopEntry( nCount - mnMaxVisibleEntries );
+ }
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_LEFT:
+ {
+ if ( !bCtrl && !bMod2 )
+ {
+ ScrollHorz( -HORZ_SCROLL );
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ {
+ if ( !bCtrl && !bMod2 )
+ {
+ ScrollHorz( HORZ_SCROLL );
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ case KEY_RETURN:
+ {
+ if ( !bMod2 && !IsReadOnly() )
+ {
+ mnSelectModifier = rKEvt.GetKeyCode().GetModifier();
+ ImplCallSelect();
+ bDone = FALSE; // RETURN nicht abfangen.
+ }
+ }
+ break;
+
+ case KEY_SPACE:
+ {
+ if ( !bMod2 && !IsReadOnly() )
+ {
+ if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) ) )
+ {
+ nSelect = mnCurrentPos;
+ eLET = LET_KEYSPACE;
+ }
+ bDone = TRUE;
+ }
+ }
+ break;
+
+ default:
+ {
+ xub_Unicode c = rKEvt.GetCharCode();
+
+ if ( !IsReadOnly() && (c >= 32) && (c != 127) &&
+ !rKEvt.GetKeyCode().IsControlMod() )
+ {
+ maSearchStr += c;
+ XubString aTmpSearch( maSearchStr );
+
+ nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), mnCurrentPos );
+ if ( (nSelect == LISTBOX_ENTRY_NOTFOUND) && (aTmpSearch.Len() > 1) )
+ {
+ // Wenn alles die gleichen Buchstaben, dann anderer Such-Modus
+ BOOL bAllEqual = TRUE;
+ for ( USHORT n = aTmpSearch.Len(); n && bAllEqual; )
+ bAllEqual = aTmpSearch.GetChar( --n ) == c;
+ if ( bAllEqual )
+ {
+ aTmpSearch = c;
+ nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), mnCurrentPos+1 );
+ }
+ }
+ if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
+ nSelect = mpEntryList->FindEntry( aTmpSearch, MATCH_IGNORECASE, aTmpSearch.Len(), 0 );
+
+ if ( nSelect != LISTBOX_ENTRY_NOTFOUND )
+ {
+ if( nSelect < mnTop )
+ SetTopEntry( nSelect );
+ else if( nSelect >= (mnTop + mnMaxVisibleEntries) )
+ SetTopEntry( nSelect - mnMaxVisibleEntries + 1 );
+
+ if ( nSelect == mnCurrentPos )
+ nSelect = LISTBOX_ENTRY_NOTFOUND;
+
+ maSearchTimeout.Start();
+ }
+ else
+ maSearchStr.Erase();
+ bDone = TRUE;
+ }
+ }
+ }
+
+ if ( (nSelect != LISTBOX_ENTRY_NOTFOUND) &&
+ ((nSelect != mnCurrentPos ) || ( eLET == LET_KEYSPACE)) )
+ {
+ DBG_ASSERT( (nSelect != mnCurrentPos) || mbMulti, "ImplListBox: Selecting same Entry" );
+ mnCurrentPos = nSelect;
+ if ( SelectEntries( nSelect, eLET, bShift, bCtrl ) )
+ {
+ mbTravelSelect = TRUE;
+ mnSelectModifier = rKEvt.GetKeyCode().GetModifier();
+ ImplCallSelect();
+ mbTravelSelect = FALSE;
+ }
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ImplPaint( USHORT nPos, BOOL bErase )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ long nWidth = GetOutputSizePixel().Width();
+ long nY = ( nPos - mnTop ) * mnMaxHeight;
+ Rectangle aRect( Point( 0, nY ), Size( nWidth, mnMaxHeight ) );
+
+ if( IsEnabled() )
+ {
+ if( mpEntryList->IsEntryPosSelected( nPos ) )
+ {
+ SetTextColor( rStyleSettings.GetHighlightTextColor() );
+ SetFillColor( rStyleSettings.GetHighlightColor() );
+ DrawRect( aRect );
+ }
+ else
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ if( bErase )
+ Erase( aRect );
+ }
+ }
+ else // Disabled
+ {
+ SetTextColor( rStyleSettings.GetDisableColor() );
+ //SetFillColor( rStyleSettings.Get???Color() );
+ //DrawRect( aRect );
+ if( bErase )
+ Erase( aRect );
+ }
+
+ if ( IsUserDrawEnabled() )
+ {
+ mbInUserDraw = TRUE;
+ mnUserDrawEntry = nPos;
+ aRect.Left() -= mnLeft;
+ if ( nPos < GetEntryList()->GetMRUCount() )
+ nPos = GetEntryList()->FindEntry( GetEntryList()->GetEntryText( nPos ), MATCH_CASE, STRING_LEN, GetEntryList()->GetMRUCount() );
+ nPos -= GetEntryList()->GetMRUCount();
+ UserDrawEvent aUDEvt( this, aRect, nPos, 0 );
+ maUserDrawHdl.Call( &aUDEvt );
+ mbInUserDraw = FALSE;
+ }
+ else
+ {
+ DrawEntry( nPos, TRUE, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::DrawEntry( USHORT nPos, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos )
+{
+ // Bei Aenderungen in dieser Methode ggf. auch ImplWin::DrawEntry() anpassen.
+
+ if ( mbInUserDraw )
+ nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
+
+ long nY = ( nPos - mnTop ) * mnMaxHeight;
+
+ if( bDrawImage && mpEntryList->HasImages() )
+ {
+ Image aImage = mpEntryList->GetEntryImage( nPos );
+ if( !!aImage )
+ {
+ Size aImgSz = aImage.GetSizePixel();
+ Point aPtImg( mnBorder - mnLeft, nY + ( ( mnMaxHeight - aImgSz.Height() ) / 2 ) );
+
+ if ( !IsZoom() )
+ {
+ DrawImage( aPtImg, aImage );
+ }
+ else
+ {
+ aImgSz.Width() = CalcZoom( aImgSz.Width() );
+ aImgSz.Height() = CalcZoom( aImgSz.Height() );
+ DrawImage( aPtImg, aImgSz, aImage );
+ }
+ }
+ }
+
+ if( bDrawText )
+ {
+ XubString aStr( mpEntryList->GetEntryText( nPos ) );
+ if ( aStr.Len() )
+ {
+ Point aPtTxt( mnBorder - mnLeft, nY + ( ( mnMaxHeight - mnMaxTxtHeight ) / 2 ) );
+ if( !bDrawTextAtImagePos && ( mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled() ) )
+ {
+ USHORT nMaxWidth = Max( mnMaxImgWidth, (USHORT)maUserItemSize.Width() );
+ aPtTxt.X() += nMaxWidth + IMG_TXT_DISTANCE;
+ }
+ DrawText( aPtTxt, aStr );
+ }
+ }
+
+ if ( ( mnSeparatorPos != LISTBOX_ENTRY_NOTFOUND ) &&
+ ( ( nPos == mnSeparatorPos ) || ( nPos == mnSeparatorPos+1 ) ) )
+ {
+ Color aOldLineColor( GetLineColor() );
+ SetLineColor( ( GetBackground().GetColor() != COL_LIGHTGRAY ) ? COL_LIGHTGRAY : COL_GRAY );
+ Point aStartPos( 0, nY );
+ if ( nPos == mnSeparatorPos )
+ aStartPos.Y() += mnMaxHeight-1;
+ Point aEndPos( aStartPos );
+ aEndPos.X() = GetOutputSizePixel().Width();
+ DrawLine( aStartPos, aEndPos );
+ SetLineColor( aOldLineColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::Paint( const Rectangle& rRect )
+{
+ USHORT nCount = mpEntryList->GetEntryCount();
+
+ if( HasFocus() )
+ HideFocus();
+
+ long nY = 0; // + mnBorder;
+ long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + mnBorder;
+
+ for( USHORT i = (USHORT)mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++ )
+ {
+ if( nY + mnMaxHeight >= rRect.Top() &&
+ nY <= rRect.Bottom() + mnMaxHeight )
+ {
+ ImplPaint( i );
+ }
+ nY += mnMaxHeight;
+ }
+
+ maFocusRect.SetPos( Point( 0, ( mnCurrentPos - mnTop ) * mnMaxHeight ) );
+ if( HasFocus() )
+ ShowFocus( maFocusRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::Resize()
+{
+ Size aSz( GetOutputSizePixel().Width(), mnMaxHeight );
+ maFocusRect.SetSize( aSz );
+ mnMaxVisibleEntries = (USHORT) ( GetOutputSizePixel().Height() / mnMaxHeight );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::GetFocus()
+{
+ USHORT nPos = mnCurrentPos;
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = 0;
+ maFocusRect.SetPos( Point( 0, ( nPos - mnTop ) * mnMaxHeight ) );
+ ShowFocus( maFocusRect );
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::LoseFocus()
+{
+ HideFocus();
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+/*
+void ImplListBoxWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), String() );
+
+ Window::RequestHelp( rHEvt );
+}
+*/
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::SetTopEntry( USHORT nTop )
+{
+ USHORT nMaxTop = 0;
+ if ( GetEntryList()->GetEntryCount() > mnMaxVisibleEntries )
+ nMaxTop = GetEntryList()->GetEntryCount() - mnMaxVisibleEntries;
+ nTop = Min( nTop, nMaxTop );
+ if ( nTop != mnTop )
+ {
+ HideFocus();
+ long nDiff = ( mnTop - nTop ) * mnMaxHeight;
+ mnTop = nTop;
+ Scroll( 0, nDiff );
+ maFocusRect.Top() += nDiff;
+ maFocusRect.Bottom() += nDiff;
+ if( HasFocus() )
+ ShowFocus( maFocusRect );
+ maScrollHdl.Call( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::SetLeftIndent( USHORT n )
+{
+ ScrollHorz( n - mnLeft );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::ScrollHorz( short n )
+{
+ short nDiff = 0;
+ if ( n > 0 )
+ {
+ long nWidth = GetOutputSizePixel().Width();
+ if( ( mnMaxWidth - mnLeft + n ) > nWidth )
+ nDiff = n;
+ }
+ else if ( n < 0 )
+ {
+ if( mnLeft )
+ {
+ USHORT nAbs = -n;
+ nDiff = - ( ( mnLeft > nAbs ) ? nAbs : mnLeft );
+ }
+ }
+
+ if ( nDiff )
+ {
+ HideFocus();
+ mnLeft += nDiff;
+ Scroll( -nDiff, 0 );
+ if( HasFocus() )
+ ShowFocus( maFocusRect );
+ maScrollHdl.Call( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size ImplListBoxWindow::CalcSize( USHORT nMaxLines ) const
+{
+ Size aSz;
+// USHORT nL = Min( nMaxLines, mpEntryList->GetEntryCount() );
+ aSz.Height() = nMaxLines * mnMaxHeight;
+ aSz.Width() = mnMaxWidth + 2*mnBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_ZOOM )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ ImplCalcMetrics();
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() && IsReallyVisible() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ ImplCalcMetrics();
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ ImplCalcMetrics();
+ Invalidate();
+ }
+}
+
+// =======================================================================
+
+ImplListBox::ImplListBox( Window* pParent, WinBits nWinStyle ) :
+ Control( pParent, nWinStyle ),
+ maLBWindow( this, nWinStyle&(~WB_BORDER) )
+{
+ mpVScrollBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG );
+ mpHScrollBar = new ScrollBar( this, WB_HSCROLL | WB_DRAG );
+ mpScrollBarBox = new ScrollBarBox( this );
+
+ Link aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
+ mpVScrollBar->SetScrollHdl( aLink );
+ mpHScrollBar->SetScrollHdl( aLink );
+
+ mbVScroll = FALSE;
+ mbHScroll = FALSE;
+ mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL ) ? TRUE : FALSE;
+
+ maLBWindow.SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
+ maLBWindow.SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
+ maLBWindow.Show();
+}
+
+// -----------------------------------------------------------------------
+
+ImplListBox::~ImplListBox()
+{
+ delete mpHScrollBar;
+ delete mpVScrollBar;
+ delete mpScrollBarBox;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::Clear()
+{
+ maLBWindow.Clear();
+ if ( GetEntryList()->GetMRUCount() )
+ {
+ maLBWindow.GetEntryList()->SetMRUCount( 0 );
+ maLBWindow.SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
+ }
+ mpVScrollBar->SetThumbPos( 0 );
+ mpHScrollBar->SetThumbPos( 0 );
+ StateChanged( STATE_CHANGE_DATA );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplListBox::InsertEntry( USHORT nPos, const XubString& rStr )
+{
+ ImplEntryType* pNewEntry = new ImplEntryType( rStr );
+ USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry );
+ StateChanged( STATE_CHANGE_DATA );
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplListBox::InsertEntry( USHORT nPos, const Image& rImage )
+{
+ ImplEntryType* pNewEntry = new ImplEntryType( rImage );
+ USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry );
+ StateChanged( STATE_CHANGE_DATA );
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplListBox::InsertEntry( USHORT nPos, const XubString& rStr, const Image& rImage )
+{
+ ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
+ USHORT nNewPos = maLBWindow.InsertEntry( nPos, pNewEntry );
+ StateChanged( STATE_CHANGE_DATA );
+ return nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::RemoveEntry( USHORT nPos )
+{
+ maLBWindow.RemoveEntry( nPos );
+ StateChanged( STATE_CHANGE_DATA );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::SelectEntry( USHORT nPos, BOOL bSelect )
+{
+ maLBWindow.SelectEntry( nPos, bSelect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::SetNoSelection()
+{
+ USHORT nSelected = GetEntryList()->GetSelectEntryCount();
+ for ( USHORT n = 0; n < nSelected; n++ )
+ {
+ USHORT nS = GetEntryList()->GetSelectEntryPos( n );
+ SelectEntry( nS, FALSE );
+ }
+ maLBWindow.GetEntryList()->SetNoSelection();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::GetFocus()
+{
+ maLBWindow.GrabFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::Resize()
+{
+ ImplResizeControls();
+ ImplCheckScrollBars();
+}
+
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplListBox, MRUChanged, void*, EMPTYARG )
+{
+ StateChanged( STATE_CHANGE_DATA );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplListBox, LBWindowScrolled, void*, EMPTYARG )
+{
+ mpVScrollBar->SetThumbPos( GetTopEntry() );
+ mpHScrollBar->SetThumbPos( GetLeftIndent() );
+
+ maScrollHdl.Call( this );
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB )
+{
+ USHORT nPos = (USHORT) pSB->GetThumbPos();
+ if( pSB == mpVScrollBar )
+ SetTopEntry( nPos );
+ else if( pSB == mpHScrollBar )
+ SetLeftIndent( nPos );
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::ImplCheckScrollBars()
+{
+ BOOL bArrange = FALSE;
+
+ Size aOutSz = GetOutputSizePixel();
+ USHORT nEntries = GetEntryList()->GetEntryCount();
+ USHORT nMaxVisEntries = (USHORT) (aOutSz.Height() / GetEntryHeight());
+
+ // vert. ScrollBar
+ if( nEntries > nMaxVisEntries )
+ {
+ if( !mbVScroll )
+ bArrange = TRUE;
+ mbVScroll = TRUE;
+
+ // Ueberpruefung des rausgescrollten Bereichs
+ SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft...
+ }
+ else
+ {
+ if( mbVScroll )
+ bArrange = TRUE;
+ mbVScroll = FALSE;
+ SetTopEntry( 0 );
+ }
+
+ // horz. ScrollBar
+ if( mbAutoHScroll )
+ {
+ long nWidth = (USHORT) aOutSz.Width();
+ if ( mbVScroll )
+ nWidth -= mpVScrollBar->GetSizePixel().Width();
+
+ long nMaxWidth = GetMaxEntryWidth();
+ if( nWidth < nMaxWidth )
+ {
+ if( !mbHScroll )
+ bArrange = TRUE;
+ mbHScroll = TRUE;
+
+ if ( !mbVScroll ) // ggf. brauchen wir jetzt doch einen
+ {
+ nMaxVisEntries = (USHORT) ( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeight() );
+ if( nEntries > nMaxVisEntries )
+ {
+ bArrange = TRUE;
+ mbVScroll = TRUE;
+
+ // Ueberpruefung des rausgescrollten Bereichs
+ SetTopEntry( GetTopEntry() ); // MaxTop wird geprueft...
+ }
+ }
+
+ // Ueberpruefung des rausgescrollten Bereichs
+ USHORT nMaxLI = (USHORT) (nMaxWidth - nWidth);
+ if ( nMaxLI < GetLeftIndent() )
+ SetLeftIndent( nMaxLI );
+ }
+ else
+ {
+ if( mbHScroll )
+ bArrange = TRUE;
+ mbHScroll = FALSE;
+ SetLeftIndent( 0 );
+ }
+ }
+
+ if( bArrange )
+ ImplResizeControls();
+
+ ImplInitScrollBars();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::ImplInitScrollBars()
+{
+ Size aOutSz = maLBWindow.GetOutputSizePixel();
+
+ if ( mbVScroll )
+ {
+ USHORT nEntries = GetEntryList()->GetEntryCount();
+ USHORT nVisEntries = (USHORT) (aOutSz.Height() / GetEntryHeight());
+ mpVScrollBar->SetRangeMax( nEntries );
+ mpVScrollBar->SetVisibleSize( nVisEntries );
+ mpVScrollBar->SetPageSize( nVisEntries - 1 );
+ }
+
+ if ( mbHScroll )
+ {
+ mpHScrollBar->SetRangeMax( GetMaxEntryWidth() + HORZ_SCROLL );
+ mpHScrollBar->SetVisibleSize( (USHORT)aOutSz.Width() );
+ mpHScrollBar->SetLineSize( HORZ_SCROLL );
+ mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::ImplResizeControls()
+{
+ // Hier werden die Controls nur angeordnet, ob die Scrollbars
+ // sichtbar sein sollen wird bereits in ImplCheckScrollBars ermittelt.
+
+ Size aOutSz = GetOutputSizePixel();
+ long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ nSBWidth = CalcZoom( nSBWidth );
+
+ Size aInnerSz( aOutSz );
+ if ( mbVScroll )
+ aInnerSz.Width() -= nSBWidth;
+ if ( mbHScroll )
+ aInnerSz.Height() -= nSBWidth;
+
+ maLBWindow.SetPosSizePixel( Point(), aInnerSz );
+
+ // ScrollBarBox
+ if( mbVScroll && mbHScroll )
+ {
+ mpScrollBarBox->SetPosSizePixel( Point( aInnerSz.Width(), aInnerSz.Height() ),
+ Size( nSBWidth, nSBWidth ) );
+ mpScrollBarBox->Show();
+ }
+ else
+ {
+ mpScrollBarBox->Hide();
+ }
+
+ // vert. ScrollBar
+ if( mbVScroll )
+ {
+ mpVScrollBar->SetPosSizePixel( Point( aOutSz.Width()-nSBWidth, 0 ),
+ Size( nSBWidth, aInnerSz.Height() ) );
+ mpVScrollBar->Show();
+ }
+ else
+ {
+ mpVScrollBar->Hide();
+ SetTopEntry( 0 );
+ }
+
+ // horz. ScrollBar
+ if( mbHScroll )
+ {
+ mpHScrollBar->SetPosSizePixel( Point( 0, aOutSz.Height()-nSBWidth ),
+ Size( aInnerSz.Width(), nSBWidth ) );
+ mpHScrollBar->Show();
+ }
+ else
+ {
+ mpHScrollBar->Hide();
+ SetLeftIndent( 0 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ ImplCheckScrollBars();
+ }
+ else if ( ( nType == STATE_CHANGE_UPDATEMODE ) || ( nType == STATE_CHANGE_DATA ) )
+ {
+ BOOL bUpdate = IsUpdateMode();
+ maLBWindow.SetUpdateMode( bUpdate );
+// mpHScrollBar->SetUpdateMode( bUpdate );
+// mpVScrollBar->SetUpdateMode( bUpdate );
+ if ( bUpdate && IsReallyVisible() )
+ ImplCheckScrollBars();
+ }
+ else if( nType == STATE_CHANGE_ENABLE )
+ {
+ mpHScrollBar->Enable( IsEnabled() );
+ mpVScrollBar->Enable( IsEnabled() );
+ mpScrollBarBox->Enable( IsEnabled() );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ maLBWindow.SetZoom( GetZoom() );
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ maLBWindow.SetControlFont( GetControlFont() );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ maLBWindow.SetControlForeground( GetControlForeground() );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ maLBWindow.SetControlBackground( GetControlBackground() );
+ }
+
+ Control::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+// if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+// (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+// {
+// maLBWindow.SetSettings( GetSettings() );
+// Resize();
+// }
+// else
+ Control::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long ImplListBox::Notify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ if ( rNEvt.GetType() == EVENT_COMMAND )
+ {
+ const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
+ if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
+ {
+ nDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
+ }
+ }
+ }
+
+ return nDone ? nDone : Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplListBox::HandleWheelAsCursorTravel( const CommandEvent& rCEvt )
+{
+ BOOL bDone = FALSE;
+ if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
+ {
+ USHORT nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
+ KeyEvent aKeyEvent( 0, KeyCode( nKey ) );
+ bDone = ProcessKeyInput( aKeyEvent );
+ }
+ }
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
+{
+ BOOL bChanges = GetEntryList()->GetMRUCount() ? TRUE : FALSE;
+
+ // Remove old MRU entries
+ for ( USHORT n = GetEntryList()->GetMRUCount();n; )
+ maLBWindow.RemoveEntry( --n );
+
+ USHORT nMRUCount = 0;
+ USHORT nEntries = rEntries.GetTokenCount( cSep );
+ for ( USHORT nEntry = 0; nEntry < nEntries; nEntry++ )
+ {
+ XubString aEntry = rEntries.GetToken( nEntry, cSep );
+ // Accept only existing entries
+ if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
+ {
+ ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
+ maLBWindow.GetEntryList()->InsertEntry( nMRUCount++, pNewEntry, FALSE );
+ bChanges = TRUE;
+ }
+ }
+
+ if ( bChanges )
+ {
+ maLBWindow.GetEntryList()->SetMRUCount( nMRUCount );
+ SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString ImplListBox::GetMRUEntries( xub_Unicode cSep ) const
+{
+ String aEntries;
+ for ( USHORT n = 0; n < GetEntryList()->GetMRUCount(); n++ )
+ {
+ aEntries += GetEntryList()->GetEntryText( n );
+ if( n < ( GetEntryList()->GetMRUCount() - 1 ) )
+ aEntries += cSep;
+ }
+ return aEntries;
+}
+
+// =======================================================================
+
+ImplWin::ImplWin( Window* pParent, WinBits nWinStyle ) :
+ Control ( pParent, nWinStyle )
+{
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
+ mbInUserDraw = FALSE;
+ mbUserDrawEnabled = FALSE;
+ mnItemPos = LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::MBDown()
+{
+ if( IsEnabled() )
+ maMBDownHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if( IsEnabled() )
+ {
+// Control::MouseButtonDown( rMEvt );
+ MBDown();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::Paint( const Rectangle& rRect )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if( IsEnabled() )
+ {
+ if( HasFocus() )
+ {
+ SetTextColor( rStyleSettings.GetHighlightTextColor() );
+ SetFillColor( rStyleSettings.GetHighlightColor() );
+ DrawRect( maFocusRect );
+ }
+ else
+ {
+ Color aColor = rStyleSettings.GetFieldTextColor();
+ if( IsControlForeground() )
+ aColor = GetControlForeground();
+ SetTextColor( aColor );
+ Erase( maFocusRect );
+ }
+ }
+ else // Disabled
+ {
+ SetTextColor( rStyleSettings.GetDisableColor() );
+ Erase( maFocusRect );
+ }
+
+ if ( IsUserDrawEnabled() )
+ {
+ mbInUserDraw = TRUE;
+ UserDrawEvent aUDEvt( this, maFocusRect, mnItemPos, 0 );
+ maUserDrawHdl.Call( &aUDEvt );
+ mbInUserDraw = FALSE;
+ }
+ else
+ {
+ DrawEntry( TRUE, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::DrawEntry( BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos )
+{
+ long nBorder = 1;
+ Size aOutSz = GetOutputSizePixel();
+
+ BOOL bImage = !!maImage;
+ if( bDrawImage && bImage )
+ {
+ Size aImgSz = maImage.GetSizePixel();
+ Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
+
+ if ( !IsZoom() )
+ {
+ DrawImage( aPtImg, maImage );
+ }
+ else
+ {
+ aImgSz.Width() = CalcZoom( aImgSz.Width() );
+ aImgSz.Height() = CalcZoom( aImgSz.Height() );
+ DrawImage( aPtImg, aImgSz, maImage );
+ }
+ }
+
+ if( bDrawText && maString.Len() )
+ {
+ long nTextHeight = GetTextHeight();
+ Point aPtTxt( nBorder, (aOutSz.Height()-nTextHeight)/2 );
+ if ( !bDrawTextAtImagePos && ( bImage || IsUserDrawEnabled() ) )
+ {
+ long nMaxWidth = Max( maImage.GetSizePixel().Width(), maUserItemSize.Width() );
+ aPtTxt.X() += nMaxWidth + IMG_TXT_DISTANCE;
+ }
+ DrawText( aPtTxt, maString );
+ }
+
+ if( HasFocus() )
+ ShowFocus( maFocusRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::Resize()
+{
+ maFocusRect.SetSize( GetOutputSizePixel() );
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::GetFocus()
+{
+ ShowFocus( maFocusRect );
+ Invalidate();
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWin::LoseFocus()
+{
+ HideFocus();
+ Invalidate();
+ Control::LoseFocus();
+}
+
+// =======================================================================
+
+ImplBtn::ImplBtn( Window* pParent, WinBits nWinStyle ) :
+ PushButton( pParent, nWinStyle ),
+ mbDown ( FALSE )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBtn::MBDown()
+{
+ if( IsEnabled() )
+ maMBDownHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBtn::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ //PushButton::MouseButtonDown( rMEvt );
+ if( IsEnabled() )
+ {
+ MBDown();
+ mbDown = TRUE;
+ }
+}
+
+// =======================================================================
+
+ImplListBoxFloatingWindow::ImplListBoxFloatingWindow( Window* pParent ) :
+ FloatingWindow( pParent, WB_NOBORDER )
+{
+ mpImplLB = NULL;
+ mnDDLineCount = 0;
+ mbAutoWidth = FALSE;
+
+ EnableSaveBackground();
+}
+
+// -----------------------------------------------------------------------
+
+long ImplListBoxFloatingWindow::PreNotify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if( !GetParent()->HasChildPathFocus( TRUE ) )
+ EndPopupMode();
+ }
+
+ return FloatingWindow::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxFloatingWindow::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, USHORT nFlags )
+{
+ FloatingWindow::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+
+ // Fix #60890# ( MBA ): um auch im aufgeklappten Zustand der Listbox die Gr"o\se einfach zu einen
+ // Aufruf von Resize() "andern zu k"onnen, wird die Position hier ggf. angepa\t
+ if ( IsReallyVisible() && ( nFlags & WINDOW_POSSIZE_HEIGHT ) )
+ {
+ Point aPos = GetParent()->GetPosPixel();
+ aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
+
+ if ( nFlags & WINDOW_POSSIZE_X )
+ aPos.X() = nX;
+
+ if ( nFlags & WINDOW_POSSIZE_Y )
+ aPos.Y() = nY;
+
+ USHORT nIndex;
+ SetPosPixel( ImplCalcPos( this, Rectangle( aPos, GetParent()->GetSizePixel() ), FLOATWIN_POPUPMODE_DOWN, nIndex ) );
+ }
+
+// if( !IsReallyVisible() )
+ {
+ // Die ImplListBox erhaelt kein Resize, weil nicht sichtbar.
+ // Die Fenster muessen aber ein Resize() erhalten, damit die
+ // Anzahl der sichtbaren Eintraege fuer PgUp/PgDown stimmt.
+ // Die Anzahl kann auch nicht von List/Combobox berechnet werden,
+ // weil hierfuer auch die ggf. vorhandene vertikale Scrollbar
+ // beruecksichtigt werden muss.
+ mpImplLB->SetSizePixel( GetOutputSizePixel() );
+ ((Window*)mpImplLB)->Resize();
+ ((Window*)mpImplLB->GetMainWindow())->Resize();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size ImplListBoxFloatingWindow::CalcFloatSize()
+{
+ Size aFloatSz( maPrefSz );
+
+ long nLeft, nTop, nRight, nBottom;
+ GetBorder( nLeft, nTop, nRight, nBottom );
+
+ USHORT nLines = mpImplLB->GetEntryList()->GetEntryCount();
+ if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
+ nLines = mnDDLineCount;
+
+ Size aSz = mpImplLB->CalcSize( nLines );
+ long nMaxHeight = aSz.Height() + nTop + nBottom;
+
+ if ( mnDDLineCount )
+ aFloatSz.Height() = nMaxHeight;
+
+ if( mbAutoWidth )
+ {
+ // AutoSize erstmal nur fuer die Breite...
+
+ aFloatSz.Width() = aSz.Width() + nLeft + nRight;
+ aFloatSz.Width() += nRight; // etwas mehr Platz sieht besser aus...
+
+ if ( aFloatSz.Height() < nMaxHeight )
+ {
+ // dann wird noch der vertikale Scrollbar benoetigt
+ long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ aFloatSz.Width() += nSBWidth;
+ }
+ }
+
+ if ( aFloatSz.Height() > nMaxHeight )
+ aFloatSz.Height() = nMaxHeight;
+
+ // Minimale Hoehe, falls Hoehe nicht auf Float-Hoehe eingestellt wurde.
+ // Der Parent vom FloatWin muss die DropDown-Combo/Listbox sein.
+ Size aParentSz = GetParent()->GetSizePixel();
+ if( aFloatSz.Height() < aParentSz.Height() )
+ aFloatSz.Height() = aParentSz.Height();
+
+ // Nicht schmaler als der Parent werden...
+ if( aFloatSz.Width() < aParentSz.Width() )
+ aFloatSz.Width() = aParentSz.Width();
+
+ // Hoehe auf Entries alignen...
+ long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
+ long nEntryHeight = mpImplLB->GetEntryHeight();
+ if ( nInnerHeight % nEntryHeight )
+ {
+ nInnerHeight /= nEntryHeight;
+ nInnerHeight++;
+ nInnerHeight *= nEntryHeight;
+ aFloatSz.Height() = nInnerHeight + nTop + nBottom;
+ }
+
+ return aFloatSz;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplListBoxFloatingWindow::StartFloat( BOOL bStartTracking )
+{
+ if( !IsInPopupMode() )
+ {
+ Size aFloatSz = CalcFloatSize();
+
+ SetSizePixel( aFloatSz );
+ mpImplLB->SetSizePixel( GetOutputSizePixel() );
+
+ Size aSz = GetParent()->GetSizePixel();
+ Point aPos = GetParent()->GetPosPixel();
+ aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
+ Rectangle aRect( aPos, aSz );
+ StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN );
+
+ USHORT nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 );
+ if( nPos != LISTBOX_ENTRY_NOTFOUND )
+ mpImplLB->SetTopEntry( nPos );
+
+ if( bStartTracking )
+ mpImplLB->GetMainWindow()->EnableMouseMoveSelect( TRUE );
+
+ if ( mpImplLB->GetMainWindow()->IsGrabFocusAllowed() )
+ mpImplLB->GetMainWindow()->GrabFocus();
+ }
+}
+
diff --git a/vcl/source/control/imgctrl.cxx b/vcl/source/control/imgctrl.cxx
new file mode 100644
index 000000000000..ac1758e8e27d
--- /dev/null
+++ b/vcl/source/control/imgctrl.cxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * $RCSfile: imgctrl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMGCTRL_CXX
+
+#include <imgctrl.hxx>
+
+// -----------------------------------------------------------------------
+
+ImageControl::ImageControl( Window* pParent, WinBits nStyle ) :
+ FixedImage( pParent, nStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImageControl::Resize()
+{
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImageControl::UserDraw( const UserDrawEvent& rUDEvt )
+{
+ maBmp.Draw( rUDEvt.GetDevice(),
+ rUDEvt.GetRect().TopLeft(),
+ rUDEvt.GetRect().GetSize() );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageControl::SetBitmap( const BitmapEx& rBmp )
+{
+ maBmp = rBmp;
+ StateChanged( STATE_CHANGE_DATA );
+}
diff --git a/vcl/source/control/longcurr.cxx b/vcl/source/control/longcurr.cxx
new file mode 100644
index 000000000000..2fe137dda52f
--- /dev/null
+++ b/vcl/source/control/longcurr.cxx
@@ -0,0 +1,873 @@
+/*************************************************************************
+ *
+ * $RCSfile: longcurr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define VCL_LONGCURR_CXX
+
+#include <sot/object.hxx>
+#define _TOOLS_BIGINT
+#include <sot/factory.hxx>
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _BIGINT_HXX
+#include <tools/bigint.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#include <event.hxx>
+#include <svapp.hxx>
+#include <svdata.hxx>
+#include <longcurr.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define FORMAT_LONGCURRENCY 4
+
+// =======================================================================
+
+static BigInt ImplPower10( USHORT n )
+{
+ USHORT i;
+ BigInt nValue = 1;
+
+ for ( i=0; i < n; i++ )
+ nValue *= 10;
+
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
+ BOOL bStrictFormat,
+ const International& rInter )
+{
+ if ( !bStrictFormat )
+ return FALSE;
+ else
+ {
+ sal_Unicode cChar = rKEvt.GetCharCode();
+ USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
+
+ if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
+ (nGroup == KEYGROUP_MISC) ||
+ ((cChar >= '0') && (cChar <= '9')) ||
+ (rInter.IsNumThousandSep() && (cChar == rInter.GetNumThousandSep())) ||
+ (cChar == rInter.GetNumDecimalSep()) ||
+ (cChar == '-') )
+ return FALSE;
+ else
+ return TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplNumericGetValue( const XubString& rStr, BigInt& rValue,
+ USHORT nDecDigits, const International& rInter,
+ BOOL bCurrency = FALSE )
+{
+ XubString aStr = rStr;
+ XubString aStr1;
+ XubString aStr2;
+ USHORT nDecPos;
+ BOOL bNegative = FALSE;
+ xub_StrLen i;
+
+ // Reaktion auf leeren String
+ if ( !rStr.Len() )
+ return FALSE;
+
+ // Fuehrende und nachfolgende Leerzeichen entfernen
+ aStr.EraseLeadingAndTrailingChars( ' ' );
+
+ // Position des Dezimalpunktes suchen
+ nDecPos = aStr.Search( rInter.GetNumDecimalSep() );
+
+ if ( nDecPos != STRING_NOTFOUND )
+ {
+ aStr1 = aStr.Copy( 0, nDecPos );
+ aStr2 = aStr.Copy( nDecPos+1 );
+ }
+ else
+ aStr1 = aStr;
+
+ // Negativ ?
+ if ( bCurrency )
+ {
+ if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') )
+ bNegative = TRUE;
+ if ( !bNegative )
+ {
+ for ( i=0; i < aStr.Len(); i++ )
+ {
+ if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
+ break;
+ else if ( aStr.GetChar( i ) == '-' )
+ {
+ bNegative = TRUE;
+ break;
+ }
+ }
+ }
+ if ( !bNegative && bCurrency && aStr.Len() )
+ {
+ USHORT nFormat = rInter.GetCurrNegativeFormat();
+ if ( (nFormat == 3) || (nFormat == 6) ||
+ (nFormat == 7) || (nFormat == 10) )
+ {
+ for ( i = (USHORT)(aStr.Len()-1); i > 0; i++ )
+ {
+ if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
+ break;
+ else if ( aStr.GetChar( i ) == '-' )
+ {
+ bNegative = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( aStr1.GetChar( 0 ) == '-' )
+ bNegative = TRUE;
+ }
+
+ // Alle unerwuenschten Zeichen rauswerfen
+ for ( i=0; i < aStr1.Len(); )
+ {
+ if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') )
+ i++;
+ else
+ aStr1.Erase( i, 1 );
+ }
+ for ( i=0; i < aStr2.Len(); )
+ {
+ if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') )
+ i++;
+ else
+ aStr2.Erase( i, 1 );
+ }
+
+ if ( !aStr1.Len() && !aStr2.Len() )
+ return FALSE;
+
+ if ( !aStr1.Len() )
+ aStr1.Insert( '0' );
+ if ( bNegative )
+ aStr1.Insert( '-', 0 );
+
+ // Nachkommateil zurechtstutzen und dabei runden
+ BOOL bRound = FALSE;
+ if ( aStr2.Len() > nDecDigits )
+ {
+ if ( aStr2.GetChar( nDecDigits ) >= '5' )
+ bRound = TRUE;
+ aStr2.Erase( nDecDigits );
+ }
+ if ( aStr2.Len() < nDecDigits )
+ aStr2.Expand( nDecDigits, '0' );
+
+ aStr = aStr1;
+ aStr += aStr2;
+
+ // Bereichsueberpruefung
+ BigInt nValue( aStr );
+ if ( bRound )
+ {
+ if ( !bNegative )
+ nValue+=1;
+ else
+ nValue-=1;
+ }
+
+ rValue = nValue;
+
+ return TRUE;
+}
+
+// =======================================================================
+
+static BOOL ImplLongCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
+ BOOL, const International& rInter )
+{
+ // Es gibt hier kein sinnvolles StrictFormat, also alle
+ // Zeichen erlauben
+ return ImplNumericProcessKeyInput( pEdit, rKEvt, FALSE, rInter );
+}
+
+// -----------------------------------------------------------------------
+
+inline XubString ImplLongCurrencySetValue( BigInt nValue, USHORT nDecDigits,
+ const International& rInter )
+{
+ // Umwandeln in einen Waehrungsstring
+ return rInter.GetCurr( nValue, nDecDigits ); // ???
+}
+
+// -----------------------------------------------------------------------
+
+inline BOOL ImplLongCurrencyGetValue( const XubString& rStr, BigInt& rValue,
+ USHORT nDecDigits, const International& rInter )
+{
+ // Zahlenwert holen
+ return ImplNumericGetValue( rStr, rValue, nDecDigits, rInter, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplLongCurrencyReformat( const XubString& rStr, BigInt nMin, BigInt nMax,
+ USHORT nDecDigits,
+ const International& rInter, String& rOutStr,
+ LongCurrencyFormatter& rFormatter )
+{
+ BigInt nValue;
+ if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rInter, TRUE ) )
+ return TRUE;
+ else
+ {
+ BigInt nTempVal = nValue;
+ if ( nTempVal > nMax )
+ nTempVal = nMax;
+ else if ( nTempVal < nMin )
+ nTempVal = nMin;
+
+ if ( rFormatter.GetErrorHdl().IsSet() && (nValue != nTempVal) )
+ {
+ rFormatter.mnCorrectedValue = nTempVal;
+ if ( !rFormatter.GetErrorHdl().Call( &rFormatter ) )
+ {
+ rFormatter.mnCorrectedValue = 0;
+ return FALSE;
+ }
+ else
+ rFormatter.mnCorrectedValue = 0;
+ }
+
+ rOutStr = rInter.GetCurr( nTempVal, nDecDigits );
+ return TRUE;
+ }
+}
+
+// =======================================================================
+
+void LongCurrencyFormatter::ImpInit()
+{
+ mnFieldValue = 0;
+ mnLastValue = 0;
+ mnMin = 0;
+ mnMax = 0x7FFFFFFF;
+ mnMax *= 0x7FFFFFFF;
+ mnCorrectedValue = 0;
+ mnType = FORMAT_LONGCURRENCY;
+ SetDecimalDigits( 0 );
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyFormatter::LongCurrencyFormatter()
+{
+ ImpInit();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::ImplLoadRes( const ResId& rResId )
+{
+ ImpInit();
+
+ ResMgr* pMgr = Resource::GetResManager();
+ USHORT nMask = pMgr->ReadShort();
+
+ if ( NUMERICFORMATTER_MIN & nMask )
+ mnMin = pMgr->ReadLong();
+
+ if ( NUMERICFORMATTER_MAX & nMask )
+ mnMax = pMgr->ReadLong();
+
+ if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
+ SetStrictFormat( (BOOL)pMgr->ReadShort() );
+
+ if ( NUMERICFORMATTER_I12 & nMask )
+ {
+ SetInternational( International( ResId( (RSHEADER_TYPE *)pMgr->GetClass() ) ) );
+ pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
+ }
+ if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
+ SetDecimalDigits( pMgr->ReadShort() );
+
+ if ( NUMERICFORMATTER_VALUE & nMask )
+ {
+ mnFieldValue = pMgr->ReadLong();
+ if ( mnFieldValue > mnMax )
+ mnFieldValue = mnMax;
+ else if ( mnFieldValue < mnMin )
+ mnFieldValue = mnMin;
+ mnLastValue = mnFieldValue;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyFormatter::~LongCurrencyFormatter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetValue( BigInt nNewValue )
+{
+ SetUserValue( nNewValue );
+ mnFieldValue = mnLastValue;
+ ImplGetEmptyFieldValue() = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetUserValue( BigInt nNewValue )
+{
+ if ( nNewValue > mnMax )
+ nNewValue = mnMax;
+ else if ( nNewValue < mnMin )
+ nNewValue = mnMin;
+ mnLastValue = nNewValue;
+
+ if ( !GetField() )
+ return;
+
+ XubString aStr = ImplLongCurrencySetValue( nNewValue, GetDecimalDigits(), GetInternational() );
+ if ( GetField()->HasFocus() )
+ {
+ Selection aSelection = GetField()->GetSelection();
+ GetField()->SetText( aStr );
+ GetField()->SetSelection( aSelection );
+ }
+ else
+ GetField()->SetText( aStr );
+ MarkToBeReformatted( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+BigInt LongCurrencyFormatter::GetValue() const
+{
+ if ( !GetField() )
+ return 0;
+
+ BigInt nTempValue;
+ if ( ImplLongCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(),
+ GetInternational() ) )
+ {
+ if ( nTempValue > mnMax )
+ nTempValue = mnMax;
+ else if ( nTempValue < mnMin )
+ nTempValue = mnMin;
+ return nTempValue;
+ }
+ else
+ return mnLastValue;
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::Reformat()
+{
+ if ( !GetField() )
+ return;
+
+ if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
+ return;
+
+ XubString aStr;
+ BOOL bOK = ImplLongCurrencyReformat( GetField()->GetText(), mnMin, mnMax,
+ GetDecimalDigits(), GetInternational(), aStr, *this );
+ if ( !bOK )
+ return;
+
+ if ( aStr.Len() )
+ {
+ GetField()->SetText( aStr );
+ MarkToBeReformatted( FALSE );
+ ImplLongCurrencyGetValue( aStr, mnLastValue, GetDecimalDigits(), GetInternational() );
+ }
+ else
+ SetValue( mnLastValue );
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::ReformatAll()
+{
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetMin( BigInt nNewMin )
+{
+ mnMin = nNewMin;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetMax( BigInt nNewMax )
+{
+ mnMax = nNewMax;
+ ReformatAll();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetDecimalDigits( USHORT nDigits )
+{
+ International aInter( GetInternational() );
+ aInter.SetCurrDigits( nDigits );
+ SetInternational( aInter );
+
+// ReformatAll(); // macht SetInternational()
+}
+
+// -----------------------------------------------------------------------
+
+USHORT LongCurrencyFormatter::GetDecimalDigits() const
+{
+ return GetInternational().GetCurrDigits();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL LongCurrencyFormatter::IsValueModified() const
+{
+ if ( ImplGetEmptyFieldValue() )
+ return !IsEmptyValue();
+ else if ( GetValue() != mnFieldValue )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyFormatter::SetEmptyValue()
+{
+ GetField()->SetText( ImplGetSVEmptyStr() );
+ ImplGetEmptyFieldValue() = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BigInt LongCurrencyFormatter::Normalize( BigInt nValue ) const
+{
+ return (nValue * ImplPower10( GetDecimalDigits() ) );
+}
+
+// -----------------------------------------------------------------------
+
+BigInt LongCurrencyFormatter::Denormalize( BigInt nValue ) const
+{
+ BigInt nFactor = ImplPower10( GetDecimalDigits() );
+ BigInt nTmp = nFactor;
+ nTmp /= 2;
+ nTmp += nValue;
+ nTmp /= nFactor;
+ return nTmp;
+}
+
+// =======================================================================
+
+void ImplNewLongCurrencyFieldValue( LongCurrencyField* pField, BigInt nNewValue )
+{
+ Selection aSelect = pField->GetSelection();
+ aSelect.Justify();
+ XubString aText = pField->GetText();
+ BOOL bLastSelected = ((xub_StrLen)aSelect.Max() == aText.Len()) ? TRUE : FALSE;
+
+ BigInt nOldLastValue = pField->mnLastValue;
+ pField->SetUserValue( nNewValue );
+ pField->mnLastValue = nOldLastValue;
+
+ if ( bLastSelected )
+ {
+ if ( !aSelect.Len() )
+ aSelect.Min() = SELECTION_MAX;
+ aSelect.Max() = SELECTION_MAX;
+ }
+ pField->SetSelection( aSelect );
+ pField->SetModifyFlag();
+ pField->Modify();
+}
+
+// =======================================================================
+
+LongCurrencyField::LongCurrencyField( Window* pParent, WinBits nWinStyle ) :
+ SpinField( pParent, nWinStyle )
+{
+ SetField( this );
+ mnSpinSize = 1;
+ mnFirst = mnMin;
+ mnLast = mnMax;
+
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyField::LongCurrencyField( Window* pParent, const ResId& rResId ) :
+ SpinField( WINDOW_NUMERICFIELD )
+{
+ rResId.SetRT( RSC_NUMERICFIELD );
+ WinBits nStyle = ImplInitRes( rResId ) ;
+ SpinField::ImplInit( pParent, nStyle );
+
+ SetField( this );
+ mnSpinSize = 1;
+ mnFirst = mnMin;
+ mnLast = mnMax;
+
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::ImplLoadRes( const ResId& rResId )
+{
+ SpinField::ImplLoadRes( rResId );
+ LongCurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+
+ USHORT nMask = ReadShortRes();
+ if ( CURRENCYFIELD_FIRST & nMask )
+ mnFirst = ReadLongRes();
+
+ if ( CURRENCYFIELD_LAST & nMask )
+ mnLast = ReadLongRes();
+
+ if ( CURRENCYFIELD_SPINSIZE & nMask )
+ mnSpinSize = ReadLongRes();
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyField::~LongCurrencyField()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long LongCurrencyField::PreNotify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+ return SpinField::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long LongCurrencyField::Notify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ MarkToBeReformatted( FALSE );
+ }
+ else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() )
+ {
+ Reformat();
+ SpinField::Modify();
+ }
+ }
+ return SpinField::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ SpinField::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::Up()
+{
+ BigInt nValue = GetValue();
+ nValue += mnSpinSize;
+ if ( nValue > mnMax )
+ nValue = mnMax;
+
+ ImplNewLongCurrencyFieldValue( this, nValue );
+ SpinField::Up();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::Down()
+{
+ BigInt nValue = GetValue();
+ nValue -= mnSpinSize;
+ if ( nValue < mnMin )
+ nValue = mnMin;
+
+ ImplNewLongCurrencyFieldValue( this, nValue );
+ SpinField::Down();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::First()
+{
+ ImplNewLongCurrencyFieldValue( this, mnFirst );
+ SpinField::First();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyField::Last()
+{
+ ImplNewLongCurrencyFieldValue( this, mnLast );
+ SpinField::Last();
+}
+
+// =======================================================================
+
+LongCurrencyBox::LongCurrencyBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ SetField( this );
+ Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyBox::LongCurrencyBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( WINDOW_NUMERICFIELD )
+{
+ SetField( this );
+ WinBits nStyle = ImplInitRes( rResId ) ;
+ ComboBox::ImplLoadRes( rResId );
+ LongCurrencyFormatter::ImplLoadRes( rResId );
+ Reformat();
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+LongCurrencyBox::~LongCurrencyBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+long LongCurrencyBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), GetInternational() ) )
+ return 1;
+ }
+ return ComboBox::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long LongCurrencyBox::Notify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ MarkToBeReformatted( FALSE );
+ }
+ else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( MustBeReformatted() )
+ {
+ Reformat();
+ ComboBox::Modify();
+ }
+ }
+ return ComboBox::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyBox::Modify()
+{
+ MarkToBeReformatted( TRUE );
+ ComboBox::Modify();
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyBox::ReformatAll()
+{
+ XubString aStr;
+ SetUpdateMode( FALSE );
+ USHORT nEntryCount = GetEntryCount();
+ for ( USHORT i=0; i < nEntryCount; i++ )
+ {
+ ImplLongCurrencyReformat( GetEntry( i ), mnMin, mnMax,
+ GetDecimalDigits(), GetInternational(),
+ aStr, *this );
+ RemoveEntry( i );
+ InsertEntry( aStr, i );
+ }
+ LongCurrencyFormatter::Reformat();
+ SetUpdateMode( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyBox::InsertValue( BigInt nValue, USHORT nPos )
+{
+ XubString aStr = ImplLongCurrencySetValue( nValue, GetDecimalDigits(), GetInternational() );
+ ComboBox::InsertEntry( aStr, nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void LongCurrencyBox::RemoveValue( BigInt nValue )
+{
+ XubString aStr = ImplLongCurrencySetValue( nValue, GetDecimalDigits(), GetInternational() );
+ ComboBox::RemoveEntry( aStr );
+}
+
+// -----------------------------------------------------------------------
+
+BigInt LongCurrencyBox::GetValue( USHORT nPos ) const
+{
+ BigInt nValue = 0;
+ ImplLongCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue,
+ GetDecimalDigits(), GetInternational() );
+ return nValue;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT LongCurrencyBox::GetValuePos( BigInt nValue ) const
+{
+ XubString aStr = ImplLongCurrencySetValue( nValue, GetDecimalDigits(), GetInternational() );
+ return ComboBox::GetEntryPos( aStr );
+}
+
+// =======================================================================
+
+XubString International::GetCurr( const BigInt &rNumber, USHORT nDigits ) const
+{
+ DBG_ASSERT( nDigits < 10, "LongCurrency duerfen nur maximal 9 Nachkommastellen haben" );
+
+ if ( rNumber.IsZero() || (long)rNumber )
+ return GetCurr( (long)rNumber, nDigits );
+
+ BigInt aTmp( ImplPower10( nDigits ) );
+ BigInt aInteger( rNumber );
+ aInteger.Abs();
+ aInteger /= aTmp;
+ BigInt aFraction( rNumber );
+ aFraction.Abs();
+ aFraction %= aTmp;
+ if ( !aInteger.IsZero() )
+ {
+ aFraction += aTmp;
+ aTmp = 1000000000L;
+ }
+ if ( rNumber.IsNeg() )
+ aFraction *= -1;
+
+ XubString aTemplate = GetCurr( (long)aFraction, nDigits );
+ while( !aInteger.IsZero() )
+ {
+ aFraction = aInteger;
+ aFraction %= aTmp;
+ aInteger /= aTmp;
+ if( !aInteger.IsZero() )
+ aFraction += aTmp;
+
+ XubString aFractionStr = GetNum( (long)aFraction, 0 );
+
+ xub_StrLen nSPos = aTemplate.Search( '1' );
+ if ( aFractionStr.Len() == 1 )
+ aTemplate.SetChar( nSPos, aFractionStr.GetChar( 0 ) );
+ else
+ {
+ aTemplate.Erase( nSPos, 1 );
+ aTemplate.Insert( aFractionStr, nSPos );
+ }
+ }
+
+ return aTemplate;
+}
diff --git a/vcl/source/control/lstbox.cxx b/vcl/source/control/lstbox.cxx
new file mode 100644
index 000000000000..f1e6eaadef8b
--- /dev/null
+++ b/vcl/source/control/lstbox.cxx
@@ -0,0 +1,1242 @@
+/*************************************************************************
+ *
+ * $RCSfile: lstbox.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_LSTBOX_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SCRBAR_HXX
+#include <scrbar.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_EDIT_HXX
+#include <edit.hxx>
+#endif
+#ifndef _SV_SUBEDIT_HXX
+#include <subedit.hxx>
+#endif
+#ifndef _SV_ILSTBOX_HXX
+#include <ilstbox.hxx>
+#endif
+#ifndef _SV_LSTBOX_HXX
+#include <lstbox.hxx>
+#endif
+#ifndef _SV_COMBOBOX_HXX
+#include <combobox.hxx>
+#endif
+
+#pragma hdrstop
+
+ // =======================================================================
+
+ListBox::ListBox( WindowType nType ) : Control( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::ListBox( Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::ListBox( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_LISTBOX )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_LISTBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ListBox::~ListBox()
+{
+ delete mpImplLB;
+
+ // Beim zerstoeren des FloatWins macht TH ein GrabFocus auf den Parent,
+ // also diese ListBox => PreNotify()...
+ mpImplLB = NULL;
+
+ delete mpFloatWin;
+ delete mpImplWin;
+ delete mpBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplInitData()
+{
+ mpFloatWin = NULL;
+ mpImplWin = NULL;
+ mpBtn = NULL;
+
+ mnDDHeight = 0;
+ mbDDAutoSize = TRUE;
+ mnSaveValue = LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ nStyle = ImplInitStyle( nStyle );
+ if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
+ nStyle |= WB_BORDER;
+
+ Control::ImplInit( pParent, nStyle, NULL );
+ SetBackground();
+
+ if( nStyle & WB_DROPDOWN )
+ {
+ long nLeft, nTop, nRight, nBottom;
+ GetBorder( nLeft, nTop, nRight, nBottom );
+ mnDDHeight = (USHORT)(GetTextHeight() + nTop + nBottom + 4);
+
+ mpFloatWin = new ImplListBoxFloatingWindow( this );
+ mpFloatWin->SetAutoWidth( TRUE );
+ mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) );
+
+ mpImplWin = new ImplWin( this, WB_NOBORDER );
+ mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
+ mpImplWin->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
+ mpImplWin->Show();
+
+ mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
+ ImplInitDropDownButton( mpBtn );
+ mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl ) );
+ mpBtn->Show();
+
+ }
+
+ Window* pLBParent = this;
+ if ( mpFloatWin )
+ pLBParent = mpFloatWin;
+ mpImplLB = new ImplListBox( pLBParent, nStyle&(~WB_BORDER) );
+ mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) );
+ mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) );
+ mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) );
+ mpImplLB->SetUserDrawHdl( LINK( this, ListBox, ImplUserDrawHdl ) );
+ mpImplLB->SetPosPixel( Point() );
+ mpImplLB->Show();
+
+ if ( mpFloatWin )
+ {
+ mpFloatWin->SetImplListBox( mpImplLB );
+ mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) );
+ }
+ else
+ mpImplLB->GetMainWindow()->AllowGrabFocus( TRUE );
+
+ SetCompoundControl( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits ListBox::ImplInitStyle( WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ USHORT nSelPos = ReadShortRes();
+ USHORT nNumber = ReadShortRes();
+
+ for( USHORT i = 0; i < nNumber; i++ )
+ {
+ USHORT nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND );
+
+ long nId = ReadLongRes();
+ if( nId )
+ SetEntryData( nPos, (void *)nId ); // ID als UserData
+ }
+
+ if( nSelPos < nNumber )
+ SelectEntryPos( nSelPos );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplSelectHdl, void*, EMPTYARG )
+{
+ BOOL bPopup = IsInDropDown();
+ if( IsDropDownBox() )
+ {
+ if( !mpImplLB->IsTravelSelect() )
+ {
+ mpFloatWin->EndPopupMode();
+ mpImplWin->GrabFocus();
+ }
+
+ mpImplWin->SetItemPos( GetSelectEntryPos() );
+ mpImplWin->SetString( GetSelectEntry() );
+ if( mpImplLB->GetEntryList()->HasImages() )
+ {
+ Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() );
+ mpImplWin->SetImage( aImage );
+ }
+ mpImplWin->Invalidate();
+ }
+
+ if ( mpImplLB->IsSelectionChanged() || ( bPopup && !IsMultiSelectionEnabled() ) )
+ Select();
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplCancelHdl, void*, EMPTYARG )
+{
+ if( IsInDropDown() )
+ mpFloatWin->EndPopupMode();
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n )
+{
+ if ( !mpImplLB->IsTrackingSelect() )
+ {
+ USHORT nChanged = (USHORT)(ULONG)n;
+ const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
+ if ( pEntryList->IsEntryPosSelected( nChanged ) )
+ {
+ // Sollte mal ein ImplPaintEntry werden...
+ if ( nChanged < pEntryList->GetMRUCount() )
+ nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ), MATCH_CASE, STRING_LEN, pEntryList->GetMRUCount() );
+ mpImplWin->SetItemPos( nChanged );
+ mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
+ if( mpImplLB->GetEntryList()->HasImages() )
+ {
+ Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
+ mpImplWin->SetImage( aImage );
+ }
+ mpImplWin->Invalidate();
+ }
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplDoubleClickHdl, void*, p )
+{
+ DoubleClick();
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplClickBtnHdl, void*, EMPTYARG )
+{
+ if( !mpFloatWin->IsInPopupMode() )
+ {
+ mpImplWin->GrabFocus();
+ mpBtn->SetPressed( TRUE );
+ mpFloatWin->StartFloat( TRUE );
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplPopupModeEndHdl, void*, p )
+{
+ mpBtn->SetPressed( FALSE );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
+{
+ mpImplLB->GetMainWindow()->ImplInitSettings( TRUE, TRUE, TRUE );
+
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
+ OutDevType eOutDevType = pDev->GetOutDevType();
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ pDev->SetTextFillColor();
+
+ // Border/Background
+ pDev->SetLineColor();
+ pDev->SetFillColor();
+ BOOL bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
+ BOOL bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
+ if ( bBorder || bBackground )
+ {
+ Rectangle aRect( aPos, aSize );
+ if ( bBorder )
+ {
+ DecorationView aDecoView( pDev );
+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ if ( bBackground )
+ {
+ pDev->SetFillColor( GetControlBackground() );
+ pDev->DrawRect( aRect );
+ }
+ }
+
+ // Inhalt
+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
+ {
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ }
+ else
+ {
+ if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ pDev->SetTextColor( rStyleSettings.GetDisableColor() );
+ }
+ else
+ {
+ pDev->SetTextColor( GetTextColor() );
+ }
+ }
+
+ long nOnePixel = GetDrawPixel( pDev, 1 );
+ if ( IsDropDownBox() )
+ {
+ XubString aText = GetSelectEntry();
+ long nTextHeight = pDev->GetTextHeight();
+ long nTextWidth = pDev->GetTextWidth( aText );
+ long nOffX = 3*nOnePixel;
+ long nOffY = (aSize.Height()-nTextHeight) / 2;
+
+ // Clipping?
+ if ( (nOffY < 0) ||
+ ((nOffY+nTextHeight) > aSize.Height()) ||
+ ((nOffX+nTextWidth) > aSize.Width()) )
+ {
+ Rectangle aClip( aPos, aSize );
+ if ( nTextHeight > aSize.Height() )
+ aClip.Bottom() += nTextHeight-aSize.Height()+1; // Damit HP-Drucker nicht 'weg-optimieren'
+ pDev->IntersectClipRegion( aClip );
+ }
+
+ pDev->DrawText( Point( aPos.X()+nOffX, aPos.Y()+nOffY ), aText );
+ }
+ else
+ {
+ long nTextHeight = pDev->GetTextHeight();
+ USHORT nLines = (USHORT)(aSize.Height() / nTextHeight);
+ Rectangle aClip( aPos, aSize );
+ pDev->IntersectClipRegion( aClip );
+ if ( !nLines )
+ nLines = 1;
+ for ( USHORT n = 0; n < nLines; n++ )
+ {
+ USHORT nEntry = n+mpImplLB->GetTopEntry();
+ BOOL bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
+ if ( bSelected )
+ {
+ pDev->SetFillColor( COL_BLACK );
+ pDev->DrawRect( Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ),
+ Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
+ pDev->SetFillColor();
+ pDev->SetTextColor( COL_WHITE );
+ }
+ pDev->DrawText( Point( aPos.X() + 3*nOnePixel, aPos.Y() + n*nTextHeight + nOnePixel ), mpImplLB->GetEntryList()->GetEntryText( nEntry ) );
+ if ( bSelected )
+ pDev->SetTextColor( COL_BLACK );
+ }
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::GetFocus()
+{
+ if ( mpImplLB )
+ {
+ if( IsDropDownBox() )
+ mpImplWin->GrabFocus();
+ else
+ mpImplLB->GrabFocus();
+ }
+
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::LoseFocus()
+{
+ if( IsDropDownBox() )
+ mpImplWin->HideFocus();
+ else
+ mpImplLB->HideFocus();
+
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ Resize();
+ mpImplLB->Resize(); // Wird nicht durch ListBox::Resize() gerufen, wenn sich die ImplLB nicht aendert.
+
+ if ( mpImplWin )
+ {
+ mpImplWin->SetSettings( GetSettings() ); // Falls noch nicht eingestellt...
+ ImplInitFieldSettings( mpImplWin, TRUE, TRUE, TRUE );
+
+ mpBtn->SetSettings( GetSettings() );
+ ImplInitDropDownButton( mpBtn );
+ }
+
+
+ if ( IsDropDownBox() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableAutoSize( BOOL bAuto )
+{
+ mbDDAutoSize = bAuto;
+ if ( mpFloatWin )
+ {
+ if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
+ mpFloatWin->SetDropDownLineCount( 5 );
+ else if ( !bAuto )
+ mpFloatWin->SetDropDownLineCount( 0 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetDropDownLineCount( USHORT nLines )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetDropDownLineCount( nLines );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetDropDownLineCount() const
+{
+ USHORT nLines = 0;
+ if ( mpFloatWin )
+ nLines = mpFloatWin->GetDropDownLineCount();
+ return nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, USHORT nFlags )
+{
+ if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
+ {
+ Size aPrefSz = mpFloatWin->GetPrefSize();
+ if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight > mnDDHeight ) )
+ aPrefSz.Height() = nHeight-mnDDHeight;
+ if ( nFlags & WINDOW_POSSIZE_WIDTH )
+ aPrefSz.Width() = nWidth;
+ mpFloatWin->SetPrefSize( aPrefSz );
+
+ if ( IsAutoSizeEnabled() )
+ nHeight = mnDDHeight;
+ }
+
+ Control::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Resize()
+{
+ Size aOutSz = GetOutputSizePixel();
+ if( IsDropDownBox() )
+ {
+ long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ nSBWidth = CalcZoom( nSBWidth );
+ mpImplWin->SetPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
+ mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
+ }
+ else
+ {
+ mpImplLB->SetSizePixel( aOutSz );
+ }
+
+ // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten,
+ // weil KEY_PGUP/DOWN ausgewertet wird...
+ if ( mpFloatWin )
+ mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::StateChanged( StateChangedType nType )
+{
+ if( nType == STATE_CHANGE_READONLY )
+ {
+ if( mpImplWin )
+ mpImplWin->Enable( !IsReadOnly() );
+ if( mpBtn )
+ mpBtn->Enable( !IsReadOnly() );
+ }
+ else if( nType == STATE_CHANGE_ENABLE )
+ {
+ mpImplLB->Enable( IsEnabled() );
+ if( mpImplWin )
+ {
+ mpImplWin->Enable( IsEnabled() );
+ mpImplWin->Invalidate();
+ }
+ if( mpBtn )
+ mpBtn->Enable( IsEnabled() );
+ }
+ else if( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ mpImplLB->SetUpdateMode( IsUpdateMode() );
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ mpImplLB->SetZoom( GetZoom() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetZoom( GetZoom() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ mpImplLB->SetControlFont( GetControlFont() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetControlFont( GetControlFont() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ Resize();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ mpImplLB->SetControlForeground( GetControlForeground() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetControlForeground( GetControlForeground() );
+ mpImplWin->SetTextColor( GetControlForeground() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ mpImplLB->SetControlBackground( GetControlBackground() );
+ if ( mpImplWin )
+ {
+ mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
+ mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
+ mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
+ mpImplWin->Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? TRUE : FALSE );
+ }
+
+ Control::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::PreNotify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ if ( mpImplLB )
+ {
+ if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
+ {
+ KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
+ switch( aKeyEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_DOWN:
+ {
+ if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
+ aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ mpBtn->SetPressed( TRUE );
+ mpFloatWin->StartFloat( FALSE );
+ nDone = 1;
+ }
+ else
+ {
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ break;
+ case KEY_UP:
+ {
+ if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
+ aKeyEvt.GetKeyCode().IsMod2() )
+ {
+ mpFloatWin->EndPopupMode();
+ nDone = 1;
+ }
+ else
+ {
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ if( IsInDropDown() )
+ {
+ mpImplLB->ProcessKeyInput( aKeyEvt );
+ nDone = 1;
+ }
+ }
+ break;
+
+ default:
+ nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
+ }
+ }
+ else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ if ( IsInDropDown() && !HasChildPathFocus( TRUE ) )
+ mpFloatWin->EndPopupMode();
+ }
+ else if ( (rNEvt.GetType() == EVENT_COMMAND) &&
+ (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
+ (rNEvt.GetWindow() == mpImplWin) )
+ {
+ nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
+ }
+ }
+
+ return nDone ? nDone : Control::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::Clear()
+{
+ mpImplLB->Clear();
+ if( IsDropDownBox() )
+ {
+ mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
+ mpImplWin->SetString( ImplGetSVEmptyStr() );
+ Image aImage;
+ mpImplWin->SetImage( aImage );
+ mpImplWin->Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetNoSelection()
+{
+ mpImplLB->SetNoSelection();
+ if( IsDropDownBox() )
+ {
+ mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
+ mpImplWin->SetString( ImplGetSVEmptyStr() );
+ Image aImage;
+ mpImplWin->SetImage( aImage );
+ mpImplWin->Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::InsertEntry( const XubString& rStr, USHORT nPos )
+{
+ USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
+ nRealPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::InsertEntry( const Image& rImage, USHORT nPos )
+{
+ USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rImage );
+ nRealPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::InsertEntry( const XubString& rStr, const Image& rImage, USHORT nPos )
+{
+ USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
+ nRealPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nRealPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::RemoveEntry( const XubString& rStr )
+{
+ RemoveEntry( GetEntryPos( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::RemoveEntry( USHORT nPos )
+{
+ mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetEntryPos( const XubString& rStr ) const
+{
+ USHORT nPos = mpImplLB->GetEntryList()->FindEntry( rStr, MATCH_CASE, STRING_LEN, mpImplLB->GetEntryList()->GetMRUCount() );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetEntryPos( const void* pData ) const
+{
+ USHORT nPos = mpImplLB->GetEntryList()->FindEntry( pData );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ nPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetEntry( USHORT nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetEntryCount() const
+{
+ return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetSelectEntry( USHORT nIndex ) const
+{
+ return GetEntry( GetSelectEntryPos( nIndex ) );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetSelectEntryCount() const
+{
+ return mpImplLB->GetEntryList()->GetSelectEntryCount();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetSelectEntryPos( USHORT nIndex ) const
+{
+ USHORT nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ {
+ if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
+ nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ), MATCH_CASE, STRING_LEN, mpImplLB->GetEntryList()->GetMRUCount() );
+ nPos -= mpImplLB->GetEntryList()->GetMRUCount();
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsEntrySelected( const XubString& rStr ) const
+{
+ return IsEntryPosSelected( GetEntryPos( rStr ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsEntryPosSelected( USHORT nPos ) const
+{
+ return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SelectEntry( const XubString& rStr, BOOL bSelect )
+{
+ SelectEntryPos( GetEntryPos( rStr ), bSelect );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SelectEntryPos( USHORT nPos, BOOL bSelect )
+{
+ if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() )
+ mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetEntryData( USHORT nPos, void* pNewData )
+{
+ mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
+}
+
+// -----------------------------------------------------------------------
+
+void* ListBox::GetEntryData( USHORT nPos ) const
+{
+ return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetTopEntry( USHORT nPos )
+{
+ mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetTopEntry() const
+{
+ USHORT nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
+ if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
+ nPos = 0;
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsTravelSelect() const
+{
+ return mpImplLB->IsTravelSelect();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsInDropDown() const
+{
+ return mpFloatWin && mpFloatWin->IsInPopupMode();
+}
+
+// -----------------------------------------------------------------------
+
+long ListBox::CalcWindowSizePixel( USHORT nLines ) const
+{
+ return mpImplLB->GetEntryHeight() * nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableMultiSelection( BOOL bMulti )
+{
+ mpImplLB->EnableMultiSelection( bMulti );
+
+ // WB_SIMPLEMODE:
+ // Die MultiListBox verhält sich wie eine normale ListBox.
+ // Die Mehrfachselektion kann nur über entsprechende Zusatztasten erfolgen.
+
+ BOOL bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) ? TRUE : FALSE;
+ mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
+
+ // ohne Focus ist das Traveln in einer MultiSelection nicht zu sehen:
+ if ( mpFloatWin )
+ mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsMultiSelectionEnabled() const
+{
+ return mpImplLB->IsMultiSelectionEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcMinimumSize() const
+{
+ Size aSz;
+ if ( !IsDropDownBox() )
+ {
+ aSz = mpImplLB->CalcSize( mpImplLB->GetEntryList()->GetEntryCount() );
+ }
+ else
+ {
+ aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
+ aSz.Width() = mpImplLB->GetMaxEntryWidth();
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
+{
+ Size aSz = rPrefSize;
+ long nLeft, nTop, nRight, nBottom;
+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
+ aSz.Height() -= nTop+nBottom;
+ if ( !IsDropDownBox() )
+ {
+ long nEntryHeight = CalcSize( 1, 1 ).Height();
+ long nLines = aSz.Height() / nEntryHeight;
+ if ( nLines < 1 )
+ nLines = 1;
+ aSz.Height() = nLines * nEntryHeight;
+ }
+ else
+ {
+ aSz.Height() = mnDDHeight;
+ }
+ aSz.Height() += nTop+nBottom;
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size ListBox::CalcSize( USHORT nColumns, USHORT nLines ) const
+{
+ // ggf. werden ScrollBars eingeblendet
+ Size aMinSz = CalcMinimumSize();
+// aMinSz = ImplCalcOutSz( aMinSz );
+
+ Size aSz;
+
+ // Hoehe
+ if ( nLines )
+ {
+ if ( !IsDropDownBox() )
+ aSz.Height() = mpImplLB->CalcSize( nLines ).Height();
+ else
+ aSz.Height() = mnDDHeight;
+ }
+ else
+ aSz.Height() = aMinSz.Height();
+
+ // Breite
+ if ( nColumns )
+ aSz.Width() = nColumns * GetTextWidth( XubString( 'X' ) );
+ else
+ aSz.Width() = aMinSz.Width();
+
+ if ( IsDropDownBox() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ if ( !IsDropDownBox() )
+ {
+ if ( aSz.Width() < aMinSz.Width() )
+ aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aSz.Height() < aMinSz.Height() )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ }
+
+ aSz = CalcWindowSize( aSz );
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::GetMaxVisColumnsAndLines( USHORT& rnCols, USHORT& rnLines ) const
+{
+ long nCharWidth = GetTextWidth( UniString( 'x' ) );
+ if ( !IsDropDownBox() )
+ {
+ Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
+ rnCols = (USHORT) (aOutSz.Width()/nCharWidth);
+ rnLines = (USHORT) (aOutSz.Height()/mpImplLB->GetEntryHeight());
+ }
+ else
+ {
+ Size aOutSz = mpImplWin->GetOutputSizePixel();
+ rnCols = (USHORT) (aOutSz.Width()/nCharWidth);
+ rnLines = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ListBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
+{
+ UserDraw( *pEvent );
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+#if SUPD < 593
+void ListBox::DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText )
+{
+ if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() )
+ mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText );
+ else if ( rEvt.GetDevice() == mpImplWin )
+ mpImplWin->DrawEntry( bDrawImage, bDrawText );
+}
+#endif
+
+void ListBox::DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos )
+{
+ if ( rEvt.GetDevice() == mpImplLB->GetMainWindow() )
+ mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
+ else if ( rEvt.GetDevice() == mpImplWin )
+ mpImplWin->DrawEntry( bDrawImage, bDrawText, bDrawTextAtImagePos );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetUserItemSize( const Size& rSz )
+{
+ mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
+ if ( mpImplWin )
+ mpImplWin->SetUserItemSize( rSz );
+}
+
+// -----------------------------------------------------------------------
+
+const Size& ListBox::GetUserItemSize() const
+{
+ return mpImplLB->GetMainWindow()->GetUserItemSize();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::EnableUserDraw( BOOL bUserDraw )
+{
+ mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
+ if ( mpImplWin )
+ mpImplWin->EnableUserDraw( bUserDraw );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsUserDrawEnabled() const
+{
+ return mpImplLB->GetMainWindow()->IsUserDrawEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetReadOnly( BOOL bReadOnly )
+{
+ if ( mpImplLB->IsReadOnly() != bReadOnly )
+ {
+ mpImplLB->SetReadOnly( bReadOnly );
+ StateChanged( STATE_CHANGE_READONLY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ListBox::IsReadOnly() const
+{
+ return mpImplLB->IsReadOnly();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetSeparatorPos( USHORT n )
+{
+ mpImplLB->SetSeparatorPos( n );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetSeparatorPos()
+{
+ mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetSeparatorPos() const
+{
+ return mpImplLB->GetSeparatorPos();
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
+{
+ mpImplLB->SetMRUEntries( rEntries, cSep );
+}
+
+// -----------------------------------------------------------------------
+
+XubString ListBox::GetMRUEntries( xub_Unicode cSep ) const
+{
+ return mpImplLB->GetMRUEntries( cSep );
+}
+
+// -----------------------------------------------------------------------
+
+void ListBox::SetMaxMRUCount( USHORT n )
+{
+ mpImplLB->SetMaxMRUCount( n );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ListBox::GetMaxMRUCount() const
+{
+ return mpImplLB->GetMaxMRUCount();
+}
+
+// =======================================================================
+
+MultiListBox::MultiListBox( Window* pParent, WinBits nStyle ) :
+ ListBox( WINDOW_MULTILISTBOX )
+{
+ ImplInit( pParent, nStyle );
+ EnableMultiSelection( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+MultiListBox::MultiListBox( Window* pParent, const ResId& rResId ) :
+ ListBox( WINDOW_MULTILISTBOX )
+{
+ rResId.SetRT( RSC_MULTILISTBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE ) )
+ Show();
+ EnableMultiSelection( TRUE );
+}
diff --git a/vcl/source/control/makefile.mk b/vcl/source/control/makefile.mk
new file mode 100644
index 000000000000..ba03559c2b71
--- /dev/null
+++ b/vcl/source/control/makefile.mk
@@ -0,0 +1,119 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=ctrl
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+.IF "$(COM)"=="ICC"
+CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/button.obj \
+ $(SLO)$/ctrl.obj \
+ $(SLO)$/combobox.obj \
+ $(SLO)$/edit.obj \
+ $(SLO)$/field.obj \
+ $(SLO)$/field2.obj \
+ $(SLO)$/fixbrd.obj \
+ $(SLO)$/fixed.obj \
+ $(SLO)$/group.obj \
+ $(SLO)$/ilstbox.obj \
+ $(SLO)$/imgctrl.obj \
+ $(SLO)$/longcurr.obj \
+ $(SLO)$/lstbox.obj \
+ $(SLO)$/morebtn.obj \
+ $(SLO)$/menubtn.obj \
+ $(SLO)$/scrbar.obj \
+ $(SLO)$/slider.obj \
+ $(SLO)$/spinfld.obj \
+ $(SLO)$/spinbtn.obj \
+ $(SLO)$/tabctrl.obj
+
+.IF "$(remote)"!=""
+EXCEPTIONSFILES= \
+ $(SLO)$/button.obj \
+ $(SLO)$/ctrl.obj \
+ $(SLO)$/edit.obj \
+ $(SLO)$/field.obj \
+ $(SLO)$/field2.obj \
+ $(SLO)$/longcurr.obj \
+ $(SLO)$/ilstbox.obj \
+ $(SLO)$/tabctrl.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
diff --git a/vcl/source/control/menubtn.cxx b/vcl/source/control/menubtn.cxx
new file mode 100644
index 000000000000..6891577b0b54
--- /dev/null
+++ b/vcl/source/control/menubtn.cxx
@@ -0,0 +1,285 @@
+/*************************************************************************
+ *
+ * $RCSfile: menubtn.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MENUBTN_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_MENUBTN_HXX
+#include <menubtn.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define IMAGEBUTTON_BORDER_OFF1 11
+#define IMAGEBUTTON_BORDER_OFF2 16
+
+// =======================================================================
+
+void MenuButton::ImplInitData()
+{
+ mnDDStyle = PUSHBUTTON_DROPDOWN_MENUBUTTON;
+
+ mpMenuTimer = NULL;
+ mpMenu = NULL;
+ mpOwnMenu = NULL;
+ mnCurItemId = 0;
+ mnMenuMode = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+
+ PushButton::ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::ImplExecuteMenu()
+{
+ Activate();
+
+ if ( mpMenu )
+ {
+ Point aPos( 0, 1 );
+ Size aSize = GetSizePixel();
+ Rectangle aRect( aPos, aSize );
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if ( !((GetStyle() & (WB_RECTSTYLE | WB_SMALLSTYLE)) ||
+ !(rStyleSettings.GetOptions() & STYLE_OPTION_MACSTYLE)) )
+ {
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+ }
+ SetPressed( TRUE );
+ EndSelection();
+ mnCurItemId = mpMenu->Execute( this, aRect, POPUPMENU_EXECUTE_DOWN );
+ SetPressed( FALSE );
+ if ( mnCurItemId )
+ {
+ Select();
+ mnCurItemId = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MenuButton::MenuButton( Window* pParent, WinBits nWinBits ) :
+ PushButton( WINDOW_MENUBUTTON )
+{
+ ImplInitData();
+ ImplInit( pParent, nWinBits );
+}
+
+// -----------------------------------------------------------------------
+
+MenuButton::MenuButton( Window* pParent, const ResId& rResId ) :
+ PushButton( WINDOW_MENUBUTTON )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_MENUBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( RSCMENUBUTTON_MENU & nObjMask )
+ {
+ mpOwnMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ SetPopupMenu( mpOwnMenu );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MenuButton::~MenuButton()
+{
+ if ( mpMenuTimer )
+ delete mpMenuTimer;
+ if ( mpOwnMenu )
+ delete mpOwnMenu;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( MenuButton, ImplMenuTimeoutHdl, Timer*, EMPTYARG )
+{
+ // Abfragen, ob Button-Benutzung noch aktiv ist, da diese ja auch
+ // vorher abgebrochen wurden sein koennte
+ if ( IsTracking() )
+ {
+ if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
+ GrabFocus();
+ ImplExecuteMenu();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( mnMenuMode & MENUBUTTON_MENUMODE_TIMED )
+ {
+ if ( !mpMenuTimer )
+ {
+ mpMenuTimer = new Timer;
+ mpMenuTimer->SetTimeoutHdl( LINK( this, MenuButton, ImplMenuTimeoutHdl ) );
+ }
+
+ mpMenuTimer->SetTimeout( GetSettings().GetMouseSettings().GetActionDelay() );
+ mpMenuTimer->Start();
+
+ PushButton::MouseButtonDown( rMEvt );
+ }
+ else
+ {
+ if ( PushButton::ImplHitTestPushButton( this, rMEvt.GetPosPixel(), 0 ) )
+ {
+ if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
+ GrabFocus();
+ ImplExecuteMenu();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ USHORT nCode = aKeyCode.GetCode();
+ if ( (nCode == KEY_DOWN) && aKeyCode.IsMod2() )
+ ImplExecuteMenu();
+ else if ( !(mnMenuMode & MENUBUTTON_MENUMODE_TIMED) &&
+ !aKeyCode.GetModifier() &&
+ ((nCode == KEY_RETURN) || (nCode == KEY_SPACE)) )
+ ImplExecuteMenu();
+ else
+ PushButton::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::Activate()
+{
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::SetMenuMode( USHORT nMode )
+{
+ // Fuer die 5.1-Auslieferung besser noch nicht inline, ansonsten kann
+ // diese Funktion zur 6.0 inline werden
+ mnMenuMode = nMode;
+}
+
+// -----------------------------------------------------------------------
+
+void MenuButton::SetPopupMenu( PopupMenu* pNewMenu )
+{
+ // Fuer die 5.1-Auslieferung besser noch nicht inline, ansonsten kann
+ // diese Funktion zur 6.0 inline werden
+ mpMenu = pNewMenu;
+}
diff --git a/vcl/source/control/morebtn.cxx b/vcl/source/control/morebtn.cxx
new file mode 100644
index 000000000000..6712e2e20399
--- /dev/null
+++ b/vcl/source/control/morebtn.cxx
@@ -0,0 +1,266 @@
+/*************************************************************************
+ *
+ * $RCSfile: morebtn.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MOREBTN_CXX
+
+#ifndef _SV_MOREBTN_HXX
+#include <morebtn.hxx>
+#endif
+
+#ifndef _SV_RD_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+// Muss mit der Laenge der folgenden Texte uebereinstimmen
+#define EXTRA_TEXTLEN 3
+
+static sal_Char const aImplMoreOpen[] = " >>";
+static sal_Char const aImplMoreClose[] = " <<";
+
+DECLARE_LIST( ImplMoreWindowList, Window* );
+
+// =======================================================================
+
+void MoreButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mpItemList = NULL;
+ mnDelta = 0;
+ meUnit = MAP_PIXEL;
+ mbState = FALSE;
+
+ PushButton::ImplInit( pParent, nStyle );
+
+ SetText( Button::GetStandardText( BUTTON_MORE ) );
+ SetHelpText( Button::GetStandardHelpText( BUTTON_MORE ) );
+}
+
+// -----------------------------------------------------------------------
+
+MoreButton::MoreButton( Window* pParent, WinBits nStyle ) :
+ PushButton( WINDOW_MOREBUTTON )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+MoreButton::MoreButton( Window* pParent, const ResId& rResId ) :
+ PushButton( WINDOW_MOREBUTTON )
+{
+ rResId.SetRT( RSC_MOREBUTTON );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void MoreButton::ImplLoadRes( const ResId& rResId )
+{
+ PushButton::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( nObjMask & RSC_MOREBUTTON_STATE )
+ {
+ // Nicht Methode rufen, da Dialog nicht umgeschaltet werden soll
+ mbState = (BOOL)ReadShortRes();
+ SetText( GetText() );
+ }
+ if ( nObjMask & RSC_MOREBUTTON_MAPUNIT )
+ meUnit = (MapUnit)ReadShortRes();
+ if ( nObjMask & RSC_MOREBUTTON_DELTA )
+ // Groesse fuer Erweitern des Dialogs
+ mnDelta = ReadShortRes();
+}
+
+// -----------------------------------------------------------------------
+
+MoreButton::~MoreButton()
+{
+ if ( mpItemList )
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+void MoreButton::Click()
+{
+ Window* pParent = GetParent();
+ Size aSize( pParent->GetSizePixel() );
+ Window* pWindow = (mpItemList) ? mpItemList->First() : NULL;
+ long nDeltaPixel = LogicToPixel( Size( 0, mnDelta ), meUnit ).Height();
+
+ // Status aendern
+ XubString aText = GetText();
+ mbState = !mbState;
+ SetText( aText );
+
+ // Hier den Click-Handler rufen, damit vorher die Controls initialisiert
+ // werden koennen
+ PushButton::Click();
+
+ // Je nach Status die Fenster updaten
+ if ( mbState )
+ {
+ // Fenster anzeigen
+ while ( pWindow )
+ {
+ pWindow->Show();
+ pWindow = mpItemList->Next();
+ }
+
+ // Dialogbox anpassen
+ Point aPos( pParent->GetPosPixel() );
+ Rectangle aDeskRect( pParent->ImplGetFrameWindow()->GetDesktopRectPixel() );
+
+ aSize.Height() += nDeltaPixel;
+ if ( (aPos.Y()+aSize.Height()) > aDeskRect.Bottom() )
+ {
+ aPos.Y() = aDeskRect.Bottom()-aSize.Height();
+
+ if ( aPos.Y() < aDeskRect.Top() )
+ aPos.Y() = aDeskRect.Top();
+
+ pParent->SetPosSizePixel( aPos, aSize );
+ }
+ else
+ pParent->SetSizePixel( aSize );
+ }
+ else
+ {
+ // Dialogbox anpassen
+ aSize.Height() -= nDeltaPixel;
+ pParent->SetSizePixel( aSize );
+
+ // Fenster nicht mehr anzeigen
+ while ( pWindow )
+ {
+ pWindow->Hide();
+ pWindow = mpItemList->Next();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MoreButton::AddWindow( Window* pWindow )
+{
+ if ( !mpItemList )
+ mpItemList = new ImplMoreWindowList( 1024, 16, 16 );
+
+ mpItemList->Insert( pWindow, LIST_APPEND );
+
+ if ( mbState )
+ pWindow->Show();
+ else
+ pWindow->Hide();
+}
+
+// -----------------------------------------------------------------------
+
+void MoreButton::RemoveWindow( Window* pWindow )
+{
+ if ( mpItemList )
+ mpItemList->Remove( pWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void MoreButton::SetText( const XubString& rText )
+{
+ XubString aText = rText;
+
+ if ( !mbState )
+ aText.AppendAscii( aImplMoreOpen );
+ else
+ aText.AppendAscii( aImplMoreClose );
+
+ PushButton::SetText( aText );
+}
+
+// -----------------------------------------------------------------------
+
+XubString MoreButton::GetText() const
+{
+ XubString aText = PushButton::GetText();
+
+ XubString aSubText = aText.Copy( aText.Len()-EXTRA_TEXTLEN, EXTRA_TEXTLEN );
+ if ( !mbState )
+ {
+ if ( aSubText.EqualsAscii( aImplMoreOpen ) )
+ aText.Erase( aText.Len()-EXTRA_TEXTLEN, EXTRA_TEXTLEN );
+ }
+ else
+ {
+ if ( aSubText.EqualsAscii( aImplMoreClose ) )
+ aText.Erase( aText.Len()-EXTRA_TEXTLEN, EXTRA_TEXTLEN );
+ }
+
+ return aText;
+}
diff --git a/vcl/source/control/scrbar.cxx b/vcl/source/control/scrbar.cxx
new file mode 100644
index 000000000000..e070b607dd74
--- /dev/null
+++ b/vcl/source/control/scrbar.cxx
@@ -0,0 +1,1245 @@
+/*************************************************************************
+ *
+ * $RCSfile: scrbar.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SCRBAR_CXX
+
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SCRBAR_HXX
+#include <scrbar.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
+{
+ double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
+ return (long)n;
+}
+
+// =======================================================================
+
+#define SCRBAR_DRAW_BTN1 ((USHORT)0x0001)
+#define SCRBAR_DRAW_BTN2 ((USHORT)0x0002)
+#define SCRBAR_DRAW_PAGE1 ((USHORT)0x0004)
+#define SCRBAR_DRAW_PAGE2 ((USHORT)0x0008)
+#define SCRBAR_DRAW_THUMB ((USHORT)0x0010)
+#define SCRBAR_DRAW_ALL (SCRBAR_DRAW_BTN1 | SCRBAR_DRAW_BTN2 | \
+ SCRBAR_DRAW_PAGE1 | SCRBAR_DRAW_PAGE2 |\
+ SCRBAR_DRAW_THUMB)
+
+#define SCRBAR_STATE_BTN1_DOWN ((USHORT)0x0001)
+#define SCRBAR_STATE_BTN1_DISABLE ((USHORT)0x0002)
+#define SCRBAR_STATE_BTN2_DOWN ((USHORT)0x0004)
+#define SCRBAR_STATE_BTN2_DISABLE ((USHORT)0x0008)
+#define SCRBAR_STATE_PAGE1_DOWN ((USHORT)0x0010)
+#define SCRBAR_STATE_PAGE2_DOWN ((USHORT)0x0020)
+#define SCRBAR_STATE_THUMB_DOWN ((USHORT)0x0040)
+
+#define SCRBAR_MIN_THUMB 8
+
+#define SCRBAR_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
+
+// =======================================================================
+
+void ScrollBar::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mpDDScrollTimer = NULL;
+ mnThumbPixRange = 0;
+ mnThumbPixPos = 0;
+ mnThumbPixSize = 0;
+ mnMinRange = 0;
+ mnMaxRange = 100;
+ mnThumbPos = 0;
+ mnVisibleSize = 0;
+ mnLineSize = 1;
+ mnPageSize = 1;
+ mnDelta = 0;
+ mnDragDraw = 0;
+ mnStateFlags = 0;
+ meScrollType = SCROLL_DONTKNOW;
+ meDDScrollType = SCROLL_DONTKNOW;
+ mbCalcSize = TRUE;
+ mbFullDrag = 0;
+ mbDDScroll = FALSE;
+
+ ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+
+ long nScrollSize = GetSettings().GetStyleSettings().GetScrollBarSize();
+ SetSizePixel( Size( nScrollSize, nScrollSize ) );
+ SetBackground();
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplInitStyle( WinBits nStyle )
+{
+ if ( nStyle & WB_DRAG )
+ mbFullDrag = TRUE;
+ else
+ mbFullDrag = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SCROLL) != 0;
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::ScrollBar( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_SCROLLBAR )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::ScrollBar( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_SCROLLBAR )
+{
+ rResId.SetRT( RSC_SCROLLBAR );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBar::~ScrollBar()
+{
+ if ( mpDDScrollTimer )
+ {
+ delete mpDDScrollTimer;
+ mpDDScrollTimer = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ INT16 nMin = ReadShortRes();
+ INT16 nMax = ReadShortRes();
+ INT16 nThumbPos = ReadShortRes();
+ INT16 nPage = ReadShortRes();
+ INT16 nStep = ReadShortRes();
+ INT16 nVisibleSize = ReadShortRes();
+
+ SetRange( Range( nMin, nMax ) );
+ SetLineSize( nStep );
+ SetPageSize( nPage );
+ SetVisibleSize( nVisibleSize );
+ SetThumbPos( nThumbPos );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ScrollBar::ImplUpdateThumbRect( const Rectangle& rOldRect )
+{
+ Size aThumbRectSize = rOldRect.GetSize();
+/* !!! Wegen ueberlappenden Fenstern ... !!!
+ if ( aThumbRectSize == maThumbRect.GetSize() )
+ {
+ DrawOutDev( maThumbRect.TopLeft(), aThumbRectSize,
+ rOldRect.TopLeft(), aThumbRectSize );
+ return TRUE;
+ }
+ else
+*/
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplUpdateRects( BOOL bUpdate )
+{
+ USHORT nOldStateFlags = mnStateFlags;
+ Rectangle aOldPage1Rect = maPage1Rect;
+ Rectangle aOldPage2Rect = maPage2Rect;
+ Rectangle aOldThumbRect = maThumbRect;
+
+ mnStateFlags &= ~SCRBAR_STATE_BTN1_DISABLE;
+ mnStateFlags &= ~SCRBAR_STATE_BTN2_DISABLE;
+
+ if ( mnThumbPixRange )
+ {
+ if ( GetStyle() & WB_HORZ )
+ {
+ maThumbRect.Left() = maBtn1Rect.Right()+1+mnThumbPixPos;
+ maThumbRect.Right() = maThumbRect.Left()+mnThumbPixSize-1;
+ if ( !mnThumbPixPos )
+ maPage1Rect.Right() = RECT_EMPTY;
+ else
+ maPage1Rect.Right() = maThumbRect.Left()-1;
+ if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
+ maPage2Rect.Right() = RECT_EMPTY;
+ else
+ {
+ maPage2Rect.Left() = maThumbRect.Right()+1;
+ maPage2Rect.Right() = maBtn2Rect.Left()-1;
+ }
+ }
+ else
+ {
+ maThumbRect.Top() = maBtn1Rect.Bottom()+1+mnThumbPixPos;
+ maThumbRect.Bottom() = maThumbRect.Top()+mnThumbPixSize-1;
+ if ( !mnThumbPixPos )
+ maPage1Rect.Bottom() = RECT_EMPTY;
+ else
+ maPage1Rect.Bottom() = maThumbRect.Top()-1;
+ if ( mnThumbPixPos >= (mnThumbPixRange-mnThumbPixSize) )
+ maPage2Rect.Bottom() = RECT_EMPTY;
+ else
+ {
+ maPage2Rect.Top() = maThumbRect.Bottom()+1;
+ maPage2Rect.Bottom() = maBtn2Rect.Top()-1;
+ }
+ }
+ }
+
+ if ( mnThumbPos == mnMinRange )
+ mnStateFlags |= SCRBAR_STATE_BTN1_DISABLE;
+ if ( mnThumbPos >= (mnMaxRange-mnVisibleSize) )
+ mnStateFlags |= SCRBAR_STATE_BTN2_DISABLE;
+
+ if ( bUpdate )
+ {
+ USHORT nDraw = 0;
+ if ( (nOldStateFlags & SCRBAR_STATE_BTN1_DISABLE) !=
+ (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
+ nDraw |= SCRBAR_DRAW_BTN1;
+ if ( (nOldStateFlags & SCRBAR_STATE_BTN2_DISABLE) !=
+ (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
+ nDraw |= SCRBAR_DRAW_BTN2;
+ if ( aOldPage1Rect != maPage1Rect )
+ nDraw |= SCRBAR_DRAW_PAGE1;
+ if ( aOldPage2Rect != maPage2Rect )
+ nDraw |= SCRBAR_DRAW_PAGE2;
+ if ( aOldThumbRect != maThumbRect )
+ {
+ if ( !ImplUpdateThumbRect( aOldThumbRect ) )
+ nDraw |= SCRBAR_DRAW_THUMB;
+ }
+ ImplDraw( nDraw );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplCalcThumbPos( long nPixPos )
+{
+ // Position berechnen
+ long nCalcThumbPos;
+ nCalcThumbPos = ImplMulDiv( nPixPos, mnMaxRange-mnVisibleSize-mnMinRange,
+ mnThumbPixRange-mnThumbPixSize );
+ nCalcThumbPos += mnMinRange;
+ return nCalcThumbPos;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplCalcThumbPosPix( long nPos )
+{
+ long nCalcThumbPos;
+
+ // Position berechnen
+ nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-mnThumbPixSize,
+ mnMaxRange-mnVisibleSize-mnMinRange );
+
+ // Am Anfang und Ende des ScrollBars versuchen wir die Anzeige korrekt
+ // anzuzeigen
+ if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
+ nCalcThumbPos = 1;
+ if ( nCalcThumbPos &&
+ ((nCalcThumbPos+mnThumbPixSize) >= mnThumbPixRange) &&
+ (mnThumbPos < (mnMaxRange-mnVisibleSize)) )
+ nCalcThumbPos--;
+
+ return nCalcThumbPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplCalc( BOOL bUpdate )
+{
+ if ( mbCalcSize )
+ {
+ Size aSize = GetOutputSizePixel();
+ Size aBtnSize;
+
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( aSize.Height()*2 > aSize.Width()-SCRBAR_MIN_THUMB )
+ {
+ mnThumbPixRange = 0;
+ maBtn1Rect.Bottom() = aSize.Height()-1;
+ maBtn1Rect.Right() = aSize.Width()/2;
+ maBtn2Rect.Bottom() = maBtn1Rect.Bottom();
+ maBtn2Rect.Left() = maBtn1Rect.Right()+1;
+ maBtn2Rect.Right() = aSize.Width()-1;
+ }
+ else
+ {
+ mnThumbPixRange = aSize.Width()-(aSize.Height()*2);
+ aBtnSize = Size( aSize.Height(), aSize.Height() );
+ maBtn2Rect.Left() = aSize.Width()-aSize.Height();
+ maBtn1Rect.SetSize( aBtnSize );
+ maBtn2Rect.SetSize( aBtnSize );
+ maPage1Rect.Left() = maBtn1Rect.Right()+1;
+ maPage1Rect.Bottom() = maBtn1Rect.Bottom();
+ maPage2Rect.Bottom() = maBtn1Rect.Bottom();
+ maThumbRect.Bottom() = maBtn1Rect.Bottom();
+ }
+ }
+ else
+ {
+ if ( aSize.Width()*2 > aSize.Height()-SCRBAR_MIN_THUMB )
+ {
+ mnThumbPixRange = 0;
+ maBtn1Rect.Right() = aSize.Width()-1;
+ maBtn1Rect.Bottom() = aSize.Height()/2;
+ maBtn2Rect.Right() = maBtn1Rect.Right();
+ maBtn2Rect.Top() = maBtn1Rect.Bottom()+1;
+ maBtn2Rect.Bottom() = aSize.Height()-1;
+ }
+ else
+ {
+ mnThumbPixRange = aSize.Height()-(aSize.Width()*2);
+ aBtnSize = Size( aSize.Width(), aSize.Width() );
+ maBtn2Rect.Top() = aSize.Height()-aSize.Width();
+ maBtn1Rect.SetSize( aBtnSize );
+ maBtn2Rect.SetSize( aBtnSize );
+ maPage1Rect.Top() = maBtn1Rect.Bottom()+1;
+ maPage1Rect.Right() = maBtn1Rect.Right();
+ maPage2Rect.Right() = maBtn1Rect.Right();
+ maThumbRect.Right() = maBtn1Rect.Right();
+ }
+ }
+
+ if ( !mnThumbPixRange )
+ {
+ maPage1Rect.SetEmpty();
+ maPage2Rect.SetEmpty();
+ maThumbRect.SetEmpty();
+ }
+
+ mbCalcSize = FALSE;
+ }
+
+ if ( mnThumbPixRange )
+ {
+ // Werte berechnen
+ if ( (mnVisibleSize >= (mnMaxRange-mnMinRange)) ||
+ ((mnMaxRange-mnMinRange) <= 0) )
+ {
+ mnThumbPos = mnMinRange;
+ mnThumbPixPos = 0;
+ mnThumbPixSize = mnThumbPixRange;
+ }
+ else
+ {
+ if ( mnVisibleSize )
+ mnThumbPixSize = ImplMulDiv( mnThumbPixRange, mnVisibleSize, mnMaxRange-mnMinRange );
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ mnThumbPixSize = maThumbRect.GetHeight();
+ else
+ mnThumbPixSize = maThumbRect.GetWidth();
+ }
+ if ( mnThumbPixSize < SCRBAR_MIN_THUMB )
+ mnThumbPixSize = SCRBAR_MIN_THUMB;
+ if ( mnThumbPixSize > mnThumbPixRange )
+ mnThumbPixSize = mnThumbPixRange;
+ mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
+ }
+ }
+
+ // Wenn neu ausgegeben werden soll und wir schon ueber eine
+ // Aktion einen Paint-Event ausgeloest bekommen haben, dann
+ // geben wir nicht direkt aus, sondern invalidieren nur alles
+ if ( bUpdate && HasPaintEvent() )
+ {
+ Invalidate();
+ bUpdate = FALSE;
+ }
+ ImplUpdateRects( bUpdate );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplDraw( USHORT nDrawFlags )
+{
+ DecorationView aDecoView( this );
+ Rectangle aTempRect;
+ USHORT nStyle;
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SymbolType eSymbolType;
+ BOOL bEnabled = IsEnabled();
+
+ // Evt. noch offene Berechnungen nachholen
+ if ( mbCalcSize )
+ ImplCalc( FALSE );
+
+ if ( nDrawFlags & SCRBAR_DRAW_BTN1 )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mnStateFlags & SCRBAR_STATE_BTN1_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maBtn1Rect, nStyle );
+ ImplCalcSymbolRect( aTempRect );
+ nStyle = 0;
+ if ( (mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) || !bEnabled )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_ARROW_LEFT;
+ else
+ eSymbolType = SYMBOL_ARROW_UP;
+ }
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_SPIN_LEFT;
+ else
+ eSymbolType = SYMBOL_SPIN_UP;
+ }
+ aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
+ }
+
+ if ( nDrawFlags & SCRBAR_DRAW_BTN2 )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mnStateFlags & SCRBAR_STATE_BTN2_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maBtn2Rect, nStyle );
+ ImplCalcSymbolRect( aTempRect );
+ nStyle = 0;
+ if ( (mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) || !bEnabled )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_SCROLLARROW )
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_ARROW_RIGHT;
+ else
+ eSymbolType = SYMBOL_ARROW_DOWN;
+ }
+ else
+ {
+ if ( GetStyle() & WB_HORZ )
+ eSymbolType = SYMBOL_SPIN_RIGHT;
+ else
+ eSymbolType = SYMBOL_SPIN_DOWN;
+ }
+ aDecoView.DrawSymbol( aTempRect, eSymbolType, rStyleSettings.GetButtonTextColor(), nStyle );
+ }
+
+ SetLineColor();
+
+ if ( nDrawFlags & SCRBAR_DRAW_THUMB )
+ {
+ if ( !maThumbRect.IsEmpty() )
+ {
+ if ( bEnabled )
+ {
+ nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mnStateFlags & SCRBAR_STATE_THUMB_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aTempRect = aDecoView.DrawButton( maThumbRect, nStyle );
+ // Im OS2-Look geben wir auch ein Muster auf dem Thumb aus
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_OS2STYLE )
+ {
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( aTempRect.GetWidth() > 6 )
+ {
+ long nX = aTempRect.Center().X();
+ nX -= 6;
+ if ( nX < aTempRect.Left() )
+ nX = aTempRect.Left();
+ for ( int i = 0; i < 6; i++ )
+ {
+ if ( nX > aTempRect.Right()-1 )
+ break;
+
+ SetLineColor( rStyleSettings.GetButtonTextColor() );
+ DrawLine( Point( nX, aTempRect.Top()+1 ),
+ Point( nX, aTempRect.Bottom()-1 ) );
+ nX++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( nX, aTempRect.Top()+1 ),
+ Point( nX, aTempRect.Bottom()-1 ) );
+ nX++;
+ }
+ }
+ }
+ else
+ {
+ if ( aTempRect.GetHeight() > 6 )
+ {
+ long nY = aTempRect.Center().Y();
+ nY -= 6;
+ if ( nY < aTempRect.Top() )
+ nY = aTempRect.Top();
+ for ( int i = 0; i < 6; i++ )
+ {
+ if ( nY > aTempRect.Bottom()-1 )
+ break;
+
+ SetLineColor( rStyleSettings.GetButtonTextColor() );
+ DrawLine( Point( aTempRect.Left()+1, nY ),
+ Point( aTempRect.Right()-1, nY ) );
+ nY++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( aTempRect.Left()+1, nY ),
+ Point( aTempRect.Right()-1, nY ) );
+ nY++;
+ }
+ }
+ }
+ SetLineColor();
+ }
+ }
+ else
+ {
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( maThumbRect );
+ }
+ }
+ }
+
+ if ( nDrawFlags & SCRBAR_DRAW_PAGE1 )
+ {
+ if ( mnStateFlags & SCRBAR_STATE_PAGE1_DOWN )
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( maPage1Rect );
+ }
+ if ( nDrawFlags & SCRBAR_DRAW_PAGE2 )
+ {
+ if ( mnStateFlags & SCRBAR_STATE_PAGE2_DOWN )
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( maPage2Rect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplScroll( long nNewPos, BOOL bCallEndScroll )
+{
+ long nOldPos = mnThumbPos;
+ SetThumbPos( nNewPos );
+ long nDelta = mnThumbPos-nOldPos;
+ if ( nDelta )
+ {
+ mnDelta = nDelta;
+ Scroll();
+ if ( bCallEndScroll )
+ EndScroll();
+ mnDelta = 0;
+ }
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::ImplDoAction( BOOL bCallEndScroll )
+{
+ long nDelta = 0;
+
+ switch ( meScrollType )
+ {
+ case SCROLL_LINEUP:
+ nDelta = ImplScroll( mnThumbPos-mnLineSize, bCallEndScroll );
+ break;
+
+ case SCROLL_LINEDOWN:
+ nDelta = ImplScroll( mnThumbPos+mnLineSize, bCallEndScroll );
+ break;
+
+ case SCROLL_PAGEUP:
+ nDelta = ImplScroll( mnThumbPos-mnPageSize, bCallEndScroll );
+ break;
+
+ case SCROLL_PAGEDOWN:
+ nDelta = ImplScroll( mnThumbPos+mnPageSize, bCallEndScroll );
+ break;
+ }
+
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::ImplDoMouseAction( const Point& rMousePos, BOOL bCallAction )
+{
+ USHORT nOldStateFlags = mnStateFlags;
+ BOOL bAction = FALSE;
+
+ switch ( meScrollType )
+ {
+ case SCROLL_LINEUP:
+ if ( maBtn1Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_BTN1_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_BTN1_DOWN;
+ break;
+
+ case SCROLL_LINEDOWN:
+ if ( maBtn2Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_BTN2_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_BTN2_DOWN;
+ break;
+
+ case SCROLL_PAGEUP:
+ if ( maPage1Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_PAGE1_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_PAGE1_DOWN;
+ break;
+
+ case SCROLL_PAGEDOWN:
+ if ( maPage2Rect.IsInside( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SCRBAR_STATE_PAGE2_DOWN;
+ }
+ else
+ mnStateFlags &= ~SCRBAR_STATE_PAGE2_DOWN;
+ break;
+ }
+
+ if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw );
+ if ( bAction )
+ ImplDoAction( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ScrollBar, ImplTimerHdl, Timer*, pTimer )
+{
+ pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
+ DoScroll( meDDScrollType );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ const Point& rMousePos = rMEvt.GetPosPixel();
+ USHORT nTrackFlags = 0;
+
+ if ( maBtn1Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_LINEUP;
+ mnDragDraw = SCRBAR_DRAW_BTN1;
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else if ( maBtn2Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_LINEDOWN;
+ mnDragDraw = SCRBAR_DRAW_BTN2;
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else if ( maThumbRect.IsInside( rMousePos ) )
+ {
+ if ( mnVisibleSize < mnMaxRange-mnMinRange )
+ {
+ nTrackFlags = 0;
+ meScrollType = SCROLL_DRAG;
+ mnDragDraw = SCRBAR_DRAW_THUMB;
+
+ // Zusaetzliche Daten berechnen
+ if ( GetStyle() & WB_HORZ )
+ mnMouseOff = rMousePos.X()-maThumbRect.Left();
+ else
+ mnMouseOff = rMousePos.Y()-maThumbRect.Top();
+
+ // Im OS2-Look geben wir den Thumb gedrueck aus
+ if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_OS2STYLE )
+ {
+ mnStateFlags |= SCRBAR_STATE_THUMB_DOWN;
+ ImplDraw( mnDragDraw );
+ }
+ }
+ else
+ Sound::Beep( SOUND_DISABLE, this );
+ }
+ else
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+
+ if ( maPage1Rect.IsInside( rMousePos ) )
+ {
+ meScrollType = SCROLL_PAGEUP;
+ mnDragDraw = SCRBAR_DRAW_PAGE1;
+ }
+ else
+ {
+ meScrollType = SCROLL_PAGEDOWN;
+ mnDragDraw = SCRBAR_DRAW_PAGE2;
+ }
+ }
+
+ // Soll Tracking gestartet werden
+ if ( meScrollType != SCROLL_DONTKNOW )
+ {
+ // Startposition merken fuer Abbruch und EndScroll-Delta
+ mnStartPos = mnThumbPos;
+ ImplDoMouseAction( rMousePos );
+ StartTracking( nTrackFlags );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // Button und PageRect-Status wieder herstellen
+ USHORT nOldStateFlags = mnStateFlags;
+ mnStateFlags &= ~(SCRBAR_STATE_BTN1_DOWN | SCRBAR_STATE_BTN2_DOWN |
+ SCRBAR_STATE_PAGE1_DOWN | SCRBAR_STATE_PAGE2_DOWN |
+ SCRBAR_STATE_THUMB_DOWN);
+ if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw );
+ mnDragDraw = 0;
+
+ // Bei Abbruch, die alte ThumbPosition wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ long nOldPos = mnThumbPos;
+ SetThumbPos( mnStartPos );
+ mnDelta = mnThumbPos-nOldPos;
+ Scroll();
+ }
+
+ if ( meScrollType == SCROLL_DRAG )
+ {
+ // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
+ // er wieder auf einer gerundeten ThumbPosition steht
+ ImplCalc();
+
+ if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-mnStartPos;
+ Scroll();
+ mnDelta = 0;
+ }
+ }
+
+ mnDelta = mnThumbPos-mnStartPos;
+ EndScroll();
+ mnDelta = 0;
+ meScrollType = SCROLL_DONTKNOW;
+ }
+ else
+ {
+ const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ // Dragging wird speziell behandelt
+ if ( meScrollType == SCROLL_DRAG )
+ {
+ long nMovePix;
+ if ( GetStyle() & WB_HORZ )
+ nMovePix = rMousePos.X()-(maThumbRect.Left()+mnMouseOff);
+ else
+ nMovePix = rMousePos.Y()-(maThumbRect.Top()+mnMouseOff);
+ // Nur wenn sich Maus in die Scrollrichtung bewegt, muessen
+ // wir etwas tun
+ if ( nMovePix )
+ {
+ mnThumbPixPos += nMovePix;
+ if ( mnThumbPixPos < 0 )
+ mnThumbPixPos = 0;
+ if ( mnThumbPixPos > (mnThumbPixRange-mnThumbPixSize) )
+ mnThumbPixPos = mnThumbPixRange-mnThumbPixSize;
+ long nOldPos = mnThumbPos;
+ mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
+ ImplUpdateRects();
+ if ( mbFullDrag && (nOldPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-nOldPos;
+ Scroll();
+ mnDelta = 0;
+ }
+ }
+ }
+ else
+ ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
+
+ // Wenn ScrollBar-Werte so umgesetzt wurden, das es nichts
+ // mehr zum Tracking gibt, dann berechen wir hier ab
+ if ( !IsVisible() || (mnVisibleSize >= (mnMaxRange-mnMinRange)) )
+ EndTracking();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( !rKEvt.GetKeyCode().GetModifier() )
+ {
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_HOME:
+ DoScroll( 0 );
+ break;
+
+ case KEY_END:
+ DoScroll( GetRangeMax() );
+ break;
+
+ case KEY_LEFT:
+ case KEY_UP:
+ DoScrollAction( SCROLL_LINEUP );
+ break;
+
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ DoScrollAction( SCROLL_LINEDOWN );
+ break;
+
+ case KEY_PAGEUP:
+ DoScrollAction( SCROLL_PAGEUP );
+ break;
+
+ case KEY_PAGEDOWN:
+ DoScrollAction( SCROLL_PAGEDOWN );
+ break;
+
+ default:
+ Control::KeyInput( rKEvt );
+ break;
+ }
+ }
+ else
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Paint( const Rectangle& rRect )
+{
+ ImplDraw( SCRBAR_DRAW_ALL );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Resize()
+{
+ mbCalcSize = TRUE;
+ if ( IsReallyVisible() )
+ ImplCalc( FALSE );
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ScrollBar::QueryDrop( DropEvent& rDEvt )
+{
+ if ( mbDDScroll )
+ DDScroll( rDEvt );
+ return Control::QueryDrop( rDEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplCalc( FALSE );
+ else if ( nType == STATE_CHANGE_DATA )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplCalc( TRUE );
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_ENABLE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ ImplInitStyle( GetStyle() );
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( (GetPrevStyle() & SCRBAR_VIEW_STYLE) !=
+ (GetStyle() & SCRBAR_VIEW_STYLE) )
+ {
+ mbCalcSize = TRUE;
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::Scroll()
+{
+ maScrollHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::EndScroll()
+{
+ maEndScrollHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::DoScroll( long nNewPos )
+{
+ if ( meScrollType != SCROLL_DONTKNOW )
+ return 0;
+
+ meScrollType = SCROLL_DRAG;
+ long nDelta = ImplScroll( nNewPos, TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long ScrollBar::DoScrollAction( ScrollType eScrollType )
+{
+ if ( (meScrollType != SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DRAG) )
+ return 0;
+
+ meScrollType = eScrollType;
+ long nDelta = ImplDoAction( TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::DDScroll( const DropEvent& rDEvt )
+{
+ if ( rDEvt.IsLeaveWindow() )
+ meDDScrollType = SCROLL_DONTKNOW;
+ else
+ {
+ const Point& rMousePos = rDEvt.GetPosPixel();
+ if ( maBtn1Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN1_DISABLE) )
+ meDDScrollType = SCROLL_LINEUP;
+ }
+ else if ( maBtn2Rect.IsInside( rMousePos ) )
+ {
+ if ( !(mnStateFlags & SCRBAR_STATE_BTN2_DISABLE) )
+ meDDScrollType = SCROLL_LINEDOWN;
+ }
+ else if ( maThumbRect.IsInside( rMousePos ) )
+ meDDScrollType = SCROLL_DONTKNOW;
+ else
+ {
+ if ( maPage1Rect.IsInside( rMousePos ) )
+ meDDScrollType = SCROLL_PAGEUP;
+ else
+ meDDScrollType = SCROLL_PAGEDOWN;
+ }
+ }
+
+ if ( meDDScrollType == SCROLL_DONTKNOW )
+ {
+ if ( mpDDScrollTimer )
+ {
+ delete mpDDScrollTimer;
+ mpDDScrollTimer = NULL;
+ meDDScrollType = SCROLL_DONTKNOW;
+ }
+ }
+ else
+ {
+ if ( !mpDDScrollTimer )
+ {
+ mpDDScrollTimer = new Timer;
+ mpDDScrollTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
+ mpDDScrollTimer->SetTimeoutHdl( LINK( this, ScrollBar, ImplTimerHdl ) );
+ mpDDScrollTimer->Start();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRangeMin( long nNewRange )
+{
+ SetRange( Range( nNewRange, GetRangeMax() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRangeMax( long nNewRange )
+{
+ SetRange( Range( GetRangeMin(), nNewRange ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetRange( const Range& rRange )
+{
+ // Range einpassen
+ Range aRange = rRange;
+ aRange.Justify();
+ long nNewMinRange = aRange.Min();
+ long nNewMaxRange = aRange.Max();
+
+ // Wenn Range sich unterscheidet, dann neuen setzen
+ if ( (mnMinRange != nNewMinRange) ||
+ (mnMaxRange != nNewMaxRange) )
+ {
+ mnMinRange = nNewMinRange;
+ mnMaxRange = nNewMaxRange;
+
+ // Thumb einpassen
+ if ( mnThumbPos > mnMaxRange-mnVisibleSize )
+ mnThumbPos = mnMaxRange-mnVisibleSize;
+ if ( mnThumbPos < mnMinRange )
+ mnThumbPos = mnMinRange;
+
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetThumbPos( long nNewThumbPos )
+{
+ if ( nNewThumbPos > mnMaxRange-mnVisibleSize )
+ nNewThumbPos = mnMaxRange-mnVisibleSize;
+ if ( nNewThumbPos < mnMinRange )
+ nNewThumbPos = mnMinRange;
+
+ if ( mnThumbPos != nNewThumbPos )
+ {
+ mnThumbPos = nNewThumbPos;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBar::SetVisibleSize( long nNewSize )
+{
+ if ( mnVisibleSize != nNewSize )
+ {
+ mnVisibleSize = nNewSize;
+
+ // Thumb einpassen
+ if ( mnThumbPos > mnMaxRange-mnVisibleSize )
+ mnThumbPos = mnMaxRange-mnVisibleSize;
+ if ( mnThumbPos < mnMinRange )
+ mnThumbPos = mnMinRange;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// =======================================================================
+
+void ScrollBarBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ long nScrollSize = rStyleSettings.GetScrollBarSize();
+ SetSizePixel( Size( nScrollSize, nScrollSize ) );
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBarBox::ScrollBarBox( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SCROLLBARBOX )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ScrollBarBox::ScrollBarBox( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SCROLLBARBOX )
+{
+ rResId.SetRT( RSC_SCROLLBAR );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::ImplInitSettings()
+{
+ // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
+ // und noch nicht alles umgestellt ist
+ if ( IsBackground() )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = GetSettings().GetStyleSettings().GetFaceColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollBarBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
diff --git a/vcl/source/control/slider.cxx b/vcl/source/control/slider.cxx
new file mode 100644
index 000000000000..3d8fca3c2501
--- /dev/null
+++ b/vcl/source/control/slider.cxx
@@ -0,0 +1,1024 @@
+/*************************************************************************
+ *
+ * $RCSfile: slider.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SLIDER_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SLIDER_HXX
+#include <slider.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+static long ImplMulDiv( long nNumber, long nNumerator, long nDenominator )
+{
+ double n = ((double)nNumber * (double)nNumerator) / (double)nDenominator;
+ return (long)n;
+}
+
+// =======================================================================
+
+#define SLIDER_DRAW_THUMB ((USHORT)0x0001)
+#define SLIDER_DRAW_CHANNEL1 ((USHORT)0x0002)
+#define SLIDER_DRAW_CHANNEL2 ((USHORT)0x0004)
+#define SLIDER_DRAW_CHANNEL (SLIDER_DRAW_CHANNEL1 | SLIDER_DRAW_CHANNEL2)
+#define SLIDER_DRAW_ALL (SLIDER_DRAW_THUMB | SLIDER_DRAW_CHANNEL)
+
+#define SLIDER_STATE_CHANNEL1_DOWN ((USHORT)0x0001)
+#define SLIDER_STATE_CHANNEL2_DOWN ((USHORT)0x0002)
+#define SLIDER_STATE_THUMB_DOWN ((USHORT)0x0004)
+
+#define SLIDER_THUMB_SIZE 9
+#define SLIDER_THUMB_HALFSIZE 4
+#define SLIDER_CHANNEL_OFFSET 0
+#define SLIDER_CHANNEL_SIZE 4
+#define SLIDER_CHANNEL_HALFSIZE 2
+
+#define SLIDER_HEIGHT 16
+
+#define SLIDER_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
+
+// =======================================================================
+
+void Slider::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mnThumbPixOffset = 0;
+ mnThumbPixRange = 0;
+ mnThumbPixPos = 0; // between mnThumbPixOffset and mnThumbPixOffset+mnThumbPixRange
+ mnChannelPixOffset = 0;
+ mnChannelPixRange = 0;
+ mnChannelPixTop = 0;
+ mnChannelPixBottom = 0;
+
+ mnMinRange = 0;
+ mnMaxRange = 100;
+ mnThumbPos = 0;
+ mnLineSize = 1;
+ mnPageSize = 1;
+ mnDelta = 0;
+ mnDragDraw = 0;
+ mnStateFlags = 0;
+ meScrollType = SCROLL_DONTKNOW;
+ mbCalcSize = TRUE;
+ mbFullDrag = TRUE;
+
+ ImplInitStyle( nStyle );
+ Control::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings();
+ SetSizePixel( CalcWindowSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplInitStyle( WinBits nStyle )
+{
+}
+
+// -----------------------------------------------------------------------
+
+Slider::Slider( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_SLIDER )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Slider::Slider( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_SLIDER )
+{
+ rResId.SetRT( RSC_SCROLLBAR );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ INT16 nMin = ReadShortRes();
+ INT16 nMax = ReadShortRes();
+ INT16 nThumbPos = ReadShortRes();
+ INT16 nPage = ReadShortRes();
+ INT16 nStep = ReadShortRes();
+ INT16 nVisibleSize = ReadShortRes();
+
+ SetRange( Range( nMin, nMax ) );
+ SetLineSize( nStep );
+ SetPageSize( nPage );
+ SetThumbPos( nThumbPos );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplInitSettings()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplUpdateRects( BOOL bUpdate )
+{
+ Rectangle aOldThumbRect = maThumbRect;
+
+ if ( mnThumbPixRange )
+ {
+ if ( GetStyle() & WB_HORZ )
+ {
+ maThumbRect.Left() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
+ maThumbRect.Right() = maThumbRect.Left()+SLIDER_THUMB_SIZE-1;
+ if ( mnChannelPixOffset < maThumbRect.Left() )
+ {
+ maChannel1Rect.Left() = mnChannelPixOffset;
+ maChannel1Rect.Right() = maThumbRect.Left()-1;
+ maChannel1Rect.Top() = mnChannelPixTop;
+ maChannel1Rect.Bottom() = mnChannelPixBottom;
+ }
+ else
+ maChannel1Rect.SetEmpty();
+ if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Right() )
+ {
+ maChannel2Rect.Left() = maThumbRect.Right()+1;
+ maChannel2Rect.Right() = mnChannelPixOffset+mnChannelPixRange-1;
+ maChannel2Rect.Top() = mnChannelPixTop;
+ maChannel2Rect.Bottom() = mnChannelPixBottom;
+ }
+ else
+ maChannel2Rect.SetEmpty();
+ }
+ else
+ {
+ maThumbRect.Top() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
+ maThumbRect.Bottom() = maThumbRect.Top()+SLIDER_THUMB_SIZE-1;
+ if ( mnChannelPixOffset < maThumbRect.Top() )
+ {
+ maChannel1Rect.Top() = mnChannelPixOffset;
+ maChannel1Rect.Bottom() = maThumbRect.Top()-1;
+ maChannel1Rect.Left() = mnChannelPixTop;
+ maChannel1Rect.Right() = mnChannelPixBottom;
+ }
+ else
+ maChannel1Rect.SetEmpty();
+ if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Bottom() )
+ {
+ maChannel2Rect.Top() = maThumbRect.Bottom()+1;
+ maChannel2Rect.Bottom() = mnChannelPixOffset+mnChannelPixRange-1;
+ maChannel2Rect.Left() = mnChannelPixTop;
+ maChannel2Rect.Right() = mnChannelPixBottom;
+ }
+ else
+ maChannel2Rect.SetEmpty();
+ }
+ }
+ else
+ {
+ maChannel1Rect.SetEmpty();
+ maChannel2Rect.SetEmpty();
+ maThumbRect.SetEmpty();
+ }
+
+ if ( bUpdate )
+ {
+ if ( aOldThumbRect != maThumbRect )
+ {
+ Region aInvalidRegion( aOldThumbRect );
+ aInvalidRegion.Union( maThumbRect );
+ Invalidate( aInvalidRegion );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplCalcThumbPos( long nPixPos )
+{
+ // Position berechnen
+ long nCalcThumbPos;
+ nCalcThumbPos = ImplMulDiv( nPixPos-mnThumbPixOffset, mnMaxRange-mnMinRange, mnThumbPixRange-1 );
+ nCalcThumbPos += mnMinRange;
+ return nCalcThumbPos;
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplCalcThumbPosPix( long nPos )
+{
+ // Position berechnen
+ long nCalcThumbPos;
+ nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-1, mnMaxRange-mnMinRange );
+ // Am Anfang und Ende des Sliders versuchen wir die Anzeige korrekt
+ // anzuzeigen
+ if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
+ nCalcThumbPos = 1;
+ if ( nCalcThumbPos &&
+ (nCalcThumbPos == mnThumbPixRange-1) &&
+ (mnThumbPos < mnMaxRange) )
+ nCalcThumbPos--;
+ return nCalcThumbPos+mnThumbPixOffset;
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplCalc( BOOL bUpdate )
+{
+ BOOL bInvalidateAll = FALSE;
+
+ if ( mbCalcSize )
+ {
+ long nOldChannelPixOffset = mnChannelPixOffset;
+ long nOldChannelPixRange = mnChannelPixRange;
+ long nOldChannelPixTop = mnChannelPixTop;
+ long nOldChannelPixBottom = mnChannelPixBottom;
+ long nCalcWidth;
+ long nCalcHeight;
+
+ maChannel1Rect.SetEmpty();
+ maChannel2Rect.SetEmpty();
+ maThumbRect.SetEmpty();
+
+ Size aSize = GetOutputSizePixel();
+ if ( GetStyle() & WB_HORZ )
+ {
+ nCalcWidth = aSize.Width();
+ nCalcHeight = aSize.Height();
+ maThumbRect.Top() = 0;
+ maThumbRect.Bottom()= aSize.Height()-1;
+ }
+ else
+ {
+ nCalcWidth = aSize.Height();
+ nCalcHeight = aSize.Width();
+ maThumbRect.Left() = 0;
+ maThumbRect.Right() = aSize.Width()-1;
+ }
+
+ if ( nCalcWidth >= SLIDER_THUMB_SIZE )
+ {
+ mnThumbPixOffset = SLIDER_THUMB_HALFSIZE;
+ mnThumbPixRange = nCalcWidth-(SLIDER_THUMB_HALFSIZE*2);
+ mnThumbPixPos = 0;
+ mnChannelPixOffset = SLIDER_CHANNEL_OFFSET;
+ mnChannelPixRange = nCalcWidth-(SLIDER_CHANNEL_OFFSET*2);
+ mnChannelPixTop = (nCalcHeight/2)-SLIDER_CHANNEL_HALFSIZE;
+ mnChannelPixBottom = mnChannelPixTop+SLIDER_CHANNEL_SIZE-1;
+ }
+ else
+ {
+ mnThumbPixRange = 0;
+ mnChannelPixRange = 0;
+ }
+
+ if ( (nOldChannelPixOffset != mnChannelPixOffset) ||
+ (nOldChannelPixRange != mnChannelPixRange) ||
+ (nOldChannelPixTop != mnChannelPixTop) ||
+ (nOldChannelPixBottom != mnChannelPixBottom) )
+ bInvalidateAll = TRUE;
+
+ mbCalcSize = FALSE;
+ }
+
+ if ( mnThumbPixRange )
+ mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
+
+ if ( bUpdate && bInvalidateAll )
+ {
+ Invalidate();
+ bUpdate = FALSE;
+ }
+ ImplUpdateRects( bUpdate );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplDraw( USHORT nDrawFlags )
+{
+ DecorationView aDecoView( this );
+ USHORT nStyle;
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ BOOL bEnabled = IsEnabled();
+
+ // Evt. noch offene Berechnungen nachholen
+ if ( mbCalcSize )
+ ImplCalc( FALSE );
+
+ if ( (nDrawFlags & SLIDER_DRAW_CHANNEL1) && !maChannel1Rect.IsEmpty() )
+ {
+ long nRectSize;
+ Rectangle aRect = maChannel1Rect;
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( GetStyle() & WB_HORZ )
+ {
+ DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-1 ) );
+ DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ }
+ else
+ {
+ DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
+ DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
+ }
+ SetLineColor( rStyleSettings.GetLightColor() );
+ if ( GetStyle() & WB_HORZ )
+ {
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ nRectSize = aRect.GetWidth();
+ }
+ else
+ {
+ DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ nRectSize = aRect.GetHeight();
+ }
+
+ if ( nRectSize > 1 )
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ if ( GetStyle() & WB_HORZ )
+ aRect.Bottom()--;
+ else
+ aRect.Right()--;
+ SetLineColor();
+ if ( mnStateFlags & SLIDER_STATE_CHANNEL1_DOWN )
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( aRect );
+ }
+ }
+
+ if ( (nDrawFlags & SLIDER_DRAW_CHANNEL2) && !maChannel2Rect.IsEmpty() )
+ {
+ long nRectSize;
+ Rectangle aRect = maChannel2Rect;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ if ( GetStyle() & WB_HORZ )
+ {
+ DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ nRectSize = aRect.GetWidth();
+ }
+ else
+ {
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ nRectSize = aRect.GetHeight();
+ }
+
+ if ( nRectSize > 1 )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( GetStyle() & WB_HORZ )
+ DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
+ else
+ DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-1 ) );
+
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( GetStyle() & WB_HORZ )
+ aRect.Top()++;
+ else
+ aRect.Left()++;
+ SetLineColor();
+ if ( mnStateFlags & SLIDER_STATE_CHANNEL2_DOWN )
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( aRect );
+ }
+ }
+
+ if ( nDrawFlags & SLIDER_DRAW_THUMB )
+ {
+ if ( !maThumbRect.IsEmpty() )
+ {
+ if ( bEnabled )
+ {
+ nStyle = 0;
+ if ( mnStateFlags & SLIDER_STATE_THUMB_DOWN )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ aDecoView.DrawButton( maThumbRect, nStyle );
+ }
+ else
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( maThumbRect );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Slider::ImplIsPageUp( const Point& rPos )
+{
+ Size aSize = GetOutputSizePixel();
+ Rectangle aRect = maChannel1Rect;
+ if ( GetStyle() & WB_HORZ )
+ {
+ aRect.Top() = 0;
+ aRect.Bottom() = aSize.Height()-1;
+ }
+ else
+ {
+ aRect.Left() = 0;
+ aRect.Right() = aSize.Width()-1;
+ }
+ return aRect.IsInside( rPos );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Slider::ImplIsPageDown( const Point& rPos )
+{
+ Size aSize = GetOutputSizePixel();
+ Rectangle aRect = maChannel2Rect;
+ if ( GetStyle() & WB_HORZ )
+ {
+ aRect.Top() = 0;
+ aRect.Bottom() = aSize.Height()-1;
+ }
+ else
+ {
+ aRect.Left() = 0;
+ aRect.Right() = aSize.Width()-1;
+ }
+ return aRect.IsInside( rPos );
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplSlide( long nNewPos, BOOL bCallEndSlide )
+{
+ long nOldPos = mnThumbPos;
+ SetThumbPos( nNewPos );
+ long nDelta = mnThumbPos-nOldPos;
+ if ( nDelta )
+ {
+ mnDelta = nDelta;
+ Slide();
+ if ( bCallEndSlide )
+ EndSlide();
+ mnDelta = 0;
+ }
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplDoAction( BOOL bCallEndSlide )
+{
+ long nDelta = 0;
+
+ switch ( meScrollType )
+ {
+ case SCROLL_LINEUP:
+ nDelta = ImplSlide( mnThumbPos-mnLineSize, bCallEndSlide );
+ break;
+
+ case SCROLL_LINEDOWN:
+ nDelta = ImplSlide( mnThumbPos+mnLineSize, bCallEndSlide );
+ break;
+
+ case SCROLL_PAGEUP:
+ nDelta = ImplSlide( mnThumbPos-mnPageSize, bCallEndSlide );
+ break;
+
+ case SCROLL_PAGEDOWN:
+ nDelta = ImplSlide( mnThumbPos+mnPageSize, bCallEndSlide );
+ break;
+ }
+
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::ImplDoMouseAction( const Point& rMousePos, BOOL bCallAction )
+{
+ USHORT nOldStateFlags = mnStateFlags;
+ BOOL bAction = FALSE;
+
+ switch ( meScrollType )
+ {
+ case SCROLL_PAGEUP:
+ if ( ImplIsPageUp( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SLIDER_STATE_CHANNEL1_DOWN;
+ }
+ else
+ mnStateFlags &= ~SLIDER_STATE_CHANNEL1_DOWN;
+ break;
+
+ case SCROLL_PAGEDOWN:
+ if ( ImplIsPageDown( rMousePos ) )
+ {
+ bAction = bCallAction;
+ mnStateFlags |= SLIDER_STATE_CHANNEL2_DOWN;
+ }
+ else
+ mnStateFlags &= ~SLIDER_STATE_CHANNEL2_DOWN;
+ break;
+ }
+
+ if ( bAction )
+ {
+ if ( ImplDoAction( FALSE ) )
+ {
+ // Update the channel complete
+ if ( mnDragDraw & SLIDER_DRAW_CHANNEL )
+ {
+ Update();
+ ImplDraw( mnDragDraw );
+ }
+ }
+ }
+ else if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw );
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplDoSlide( long nNewPos )
+{
+ if ( meScrollType != SCROLL_DONTKNOW )
+ return 0;
+
+ meScrollType = SCROLL_DRAG;
+ long nDelta = ImplSlide( nNewPos, TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+long Slider::ImplDoSlideAction( ScrollType eScrollType )
+{
+ if ( (meScrollType != SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DONTKNOW) ||
+ (eScrollType == SCROLL_DRAG) )
+ return 0;
+
+ meScrollType = eScrollType;
+ long nDelta = ImplDoAction( TRUE );
+ meScrollType = SCROLL_DONTKNOW;
+ return nDelta;
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ const Point& rMousePos = rMEvt.GetPosPixel();
+ USHORT nTrackFlags = 0;
+
+ if ( maThumbRect.IsInside( rMousePos ) )
+ {
+ nTrackFlags = 0;
+ meScrollType = SCROLL_DRAG;
+ mnDragDraw = SLIDER_DRAW_THUMB;
+
+ // Zusaetzliche Daten berechnen
+ Point aCenterPos = maThumbRect.Center();
+ if ( GetStyle() & WB_HORZ )
+ mnMouseOff = rMousePos.X()-aCenterPos.X();
+ else
+ mnMouseOff = rMousePos.Y()-aCenterPos.Y();
+
+ // Im OS2-Look geben wir den Thumb gedrueckt aus
+ if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_OS2STYLE )
+ {
+ mnStateFlags |= SLIDER_STATE_THUMB_DOWN;
+ ImplDraw( SLIDER_DRAW_THUMB );
+ }
+ }
+ else if ( ImplIsPageUp( rMousePos ) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_PAGEUP;
+ mnDragDraw = SLIDER_DRAW_CHANNEL;
+ }
+ else if ( ImplIsPageDown( rMousePos ) )
+ {
+ nTrackFlags = STARTTRACK_BUTTONREPEAT;
+ meScrollType = SCROLL_PAGEDOWN;
+ mnDragDraw = SLIDER_DRAW_CHANNEL;
+ }
+
+ // Soll Tracking gestartet werden
+ if ( meScrollType != SCROLL_DONTKNOW )
+ {
+ // Startposition merken fuer Abbruch und EndScroll-Delta
+ mnStartPos = mnThumbPos;
+ ImplDoMouseAction( rMousePos );
+ Update();
+ StartTracking( nTrackFlags );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // Button und PageRect-Status wieder herstellen
+ USHORT nOldStateFlags = mnStateFlags;
+ mnStateFlags &= ~(SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN |
+ SLIDER_STATE_THUMB_DOWN);
+ if ( nOldStateFlags != mnStateFlags )
+ ImplDraw( mnDragDraw );
+ mnDragDraw = 0;
+
+ // Bei Abbruch, die alte ThumbPosition wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ long nOldPos = mnThumbPos;
+ SetThumbPos( mnStartPos );
+ mnDelta = mnThumbPos-nOldPos;
+ Slide();
+ }
+
+ if ( meScrollType == SCROLL_DRAG )
+ {
+ // Wenn gedragt wurde, berechnen wir den Thumb neu, damit
+ // er wieder auf einer gerundeten ThumbPosition steht
+ ImplCalc();
+ Update();
+
+ if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-mnStartPos;
+ Slide();
+ mnDelta = 0;
+ }
+ }
+
+ mnDelta = mnThumbPos-mnStartPos;
+ EndSlide();
+ mnDelta = 0;
+ meScrollType = SCROLL_DONTKNOW;
+ }
+ else
+ {
+ const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ // Dragging wird speziell behandelt
+ if ( meScrollType == SCROLL_DRAG )
+ {
+ long nMovePix;
+ Point aCenterPos = maThumbRect.Center();
+ if ( GetStyle() & WB_HORZ )
+ nMovePix = rMousePos.X()-(aCenterPos.X()+mnMouseOff);
+ else
+ nMovePix = rMousePos.Y()-(aCenterPos.Y()+mnMouseOff);
+ // Nur wenn sich Maus in die Scrollrichtung bewegt, muessen
+ // wir etwas tun
+ if ( nMovePix )
+ {
+ mnThumbPixPos += nMovePix;
+ if ( mnThumbPixPos < mnThumbPixOffset )
+ mnThumbPixPos = mnThumbPixOffset;
+ if ( mnThumbPixPos > (mnThumbPixOffset+mnThumbPixRange-1) )
+ mnThumbPixPos = mnThumbPixOffset+mnThumbPixRange-1;
+ long nOldPos = mnThumbPos;
+ mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
+ if ( nOldPos != mnThumbPos )
+ {
+ ImplUpdateRects();
+ Update();
+ if ( mbFullDrag && (nOldPos != mnThumbPos) )
+ {
+ mnDelta = mnThumbPos-nOldPos;
+ Slide();
+ mnDelta = 0;
+ }
+ }
+ }
+ }
+ else
+ ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
+
+ // Wenn Slider-Werte so umgesetzt wurden, das es nichts
+ // mehr zum Tracking gibt, dann berechen wir hier ab
+ if ( !IsVisible() )
+ EndTracking();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( !rKEvt.GetKeyCode().GetModifier() )
+ {
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_HOME:
+ ImplDoSlide( GetRangeMin() );
+ break;
+ case KEY_END:
+ ImplDoSlide( GetRangeMax() );
+ break;
+
+ case KEY_LEFT:
+ case KEY_UP:
+ ImplDoSlideAction( SCROLL_LINEUP );
+ break;
+
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ ImplDoSlideAction( SCROLL_LINEDOWN );
+ break;
+
+ case KEY_PAGEUP:
+ ImplDoSlideAction( SCROLL_PAGEUP );
+ break;
+
+ case KEY_PAGEDOWN:
+ ImplDoSlideAction( SCROLL_PAGEDOWN );
+ break;
+
+ default:
+ Control::KeyInput( rKEvt );
+ break;
+ }
+ }
+ else
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::Paint( const Rectangle& rRect )
+{
+ ImplDraw( SLIDER_DRAW_ALL );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::Resize()
+{
+ mbCalcSize = TRUE;
+ if ( IsReallyVisible() )
+ ImplCalc( FALSE );
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::RequestHelp( const HelpEvent& rHEvt )
+{
+ Control::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplCalc( FALSE );
+ else if ( nType == STATE_CHANGE_DATA )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplCalc( TRUE );
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ else if ( nType == STATE_CHANGE_ENABLE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ ImplInitStyle( GetStyle() );
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( (GetPrevStyle() & SLIDER_VIEW_STYLE) !=
+ (GetStyle() & SLIDER_VIEW_STYLE) )
+ {
+ mbCalcSize = TRUE;
+ ImplCalc( FALSE );
+ Invalidate();
+ }
+ }
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::Slide()
+{
+ maSlideHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::EndSlide()
+{
+ maEndSlideHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::SetRangeMin( long nNewRange )
+{
+ SetRange( Range( nNewRange, GetRangeMax() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::SetRangeMax( long nNewRange )
+{
+ SetRange( Range( GetRangeMin(), nNewRange ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::SetRange( const Range& rRange )
+{
+ // Range einpassen
+ Range aRange = rRange;
+ aRange.Justify();
+ long nNewMinRange = aRange.Min();
+ long nNewMaxRange = aRange.Max();
+
+ // Wenn Range sich unterscheidet, dann neuen setzen
+ if ( (mnMinRange != nNewMinRange) ||
+ (mnMaxRange != nNewMaxRange) )
+ {
+ mnMinRange = nNewMinRange;
+ mnMaxRange = nNewMaxRange;
+
+ // Thumb einpassen
+ if ( mnThumbPos > mnMaxRange )
+ mnThumbPos = mnMaxRange;
+ if ( mnThumbPos < mnMinRange )
+ mnThumbPos = mnMinRange;
+
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Slider::SetThumbPos( long nNewThumbPos )
+{
+ if ( nNewThumbPos < mnMinRange )
+ nNewThumbPos = mnMinRange;
+ if ( nNewThumbPos > mnMaxRange )
+ nNewThumbPos = mnMaxRange;
+
+ if ( mnThumbPos != nNewThumbPos )
+ {
+ mnThumbPos = nNewThumbPos;
+ StateChanged( STATE_CHANGE_DATA );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Slider::CalcWindowSizePixel()
+{
+ long nWidth = mnMaxRange-mnMinRange+(SLIDER_THUMB_HALFSIZE*2)+1;
+ long nHeight = SLIDER_HEIGHT;
+ Size aSize;
+ if ( GetStyle() & WB_HORZ )
+ {
+ aSize.Width() = nWidth;
+ aSize.Height() = nHeight;
+ }
+ else
+ {
+ aSize.Height() = nWidth;
+ aSize.Width() = nHeight;
+ }
+ return aSize;
+}
diff --git a/vcl/source/control/spinbtn.cxx b/vcl/source/control/spinbtn.cxx
new file mode 100644
index 000000000000..d2d91f1158c4
--- /dev/null
+++ b/vcl/source/control/spinbtn.cxx
@@ -0,0 +1,313 @@
+/*************************************************************************
+ *
+ * $RCSfile: spinbtn.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SPIN_CXX
+
+#ifndef _SV_RCID_H
+#include <rcid.h>
+#endif
+#ifndef _SV_SPIN_H
+#include <spin.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SPIN_HXX
+#include <spin.hxx>
+#endif
+
+// =======================================================================
+
+void SpinButton::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mbUpperIn = FALSE;
+ mbLowerIn = FALSE;
+ mbInitialUp = FALSE;
+ mbInitialDown = FALSE;
+
+ if ( nStyle & WB_REPEAT )
+ {
+ mbRepeat = TRUE;
+
+ maRepeatTimer.SetTimeout( SPIN_DELAY );
+ maRepeatTimer.SetTimeoutHdl( LINK( this, SpinButton, ImplTimeout ) );
+ }
+ else
+ mbRepeat = FALSE;
+
+ if ( nStyle & WB_HSCROLL )
+ mbHorz = TRUE;
+ else
+ mbHorz = FALSE;
+
+ Control::ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+SpinButton::SpinButton( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_SPINBUTTON )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+SpinButton::SpinButton( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_SPINBUTTON )
+{
+ rResId.SetRT( RSC_SPINBUTTON );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+SpinButton::~SpinButton()
+{
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( SpinButton, ImplTimeout, Timer*, pTimer )
+{
+ if ( pTimer->GetTimeout() == SPIN_DELAY )
+ {
+ pTimer->SetTimeout( SPIN_SPEED );
+ pTimer->Start();
+ }
+ else
+ {
+ if ( mbInitialUp )
+ Up();
+ else
+ Down();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::Up()
+{
+ maUpHdlLink.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::Down()
+{
+ maDownHdlLink.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::Resize()
+{
+ Size aSize( GetOutputSizePixel() );
+ Point aTmpPoint;
+ Rectangle aRect( aTmpPoint, aSize );
+ if ( mbHorz )
+ {
+ maUpperRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
+ maLowerRect = Rectangle( maUpperRect.TopRight(), aRect.BottomRight() );
+ }
+ else
+ {
+ maUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
+ maLowerRect = Rectangle( maUpperRect.BottomLeft(), aRect.BottomRight() );
+ }
+
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::Paint( const Rectangle& )
+{
+ BOOL bEnable = IsEnabled();
+ ImplDrawSpinButton( this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn,
+ bEnable, bEnable, mbHorz );
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mbUpperIn = TRUE;
+ mbInitialUp = TRUE;
+ Invalidate( maUpperRect );
+ }
+ else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mbLowerIn = TRUE;
+ mbInitialDown = TRUE;
+ Invalidate( maLowerRect );
+ }
+
+ if ( mbUpperIn || mbLowerIn )
+ {
+ Update();
+ CaptureMouse();
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::MouseButtonUp( const MouseEvent& )
+{
+ ReleaseMouse();
+
+ if ( mbUpperIn )
+ {
+ mbUpperIn = FALSE;
+ Invalidate( maUpperRect );
+ Update();
+ Up();
+ }
+ else if ( mbLowerIn )
+ {
+ mbLowerIn = FALSE;
+ Invalidate( maLowerRect );
+ Update();
+ Down();
+ }
+
+ mbInitialUp = mbInitialDown = FALSE;
+
+ if ( mbRepeat )
+ {
+ maRepeatTimer.Stop();
+ maRepeatTimer.SetTimeout( SPIN_DELAY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) )
+ return;
+
+ if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
+ mbUpperIn && mbInitialUp )
+ {
+ mbUpperIn = FALSE;
+ maRepeatTimer.Stop();
+ Invalidate( maUpperRect );
+ Update();
+ }
+ else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
+ mbLowerIn & mbInitialDown )
+ {
+ mbLowerIn = FALSE;
+ maRepeatTimer.Stop();
+ Invalidate( maLowerRect );
+ Update();
+ }
+ else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
+ !mbUpperIn && mbInitialUp )
+ {
+ mbUpperIn = TRUE;
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ Invalidate( maUpperRect );
+ Update();
+ }
+ else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
+ !mbLowerIn && mbInitialDown )
+ {
+ mbLowerIn = TRUE;
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ Invalidate( maLowerRect );
+ Update();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::KeyInput( const KeyEvent& rKEvt )
+{
+ KeyCode aCode = rKEvt.GetKeyCode();
+
+ if ( aCode.GetCode() == KEY_UP )
+ Up();
+ else if( aCode.GetCode() == KEY_DOWN )
+ Down();
+ else
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SpinButton::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_ENABLE )
+ Invalidate();
+ Control::StateChanged( nType );
+}
diff --git a/vcl/source/control/spinfld.cxx b/vcl/source/control/spinfld.cxx
new file mode 100644
index 000000000000..d87d20865726
--- /dev/null
+++ b/vcl/source/control/spinfld.cxx
@@ -0,0 +1,791 @@
+/*************************************************************************
+ *
+ * $RCSfile: spinfld.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SPINFLD_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SPIN_H
+#include <spin.h>
+#endif
+#ifndef _SV_SPINFLD_HXX
+#include <spinfld.hxx>
+#endif
+
+// =======================================================================
+
+void ImplDrawSpinButton( OutputDevice* pOutDev,
+ const Rectangle& rUpperRect,
+ const Rectangle& rLowerRect,
+ BOOL bUpperIn, BOOL bLowerIn,
+ BOOL bUpperEnabled, BOOL bLowerEnabled, BOOL bHorz )
+{
+ DecorationView aDecoView( pOutDev );
+
+ USHORT nStyle = BUTTON_DRAW_NOLEFTLIGHTBORDER;
+ USHORT nSymStyle = 0;
+
+ SymbolType eType1, eType2;
+
+ const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_SPINARROW )
+ {
+ if ( bHorz )
+ {
+ eType1 = SYMBOL_ARROW_LEFT;
+ eType2 = SYMBOL_ARROW_RIGHT;
+ }
+ else
+ {
+ eType1 = SYMBOL_ARROW_UP;
+ eType2 = SYMBOL_ARROW_DOWN;
+ }
+ }
+ else
+ {
+ if ( bHorz )
+ {
+ eType1 = SYMBOL_SPIN_LEFT;
+ eType2 = SYMBOL_SPIN_RIGHT;
+ }
+ else
+ {
+ eType1 = SYMBOL_SPIN_UP;
+ eType2 = SYMBOL_SPIN_DOWN;
+ }
+ }
+
+ // Oberen/linken Button malen
+ USHORT nTempStyle = nStyle;
+ if ( bUpperIn )
+ nTempStyle |= BUTTON_DRAW_PRESSED;
+ Rectangle aUpRect = aDecoView.DrawButton( rUpperRect, nTempStyle );
+
+ // Unteren/rechten Button malen
+ if ( bLowerIn )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ Rectangle aLowRect = aDecoView.DrawButton( rLowerRect, nStyle );
+
+ // Zusaetzliche Default-Kante wollen wir auch ausnutzen
+ aUpRect.Left()--;
+ aUpRect.Top()--;
+ aUpRect.Right()++;
+ aUpRect.Bottom()++;
+ aLowRect.Left()--;
+ aLowRect.Top()--;
+ aLowRect.Right()++;
+ aLowRect.Bottom()++;
+
+ // Wir malen auch in die Kante rein, damit man etwas erkennen kann,
+ // wenn das Rechteck zu klein ist
+ if ( aUpRect.GetHeight() < 4 )
+ {
+ aUpRect.Right()++;
+ aUpRect.Bottom()++;
+ aLowRect.Right()++;
+ aLowRect.Bottom()++;
+ }
+
+ // Symbolgroesse berechnen
+ long nTempSize1 = aUpRect.GetWidth();
+ long nTempSize2 = aLowRect.GetWidth();
+ if ( Abs( nTempSize1-nTempSize2 ) == 1 )
+ {
+ if ( nTempSize1 > nTempSize2 )
+ aUpRect.Left()++;
+ else
+ aLowRect.Left()++;
+ }
+ nTempSize1 = aUpRect.GetHeight();
+ nTempSize2 = aLowRect.GetHeight();
+ if ( Abs( nTempSize1-nTempSize2 ) == 1 )
+ {
+ if ( nTempSize1 > nTempSize2 )
+ aUpRect.Top()++;
+ else
+ aLowRect.Top()++;
+ }
+
+ nTempStyle = nSymStyle;
+ if ( !bUpperEnabled )
+ nTempStyle |= SYMBOL_DRAW_DISABLE;
+ aDecoView.DrawSymbol( aUpRect, eType1, rStyleSettings.GetButtonTextColor(), nTempStyle );
+
+ if ( !bLowerEnabled )
+ nSymStyle |= SYMBOL_DRAW_DISABLE;
+ aDecoView.DrawSymbol( aLowRect, eType2, rStyleSettings.GetButtonTextColor(), nSymStyle );
+}
+
+// =======================================================================
+
+void SpinField::ImplInitData()
+{
+ mpEdit = NULL;
+ mbSpin = FALSE;
+ mbRepeat = FALSE;
+ mbUpperIn = FALSE;
+ mbLowerIn = FALSE;
+ mbInitialUp = FALSE;
+ mbInitialDown = FALSE;
+ mbNoSelect = FALSE;
+ mbInDropDown = FALSE;
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::ImplInit( Window* pParent, WinBits nWinStyle )
+{
+ Edit::ImplInit( pParent, nWinStyle );
+
+ if ( nWinStyle & (WB_SPIN|WB_DROPDOWN) )
+ {
+ mbSpin = TRUE;
+ mpEdit = new Edit( this, WB_NOBORDER );
+ mpEdit->SetPosPixel( Point() );
+ mpEdit->Show();
+ SetSubEdit( mpEdit );
+
+ maRepeatTimer.SetTimeoutHdl( LINK( this, SpinField, ImplTimeout ) );
+ maRepeatTimer.SetTimeout( SPIN_DELAY );
+ if ( nWinStyle & WB_REPEAT )
+ mbRepeat = TRUE;
+
+ SetCompoundControl( TRUE );
+ }
+}
+
+// --------------------------------------------------------------------
+
+SpinField::SpinField( WindowType nTyp ) :
+ Edit( nTyp )
+{
+ ImplInitData();
+}
+
+// --------------------------------------------------------------------
+
+SpinField::SpinField( Window* pParent, WinBits nWinStyle ) :
+ Edit( WINDOW_SPINFIELD )
+{
+ ImplInitData();
+ ImplInit( pParent, nWinStyle );
+}
+
+// --------------------------------------------------------------------
+
+SpinField::SpinField( Window* pParent, const ResId& rResId ) :
+ Edit( WINDOW_SPINFIELD )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_SPINFIELD );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// --------------------------------------------------------------------
+
+SpinField::~SpinField()
+{
+ delete mpEdit;
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Up()
+{
+ maUpHdlLink.Call( this );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Down()
+{
+ maDownHdlLink.Call( this );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::First()
+{
+ maFirstHdlLink.Call( this );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Last()
+{
+ maLastHdlLink.Call( this );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !HasFocus() && ( !mpEdit || !mpEdit->HasFocus() ) )
+ {
+ mbNoSelect = TRUE;
+ GrabFocus();
+ }
+
+ if ( !IsReadOnly() )
+ {
+ if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mbUpperIn = TRUE;
+ mbInitialUp = TRUE;
+ Invalidate( maUpperRect );
+ }
+ else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mbLowerIn = TRUE;
+ mbInitialDown = TRUE;
+ Invalidate( maLowerRect );
+ }
+ else if ( maDropDownRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ // Rechts daneben liegt der DropDownButton:
+ mbInDropDown = ShowDropDown( mbInDropDown ? FALSE : TRUE );
+ Paint( Rectangle( Point(), GetOutputSizePixel() ) );
+ }
+
+ if ( mbUpperIn || mbLowerIn )
+ {
+ Update();
+ CaptureMouse();
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ return;
+ }
+ }
+
+ Edit::MouseButtonDown( rMEvt );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ ReleaseMouse();
+ mbInitialUp = mbInitialDown = FALSE;
+ maRepeatTimer.Stop();
+ maRepeatTimer.SetTimeout( SPIN_DELAY );
+
+ if ( mbUpperIn )
+ {
+ mbUpperIn = FALSE;
+ Invalidate( maUpperRect );
+ Update();
+ Up();
+ }
+ else if ( mbLowerIn )
+ {
+ mbLowerIn = FALSE;
+ Invalidate( maLowerRect );
+ Update();
+ Down();
+ }
+
+ Edit::MouseButtonUp( rMEvt );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ if ( mbInitialUp )
+ {
+ BOOL bNewUpperIn = maUpperRect.IsInside( rMEvt.GetPosPixel() );
+ if ( bNewUpperIn != mbUpperIn )
+ {
+ if ( bNewUpperIn )
+ {
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ }
+ else
+ maRepeatTimer.Stop();
+
+ mbUpperIn = bNewUpperIn;
+ Invalidate( maUpperRect );
+ Update();
+ }
+ }
+ else if ( mbInitialDown )
+ {
+ BOOL bNewLowerIn = maLowerRect.IsInside( rMEvt.GetPosPixel() );
+ if ( bNewLowerIn != mbLowerIn )
+ {
+ if ( bNewLowerIn )
+ {
+ if ( mbRepeat )
+ maRepeatTimer.Start();
+ }
+ else
+ maRepeatTimer.Stop();
+
+ mbLowerIn = bNewLowerIn;
+ Invalidate( maLowerRect );
+ Update();
+ }
+ }
+ }
+
+ Edit::MouseMove( rMEvt );
+}
+
+// --------------------------------------------------------------------
+
+long SpinField::Notify( NotifyEvent& rNEvt )
+{
+ long nDone = 0;
+ if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
+ if ( !IsReadOnly() )
+ {
+ USHORT nMod = rKEvt.GetKeyCode().GetModifier();
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_UP:
+ {
+ if ( !nMod )
+ {
+ Up();
+ nDone = 1;
+ }
+ }
+ break;
+ case KEY_DOWN:
+ {
+ if ( !nMod )
+ {
+ Down();
+ nDone = 1;
+ }
+ else if ( ( nMod == KEY_MOD2 ) && !mbInDropDown && ( GetStyle() & WB_DROPDOWN ) )
+ {
+ mbInDropDown = ShowDropDown( TRUE );
+ Paint( Rectangle( Point(), GetOutputSizePixel() ) );
+ nDone = 1;
+ }
+ }
+ break;
+ case KEY_PAGEUP:
+ {
+ if ( !nMod )
+ {
+ Last();
+ nDone = 1;
+ }
+ }
+ break;
+ case KEY_PAGEDOWN:
+ {
+ if ( !nMod )
+ {
+ First();
+ nDone = 1;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if ( rNEvt.GetType() == EVENT_COMMAND )
+ {
+ if ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
+ if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
+ {
+ if ( pData->GetDelta() < 0L )
+ Down();
+ else
+ Up();
+ nDone = 1;
+ }
+ }
+ }
+
+ return nDone ? nDone : Edit::Notify( rNEvt );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Command( const CommandEvent& rCEvt )
+{
+ Edit::Command( rCEvt );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Paint( const Rectangle& rRect )
+{
+ if ( mbSpin )
+ {
+ BOOL bEnable = IsEnabled();
+ ImplDrawSpinButton( this, maUpperRect, maLowerRect,
+ mbUpperIn, mbLowerIn, bEnable, bEnable );
+ }
+
+ if ( GetStyle() & WB_DROPDOWN )
+ {
+ DecorationView aView( this );
+
+ USHORT nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ if ( mbInDropDown )
+ nStyle |= BUTTON_DRAW_PRESSED;
+ Rectangle aInnerRect = aView.DrawButton( maDropDownRect, nStyle );
+
+ SymbolType eSymbol = SYMBOL_SPIN_DOWN;
+ if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN )
+ eSymbol = SYMBOL_SPIN_UPDOWN;
+
+ nStyle = IsEnabled() ? 0 : SYMBOL_DRAW_DISABLE;
+ aView.DrawSymbol( aInnerRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
+ }
+
+ Edit::Paint( rRect );
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::ImplCalcButtonAreas( OutputDevice* pDev, const Size& rOutSz, Rectangle& rDDArea, Rectangle& rSpinUpArea, Rectangle& rSpinDownArea )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Size aSize = rOutSz;
+ Size aDropDownSize;
+
+ if ( GetStyle() & WB_DROPDOWN )
+ {
+ long nW = rStyleSettings.GetScrollBarSize();
+ nW = GetDrawPixel( pDev, nW );
+ aDropDownSize = Size( CalcZoom( nW ), aSize.Height() );
+ aSize.Width() -= aDropDownSize.Width();
+ rDDArea = Rectangle( Point( aSize.Width(), 0 ), aDropDownSize );
+ rDDArea.Top()--;
+ }
+ else
+ rDDArea.SetEmpty();
+
+ // Je nach Hoehe, die groessen Berechnen
+ if ( GetStyle() & WB_SPIN )
+ {
+ long nBottom1 = aSize.Height()/2;
+ long nTop2 = nBottom1;
+ if ( !(aSize.Height() & 0x01) )
+ nBottom1--;
+
+ aSize.Width() -= CalcZoom( GetDrawPixel( pDev, rStyleSettings.GetSpinSize() ) );
+ rSpinUpArea = Rectangle( aSize.Width(), 0, rOutSz.Width()-aDropDownSize.Width()-1, nBottom1 );
+ rSpinDownArea = Rectangle( rSpinUpArea.Left(), nTop2, rSpinUpArea.Right(), aSize.Height()-1 );
+ }
+ else
+ {
+ rSpinUpArea.SetEmpty();
+ rSpinDownArea.SetEmpty();
+ }
+}
+
+// --------------------------------------------------------------------
+
+void SpinField::Resize()
+{
+ if ( mbSpin )
+ {
+ Size aSize = GetOutputSizePixel();
+
+ if ( GetStyle() & (WB_SPIN|WB_DROPDOWN) )
+ {
+ ImplCalcButtonAreas( this, aSize, maDropDownRect, maUpperRect, maLowerRect );
+ aSize.Width() -= maDropDownRect.GetWidth();
+ aSize.Width() -= maUpperRect.GetWidth();
+ }
+
+ mpEdit->SetSizePixel( aSize );
+
+ if ( GetStyle() & WB_SPIN )
+ Invalidate( Rectangle( maUpperRect.TopLeft(), maLowerRect.BottomRight() ) );
+ if ( GetStyle() & WB_DROPDOWN )
+ Invalidate( maDropDownRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinField::StateChanged( StateChangedType nType )
+{
+ Edit::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_ENABLE )
+ {
+ if ( mbSpin || ( GetStyle() & WB_DROPDOWN ) )
+ {
+ mpEdit->Enable( IsEnabled() );
+
+ if ( mbSpin )
+ {
+ Invalidate( maLowerRect );
+ Invalidate( maUpperRect );
+ }
+ if ( GetStyle() & WB_DROPDOWN )
+ Invalidate( maDropDownRect );
+ }
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ if ( GetStyle() & WB_REPEAT )
+ mbRepeat = TRUE;
+ else
+ mbRepeat = FALSE;
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ Resize();
+ if ( mpEdit )
+ mpEdit->SetZoom( GetZoom() );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ if ( mpEdit )
+ mpEdit->SetControlFont( GetControlFont() );
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ if ( mpEdit )
+ mpEdit->SetControlForeground( GetControlForeground() );
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ if ( mpEdit )
+ mpEdit->SetControlBackground( GetControlBackground() );
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinField::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Edit::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ Resize();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SpinField::EndDropDown()
+{
+ mbInDropDown = FALSE;
+ Paint( Rectangle( Point(), GetOutputSizePixel() ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SpinField::ShowDropDown( BOOL bShow )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Size SpinField::CalcMinimumSize() const
+{
+ Size aSz = Edit::CalcMinimumSize();
+
+ if ( GetStyle() & WB_DROPDOWN )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( GetStyle() & WB_SPIN )
+ aSz.Width() += GetSettings().GetStyleSettings().GetSpinSize();
+
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size SpinField::CalcSize( USHORT nChars ) const
+{
+ Size aSz = Edit::CalcSize( nChars );
+
+ if ( GetStyle() & WB_DROPDOWN )
+ aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( GetStyle() & WB_SPIN )
+ aSz.Width() += GetSettings().GetStyleSettings().GetSpinSize();
+
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SpinField::GetMaxVisChars() const
+{
+ long nOutWidth = mpEdit->GetOutputSizePixel().Width();
+ long nCharWidth = GetTextWidth( XubString( 'x' ) );
+ return nCharWidth ? (USHORT)(nOutWidth/nCharWidth) : 0;
+}
+
+// --------------------------------------------------------------------
+
+IMPL_LINK( SpinField, ImplTimeout, Timer*, pTimer )
+{
+ if ( pTimer->GetTimeout() == SPIN_DELAY )
+ {
+ pTimer->SetTimeout( SPIN_SPEED );
+ pTimer->Start();
+ }
+ else
+ {
+ if ( mbInitialUp )
+ Up();
+ else
+ Down();
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SpinField::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
+{
+ Edit::Draw( pDev, rPos, rSize, nFlags );
+
+ WinBits nStyle = GetStyle();
+ if ( !(nFlags & WINDOW_DRAW_NOCONTROLS ) && ( nStyle & (WB_SPIN|WB_DROPDOWN) ) )
+ {
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ OutDevType eOutDevType = pDev->GetOutDevType();
+ AllSettings aOldSettings = pDev->GetSettings();
+
+ pDev->Push();
+ pDev->SetMapMode();
+
+ if ( eOutDevType == OUTDEV_PRINTER )
+ {
+ StyleSettings aStyleSettings = aOldSettings.GetStyleSettings();
+ aStyleSettings.SetFaceColor( COL_LIGHTGRAY );
+ aStyleSettings.SetButtonTextColor( COL_BLACK );
+ AllSettings aSettings( aOldSettings );
+ aSettings.SetStyleSettings( aStyleSettings );
+ pDev->SetSettings( aSettings );
+ }
+
+ Rectangle aDD, aUp, aDown;
+ ImplCalcButtonAreas( pDev, aSize, aDD, aUp, aDown );
+ aDD.Move( aPos.X(), aPos.Y() );
+ aUp.Move( aPos.X(), aPos.Y() );
+ aUp.Top()++;
+ aDown.Move( aPos.X(), aPos.Y() );
+
+ Color aButtonTextColor;
+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
+ aButtonTextColor = Color( COL_BLACK );
+ else
+ aButtonTextColor = GetSettings().GetStyleSettings().GetButtonTextColor();
+
+ if ( GetStyle() & WB_DROPDOWN )
+ {
+ DecorationView aView( pDev );
+ USHORT nStyle = BUTTON_DRAW_NOLIGHTBORDER;
+ Rectangle aInnerRect = aView.DrawButton( aDD, nStyle );
+ SymbolType eSymbol = SYMBOL_SPIN_DOWN;
+ if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_SPINUPDOWN )
+ eSymbol = SYMBOL_SPIN_UPDOWN;
+
+ nStyle = ( IsEnabled() || ( nFlags & WINDOW_DRAW_NODISABLE ) ) ? 0 : SYMBOL_DRAW_DISABLE;
+ aView.DrawSymbol( aInnerRect, eSymbol, aButtonTextColor, nStyle );
+ }
+
+ if ( GetStyle() & WB_SPIN )
+ {
+ ImplDrawSpinButton( pDev, aUp, aDown, FALSE, FALSE, TRUE, TRUE );
+ }
+
+ pDev->Pop();
+ pDev->SetSettings( aOldSettings );
+ }
+}
diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx
new file mode 100644
index 000000000000..5165acb84e8a
--- /dev/null
+++ b/vcl/source/control/tabctrl.cxx
@@ -0,0 +1,1772 @@
+/*************************************************************************
+ *
+ * $RCSfile: tabctrl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TABCTRL_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_APP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_TABPAGE_HXX
+#include <tabpage.hxx>
+#endif
+#ifndef _SV_TABCTRL_HXX
+#include <tabctrl.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+struct ImplTabCtrlData
+{
+ PushButton* mpLeftBtn;
+ PushButton* mpRightBtn;
+};
+
+// -----------------------------------------------------------------------
+
+struct ImplTabItem
+{
+ USHORT mnId;
+ USHORT mnTabPageResId;
+ TabPage* mpTabPage;
+ String maText;
+ String maFormatText;
+ String maHelpText;
+ ULONG mnHelpId;
+ Rectangle maRect;
+ USHORT mnLine;
+ BOOL mbFullVisible;
+};
+
+DECLARE_LIST( ImplTabItemList, ImplTabItem* );
+
+// -----------------------------------------------------------------------
+
+#define TABCOLORCOUNT 10
+
+static ColorData aImplTabColorAry[TABCOLORCOUNT] =
+{
+ RGB_COLORDATA( 80, 216, 248 ),
+ RGB_COLORDATA( 128, 216, 168 ),
+ RGB_COLORDATA( 128, 144, 248 ),
+ RGB_COLORDATA( 208, 180, 168 ),
+ RGB_COLORDATA( 248, 252, 168 ),
+ RGB_COLORDATA( 168, 144, 168 ),
+ RGB_COLORDATA( 248, 144, 80 ),
+ RGB_COLORDATA( 248, 216, 80 ),
+ RGB_COLORDATA( 248, 180, 168 ),
+ RGB_COLORDATA( 248, 216, 168 )
+};
+
+// -----------------------------------------------------------------------
+
+#define TAB_OFFSET 3
+#define TAB_TABOFFSET_X 3
+#define TAB_TABOFFSET_Y 3
+#define TAB_BORDER_LEFT 1
+#define TAB_BORDER_TOP 1
+#define TAB_BORDER_RIGHT 2
+#define TAB_BORDER_BOTTOM 2
+
+// Fuer die Ermittlung von den Tab-Positionen
+#define TAB_PAGERECT 0xFFFF
+
+// =======================================================================
+
+void TabControl::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NOTABSTOP) )
+ nStyle |= WB_TABSTOP;
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ Control::ImplInit( pParent, nStyle, NULL );
+
+ mpItemList = new ImplTabItemList( 8, 8 );
+ mpTabCtrlData = NULL;
+ mnLastWidth = 0;
+ mnLastHeight = 0;
+ mnBtnSize = 0;
+ mnMaxPageWidth = 0;
+ mnActPageId = 0;
+ mnCurPageId = 0;
+ mnFirstPagePos = 0;
+ mnLastFirstPagePos = 0;
+ mbFormat = TRUE;
+ mbRestoreHelpId = FALSE;
+ mbRestoreUnqId = FALSE;
+ mbSingleLine = FALSE;
+ mbScroll = FALSE;
+ mbColored = FALSE;
+
+ if ( GetSettings().GetStyleSettings().GetTabControlStyle() & STYLE_TABCONTROL_SINGLELINE )
+ mbSingleLine = TRUE;
+
+ if ( mbSingleLine )
+ {
+ mpTabCtrlData = new ImplTabCtrlData;
+ mpTabCtrlData->mpLeftBtn = NULL;
+ mpTabCtrlData->mpRightBtn = NULL;
+ }
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetAppFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetButtonTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+ }
+
+ // Sollen TabReiter farbig dargestellt werden
+ mbColored = (rStyleSettings.GetTabControlStyle() & STYLE_TABCONTROL_COLOR) != 0;
+ ImplScrollBtnsColor();
+}
+
+// -----------------------------------------------------------------------
+
+TabControl::TabControl( Window* pParent, WinBits nStyle ) :
+ Control( WINDOW_TABCONTROL )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabControl::TabControl( Window* pParent, const ResId& rResId ) :
+ Control( WINDOW_TABCONTROL )
+{
+ rResId.SetRT( RSC_TABCONTROL );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplLoadRes( const ResId& rResId )
+{
+ Control::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( nObjMask & RSC_TABCONTROL_ITEMLIST )
+ {
+ USHORT nEle = ReadShortRes();
+
+ // Item hinzufuegen
+ for( USHORT i = 0; i < nEle; i++ )
+ {
+ InsertPage( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabControl::~TabControl()
+{
+ // Alle Items loeschen
+ ImplTabItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Itemlist loeschen
+ delete mpItemList;
+
+ // TabCtrl-Daten loeschen
+ if ( mpTabCtrlData )
+ {
+ if ( mpTabCtrlData->mpLeftBtn )
+ delete mpTabCtrlData->mpLeftBtn;
+ if ( mpTabCtrlData->mpRightBtn )
+ delete mpTabCtrlData->mpRightBtn;
+ delete mpTabCtrlData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplTabItem* TabControl::ImplGetItem( USHORT nId ) const
+{
+ ImplTabItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nId )
+ return pItem;
+
+ pItem = mpItemList->Next();
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplScrollBtnsColor()
+{
+ if ( mpTabCtrlData && mpTabCtrlData->mpLeftBtn )
+ {
+ if ( mbColored )
+ {
+ Color aScrollBtnColor( COL_LIGHTBLUE );
+ mpTabCtrlData->mpLeftBtn->SetControlForeground( aScrollBtnColor );
+ mpTabCtrlData->mpRightBtn->SetControlForeground( aScrollBtnColor );
+ }
+ else
+ {
+ mpTabCtrlData->mpLeftBtn->SetControlForeground();
+ mpTabCtrlData->mpRightBtn->SetControlForeground();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplSetScrollBtnsState()
+{
+ if ( mbScroll )
+ {
+ mpTabCtrlData->mpLeftBtn->Enable( mnFirstPagePos != 0 );
+ mpTabCtrlData->mpRightBtn->Enable( mnFirstPagePos < mnLastFirstPagePos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplPosScrollBtns()
+{
+ if ( mbScroll )
+ {
+ if ( !mpTabCtrlData->mpLeftBtn )
+ {
+ mpTabCtrlData->mpLeftBtn = new PushButton( this, WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOPOINTERFOCUS | WB_REPEAT );
+ mpTabCtrlData->mpLeftBtn->SetSymbol( SYMBOL_PREV );
+ mpTabCtrlData->mpLeftBtn->SetClickHdl( LINK( this, TabControl, ImplScrollBtnHdl ) );
+ }
+ if ( !mpTabCtrlData->mpRightBtn )
+ {
+ mpTabCtrlData->mpRightBtn = new PushButton( this, WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOPOINTERFOCUS | WB_REPEAT );
+ mpTabCtrlData->mpRightBtn->SetSymbol( SYMBOL_NEXT );
+ mpTabCtrlData->mpRightBtn->SetClickHdl( LINK( this, TabControl, ImplScrollBtnHdl ) );
+ }
+
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+ aRect.Left() -= TAB_OFFSET;
+ aRect.Top() -= TAB_OFFSET;
+ aRect.Right() += TAB_OFFSET;
+ aRect.Bottom() += TAB_OFFSET;
+ long nX = aRect.Right()-mnBtnSize+1;
+ long nY = aRect.Top()-mnBtnSize;
+ mpTabCtrlData->mpRightBtn->SetPosSizePixel( nX, nY, mnBtnSize, mnBtnSize );
+ nX -= mnBtnSize;
+ mpTabCtrlData->mpLeftBtn->SetPosSizePixel( nX, nY, mnBtnSize, mnBtnSize );
+ ImplScrollBtnsColor();
+ ImplSetScrollBtnsState();
+ mpTabCtrlData->mpLeftBtn->Show();
+ mpTabCtrlData->mpRightBtn->Show();
+ }
+ else
+ {
+ if ( mpTabCtrlData )
+ {
+ if ( mpTabCtrlData->mpLeftBtn )
+ mpTabCtrlData->mpLeftBtn->Hide();
+ if ( mpTabCtrlData->mpRightBtn )
+ mpTabCtrlData->mpRightBtn->Hide();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size TabControl::ImplGetItemSize( ImplTabItem* pItem, long nMaxWidth ) const
+{
+ pItem->maFormatText = pItem->maText;
+ Size aSize( GetCtrlTextWidth( pItem->maFormatText ), GetTextHeight() );
+ aSize.Width() += TAB_TABOFFSET_X*2;
+ aSize.Height() += TAB_TABOFFSET_Y*2;
+
+ // Evt. den Text kuerzen
+ if ( aSize.Width()+4 >= nMaxWidth )
+ {
+ XubString aAppendStr( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
+ pItem->maFormatText += aAppendStr;
+ do
+ {
+ pItem->maFormatText.Erase( pItem->maFormatText.Len()-aAppendStr.Len()-1, 1 );
+ aSize.Width() = GetCtrlTextWidth( pItem->maFormatText );
+ aSize.Width() += TAB_TABOFFSET_X*2;
+ }
+ while ( (aSize.Width()+4 >= nMaxWidth) && (pItem->maFormatText.Len() > aAppendStr.Len()) );
+ if ( aSize.Width()+4 >= nMaxWidth )
+ {
+ pItem->maFormatText.Assign( '.' );
+ aSize.Width() = 1;
+ }
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle TabControl::ImplGetTabRect( USHORT nPos, long nWidth, long nHeight )
+{
+ Size aWinSize = Control::GetOutputSizePixel();
+ if ( nWidth == -1 )
+ nWidth = aWinSize.Width();
+ if ( nHeight == -1 )
+ nHeight = aWinSize.Height();
+
+ if ( !mpItemList->Count() )
+ {
+ return Rectangle( Point( TAB_OFFSET, TAB_OFFSET ),
+ Size( nWidth-TAB_OFFSET*2, nHeight-TAB_OFFSET*2 ) );
+ }
+
+ if ( nPos == TAB_PAGERECT )
+ {
+ USHORT nLastPos;
+ if ( mbSingleLine )
+ nLastPos = mnFirstPagePos;
+ else
+ {
+ if ( mnCurPageId )
+ nLastPos = GetPagePos( mnCurPageId );
+ else
+ nLastPos = 0;
+ }
+ Rectangle aRect = ImplGetTabRect( nLastPos, nWidth, nHeight );
+ aRect = Rectangle( Point( TAB_OFFSET, aRect.Bottom()+TAB_OFFSET ),
+ Size( nWidth-TAB_OFFSET*2,
+ nHeight-aRect.Bottom()-TAB_OFFSET*2 ) );
+ return aRect;
+ }
+
+ nWidth -= 1;
+
+ if ( (nWidth <= 0) || (nHeight <= 0) )
+ return Rectangle();
+
+ Font aFont = GetFont();
+ FontWeight eWeight = aFont.GetWeight();
+ if ( eWeight != WEIGHT_BOLD )
+ aFont.SetWeight( WEIGHT_BOLD );
+ if ( !aFont.IsTransparent() )
+ aFont.SetTransparent( TRUE );
+
+ if ( mbFormat || (mnLastWidth != nWidth) || (mnLastHeight != nHeight) )
+ {
+ if ( eWeight != WEIGHT_BOLD )
+ SetFont( aFont );
+
+ ImplTabItem* pItem;
+ Size aSize;
+ long nX = 2;
+ long nY = 2;
+ long nMaxWidth = nWidth;
+ USHORT nPos = 0;
+
+ if ( (mnMaxPageWidth > 0) && (mnMaxPageWidth < nMaxWidth) )
+ nMaxWidth = mnMaxPageWidth;
+
+ mbScroll = FALSE;
+ if ( mbSingleLine )
+ {
+ // Zuerst ermitteln wir, ob wir scrollen muessen
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ aSize = ImplGetItemSize( pItem, nMaxWidth );
+ pItem->maRect = Rectangle( Point( nX, nY ), aSize );
+ pItem->mnLine = 1;
+ pItem->mbFullVisible = TRUE;
+ nX += aSize.Width();
+
+ if ( (nX > nWidth-2) && (nWidth > 4) )
+ mbScroll = TRUE;
+
+ pItem = mpItemList->Next();
+ }
+
+ // Wenn wir Scrollen muessen, dann muessen die Reiter
+ // entsprechend angeordnet werden
+ if ( mbScroll )
+ {
+ // Zuerst ermitteln wir den letzten TabReiter, bei dem
+ // die restlichen noch sichtbar bleiben und passen
+ // gegebenenfalls den ersten sichtbaren Writer an
+ mnBtnSize = GetTextHeight()+(TAB_TABOFFSET_Y*2);
+ long nMaxWidth = nWidth-(mnBtnSize*2);
+ long nTempWidth = 0;
+ USHORT nPageCount = GetPageCount();
+ mnLastFirstPagePos = nPageCount;
+ pItem = mpItemList->Last();
+ while ( pItem )
+ {
+ nTempWidth += pItem->maRect.GetSize().Width();
+ if ( nTempWidth > nMaxWidth )
+ break;
+
+ mnLastFirstPagePos--;
+ pItem = mpItemList->Prev();
+ }
+ if ( mnLastFirstPagePos > nPageCount-1 )
+ mnLastFirstPagePos = nPageCount-1;
+ if ( mnFirstPagePos > mnLastFirstPagePos )
+ mnFirstPagePos = mnLastFirstPagePos;
+
+ // Jetzt die TabReiter anordnen und die Reiter ausblenden,
+ // die nicht zu sehen sind
+ nPos = 0;
+ nX = 2;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( (nPos < mnFirstPagePos) ||
+ ((nX > nWidth-2) && (nWidth > 4)) )
+ {
+ pItem->mbFullVisible = FALSE;
+ pItem->maRect.SetEmpty();
+ }
+ else
+ {
+ aSize = pItem->maRect.GetSize();
+ pItem->maRect = Rectangle( Point( nX, nY ), aSize );
+ nX += aSize.Width();
+ }
+
+ if ( nX > nMaxWidth )
+ pItem->mbFullVisible = FALSE;
+
+ pItem = mpItemList->Next();
+ nPos++;
+ }
+ }
+ else
+ mnFirstPagePos = 0;
+ }
+ else
+ {
+ USHORT nLines = 0;
+ USHORT nCurLine = 0;
+ long nLineWidthAry[100];
+ USHORT nLinePosAry[100];
+
+ nLineWidthAry[0] = 0;
+ nLinePosAry[0] = 0;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ aSize = ImplGetItemSize( pItem, nMaxWidth );
+
+ if ( ((nX+aSize.Width()) > nWidth-2) && (nWidth > 4) )
+ {
+ if ( nLines == 99 )
+ break;
+
+ nX = 2;
+ nY += aSize.Height();
+ nLines++;
+ nLineWidthAry[nLines] = 0;
+ nLinePosAry[nLines] = nPos;
+ }
+
+ pItem->maRect = Rectangle( Point( nX, nY ), aSize );
+ pItem->mnLine = nLines;
+ pItem->mbFullVisible = TRUE;
+
+ nLineWidthAry[nLines] += aSize.Width();
+ nX += aSize.Width();
+
+ if ( pItem->mnId == mnCurPageId )
+ nCurLine = nLines;
+
+ pItem = mpItemList->Next();
+ nPos++;
+ }
+
+ if ( nLines )
+ {
+ long nDX;
+ long nModDX;
+ long nIDX;
+ USHORT i;
+ USHORT n;
+ long nLineHeightAry[100];
+ long nIH = mpItemList->GetObject( 0 )->maRect.Bottom()-2;
+
+ i = 0;
+ while ( i < nLines+1 )
+ {
+ if ( i <= nCurLine )
+ nLineHeightAry[i] = nIH*(nLines-(nCurLine-i));
+ else
+ nLineHeightAry[i] = nIH*(i-nCurLine-1);
+ i++;
+ }
+
+ i = 0;
+ n = 0;
+ nLinePosAry[nLines+1] = (USHORT)mpItemList->Count();
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( i == nLinePosAry[n] )
+ {
+ if ( n == nLines+1 )
+ break;
+
+ nIDX = 0;
+ nDX = (nWidth-2-nLineWidthAry[n]) / (nLinePosAry[n+1]-i);
+ nModDX = (nWidth-2-nLineWidthAry[n]) % (nLinePosAry[n+1]-i);
+ n++;
+ }
+
+ pItem->maRect.Left() += nIDX;
+ pItem->maRect.Right() += nIDX+nDX;
+ pItem->maRect.Top() = nLineHeightAry[n-1];
+ pItem->maRect.Bottom() = nLineHeightAry[n-1]+nIH;
+ nIDX += nDX;
+
+ if ( nModDX )
+ {
+ nIDX++;
+ pItem->maRect.Right()++;
+ nModDX--;
+ }
+
+ pItem = mpItemList->Next();
+ i++;
+ }
+ }
+ }
+
+ mnLastWidth = nWidth;
+ mnLastHeight = nHeight;
+ mbFormat = FALSE;
+
+ ImplPosScrollBtns();
+ }
+
+ return mpItemList->GetObject( nPos )->maRect;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplChangeTabPage( USHORT nId, USHORT nOldId )
+{
+ ImplTabItem* pOldItem = ImplGetItem( nOldId );
+ ImplTabItem* pItem = ImplGetItem( nId );
+ TabPage* pOldPage = (pOldItem) ? pOldItem->mpTabPage : NULL;
+ TabPage* pPage = (pItem) ? pItem->mpTabPage : NULL;
+ Window* pCtrlParent = GetParent();
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ USHORT nPos = GetPagePos( nId );
+ Rectangle aRect = ImplGetTabRect( nPos );
+
+ if ( !pOldItem || (pOldItem->mnLine != pItem->mnLine) )
+ {
+ aRect.Left() = 0;
+ aRect.Top() = 0;
+ aRect.Right() = Control::GetOutputSizePixel().Width();
+ }
+ else
+ {
+ aRect.Left() -= 3;
+ aRect.Top() -= 2;
+ aRect.Right() += 3;
+ Invalidate( aRect );
+ nPos = GetPagePos( nOldId );
+ aRect = ImplGetTabRect( nPos );
+ aRect.Left() -= 3;
+ aRect.Top() -= 2;
+ aRect.Right() += 3;
+ }
+ Invalidate( aRect );
+ }
+
+ if ( pOldPage == pPage )
+ return;
+
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+
+ if ( pOldPage )
+ {
+ if ( mbRestoreHelpId )
+ pCtrlParent->SetHelpId( 0 );
+ if ( mbRestoreUnqId )
+ pCtrlParent->SetUniqueId( 0 );
+ pOldPage->DeactivatePage();
+ }
+
+ if ( pPage )
+ {
+ pPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
+
+ // Hier Page aktivieren, damit die Controls entsprechend umgeschaltet
+ // werden koennen und HilfeId gegebenenfalls beim Parent umsetzen
+ if ( !GetHelpId() )
+ {
+ mbRestoreHelpId = TRUE;
+ pCtrlParent->SetHelpId( pPage->GetHelpId() );
+ }
+ if ( !pCtrlParent->GetUniqueId() )
+ {
+ mbRestoreUnqId = TRUE;
+ pCtrlParent->SetUniqueId( pPage->GetUniqueId() );
+ }
+
+ pPage->ActivatePage();
+
+ if ( pOldPage && pOldPage->HasChildPathFocus() )
+ {
+ USHORT n = 0;
+ Window* pFirstChild = pPage->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ if ( pFirstChild )
+ pFirstChild->ImplControlFocus( GETFOCUS_INIT );
+ else
+ GrabFocus();
+ }
+
+ pPage->Show();
+
+ if( Application::GetAccessHdlCount() && pPage->IsReallyVisible() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_DLGCONTROLS, GetParent() ) );
+ }
+
+ if ( pOldPage )
+ pOldPage->Hide();
+
+ Invalidate( aRect );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabControl::ImplPosCurTabPage()
+{
+ // Aktuelle TabPage resizen/positionieren
+ ImplTabItem* pItem = ImplGetItem( GetCurPageId() );
+ if ( pItem && pItem->mpTabPage )
+ {
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+ pItem->mpTabPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplActivateTabPage( BOOL bNext )
+{
+ USHORT nCurPos = GetPagePos( GetCurPageId() );
+
+ if ( bNext )
+ nCurPos = (nCurPos + 1) % GetPageCount();
+ else
+ {
+ if ( !nCurPos )
+ nCurPos = GetPageCount()-1;
+ else
+ nCurPos--;
+ }
+
+ SelectTabPage( GetPageId( nCurPos ) );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplSetFirstPagePos( USHORT nPagePos )
+{
+ if ( !mbSingleLine )
+ return;
+
+ if ( mbFormat )
+ mnFirstPagePos = nPagePos;
+ else
+ {
+ if ( nPagePos > mnLastFirstPagePos )
+ nPagePos = mnLastFirstPagePos;
+
+ if ( nPagePos != mnFirstPagePos )
+ {
+ // Neu auszugebene Rechteck berechnen
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+ aRect.Bottom() = aRect.Top();
+ aRect.Left() = 0;
+ aRect.Top() = 0;
+ aRect.Right() = Control::GetOutputSizePixel().Width();
+
+ mbFormat = TRUE;
+ mnFirstPagePos = nPagePos;
+ Invalidate( aRect, INVALIDATE_NOCHILDREN );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplShowFocus()
+{
+ if ( !GetPageCount() )
+ return;
+
+ USHORT nCurPos = GetPagePos( mnCurPageId );
+ Rectangle aRect = ImplGetTabRect( nCurPos );
+ ImplTabItem* pItem = mpItemList->GetObject( nCurPos );
+ Size aTabSize = aRect.GetSize();
+ long nTextHeight = GetTextHeight();
+ long nTextWidth = GetCtrlTextWidth( pItem->maFormatText );
+ USHORT nOff;
+
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO) )
+ nOff = 1;
+ else
+ nOff = 0;
+
+ aRect.Left() = aRect.Left()+((aTabSize.Width()-nTextWidth)/2)-nOff-1-1;
+ aRect.Top() = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-1-1;
+ aRect.Right() = aRect.Left()+nTextWidth+2;
+ aRect.Bottom() = aRect.Top()+nTextHeight+2;
+ ShowFocus( aRect );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect )
+{
+ if ( pItem->maRect.IsEmpty() )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aRect = pItem->maRect;
+ long nLeftBottom = aRect.Bottom();
+ long nRightBottom = aRect.Bottom();
+ BOOL bLeftBorder = TRUE;
+ BOOL bRightBorder = TRUE;
+ USHORT nOff;
+
+ USHORT nOff2 = 0;
+ USHORT nOff3 = 0;
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ nOff = 1;
+ else
+ nOff = 0;
+
+ // Wenn wir die aktuelle Page sind, muessen wir etwas mehr zeichnen
+ if ( pItem->mnId == mnCurPageId )
+ {
+ nOff2 = 2;
+ nOff3 = 1;
+ }
+ else
+ {
+ Point aLeftTestPos = aRect.BottomLeft();
+ Point aRightTestPos = aRect.BottomRight();
+ if ( aLeftTestPos.Y() == rCurRect.Bottom() )
+ {
+ aLeftTestPos.X() -= 2;
+ if ( rCurRect.IsInside( aLeftTestPos ) )
+ bLeftBorder = FALSE;
+ aRightTestPos.X() += 2;
+ if ( rCurRect.IsInside( aRightTestPos ) )
+ bRightBorder = FALSE;
+ }
+ else
+ {
+ if ( rCurRect.IsInside( aLeftTestPos ) )
+ nLeftBottom -= 2;
+ if ( rCurRect.IsInside( aRightTestPos ) )
+ nRightBottom -= 2;
+ }
+ }
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ if ( mbColored )
+ {
+ USHORT nPos = (USHORT)mpItemList->GetPos( pItem );
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( aImplTabColorAry[nPos%TABCOLORCOUNT] );
+ Rectangle aColorRect;
+ aColorRect.Left() = aRect.Left()-nOff2+1;
+ aColorRect.Top() = aRect.Top()-nOff2+1;
+ aColorRect.Right() = aRect.Right()+nOff2-3;
+ aColorRect.Bottom() = nLeftBottom;
+ if ( pItem->mnId != mnCurPageId )
+ aColorRect.Bottom()--;
+ DrawRect( aColorRect );
+ SetFillColor( aOldFillColor );
+ }
+
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) );
+ if ( bLeftBorder )
+ {
+ DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
+ Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
+ }
+ DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ),
+ Point( aRect.Right()+nOff2-3, aRect.Top()-nOff2 ) );
+
+ if ( bRightBorder )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ),
+ Point( aRect.Right()+nOff2-2, nRightBottom-1 ) );
+
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+3-nOff2 ),
+ Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
+ }
+ }
+ else
+ {
+ SetLineColor( Color( COL_BLACK ) );
+ DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) );
+ DrawPixel( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ) );
+ if ( bLeftBorder )
+ {
+ DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
+ Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
+ }
+ DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ),
+ Point( aRect.Right()-3, aRect.Top()-nOff2 ) );
+ if ( bRightBorder )
+ {
+ DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+2-nOff2 ),
+ Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
+ }
+ }
+
+ Size aTabSize = aRect.GetSize();
+ long nTextHeight = GetTextHeight();
+ long nTextWidth = GetCtrlTextWidth( pItem->maFormatText );
+ DrawCtrlText( Point( aRect.Left()+((aTabSize.Width()-nTextWidth)/2)-nOff-nOff3,
+ aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-nOff3 ),
+ pItem->maFormatText );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TabControl, ImplScrollBtnHdl, PushButton*, pBtn )
+{
+ if ( pBtn == mpTabCtrlData->mpRightBtn )
+ ImplSetFirstPagePos( mnFirstPagePos+1 );
+ else
+ ImplSetFirstPagePos( mnFirstPagePos-1 );
+ ImplSetScrollBtnsState();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ SelectTabPage( GetPageId( rMEvt.GetPosPixel() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( GetPageCount() > 1 )
+ {
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_RIGHT) )
+ {
+ BOOL bNext = (nKeyCode == KEY_RIGHT);
+ ImplActivateTabPage( bNext );
+ }
+ }
+
+ Control::KeyInput( rKEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::Paint( const Rectangle& rRect )
+{
+ HideFocus();
+
+ // Hier wird gegebenenfalls auch neu formatiert
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+
+ // Fonts entsprechend setzen
+ Font aFont( GetFont() );
+ Font aLightFont = aFont;
+ aFont.SetTransparent( TRUE );
+ aFont.SetWeight( WEIGHT_BOLD );
+ aLightFont.SetTransparent( TRUE );
+ aLightFont.SetWeight( WEIGHT_LIGHT );
+
+ // Aktuelles Item ermitteln
+ ImplTabItem* pPrevCurItem = NULL;
+ ImplTabItem* pCurItem = NULL;
+ ImplTabItem* pItem = mpItemList->First();
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == mnCurPageId )
+ {
+ pCurItem = pItem;
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ // Border um TabPage zeichnen
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aCurRect;
+ long nTopOff = 1;
+ aRect.Left() -= TAB_OFFSET;
+ aRect.Top() -= TAB_OFFSET;
+ aRect.Right() += TAB_OFFSET;
+ aRect.Bottom() += TAB_OFFSET;
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ SetLineColor( Color( COL_BLACK ) );
+ if ( pCurItem && !pCurItem->maRect.IsEmpty() )
+ {
+ aCurRect = pCurItem->maRect;
+ DrawLine( aRect.TopLeft(), Point( aCurRect.Left()-2, aRect.Top() ) );
+ if ( aCurRect.Right()+1 < aRect.Right() )
+ DrawLine( Point( aCurRect.Right(), aRect.Top() ), aRect.TopRight() );
+ else
+ nTopOff = 0;
+ }
+ else
+ DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( 1, aRect.Bottom()-1 ),
+ Point( aRect.Right()-1, aRect.Bottom()-1 ) );
+ DrawLine( Point( aRect.Right()-1, aRect.Top()+nTopOff ),
+ Point( aRect.Right()-1, aRect.Bottom()-1 ) );
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( Point( 0, aRect.Bottom() ),
+ Point( aRect.Right(), aRect.Bottom() ) );
+ DrawLine( Point( aRect.Right(), aRect.Top()+nTopOff ),
+ Point( aRect.Right(), aRect.Bottom() ) );
+ }
+ else
+ {
+ DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ }
+
+ // Alle Items bis auf das aktuelle Zeichnen (nicht fett)
+ SetFont( aLightFont );
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem != pCurItem )
+ ImplDrawItem( pItem, aCurRect );
+ pItem = mpItemList->Next();
+ }
+
+ // aktuelles Item zeichnen wir fett
+ SetFont( aFont );
+ if ( pCurItem )
+ ImplDrawItem( pCurItem, aCurRect );
+
+ if ( HasFocus() )
+ ImplShowFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::Resize()
+{
+ if ( !IsReallyShown() )
+ return;
+
+ mbFormat = TRUE;
+
+ // Aktuelle TabPage resizen/positionieren
+ BOOL bTabPage = ImplPosCurTabPage();
+ // Feststellen, was invalidiert werden muss
+ Size aNewSize = Control::GetOutputSizePixel();
+ long nWidthTest = aNewSize.Width();
+ BOOL bSmallInvalidate = TRUE;
+ BOOL bWidthChanged = (nWidthTest != mnLastWidth);
+ if ( mbScroll )
+ bSmallInvalidate = FALSE;
+ else if ( bWidthChanged )
+ {
+ if ( mnLastWidth < nWidthTest )
+ nWidthTest = mnLastWidth;
+
+ ImplTabItem* pItem;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( !pItem->mbFullVisible ||
+ (pItem->maRect.Right()-2 >= nWidthTest) )
+ {
+ bSmallInvalidate = FALSE;
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+
+ if ( bSmallInvalidate )
+ {
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
+ aRect.Left() -= TAB_OFFSET+TAB_BORDER_LEFT;
+ aRect.Top() -= TAB_OFFSET+TAB_BORDER_TOP;
+ aRect.Right() += TAB_OFFSET+TAB_BORDER_RIGHT;
+ aRect.Bottom() += TAB_OFFSET+TAB_BORDER_BOTTOM;
+ if ( bTabPage )
+ Invalidate( aRect, INVALIDATE_NOCHILDREN );
+ else
+ Invalidate( aRect );
+ }
+ else
+ {
+ if ( bTabPage )
+ Invalidate( INVALIDATE_NOCHILDREN );
+ else
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::GetFocus()
+{
+ ImplShowFocus();
+ SetInputContext( InputContext( GetFont() ) );
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::LoseFocus()
+{
+ HideFocus();
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ XubString aStr = GetHelpText( nItemId );
+ if ( aStr.Len() )
+ {
+ Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ return;
+ }
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ ULONG nHelpId = GetHelpId( nItemId );
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId );
+ return;
+ }
+ }
+
+ // Bei Quick- oder Ballloon-Help zeigen wir den Text an,
+ // wenn dieser abgeschnitten ist
+ if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
+ {
+ ImplTabItem* pItem = ImplGetItem( nItemId );
+ const XubString& rStr = pItem->maText;
+ if ( rStr != pItem->maFormatText )
+ {
+ Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ if ( rStr.Len() )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, rStr );
+ else
+ Help::ShowQuickHelp( this, aItemRect, rStr );
+ return;
+ }
+ }
+ }
+ }
+
+ Control::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::Command( const CommandEvent& rCEvt )
+{
+ if ( (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) && (GetPageCount() > 1) )
+ {
+ Point aMenuPos;
+ BOOL bMenu;
+ if ( rCEvt.IsMouseEvent() )
+ {
+ aMenuPos = rCEvt.GetMousePosPixel();
+ bMenu = GetPageId( aMenuPos ) != 0;
+ }
+ else
+ {
+ aMenuPos = ImplGetTabRect( GetPagePos( mnCurPageId ) ).Center();
+ bMenu = TRUE;
+ }
+
+ if ( bMenu )
+ {
+ PopupMenu aMenu;
+ ImplTabItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ aMenu.InsertItem( pItem->mnId, pItem->maText, MIB_CHECKABLE | MIB_RADIOCHECK );
+ if ( pItem->mnId == mnCurPageId )
+ aMenu.CheckItem( pItem->mnId );
+ aMenu.SetHelpId( pItem->mnId, pItem->mnHelpId );
+ pItem = mpItemList->Next();
+ }
+
+ USHORT nId = aMenu.Execute( this, aMenuPos );
+ if ( nId && (nId != mnCurPageId) )
+ SelectTabPage( nId );
+ return;
+ }
+ }
+
+ Control::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplPosCurTabPage();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long TabControl::Notify( NotifyEvent& rNEvt )
+{
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) && (GetPageCount() > 1) )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( aKeyCode.IsMod1() )
+ {
+ if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) )
+ {
+ if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) )
+ {
+ ImplActivateTabPage( FALSE );
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) )
+ {
+ ImplActivateTabPage( TRUE );
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return Control::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::ActivatePage()
+{
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+long TabControl::DeactivatePage()
+{
+ if ( maDeactivateHdl.IsSet() )
+ return maDeactivateHdl.Call( this );
+ else
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetTabPageSizePixel( const Size& rSize )
+{
+ Size aNewSize( rSize );
+ aNewSize.Width() += TAB_OFFSET*2;
+ Rectangle aRect = ImplGetTabRect( TAB_PAGERECT,
+ aNewSize.Width(), aNewSize.Height() );
+ aNewSize.Height() += aRect.Top()+TAB_OFFSET;
+ Window::SetOutputSizePixel( aNewSize );
+}
+
+// -----------------------------------------------------------------------
+
+Size TabControl::GetTabPageSizePixel() const
+{
+ Rectangle aRect = ((TabControl*)this)->ImplGetTabRect( TAB_PAGERECT );
+ return aRect.GetSize();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::InsertPage( const ResId& rResId, USHORT nPos )
+{
+ GetRes( rResId.SetRT( RSC_TABCONTROLITEM ) );
+
+ USHORT nObjMask = ReadShortRes();
+ USHORT nItemId = 1;
+
+ // ID
+ if ( nObjMask & RSC_TABCONTROLITEM_ID )
+ nItemId = ReadShortRes();
+
+ // Text
+ XubString aTmpStr;
+ if( nObjMask & RSC_TABCONTROLITEM_TEXT )
+ aTmpStr = ReadStringRes();
+ InsertPage( nItemId, aTmpStr, nPos );
+
+ // PageResID
+ if ( nObjMask & RSC_TABCONTROLITEM_PAGERESID )
+ {
+ ImplTabItem* pItem = mpItemList->GetObject( GetPagePos( nItemId ) );
+ pItem->mnTabPageResId = ReadShortRes();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::InsertPage( USHORT nPageId, const XubString& rText,
+ USHORT nPos )
+{
+ DBG_ASSERT( nPageId, "TabControl::InsertPage(): PageId == 0" );
+ DBG_ASSERT( GetPagePos( nPageId ) == TAB_PAGE_NOTFOUND,
+ "TabControl::InsertPage(): PageId already exists" );
+
+ // CurPageId gegebenenfalls setzen
+ if ( !mnCurPageId )
+ mnCurPageId = nPageId;
+
+ // PageItem anlegen
+ ImplTabItem* pItem = new ImplTabItem;
+ pItem->mnId = nPageId;
+ pItem->mpTabPage = NULL;
+ pItem->mnTabPageResId = 0;
+ pItem->mnHelpId = 0;
+ pItem->maText = rText;
+ pItem->mbFullVisible = FALSE;
+
+ // In die StarView-Liste eintragen
+ mpItemList->Insert( pItem, nPos );
+
+ mbFormat = TRUE;
+ if ( IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::RemovePage( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ // Existiert Item
+ if ( nPos != TAB_PAGE_NOTFOUND )
+ {
+ // Item-Daten loeschen und Windows-Item entfernen
+ ImplTabItem* pItem = mpItemList->Remove( nPos );
+ if ( pItem->mnId == mnCurPageId )
+ mnCurPageId = 0;
+ delete pItem;
+
+ mbFormat = TRUE;
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::Clear()
+{
+ // Alle Items loeschen
+ ImplTabItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Item-Daten loeschen
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+ mnCurPageId = 0;
+
+ mbFormat = TRUE;
+ if ( IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetPageCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetPageId( USHORT nPos ) const
+{
+ ImplTabItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetPagePos( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nPageId )
+ return (USHORT)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return TAB_PAGE_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetPageId( const Point& rPos ) const
+{
+ USHORT i = 0;
+ while ( i < mpItemList->Count() )
+ {
+ if ( ((TabControl*)this)->ImplGetTabRect( i ).IsInside( rPos ) )
+ return mpItemList->GetObject( i )->mnId;
+ i++;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetCurPageId( USHORT nPageId )
+{
+ if ( nPageId == mnCurPageId )
+ {
+ if ( mnActPageId )
+ mnActPageId = nPageId;
+ return;
+ }
+
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+ if ( pItem )
+ {
+ if ( mnActPageId )
+ mnActPageId = nPageId;
+ else
+ {
+ if ( pItem->maRect.IsEmpty() || !pItem->mbFullVisible )
+ SetFirstPageId( nPageId );
+ mbFormat = TRUE;
+ USHORT nOldId = mnCurPageId;
+ mnCurPageId = nPageId;
+ ImplChangeTabPage( nPageId, nOldId );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetCurPageId() const
+{
+ if ( mnActPageId )
+ return mnActPageId;
+ else
+ return mnCurPageId;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetFirstPageId( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( (nPos != TAB_PAGE_NOTFOUND) && (nPos != mnFirstPagePos) )
+ ImplSetFirstPagePos( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SelectTabPage( USHORT nPageId )
+{
+ if ( nPageId && (nPageId != mnCurPageId) )
+ {
+ if ( DeactivatePage() )
+ {
+ mnActPageId = nPageId;
+ ActivatePage();
+ // Page koennte im Activate-Handler umgeschaltet wurden sein
+ nPageId = mnActPageId;
+ mnActPageId = 0;
+ SetCurPageId( nPageId );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetTabPage( USHORT nPageId, TabPage* pTabPage )
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem && (pItem->mpTabPage != pTabPage) )
+ {
+ if ( pTabPage )
+ {
+ DBG_ASSERT( !pTabPage->IsVisible(), "TabControl::SetTabPage() - Page is visible" );
+
+ if ( IsDefaultSize() )
+ SetTabPageSizePixel( pTabPage->GetSizePixel() );
+
+ // Erst hier setzen, damit Resize nicht TabPage umpositioniert
+ pItem->mpTabPage = pTabPage;
+ if ( pItem->mnId == mnCurPageId )
+ ImplChangeTabPage( pItem->mnId, 0 );
+ }
+ else
+ pItem->mpTabPage = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabPage* TabControl::GetTabPage( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ return pItem->mpTabPage;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabControl::GetTabPageResId( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ return pItem->mnTabPageResId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetPageText( USHORT nPageId, const XubString& rText )
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ {
+ pItem->maText = rText;
+ mbFormat = TRUE;
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString TabControl::GetPageText( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ return pItem->maText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetHelpText( USHORT nPageId, const XubString& rText )
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ pItem->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& TabControl::GetHelpText( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ {
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void TabControl::SetHelpId( USHORT nPageId, ULONG nHelpId )
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ pItem->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG TabControl::GetHelpId( USHORT nPageId ) const
+{
+ ImplTabItem* pItem = ImplGetItem( nPageId );
+
+ if ( pItem )
+ return pItem->mnHelpId;
+ else
+ return 0;
+}
diff --git a/vcl/source/gdi/alpha.cxx b/vcl/source/gdi/alpha.cxx
new file mode 100644
index 000000000000..9e00d0044787
--- /dev/null
+++ b/vcl/source/gdi/alpha.cxx
@@ -0,0 +1,353 @@
+/*************************************************************************
+ *
+ * $RCSfile: alpha.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ALPHA_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_COLOR_HXX
+#include <color.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+
+// -------------
+// - AlphaMask -
+// -------------
+
+AlphaMask::AlphaMask()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const Bitmap& rBitmap ) :
+ Bitmap( rBitmap )
+{
+ if( !!rBitmap )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) :
+ Bitmap( rAlphaMask )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const Size& rSizePixel, BYTE* pEraseTransparency ) :
+ Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) )
+{
+ if( pEraseTransparency )
+ Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::~AlphaMask()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap )
+{
+ *(Bitmap*) this = rBitmap;
+
+ if( !!rBitmap )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------------
+
+const Bitmap& AlphaMask::ImplGetBitmap() const
+{
+ return( (const Bitmap&) *this );
+}
+
+// -----------------------------------------------------------------------------
+
+void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap )
+{
+ *(Bitmap*) this = rBitmap;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Crop( const Rectangle& rRectPixel )
+{
+ return Bitmap::Crop( rRectPixel );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Expand( ULONG nDX, ULONG nDY, BYTE* pInitTransparency )
+{
+ Color aColor;
+
+ if( pInitTransparency )
+ aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency );
+
+ return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Erase( BYTE cTransparency )
+{
+ return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Invert()
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc && pAcc->GetBitCount() == 8 )
+ {
+ BitmapColor aCol( 0 );
+ const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
+ BYTE* pMap = new BYTE[ 256 ];
+
+ for( long i = 0; i < 256; i++ )
+ pMap[ i ] = ~(BYTE) i;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+
+ delete[] pMap;
+ bRet = TRUE;
+ }
+
+ if( pAcc )
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Mirror( ULONG nMirrorFlags )
+{
+ return Bitmap::Mirror( nMirrorFlags );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ BOOL bRet = Bitmap::Scale( rNewSize, nScaleFlag );
+
+ if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag );
+
+ if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Rotate( long nAngle10, BYTE cFillTransparency )
+{
+ return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( const Bitmap& rMask, BYTE cReplaceTransparency )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const BitmapColor aReplace( cReplaceTransparency );
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( BYTE cSearchTransparency, BYTE cReplaceTransparency, ULONG nTol )
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" );
+
+ if( pAcc && pAcc->GetBitCount() == 8 )
+ {
+ const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
+
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++, pScan++ )
+ {
+ if( *pScan == cSearchTransparency )
+ *pScan = cReplaceTransparency;
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aReplace( cReplaceTransparency );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ if( pAcc )
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( BYTE* pSearchTransparencies, BYTE* pReplaceTransparencies,
+ ULONG nColorCount, ULONG* pTols )
+{
+ Color* pSearchColors = new Color[ nColorCount ];
+ Color* pReplaceColors = new Color[ nColorCount ];
+ BOOL bRet;
+
+ for( ULONG i = 0; i < nColorCount; i++ )
+ {
+ const BYTE cSearchTransparency = pSearchTransparencies[ i ];
+ const BYTE cReplaceTransparency = pReplaceTransparencies[ i ];
+
+ pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency );
+ pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency );
+ }
+
+ bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) &&
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ delete[] pSearchColors;
+ delete[] pReplaceColors;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess )
+{
+ if( pAccess )
+ {
+ Bitmap::ReleaseAccess( pAccess );
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+ }
+}
diff --git a/vcl/source/gdi/animate.cxx b/vcl/source/gdi/animate.cxx
new file mode 100644
index 000000000000..2a1c7e26ad2b
--- /dev/null
+++ b/vcl/source/gdi/animate.cxx
@@ -0,0 +1,992 @@
+/*************************************************************************
+ *
+ * $RCSfile: animate.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ANIMATE_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_IMPANMVW_HXX
+#include <impanmvw.hxx>
+#endif
+#ifndef _SV_ANIMATE_HXX
+#include <animate.hxx>
+#endif
+
+DBG_NAME( Animation );
+
+// -----------
+// - Defines -
+// -----------
+
+#define MIN_TIMEOUT 2L
+#define INC_TIMEOUT 0L
+
+// -----------
+// - statics -
+// -----------
+
+ULONG Animation::mnAnimCount = 0UL;
+
+// -------------------
+// - AnimationBitmap -
+// -------------------
+
+ULONG AnimationBitmap::GetChecksum() const
+{
+ sal_uInt32 nCrc = aBmpEx.GetChecksum();
+ SVBT32 aBT32;
+
+ LongToSVBT32( aPosPix.X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aPosPix.Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aSizePix.Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aSizePix.Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) nWait, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) eDisposal, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) bUserInput, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ return nCrc;
+}
+
+// -------------
+// - Animation -
+// -------------
+
+Animation::Animation() :
+ mbIsInAnimation ( FALSE ),
+ meCycleMode ( CYCLE_NORMAL ),
+ mnLoopCount ( 0 ),
+ mnLoops ( 0 ),
+ mnPos ( 0 ),
+ mbLoopTerminated ( FALSE ),
+ mbIsWaiting ( FALSE )
+{
+ DBG_CTOR( Animation, NULL );
+ maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
+ mpViewList = new List;
+}
+
+// -----------------------------------------------------------------------
+
+Animation::Animation( const Animation& rAnimation ) :
+ maGlobalSize ( rAnimation.maGlobalSize ),
+ maBitmapEx ( rAnimation.maBitmapEx ),
+ meCycleMode ( rAnimation.meCycleMode ),
+ mbIsInAnimation ( FALSE ),
+ mnLoopCount ( rAnimation.mnLoopCount ),
+ mnPos ( rAnimation.mnPos ),
+ mbLoopTerminated ( rAnimation.mbLoopTerminated ),
+ mbIsWaiting ( rAnimation.mbIsWaiting )
+{
+ DBG_CTOR( Animation, NULL );
+
+ for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
+ maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
+
+ maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
+ mpViewList = new List;
+ mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
+}
+
+// -----------------------------------------------------------------------
+
+Animation::~Animation()
+{
+ DBG_DTOR( Animation, NULL );
+
+ if( mbIsInAnimation )
+ Stop();
+
+ for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
+ delete (AnimationBitmap*) pStepBmp;
+
+ for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
+ delete (ImplAnimView*) pView;
+
+ delete mpViewList;
+}
+
+// -----------------------------------------------------------------------
+
+Animation& Animation::operator=( const Animation& rAnimation )
+{
+ Clear();
+
+ for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
+ maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
+
+ maGlobalSize = rAnimation.maGlobalSize;
+ maBitmapEx = rAnimation.maBitmapEx;
+ meCycleMode = rAnimation.meCycleMode;
+ mnLoopCount = rAnimation.mnLoopCount;
+ mnPos = rAnimation.mnPos;
+ mbLoopTerminated = rAnimation.mbLoopTerminated;
+ mbIsWaiting = rAnimation.mbIsWaiting;
+ mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::operator==( const Animation& rAnimation ) const
+{
+ const ULONG nCount = maList.Count();
+ BOOL bRet = FALSE;
+
+ if( rAnimation.maList.Count() == nCount &&
+ rAnimation.maBitmapEx == maBitmapEx &&
+ rAnimation.maGlobalSize == maGlobalSize &&
+ rAnimation.meCycleMode == meCycleMode )
+ {
+ bRet = TRUE;
+
+ for( ULONG n = 0; n < nCount; n++ )
+ {
+ if( ( *(AnimationBitmap*) maList.GetObject( n ) ) !=
+ ( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Animation::IsEqual( const Animation& rAnimation ) const
+{
+ const ULONG nCount = maList.Count();
+ BOOL bRet = FALSE;
+
+ if( rAnimation.maList.Count() == nCount &&
+ rAnimation.maBitmapEx.IsEqual( maBitmapEx ) &&
+ rAnimation.maGlobalSize == maGlobalSize &&
+ rAnimation.meCycleMode == meCycleMode )
+ {
+ for( ULONG n = 0; ( n < nCount ) && !bRet; n++ )
+ if( ( (AnimationBitmap*) maList.GetObject( n ) )->IsEqual( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Animation::IsEmpty() const
+{
+ return( maBitmapEx.IsEmpty() && !maList.Count() );
+}
+
+// ------------------------------------------------------------------
+
+void Animation::SetEmpty()
+{
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ maGlobalSize = Size();
+ maBitmapEx.SetEmpty();
+
+ for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
+ delete (AnimationBitmap*) pStepBmp;
+ maList.Clear();
+
+ for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
+ delete (ImplAnimView*) pView;
+ mpViewList->Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Clear()
+{
+ SetEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::IsTransparent() const
+{
+ Point aPoint;
+ Rectangle aRect( aPoint, maGlobalSize );
+ BOOL bRet = FALSE;
+
+ // Falls irgendein 'kleines' Bildchen durch den Hintergrund
+ // ersetzt werden soll, muessen wir 'transparent' sein, um
+ // richtig dargestellt zu werden, da die Appl. aus Optimierungsgruenden
+ // kein Invalidate auf nicht-transp. Grafiken ausfuehren
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
+
+ if( DISPOSE_BACK == pAnimBmp->eDisposal && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect )
+ {
+ bRet = TRUE;
+ break;
+ }
+ }
+
+ if( !bRet )
+ bRet = maBitmapEx.IsTransparent();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Animation::GetSizeBytes() const
+{
+ ULONG nSizeBytes = GetBitmapEx().GetSizeBytes();
+
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
+ nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes();
+ }
+
+ return nSizeBytes;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Animation::GetChecksum() const
+{
+ SVBT32 aBT32;
+ sal_uInt32 nCrc = GetBitmapEx().GetChecksum();
+
+ LongToSVBT32( maList.Count(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( maGlobalSize.Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( maGlobalSize.Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) meCycleMode, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ LongToSVBT32( ( (AnimationBitmap*) maList.GetObject( i ) )->GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+
+ return nCrc;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ return Start( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ), nExtraData, pFirstFrameOutDev );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ BOOL bRet = FALSE;
+
+ if( maList.Count() )
+ {
+ if( ( pOut->GetOutDevType() == OUTDEV_WINDOW ) && !mbLoopTerminated &&
+ ( ANIMATION_TIMEOUT_ON_CLICK != ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ) )
+ {
+ ImplAnimView* pView;
+ ImplAnimView* pMatch = NULL;
+
+ for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
+ {
+ if( pView->ImplMatches( pOut, nExtraData ) )
+ {
+ if( pView->ImplGetOutPos() == rDestPt &&
+ pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) )
+ {
+ pView->ImplRepaint();
+ pMatch = pView;
+ }
+ else
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = NULL;
+ }
+
+ break;
+ }
+ }
+
+ if( !mpViewList->Count() )
+ {
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ mnPos = 0UL;
+ }
+
+ if( !pMatch )
+ mpViewList->Insert( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ), LIST_APPEND );
+
+ if( !mbIsInAnimation )
+ {
+ ImplRestartTimer( ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait );
+ mbIsInAnimation = TRUE;
+ }
+ }
+ else
+ Draw( pOut, rDestPt, rDestSz );
+
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Stop( OutputDevice* pOut, long nExtraData )
+{
+ ImplAnimView* pView = (ImplAnimView*) mpViewList->First();
+
+ while( pView )
+ {
+ if( pView->ImplMatches( pOut, nExtraData ) )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+
+ if( !mpViewList->Count() )
+ {
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
+{
+ Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const
+{
+ const ULONG nCount = maList.Count();
+
+ if( nCount )
+ {
+ AnimationBitmap* pObj = (AnimationBitmap*) maList.GetObject( Min( mnPos, (long) nCount - 1L ) );
+
+ if( pOut->GetConnectMetaFile() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) )
+ ( (AnimationBitmap*) maList.GetObject( 0 ) )->aBmpEx.Draw( pOut, rDestPt, rDestSz );
+ else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait )
+ pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz );
+ else
+ {
+ const ULONG nOldPos = mnPos;
+ ( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
+ delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 );
+ ( (Animation*) this )->mnPos = nOldPos;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::ImplRestartTimer( ULONG nTimeout )
+{
+#ifdef REMOTE_APPSERVER
+ nTimeout = nTimeout > 40 ? nTimeout : 40;
+#endif
+ maTimer.SetTimeout( Max( nTimeout, MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT ) * 10L );
+ maTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Animation, ImplTimeoutHdl, Timer*, pTimer )
+{
+ const ULONG nAnimCount = maList.Count();
+
+ if( nAnimCount )
+ {
+ ImplAnimView* pView;
+ BOOL bGlobalPause = TRUE;
+
+ if( maNotifyLink.IsSet() )
+ {
+ AInfo* pAInfo;
+
+ // create AInfo-List
+ for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
+ maAInfoList.Insert( pView->ImplCreateAInfo() );
+
+ maNotifyLink.Call( this );
+
+ // set view state from AInfo structure
+ for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
+ {
+ if( !pAInfo->pViewData )
+ {
+ pView = new ImplAnimView( this, pAInfo->pOutDev,
+ pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
+
+ mpViewList->Insert( pView, LIST_APPEND );
+ }
+ else
+ pView = (ImplAnimView*) pAInfo->pViewData;
+
+ pView->ImplPause( pAInfo->bPause );
+ pView->ImplSetMarked( TRUE );
+ }
+
+ // delete AInfo structures
+ for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
+ delete (AInfo*) pAInfo;
+ maAInfoList.Clear();
+
+ // delete all unmarked views and reset marked state
+ pView = (ImplAnimView*) mpViewList->First();
+ while( pView )
+ {
+ if( !pView->ImplIsMarked() )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ {
+ if( !pView->ImplIsPause() )
+ bGlobalPause = FALSE;
+
+ pView->ImplSetMarked( FALSE );
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+ }
+ }
+ else
+ bGlobalPause = FALSE;
+
+ if( !mpViewList->Count() )
+ Stop();
+ else if( bGlobalPause )
+ ImplRestartTimer( 10 );
+ else
+ {
+ AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.GetObject( ++mnPos );
+
+ if( !pStepBmp )
+ {
+ if( mnLoops == 1 )
+ {
+ Stop();
+ mbLoopTerminated = TRUE;
+ mnPos = nAnimCount - 1UL;
+ maBitmapEx = ( (AnimationBitmap*) maList.GetObject( mnPos ) )->aBmpEx;
+ return 0L;
+ }
+ else
+ {
+ if( mnLoops )
+ mnLoops--;
+
+ mnPos = 0;
+ pStepBmp = (AnimationBitmap*) maList.GetObject( mnPos );
+ }
+ }
+
+ // Paint all views; after painting check, if view is
+ // marked; in this case remove view, because area of output
+ // lies out of display area of window; mark state is
+ // set from view itself
+ pView = (ImplAnimView*) mpViewList->First();
+ while( pView )
+ {
+ pView->ImplDraw( mnPos );
+
+ if( pView->ImplIsMarked() )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+
+ // stop or restart timer
+ if( !mpViewList->Count() )
+ Stop();
+ else
+ ImplRestartTimer( pStepBmp->nWait );
+ }
+ }
+ else
+ Stop();
+
+ return 0L;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Insert( const AnimationBitmap& rStepBmp )
+{
+ BOOL bRet = FALSE;
+
+ if( !IsInAnimation() )
+ {
+ Point aPoint;
+ Rectangle aGlobalRect( aPoint, maGlobalSize );
+
+ maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
+ maList.Insert( new AnimationBitmap( rStepBmp ), LIST_APPEND );
+
+ // zunaechst nehmen wir die erste BitmapEx als Ersatz-BitmapEx
+ if( maList.Count() == 1 )
+ maBitmapEx = rStepBmp.aBmpEx;
+
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+const AnimationBitmap& Animation::Get( USHORT nAnimation ) const
+{
+ DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
+ return *(AnimationBitmap*) maList.GetObject( nAnimation );
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, USHORT nAnimation )
+{
+ DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
+
+ delete (AnimationBitmap*) maList.Replace( new AnimationBitmap( rNewAnimationBitmap ), nAnimation );
+
+ // Falls wir an erster Stelle einfuegen,
+ // muessen wir natuerlich auch,
+ // auch die Ersatzdarstellungs-BitmapEx
+ // aktualisieren;
+ if ( ( !nAnimation && ( !mbLoopTerminated || ( maList.Count() == 1 ) ) ) ||
+ ( ( nAnimation == maList.Count() - 1 ) && mbLoopTerminated ) )
+ {
+ maBitmapEx = rNewAnimationBitmap.aBmpEx;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::SetLoopCount( const ULONG nLoopCount )
+{
+ mnLoopCount = nLoopCount;
+ ResetLoopCount();
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::ResetLoopCount()
+{
+ mnLoops = mnLoopCount;
+ mbLoopTerminated = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Convert( BmpConversion eConversion )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Convert( eConversion );
+
+ maBitmapEx.Convert( eConversion );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::ReduceColors( USHORT nNewColorCount, BmpReduce eReduce )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.ReduceColors( nNewColorCount, eReduce );
+
+ maBitmapEx.ReduceColors( nNewColorCount, eReduce );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Invert()
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Invert();
+
+ maBitmapEx.Invert();
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Mirror( ULONG nMirrorFlags )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ if( nMirrorFlags )
+ {
+ for( AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.First();
+ pStepBmp && bRet;
+ pStepBmp = (AnimationBitmap*) maList.Next() )
+ {
+ if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) == TRUE )
+ {
+ if( nMirrorFlags & BMP_MIRROR_HORZ )
+ pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
+
+ if( nMirrorFlags & BMP_MIRROR_VERT )
+ pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
+ }
+ }
+
+ maBitmapEx.Mirror( nMirrorFlags );
+ }
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Dither( nDitherFlags, pDitherPal );
+
+ maBitmapEx.Dither( nDitherFlags, pDitherPal );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ {
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert );
+ }
+
+ maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
+
+ maBitmapEx.Filter( eFilter, pFilterParam, pProgress );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Animation& rAnimation )
+{
+ const USHORT nCount = rAnimation.Count();
+
+ if( nCount )
+ {
+ const ByteString aDummyStr;
+ const UINT32 nDummy32 = 0UL;
+
+ // Falls keine BitmapEx gesetzt wurde, schreiben wir
+ // einfach die erste Bitmap der Animation
+ if( !rAnimation.GetBitmapEx().GetBitmap() )
+ rOStm << rAnimation.Get( 0 ).aBmpEx;
+ else
+ rOStm << rAnimation.GetBitmapEx();
+
+ // Kennung schreiben ( SDANIMA1 )
+ rOStm << (UINT32) 0x5344414e << (UINT32) 0x494d4931;
+
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
+ const UINT16 nRest = nCount - i - 1;
+
+ // AnimationBitmap schreiben
+ rOStm << rAnimBmp.aBmpEx;
+ rOStm << rAnimBmp.aPosPix;
+ rOStm << rAnimBmp.aSizePix;
+ rOStm << rAnimation.maGlobalSize;
+ rOStm << (UINT16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait );
+ rOStm << (UINT16) rAnimBmp.eDisposal;
+ rOStm << (BYTE) rAnimBmp.bUserInput;
+ rOStm << (UINT32) rAnimation.mnLoopCount;
+ rOStm << nDummy32; // unbenutzt
+ rOStm << nDummy32; // unbenutzt
+ rOStm << nDummy32; // unbenutzt
+ rOStm << aDummyStr; // unbenutzt
+ rOStm << nRest; // Anzahl der Strukturen, die noch _folgen_
+ }
+ }
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Animation& rAnimation )
+{
+ Bitmap aBmp;
+ ULONG nStmPos = rIStm.Tell();
+ UINT32 nAnimMagic1, nAnimMagic2;
+ USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bReadAnimations = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ nStmPos = rIStm.Tell();
+ rIStm >> nAnimMagic1 >> nAnimMagic2;
+
+ rAnimation.Clear();
+
+ // Wenn die BitmapEx am Anfang schon gelesen
+ // wurde ( von Graphic ), koennen wir direkt die Animationsbitmaps einlesen
+ if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
+ bReadAnimations = TRUE;
+ // ansonsten versuchen wir erstmal die Bitmap(-Ex) zu lesen
+ else
+ {
+ rIStm.Seek( nStmPos );
+ rIStm >> rAnimation.maBitmapEx;
+ nStmPos = rIStm.Tell();
+ rIStm >> nAnimMagic1 >> nAnimMagic2;
+
+ if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
+ bReadAnimations = TRUE;
+ else
+ rIStm.Seek( nStmPos );
+ }
+
+ // ggf. Animationsbitmaps lesen
+ if( bReadAnimations )
+ {
+ AnimationBitmap aAnimBmp;
+ BitmapEx aBmpEx;
+ ByteString aDummyStr;
+ Point aPoint;
+ Size aSize;
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ BYTE cTmp;
+
+ do
+ {
+ rIStm >> aAnimBmp.aBmpEx;
+ rIStm >> aAnimBmp.aPosPix;
+ rIStm >> aAnimBmp.aSizePix;
+ rIStm >> rAnimation.maGlobalSize;
+ rIStm >> nTmp16; aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
+ rIStm >> nTmp16; aAnimBmp.eDisposal = ( Disposal) nTmp16;
+ rIStm >> cTmp; aAnimBmp.bUserInput = (BOOL) cTmp;
+ rIStm >> nTmp32; rAnimation.mnLoopCount = (USHORT) nTmp32;
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> aDummyStr; // unbenutzt
+ rIStm >> nTmp16; // Rest zu lesen
+
+ rAnimation.Insert( aAnimBmp );
+ }
+ while( nTmp16 && !rIStm.GetError() );
+
+ rAnimation.ResetLoopCount();
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return rIStm;
+}
diff --git a/vcl/source/gdi/bitmap.cxx b/vcl/source/gdi/bitmap.cxx
new file mode 100644
index 000000000000..d5016647cfca
--- /dev/null
+++ b/vcl/source/gdi/bitmap.cxx
@@ -0,0 +1,1980 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BITMAP_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap() :
+ mpImpBmp( NULL )
+{
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const ResId& rResId ) :
+ mpImpBmp( NULL )
+{
+ ResMgr * pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
+
+ USHORT nBitmapType;
+ USHORT nBitmapId;
+ nBitmapType = pResMgr->ReadShort();
+ nBitmapId = pResMgr->ReadShort();
+
+ SvStream* pBmpStream = pResMgr->pImpRes->GetBitmapStream( nBitmapId );
+ if( pBmpStream )
+ *pBmpStream >> *this;
+ // pop filename
+ String aDummy = pResMgr->ReadString();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Bitmap& rBitmap ) :
+ maPrefMapMode ( rBitmap.maPrefMapMode ),
+ maPrefSize ( rBitmap.maPrefSize )
+{
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ if ( mpImpBmp )
+ mpImpBmp->ImplIncRefCount();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Size& rSizePixel, USHORT nBitCount, const BitmapPalette* pPal )
+{
+ if( rSizePixel.Width() && rSizePixel.Height() )
+ {
+ BitmapPalette aPal;
+ BitmapPalette* pRealPal = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ if( !pPal )
+ {
+ if( 1 == nBitCount )
+ {
+ aPal.SetEntryCount( 2 );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_WHITE );
+ }
+ else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
+ {
+ aPal.SetEntryCount( 1 << nBitCount );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_BLUE );
+ aPal[ 2 ] = Color( COL_GREEN );
+ aPal[ 3 ] = Color( COL_CYAN );
+ aPal[ 4 ] = Color( COL_RED );
+ aPal[ 5 ] = Color( COL_MAGENTA );
+ aPal[ 6 ] = Color( COL_BROWN );
+ aPal[ 7 ] = Color( COL_GRAY );
+ aPal[ 8 ] = Color( COL_LIGHTGRAY );
+ aPal[ 9 ] = Color( COL_LIGHTBLUE );
+ aPal[ 10 ] = Color( COL_LIGHTGREEN );
+ aPal[ 11 ] = Color( COL_LIGHTCYAN );
+ aPal[ 12 ] = Color( COL_LIGHTRED );
+ aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
+ aPal[ 14 ] = Color( COL_YELLOW );
+ aPal[ 15 ] = Color( COL_WHITE );
+
+ // Dither-Palette erzeugen
+ if( 8 == nBitCount )
+ {
+ USHORT nActCol = 16;
+
+ for( USHORT nB = 0; nB < 256; nB += 51 )
+ for( USHORT nG = 0; nG < 256; nG += 51 )
+ for( USHORT nR = 0; nR < 256; nR += 51 )
+ aPal[ nActCol++ ] = BitmapColor( (BYTE) nR, (BYTE) nG, (BYTE) nB );
+
+ // Standard-Office-Farbe setzen
+ aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
+ }
+ }
+ }
+ else
+ pRealPal = (BitmapPalette*) pPal;
+ }
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
+ }
+ else
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::~Bitmap()
+{
+ ImplReleaseRef();
+}
+
+// ------------------------------------------------------------------
+
+const BitmapPalette& Bitmap::GetGreyPalette( USHORT nEntries )
+{
+ static BitmapPalette aGreyPalette2;
+ static BitmapPalette aGreyPalette4;
+ static BitmapPalette aGreyPalette16;
+ static BitmapPalette aGreyPalette256;
+
+ // create greyscale palette with 2, 4, 16 or 256 entries
+ if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
+ {
+ if( 2 == nEntries )
+ {
+ if( !aGreyPalette2.GetEntryCount() )
+ {
+ aGreyPalette2.SetEntryCount( 2 );
+ aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette2;
+ }
+ else if( 4 == nEntries )
+ {
+ if( !aGreyPalette4.GetEntryCount() )
+ {
+ aGreyPalette4.SetEntryCount( 4 );
+ aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
+ aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
+ aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette4;
+ }
+ else if( 16 == nEntries )
+ {
+ if( !aGreyPalette16.GetEntryCount() )
+ {
+ BYTE cGrey = 0, cGreyInc = 17;
+
+ aGreyPalette16.SetEntryCount( 16 );
+
+ for( USHORT i = 0; i < 16; i++, cGrey += cGreyInc )
+ aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
+ }
+
+ return aGreyPalette16;
+ }
+ else
+ {
+ if( !aGreyPalette256.GetEntryCount() )
+ {
+ aGreyPalette256.SetEntryCount( 256 );
+
+ for( USHORT i = 0; i < 256; i++ )
+ aGreyPalette256[ i ] = BitmapColor( (BYTE) i, (BYTE) i, (BYTE) i );
+ }
+
+ return aGreyPalette256;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
+ return aGreyPalette2;
+ }
+}
+
+// ------------------------------------------------------------------
+
+Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
+{
+ maPrefSize = rBitmap.maPrefSize;
+ maPrefMapMode = rBitmap.maPrefMapMode;
+
+ if ( rBitmap.mpImpBmp )
+ rBitmap.mpImpBmp->ImplIncRefCount();
+
+ ImplReleaseRef();
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ return *this;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::IsEqual( const Bitmap& rBmp ) const
+{
+ return( IsSameInstance( rBmp ) ||
+ ( rBmp.GetSizePixel() == GetSizePixel() &&
+ rBmp.GetBitCount() == GetBitCount() &&
+ rBmp.GetChecksum() == GetChecksum() ) );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetEmpty()
+{
+ maPrefMapMode = MapMode();
+ maPrefSize = Size();
+
+ ImplReleaseRef();
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Size Bitmap::GetSizePixel() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetSizePixel( const Size& rNewSize )
+{
+ Scale( rNewSize );
+}
+
+// ------------------------------------------------------------------
+
+USHORT Bitmap::GetBitCount() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::HasGreyPalette() const
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ if( 1 == nBitCount )
+ bRet = TRUE;
+ else if( 4 == nBitCount || 8 == nBitCount )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) )
+ bRet = TRUE;
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+ULONG Bitmap::GetChecksum() const
+{
+ ULONG nRet = 0UL;
+
+ if( mpImpBmp )
+ {
+ nRet = mpImpBmp->ImplGetChecksum();
+
+ if( !nRet )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc && pRAcc->Width() && pRAcc->Height() )
+ {
+ sal_uInt32 nCrc = 0;
+ SVBT32 aBT32;
+
+ pRAcc->ImplZeroInitUnusedBits();
+
+ LongToSVBT32( pRAcc->Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetBitCount(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ if( pRAcc->HasPalette() )
+ {
+ nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
+ pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
+ }
+
+ nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+
+ mpImpBmp->ImplSetChecksum( nRet = nCrc );
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplReleaseRef()
+{
+ if( mpImpBmp )
+ {
+ if( mpImpBmp->ImplGetRefCount() > 1UL )
+ mpImpBmp->ImplDecRefCount();
+ else
+ {
+ delete mpImpBmp;
+ mpImpBmp = NULL;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplMakeUnique()
+{
+ if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
+ {
+ ImpBitmap* pOldImpBmp = mpImpBmp;
+
+ pOldImpBmp->ImplDecRefCount();
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( *pOldImpBmp );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
+{
+ const Size aOldSizePix( GetSizePixel() );
+ const Size aNewSizePix( rBitmap.GetSizePixel() );
+ const MapMode aOldMapMode( maPrefMapMode );
+ Size aNewPrefSize;
+
+ if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
+ {
+ aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
+ aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
+ }
+ else
+ aNewPrefSize = maPrefSize;
+
+ *this = rBitmap;
+
+ maPrefSize = aNewPrefSize;
+ maPrefMapMode = aOldMapMode;
+}
+
+// ------------------------------------------------------------------
+
+ImpBitmap* Bitmap::ImplGetImpBitmap() const
+{
+ return mpImpBmp;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
+{
+ if( pImpBmp != mpImpBmp )
+ {
+ ImplReleaseRef();
+ mpImpBmp = pImpBmp;
+ }
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess* Bitmap::AcquireReadAccess()
+{
+#ifdef REMOTE_APPSERVER
+ BOOL bGottenFromServer = FALSE;
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet(), bGottenFromServer = TRUE;
+#endif
+
+ BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
+
+ if( !*pReadAccess )
+ {
+ delete pReadAccess;
+ pReadAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pReadAccess && mpImpBmp && bGottenFromServer )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pReadAccess;
+}
+
+// ------------------------------------------------------------------
+
+BitmapWriteAccess* Bitmap::AcquireWriteAccess()
+{
+#ifdef REMOTE_APPSERVER
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet();
+#endif
+
+ BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
+
+ if( !*pWriteAccess )
+ {
+ delete pWriteAccess;
+ pWriteAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pWriteAccess && mpImpBmp )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pWriteAccess;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
+{
+ delete pBitmapAccess;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Erase( const Color& rFillColor )
+{
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ const ULONG nFormat = pWriteAcc->GetScanlineFormat();
+ BYTE cIndex;
+ BOOL bFast;
+
+ switch( nFormat )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_1BIT_LSB_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = ( cIndex ? 255 : 0 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_4BIT_LSN_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = cIndex | ( cIndex << 4 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_8BIT_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ {
+ if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
+ ( rFillColor.GetRed() == rFillColor.GetBlue() ) )
+ {
+ cIndex = rFillColor.GetRed();
+ bFast = TRUE;
+ }
+ else
+ bFast = FALSE;
+ }
+ break;
+
+ default:
+ bFast = FALSE;
+ break;
+ }
+
+ if( bFast )
+ {
+ const ULONG nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
+ HMEMSET( pWriteAcc->GetBuffer(), cIndex, nBufSize );
+ }
+ else
+ {
+ Point aTmpPoint;
+ const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
+ pWriteAcc->SetFillColor( rFillColor );
+ pWriteAcc->FillRect( aRect );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Invert()
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ if( pAcc->HasPalette() )
+ {
+ BitmapPalette aBmpPal( pAcc->GetPalette() );
+ const USHORT nCount = aBmpPal.GetEntryCount();
+
+ for( USHORT i = 0; i < nCount; i++ )
+ aBmpPal[ i ].Invert();
+
+ pAcc->SetPalette( aBmpPal );
+ }
+ else
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ for( long nY = 0L; nY < nHeight; nY++ )
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Mirror( ULONG nMirrorFlags )
+{
+ BOOL bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
+ BOOL bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
+ BOOL bRet = FALSE;
+
+ if( bHorz && !bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+ const long nWidth1 = nWidth - 1L;
+ const long nWidth_2 = nWidth >> 1L;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
+ pAcc->SetPixel( nY, nOther, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bVert && !bHorz )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nScanSize = pAcc->GetScanlineSize();
+ BYTE* pBuffer = new BYTE[ nScanSize ];
+ const long nHeight = pAcc->Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nHeight_2 = nHeight >> 1L;
+
+ for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
+ {
+ HMEMCPY( pBuffer, pAcc->GetScanline( nY ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
+ }
+
+ delete[] pBuffer;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bHorz && bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pAcc->Height();
+ long nHeight_2 = nHeight >> 1;
+
+ for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
+ {
+ for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
+ pAcc->SetPixel( nOtherY, nOtherX, aTemp );
+ }
+ }
+
+ // ggf. noch mittlere Zeile horizontal spiegeln
+ if( nHeight & 1 )
+ {
+ for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
+ pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
+ pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Rotate( long nAngle10, const Color& rFillColor )
+{
+ BOOL bRet = FALSE;
+
+ nAngle10 %= 3600L;
+ nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
+
+ if( !nAngle10 )
+ bRet = TRUE;
+ else if( 1800L == nAngle10 )
+ bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
+ else
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aRotatedBmp;
+
+ if( pReadAcc )
+ {
+ const Size aSizePix( GetSizePixel() );
+
+ if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
+ {
+ const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = aSizePix.Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = aSizePix.Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+
+ if( 900L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
+ for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
+ }
+ else if( 2700L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
+ for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+ else
+ {
+ Point aTmpPoint;
+ Rectangle aTmpRectangle( aTmpPoint, aSizePix );
+ Polygon aPoly( aTmpRectangle );
+ aPoly.Rotate( aTmpPoint, (USHORT) nAngle10 );
+
+ Rectangle aNewBound( aPoly.GetBoundRect() );
+ const Size aNewSizePix( aNewBound.GetSize() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
+ const double fCosAngle = cos( nAngle10 * F_PI1800 );
+ const double fSinAngle = sin( nAngle10 * F_PI1800 );
+ const double fXMin = aNewBound.Left();
+ const double fYMin = aNewBound.Top();
+ const long nWidth = aSizePix.Width();
+ const long nHeight = aSizePix.Height();
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+ long nX;
+ long nY;
+ long nRotX;
+ long nRotY;
+ long nSinY;
+ long nCosY;
+ long* pCosX = new long[ nNewWidth ];
+ long* pSinX = new long[ nNewWidth ];
+ long* pCosY = new long[ nNewHeight ];
+ long* pSinY = new long[ nNewHeight ];
+
+ for ( nX = 0; nX < nNewWidth; nX++ )
+ {
+ const double fTmp = ( fXMin + nX ) * 64.;
+
+ pCosX[ nX ] = FRound( fCosAngle * fTmp );
+ pSinX[ nX ] = FRound( fSinAngle * fTmp );
+ }
+
+ for ( nY = 0; nY < nNewHeight; nY++ )
+ {
+ const double fTmp = ( fYMin + nY ) * 64.;
+
+ pCosY[ nY ] = FRound( fCosAngle * fTmp );
+ pSinY[ nY ] = FRound( fSinAngle * fTmp );
+ }
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nSinY = pSinY[ nY ];
+ nCosY = pCosY[ nY ];
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
+ nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
+
+ if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
+ else
+ pWriteAcc->SetPixel( nY, nX, aFillColor );
+ }
+ }
+
+ delete[] pSinX;
+ delete[] pCosX;
+ delete[] pSinY;
+ delete[] pCosY;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+
+ ReleaseAccess( pReadAcc );
+ }
+
+ if( ( bRet = !!aRotatedBmp ) == TRUE )
+ ImplAssignWithSize( aRotatedBmp );
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Crop( const Rectangle& rRectPixel )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRect( rRectPixel );
+ BOOL bRet = FALSE;
+
+ aRect.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRect.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Point aTmpPoint;
+ const Rectangle aNewRect( aTmpPoint, aRect.GetSize() );
+ Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nOldX = aRect.Left();
+ const long nOldY = aRect.Top();
+ const long nNewWidth = aNewRect.GetWidth();
+ const long nNewHeight = aNewRect.GetHeight();
+
+ for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
+ for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CopyPixel( const Rectangle& rRectDst,
+ const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRectDst( rRectDst );
+ BOOL bRet = FALSE;
+
+ aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectDst.IsEmpty() )
+ {
+ if( pBmpSrc && ( *pBmpSrc != *this ) )
+ {
+ Bitmap* pSrc = (Bitmap*) pBmpSrc;
+ const Size aCopySizePix( pSrc->GetSizePixel() );
+ Rectangle aRectSrc( rRectSrc );
+ const USHORT nSrcBitCount = pBmpSrc->GetBitCount();
+ const USHORT nDstBitCount = GetBitCount();
+
+ if( nSrcBitCount > nDstBitCount )
+ {
+ long nNextIndex = 0L;
+
+ if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
+ Convert( BMP_CONVERSION_24BIT );
+ else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
+ {
+ Convert( BMP_CONVERSION_8BIT_COLORS );
+ nNextIndex = 16;
+ }
+ else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
+ {
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+ nNextIndex = 2;
+ }
+
+ if( nNextIndex )
+ {
+ BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess();
+ BitmapWriteAccess* pDstAcc = AcquireWriteAccess();
+
+ if( pSrcAcc && pDstAcc )
+ {
+ const long nSrcCount = pDstAcc->GetPaletteEntryCount();
+ const long nDstCount = 1 << nDstBitCount;
+ BOOL bFound;
+
+ for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
+ {
+ const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (USHORT) i );
+
+ bFound = FALSE;
+
+ for( long j = 0L; j < nDstCount; j++ )
+ {
+ if( rSrcCol == pDstAcc->GetPaletteColor( (USHORT) j ) )
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if( !bFound )
+ pDstAcc->SetPaletteColor( (USHORT) nNextIndex++, rSrcCol );
+ }
+ }
+
+ if( pSrcAcc )
+ pSrc->ReleaseAccess( pSrcAcc );
+
+ if( pDstAcc )
+ ReleaseAccess( pDstAcc );
+ }
+ }
+
+ aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
+
+ if( !aRectSrc.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcEndX = aRectSrc.Left() + nWidth;
+ const long nSrcEndY = aRectSrc.Top() + nHeight;
+ long nDstY = aRectDst.Top();
+
+ if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
+ {
+ const USHORT nCount = pReadAcc->GetPaletteEntryCount();
+ BYTE* pMap = new BYTE[ nCount ];
+
+ // Index-Map fuer Farbtabelle
+ // aufbauen, da das Bild ja (relativ) farbgenau
+ // kopiert werden soll
+ for( USHORT i = 0; i < nCount; i++ )
+ pMap[ i ] = (BYTE) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
+
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
+
+ delete[] pMap;
+ }
+ else if( pReadAcc->HasPalette() )
+ {
+ }
+ else
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
+
+ ReleaseAccess( pWriteAcc );
+ bRet = ( nWidth > 0L ) && ( nHeight > 0L );
+ }
+
+ pSrc->ReleaseAccess( pReadAcc );
+ }
+ }
+ }
+ else
+ {
+ Rectangle aRectSrc( rRectSrc );
+
+ aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcX = aRectSrc.Left();
+ const long nSrcY = aRectSrc.Top();
+ const long nSrcEndX1 = nSrcX + nWidth - 1L;
+ const long nSrcEndY1 = nSrcY + nHeight - 1L;
+ const long nDstX = aRectDst.Left();
+ const long nDstY = aRectDst.Top();
+ const long nDstEndX1 = nDstX + nWidth - 1L;
+ const long nDstEndY1 = nDstY + nHeight - 1L;
+
+ if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Expand( ULONG nDX, ULONG nDY, const Color* pInitColor )
+{
+ BOOL bRet = FALSE;
+
+ if( nDX || nDY )
+ {
+ const Size aSizePixel( GetSizePixel() );
+ const long nWidth = aSizePixel.Width();
+ const long nHeight = aSizePixel.Height();
+ const Size aNewSize( nWidth + nDX, nHeight + nDY );
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+// Was soll den das ?
+// BitmapPalette aBmpPal( pReadAcc ? pReadAcc->GetPalette() : BitmapPalette() );
+ BitmapPalette aBmpPal( pReadAcc->GetPalette() );
+ Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aColor;
+ const ULONG nScanlineSize = pReadAcc->GetScanlineSize();
+ const long nNewX = nWidth;
+ const long nNewY = nHeight;
+ const long nNewWidth = pWriteAcc->Width();
+ const long nNewHeight = pWriteAcc->Height();
+ long nX;
+ long nY;
+
+ if( pInitColor )
+ aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
+
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ pWriteAcc->CopyScanline( nY, *pReadAcc );
+
+ if( pInitColor && nDX )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+ }
+
+ if( pInitColor && nDY )
+ for( nY = nNewY; nY < nNewHeight; nY++ )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateMask( const Color& rTransColor, ULONG nTol ) const
+{
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ const long nWidth = pReadAcc->Width();
+ const long nHeight = pReadAcc->Height();
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ if( !nTol )
+ {
+ const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
+ long nX, nY, nShift;
+
+ if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
+ pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
+ {
+ // optimized for 4Bit-MSN/LSN source palette
+ const BYTE cTest = aTest.GetIndex();
+ const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ // optimized for 8Bit source palette
+ const BYTE cTest = aTest.GetIndex();
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ // not optimized
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( aTest == pReadAcc->GetPixel( nY, nX ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ long nR, nG, nB;
+ const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPixel( nY, nX );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ bRet = TRUE;
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ if( bRet )
+ {
+ aNewBmp.maPrefSize = maPrefSize;
+ aNewBmp.maPrefMapMode = maPrefMapMode;
+ }
+ else
+ aNewBmp = Bitmap();
+
+ return aNewBmp;
+}
+
+// ------------------------------------------------------------------
+
+Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
+{
+ Region aRegion;
+ Rectangle aRect( rRect );
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
+ aRect.Justify();
+
+ if( pReadAcc )
+ {
+ Rectangle aSubRect;
+ const long nLeft = aRect.Left();
+ const long nTop = aRect.Top();
+ const long nRight = aRect.Right();
+ const long nBottom = aRect.Bottom();
+ const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
+
+ aRegion.ImplBeginAddRect();
+
+ for( long nY = nTop; nY <= nBottom; nY++ )
+ {
+ aSubRect.Top() = aSubRect.Bottom() = nY;
+
+ for( long nX = nLeft; nX <= nRight; )
+ {
+ while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ if( nX <= nRight )
+ {
+ aSubRect.Left() = nX;
+
+ while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ aSubRect.Right() = nX - 1L;
+ aRegion.ImplAddRect( aSubRect );
+ }
+ }
+ }
+
+ aRegion.ImplEndAddRect();
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ }
+ else
+ aRegion = aRect;
+
+ return aRegion;
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BITMAP_SEG1
+#endif
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ BitmapColor aReplace;
+
+ if( pAcc->HasPalette() )
+ {
+ const USHORT nActColors = pAcc->GetPaletteEntryCount();
+ const USHORT nMaxColors = 1 << pAcc->GetBitCount();
+
+ // erst einmal naechste Farbe nehmen
+ aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
+
+ // falls Palettenbild, und die zu setzende Farbe ist nicht
+ // in der Palette, suchen wir nach freien Eintraegen (teuer)
+ if( pAcc->GetPaletteColor( (BYTE) aReplace ) != BitmapColor( rReplaceColor ) )
+ {
+ // erst einmal nachsehen, ob wir unsere ReplaceColor
+ // nicht auf einen freien Platz am Ende der Palette
+ // setzen koennen
+ if( nActColors < nMaxColors )
+ {
+ pAcc->SetPaletteEntryCount( nActColors + 1 );
+ pAcc->SetPaletteColor( nActColors, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) nActColors );
+ }
+ else
+ {
+ BOOL* pFlags = new BOOL[ nMaxColors ];
+
+ // alle Eintraege auf 0 setzen
+ memset( pFlags, 0, nMaxColors );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFlags[ (BYTE) pAcc->GetPixel( nY, nX ) ] = TRUE;
+
+ for( USHORT i = 0UL; i < nMaxColors; i++ )
+ {
+ // Hurra, wir haben einen unbenutzten Eintrag
+ if( !pFlags[ i ] )
+ {
+ pAcc->SetPaletteColor( (USHORT) i, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) i );
+ }
+ }
+
+ delete[] pFlags;
+ }
+ }
+ }
+ else
+ aReplace = rReplaceColor;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
+{
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapReadAccess* pAcc = AcquireReadAccess();
+ BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc && pAlphaAcc && pNewAcc )
+ {
+ BitmapColor aCol;
+ const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetColor( nY, nX );
+ pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (BYTE) pAlphaAcc->GetPixel( nY, nX ) ) );
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pAcc );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
+ aNewBmp.ReleaseAccess( pNewAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+
+ if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
+ nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
+ nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( i, rReplaceColor );
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
+ nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
+ nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+ }
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
+ ULONG nColorCount, ULONG* _pTols )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ long* pMinR = new long[ nColorCount ];
+ long* pMaxR = new long[ nColorCount ];
+ long* pMinG = new long[ nColorCount ];
+ long* pMaxG = new long[ nColorCount ];
+ long* pMinB = new long[ nColorCount ];
+ long* pMaxB = new long[ nColorCount ];
+ long* pTols;
+ ULONG i;
+
+ if( !_pTols )
+ {
+ pTols = new long[ nColorCount ];
+ memset( pTols, 0, nColorCount * sizeof( long ) );
+ }
+ else
+ pTols = (long*) _pTols;
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ const Color& rCol = pSearchColors[ i ];
+ const long nTol = pTols[ i ];
+
+ pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
+ pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
+ pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
+ pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
+ pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
+ pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
+ pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
+ pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( (USHORT)nEntry, pReplaceColors[ i ] );
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ BitmapColor* pReplaces = new BitmapColor[ nColorCount ];
+
+ for( i = 0UL; i < nColorCount; i++ )
+ pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
+ pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
+ pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, pReplaces[ i ] );
+ break;
+ }
+ }
+ }
+ }
+
+ delete[] pReplaces;
+ }
+
+ if( !_pTols )
+ delete[] pTols;
+
+ delete[] pMinR;
+ delete[] pMaxR;
+ delete[] pMinG;
+ delete[] pMaxG;
+ delete[] pMinB;
+ delete[] pMaxB;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
+{
+ Bitmap aDispBmp( *this );
+
+#ifndef REMOTE_APPSERVER
+ if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
+ {
+ ImpBitmap* pImpDispBmp = new ImpBitmap;
+
+ if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
+ aDispBmp.ImplSetImpBitmap( pImpDispBmp );
+ else
+ delete pImpDispBmp;
+ }
+#endif
+
+ return aDispBmp;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const Color aColBlack( COL_BLACK );
+ BitmapColor aPixel;
+ BitmapColor aMaskPixel;
+ const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
+ const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
+
+ switch( eCombine )
+ {
+ case( BMP_COMBINE_COPY ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_INVERT ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ) == aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_AND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NAND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_OR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_XOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NXOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+ }
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+void Bitmap::ImplDrawRemote( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmp( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteEx( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Bitmap& rMask ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rMask );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteAlpha( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const AlphaMask& rAlpha ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rAlpha );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteMask( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Color& rColor ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpMask( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplGetRemoteBmp( OutputDevice* pOut, const Point& rPt, const Size& rSz )
+{
+ DBG_ASSERT( !mpImpBmp, "Bitmap::ImplGetRemoteBmp???" );
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreateRemoteBmp( *this, pOut, rPt, rSz );
+}
+
+#endif
diff --git a/vcl/source/gdi/bitmap2.cxx b/vcl/source/gdi/bitmap2.cxx
new file mode 100644
index 000000000000..e4e4c407fc18
--- /dev/null
+++ b/vcl/source/gdi/bitmap2.cxx
@@ -0,0 +1,1269 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef WIN
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#define _SV_BITMAP_CXX
+
+#include <tools/zcodec.hxx>
+#ifndef _TOOLS_NEW_HXX
+#include <tools/new.hxx>
+#endif
+#ifndef _TOOLS_STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+#define USE_ZCODEC
+
+// -----------
+// - Defines -
+// -----------
+
+#define DIBCOREHEADERSIZE ( 12UL )
+#define DIBINFOHEADERSIZE ( sizeof( DIBInfoHeader ) )
+#define SETPIXEL4( pBuf, nX, cChar )( (pBuf)[ (nX) >> 1 ] |= ( (nX) & 1 ) ? ( cChar ): (cChar) << 4 );
+
+// ----------------------
+// - Compression defines
+// ----------------------
+
+#define COMPRESS_OWN ('S'|('D'<<8UL))
+#define COMPRESS_NONE ( 0UL )
+#define RLE_8 ( 1UL )
+#define RLE_4 ( 2UL )
+#define BITFIELDS ( 3UL )
+#define ZCOMPRESS ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
+
+// -----------------
+// - DIBInfoHeader -
+// -----------------
+
+struct DIBInfoHeader
+{
+ UINT32 nSize;
+ UINT32 nWidth;
+ UINT32 nHeight;
+ UINT16 nPlanes;
+ UINT16 nBitCount;
+ UINT32 nCompression;
+ UINT32 nSizeImage;
+ UINT32 nXPelsPerMeter;
+ UINT32 nYPelsPerMeter;
+ UINT32 nColsUsed;
+ UINT32 nColsImportant;
+
+ DIBInfoHeader() :
+ nSize( 0UL ),
+ nWidth( 0UL ),
+ nHeight( 0UL ),
+ nPlanes( 0 ),
+ nBitCount( 0 ),
+ nCompression( 0UL ),
+ nSizeImage( 0UL ),
+ nXPelsPerMeter( 0UL ),
+ nYPelsPerMeter( 0UL ),
+ nColsUsed( 0UL ),
+ nColsImportant( 0UL ) {}
+
+ ~DIBInfoHeader() {}
+};
+
+// ----------
+// - Bitmap -
+// ----------
+
+SvStream& operator>>( SvStream& rIStm, Bitmap& rBitmap )
+{
+ rBitmap.Read( rIStm, TRUE );
+ return rIStm;
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Bitmap& rBitmap )
+{
+ rBitmap.Write( rOStm, FALSE, TRUE );
+ return rOStm;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Read( SvStream& rIStm, BOOL bFileHeader )
+{
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ const ULONG nOldPos = rIStm.Tell();
+ ULONG nOffset = 0UL;
+ BOOL bRet = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( bFileHeader )
+ {
+ if( ImplReadDIBFileHeader( rIStm, nOffset ) )
+ bRet = ImplReadDIB( rIStm, *this, nOffset );
+ }
+ else
+ bRet = ImplReadDIB( rIStm, *this, nOffset );
+
+ if( !bRet )
+ {
+ if( !rIStm.GetError() )
+ rIStm.SetError( SVSTREAM_GENERALERROR );
+
+ rIStm.Seek( nOldPos );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIB( SvStream& rIStm, Bitmap& rBmp, ULONG nOffset )
+{
+ DIBInfoHeader aHeader;
+ const ULONG nStmPos = rIStm.Tell();
+ BitmapPalette* pPalette = NULL;
+ BOOL bHeaderRead = FALSE;
+ BOOL bRet = FALSE;
+
+ if( ImplReadDIBInfoHeader( rIStm, aHeader ) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount )
+ {
+ USHORT nBitCount = ( aHeader.nBitCount <= 1 ) ? 1 :
+ ( aHeader.nBitCount <= 4 ) ? 4 :
+ ( aHeader.nBitCount <= 8 ) ? 8 : 24;
+
+ const Size aSizePixel( aHeader.nWidth, aHeader.nHeight );
+ BitmapPalette aDummyPal;
+ Bitmap aNewBmp( aSizePixel, nBitCount, &aDummyPal );
+ BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ USHORT nColors;
+ SvStream* pIStm;
+ SvMemoryStream* pMemStm = NULL;
+ BYTE* pData = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ if( aHeader.nColsUsed )
+ nColors = (USHORT) aHeader.nColsUsed;
+ else
+ nColors = ( 1 << aHeader.nBitCount );
+ }
+ else
+ nColors = 0;
+
+#ifdef USE_ZCODEC
+ if( ZCOMPRESS == aHeader.nCompression )
+ {
+ ZCodec aCodec;
+ ULONG nCodedSize, nUncodedSize;
+ ULONG nCodedPos;
+
+ // read coding information
+ rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
+ pData = (BYTE*) SvMemAlloc( nUncodedSize );
+
+ // decode buffer
+ nCodedPos = rIStm.Tell();
+ aCodec.BeginCompression();
+ aCodec.Read( rIStm, pData, nUncodedSize );
+ aCodec.EndCompression();
+
+ // skip unread bytes from coded buffer
+ rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
+
+ // set decoded bytes to memory stream,
+ // from which we will read the bitmap data
+ pIStm = pMemStm = new SvMemoryStream;
+ pMemStm->SetBuffer( (char*) pData, nUncodedSize, FALSE, nUncodedSize );
+ nOffset = 0;
+ }
+ else
+#endif // USE_ZCODEC
+ pIStm = &rIStm;
+
+ // read palette
+ if( nColors )
+ {
+ pAcc->SetPaletteEntryCount( nColors );
+ ImplReadDIBPalette( *pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE );
+ }
+
+ // read bits
+ if( !pIStm->GetError() )
+ {
+ if( nOffset )
+ pIStm->SeekRel( nOffset - ( pIStm->Tell() - nStmPos ) );
+
+ bRet = ImplReadDIBBits( *pIStm, aHeader, *pAcc );
+
+ if( bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter )
+ {
+ MapMode aMapMode( MAP_MM, Point(),
+ Fraction( 1000, aHeader.nXPelsPerMeter ),
+ Fraction( 1000, aHeader.nYPelsPerMeter ) );
+
+ aNewBmp.SetPrefMapMode( aMapMode );
+ aNewBmp.SetPrefSize( Size( aHeader.nWidth, aHeader.nHeight ) );
+ }
+ }
+
+ if( pData )
+ SvMemFree( pData );
+
+ delete pMemStm;
+ aNewBmp.ReleaseAccess( pAcc );
+
+ if( bRet )
+ rBmp = aNewBmp;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBFileHeader( SvStream& rIStm, ULONG& rOffset )
+{
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ BOOL bRet = FALSE;
+
+ rIStm >> nTmp16;
+
+ if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
+ {
+ if ( 0x4142 == nTmp16 )
+ {
+ rIStm.SeekRel( 12L );
+ rIStm >> nTmp16;
+ rIStm.SeekRel( 8L );
+ rIStm >> nTmp32;
+ rOffset = nTmp32 - 28UL;;
+ bRet = ( 0x4D42 == nTmp16 );
+ }
+ else
+ {
+ rIStm.SeekRel( 8L );
+ rIStm >> nTmp32;
+ rOffset = nTmp32 - 14UL;
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ }
+ else
+ rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBInfoHeader( SvStream& rIStm, DIBInfoHeader& rHeader )
+{
+ // BITMAPINFOHEADER or BITMAPCOREHEADER
+ rIStm >> rHeader.nSize;
+
+ // BITMAPCOREHEADER
+ if ( rHeader.nSize == DIBCOREHEADERSIZE )
+ {
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rHeader.nWidth = nTmp16;
+ rIStm >> nTmp16; rHeader.nHeight = nTmp16;
+ rIStm >> nTmp16; rHeader.nPlanes = nTmp16;
+ rIStm >> nTmp16; rHeader.nBitCount = nTmp16;
+ }
+ else
+ {
+ // unknown Header
+ if( rHeader.nSize < DIBINFOHEADERSIZE )
+ {
+ ULONG nUnknownSize = sizeof( rHeader.nSize );
+
+ rIStm >> rHeader.nWidth; nUnknownSize += sizeof( rHeader.nWidth );
+ rIStm >> rHeader.nHeight; nUnknownSize += sizeof( rHeader.nHeight );
+ rIStm >> rHeader.nPlanes; nUnknownSize += sizeof( rHeader.nPlanes );
+ rIStm >> rHeader.nBitCount; nUnknownSize += sizeof( rHeader.nBitCount );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nCompression;
+ nUnknownSize += sizeof( rHeader.nCompression );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nSizeImage;
+ nUnknownSize += sizeof( rHeader.nSizeImage );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nXPelsPerMeter;
+ nUnknownSize += sizeof( rHeader.nXPelsPerMeter );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nYPelsPerMeter;
+ nUnknownSize += sizeof( rHeader.nYPelsPerMeter );
+ }
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nColsUsed;
+ nUnknownSize += sizeof( rHeader.nColsUsed );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nColsImportant;
+ nUnknownSize += sizeof( rHeader.nColsImportant );
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ rIStm >> rHeader.nWidth;
+ rIStm >> rHeader.nHeight;
+ rIStm >> rHeader.nPlanes;
+ rIStm >> rHeader.nBitCount;
+ rIStm >> rHeader.nCompression;
+ rIStm >> rHeader.nSizeImage;
+ rIStm >> rHeader.nXPelsPerMeter;
+ rIStm >> rHeader.nYPelsPerMeter;
+ rIStm >> rHeader.nColsUsed;
+ rIStm >> rHeader.nColsImportant;
+ }
+
+ // Eventuell bis zur Palette ueberlesen
+ if ( rHeader.nSize > DIBINFOHEADERSIZE )
+ rIStm.SeekRel( rHeader.nSize - DIBINFOHEADERSIZE );
+ }
+
+ return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, BOOL bQuad )
+{
+ const USHORT nColors = rAcc.GetPaletteEntryCount();
+ const ULONG nPalSize = nColors * ( bQuad ? 4UL : 3UL );
+ BitmapColor aPalColor;
+
+ BYTE* pEntries = new BYTE[ nPalSize ];
+ rIStm.Read( pEntries, nPalSize );
+
+ BYTE* pTmpEntry = pEntries;
+ for( USHORT i = 0; i < nColors; i++ )
+ {
+ aPalColor.SetBlue( *pTmpEntry++ );
+ aPalColor.SetGreen( *pTmpEntry++ );
+ aPalColor.SetRed( *pTmpEntry++ );
+
+ if( bQuad )
+ pTmpEntry++;
+
+ rAcc.SetPaletteColor( i, aPalColor );
+ }
+
+ delete[] pEntries;
+
+ return( rIStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBBits( SvStream& rIStm, DIBInfoHeader& rHeader, BitmapWriteAccess& rAcc )
+{
+ const ULONG nAlignedWidth = AlignedWidth4Bytes( rHeader.nWidth * rHeader.nBitCount );
+ UINT32 nRMask;
+ UINT32 nGMask;
+ UINT32 nBMask;
+ BOOL bNative;
+ BOOL bTCMask = ( rHeader.nBitCount == 16 ) || ( rHeader.nBitCount == 32 );
+ BOOL bRLE = ( RLE_8 == rHeader.nCompression && rHeader.nBitCount == 8 ) ||
+ ( RLE_4 == rHeader.nCompression && rHeader.nBitCount == 4 );
+
+ // Is native format?
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ bNative = ( rAcc.IsBottomUp() && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
+ break;
+
+ default:
+ bNative = FALSE;
+ break;
+ }
+
+ // Read data
+ if( bNative )
+ {
+ // true color DIB's can have a (optimization) palette
+ if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
+ rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
+
+ rIStm.Read( rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth );
+ }
+ else
+ {
+ // Read color mask
+ if( bTCMask )
+ {
+ if( rHeader.nCompression == BITFIELDS )
+ {
+ rIStm.SeekRel( -12L );
+ rIStm >> nRMask;
+ rIStm >> nGMask;
+ rIStm >> nBMask;
+ }
+ else
+ {
+ nRMask = ( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL;
+ nGMask = ( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL;
+ nBMask = ( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL;
+ }
+ }
+
+ if( bRLE )
+ {
+ if ( !rHeader.nSizeImage )
+ {
+ const ULONG nOldPos = rIStm.Tell();
+
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ rHeader.nSizeImage = rIStm.Tell() - nOldPos;
+ rIStm.Seek( nOldPos );
+ }
+
+ BYTE* pBuffer = (BYTE*) SvMemAlloc( rHeader.nSizeImage );
+
+ rIStm.Read( (char*) pBuffer, rHeader.nSizeImage );
+ ImplDecodeRLE( pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression );
+
+ SvMemFree( pBuffer );
+ }
+ else
+ {
+ const long nWidth = rHeader.nWidth;
+ const long nHeight = rHeader.nHeight;
+ BYTE* pBuf = new BYTE[ nAlignedWidth ];
+
+ // true color DIB's can have a (optimization) palette
+ if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
+ rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
+
+ switch( rHeader.nBitCount )
+ {
+ case( 1 ):
+ {
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+ cTmp = *pTmp++;
+
+ for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 8L,
+ cTmp = *pTmp++;
+ }
+
+ rAcc.SetPixel( nY, nX, ( cTmp >> --nShift ) & 1 );
+ }
+ }
+ }
+ break;
+
+ case( 4 ):
+ {
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+ cTmp = *pTmp++;
+
+ for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 2UL,
+ cTmp = *pTmp++;
+ }
+
+ rAcc.SetPixel( nY, nX, ( cTmp >> ( --nShift << 2UL ) ) & 0x0f );
+ }
+ }
+ }
+ break;
+
+ case( 8 ):
+ {
+ BYTE* pTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ rAcc.SetPixel( nY, nX, *pTmp++ );
+ }
+ }
+ break;
+
+ case( 16 ):
+ {
+ ColorMask aMask( nRMask, nGMask, nBMask );
+ BitmapColor aColor;
+ UINT16* pTmp16;
+
+ for( long nY = rHeader.nHeight - 1L; nY >= 0L; nY-- )
+ {
+ rIStm.Read( (char*)( pTmp16 = (UINT16*) pBuf ), nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aMask.GetColorFor16Bit( aColor, (BYTE*) pTmp16++ );
+ rAcc.SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ break;
+
+ case( 24 ):
+ {
+ BitmapColor aPixelColor;
+ BYTE* pTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixelColor.SetBlue( *pTmp++ );
+ aPixelColor.SetGreen( *pTmp++ );
+ aPixelColor.SetRed( *pTmp++ );
+ rAcc.SetPixel( nY, nX, aPixelColor );
+ }
+ }
+ }
+ break;
+
+ case( 32 ):
+ {
+ ColorMask aMask( nRMask, nGMask, nBMask );
+ BitmapColor aColor;
+ UINT32* pTmp32;
+
+ for( long nY = rHeader.nHeight - 1L; nY >= 0L; nY-- )
+ {
+ rIStm.Read( (char*)( pTmp32 = (UINT32*) pBuf ), nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aMask.GetColorFor32Bit( aColor, (BYTE*) pTmp32++ );
+ rAcc.SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ }
+
+ delete[] pBuf;
+ }
+ }
+
+ return( rIStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Write( SvStream& rOStm, BOOL bCompressed, BOOL bFileHeader ) const
+{
+ BMP_ASSERT( mpImpBmp, "Empty Bitmaps can't be saved" );
+
+ const Size aSizePix( GetSizePixel() );
+ BOOL bRet = FALSE;
+
+ if( mpImpBmp && aSizePix.Width() && aSizePix.Height() )
+ {
+ BitmapReadAccess* pAcc = ( (Bitmap*) this)->AcquireReadAccess();
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ const ULONG nOldPos = rOStm.Tell();
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( pAcc )
+ {
+ if( bFileHeader )
+ {
+ if( ImplWriteDIBFileHeader( rOStm, *pAcc ) )
+ bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
+ }
+ else
+ bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
+
+ ( (Bitmap*) this)->ReleaseAccess( pAcc );
+ }
+
+ if( !bRet )
+ {
+ rOStm.SetError( SVSTREAM_GENERALERROR );
+ rOStm.Seek( nOldPos );
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIB( SvStream& rOStm, BitmapReadAccess& rAcc, BOOL bCompressed ) const
+{
+ DIBInfoHeader aHeader;
+ ULONG nImageSizePos;
+ ULONG nEndPos;
+ ULONG nCompression = 0UL;
+ BOOL bRet = FALSE;
+
+ aHeader.nSize = DIBINFOHEADERSIZE;
+ aHeader.nWidth = rAcc.Width();
+ aHeader.nHeight = rAcc.Height();
+ aHeader.nPlanes = 1;
+
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_16BIT_TC_MASK ):
+ case( BMP_FORMAT_32BIT_TC_MASK ):
+ {
+ aHeader.nBitCount = ( rAcc.GetScanlineFormat() == BMP_FORMAT_16BIT_TC_MASK ) ? 16 : 32;
+ nCompression = BITFIELDS;
+ }
+ break;
+
+ default:
+ {
+ aHeader.nBitCount = rAcc.GetBitCount();
+
+ if( bCompressed )
+ {
+ if( 4 == aHeader.nBitCount )
+ nCompression = RLE_4;
+ else if( 8 == aHeader.nBitCount )
+ nCompression = RLE_8;
+ }
+ else
+ nCompression = COMPRESS_NONE;
+ }
+ break;
+ }
+
+#ifdef USE_ZCODEC
+ if( ( rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP ) &&
+ ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40 ) )
+ {
+ aHeader.nCompression = ZCOMPRESS;
+ }
+ else
+#endif // USE_ZCODEC
+ aHeader.nCompression = nCompression;
+
+ aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
+
+ if( maPrefSize.Width() && maPrefSize.Height() )
+ {
+ const Size aSize100( OutputDevice::LogicToLogic( maPrefSize, maPrefMapMode, MAP_100TH_MM ) );
+
+ if( aSize100.Width() && aSize100.Height() )
+ {
+ aHeader.nXPelsPerMeter = ( rAcc.Width() * 100000UL ) / aSize100.Width();
+ aHeader.nYPelsPerMeter = ( rAcc.Height() * 100000UL ) / aSize100.Height();
+ }
+ }
+
+ aHeader.nColsUsed = ( ( aHeader.nBitCount <= 8 ) ? rAcc.GetPaletteEntryCount() : 0 );
+ aHeader.nColsImportant = 0;
+
+ rOStm << aHeader.nSize;
+ rOStm << aHeader.nWidth;
+ rOStm << aHeader.nHeight;
+ rOStm << aHeader.nPlanes;
+ rOStm << aHeader.nBitCount;
+ rOStm << aHeader.nCompression;
+
+ nImageSizePos = rOStm.Tell();
+ rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
+
+ rOStm << aHeader.nXPelsPerMeter;
+ rOStm << aHeader.nYPelsPerMeter;
+ rOStm << aHeader.nColsUsed;
+ rOStm << aHeader.nColsImportant;
+
+#ifdef USE_ZCODEC
+ if( aHeader.nCompression == ZCOMPRESS )
+ {
+ ZCodec aCodec;
+ SvMemoryStream aMemStm( aHeader.nSizeImage + 4096, 65535 );
+ ULONG nCodedPos = rOStm.Tell(), nLastPos;
+ ULONG nCodedSize, nUncodedSize;
+
+ // write uncoded data palette
+ if( aHeader.nColsUsed )
+ ImplWriteDIBPalette( aMemStm, rAcc );
+
+ // write uncoded bits
+ bRet = ImplWriteDIBBits( aMemStm, rAcc, nCompression, aHeader.nSizeImage );
+
+ // get uncoded size
+ nUncodedSize = aMemStm.Tell();
+
+ // seek over compress info
+ rOStm.SeekRel( 12 );
+
+ // write compressed data
+ aCodec.BeginCompression( 3 );
+ aCodec.Write( rOStm, (BYTE*) aMemStm.GetData(), nUncodedSize );
+ aCodec.EndCompression();
+
+ // update compress info ( coded size, uncoded size, uncoded compression )
+ nCodedSize = ( nLastPos = rOStm.Tell() ) - nCodedPos - 12;
+ rOStm.Seek( nCodedPos );
+ rOStm << nCodedSize << nUncodedSize << nCompression;
+ rOStm.Seek( nLastPos );
+
+ if( bRet )
+ bRet = ( rOStm.GetError() == ERRCODE_NONE );
+ }
+ else
+#endif // USE_ZCODEC
+ {
+ if( aHeader.nColsUsed )
+ ImplWriteDIBPalette( rOStm, rAcc );
+
+ bRet = ImplWriteDIBBits( rOStm, rAcc, aHeader.nCompression, aHeader.nSizeImage );
+ }
+
+ nEndPos = rOStm.Tell();
+ rOStm.Seek( nImageSizePos );
+ rOStm << aHeader.nSizeImage;
+ rOStm.Seek( nEndPos );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBFileHeader( SvStream& rOStm, BitmapReadAccess& rAcc )
+{
+ UINT32 nPalCount = ( rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : rAcc.HasColorMask() ? 3UL : 0UL );
+ UINT32 nOffset = 14 + DIBINFOHEADERSIZE + nPalCount * 4UL;
+
+ rOStm << (UINT16) 0x4D42;
+ rOStm << (UINT32) ( nOffset + ( rAcc.Height() * rAcc.GetScanlineSize() ) );
+ rOStm << (UINT16) 0;
+ rOStm << (UINT16) 0;
+ rOStm << nOffset;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
+{
+ const USHORT nColors = rAcc.GetPaletteEntryCount();
+ const ULONG nPalSize = nColors * 4UL;
+ BYTE* pEntries = new BYTE[ nPalSize ];
+ BYTE* pTmpEntry = pEntries;
+ BitmapColor aPalColor;
+
+ for( USHORT i = 0; i < nColors; i++ )
+ {
+ const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
+
+ *pTmpEntry++ = rPalColor.GetBlue();
+ *pTmpEntry++ = rPalColor.GetGreen();
+ *pTmpEntry++ = rPalColor.GetRed();
+ *pTmpEntry++ = 0;
+ }
+
+ rOStm.Write( pEntries, nPalSize );
+ delete[] pEntries;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBBits( SvStream& rOStm, BitmapReadAccess& rAcc,
+ ULONG nCompression, ULONG& rImageSize )
+{
+ if( BITFIELDS == nCompression )
+ {
+ const ColorMask& rMask = rAcc.GetColorMask();
+ SVBT32 aVal32;
+
+ LongToSVBT32( rMask.GetRedMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ LongToSVBT32( rMask.GetGreenMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ LongToSVBT32( rMask.GetBlueMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ rImageSize = rOStm.Tell();
+
+ if( rAcc.IsBottomUp() )
+ rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
+ else
+ {
+ for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
+ rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
+ }
+ }
+ else if( ( RLE_4 == nCompression ) || ( RLE_8 == nCompression ) )
+ {
+ rImageSize = rOStm.Tell();
+ ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
+ }
+ else if( !nCompression )
+ {
+ const ULONG nAlignedWidth = AlignedWidth4Bytes( rAcc.Width() * rAcc.GetBitCount() );
+ BOOL bNative = FALSE;
+
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ {
+ if( rAcc.IsBottomUp() && ( rAcc.GetScanlineSize() == nAlignedWidth ) )
+ bNative = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ rImageSize = rOStm.Tell();
+
+ if( bNative )
+ rOStm.Write( rAcc.GetBuffer(), nAlignedWidth * rAcc.Height() );
+ else
+ {
+ const long nWidth = rAcc.Width();
+ const long nHeight = rAcc.Height();
+ BYTE* pBuf = new BYTE[ nAlignedWidth ];
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ switch( rAcc.GetBitCount() )
+ {
+ case( 1 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ cTmp = 0;
+
+ for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 8L;
+ *pTmp++ = cTmp;
+ cTmp = 0;
+ }
+
+ cTmp |= ( (BYTE) rAcc.GetPixel( nY, nX ) << --nShift );
+ }
+
+ *pTmp = cTmp;
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ case( 4 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ cTmp = 0;
+
+ for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 2L;
+ *pTmp++ = cTmp;
+ cTmp = 0;
+ }
+
+ cTmp |= ( (BYTE) rAcc.GetPixel( nY, nX ) << ( --nShift << 2L ) );
+ }
+ *pTmp = cTmp;
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ case( 8 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ *pTmp++ = rAcc.GetPixel( nY, nX );
+
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ default:
+ {
+ BitmapColor aPixelColor;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixelColor = rAcc.GetPixel( nY, nX );
+ *pTmp++ = aPixelColor.GetBlue();
+ *pTmp++ = aPixelColor.GetGreen();
+ *pTmp++ = aPixelColor.GetRed();
+ }
+
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+ }
+
+ delete[] pBuf;
+ }
+ }
+
+ rImageSize = rOStm.Tell() - rImageSize;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDecodeRLE( BYTE* pBuffer, DIBInfoHeader& rHeader,
+ BitmapWriteAccess& rAcc, BOOL bRLE4 )
+{
+ Scanline pRLE = pBuffer;
+ long nY = rHeader.nHeight - 1L;
+ const ULONG nWidth = rAcc.Width();
+ ULONG nCountByte;
+ ULONG nRunByte;
+ ULONG nX = 0UL;
+ BYTE cTmp;
+ BOOL bEndDecoding = FALSE;
+
+ do
+ {
+ if( !( nCountByte = *pRLE++ ) )
+ {
+ nRunByte = *pRLE++;
+
+ if( nRunByte > 2 )
+ {
+ if( bRLE4 )
+ {
+ nCountByte = nRunByte >> 1;
+
+ for( ULONG i = 0UL; i < nCountByte; i++ )
+ {
+ cTmp = *pRLE++;
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
+ }
+
+ if( nRunByte & 1 )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, *pRLE >> 4 );
+
+ pRLE++;
+ }
+
+ if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
+ pRLE++;
+ }
+ else
+ {
+ for( ULONG i = 0UL; i < nRunByte; i++ )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, *pRLE );
+
+ pRLE++;
+ }
+
+ if( nRunByte & 1 )
+ pRLE++;
+ }
+ }
+ else if( !nRunByte )
+ {
+ nY--;
+ nX = 0UL;
+ }
+ else if( nRunByte == 1 )
+ bEndDecoding = TRUE;
+ else
+ {
+ nX += *pRLE++;
+ nY -= *pRLE++;
+ }
+ }
+ else
+ {
+ cTmp = *pRLE++;
+
+ if( bRLE4 )
+ {
+ nRunByte = nCountByte >> 1;
+
+ for( ULONG i = 0UL; i < nRunByte; i++ )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
+ }
+
+ if( ( nCountByte & 1 ) && ( nX < nWidth ) )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+ }
+ else
+ {
+ for( ULONG i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
+ rAcc.SetPixel( nY, nX++, cTmp );
+ }
+ }
+ }
+ while ( !bEndDecoding && ( nY >= 0L ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, BOOL bRLE4 )
+{
+ const ULONG nWidth = rAcc.Width();
+ const ULONG nHeight = rAcc.Height();
+ ULONG nX;
+ ULONG nSaveIndex;
+ ULONG nCount;
+ ULONG nBufCount;
+ BYTE* pBuf = new BYTE[ nWidth << 1 ];
+ BYTE* pTmp;
+ BYTE cPix;
+ BYTE cLast;
+ BOOL bFound;
+
+ for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ nX = nBufCount = 0UL;
+
+ while( nX < nWidth )
+ {
+ nCount = 1L;
+ cPix = rAcc.GetPixel( nY, nX++ );
+
+ while( ( nX < nWidth ) && ( nCount < 255L ) && ( cPix == rAcc.GetPixel( nY, nX ) ) )
+ {
+ nX++;
+ nCount++;
+ }
+
+ if ( nCount > 1 )
+ {
+ *pTmp++ = (BYTE) nCount;
+ *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
+ nBufCount += 2;
+ }
+ else
+ {
+ cLast = cPix;
+ nSaveIndex = nX - 1UL;
+ bFound = FALSE;
+
+ while( ( nX < nWidth ) && ( nCount < 256L ) && ( cPix = rAcc.GetPixel( nY, nX ) ) != cLast )
+ {
+ nX++; nCount++;
+ cLast = cPix;
+ bFound = TRUE;
+ }
+
+ if ( bFound )
+ nX--;
+
+ if ( nCount > 3 )
+ {
+ *pTmp++ = 0;
+ *pTmp++ = (BYTE) --nCount;
+
+ if( bRLE4 )
+ {
+ for ( ULONG i = 0; i < nCount; i++, pTmp++ )
+ {
+ *pTmp = (BYTE) rAcc.GetPixel( nY, nSaveIndex++ ) << 4;
+
+ if ( ++i < nCount )
+ *pTmp |= rAcc.GetPixel( nY, nSaveIndex++ );
+ }
+
+ nCount = ( nCount + 1 ) >> 1;
+ }
+ else
+ {
+ for( ULONG i = 0UL; i < nCount; i++ )
+ *pTmp++ = rAcc.GetPixel( nY, nSaveIndex++ );
+ }
+
+ if ( nCount & 1 )
+ {
+ *pTmp++ = 0;
+ nBufCount += ( nCount + 3 );
+ }
+ else
+ nBufCount += ( nCount + 2 );
+ }
+ else
+ {
+ *pTmp++ = 1;
+ *pTmp++ = (BYTE) rAcc.GetPixel( nY, nSaveIndex ) << ( bRLE4 ? 4 : 0 );
+
+ if ( nCount == 3 )
+ {
+ *pTmp++ = 1;
+ *pTmp++ = (BYTE) rAcc.GetPixel( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
+ nBufCount += 4;
+ }
+ else
+ nBufCount += 2;
+ }
+ }
+ }
+
+ pBuf[ nBufCount++ ] = 0;
+ pBuf[ nBufCount++ ] = 0;
+
+ rOStm.Write( pBuf, nBufCount );
+ }
+
+ rOStm << (BYTE) 0;
+ rOStm << (BYTE) 1;
+
+ delete[] pBuf;
+
+ return( rOStm.GetError() == 0UL );
+}
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
new file mode 100644
index 000000000000..34776a8b00bf
--- /dev/null
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -0,0 +1,2248 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdlib.h>
+#define _SV_BITMAP_CXX
+
+#ifdef W31
+#include <tools/svwin.h>
+#endif
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_IMPOCT_HXX
+#include <impoct.hxx>
+#endif
+#ifndef _SV_OCTREE_HXX
+#include <octree.hxx>
+#endif
+#ifndef _SV_IMPVECT_HXX
+#include <impvect.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define RGB15( _def_cR, _def_cG, _def_cB ) (((ULONG)(_def_cR)<<10UL)|((ULONG)(_def_cG)<<5UL)|(ULONG)(_def_cB))
+#define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
+
+#define CALC_ERRORS \
+ nTemp = p1T[nX++] >> 12; \
+ nBErr = MinMax( nTemp, 0, 255 ); \
+ nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
+ nTemp = p1T[nX++] >> 12; \
+ nGErr = MinMax( nTemp, 0, 255 ); \
+ nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
+ nTemp = p1T[nX] >> 12; \
+ nRErr = MinMax( nTemp, 0, 255 ); \
+ nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
+
+#define CALC_TABLES3 \
+ p2T[nX++] += FloydError3[nBErr]; \
+ p2T[nX++] += FloydError3[nGErr]; \
+ p2T[nX++] += FloydError3[nRErr];
+
+#define CALC_TABLES5 \
+ p2T[nX++] += FloydError5[nBErr]; \
+ p2T[nX++] += FloydError5[nGErr]; \
+ p2T[nX++] += FloydError5[nRErr];
+
+#define CALC_TABLES7 \
+ p1T[++nX] += FloydError7[nBErr]; \
+ p2T[nX++] += FloydError1[nBErr]; \
+ p1T[nX] += FloydError7[nGErr]; \
+ p2T[nX++] += FloydError1[nGErr]; \
+ p1T[nX] += FloydError7[nRErr]; \
+ p2T[nX] += FloydError1[nRErr];
+
+// -----------
+// - Statics -
+// -----------
+
+ULONG nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
+ULONG nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
+ULONG nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
+
+// ------------------------------------------------------------------------
+
+ULONG nVCLDitherLut[ 256 ] =
+{
+ 0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056,
+ 62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
+ 48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
+ 57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016,
+ 12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
+ 23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
+ 14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792,
+ 50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
+ 35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144,
+ 55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136,
+ 5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
+ 27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952,
+ 3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616,
+ 64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
+ 45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776,
+ 60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576,
+ 41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
+ 20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688,
+ 13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328,
+ 18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
+ 34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632,
+ 54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136,
+ 39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
+ 25856, 38144, 21760
+};
+
+// ------------------------------------------------------------------------
+
+ULONG nVCLLut[ 256 ] =
+{
+ 0, 1286, 2572, 3858, 5144, 6430, 7716, 9002,
+ 10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
+ 20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
+ 30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
+ 41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
+ 51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
+ 61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
+ 72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
+ 82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
+ 92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
+ 102880,104166,105452,106738,108024,109310,110596,111882,
+ 113168,114454,115740,117026,118312,119598,120884,122170,
+ 123456,124742,126028,127314,128600,129886,131172,132458,
+ 133744,135030,136316,137602,138888,140174,141460,142746,
+ 144032,145318,146604,147890,149176,150462,151748,153034,
+ 154320,155606,156892,158178,159464,160750,162036,163322,
+ 164608,165894,167180,168466,169752,171038,172324,173610,
+ 174896,176182,177468,178754,180040,181326,182612,183898,
+ 185184,186470,187756,189042,190328,191614,192900,194186,
+ 195472,196758,198044,199330,200616,201902,203188,204474,
+ 205760,207046,208332,209618,210904,212190,213476,214762,
+ 216048,217334,218620,219906,221192,222478,223764,225050,
+ 226336,227622,228908,230194,231480,232766,234052,235338,
+ 236624,237910,239196,240482,241768,243054,244340,245626,
+ 246912,248198,249484,250770,252056,253342,254628,255914,
+ 257200,258486,259772,261058,262344,263630,264916,266202,
+ 267488,268774,270060,271346,272632,273918,275204,276490,
+ 277776,279062,280348,281634,282920,284206,285492,286778,
+ 288064,289350,290636,291922,293208,294494,295780,297066,
+ 298352,299638,300924,302210,303496,304782,306068,307354,
+ 308640,309926,311212,312498,313784,315070,316356,317642,
+ 318928,320214,321500,322786,324072,325358,326644,327930
+};
+
+// ------------------------------------------------------------------------
+
+long FloydMap[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError1[61] =
+{
+ -7680, -7424, -7168, -6912, -6656, -6400, -6144,
+ -5888, -5632, -5376, -5120, -4864, -4608, -4352,
+ -4096, -3840, -3584, -3328, -3072, -2816, -2560,
+ -2304, -2048, -1792, -1536, -1280, -1024, -768,
+ -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
+ 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
+ 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
+ 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError3[61] =
+{
+ -23040, -22272, -21504, -20736, -19968, -19200,
+ -18432, -17664, -16896, -16128, -15360, -14592,
+ -13824, -13056, -12288, -11520, -10752, -9984,
+ -9216, -8448, -7680, -6912, -6144, -5376, -4608,
+ -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
+ 2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
+ 8448, 9216, 9984, 10752, 11520, 12288, 13056,
+ 13824, 14592, 15360, 16128, 16896, 17664, 18432,
+ 19200, 19968, 20736, 21504, 22272, 23040
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError5[61] =
+{
+ -38400, -37120, -35840, -34560, -33280, -32000,
+ -30720, -29440, -28160, -26880, -25600, -24320,
+ -23040, -21760, -20480, -19200, -17920, -16640,
+ -15360, -14080, -12800, -11520, -10240, -8960,
+ -7680, -6400, -5120, -3840, -2560, -1280, 0,
+ 1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
+ 11520, 12800, 14080, 15360, 16640, 17920, 19200,
+ 20480, 21760, 23040, 24320, 25600, 26880, 28160,
+ 29440, 30720, 32000, 33280, 34560, 35840, 37120,
+ 38400
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError7[61] =
+{
+ -53760, -51968, -50176, -48384, -46592, -44800,
+ -43008, -41216, -39424, -37632, -35840, -34048,
+ -32256, -30464, -28672, -26880, -25088, -23296,
+ -21504, -19712, -17920, -16128, -14336, -12544,
+ -10752, -8960, -7168, -5376, -3584, -1792, 0,
+ 1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
+ 16128, 17920, 19712, 21504, 23296, 25088, 26880,
+ 28672, 30464, 32256, 34048, 35840, 37632, 39424,
+ 41216, 43008, 44800, 46592, 48384, 50176, 51968,
+ 53760
+};
+
+// ------------------------------------------------------------------------
+
+long FloydIndexMap[6] =
+{
+ -30, 21, 72, 123, 174, 225
+};
+
+// --------------------------
+// - ImplCreateDitherMatrix -
+// --------------------------
+
+void ImplCreateDitherMatrix( BYTE (*pDitherMatrix)[16][16] )
+{
+ double fVal = 3.125;
+ const double fVal16 = fVal / 16.;
+ long i, j, k, l;
+ USHORT pMtx[ 16 ][ 16 ];
+ USHORT nMax = 0;
+ static BYTE pMagic[4][4] = { 0, 14, 3, 13,
+ 11, 5, 8, 6,
+ 12, 2, 15, 1,
+ 7, 9, 4, 10 };
+
+ // MagicSquare aufbauen
+ for ( i = 0; i < 4; i++ )
+ for ( j = 0; j < 4; j++ )
+ for ( k = 0; k < 4; k++ )
+ for ( l = 0; l < 4; l++ )
+ nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
+ (USHORT) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
+
+ // auf Intervall [0;254] skalieren
+ for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
+ for( j = 0; j < 16; j++ )
+ (*pDitherMatrix)[i][j] = (BYTE) ( fVal * pMtx[i][j] );
+}
+
+// ----------
+// - Bitmap -
+// ----------
+
+BOOL Bitmap::Convert( BmpConversion eConversion )
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ switch( eConversion )
+ {
+ case( BMP_CONVERSION_1BIT_THRESHOLD ):
+ bRet = ImplMakeMono( 128 );
+ break;
+
+ case( BMP_CONVERSION_1BIT_MATRIX ):
+ bRet = ImplMakeMonoDither();
+ break;
+
+ case( BMP_CONVERSION_4BIT_GREYS ):
+ bRet = ImplMakeGreyscales( 16 );
+ break;
+
+ case( BMP_CONVERSION_4BIT_COLORS ):
+ {
+ if( nBitCount < 4 )
+ bRet = ImplConvertUp( 4, NULL );
+ else if( nBitCount > 4 )
+ bRet = ImplConvertDown( 4, NULL );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_4BIT_TRANS ):
+ {
+ Color aTrans( BMP_COL_TRANS );
+
+ if( nBitCount < 4 )
+ bRet = ImplConvertUp( 4, &aTrans );
+ else
+ bRet = ImplConvertDown( 4, &aTrans );
+ }
+ break;
+
+ case( BMP_CONVERSION_8BIT_GREYS ):
+ bRet = ImplMakeGreyscales( 256 );
+ break;
+
+ case( BMP_CONVERSION_8BIT_COLORS ):
+ {
+ if( nBitCount < 8 )
+ bRet = ImplConvertUp( 8 );
+ else if( nBitCount > 8 )
+ bRet = ImplConvertDown( 8 );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_8BIT_TRANS ):
+ {
+ Color aTrans( BMP_COL_TRANS );
+
+ if( nBitCount < 8 )
+ bRet = ImplConvertUp( 8, &aTrans );
+ else
+ bRet = ImplConvertDown( 8, &aTrans );
+ }
+ break;
+
+ case( BMP_CONVERSION_24BIT ):
+ {
+ if( nBitCount < 24 )
+ bRet = ImplConvertUp( 24, FALSE );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_GHOSTED ):
+ bRet = ImplConvertGhosted();
+ break;
+
+ default:
+ DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
+ break;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeMono( BYTE cThreshold )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >=
+ cThreshold )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
+ cThreshold )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeMonoDither()
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ BYTE pDitherMatrix[ 16 ][ 16 ];
+
+ ImplCreateDitherMatrix( &pDitherMatrix );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >
+ pDitherMatrix[ nModY ][ nX % 16 ] )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
+ pDitherMatrix[ nModY ][ nX % 16 ] )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeGreyscales( USHORT nGreys )
+{
+ DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" )
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ const BitmapPalette& rPal = GetGreyPalette( nGreys );
+ ULONG nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
+ BOOL bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
+
+ if( !bPalDiffers )
+ bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
+
+ if( bPalDiffers )
+ {
+ Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ pWriteAcc->SetPixel( nY, nX,
+ (BYTE) ( pReadAcc->GetPaletteColor(
+ pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift ) );
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
+ pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ nShift += 8;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pReadScan = pReadAcc->GetScanline( nY );
+ Scanline pWriteScan = pWriteAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const ULONG nB = *pReadScan++;
+ const ULONG nG = *pReadScan++;
+ const ULONG nR = *pReadScan++;
+
+ *pWriteScan++ = (BYTE) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
+ pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ nShift += 8;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pReadScan = pReadAcc->GetScanline( nY );
+ Scanline pWriteScan = pWriteAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const ULONG nR = *pReadScan++;
+ const ULONG nG = *pReadScan++;
+ const ULONG nB = *pReadScan++;
+
+ *pWriteScan++ = (BYTE) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, ( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ else
+ {
+ ReleaseAccess( pReadAcc );
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertUp( USHORT nBitCount, Color* pExtColor )
+{
+ DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ BitmapPalette aPal;
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pWriteAcc->HasPalette() )
+ {
+ const USHORT nOldCount = 1 << GetBitCount();
+ const BitmapPalette& rOldPal = pReadAcc->GetPalette();
+
+ aPal.SetEntryCount( 1 << nBitCount );
+
+ for( USHORT i = 0; i < nOldCount; i++ )
+ aPal[ i ] = rOldPal[ i ];
+
+ if( pExtColor )
+ aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
+
+ pWriteAcc->SetPalette( aPal );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
+ }
+ else
+ {
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertDown( USHORT nBitCount, Color* pExtColor )
+{
+ DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ BitmapPalette aPal;
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const USHORT nCount = 1 << nBitCount;
+ const long nWidth = pWriteAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pWriteAcc->Height();
+ Octree aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
+ InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
+ BitmapColor aColor;
+ ImpErrorQuad aErrQuad;
+ ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pQLine1 = pErrQuad1;
+ ImpErrorQuad* pQLine2;
+ long nX, nY;
+ long nYTmp = 0L;
+ BYTE cIndex;
+ BOOL bQ1 = TRUE;
+
+ if( pExtColor )
+ {
+ aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
+ aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
+ }
+
+ // set Black/White always, if we have enough space
+ if( aPal.GetEntryCount() < ( nCount - 1 ) )
+ {
+ aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
+ aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
+ aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
+ }
+
+ pWriteAcc->SetPalette( aPal );
+
+ for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
+ {
+ for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->HasPalette() )
+ pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
+ else
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+ }
+
+ for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
+ {
+ // erstes ZeilenPixel
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
+ pWriteAcc->SetPixel( nY, 0, cIndex );
+
+ for( nX = 1L; nX < nWidth1; nX++ )
+ {
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
+ aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
+ pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
+ pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
+ pWriteAcc->SetPixel( nY, nX, cIndex );
+ }
+
+ // letztes ZeilenPixel
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
+ pWriteAcc->SetPixel( nY, nX, cIndex );
+
+ // Zeilenpuffer neu fuellen/kopieren
+ pQLine1 = pQLine2;
+ pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
+
+ if( nYTmp < nHeight )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->HasPalette() )
+ pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
+ else
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+ }
+ }
+
+ // Zeilenpuffer zerstoeren
+ delete[] pErrQuad1;
+ delete[] pErrQuad2;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertGhosted()
+{
+ Bitmap aNewBmp;
+ BitmapReadAccess* pR = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pR )
+ {
+ if( pR->HasPalette() )
+ {
+ BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
+
+ for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rOld = pR->GetPaletteColor( (USHORT) i );
+ aNewPal[ (USHORT) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
+ ( rOld.GetGreen() >> 1 ) | 0x80,
+ ( rOld.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
+ BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
+
+ if( pW )
+ {
+ pW->CopyBuffer( *pR );
+ aNewBmp.ReleaseAccess( pW );
+ bRet = TRUE;
+ }
+ }
+ else
+ {
+ aNewBmp = Bitmap( GetSizePixel(), 24 );
+
+ BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
+
+ if( pW )
+ {
+ const long nWidth = pR->Width(), nHeight = pR->Height();
+
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ const BitmapColor aOld( pR->GetPixel( nY, nX ) );
+ pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
+ ( aOld.GetGreen() >> 1 ) | 0x80,
+ ( aOld.GetBlue() >> 1 ) | 0x80 ) );
+
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pW );
+ bRet = TRUE;
+ }
+ }
+
+ ReleaseAccess( pR );
+ }
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet;
+
+ if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
+ {
+ if( BMP_SCALE_FAST == nScaleFlag )
+ bRet = ImplScaleFast( rScaleX, rScaleY );
+ else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
+ bRet = ImplScaleInterpolate( rScaleX, rScaleY );
+ else
+ bRet = FALSE;
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ const Size aSize( GetSizePixel() );
+ BOOL bRet;
+
+ if( aSize.Width() && aSize.Height() )
+ {
+ bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
+ (double) rNewSize.Height() / aSize.Height(),
+ nScaleFlag );
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
+{
+ const Size aSizePix( GetSizePixel() );
+ const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
+ const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
+ BOOL bRet = FALSE;
+
+ if( nNewWidth && nNewHeight )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nScanlineSize = pWriteAcc->GetScanlineSize();
+ const long nNewWidth1 = nNewWidth - 1L;
+ const long nNewHeight1 = nNewHeight - 1L;
+ const long nWidth1 = pReadAcc->Width() - 1L;
+ const long nHeight1 = pReadAcc->Height() - 1L;
+ long* pLutX = new long[ nNewWidth ];
+ long* pLutY = new long[ nNewHeight ];
+ long nX, nY, nMapY, nActY = 0L;
+
+ if( nNewWidth1 && nNewHeight1 )
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pLutX[ nX ] = nX * nWidth1 / nNewWidth1;
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pLutY[ nY ] = nY * nHeight1 / nNewHeight1;
+
+ while( nActY < nNewHeight )
+ {
+ nMapY = pLutY[ nActY ];
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
+
+ while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
+ {
+ HMEMCPY( pWriteAcc->GetScanline( nActY + 1L ),
+ pWriteAcc->GetScanline( nActY ), nScanlineSize );
+ nActY++;
+ }
+
+ nActY++;
+ }
+
+ bRet = TRUE;
+ }
+
+ delete[] pLutX;
+ delete[] pLutY;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
+{
+ const Size aSizePix( GetSizePixel() );
+ const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
+ const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
+ BOOL bRet = FALSE;
+
+ if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
+ {
+ BitmapColor aCol0;
+ BitmapColor aCol1;
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ long nWidth = pReadAcc->Width();
+ long nHeight = pReadAcc->Height();
+ Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ long* pLutInt;
+ long* pLutFrac;
+ long nX, nY;
+ long lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
+ double fTemp;
+ long nTemp;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nNewWidth1 = nNewWidth - 1L;
+ const long nWidth1 = pReadAcc->Width() - 1L;
+ const double fRevScaleX = (double) nWidth1 / nNewWidth1;
+
+ pLutInt = new long[ nNewWidth ];
+ pLutFrac = new long[ nNewWidth ];
+
+ for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
+ {
+ fTemp = nX * fRevScaleX;
+ pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
+ fTemp -= pLutInt[ nX ];
+ pLutFrac[ nX ] = (long) ( fTemp * 1024. );
+ }
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ if( 1 == nWidth )
+ {
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, 0 ) );
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nTemp = pLutInt[ nX ];
+
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp++ ) );
+ aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp ) );
+
+ nTemp = pLutFrac[ nX ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ if( 1 == nWidth )
+ {
+ aCol0 = pReadAcc->GetPixel( nY, 0 );
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nTemp = pLutInt[ nX ];
+
+ aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
+ aCol1 = pReadAcc->GetPixel( nY, nTemp );
+
+ nTemp = pLutFrac[ nX ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+
+ delete[] pLutInt;
+ delete[] pLutFrac;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+ ImplAssignWithSize( aNewBmp );
+ pReadAcc = AcquireReadAccess();
+ aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
+ pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nNewHeight1 = nNewHeight - 1L;
+ const long nHeight1 = pReadAcc->Height() - 1L;
+ const double fRevScaleY = (double) nHeight1 / nNewHeight1;
+
+ pLutInt = new long[ nNewHeight ];
+ pLutFrac = new long[ nNewHeight ];
+
+ for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
+ {
+ fTemp = nY * fRevScaleY;
+ pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
+ fTemp -= pLutInt[ nY ];
+ pLutFrac[ nY ] = (long) ( fTemp * 1024. );
+ }
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ if( 1 == nHeight )
+ {
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nX ) );
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nTemp = pLutInt[ nY ];
+
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp++, nX ) );
+ aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp, nX ) );
+
+ nTemp = pLutFrac[ nY ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ if( 1 == nHeight )
+ {
+ aCol0 = pReadAcc->GetPixel( 0, nX );
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nTemp = pLutInt[ nY ];
+
+ aCol0 = pReadAcc->GetPixel( nTemp++, nX );
+ aCol1 = pReadAcc->GetPixel( nTemp, nX );
+
+ nTemp = pLutFrac[ nY ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+
+ delete[] pLutInt;
+ delete[] pLutFrac;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ if( !bRet )
+ bRet = ImplScaleFast( rScaleX, rScaleY );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ DBG_ASSERT( !pDitherPal, "Sorry, using owner defined palettes is not yet supportet..." );
+
+ BOOL bRet = FALSE;
+
+ const Size aSizePix( GetSizePixel() );
+
+ if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
+ bRet = TRUE;
+ else if( nDitherFlags & BMP_DITHER_MATRIX )
+ bRet = ImplDitherMatrix( pDitherPal );
+ else if( nDitherFlags & BMP_DITHER_FLOYD )
+ bRet = ImplDitherFloyd( pDitherPal );
+ else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
+ bRet = ImplDitherFloyd16();
+
+ return bRet;
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BITMAP3_SEG1
+#endif
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherMatrix( const BitmapPalette* pDitherPal )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 8 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const ULONG nWidth = pReadAcc->Width();
+ const ULONG nHeight = pReadAcc->Height();
+ BitmapColor aIndex( (BYTE) 0 );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( ULONG nY = 0UL; nY < nHeight; nY++ )
+ {
+ for( ULONG nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
+ const ULONG nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
+ const ULONG nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
+ const ULONG nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
+ const ULONG nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
+
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
+ pWriteAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+ else
+ {
+ for( ULONG nY = 0UL; nY < nHeight; nY++ )
+ {
+ for( ULONG nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) );
+ const ULONG nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
+ const ULONG nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
+ const ULONG nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
+ const ULONG nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
+
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
+ pWriteAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherFloyd( const BitmapPalette* pDitherPal )
+{
+ const Size aSize( GetSizePixel() );
+ BOOL bRet = FALSE;
+
+ if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 8 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ BitmapColor aColor;
+ long nWidth = pReadAcc->Width();
+ long nWidth1 = nWidth - 1L;
+ long nHeight = pReadAcc->Height();
+ long nX;
+ long nW = nWidth * 3L;
+ long nW2 = nW - 3L;
+ long nWLen = nW << 2;
+ long nRErr, nGErr, nBErr;
+ long nRC, nGC, nBC;
+ long nTemp;
+ long nZ;
+ long* p1 = new long[ nW ];
+ long* p2 = new long[ nW ];
+ long* p1T = p1;
+ long* p2T = p2;
+ long* pTmp;
+ BOOL bPal = pReadAcc->HasPalette();
+
+ pTmp = p2T;
+
+ if( bPal )
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nZ ) );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ else
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPixel( 0, nZ );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+
+ for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
+ {
+ pTmp = p1T;
+ p1T = p2T;
+ p2T = pTmp;
+
+ if( nY < nHeight )
+ {
+ if( bPal )
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nZ ) );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ else
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPixel( nY, nZ );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ }
+
+ // erstes Pixel gesondert betrachten
+ nX = 0;
+ CALC_ERRORS;
+ CALC_TABLES7;
+ nX -= 5;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, 0, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+
+ // mittlere Pixel ueber Schleife
+ for ( long nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
+ {
+ CALC_ERRORS;
+ CALC_TABLES7;
+ nX -= 8;
+ CALC_TABLES3;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, nXAcc, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+ }
+
+ // letztes Pixel gesondert betrachten
+ CALC_ERRORS;
+ nX -= 5;
+ CALC_TABLES3;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, nWidth1, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+ }
+
+ delete[] p1;
+ delete[] p2;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherFloyd16()
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pWriteAcc->Height();
+ BitmapColor aColor;
+ BitmapColor aBestCol;
+ ImpErrorQuad aErrQuad;
+ ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pQLine1 = pErrQuad1;
+ ImpErrorQuad* pQLine2;
+ long nX, nY;
+ long nYTmp = 0L;
+ BOOL bQ1 = TRUE;
+
+ for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
+ for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+
+ for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
+ {
+ // erstes ZeilenPixel
+ aBestCol = pQLine1[ 0 ].ImplGetColor();
+ aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
+ pWriteAcc->SetPixel( nY, 0, aBestCol );
+
+ for( nX = 1L; nX < nWidth1; nX++ )
+ {
+ aColor = pQLine1[ nX ].ImplGetColor();
+ aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
+ aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
+ pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
+ pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
+ pWriteAcc->SetPixel( nY, nX, aBestCol );
+ }
+
+ // letztes ZeilenPixel
+ aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
+ aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
+ pWriteAcc->SetPixel( nY, nX, aBestCol );
+
+ // Zeilenpuffer neu fuellen/kopieren
+ pQLine1 = pQLine2;
+ pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
+
+ if( nYTmp < nHeight )
+ for( nX = 0L; nX < nWidth; nX++ )
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+
+ // Zeilenpuffer zerstoeren
+ delete[] pErrQuad1;
+ delete[] pErrQuad2;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ReduceColors( USHORT nColorCount, BmpReduce eReduce )
+{
+ BOOL bRet;
+
+ if( GetColorCount() <= (ULONG) nColorCount )
+ bRet = TRUE;
+ else if( nColorCount )
+ {
+ if( BMP_REDUCE_SIMPLE == eReduce )
+ bRet = ImplReduceSimple( nColorCount );
+ else if( BMP_REDUCE_POPULAR == eReduce )
+ bRet = ImplReducePopular( nColorCount );
+ else
+ bRet = ImplReduceMedian( nColorCount );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReduceSimple( USHORT nColorCount )
+{
+ Bitmap aNewBmp;
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ const USHORT nColCount = Min( nColorCount, (USHORT) 256 );
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount <= 2 )
+ nBitCount = 1;
+ else if( nColCount <= 16 )
+ nBitCount = 4;
+ else
+ nBitCount = 8;
+
+ if( pRAcc )
+ {
+ Octree aOct( *pRAcc, nColCount );
+ const BitmapPalette& rPal = aOct.GetPalette();
+ BitmapWriteAccess* pWAcc;
+
+ aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
+ pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+
+ if( pRAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX =0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) ) ) );
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX =0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) ) );
+ }
+
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pRAcc );
+ }
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+struct PopularColorCount
+{
+ sal_uInt32 mnIndex;
+ sal_uInt32 mnCount;
+};
+
+// ------------------------------------------------------------------------
+
+extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
+{
+ int nRet;
+
+ if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
+ nRet = 1;
+ else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
+ nRet = 0;
+ else
+ nRet = -1;
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReducePopular( USHORT nColCount )
+{
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount > 256 )
+ nColCount = 256;
+
+ if( nColCount < 17 )
+ nBitCount = 4;
+ else
+ nBitCount = 8;
+
+ if( pRAcc )
+ {
+ const sal_uInt32 nValidBits = 4;
+ const sal_uInt32 nRightShiftBits = 8 - nValidBits;
+ const sal_uInt32 nLeftShiftBits1 = nValidBits;
+ const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
+ const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
+ const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
+ const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+ PopularColorCount* pCountTable = new PopularColorCount[ nTotalColors ];
+ long nX, nY, nR, nG, nB, nIndex;
+
+ rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
+
+ for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
+ for( nG = 0; nG < 256; nG += nColorOffset )
+ for( nB = 0; nB < 256; nB += nColorOffset )
+ pCountTable[ nIndex ].mnIndex = nIndex++;
+
+ if( pRAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
+ }
+ }
+ }
+
+ BitmapPalette aNewPal( nColCount );
+
+ qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
+
+ for( USHORT n = 0; n < nColCount; n++ )
+ {
+ const PopularColorCount& rPop = pCountTable[ n ];
+ aNewPal[ n ] = BitmapColor( (BYTE) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
+ (BYTE) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
+ (BYTE) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
+ }
+
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
+ BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ BitmapColor aDstCol( (BYTE) 0 );
+ BYTE* pIndexMap = new BYTE[ nTotalColors ];
+
+ for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
+ for( nG = 0; nG < 256; nG += nColorOffset )
+ for( nB = 0; nB < 256; nB += nColorOffset )
+ pIndexMap[ nIndex++ ] = aNewPal.GetBestIndex( BitmapColor( (BYTE) nR, (BYTE) nG, (BYTE) nB ) );
+
+ if( pRAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
+ pWAcc->SetPixel( nY, nX, aDstCol );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
+ pWAcc->SetPixel( nY, nX, aDstCol );
+ }
+ }
+ }
+
+ delete[] pIndexMap;
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ delete[] pCountTable;
+ ReleaseAccess( pRAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReduceMedian( USHORT nColCount )
+{
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount < 17 )
+ nBitCount = 4;
+ else if( nColCount < 257 )
+ nBitCount = 8;
+ else
+ {
+ DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
+ nBitCount = 8;
+ nColCount = 256;
+ }
+
+ if( pRAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), nBitCount );
+ BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const ULONG nSize = 32768UL * sizeof( ULONG );
+ HPULONG pColBuf = (HPULONG) SvMemAlloc( nSize );
+ const long nWidth = pWAcc->Width();
+ const long nHeight = pWAcc->Height();
+ long nIndex = 0L;
+
+ HMEMSET( (HPBYTE) pColBuf, 0, nSize );
+
+ // create Buffer
+ if( pRAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
+ }
+ }
+ }
+
+ // create palette via median cut
+ BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
+ ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
+ nColCount, nWidth * nHeight, nIndex );
+
+ // do mapping of colors to palette
+ InverseColorMap aMap( aPal );
+ pWAcc->SetPalette( aPal );
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) ) );
+
+ SvMemFree( pColBuf );
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pRAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void Bitmap::ImplMedianCut( ULONG* pColBuf, BitmapPalette& rPal,
+ long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
+ long nColors, long nPixels, long& rIndex )
+{
+ if( !nPixels )
+ return;
+
+ BitmapColor aCol;
+ const long nRLen = nR2 - nR1;
+ const long nGLen = nG2 - nG1;
+ const long nBLen = nB2 - nB1;
+ long nR, nG, nB;
+ HPULONG pBuf = pColBuf;
+
+ if( !nRLen && !nGLen && !nBLen )
+ {
+ if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
+ {
+ aCol.SetRed( (BYTE) ( nR1 << 3 ) );
+ aCol.SetGreen( (BYTE) ( nG1 << 3 ) );
+ aCol.SetBlue( (BYTE) ( nB1 << 3 ) );
+ rPal[ (USHORT) rIndex++ ] = aCol;
+ }
+ }
+ else
+ {
+ if( 1 == nColors || 1 == nPixels )
+ {
+ long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
+
+ for( nR = nR1; nR <= nR2; nR++ )
+ {
+ for( nG = nG1; nG <= nG2; nG++ )
+ {
+ for( nB = nB1; nB <= nB2; nB++ )
+ {
+ nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
+
+ if( nPixSum )
+ {
+ nRSum += nR * nPixSum;
+ nGSum += nG * nPixSum;
+ nBSum += nB * nPixSum;
+ }
+ }
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( ( nRSum / nPixels ) << 3 ) );
+ aCol.SetGreen( (BYTE) ( ( nGSum / nPixels ) << 3 ) );
+ aCol.SetBlue( (BYTE) ( ( nBSum / nPixels ) << 3 ) );
+ rPal[ (USHORT) rIndex++ ] = aCol;
+ }
+ else
+ {
+ const long nTest = ( nPixels >> 1 );
+ long nPixOld, nPixNew = 0;
+
+ if( nBLen > nGLen && nBLen > nRLen )
+ {
+ nB = nB1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nB++, nPixOld = nPixNew;
+ for( nR = nR1; nR <= nR2; nR++ )
+ for( nG = nG1; nG <= nG2; nG++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nB < nB2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ else if( nGLen > nRLen )
+ {
+ nG = nG1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nG++, nPixOld = nPixNew;
+ for( nR = nR1; nR <= nR2; nR++ )
+ for( nB = nB1; nB <= nB2; nB++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nG < nG2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ else
+ {
+ nR = nR1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nR++, nPixOld = nPixNew;
+ for( nG = nG1; nG <= nG2; nG++ )
+ for( nB = nB1; nB <= nB2; nB++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nR < nR2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Vectorize( PolyPolygon& rPolyPoly, ULONG nFlags, const Link* pProgress )
+{
+ return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Vectorize( GDIMetaFile& rMtf, BYTE cReduce, ULONG nFlags, const Link* pProgress )
+{
+ return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ BOOL bRet = FALSE;
+
+ // nothing to do => return quickly
+ if( !nLuminancePercent && !nContrastPercent &&
+ !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
+ ( fGamma == 1.0 ) && !bInvert )
+ {
+ bRet = TRUE;
+ }
+ else
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ BitmapColor aCol;
+ const long nW = pAcc->Width();
+ const long nH = pAcc->Height();
+ BYTE* cMapR = new BYTE[ 256 ];
+ BYTE* cMapG = new BYTE[ 256 ];
+ BYTE* cMapB = new BYTE[ 256 ];
+ long nX, nY;
+ double fM, fROff, fGOff, fBOff, fOff;
+
+ // calculate slope
+ if( nContrastPercent >= 0 )
+ fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
+ else
+ fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
+
+ // total offset = luminance offset + contrast offset
+ fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
+
+ // channel offset = channel offset + total offset
+ fROff = nChannelRPercent * 2.55 + fOff;
+ fGOff = nChannelGPercent * 2.55 + fOff;
+ fBOff = nChannelBPercent * 2.55 + fOff;
+
+ // calculate gamma value
+ fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
+ const BOOL bGamma = ( fGamma != 1.0 );
+
+ // create mapping table
+ for( nX = 0L; nX < 256L; nX++ )
+ {
+ cMapR[ nX ] = (BYTE) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
+ cMapG[ nX ] = (BYTE) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
+ cMapB[ nX ] = (BYTE) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
+
+ if( bGamma )
+ {
+ cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
+ cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
+ cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
+ }
+
+ if( bInvert )
+ {
+ cMapR[ nX ] = ~cMapR[ nX ];
+ cMapG[ nX ] = ~cMapG[ nX ];
+ cMapB[ nX ] = ~cMapB[ nX ];
+ }
+ }
+
+ // do modifying
+ if( pAcc->HasPalette() )
+ {
+ BitmapColor aNewCol;
+
+ for( USHORT i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+ aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
+ aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
+ aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
+ pAcc->SetPaletteColor( i, aNewCol );
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = cMapB[ *pScan ]; pScan++;
+ *pScan = cMapG[ *pScan ]; pScan++;
+ *pScan = cMapR[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = cMapR[ *pScan ]; pScan++;
+ *pScan = cMapG[ *pScan ]; pScan++;
+ *pScan = cMapB[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+ aCol.SetRed( cMapR[ aCol.GetRed() ] );
+ aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
+ aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ delete[] cMapR;
+ delete[] cMapG;
+ delete[] cMapB;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/bitmap4.cxx b/vcl/source/gdi/bitmap4.cxx
new file mode 100644
index 000000000000..d959166272f5
--- /dev/null
+++ b/vcl/source/gdi/bitmap4.cxx
@@ -0,0 +1,953 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#define _SV_BITMAP_CXX
+
+#include <vos/macros.hxx>
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define S2(a,b) { register long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
+#define MN3(a,b,c) S2(a,b); S2(a,c);
+#define MX3(a,b,c) S2(b,c); S2(a,c);
+#define MNMX3(a,b,c) MX3(a,b,c); S2(a,b);
+#define MNMX4(a,b,c,d) S2(a,b); S2(c,d); S2(a,c); S2(b,d);
+#define MNMX5(a,b,c,d,e) S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e);
+#define MNMX6(a,b,c,d,e,f) S2(a,d); S2(b,e); S2(c,f); MN3(a,b,c); MX3(d,e,f);
+
+// ----------
+// - Bitmap -
+// ----------
+
+BOOL Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ switch( eFilter )
+ {
+ case( BMP_FILTER_SMOOTH ):
+ {
+ const long pSmoothMatrix[] = { 1, 2, 1, 2, 5, 2, 1, 2, 1 };
+ bRet = ImplConvolute3( &pSmoothMatrix[ 0 ], 17, pFilterParam, pProgress );
+ }
+ break;
+
+ case( BMP_FILTER_SHARPEN ):
+ {
+ const long pSharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
+ bRet = ImplConvolute3( &pSharpenMatrix[ 0 ], 8, pFilterParam, pProgress );
+ }
+ break;
+
+ case( BMP_FILTER_REMOVENOISE ):
+ bRet = ImplMedianFilter( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SOBEL_GREY ):
+ bRet = ImplSobelGrey( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SOLARIZE ):
+ bRet = ImplSolarize( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SEPIA ):
+ bRet = ImplSepia( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_MOSAIC ):
+ bRet = ImplMosaic( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_EMBOSS_GREY ):
+ bRet = ImplEmbossGrey( pFilterParam, pProgress );
+ break;
+
+ default:
+ DBG_ERROR( "Bitmap::Convert(): Unsupported filter" );
+ break;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvolute3( const long* pMatrix, long nDivisor,
+ const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
+ const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
+ long* pColm = new long[ nWidth2 ];
+ long* pRows = new long[ nHeight2 ];
+ BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pRowTmp1 = pColRow1;
+ BitmapColor* pRowTmp2 = pColRow2;
+ BitmapColor* pRowTmp3 = pColRow3;
+ BitmapColor* pColor;
+ long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
+ long (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ];
+ long* pTmp;
+
+ // create LUT of products of matrix value and possible color component values
+ for( nY = 0; nY < 9; nY++ )
+ for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal )
+ pKoeff[ nY ][ nX ] = nTmp;
+
+ // create column LUT
+ for( i = 0; i < nWidth2; i++ )
+ pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pColm[ nWidth + 1 ] = pColm[ nWidth ];
+
+ // create row LUT
+ for( i = 0; i < nHeight2; i++ )
+ pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pRows[ nHeight + 1 ] = pRows[ nHeight ];
+
+ // read first three rows of bitmap color
+ for( i = 0; i < nWidth2; i++ )
+ {
+ pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
+ pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
+ pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
+ }
+
+ // do convolution
+ for( nY = 0; nY < nHeight; )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ // first row
+ nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ];
+ nSumG = pTmp[ pColor->GetGreen() ];
+ nSumB = pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // second row
+ nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // third row
+ nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // calculate destination color
+ pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) MinMax( nSumR / nDivisor, 0, 255 ),
+ (BYTE) MinMax( nSumG / nDivisor, 0, 255 ),
+ (BYTE) MinMax( nSumB / nDivisor, 0, 255 ) ) );
+ }
+
+ if( ++nY < nHeight )
+ {
+ if( pRowTmp1 == pColRow1 )
+ pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
+ else if( pRowTmp1 == pColRow2 )
+ pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
+ else
+ pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
+
+ for( i = 0; i < nWidth2; i++ )
+ pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
+ }
+ }
+
+ delete[] pKoeff;
+ delete[] (BYTE*) pColRow1;
+ delete[] (BYTE*) pColRow2;
+ delete[] (BYTE*) pColRow3;
+ delete[] pColm;
+ delete[] pRows;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMedianFilter( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
+ const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
+ long* pColm = new long[ nWidth2 ];
+ long* pRows = new long[ nHeight2 ];
+ BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pRowTmp1 = pColRow1;
+ BitmapColor* pRowTmp2 = pColRow2;
+ BitmapColor* pRowTmp3 = pColRow3;
+ BitmapColor* pColor;
+ long nY, nX, i;
+ long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
+ long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
+ long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
+
+ // create column LUT
+ for( i = 0; i < nWidth2; i++ )
+ pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pColm[ nWidth + 1 ] = pColm[ nWidth ];
+
+ // create row LUT
+ for( i = 0; i < nHeight2; i++ )
+ pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pRows[ nHeight + 1 ] = pRows[ nHeight ];
+
+ // read first three rows of bitmap color
+ for( i = 0; i < nWidth2; i++ )
+ {
+ pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
+ pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
+ pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
+ }
+
+ // do median filtering
+ for( nY = 0; nY < nHeight; )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nR1 = ( pColor = pRowTmp1 + nX )->GetRed(), nG1 = pColor->GetGreen(), nB1 = pColor->GetBlue();
+ nR2 = ( ++pColor )->GetRed(), nG2 = pColor->GetGreen(), nB2 = pColor->GetBlue();
+ nR3 = ( ++pColor )->GetRed(), nG3 = pColor->GetGreen(), nB3 = pColor->GetBlue();
+
+ nR4 = ( pColor = pRowTmp2 + nX )->GetRed(), nG4 = pColor->GetGreen(), nB4 = pColor->GetBlue();
+ nR5 = ( ++pColor )->GetRed(), nG5 = pColor->GetGreen(), nB5 = pColor->GetBlue();
+ nR6 = ( ++pColor )->GetRed(), nG6 = pColor->GetGreen(), nB6 = pColor->GetBlue();
+
+ nR7 = ( pColor = pRowTmp3 + nX )->GetRed(), nG7 = pColor->GetGreen(), nB7 = pColor->GetBlue();
+ nR8 = ( ++pColor )->GetRed(), nG8 = pColor->GetGreen(), nB8 = pColor->GetBlue();
+ nR9 = ( ++pColor )->GetRed(), nG9 = pColor->GetGreen(), nB9 = pColor->GetBlue();
+
+ MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 );
+ MNMX5( nR7, nR2, nR3, nR4, nR5 );
+ MNMX4( nR8, nR2, nR3, nR4 );
+ MNMX3( nR9, nR2, nR3 );
+
+ MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 );
+ MNMX5( nG7, nG2, nG3, nG4, nG5 );
+ MNMX4( nG8, nG2, nG3, nG4 );
+ MNMX3( nG9, nG2, nG3 );
+
+ MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 );
+ MNMX5( nB7, nB2, nB3, nB4, nB5 );
+ MNMX4( nB8, nB2, nB3, nB4 );
+ MNMX3( nB9, nB2, nB3 );
+
+ // set destination color
+ pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) nR2, (BYTE) nG2, (BYTE) nB2 ) );
+ }
+
+ if( ++nY < nHeight )
+ {
+ if( pRowTmp1 == pColRow1 )
+ pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
+ else if( pRowTmp1 == pColRow2 )
+ pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
+ else
+ pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
+
+ for( i = 0; i < nWidth2; i++ )
+ pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
+ }
+ }
+
+ delete[] (BYTE*) pColRow1;
+ delete[] (BYTE*) pColRow2;
+ delete[] (BYTE*) pColRow3;
+ delete[] pColm;
+ delete[] pRows;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSobelGrey( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = ImplMakeGreyscales( 256 );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aGrey( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ const long nMask111 = -1, nMask121 = 0, nMask131 = 1;
+ const long nMask211 = -2, nMask221 = 0, nMask231 = 2;
+ const long nMask311 = -1, nMask321 = 0, nMask331 = 1;
+ const long nMask112 = 1, nMask122 = 2, nMask132 = 1;
+ const long nMask212 = 0, nMask222 = 0, nMask232 = 0;
+ const long nMask312 = -1, nMask322 = -2, nMask332 = -1;
+ long nGrey11, nGrey12, nGrey13;
+ long nGrey21, nGrey22, nGrey23;
+ long nGrey31, nGrey32, nGrey33;
+ long* pHMap = new long[ nWidth + 2 ];
+ long* pVMap = new long[ nHeight + 2 ];
+ long nX, nY, nSum1, nSum2;
+
+ // fill mapping tables
+ pHMap[ 0 ] = 0;
+ for( nX = 1; nX <= nWidth; nX++ )
+ pHMap[ nX ] = nX - 1;
+ pHMap[ nWidth + 1 ] = nWidth - 1;
+
+ pVMap[ 0 ] = 0;
+ for( nY = 1; nY <= nHeight; nY++ )
+ pVMap[ nY ] = nY - 1;
+ pVMap[ nHeight + 1 ] = nHeight - 1;
+
+ for( nY = 0; nY < nHeight ; nY++ )
+ {
+ nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
+ nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
+ nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
+ nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
+ nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
+ nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
+ nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
+ nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
+ nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
+
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nSum1 = nSum2 = 0;
+
+ nSum1 += nMask111 * nGrey11;
+ nSum2 += nMask112 * nGrey11;
+
+ nSum1 += nMask121 * nGrey12;
+ nSum2 += nMask122 * nGrey12;
+
+ nSum1 += nMask131 * nGrey13;
+ nSum2 += nMask132 * nGrey13;
+
+ nSum1 += nMask211 * nGrey21;
+ nSum2 += nMask212 * nGrey21;
+
+ nSum1 += nMask221 * nGrey22;
+ nSum2 += nMask222 * nGrey22;
+
+ nSum1 += nMask231 * nGrey23;
+ nSum2 += nMask232 * nGrey23;
+
+ nSum1 += nMask311 * nGrey31;
+ nSum2 += nMask312 * nGrey31;
+
+ nSum1 += nMask321 * nGrey32;
+ nSum2 += nMask322 * nGrey32;
+
+ nSum1 += nMask331 * nGrey33;
+ nSum2 += nMask332 * nGrey33;
+
+ nSum1 = (long) sqrt( ( nSum1 * nSum1 + nSum2 * nSum2 ) );
+ aGrey.SetIndex( ~(BYTE) VOS_BOUND( nSum1, 0, 255 ) );
+ pWriteAcc->SetPixel( nY, nX, aGrey );
+
+ if( nX < ( nWidth - 1 ) )
+ {
+ const long nNextX = pHMap[ nX + 3 ];
+
+ nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
+ nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
+ nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
+ }
+ }
+ }
+
+ delete[] pHMap;
+ delete[] pVMap;
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = ImplMakeGreyscales( 256 );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aGrey( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ long nGrey11, nGrey12, nGrey13;
+ long nGrey21, nGrey22, nGrey23;
+ long nGrey31, nGrey32, nGrey33;
+ double fAzim = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
+ ( pFilterParam->maEmbossAngles.mnAzimuthAngle100 * 0.01 ) : 0.0 ) * F_PI180;
+ double fElev = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
+ ( pFilterParam->maEmbossAngles.mnElevationAngle100 * 0.01 ) : 90.0 ) * F_PI180;
+ long* pHMap = new long[ nWidth + 2 ];
+ long* pVMap = new long[ nHeight + 2 ];
+ long nX, nY, nNx, nNy, nDotL;
+ const long nLx = FRound( cos( fAzim ) * cos( fElev ) * 255.0 );
+ const long nLy = FRound( sin( fAzim ) * cos( fElev ) * 255.0 );
+ const long nLz = FRound( sin( fElev ) * 255.0 );
+ const long nZ2 = ( ( 6 * 255 ) / 4 ) * ( ( 6 * 255 ) / 4 );
+ const long nNzLz = ( ( 6 * 255 ) / 4 ) * nLz;
+ const BYTE cLz = (BYTE) VOS_BOUND( nLz, 0, 255 );
+
+ // fill mapping tables
+ pHMap[ 0 ] = 0;
+ for( nX = 1; nX <= nWidth; nX++ )
+ pHMap[ nX ] = nX - 1;
+ pHMap[ nWidth + 1 ] = nWidth - 1;
+
+ pVMap[ 0 ] = 0;
+ for( nY = 1; nY <= nHeight; nY++ )
+ pVMap[ nY ] = nY - 1;
+ pVMap[ nHeight + 1 ] = nHeight - 1;
+
+ for( nY = 0; nY < nHeight ; nY++ )
+ {
+ nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
+ nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
+ nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
+ nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
+ nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
+ nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
+ nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
+ nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
+ nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
+
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
+ nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
+
+ if( !nNx && !nNy )
+ aGrey.SetIndex( cLz );
+ else if( ( nDotL = nNx * nLx + nNy * nLy +nNzLz ) < 0 )
+ aGrey.SetIndex( 0 );
+ else
+ {
+ const double fGrey = nDotL / sqrt( nNx * nNx + nNy * nNy + nZ2 );
+ aGrey.SetIndex( (BYTE) VOS_BOUND( fGrey, 0, 255 ) );
+ }
+
+ pWriteAcc->SetPixel( nY, nX, aGrey );
+
+ if( nX < ( nWidth - 1 ) )
+ {
+ const long nNextX = pHMap[ nX + 3 ];
+
+ nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
+ nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
+ nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
+ }
+ }
+ }
+
+ delete[] pHMap;
+ delete[] pVMap;
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSolarize( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = FALSE;
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BYTE cThreshold = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SOLARIZE ) ?
+ pFilterParam->mcSolarGreyThreshold : 128;
+
+ if( pWriteAcc->HasPalette() )
+ {
+ const BitmapPalette& rPal = pWriteAcc->GetPalette();
+
+ for( USHORT i = 0, nCount = rPal.GetEntryCount(); i < nCount; i++ )
+ {
+ if( rPal[ i ].GetLuminance() >= cThreshold )
+ {
+ BitmapColor aCol( rPal[ i ] );
+ pWriteAcc->SetPaletteColor( i, aCol.Invert() );
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol = pWriteAcc->GetPixel( nY, nX );
+
+ if( aCol.GetLuminance() >= cThreshold )
+ pWriteAcc->SetPixel( nY, nX, aCol.Invert() );
+ }
+ }
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSepia( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ long nSepiaPercent = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SEPIA ) ?
+ pFilterParam->mcSolarGreyThreshold : 10;
+ const long nSepia = 10000 - 100 * VOS_BOUND( nSepiaPercent, 0, 100 );
+ BitmapPalette aSepiaPal( 256 );
+
+ DBG_ASSERT( nSepiaPercent <= 100, "Bitmap::ImplSepia(): sepia value out of range; defaulting to 100%" );
+
+ for( long i = 0; i < 256; i++ )
+ {
+ BitmapColor& rCol = aSepiaPal[ i ];
+ const BYTE cSepiaValue = (BYTE) ( ( nSepia * i ) / 10000 );
+
+ rCol.SetRed( (BYTE) i );
+ rCol.SetGreen( cSepiaValue );
+ rCol.SetBlue( cSepiaValue );
+ }
+
+ Bitmap aNewBmp( GetSizePixel(), 8, &aSepiaPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aCol( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ const USHORT nPalCount = pReadAcc->GetPaletteEntryCount();
+ BYTE* pIndexMap = new BYTE[ nPalCount ];
+
+ for( USHORT i = 0; i < nPalCount; i++ )
+ pIndexMap[ i ] = pReadAcc->GetPaletteColor( i ).GetLuminance();
+
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pIndexMap[ pReadAcc->GetPixel( nY, nX ).GetIndex() ] );
+ pWriteAcc->SetPixel( nY, nX, aCol );
+ }
+
+ delete[] pIndexMap;
+ }
+ }
+ else
+ {
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pReadAcc->GetPixel( nY, nX ).GetLuminance() );
+ pWriteAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMosaic( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ ULONG nTileWidth = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
+ pFilterParam->maMosaicTileSize.mnTileWidth : 4;
+ ULONG nTileHeight = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
+ pFilterParam->maMosaicTileSize.mnTileHeight : 4;
+ BOOL bRet = FALSE;
+
+ if( !nTileWidth )
+ nTileWidth = 1;
+
+ if( !nTileHeight )
+ nTileHeight = 1;
+
+ if( nTileWidth > 1 || nTileHeight > 1 )
+ {
+ Bitmap* pNewBmp;
+ BitmapReadAccess* pReadAcc;
+ BitmapWriteAccess* pWriteAcc;
+
+ if( GetBitCount() > 8 )
+ {
+ pNewBmp = NULL;
+ pReadAcc = pWriteAcc = AcquireWriteAccess();
+ }
+ else
+ {
+ pNewBmp = new Bitmap( GetSizePixel(), 24 );
+ pReadAcc = AcquireReadAccess();
+ pWriteAcc = pNewBmp->AcquireWriteAccess();
+ }
+
+ if( pReadAcc && pWriteAcc )
+ {
+ BitmapColor aCol;
+ long nWidth = pReadAcc->Width();
+ long nHeight = pReadAcc->Height();
+ long nX, nY, nX1, nX2, nY1, nY2, nSumR, nSumG, nSumB;
+ double fArea_1;
+
+ nY1 = 0; nY2 = nTileHeight - 1;
+
+ if( nY2 >= nHeight )
+ nY2 = nHeight - 1;
+
+ do
+ {
+ nX1 = 0; nX2 = nTileWidth - 1;
+
+ if( nX2 >= nWidth )
+ nX2 = nWidth - 1;
+
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+
+ if( !pNewBmp )
+ {
+ do
+ {
+ for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
+ {
+ for( nX = nX1; nX <= nX2; nX++ )
+ {
+ aCol = pReadAcc->GetPixel( nY, nX );
+ nSumR += aCol.GetRed();
+ nSumG += aCol.GetGreen();
+ nSumB += aCol.GetBlue();
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
+ aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
+ aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
+
+ for( nY = nY1; nY <= nY2; nY++ )
+ for( nX = nX1; nX <= nX2; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol );
+
+ nX1 += nTileWidth; nX2 += nTileWidth;
+
+ if( nX2 >= nWidth )
+ {
+ nX2 = nWidth - 1;
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+ }
+ }
+ while( nX1 < nWidth );
+ }
+ else
+ {
+ do
+ {
+ for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
+ {
+ for( nX = nX1; nX <= nX2; nX++ )
+ {
+ const BitmapColor& rCol = pReadAcc->GetPaletteColor( (BYTE) pReadAcc->GetPixel( nY, nX ) );
+ nSumR += rCol.GetRed();
+ nSumG += rCol.GetGreen();
+ nSumB += rCol.GetBlue();
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
+ aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
+ aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
+
+ for( nY = nY1; nY <= nY2; nY++ )
+ for( nX = nX1; nX <= nX2; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol );
+
+ nX1 += nTileWidth; nX2 += nTileWidth;
+
+ if( nX2 >= nWidth )
+ {
+ nX2 = nWidth - 1;
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+ }
+ }
+ while( nX1 < nWidth );
+ }
+
+ nY1 += nTileHeight; nY2 += nTileHeight;
+
+ if( nY2 >= nHeight )
+ nY2 = nHeight - 1;
+ }
+ while( nY1 < nHeight );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( pNewBmp )
+ {
+ pNewBmp->ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = *pNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ delete pNewBmp;
+ }
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
new file mode 100644
index 000000000000..a0e388a1db0f
--- /dev/null
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -0,0 +1,690 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmapex.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BITMAPEX_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+
+// ------------
+// - BitmapEx -
+// ------------
+
+BitmapEx::BitmapEx() :
+ eTransparent( TRANSPARENT_NONE ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
+ aBitmap ( rBitmapEx.aBitmap ),
+ aMask ( rBitmapEx.aMask ),
+ aBitmapSize ( rBitmapEx.aBitmapSize ),
+ aTransparentColor ( rBitmapEx.aTransparentColor ),
+ eTransparent ( rBitmapEx.eTransparent ),
+ bAlpha ( rBitmapEx.bAlpha )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp ) :
+ aBitmap ( rBmp ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent( TRANSPARENT_NONE ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
+ aBitmap ( rBmp ),
+ aMask ( rMask ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
+ aBitmap ( rBmp ),
+ aMask ( rAlphaMask.ImplGetBitmap() ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
+ bAlpha ( !rAlphaMask ? FALSE : TRUE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
+ aBitmap ( rBmp ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ aTransparentColor ( rTransparentColor ),
+ eTransparent ( TRANSPARENT_BITMAP ),
+ bAlpha ( FALSE )
+{
+ aMask = aBitmap.CreateMask( aTransparentColor );
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::~BitmapEx()
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
+{
+ if( &rBitmapEx != this )
+ {
+ aBitmap = rBitmapEx.aBitmap;
+ aMask = rBitmapEx.aMask;
+ aBitmapSize = rBitmapEx.aBitmapSize;
+ aTransparentColor = rBitmapEx.aTransparentColor;
+ eTransparent = rBitmapEx.eTransparent;
+ bAlpha = rBitmapEx.bAlpha;
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
+{
+ if( eTransparent != rBitmapEx.eTransparent )
+ return FALSE;
+
+ if( aBitmap != rBitmapEx.aBitmap )
+ return FALSE;
+
+ if( aBitmapSize != rBitmapEx.aBitmapSize )
+ return FALSE;
+
+ if( eTransparent == TRANSPARENT_NONE )
+ return TRUE;
+
+ if( eTransparent == TRANSPARENT_COLOR )
+ return aTransparentColor == rBitmapEx.aTransparentColor;
+
+ return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
+{
+ return( rBmpEx.eTransparent == eTransparent &&
+ rBmpEx.bAlpha == bAlpha &&
+ rBmpEx.aBitmap.IsEqual( aBitmap ) &&
+ rBmpEx.aMask.IsEqual( aMask ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsEmpty() const
+{
+ return( aBitmap.IsEmpty() && aMask.IsEmpty() );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::SetEmpty()
+{
+ aBitmap.SetEmpty();
+ aMask.SetEmpty();
+ eTransparent = TRANSPARENT_NONE;
+ bAlpha = FALSE;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Clear()
+{
+ SetEmpty();
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsTransparent() const
+{
+ return( eTransparent != TRANSPARENT_NONE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsAlpha() const
+{
+ return( IsTransparent() && bAlpha );
+}
+
+// ------------------------------------------------------------------
+
+Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
+{
+ Bitmap aRetBmp( aBitmap );
+
+ if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
+ {
+ Bitmap aTempMask;
+
+ if( eTransparent == TRANSPARENT_COLOR )
+ aTempMask = aBitmap.CreateMask( aTransparentColor );
+ else
+ aTempMask = aMask;
+
+ if( !IsAlpha() )
+ aRetBmp.Replace( aTempMask, *pTransReplaceColor );
+ else
+ aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
+ }
+
+ return aRetBmp;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap BitmapEx::GetMask() const
+{
+ Bitmap aRet( aMask );
+
+ if( IsAlpha() )
+ aRet.ImplMakeMono( 255 );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------
+
+AlphaMask BitmapEx::GetAlpha() const
+{
+ AlphaMask aAlpha;
+
+ if( IsAlpha() )
+ aAlpha.ImplSetBitmap( aMask );
+ else
+ aAlpha = aMask;
+
+ return aAlpha;
+}
+
+// ------------------------------------------------------------------
+
+ULONG BitmapEx::GetSizeBytes() const
+{
+ ULONG nSizeBytes = aBitmap.GetSizeBytes();
+
+ if( eTransparent == TRANSPARENT_BITMAP )
+ nSizeBytes += aMask.GetSizeBytes();
+
+ return nSizeBytes;
+}
+
+// ------------------------------------------------------------------
+
+ULONG BitmapEx::GetChecksum() const
+{
+ sal_uInt32 nCrc = aBitmap.GetChecksum();
+ SVBT32 aBT32;
+
+ LongToSVBT32( (long) eTransparent, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) bAlpha, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
+ {
+ LongToSVBT32( aMask.GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+
+ return nCrc;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::SetSizePixel( const Size& rNewSize )
+{
+ Scale( rNewSize );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Invert()
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Invert();
+
+ if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
+ aTransparentColor = BitmapColor( aTransparentColor ).Invert();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Mirror( ULONG nMirrorFlags )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Mirror( nMirrorFlags );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Mirror( nMirrorFlags );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL BitmapEx::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ BOOL bRet;
+
+ if( aBitmapSize.Width() && aBitmapSize.Height() )
+ {
+ bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
+ (double) rNewSize.Height() / aBitmapSize.Height(),
+ nScaleFlag );
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ const BOOL bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
+
+ if( bTransRotate )
+ {
+ if( eTransparent == TRANSPARENT_COLOR )
+ bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
+ else
+ {
+ bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
+
+ if( eTransparent == TRANSPARENT_NONE )
+ {
+ aMask = Bitmap( aBitmapSize, 1 );
+ aMask.Erase( COL_BLACK );
+ eTransparent = TRANSPARENT_BITMAP;
+ }
+
+ if( bRet && !!aMask )
+ aMask.Rotate( nAngle10, COL_WHITE );
+ }
+ }
+ else
+ {
+ bRet = aBitmap.Rotate( nAngle10, rFillColor );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Rotate( nAngle10, COL_WHITE );
+ }
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Crop( const Rectangle& rRectPixel )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Crop( rRectPixel );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Crop( rRectPixel );
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Convert( BmpConversion eConversion )
+{
+ return( !!aBitmap ? aBitmap.Convert( eConversion ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::ReduceColors( USHORT nNewColorCount, BmpReduce eReduce )
+{
+ return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Expand( ULONG nDX, ULONG nDY, const Color* pInitColor, BOOL bExpandTransparent )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Expand( nDX, nDY, pInitColor );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ {
+ Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
+ aMask.Expand( nDX, nDY, &aColor );
+ }
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ return( !!aBitmap ? aBitmap.Dither( nDitherFlags, pDitherPal ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, ULONG nColorCount, const ULONG* pTols )
+{
+ return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (ULONG*) pTols ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, *this );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
+{
+ rBitmapEx.aBitmap.Write( rOStm );
+
+ rOStm << (UINT32) 0x25091962;
+ rOStm << (UINT32) 0xACB20201;
+ rOStm << (BYTE) rBitmapEx.eTransparent;
+
+ if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
+ rBitmapEx.aMask.Write( rOStm );
+ else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
+ rOStm << rBitmapEx.aTransparentColor;
+
+ return rOStm;
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
+{
+ Bitmap aBmp;
+
+ rIStm >> aBmp;
+
+ if( !rIStm.GetError() )
+ {
+ const ULONG nStmPos = rIStm.Tell();
+ UINT32 nMagic1;
+ UINT32 nMagic2;
+
+ rIStm >> nMagic1 >> nMagic2;
+
+ if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
+ {
+ rIStm.Seek( nStmPos );
+ rBitmapEx = aBmp;
+ }
+ else
+ {
+ BYTE bTransparent;
+
+ rIStm >> bTransparent;
+
+ if( bTransparent == (BYTE) TRANSPARENT_BITMAP )
+ {
+ Bitmap aMask;
+
+ rIStm >> aMask;
+
+ if( !!aMask)
+ {
+ // do we have an alpha mask?
+ if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
+ {
+ AlphaMask aAlpha;
+
+ // create alpha mask quickly (without greyscale conversion)
+ aAlpha.ImplSetBitmap( aMask );
+ rBitmapEx = BitmapEx( aBmp, aAlpha );
+ }
+ else
+ rBitmapEx = BitmapEx( aBmp, aMask );
+ }
+ else
+ rBitmapEx = aBmp;
+ }
+ else if( bTransparent == (BYTE) TRANSPARENT_COLOR )
+ {
+ Color aTransparentColor;
+
+ rIStm >> aTransparentColor;
+ rBitmapEx = BitmapEx( aBmp, aTransparentColor );
+ }
+ else
+ rBitmapEx = aBmp;
+ }
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+void BitmapEx::ImplDrawRemote( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( !!aBitmap )
+ {
+ switch( eTransparent )
+ {
+ case( TRANSPARENT_NONE ):
+ aBitmap.ImplDrawRemote( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ break;
+
+ case( TRANSPARENT_BITMAP ):
+ {
+ if( !!aMask )
+ {
+ if( IsAlpha() )
+ aBitmap.ImplDrawRemoteAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, GetAlpha() );
+ else
+ aBitmap.ImplDrawRemoteEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, aMask );
+ }
+ else
+ aBitmap.ImplDrawRemote( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ }
+ break;
+
+ default:
+ {
+ DBG_ERROR( "BitmapEx::ImplDrawRemote???" );
+ }
+ break;
+ }
+ }
+}
+
+#endif // REMOTE
diff --git a/vcl/source/gdi/bmpacc.cxx b/vcl/source/gdi/bmpacc.cxx
new file mode 100644
index 000000000000..6fc3657c90fd
--- /dev/null
+++ b/vcl/source/gdi/bmpacc.cxx
@@ -0,0 +1,448 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC_CXX
+
+#ifdef W31
+#include <tools/svwin.h>
+#endif
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#include <string.h>
+
+// --------------------
+// - BitmapReadAccess -
+// --------------------
+
+BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, BOOL bModify ) :
+ mpBuffer ( NULL ),
+ mpScanBuf ( NULL ),
+ mbModify ( bModify ),
+ mFncGetPixel ( NULL ),
+ mFncSetPixel ( NULL )
+{
+ ImplCreate( rBitmap );
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
+ mpBuffer ( NULL ),
+ mpScanBuf ( NULL ),
+ mbModify ( FALSE ),
+ mFncGetPixel ( NULL ),
+ mFncSetPixel ( NULL )
+{
+ ImplCreate( rBitmap );
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess::~BitmapReadAccess()
+{
+ ImplDestroy();
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
+{
+ ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
+
+ BMP_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
+
+ if( pImpBmp )
+ {
+ if( mbModify && !maBitmap.ImplGetImpBitmap() )
+ {
+ rBitmap.ImplMakeUnique();
+ pImpBmp = rBitmap.ImplGetImpBitmap();
+ }
+ else
+ {
+ BMP_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
+ "Unpredictable results: bitmap is referenced more than once!" );
+ }
+
+ mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
+
+ if( !mpBuffer )
+ {
+ ImpBitmap* pNewImpBmp = new ImpBitmap;
+
+ if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
+ {
+ pImpBmp = pNewImpBmp;
+ rBitmap.ImplSetImpBitmap( pImpBmp );
+ mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
+ }
+ else
+ delete pNewImpBmp;
+ }
+
+ if( mpBuffer )
+ {
+ const long nHeight = mpBuffer->mnHeight;
+ Scanline pTmpLine = mpBuffer->mpBits;
+
+ mpScanBuf = new Scanline[ nHeight ];
+ maColorMask = mpBuffer->maColorMask;
+
+ if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ {
+ for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
+ mpScanBuf[ nY ] = pTmpLine;
+ }
+ else
+ {
+ for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
+ mpScanBuf[ nY ] = pTmpLine;
+ }
+
+ if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
+ {
+ delete[] mpScanBuf;
+ mpScanBuf = NULL;
+
+ pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
+ mpBuffer = NULL;
+ }
+ else
+ maBitmap = rBitmap;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplDestroy()
+{
+ ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
+
+ delete[] mpScanBuf;
+ mpScanBuf = NULL;
+
+ if( mpBuffer && pImpBmp )
+ {
+ pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
+ mpBuffer = NULL;
+ }
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapReadAccess::ImplSetAccessPointers( ULONG nFormat )
+{
+ BOOL bRet = TRUE;
+
+ switch( nFormat )
+ {
+ CASE_FORMAT( _1BIT_MSB_PAL )
+ CASE_FORMAT( _1BIT_LSB_PAL )
+ CASE_FORMAT( _4BIT_MSN_PAL )
+ CASE_FORMAT( _4BIT_LSN_PAL )
+ CASE_FORMAT( _8BIT_PAL )
+ CASE_FORMAT( _8BIT_TC_MASK )
+ CASE_FORMAT( _16BIT_TC_MASK )
+ CASE_FORMAT( _24BIT_TC_BGR )
+ CASE_FORMAT( _24BIT_TC_RGB )
+ CASE_FORMAT( _24BIT_TC_MASK )
+ CASE_FORMAT( _32BIT_TC_ABGR )
+ CASE_FORMAT( _32BIT_TC_ARGB )
+ CASE_FORMAT( _32BIT_TC_BGRA )
+ CASE_FORMAT( _32BIT_TC_RGBA )
+ CASE_FORMAT( _32BIT_TC_MASK )
+
+ default:
+ bRet = FALSE;
+ break;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplZeroInitUnusedBits()
+{
+ const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
+
+ if( nWidth && nHeight && nScanSize && GetBuffer() )
+ {
+ DBG_ASSERT( !( nScanSize % 4 ), "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported scanline alignment" );
+
+ sal_uInt32 nBits;
+
+ switch( GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ nBits = 1;
+ break;
+
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ nBits = 4;
+ break;
+
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_8BIT_TC_MASK ):
+ nBits = 8;
+ break;
+
+ case( BMP_FORMAT_16BIT_TC_MASK ):
+ nBits = 16;
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ case( BMP_FORMAT_24BIT_TC_MASK ):
+ nBits = 24;
+ break;
+
+ case( BMP_FORMAT_32BIT_TC_ABGR ):
+ case( BMP_FORMAT_32BIT_TC_ARGB ):
+ case( BMP_FORMAT_32BIT_TC_BGRA ):
+ case( BMP_FORMAT_32BIT_TC_RGBA ):
+ case( BMP_FORMAT_32BIT_TC_MASK ):
+ nBits = 32;
+ break;
+
+ default:
+ {
+ DBG_ERROR( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format" );
+ nBits = 0;
+ }
+ break;
+ }
+
+ if( ( nBits *= nWidth ) & 0x1f )
+ {
+ sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
+ BYTE* pLast4Bytes = (BYTE*) GetBuffer() + ( nScanSize - 4 );
+
+#ifdef __LITTLEENDIAN
+ nMask = SWAPLONG( nMask );
+#endif
+ for( long i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
+ ( *(long*) pLast4Bytes ) &= nMask;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::Flush()
+{
+ ImplDestroy();
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ReAccess( BOOL bModify )
+{
+ const ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
+
+ BMP_ASSERT( !mpBuffer, "No ReAccess possible while bitmap is being accessed!" );
+ BMP_ASSERT( pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ), "Accessed bitmap does not exist anymore!" );
+
+ if( !mpBuffer && pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ) )
+ {
+ mbModify = bModify;
+ ImplCreate( maBitmap );
+ }
+}
+
+// ------------------------------------------------------------------
+
+USHORT BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
+{
+ return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
+}
+
+// ---------------------
+// - BitmapWriteAccess -
+// ---------------------
+
+BitmapWriteAccess::~BitmapWriteAccess()
+{
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::ImplInitDraw()
+{
+ if( HasPalette() )
+ {
+ if( !maLineColor.IsIndex() )
+ maLineColor = (BYTE) GetBestPaletteIndex( maLineColor );
+
+ if( !maFillColor.IsIndex() )
+ maFillColor = (BYTE) GetBestPaletteIndex( maFillColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
+{
+ BMP_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
+ BMP_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
+ BMP_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
+
+ if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
+ ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
+ {
+ HMEMCPY( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
+ }
+ else
+ for( long nX = 0L, nWidth = Min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
+ SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyScanline( long nY, const Scanline aSrcScanline,
+ ULONG nSrcScanlineFormat, ULONG nSrcScanlineSize )
+{
+ const ULONG nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
+
+ BMP_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
+ BMP_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
+ ( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
+ "No copying possible between palette and non palette scanlines!" );
+
+ const ULONG nCount = Min( GetScanlineSize(), nSrcScanlineSize );
+
+ if( nCount )
+ {
+ if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
+ HMEMCPY( mpScanBuf[ nY ], aSrcScanline, nCount );
+ else
+ {
+ BMP_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK && nFormat != BMP_FORMAT_16BIT_TC_MASK &&
+ nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
+ "No support for pixel formats with color masks yet!" );
+
+ FncGetPixel pFncGetPixel;
+
+ switch( nFormat )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
+ case( BMP_FORMAT_1BIT_LSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
+ case( BMP_FORMAT_4BIT_MSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
+ case( BMP_FORMAT_4BIT_LSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
+ case( BMP_FORMAT_8BIT_PAL ): pFncGetPixel = GetPixelFor_8BIT_PAL; break;
+ case( BMP_FORMAT_8BIT_TC_MASK ): pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
+ case( BMP_FORMAT_16BIT_TC_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_MASK; break;
+ case( BMP_FORMAT_24BIT_TC_BGR ): pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
+ case( BMP_FORMAT_24BIT_TC_RGB ): pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
+ case( BMP_FORMAT_24BIT_TC_MASK ): pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
+ case( BMP_FORMAT_32BIT_TC_ABGR ): pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
+ case( BMP_FORMAT_32BIT_TC_ARGB ): pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
+ case( BMP_FORMAT_32BIT_TC_BGRA ): pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
+ case( BMP_FORMAT_32BIT_TC_RGBA ): pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
+ case( BMP_FORMAT_32BIT_TC_MASK ): pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
+
+ default:
+ pFncGetPixel = NULL;
+ break;
+ }
+
+ if( pFncGetPixel )
+ {
+ const ColorMask aDummyMask;
+
+ for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
+ SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
+ }
+ }
+ }
+}
+
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
+{
+ BMP_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
+
+ if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
+ ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
+ {
+ const long nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() );
+ const ULONG nCount = nHeight * mpBuffer->mnScanlineSize;
+
+ HMEMCPY( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
+ }
+ else
+ for( long nY = 0L, nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
+ CopyScanline( nY, rReadAcc );
+}
diff --git a/vcl/source/gdi/bmpacc2.cxx b/vcl/source/gdi/bmpacc2.cxx
new file mode 100644
index 000000000000..a07f58815a88
--- /dev/null
+++ b/vcl/source/gdi/bmpacc2.cxx
@@ -0,0 +1,353 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC2_CXX
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+
+// ----------------
+// - BitmapAccess -
+// ----------------
+
+IMPL_FORMAT_GETPIXEL( _1BIT_MSB_PAL )
+{
+ return( pScanline[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _1BIT_MSB_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 3 ];
+
+ ( rBitmapColor.GetIndex() & 1 ) ? ( rByte |= 1 << ( 7 - ( nX & 7 ) ) ) :
+ ( rByte &= ~( 1 << ( 7 - ( nX & 7 ) ) ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _1BIT_LSB_PAL )
+{
+ return( pScanline[ nX >> 3 ] & ( 1 << ( nX & 7 ) ) ? 1 : 0 );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _1BIT_LSB_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 3 ];
+
+ ( rBitmapColor.GetIndex() & 1 ) ? ( rByte |= 1 << ( nX & 7 ) ) :
+ ( rByte &= ~( 1 << ( nX & 7 ) ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _4BIT_MSN_PAL )
+{
+ return( ( pScanline[ nX >> 1 ] >> ( nX & 1 ? 0 : 4 ) ) & 0x0f );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _4BIT_MSN_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 1 ];
+
+ ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( rBitmapColor.GetIndex() & 0x0f ) ) :
+ ( rByte &= 0x0f, rByte |= ( rBitmapColor.GetIndex() << 4 ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _4BIT_LSN_PAL )
+{
+ return( ( pScanline[ nX >> 1 ] >> ( nX & 1 ? 4 : 0 ) ) & 0x0f );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _4BIT_LSN_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 1 ];
+
+ ( nX & 1 ) ? ( rByte &= 0x0f, rByte |= ( rBitmapColor.GetIndex() << 4 ) ) :
+ ( rByte &= 0xf0, rByte |= ( rBitmapColor.GetIndex() & 0x0f ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _8BIT_PAL )
+{
+ return pScanline[ nX ];
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _8BIT_PAL )
+{
+ pScanline[ nX ] = rBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _8BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor8Bit( aColor, pScanline + nX );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _8BIT_TC_MASK )
+{
+ rMask.SetColorFor8Bit( rBitmapColor, pScanline + nX );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _16BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor16Bit( aColor, pScanline + ( nX << 1UL ) );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _16BIT_TC_MASK )
+{
+ rMask.SetColorFor16Bit( rBitmapColor, pScanline + ( nX << 1UL ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_BGR )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + nX * 3 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_BGR )
+{
+ *( pScanline = pScanline + nX * 3 )++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_RGB )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + nX * 3 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_RGB )
+{
+ *( pScanline = pScanline + nX * 3 )++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor24Bit( aColor, pScanline + nX * 3L );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_MASK )
+{
+ rMask.SetColorFor24Bit( rBitmapColor, pScanline + nX * 3L );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_ABGR )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + ( nX << 2 ) + 1 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_ABGR )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = 0;
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_ARGB )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + ( nX << 2 ) + 1 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_ARGB )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = 0;
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_BGRA )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + ( nX << 2 ) )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_BGRA )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline = 0;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_RGBA )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + ( nX << 2 ) )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_RGBA )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline = 0;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor32Bit( aColor, pScanline + ( nX << 2UL ) );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_MASK )
+{
+ rMask.SetColorFor32Bit( rBitmapColor, pScanline + ( nX << 2UL ) );
+}
diff --git a/vcl/source/gdi/bmpacc3.cxx b/vcl/source/gdi/bmpacc3.cxx
new file mode 100644
index 000000000000..c26de8c7ecfa
--- /dev/null
+++ b/vcl/source/gdi/bmpacc3.cxx
@@ -0,0 +1,351 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC_CXX
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+
+// ---------------------
+// - BitmapWriteAccess -
+// ---------------------
+
+void BitmapWriteAccess::Erase( const Color& rColor )
+{
+ const BitmapColor aOldFillColor( maFillColor );
+ const Point aPoint;
+ const Rectangle aRect( aPoint, maBitmap.GetSizePixel() );
+
+ SetFillColor( rColor );
+ FillRect( aRect );
+ maFillColor = aOldFillColor;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawLine( const Point& rStart, const Point& rEnd )
+{
+ long nX;
+ long nY;
+
+ ImplInitDraw();
+
+ if ( rStart.X() == rEnd.X() )
+ {
+ // vertikale Line
+ const long nEndY = rEnd.Y();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if ( nEndY > nY )
+ {
+ for (; nY <= nEndY; nY++ )
+ SetPixel( nY, nX, maLineColor );
+ }
+ else
+ {
+ for (; nY >= nEndY; nY-- )
+ SetPixel( nY, nX, maLineColor );
+ }
+ }
+ else if ( rStart.Y() == rEnd.Y() )
+ {
+ // horizontale Line
+ const long nEndX = rEnd.X();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if ( nEndX > nX )
+ {
+ for (; nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maLineColor );
+ }
+ else
+ {
+ for (; nX >= nEndX; nX-- )
+ SetPixel( nY, nX, maLineColor );
+ }
+ }
+ else
+ {
+ const long nDX = labs( rEnd.X() - rStart.X() );
+ const long nDY = labs( rEnd.Y() - rStart.Y() );
+ long nX1;
+ long nY1;
+ long nX2;
+ long nY2;
+
+ if ( nDX >= nDY )
+ {
+ if ( rStart.X() < rEnd.X() )
+ {
+ nX1 = rStart.X();
+ nY1 = rStart.Y();
+ nX2 = rEnd.X();
+ nY2 = rEnd.Y();
+ }
+ else
+ {
+ nX1 = rEnd.X();
+ nY1 = rEnd.Y();
+ nX2 = rStart.X();
+ nY2 = rStart.Y();
+ }
+
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+ BOOL bPos = nY1 < nY2;
+
+ for ( nX = nX1, nY = nY1; nX <= nX2; nX++ )
+ {
+ SetPixel( nY, nX, maLineColor );
+
+ if ( nD < 0 )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+
+ if ( bPos )
+ nY++;
+ else
+ nY--;
+ }
+ }
+ }
+ else
+ {
+ if ( rStart.Y() < rEnd.Y() )
+ {
+ nX1 = rStart.X();
+ nY1 = rStart.Y();
+ nX2 = rEnd.X();
+ nY2 = rEnd.Y();
+ }
+ else
+ {
+ nX1 = rEnd.X();
+ nY1 = rEnd.Y();
+ nX2 = rStart.X();
+ nY2 = rStart.Y();
+ }
+
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+ BOOL bPos = nX1 < nX2;
+
+ for ( nX = nX1, nY = nY1; nY <= nY2; nY++ )
+ {
+ SetPixel( nY, nX, maLineColor );
+
+ if ( nD < 0 )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+
+ if ( bPos )
+ nX++;
+ else
+ nX--;
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawRect( const Rectangle& rRect )
+{
+ ImplInitDraw();
+ FillRect( rRect );
+ DrawLine( rRect.TopLeft(), rRect.TopRight() );
+ DrawLine( rRect.TopRight(), rRect.BottomRight() );
+ DrawLine( rRect.BottomRight(), rRect.BottomLeft() );
+ DrawLine( rRect.BottomLeft(), rRect.TopLeft() );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::FillRect( const Rectangle& rRect )
+{
+ Point aPoint;
+ Rectangle aRect( aPoint, maBitmap.GetSizePixel() );
+
+ aRect.Intersection( rRect );
+
+ if( !aRect.IsEmpty() )
+ {
+ const long nStartX = rRect.TopLeft().X();
+ const long nStartY = rRect.TopLeft().Y();
+ const long nEndX = rRect.BottomRight().X();
+ const long nEndY = rRect.BottomRight().Y();
+
+ ImplInitDraw();
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolygon( const Polygon& rPoly )
+{
+ const USHORT nSize = rPoly.GetSize();
+
+ if( nSize )
+ {
+ Region aRegion( rPoly );
+ Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+
+ ImplInitDraw();
+
+ while( aRegion.GetNextEnumRect( aRegHandle, aRect ) )
+ for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+
+ aRegion.EndEnumRects( aRegHandle );
+ }
+
+ if( maLineColor != maFillColor )
+ {
+ for( USHORT i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ const USHORT nCount = rPolyPoly.Count();
+
+ if( nCount )
+ {
+ Region aRegion( rPolyPoly );
+ Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+
+ ImplInitDraw();
+
+ while( aRegion.GetNextEnumRect( aRegHandle, aRect ) )
+ for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+
+ aRegion.EndEnumRects( aRegHandle );
+ }
+
+ if( maLineColor != maFillColor )
+ {
+ for( USHORT n = 0; n < nCount; )
+ {
+ const Polygon& rPoly = rPolyPoly[ n++ ];
+ const USHORT nSize = rPoly.GetSize();
+
+ if( nSize )
+ {
+ for( USHORT i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+ }
+ }
+ }
+}
diff --git a/vcl/source/gdi/cvtgrf.cxx b/vcl/source/gdi/cvtgrf.cxx
new file mode 100644
index 000000000000..1005cf3396d5
--- /dev/null
+++ b/vcl/source/gdi/cvtgrf.cxx
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * $RCSfile: cvtgrf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CVTGRF_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+
+// --------------
+// - Callback -
+// --------------
+
+#ifndef REMOTE_APPSERVER
+
+ULONG ImplFilterCallback( void* pInst,
+ ULONG nInFormat, void* pInBuffer, ULONG nInBufSize,
+ ULONG nOutFormat, void** ppOutBuffer )
+{
+ return( ( (GraphicConverter*) pInst )->ImplConvert( nInFormat,
+ pInBuffer, nInBufSize,
+ ppOutBuffer, nOutFormat ) );
+}
+
+#endif
+
+// --------------------
+// - GraphicConverter -
+// --------------------
+
+GraphicConverter::GraphicConverter() :
+ mpConvertData( NULL )
+{
+#ifndef REMOTE_APPSERVER
+ SetFilterCallback( ImplFilterCallback, this );
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GraphicConverter::~GraphicConverter()
+{
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::ImplConvert( ULONG nInFormat, void* pInBuffer, ULONG nInBufSize,
+ void** ppOutBuffer, ULONG nOutFormat )
+{
+ ULONG nRetBufSize = 0UL;
+
+ if( ( nInFormat != nOutFormat ) && pInBuffer )
+ {
+ if( ( nInFormat == CVT_SVM ) || ( nInFormat == CVT_BMP ) )
+ {
+ SvMemoryStream aIStm;
+ Graphic aGraphic;
+
+ aIStm.SetBuffer( (char*) pInBuffer, nInBufSize, FALSE, nInBufSize );
+ aIStm >> aGraphic;
+
+ if( !aIStm.GetError() )
+ {
+ SvMemoryStream aOStm( 64535, 64535 );
+
+ mpConvertData = new ConvertData( aGraphic, aOStm, nOutFormat );
+
+ if( maFilterHdl.IsSet() && maFilterHdl.Call( mpConvertData ) )
+ {
+ nRetBufSize = aOStm.Seek( STREAM_SEEK_TO_END );
+ *ppOutBuffer = (void*) aOStm.GetData();
+ aOStm.ObjectOwnsMemory( FALSE );
+ }
+
+ delete mpConvertData;
+ mpConvertData = NULL;
+ }
+ }
+ else if( ( nOutFormat == CVT_SVM ) || ( nOutFormat == CVT_BMP ) )
+ {
+ SvMemoryStream aIStm;
+
+ aIStm.SetBuffer( (char*) pInBuffer, nInBufSize, FALSE, nInBufSize );
+ mpConvertData = new ConvertData( Graphic(), aIStm, nInFormat );
+
+ if( maFilterHdl.IsSet() && maFilterHdl.Call( mpConvertData ) )
+ {
+ SvMemoryStream aOStm( 645535, 64535 );
+ Graphic& rGraphic = mpConvertData->maGraphic;
+
+ if( ( rGraphic.GetType() == GRAPHIC_BITMAP ) && ( CVT_SVM == nOutFormat ) )
+ {
+ GDIMetaFile aMtf;
+
+ aMtf.SetPrefSize( rGraphic.GetPrefSize() );
+ aMtf.SetPrefMapMode( rGraphic.GetPrefMapMode() );
+ aMtf.AddAction( new MetaBmpExScaleAction( Point(), aMtf.GetPrefSize(), rGraphic.GetBitmapEx() ) );
+ rGraphic = aMtf;
+ }
+ else if( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && ( CVT_BMP == nOutFormat ) )
+ rGraphic = rGraphic.GetBitmapEx();
+
+ aOStm << rGraphic;
+
+ if( !aOStm.GetError() )
+ {
+ nRetBufSize = aOStm.Seek( STREAM_SEEK_TO_END );
+ *ppOutBuffer = (void*) aOStm.GetData();
+ aOStm.ObjectOwnsMemory( FALSE );
+ }
+ }
+
+ delete mpConvertData;
+ mpConvertData = NULL;
+ }
+ }
+
+ return nRetBufSize;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::Import( SvStream& rIStm, Graphic& rGraphic, ULONG nFormat )
+{
+ GraphicConverter* pCvt = ImplGetSVData()->maGDIData.mpGrfConverter;
+ ULONG nRet = ERRCODE_IO_GENERAL;
+
+ if( pCvt && pCvt->GetFilterHdl().IsSet() )
+ {
+ ConvertData aData( rGraphic, rIStm, nFormat );
+
+ if( pCvt->GetFilterHdl().Call( &aData ) )
+ {
+ rGraphic = aData.maGraphic;
+ nRet = ERRCODE_NONE;
+ }
+ else if( rIStm.GetError() )
+ nRet = rIStm.GetError();
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::Export( SvStream& rOStm, const Graphic& rGraphic, ULONG nFormat )
+{
+ GraphicConverter* pCvt = ImplGetSVData()->maGDIData.mpGrfConverter;
+ ULONG nRet = ERRCODE_IO_GENERAL;
+
+ if( pCvt && pCvt->GetFilterHdl().IsSet() )
+ {
+ ConvertData aData( rGraphic, rOStm, nFormat );
+
+ if( pCvt->GetFilterHdl().Call( &aData ) )
+ nRet = ERRCODE_NONE;
+ else if( rOStm.GetError() )
+ nRet = rOStm.GetError();
+ }
+
+ return nRet;
+}
diff --git a/vcl/source/gdi/cvtsvm.cxx b/vcl/source/gdi/cvtsvm.cxx
new file mode 100644
index 000000000000..f2ac9be53d5d
--- /dev/null
+++ b/vcl/source/gdi/cvtsvm.cxx
@@ -0,0 +1,2106 @@
+/*************************************************************************
+ *
+ * $RCSfile: cvtsvm.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CVTSVM_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#include <string.h>
+
+#ifndef _STACK_HXX //autogen
+#include <tools/stack.hxx>
+#endif
+#ifndef _DEBUG_HXX //autogen
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#include <cvtsvm.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define CVTSVM_WRITE_SUBACTIONCOUNT 1
+
+// -----------
+// - Inlines -
+// -----------
+
+void ImplReadRect( SvStream& rIStm, Rectangle& rRect )
+{
+ Point aTL;
+ Point aBR;
+
+ rIStm >> aTL;
+ rIStm >> aBR;
+
+ rRect = Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteRect( SvStream& rOStm, const Rectangle& rRect )
+{
+ rOStm << rRect.TopLeft();
+ rOStm << rRect.BottomRight();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadPoly( SvStream& rIStm, Polygon& rPoly )
+{
+ INT32 nSize;
+
+ rIStm >> nSize;
+ rPoly = Polygon( (USHORT) nSize );
+
+ for( USHORT i = 0; i < (USHORT) nSize; i++ )
+ rIStm >> rPoly[ i ];
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePoly( SvStream& rOStm, const Polygon& rPoly )
+{
+ INT32 nSize = rPoly.GetSize();
+
+ rOStm << nSize;
+
+ for( INT32 i = 0; i < nSize; i++ )
+ rOStm << rPoly[ (USHORT) i ];
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadPolyPoly( SvStream& rIStm, PolyPolygon& rPolyPoly )
+{
+ Polygon aPoly;
+ INT32 nPolyCount;
+
+ rIStm >> nPolyCount;
+
+ for( USHORT i = 0; i < (USHORT) nPolyCount; i++ )
+ {
+ ImplReadPoly( rIStm, aPoly );
+ rPolyPoly.Insert( aPoly );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePolyPolyAction( SvStream& rOStm, const PolyPolygon& rPolyPoly )
+{
+ const USHORT nPoly = rPolyPoly.Count();
+ USHORT nPoints = 0;
+ USHORT n;
+
+ for( n = 0; n < nPoly; n++ )
+ nPoints += rPolyPoly[ n ].GetSize();
+
+ rOStm << (INT16) GDI_POLYPOLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoly << 2 ) + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoly;
+
+ for( n = 0; n < nPoly; n++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ n ];
+ const USHORT nSize = rPoly.GetSize();
+
+ rOStm << (INT32) nSize;
+
+ for( USHORT j = 0; j < nSize; j++ )
+ rOStm << rPoly[ j ];
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadColor( SvStream& rIStm, Color& rColor )
+{
+ INT16 nVal;
+
+ rIStm >> nVal; rColor.SetRed( (USHORT) nVal >> 8 );
+ rIStm >> nVal; rColor.SetGreen( (USHORT) nVal >> 8 );
+ rIStm >> nVal; rColor.SetBlue( (USHORT) nVal >> 8 );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteColor( SvStream& rOStm, const Color& rColor )
+{
+ INT16 nVal;
+
+ nVal = ( (INT16) rColor.GetRed() << 8 ) | rColor.GetRed();
+ rOStm << nVal;
+
+ nVal = ( (INT16) rColor.GetGreen() << 8 ) | rColor.GetGreen();
+ rOStm << nVal;
+
+ nVal = ( (INT16) rColor.GetBlue() << 8 ) | rColor.GetBlue();
+ rOStm << nVal;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadMapMode( SvStream& rIStm, MapMode& rMapMode )
+{
+ Point aOrg;
+ INT32 nXNum;
+ INT32 nXDenom;
+ INT32 nYNum;
+ INT32 nYDenom;
+ INT16 nUnit;
+
+ rIStm >> nUnit >> aOrg >> nXNum >> nXDenom >> nYNum >> nYDenom;
+ rMapMode = MapMode( (MapUnit) nUnit, aOrg, Fraction( nXNum, nXDenom ), Fraction( nYNum, nYDenom ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteMapMode( SvStream& rOStm, const MapMode& rMapMode )
+{
+ rOStm << (INT16) rMapMode.GetMapUnit();
+ rOStm << rMapMode.GetOrigin();
+ rOStm << (INT32) rMapMode.GetScaleX().GetNumerator();
+ rOStm << (INT32) rMapMode.GetScaleX().GetDenominator();
+ rOStm << (INT32) rMapMode.GetScaleY().GetNumerator();
+ rOStm << (INT32) rMapMode.GetScaleY().GetDenominator();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePushAction( SvStream& rOStm )
+{
+ rOStm << (INT16) GDI_PUSH_ACTION;
+ rOStm << (INT32) 4;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePopAction( SvStream& rOStm )
+{
+ rOStm << (INT16) GDI_POP_ACTION;
+ rOStm << (INT32) 4;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteLineColor( SvStream& rOStm, const Color& rColor, INT16 nStyle, INT32 nWidth = 0L )
+{
+ if( rColor.GetTransparency() > 127 )
+ nStyle = 0;
+
+ rOStm << (INT16) GDI_PEN_ACTION;
+ rOStm << (INT32) 16;
+ ImplWriteColor( rOStm, rColor );
+ rOStm << nWidth;
+ rOStm << nStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteFillColor( SvStream& rOStm, const Color& rColor, INT16 nStyle )
+{
+ rOStm << (INT16) GDI_FILLBRUSH_ACTION;
+ rOStm << (INT32) 20;
+ ImplWriteColor( rOStm, rColor );
+
+ if( rColor.GetTransparency() > 127 )
+ nStyle = 0;
+
+ if( nStyle > 1 )
+ {
+ ImplWriteColor( rOStm, COL_WHITE );
+ rOStm << nStyle;
+ rOStm << (INT16) 1;
+ }
+ else
+ {
+ ImplWriteColor( rOStm, COL_BLACK );
+ rOStm << nStyle;
+ rOStm << (INT16) 0;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteFont( SvStream& rOStm, const Font& rFont,
+ rtl_TextEncoding& rActualCharSet )
+{
+ char aName[32];
+ short nWeight;
+
+ ByteString aByteName( rFont.GetName(), rOStm.GetStreamCharSet() );
+ strncpy( aName, aByteName.GetBuffer(), 32 );
+
+ switch ( rFont.GetWeight() )
+ {
+ case WEIGHT_THIN:
+ case WEIGHT_ULTRALIGHT:
+ case WEIGHT_LIGHT:
+ nWeight = 1;
+ break;
+
+ case WEIGHT_NORMAL:
+ case WEIGHT_MEDIUM:
+ nWeight = 2;
+ break;
+
+ case WEIGHT_BOLD:
+ case WEIGHT_ULTRABOLD:
+ case WEIGHT_BLACK:
+ nWeight = 3;
+ break;
+
+ default:
+ nWeight = 0;
+ break;
+ }
+
+ rOStm << (INT16) GDI_FONT_ACTION;
+ rOStm << (INT32) 78;
+
+ rActualCharSet = GetStoreCharSet( rFont.GetCharSet(), rOStm.GetVersion() );
+ ImplWriteColor( rOStm, rFont.GetColor() );
+ ImplWriteColor( rOStm, rFont.GetFillColor() );
+ rOStm.Write( aName, 32 );
+ rOStm << rFont.GetSize();
+ rOStm << (INT16) 0; // no character orientation anymore
+ rOStm << (INT16) rFont.GetOrientation();
+ rOStm << (INT16) rActualCharSet;
+ rOStm << (INT16) rFont.GetFamily();
+ rOStm << (INT16) rFont.GetPitch();
+ rOStm << (INT16) rFont.GetAlign();
+ rOStm << (INT16) nWeight;
+ rOStm << (INT16) rFont.GetUnderline();
+ rOStm << (INT16) rFont.GetStrikeout();
+ rOStm << (BOOL) ( rFont.GetItalic() != ITALIC_NONE );
+ rOStm << rFont.IsOutline();
+ rOStm << rFont.IsShadow();
+ rOStm << rFont.IsTransparent();
+ if ( rActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ rActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteRasterOpAction( SvStream& rOStm, INT16 nRasterOp )
+{
+ rOStm << (INT16) GDI_RASTEROP_ACTION << (INT32) 6 << nRasterOp;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplSkipActions( SvStream& rIStm, ULONG nSkipCount )
+{
+ INT32 nActionSize;
+ INT16 nType;
+
+ for( ULONG i = 0UL; i < nSkipCount; i++ )
+ {
+ rIStm >> nType >> nActionSize;
+ rIStm.SeekRel( nActionSize - 4L );
+ }
+}
+
+// ----------------
+// - SVMConverter -
+// ----------------
+
+SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf, ULONG nConvertMode )
+{
+ if( !rStm.GetError() )
+ {
+ if( CONVERT_FROM_SVM1 == nConvertMode )
+ ImplConvertFromSVM1( rStm, rMtf );
+ else if( CONVERT_TO_SVM1 == nConvertMode )
+ ImplConvertToSVM1( rStm, rMtf );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
+{
+ LineInfo aLineInfo( LINE_NONE, 0 );
+ Stack aLIStack;
+ ULONG nPos = rIStm.Tell();
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding();
+ BOOL bFatLine = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ char aCode[ 5 ];
+ MapMode aMapMode;
+ Size aPrefSz;
+ INT32 nActions;
+ INT16 nSize;
+ INT16 nVersion;
+
+ // Header lesen
+ rIStm.Read( (char*) &aCode, sizeof( aCode ) ); // Kennung
+ rIStm >> nSize; // Size
+ rIStm >> nVersion; // Version
+ rIStm >> aPrefSz; // PrefSize
+ ImplReadMapMode( rIStm, aMapMode ); // MapMode
+ rIStm >> nActions; // Action count
+
+ // Header-Kennung und Versionsnummer pruefen
+ if( ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 ) || ( nVersion != 200 ) )
+ {
+ rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ rIStm.SetNumberFormatInt( nOldFormat );
+ rIStm.Seek( nPos );
+ }
+ else
+ {
+ Polygon aPoly;
+ Rectangle aRect;
+ Point aPt, aPt1;
+ Size aSz;
+ Color aColor;
+ INT32 nTmp, nTmp1, nActionSize;
+ INT16 nType;
+
+ rMtf.SetPrefSize( aPrefSz );
+ rMtf.SetPrefMapMode( aMapMode );
+
+ for( INT32 i = 0L; i < nActions; i++ )
+ {
+ rIStm >> nType;
+ rIStm >> nActionSize;
+
+ DBG_ASSERT( ( nType <= 33 ) || ( nType >= 1024 ), "Unknown GDIMetaAction while converting!" );
+
+ switch( nType )
+ {
+ case( GDI_PIXEL_ACTION ):
+ {
+ rIStm >> aPt;
+ ImplReadColor( rIStm, aColor );
+ rMtf.AddAction( new MetaPixelAction( aPt, aColor ) );
+ }
+ break;
+
+ case( GDI_POINT_ACTION ):
+ {
+ rIStm >> aPt;
+ rMtf.AddAction( new MetaPointAction( aPt ) );
+ }
+ break;
+
+ case( GDI_LINE_ACTION ):
+ {
+ rIStm >> aPt >> aPt1;
+ rMtf.AddAction( new MetaLineAction( aPt, aPt1, aLineInfo ) );
+ }
+ break;
+
+ case( GDI_RECT_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> nTmp >> nTmp1;
+
+ if( nTmp || nTmp1 )
+ rMtf.AddAction( new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
+ else
+ {
+ rMtf.AddAction( new MetaRectAction( aRect ) );
+
+ if( bFatLine )
+ rMtf.AddAction( new MetaPolyLineAction( aRect, aLineInfo ) );
+ }
+ }
+ break;
+
+ case( GDI_ELLIPSE_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaEllipseAction( aRect ) );
+ }
+ break;
+
+ case( GDI_ARC_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> aPt >> aPt1;
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect, aPt, aPt1, POLY_ARC );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaArcAction( aRect, aPt, aPt1 ) );
+ }
+ break;
+
+ case( GDI_PIE_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> aPt >> aPt1;
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect, aPt, aPt1, POLY_PIE );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPieAction( aRect, aPt, aPt1 ) );
+ }
+ break;
+
+ case( GDI_INVERTRECT_ACTION ):
+ case( GDI_HIGHLIGHTRECT_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rMtf.AddAction( new MetaPushAction( PUSH_RASTEROP ) );
+ rMtf.AddAction( new MetaRasterOpAction( ROP_INVERT ) );
+ rMtf.AddAction( new MetaRectAction( aRect ) );
+ rMtf.AddAction( new MetaPopAction() );
+ }
+ break;
+
+ case( GDI_POLYLINE_ACTION ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+
+ if( bFatLine )
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ else
+ rMtf.AddAction( new MetaPolyLineAction( aPoly ) );
+ }
+ break;
+
+ case( GDI_POLYGON_ACTION ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+
+ if( bFatLine )
+ {
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ }
+ break;
+
+ case( GDI_POLYPOLYGON_ACTION ):
+ {
+ PolyPolygon aPolyPoly;
+
+ ImplReadPolyPoly( rIStm, aPolyPoly );
+
+ if( bFatLine )
+ {
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+
+ for( USHORT nPoly = 0, nCount = aPolyPoly.Count(); nPoly < nCount; nPoly++ )
+ rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ }
+ break;
+
+ case( GDI_FONT_ACTION ):
+ {
+ Font aFont;
+ char aName[ 32 ];
+ INT32 nWidth, nHeight;
+ INT16 nCharSet, nFamily, nPitch, nAlign, nWeight, nUnderline, nStrikeout;
+ INT16 nCharOrient, nLineOrient;
+ BOOL bItalic, bOutline, bShadow, bTransparent;
+
+ ImplReadColor( rIStm, aColor ); aFont.SetColor( aColor );
+ ImplReadColor( rIStm, aColor ); aFont.SetFillColor( aColor );
+ rIStm.Read( aName, 32 );
+ aFont.SetName( UniString( aName, rIStm.GetStreamCharSet() ) );
+ rIStm >> nWidth >> nHeight;
+ rIStm >> nCharOrient >> nLineOrient;
+ rIStm >> nCharSet >> nFamily >> nPitch >> nAlign >> nWeight >> nUnderline >> nStrikeout;
+ rIStm >> bItalic >> bOutline >> bShadow >> bTransparent;
+
+ aFont.SetSize( Size( nWidth, nHeight ) );
+ aFont.SetCharSet( (CharSet) nCharSet );
+ aFont.SetFamily( (FontFamily) nFamily );
+ aFont.SetPitch( (FontPitch) nPitch );
+ aFont.SetAlign( (FontAlign) nAlign );
+ aFont.SetWeight( ( nWeight == 1 ) ? WEIGHT_LIGHT : ( nWeight == 2 ) ? WEIGHT_NORMAL :
+ ( nWeight == 3 ) ? WEIGHT_BOLD : WEIGHT_DONTKNOW );
+ aFont.SetUnderline( (FontUnderline) nUnderline );
+ aFont.SetStrikeout( (FontStrikeout) nStrikeout );
+ aFont.SetItalic( bItalic ? ITALIC_NORMAL : ITALIC_NONE );
+ aFont.SetOutline( bOutline );
+ aFont.SetShadow( bShadow );
+ aFont.SetOrientation( nLineOrient );
+ aFont.SetTransparent( bTransparent );
+
+ eActualCharSet = aFont.GetCharSet();
+ if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eActualCharSet = gsl_getSystemTextEncoding();
+ rMtf.AddAction( new MetaFontAction( aFont ) );
+ }
+ break;
+
+ case( GDI_TEXT_ACTION ):
+ {
+ ByteString aByteStr;
+ INT32 nIndex, nLen;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+ rMtf.AddAction( new MetaTextAction( aPt, aStr, (USHORT) nIndex, (USHORT) nLen ) );
+ }
+ break;
+
+ case( GDI_TEXTARRAY_ACTION ):
+ {
+ ByteString aByteStr;
+ long* pDXAry = NULL;
+ INT32 nIndex, nLen, nAryLen;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp >> nAryLen;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+
+ if( nAryLen > 0L )
+ {
+ pDXAry = new long[ nAryLen ];
+
+ for( long i = 0L; i < nAryLen; i++ )
+ rIStm >> nTmp, pDXAry[ i ] = nTmp;
+ }
+
+ rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, pDXAry, (USHORT) nIndex, (USHORT) nLen ) );
+
+ if( pDXAry )
+ delete[] pDXAry;
+ }
+ break;
+
+ case( GDI_STRETCHTEXT_ACTION ):
+ {
+ ByteString aByteStr;
+ INT32 nIndex, nLen, nWidth;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp >> nWidth;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+ rMtf.AddAction( new MetaStretchTextAction( aPt, nWidth, aStr, (USHORT) nIndex, (USHORT) nLen ) );
+ }
+ break;
+
+ case( GDI_BITMAP_ACTION ):
+ {
+ Bitmap aBmp;
+
+ rIStm >> aPt >> aBmp;
+ rMtf.AddAction( new MetaBmpAction( aPt, aBmp ) );
+ }
+ break;
+
+ case( GDI_BITMAPSCALE_ACTION ):
+ {
+ Bitmap aBmp;
+
+ rIStm >> aPt >> aSz >> aBmp;
+ rMtf.AddAction( new MetaBmpScaleAction( aPt, aSz, aBmp ) );
+ }
+ break;
+
+ case( GDI_BITMAPSCALEPART_ACTION ):
+ {
+ Bitmap aBmp;
+ Size aSz2;
+
+ rIStm >> aPt >> aSz >> aPt1 >> aSz2 >> aBmp;
+ rMtf.AddAction( new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
+ }
+ break;
+
+ case( GDI_PEN_ACTION ):
+ {
+ INT32 nPenWidth;
+ INT16 nPenStyle;
+
+ ImplReadColor( rIStm, aColor );
+ rIStm >> nPenWidth >> nPenStyle;
+
+ aLineInfo.SetStyle( nPenStyle ? LINE_SOLID : LINE_NONE );
+ aLineInfo.SetWidth( nPenWidth );
+ bFatLine = nPenStyle && !aLineInfo.IsDefault();
+
+ rMtf.AddAction( new MetaLineColorAction( aColor, nPenStyle != 0 ) );
+ }
+ break;
+
+ case( GDI_FILLBRUSH_ACTION ):
+ {
+ INT16 nBrushStyle;
+
+ ImplReadColor( rIStm, aColor );
+ rIStm.SeekRel( 6L );
+ rIStm >> nBrushStyle;
+ rMtf.AddAction( new MetaFillColorAction( aColor, nBrushStyle != 0 ) );
+ rIStm.SeekRel( 2L );
+ }
+ break;
+
+ case( GDI_MAPMODE_ACTION ):
+ {
+ ImplReadMapMode( rIStm, aMapMode );
+ rMtf.AddAction( new MetaMapModeAction( aMapMode ) );
+ }
+ break;
+
+ case( GDI_CLIPREGION_ACTION ):
+ {
+ Region aRegion;
+ INT16 nRegType;
+ INT16 bIntersect;
+ BOOL bClip = FALSE;
+
+ rIStm >> nRegType >> bIntersect;
+ ImplReadRect( rIStm, aRect );
+
+ switch( nRegType )
+ {
+ case( 0 ):
+ break;
+
+ case( 1 ):
+ {
+ Rectangle aRegRect;
+
+ ImplReadRect( rIStm, aRegRect );
+ aRegion = Region( aRegRect );
+ bClip = TRUE;
+ }
+ break;
+
+ case( 2 ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+ aRegion = Region( aPoly );
+ bClip = TRUE;
+ }
+ break;
+
+ case( 3 ):
+ {
+ PolyPolygon aPolyPoly;
+ INT32 nPolyCount;
+
+ rIStm >> nPolyCount;
+
+ for( USHORT i = 0; i < (USHORT) nPolyCount; i++ )
+ {
+ ImplReadPoly( rIStm, aPoly );
+ aPolyPoly.Insert( aPoly );
+ }
+
+ aRegion = Region( aPolyPoly );
+ bClip = TRUE;
+ }
+ break;
+ }
+
+ if( bIntersect )
+ aRegion.Intersect( aRect );
+
+ rMtf.AddAction( new MetaClipRegionAction( aRegion, bClip ) );
+ }
+ break;
+
+ case( GDI_MOVECLIPREGION_ACTION ):
+ {
+ rIStm >> nTmp >> nTmp1;
+ rMtf.AddAction( new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
+ }
+ break;
+
+ case( GDI_ISECTCLIPREGION_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rMtf.AddAction( new MetaISectRectClipRegionAction( aRect ) );
+ }
+ break;
+
+ case( GDI_RASTEROP_ACTION ):
+ {
+ RasterOp eRasterOp;
+ INT16 nRasterOp;
+
+ rIStm >> nRasterOp;
+
+ switch( nRasterOp )
+ {
+ case( 1 ):
+ eRasterOp = ROP_INVERT;
+ break;
+
+ case( 4 ):
+ case( 5 ):
+ eRasterOp = ROP_XOR;
+ break;
+
+ default:
+ eRasterOp = ROP_OVERPAINT;
+ break;
+ }
+
+ rMtf.AddAction( new MetaRasterOpAction( eRasterOp ) );
+ }
+ break;
+
+ case( GDI_PUSH_ACTION ):
+ {
+ aLIStack.Push( new LineInfo( aLineInfo ) );
+ rMtf.AddAction( new MetaPushAction( PUSH_ALL ) );
+ }
+ break;
+
+ case( GDI_POP_ACTION ):
+ {
+
+ LineInfo* pLineInfo = (LineInfo*) aLIStack.Pop();
+
+ // restore line info
+ if( pLineInfo )
+ {
+ aLineInfo = *pLineInfo;
+ delete pLineInfo;
+ bFatLine = ( LINE_NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
+ }
+
+ rMtf.AddAction( new MetaPopAction() );
+ }
+ break;
+
+ case( GDI_GRADIENT_ACTION ):
+ {
+ Color aStartCol;
+ Color aEndCol;
+ INT16 nStyle;
+ INT16 nAngle;
+ INT16 nBorder;
+ INT16 nOfsX;
+ INT16 nOfsY;
+ INT16 nIntensityStart;
+ INT16 nIntensityEnd;
+
+ ImplReadRect( rIStm, aRect );
+ rIStm >> nStyle;
+ ImplReadColor( rIStm, aStartCol );
+ ImplReadColor( rIStm, aEndCol );
+ rIStm >> nAngle >> nBorder >> nOfsX >> nOfsY >> nIntensityStart >> nIntensityEnd;
+
+ Gradient aGrad( (GradientStyle) nStyle, aStartCol, aEndCol );
+
+ aGrad.SetAngle( nAngle );
+ aGrad.SetBorder( nBorder );
+ aGrad.SetOfsX( nOfsX );
+ aGrad.SetOfsY( nOfsY );
+ aGrad.SetStartIntensity( nIntensityStart );
+ aGrad.SetEndIntensity( nIntensityEnd );
+ rMtf.AddAction( new MetaGradientAction( aRect, aGrad ) );
+ }
+ break;
+
+ case( GDI_TRANSPARENT_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ INT32 nFollowingActionCount;
+ INT16 nTrans;
+
+ rIStm >> aPolyPoly >> nTrans >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTransparentAction( aPolyPoly, nTrans ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_FLOATTRANSPARENT_COMMENT ):
+ {
+ GDIMetaFile aMtf;
+ Point aPos;
+ Size aSize;
+ Gradient aGradient;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aMtf >> aPos >> aSize >> aGradient >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaFloatTransparentAction( aMtf, aPos, aSize, aGradient ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_HATCH_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ Hatch aHatch;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aPolyPoly >> aHatch >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaHatchAction( aPolyPoly, aHatch ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_REFPOINT_COMMENT ):
+ {
+ Point aRefPoint;
+ BOOL bSet;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aRefPoint >> bSet >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaRefPointAction( aRefPoint, bSet ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_TEXTLINECOLOR_COMMENT ):
+ {
+ Color aColor;
+ BOOL bSet;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aColor >> bSet >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTextLineColorAction( aColor, bSet ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_TEXTLINE_COMMENT ):
+ {
+ Point aStartPt;
+ long nWidth;
+ ULONG nStrikeout;
+ ULONG nUnderline;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aStartPt >> nWidth >> nStrikeout >> nUnderline >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTextLineAction( aStartPt, nWidth,
+ (FontStrikeout) nStrikeout,
+ (FontUnderline) nUnderline ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_GRADIENTEX_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ Gradient aGradient;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aPolyPoly >> aGradient >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaGradientExAction( aPolyPoly, aGradient ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_COMMENT_COMMENT ):
+ {
+ ByteString aComment;
+ long nValue;
+ ULONG nDataSize;
+ BYTE* pData;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aComment >> nValue >> nDataSize;
+
+ if( nDataSize )
+ {
+ pData = new BYTE[ nDataSize ];
+ rIStm.Read( pData, nDataSize );
+ }
+ else
+ pData = NULL;
+
+ rIStm >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaCommentAction( aComment, nValue, pData, nDataSize ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ default:
+ rIStm.SeekRel( nActionSize - 4L );
+ break;
+ }
+ }
+
+ // cleanup push-pop stack if neccessary
+ for( void* pLineInfo = aLIStack.Pop(); pLineInfo; pLineInfo = aLIStack.Pop() )
+ delete (LineInfo*) pLineInfo;
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+}
+
+// ------------------------------------------------------------------------
+
+void SVMConverter::ImplConvertToSVM1( SvStream& rOStm, GDIMetaFile& rMtf )
+{
+ ULONG nPos;
+ ULONG nCountPos;
+ Font aSaveFont;
+ const ULONG nActionCount = rMtf.GetActionCount();
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding();
+ const Size aPrefSize( rMtf.GetPrefSize() );
+ BOOL bRop_0_1 = FALSE;
+ VirtualDevice aSaveVDev;
+ Color aLineCol( COL_BLACK );
+ Stack aLineColStack;
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ //MagicCode schreiben
+ rOStm << "SVGDI"; // Kennung
+ nPos = rOStm.Tell();
+ rOStm << (INT16) 42; // HeaderSize
+ rOStm << (INT16) 200; // VERSION
+ rOStm << (INT32) aPrefSize.Width();
+ rOStm << (INT32) aPrefSize.Height();
+ ImplWriteMapMode( rOStm, rMtf.GetPrefMapMode() );
+
+ // ActionCount wird spaeter geschrieben
+ nCountPos = rOStm.Tell();
+ rOStm.SeekRel( 4L );
+
+ const INT32 nActCount = ImplWriteActions( rOStm, rMtf, aSaveVDev, bRop_0_1, aLineCol, aLineColStack, eActualCharSet );
+ const ULONG nActPos = rOStm.Tell();
+
+ rOStm.Seek( nCountPos );
+ rOStm << nActCount;
+ rOStm.Seek( nActPos );
+ rOStm.SetNumberFormatInt( nOldFormat );
+
+ // cleanup push-pop stack if neccessary
+ for( void* pCol = aLineColStack.Pop(); pCol; pCol = aLineColStack.Pop() )
+ delete (Color*) pCol;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
+ VirtualDevice& rSaveVDev, BOOL& rRop_0_1,
+ Color& rLineCol, Stack& rLineColStack,
+ rtl_TextEncoding& rActualCharSet )
+{
+ ULONG nCount = 0;
+ for( ULONG i = 0, nActionCount = rMtf.GetActionCount(); i < nActionCount; i++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( i );
+
+ switch( pAction->GetType() )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ MetaPixelAction* pAct = (MetaPixelAction*) pAction;
+
+ rOStm << (INT16) GDI_PIXEL_ACTION;
+ rOStm << (INT32) 18;
+ rOStm << pAct->GetPoint();
+ ImplWriteColor( rOStm, pAct->GetColor() );
+ nCount++;
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ MetaPointAction* pAct = (MetaPointAction*) pAction;
+
+ rOStm << (INT16) GDI_POINT_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ MetaLineAction* pAct = (MetaLineAction*) pAction;
+ const LineInfo& rInfo = pAct->GetLineInfo();
+ const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+
+ if( bFatLine )
+ {
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+ }
+
+ rOStm << (INT16) GDI_LINE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+
+ if( bFatLine )
+ {
+ ImplWritePopAction( rOStm );
+ nCount += 3;
+ }
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ MetaRectAction* pAct = (MetaRectAction*) pAction;
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) 0;
+ rOStm << (INT32) 0;
+ nCount++;
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) pAct->GetHorzRound();
+ rOStm << (INT32) pAct->GetVertRound();
+ nCount++;
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
+
+ rOStm << (INT16) GDI_ELLIPSE_ACTION;
+ rOStm << (INT32) 20;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ nCount++;
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ MetaArcAction* pAct = (MetaArcAction*) pAction;
+
+ rOStm << (INT16) GDI_ARC_ACTION;
+ rOStm << (INT32) 36;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ MetaPieAction* pAct = (MetaPieAction*) pAction;
+
+ rOStm << (INT16) GDI_PIE_ACTION;
+ rOStm << (INT32) 36;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ MetaChordAction* pAct = (MetaChordAction*) pAction;
+ Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(),
+ pAct->GetEndPoint(), POLY_CHORD );
+ const USHORT nPoints = aChordPoly.GetSize();
+
+ rOStm << (INT16) GDI_POLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << aChordPoly[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
+ const Polygon& rPoly = pAct->GetPolygon();
+ const LineInfo& rInfo = pAct->GetLineInfo();
+ const USHORT nPoints = rPoly.GetSize();
+ const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+
+ if( bFatLine )
+ {
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+ }
+
+ rOStm << (INT16) GDI_POLYLINE_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << rPoly[ n ];
+
+ nCount++;
+
+ if( bFatLine )
+ {
+ ImplWritePopAction( rOStm );
+ nCount += 3;
+ }
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
+ const Polygon& rPoly = pAct->GetPolygon();
+ const USHORT nPoints = rPoly.GetSize();
+
+ rOStm << (INT16) GDI_POLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << rPoly[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
+ ImplWritePolyPolyAction( rOStm, pAct->GetPolyPolygon() );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ MetaTextAction* pAct = (MetaTextAction*) pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ const ULONG nStrLen = aText.Len();
+
+ rOStm << (INT16) GDI_TEXT_ACTION;
+ rOStm << (INT32) ( 24 + ( nStrLen + 1 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) pAct->GetIndex();
+ rOStm << (INT32) pAct->GetLen();
+ rOStm << (INT32) nStrLen;
+ rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ MetaTextArrayAction* pAct = (MetaTextArrayAction*)pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ ULONG nAryLen;
+ ULONG nLen = pAct->GetLen();
+ const ULONG nTextLen = aText.Len();
+ long* pDXArray = pAct->GetDXArray();
+
+ if( ( nLen + pAct->GetIndex() ) > nTextLen )
+ {
+ if( pAct->GetIndex() <= nTextLen )
+ nLen = nTextLen - pAct->GetIndex();
+ else
+ nLen = 0UL;
+ }
+
+ if( !pDXArray || !nLen )
+ nAryLen = 0;
+ else
+ nAryLen = nLen - 1;
+
+ rOStm << (INT16) GDI_TEXTARRAY_ACTION;
+ rOStm << (INT32) ( 28 + ( nLen + 1 ) + ( nAryLen * 4 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) 0;
+ rOStm << (INT32) nLen;
+ rOStm << (INT32) nLen;
+ rOStm << (INT32) nAryLen;
+ rOStm.Write( aText.GetBuffer()+pAct->GetIndex(), nLen + 1 );
+
+ for( ULONG n = 0UL ; n < nAryLen; n++ )
+ rOStm << (INT32) pDXArray[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ {
+ MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ const ULONG nStrLen = aText.Len();
+
+ rOStm << (INT16) GDI_STRETCHTEXT_ACTION;
+ rOStm << (INT32) ( 28 + ( nStrLen + 1 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) pAct->GetIndex();
+ rOStm << (INT32) pAct->GetLen();
+ rOStm << (INT32) nStrLen;
+ rOStm << (INT32) pAct->GetWidth();
+ rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
+ nCount++;
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pAct = (MetaBmpAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAP_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAPSCALE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetSize();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAPSCALEPART_ACTION;
+ rOStm << (INT32) 36;
+ rOStm << pAct->GetDestPoint();
+ rOStm << pAct->GetDestSize();
+ rOStm << pAct->GetSrcPoint();
+ rOStm << pAct->GetSrcSize();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAP_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAPSCALE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetSize();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAPSCALEPART_ACTION;
+ rOStm << (INT32) 36;
+ rOStm << pAct->GetDestPoint();
+ rOStm << pAct->GetDestSize();
+ rOStm << pAct->GetSrcPoint();
+ rOStm << pAct->GetSrcSize();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ MetaGradientAction* pAct = (MetaGradientAction*) pAction;
+ const Gradient& rGrad = pAct->GetGradient();
+
+ rOStm << (INT16) GDI_GRADIENT_ACTION;
+ rOStm << (INT32) 46;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT16) rGrad.GetStyle();
+ ImplWriteColor( rOStm, rGrad.GetStartColor() );
+ ImplWriteColor( rOStm, rGrad.GetEndColor() );
+ rOStm << (INT16) rGrad.GetAngle();
+ rOStm << (INT16) rGrad.GetBorder();
+ rOStm << (INT16) rGrad.GetOfsX();
+ rOStm << (INT16) rGrad.GetOfsY();
+ rOStm << (INT16) rGrad.GetStartIntensity();
+ rOStm << (INT16) rGrad.GetEndIntensity();
+ nCount++;
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ const MetaGradientExAction* pA = (MetaGradientExAction*) pAction;
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_GRADIENTEX_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << pA->GetPolyPolygon() << pA->GetGradient();
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
+ const Color& rColor = pAct->GetWallpaper().GetColor();
+
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rColor, 1 );
+ ImplWriteFillColor( rOStm, rColor, 1 );
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) 0;
+ rOStm << (INT32) 0;
+
+ ImplWritePopAction( rOStm );
+ nCount += 5;
+ }
+ break;
+
+ case( META_CLIPREGION_ACTION ):
+ {
+ MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
+ const Region& rRegion = pAct->GetRegion();
+ Rectangle aClipRect;
+
+ rOStm << (INT16) GDI_CLIPREGION_ACTION;
+ rOStm << (INT32) 24;
+
+ if( pAct->IsClipping() )
+ {
+ aClipRect = rRegion.GetBoundRect();
+ rOStm << (INT16) 1;
+ }
+ else
+ rOStm << (INT16) 0;
+
+ rOStm << (INT16) 0;
+ ImplWriteRect( rOStm, aClipRect );
+
+ if( pAct->IsClipping() )
+ ImplWriteRect( rOStm, aClipRect );
+
+ nCount++;
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
+
+ rOStm << (INT16) GDI_ISECTCLIPREGION_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetRect();
+ nCount++;
+ }
+ break;
+
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
+
+ rOStm << (INT16) GDI_MOVECLIPREGION_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << (INT32) pAct->GetHorzMove();
+ rOStm << (INT32) pAct->GetVertMove();
+ nCount++;
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
+ ImplWriteLineColor( rOStm, rLineCol = pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
+ nCount++;
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
+ ImplWriteFillColor( rOStm, pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
+ nCount++;
+ }
+ break;
+
+ case( META_FONT_ACTION ):
+ {
+ rSaveVDev.SetFont( ( (MetaFontAction*) pAction )->GetFont() );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ {
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ aSaveFont.SetColor( ( (MetaTextColorAction*) pAction )->GetColor() );
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTFILLCOLOR_ACTION ):
+ {
+ MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ if( pAct->IsSetting() )
+ aSaveFont.SetFillColor( pAct->GetColor() );
+ else
+ aSaveFont.SetFillColor( Color( COL_TRANSPARENT ) );
+
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTALIGN_ACTION ):
+ {
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ aSaveFont.SetAlign( ( (MetaTextAlignAction*) pAction )->GetTextAlign() );
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_MAPMODE_ACTION ):
+ {
+ MetaMapModeAction* pAct = (MetaMapModeAction*) pAction;
+
+ rOStm << (INT16) GDI_MAPMODE_ACTION;
+ rOStm << (INT32) 30;
+ ImplWriteMapMode( rOStm, pAct->GetMapMode() );
+ nCount++;
+ }
+ break;
+
+ case( META_PUSH_ACTION ):
+ {
+ ImplWritePushAction( rOStm );
+ rLineColStack.Push( new Color( rLineCol ) );
+ rSaveVDev.Push();
+ nCount++;
+ }
+ break;
+
+ case( META_POP_ACTION ):
+ {
+ Color* pCol = (Color*) rLineColStack.Pop();
+
+ if( pCol )
+ {
+ rLineCol = *pCol;
+ delete pCol;
+ }
+
+ ImplWritePopAction( rOStm );
+ rSaveVDev.Pop();
+ nCount++;
+ }
+ break;
+
+ case( META_RASTEROP_ACTION ):
+ {
+ MetaRasterOpAction* pAct = (MetaRasterOpAction*) pAction;
+
+ if( ( pAct->GetRasterOp() != ROP_0 ) && ( pAct->GetRasterOp() != ROP_1 ) )
+ {
+ INT16 nRasterOp;
+
+ // Falls vorher ROP_0/1 gesetzt war, alten
+ // Zustand durch Pop erst wieder herstellen
+ if( rRop_0_1 )
+ {
+ ImplWritePopAction( rOStm );
+ rSaveVDev.Pop();
+ rRop_0_1 = FALSE;
+ nCount++;
+ }
+
+ switch( pAct->GetRasterOp() )
+ {
+ case( ROP_OVERPAINT ) : nRasterOp = 0; break;
+ case( ROP_XOR ) : nRasterOp = 4; break;
+ case( ROP_INVERT ): nRasterOp = 1; break;
+ default: nRasterOp = 0; break;
+ }
+
+ ImplWriteRasterOpAction( rOStm, nRasterOp );
+ nCount++;
+ }
+ else
+ {
+ ImplWritePushAction( rOStm );
+ rSaveVDev.Push();
+
+ if( pAct->GetRasterOp() == ROP_0 )
+ {
+ ImplWriteLineColor( rOStm, COL_BLACK, 1 );
+ ImplWriteFillColor( rOStm, COL_BLACK, 1 );
+ }
+ else
+ {
+ ImplWriteLineColor( rOStm, COL_WHITE, 1 );
+ ImplWriteFillColor( rOStm, COL_WHITE, 1 );
+ }
+
+ ImplWriteRasterOpAction( rOStm, 0 );
+ rRop_0_1 = TRUE;
+ nCount += 4;
+ }
+ }
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ {
+ const PolyPolygon& rPolyPoly = ( (MetaTransparentAction*) pAction )->GetPolyPolygon();
+ const INT16 nTrans = ( (MetaTransparentAction*) pAction )->GetTransparence();
+ const INT16 nBrushStyle = ( nTrans < 38 ) ? 8 : ( nTrans < 63 ) ? 9 : 10;
+ ULONG nOldPos, nNewPos;
+
+ // write transparence comment
+ rOStm << (INT16) GDI_TRANSPARENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rPolyPoly;
+ rOStm << nTrans;
+ rOStm << (INT32) 15; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ {
+ // write actions for transparence
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteRasterOpAction( rOStm, 4 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteRasterOpAction( rOStm, 2 );
+ ImplWriteFillColor( rOStm, COL_BLACK, nBrushStyle );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+ ImplWriteRasterOpAction( rOStm, 4 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteFillColor( rOStm, Color(), 0 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += 15;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ const MetaFloatTransparentAction* pA = (MetaFloatTransparentAction*) pAction;
+ const GDIMetaFile& rTransMtf = pA->GetGDIMetaFile();
+ const Point& rPos = pA->GetPoint();
+ const Size& rSize = pA->GetSize();
+ const Gradient& rGradient = pA->GetGradient();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_FLOATTRANSPARENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rTransMtf << rPos << rSize << rGradient;
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos + 4 );
+ rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
+
+ {
+ // write actions for float transparence
+ ULONG nAddCount;
+ GDIMetaFile aMtf( rTransMtf );
+ const Size aSrcSize( rTransMtf.GetPrefSize() );
+ Point aSrcPt( rTransMtf.GetPrefMapMode().GetOrigin() );
+ const double fScaleX = aSrcSize.Width() ? (double) rSize.Width() / aSrcSize.Width() : 1.0;
+ const double fScaleY = aSrcSize.Height() ? (double) rSize.Height() / aSrcSize.Height() : 1.0;
+ long nMoveX, nMoveY;
+
+ if( fScaleX != 1.0 || fScaleY != 1.0 )
+ {
+ aMtf.Scale( fScaleX, fScaleY );
+ aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
+ }
+
+ nMoveX = rPos.X() - aSrcPt.X(), nMoveY = rPos.Y() - aSrcPt.Y();
+
+ if( nMoveX || nMoveY )
+ aMtf.Move( nMoveX, nMoveY );
+
+ nAddCount = ImplWriteActions( rOStm, aMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) nAddCount;
+ rOStm.Seek( nNewPos );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += nAddCount;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_HATCH_ACTION ):
+ {
+ const MetaHatchAction* pA = (MetaHatchAction*) pAction;
+ const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+ const Hatch& rHatch = pA->GetHatch();
+ ULONG nOldPos, nNewPos, nAddCount;
+
+ // write hatch comment
+ rOStm << (INT16) GDI_HATCH_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rPolyPoly;
+ rOStm << rHatch;
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos + 4 );
+ rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
+
+ {
+ // write actions for hatch
+ VirtualDevice aVDev;
+ GDIMetaFile aTmpMtf;
+
+ aVDev.AddHatchActions( rPolyPoly, rHatch, aTmpMtf );
+ nAddCount = ImplWriteActions( rOStm, aTmpMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) nAddCount;
+ rOStm.Seek( nNewPos );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += nAddCount;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_REFPOINT_ACTION ):
+ {
+ const MetaRefPointAction* pA = (MetaRefPointAction*) pAction;
+ const Point& rRefPoint = pA->GetRefPoint();
+ const BOOL bSet = pA->IsSetting();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_REFPOINT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rRefPoint << bSet;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTLINECOLOR_ACTION ):
+ {
+ const MetaTextLineColorAction* pA = (MetaTextLineColorAction*) pAction;
+ const Color& rColor = pA->GetColor();
+ const BOOL bSet = pA->IsSetting();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_TEXTLINECOLOR_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rColor << bSet;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTLINE_ACTION ):
+ {
+ const MetaTextLineAction* pA = (MetaTextLineAction*) pAction;
+ const Point& rStartPt = pA->GetStartPoint();
+ const long nWidth = pA->GetWidth();
+ const FontStrikeout eStrikeout = pA->GetStrikeout();
+ const FontUnderline eUnderline = pA->GetUnderline();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_TEXTLINE_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rStartPt << nWidth << (ULONG) eStrikeout << (ULONG) eUnderline;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ break;
+
+ case( META_COMMENT_ACTION ):
+ {
+ const MetaCommentAction* pA = (MetaCommentAction*) pAction;
+ const ULONG nDataSize = pA->GetDataSize();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_COMMENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << pA->GetComment() << pA->GetValue() << nDataSize;
+
+ if( nDataSize )
+ rOStm.Write( pA->GetData(), nDataSize );
+
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+#ifdef DBG_UTIL
+ default:
+ {
+ ByteString aStr( "Missing implementation for Action#: " );
+ aStr += ByteString::CreateFromInt32( pAction->GetType() );
+ aStr += '!';
+ DBG_ERROR( aStr.GetBuffer() );
+ }
+ break;
+#endif
+
+/*
+ case( META_TEXTRECT_ACTION ):
+ {
+ MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pAct = (MetaMaskAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ {
+ MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+ }
+ }
+
+ return nCount;
+}
diff --git a/vcl/source/gdi/font.cxx b/vcl/source/gdi/font.cxx
new file mode 100644
index 000000000000..657d42a21546
--- /dev/null
+++ b/vcl/source/gdi/font.cxx
@@ -0,0 +1,625 @@
+/*************************************************************************
+ *
+ * $RCSfile: font.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FONT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_FONT_HXX
+#include <font.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Font );
+
+// -----------------------------------------------------------------------
+
+Impl_Font::Impl_Font() :
+ maColor( COL_BLACK ),
+ maFillColor( COL_TRANSPARENT )
+{
+ mnRefCount = 1;
+ meCharSet = RTL_TEXTENCODING_DONTKNOW;
+ meLanguage = LANGUAGE_DONTKNOW;
+ meFamily = FAMILY_DONTKNOW;
+ mePitch = PITCH_DONTKNOW;
+ meAlign = ALIGN_TOP;
+ meWeight = WEIGHT_DONTKNOW;
+ meWidthType = WIDTH_DONTKNOW;
+ meUnderline = UNDERLINE_NONE;
+ meStrikeout = STRIKEOUT_NONE;
+ meItalic = ITALIC_NONE;
+ mbWordLine = FALSE;
+ mbOutline = FALSE;
+ mbShadow = FALSE;
+ mbKerning = FALSE;
+ mbTransparent = TRUE;
+ mnOrientation = 0;
+}
+
+// -----------------------------------------------------------------------
+
+Impl_Font::Impl_Font( const Impl_Font& rImplFont ) :
+ maColor( rImplFont.maColor ),
+ maFillColor( rImplFont.maFillColor ),
+ maName( rImplFont.maName ),
+ maStyleName( rImplFont.maStyleName ),
+ maSize( rImplFont.maSize )
+{
+ mnRefCount = 1;
+ meCharSet = rImplFont.meCharSet;
+ meLanguage = rImplFont.meLanguage;
+ meFamily = rImplFont.meFamily;
+ mePitch = rImplFont.mePitch;
+ meAlign = rImplFont.meAlign;
+ meWeight = rImplFont.meWeight;
+ meWidthType = rImplFont.meWidthType;
+ meUnderline = rImplFont.meUnderline;
+ meStrikeout = rImplFont.meStrikeout;
+ meItalic = rImplFont.meItalic;
+ mbWordLine = rImplFont.mbWordLine;
+ mbOutline = rImplFont.mbOutline;
+ mbShadow = rImplFont.mbShadow;
+ mbKerning = rImplFont.mbKerning;
+ mbTransparent = rImplFont.mbTransparent;
+ mnOrientation = rImplFont.mnOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::MakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplFont->mnRefCount != 1 )
+ {
+ if ( mpImplFont->mnRefCount )
+ mpImplFont->mnRefCount--;
+ mpImplFont = new Impl_Font( *mpImplFont );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font()
+{
+ DBG_CTOR( Font, NULL );
+
+#ifdef WIN
+ static Impl_Font _near aStaticImplFont;
+#else
+ static Impl_Font aStaticImplFont;
+#endif
+ // RefCount == 0 fuer statische Objekte
+ aStaticImplFont.mnRefCount = 0;
+ mpImplFont = &aStaticImplFont;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const Font& rFont )
+{
+ DBG_CTOR( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+ DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplFont = rFont.mpImplFont;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplFont->mnRefCount )
+ mpImplFont->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const XubString& rName, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->maName = rName;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const XubString& rName, const XubString& rStyleName, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->maName = rName;
+ mpImplFont->maStyleName = rStyleName;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( FontFamily eFamily, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->meFamily = eFamily;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::~Font()
+{
+ DBG_DTOR( Font, NULL );
+
+ // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplFont->mnRefCount )
+ {
+ if ( mpImplFont->mnRefCount == 1 )
+ delete mpImplFont;
+ else
+ mpImplFont->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetFillColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maFillColor = rColor;
+ if ( rColor.GetTransparency() )
+ mpImplFont->mbTransparent = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetAlign( FontAlign eAlign )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meAlign = eAlign;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetName( const XubString& rName )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maName = rName;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetStyleName( const XubString& rStyleName )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maStyleName = rStyleName;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetSize( const Size& rSize )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetFamily( FontFamily eFamily )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meFamily = eFamily;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetCharSet( CharSet eCharSet )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meCharSet = eCharSet;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetLanguage( LanguageType eLanguage )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meLanguage = eLanguage;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetPitch( FontPitch ePitch )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mePitch = ePitch;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetOrientation( short nOrientation )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mnOrientation = nOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetKerning( BOOL bKerning )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbKerning = bKerning;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWeight( FontWeight eWeight )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meWeight = eWeight;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWidthType( FontWidth eWidth )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meWidthType = eWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetItalic( FontItalic eItalic )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meItalic = eItalic;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetOutline( BOOL bOutline )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbOutline = bOutline;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetShadow( BOOL bShadow )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbShadow = bShadow;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetUnderline( FontUnderline eUnderline )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meUnderline = eUnderline;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetStrikeout( FontStrikeout eStrikeout )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meStrikeout = eStrikeout;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWordLineMode( BOOL bWordLine )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbWordLine = bWordLine;
+}
+
+// -----------------------------------------------------------------------
+
+Font& Font::operator=( const Font& rFont )
+{
+ DBG_CHKTHIS( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+ DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rFont.mpImplFont->mnRefCount )
+ rFont.mpImplFont->mnRefCount++;
+
+ // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplFont->mnRefCount )
+ {
+ if ( mpImplFont->mnRefCount == 1 )
+ delete mpImplFont;
+ else
+ mpImplFont->mnRefCount--;
+ }
+
+ mpImplFont = rFont.mpImplFont;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Font::operator==( const Font& rFont ) const
+{
+ DBG_CHKTHIS( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+
+ if ( mpImplFont == rFont.mpImplFont )
+ return TRUE;
+
+ if ( (mpImplFont->meWeight == rFont.mpImplFont->meWeight ) &&
+ (mpImplFont->meItalic == rFont.mpImplFont->meItalic ) &&
+ (mpImplFont->meUnderline == rFont.mpImplFont->meUnderline ) &&
+ (mpImplFont->mbWordLine == rFont.mpImplFont->mbWordLine ) &&
+ (mpImplFont->meFamily == rFont.mpImplFont->meFamily ) &&
+ (mpImplFont->mePitch == rFont.mpImplFont->mePitch ) &&
+ (mpImplFont->meCharSet == rFont.mpImplFont->meCharSet ) &&
+ (mpImplFont->meAlign == rFont.mpImplFont->meAlign ) &&
+ (mpImplFont->maName == rFont.mpImplFont->maName ) &&
+ (mpImplFont->maStyleName == rFont.mpImplFont->maStyleName ) &&
+ (mpImplFont->maColor == rFont.mpImplFont->maColor ) &&
+ (mpImplFont->maFillColor == rFont.mpImplFont->maFillColor ) &&
+ (mpImplFont->maSize == rFont.mpImplFont->maSize ) &&
+ (mpImplFont->mnOrientation == rFont.mpImplFont->mnOrientation ) &&
+ (mpImplFont->meStrikeout == rFont.mpImplFont->meStrikeout ) &&
+ (mpImplFont->mbOutline == rFont.mpImplFont->mbOutline ) &&
+ (mpImplFont->mbShadow == rFont.mpImplFont->mbShadow ) &&
+ (mpImplFont->mbKerning == rFont.mpImplFont->mbKerning ) &&
+ (mpImplFont->mbTransparent == rFont.mpImplFont->mbTransparent ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::Merge( const Font& rFont )
+{
+ if ( rFont.GetName().Len() )
+ {
+ SetName( rFont.GetName() );
+ SetStyleName( rFont.GetStyleName() );
+ SetFamily( rFont.GetFamily() );
+ SetCharSet( GetCharSet() );
+ SetLanguage( rFont.GetLanguage() );
+ SetPitch( rFont.GetPitch() );
+ }
+
+ if ( rFont.GetSize().Height() )
+ SetSize( rFont.GetSize() );
+ if ( rFont.GetWeight() != WEIGHT_DONTKNOW )
+ SetWeight( rFont.GetWeight() );
+ if ( rFont.GetWidthType() != WIDTH_DONTKNOW )
+ SetWidthType( rFont.GetWidthType() );
+ if ( rFont.GetItalic() != ITALIC_DONTKNOW )
+ SetItalic( rFont.GetItalic() );
+ if ( rFont.GetUnderline() != UNDERLINE_DONTKNOW )
+ {
+ SetUnderline( rFont.GetUnderline() );
+ SetWordLineMode( rFont.IsWordLineMode() );
+ }
+ if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW )
+ {
+ SetStrikeout( rFont.GetStrikeout() );
+ SetWordLineMode( rFont.IsWordLineMode() );
+ }
+
+ // Defaults?
+ SetOrientation( rFont.GetOrientation() );
+ SetKerning( rFont.IsKerning() );
+ SetOutline( rFont.IsOutline() );
+ SetShadow( rFont.IsShadow() );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Impl_Font& rImpl_Font )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+ BOOL bTmp;
+
+ rIStm.ReadByteString( rImpl_Font.maName, rIStm.GetStreamCharSet() );
+ rIStm.ReadByteString( rImpl_Font.maStyleName, rIStm.GetStreamCharSet() );
+ rIStm >> rImpl_Font.maSize;
+// rIStm >> rImpl_Font.maColor; // removed since SUPD396
+// rIStm >> rImpl_Font.maFillColor; // removed since SUPD396
+
+ rIStm >> nTmp16; rImpl_Font.meCharSet = (rtl_TextEncoding) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meFamily = (FontFamily) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.mePitch = (FontPitch) nTmp16;
+// rIStm >> nTmp16; rImpl_Font.meAlign = (FontAlign) nTmp16; // removed since SUPD396
+ rIStm >> nTmp16; rImpl_Font.meWeight = (FontWeight) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meUnderline = (FontUnderline) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meStrikeout = (FontStrikeout) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meItalic = (FontItalic) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meLanguage = (LanguageType) nTmp16; // new since SUPD 396
+ rIStm >> nTmp16; rImpl_Font.meWidthType = (FontWidth) nTmp16; // new since SUPD 396
+
+ rIStm >> rImpl_Font.mnOrientation;
+
+ rIStm >> bTmp; rImpl_Font.mbWordLine = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbOutline = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbShadow = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbKerning = bTmp;
+// rIStm >> bTmp; rImpl_Font.mbTransparent = bTmp; // removed since SUPD396
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Impl_Font& rImpl_Font )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+ rOStm.WriteByteString( rImpl_Font.maName, rOStm.GetStreamCharSet() );
+ rOStm.WriteByteString( rImpl_Font.maStyleName, rOStm.GetStreamCharSet() );
+ rOStm << rImpl_Font.maSize;
+// rOStm << rImpl_Font.maColor; // removed since SUPD396
+// rOStm << rImpl_Font.maFillColor; // removed since SUPD396
+
+ rOStm << (UINT16) GetStoreCharSet( rImpl_Font.meCharSet, rOStm.GetVersion() );
+ rOStm << (UINT16) rImpl_Font.meFamily;
+ rOStm << (UINT16) rImpl_Font.mePitch;
+// rOStm << (UINT16) rImpl_Font.meAlign; // removed since SUPD396
+ rOStm << (UINT16) rImpl_Font.meWeight;
+ rOStm << (UINT16) rImpl_Font.meUnderline;
+ rOStm << (UINT16) rImpl_Font.meStrikeout;
+ rOStm << (UINT16) rImpl_Font.meItalic;
+ rOStm << (UINT16) rImpl_Font.meLanguage; // new since SUPD 396
+ rOStm << (UINT16) rImpl_Font.meWidthType; // new since SUPD 396
+
+ rOStm << rImpl_Font.mnOrientation;
+
+ rOStm << (BOOL) rImpl_Font.mbWordLine;
+ rOStm << (BOOL) rImpl_Font.mbOutline;
+ rOStm << (BOOL) rImpl_Font.mbShadow;
+ rOStm << (BOOL) rImpl_Font.mbKerning;
+// rOStm << (BOOL) rImpl_Font.mbTransparent; // removed since SUPD396
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Font& rFont )
+{
+ rFont.MakeUnique();
+ return( rIStm >> *rFont.mpImplFont );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Font& rFont )
+{
+ return( rOStm << *rFont.mpImplFont );
+}
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
new file mode 100644
index 000000000000..852dbfcb87a3
--- /dev/null
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -0,0 +1,1724 @@
+/*************************************************************************
+ *
+ * $RCSfile: gdimtf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GDIMTF_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_CVTSVM_HXX
+#include <cvtsvm.hxx>
+#endif
+#include <gdimtf.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
+
+// --------------------------
+// - Color exchange structs -
+// --------------------------
+
+struct ImplColAdjustParam
+{
+ BYTE* pMapR;
+ BYTE* pMapG;
+ BYTE* pMapB;
+};
+
+struct ImplBmpAdjustParam
+{
+ short nLuminancePercent;
+ short nContrastPercent;
+ short nChannelRPercent;
+ short nChannelGPercent;
+ short nChannelBPercent;
+ double fGamma;
+ BOOL bInvert;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColConvertParam
+{
+ MtfConversion eConversion;
+};
+
+struct ImplBmpConvertParam
+{
+ BmpConversion eConversion;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColMonoParam
+{
+ Color aColor;
+};
+
+struct ImplBmpMonoParam
+{
+ Color aColor;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColReplaceParam
+{
+ ULONG* pMinR;
+ ULONG* pMaxR;
+ ULONG* pMinG;
+ ULONG* pMaxG;
+ ULONG* pMinB;
+ ULONG* pMaxB;
+ const Color* pDstCols;
+ ULONG nCount;
+};
+
+struct ImplBmpReplaceParam
+{
+ const Color* pSrcCols;
+ const Color* pDstCols;
+ ULONG nCount;
+ const ULONG* pTols;
+};
+
+
+// ---------
+// - Label -
+// ---------
+
+struct ImpLabel
+{
+ String aLabelName;
+ ULONG nActionPos;
+
+ ImpLabel( const String& rLabelName, ULONG _nActionPos ) :
+ aLabelName( rLabelName ),
+ nActionPos( _nActionPos ) {}
+};
+
+// -------------
+// - LabelList -
+// -------------
+
+class ImpLabelList : private List
+{
+public:
+
+ ImpLabelList() : List( 8, 4, 4 ) {}
+ ImpLabelList( const ImpLabelList& rList );
+ ~ImpLabelList();
+
+ void ImplInsert( ImpLabel* p ) { Insert( p, LIST_APPEND ); }
+ ImpLabel* ImplRemove( ULONG nPos ) { return (ImpLabel*) Remove( nPos ); }
+ void ImplReplace( ImpLabel* p ) { Replace( (void*)p ); }
+ ImpLabel* ImplFirst() { return (ImpLabel*) First(); }
+ ImpLabel* ImplNext() { return (ImpLabel*) Next(); }
+ ImpLabel* ImplGetLabel( ULONG nPos ) const { return (ImpLabel*) GetObject( nPos ); }
+ ULONG ImplGetLabelPos( const String& rLabelName );
+ ULONG ImplCount() const { return Count(); }
+};
+
+// ------------------------------------------------------------------------
+
+ImpLabelList::ImpLabelList( const ImpLabelList& rList ) :
+ List( rList )
+{
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ ImplReplace( new ImpLabel( *pLabel ) );
+}
+
+// ------------------------------------------------------------------------
+
+ImpLabelList::~ImpLabelList()
+{
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ delete pLabel;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpLabelList::ImplGetLabelPos( const String& rLabelName )
+{
+ ULONG nLabelPos = METAFILE_LABEL_NOTFOUND;
+
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ {
+ if ( rLabelName == pLabel->aLabelName )
+ {
+ nLabelPos = GetCurPos();
+ break;
+ }
+ }
+
+ return nLabelPos;
+}
+
+// ---------------
+// - GDIMetaFile -
+// ---------------
+
+GDIMetaFile::GDIMetaFile() :
+ List ( 0x3EFF, 64, 64 ),
+ aPrefSize ( 1, 1 ),
+ pPrev ( NULL ),
+ pNext ( NULL ),
+ pOutDev ( NULL ),
+ pLabelList ( NULL ),
+ bPause ( FALSE ),
+ bRecord ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
+ List ( rMtf ),
+ aPrefMapMode ( rMtf.aPrefMapMode ),
+ aPrefSize ( rMtf.aPrefSize ),
+ aHookHdlLink ( rMtf.aHookHdlLink ),
+ pPrev ( rMtf.pPrev ),
+ pNext ( rMtf.pNext ),
+ pOutDev ( NULL ),
+ bPause ( FALSE ),
+ bRecord ( FALSE )
+{
+ // RefCount der MetaActions erhoehen
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Duplicate();
+
+ if( rMtf.pLabelList )
+ pLabelList = new ImpLabelList( *rMtf.pLabelList );
+ else
+ pLabelList = NULL;
+
+ if( rMtf.bRecord )
+ {
+ Record( rMtf.pOutDev );
+
+ if ( rMtf.bPause )
+ Pause( TRUE );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile::~GDIMetaFile()
+{
+ Clear();
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
+{
+ if( this != &rMtf )
+ {
+ Clear();
+
+ List::operator=( rMtf );
+
+ // RefCount der MetaActions erhoehen
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Duplicate();
+
+ if( rMtf.pLabelList )
+ pLabelList = new ImpLabelList( *rMtf.pLabelList );
+ else
+ pLabelList = NULL;
+
+ aPrefMapMode = rMtf.aPrefMapMode;
+ aPrefSize = rMtf.aPrefSize;
+ aHookHdlLink = rMtf.aHookHdlLink;
+ pPrev = rMtf.pPrev;
+ pNext = rMtf.pNext;
+ pOutDev = NULL;
+ bPause = FALSE;
+ bRecord = FALSE;
+
+ if( rMtf.bRecord )
+ {
+ Record( rMtf.pOutDev );
+
+ if( rMtf.bPause )
+ Pause( TRUE );
+ }
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
+{
+ const ULONG nCount = Count();
+ BOOL bRet = FALSE;
+
+ if( this == &rMtf )
+ bRet = TRUE;
+ else if( rMtf.GetActionCount() == nCount &&
+ rMtf.GetPrefSize() == aPrefSize &&
+ rMtf.GetPrefMapMode() == aPrefMapMode )
+ {
+ bRet = TRUE;
+
+ for( ULONG n = 0UL; n < nCount; n++ )
+ {
+ if( GetObject( n ) != rMtf.GetObject( n ) )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Clear()
+{
+ if( bRecord )
+ Stop();
+
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Delete();
+
+ List::Clear();
+
+ delete pLabelList;
+ pLabelList = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Linker( OutputDevice* pOut, BOOL bLink )
+{
+ if( bLink )
+ {
+ pNext = NULL;
+ pPrev = pOut->GetConnectMetaFile();
+ pOut->SetConnectMetaFile( this );
+
+ if( pPrev )
+ pPrev->pNext = this;
+ }
+ else
+ {
+ if( pNext )
+ {
+ pNext->pPrev = pPrev;
+
+ if( pPrev )
+ pPrev->pNext = pNext;
+ }
+ else
+ {
+ if( pPrev )
+ pPrev->pNext = NULL;
+
+ pOut->SetConnectMetaFile( pPrev );
+ }
+
+ pPrev = NULL;
+ pNext = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+long GDIMetaFile::Hook()
+{
+ return aHookHdlLink.Call( this );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Record( OutputDevice* pOut )
+{
+ if( bRecord )
+ Stop();
+
+ Last();
+ pOutDev = pOut;
+ bRecord = TRUE;
+ Linker( pOut, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( GDIMetaFile& rMtf, ULONG nPos )
+{
+ if ( !bRecord && !rMtf.bRecord )
+ {
+ MetaAction* pAction = GetCurAction();
+ const ULONG nCount = Count();
+
+ if( nPos > nCount )
+ nPos = nCount;
+
+ for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
+ {
+ if( !Hook() )
+ {
+ pAction->Duplicate();
+ rMtf.AddAction( pAction );
+ }
+
+ pAction = (MetaAction*) Next();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( OutputDevice* pOut, ULONG nPos )
+{
+ if( !bRecord )
+ {
+ MetaAction* pAction = GetCurAction();
+ const ULONG nCount = Count();
+ ULONG i = 0, nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
+
+ if( nPos > nCount )
+ nPos = nCount;
+
+ for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
+ {
+ if( !Hook() )
+ {
+ pAction->Execute( pOut );
+
+ // flush output from time to time
+ if( i++ > nSyncCount )
+ ( (Window*) pOut )->Flush(), i = 0;
+ }
+
+ pAction = (MetaAction*) Next();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
+ const Size& rSize, ULONG nPos )
+{
+ Region aDrawClipRegion;
+ MapMode aDrawMap( GetPrefMapMode() );
+ Size aDestSize( pOut->LogicToPixel( rSize ) );
+
+ if( aDestSize.Width() && aDestSize.Height() )
+ {
+ Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
+ GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
+
+ if( !aTmpPrefSize.Width() )
+ aTmpPrefSize.Width() = aDestSize.Width();
+
+ if( !aTmpPrefSize.Height() )
+ aTmpPrefSize.Height() = aDestSize.Height();
+
+ Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
+ Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
+
+ aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
+ aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
+
+ aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
+
+ pOut->Push();
+
+ if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
+ pOut->SetRelativeMapMode( aDrawMap );
+ else
+ pOut->SetMapMode( aDrawMap );
+
+ Play( pOut, nPos );
+
+ pOut->Pop();
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Pause( BOOL _bPause )
+{
+ if( bRecord )
+ {
+ if( _bPause )
+ {
+ if( !bPause )
+ Linker( pOutDev, FALSE );
+ }
+ else
+ {
+ if( bPause )
+ Linker( pOutDev, TRUE );
+ }
+
+ bPause = _bPause;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Stop()
+{
+ if( bRecord )
+ {
+ bRecord = FALSE;
+
+ if( !bPause )
+ Linker( pOutDev, FALSE );
+ else
+ bPause = FALSE;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindStart()
+{
+ if( !bRecord )
+ First();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindEnd()
+{
+ if( !bRecord )
+ Last();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Wind( ULONG nActionPos )
+{
+ if( !bRecord )
+ Seek( nActionPos );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindPrev()
+{
+ if( !bRecord )
+ Prev();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindNext()
+{
+ if( !bRecord )
+ Next();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::AddAction( MetaAction* pAction )
+{
+ Insert( pAction, LIST_APPEND );
+
+ if( pPrev )
+ {
+ pAction->Duplicate();
+ pPrev->AddAction( pAction );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::AddAction( MetaAction* pAction, ULONG nPos )
+{
+ Insert( pAction, nPos );
+
+ if( pPrev )
+ {
+ pAction->Duplicate();
+ pPrev->AddAction( pAction, nPos );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* GDIMetaFile::CopyAction( ULONG nPos ) const
+{
+ return ( (MetaAction*) GetObject( nPos ) )->Clone();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetActionPos( const String& rLabel )
+{
+ ImpLabel* pLabel = NULL;
+
+ if( pLabelList )
+ pLabel = pLabelList->ImplGetLabel( pLabelList->ImplGetLabelPos( rLabel ) );
+ else
+ pLabel = NULL;
+
+ return( pLabel ? pLabel->nActionPos : METAFILE_LABEL_NOTFOUND );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::InsertLabel( const String& rLabel, ULONG nActionPos )
+{
+ BOOL bRet = FALSE;
+
+ if( !pLabelList )
+ pLabelList = new ImpLabelList;
+
+ if( pLabelList->ImplGetLabelPos( rLabel ) == METAFILE_LABEL_NOTFOUND )
+ {
+ pLabelList->ImplInsert( new ImpLabel( rLabel, nActionPos ) );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::RemoveLabel( const String& rLabel )
+{
+ if( pLabelList )
+ {
+ const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
+
+ if( nLabelPos != METAFILE_LABEL_NOTFOUND )
+ delete pLabelList->ImplRemove( nLabelPos );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::RenameLabel( const String& rLabel, const String& rNewLabel )
+{
+ if( pLabelList )
+ {
+ const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
+
+ if ( nLabelPos != METAFILE_LABEL_NOTFOUND )
+ pLabelList->ImplGetLabel( nLabelPos )->aLabelName = rNewLabel;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetLabelCount() const
+{
+ return( pLabelList ? pLabelList->ImplCount() : 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+String GDIMetaFile::GetLabel( ULONG nLabel )
+{
+ String aString;
+
+ if( pLabelList )
+ {
+ const ImpLabel* pLabel = pLabelList->ImplGetLabel( nLabel );
+
+ if( pLabel )
+ aString = pLabel->aLabelName;
+ }
+
+ return aString;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::SaveStatus()
+{
+ if ( bRecord )
+ {
+ if ( bPause )
+ Linker( pOutDev, TRUE );
+
+ AddAction( new MetaLineColorAction( pOutDev->GetLineColor(),
+ pOutDev->IsLineColor() ) );
+ AddAction( new MetaFillColorAction( pOutDev->GetFillColor(),
+ pOutDev->IsFillColor() ) );
+ AddAction( new MetaFontAction( pOutDev->GetFont() ) );
+ AddAction( new MetaTextColorAction( pOutDev->GetTextColor() ) );
+ AddAction( new MetaTextFillColorAction( pOutDev->GetTextFillColor(),
+ pOutDev->IsTextFillColor() ) );
+ AddAction( new MetaTextLineColorAction( pOutDev->GetTextLineColor(),
+ pOutDev->IsTextLineColor() ) );
+ AddAction( new MetaTextAlignAction( pOutDev->GetTextAlign() ) );
+ AddAction( new MetaRasterOpAction( pOutDev->GetRasterOp() ) );
+ AddAction( new MetaMapModeAction( pOutDev->GetMapMode() ) );
+ AddAction( new MetaClipRegionAction( pOutDev->GetClipRegion(),
+ pOutDev->IsClipRegion() ) );
+
+ if ( bPause )
+ Linker( pOutDev, FALSE );
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Move( long nX, long nY )
+{
+ for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
+ {
+ MetaAction* pModAct;
+
+ if( pAct->GetRefCount() > 1 )
+ {
+ Replace( pModAct = pAct->Clone(), pAct );
+ pAct->Delete();
+ }
+ else
+ pModAct = pAct;
+
+ pModAct->Move( nX, nY );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Scale( double fScaleX, double fScaleY )
+{
+ for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
+ {
+ MetaAction* pModAct;
+
+ if( pAct->GetRefCount() > 1 )
+ {
+ Replace( pModAct = pAct->Clone(), pAct );
+ pAct->Delete();
+ }
+ else
+ pModAct = pAct;
+
+ pModAct->Scale( fScaleX, fScaleY );
+ }
+
+ aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
+ aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
+{
+ Scale( (double) rScaleX, (double) rScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
+{
+ return Color( rColor.GetTransparency(),
+ ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ],
+ ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ],
+ ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] );
+
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ const ImplBmpAdjustParam* p = (const ImplBmpAdjustParam*) pBmpParam;
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
+ p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
+ p->fGamma, p->bInvert );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
+{
+ BYTE cLum = rColor.GetLuminance();
+
+ if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion )
+ cLum = ( cLum < 128 ) ? 0 : 255;
+
+ return Color( rColor.GetTransparency(), cLum, cLum, cLum );
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColMonoFnc( const Color& rColor, const void* pColParam )
+{
+ return( ( (const ImplColMonoParam*) pColParam )->aColor );
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ BitmapPalette aPal( 3 );
+
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_WHITE );
+ aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor;
+
+ Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
+ aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor );
+
+ if( rBmpEx.IsAlpha() )
+ return BitmapEx( aBmp, rBmpEx.GetAlpha() );
+ else if( rBmpEx.IsTransparent() )
+ return BitmapEx( aBmp, rBmpEx.GetMask() );
+ else
+ return aBmp;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
+{
+ const ULONG nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
+
+ for( ULONG i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ )
+ {
+ if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) )
+ {
+ return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] );
+ }
+ }
+
+ return rColor;
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ const ImplBmpReplaceParam* p = (const ImplBmpReplaceParam*) pBmpParam;
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
+ BmpExchangeFnc pFncBmp, const void* pBmpParam )
+{
+ GDIMetaFile aMtf;
+
+ aMtf.aPrefSize = aPrefSize;
+ aMtf.aPrefMapMode = aPrefMapMode;
+
+ for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
+ {
+ const USHORT nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ MetaPixelAction* pAct = (MetaPixelAction*) pAction;
+ aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ {
+ MetaTextColorAction* pAct = (MetaTextColorAction*) pAction;
+ aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTFILLCOLOR_ACTION ):
+ {
+ MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTLINECOLOR_ACTION ):
+ {
+ MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_FONT_ACTION ):
+ {
+ MetaFontAction* pAct = (MetaFontAction*) pAction;
+ Font aFont( pAct->GetFont() );
+
+ aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
+ aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
+ aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND );
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
+ Wallpaper aWall( pAct->GetWallpaper() );
+ const Rectangle& rRect = pAct->GetRect();
+
+ aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
+
+ if( aWall.IsBitmap() )
+ aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
+
+ if( aWall.IsGradient() )
+ {
+ Gradient aGradient( aWall.GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aWall.SetGradient( aGradient );
+ }
+
+ aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ case( META_BMPEX_ACTION ):
+ case( META_MASK_ACTION ):
+ {
+ DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+ aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+ aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+ aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+ aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+ aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetBitmap(),
+ pFncCol( pAct->GetColor(), pColParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+ aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pAct->GetBitmap(),
+ pFncCol( pAct->GetColor(), pColParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ MetaGradientAction* pAct = (MetaGradientAction*) pAction;
+ Gradient aGradient( pAct->GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND );
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
+ Gradient aGradient( pAct->GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND );
+ }
+ break;
+
+ case( META_HATCH_ACTION ):
+ {
+ MetaHatchAction* pAct = (MetaHatchAction*) pAction;
+ Hatch aHatch( pAct->GetHatch() );
+
+ aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
+ aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND );
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
+ GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
+
+ aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
+ aMtf.Insert( new MetaFloatTransparentAction( aTransMtf,
+ pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetGradient() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ MetaEPSAction* pAct = (MetaEPSAction*) pAction;
+ GDIMetaFile aSubst( pAct->GetSubstitute() );
+
+ aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
+ aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetLink(), aSubst ),
+ LIST_APPEND );
+ }
+ break;
+
+ default:
+ {
+ pAction->Duplicate();
+ aMtf.Insert( pAction, LIST_APPEND );
+ }
+ break;
+ }
+ }
+
+ *this = aMtf;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent,
+ short nChannelBPercent, double fGamma, BOOL bInvert )
+{
+ // nothing to do? => return quickly
+ if( nLuminancePercent || nContrastPercent ||
+ nChannelRPercent || nChannelGPercent || nChannelBPercent ||
+ ( fGamma != 1.0 ) || bInvert )
+ {
+ double fM, fROff, fGOff, fBOff, fOff;
+ ImplColAdjustParam aColParam;
+ ImplBmpAdjustParam aBmpParam;
+
+ aColParam.pMapR = new BYTE[ 256 ];
+ aColParam.pMapG = new BYTE[ 256 ];
+ aColParam.pMapB = new BYTE[ 256 ];
+
+ // calculate slope
+ if( nContrastPercent >= 0 )
+ fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
+ else
+ fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
+
+ // total offset = luminance offset + contrast offset
+ fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
+
+ // channel offset = channel offset + total offset
+ fROff = nChannelRPercent * 2.55 + fOff;
+ fGOff = nChannelGPercent * 2.55 + fOff;
+ fBOff = nChannelBPercent * 2.55 + fOff;
+
+ // calculate gamma value
+ fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
+ const BOOL bGamma = ( fGamma != 1.0 );
+
+ // create mapping table
+ for( long nX = 0L; nX < 256L; nX++ )
+ {
+ aColParam.pMapR[ nX ] = (BYTE) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
+ aColParam.pMapG[ nX ] = (BYTE) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
+ aColParam.pMapB[ nX ] = (BYTE) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
+
+ if( bGamma )
+ {
+ aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
+ aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
+ aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
+ }
+
+ if( bInvert )
+ {
+ aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
+ aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
+ aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
+ }
+ }
+
+ aBmpParam.nLuminancePercent = nLuminancePercent;
+ aBmpParam.nContrastPercent = nContrastPercent;
+ aBmpParam.nChannelRPercent = nChannelRPercent;
+ aBmpParam.nChannelGPercent = nChannelGPercent;
+ aBmpParam.nChannelBPercent = nChannelBPercent;
+ aBmpParam.fGamma = fGamma;
+ aBmpParam.bInvert = bInvert;
+
+ // do color adjustment
+ ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
+
+ delete[] aColParam.pMapR;
+ delete[] aColParam.pMapG;
+ delete[] aColParam.pMapB;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Convert( MtfConversion eConversion )
+{
+ // nothing to do? => return quickly
+ if( eConversion != MTF_CONVERSION_NONE )
+ {
+ ImplColConvertParam aColParam;
+ ImplBmpConvertParam aBmpParam;
+
+ aColParam.eConversion = eConversion;
+ aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
+
+ ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, ULONG nColorCount, ULONG* pTols )
+{
+ ImplColReplaceParam aColParam;
+ ImplBmpReplaceParam aBmpParam;
+
+ aColParam.pMinR = new ULONG[ nColorCount ];
+ aColParam.pMaxR = new ULONG[ nColorCount ];
+ aColParam.pMinG = new ULONG[ nColorCount ];
+ aColParam.pMaxG = new ULONG[ nColorCount ];
+ aColParam.pMinB = new ULONG[ nColorCount ];
+ aColParam.pMaxB = new ULONG[ nColorCount ];
+
+ for( ULONG i = 0; i < nColorCount; i++ )
+ {
+ const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
+ long nVal;
+
+ nVal = pSearchColors[ i ].GetRed();
+ aColParam.pMinR[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxR[ i ] = (ULONG) Min( nVal + nTol, 255L );
+
+ nVal = pSearchColors[ i ].GetGreen();
+ aColParam.pMinG[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxG[ i ] = (ULONG) Min( nVal + nTol, 255L );
+
+ nVal = pSearchColors[ i ].GetBlue();
+ aColParam.pMinB[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxB[ i ] = (ULONG) Min( nVal + nTol, 255L );
+ }
+
+ aColParam.pDstCols = pReplaceColors;
+ aColParam.nCount = nColorCount;
+
+ aBmpParam.pSrcCols = pSearchColors;
+ aBmpParam.pDstCols = pReplaceColors;
+ aBmpParam.nCount = nColorCount;
+ aBmpParam.pTols = pTols;
+
+ ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
+
+ delete[] aColParam.pMinR;
+ delete[] aColParam.pMaxR;
+ delete[] aColParam.pMinG;
+ delete[] aColParam.pMaxG;
+ delete[] aColParam.pMinB;
+ delete[] aColParam.pMaxB;
+};
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
+{
+ GDIMetaFile aRet( *this );
+
+ ImplColMonoParam aColParam;
+ ImplBmpMonoParam aBmpParam;
+
+ aColParam.aColor = rColor;
+ aBmpParam.aColor = rColor;
+
+ aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetChecksum() const
+{
+ GDIMetaFile aMtf;
+ SvMemoryStream aMemStm( 65535, 65535 );
+ ImplMetaWriteData aWriteData; aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
+ SVBT16 aBT16;
+ SVBT32 aBT32;
+ ULONG nCrc = 0;
+
+ for( ULONG i = 0, nCount = GetActionCount(); i < nCount; i++ )
+ {
+ MetaAction* pAction = GetAction( i );
+
+ switch( pAction->GetType() )
+ {
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pAct = (MetaBmpAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pAct = (MetaMaskAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ default:
+ {
+ pAction->Write( aMemStm, &aWriteData );
+ nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
+ aMemStm.Seek( 0 );
+ }
+ break;
+ }
+ }
+
+ return nCrc;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
+{
+ if( !rIStm.GetError() )
+ {
+ char aId[ 7 ];
+ ULONG nStmPos = rIStm.Tell();
+ USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bError = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ rIStm.Read( aId, 6 );
+ aId[ 6 ] = 0;
+
+ if ( !strcmp( aId, "VCLMTF" ) )
+ {
+ // new format
+ VersionCompat* pCompat;
+ MetaAction* pAction;
+ UINT32 nStmCompressMode;
+ UINT32 nCount;
+
+ pCompat = new VersionCompat( rIStm, STREAM_READ );
+
+ rIStm >> nStmCompressMode;
+ rIStm >> rGDIMetaFile.aPrefMapMode;
+ rIStm >> rGDIMetaFile.aPrefSize;
+ rIStm >> nCount;
+
+ delete pCompat;
+
+ ImplMetaReadData aReadData;
+ aReadData.meActualCharSet = rIStm.GetStreamCharSet();
+
+ for( UINT32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
+ {
+ pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
+
+ if( pAction )
+ rGDIMetaFile.AddAction( pAction );
+ }
+ }
+ else
+ {
+ // to avoid possible compiler optimizations => new/delete
+ rIStm.Seek( nStmPos );
+ delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
+ }
+
+ // check for errors
+ if( rIStm.GetError() )
+ {
+ rGDIMetaFile.Clear();
+ rIStm.Seek( nStmPos );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
+{
+ if( !rOStm.GetError() )
+ {
+ if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
+ ((GDIMetaFile&) rGDIMetaFile ).Write( rOStm );
+ else
+ delete( new SVMConverter( rOStm, (GDIMetaFile&) rGDIMetaFile, CONVERT_TO_SVM1 ) );
+ }
+
+ return rOStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& GDIMetaFile::Read( SvStream& rIStm )
+{
+ Clear();
+ rIStm >> *this;
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& GDIMetaFile::Write( SvStream& rOStm )
+{
+ VersionCompat* pCompat;
+ const UINT32 nStmCompressMode = rOStm.GetCompressMode();
+ USHORT nOldFormat = rOStm.GetNumberFormatInt();
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rOStm.Write( "VCLMTF", 6 );
+
+ pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << nStmCompressMode;
+ rOStm << aPrefMapMode;
+ rOStm << aPrefSize;
+ rOStm << (UINT32) GetActionCount();
+
+ delete pCompat;
+
+ ImplMetaWriteData aWriteData;
+ aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
+
+ MetaAction* pAct = (MetaAction*)First();
+ while ( pAct )
+ {
+ pAct->Write( rOStm, &aWriteData );
+ pAct = (MetaAction*)Next();
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+
+ return rOStm;
+}
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
new file mode 100644
index 000000000000..3a175017708e
--- /dev/null
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -0,0 +1,450 @@
+/*************************************************************************
+ *
+ * $RCSfile: gfxlink.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <tools/vcompat.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+#include <tools/tempfile.hxx>
+#include <ucbhelper/content.hxx>
+#include "graph.hxx"
+#include "gfxlink.hxx"
+#include "cvtgrf.hxx"
+
+// -----------
+// - GfxLink -
+// -----------
+
+GfxLink::GfxLink() :
+ meType ( GFX_LINK_TYPE_NONE ),
+ mnBufSize ( 0 ),
+ mpBuf ( NULL ),
+ mpSwap ( NULL ),
+ mnUserId ( 0UL )
+{
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( const GfxLink& rGfxLink )
+{
+ ImplCopy( rGfxLink );
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( const String& rPath, GfxLinkType nType )
+{
+ sal_Int64 nFileSize = 0;
+
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( rPath, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.getPropertyValue( ::rtl::OUString::createFromAscii( "Size" ) ) >>= nFileSize;
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ meType = nType;
+ mnBufSize = nFileSize;
+ mpSwap = NULL;
+ mnUserId = 0UL;
+
+ if( mnBufSize )
+ {
+ SvFileStream aFileStream( rPath, STREAM_READ );
+
+ mpBuf = new ImpBuffer( mnBufSize );
+ aFileStream.Read( mpBuf->mpBuffer, mnBufSize );
+ }
+ else
+ mpBuf = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( BYTE* pBuf, ULONG nSize, GfxLinkType nType, BOOL bOwns )
+{
+ meType = nType;
+ mnBufSize = nSize;
+ mpSwap = NULL;
+ mnUserId = 0UL;
+
+ if( bOwns )
+ mpBuf = new ImpBuffer( pBuf );
+ else if( nSize )
+ {
+ mpBuf = new ImpBuffer( nSize );
+ memcpy( mpBuf->mpBuffer, pBuf, nSize );
+ }
+ else
+ mpBuf = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::~GfxLink()
+{
+ if( mpBuf && !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ if( mpSwap && !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
+{
+ if( &rGfxLink != this )
+ {
+ if ( mpBuf && !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ if( mpSwap && !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+
+ ImplCopy( rGfxLink );
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::ImplCopy( const GfxLink& rGfxLink )
+{
+ mnBufSize = rGfxLink.mnBufSize;
+ meType = rGfxLink.meType;
+ mpBuf = rGfxLink.mpBuf;
+ mpSwap = rGfxLink.mpSwap;
+ mnUserId = rGfxLink.mnUserId;
+
+ if( mpBuf )
+ mpBuf->mnRefCount++;
+
+ if( mpSwap )
+ mpSwap->mnRefCount++;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLinkType GfxLink::GetType() const
+{
+ return meType;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GfxLink::IsNative() const
+{
+ return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GfxLink::GetDataSize() const
+{
+ return mnBufSize;
+}
+
+// ------------------------------------------------------------------------
+
+const BYTE* GfxLink::GetData() const
+{
+ if( IsSwappedOut() )
+ ( (GfxLink*) this )->SwapIn();
+
+ return( mpBuf ? mpBuf->mpBuffer : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GfxLink::LoadNative( Graphic& rGraphic )
+{
+ BOOL bRet = FALSE;
+
+ if( IsNative() && mnBufSize )
+ {
+ const BYTE* pData = GetData();
+
+ if( pData )
+ {
+ SvMemoryStream aMemStm;
+ ULONG nCvtType;
+
+ aMemStm.SetBuffer( (char*) pData, mnBufSize, FALSE, mnBufSize );
+
+ switch( meType )
+ {
+ case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
+ case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
+ case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
+ case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
+ case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
+ case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
+ case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
+
+ default: nCvtType = CVT_UNKNOWN; break;
+ }
+
+ if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::SwapOut()
+{
+ if( !IsSwappedOut() && mpBuf )
+ {
+ mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );
+
+ if( !mpSwap->IsSwapped() )
+ {
+ delete mpSwap;
+ mpSwap = NULL;
+ }
+ else if( !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ mpBuf = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::SwapIn()
+{
+ if( IsSwappedOut() )
+ {
+ mpBuf = new ImpBuffer( mpSwap->GetData() );
+
+ if( !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+
+ mpSwap = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
+{
+ VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 1 );
+
+ rOStream << (UINT16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();
+
+ delete pCompat;
+
+ if( rGfxLink.GetDataSize() )
+ {
+ if( rGfxLink.IsSwappedOut() )
+ rGfxLink.mpSwap->WriteTo( rOStream );
+ else
+ rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
+ }
+
+ return rOStream;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
+{
+ ULONG nSize;
+ ULONG nUserId;
+ UINT16 nType;
+ BYTE* pBuf;
+ VersionCompat* pCompat = new VersionCompat( rIStream, STREAM_READ );
+
+ rIStream >> nType >> nSize >> nUserId;
+
+ delete pCompat;
+
+ pBuf = new BYTE[ nSize ];
+ rIStream.Read( pBuf, nSize );
+
+ rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, TRUE );
+ rGfxLink.SetUserId( nUserId );
+
+ return rIStream;
+}
+
+// -----------
+// - ImpSwap -
+// -----------
+
+ImpSwap::ImpSwap( BYTE* pData, ULONG nDataSize ) :
+ mnDataSize( nDataSize ),
+ mnRefCount( 1UL )
+{
+ if( pData && mnDataSize )
+ {
+ maFileName = TempFile::CreateTempName();
+
+ if( maFileName.Len() )
+ {
+ SvFileStream aOStm( maFileName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.Write( pData, mnDataSize );
+
+ if( aOStm.GetError() )
+ {
+ aOStm.Close();
+
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( maFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ maFileName.Erase();
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImpSwap::~ImpSwap()
+{
+ if( IsSwapped() )
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( maFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+BYTE* ImpSwap::GetData() const
+{
+ BYTE* pData;
+
+ if( IsSwapped() )
+ {
+ SvFileStream aIStm( maFileName, STREAM_READ );
+
+ pData = new BYTE[ mnDataSize ];
+ aIStm.Read( pData, mnDataSize );
+
+ if( aIStm.GetError() )
+ {
+ aIStm.Close();
+ delete[] pData;
+ pData = NULL;
+ }
+ }
+ else
+ pData = NULL;
+
+ return pData;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpSwap::WriteTo( SvStream& rOStm ) const
+{
+ BYTE* pData = GetData();
+
+ if( pData )
+ {
+ rOStm.Write( pData, mnDataSize );
+ delete[] pData;
+ }
+}
diff --git a/vcl/source/gdi/gradient.cxx b/vcl/source/gdi/gradient.cxx
new file mode 100644
index 000000000000..7a6489f9c8e6
--- /dev/null
+++ b/vcl/source/gdi/gradient.cxx
@@ -0,0 +1,386 @@
+/*************************************************************************
+ *
+ * $RCSfile: gradient.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GRADIENT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Gradient );
+
+// -----------------------------------------------------------------------
+
+Impl_Gradient::Impl_Gradient() :
+ maStartColor( COL_BLACK ),
+ maEndColor( COL_WHITE )
+{
+ mnRefCount = 1;
+ meStyle = GRADIENT_LINEAR;
+ mnAngle = 0;
+ mnBorder = 0;
+ mnOfsX = 50;
+ mnOfsY = 50;
+ mnIntensityStart = 100;
+ mnIntensityEnd = 100;
+ mnStepCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+Impl_Gradient::Impl_Gradient( const Impl_Gradient& rImplGradient ) :
+ maStartColor( rImplGradient.maStartColor ),
+ maEndColor( rImplGradient.maEndColor )
+{
+ mnRefCount = 1;
+ meStyle = rImplGradient.meStyle;
+ mnAngle = rImplGradient.mnAngle;
+ mnBorder = rImplGradient.mnBorder;
+ mnOfsX = rImplGradient.mnOfsX;
+ mnOfsY = rImplGradient.mnOfsY;
+ mnIntensityStart = rImplGradient.mnIntensityStart;
+ mnIntensityEnd = rImplGradient.mnIntensityEnd;
+ mnStepCount = rImplGradient.mnStepCount;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::MakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplGradient->mnRefCount != 1 )
+ {
+ if( mpImplGradient->mnRefCount )
+ mpImplGradient->mnRefCount--;
+
+ mpImplGradient = new Impl_Gradient( *mpImplGradient );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient()
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( const Gradient& rGradient )
+{
+ DBG_CTOR( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ // Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplGradient = rGradient.mpImplGradient;
+ mpImplGradient->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( GradientStyle eStyle )
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+ mpImplGradient->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( GradientStyle eStyle,
+ const Color& rStartColor, const Color& rEndColor )
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+ mpImplGradient->meStyle = eStyle;
+ mpImplGradient->maStartColor = rStartColor;
+ mpImplGradient->maEndColor = rEndColor;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::~Gradient()
+{
+ DBG_DTOR( Gradient, NULL );
+
+ // Wenn es die letzte Referenz ist, loeschen,
+ // sonst Referenzcounter decrementieren
+ if ( mpImplGradient->mnRefCount == 1 )
+ delete mpImplGradient;
+ else
+ mpImplGradient->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStyle( GradientStyle eStyle )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStartColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->maStartColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetEndColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->maEndColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetAngle( USHORT nAngle )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnAngle = nAngle;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetBorder( USHORT nBorder )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnBorder = nBorder;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetOfsX( USHORT nOfsX )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnOfsX = nOfsX;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetOfsY( USHORT nOfsY )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnOfsY = nOfsY;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStartIntensity( USHORT nIntens )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnIntensityStart = nIntens;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetEndIntensity( USHORT nIntens )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnIntensityEnd = nIntens;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetSteps( USHORT nSteps )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnStepCount = nSteps;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient& Gradient::operator=( const Gradient& rGradient )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rGradient.mpImplGradient->mnRefCount++;
+
+ // Wenn es die letzte Referenz ist, loeschen,
+ // sonst Referenzcounter decrementieren
+ if ( mpImplGradient->mnRefCount == 1 )
+ delete mpImplGradient;
+ else
+ mpImplGradient->mnRefCount--;
+ mpImplGradient = rGradient.mpImplGradient;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Gradient::operator==( const Gradient& rGradient ) const
+{
+ DBG_CHKTHIS( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if ( mpImplGradient == rGradient.mpImplGradient )
+ return TRUE;
+
+ if ( (mpImplGradient->meStyle == rGradient.mpImplGradient->meStyle) ||
+ (mpImplGradient->mnAngle == rGradient.mpImplGradient->mnAngle) ||
+ (mpImplGradient->mnBorder == rGradient.mpImplGradient->mnBorder) ||
+ (mpImplGradient->mnOfsX == rGradient.mpImplGradient->mnOfsX) ||
+ (mpImplGradient->mnOfsY == rGradient.mpImplGradient->mnOfsY) ||
+ (mpImplGradient->mnStepCount == rGradient.mpImplGradient->mnStepCount) ||
+ (mpImplGradient->mnIntensityStart == rGradient.mpImplGradient->mnIntensityStart) ||
+ (mpImplGradient->mnIntensityEnd == rGradient.mpImplGradient->mnIntensityEnd) ||
+ (mpImplGradient->maStartColor == rGradient.mpImplGradient->maStartColor) ||
+ (mpImplGradient->maEndColor == rGradient.mpImplGradient->maEndColor) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+SvStream& operator>>( SvStream& rIStm, Impl_Gradient& rImpl_Gradient )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImpl_Gradient.meStyle = (GradientStyle) nTmp16;
+
+ rIStm >> rImpl_Gradient.maStartColor >>
+ rImpl_Gradient.maEndColor >>
+ rImpl_Gradient.mnAngle >>
+ rImpl_Gradient.mnBorder >>
+ rImpl_Gradient.mnOfsX >>
+ rImpl_Gradient.mnOfsY >>
+ rImpl_Gradient.mnIntensityStart >>
+ rImpl_Gradient.mnIntensityEnd >>
+ rImpl_Gradient.mnStepCount;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Impl_Gradient& rImpl_Gradient )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImpl_Gradient.meStyle <<
+ rImpl_Gradient.maStartColor <<
+ rImpl_Gradient.maEndColor <<
+ rImpl_Gradient.mnAngle <<
+ rImpl_Gradient.mnBorder <<
+ rImpl_Gradient.mnOfsX <<
+ rImpl_Gradient.mnOfsY <<
+ rImpl_Gradient.mnIntensityStart <<
+ rImpl_Gradient.mnIntensityEnd <<
+ rImpl_Gradient.mnStepCount;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Gradient& rGradient )
+{
+ rGradient.MakeUnique();
+ return( rIStm >> *rGradient.mpImplGradient );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Gradient& rGradient )
+{
+ return( rOStm << *rGradient.mpImplGradient );
+}
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
new file mode 100644
index 000000000000..3c847d7dd916
--- /dev/null
+++ b/vcl/source/gdi/graph.cxx
@@ -0,0 +1,832 @@
+/*************************************************************************
+ *
+ * $RCSfile: graph.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GRAPH_CXX
+
+#ifndef _SV_CLIP_HXX
+#include <clip.hxx>
+#endif
+#ifndef _SV_IMPGRAPH_HXX
+#include <impgraph.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_CLIP_HXX
+#include <clip.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+#include <graph.hxx>
+
+// -----------------------
+// - Compression defines -
+// -----------------------
+
+#define COMPRESS_OWN ('S'|('D'<<8UL))
+#define COMPRESS_NONE ( 0UL )
+#define RLE_8 ( 1UL )
+#define RLE_4 ( 2UL )
+#define BITFIELDS ( 3UL )
+#define ZCOMPRESS ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
+
+// -----------------------
+// - Default-Drawmethode -
+// -----------------------
+
+static void ImplDrawDefault( OutputDevice* pOutDev, const UniString* pText,
+ Font* pFont, const Bitmap* pBitmap,
+ const Point& rDestPt, const Size& rDestSize )
+{
+ USHORT nPixel = (USHORT) pOutDev->PixelToLogic( Size( 1, 1 ) ).Width();
+ USHORT nWidth = nPixel;
+ Point aPoint( rDestPt.X() + nWidth, rDestPt.Y() + nWidth );
+ Size aSize( rDestSize.Width() - ( nWidth << 1 ), rDestSize.Height() - ( nWidth << 1 ) );
+ BOOL bFilled = ( pBitmap != NULL || pFont != NULL );
+ Rectangle aBorderRect( aPoint, aSize );
+
+ pOutDev->Push();
+
+ pOutDev->SetFillColor();
+
+ // Auf dem Drucker ein schwarzes Rechteck und auf dem Bildschirm eins mit 3D-Effekt
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ pOutDev->SetLineColor( COL_BLACK );
+ else
+ {
+ aBorderRect.Left() += nPixel;
+ aBorderRect.Top() += nPixel;
+
+ pOutDev->SetLineColor( COL_LIGHTGRAY );
+ pOutDev->DrawRect( aBorderRect );
+
+ aBorderRect.Left() -= nPixel;
+ aBorderRect.Top() -= nPixel;
+ aBorderRect.Right() -= nPixel;
+ aBorderRect.Bottom() -= nPixel;
+ pOutDev->SetLineColor( COL_GRAY );
+ }
+
+ pOutDev->DrawRect( aBorderRect );
+
+ aPoint.X() += nWidth + 2*nPixel;
+ aPoint.Y() += nWidth + 2*nPixel;
+ aSize.Width() -= 2*nWidth + 4*nPixel;
+ aSize.Height() -= 2*nWidth + 4*nPixel;
+
+ if( aSize.Width() > 0 && aSize.Height() > 0 && pBitmap && !!*pBitmap )
+ {
+ Size aBitmapSize( pOutDev->PixelToLogic(pBitmap->GetSizePixel() ) );
+
+ if( aSize.Height() > aBitmapSize.Height() && aSize.Width() > aBitmapSize.Width() )
+ {
+ pOutDev->DrawBitmap( aPoint, *pBitmap );
+ aPoint.X() += aBitmapSize.Width() + 2*nPixel;
+ aSize.Width() -= aBitmapSize.Width() + 2*nPixel;
+ }
+ }
+
+ if ( aSize.Width() > 0 && aSize.Height() > 0 && pFont && pText && pText->Len()
+ && !(!pOutDev->IsOutputEnabled() /*&& pOutDev->GetConnectMetaFile() */) )
+ {
+ MapMode aMapMode( MAP_POINT );
+ Size aSz = pOutDev->LogicToLogic( Size( 0, 12 ), &aMapMode, NULL );
+ long nThreshold = aSz.Height() / 2;
+ long nStep = nThreshold / 3;
+
+ if ( !nStep )
+ nStep = aSz.Height() - nThreshold;
+
+ for(;; aSz.Height() -= nStep )
+ {
+ pFont->SetSize( aSz );
+ pOutDev->SetFont( *pFont );
+
+ long nTextHeight = pOutDev->GetTextHeight();
+ long nTextWidth = pOutDev->GetTextWidth( *pText );
+ if ( nTextHeight )
+ {
+ // Die N"aherung ber"ucksichtigt keine Ungenauigkeiten durch
+ // Wortumbr"uche
+ long nLines = aSize.Height() / nTextHeight;
+ long nWidth = aSize.Width() * nLines; // N"aherung!!!
+
+ if ( nTextWidth <= nWidth || aSz.Height() <= nThreshold )
+ {
+ USHORT nStart = 0;
+ USHORT nLen = 0;
+
+ while( nStart < pText->Len() && pText->GetChar( nStart ) == ' ' )
+ nStart++;
+ while( nStart+nLen < pText->Len() && pText->GetChar( nStart+nLen ) != ' ' )
+ nLen++;
+ while( nStart < pText->Len() && nLines-- )
+ {
+ USHORT nNext = nLen;
+ do
+ {
+ while ( nStart+nNext < pText->Len() && pText->GetChar( nStart+nNext ) == ' ' )
+ nNext++;
+ while ( nStart+nNext < pText->Len() && pText->GetChar( nStart+nNext ) != ' ' )
+ nNext++;
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, nNext );
+ if ( nTextWidth > aSize.Width() )
+ break;
+ nLen = nNext;
+ }
+ while ( nStart+nNext < pText->Len() );
+
+ USHORT n = nLen;
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, n );
+ while( nTextWidth > aSize.Width() )
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, --n );
+ pOutDev->DrawText( aPoint, *pText, nStart, n );
+
+ aPoint.Y() += nTextHeight;
+ nStart += nLen;
+ nLen = nNext-nLen;
+ while( nStart < pText->Len() && pText->GetChar( nStart ) == ' ' )
+ {
+ nStart++;
+ nLen--;
+ }
+ }
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+ // Falls die Default-Graphik keinen Inhalt hat,
+ // malen wir ein rotes Kreuz
+ if( !bFilled )
+ {
+ aBorderRect.Left()++;
+ aBorderRect.Top()++;
+ aBorderRect.Right()--;
+ aBorderRect.Bottom()--;
+
+ pOutDev->SetLineColor( COL_LIGHTRED );
+ pOutDev->DrawLine( aBorderRect.TopLeft(), aBorderRect.BottomRight() );
+ pOutDev->DrawLine( aBorderRect.TopRight(), aBorderRect.BottomLeft() );
+ }
+
+ pOutDev->Pop();
+}
+
+// -----------
+// - Graphic -
+// -----------
+
+TYPEINIT1_AUTOFACTORY( Graphic, SvDataCopyStream );
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic()
+{
+ mpImpGraphic = new ImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Graphic& rGraphic )
+{
+ if( rGraphic.IsAnimated() )
+ mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
+ else
+ {
+ mpImpGraphic = rGraphic.mpImpGraphic;
+ mpImpGraphic->mnRefCount++;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Bitmap& rBmp )
+{
+ mpImpGraphic = new ImpGraphic( rBmp );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const BitmapEx& rBmpEx )
+{
+ mpImpGraphic = new ImpGraphic( rBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Animation& rAnimation )
+{
+ mpImpGraphic = new ImpGraphic( rAnimation );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const GDIMetaFile& rMtf )
+{
+ mpImpGraphic = new ImpGraphic( rMtf );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::~Graphic()
+{
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::ImplTestRefCount()
+{
+ if( mpImpGraphic->mnRefCount > 1UL )
+ {
+ mpImpGraphic->mnRefCount--;
+ mpImpGraphic = new ImpGraphic( *mpImpGraphic );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic& Graphic::operator=( const Graphic& rGraphic )
+{
+ if( &rGraphic != this )
+ {
+ if( rGraphic.IsAnimated() )
+ {
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+
+ mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
+ }
+ else
+ {
+ rGraphic.mpImpGraphic->mnRefCount++;
+
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+
+ mpImpGraphic = rGraphic.mpImpGraphic;
+ }
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator==( const Graphic& rGraphic ) const
+{
+ return( *mpImpGraphic == *rGraphic.mpImpGraphic );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator!=( const Graphic& rGraphic ) const
+{
+ return( *mpImpGraphic != *rGraphic.mpImpGraphic );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator!() const
+{
+ return( GRAPHIC_NONE == mpImpGraphic->ImplGetType() );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Load( SvStream& rIStm )
+{
+ rIStm >> *this;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Save( SvStream& rOStm )
+{
+ rOStm << *this;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Assign( const SvDataCopyStream& rCopyStream )
+{
+ *this = (const Graphic& ) rCopyStream;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Clear()
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplClear();
+}
+
+// ------------------------------------------------------------------------
+
+GraphicType Graphic::GetType() const
+{
+ return mpImpGraphic->ImplGetType();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetDefaultType()
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetDefaultType();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsSupportedGraphic() const
+{
+ return mpImpGraphic->ImplIsSupportedGraphic();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsTransparent() const
+{
+ return mpImpGraphic->ImplIsTransparent();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsAlpha() const
+{
+ return mpImpGraphic->ImplIsAlpha();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsAnimated() const
+{
+ return mpImpGraphic->ImplIsAnimated();
+}
+
+// ------------------------------------------------------------------------
+
+Bitmap Graphic::GetBitmap() const
+{
+ return mpImpGraphic->ImplGetBitmap();
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx Graphic::GetBitmapEx() const
+{
+ return mpImpGraphic->ImplGetBitmapEx();
+}
+
+// ------------------------------------------------------------------------
+
+Animation Graphic::GetAnimation() const
+{
+ return mpImpGraphic->ImplGetAnimation();
+}
+
+// ------------------------------------------------------------------------
+
+const GDIMetaFile& Graphic::GetGDIMetaFile() const
+{
+ return mpImpGraphic->ImplGetGDIMetaFile();
+}
+
+// ------------------------------------------------------------------------
+
+Size Graphic::GetPrefSize() const
+{
+ return mpImpGraphic->ImplGetPrefSize();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetPrefSize( const Size& rPrefSize )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetPrefSize( rPrefSize );
+}
+
+// ------------------------------------------------------------------------
+
+MapMode Graphic::GetPrefMapMode() const
+{
+ return mpImpGraphic->ImplGetPrefMapMode();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetPrefMapMode( const MapMode& rPrefMapMode )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetPrefMapMode( rPrefMapMode );
+}
+
+// ------------------------------------------------------------------
+
+ULONG Graphic::GetSizeBytes() const
+{
+ return mpImpGraphic->ImplGetSizeBytes();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ mpImpGraphic->ImplDraw( pOutDev, rDestPt );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( GRAPHIC_DEFAULT == mpImpGraphic->ImplGetType() )
+ ImplDrawDefault( pOutDev, NULL, NULL, NULL, rDestPt, rDestSz );
+ else
+ mpImpGraphic->ImplDraw( pOutDev, rDestPt, rDestSz );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev, const String& rText,
+ Font& rFont, const Bitmap& rBitmap,
+ const Point& rDestPt, const Size& rDestSz )
+{
+ ImplDrawDefault( pOutDev, &rText, &rFont, &rBitmap, rDestPt, rDestSz );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StartAnimation( OutputDevice* pOutDev, const Point& rDestPt, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStartAnimation( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
+ const Size& rDestSz, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStartAnimation( pOutDev, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StopAnimation( OutputDevice* pOutDev, long nExtraData )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStopAnimation( pOutDev, nExtraData );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetAnimationNotifyHdl( const Link& rLink )
+{
+ mpImpGraphic->ImplSetAnimationNotifyHdl( rLink );
+}
+
+// ------------------------------------------------------------------------
+
+Link Graphic::GetAnimationNotifyHdl() const
+{
+ return mpImpGraphic->ImplGetAnimationNotifyHdl();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetAnimationLoopCount() const
+{
+ return mpImpGraphic->ImplGetAnimationLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::ResetAnimationLoopCount()
+{
+ mpImpGraphic->ImplResetAnimationLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+List* Graphic::GetAnimationInfoList() const
+{
+ return mpImpGraphic->ImplGetAnimationInfoList();
+}
+
+// ------------------------------------------------------------------------
+
+GraphicReader* Graphic::GetContext()
+{
+ return mpImpGraphic->ImplGetContext();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetContext( GraphicReader* pReader )
+{
+ mpImpGraphic->ImplSetContext( pReader );
+}
+
+// ------------------------------------------------------------------------
+
+USHORT Graphic::GetGraphicsCompressMode( SvStream& rIStm )
+{
+ const ULONG nPos = rIStm.Tell();
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ USHORT nCompressMode = COMPRESSMODE_NONE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ rIStm >> nTmp32;
+
+ // is it a swapped graphic with a bitmap?
+ rIStm.SeekRel( (nTmp32 == (UINT32) GRAPHIC_BITMAP ) ? 40 : -4 );
+
+ // try to read bitmap id
+ rIStm >> nTmp16;
+
+ // check id of BitmapFileHeader
+ if( 0x4D42 == nTmp16 )
+ {
+ // seek to compress field of BitmapInfoHeader
+ rIStm.SeekRel( 28 );
+ rIStm >> nTmp32;
+
+ // Compare with our own compressmode
+ if( ZCOMPRESS == nTmp32 )
+ nCompressMode = COMPRESSMODE_ZBITMAP;
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ rIStm.Seek( nPos );
+
+ return nCompressMode;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetDocFileName( const String& rName, ULONG nFilePos )
+{
+ mpImpGraphic->ImplSetDocFileName( rName, nFilePos );
+}
+
+// ------------------------------------------------------------------------
+
+const String& Graphic::GetDocFileName() const
+{
+ return mpImpGraphic->ImplGetDocFileName();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetDocFilePos() const
+{
+ return mpImpGraphic->ImplGetDocFilePos();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::ReadEmbedded( SvStream& rIStream, BOOL bSwap )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplReadEmbedded( rIStream, bSwap );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::WriteEmbedded( SvStream& rOStream )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplWriteEmbedded( rOStream );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapOut()
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapOut( SvStream* pOStream )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapOut( pOStream );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapIn()
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapIn();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapIn( SvStream* pStrm )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapIn( pStrm );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsSwapOut() const
+{
+ return mpImpGraphic->ImplIsSwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetLink( const GfxLink& rGfxLink )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetLink( rGfxLink );
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink Graphic::GetLink()
+{
+ return mpImpGraphic->ImplGetLink();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsLink() const
+{
+ return mpImpGraphic->ImplIsLink();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetChecksum() const
+{
+ return mpImpGraphic->ImplGetChecksum();
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, Graphic& rGraphic )
+{
+ rGraphic.ImplTestRefCount();
+ return rIStream >> *rGraphic.mpImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const Graphic& rGraphic )
+{
+ return rOStream << *rGraphic.mpImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::RegisterClipboardFormatName()
+{
+ static ULONG nFormat = 0;
+
+ if ( !nFormat )
+ nFormat = Clipboard::RegisterFormatName( XubString( RTL_CONSTASCII_USTRINGPARAM( "SVXB (StarView Bitmap/Animation)" ) ) );
+
+ return nFormat;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::ClipboardHasFormat()
+{
+ return Clipboard::HasFormat( RegisterClipboardFormatName() )
+ || Clipboard::HasFormat( FORMAT_GDIMETAFILE )
+ || Clipboard::HasFormat( FORMAT_BITMAP );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::DragServerHasFormat( USHORT nItem )
+{
+ return DragServer::HasFormat( nItem, RegisterClipboardFormatName() )
+ || DragServer::HasFormat( nItem, FORMAT_GDIMETAFILE )
+ || DragServer::HasFormat( nItem, FORMAT_BITMAP );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::Copy() const
+{
+ SotDataMemberObjectRef aDataObject = new SotDataMemberObject;
+ SvData* pData = new SvData( RegisterClipboardFormatName() );
+
+ pData->SetData( (SvDataCopyStream*) this, TRANSFER_COPY );
+ aDataObject->Append( pData );
+ VclClipboard::Copy( aDataObject );
+
+ return TRUE;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::Paste()
+{
+ const ULONG nFormat = RegisterClipboardFormatName();
+ BOOL bRet = FALSE;
+
+ if( VclClipboard::HasFormat( nFormat ) )
+ {
+ SotDataObjectRef aDataObject = VclClipboard::Paste();
+ SvData aData( nFormat );
+
+ if( aDataObject.Is() && aDataObject->GetData( &aData ) )
+ {
+ Graphic* pGraphic = NULL;
+
+ if( aData.GetData( (SvDataCopyStream**) &pGraphic, StaticType(), TRANSFER_MOVE ) )
+ *this = *pGraphic;
+
+ delete pGraphic;
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/hatch.cxx b/vcl/source/gdi/hatch.cxx
new file mode 100644
index 000000000000..ac66e89fd0cf
--- /dev/null
+++ b/vcl/source/gdi/hatch.cxx
@@ -0,0 +1,262 @@
+/*************************************************************************
+ *
+ * $RCSfile: hatch.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_HATCH_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_HATCX_HXX
+#include <hatch.hxx>
+#endif
+
+DBG_NAME( Hatch );
+
+// --------------
+// - ImplHatch -
+// --------------
+
+ImplHatch::ImplHatch() :
+ mnRefCount ( 1 ),
+ maColor ( COL_BLACK ),
+ meStyle ( HATCH_SINGLE ),
+ mnDistance ( 1 ),
+ mnAngle ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplHatch::ImplHatch( const ImplHatch& rImplHatch ) :
+ mnRefCount ( 1 ),
+ maColor ( rImplHatch.maColor ),
+ meStyle ( rImplHatch.meStyle ),
+ mnDistance ( rImplHatch.mnDistance ),
+ mnAngle ( rImplHatch.mnAngle )
+{
+}
+
+// ---------
+// - Hatch -
+// ---------
+
+Hatch::Hatch()
+{
+ DBG_CTOR( Hatch, NULL );
+ mpImplHatch = new ImplHatch;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::Hatch( const Hatch& rHatch )
+{
+ DBG_CTOR( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+ mpImplHatch = rHatch.mpImplHatch;
+ mpImplHatch->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::Hatch( HatchStyle eStyle, const Color& rColor,
+ long nDistance, USHORT nAngle10 )
+{
+ DBG_CTOR( Hatch, NULL );
+ mpImplHatch = new ImplHatch;
+ mpImplHatch->maColor = rColor;
+ mpImplHatch->meStyle = eStyle;
+ mpImplHatch->mnDistance = nDistance;
+ mpImplHatch->mnAngle = nAngle10;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::~Hatch()
+{
+ DBG_DTOR( Hatch, NULL );
+ if( !( --mpImplHatch->mnRefCount ) )
+ delete mpImplHatch;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch& Hatch::operator=( const Hatch& rHatch )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+
+ rHatch.mpImplHatch->mnRefCount++;
+
+ if( !( --mpImplHatch->mnRefCount ) )
+ delete mpImplHatch;
+
+ mpImplHatch = rHatch.mpImplHatch;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Hatch::operator==( const Hatch& rHatch ) const
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+
+ return( mpImplHatch == rHatch.mpImplHatch ||
+ ( mpImplHatch->maColor == rHatch.mpImplHatch->maColor &&
+ mpImplHatch->meStyle == rHatch.mpImplHatch->meStyle &&
+ mpImplHatch->mnDistance == rHatch.mpImplHatch->mnDistance &&
+ mpImplHatch->mnAngle == rHatch.mpImplHatch->mnAngle ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::ImplMakeUnique()
+{
+ if( mpImplHatch->mnRefCount != 1 )
+ {
+ if( mpImplHatch->mnRefCount )
+ mpImplHatch->mnRefCount--;
+
+ mpImplHatch = new ImplHatch( *mpImplHatch );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetStyle( HatchStyle eStyle )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->maColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetDistance( long nDistance )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->mnDistance = nDistance;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetAngle( USHORT nAngle10 )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->mnAngle = nAngle10;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplHatch& rImplHatch )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplHatch.meStyle = (HatchStyle) nTmp16;
+ rIStm >> rImplHatch.maColor >> rImplHatch.mnDistance >> rImplHatch.mnAngle;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplHatch& rImplHatch )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImplHatch.meStyle << rImplHatch.maColor;
+ rOStm << rImplHatch.mnDistance << rImplHatch.mnAngle;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Hatch& rHatch )
+{
+ rHatch.ImplMakeUnique();
+ return( rIStm >> *rHatch.mpImplHatch );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Hatch& rHatch )
+{
+ return( rOStm << *rHatch.mpImplHatch );
+}
diff --git a/vcl/source/gdi/image.cxx b/vcl/source/gdi/image.cxx
new file mode 100644
index 000000000000..16188cdc5143
--- /dev/null
+++ b/vcl/source/gdi/image.cxx
@@ -0,0 +1,1521 @@
+/*************************************************************************
+ *
+ * $RCSfile: image.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#define _SV_IMAGE_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_RC_HXX
+#include <rc.hxx>
+#endif
+#ifndef _SV_RESMGR_HXX
+#include <resmgr.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_IMAGE_H
+#include <image.h>
+#endif
+#define private public
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#undef private
+
+// =======================================================================
+
+DBG_NAME( Image );
+DBG_NAME( ImageList );
+
+#define IMAGE_FILE_VERSION 100
+
+// =======================================================================
+
+ImplImageList::~ImplImageList()
+{
+ if ( mpImageBitmap )
+ delete mpImageBitmap;
+ delete mpAry;
+}
+
+// =======================================================================
+
+ImplImageRefData::~ImplImageRefData()
+{
+ mpImplData->mnIRefCount--;
+ if ( mpImplData->mnRefCount || mpImplData->mnIRefCount )
+ {
+ mpImplData->mpAry[mnIndex].mnRefCount--;
+ if ( !mpImplData->mpAry[mnIndex].mnRefCount )
+ mpImplData->mnRealCount--;
+ }
+ else
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageRefData::IsEqual( const ImplImageRefData& rData )
+{
+ if ( (mpImplData == rData.mpImplData) && (mnIndex == rData.mnIndex) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplImageData::ImplImageData( const Bitmap& rBmp, const Bitmap& rMaskBmp ) :
+ maBmp( rBmp ),
+ maMaskBmp( rMaskBmp )
+{
+ mbColor = FALSE;
+ mpImageBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageData::ImplImageData( const Bitmap& rBmp, const Color& rColor ) :
+ maBmp( rBmp ),
+ maColor( rColor )
+{
+ mbColor = TRUE;
+ mpImageBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageData::~ImplImageData()
+{
+ if ( mpImageBitmap )
+ delete mpImageBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageData::IsEqual( const ImplImageData& rData )
+{
+ if ( (maBmp == rData.maBmp) && (maMaskBmp == rData.maMaskBmp) &&
+ (maColor == rData.maColor) && (mbColor == rData.mbColor) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplImage::~ImplImage()
+{
+ switch ( meType )
+ {
+ case IMAGETYPE_BITMAP:
+ delete (Bitmap*)mpData;
+ break;
+
+ case IMAGETYPE_IMAGE:
+ delete (ImplImageData*)mpData;
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ delete (ImplImageRefData*)mpData;
+ break;
+ }
+}
+
+// =======================================================================
+
+Image::Image()
+{
+ DBG_CTOR( Image, NULL );
+
+ mpImplData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const ResId& rResId )
+{
+ DBG_CTOR( Image, NULL );
+
+ rResId.SetRT( RSC_IMAGE );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // Header ueberspringen
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ USHORT nObjMask = pResMgr->ReadShort();
+
+ Bitmap aImageBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ if( nObjMask & RSC_IMAGE_IMAGEBITMAP )
+ {
+ aImageBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if( nObjMask & RSC_IMAGE_MASKBITMAP )
+ {
+ aMaskBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ {
+ aMaskColor = Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+
+ if ( !aImageBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ if ( !aMaskBitmap )
+ {
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aImageBitmap, aMaskColor );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( aImageBitmap );
+ }
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aImageBitmap, aMaskBitmap );
+ }
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Image::Image( const ResId& rResId ): No resource!" );
+ mpImplData = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Image& rImage )
+{
+ DBG_CTOR( Image, NULL );
+
+ mpImplData = rImage.mpImplData;
+ if ( mpImplData )
+ mpImplData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( rBitmap );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap, const Bitmap& rMaskBitmap )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ if ( !rMaskBitmap )
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( rBitmap );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( rBitmap, rMaskBitmap );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap, const Color& rColor )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( rBitmap, rColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const BitmapEx& rBitmapEx )
+{
+ DBG_CTOR( Image, NULL );
+
+ const Bitmap aBmp( rBitmapEx.GetBitmap() );
+
+ if( !aBmp )
+ mpImplData = NULL;
+ else
+ {
+ const Bitmap aMask( rBitmapEx.GetMask() );
+
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+
+ if( !aMask )
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( aBmp );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aBmp, aMask );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::~Image()
+{
+ DBG_DTOR( Image, NULL );
+
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Image::GetSizePixel() const
+{
+ DBG_CHKTHIS( Image, NULL );
+
+ if ( mpImplData )
+ {
+ switch ( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ return ((Bitmap*)mpImplData->mpData)->GetSizePixel();
+
+ case IMAGETYPE_IMAGE:
+ return ((ImplImageData*)mpImplData->mpData)->maBmp.GetSizePixel();
+
+ case IMAGETYPE_IMAGEREF:
+ return ((ImplImageRefData*)mpImplData->mpData)->mpImplData->maImageSize;
+ }
+ }
+
+ return Size();
+}
+
+// -----------------------------------------------------------------------
+
+Image& Image::operator=( const Image& rImage )
+{
+ DBG_CHKTHIS( Image, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rImage.mpImplData )
+ rImage.mpImplData->mnRefCount++;
+
+ // Abkoppeln
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+
+ // Neue Daten zuweisen
+ mpImplData = rImage.mpImplData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Image::operator==( const Image& rImage ) const
+{
+ DBG_CHKTHIS( Image, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+
+ if ( rImage.mpImplData == mpImplData )
+ return TRUE;
+ if ( !rImage.mpImplData || !mpImplData )
+ return FALSE;
+
+ if ( rImage.mpImplData->mpData == mpImplData->mpData )
+ return TRUE;
+
+ if ( rImage.mpImplData->meType == mpImplData->meType )
+ {
+ switch ( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ if ( *((Bitmap*)rImage.mpImplData->mpData) == *((Bitmap*)mpImplData->mpData) )
+ return TRUE;
+ break;
+
+ case IMAGETYPE_IMAGE:
+ if ( ((ImplImageData*)rImage.mpImplData->mpData)->IsEqual( *((ImplImageData*)mpImplData->mpData) ) )
+ return TRUE;
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ if ( ((ImplImageRefData*)rImage.mpImplData->mpData)->IsEqual( *((ImplImageRefData*)mpImplData->mpData) ) )
+ return TRUE;
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+static void ImplCopyImageListData( ImageList* pThis )
+{
+ if ( pThis->mpImplData->mnRefCount > 1 )
+ {
+ pThis->mpImplData->mnRefCount--;
+
+ ImplImageList* pNewData = new ImplImageList;
+ pNewData->mnRefCount = 1;
+ pNewData->mnIRefCount = 0;
+ pNewData->mnCount = pThis->mpImplData->mnCount;
+ pNewData->mnRealCount = pThis->mpImplData->mnRealCount;
+ pNewData->mnArySize = pThis->mpImplData->mnArySize;
+ pNewData->mpAry = new ImageAryData[pNewData->mnArySize];
+ pNewData->maImageSize = pThis->mpImplData->maImageSize;
+ pNewData->mpImageBitmap = new ImplImageBmp;
+ pNewData->mpImageBitmap->Create( pNewData->maImageSize.Width(),
+ pNewData->maImageSize.Height(),
+ pNewData->mnArySize );
+ memset( pNewData->mpAry, 0, pNewData->mnArySize*sizeof(ImageAryData) );
+
+ USHORT i = 0;
+ USHORT n = 0;
+ while ( i < pThis->mpImplData->mnArySize )
+ {
+ // Nur die Images kopieren, die gebraucht werden
+ if ( pThis->mpImplData->mpAry[i].mnId )
+ {
+ pNewData->mpAry[n].mnId = pThis->mpImplData->mpAry[i].mnId;
+ pNewData->mpAry[n].mnRefCount = 1;
+ pNewData->mpImageBitmap->Replace( n,
+ *(pThis->mpImplData->mpImageBitmap),
+ i );
+ n++;
+ }
+
+ i++;
+ }
+
+ pThis->mpImplData = pNewData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplBmpImageCreate( ImageList* pThis,
+ const Bitmap& rBitmap, const Bitmap& rMaskBmp,
+ const Color& rColor, BOOL bColor,
+ USHORT nInit, USHORT* mpIdAry = NULL,
+ USHORT nGrow = 4 )
+{
+ // Falls es sich um eine leere ImageListe handelt, dann Defaul-Werte
+ // setzen und nichts machen
+ if ( !nInit )
+ {
+ pThis->mpImplData = NULL;
+ pThis->mnInitSize = 1;
+ pThis->mnGrowSize = nGrow;
+ return;
+ }
+
+ DBG_ASSERT( !nInit || rBitmap.GetSizePixel().Width(),
+ "ImageList::ImageList(): nInitSize != 0 and BmpSize.Width() == 0" );
+ DBG_ASSERT( (rBitmap.GetSizePixel().Width() % nInit) == 0,
+ "ImageList::ImageList(): BmpSize % nInitSize != 0" );
+ DBG_ASSERT( !rMaskBmp || (rMaskBmp.GetSizePixel() == rBitmap.GetSizePixel()),
+ "ImageList::ImageList(): BmpSize != MaskBmpSize" );
+#ifdef DBG_UTIL
+ if ( mpIdAry )
+ {
+ for ( USHORT n1 = 0; n1 < nInit; n1++ )
+ {
+ USHORT nId = mpIdAry[n1];
+ if ( !nId )
+ {
+ DBG_ERROR( "ImageList::ImageList(): Id == 0" );
+ }
+ for ( USHORT n2 = 0; n2 < n1; n2++ )
+ {
+ if ( nId == mpIdAry[n2] )
+ {
+ DBG_ERROR1( "ImageList::ImageList(): Double Id (%u)", nId );
+ }
+ }
+ }
+ }
+#endif
+
+ Size aBmpSize = rBitmap.GetSizePixel();
+ pThis->mnInitSize = nInit;
+ pThis->mnGrowSize = nGrow;
+ pThis->mpImplData = new ImplImageList;
+ pThis->mpImplData->mnRefCount = 1;
+ pThis->mpImplData->mnIRefCount = 0;
+ pThis->mpImplData->mnCount = nInit;
+ pThis->mpImplData->mnRealCount = nInit;
+ pThis->mpImplData->mnArySize = nInit;
+ pThis->mpImplData->mpAry = new ImageAryData[nInit];
+ pThis->mpImplData->maImageSize = Size( aBmpSize.Width() / nInit, aBmpSize.Height() );
+
+ for ( USHORT i = 0; i < nInit; i++ )
+ {
+ if ( mpIdAry )
+ pThis->mpImplData->mpAry[i].mnId = mpIdAry[i];
+ else
+ pThis->mpImplData->mpAry[i].mnId = i+1;
+ pThis->mpImplData->mpAry[i].mnRefCount = 1;
+ }
+
+ pThis->mpImplData->mpImageBitmap = new ImplImageBmp;
+ pThis->mpImplData->mpImageBitmap->Create( rBitmap, rMaskBmp,
+ rColor, bColor,
+ pThis->mpImplData->maImageSize.Width(),
+ pThis->mpImplData->maImageSize.Height(),
+ nInit );
+}
+
+// =======================================================================
+
+ImageList::ImageList( USHORT nInit, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ mpImplData = NULL;
+ mnInitSize = nInit;
+ mnGrowSize = nGrow;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const ResId& rResId )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ rResId.SetRT( RSC_IMAGELIST );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // Header ueberspringen
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ USHORT nObjMask = pResMgr->ReadShort();
+
+ Bitmap aImageBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ BOOL bCol = FALSE;
+ BOOL bIsIdList = FALSE;
+
+ if ( nObjMask & RSC_IMAGELIST_IMAGEBITMAP )
+ {
+ aImageBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if ( nObjMask & RSC_IMAGELIST_MASKBITMAP )
+ {
+ aMaskBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if ( nObjMask & RSC_IMAGELIST_MASKCOLOR )
+ {
+ aMaskColor = Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ bCol = TRUE;
+ }
+ if ( nObjMask & RSC_IMAGELIST_IDLIST )
+ {
+ bIsIdList = TRUE;
+ USHORT nCount = pResMgr->ReadShort();
+ USHORT* pAry = new USHORT[ nCount ];
+ for( int i = 0; i < nCount; i++ )
+ pAry[ i ] = pResMgr->ReadShort();
+ ImplBmpImageCreate( this, aImageBitmap, aMaskBitmap, aMaskColor,
+ bCol, nCount, pAry, 4 );
+ delete pAry;
+ }
+ if ( nObjMask & RSC_IMAGELIST_IDCOUNT )
+ {
+ USHORT nCount = pResMgr->ReadShort();
+ if ( !bIsIdList )
+ {
+ ImplBmpImageCreate( this, aImageBitmap, aMaskBitmap, aMaskColor,
+ bCol, nCount, NULL, 4 );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const ImageList& rImageList )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ mpImplData = rImageList.mpImplData;
+ if ( mpImplData )
+ mpImplData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, Bitmap(), Color(), FALSE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap, const Bitmap& rMaskBmp,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, rMaskBmp, Color(), FALSE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap, const Color& rColor,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, Bitmap(), rColor, TRUE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::~ImageList()
+{
+ DBG_DTOR( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ mpImplData->mnRefCount--;
+ if ( !mpImplData->mnRefCount && !mpImplData->mnIRefCount )
+ delete mpImplData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::AddImage( USHORT nId, const Image& rImage )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( nId, "ImageList::AddImage(): ImageId == 0" );
+ DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::AddImage() - ImageId already exists" );
+ DBG_ASSERT( rImage.mpImplData, "ImageList::AddImage(): Wrong Size" );
+ DBG_ASSERT( !mpImplData || (rImage.GetSizePixel() == mpImplData->maImageSize),
+ "ImageList::AddImage(): Wrong Size" );
+
+ ImageType eImageType = rImage.mpImplData->meType;
+ Size aImageSize = rImage.GetSizePixel();
+ USHORT nIndex;
+
+ if ( !mpImplData )
+ {
+ mpImplData = new ImplImageList;
+ mpImplData->mnRefCount = 1;
+ mpImplData->mnIRefCount = 0;
+ mpImplData->mnCount = 0;
+ mpImplData->mnRealCount = 0;
+ mpImplData->mnArySize = mnInitSize;
+ mpImplData->mpAry = new ImageAryData[mnInitSize];
+ mpImplData->maImageSize = aImageSize;
+ mpImplData->mpImageBitmap = new ImplImageBmp;
+ mpImplData->mpImageBitmap->Create( aImageSize.Width(), aImageSize.Height(),
+ mnInitSize );
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ }
+ else
+ ImplCopyImageListData( this );
+
+ // Gegebenenfalls unser Array erweitern und freien Index ermitteln
+ if ( mpImplData->mnRealCount == mpImplData->mnArySize )
+ {
+ ImageAryData* pOldAry = mpImplData->mpAry;
+ USHORT nOldSize = mpImplData->mnArySize;
+
+ mpImplData->mnArySize += mnGrowSize;
+ mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize];
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ memcpy( mpImplData->mpAry, pOldAry, nOldSize*sizeof(ImageAryData) );
+ mpImplData->mpImageBitmap->Expand( mnGrowSize );
+ delete pOldAry;
+
+ nIndex = mpImplData->mnRealCount;
+ }
+ else
+ {
+ nIndex = 0;
+ while ( mpImplData->mpAry[nIndex].mnRefCount )
+ nIndex++;
+ }
+
+ // Image in Bitmap einfuegen
+ switch ( eImageType )
+ {
+ case IMAGETYPE_BITMAP:
+ mpImplData->mpImageBitmap->Replace( nIndex, *((Bitmap*)rImage.mpImplData->mpData) );
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+ if ( pData->mpImageBitmap )
+ mpImplData->mpImageBitmap->Replace( nIndex, *(pData->mpImageBitmap), 0 );
+ else
+ {
+ if ( pData->mbColor )
+ mpImplData->mpImageBitmap->Replace( nIndex, pData->maBmp, pData->maColor );
+ else
+ mpImplData->mpImageBitmap->Replace( nIndex, pData->maBmp, pData->maMaskBmp );
+ }
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ mpImplData->mpImageBitmap->Replace( nIndex, *(pData->mpImplData->mpImageBitmap),
+ pData->mnIndex );
+ }
+ break;
+ }
+
+ // Array-Daten updaten
+ mpImplData->mnCount++;
+ mpImplData->mnRealCount++;
+ mpImplData->mpAry[nIndex].mnId = nId;
+ mpImplData->mpAry[nIndex].mnRefCount = 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::CopyImage( USHORT nId, USHORT nCopyId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( nId, "ImageList::CopyImage(): ImageId == 0" );
+ DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::CopyImage(): ImageId already exists" );
+ DBG_ASSERT( GetImagePos( nCopyId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::CopyImage(): Unknown nCopyId" );
+
+ USHORT nIndex;
+ USHORT nCopyIndex = 0;
+
+ // Index von CopyId holen
+ while ( nCopyIndex < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nCopyIndex].mnId == nCopyId )
+ break;
+
+ nCopyIndex++;
+ }
+ if ( nCopyIndex >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Gegebenenfalls unser Array erweitern
+ if ( mpImplData->mnRealCount == mpImplData->mnArySize )
+ {
+ ImageAryData* pOldAry = mpImplData->mpAry;
+ USHORT nOldSize = mpImplData->mnArySize;
+
+ mpImplData->mnArySize += mnGrowSize;
+ mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize];
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ memcpy( mpImplData->mpAry, pOldAry, nOldSize*sizeof(ImageAryData) );
+ mpImplData->mpImageBitmap->Expand( mnGrowSize );
+ delete pOldAry;
+
+ nIndex = mpImplData->mnRealCount;
+ }
+ else
+ {
+ nIndex = 0;
+ while ( mpImplData->mpAry[nIndex].mnRefCount )
+ nIndex++;
+ }
+
+ // Kopieren
+ mpImplData->mpImageBitmap->Replace( nIndex, *(mpImplData->mpImageBitmap), nCopyIndex );
+
+ // Array-Daten updaten
+ mpImplData->mnCount++;
+ mpImplData->mnRealCount++;
+ mpImplData->mpAry[nIndex].mnId = nId;
+ mpImplData->mpAry[nIndex].mnRefCount = 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::ReplaceImage( USHORT nId, const Image& rImage )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nId" );
+
+ RemoveImage( nId );
+ AddImage( nId, rImage );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::ReplaceImage( USHORT nId, USHORT nReplaceId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nId" );
+ DBG_ASSERT( GetImagePos( nReplaceId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nReplaceId" );
+
+ USHORT nPos1 = 0;
+ USHORT nPos2 = 0;
+
+ // Index von Id holen
+ while ( nPos1 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos1].mnId == nId )
+ break;
+
+ nPos1++;
+ }
+ if ( nPos1 >= mpImplData->mnArySize )
+ return;
+
+ // Index von ReplaceId holen
+ while ( nPos2 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos2].mnId == nReplaceId )
+ break;
+
+ nPos2++;
+ }
+ if ( nPos2 >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Ersetzen
+ mpImplData->mpImageBitmap->Replace( nPos1, nPos2 );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::MergeImage( USHORT nId, USHORT nMergeId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::MergeImage(): Unknown nId" );
+ DBG_ASSERT( GetImagePos( nMergeId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::MergeImage(): Unknown nMergeId" );
+
+ USHORT nPos1 = 0;
+ USHORT nPos2 = 0;
+
+ // Index von Id holen
+ while ( nPos1 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos1].mnId == nId )
+ break;
+
+ nPos1++;
+ }
+ if ( nPos1 >= mpImplData->mnArySize )
+ return;
+
+ // Index von MergeId holen
+ while ( nPos2 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos2].mnId == nMergeId )
+ break;
+
+ nPos2++;
+ }
+ if ( nPos2 >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Ersetzen
+ mpImplData->mpImageBitmap->Merge( nPos1, nPos2 );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::RemoveImage( USHORT nId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ ImplCopyImageListData( this );
+
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ break;
+
+ i++;
+ }
+
+ if ( i < mpImplData->mnArySize )
+ {
+ mpImplData->mpAry[i].mnRefCount--;
+ mpImplData->mpAry[i].mnId = 0;
+ if ( !mpImplData->mpAry[i].mnRefCount )
+ mpImplData->mnRealCount--;
+
+ mpImplData->mnCount--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ImageList::GetImage( USHORT nId ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Image aImage;
+
+ if ( mpImplData )
+ {
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ break;
+
+ i++;
+ }
+
+ if ( i < mpImplData->mnArySize )
+ {
+ ImplImageRefData* mpData = new ImplImageRefData;
+
+ mpImplData->mnIRefCount++;
+ mpImplData->mpAry[i].mnRefCount++;
+ mpData->mpImplData = mpImplData;
+ mpData->mnIndex = i;
+
+ aImage.mpImplData = new ImplImage;
+ aImage.mpImplData->mnRefCount = 1;
+ aImage.mpImplData->meType = IMAGETYPE_IMAGEREF;
+ aImage.mpImplData->mpData = mpData;
+ }
+ }
+
+ return aImage;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::Clear()
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+
+ mpImplData = 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImageCount() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mnCount;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImagePos( USHORT nId ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData && nId )
+ {
+ USHORT nPos = 0;
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ return nPos;
+
+ if ( mpImplData->mpAry[i].mnId )
+ nPos++;
+ i++;
+ }
+ }
+
+ return IMAGELIST_IMAGE_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImageId( USHORT nPos ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ USHORT nRealPos = 0;
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( (nPos == nRealPos) && (mpImplData->mpAry[i].mnId) )
+ return mpImplData->mpAry[i].mnId;
+
+ if ( mpImplData->mpAry[i].mnId )
+ nRealPos++;
+ i++;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Size ImageList::GetImageSize() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->maImageSize;
+ else
+ return Size();
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImageList::GetBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Bitmap aBmp;
+
+ if ( mpImplData )
+ {
+ // Positionen ermitteln, die in der Bitmap enthalten sein sollen
+ USHORT* mpPosAry = new USHORT[mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < mpImplData->mnArySize; i++ )
+ {
+ if ( mpImplData->mpAry[i].mnId )
+ {
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmap besorgen
+ aBmp = mpImplData->mpImageBitmap->GetBitmap( nPosCount, mpPosAry );
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+ }
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImageList::GetMaskBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Bitmap aBmp;
+
+ if ( HasMaskBitmap() )
+ {
+ // Positionen ermitteln, die in der Bitmap enthalten sein sollen
+ USHORT* mpPosAry = new USHORT[mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < mpImplData->mnArySize; i++ )
+ {
+ if ( mpImplData->mpAry[i].mnId )
+ {
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmap besorgen
+ aBmp = mpImplData->mpImageBitmap->GetMaskBitmap( nPosCount, mpPosAry );
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+ }
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::HasMaskBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mpImageBitmap->HasMaskBitmap();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Color ImageList::GetMaskColor() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Color aColor;
+
+ if ( HasMaskColor() )
+ aColor = mpImplData->mpImageBitmap->GetMaskColor();
+
+ return aColor;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::HasMaskColor() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mpImageBitmap->HasMaskColor();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList& ImageList::operator=( const ImageList& rImageList )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rImageList.mpImplData )
+ rImageList.mpImplData->mnRefCount++;
+
+ // Abkoppeln
+ if ( mpImplData )
+ {
+ mpImplData->mnRefCount--;
+ if ( !mpImplData->mnRefCount && !mpImplData->mnIRefCount )
+ delete mpImplData;
+ }
+
+ // Neue Daten zuweisen
+ mpImplData = rImageList.mpImplData;
+ mnInitSize = rImageList.mnInitSize;
+ mnGrowSize = rImageList.mnGrowSize;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::operator==( const ImageList& rImageList ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ if ( rImageList.mpImplData == mpImplData )
+ return TRUE;
+ if ( !rImageList.mpImplData || !mpImplData )
+ return FALSE;
+
+ if ( (rImageList.mpImplData->mnCount == mpImplData->mnCount) &&
+ (rImageList.mpImplData->maImageSize == mpImplData->maImageSize) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, ImageList& rImageList )
+{
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ // Falls es eine bestehende ImageListe ist, dann erst abkoppeln
+ if ( rImageList.mpImplData )
+ {
+ rImageList.mpImplData->mnRefCount--;
+ if ( !rImageList.mpImplData->mnRefCount && !rImageList.mpImplData->mnIRefCount )
+ delete rImageList.mpImplData;
+ }
+ rImageList.mpImplData = NULL;
+
+ // Daten lesen
+ USHORT nVersion;
+ Size aImageSize;
+ BOOL bImageList;
+ rIStream >> nVersion;
+ rIStream >> rImageList.mnInitSize;
+ rIStream >> rImageList.mnGrowSize;
+ rIStream >> bImageList;
+
+ // Wenn es eine leere ImageListe ist, dann brauchen wir nicht weiter lesen
+ if ( !bImageList )
+ return rIStream;
+
+ // Image-Groesse lesen
+ rIStream >> aImageSize.Width();
+ rIStream >> aImageSize.Height();
+
+ // Image-Daten anlegen und initialisieren
+ rImageList.mpImplData = new ImplImageList;
+ rImageList.mpImplData->mnRefCount = 1;
+ rImageList.mpImplData->mnIRefCount = 0;
+ rImageList.mpImplData->mnCount = rImageList.mnInitSize;
+ rImageList.mpImplData->mnRealCount = rImageList.mnInitSize;
+ rImageList.mpImplData->mnArySize = rImageList.mnInitSize;
+ rImageList.mpImplData->mpAry = new ImageAryData[rImageList.mnInitSize];
+ rImageList.mpImplData->maImageSize = aImageSize;
+
+ // Array mit ID's lesen und initialisieren
+ for ( USHORT i = 0; i < rImageList.mnInitSize; i++ )
+ {
+ rIStream >> rImageList.mpImplData->mpAry[i].mnId;
+ rImageList.mpImplData->mpAry[i].mnRefCount = 1;
+ }
+
+ // Bitmaps lesen
+ Bitmap aBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ BYTE bMaskBitmap;
+ BYTE bMaskColor;
+ rIStream >> aBitmap;
+ rIStream >> bMaskBitmap;
+ if ( bMaskBitmap )
+ rIStream >> aMaskBitmap;
+ rIStream >> bMaskColor;
+ if ( bMaskColor )
+ rIStream >> aMaskColor;
+
+ // Systemdaten anlegen
+ rImageList.mpImplData->mpImageBitmap = new ImplImageBmp;
+ rImageList.mpImplData->mpImageBitmap->Create( aBitmap, aMaskBitmap,
+ aMaskColor, bMaskColor,
+ aImageSize.Width(),
+ aImageSize.Height(),
+ rImageList.mnInitSize );
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const ImageList& rImageList )
+{
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ BOOL bImageList = (rImageList.mpImplData) ? TRUE : FALSE;
+
+ USHORT nVersion = IMAGE_FILE_VERSION;
+ rOStream << nVersion;
+
+ // Wenn es eine leere ImageListe ist, dann nur InitSize und
+ // GrowSize schreiben
+ if ( !bImageList || !rImageList.mpImplData->mnCount )
+ {
+ BOOL bSaveImageList = FALSE;
+ rOStream << rImageList.mnInitSize;
+ rOStream << rImageList.mnGrowSize;
+ rOStream << bSaveImageList;
+ return rOStream;
+ }
+
+ // Normale Daten schreiben
+ rOStream << rImageList.mpImplData->mnCount;
+ rOStream << rImageList.mnGrowSize;
+ rOStream << bImageList;
+ rOStream << rImageList.mpImplData->maImageSize.Width();
+ rOStream << rImageList.mpImplData->maImageSize.Height();
+
+ // Array schreiben und feststellen, welche Eintraege gespeichert werden
+ // muessen
+ USHORT* mpPosAry = new USHORT[rImageList.mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < rImageList.mpImplData->mnArySize; i++ )
+ {
+ if ( rImageList.mpImplData->mpAry[i].mnId )
+ {
+ rOStream << rImageList.mpImplData->mpAry[i].mnId;
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmaps rausschreiben
+ Bitmap aBmp;
+ BYTE bMaskBitmap = (BYTE)rImageList.mpImplData->mpImageBitmap->HasMaskBitmap();
+ BYTE bMaskColor = (BYTE)rImageList.mpImplData->mpImageBitmap->HasMaskColor();
+ aBmp = rImageList.mpImplData->mpImageBitmap->GetBitmap( nPosCount, mpPosAry );
+ rOStream << aBmp;
+ rOStream << bMaskBitmap;
+ if ( bMaskBitmap )
+ {
+ aBmp = rImageList.mpImplData->mpImageBitmap->GetMaskBitmap( nPosCount, mpPosAry );
+ rOStream << aBmp;
+ }
+ rOStream << bMaskColor;
+ if ( bMaskColor )
+ {
+ Color aColor = rImageList.mpImplData->mpImageBitmap->GetMaskColor();
+ rOStream << aColor;
+ }
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+
+ return rOStream;
+}
+
+// =======================================================================
+
+void OutputDevice::DrawImage( const Point& rPos, const Image& rImage,
+ USHORT nStyle )
+{
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER,
+ "DrawImage(): Images can't be drawn on any mprinter" );
+
+ if( !rImage.mpImplData )
+ return;
+
+ switch( rImage.mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ {
+ DrawBitmap( rPos, *((Bitmap*)rImage.mpImplData->mpData) );
+ }
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+
+ if ( !pData->mpImageBitmap )
+ {
+ Size aSize = pData->maBmp.GetSizePixel();
+ pData->mpImageBitmap = new ImplImageBmp;
+ pData->mpImageBitmap->Create( pData->maBmp, pData->maMaskBmp,
+ pData->maColor, pData->mbColor,
+ aSize.Width(), aSize.Height(),
+ 1 );
+ }
+
+ pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ pData->mpImplData->mpImageBitmap->Draw( pData->mnIndex, this, rPos, nStyle );
+ }
+ break;
+ }
+}
+
+// =======================================================================
+
+void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
+ const Image& rImage, USHORT nStyle )
+{
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER,
+ "DrawImage(): Images can't be drawn on any mprinter" );
+
+ if( !rImage.mpImplData )
+ return;
+
+ switch( rImage.mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ {
+ DrawBitmap( rPos, rSize, *((Bitmap*)rImage.mpImplData->mpData) );
+ }
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+
+ if ( !pData->mpImageBitmap )
+ {
+ Size aSize = pData->maBmp.GetSizePixel();
+ pData->mpImageBitmap = new ImplImageBmp;
+ pData->mpImageBitmap->Create( pData->maBmp, pData->maMaskBmp,
+ pData->maColor, pData->mbColor,
+ aSize.Width(), aSize.Height(),
+ 1 );
+ }
+
+ pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ pData->mpImplData->mpImageBitmap->Draw( pData->mnIndex, this, rPos, nStyle, &rSize );
+ }
+ break;
+ }
+}
diff --git a/vcl/source/gdi/imgcons.cxx b/vcl/source/gdi/imgcons.cxx
new file mode 100644
index 000000000000..d20f9c26f1c9
--- /dev/null
+++ b/vcl/source/gdi/imgcons.cxx
@@ -0,0 +1,593 @@
+/*************************************************************************
+ *
+ * $RCSfile: imgcons.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <bmpacc.hxx>
+#include <bitmapex.hxx>
+#include <image.hxx>
+#include <imgcons.hxx>
+
+// -------------------
+// - ImplColorMapper -
+// -------------------
+
+class ImplColorMapper
+{
+ Color maCol;
+ ULONG mnR;
+ ULONG mnG;
+ ULONG mnB;
+ ULONG mnT;
+ ULONG mnRShift;
+ ULONG mnGShift;
+ ULONG mnBShift;
+ ULONG mnTShift;
+
+ ULONG ImplCalcMaskShift( ULONG nVal );
+
+public:
+
+ ImplColorMapper( ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nTMask );
+ ~ImplColorMapper();
+
+ const Color& ImplGetColor( ULONG nColor )
+ {
+ maCol.SetRed( (UINT8) ( ( nColor & mnR ) >> mnRShift ) );
+ maCol.SetGreen( (UINT8) ( ( nColor & mnG ) >> mnGShift ) );
+ maCol.SetBlue( (UINT8) ( ( nColor & mnB ) >> mnBShift ) );
+ maCol.SetTransparency( (UINT8) ( ( nColor & mnT ) >> mnTShift ) );
+ return maCol;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+ImplColorMapper::ImplColorMapper( ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nTMask ) :
+ mnR( nRMask ),
+ mnG( nGMask ),
+ mnB( nBMask ),
+ mnT( nTMask )
+{
+ mnRShift = ImplCalcMaskShift( mnR );
+ mnGShift = ImplCalcMaskShift( mnG );
+ mnBShift = ImplCalcMaskShift( mnB );
+ mnTShift = ImplCalcMaskShift( mnT );
+}
+
+// -----------------------------------------------------------------------------
+
+ImplColorMapper::~ImplColorMapper()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ULONG ImplColorMapper::ImplCalcMaskShift( ULONG nVal )
+{
+ DBG_ASSERT( nVal > 0, "Mask has no value!" );
+
+ ULONG nRet = 0UL;
+
+ for( ULONG i = 0UL; i < 32; i++ )
+ {
+ if( nVal & ( 1UL << i ) )
+ {
+ nRet = i;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------
+// - ImageConsumer -
+// -----------------
+
+ImageConsumer::ImageConsumer() :
+ mnStatus( 0UL ),
+ mpPal ( NULL ),
+ mpMapper( NULL ),
+ mbTrans ( FALSE )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImageConsumer::~ImageConsumer()
+{
+ delete[] mpPal;
+ delete mpMapper;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::Init( ULONG nWidth, ULONG nHeight )
+{
+ maSize = Size( nWidth, nHeight );
+ maBitmap = maMask = Bitmap();
+ mnStatus = 0UL;
+ mbTrans = FALSE;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetColorModel( USHORT nBitCount,
+ ULONG nPalEntries, const ULONG* pRGBAPal,
+ ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nAMask )
+{
+ DBG_ASSERT( maSize.Width() && maSize.Height(), "Missing call to ImageConsumer::Init(...)!" );
+
+ BitmapPalette aPal( Min( (USHORT) nPalEntries, (USHORT) 256 ) );
+
+ if( nPalEntries )
+ {
+ BitmapColor aCol;
+ const ULONG* pTmp = pRGBAPal;
+
+ delete mpMapper;
+ mpMapper = NULL;
+
+ delete[] mpPal;
+ mpPal = new Color[ nPalEntries ];
+
+ for( ULONG i = 0; i < nPalEntries; i++, pTmp++ )
+ {
+ Color& rCol = mpPal[ i ];
+ BYTE cVal;
+
+ cVal = (BYTE) ( ( *pTmp & 0xff000000UL ) >> 24UL );
+ rCol.SetRed( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetRed( cVal );
+
+ cVal = (BYTE) ( ( *pTmp & 0x00ff0000UL ) >> 16UL );
+ rCol.SetGreen( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetGreen( cVal );
+
+ cVal = (BYTE) ( ( *pTmp & 0x0000ff00UL ) >> 8UL );
+ rCol.SetBlue( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetBlue( cVal );
+
+ rCol.SetTransparency( (BYTE) ( ( *pTmp & 0x000000ffUL ) ) );
+ }
+
+ if( nBitCount <= 1 )
+ nBitCount = 1;
+ else if( nBitCount <= 4 )
+ nBitCount = 4;
+ else if( nBitCount <= 8 )
+ nBitCount = 8;
+ else
+ nBitCount = 24;
+ }
+ else
+ {
+ delete mpMapper;
+ mpMapper = new ImplColorMapper( nRMask, nGMask, nBMask, nAMask );
+
+ delete[] mpPal;
+ mpPal = NULL;
+
+ nBitCount = 24;
+ }
+
+ if( !maBitmap )
+ {
+
+ maBitmap = Bitmap( maSize, nBitCount, &aPal );
+ maMask = Bitmap( maSize, 1 );
+ maMask.Erase( COL_BLACK );
+ mbTrans = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetPixelsByBytes( ULONG nConsX, ULONG nConsY,
+ ULONG nConsWidth, ULONG nConsHeight,
+ const BYTE* pData, ULONG nOffset, ULONG nScanSize )
+{
+ DBG_ASSERT( !!maBitmap && !!maMask, "Missing call to ImageConsumer::SetColorModel(...)!" );
+
+ BitmapWriteAccess* pBmpAcc = maBitmap.AcquireWriteAccess();
+ BitmapWriteAccess* pMskAcc = maMask.AcquireWriteAccess();
+
+ if( pBmpAcc && pMskAcc )
+ {
+ const long nWidth = pBmpAcc->Width();
+ const long nHeight = pBmpAcc->Height();
+
+ maChangedRect = Rectangle( Point(), Size( nWidth, nHeight ) );
+ maChangedRect.Intersection( Rectangle( Point( nConsX, nConsY ), Size( nConsWidth, nConsHeight ) ) );
+
+ if( !maChangedRect.IsEmpty() )
+ {
+ const long nStartX = maChangedRect.Left();
+ const long nEndX = maChangedRect.Right();
+ const long nStartY = maChangedRect.Top();
+ const long nEndY = maChangedRect.Bottom();
+
+ if( mpMapper && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const Color& rCol = mpMapper->ImplGetColor( *pTmp++ );
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() <= 8 ) )
+ {
+ BitmapColor aIndex( (BYTE) 0 );
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const BYTE cIndex = *pTmp++;
+ const Color& rCol = mpPal[ cIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aIndex.SetIndex( cIndex );
+ pBmpAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const BYTE cIndex = *pTmp++;
+ const Color& rCol = mpPal[ cIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else
+ {
+ DBG_ERROR( "Producer format error!" );
+ maChangedRect.SetEmpty();
+ }
+ }
+ }
+ else
+ maChangedRect.SetEmpty();
+
+ maBitmap.ReleaseAccess( pBmpAcc );
+ maMask.ReleaseAccess( pMskAcc );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetPixelsByLongs( ULONG nConsX, ULONG nConsY,
+ ULONG nConsWidth, ULONG nConsHeight,
+ const ULONG* pData, ULONG nOffset, ULONG nScanSize )
+{
+ DBG_ASSERT( !!maBitmap && !!maMask, "Missing call to ImageConsumer::SetColorModel(...)!" );
+
+ BitmapWriteAccess* pBmpAcc = maBitmap.AcquireWriteAccess();
+ BitmapWriteAccess* pMskAcc = maMask.AcquireWriteAccess();
+
+ if( pBmpAcc && pMskAcc )
+ {
+ const long nWidth = pBmpAcc->Width();
+ const long nHeight = pBmpAcc->Height();
+
+ maChangedRect = Rectangle( Point(), Size( nWidth, nHeight ) );
+ maChangedRect.Intersection( Rectangle( Point( nConsX, nConsY ), Size( nConsWidth, nConsHeight ) ) );
+
+ if( !maChangedRect.IsEmpty() )
+ {
+ const long nStartX = maChangedRect.Left();
+ const long nEndX = maChangedRect.Right();
+ const long nStartY = maChangedRect.Top();
+ const long nEndY = maChangedRect.Bottom();
+
+ if( mpMapper && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const Color& rCol = mpMapper->ImplGetColor( *pTmp++ );
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() <= 8 ) )
+ {
+ BitmapColor aIndex( (BYTE) 0 );
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const ULONG nIndex = *pTmp++;
+ const Color& rCol = mpPal[ nIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aIndex.SetIndex( (BYTE) nIndex );
+ pBmpAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const ULONG nIndex = *pTmp++;
+ const Color& rCol = mpPal[ nIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else
+ {
+ DBG_ERROR( "Producer format error!" );
+ maChangedRect.SetEmpty();
+ }
+ }
+ }
+ else
+ maChangedRect.SetEmpty();
+
+ maBitmap.ReleaseAccess( pBmpAcc );
+ maMask.ReleaseAccess( pMskAcc );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::Completed( ULONG nStatus /*, ImageProducer& rProducer */ )
+{
+ delete mpMapper;
+ mpMapper = NULL;
+ delete[] mpPal;
+ mpPal = NULL;
+ maSize = Size();
+ mnStatus = nStatus;
+
+ switch( nStatus )
+ {
+ case( SINGLEFRAMEDONE ):
+ case( STATICIMAGEDONE ):
+ {
+ if( !mbTrans )
+ maMask = Bitmap();
+ }
+ break;
+
+ case( IMAGEERROR ):
+ case( IMAGEABORTED ):
+ maBitmap = maMask = Bitmap();
+ break;
+
+ default:
+ break;
+ }
+
+// rProducer.RemoveConsumer( *this );
+
+ if( maDoneLink.IsSet() )
+ maDoneLink.Call( this );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::DataChanged()
+{
+ if( maChgLink.IsSet() )
+ maChgLink.Call( this );
+}
+
+// -----------------------------------------------------------------------------
+
+ULONG ImageConsumer::GetStatus() const
+{
+ return mnStatus;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImageConsumer::GetData( BitmapEx& rBmpEx ) const
+{
+ const BOOL bRet = ( SINGLEFRAMEDONE == mnStatus || STATICIMAGEDONE == mnStatus );
+
+ if( bRet )
+ {
+ if( !!maMask )
+ rBmpEx = BitmapEx( maBitmap, maMask );
+ else
+ rBmpEx = BitmapEx( maBitmap );
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImageConsumer::GetData( Image& rImage ) const
+{
+ const BOOL bRet = ( SINGLEFRAMEDONE == mnStatus || STATICIMAGEDONE == mnStatus );
+
+ if( bRet )
+ {
+ if( !!maMask )
+ rImage = Image( maBitmap, maMask );
+ else
+ rImage = Image( maBitmap );
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/impanmvw.cxx b/vcl/source/gdi/impanmvw.cxx
new file mode 100644
index 000000000000..fc3a943c0471
--- /dev/null
+++ b/vcl/source/gdi/impanmvw.cxx
@@ -0,0 +1,392 @@
+/*************************************************************************
+ *
+ * $RCSfile: impanmvw.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPANMVW_CXX
+
+#define private public
+
+#include "impanmvw.hxx"
+#include "virdev.hxx"
+#include "window.hxx"
+#include "salbtype.hxx"
+
+// ----------------
+// - ImplAnimView -
+// ----------------
+
+ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut,
+ const Point& rPt, const Size& rSz,
+ ULONG nExtraData,
+ OutputDevice* pFirstFrameOutDev ) :
+ mpParent ( pParent ),
+ mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
+ maPt ( rPt ),
+ maSz ( rSz ),
+ maClip ( mpOut->GetClipRegion() ),
+ maSzPix ( mpOut->LogicToPixel( maSz ) ),
+ mnExtraData ( nExtraData ),
+ mpBackground ( new VirtualDevice ),
+ mpRestore ( new VirtualDevice ),
+ meLastDisposal ( DISPOSE_BACK ),
+ mbPause ( FALSE ),
+ mbMarked ( FALSE ),
+ mbHMirr ( maSz.Width() < 0L ),
+ mbVMirr ( maSz.Height() < 0L )
+{
+ mpParent->ImplIncAnimCount();
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ {
+ maDispPt.X() = maPt.X() + maSz.Width() + 1L;
+ maDispSz.Width() = -maSz.Width();
+ maSzPix.Width() = -maSzPix.Width();
+ }
+ else
+ {
+ maDispPt.X() = maPt.X();
+ maDispSz.Width() = maSz.Width();
+ }
+
+ // mirrored vertically?
+ if( mbVMirr )
+ {
+ maDispPt.Y() = maPt.Y() + maSz.Height() + 1L;
+ maDispSz.Height() = -maSz.Height();
+ maSzPix.Height() = -maSzPix.Height();
+ }
+ else
+ {
+ maDispPt.Y() = maPt.Y();
+ maDispSz.Height() = maSz.Height();
+ }
+
+ // save background
+ mpBackground->SetOutputSizePixel( maSzPix );
+
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ MapMode aTempMap( mpOut->GetMapMode() );
+ aTempMap.SetOrigin( Point() );
+ mpBackground->SetMapMode( aTempMap );
+ ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
+ mpBackground->SetMapMode( MapMode() );
+ }
+ else
+ mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+
+ // initial drawing to actual position
+ ImplDrawToPos( mpParent->ImplGetCurPos() );
+
+ // if first frame OutputDevice is set, update variables now for real OutputDevice
+ if( pFirstFrameOutDev )
+ maClip = ( mpOut = pOut )->GetClipRegion();
+}
+
+// ------------------------------------------------------------------------
+
+ImplAnimView::~ImplAnimView()
+{
+ delete mpBackground;
+ delete mpRestore;
+
+ mpParent->ImplDecAnimCount();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImplAnimView::ImplMatches( OutputDevice* pOut, long nExtraData ) const
+{
+ BOOL bRet = FALSE;
+
+ if( nExtraData )
+ {
+ if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
+ bRet = TRUE;
+ }
+ else if( !pOut || ( pOut == mpOut ) )
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix )
+{
+ const Size& rAnmSize = mpParent->GetDisplaySizePixel();
+ Point aPt2( rAnm.aPosPix.X() + rAnm.aSizePix.Width() - 1L,
+ rAnm.aPosPix.Y() + rAnm.aSizePix.Height() - 1L );
+ double fFactX, fFactY;
+
+ // calculate x scaling
+ if( rAnmSize.Width() > 1L )
+ fFactX = (double) ( maSzPix.Width() - 1L ) / ( rAnmSize.Width() - 1L );
+ else
+ fFactX = 1.0;
+
+ // calculate y scaling
+ if( rAnmSize.Height() > 1L )
+ fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L );
+ else
+ fFactY = 1.0;
+
+ rPosPix.X() = FRound( rAnm.aPosPix.X() * fFactX );
+ rPosPix.Y() = FRound( rAnm.aPosPix.Y() * fFactY );
+
+ aPt2.X() = FRound( aPt2.X() * fFactX );
+ aPt2.Y() = FRound( aPt2.Y() * fFactY );
+
+ rSizePix.Width() = aPt2.X() - rPosPix.X() + 1L;
+ rSizePix.Height() = aPt2.Y() - rPosPix.Y() + 1L;
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ rPosPix.X() = maSzPix.Width() - 1L - aPt2.X();
+
+ // mirrored vertically?
+ if( mbVMirr )
+ rPosPix.Y() = maSzPix.Height() - 1L - aPt2.Y();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDrawToPos( ULONG nPos )
+{
+ VirtualDevice aVDev;
+ Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
+
+ aVDev.SetOutputSizePixel( maSzPix, FALSE );
+ nPos = Min( nPos, (ULONG) mpParent->Count() - 1UL );
+
+ for( ULONG i = 0UL; i <= nPos; i++ )
+ ImplDraw( i, &aVDev );
+
+ if( pOldClip )
+ mpOut->SetClipRegion( maClip );
+
+ mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, aVDev );
+
+ if( pOldClip )
+ {
+ mpOut->SetClipRegion( *pOldClip );
+ delete pOldClip;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDraw( ULONG nPos )
+{
+ ImplDraw( nPos, NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDraw( ULONG nPos, VirtualDevice* pVDev )
+{
+ Rectangle aOutRect( mpOut->PixelToLogic( Point() ), mpOut->GetOutputSize() );
+
+ // check, if output lies out of display
+ if( aOutRect.Intersection( Rectangle( maDispPt, maDispSz ) ).IsEmpty() )
+ ImplSetMarked( TRUE );
+ else if( !mbPause )
+ {
+ VirtualDevice* pDev;
+ Point aPosPix;
+ Point aBmpPosPix;
+ Size aSizePix;
+ Size aBmpSizePix;
+ const ULONG nLastPos = mpParent->Count() - 1;
+ const AnimationBitmap& rAnm = mpParent->Get( (USHORT) ( mnActPos = Min( nPos, nLastPos ) ) );
+
+ ImplGetPosSize( rAnm, aPosPix, aSizePix );
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ {
+ aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L;
+ aBmpSizePix.Width() = -aSizePix.Width();
+ }
+ else
+ {
+ aBmpPosPix.X() = aPosPix.X();
+ aBmpSizePix.Width() = aSizePix.Width();
+ }
+
+ // mirrored vertically?
+ if( mbVMirr )
+ {
+ aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L;
+ aBmpSizePix.Height() = -aSizePix.Height();
+ }
+ else
+ {
+ aBmpPosPix.Y() = aPosPix.Y();
+ aBmpSizePix.Height() = aSizePix.Height();
+ }
+
+ // get output device
+ if( !pVDev )
+ {
+ pDev = new VirtualDevice;
+ pDev->SetOutputSizePixel( maSzPix, FALSE );
+ pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+ }
+ else
+ pDev = pVDev;
+
+ // restore background after each run
+ if( !nPos )
+ {
+ meLastDisposal = DISPOSE_BACK;
+ maRestPt = Point();
+ maRestSz = maSzPix;
+ }
+
+ // restore
+ if( ( DISPOSE_NOT != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
+ {
+ if( DISPOSE_BACK == meLastDisposal )
+ pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
+ else
+ pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
+ }
+
+ meLastDisposal = rAnm.eDisposal;
+ maRestPt = aPosPix;
+ maRestSz = aSizePix;
+
+ // Was muessen wir beim naechsten Mal restaurieren ?
+ // ==> ggf. in eine Bitmap stecken, ansonsten SaveBitmap
+ // aus Speichergruenden loeschen
+ if( ( meLastDisposal == DISPOSE_BACK ) || ( meLastDisposal == DISPOSE_NOT ) )
+ mpRestore->SetOutputSizePixel( Size( 1, 1 ), FALSE );
+ else
+ {
+ mpRestore->SetOutputSizePixel( maRestSz, FALSE );
+ mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
+ }
+
+ pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
+
+ if( !pVDev )
+ {
+ Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
+
+ if( pOldClip )
+ mpOut->SetClipRegion( maClip );
+
+ mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
+
+ if( pOldClip )
+ {
+ mpOut->SetClipRegion( *pOldClip );
+ delete pOldClip;
+ }
+
+ delete pDev;
+
+#ifndef REMOTE_APPSERVER
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ ( (Window*) mpOut )->Sync();
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplRepaint()
+{
+ const BOOL bOldPause = mbPause;
+
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ MapMode aTempMap( mpOut->GetMapMode() );
+ aTempMap.SetOrigin( Point() );
+ mpBackground->SetMapMode( aTempMap );
+ ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
+ mpBackground->SetMapMode( MapMode() );
+ }
+ else
+ mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+
+ mbPause = FALSE;
+ ImplDrawToPos( mnActPos );
+ mbPause = bOldPause;
+}
+
+// ------------------------------------------------------------------------
+
+AInfo* ImplAnimView::ImplCreateAInfo() const
+{
+ AInfo* pAInfo = new AInfo;
+
+ pAInfo->aStartOrg = maPt;
+ pAInfo->aStartSize = maSz;
+ pAInfo->pOutDev = mpOut;
+ pAInfo->pViewData = (void*) this;
+ pAInfo->nExtraData = mnExtraData;
+ pAInfo->bPause = mbPause;
+
+ return pAInfo;
+}
diff --git a/vcl/source/gdi/impanmvw.hxx b/vcl/source/gdi/impanmvw.hxx
new file mode 100644
index 000000000000..fdefa420cc62
--- /dev/null
+++ b/vcl/source/gdi/impanmvw.hxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * $RCSfile: impanmvw.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_IMPANMVW_HXX
+#define _SV_IMPANMVW_HXX
+
+#include "animate.hxx"
+
+// ----------------
+// - ImplAnimView -
+// ----------------
+
+class Animation;
+class OutputDevice;
+class VirtualDevice;
+struct AnimationBitmap;
+
+class ImplAnimView
+{
+private:
+
+ Animation* mpParent;
+ OutputDevice* mpOut;
+ long mnExtraData;
+ Point maPt;
+ Point maDispPt;
+ Point maRestPt;
+ Size maSz;
+ Size maSzPix;
+ Size maDispSz;
+ Size maRestSz;
+ MapMode maMap;
+ Region maClip;
+ VirtualDevice* mpBackground;
+ VirtualDevice* mpRestore;
+ ULONG mnActPos;
+ Disposal meLastDisposal;
+ BOOL mbPause;
+ BOOL mbFirst;
+ BOOL mbMarked;
+ BOOL mbHMirr;
+ BOOL mbVMirr;
+
+ void ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix );
+ void ImplDraw( ULONG nPos, VirtualDevice* pVDev );
+
+public:
+
+ ImplAnimView( Animation* pParent, OutputDevice* pOut,
+ const Point& rPt, const Size& rSz, ULONG nExtraData,
+ OutputDevice* pFirstFrameOutDev = NULL );
+ ~ImplAnimView();
+
+ BOOL ImplMatches( OutputDevice* pOut, long nExtraData ) const;
+ void ImplDrawToPos( ULONG nPos );
+ void ImplDraw( ULONG nPos );
+ void ImplRepaint();
+ AInfo* ImplCreateAInfo() const;
+
+ const Point& ImplGetOutPos() const { return maPt; }
+
+ const Size& ImplGetOutSize() const { return maSz; }
+ const Size& ImplGetOutSizePix() const { return maSzPix; }
+
+ void ImplPause( BOOL bPause ) { mbPause = bPause; }
+ BOOL ImplIsPause() const { return mbPause; }
+
+ void ImplSetMarked( BOOL bMarked ) { mbMarked = bMarked; }
+ BOOL ImplIsMarked() const { return mbMarked; }
+};
+
+#endif
diff --git a/vcl/source/gdi/impbmp.cxx b/vcl/source/gdi/impbmp.cxx
new file mode 100644
index 000000000000..3cb648163026
--- /dev/null
+++ b/vcl/source/gdi/impbmp.cxx
@@ -0,0 +1,309 @@
+/*************************************************************************
+ *
+ * $RCSfile: impbmp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPBMP_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALBMP_HXX
+#include <salbmp.hxx>
+#endif
+#else
+#include <indbmp.hxx>
+#ifndef _SV_RMBITMAP_HXX
+#include <rmbitmap.hxx>
+#endif
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#include <impbmp.hxx>
+#include <bitmap.hxx>
+
+// --------------
+// - ImpBitmap -
+// --------------
+
+ImpBitmap::ImpBitmap() :
+ mnRefCount ( 1UL ),
+ mnChecksum ( 0UL ),
+ mpRMBitmap ( NULL ),
+#ifndef REMOTE_APPSERVER
+ mpSalBitmap ( new SalBitmap )
+#else
+ mpSalBitmap ( new ImplServerBitmap )
+#endif
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImpBitmap::~ImpBitmap()
+{
+#ifdef REMOTE_APPSERVER
+ ImplReleaseRemoteBmp();
+#endif
+ delete mpSalBitmap;
+}
+
+// -----------------------------------------------------------------------
+#ifndef REMOTE_APPSERVER
+void ImpBitmap::ImplSetSalBitmap( SalBitmap* pBitmap )
+#else
+void ImpBitmap::ImplSetSalBitmap( ImplServerBitmap* pBitmap )
+#endif
+{
+ delete mpSalBitmap, mpSalBitmap = pBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
+{
+ return mpSalBitmap->Create( rSize, nBitCount, rPal );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap )
+{
+ mnChecksum = rImpBitmap.mnChecksum;
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap, SalGraphics* pGraphics )
+{
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap, pGraphics );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap, USHORT nNewBitCount )
+{
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap, nNewBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDestroy()
+{
+ mpSalBitmap->Destroy();
+}
+
+// -----------------------------------------------------------------------
+
+Size ImpBitmap::ImplGetSize() const
+{
+#ifdef REMOTE_APPSERVER
+ if( ImplIsGetPrepared() )
+ return mpRMBitmap->GetSize();
+ else
+#endif
+ return mpSalBitmap->GetSize();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImpBitmap::ImplGetBitCount() const
+{
+ USHORT nBitCount;
+
+#ifdef REMOTE_APPSERVER
+ if( ImplIsGetPrepared() )
+ nBitCount = mpRMBitmap->GetBitCount();
+ else
+#endif
+ nBitCount = mpSalBitmap->GetBitCount();
+
+ return( ( nBitCount <= 1 ) ? 1 : ( nBitCount <= 4 ) ? 4 : ( nBitCount <= 8 ) ? 8 : 24 );
+}
+
+// -----------------------------------------------------------------------
+
+BitmapBuffer* ImpBitmap::ImplAcquireBuffer( BOOL bReadOnly )
+{
+ return mpSalBitmap->AcquireBuffer( bReadOnly );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplReleaseBuffer( BitmapBuffer* pBuffer, BOOL bReadOnly )
+{
+ mpSalBitmap->ReleaseBuffer( pBuffer, bReadOnly );
+
+ if( !bReadOnly )
+ mnChecksum = 0;
+}
+
+#ifdef REMOTE_APPSERVER
+
+RMBitmap* ImpBitmap::ImplGetRemoteBmp()
+{
+ return mpRMBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplCreateRemoteBmp( const Bitmap& rBitmap )
+{
+ DBG_ASSERT( !mpRMBitmap, "ImplCreateRemoteBmp( Bitmap& rBitmap )???" );
+
+ mpRMBitmap = new RMBitmap( &(Bitmap&) rBitmap );
+ mpRMBitmap->Create();
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplCreateRemoteBmp( const Bitmap& rBitmap,
+ OutputDevice* pOut,
+ const Point& rPt, const Size& rSz )
+{
+ DBG_ASSERT( !mpRMBitmap, "ImplCreateRemoteBmp( Bitmap& rBitmap )???" );
+
+ mpRMBitmap = new RMBitmap( &(Bitmap&) rBitmap );
+ mpRMBitmap->CreateGet( pOut, rPt, rSz );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplReleaseRemoteBmp()
+{
+ delete mpRMBitmap;
+ mpRMBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmp( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->Draw( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpEx( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Bitmap& rMask )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rMask );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpAlpha( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const AlphaMask& rAlpha )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rAlpha );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpMask( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Color& rColor )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawMask( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rColor );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplIsGetPrepared() const
+{
+ return( mpRMBitmap ? mpRMBitmap->IsGetPrepared() : FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplResolveGet()
+{
+ if( mpRMBitmap )
+ {
+ Bitmap aBmp;
+ mpRMBitmap->Get( aBmp );
+ ImpBitmap* pGetImpBmp = aBmp.ImplGetImpBitmap();
+
+ if( pGetImpBmp )
+ {
+ // wir nehmen der gegetteten Bitmap einfach
+ // die SalBitmap weg; Null-Setzen nicht vergessen,
+ // da die Bitmap die SalBitmap sonst abraeumt
+ delete mpSalBitmap;
+ mpSalBitmap = pGetImpBmp->mpSalBitmap;
+ pGetImpBmp->mpSalBitmap = NULL;
+ }
+ }
+}
+
+#endif
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
new file mode 100644
index 000000000000..a53739ec6041
--- /dev/null
+++ b/vcl/source/gdi/impgraph.cxx
@@ -0,0 +1,1571 @@
+/*************************************************************************
+ *
+ * $RCSfile: impgraph.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPGRAPH_CXX
+
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _TOOLS_TEMPFILE_HXX
+#include <tools/tempfile.hxx>
+#endif
+#ifndef _UCBHELPER_CONTENT_HXX
+#include <ucbhelper/content.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _NEW_HXX
+#include <tools/new.hxx>
+#endif
+#include <impgraph.hxx>
+#ifndef _GFXLINK_HXX
+#include <gfxlink.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define GRAPHIC_MAXPARTLEN 256000L
+#define GRAPHIC_MTFTOBMP_MAXEXT 2048
+#define GRAPHIC_STREAMBUFSIZE 8192UL
+
+#define SYS_WINMETAFILE 0x00000003UL
+#define SYS_WNTMETAFILE 0x00000004UL
+#define SYS_OS2METAFILE 0x00000005UL
+#define SYS_MACMETAFILE 0x00000006UL
+
+#define GRAPHIC_FORMAT_50 COMPAT_FORMAT( 'G', 'R', 'F', '5' )
+#define NATIVE_FORMAT_50 COMPAT_FORMAT( 'N', 'A', 'T', '5' )
+
+// ---------------
+// - ImpSwapFile -
+// ---------------
+
+struct ImpSwapFile
+{
+ String aSwapFileName;
+ USHORT nRefCount;
+};
+
+// -----------------
+// - Graphicreader -
+// -----------------
+
+GraphicReader::~GraphicReader()
+{
+}
+
+// --------------
+// - ImpGraphic -
+// --------------
+
+ImpGraphic::ImpGraphic() :
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_NONE ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) :
+ maEx ( rImpGraphic.maEx ),
+ maMetaFile ( rImpGraphic.maMetaFile ),
+ mpContext ( NULL ),
+ mpSwapFile ( rImpGraphic.mpSwapFile ),
+ meType ( rImpGraphic.meType ),
+ maDocFileName ( rImpGraphic.maDocFileName ),
+ mnDocFilePos ( rImpGraphic.mnDocFilePos ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( rImpGraphic.mbSwapOut ),
+ mbSwapUnderway ( FALSE )
+{
+ if( mpSwapFile )
+ mpSwapFile->nRefCount++;
+
+ if( rImpGraphic.mpGfxLink )
+ mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
+ else
+ mpGfxLink = NULL;
+
+ if( rImpGraphic.mpAnimation )
+ {
+ mpAnimation = new Animation( *rImpGraphic.mpAnimation );
+ maEx = mpAnimation->GetBitmapEx();
+ }
+ else
+ mpAnimation = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
+ maEx ( rBitmap ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
+ maEx ( rBitmapEx ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
+ maEx ( rAnimation.GetBitmapEx() ),
+ mpAnimation ( new Animation( rAnimation ) ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
+ maMetaFile ( rMtf ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_GDIMETAFILE ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::~ImpGraphic()
+{
+ ImplClear();
+
+ if( (ULONG) mpContext > 1UL )
+ delete mpContext;
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
+{
+ if( &rImpGraphic != this )
+ {
+ if( !mbSwapUnderway )
+ ImplClear();
+
+ maMetaFile = rImpGraphic.maMetaFile;
+ meType = rImpGraphic.meType;
+
+ delete mpAnimation;
+
+ if ( rImpGraphic.mpAnimation )
+ {
+ mpAnimation = new Animation( *rImpGraphic.mpAnimation );
+ maEx = mpAnimation->GetBitmapEx();
+ }
+ else
+ {
+ mpAnimation = NULL;
+ maEx = rImpGraphic.maEx;
+ }
+
+ if( !mbSwapUnderway )
+ {
+ maDocFileName = rImpGraphic.maDocFileName;
+ mnDocFilePos = rImpGraphic.mnDocFilePos;
+ mbSwapOut = rImpGraphic.mbSwapOut;
+ mpSwapFile = rImpGraphic.mpSwapFile;
+
+ if( mpSwapFile )
+ mpSwapFile->nRefCount++;
+ }
+
+ delete mpGfxLink;
+
+ if( rImpGraphic.mpGfxLink )
+ mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
+ else
+ mpGfxLink = NULL;
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
+{
+ BOOL bRet = FALSE;
+
+ if( this == &rImpGraphic )
+ bRet = TRUE;
+ else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ bRet = TRUE;
+ break;
+
+ case( GRAPHIC_GDIMETAFILE ):
+ {
+ if( rImpGraphic.maMetaFile == maMetaFile )
+ bRet = TRUE;
+ }
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ {
+ if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) )
+ bRet = TRUE;
+ }
+ else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) )
+ bRet = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplClearGraphics( BOOL bCreateSwapInfo )
+{
+ if( bCreateSwapInfo && !ImplIsSwapOut() )
+ {
+ maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
+ maSwapInfo.maPrefSize = ImplGetPrefSize();
+ }
+
+ maEx.Clear();
+ maMetaFile.Clear();
+
+ if( mpAnimation )
+ {
+ mpAnimation->Clear();
+ delete mpAnimation;
+ mpAnimation = NULL;
+ }
+
+ if( mpGfxLink )
+ {
+ delete mpGfxLink;
+ mpGfxLink = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplClear()
+{
+ if( mpSwapFile )
+ {
+ if( mpSwapFile->nRefCount > 1 )
+ mpSwapFile->nRefCount--;
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( mpSwapFile->aSwapFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ delete mpSwapFile;
+ }
+
+ mpSwapFile = NULL;
+ }
+
+ mbSwapOut = FALSE;
+ mnDocFilePos = 0UL;
+ maDocFileName.Erase();
+
+ // cleanup
+ ImplClearGraphics( FALSE );
+ meType = GRAPHIC_NONE;
+}
+
+// ------------------------------------------------------------------------
+
+GraphicType ImpGraphic::ImplGetType() const
+{
+ return meType;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetDefaultType()
+{
+ ImplClear();
+ meType = GRAPHIC_DEFAULT;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsSupportedGraphic() const
+{
+ return( meType != GRAPHIC_NONE );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsTransparent() const
+{
+ BOOL bRet;
+
+ if( meType == GRAPHIC_BITMAP )
+ bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsAlpha() const
+{
+ BOOL bRet;
+
+ if( meType == GRAPHIC_BITMAP )
+ bRet = ( NULL == mpAnimation ) && maEx.IsAlpha();
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsAnimated() const
+{
+ return( mpAnimation != NULL );
+}
+
+// ------------------------------------------------------------------------
+
+Bitmap ImpGraphic::ImplGetBitmap() const
+{
+ Bitmap aRetBmp;
+
+ if( meType == GRAPHIC_BITMAP )
+ {
+ const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
+ const Color aReplaceColor( COL_WHITE );
+
+ aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
+ }
+ else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
+ {
+ VirtualDevice aVDev;
+ Size aSizePix( aVDev.LogicToPixel( maMetaFile.GetPrefSize(),
+ maMetaFile.GetPrefMapMode() ) );
+
+ if( aSizePix.Width() && aSizePix.Height() &&
+ ( aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT ) )
+ {
+ double fWH = (double) aSizePix.Width() / aSizePix.Height();
+
+ if( fWH <= 1.0 )
+ {
+ aSizePix.Width() = FRound( fWH * GRAPHIC_MTFTOBMP_MAXEXT );
+ aSizePix.Height() = GRAPHIC_MTFTOBMP_MAXEXT;
+ }
+ else
+ {
+ aSizePix.Width() = GRAPHIC_MTFTOBMP_MAXEXT;
+ aSizePix.Height() = FRound( GRAPHIC_MTFTOBMP_MAXEXT / fWH );
+ }
+ }
+
+ if( aVDev.SetOutputSizePixel( aSizePix ) )
+ {
+ const Point aPt;
+ ImplDraw( &aVDev, aPt, aSizePix );
+ aRetBmp = aVDev.GetBitmap( aPt, aSizePix );
+ }
+ }
+
+ if( !!aRetBmp )
+ {
+ aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
+ aRetBmp.SetPrefSize( ImplGetPrefSize() );
+ }
+
+ return aRetBmp;
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx ImpGraphic::ImplGetBitmapEx() const
+{
+ BitmapEx aRetBmpEx;
+
+ if( meType == GRAPHIC_BITMAP )
+ aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
+ else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
+ {
+ const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
+ aRetBmpEx = BitmapEx( ImplGetBitmap(), aMonoMask.ImplGetBitmap() );
+ }
+
+ return aRetBmpEx;
+}
+
+// ------------------------------------------------------------------------
+
+Animation ImpGraphic::ImplGetAnimation() const
+{
+ Animation aAnimation;
+
+ if( mpAnimation )
+ aAnimation = *mpAnimation;
+
+ return aAnimation;
+}
+
+// ------------------------------------------------------------------------
+
+const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
+{
+ return maMetaFile;
+}
+
+// ------------------------------------------------------------------------
+
+Size ImpGraphic::ImplGetPrefSize() const
+{
+ Size aSize;
+
+ if( ImplIsSwapOut() )
+ aSize = maSwapInfo.maPrefSize;
+ else
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ aSize = maEx.GetPrefSize();
+
+ if( !aSize.Width() || !aSize.Height() )
+ aSize = maEx.GetSizePixel();
+ }
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ aSize = maMetaFile.GetPrefSize();
+ }
+ break;
+ }
+ }
+
+ return aSize;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
+{
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ maEx.SetPrefSize( rPrefSize );
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ maMetaFile.SetPrefSize( rPrefSize );
+ }
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+MapMode ImpGraphic::ImplGetPrefMapMode() const
+{
+ MapMode aMapMode;
+
+ if( ImplIsSwapOut() )
+ aMapMode = maSwapInfo.maPrefMapMode;
+ else
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ const Size aSize( maEx.GetPrefSize() );
+
+ if ( aSize.Width() && aSize.Height() )
+ aMapMode = maEx.GetPrefMapMode();
+ }
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ return maMetaFile.GetPrefMapMode();
+ }
+ break;
+ }
+ }
+
+ return aMapMode;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
+{
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ maEx.SetPrefMapMode( rPrefMapMode );
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ maMetaFile.SetPrefMapMode( rPrefMapMode );
+ }
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetSizeBytes() const
+{
+ ULONG nSizeBytes;
+
+ if( meType == GRAPHIC_BITMAP )
+ {
+ if( mpAnimation )
+ nSizeBytes = mpAnimation->GetSizeBytes();
+ else
+ nSizeBytes = maEx.GetSizeBytes();
+ }
+ else
+ nSizeBytes = 0UL;
+
+ return nSizeBytes;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if ( mpAnimation )
+ mpAnimation->Draw( pOutDev, rDestPt );
+ else
+ maEx.Draw( pOutDev, rDestPt );
+ }
+ break;
+
+ default:
+ ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize ) const
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
+ else
+ maEx.Draw( pOutDev, rDestPt, rDestSize );
+ }
+ break;
+
+ default:
+ {
+ ( (ImpGraphic*) this )->maMetaFile.WindStart();
+ ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
+ ( (ImpGraphic*) this )->maMetaFile.WindStart();
+ }
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev,
+ const Point& rDestPt,
+ long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
+ const Size& rDestSize, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Stop( pOutDev, nExtraData );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink )
+{
+ if( mpAnimation )
+ mpAnimation->SetNotifyHdl( rLink );
+}
+
+// ------------------------------------------------------------------------
+
+Link ImpGraphic::ImplGetAnimationNotifyHdl() const
+{
+ Link aLink;
+
+ if( mpAnimation )
+ aLink = mpAnimation->GetNotifyHdl();
+
+ return aLink;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetAnimationLoopCount() const
+{
+ return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplResetAnimationLoopCount()
+{
+ if( mpAnimation )
+ mpAnimation->ResetLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+List* ImpGraphic::ImplGetAnimationInfoList() const
+{
+ return( mpAnimation ? mpAnimation->GetAInfoList() : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+GraphicReader* ImpGraphic::ImplGetContext()
+{
+ return mpContext;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetContext( GraphicReader* pReader )
+{
+ mpContext = pReader;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetDocFileName( const String& rName, ULONG nFilePos )
+{
+ maDocFileName = rName;
+ mnDocFilePos = nFilePos;
+}
+
+// ------------------------------------------------------------------------
+
+const String& ImpGraphic::ImplGetDocFileName() const
+{
+ return maDocFileName;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetDocFilePos() const
+{
+ return mnDocFilePos;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplReadEmbedded( SvStream& rIStm, BOOL bSwap )
+{
+ MapMode aMapMode;
+ Size aSize;
+ const ULONG nStartPos = rIStm.Tell();
+ ULONG nId;
+ ULONG nHeaderLen;
+ long nType;
+ long nLen;
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bRet = FALSE;
+
+ if( !mbSwapUnderway )
+ {
+ const String aTempName( maDocFileName );
+ const ULONG nTempPos = mnDocFilePos;
+
+ ImplClear();
+
+ maDocFileName = aTempName;
+ mnDocFilePos = nTempPos;
+ }
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rIStm >> nId;
+
+ // check version
+ if( GRAPHIC_FORMAT_50 == nId )
+ {
+ // read new style header
+ VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ );
+
+ rIStm >> nType;
+ rIStm >> nLen;
+ rIStm >> aSize;
+ rIStm >> aMapMode;
+
+ delete pCompat;
+ }
+ else
+ {
+ // read old style header
+ long nWidth, nHeight;
+ long nMapMode, nScaleNumX, nScaleDenomX;
+ long nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
+
+ rIStm.SeekRel( -4L );
+
+ rIStm >> nType >> nLen >> nWidth >> nHeight;
+ rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY;
+ rIStm >> nScaleDenomY >> nOffsX >> nOffsY;
+
+ // swapped
+ if( nType > 100L )
+ {
+ nType = SWAPLONG( nType );
+ nLen = SWAPLONG( nLen );
+ nWidth = SWAPLONG( nWidth );
+ nHeight = SWAPLONG( nHeight );
+ nMapMode = SWAPLONG( nMapMode );
+ nScaleNumX = SWAPLONG( nScaleNumX );
+ nScaleDenomX = SWAPLONG( nScaleDenomX );
+ nScaleNumY = SWAPLONG( nScaleNumY );
+ nScaleDenomY = SWAPLONG( nScaleDenomY );
+ nOffsX = SWAPLONG( nOffsX );
+ nOffsY = SWAPLONG( nOffsY );
+ }
+
+ aSize = Size( nWidth, nHeight );
+ aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
+ Fraction( nScaleNumX, nScaleDenomX ),
+ Fraction( nScaleNumY, nScaleDenomY ) );
+ }
+
+ nHeaderLen = rIStm.Tell() - nStartPos;
+ meType = (GraphicType) nType;
+
+ if( meType )
+ {
+ if( meType == GRAPHIC_BITMAP )
+ {
+ maEx.aBitmapSize = aSize;
+
+ if( aMapMode != MapMode() )
+ {
+ maEx.SetPrefMapMode( aMapMode );
+ maEx.SetPrefSize( aSize );
+ }
+ }
+ else
+ {
+ maMetaFile.SetPrefMapMode( aMapMode );
+ maMetaFile.SetPrefSize( aSize );
+ }
+
+ if( bSwap )
+ {
+ if( maDocFileName.Len() )
+ {
+ rIStm.Seek( nStartPos + nHeaderLen + nLen );
+ bRet = mbSwapOut = TRUE;
+ }
+ else
+ {
+ const String aTmpName( TempFile::CreateTempName() );
+
+ if( aTmpName.Len() )
+ {
+ SvFileStream aOStm( aTmpName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( !aOStm.GetError() )
+ {
+ ULONG nFullLen = nHeaderLen + nLen;
+ ULONG nPartLen = Min( nFullLen, (ULONG) GRAPHIC_MAXPARTLEN );
+ BYTE* pBuffer = (BYTE*) SvMemAlloc( nPartLen );
+
+ if( pBuffer )
+ {
+ rIStm.Seek( nStartPos );
+
+ while( nFullLen )
+ {
+ rIStm.Read( (char*) pBuffer, nPartLen );
+ aOStm.Write( (char*) pBuffer, nPartLen );
+
+ nFullLen -= nPartLen;
+
+ if( nFullLen < GRAPHIC_MAXPARTLEN )
+ nPartLen = nFullLen;
+ }
+
+ SvMemFree( pBuffer );
+
+ ULONG nReadErr = rIStm.GetError();
+ ULONG nWriteErr = aOStm.GetError();
+
+ aOStm.Close();
+
+ if( !nReadErr && !nWriteErr )
+ {
+ bRet = mbSwapOut = TRUE;
+ mpSwapFile = new ImpSwapFile;
+ mpSwapFile->nRefCount = 1;
+ mpSwapFile->aSwapFileName = aTmpName;
+ }
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( aTmpName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
+ {
+ rIStm >> *this;
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE )
+ {
+ Graphic aSysGraphic;
+ ULONG nCvtType;
+
+ switch( (ULONG) meType )
+ {
+ case( SYS_WINMETAFILE ):
+ case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
+ case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
+ case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
+
+ default:
+ nCvtType = CVT_UNKNOWN;
+ break;
+ }
+
+ if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
+ {
+ *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ else
+ meType = GRAPHIC_DEFAULT;
+ }
+
+ if( bRet )
+ {
+ ImplSetPrefMapMode( aMapMode );
+ ImplSetPrefSize( aSize );
+ }
+ }
+ else
+ bRet = TRUE;
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
+{
+ BOOL bRet = FALSE;
+
+ if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
+ {
+ const MapMode aMapMode( ImplGetPrefMapMode() );
+ const Size aSize( ImplGetPrefSize() );
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ const ULONG nStmPos1 = rOStm.Tell();
+ ULONG nDataFieldPos;
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ // write correct version ( old style/new style header )
+ if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
+ {
+ // write ID for new format (5.0)
+ rOStm << GRAPHIC_FORMAT_50;
+
+ // write new style header
+ VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (long) meType;
+
+ // data size is updated later
+ nDataFieldPos = rOStm.Tell();
+ rOStm << (long) 0;
+
+ rOStm << aSize;
+ rOStm << aMapMode;
+
+ delete pCompat;
+ }
+ else
+ {
+ // write old style (<=4.0) header
+ rOStm << (long) meType;
+
+ // data size is updated later
+ nDataFieldPos = rOStm.Tell();
+ rOStm << (long) 0;
+
+ rOStm << (long) aSize.Width();
+ rOStm << (long) aSize.Height();
+ rOStm << (long) aMapMode.GetMapUnit();
+ rOStm << (long) aMapMode.GetScaleX().GetNumerator();
+ rOStm << (long) aMapMode.GetScaleX().GetDenominator();
+ rOStm << (long) aMapMode.GetScaleY().GetNumerator();
+ rOStm << (long) aMapMode.GetScaleY().GetDenominator();
+ rOStm << (long) aMapMode.GetOrigin().X();
+ rOStm << (long) aMapMode.GetOrigin().Y();
+ }
+
+ // write data block
+ if( !rOStm.GetError() )
+ {
+ const ULONG nDataStart = rOStm.Tell();
+
+ if( ImplIsSupportedGraphic() )
+ rOStm << *this;
+
+ if( !rOStm.GetError() )
+ {
+ const ULONG nStmPos2 = rOStm.Tell();
+ rOStm.Seek( nDataFieldPos );
+ rOStm << (long) ( nStmPos2 - nDataStart );
+ rOStm.Seek( nStmPos2 );
+ bRet = TRUE;
+ }
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapOut()
+{
+ BOOL bRet = FALSE;
+
+ if( !ImplIsSwapOut() )
+ {
+ if( !maDocFileName.Len() )
+ {
+ const String aTmpName( TempFile::CreateTempName() );
+
+ if( aTmpName.Len() )
+ {
+ SvFileStream aOStm( aTmpName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.SetVersion( SOFFICE_FILEFORMAT_NOW );
+ aOStm.SetCompressMode( COMPRESSMODE_NATIVE );
+
+ if( ( bRet = ImplSwapOut( &aOStm ) ) == TRUE )
+ {
+ mpSwapFile = new ImpSwapFile;
+ mpSwapFile->nRefCount = 1;
+ mpSwapFile->aSwapFileName = aTmpName;
+ }
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( aTmpName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+ }
+ }
+ else
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapOut( SvStream* pOStm )
+{
+ BOOL bRet = FALSE;
+
+ if( pOStm )
+ {
+ pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
+
+ if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) )
+ {
+ pOStm->Flush();
+
+ if( !pOStm->GetError() )
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+ }
+ }
+ else
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapIn()
+{
+ BOOL bRet = FALSE;
+
+ if( ImplIsSwapOut() )
+ {
+ const String aFileName = ( mpSwapFile ? mpSwapFile->aSwapFileName : maDocFileName );
+ SvFileStream aIStm( aFileName, STREAM_READ | STREAM_SHARE_DENYWRITE );
+
+ aIStm.SetVersion( SOFFICE_FILEFORMAT_NOW );
+ aIStm.SetCompressMode( COMPRESSMODE_NATIVE );
+
+ if( !mpSwapFile )
+ aIStm.Seek( mnDocFilePos );
+
+ bRet = ImplSwapIn( &aIStm );
+ aIStm.Close();
+
+ if( mpSwapFile )
+ {
+ if( mpSwapFile->nRefCount > 1 )
+ mpSwapFile->nRefCount--;
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( mpSwapFile->aSwapFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ delete mpSwapFile;
+ }
+
+ mpSwapFile = NULL;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapIn( SvStream* pIStm )
+{
+ BOOL bRet = FALSE;
+
+ if( pIStm )
+ {
+ pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
+
+ if( !pIStm->GetError() )
+ {
+ mbSwapUnderway = TRUE;
+ bRet = ImplReadEmbedded( *pIStm );
+ mbSwapUnderway = FALSE;
+
+ if( !bRet )
+ ImplClear();
+ else
+ mbSwapOut = FALSE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsSwapOut() const
+{
+ return mbSwapOut;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink )
+{
+ delete mpGfxLink;
+ mpGfxLink = new GfxLink( rGfxLink );
+
+ if( mpGfxLink->IsNative() )
+ mpGfxLink->SwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink ImpGraphic::ImplGetLink()
+{
+ return( mpGfxLink ? *mpGfxLink : GfxLink() );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsLink() const
+{
+ return ( mpGfxLink != NULL ) ? TRUE : FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetChecksum() const
+{
+ ULONG nRet = 0;
+
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ nRet = mpAnimation->GetChecksum();
+ else
+ nRet = maEx.GetChecksum();
+ }
+ break;
+
+ default:
+ nRet = maMetaFile.GetChecksum();
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplCopy() const
+{
+ DBG_ERROR( "Missing implementation!" );
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplPaste()
+{
+ DBG_ERROR( "Missing implementation!" );
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic )
+{
+ if( !rIStm.GetError() )
+ {
+ const ULONG nStmPos1 = rIStm.Tell();
+ ULONG nTmp;
+
+ if ( !rImpGraphic.mbSwapUnderway )
+ rImpGraphic.ImplClear();
+
+ // read Id
+ rIStm >> nTmp;
+
+ if( NATIVE_FORMAT_50 == nTmp )
+ {
+ Graphic aGraphic;
+ GfxLink aLink;
+ VersionCompat* pCompat;
+
+ // read compat info
+ pCompat = new VersionCompat( rIStm, STREAM_READ );
+ delete pCompat;
+
+ rIStm >> aLink;
+
+ // set dummy link to avoid creation of additional link after filtering;
+ // we set a default link to avoid unnecessary swapping of native data
+ aGraphic.SetLink( GfxLink() );
+
+ if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
+ {
+ // set link only, if no other link was set
+ const BOOL bSetLink = ( rImpGraphic.mpGfxLink == NULL );
+
+ // assign graphic
+ rImpGraphic = *aGraphic.ImplGetImpGraphic();
+
+ if( bSetLink )
+ rImpGraphic.ImplSetLink( aLink );
+ }
+ else
+ {
+ rIStm.Seek( nStmPos1 );
+ rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
+ }
+ }
+ else
+ {
+ BitmapEx aBmpEx;
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+
+ rIStm.SeekRel( -4 );
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rIStm >> aBmpEx;
+
+ if( !rIStm.GetError() )
+ {
+ UINT32 nMagic1, nMagic2;
+ ULONG nActPos = rIStm.Tell();
+
+ rIStm >> nMagic1 >> nMagic2;
+ rIStm.Seek( nActPos );
+
+ rImpGraphic = ImpGraphic( aBmpEx );
+
+ if( ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) && !rIStm.GetError() )
+ {
+ delete rImpGraphic.mpAnimation;
+ rImpGraphic.mpAnimation = new Animation;
+ rIStm >> *rImpGraphic.mpAnimation;
+ }
+ }
+ else
+ {
+ GDIMetaFile aMtf;
+
+ rIStm.Seek( nStmPos1 );
+ rIStm.ResetError();
+ rIStm >> aMtf;
+
+ if( !rIStm.GetError() )
+ rImpGraphic = aMtf;
+ else
+ rIStm.Seek( nStmPos1 );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ }
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic )
+{
+ if( !rOStm.GetError() )
+ {
+ if( !rImpGraphic.ImplIsSwapOut() )
+ {
+ if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
+ ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) &&
+ rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
+ {
+ VersionCompat* pCompat;
+
+ // native format
+ rOStm << NATIVE_FORMAT_50;
+
+ // write compat info
+ pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+ delete pCompat;
+
+ rOStm << *rImpGraphic.mpGfxLink;
+ }
+ else
+ {
+ // own format
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ switch( rImpGraphic.ImplGetType() )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case GRAPHIC_BITMAP:
+ {
+ if ( rImpGraphic.ImplIsAnimated() )
+ rOStm << *rImpGraphic.mpAnimation;
+ else
+ rOStm << rImpGraphic.maEx;
+ }
+ break;
+
+ default:
+ {
+ if( rImpGraphic.ImplIsSupportedGraphic() )
+ rOStm << rImpGraphic.maMetaFile;
+ }
+ break;
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+ }
+ else
+ rOStm.SetError( SVSTREAM_GENERALERROR );
+ }
+
+ return rOStm;
+}
diff --git a/vcl/source/gdi/impimage.cxx b/vcl/source/gdi/impimage.cxx
new file mode 100644
index 000000000000..1dcebb60009a
--- /dev/null
+++ b/vcl/source/gdi/impimage.cxx
@@ -0,0 +1,744 @@
+/*************************************************************************
+ *
+ * $RCSfile: impimage.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPIMAGE_CXX
+
+#include <string.h>
+
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_IMAGE_H
+#include <image.h>
+#endif
+
+// -------------
+// - FASTIMAGE -
+// -------------
+
+#ifndef REMOTE_APPSERVER
+#if defined WIN || defined WNT || defined OS2
+#undef FASTTRANSPARENT
+extern BOOL bFastTransparent;
+#else
+#undef FASTTRANSPARENT
+#endif
+#else
+#undef FASTTRANSPARENT
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define IPOS( nPos ) ( Point( (nPos) * aSize.Width(), 0L ) )
+#define IMPSYSIMAGEITEM_NOTFREE ( 0x01 )
+#define IMPSYSIMAGEITEM_MASK ( 0x02 )
+#define DISA_ALL ( 0xffff )
+#define PAINT_ALL ( 0xffff )
+
+// ----------------
+// - ImplImageBmp -
+// ----------------
+
+ImplImageBmp::ImplImageBmp() :
+ pInfoAry ( NULL ),
+ nCount ( 0 ),
+ nSize ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageBmp::~ImplImageBmp()
+{
+ delete[] pInfoAry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Create( long nItemWidth, long nItemHeight, USHORT nInitSize )
+{
+ const Size aTotalSize( nInitSize * nItemWidth, nItemHeight );
+
+ nCount = 0;
+ aSize = Size( nItemWidth, nItemHeight );
+ nSize = nInitSize;
+
+ aBmp = Bitmap( aTotalSize, 4 );
+ aMask = Bitmap( aTotalSize, 1 );
+
+ delete[] pInfoAry;
+ pInfoAry = new BYTE[ nSize ];
+ memset( pInfoAry, 0, nSize );
+ ImplClearCaches();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Create( const Bitmap& rBmp, const Bitmap& rMaskBmp,
+ const Color& rColor, BOOL bColor,
+ long nItemWidth, long nItemHeight, USHORT nInitSize )
+{
+ BYTE nStyle = IMPSYSIMAGEITEM_NOTFREE;
+
+ ImplClearCaches();
+
+ if ( bColor || !!rMaskBmp )
+ nStyle |= IMPSYSIMAGEITEM_MASK;
+
+ aSize = Size( nItemWidth, nItemHeight );
+ nCount = 0;
+ nSize = nInitSize;
+
+ delete[] pInfoAry;
+ pInfoAry = new BYTE[ nSize ];
+ memset( pInfoAry, nStyle, nSize );
+
+ aBmp = rBmp;
+
+ if( !!rMaskBmp )
+ aMask = rMaskBmp;
+ else if( bColor )
+ aMask = aBmp.CreateMask( rColor );
+
+#ifdef FASTTRANSPARENT
+ if( nStyle & IMPSYSIMAGEITEM_MASK )
+ ImplUpdatePaintBmp( DISA_ALL );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Expand( USHORT nGrowSize )
+{
+ const ULONG nDX = nGrowSize * aSize.Width();
+ const USHORT nOldSize = nSize;
+ BYTE* pNewAry = new BYTE[ nSize += nGrowSize ];
+
+ ImplClearCaches();
+
+ aBmp.Expand( nDX, 0UL );
+ aMask.Expand( nDX, 0UL );
+
+ if( !!aDisa )
+ aDisa.Expand( nDX, 0UL );
+
+ memset( pNewAry, 0, nSize );
+ memcpy( pNewAry, pInfoAry, nOldSize );
+ delete[] pInfoAry;
+ pInfoAry = pNewAry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, USHORT nSrcPos )
+{
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect );
+
+ if ( pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+ aMask.CopyPixel( aDstRect, aSrcRect );
+
+ if( !!aDisa )
+ aDisa.CopyPixel( aDstRect, aSrcRect );
+ }
+
+ pInfoAry[ nPos ] = pInfoAry[ nSrcPos ];
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const ImplImageBmp& rImageBmp, USHORT nSrcPos )
+{
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aBmp );
+
+ if ( rImageBmp.pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+ aMask.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aMask );
+
+ if( !!aDisa )
+ aDisa.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aDisa );
+ }
+
+ pInfoAry[ nPos ] = rImageBmp.pInfoAry[ nSrcPos ];
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp )
+{
+ Point aPoint;
+ const Rectangle aSrcRect( aPoint, aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rBmp );
+ pInfoAry[ nPos ] &= ~IMPSYSIMAGEITEM_MASK;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp, const Bitmap& rMaskBmp )
+{
+ Point aPoint;
+ const Rectangle aSrcRect( aPoint, aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rBmp );
+ aMask.CopyPixel( aDstRect, aSrcRect, &rMaskBmp );
+
+ if( !!aDisa )
+ ImplUpdateDisaBmp( nPos );
+
+ pInfoAry[ nPos ] |= IMPSYSIMAGEITEM_MASK;
+
+#ifdef FASTTRANSPARENT
+ ImplUpdatePaintBmp( nPos );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp, const Color& rColor )
+{
+ Replace( nPos, rBmp, rBmp.CreateMask( rColor ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Merge( USHORT nPos, USHORT nSrcPos )
+{
+ if ( !( pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK ) )
+ Replace( nPos, nSrcPos );
+ else
+ {
+ ImplClearCaches();
+
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+ BitmapWriteAccess* pBmp = aBmp.AcquireWriteAccess();
+ BitmapWriteAccess* pMsk = aMask.AcquireWriteAccess();
+
+ if ( pBmp && pMsk )
+ {
+ const BitmapColor aMskBlack( pMsk->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ BitmapColor aDstCol, aSrcCol;
+ long nDstLeft = aDstRect.Left();
+ long nDstRight = aDstRect.Right();
+ long nDstBottom = aDstRect.Bottom();
+ long nSrcLeft = aSrcRect.Left();
+ long nSrcRight = aSrcRect.Right();
+ long nSrcTop = aSrcRect.Bottom();
+
+ for( long nDstY = aDstRect.Top(), nSrcY = aSrcRect.Top(); nDstY <= nDstBottom; nDstY++, nSrcY++ )
+ {
+ for( long nDstX = nDstLeft, nSrcX = nSrcLeft; nDstX <= nDstRight; nDstX++, nSrcX++ )
+ {
+ aDstCol = pMsk->GetPixel( nDstY, nDstX );
+ aSrcCol = pMsk->GetPixel( nSrcY, nSrcX );
+
+ if( aMskBlack == aDstCol )
+ {
+ if( aMskBlack == aSrcCol )
+ pBmp->SetPixel( nDstY, nDstX, pBmp->GetPixel( nSrcY, nSrcX ) );
+ }
+ else if( aMskBlack == aSrcCol )
+ {
+ pBmp->SetPixel( nDstY, nDstX, pBmp->GetPixel( nSrcY, nSrcX ) );
+ pMsk->SetPixel( nDstY, nDstX, aMskBlack );
+ }
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pBmp );
+ aMask.ReleaseAccess( pMsk );
+
+ if( !!aDisa )
+ ImplUpdateDisaBmp( nPos );
+
+ pInfoAry[ nPos ] |= IMPSYSIMAGEITEM_MASK;
+
+#ifdef FASTTRANSPARENT
+ ImplUpdatePaintBmp( nPos );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImplImageBmp::GetBitmap( USHORT nPosCount, USHORT* pPosAry ) const
+{
+ Bitmap aNewBmp( Size( nPosCount * aSize.Width(), aSize.Height() ), aBmp.GetBitCount() );
+
+ for( USHORT i = 0; i < nPosCount; i++ )
+ {
+ const Rectangle aSrcRect( IPOS( pPosAry[ i ] ), aSize );
+ const Rectangle aDstRect( IPOS( i ), aSize );
+
+ aNewBmp.CopyPixel( aDstRect, aSrcRect, &aBmp );
+ }
+
+ return aNewBmp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageBmp::HasMaskBitmap() const
+{
+ return( !!aMask );
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImplImageBmp::GetMaskBitmap( USHORT nPosCount, USHORT* pPosAry ) const
+{
+ Bitmap aNewMask( Size( nPosCount * aSize.Width(), aSize.Height() ), aMask.GetBitCount() );
+
+ for( USHORT i = 0; i < nPosCount; i++ )
+ {
+ const Rectangle aSrcRect( IPOS( pPosAry[ i ] ), aSize );
+ const Rectangle aDstRect( IPOS( i ), aSize );
+
+ aNewMask.CopyPixel( aDstRect, aSrcRect, &aMask );
+ }
+
+ return aNewMask;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageBmp::HasMaskColor() const
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Color ImplImageBmp::GetMaskColor() const
+{
+ return Color();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Draw( USHORT nPos, OutputDevice* pOutDev,
+ const Point& rPos, USHORT nStyle,
+ const Size* pSize )
+{
+ if( pOutDev->IsDeviceOutputNecessary() )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( !aBmpDisp && !!aBmp )
+ aBmpDisp = aBmp.CreateDisplayBitmap( pOutDev );
+
+ if( !aMaskDisp && !!aMask )
+ aMaskDisp = aMask.CreateDisplayBitmap( pOutDev );
+
+#else // REMOTE_APPSERVER
+
+ if( !aBmpDisp && !!aBmp )
+ aBmpDisp = aBmp;
+
+ if( !aMaskDisp && !!aMask )
+ aMaskDisp = aMask;
+
+ if( !aDisaDisp && !!aDisa )
+ aDisaDisp = aDisa;
+
+#endif // REMOTE_APPSERVER
+
+ if( !aBmpEx )
+ aBmpEx = BitmapEx( aBmpDisp, aMaskDisp );
+
+ if( pInfoAry[ nPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+#ifdef FASTTRANSPARENT
+ BOOL bTmp = bFastTransparent;
+ bFastTransparent = TRUE;
+#endif
+
+ Point aOutPos = pOutDev->LogicToPixel( rPos );
+ Size aOutSize;
+ BOOL bOldMap = pOutDev->mbMap;
+
+ if( pSize )
+ aOutSize = pOutDev->LogicToPixel( *pSize );
+ else
+ aOutSize = aSize;
+
+ pOutDev->mbMap = FALSE;
+
+ if ( nStyle & IMAGE_DRAW_DISABLE )
+ {
+ Point aOutPos1( aOutPos.X()+1, aOutPos.Y()+1 );
+ const Point aPos( IPOS( nPos) );
+ const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+
+ if( !aDisa )
+ {
+ aDisa = Bitmap( aBmpEx.GetSizePixel(), 1 );
+ ImplUpdateDisaBmp( DISA_ALL );
+#ifndef REMOTE_APPSERVER
+ aDisaDisp = aDisa.CreateDisplayBitmap( pOutDev );
+#else // REMOTE_APPSERVER
+ aDisaDisp = aDisa;
+#endif // REMOTE_APPSERVER
+ }
+
+ if( !aDisaDisp && !!aDisa )
+ aDisaDisp = aDisa.CreateDisplayBitmap( pOutDev );
+
+ pOutDev->DrawMask( aOutPos1, aOutSize, aPos, aSize,
+ aDisaDisp, rSettings.GetLightColor() );
+ pOutDev->DrawMask( aOutPos, aOutSize, aPos, aSize,
+ aDisaDisp, rSettings.GetShadowColor() );
+ }
+ else
+ {
+ BOOL bDrawn = FALSE;
+
+ if( nStyle & ( IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE ) )
+ {
+ Bitmap aTmpBmp( aBmp );
+ BitmapWriteAccess* pAcc;
+
+ aTmpBmp.Crop( Rectangle( IPOS( nPos ), aSize ) );
+ pAcc = aTmpBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+ Color aColor;
+ BitmapColor aCol;
+ const long nW = pAcc->Width();
+ const long nH = pAcc->Height();
+ BYTE* pMapR = new BYTE[ 256 ];
+ BYTE* pMapG = new BYTE[ 256 ];
+ BYTE* pMapB = new BYTE[ 256 ];
+ long nX, nY;
+
+ if( nStyle & IMAGE_DRAW_HIGHLIGHT )
+ aColor = rSettings.GetHighlightColor();
+ else
+ aColor = rSettings.GetDeactiveColor();
+
+ const BYTE cR = aColor.GetRed();
+ const BYTE cG = aColor.GetGreen();
+ const BYTE cB = aColor.GetBlue();
+
+ for( nX = 0L; nX < 256L; nX++ )
+ {
+ pMapR[ nX ] = (BYTE) ( ( ( nY = ( nX + cR ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapG[ nX ] = (BYTE) ( ( ( nY = ( nX + cG ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapB[ nX ] = (BYTE) ( ( ( nY = ( nX + cB ) >> 1 ) > 255 ) ? 255 : nY );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+ aCol.SetRed( pMapR[ rCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ rCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ rCol.GetBlue() ] );
+ pAcc->SetPaletteColor( i, aCol );
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = pMapB[ *pScan ]; pScan++;
+ *pScan = pMapG[ *pScan ]; pScan++;
+ *pScan = pMapR[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+ aCol.SetRed( pMapR[ aCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ aCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ aCol.GetBlue() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ delete[] pMapR;
+ delete[] pMapG;
+ delete[] pMapB;
+ aTmpBmp.ReleaseAccess( pAcc );
+
+ Bitmap aTmpMsk( aMask );
+ aTmpMsk.Crop( Rectangle( IPOS( nPos), aSize ) );
+ pOutDev->DrawBitmapEx( aOutPos, BitmapEx( aTmpBmp, aTmpMsk ) );
+ bDrawn = TRUE;
+ }
+ }
+
+ if( !bDrawn )
+ pOutDev->DrawBitmapEx( aOutPos, aOutSize, IPOS( nPos), aSize, aBmpEx );
+ }
+
+ pOutDev->mbMap = bOldMap;
+
+#ifdef FASTTRANSPARENT
+ bFastTransparent = bTmp;
+#endif
+ }
+ else if( pSize )
+ pOutDev->DrawBitmap( rPos, *pSize,
+ IPOS( nPos), aSize, aBmpEx.GetBitmap() );
+ else
+ pOutDev->DrawBitmap( rPos, pOutDev->PixelToLogic( aSize ),
+ IPOS( nPos), aSize, aBmpEx.GetBitmap() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplUpdateDisaBmp( USHORT nPos )
+{
+ BitmapReadAccess* pAcc = aBmp.AcquireReadAccess();
+ BitmapReadAccess* pMsk = aMask.AcquireReadAccess();
+ BitmapWriteAccess* pDis = aDisa.AcquireWriteAccess();
+
+ if( pAcc && pMsk && pDis )
+ {
+ const Color aWhite( COL_WHITE );
+ const Color aBlack( COL_BLACK );
+ const BitmapColor aAccWhite( pAcc->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aMskWhite( pMsk->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aDisWhite( pDis->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aDisBlack( pDis->GetBestMatchingColor( aBlack ) );
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+
+ if( DISA_ALL != nPos )
+ {
+ const Point aPos( IPOS( nPos ) );
+
+ nLeft = aPos.X();
+ nTop = aPos.Y();
+ nRight = nLeft + aSize.Width();
+ nBottom = nTop + aSize.Height();
+ }
+ else
+ {
+ nLeft = nTop = 0L;
+ nRight = pDis->Width();
+ nBottom = pDis->Height();
+ }
+
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL &&
+ pMsk->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ // optimized version
+ const BYTE cAccTest = aAccWhite.GetIndex();
+ const BYTE cMskTest = aMskWhite.GetIndex();
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ Scanline pAccScan = pAcc->GetScanline( nY );
+ Scanline pMskScan = pMsk->GetScanline( nY );
+
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( cMskTest == ( pMskScan[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 ) ) ||
+ ( cAccTest == ( ( pAccScan[ nX >> 1 ] >> ( nX & 1 ? 0 : 4 ) ) & 0x0f ) ) )
+ {
+ pDis->SetPixel( nY, nX, aDisWhite );
+ }
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL &&
+ pMsk->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ // optimized version
+ const BYTE cAccTest = aAccWhite.GetIndex();
+ const BYTE cMskTest = aMskWhite.GetIndex();
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ Scanline pAccScan = pAcc->GetScanline( nY );
+ Scanline pMskScan = pMsk->GetScanline( nY );
+
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( cMskTest == ( pMskScan[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 ) ) ||
+ ( cAccTest == pAccScan[ nX ] ) )
+ {
+ pDis->SetPixel( nY, nX, aDisWhite );
+ }
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( aMskWhite == pMsk->GetPixel( nY, nX ) ) || ( aAccWhite == pAcc->GetPixel( nY, nX ) ) )
+ pDis->SetPixel( nY, nX, aDisWhite );
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ aMask.ReleaseAccess( pMsk );
+ aDisa.ReleaseAccess( pDis );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplUpdatePaintBmp( USHORT nPos )
+{
+ BitmapWriteAccess* pBmp = aBmp.AcquireWriteAccess();
+ BitmapReadAccess* pMsk = aMask.AcquireReadAccess();
+
+ if ( pBmp && pMsk )
+ {
+ const Color aBlack( COL_BLACK );
+ const BitmapColor aBmpBlack( pBmp->GetBestMatchingColor( aBlack ) );
+ const BitmapColor aMskBlack( pMsk->GetBestMatchingColor( aBlack ) );
+ long nLeft, nTop, nRight, nBottom;
+
+ if( PAINT_ALL != nPos )
+ {
+ const Point aPos( IPOS( nPos ) );
+
+ nLeft = aPos.X();
+ nTop = aPos.Y();
+ nRight = nLeft + aSize.Width();
+ nBottom = nTop + aSize.Height();
+ }
+ else
+ {
+ nLeft = nTop = 0L;
+ nRight = pBmp->Width();
+ nBottom = pBmp->Height();
+ }
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ for( long nX = nLeft; nX < nRight; nX++ )
+ if( aMskBlack != pMsk->GetPixel( nY, nX ) )
+ pBmp->SetPixel( nY, nX, aBmpBlack );
+ }
+
+ aBmp.ReleaseAccess( pBmp );
+ aMask.ReleaseAccess( pMsk );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplClearCaches()
+{
+ aBmpEx.Clear();
+ aBmpDisp = aMaskDisp = aDisaDisp = Bitmap();
+}
diff --git a/vcl/source/gdi/implncvt.cxx b/vcl/source/gdi/implncvt.cxx
new file mode 100644
index 000000000000..98a428d36380
--- /dev/null
+++ b/vcl/source/gdi/implncvt.cxx
@@ -0,0 +1,605 @@
+/*************************************************************************
+ *
+ * $RCSfile: implncvt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_SALBTYPE_HXX
+#include "salbtype.hxx"
+#endif
+#ifndef _SV_IMPLNCVT_HXX
+#include "implncvt.hxx"
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define CURVE_LEFT 1
+#define CURVE_RIGHT 2
+#define CURVE_STRAIGHTON 3
+
+// -----------------
+// - ImplFloatPoint
+// -----------------
+
+struct ImplFloatPoint
+{
+ double fX;
+ double fY;
+
+ inline ImplFloatPoint() {}
+ inline ImplFloatPoint( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
+ inline ImplFloatPoint( double _fX, double _fY ) { fX = _fX; fY = _fY; }
+ inline ImplFloatPoint( const ImplFloatPoint& rPoint ) { fX = rPoint.fX; fY = rPoint.fY; }
+ inline ~ImplFloatPoint() {}
+
+ void operator+=( const ImplFloatPoint& rPoint ) { fX += rPoint.fX; fY += rPoint.fY; }
+ void operator-=( const ImplFloatPoint& rPoint ) { fX -= rPoint.fX; fY -= rPoint.fY; }
+ void operator*=( const double& rD ) { fX *= rD; fY *= rD; }
+ BOOL operator==( const ImplFloatPoint& rPoint ) const { return ( ( rPoint.fX == fX ) && ( rPoint.fY == fY ) ); } const
+ void operator=( const Point rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
+
+ ImplFloatPoint GetOVec( const ImplFloatPoint& rPoint ) const;
+ ImplFloatPoint GetNVec( const ImplFloatPoint& rPoint ) const;
+};
+
+// -----------------------------------------------------------------------------
+
+ImplFloatPoint ImplFloatPoint::GetOVec( const ImplFloatPoint& rPoint ) const
+{
+ double fxt = rPoint.fX - fX;
+ double fyt = rPoint.fY - fY;
+ double fL;
+
+ if( fyt != 0.0 )
+ {
+ fyt = -fxt / fyt;
+ fL = sqrt( 1 + fyt * fyt );
+
+ return ImplFloatPoint( 1.0 / fL, fyt / fL );
+ }
+ else
+ return ImplFloatPoint( fyt, ( fxt > 0.0 ) ? 1.0 : -1.0 );
+};
+
+// -----------------------------------------------------------------------------
+
+ImplFloatPoint ImplFloatPoint::GetNVec( const ImplFloatPoint& rPoint ) const
+{
+ const double fxt = rPoint.fX - fX;
+ const double fyt = rPoint.fY - fY;
+ const double fL = hypot( fxt, fyt );
+
+ return ImplFloatPoint( fxt / fL, fyt / fL );
+};
+
+// --------------------
+// - ImplLineConverter
+// --------------------
+
+ImplLineConverter::ImplLineConverter( const Polygon& rPolygon, const LineInfo& rLineInfo, const Point* pRefPoint ) :
+ maLineInfo ( rLineInfo ),
+ mfWidthHalf ( rLineInfo.GetWidth() >> 1 ),
+ mpFloatPoint ( NULL ),
+ mpFloat0 ( new ImplFloatPoint[ 6 ] ),
+ mpFloat1 ( new ImplFloatPoint[ 6 ] ),
+ mnLines ( 0 )
+{
+ UINT16 nIndex, nPolySize = rPolygon.GetSize();
+ if ( nPolySize )
+ {
+ if( rPolygon.GetFlags( 0 ) == POLY_NORMAL )
+ {
+ mpFloatPoint = new ImplFloatPoint[ nPolySize ];
+ mpFloatPoint[ 0 ] = rPolygon[ 0 ];
+
+ nIndex = 0;
+
+ while( ++nIndex < nPolySize ) // doppelte Punkte eliminieren und ein FloatPointArray anlegen
+ {
+ if( rPolygon.GetFlags( nIndex ) == POLY_NORMAL )
+ {
+ double nxt = mpFloatPoint[ mnLines ].fX;
+ double nyt = mpFloatPoint[ mnLines ].fY;
+
+ if ( ( nxt == rPolygon[ nIndex ].X() ) && ( nyt == rPolygon[ nIndex ].Y() ) )
+ continue;
+
+ mpFloatPoint[ ++mnLines ] = rPolygon[ nIndex ];
+ }
+ else
+ {
+ DBG_ERROR( "Bezier points not supported!" );
+ }
+ }
+ mbClosed = ( mpFloatPoint[ 0 ] == mpFloatPoint[ mnLines ] ) ;
+
+ if ( ( mnLines == 1 ) && ( maLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ BOOL bX = mpFloatPoint[ 0 ].fY == mpFloatPoint[ 1 ].fY;
+ BOOL bY = mpFloatPoint[ 0 ].fX == mpFloatPoint[ 1 ].fX;
+ mbRefPoint = pRefPoint && ( bX || bY );
+ if ( mbRefPoint )
+ {
+ if ( !maLineInfo.GetDashCount() )
+ {
+ maLineInfo.SetDashCount( maLineInfo.GetDotCount() );
+ maLineInfo.SetDashLen( maLineInfo.GetDotLen() );
+ maLineInfo.SetDotCount( 0 );
+ }
+ INT32 nDistance = maLineInfo.GetDistance();
+ INT32 nDashLen = maLineInfo.GetDashCount() * ( maLineInfo.GetDashLen() + nDistance );
+ INT32 nDotLen = maLineInfo.GetDotCount() * ( maLineInfo.GetDotLen() + nDistance );
+ if ( bX )
+ {
+ if ( mpFloatPoint[ 1 ].fX > mpFloatPoint[ 0 ].fX )
+ {
+ ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
+ mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
+ mpFloatPoint[ 1 ] = aFloat;
+ }
+ mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X();
+ }
+ else
+ {
+ if ( mpFloatPoint[ 1 ].fY > mpFloatPoint[ 0 ].fY )
+ {
+ ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
+ mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
+ mpFloatPoint[ 1 ] = aFloat;
+ }
+ mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y();
+ }
+
+// mnRefDistance = ( (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X() ) +
+// ( (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y() );
+
+ mnRefDistance = mnRefDistance % ( nDashLen + nDotLen );
+ if ( mnRefDistance < 0 )
+ mnRefDistance = ( nDashLen + nDotLen ) + mnRefDistance;
+ }
+ }
+ }
+ }
+};
+
+//------------------------------------------------------------------------
+
+ImplLineConverter::~ImplLineConverter()
+{
+ delete[] mpFloat0;
+ delete[] mpFloat1;
+ delete[] mpFloatPoint;
+};
+
+//------------------------------------------------------------------------
+
+const Polygon* ImplLineConverter::ImplGetFirst()
+{
+ mnFloat1Points = 0;
+ mnLinesAvailable = mnLines;
+
+ if ( mnLines )
+ {
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ mfDashDotLenght = mnDashCount ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+
+ if ( mbRefPoint )
+ {
+ INT32 nDistance = maLineInfo.GetDistance();
+ INT32 nDashLen = maLineInfo.GetDashLen() + nDistance;
+ INT32 nDashesLen = maLineInfo.GetDashCount() * nDashLen;
+ INT32 nDotLen = maLineInfo.GetDotLen() + nDistance;
+ INT32 nDotsLen = maLineInfo.GetDotCount() * nDotLen;
+
+ if ( mnRefDistance >= nDashesLen )
+ {
+ // get dotcount
+ if ( nDotLen )
+ {
+ INT32 nLen = ( mnRefDistance - nDashesLen ) % nDotLen;
+ if ( nLen >= maLineInfo.GetDotLen() )
+ {
+ mnDotCount -= 1 + ( mnRefDistance - nDashesLen ) / nDotLen;
+ if ( mnDotCount )
+ mnDashCount = 0;
+ else
+ mnDotCount = maLineInfo.GetDotCount();
+ mfDashDotLenght = 0.0;
+ mfDistanceLenght = ( maLineInfo.GetDotLen() + nDistance ) - nLen;
+ }
+ else
+ {
+ mnDashCount = 0;
+ mfDashDotLenght = maLineInfo.GetDotLen() - nLen;
+ mnDotCount -= ( mnRefDistance - nDashesLen ) / nDotLen;
+ }
+ }
+ }
+ else
+ {
+ if ( nDashLen )
+ {
+ // get dashcount
+ INT32 nLen = mnRefDistance % nDashLen;
+ if ( nLen >= maLineInfo.GetDashLen() )
+ {
+ mfDashDotLenght = 0.0;
+ mfDistanceLenght = ( maLineInfo.GetDashLen() + nDistance ) - nLen;
+ mnDashCount -= 1 + ( mnRefDistance / nDashLen );
+ }
+ else
+ {
+ mfDashDotLenght = maLineInfo.GetDashLen() - nLen;
+ mnDashCount -= ( mnRefDistance / nDashLen );
+ }
+ }
+ }
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ if ( ( mfDashDotLenght == 0.0 ) && ( mfDistanceLenght == 0.0 ) )
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ }
+ return ImplGetNext();
+};
+
+//------------------------------------------------------------------------
+
+const Polygon* ImplLineConverter::ImplGetNext()
+{
+ while( mnFloat1Points || mnLinesAvailable )
+ {
+ if ( maLineInfo.GetWidth() > 1 )
+ {
+ if ( !mnFloat1Points )
+ {
+ ImplFloatPoint aPointA( mpFloatPoint[ mnLinesAvailable-- ] );
+ ImplFloatPoint aPointB( mpFloatPoint[ mnLinesAvailable ] );
+ ImplFloatPoint aOVecAB( aPointA.GetOVec( aPointB ) );
+ ImplFloatPoint aN1Vec( aPointA.GetNVec( aPointB ) );
+ aN1Vec *= mfWidthHalf;
+
+ if ( !mbClosed && ( ( mnLinesAvailable + 1 ) == mnLines ) )
+ aPointA -= aN1Vec;
+
+ aOVecAB *= mfWidthHalf;
+ mpFloat0[ 0 ] = aPointA;
+ mpFloat0[ 0 ] -= aOVecAB;
+ mpFloat0[ 3 ] = aPointA;
+ mpFloat0[ 3 ] += aOVecAB;
+ mpFloat0[ 1 ] = aPointB;
+ mpFloat0[ 1 ] -= aOVecAB;
+ mpFloat0[ 2 ] = aPointB;
+ mpFloat0[ 2 ] += aOVecAB;
+
+ double f1D = ( aN1Vec.fX == 0 ) ? 1 : ( aN1Vec.fY / aN1Vec.fX );
+ double f2D = -f1D;
+
+ mnFloat0Points = 4;
+
+ int nDirection;
+
+ BOOL bContinues = ( mnLinesAvailable || mbClosed );
+ if ( bContinues )
+ {
+ ImplFloatPoint aPointC;
+
+ if ( mnLinesAvailable )
+ aPointC = mpFloatPoint[ mnLinesAvailable - 1 ];
+ else
+ aPointC = mpFloatPoint[ mnLines - 1 ];
+
+ ImplFloatPoint aOVecBC( aPointB.GetOVec( aPointC ) );
+ aOVecBC *= mfWidthHalf;
+ ImplFloatPoint aPointR0( aPointB );
+ aPointR0 -= aOVecBC;
+ ImplFloatPoint aPointR1( aPointB );
+ aPointR1 += aOVecBC;
+ ImplFloatPoint aN2Vec( aPointB.GetNVec( aPointC ) );
+ aN2Vec *= mfWidthHalf;
+
+ f2D = ( aN2Vec.fX == 0 ) ? 1 : ( aN2Vec.fY / aN2Vec.fX );
+ if ( f1D == f2D )
+ nDirection = CURVE_STRAIGHTON;
+ else
+ {
+ if ( ( aN1Vec.fX * aN2Vec.fY - aN1Vec.fY * aN2Vec.fX ) > 0 )
+ nDirection = CURVE_LEFT;
+ else
+ nDirection = CURVE_RIGHT;
+ }
+ if ( nDirection != CURVE_STRAIGHTON )
+ {
+ double fWidth;
+ ImplFloatPoint aDestPoint;
+ if ( hypot( aPointR0.fX - aPointA.fX, aPointR0.fY - aPointA.fY ) > hypot( aPointR1.fX - aPointA.fX, aPointR1.fY - aPointA.fY ) )
+ aDestPoint = aPointR0;
+ else
+ aDestPoint = aPointR1;
+
+ UINT16 nFirst = 0;
+ if ( aN1Vec.fY > 0 )
+ {
+ if ( nDirection != CURVE_RIGHT )
+ nFirst++;
+ }
+ else
+ {
+ if ( nDirection == CURVE_RIGHT )
+ nFirst++;
+ }
+ fWidth = hypot( mpFloat0[ 1 + nFirst ].fX - aDestPoint.fX, mpFloat0[ 1 + nFirst ].fY - aDestPoint.fY );
+ fWidth = sqrt( fWidth * fWidth / 2 );
+ if ( fWidth > mfWidthHalf )
+ {
+ // Spitzer Winkel :
+ mnFloat0Points = 6;
+ mpFloat0[ 4 + nFirst ^ 1 ] = aDestPoint;
+ aDestPoint -= aN2Vec;
+ mpFloat0[ 4 + nFirst ] = aDestPoint;
+ mpFloat0[ 1 + nFirst ] += aN1Vec;
+ }
+ else
+ {
+ // Stumpferwinkel : Schnittpunkt wird berechnet
+ mnFloat0Points = 5;
+ ImplFloatPoint aSourcePoint;
+ double fX, fY, fBDest, fBSource;
+ aSourcePoint = mpFloat0[ 1 + nFirst ];
+
+ int nValid = 0;
+
+ if ( ( aN2Vec.fX ) == 0 )
+ {
+ fX = aDestPoint.fX;
+ nValid = 1;
+ }
+ else
+ fBDest = aDestPoint.fY - ( aN2Vec.fY / aN2Vec.fX * aDestPoint.fX );
+
+ if ( ( aN1Vec.fX ) == 0 )
+ {
+ fX = aSourcePoint.fX;
+ nValid = 2;
+ }
+ else
+ fBSource = aSourcePoint.fY - ( aN1Vec.fY / aN1Vec.fX * aSourcePoint.fX );
+
+ if ( !nValid )
+ fX = ( fBSource - fBDest ) / ( aN2Vec.fY / aN2Vec.fX - aN1Vec.fY / aN1Vec.fX );
+ if ( nValid < 2 )
+ fY = aN1Vec.fY / aN1Vec.fX * fX + fBSource;
+ else
+ fY = aN2Vec.fY / aN2Vec.fX * fX + fBDest;
+
+ mpFloat0[ 1 + nFirst ].fX = fX;
+ mpFloat0[ 1 + nFirst ].fY = fY;
+ mpFloat0[ 4 ] = aDestPoint;
+ }
+ }
+ else if ( ( aN1Vec.fX - aN2Vec.fX + aN1Vec.fY - aN2Vec.fY ) != 0 ) // besitzt zweiter Richtungsvektor die gleiche Steigung aber andere
+ bContinues = FALSE; // Richtung, dann wird hinten noch eine halbe Linienbreite angehaengt
+ }
+ if ( !bContinues )
+ {
+ mpFloat0[ 1 ] += aN1Vec;
+ mpFloat0[ 2 ] += aN1Vec;
+ }
+ }
+ else
+ {
+ mnFloat0Points = mnFloat1Points;
+ ImplFloatPoint* pTemp = mpFloat1;
+ mpFloat1 = mpFloat0;
+ mpFloat0 = pTemp;
+ }
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ double fLenghtDone = 0;
+ double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
+
+ double fDistance;
+
+ fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
+ if ( mnFloat0Points == 5 )
+ {
+ double fDist = hypot( mpFloat0[ 2 ].fX - mpFloat0[ 3 ].fX, mpFloat0[ 2 ].fY - mpFloat0[ 3 ].fY );
+ if ( fDist < fDistance )
+ fDistance = fDist;
+ }
+
+ if ( fDistance > fLenght )
+ {
+ fLenghtDone = fLenght;
+
+ ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
+ aNVec *= fLenght;
+ mnFloat1Points = mnFloat0Points;
+ ImplFloatPoint* pTemp = mpFloat1;
+ mpFloat1 = mpFloat0;
+ mpFloat0 = pTemp;
+ mnFloat0Points = 4;
+ mpFloat0[ 0 ] = mpFloat0[ 1 ] = mpFloat1[ 0 ];
+ mpFloat0[ 1 ] += aNVec;
+ mpFloat0[ 2 ] = mpFloat0[ 3 ] = mpFloat1[ 3 ];
+ mpFloat0[ 2 ] += aNVec;
+
+ mpFloat1[ 0 ] = mpFloat0[ 1 ];
+ mpFloat1[ 3 ] = mpFloat0[ 2 ];
+ }
+ else
+ {
+ mnFloat1Points = 0;
+ fLenghtDone = fDistance;
+ }
+
+ if ( mfDashDotLenght > 0.0 )
+ { // Ein Dash oder Dot wurde erzeugt
+ mfDashDotLenght -= fLenghtDone;
+ if ( mfDashDotLenght == 0.0 )
+ { // Komplett erzeugt
+ if ( mnDashCount )
+ mnDashCount--;
+ else
+ mnDotCount--;
+
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ else
+ { // Das erzeugte Polygon muessen wir ignorieren
+ mfDistanceLenght -= fLenghtDone;
+ if ( mfDistanceLenght == 0.0 )
+ mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+ continue;
+ }
+ }
+ maPolygon.SetSize( (UINT16)mnFloat0Points );
+ UINT16 i = 0;
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 0 ].fX ), FRound( mpFloat0[ 0 ].fY ) );
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 1 ].fX ), FRound( mpFloat0[ 1 ].fY ) );
+ if ( mnFloat0Points > 4 )
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 4 ].fX ), FRound( mpFloat0[ 4 ].fY ) );
+ if ( mnFloat0Points > 5 )
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 5 ].fX ), FRound( mpFloat0[ 5 ].fY ) );
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 2 ].fX ), FRound( mpFloat0[ 2 ].fY ) );
+ maPolygon[ i ] = Point( FRound( mpFloat0[ 3 ].fX ), FRound( mpFloat0[ 3 ].fY ) );
+
+ }
+ else
+ {
+ if ( !mnFloat1Points )
+ {
+ mpFloat0[ 0 ] = mpFloatPoint[ mnLinesAvailable-- ];
+ mpFloat0[ 1 ] = mpFloatPoint[ mnLinesAvailable ];
+ }
+ else
+ {
+ mpFloat0[ 0 ] = mpFloat1[ 0 ];
+ mpFloat0[ 1 ] = mpFloat1[ 1 ];
+ }
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ double fLenghtDone = 0;
+ double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
+ double fDistance;
+ fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
+ if ( fDistance > fLenght )
+ {
+ fLenghtDone = fLenght;
+ ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
+ aNVec *= fLenght;
+ mpFloat1[ 1 ] = mpFloat0[ 1 ];
+ mpFloat0[ 1 ] = mpFloat0[ 0 ];
+ mpFloat0[ 1 ] += aNVec;
+ mpFloat1[ 0 ] = mpFloat0[ 1 ];
+ mnFloat1Points = 2;
+ }
+ else
+ {
+ mnFloat1Points = 0;
+ fLenghtDone = fDistance;
+ }
+ if ( mfDashDotLenght > 0.0 )
+ { // Ein Dash oder Dot wurde erzeugt
+ mfDashDotLenght -= fLenghtDone;
+ if ( mfDashDotLenght == 0.0 )
+ { // Komplett erzeugt
+ if ( mnDashCount )
+ mnDashCount--;
+ else
+ mnDotCount--;
+
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ else
+ { // Das erzeugte Polygon muessen wir ignorieren
+ mfDistanceLenght -= fLenghtDone;
+ if ( mfDistanceLenght == 0.0 )
+ mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+ continue;
+ }
+ }
+ maPolygon.SetSize( 2 );
+ maPolygon[ 0 ] = Point( (long)mpFloat0[ 0 ].fX, (long)mpFloat0[ 0 ].fY );
+ maPolygon[ 1 ] = Point( (long)mpFloat0[ 1 ].fX, (long)mpFloat0[ 1 ].fY );
+ }
+ return &maPolygon;
+ }
+ return NULL;
+};
diff --git a/vcl/source/gdi/implncvt.hxx b/vcl/source/gdi/implncvt.hxx
new file mode 100644
index 000000000000..5b4aa5bcee6e
--- /dev/null
+++ b/vcl/source/gdi/implncvt.hxx
@@ -0,0 +1,113 @@
+/*************************************************************************
+ *
+ * $RCSfile: implncvt.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_LINECONV_HXX
+#define _SV_LINECONV_HXX
+
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+
+// --------------------
+// - ImplLineConverter
+// --------------------
+
+struct ImplFloatPoint;
+
+class ImplLineConverter
+{
+ BOOL mbClosed;
+ BOOL mbRefPoint;
+ INT32 mnRefDistance;
+
+ double mfWidthHalf;
+ LineInfo maLineInfo;
+
+ double mfDashDotLenght;
+ double mfDistanceLenght;
+
+ UINT32 mnDashCount;
+ UINT32 mnDotCount;
+
+ Polygon maPolygon;
+ UINT32 mnFloat0Points;
+ ImplFloatPoint* mpFloat0;
+ UINT32 mnFloat1Points;
+ ImplFloatPoint* mpFloat1;
+
+ UINT32 mnLinesAvailable;
+ UINT32 mnLines;
+
+ ImplFloatPoint* mpFloatPoint;
+
+ public:
+
+ ImplLineConverter( const Polygon& rPoly, const LineInfo& rLineInfo, const Point* pRefPoint );
+ ~ImplLineConverter();
+
+ const Polygon* ImplGetFirst();
+ const Polygon* ImplGetNext();
+};
+
+#endif
diff --git a/vcl/source/gdi/impprn.cxx b/vcl/source/gdi/impprn.cxx
new file mode 100644
index 000000000000..ce41b8cce763
--- /dev/null
+++ b/vcl/source/gdi/impprn.cxx
@@ -0,0 +1,256 @@
+/*************************************************************************
+ *
+ * $RCSfile: impprn.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef REMOTE_APPSERVER
+
+#define _SV_IMPPRN_CXX
+#define _SPOOLPRINTER_EXT
+
+#ifndef _QUEUE_HXX
+#include <tools/queue.hxx>
+#endif
+
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_IMPPRN_HXX
+#include <impprn.hxx>
+#endif
+
+// =======================================================================
+
+struct QueuePage
+{
+ GDIMetaFile* mpMtf;
+ JobSetup* mpSetup;
+ USHORT mnPage;
+ BOOL mbEndJob;
+
+ QueuePage() { mpMtf = NULL; mpSetup = NULL; }
+ ~QueuePage() { delete mpMtf; if ( mpSetup ) delete mpSetup; }
+};
+
+// =======================================================================
+
+ImplQPrinter::ImplQPrinter( Printer* pParent ) :
+ Printer( pParent->GetName() )
+{
+ SetSelfAsQueuePrinter( TRUE );
+ SetPrinterProps( pParent );
+ SetPageQueueSize( 0 );
+ mpParent = pParent;
+ mnCopyCount = pParent->mnCopyCount;
+ mbCollateCopy = pParent->mbCollateCopy;
+ mpQueue = new Queue( mpParent->GetPageQueueSize() );
+ mbAborted = FALSE;
+ mbUserCopy = FALSE;
+ mbDestroyAllowed= TRUE;
+ mbDestroyed = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplQPrinter::~ImplQPrinter()
+{
+ QueuePage* pQueuePage = (QueuePage*)mpQueue->Get();
+ while ( pQueuePage )
+ {
+ delete pQueuePage;
+ pQueuePage = (QueuePage*)mpQueue->Get();
+ }
+
+ delete mpQueue;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplQPrinter::Destroy()
+{
+ if( mbDestroyAllowed )
+ delete this;
+ else
+ mbDestroyed = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplQPrinter, ImplPrintHdl, Timer*, EMPTYARG )
+{
+ // Ist Drucken abgebrochen wurden?
+ if ( !IsPrinting() )
+ return 0;
+
+ // Nur drucken, wenn genuegend Seiten im Cache stehen
+ if ( mpParent->IsJobActive() && (mpQueue->Count() < (ULONG)mpParent->GetPageQueueSize()) )
+ return 0;
+
+ // Druck-Job zuende?
+ QueuePage* pActPage = (QueuePage*) mpQueue->Get();
+
+ if ( pActPage->mbEndJob )
+ {
+ maTimer.Stop();
+ delete pActPage;
+ EndJob();
+ mpParent->ImplEndPrint();
+ }
+ else
+ {
+ USHORT nCopyCount = 1;
+ GDIMetaFile aMtf;
+
+ mbDestroyAllowed = FALSE;
+ GetPreparedMetaFile( *pActPage->mpMtf, aMtf );
+
+ if ( mbUserCopy && !mbCollateCopy )
+ nCopyCount = mnCopyCount;
+
+ for ( USHORT i = 0; i < nCopyCount; i++ )
+ {
+ ULONG nActionPos = 0UL;
+
+ if ( pActPage->mpSetup )
+ {
+ SetJobSetup( *pActPage->mpSetup );
+ if ( mbAborted )
+ break;
+ }
+
+ StartPage();
+
+ if ( mbAborted )
+ break;
+
+ for( MetaAction* pAct = aMtf.FirstAction(); pAct; pAct = aMtf.NextAction() )
+ {
+ pAct->Execute( this );
+ Application::Reschedule();
+
+ if( mbAborted )
+ break;
+ }
+
+ if( !mbAborted )
+ EndPage();
+ else
+ break;
+ }
+
+ delete pActPage;
+ mbDestroyAllowed = TRUE;
+
+ if( mbDestroyed )
+ Destroy();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::StartQueuePrint()
+{
+ maTimer.SetTimeout( 50 );
+ maTimer.SetTimeoutHdl( LINK( this, ImplQPrinter, ImplPrintHdl ) );
+ maTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::EndQueuePrint()
+{
+ QueuePage* pQueuePage = new QueuePage;
+ pQueuePage->mbEndJob = TRUE;
+ mpQueue->Put( pQueuePage );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::AbortQueuePrint()
+{
+ maTimer.Stop();
+ mbAborted = TRUE;
+ AbortJob();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::AddQueuePage( GDIMetaFile* pPage, USHORT nPage, BOOL bNewJobSetup )
+{
+ QueuePage* pQueuePage = new QueuePage;
+ pQueuePage->mpMtf = pPage;
+ pQueuePage->mnPage = nPage;
+ pQueuePage->mbEndJob = FALSE;
+ if ( bNewJobSetup )
+ pQueuePage->mpSetup = new JobSetup( mpParent->GetJobSetup() );
+ mpQueue->Put( pQueuePage );
+}
+
+#endif
diff --git a/vcl/source/gdi/impvect.cxx b/vcl/source/gdi/impvect.cxx
new file mode 100644
index 000000000000..2a3e27ebf2c5
--- /dev/null
+++ b/vcl/source/gdi/impvect.cxx
@@ -0,0 +1,1267 @@
+/*************************************************************************
+ *
+ * $RCSfile: impvect.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPVECT_CXX
+
+#include <stdlib.h>
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_VECTORIZ_HXX
+#include <impvect.hxx>
+#endif
+
+// !!! ggf. einkommentieren, um Bitmaps zu erzeugen (nur, wenn File mit Debug uebersetzt wurde)
+// #define DEBUG_BMPOUTPUT
+
+#if defined DEBUG && defined DEBUG_BMPOUTPUT
+#define DBG_BMP 1
+#else
+#undef DBG_BMP
+#endif
+
+#ifdef DBG_BMP
+#include <tools/stream.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define VECT_POLY_MAX 8192
+
+// -----------------------------------------------------------------------------
+
+#define VECT_FREE_INDEX 0
+#define VECT_CONT_INDEX 1
+#define VECT_DONE_INDEX 2
+
+// -----------------------------------------------------------------------------
+
+#define VECT_POLY_INLINE_INNER 1UL
+#define VECT_POLY_INLINE_OUTER 2UL
+#define VECT_POLY_OUTLINE_INNER 4UL
+#define VECT_POLY_OUTLINE_OUTER 8UL
+
+// -----------------------------------------------------------------------------
+
+#define VECT_MAP( _def_pIn, _def_pOut, _def_nVal ) _def_pOut[_def_nVal]=(_def_pIn[_def_nVal]=((_def_nVal)*4L)+1L)+5L;
+#define BACK_MAP( _def_nVal ) ((((_def_nVal)+2)>>2)-1)
+#define VECT_PROGRESS( _def_pProgress, _def_nVal ) if(_def_pProgress&&_def_pProgress->IsSet())(_def_pProgress->Call((void*)_def_nVal));
+
+// -----------
+// - statics -
+// -----------
+
+struct ChainMove { long nDX; long nDY; };
+
+static ChainMove aImplMove[ 8 ] = {
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, -1L },
+ { -1, -1L },
+ { -1L, 1L },
+ { 1L, 1L }
+ };
+
+static ChainMove aImplMoveInner[ 8 ] = {
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L }
+ };
+
+static ChainMove aImplMoveOuter[ 8 ] = {
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L }
+ };
+
+// ----------------
+// - ImplColorSet -
+// ----------------
+
+struct ImplColorSet
+{
+ BitmapColor maColor;
+ USHORT mnIndex;
+ BOOL mbSet;
+
+ BOOL operator<( const ImplColorSet& rSet ) const;
+ BOOL operator>( const ImplColorSet& rSet ) const;
+};
+
+// ----------------------------------------------------------------------------
+
+inline BOOL ImplColorSet::operator<( const ImplColorSet& rSet ) const
+{
+ return( mbSet && ( !rSet.mbSet || ( maColor.GetLuminance() > rSet.maColor.GetLuminance() ) ) );
+}
+
+// ----------------------------------------------------------------------------
+
+inline BOOL ImplColorSet::operator>( const ImplColorSet& rSet ) const
+{
+ return( !mbSet || ( rSet.mbSet && maColor.GetLuminance() < rSet.maColor.GetLuminance() ) );
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" int __LOADONCALLAPI ImplColorSetCmpFnc( const void* p1, const void* p2 )
+{
+ ImplColorSet* pSet1 = (ImplColorSet*) p1;
+ ImplColorSet* pSet2 = (ImplColorSet*) p2;
+ int nRet;
+
+ if( pSet1->mbSet && pSet2->mbSet )
+ {
+ const BYTE cLum1 = pSet1->maColor.GetLuminance();
+ const BYTE cLum2 = pSet2->maColor.GetLuminance();
+ nRet = ( ( cLum1 > cLum2 ) ? -1 : ( ( cLum1 == cLum2 ) ? 0 : 1 ) );
+ }
+ else if( pSet1->mbSet )
+ nRet = -1;
+ else if( pSet2->mbSet )
+ nRet = 1;
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+// ------------------
+// - ImplPointArray -
+// ------------------
+
+#ifdef WIN
+typedef Point* huge HPPoint;
+#else
+typedef Point* HPPoint;
+#endif
+
+class ImplPointArray
+{
+ HPPoint mpArray;
+ ULONG mnSize;
+ ULONG mnRealSize;
+
+public:
+
+ ImplPointArray();
+ ~ImplPointArray();
+
+ void ImplSetSize( ULONG nSize );
+
+ ULONG ImplGetRealSize() const { return mnRealSize; }
+ void ImplSetRealSize( ULONG nRealSize ) { mnRealSize = nRealSize; }
+
+ inline Point& operator[]( ULONG nPos );
+ inline const Point& operator[]( ULONG nPos ) const;
+
+ void ImplCreatePoly( Polygon& rPoly ) const;
+};
+
+// -----------------------------------------------------------------------------
+
+ImplPointArray::ImplPointArray() :
+ mnSize ( 0UL ),
+ mnRealSize ( 0UL ),
+ mpArray ( NULL )
+
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImplPointArray::~ImplPointArray()
+{
+ if( mpArray )
+ SvMemFree( mpArray );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplPointArray::ImplSetSize( ULONG nSize )
+{
+ const ULONG nTotal = nSize * sizeof( Point );
+
+ mnSize = nSize;
+ mnRealSize = 0UL;
+
+ if( mpArray )
+ SvMemFree( mpArray );
+
+ mpArray = (HPPoint) SvMemAlloc( nTotal );
+ HMEMSET( (HPBYTE) mpArray, 0, nTotal );
+}
+
+// -----------------------------------------------------------------------------
+
+inline Point& ImplPointArray::operator[]( ULONG nPos )
+{
+ DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
+ return mpArray[ nPos ];
+}
+
+// -----------------------------------------------------------------------------
+
+inline const Point& ImplPointArray::operator[]( ULONG nPos ) const
+{
+ DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
+ return mpArray[ nPos ];
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplPointArray::ImplCreatePoly( Polygon& rPoly ) const
+{
+ rPoly.SetSize( (USHORT) mnRealSize );
+ HMEMCPY( rPoly.ImplGetPointAry(), mpArray, mnRealSize * sizeof( Point ) );
+}
+
+// ---------------
+// - ImplVectMap -
+// ---------------
+
+class ImplVectMap
+{
+private:
+
+ Scanline mpBuf;
+ Scanline* mpScan;
+ long mnWidth;
+ long mnHeight;
+
+ ImplVectMap() {};
+
+public:
+
+ ImplVectMap( long nWidth, long nHeight );
+ ~ImplVectMap();
+
+ inline long Width() const { return mnWidth; }
+ inline long Height() const { return mnHeight; }
+
+ inline void Set( long nY, long nX, BYTE cVal );
+ inline BYTE Get( long nY, long nX ) const;
+
+ inline BOOL IsFree( long nY, long nX ) const;
+ inline BOOL IsCont( long nY, long nX ) const;
+ inline BOOL IsDone( long nY, long nX ) const;
+
+#ifdef DBG_BMP
+ Bitmap GetBitmap() const;
+#endif // DBG_BMP
+};
+
+// -----------------------------------------------------------------------------
+
+ImplVectMap::ImplVectMap( long nWidth, long nHeight ) :
+ mnWidth ( nWidth ),
+ mnHeight( nHeight )
+{
+ const long nWidthAl = ( nWidth >> 2L ) + 1L;
+ const long nSize = nWidthAl * nHeight;
+ Scanline pTmp = mpBuf = (Scanline) SvMemAlloc( nSize );
+
+ HMEMSET( mpBuf, 0, nSize );
+ mpScan = (Scanline*) SvMemAlloc( nHeight * sizeof( Scanline ) );
+
+ for( long nY = 0L; nY < nHeight; pTmp += nWidthAl )
+ mpScan[ nY++ ] = pTmp;
+}
+
+// -----------------------------------------------------------------------------
+
+
+ImplVectMap::~ImplVectMap()
+{
+ SvMemFree( mpBuf );
+ SvMemFree( mpScan );
+}
+
+// -----------------------------------------------------------------------------
+
+inline void ImplVectMap::Set( long nY, long nX, BYTE cVal )
+{
+ const BYTE cShift = 6 - ( ( nX & 3 ) << 1 );
+ ( ( mpScan[ nY ][ nX >> 2 ] ) &= ~( 3 << cShift ) ) |= ( cVal << cShift );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BYTE ImplVectMap::Get( long nY, long nX ) const
+{
+ return( ( ( mpScan[ nY ][ nX >> 2 ] ) >> ( 6 - ( ( nX & 3 ) << 1 ) ) ) & 3 );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsFree( long nY, long nX ) const
+{
+ return( VECT_FREE_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsCont( long nY, long nX ) const
+{
+ return( VECT_CONT_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsDone( long nY, long nX ) const
+{
+ return( VECT_DONE_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+#ifdef DBG_BMP
+Bitmap ImplVectMap::GetBitmap() const
+{
+ Bitmap aBmp( Size( mnWidth, mnHeight ), 4 );
+ BitmapWriteAccess* pAcc = aBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ for( long nY = 0L; nY < mnHeight; nY++ )
+ {
+ for( long nX = 0L; nX < mnWidth; nX++ )
+ {
+ switch( Get( nY, nX ) )
+ {
+ case( VECT_FREE_INDEX ): pAcc->SetPixel( nY, nX, 15 ); break;
+ case( VECT_CONT_INDEX ): pAcc->SetPixel( nY, nX, 0 ); break;
+ case( VECT_DONE_INDEX ): pAcc->SetPixel( nY, nX, 2); break;
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ }
+
+ return aBmp;
+}
+#endif // DBG_BMP
+
+// -------------
+// - ImplChain -
+// -------------
+
+class ImplChain
+{
+private:
+
+ Polygon maPoly;
+ Point maStartPt;
+ ULONG mnArraySize;
+ ULONG mnCount;
+ long mnResize;
+ BYTE* mpCodes;
+
+ void ImplGetSpace();
+
+ void ImplCreate();
+ void ImplCreateInner();
+ void ImplCreateOuter();
+ void ImplPostProcess( const ImplPointArray& rArr );
+
+public:
+
+ ImplChain( ULONG nInitCount = 1024UL, long nResize = -1L );
+ ~ImplChain();
+
+ void ImplBeginAdd( const Point& rStartPt );
+ inline void ImplAdd( BYTE nCode );
+ void ImplEndAdd( ULONG nTypeFlag );
+
+ const Polygon& ImplGetPoly() { return maPoly; }
+};
+
+// -----------------------------------------------------------------------------
+
+ImplChain::ImplChain( ULONG nInitCount, long nResize ) :
+ mnCount ( 0UL ),
+ mnArraySize ( nInitCount ),
+ mnResize ( nResize )
+{
+ DBG_ASSERT( nInitCount && nResize, "ImplChain::ImplChain(): invalid parameters!" );
+ mpCodes = new BYTE[ mnArraySize ];
+}
+
+// -----------------------------------------------------------------------------
+
+ImplChain::~ImplChain()
+{
+ delete[] mpCodes;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplGetSpace()
+{
+ const ULONG nOldArraySize = mnArraySize;
+ BYTE* pNewCodes;
+
+ mnArraySize = ( mnResize < 0L ) ? ( mnArraySize << 1UL ) : ( mnArraySize + (ULONG) mnResize );
+ pNewCodes = new BYTE[ mnArraySize ];
+ HMEMCPY( pNewCodes, mpCodes, nOldArraySize );
+ delete[] mpCodes;
+ mpCodes = pNewCodes;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplBeginAdd( const Point& rStartPt )
+{
+ maPoly = Polygon();
+ maStartPt = rStartPt;
+ mnCount = 0UL;
+}
+
+// -----------------------------------------------------------------------------
+
+inline void ImplChain::ImplAdd( BYTE nCode )
+{
+ if( mnCount == mnArraySize )
+ ImplGetSpace();
+
+ mpCodes[ mnCount++ ] = nCode;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplEndAdd( ULONG nFlag )
+{
+ if( mnCount )
+ {
+ ImplPointArray aArr;
+
+ if( nFlag & VECT_POLY_INLINE_INNER )
+ {
+ long nFirstX, nFirstY;
+ long nLastX, nLastY;
+
+ nFirstX = nLastX = maStartPt.X();
+ nFirstY = nLastY = maStartPt.Y();
+ aArr.ImplSetSize( mnCount << 1 );
+
+ USHORT i, nPolyPos;
+ for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
+ {
+ const BYTE cMove = mpCodes[ i ];
+ const BYTE cNextMove = mpCodes[ i + 1 ];
+ const ChainMove& rMove = aImplMove[ cMove ];
+ const ChainMove& rMoveInner = aImplMoveInner[ cMove ];
+ Point& rPt = aArr[ nPolyPos ];
+ BOOL bDone = TRUE;
+
+ nLastX += rMove.nDX;
+ nLastY += rMove.nDY;
+
+ if( cMove < 4 )
+ {
+ if( ( cMove == 0 && cNextMove == 3 ) ||
+ ( cMove == 3 && cNextMove == 2 ) ||
+ ( cMove == 2 && cNextMove == 1 ) ||
+ ( cMove == 1 && cNextMove == 0 ) )
+ {
+ }
+ else if( cMove == 2 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 3 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 0 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 1 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+ }
+ else
+ bDone = FALSE;
+ }
+ else if( cMove == 7 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 4 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else
+ bDone = FALSE;
+
+ if( !bDone )
+ {
+ aArr[ nPolyPos ].X() = nLastX + rMoveInner.nDX;
+ aArr[ nPolyPos++ ].Y() = nLastY + rMoveInner.nDY;
+ }
+ }
+
+ aArr[ nPolyPos ].X() = nFirstX + 1L;
+ aArr[ nPolyPos++ ].Y() = nFirstY + 1L;
+ aArr.ImplSetRealSize( nPolyPos );
+ }
+ else if( nFlag & VECT_POLY_INLINE_OUTER )
+ {
+ long nFirstX, nFirstY;
+ long nLastX, nLastY;
+
+ nFirstX = nLastX = maStartPt.X();
+ nFirstY = nLastY = maStartPt.Y();
+ aArr.ImplSetSize( mnCount << 1 );
+
+ USHORT i, nPolyPos;
+ for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
+ {
+ const BYTE cMove = mpCodes[ i ];
+ const BYTE cNextMove = mpCodes[ i + 1 ];
+ const ChainMove& rMove = aImplMove[ cMove ];
+ const ChainMove& rMoveOuter = aImplMoveOuter[ cMove ];
+ Point& rPt = aArr[ nPolyPos ];
+ BOOL bDone = TRUE;
+
+ nLastX += rMove.nDX;
+ nLastY += rMove.nDY;
+
+ if( cMove < 4 )
+ {
+ if( ( cMove == 0 && cNextMove == 1 ) ||
+ ( cMove == 1 && cNextMove == 2 ) ||
+ ( cMove == 2 && cNextMove == 3 ) ||
+ ( cMove == 3 && cNextMove == 0 ) )
+ {
+ }
+ else if( cMove == 0 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 3 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 2 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 1 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+ }
+ else
+ bDone = FALSE;
+ }
+ else if( cMove == 7 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 6 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else
+ bDone = FALSE;
+
+ if( !bDone )
+ {
+ aArr[ nPolyPos ].X() = nLastX + rMoveOuter.nDX;
+ aArr[ nPolyPos++ ].Y() = nLastY + rMoveOuter.nDY;
+ }
+ }
+
+ aArr[ nPolyPos ].X() = nFirstX - 1L;
+ aArr[ nPolyPos++ ].Y() = nFirstY - 1L;
+ aArr.ImplSetRealSize( nPolyPos );
+ }
+ else
+ {
+ long nLastX = maStartPt.X(), nLastY = maStartPt.Y();
+
+ aArr.ImplSetSize( mnCount + 1 );
+ aArr[ 0 ] = Point( nLastX, nLastY );
+
+ for( ULONG i = 0; i < mnCount; )
+ {
+ const ChainMove& rMove = aImplMove[ mpCodes[ i ] ];
+ aArr[ ++i ] = Point( nLastX += rMove.nDX, nLastY += rMove.nDY );
+ }
+
+ aArr.ImplSetRealSize( mnCount + 1 );
+ }
+
+ ImplPostProcess( aArr );
+ }
+ else
+ maPoly.SetSize( 0 );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplPostProcess( const ImplPointArray& rArr )
+{
+ ImplPointArray aNewArr1;
+ ImplPointArray aNewArr2;
+ Point* pLast;
+ Point* pLeast;
+ ULONG nNewPos;
+ ULONG nCount = rArr.ImplGetRealSize();
+ ULONG n;
+
+ // pass 1
+ aNewArr1.ImplSetSize( nCount );
+ pLast = &( aNewArr1[ 0 ] );
+ pLast->X() = BACK_MAP( rArr[ 0 ].X() );
+ pLast->Y() = BACK_MAP( rArr[ 0 ].Y() );
+
+ for( n = nNewPos = 1; n < nCount; )
+ {
+ const Point& rPt = rArr[ n++ ];
+ const long nX = BACK_MAP( rPt.X() );
+ const long nY = BACK_MAP( rPt.Y() );
+
+ if( nX != pLast->X() || nY != pLast->Y() )
+ {
+ pLast = pLeast = &( aNewArr1[ nNewPos++ ] );
+ pLeast->X() = nX;
+ pLeast->Y() = nY;
+ }
+ }
+
+ aNewArr1.ImplSetRealSize( nCount = nNewPos );
+
+ // pass 2
+ aNewArr2.ImplSetSize( nCount );
+ pLast = &( aNewArr2[ 0 ] );
+ *pLast = aNewArr1[ 0 ];
+
+ for( n = nNewPos = 1; n < nCount; )
+ {
+ pLeast = &( aNewArr1[ n++ ] );
+
+ if( pLeast->X() == pLast->X() )
+ {
+ while( n < nCount && aNewArr1[ n ].X() == pLast->X() )
+ pLeast = &( aNewArr1[ n++ ] );
+ }
+ else if( pLeast->Y() == pLast->Y() )
+ {
+ while( n < nCount && aNewArr1[ n ].Y() == pLast->Y() )
+ pLeast = &( aNewArr1[ n++ ] );
+ }
+
+ aNewArr2[ nNewPos++ ] = *( pLast = pLeast );
+ }
+
+ aNewArr2.ImplSetRealSize( nNewPos );
+ aNewArr2.ImplCreatePoly( maPoly );
+}
+
+// ------------------
+// - ImplVectorizer -
+// ------------------
+
+ImplVectorizer::ImplVectorizer()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImplVectorizer::~ImplVectorizer()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf,
+ BYTE cReduce, ULONG nFlags, const Link* pProgress )
+{
+ BOOL bRet = FALSE;
+
+ VECT_PROGRESS( pProgress, 0 );
+
+ Bitmap* pBmp = new Bitmap( rColorBmp );
+ BitmapReadAccess* pRAcc = pBmp->AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ PolyPolygon aPolyPoly;
+ double fPercent = 0.0;
+ double fPercentStep_2 = 0.0;
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+ const USHORT nColorCount = pRAcc->GetPaletteEntryCount();
+ USHORT n;
+ ImplColorSet* pColorSet = (ImplColorSet*) new BYTE[ 256 * sizeof( ImplColorSet ) ];
+
+ memset( pColorSet, 0, 256 * sizeof( ImplColorSet ) );
+ rMtf.Clear();
+
+ // get used palette colors and sort them from light to dark colors
+ for( n = 0; n < nColorCount; n++ )
+ {
+ pColorSet[ n ].mnIndex = n;
+ pColorSet[ n ].maColor = pRAcc->GetPaletteColor( n );
+ }
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pColorSet[ pRAcc->GetPixel( nY, nX ).GetIndex() ].mbSet = 1;
+
+ qsort( pColorSet, 256, sizeof( ImplColorSet ), ImplColorSetCmpFnc );
+
+ for( n = 0; n < 256; n++ )
+ if( !pColorSet[ n ].mbSet )
+ break;
+
+ if( n )
+ fPercentStep_2 = 45.0 / n;
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += 10.0 ) );
+
+ for( USHORT i = 0; i < n; i++ )
+ {
+ const BitmapColor aBmpCol( pRAcc->GetPaletteColor( pColorSet[ i ].mnIndex ) );
+ const Color aFindColor( aBmpCol.GetRed(), aBmpCol.GetGreen(), aBmpCol.GetBlue() );
+ const BYTE cLum = aFindColor.GetLuminance();
+ ImplVectMap* pMap = ImplExpand( pRAcc, aFindColor );
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
+
+ if( pMap )
+ {
+ aPolyPoly.Clear();
+ ImplCalculate( pMap, aPolyPoly, cReduce, nFlags );
+ delete pMap;
+
+ if( aPolyPoly.Count() )
+ {
+ ImplLimitPolyPoly( aPolyPoly );
+
+ if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
+ aPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
+
+ if( aPolyPoly.Count() )
+ {
+ rMtf.AddAction( new MetaLineColorAction( aFindColor, TRUE ) );
+ rMtf.AddAction( new MetaFillColorAction( aFindColor, TRUE ) );
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ }
+ }
+ }
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
+ }
+
+ delete[] (BYTE*) pColorSet;
+
+ if( rMtf.GetActionCount() )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ VirtualDevice aVDev;
+ const Size aLogSize1( aVDev.PixelToLogic( Size( 1, 1 ), aMap ) );
+
+ rMtf.SetPrefMapMode( aMap );
+ rMtf.SetPrefSize( Size( nWidth + 2, nHeight + 2 ) );
+ rMtf.Move( 1, 1 );
+ rMtf.Scale( aLogSize1.Width(), aLogSize1.Height() );
+ bRet = TRUE;
+ }
+ }
+
+ pBmp->ReleaseAccess( pRAcc );
+ delete pBmp;
+ VECT_PROGRESS( pProgress, 100 );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplVectorize( const Bitmap& rMonoBmp,
+ PolyPolygon& rPolyPoly,
+ ULONG nFlags, const Link* pProgress )
+{
+ Bitmap* pBmp = new Bitmap( rMonoBmp );
+ BitmapReadAccess* pRAcc;
+ ImplVectMap* pMap;
+ BOOL bRet = FALSE;
+
+ VECT_PROGRESS( pProgress, 10 );
+
+ if( pBmp->GetBitCount() > 1 )
+ pBmp->Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ VECT_PROGRESS( pProgress, 30 );
+
+ pRAcc = pBmp->AcquireReadAccess();
+ pMap = ImplExpand( pRAcc, COL_BLACK );
+ pBmp->ReleaseAccess( pRAcc );
+ delete pBmp;
+
+ VECT_PROGRESS( pProgress, 60 );
+
+ if( pMap )
+ {
+ rPolyPoly.Clear();
+ ImplCalculate( pMap, rPolyPoly, 0, nFlags );
+ delete pMap;
+ ImplLimitPolyPoly( rPolyPoly );
+
+ if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
+ rPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
+
+ bRet = TRUE;
+ }
+
+ VECT_PROGRESS( pProgress, 100 );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplVectorizer::ImplLimitPolyPoly( PolyPolygon& rPolyPoly )
+{
+ if( rPolyPoly.Count() > VECT_POLY_MAX )
+ {
+ PolyPolygon aNewPolyPoly;
+ long nReduce = 0;
+ USHORT nNewCount;
+
+ do
+ {
+ aNewPolyPoly.Clear();
+ nReduce++;
+
+ for( USHORT i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ const Rectangle aBound( rPolyPoly[ i ].GetBoundRect() );
+
+ if( aBound.GetWidth() > nReduce && aBound.GetHeight() > nReduce )
+ {
+ if( rPolyPoly[ i ].GetSize() )
+ aNewPolyPoly.Insert( rPolyPoly[ i ] );
+ }
+ }
+
+ nNewCount = aNewPolyPoly.Count();
+ }
+ while( nNewCount > VECT_POLY_MAX );
+
+ rPolyPoly = aNewPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+ImplVectMap* ImplVectorizer::ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor )
+{
+ ImplVectMap* pMap = NULL;
+
+ if( pRAcc && pRAcc->Width() && pRAcc->Height() )
+ {
+ const long nOldWidth = pRAcc->Width();
+ const long nOldHeight = pRAcc->Height();
+ const long nNewWidth = ( nOldWidth << 2L ) + 4L;
+ const long nNewHeight = ( nOldHeight << 2L ) + 4L;
+ const BitmapColor aTest( pRAcc->GetBestMatchingColor( rColor ) );
+ long* pMapIn = new long[ Max( nOldWidth, nOldHeight ) ];
+ long* pMapOut = new long[ Max( nOldWidth, nOldHeight ) ];
+ long nX, nY, nTmpX, nTmpY;
+
+ pMap = new ImplVectMap( nNewWidth, nNewHeight );
+
+ for( nX = 0L; nX < nOldWidth; nX++ )
+ VECT_MAP( pMapIn, pMapOut, nX );
+
+ for( nY = 0L, nTmpY = 5L; nY < nOldHeight; nY++, nTmpY += 4L )
+ {
+ for( nX = 0L; nX < nOldWidth; )
+ {
+ if( pRAcc->GetPixel( nY, nX ) == aTest )
+ {
+ nTmpX = pMapIn[ nX++ ];
+ nTmpY -= 3L;
+
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+
+ while( nX < nOldWidth && pRAcc->GetPixel( nY, nX ) == aTest )
+ nX++;
+
+ nTmpX = pMapOut[ nX - 1L ];
+ nTmpY -= 3L;
+
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+ }
+ else
+ nX++;
+ }
+ }
+
+ for( nY = 0L; nY < nOldHeight; nY++ )
+ VECT_MAP( pMapIn, pMapOut, nY );
+
+ for( nX = 0L, nTmpX = 5L; nX < nOldWidth; nX++, nTmpX += 4L )
+ {
+ for( nY = 0L; nY < nOldHeight; )
+ {
+ if( pRAcc->GetPixel( nY, nX ) == aTest )
+ {
+ nTmpX -= 3L;
+ nTmpY = pMapIn[ nY++ ];
+
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+
+ while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest )
+ nY++;
+
+ nTmpX -= 3L;
+ nTmpY = pMapOut[ nY - 1L ];
+
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+ }
+ else
+ nY++;
+ }
+ }
+
+ // cleanup
+ delete[] pMapIn;
+ delete[] pMapOut;
+ }
+
+ return pMap;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplVectorizer::ImplCalculate( ImplVectMap* pMap, PolyPolygon& rPolyPoly, BYTE cReduce, ULONG nFlags )
+{
+ const long nWidth = pMap->Width(), nHeight= pMap->Height();
+
+#ifdef DBG_BMP
+ if( pMap )
+ {
+ SvFileStream aOStm( "d:\\cont.bmp", STREAM_WRITE | STREAM_TRUNC );
+ aOStm << pMap->GetBitmap();
+ }
+#endif // DBG_BMP
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ long nX = 0L;
+ BOOL bInner = TRUE;
+
+ while( nX < nWidth )
+ {
+ // skip free
+ while( ( nX < nWidth ) && pMap->IsFree( nY, nX ) )
+ nX++;
+
+ if( nX == nWidth )
+ break;
+
+ if( pMap->IsCont( nY, nX ) )
+ {
+ // new contour
+ ImplChain aChain;
+ const Point aStartPt( nX++, nY );
+
+ // get chain code
+ aChain.ImplBeginAdd( aStartPt );
+ ImplGetChain( pMap, aStartPt, aChain );
+
+ if( nFlags & BMP_VECTORIZE_INNER )
+ aChain.ImplEndAdd( bInner ? VECT_POLY_INLINE_INNER : VECT_POLY_INLINE_OUTER );
+ else
+ aChain.ImplEndAdd( bInner ? VECT_POLY_OUTLINE_INNER : VECT_POLY_OUTLINE_OUTER );
+
+ const Polygon& rPoly = aChain.ImplGetPoly();
+
+ if( rPoly.GetSize() > 2 )
+ {
+ if( cReduce )
+ {
+ const Rectangle aBound( rPoly.GetBoundRect() );
+
+ if( aBound.GetWidth() > cReduce && aBound.GetHeight() > cReduce )
+ rPolyPoly.Insert( rPoly );
+ }
+ else
+ rPolyPoly.Insert( rPoly );
+ }
+
+ // skip rest of detected contour
+ while( pMap->IsCont( nY, nX ) )
+ nX++;
+ }
+ else
+ {
+ // process done segment
+ const long nStartSegX = nX++;
+
+ while( pMap->IsDone( nY, nX ) )
+ nX++;
+
+ if( ( ( nX - nStartSegX ) == 1L ) || ( ImplIsUp( pMap, nY, nStartSegX ) != ImplIsUp( pMap, nY, nX - 1L ) ) )
+ bInner = !bInner;
+ }
+ }
+ }
+
+#ifdef DBG_BMP
+ if( pMap )
+ {
+ SvFileStream aOStm( "d:\\vect.bmp", STREAM_WRITE | STREAM_TRUNC );
+ aOStm << pMap->GetBitmap();
+ }
+#endif // DBG_BMP
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain )
+{
+ long nActX = rStartPt.X();
+ long nActY = rStartPt.Y();
+ long nTryX;
+ long nTryY;
+ ULONG nFound;
+ ULONG nLastDir = 0UL;
+ ULONG nDir;
+
+ do
+ {
+ nFound = 0UL;
+
+ // first try last direction
+ nTryX = nActX + aImplMove[ nLastDir ].nDX;
+ nTryY = nActY + aImplMove[ nLastDir ].nDY;
+
+ if( pMap->IsCont( nTryY, nTryX ) )
+ {
+ rChain.ImplAdd( (BYTE) nLastDir );
+ pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
+ nFound = 1UL;
+ }
+ else
+ {
+ // try other directions
+ for( nDir = 0UL; nDir < 8UL; nDir++ )
+ {
+ // we already tried nLastDir
+ if( nDir != nLastDir )
+ {
+ nTryX = nActX + aImplMove[ nDir ].nDX;
+ nTryY = nActY + aImplMove[ nDir ].nDY;
+
+ if( pMap->IsCont( nTryY, nTryX ) )
+ {
+ rChain.ImplAdd( (BYTE) nDir );
+ pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
+ nFound = 1UL;
+ nLastDir = nDir;
+ break;
+ }
+ }
+ }
+ }
+ }
+ while( nFound );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplIsUp( ImplVectMap* pMap, long nY, long nX ) const
+{
+ if( pMap->IsDone( nY - 1L, nX ) )
+ return TRUE;
+ else if( pMap->IsDone( nY + 1L, nX ) )
+ return FALSE;
+ else if( pMap->IsDone( nY - 1L, nX - 1L ) || pMap->IsDone( nY - 1L, nX + 1L ) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/gdi/impvect.hxx b/vcl/source/gdi/impvect.hxx
new file mode 100644
index 000000000000..34750c220109
--- /dev/null
+++ b/vcl/source/gdi/impvect.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * $RCSfile: impvect.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_IMPVECT_HXX
+#define _SV_IMPVECT_HXX
+
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+
+// --------------
+// - Vectorizer -
+// --------------
+
+class BitmapReadAccess;
+class ImplChain;
+class ImplVectMap;
+
+class ImplVectorizer
+{
+private:
+
+ ImplVectMap* ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor );
+ void ImplCalculate( ImplVectMap* pMap, PolyPolygon& rPolyPoly, BYTE cReduce, ULONG nFlags );
+ BOOL ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain );
+ BOOL ImplIsUp( ImplVectMap* pMap, long nY, long nX ) const;
+ void ImplLimitPolyPoly( PolyPolygon& rPolyPoly );
+
+public:
+
+ ImplVectorizer();
+ ~ImplVectorizer();
+
+ BOOL ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf,
+ BYTE cReduce, ULONG nFlags, const Link* pProgress );
+ BOOL ImplVectorize( const Bitmap& rMonoBmp, PolyPolygon& rPolyPoly,
+ ULONG nFlags, const Link* pProgress );
+};
+
+#endif
diff --git a/vcl/source/gdi/jobset.cxx b/vcl/source/gdi/jobset.cxx
new file mode 100644
index 000000000000..7edcf104d113
--- /dev/null
+++ b/vcl/source/gdi/jobset.cxx
@@ -0,0 +1,415 @@
+/*************************************************************************
+ *
+ * $RCSfile: jobset.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_JOBSET_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_JOBSET_HXX
+#include <jobset.hxx>
+#endif
+#ifndef _SV_JOBSET_H
+#include <jobset.h>
+#endif
+
+// =======================================================================
+
+DBG_NAME( JobSetup );
+
+#define JOBSET_FILEFORMAT2 3780
+#define JOBSET_FILE364_SYSTEM ((USHORT)0xFFFF)
+
+struct ImplOldJobSetupData
+{
+ char cPrinterName[64];
+ char cDeviceName[32];
+ char cPortName[32];
+ char cDriverName[32];
+};
+
+struct Impl364JobSetupData
+{
+ SVBT16 nSize;
+ SVBT16 nSystem;
+ SVBT32 nDriverDataLen;
+ SVBT16 nOrientation;
+ SVBT16 nPaperBin;
+ SVBT16 nPaperFormat;
+ SVBT32 nPaperWidth;
+ SVBT32 nPaperHeight;
+};
+
+// =======================================================================
+
+ImplJobSetup::ImplJobSetup()
+{
+ mnRefCount = 1;
+ mnSystem = 0;
+ meOrientation = ORIENTATION_PORTRAIT;
+ mnPaperBin = 0;
+ mePaperFormat = PAPER_USER;
+ mnPaperWidth = 0;
+ mnPaperHeight = 0;
+ mnDriverDataLen = 0;
+ mpDriverData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup::ImplJobSetup( const ImplJobSetup& rJobSetup ) :
+ maPrinterName( rJobSetup.maPrinterName ),
+ maDriver( rJobSetup.maDriver )
+{
+ mnRefCount = 1;
+ mnSystem = rJobSetup.mnSystem;
+ meOrientation = rJobSetup.meOrientation;
+ mnPaperBin = rJobSetup.mnPaperBin;
+ mePaperFormat = rJobSetup.mePaperFormat;
+ mnPaperWidth = rJobSetup.mnPaperWidth;
+ mnPaperHeight = rJobSetup.mnPaperHeight;
+ mnDriverDataLen = rJobSetup.mnDriverDataLen;
+ if ( rJobSetup.mpDriverData )
+ {
+ mpDriverData = new BYTE[mnDriverDataLen];
+ memcpy( mpDriverData, rJobSetup.mpDriverData, mnDriverDataLen );
+ }
+ else
+ mpDriverData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup::~ImplJobSetup()
+{
+ delete mpDriverData;
+}
+
+// =======================================================================
+
+ImplJobSetup* JobSetup::ImplGetData()
+{
+ if ( !mpData )
+ mpData = new ImplJobSetup;
+ else if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplJobSetup( *mpData );
+ }
+
+ return mpData;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup* JobSetup::ImplGetConstData()
+{
+ if ( !mpData )
+ mpData = new ImplJobSetup;
+ return mpData;
+}
+
+// -----------------------------------------------------------------------
+
+const ImplJobSetup* JobSetup::ImplGetConstData() const
+{
+ if ( !mpData )
+ ((JobSetup*)this)->mpData = new ImplJobSetup;
+ return mpData;
+}
+
+// =======================================================================
+
+JobSetup::JobSetup()
+{
+ DBG_CTOR( JobSetup, NULL );
+
+ mpData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup::JobSetup( const JobSetup& rJobSetup )
+{
+ DBG_CTOR( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+ DBG_ASSERT( !rJobSetup.mpData || (rJobSetup.mpData->mnRefCount < 0xFFFE), "JobSetup: RefCount overflow" );
+
+ mpData = rJobSetup.mpData;
+ if ( mpData )
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup::~JobSetup()
+{
+ DBG_DTOR( JobSetup, NULL );
+
+ if ( mpData )
+ {
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString JobSetup::GetPrinterName() const
+{
+ if ( mpData )
+ return mpData->maPrinterName;
+ else
+ {
+ XubString aName;
+ return aName;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString JobSetup::GetDriverName() const
+{
+ if ( mpData )
+ return mpData->maDriver;
+ else
+ {
+ XubString aDriver;
+ return aDriver;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup& JobSetup::operator=( const JobSetup& rJobSetup )
+{
+ DBG_CHKTHIS( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+ DBG_ASSERT( !rJobSetup.mpData || (rJobSetup.mpData->mnRefCount) < 0xFFFE, "JobSetup: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rJobSetup.mpData )
+ rJobSetup.mpData->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpData )
+ {
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+ }
+
+ mpData = rJobSetup.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL JobSetup::operator==( const JobSetup& rJobSetup ) const
+{
+ DBG_CHKTHIS( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+
+ if ( mpData == rJobSetup.mpData )
+ return TRUE;
+
+ if ( !mpData || !rJobSetup.mpData )
+ return FALSE;
+
+ ImplJobSetup* pData1 = mpData;
+ ImplJobSetup* pData2 = rJobSetup.mpData;
+ if ( (pData1->mnSystem == pData2->mnSystem) &&
+ (pData1->maPrinterName == pData2->maPrinterName) &&
+ (pData1->maDriver == pData2->maDriver) &&
+ (pData1->meOrientation == pData2->meOrientation) &&
+ (pData1->mnPaperBin == pData2->mnPaperBin) &&
+ (pData1->mePaperFormat == pData2->mePaperFormat) &&
+ (pData1->mnPaperWidth == pData2->mnPaperWidth) &&
+ (pData1->mnPaperHeight == pData2->mnPaperHeight) &&
+ (pData1->mnDriverDataLen == pData2->mnDriverDataLen) &&
+ (memcmp( pData1->mpDriverData, pData2->mpDriverData, pData1->mnDriverDataLen ) == 0) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, JobSetup& rJobSetup )
+{
+ DBG_ASSERTWARNING( rIStream.GetVersion(), "JobSetup::>> - Solar-Version not set on rOStream" );
+
+ // Zur Zeit haben wir noch kein neues FileFormat
+// if ( rIStream.GetVersion() < JOBSET_FILEFORMAT2 )
+ {
+ USHORT nLen;
+ USHORT nSystem;
+ rIStream >> nLen;
+ if ( !nLen )
+ return rIStream;
+ rIStream >> nSystem;
+ char* pTempBuf = new char[nLen];
+ rIStream.Read( pTempBuf, nLen - sizeof( nLen ) - sizeof( nSystem ) );
+ if ( nLen >= sizeof(ImplOldJobSetupData)+4 )
+ {
+ ImplOldJobSetupData* pData = (ImplOldJobSetupData*)pTempBuf;
+ if ( rJobSetup.mpData )
+ {
+ if ( rJobSetup.mpData->mnRefCount == 1 )
+ delete rJobSetup.mpData;
+ else
+ rJobSetup.mpData->mnRefCount--;
+ }
+ rJobSetup.mpData = new ImplJobSetup;
+ ImplJobSetup* pJobData = rJobSetup.mpData;
+ pJobData->maPrinterName = UniString( pData->cPrinterName, RTL_TEXTENCODING_UTF8 );
+ pJobData->maDriver = UniString( pData->cDriverName, RTL_TEXTENCODING_UTF8 );
+
+ // Sind es unsere neuen JobSetup-Daten?
+ if ( nSystem == JOBSET_FILE364_SYSTEM )
+ {
+ Impl364JobSetupData* pOldJobData = (Impl364JobSetupData*)(pTempBuf + sizeof( ImplOldJobSetupData ));
+ USHORT nOldJobDataSize = SVBT16ToShort( pOldJobData->nSize );
+ pJobData->mnSystem = SVBT16ToShort( pOldJobData->nSystem );
+ pJobData->mnDriverDataLen = SVBT32ToLong( pOldJobData->nDriverDataLen );
+ pJobData->meOrientation = (Orientation)SVBT16ToShort( pOldJobData->nOrientation );
+ pJobData->mnPaperBin = SVBT16ToShort( pOldJobData->nPaperBin );
+ pJobData->mePaperFormat = (Paper)SVBT16ToShort( pOldJobData->nPaperFormat );
+ pJobData->mnPaperWidth = (long)SVBT32ToLong( pOldJobData->nPaperWidth );
+ pJobData->mnPaperHeight = (long)SVBT32ToLong( pOldJobData->nPaperHeight );
+ if ( pJobData->mnDriverDataLen )
+ {
+ BYTE* pDriverData = ((BYTE*)pOldJobData) + nOldJobDataSize;
+ pJobData->mpDriverData = new BYTE[pJobData->mnDriverDataLen];
+ memcpy( pJobData->mpDriverData, pDriverData, pJobData->mnDriverDataLen );
+ }
+ }
+ }
+ delete pTempBuf;
+ }
+/*
+ else
+ {
+ }
+*/
+
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const JobSetup& rJobSetup )
+{
+ DBG_ASSERTWARNING( rOStream.GetVersion(), "JobSetup::<< - Solar-Version not set on rOStream" );
+
+ // Zur Zeit haben wir noch kein neues FileFormat
+// if ( rOStream.GetVersion() < JOBSET_FILEFORMAT2 )
+ {
+ USHORT nLen = 0;
+ if ( !rJobSetup.mpData )
+ rOStream << nLen;
+ else
+ {
+ USHORT nSystem = JOBSET_FILE364_SYSTEM;
+
+ const ImplJobSetup* pJobData = rJobSetup.ImplGetConstData();
+ Impl364JobSetupData aOldJobData;
+ USHORT nOldJobDataSize = sizeof( aOldJobData );
+ ShortToSVBT16( nOldJobDataSize, aOldJobData.nSize );
+ ShortToSVBT16( pJobData->mnSystem, aOldJobData.nSystem );
+ LongToSVBT32( pJobData->mnDriverDataLen, aOldJobData.nDriverDataLen );
+ ShortToSVBT16( (USHORT)(pJobData->meOrientation), aOldJobData.nOrientation );
+ ShortToSVBT16( pJobData->mnPaperBin, aOldJobData.nPaperBin );
+ ShortToSVBT16( (USHORT)(pJobData->mePaperFormat), aOldJobData.nPaperFormat );
+ LongToSVBT32( (ULONG)(pJobData->mnPaperWidth), aOldJobData.nPaperWidth );
+ LongToSVBT32( (ULONG)(pJobData->mnPaperHeight), aOldJobData.nPaperHeight );
+
+ ImplOldJobSetupData aOldData;
+ memset( &aOldData, 0, sizeof( aOldData ) );
+ ByteString aPrnByteName( rJobSetup.GetPrinterName(), RTL_TEXTENCODING_UTF8 );
+ strncpy( aOldData.cPrinterName, aPrnByteName.GetBuffer(), 63 );
+ ByteString aDriverByteName( rJobSetup.GetDriverName(), RTL_TEXTENCODING_UTF8 );
+ strncpy( aOldData.cDriverName, aDriverByteName.GetBuffer(), 31 );
+ nLen = sizeof( aOldData ) + 4 + nOldJobDataSize + pJobData->mnDriverDataLen;
+ rOStream << nLen;
+ rOStream << nSystem;
+ rOStream.Write( (char*)&aOldData, sizeof( aOldData ) );
+ rOStream.Write( (char*)&aOldJobData, nOldJobDataSize );
+ rOStream.Write( (char*)pJobData->mpDriverData, pJobData->mnDriverDataLen );
+ }
+ }
+/*
+ else
+ {
+ }
+*/
+
+ return rOStream;
+}
diff --git a/vcl/source/gdi/lineinfo.cxx b/vcl/source/gdi/lineinfo.cxx
new file mode 100644
index 000000000000..fde91e8ee702
--- /dev/null
+++ b/vcl/source/gdi/lineinfo.cxx
@@ -0,0 +1,300 @@
+/*************************************************************************
+ *
+ * $RCSfile: lineinfo.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_LINEINFO_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+
+DBG_NAME( LineInfo );
+
+// ----------------
+// - ImplLineInfo -
+// ----------------
+
+ImplLineInfo::ImplLineInfo() :
+ mnRefCount ( 1 ),
+ meStyle ( LINE_SOLID ),
+ mnWidth ( 0 ),
+ mnDashCount ( 0 ),
+ mnDashLen ( 0 ),
+ mnDotCount ( 0 ),
+ mnDotLen ( 0 ),
+ mnDistance ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
+ mnRefCount ( 1 ),
+ meStyle ( rImplLineInfo.meStyle ),
+ mnWidth ( rImplLineInfo.mnWidth ),
+ mnDashCount ( rImplLineInfo.mnDashCount ),
+ mnDashLen ( rImplLineInfo.mnDashLen ),
+ mnDotCount ( rImplLineInfo.mnDotCount ),
+ mnDotLen ( rImplLineInfo.mnDotLen ),
+ mnDistance ( rImplLineInfo.mnDistance )
+{
+}
+
+// ------------
+// - LineInfo -
+// ------------
+
+LineInfo::LineInfo( LineStyle eStyle, long nWidth )
+{
+ DBG_CTOR( LineInfo, NULL );
+ mpImplLineInfo = new ImplLineInfo;
+ mpImplLineInfo->meStyle = eStyle;
+ mpImplLineInfo->mnWidth = nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo::LineInfo( const LineInfo& rLineInfo )
+{
+ DBG_CTOR( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+ mpImplLineInfo = rLineInfo.mpImplLineInfo;
+ mpImplLineInfo->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo::~LineInfo()
+{
+ DBG_DTOR( LineInfo, NULL );
+ if( !( --mpImplLineInfo->mnRefCount ) )
+ delete mpImplLineInfo;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+
+ rLineInfo.mpImplLineInfo->mnRefCount++;
+
+ if( !( --mpImplLineInfo->mnRefCount ) )
+ delete mpImplLineInfo;
+
+ mpImplLineInfo = rLineInfo.mpImplLineInfo;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL LineInfo::operator==( const LineInfo& rLineInfo ) const
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+
+ return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
+ ( mpImplLineInfo->meStyle == rLineInfo.mpImplLineInfo->meStyle &&
+ mpImplLineInfo->mnWidth == rLineInfo.mpImplLineInfo->mnWidth &&
+ mpImplLineInfo->mnDashCount == rLineInfo.mpImplLineInfo->mnDashCount &&
+ mpImplLineInfo->mnDashLen == rLineInfo.mpImplLineInfo->mnDashLen &&
+ mpImplLineInfo->mnDotCount == rLineInfo.mpImplLineInfo->mnDotCount &&
+ mpImplLineInfo->mnDotLen == rLineInfo.mpImplLineInfo->mnDotLen &&
+ mpImplLineInfo->mnDistance == rLineInfo.mpImplLineInfo->mnDistance ) );
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::ImplMakeUnique()
+{
+ if( mpImplLineInfo->mnRefCount != 1 )
+ {
+ if( mpImplLineInfo->mnRefCount )
+ mpImplLineInfo->mnRefCount--;
+
+ mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetStyle( LineStyle eStyle )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetWidth( long nWidth )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnWidth = nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDashCount( USHORT nDashCount )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDashCount = nDashCount;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDashLen( long nDashLen )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDashLen = nDashLen;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDotCount( USHORT nDotCount )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDotCount = nDotCount;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDotLen( long nDotLen )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDotLen = nDotLen;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDistance( long nDistance )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDistance = nDistance;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
+ rIStm >> rImplLineInfo.mnWidth;
+
+ if( aCompat.GetVersion() >= 2 )
+ {
+ // version 2
+ rIStm >> rImplLineInfo.mnDashCount >> rImplLineInfo.mnDashLen;
+ rIStm >> rImplLineInfo.mnDotCount >> rImplLineInfo.mnDotLen;
+ rIStm >> rImplLineInfo.mnDistance;
+ }
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 2 );
+
+ // version 1
+ rOStm << (UINT16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
+
+ // since version2
+ rOStm << rImplLineInfo.mnDashCount << rImplLineInfo.mnDashLen;
+ rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
+ rOStm << rImplLineInfo.mnDistance;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
+{
+ rLineInfo.ImplMakeUnique();
+ return( rIStm >> *rLineInfo.mpImplLineInfo );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
+{
+ return( rOStm << *rLineInfo.mpImplLineInfo );
+}
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
new file mode 100644
index 000000000000..cecf617abb1c
--- /dev/null
+++ b/vcl/source/gdi/makefile.mk
@@ -0,0 +1,156 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=gdi
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+.IF "$(COM)"=="ICC"
+CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/salmisc.obj \
+ $(SLO)$/animate.obj \
+ $(SLO)$/impanmvw.obj \
+ $(SLO)$/bitmap.obj \
+ $(SLO)$/bitmap2.obj \
+ $(SLO)$/bitmap3.obj \
+ $(SLO)$/bitmap4.obj \
+ $(SLO)$/alpha.obj \
+ $(SLO)$/bitmapex.obj \
+ $(SLO)$/imgcons.obj \
+ $(SLO)$/bmpacc.obj \
+ $(SLO)$/bmpacc2.obj \
+ $(SLO)$/bmpacc3.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/cvtsvm.obj \
+ $(SLO)$/cvtgrf.obj \
+ $(SLO)$/font.obj \
+ $(SLO)$/gdimtf.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/gradient.obj \
+ $(SLO)$/hatch.obj \
+ $(SLO)$/graph.obj \
+ $(SLO)$/image.obj \
+ $(SLO)$/impbmp.obj \
+ $(SLO)$/impgraph.obj \
+ $(SLO)$/impimage.obj \
+ $(SLO)$/impprn.obj \
+ $(SLO)$/impvect.obj \
+ $(SLO)$/implncvt.obj \
+ $(SLO)$/jobset.obj \
+ $(SLO)$/line.obj \
+ $(SLO)$/lineinfo.obj \
+ $(SLO)$/mapmod.obj \
+ $(SLO)$/metaact.obj \
+ $(SLO)$/metric.obj \
+ $(SLO)$/octree.obj \
+ $(SLO)$/outmap.obj \
+ $(SLO)$/outdev.obj \
+ $(SLO)$/outdev2.obj \
+ $(SLO)$/outdev3.obj \
+ $(SLO)$/outdev4.obj \
+ $(SLO)$/outdev5.obj \
+ $(SLO)$/outdev6.obj \
+ $(SLO)$/poly.obj \
+ $(SLO)$/poly2.obj \
+ $(SLO)$/print.obj \
+ $(SLO)$/print2.obj \
+ $(SLO)$/regband.obj \
+ $(SLO)$/region.obj \
+ $(SLO)$/virdev.obj \
+ $(SLO)$/wall.obj \
+ $(SLO)$/opengl.obj
+
+.IF "$(remote)"!=""
+EXCEPTIONSFILES= $(SLO)$/bitmap.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/impgraph.obj \
+ $(SLO)$/impvect.obj \
+ $(SLO)$/outdev.obj \
+ $(SLO)$/outdev3.obj \
+ $(SLO)$/outdev6.obj \
+ $(SLO)$/print.obj \
+ $(SLO)$/print2.obj \
+ $(SLO)$/virdev.obj
+
+.ELSE
+EXCEPTIONSFILES= $(SLO)$/outdev.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/impgraph.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/source/gdi/mapmod.cxx b/vcl/source/gdi/mapmod.cxx
new file mode 100644
index 000000000000..5690e1c7cf0f
--- /dev/null
+++ b/vcl/source/gdi/mapmod.cxx
@@ -0,0 +1,356 @@
+/*************************************************************************
+ *
+ * $RCSfile: mapmod.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MAPMOD_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#define private public
+#ifndef _SV_MAPMOD_HXX
+#include <mapmod.hxx>
+#endif
+#undef private
+
+// =======================================================================
+
+DBG_NAME( MapMode );
+
+// -----------------------------------------------------------------------
+
+ImplMapMode::ImplMapMode() :
+ maOrigin( 0, 0 ),
+ maScaleX( 1, 1 ),
+ maScaleY( 1, 1 )
+{
+ mnRefCount = 1;
+ meUnit = MAP_PIXEL;
+ mbSimple = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMapMode::ImplMapMode( const ImplMapMode& rImplMapMode ) :
+ maOrigin( rImplMapMode.maOrigin ),
+ maScaleX( rImplMapMode.maScaleX ),
+ maScaleY( rImplMapMode.maScaleY )
+{
+ mnRefCount = 1;
+ meUnit = rImplMapMode.meUnit;
+ mbSimple = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplMapMode& rImplMapMode )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplMapMode.meUnit = (MapUnit) nTmp16;
+ rIStm >> rImplMapMode.maOrigin >> rImplMapMode.maScaleX >>
+ rImplMapMode.maScaleY >> rImplMapMode.mbSimple;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplMapMode& rImplMapMode )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImplMapMode.meUnit <<
+ rImplMapMode.maOrigin <<
+ rImplMapMode.maScaleX <<
+ rImplMapMode.maScaleY <<
+ rImplMapMode.mbSimple;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+static ImplMapMode* ImplGetStaticMapMode( MapUnit eUnit )
+{
+ // Achtung: Ganz fies und dreckig !!!
+#ifdef WIN
+ static long _near aStaticImplMapModeAry[(MAP_LASTENUMDUMMY)*sizeof(ImplMapMode)/sizeof(long)];
+#else
+ static long aStaticImplMapModeAry[(MAP_LASTENUMDUMMY)*sizeof(ImplMapMode)/sizeof(long)];
+#endif
+
+ ImplMapMode* pImplMapMode = ((ImplMapMode*)aStaticImplMapModeAry)+eUnit;
+ if ( !pImplMapMode->mbSimple )
+ {
+ Fraction aDefFraction( 1, 1 );
+ pImplMapMode->maScaleX = aDefFraction;
+ pImplMapMode->maScaleY = aDefFraction;
+ pImplMapMode->meUnit = eUnit;
+ pImplMapMode->mbSimple = TRUE;
+ }
+
+ return pImplMapMode;
+}
+
+// -----------------------------------------------------------------------
+
+inline void MapMode::ImplMakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplMapMode->mnRefCount != 1 )
+ {
+ if ( mpImplMapMode->mnRefCount )
+ mpImplMapMode->mnRefCount--;
+ mpImplMapMode = new ImplMapMode( *mpImplMapMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode()
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = ImplGetStaticMapMode( MAP_PIXEL );
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( const MapMode& rMapMode )
+{
+ DBG_CTOR( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+ DBG_ASSERT( rMapMode.mpImplMapMode->mnRefCount < 0xFFFE, "MapMode: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplMapMode = rMapMode.mpImplMapMode;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplMapMode->mnRefCount )
+ mpImplMapMode->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( MapUnit eUnit )
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = ImplGetStaticMapMode( eUnit );
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( MapUnit eUnit, const Point& rLogicOrg,
+ const Fraction& rScaleX, const Fraction& rScaleY )
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = new ImplMapMode;
+ mpImplMapMode->meUnit = eUnit;
+ mpImplMapMode->maOrigin = rLogicOrg;
+ mpImplMapMode->maScaleX = rScaleX;
+ mpImplMapMode->maScaleY = rScaleY;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::~MapMode()
+{
+ DBG_DTOR( MapMode, NULL );
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplMapMode->mnRefCount )
+ {
+ if ( mpImplMapMode->mnRefCount == 1 )
+ delete mpImplMapMode;
+ else
+ mpImplMapMode->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetMapUnit( MapUnit eUnit )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->meUnit = eUnit;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetOrigin( const Point& rLogicOrg )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maOrigin = rLogicOrg;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetScaleX( const Fraction& rScaleX )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maScaleX = rScaleX;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetScaleY( const Fraction& rScaleY )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maScaleY = rScaleY;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode& MapMode::operator=( const MapMode& rMapMode )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+ DBG_ASSERT( rMapMode.mpImplMapMode->mnRefCount < 0xFFFE, "MapMode: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rMapMode.mpImplMapMode->mnRefCount )
+ rMapMode.mpImplMapMode->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplMapMode->mnRefCount )
+ {
+ if ( mpImplMapMode->mnRefCount == 1 )
+ delete mpImplMapMode;
+ else
+ mpImplMapMode->mnRefCount--;
+ }
+
+ mpImplMapMode = rMapMode.mpImplMapMode;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MapMode::operator==( const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+
+ if ( mpImplMapMode == rMapMode.mpImplMapMode )
+ return TRUE;
+
+ if ( (mpImplMapMode->meUnit == rMapMode.mpImplMapMode->meUnit) &&
+ (mpImplMapMode->maOrigin == rMapMode.mpImplMapMode->maOrigin) &&
+ (mpImplMapMode->maScaleX == rMapMode.mpImplMapMode->maScaleX) &&
+ (mpImplMapMode->maScaleY == rMapMode.mpImplMapMode->maScaleY) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MapMode::IsDefault() const
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMapMode* pDefMapMode = ImplGetStaticMapMode( MAP_PIXEL );
+ if ( mpImplMapMode == pDefMapMode )
+ return TRUE;
+
+ if ( (mpImplMapMode->meUnit == pDefMapMode->meUnit) &&
+ (mpImplMapMode->maOrigin == pDefMapMode->maOrigin) &&
+ (mpImplMapMode->maScaleX == pDefMapMode->maScaleX) &&
+ (mpImplMapMode->maScaleY == pDefMapMode->maScaleY) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, MapMode& rMapMode )
+{
+ rMapMode.ImplMakeUnique();
+ return (rIStm >> *rMapMode.mpImplMapMode);
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const MapMode& rMapMode )
+{
+ return (rOStm << *rMapMode.mpImplMapMode);
+}
diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx
new file mode 100644
index 000000000000..caa28f1ee856
--- /dev/null
+++ b/vcl/source/gdi/metaact.cxx
@@ -0,0 +1,3434 @@
+/*************************************************************************
+ *
+ * $RCSfile: metaact.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_METAACT_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#include <string.h>
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+
+// ========================================================================
+
+inline void ImplScalePoint( Point& rPt, double fScaleX, double fScaleY )
+{
+ rPt.X() = FRound( fScaleX * rPt.X() );
+ rPt.Y() = FRound( fScaleY * rPt.Y() );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleSize( Size& rSz, double fScaleX, double fScaleY )
+{
+ rSz.Width() = FRound( fScaleX * rSz.Width() );
+ rSz.Height() = FRound( fScaleY * rSz.Height() );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleRect( Rectangle& rRect, double fScaleX, double fScaleY )
+{
+ Point aTL( rRect.TopLeft() );
+ Point aBR( rRect.BottomRight() );
+
+ ImplScalePoint( aTL, fScaleX, fScaleY );
+ ImplScalePoint( aBR, fScaleX, fScaleY );
+
+ rRect = Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScalePoly( Polygon& rPoly, double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+ ImplScalePoint( rPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleLineInfo( LineInfo& rLineInfo, double fScaleX, double fScaleY )
+{
+ if( !rLineInfo.IsDefault() )
+ {
+ const double fScale = ( fScaleX + fScaleY ) * 0.5;
+
+ rLineInfo.SetWidth( FRound( fScale * rLineInfo.GetWidth() ) );
+ rLineInfo.SetDashLen( FRound( fScale * rLineInfo.GetDashLen() ) );
+ rLineInfo.SetDotLen( FRound( fScale * rLineInfo.GetDotLen() ) );
+ rLineInfo.SetDistance( FRound( fScale * rLineInfo.GetDistance() ) );
+ }
+}
+
+// ========================================================================
+
+#define COMPAT( _def_rIStm ) VersionCompat aCompat( ( _def_rIStm ), STREAM_READ );
+#define COMPAT_VERSION() aCompat.GetVersion()
+#define WRITE_BASE_COMPAT( _def_rOStm, _def_nVer, _pWriteData ) \
+ MetaAction::Write( ( _def_rOStm ), _pWriteData ); \
+ VersionCompat aCompat( ( _def_rOStm ), STREAM_WRITE, ( _def_nVer ) );
+
+// ========================================================================
+
+MetaAction::MetaAction() :
+ mnRefCount( 1 ),
+ mnType( META_NULL_ACTION )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction::MetaAction( USHORT nType ) :
+ mnRefCount( 1 ),
+ mnType( nType )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction::~MetaAction()
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Execute( OutputDevice* pOut )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaAction::Clone()
+{
+ return new MetaAction;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Move( long nHorzMove, long nVertMove )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Scale( double fScaleX, double fScaleY )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Write( SvStream& rOStm, ImplMetaWriteData* )
+{
+ rOStm << mnType;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ rIStm >> mnType;
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaAction::ReadMetaAction( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ MetaAction* pAction = NULL;
+ UINT16 nType;
+
+ rIStm >> nType;
+
+ switch( nType )
+ {
+ case( META_NULL_ACTION ): pAction = new MetaAction; break;
+ case( META_PIXEL_ACTION ): pAction = new MetaPixelAction; break;
+ case( META_POINT_ACTION ): pAction = new MetaPointAction; break;
+ case( META_LINE_ACTION ): pAction = new MetaLineAction; break;
+ case( META_RECT_ACTION ): pAction = new MetaRectAction; break;
+ case( META_ROUNDRECT_ACTION ): pAction = new MetaRoundRectAction; break;
+ case( META_ELLIPSE_ACTION ): pAction = new MetaEllipseAction; break;
+ case( META_ARC_ACTION ): pAction = new MetaArcAction; break;
+ case( META_PIE_ACTION ): pAction = new MetaPieAction; break;
+ case( META_CHORD_ACTION ): pAction = new MetaChordAction; break;
+ case( META_POLYLINE_ACTION ): pAction = new MetaPolyLineAction; break;
+ case( META_POLYGON_ACTION ): pAction = new MetaPolygonAction; break;
+ case( META_POLYPOLYGON_ACTION ): pAction = new MetaPolyPolygonAction; break;
+ case( META_TEXT_ACTION ): pAction = new MetaTextAction; break;
+ case( META_TEXTARRAY_ACTION ): pAction = new MetaTextArrayAction; break;
+ case( META_STRETCHTEXT_ACTION ): pAction = new MetaStretchTextAction; break;
+ case( META_TEXTRECT_ACTION ): pAction = new MetaTextRectAction; break;
+ case( META_TEXTLINE_ACTION ): pAction = new MetaTextLineAction; break;
+ case( META_BMP_ACTION ): pAction = new MetaBmpAction; break;
+ case( META_BMPSCALE_ACTION ): pAction = new MetaBmpScaleAction; break;
+ case( META_BMPSCALEPART_ACTION ): pAction = new MetaBmpScalePartAction; break;
+ case( META_BMPEX_ACTION ): pAction = new MetaBmpExAction; break;
+ case( META_BMPEXSCALE_ACTION ): pAction = new MetaBmpExScaleAction; break;
+ case( META_BMPEXSCALEPART_ACTION ): pAction = new MetaBmpExScalePartAction; break;
+ case( META_MASK_ACTION ): pAction = new MetaMaskAction; break;
+ case( META_MASKSCALE_ACTION ): pAction = new MetaMaskScaleAction; break;
+ case( META_MASKSCALEPART_ACTION ): pAction = new MetaMaskScalePartAction; break;
+ case( META_GRADIENT_ACTION ): pAction = new MetaGradientAction; break;
+ case( META_GRADIENTEX_ACTION ): pAction = new MetaGradientExAction; break;
+ case( META_HATCH_ACTION ): pAction = new MetaHatchAction; break;
+ case( META_WALLPAPER_ACTION ): pAction = new MetaWallpaperAction; break;
+ case( META_CLIPREGION_ACTION ): pAction = new MetaClipRegionAction; break;
+ case( META_ISECTRECTCLIPREGION_ACTION ): pAction = new MetaISectRectClipRegionAction; break;
+ case( META_ISECTREGIONCLIPREGION_ACTION ): pAction = new MetaISectRegionClipRegionAction; break;
+ case( META_MOVECLIPREGION_ACTION ): pAction = new MetaMoveClipRegionAction; break;
+ case( META_LINECOLOR_ACTION ): pAction = new MetaLineColorAction; break;
+ case( META_FILLCOLOR_ACTION ): pAction = new MetaFillColorAction; break;
+ case( META_TEXTCOLOR_ACTION ): pAction = new MetaTextColorAction; break;
+ case( META_TEXTFILLCOLOR_ACTION ): pAction = new MetaTextFillColorAction; break;
+ case( META_TEXTLINECOLOR_ACTION ): pAction = new MetaTextLineColorAction; break;
+ case( META_TEXTALIGN_ACTION ): pAction = new MetaTextAlignAction; break;
+ case( META_MAPMODE_ACTION ): pAction = new MetaMapModeAction; break;
+ case( META_FONT_ACTION ): pAction = new MetaFontAction; break;
+ case( META_PUSH_ACTION ): pAction = new MetaPushAction; break;
+ case( META_POP_ACTION ): pAction = new MetaPopAction; break;
+ case( META_RASTEROP_ACTION ): pAction = new MetaRasterOpAction; break;
+ case( META_TRANSPARENT_ACTION ): pAction = new MetaTransparentAction; break;
+ case( META_FLOATTRANSPARENT_ACTION ): pAction = new MetaFloatTransparentAction; break;
+ case( META_EPS_ACTION ): pAction = new MetaEPSAction; break;
+ case( META_REFPOINT_ACTION ): pAction = new MetaRefPointAction; break;
+ case( META_COMMENT_ACTION ): pAction = new MetaCommentAction; break;
+
+ default:
+ {
+ // Action ueberlesen durch Kombination Ctor/Dtor,
+ // new/delete, weil Compiler sonst vielleicht wegoptimieren
+ delete ( new VersionCompat( rIStm, STREAM_READ ) );
+ }
+ break;
+ }
+
+ if( pAction )
+ pAction->Read( rIStm, pData );
+
+ return pAction;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pixel, META_PIXEL_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPixelAction::MetaPixelAction( const Point& rPt, const Color& rColor ) :
+ MetaAction ( META_PIXEL_ACTION ),
+ maPt ( rPt ),
+ maColor ( rColor )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPixel( maPt, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPixelAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPixelAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ maColor.Write( rOStm, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ maColor.Read( rIStm, TRUE );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Point, META_POINT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPointAction::MetaPointAction( const Point& rPt ) :
+ MetaAction ( META_POINT_ACTION ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPixel( maPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPointAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPointAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Line, META_LINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaLineAction::MetaLineAction( const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_LINE_ACTION ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaLineAction::MetaLineAction( const Point& rStart, const Point& rEnd,
+ const LineInfo& rLineInfo ) :
+ MetaAction ( META_LINE_ACTION ),
+ maLineInfo ( rLineInfo ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Execute( OutputDevice* pOut )
+{
+ if( maLineInfo.IsDefault() )
+ pOut->DrawLine( maStartPt, maEndPt );
+ else
+ pOut->DrawLine( maStartPt, maEndPt, maLineInfo );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+ ImplScaleLineInfo( maLineInfo, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maStartPt << maEndPt; // Version 1
+ rOStm << maLineInfo; // Version 2
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ // Version 1
+ rIStm >> maStartPt >> maEndPt;
+
+ // Version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ rIStm >> maLineInfo;
+ }
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Rect, META_RECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRectAction::MetaRectAction( const Rectangle& rRect ) :
+ MetaAction ( META_RECT_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawRect( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RoundRect, META_ROUNDRECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRoundRectAction::MetaRoundRectAction( const Rectangle& rRect,
+ long nHorzRound, long nVertRound ) :
+ MetaAction ( META_ROUNDRECT_ACTION ),
+ maRect ( rRect ),
+ mnHorzRound ( nHorzRound ),
+ mnVertRound ( nVertRound )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawRect( maRect, mnHorzRound, mnVertRound );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRoundRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRoundRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ mnHorzRound = FRound( mnHorzRound * fScaleX );
+ mnVertRound = FRound( mnVertRound * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << mnHorzRound << mnVertRound;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> mnHorzRound >> mnVertRound;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Ellipse, META_ELLIPSE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaEllipseAction::MetaEllipseAction( const Rectangle& rRect ) :
+ MetaAction ( META_ELLIPSE_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawEllipse( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaEllipseAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaEllipseAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Arc, META_ARC_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaArcAction::MetaArcAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_ARC_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawArc( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaArcAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaArcAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pie, META_PIE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPieAction::MetaPieAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_PIE_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPie( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPieAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPieAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Chord, META_CHORD_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaChordAction::MetaChordAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_CHORD_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawChord( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaChordAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaChordAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( PolyLine, META_POLYLINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolyLineAction::MetaPolyLineAction( const Polygon& rPoly ) :
+ MetaAction ( META_POLYLINE_ACTION ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaPolyLineAction::MetaPolyLineAction( const Polygon& rPoly, const LineInfo& rLineInfo ) :
+ MetaAction ( META_POLYLINE_ACTION ),
+ maLineInfo ( rLineInfo ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Execute( OutputDevice* pOut )
+{
+ if( maLineInfo.IsDefault() )
+ pOut->DrawPolyLine( maPoly );
+ else
+ pOut->DrawPolyLine( maPoly, maLineInfo );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolyLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolyLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoly( maPoly, fScaleX, fScaleY );
+ ImplScaleLineInfo( maLineInfo, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maPoly; // Version 1
+ rOStm << maLineInfo; // Version 2
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ // Version 1
+ rIStm >> maPoly;
+
+ // Version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ rIStm >> maLineInfo;
+ }
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Polygon, META_POLYGON_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolygonAction::MetaPolygonAction( const Polygon& rPoly ) :
+ MetaAction ( META_POLYGON_ACTION ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPolygon( maPoly );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolygonAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolygonAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoly( maPoly, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPoly;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPoly;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( PolyPolygon, META_POLYPOLYGON_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolyPolygonAction::MetaPolyPolygonAction( const PolyPolygon& rPolyPoly ) :
+ MetaAction ( META_POLYPOLYGON_ACTION ),
+ maPolyPoly ( rPolyPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPolyPolygon( maPolyPoly );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolyPolygonAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolyPolygonAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Text, META_TEXT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextAction::MetaTextAction( const Point& rPt, const XubString& rStr,
+ USHORT nIndex, USHORT nLen ) :
+ MetaAction ( META_TEXT_ACTION ),
+ maPt ( rPt ),
+ maStr ( rStr ),
+ mnIndex ( nIndex ),
+ mnLen ( nLen )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawText( maPt, maStr, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnIndex;
+ rOStm << mnLen;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+}
+
+// ========================================================================
+
+MetaTextArrayAction::MetaTextArrayAction() :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ mpDXAry ( NULL ),
+ mnIndex ( 0 ),
+ mnLen ( 0 )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::MetaTextArrayAction( const MetaTextArrayAction& rAction ) :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ maStartPt ( rAction.maStartPt ),
+ maStr ( rAction.maStr ),
+ mnIndex ( rAction.mnIndex ),
+ mnLen ( rAction.mnLen )
+{
+ if( rAction.mpDXAry )
+ {
+ const ULONG nAryLen = mnLen - 1;
+
+ mpDXAry = new long[ nAryLen ];
+ memcpy( mpDXAry, rAction.mpDXAry, nAryLen * sizeof( long ) );
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt,
+ const XubString& rStr,
+ const long* pDXAry,
+ USHORT nIndex,
+ USHORT nLen ) :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ maStartPt ( rStartPt ),
+ maStr ( rStr ),
+ mnIndex ( nIndex ),
+ mnLen ( ( nLen == STRING_LEN ) ? rStr.Len() : nLen )
+{
+ const ULONG nAryLen = ( ( mnLen > 1 ) && pDXAry ) ? ( mnLen - 1 ) : 0UL;
+
+ if( nAryLen )
+ {
+ mpDXAry = new long[ nAryLen ];
+ memcpy( mpDXAry, pDXAry, nAryLen * sizeof( long ) );
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::~MetaTextArrayAction()
+{
+ delete[] mpDXAry;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTextArray( maStartPt, maStr, mpDXAry, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextArrayAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextArrayAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Move( long nHorzMove, long nVertMove )
+{
+ maStartPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+
+ if ( mpDXAry && mnLen )
+ {
+ for ( USHORT i = 0, nCount = mnLen - 1; i < nCount; i++ )
+ mpDXAry[ i ] = FRound( mpDXAry[ i ] * fScaleX );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ const ULONG nAryLen = ( ( mnLen > 1 ) && mpDXAry ) ? ( mnLen - 1 ) : 0UL;
+
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maStartPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnIndex;
+ rOStm << mnLen;
+ rOStm << nAryLen;
+
+ for( ULONG i = 0UL; i < nAryLen; i++ )
+ rOStm << mpDXAry[ i ];
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ ULONG nAryLen;
+
+ delete[] mpDXAry;
+
+ COMPAT( rIStm );
+ rIStm >> maStartPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+ rIStm >> nAryLen;
+
+ if( nAryLen )
+ {
+ mpDXAry = new long[ nAryLen ];
+
+ for( ULONG i = 0UL; i < nAryLen; i++ )
+ rIStm >> mpDXAry[ i ];
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( StretchText, META_STRETCHTEXT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaStretchTextAction::MetaStretchTextAction( const Point& rPt, ULONG nWidth,
+ const XubString& rStr,
+ USHORT nIndex, USHORT nLen ) :
+ MetaAction ( META_STRETCHTEXT_ACTION ),
+ maPt ( rPt ),
+ maStr ( rStr ),
+ mnWidth ( nWidth ),
+ mnIndex ( nIndex ),
+ mnLen ( nLen )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawStretchText( maPt, mnWidth, maStr, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaStretchTextAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaStretchTextAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ mnWidth = (ULONG)FRound( mnWidth * fScaleX );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnWidth;
+ rOStm << mnIndex;
+ rOStm << mnLen;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnWidth;
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextRect, META_TEXTRECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextRectAction::MetaTextRectAction( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle ) :
+ MetaAction ( META_TEXTRECT_ACTION ),
+ maRect ( rRect ),
+ maStr ( rStr ),
+ mnStyle ( nStyle )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawText( maRect, maStr, mnStyle );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnStyle;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextLine, META_TEXTLINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextLineAction::MetaTextLineAction( const Point& rPos, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline ) :
+ MetaAction ( META_TEXTLINE_ACTION ),
+ maPos ( rPos ),
+ mnWidth ( nWidth ),
+ meStrikeout ( eStrikeout ),
+ meUnderline ( eUnderline )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTextLine( maPos, mnWidth, meStrikeout, meUnderline );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*)new MetaTextLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maPos.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPos, fScaleX, fScaleY );
+ mnWidth = FRound( mnWidth * fScaleX );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maPos;
+ rOStm << mnWidth;
+ rOStm << (ULONG)meStrikeout;
+ rOStm << (ULONG)meUnderline;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ ULONG nTemp;
+ rIStm >> maPos;
+ rIStm >> mnWidth;
+ rIStm >> nTemp;
+ meStrikeout = (FontStrikeout)nTemp;
+ rIStm >> nTemp;
+ meUnderline = (FontUnderline)nTemp;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Bmp, META_BMP_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpAction::MetaBmpAction( const Point& rPt, const Bitmap& rBmp ) :
+ MetaAction ( META_BMP_ACTION ),
+ maBmp ( rBmp ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maPt, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpScale, META_BMPSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpScaleAction::MetaBmpScaleAction( const Point& rPt, const Size& rSz,
+ const Bitmap& rBmp ) :
+ MetaAction ( META_BMPSCALE_ACTION ),
+ maBmp ( rBmp ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maPt, maSz, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpScalePart, META_BMPSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpScalePartAction::MetaBmpScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Bitmap& rBmp ) :
+ MetaAction ( META_BMPSCALEPART_ACTION ),
+ maBmp ( rBmp ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpEx, META_BMPEX_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExAction::MetaBmpExAction( const Point& rPt, const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEX_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maPt, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpExScale, META_BMPEXSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExScaleAction::MetaBmpExScaleAction( const Point& rPt, const Size& rSz,
+ const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEXSCALE_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maPt, maSz, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpExScalePart, META_BMPEXSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExScalePartAction::MetaBmpExScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEXSCALEPART_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Mask, META_MASK_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskAction::MetaMaskAction( const Point& rPt,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASK_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maPt, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MaskScale, META_MASKSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskScaleAction::MetaMaskScaleAction( const Point& rPt, const Size& rSz,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASKSCALE_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maPt, maSz, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MaskScalePart, META_MASKSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskScalePartAction::MetaMaskScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASKSCALEPART_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp;
+ maColor.Write( rOStm, TRUE );
+ rOStm << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp;
+ maColor.Read( rIStm, TRUE );
+ rIStm >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Gradient, META_GRADIENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaGradientAction::MetaGradientAction( const Rectangle& rRect, const Gradient& rGradient ) :
+ MetaAction ( META_GRADIENT_ACTION ),
+ maRect ( rRect ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawGradient( maRect, maGradient );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaGradientAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaGradientAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maGradient;
+}
+
+// ========================================================================
+
+MetaGradientExAction::MetaGradientExAction() :
+ MetaAction ( META_GRADIENTEX_ACTION )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaGradientExAction::MetaGradientExAction( const PolyPolygon& rPolyPoly, const Gradient& rGradient ) :
+ MetaAction ( META_GRADIENTEX_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaGradientExAction::~MetaGradientExAction()
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Execute( OutputDevice* pOut )
+{
+ if( pOut->GetConnectMetaFile() )
+ pOut->GetConnectMetaFile()->AddAction( Clone() );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaGradientExAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaGradientExAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly >> maGradient;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Hatch, META_HATCH_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaHatchAction::MetaHatchAction( const PolyPolygon& rPolyPoly, const Hatch& rHatch ) :
+ MetaAction ( META_HATCH_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ maHatch ( rHatch )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawHatch( maPolyPoly, maHatch );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaHatchAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaHatchAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly << maHatch;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly >> maHatch;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Wallpaper, META_WALLPAPER_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaWallpaperAction::MetaWallpaperAction( const Rectangle& rRect,
+ const Wallpaper& rPaper ) :
+ MetaAction ( META_WALLPAPER_ACTION ),
+ maRect ( rRect ),
+ maWallpaper ( rPaper )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawWallpaper( maRect, maWallpaper );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaWallpaperAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaWallpaperAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maWallpaper;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maWallpaper;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ClipRegion, META_CLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaClipRegionAction::MetaClipRegionAction( const Region& rRegion, BOOL bClip ) :
+ MetaAction ( META_CLIPREGION_ACTION ),
+ maRegion ( rRegion ),
+ mbClip ( bClip )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Execute( OutputDevice* pOut )
+{
+ if( mbClip )
+ pOut->SetClipRegion( maRegion );
+ else
+ pOut->SetClipRegion();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRegion.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ maRegion.Scale( fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRegion << mbClip;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRegion >> mbClip;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ISectRectClipRegion, META_ISECTRECTCLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaISectRectClipRegionAction::MetaISectRectClipRegionAction( const Rectangle& rRect ) :
+ MetaAction ( META_ISECTRECTCLIPREGION_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->IntersectClipRegion( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaISectRectClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaISectRectClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ISectRegionClipRegion, META_ISECTREGIONCLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaISectRegionClipRegionAction::MetaISectRegionClipRegionAction( const Region& rRegion ) :
+ MetaAction ( META_ISECTREGIONCLIPREGION_ACTION ),
+ maRegion ( rRegion )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->IntersectClipRegion( maRegion );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaISectRegionClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaISectRegionClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRegion.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ maRegion.Scale( fScaleX, fScaleY );
+}
+
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRegion;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRegion;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MoveClipRegion, META_MOVECLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMoveClipRegionAction::MetaMoveClipRegionAction( long nHorzMove, long nVertMove ) :
+ MetaAction ( META_MOVECLIPREGION_ACTION ),
+ mnHorzMove ( nHorzMove ),
+ mnVertMove ( nVertMove )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->MoveClipRegion( mnHorzMove, mnVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMoveClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMoveClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ mnHorzMove = FRound( mnHorzMove * fScaleX );
+ mnVertMove = FRound( mnVertMove * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << mnHorzMove << mnVertMove;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> mnHorzMove >> mnVertMove;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( LineColor, META_LINECOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaLineColorAction::MetaLineColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_LINECOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetLineColor( maColor );
+ else
+ pOut->SetLineColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaLineColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaLineColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( FillColor, META_FILLCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFillColorAction::MetaFillColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_FILLCOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetFillColor( maColor );
+ else
+ pOut->SetFillColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFillColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFillColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextColor, META_TEXTCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextColorAction::MetaTextColorAction( const Color& rColor ) :
+ MetaAction ( META_TEXTCOLOR_ACTION ),
+ maColor ( rColor )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetTextColor( maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextFillColor, META_TEXTFILLCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextFillColorAction::MetaTextFillColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_TEXTFILLCOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetTextFillColor( maColor );
+ else
+ pOut->SetTextFillColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextFillColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextFillColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextLineColor, META_TEXTLINECOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextLineColorAction::MetaTextLineColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_TEXTLINECOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetTextLineColor( maColor );
+ else
+ pOut->SetTextLineColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextLineColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextLineColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextAlign, META_TEXTALIGN_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextAlignAction::MetaTextAlignAction( TextAlign aAlign ) :
+ MetaAction ( META_TEXTALIGN_ACTION ),
+ maAlign ( aAlign )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetTextAlign( maAlign );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextAlignAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextAlignAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << (UINT16) maAlign;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ UINT16 nTmp16;
+
+ COMPAT( rIStm );
+ rIStm >> nTmp16; maAlign = (TextAlign) nTmp16;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MapMode, META_MAPMODE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMapModeAction::MetaMapModeAction( const MapMode& rMapMode ) :
+ MetaAction ( META_MAPMODE_ACTION ),
+ maMapMode ( rMapMode )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetMapMode( maMapMode );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMapModeAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMapModeAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Scale( double fScaleX, double fScaleY )
+{
+ Point aPoint( maMapMode.GetOrigin() );
+
+ ImplScalePoint( aPoint, fScaleX, fScaleY );
+ maMapMode.SetOrigin( aPoint );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maMapMode;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maMapMode;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Font, META_FONT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFontAction::MetaFontAction( const Font& rFont ) :
+ MetaAction ( META_FONT_ACTION ),
+ maFont ( rFont )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetFont( maFont );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFontAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFontAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Scale( double fScaleX, double fScaleY )
+{
+ Size aSize( maFont.GetSize() );
+
+ ImplScaleSize( aSize, fScaleX, fScaleY );
+ maFont.SetSize( aSize );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maFont;
+ pData->meActualCharSet = maFont.GetCharSet();
+ if ( pData->meActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ pData->meActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maFont;
+ pData->meActualCharSet = maFont.GetCharSet();
+ if ( pData->meActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ pData->meActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Push, META_PUSH_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPushAction::MetaPushAction( USHORT nFlags ) :
+ MetaAction ( META_PUSH_ACTION ),
+ mnFlags ( nFlags )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Execute( OutputDevice* pOut )
+{
+ pOut->Push( mnFlags );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPushAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPushAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << mnFlags;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> mnFlags;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pop, META_POP_ACTION )
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Execute( OutputDevice* pOut )
+{
+ pOut->Pop();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPopAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPopAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RasterOp, META_RASTEROP_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRasterOpAction::MetaRasterOpAction( RasterOp eRasterOp ) :
+ MetaAction ( META_RASTEROP_ACTION ),
+ meRasterOp ( eRasterOp )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetRasterOp( meRasterOp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRasterOpAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRasterOpAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << (UINT16) meRasterOp;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ UINT16 nTmp16;
+
+ COMPAT( rIStm );
+ rIStm >> nTmp16; meRasterOp = (RasterOp) nTmp16;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Transparent, META_TRANSPARENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTransparentAction::MetaTransparentAction( const PolyPolygon& rPolyPoly, USHORT nTransPercent ) :
+ MetaAction ( META_TRANSPARENT_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ mnTransPercent ( nTransPercent )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTransparent( maPolyPoly, mnTransPercent );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTransparentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTransparentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly;
+ rOStm << mnTransPercent;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly;
+ rIStm >> mnTransPercent;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( FloatTransparent, META_FLOATTRANSPARENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFloatTransparentAction::MetaFloatTransparentAction( const GDIMetaFile& rMtf, const Point& rPos,
+ const Size& rSize, const Gradient& rGradient ) :
+ MetaAction ( META_FLOATTRANSPARENT_ACTION ),
+ maMtf ( rMtf ),
+ maPoint ( rPos ),
+ maSize ( rSize ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTransparent( maMtf, maPoint, maSize, maGradient );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFloatTransparentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFloatTransparentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoint.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPoint, fScaleX, fScaleY );
+ ImplScaleSize( maSize, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maMtf << maPoint << maSize << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maMtf >> maPoint >> maSize >> maGradient;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( EPS, META_EPS_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaEPSAction::MetaEPSAction( const Point& rPoint, const Size& rSize,
+ const GfxLink& rGfxLink, const GDIMetaFile& rSubst ) :
+ MetaAction ( META_EPS_ACTION ),
+ maGfxLink ( rGfxLink ),
+ maSubst ( rSubst ),
+ maPoint ( rPoint ),
+ maSize ( rSize )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawEPS( maPoint, maSize, maGfxLink, &maSubst );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaEPSAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaEPSAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoint.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPoint, fScaleX, fScaleY );
+ ImplScaleSize( maSize, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maGfxLink;
+ rOStm << maPoint;
+ rOStm << maSize;
+ rOStm << maSubst;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maGfxLink;
+ rIStm >> maPoint;
+ rIStm >> maSize;
+ rIStm >> maSubst;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RefPoint, META_REFPOINT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRefPointAction::MetaRefPointAction( const Point& rRefPoint, BOOL bSet ) :
+ MetaAction ( META_REFPOINT_ACTION ),
+ maRefPoint ( rRefPoint ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetRefPoint( maRefPoint );
+ else
+ pOut->SetRefPoint();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRefPointAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRefPointAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRefPoint << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRefPoint >> mbSet;
+}
+
+// ========================================================================
+
+MetaCommentAction::MetaCommentAction( long nValue ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ mnValue ( nValue )
+{
+ ImplInitDynamicData( NULL, 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const MetaCommentAction& rAct ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ maComment ( rAct.maComment ),
+ mnValue ( rAct.mnValue )
+{
+ ImplInitDynamicData( rAct.mpData, rAct.mnDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const ByteString& rComment, long nValue, const BYTE* pData, ULONG nDataSize ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ maComment ( rComment ),
+ mnValue ( nValue )
+{
+ ImplInitDynamicData( pData, nDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const BYTE* pData, ULONG nDataSize ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ mnValue ( 0L )
+{
+ ImplInitDynamicData( pData, nDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::~MetaCommentAction()
+{
+ if ( mpData )
+ delete[] mpData;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::ImplInitDynamicData( const BYTE* pData, ULONG nDataSize )
+{
+ if ( nDataSize && pData )
+ {
+ mnDataSize = nDataSize, mpData = new BYTE[ mnDataSize ];
+ HMEMCPY( mpData, pData, mnDataSize );
+ }
+ else
+ {
+ mnDataSize = 0;
+ mpData = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Execute( OutputDevice* pOut )
+{
+ if ( pOut->GetConnectMetaFile() )
+ pOut->GetConnectMetaFile()->AddAction( Clone() );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaCommentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaCommentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maComment << mnValue << mnDataSize;
+
+ if ( mnDataSize )
+ rOStm.Write( mpData, mnDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maComment >> mnValue >> mnDataSize;
+
+ if( mpData )
+ delete[] mpData;
+
+ if( mnDataSize )
+ {
+ mpData = new BYTE[ mnDataSize ];
+ rIStm.Read( mpData, mnDataSize );
+ }
+ else
+ mpData = NULL;
+}
diff --git a/vcl/source/gdi/metric.cxx b/vcl/source/gdi/metric.cxx
new file mode 100644
index 000000000000..b4a5f70fa5cd
--- /dev/null
+++ b/vcl/source/gdi/metric.cxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * $RCSfile: metric.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <metric.hxx>
+
+// =======================================================================
+
+FontInfo::FontInfo()
+{
+ mpImplMetric = new ImplFontMetric;
+ mpImplMetric->mnRefCount = 1;
+ mpImplMetric->meType = TYPE_DONTKNOW;
+ mpImplMetric->mbDevice = FALSE;
+ mpImplMetric->mnAscent = 0;
+ mpImplMetric->mnDescent = 0;
+ mpImplMetric->mnLeading = 0;
+ mpImplMetric->mnLineHeight = 0;
+ mpImplMetric->mnSlant = 0;
+ mpImplMetric->mnFirstChar = 0;
+ mpImplMetric->mnLastChar = 0;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo::FontInfo( const FontInfo& rInfo ) :
+ Font( rInfo )
+{
+ mpImplMetric = rInfo.mpImplMetric;
+ mpImplMetric->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo::~FontInfo()
+{
+ // Eventuell Metric loeschen
+ if ( mpImplMetric->mnRefCount > 1 )
+ mpImplMetric->mnRefCount--;
+ else
+ delete mpImplMetric;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo& FontInfo::operator=( const FontInfo& rInfo )
+{
+ Font::operator=( rInfo );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rInfo.mpImplMetric->mnRefCount++;
+
+ // Sind wir nicht die letzten ?
+ if ( mpImplMetric->mnRefCount > 1 )
+ mpImplMetric->mnRefCount--;
+ else
+ delete mpImplMetric;
+
+ mpImplMetric = rInfo.mpImplMetric;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FontInfo::operator==( const FontInfo& rInfo ) const
+{
+ if ( !Font::operator==( rInfo ) )
+ return FALSE;
+
+ if ( mpImplMetric == rInfo.mpImplMetric )
+ return TRUE;
+
+ if ( (mpImplMetric->meType == rInfo.mpImplMetric->meType ) &&
+ (mpImplMetric->mbDevice == rInfo.mpImplMetric->mbDevice ) &&
+ (mpImplMetric->mnAscent == rInfo.mpImplMetric->mnAscent ) &&
+ (mpImplMetric->mnDescent == rInfo.mpImplMetric->mnDescent ) &&
+ (mpImplMetric->mnLeading == rInfo.mpImplMetric->mnLeading ) &&
+ (mpImplMetric->mnSlant == rInfo.mpImplMetric->mnSlant ) &&
+ (mpImplMetric->mnFirstChar == rInfo.mpImplMetric->mnFirstChar ) &&
+ (mpImplMetric->mnLastChar == rInfo.mpImplMetric->mnLastChar ) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/gdi/octree.cxx b/vcl/source/gdi/octree.cxx
new file mode 100644
index 000000000000..7d4f9f688d65
--- /dev/null
+++ b/vcl/source/gdi/octree.cxx
@@ -0,0 +1,419 @@
+/*************************************************************************
+ *
+ * $RCSfile: octree.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include <limits.h>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_IMPOCT_HXX
+#include <impoct.hxx>
+#endif
+#ifndef _NEW_HXX
+#include<tools/new.hxx>
+#endif
+#include <octree.hxx>
+
+// ------------
+// - Typedefs -
+// ------------
+
+#ifdef WIN
+typedef ULONG huge* HPULONG;
+#else
+typedef ULONG* HPULONG;
+#endif
+
+// ---------
+// - pMask -
+// ---------
+
+static BYTE pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+// -------------
+// - NodeCache -
+// -------------
+
+ImpNodeCache::ImpNodeCache( const ULONG nInitSize ) :
+ pActNode( NULL )
+{
+ const ULONG nSize = nInitSize + 4;
+
+ for( ULONG i = 0; i < nSize; i++ )
+ {
+ OctreeNode* pNewNode = new NODE;
+
+ pNewNode->pNextInCache = pActNode;
+ pActNode = pNewNode;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImpNodeCache::~ImpNodeCache()
+{
+ while( pActNode )
+ {
+ OctreeNode* pNode = pActNode;
+
+ pActNode = pNode->pNextInCache;
+ delete pNode;
+ }
+}
+
+// ----------
+// - Octree -
+// ----------
+
+Octree::Octree( ULONG nColors ) :
+ nMax ( nColors ),
+ nLeafCount ( 0L ),
+ pTree ( NULL ),
+ pAcc ( NULL )
+{
+ pNodeCache = new ImpNodeCache( nColors );
+ memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
+}
+
+// ------------------------------------------------------------------------
+
+Octree::Octree( const BitmapReadAccess& rReadAcc, ULONG nColors ) :
+ nMax ( nColors ),
+ nLeafCount ( 0L ),
+ pTree ( NULL ),
+ pAcc ( &rReadAcc )
+{
+ pNodeCache = new ImpNodeCache( nColors );
+ memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
+ ImplCreateOctree();
+}
+
+// ------------------------------------------------------------------------
+
+Octree::~Octree()
+{
+ ImplDeleteOctree( &pTree );
+ delete pNodeCache;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::AddColor( const BitmapColor& rColor )
+{
+ pColor = &(BitmapColor&) rColor;
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplCreateOctree()
+{
+ if( !!*pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+
+ if( pAcc->HasPalette() )
+ {
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ pColor = &(BitmapColor&) pAcc->GetPaletteColor( pAcc->GetPixel( nY, nX ) );
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aColor;
+
+ pColor = &aColor;
+
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPixel( nY, nX );
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplDeleteOctree( PPNODE ppNode )
+{
+ for ( ULONG i = 0UL; i < 8UL; i++ )
+ {
+ if ( (*ppNode)->pChild[ i ] )
+ ImplDeleteOctree( &(*ppNode)->pChild[ i ] );
+ }
+
+ pNodeCache->ImplReleaseNode( *ppNode );
+ *ppNode = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplAdd( PPNODE ppNode )
+{
+ // ggf. neuen Knoten erzeugen
+ if( !*ppNode )
+ {
+ *ppNode = pNodeCache->ImplGetFreeNode();
+ (*ppNode)->bLeaf = ( OCTREE_BITS == nLevel );
+
+ if( (*ppNode)->bLeaf )
+ nLeafCount++;
+ else
+ {
+ (*ppNode)->pNext = pReduce[ nLevel ];
+ pReduce[ nLevel ] = *ppNode;
+ }
+ }
+
+ if( (*ppNode)->bLeaf )
+ {
+ (*ppNode)->nCount++;
+ (*ppNode)->nRed += pColor->GetRed();
+ (*ppNode)->nGreen += pColor->GetGreen();
+ (*ppNode)->nBlue += pColor->GetBlue();
+ }
+ else
+ {
+ const ULONG nShift = 7 - nLevel;
+ const BYTE cMask = pImplMask[ nLevel ];
+ const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
+ ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
+ ( ( pColor->GetBlue() & cMask ) >> nShift );
+
+ nLevel++;
+ ImplAdd( &(*ppNode)->pChild[ nIndex ] );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplReduce()
+{
+ ULONG i;
+ PNODE pNode;
+ ULONG nRedSum = 0L;
+ ULONG nGreenSum = 0L;
+ ULONG nBlueSum = 0L;
+ ULONG nChilds = 0L;
+
+ for ( i = OCTREE_BITS - 1; i && !pReduce[i]; i-- ) {}
+
+ pNode = pReduce[ i ];
+ pReduce[ i ] = pNode->pNext;
+
+ for ( i = 0; i < 8; i++ )
+ {
+ if ( pNode->pChild[ i ] )
+ {
+ PNODE pChild = pNode->pChild[ i ];
+
+ nRedSum += pChild->nRed;
+ nGreenSum += pChild->nGreen;
+ nBlueSum += pChild->nBlue;
+ pNode->nCount += pChild->nCount;
+
+ pNodeCache->ImplReleaseNode( pNode->pChild[ i ] );
+ pNode->pChild[ i ] = NULL;
+ nChilds++;
+ }
+ }
+
+ pNode->bLeaf = TRUE;
+ pNode->nRed = nRedSum;
+ pNode->nGreen = nGreenSum;
+ pNode->nBlue = nBlueSum;
+ nLeafCount -= --nChilds;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::CreatePalette( PNODE pNode )
+{
+ if( pNode->bLeaf )
+ {
+ pNode->nPalIndex = nPalIndex;
+ aPal[ nPalIndex++ ] = BitmapColor( (BYTE) ( (double) pNode->nRed / pNode->nCount ),
+ (BYTE) ( (double) pNode->nGreen / pNode->nCount ),
+ (BYTE) ( (double) pNode->nBlue / pNode->nCount ) );
+ }
+ else for( ULONG i = 0UL; i < 8UL; i++ )
+ if( pNode->pChild[ i ] )
+ CreatePalette( pNode->pChild[ i ] );
+
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::GetPalIndex( PNODE pNode )
+{
+ if ( pNode->bLeaf )
+ nPalIndex = pNode->nPalIndex;
+ else
+ {
+ const ULONG nShift = 7 - nLevel;
+ const BYTE cMask = pImplMask[ nLevel++ ];
+ const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
+ ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
+ ( ( pColor->GetBlue() & cMask ) >> nShift );
+
+ GetPalIndex( pNode->pChild[ nIndex ] );
+ }
+}
+
+// -------------------
+// - InverseColorMap -
+// -------------------
+
+InverseColorMap::InverseColorMap( const BitmapPalette& rPal ) :
+ nBits( 8 - OCTREE_BITS )
+{
+ HPULONG cdp;
+ BYTE* crgbp;
+ const ULONG nColorMax = 1 << OCTREE_BITS;
+ const ULONG xsqr = 1 << ( nBits << 1 );
+ const ULONG xsqr2 = xsqr << 1;
+ const ULONG gstride = nColorMax;
+ const ULONG rstride = nColorMax * nColorMax;
+ const ULONG nColors = rPal.GetEntryCount();
+ const long x = 1L << nBits;
+ const long x2 = x >> 1L;
+ ULONG r, g, b;
+ long rxx, gxx, bxx;
+ long rdist, gdist, bdist;
+ long crinc, cginc, cbinc;
+
+ ImplCreateBuffers( nColorMax );
+
+ for( ULONG nIndex = 0; nIndex < nColors; nIndex++ )
+ {
+ const BitmapColor& rColor = rPal[ (USHORT) nIndex ];
+ const BYTE cRed = rColor.GetRed();
+ const BYTE cGreen = rColor.GetGreen();
+ const BYTE cBlue = rColor.GetBlue();
+
+ rdist = cRed - x2;
+ gdist = cGreen - x2;
+ bdist = cBlue - x2;
+ rdist = rdist*rdist + gdist*gdist + bdist*bdist;
+
+ crinc = ( xsqr - ( cRed << nBits ) ) << 1L;
+ cginc = ( xsqr - ( cGreen << nBits ) ) << 1L;
+ cbinc = ( xsqr - ( cBlue << nBits ) ) << 1L;
+
+ cdp = (HPULONG) pBuffer;
+ crgbp = pMap;
+
+ for( r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2 )
+ {
+ for( g = 0, gdist = rdist, gxx = cginc; g < nColorMax; gdist += gxx, g++, gxx += xsqr2 )
+ {
+ for( b = 0, bdist = gdist, bxx = cbinc; b < nColorMax; bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2 )
+ if ( !nIndex || ( (long) *cdp ) > bdist )
+ {
+ *cdp = bdist;
+ *crgbp = (BYTE) nIndex;
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+InverseColorMap::~InverseColorMap()
+{
+ SvMemFree( pBuffer );
+ SvMemFree( pMap );
+}
+
+// ------------------------------------------------------------------------
+
+void InverseColorMap::ImplCreateBuffers( const ULONG nMax )
+{
+ const ULONG nCount = nMax * nMax * nMax;
+ const ULONG nSize = nCount * sizeof( ULONG );
+
+ pMap = (BYTE*) SvMemAlloc( nCount );
+ HMEMSET( pMap, 0x00, nCount );
+
+ pBuffer = (BYTE*) SvMemAlloc( nSize );
+ HMEMSET( pBuffer, 0xff, nSize );
+}
diff --git a/vcl/source/gdi/opengl.cxx b/vcl/source/gdi/opengl.cxx
new file mode 100644
index 000000000000..fa45d1700725
--- /dev/null
+++ b/vcl/source/gdi/opengl.cxx
@@ -0,0 +1,1714 @@
+/*************************************************************************
+ *
+ * $RCSfile: opengl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OPENGL_CXX
+
+#define private public
+#include <svsys.h>
+#include <window.hxx>
+#undef private
+#define private public
+
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_SALOGL_HXX
+#include <salogl.hxx>
+#endif
+#ifndef _SV_OPENGL_HXX
+#include <opengl.hxx>
+#endif
+
+#include <svapp.hxx>
+#include <vos/mutex.hxx>
+
+// -----------------------
+// - Fnc-Pointer-Typedef -
+// -----------------------
+
+typedef void ( *OGLFncClearDepth )( GLclampd fDepth );
+typedef void ( *OGLFncDepthFunc )( GLenum fFunc );
+typedef void ( *OGLFncEnable )( GLenum eCap );
+typedef void ( *OGLFncDisable )( GLenum eCap );
+typedef void ( *OGLFncDepthMask )( GLboolean bFlag );
+typedef void ( *OGLFncShadeModel )( GLenum eMode );
+typedef void ( *OGLFncEdgeFlag )( GLboolean bFlag );
+typedef void ( *OGLFncClear )( GLbitfield nMask );
+typedef void ( *OGLFncFlush )( void );
+typedef void ( *OGLFncFinish )( void );
+typedef void ( *OGLFncViewport )( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight );
+typedef void ( *OGLFncBegin )( GLenum eMode );
+typedef void ( *OGLFncEnd )( void );
+typedef void ( *OGLFncVertex3dv )( const GLdouble *fV );
+typedef void ( *OGLFncNormal3dv )( const GLdouble *fV );
+typedef void ( *OGLFncColor4ub )( GLubyte cRed, GLubyte cGreen, GLubyte cBlue, GLubyte cAlpha );
+typedef void ( *OGLFncMaterialfv )( GLenum eFace, GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncMaterialf )( GLenum eFace, GLenum ePName, GLfloat fParam );
+typedef void ( *OGLFncLightModelfv )( GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncLightModelf )( GLenum ePname, GLfloat fParam );
+typedef void ( *OGLFncLightfv )( GLenum eLight, GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncLightf )( GLenum eLight, GLenum ePname, GLfloat fParam );
+typedef void ( *OGLFncPolygonMode )( GLenum eFace, GLenum eMode );
+typedef void ( *OGLFncCullFace )( GLenum eMode );
+typedef void ( *OGLFncPointSize )( GLfloat fSize );
+typedef void ( *OGLFncLineWidth )( GLfloat fWidth );
+typedef void ( *OGLFncMatrixMode )( GLenum eMode );
+typedef void ( *OGLFncLoadMatrixd )( const GLdouble *fM );
+typedef void ( *OGLFncTexCoord2dv )( const GLdouble *pParams );
+typedef void ( *OGLFncTexCoord3dv )( const GLdouble *fV );
+typedef void ( *OGLFncTexImage1D )( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncTexImage2D )( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncCopyTexImage1D )( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border );
+typedef void ( *OGLFncCopyTexImage2D )( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border );
+typedef void ( *OGLFncCopyTexSubImage1D )( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+typedef void ( *OGLFncCopyTexSubImage2D )( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+typedef void ( *OGLFncPixelTransferf )( GLenum pname, GLfloat param );
+typedef void ( *OGLFncPixelTransferi )( GLenum pname, GLint param );
+typedef void ( *OGLFncGetTexLevelParameterfv )( GLenum target, GLint level, GLenum pname, GLfloat *params );
+typedef void ( *OGLFncGetTexLevelParameteriv )( GLenum target, GLint level, GLenum pname, GLint *params );
+typedef void ( *OGLFncGetTexParameterfv )( GLenum target, GLenum pname, GLfloat *params );
+typedef void ( *OGLFncGetTexParameteriv )( GLenum target, GLenum pname, GLint *params );
+typedef void ( *OGLFncTexSubImage1D )( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncTexSubImage2D )( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncPixelStoref )( GLenum pname, GLfloat param );
+typedef void ( *OGLFncPixelStorei )( GLenum pname, GLint param );
+typedef void ( *OGLFncGenTextures )( GLsizei n, GLuint *textures );
+typedef GLboolean ( *OGLFncIsTexture )( GLuint texture );
+typedef void ( *OGLFncBindTexture )( GLenum target, GLuint texture );
+typedef void ( *OGLFncDeleteTextures )( GLsizei n, const GLuint *textures );
+typedef GLboolean ( *OGLFncAreTexturesResident )( GLsizei n, const GLuint *textures, GLboolean *residences );
+typedef void ( *OGLFncPrioritizeTextures )( GLsizei n, const GLuint *textures, const GLclampf *priorities );
+typedef void ( *OGLFncTexEnvf )( GLenum target, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexEnvfv )( GLenum target, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexEnvi )( GLenum target, GLenum pname, GLint param );
+typedef void ( *OGLFncTexEnviv )( GLenum target, GLenum pname, const GLint *params );
+typedef void ( *OGLFncTexParameterf )( GLenum target, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexParameterfv )( GLenum target, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexParameteri )( GLenum target, GLenum pname, GLint param );
+typedef void ( *OGLFncTexParameteriv )( GLenum target, GLenum pname, const GLint *params );
+typedef void ( *OGLFncTexGend )( GLenum coord, GLenum pname, GLdouble param );
+typedef void ( *OGLFncTexGendv )( GLenum coord, GLenum pname, const GLdouble *params );
+typedef void ( *OGLFncTexGenf )( GLenum coord, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexGenfv )( GLenum coord, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexGeni )( GLenum coord, GLenum pname, GLint param );
+typedef void ( *OGLFncTexGeniv )( GLenum coord, GLenum pname, const GLint *params );
+typedef void ( *OGLFncGetIntegerv )( GLenum pname, GLint *params );
+typedef void ( *OGLFncPolygonOffset ) ( GLfloat factor, GLfloat units );
+typedef void ( *OGLFncScissor ) ( GLint x, GLint y, GLsizei width, GLsizei height );
+
+typedef void ( *OGLFncEnableClientState ) ( GLenum array );
+typedef void ( *OGLFncDisableClientState ) ( GLenum array );
+typedef void ( *OGLFncVertexPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncColorPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncIndexPointer ) ( GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncNormalPointer ) ( GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncTexCoordPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncEdgeFlagPointer ) ( GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncArrayElement ) ( GLint i );
+typedef void ( *OGLFncDrawElements ) ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices );
+typedef void ( *OGLFncDrawArrays ) ( GLenum mode, GLint first, GLsizei count );
+typedef void ( *OGLFncInterleavedArrays ) ( GLenum format, GLsizei stride, const GLvoid *pointer );
+
+typedef void ( *OGLFncLoadIdentity ) ();
+typedef void ( *OGLFncBlendFunc ) ( GLenum sfactor, GLenum dfactor );
+
+// ----------
+// - Macros -
+// ----------
+
+#define PGRAPHICS mpOutDev->mpGraphics
+
+#ifndef REMOTE_APPSERVER
+#define OGL_INIT() (mpOGL && (mpOutDev->mpGraphics || mpOutDev->ImplGetGraphics()))
+#else
+#define OGL_INIT() (mpOGL && (mpOutDev->mpGraphics || mpOutDev->ImplGetGraphics()))
+#endif
+
+#define INIT_OGLFNC( FncName ) static OGLFnc##FncName pImplOpenGLFnc##FncName = NULL;
+#define GET_OGLFNC_GL( FncName ) \
+pImplOpenGLFnc##FncName = (OGLFnc##FncName##) mpOGL->GetOGLFnc( "gl" #FncName ); \
+if( !pImplOpenGLFnc##FncName ) bRet = FALSE;
+
+// ----------
+// - OpenGL -
+// ----------
+
+static BOOL bImplOpenGLFncPtrInitialized = FALSE;
+
+INIT_OGLFNC( ClearDepth );
+INIT_OGLFNC( DepthFunc );
+INIT_OGLFNC( Enable );
+INIT_OGLFNC( Disable );
+INIT_OGLFNC( DepthMask );
+INIT_OGLFNC( ShadeModel );
+INIT_OGLFNC( EdgeFlag );
+INIT_OGLFNC( Clear );
+INIT_OGLFNC( Flush );
+INIT_OGLFNC( Finish );
+INIT_OGLFNC( Viewport );
+INIT_OGLFNC( Begin );
+INIT_OGLFNC( End );
+INIT_OGLFNC( Vertex3dv );
+INIT_OGLFNC( Normal3dv );
+INIT_OGLFNC( Color4ub );
+INIT_OGLFNC( Materialfv );
+INIT_OGLFNC( Materialf );
+INIT_OGLFNC( LightModelfv );
+INIT_OGLFNC( LightModelf );
+INIT_OGLFNC( Lightfv );
+INIT_OGLFNC( Lightf );
+INIT_OGLFNC( PolygonMode );
+INIT_OGLFNC( CullFace );
+INIT_OGLFNC( PointSize );
+INIT_OGLFNC( LineWidth );
+INIT_OGLFNC( MatrixMode );
+INIT_OGLFNC( LoadMatrixd );
+INIT_OGLFNC( TexCoord2dv );
+INIT_OGLFNC( TexCoord3dv );
+INIT_OGLFNC( TexImage1D );
+INIT_OGLFNC( TexImage2D );
+INIT_OGLFNC( CopyTexImage1D );
+INIT_OGLFNC( CopyTexImage2D );
+INIT_OGLFNC( CopyTexSubImage1D );
+INIT_OGLFNC( CopyTexSubImage2D );
+INIT_OGLFNC( PixelTransferf );
+INIT_OGLFNC( PixelTransferi );
+INIT_OGLFNC( GetTexLevelParameterfv );
+INIT_OGLFNC( GetTexLevelParameteriv );
+INIT_OGLFNC( GetTexParameterfv );
+INIT_OGLFNC( GetTexParameteriv );
+INIT_OGLFNC( TexSubImage1D );
+INIT_OGLFNC( TexSubImage2D );
+INIT_OGLFNC( PixelStoref );
+INIT_OGLFNC( PixelStorei );
+INIT_OGLFNC( GenTextures );
+INIT_OGLFNC( IsTexture );
+INIT_OGLFNC( BindTexture );
+INIT_OGLFNC( DeleteTextures );
+INIT_OGLFNC( AreTexturesResident );
+INIT_OGLFNC( PrioritizeTextures );
+INIT_OGLFNC( TexEnvf );
+INIT_OGLFNC( TexEnvfv );
+INIT_OGLFNC( TexEnvi );
+INIT_OGLFNC( TexEnviv );
+INIT_OGLFNC( TexParameterf );
+INIT_OGLFNC( TexParameterfv );
+INIT_OGLFNC( TexParameteri );
+INIT_OGLFNC( TexParameteriv );
+INIT_OGLFNC( TexGend );
+INIT_OGLFNC( TexGendv );
+INIT_OGLFNC( TexGenf );
+INIT_OGLFNC( TexGenfv );
+INIT_OGLFNC( TexGeni );
+INIT_OGLFNC( TexGeniv );
+INIT_OGLFNC( GetIntegerv );
+INIT_OGLFNC( PolygonOffset );
+INIT_OGLFNC( Scissor );
+
+INIT_OGLFNC( EnableClientState );
+INIT_OGLFNC( DisableClientState );
+INIT_OGLFNC( VertexPointer );
+INIT_OGLFNC( ColorPointer );
+INIT_OGLFNC( IndexPointer );
+INIT_OGLFNC( NormalPointer );
+INIT_OGLFNC( TexCoordPointer );
+INIT_OGLFNC( EdgeFlagPointer );
+INIT_OGLFNC( ArrayElement );
+INIT_OGLFNC( DrawElements );
+INIT_OGLFNC( DrawArrays );
+INIT_OGLFNC( InterleavedArrays );
+
+INIT_OGLFNC( LoadIdentity );
+INIT_OGLFNC( BlendFunc );
+
+// ------------------------------------------------------------------------
+
+BOOL OpenGL::ImplInitFncPointers()
+{
+#ifndef REMOTE_APPSERVER
+ BOOL bRet = TRUE;
+
+ GET_OGLFNC_GL( ClearDepth );
+ GET_OGLFNC_GL( DepthFunc );
+ GET_OGLFNC_GL( Enable );
+ GET_OGLFNC_GL( Disable );
+ GET_OGLFNC_GL( DepthMask );
+ GET_OGLFNC_GL( ShadeModel );
+ GET_OGLFNC_GL( EdgeFlag );
+ GET_OGLFNC_GL( Clear );
+ GET_OGLFNC_GL( Flush );
+ GET_OGLFNC_GL( Finish );
+ GET_OGLFNC_GL( Viewport );
+ GET_OGLFNC_GL( Begin );
+ GET_OGLFNC_GL( End );
+ GET_OGLFNC_GL( Vertex3dv );
+ GET_OGLFNC_GL( Normal3dv );
+ GET_OGLFNC_GL( Color4ub );
+ GET_OGLFNC_GL( Materialfv );
+ GET_OGLFNC_GL( Materialf );
+ GET_OGLFNC_GL( LightModelfv );
+ GET_OGLFNC_GL( LightModelf );
+ GET_OGLFNC_GL( Lightfv );
+ GET_OGLFNC_GL( Lightf );
+ GET_OGLFNC_GL( PolygonMode );
+ GET_OGLFNC_GL( CullFace );
+ GET_OGLFNC_GL( PointSize );
+ GET_OGLFNC_GL( LineWidth );
+ GET_OGLFNC_GL( MatrixMode );
+ GET_OGLFNC_GL( LoadMatrixd );
+ GET_OGLFNC_GL( TexCoord2dv );
+ GET_OGLFNC_GL( TexCoord3dv );
+ GET_OGLFNC_GL( TexImage1D );
+ GET_OGLFNC_GL( TexImage2D );
+ GET_OGLFNC_GL( CopyTexImage1D );
+ GET_OGLFNC_GL( CopyTexImage2D );
+ GET_OGLFNC_GL( CopyTexSubImage1D );
+ GET_OGLFNC_GL( CopyTexSubImage2D );
+ GET_OGLFNC_GL( PixelTransferf );
+ GET_OGLFNC_GL( PixelTransferi );
+ GET_OGLFNC_GL( GetTexLevelParameterfv );
+ GET_OGLFNC_GL( GetTexLevelParameteriv );
+ GET_OGLFNC_GL( GetTexParameterfv );
+ GET_OGLFNC_GL( GetTexParameteriv );
+ GET_OGLFNC_GL( TexSubImage1D );
+ GET_OGLFNC_GL( TexSubImage2D );
+ GET_OGLFNC_GL( PixelStoref );
+ GET_OGLFNC_GL( PixelStorei );
+ GET_OGLFNC_GL( GenTextures );
+ GET_OGLFNC_GL( IsTexture );
+ GET_OGLFNC_GL( BindTexture );
+ GET_OGLFNC_GL( DeleteTextures );
+ GET_OGLFNC_GL( AreTexturesResident );
+ GET_OGLFNC_GL( PrioritizeTextures );
+ GET_OGLFNC_GL( TexEnvf );
+ GET_OGLFNC_GL( TexEnvfv );
+ GET_OGLFNC_GL( TexEnvi );
+ GET_OGLFNC_GL( TexEnviv );
+ GET_OGLFNC_GL( TexParameterf );
+ GET_OGLFNC_GL( TexParameterfv );
+ GET_OGLFNC_GL( TexParameteri );
+ GET_OGLFNC_GL( TexParameteriv );
+ GET_OGLFNC_GL( TexGend );
+ GET_OGLFNC_GL( TexGendv );
+ GET_OGLFNC_GL( TexGenf );
+ GET_OGLFNC_GL( TexGenfv );
+ GET_OGLFNC_GL( TexGeni );
+ GET_OGLFNC_GL( TexGeniv );
+ GET_OGLFNC_GL( GetIntegerv );
+ GET_OGLFNC_GL( PolygonOffset );
+ GET_OGLFNC_GL( Scissor );
+
+ GET_OGLFNC_GL( EnableClientState );
+ GET_OGLFNC_GL( DisableClientState );
+ GET_OGLFNC_GL( VertexPointer );
+ GET_OGLFNC_GL( ColorPointer );
+ GET_OGLFNC_GL( IndexPointer );
+ GET_OGLFNC_GL( NormalPointer );
+ GET_OGLFNC_GL( TexCoordPointer );
+ GET_OGLFNC_GL( EdgeFlagPointer );
+ GET_OGLFNC_GL( ArrayElement );
+ GET_OGLFNC_GL( DrawElements );
+ GET_OGLFNC_GL( DrawArrays );
+ GET_OGLFNC_GL( InterleavedArrays );
+
+ GET_OGLFNC_GL( LoadIdentity );
+ GET_OGLFNC_GL( BlendFunc );
+
+ return bRet;
+#else
+ return FALSE;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+OpenGL::OpenGL( OutputDevice* pOutDev ) :
+ mpOutDev( pOutDev )
+{
+ ImplInit();
+}
+
+// ------------------------------------------------------------------------
+
+OpenGL::~OpenGL()
+{
+#ifndef REMOTE_APPSERVER
+ delete mpOGL;
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ImplInit()
+{
+#ifndef REMOTE_APPSERVER
+ if( PGRAPHICS || mpOutDev->ImplGetGraphics() )
+ {
+ mpOGL = new SalOpenGL( PGRAPHICS );
+
+ if ( !mpOGL->Create() || (!bImplOpenGLFncPtrInitialized && !ImplInitFncPointers()) )
+ {
+ delete mpOGL;
+ mpOGL = NULL;
+ }
+ else
+ bImplOpenGLFncPtrInitialized = TRUE;
+ }
+ else
+ mpOGL = NULL;
+#else
+ mpOGL = NULL;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::SetConnectOutputDevice( OutputDevice* pOutDev )
+{
+#ifndef REMOTE_APPSERVER
+ delete mpOGL;
+ mpOutDev = pOutDev;
+ ImplInit();
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ClearDepth( GLclampd fDepth )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncClearDepth( fDepth );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DepthFunc( GLenum eFunc )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDepthFunc( eFunc );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Enable( GLenum eCap )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnable( eCap );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Disable( GLenum eCap )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDisable( eCap );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DepthMask( GLboolean bFlag )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDepthMask( bFlag );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ShadeModel( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncShadeModel( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EdgeFlag( GLboolean bFlag )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEdgeFlag( bFlag );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Clear( GLbitfield nMask )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+#if defined UNX && ! defined MACOSX
+ mpOGL->StartScene( PGRAPHICS );
+#endif
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncClear( nMask );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Flush()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncFlush();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Finish()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncFinish();
+#if defined UNX && ! defined MACOSX
+ mpOGL->StopScene();
+#endif
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Viewport( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ long nOutHeight;
+
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ nOutHeight = ( (Window*) mpOutDev )->mpFrameWindow->mnOutHeight;
+ else
+ nOutHeight = mpOutDev->mnOutHeight;
+
+ mpOGL->OGLEntry( PGRAPHICS );
+
+ pImplOpenGLFncViewport( nX + mpOutDev->mnOutOffX,
+ nOutHeight - nY - nHeight - mpOutDev->mnOutOffY,
+ nWidth, nHeight );
+
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Begin( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBegin( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::End()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnd();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Vertex3dv( const GLdouble* fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncVertex3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Normal3dv( const GLdouble* fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncNormal3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Color4ub( GLubyte cRed, GLubyte cGreen, GLubyte cBlue, GLubyte cAlpha )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncColor4ub( cRed, cGreen, cBlue, cAlpha );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Materialfv( GLenum eFace, GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMaterialfv( eFace, ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Materialf( GLenum eFace, GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMaterialf( eFace, ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LightModelfv( GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightModelfv( ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LightModelf( GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightModelf( ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Lightfv( GLenum eLight, GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightfv( eLight, ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Lightf( GLenum eLight, GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightf( eLight, ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PolygonMode( GLenum eFace, GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPolygonMode( eFace, eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CullFace( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCullFace( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PointSize( GLfloat fSize )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPointSize( fSize );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LineWidth( GLfloat fWidth )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLineWidth( fWidth );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::MatrixMode( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMatrixMode( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LoadMatrixd( const GLdouble *fM )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLoadMatrixd( fM );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoord2dv( const GLdouble *pParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoord2dv( pParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoord3dv( const GLdouble *fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoord3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexImage1D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexImage1D( target, level, internalformat, width, border, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexImage2D( target, level, internalformat, width, height, border, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexImage1D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexImage1D( target, level, internalFormat, x, y, width, border );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexImage2D( target, level, internalFormat, x, y, width, height, border );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexSubImage1D( target, level, xoffset, x, y, width );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelTransferf( GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelTransferf( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelTransferi( GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelTransferi( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexLevelParameterfv( GLenum target, GLint level, GLenum pname, GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexLevelParameterfv( target, level, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexLevelParameteriv( target, level, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexParameterfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexParameteriv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexSubImage1D( target, level, xoffset, width, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelStoref( GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelStoref( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelStorei( GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelStorei( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GenTextures( GLsizei n, GLuint *textures )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGenTextures( n, textures );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GLboolean OpenGL::IsTexture( GLuint texture )
+{
+ GLboolean bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ bRet = pImplOpenGLFncIsTexture( texture );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::BindTexture( GLenum target, GLuint texture )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBindTexture( target, texture );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DeleteTextures( GLsizei n, const GLuint *textures )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDeleteTextures( n, textures );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GLboolean OpenGL::AreTexturesResident( GLsizei n, const GLuint *textures, GLboolean *residences )
+{
+ GLboolean bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ bRet = pImplOpenGLFncAreTexturesResident( n, textures, residences );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PrioritizeTextures( GLsizei n, const GLuint *textures, const GLclampf *priorities )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPrioritizeTextures( n, textures, priorities );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvf( GLenum target, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvf( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvfv( GLenum target, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvi( GLenum target, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvi( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnviv( GLenum target, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnviv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameterf( GLenum target, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameterf( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameterfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameteri( GLenum target, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameteri( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameteriv( GLenum target, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameteriv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGend( GLenum coord, GLenum pname, GLdouble param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGend( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGendv( GLenum coord, GLenum pname, const GLdouble *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGendv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGenf( GLenum coord, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGenf( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGenfv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGeni( GLenum coord, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGeni( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGeniv( GLenum coord, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGeniv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetIntegerv( GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetIntegerv( pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PolygonOffset( GLfloat factor, GLfloat units )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPolygonOffset( factor, units );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Scissor( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ long nOutHeight;
+
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ nOutHeight = ( (Window*) mpOutDev )->mpFrameWindow->mnOutHeight;
+ else
+ nOutHeight = mpOutDev->mnOutHeight;
+
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncScissor( nX + mpOutDev->mnOutOffX,
+ nOutHeight - nY - nHeight - mpOutDev->mnOutOffY,
+ nWidth, nHeight );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EnableClientState( GLenum array )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnableClientState( array );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DisableClientState( GLenum array )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDisableClientState( array );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::VertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncVertexPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncColorPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::IndexPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncIndexPointer( type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::NormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncNormalPointer( type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoordPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EdgeFlagPointer( GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEdgeFlagPointer( stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ArrayElement( GLint i )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncArrayElement( i );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDrawElements( mode, count, type, indices );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DrawArrays( GLenum mode, GLint first, GLsizei count )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDrawArrays( mode, first, count );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::InterleavedArrays( GLenum format, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncInterleavedArrays( format, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LoadIdentity( )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLoadIdentity();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::BlendFunc( GLenum sfactor, GLenum dfactor )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBlendFunc( sfactor, dfactor);
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
new file mode 100644
index 000000000000..591ecf8c8f8d
--- /dev/null
+++ b/vcl/source/gdi/outdev.cxx
@@ -0,0 +1,1927 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+#include <tools/ref.hxx>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _SV_SALVD_HXX
+#include <salvd.hxx>
+#endif
+#ifndef _SV_SALPRN_HXX
+#include <salprn.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_SALOTYPE_HXX
+#include <salotype.hxx>
+#endif
+#ifndef _SV_OPENGL_HXX
+#include <opengl.hxx>
+#endif
+#ifndef _VCL_IMPLNCVT_HXX
+#include <implncvt.hxx>
+#endif
+#ifndef _SV_OUTDEV3D_HXX
+#include <outdev3d.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _VCL_UNOWRAP_HXX
+#include <unowrap.hxx>
+#endif
+
+#include <com/sun/star/awt/XGraphics.hpp>
+
+DBG_NAME( OutputDevice );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+DBG_NAMEEX( Region );
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgCheckOutputDevice( const void* pObj )
+{
+ DBG_TESTSOLARMUTEX();
+
+ const OutputDevice* pOutDev = (OutputDevice*)pObj;
+
+ if ( (pOutDev->GetOutDevType() != OUTDEV_DONTKNOW) &&
+ (pOutDev->GetOutDevType() != OUTDEV_WINDOW) &&
+ (pOutDev->GetOutDevType() != OUTDEV_PRINTER) &&
+ (pOutDev->GetOutDevType() != OUTDEV_VIRDEV) )
+ return "OutputDevice data overwrite";
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+#define OUTDEV_POLYPOLY_STACKBUF 32
+
+// =======================================================================
+
+struct ImplObjStack
+{
+ ImplObjStack* mpPrev;
+ MapMode* mpMapMode;
+ Region* mpClipRegion;
+ Color* mpLineColor;
+ Color* mpFillColor;
+ Font* mpFont;
+ Color* mpTextColor;
+ Color* mpTextFillColor;
+ Color* mpTextLineColor;
+ Point* mpRefPoint;
+ TextAlign meTextAlign;
+ RasterOp meRasterOp;
+ USHORT mnFlags;
+};
+
+// -----------------------------------------------------------------------
+
+static void ImplDeleteObjStack( ImplObjStack* pObjStack )
+{
+ if ( pObjStack->mnFlags & PUSH_LINECOLOR )
+ {
+ if ( pObjStack->mpLineColor )
+ delete pObjStack->mpLineColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_FILLCOLOR )
+ {
+ if ( pObjStack->mpFillColor )
+ delete pObjStack->mpFillColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_FONT )
+ delete pObjStack->mpFont;
+ if ( pObjStack->mnFlags & PUSH_TEXTCOLOR )
+ delete pObjStack->mpTextColor;
+ if ( pObjStack->mnFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( pObjStack->mpTextFillColor )
+ delete pObjStack->mpTextFillColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( pObjStack->mpTextLineColor )
+ delete pObjStack->mpTextLineColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_MAPMODE )
+ {
+ if ( pObjStack->mpMapMode )
+ delete pObjStack->mpMapMode;
+ }
+ if ( pObjStack->mnFlags & PUSH_CLIPREGION )
+ {
+ if ( pObjStack->mpClipRegion )
+ delete pObjStack->mpClipRegion;
+ }
+ if ( pObjStack->mnFlags & PUSH_REFPOINT )
+ {
+ if ( pObjStack->mpRefPoint )
+ delete pObjStack->mpRefPoint;
+ }
+
+ delete pObjStack;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+BOOL OutputDevice::ImplSelectClipRegion( SalGraphics* pGraphics, const Region& rRegion )
+{
+ DBG_TESTSOLARMUTEX();
+
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ULONG nRectCount;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+ BOOL bClipRegion = TRUE;
+
+ nRectCount = rRegion.GetRectCount();
+ pGraphics->BeginSetClipRegion( nRectCount );
+ bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ if ( !pGraphics->UnionClipRegion( nX, nY, nWidth, nHeight ) )
+ bClipRegion = FALSE;
+ DBG_ASSERT( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't cerate region" );
+ bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ pGraphics->EndSetClipRegion();
+ return bClipRegion;
+}
+
+#endif
+
+// =======================================================================
+
+OutputDevice::OutputDevice() :
+ maRegion( REGION_NULL ),
+ maSettings( Application::GetSettings() ),
+ maFillColor( COL_WHITE ),
+ maTextLineColor( COL_TRANSPARENT )
+{
+ DBG_CTOR( OutputDevice, ImplDbgCheckOutputDevice );
+
+ mpGraphics = NULL;
+ mpUnoGraphicsList = NULL;
+ mpPrevGraphics = NULL;
+ mpNextGraphics = NULL;
+ mpMetaFile = NULL;
+ mpFontEntry = NULL;
+ mpFontCache = NULL;
+ mpFontList = NULL;
+ mpGetDevFontList = NULL;
+ mpGetDevSizeList = NULL;
+ mpObjStack = NULL;
+ mpOutDevData = NULL;
+ mp3DContext = NULL;
+ mnOutOffX = 0;
+ mnOutOffY = 0;
+ mnOutWidth = 0;
+ mnOutHeight = 0;
+ mnDPIX = 0;
+ mnDPIY = 0;
+ mnTextOffX = 0;
+ mnTextOffY = 0;
+ mnDrawMode = 0;
+ meOutDevType = OUTDEV_DONTKNOW;
+ mbMap = FALSE;
+ mbClipRegion = FALSE;
+ mbBackground = FALSE;
+ mbOutput = TRUE;
+ mbDevOutput = FALSE;
+ mbOutputClipped = FALSE;
+ maTextColor = maFont.GetColor();
+ maTextFillColorDummy= maFont.GetFillColor();
+ meTextAlign = maFont.GetAlign();
+ meRasterOp = ROP_OVERPAINT;
+ mbLineColor = TRUE;
+ mbFillColor = TRUE;
+ mbInitLineColor = TRUE;
+ mbInitFillColor = TRUE;
+ mbInitFont = TRUE;
+ mbInitTextColor = TRUE;
+ mbInitClipRegion = TRUE;
+ mbClipRegionSet = FALSE;
+ mbKerning = FALSE;
+ mbNewFont = TRUE;
+ mbTextLines = FALSE;
+ mbTextSpecial = FALSE;
+ mbRefPoint = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+OutputDevice::~OutputDevice()
+{
+ DBG_DTOR( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( GetUnoGraphicsList() )
+ {
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ pWrapper->ReleaseAllGraphics( this );
+ delete mpUnoGraphicsList;
+ mpUnoGraphicsList = NULL;
+ }
+
+ if ( mp3DContext )
+ mp3DContext->Destroy( this );
+
+ if ( mpOutDevData )
+ ImplDeInitOutDevData();
+
+ ImplObjStack* pData = mpObjStack;
+ if ( pData )
+ {
+ DBG_ERRORFILE( "OutputDevice::~OutputDevice(): OutputDevice::Push() calls != OutputDevice::Pop() calls" );
+ while ( pData )
+ {
+ ImplObjStack* pTemp = pData;
+ pData = pData->mpPrev;
+ ImplDeleteObjStack( pTemp );
+ }
+ }
+
+ if ( mpFontEntry )
+ mpFontCache->Release( mpFontEntry );
+ if ( mpGetDevFontList )
+ delete mpGetDevFontList;
+ if ( mpGetDevSizeList )
+ delete mpGetDevSizeList;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+int OutputDevice::ImplGetGraphics()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mpGraphics )
+ return TRUE;
+
+ mbInitLineColor = TRUE;
+ mbInitFillColor = TRUE;
+ mbInitFont = TRUE;
+ mbInitTextColor = TRUE;
+ mbInitClipRegion = TRUE;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( meOutDevType == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+
+ mpGraphics = pWindow->mpFrame->GetGraphics();
+ // Wenn wir keinen bekommen haben, versuchen wir uns einen zu klauen
+ if ( !mpGraphics )
+ {
+ OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
+ while ( pReleaseOutDev )
+ {
+ if ( ((Window*)pReleaseOutDev)->mpFrame == pWindow->mpFrame )
+ break;
+ pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
+ }
+
+ if ( pReleaseOutDev )
+ {
+ mpGraphics = pReleaseOutDev->mpGraphics;
+ pReleaseOutDev->ImplReleaseGraphics( FALSE );
+ }
+ else
+ {
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastWinGraphics )
+ break;
+ pSVData->maGDIData.mpLastWinGraphics->ImplReleaseGraphics();
+ mpGraphics = pWindow->mpFrame->GetGraphics();
+ }
+ }
+ }
+
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
+ pSVData->maGDIData.mpFirstWinGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastWinGraphics )
+ pSVData->maGDIData.mpLastWinGraphics = this;
+ }
+ }
+ else if ( meOutDevType == OUTDEV_VIRDEV )
+ {
+ VirtualDevice* pVirDev = (VirtualDevice*)this;
+
+ if ( pVirDev->mpVirDev )
+ {
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ break;
+ pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
+ pSVData->maGDIData.mpFirstVirGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ pSVData->maGDIData.mpLastVirGraphics = this;
+ }
+ }
+ }
+ else if ( meOutDevType == OUTDEV_PRINTER )
+ {
+ Printer* pPrinter = (Printer*)this;
+
+ if ( pPrinter->mpJobGraphics )
+ mpGraphics = pPrinter->mpJobGraphics;
+ else if ( pPrinter->mpDisplayDev )
+ {
+ VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ break;
+ pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
+ pSVData->maGDIData.mpFirstVirGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ pSVData->maGDIData.mpLastVirGraphics = this;
+ }
+ }
+ else
+ {
+ mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastPrnGraphics )
+ break;
+ pSVData->maGDIData.mpLastPrnGraphics->ImplReleaseGraphics();
+ mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstPrnGraphics;
+ pSVData->maGDIData.mpFirstPrnGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastPrnGraphics )
+ pSVData->maGDIData.mpLastPrnGraphics = this;
+ }
+ }
+ }
+
+ if ( mpGraphics )
+ {
+ mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp) );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplReleaseGraphics( BOOL bRelease )
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !mpGraphics )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( meOutDevType == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+
+ if ( bRelease )
+ pWindow->mpFrame->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
+ }
+ else if ( meOutDevType == OUTDEV_VIRDEV )
+ {
+ VirtualDevice* pVirDev = (VirtualDevice*)this;
+
+ if ( bRelease )
+ pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
+ }
+ else if ( meOutDevType == OUTDEV_PRINTER )
+ {
+ Printer* pPrinter = (Printer*)this;
+
+ if ( !pPrinter->mpJobGraphics )
+ {
+ if ( pPrinter->mpDisplayDev )
+ {
+ VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
+ if ( bRelease )
+ pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
+ }
+ else
+ {
+ if ( bRelease )
+ pPrinter->mpInfoPrinter->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstPrnGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastPrnGraphics = mpPrevGraphics;
+ }
+ }
+ }
+
+ mpGraphics = NULL;
+ mpPrevGraphics = NULL;
+ mpNextGraphics = NULL;
+
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitOutDevData()
+{
+ if ( !mpOutDevData )
+ {
+ mpOutDevData = new ImplOutDevData;
+ mpOutDevData->mpRotateDev = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDeInitOutDevData()
+{
+ if ( mpOutDevData )
+ {
+ if ( mpOutDevData->mpRotateDev )
+ delete mpOutDevData->mpRotateDev;
+ delete mpOutDevData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitLineColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+#ifndef REMOTE_APPSERVER
+ if( mbLineColor )
+ {
+ if( ROP_0 == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_0 );
+ else if( ROP_1 == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_1 );
+ else if( ROP_INVERT == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_INVERT );
+ else
+ mpGraphics->SetLineColor( ImplColorToSal( maLineColor ) );
+ }
+ else
+ mpGraphics->SetLineColor();
+#else
+ mpGraphics->SetLineColor( maLineColor );
+#endif
+
+ mbInitLineColor = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitFillColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+#ifndef REMOTE_APPSERVER
+ if( mbFillColor )
+ {
+ if( ROP_0 == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_0 );
+ else if( ROP_1 == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_1 );
+ else if( ROP_INVERT == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_INVERT );
+ else
+ mpGraphics->SetFillColor( ImplColorToSal( maFillColor ) );
+ }
+ else
+ mpGraphics->SetFillColor();
+#else
+ mpGraphics->SetFillColor( maFillColor );
+#endif
+
+ mbInitFillColor = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitClipRegion()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+ Region aRegion;
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( pWindow->mpFrameData->mpFirstBackWin )
+ pWindow->ImplInvalidateAllOverlapBackgrounds();
+ if ( pWindow->mbInPaint )
+ aRegion = *(pWindow->mpPaintRegion);
+ else
+ aRegion = *(pWindow->ImplGetWinChildClipRegion());
+ if ( mbClipRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( maRegion ) );
+ if ( aRegion.IsEmpty() )
+ mbOutputClipped = TRUE;
+ else
+ {
+ mbOutputClipped = FALSE;
+#ifndef REMOTE_APPSERVER
+ ImplSelectClipRegion( mpGraphics, aRegion );
+#else
+ mpGraphics->SetClipRegion( aRegion );
+#endif
+ }
+ mbClipRegionSet = TRUE;
+ }
+ else
+ {
+ if ( mbClipRegion )
+ {
+ if ( maRegion.IsEmpty() )
+ mbOutputClipped = TRUE;
+ else
+ {
+ mbOutputClipped = FALSE;
+#ifndef REMOTE_APPSERVER
+ ImplSelectClipRegion( mpGraphics, maRegion );
+#else
+ mpGraphics->SetClipRegion( maRegion );
+#endif
+ }
+
+ mbClipRegionSet = TRUE;
+ }
+ else
+ {
+ if ( mbClipRegionSet )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->ResetClipRegion();
+#else
+ mpGraphics->SetClipRegion();
+#endif
+ mbClipRegionSet = FALSE;
+ }
+
+ mbOutputClipped = FALSE;
+ }
+ }
+
+ mbInitClipRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplSetClipRegion( const Region* pRegion )
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !pRegion )
+ {
+ if ( mbClipRegion )
+ {
+ maRegion = Region( REGION_NULL );
+ mbClipRegion = FALSE;
+ mbInitClipRegion = TRUE;
+ }
+ }
+ else
+ {
+ maRegion = *pRegion;
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetClipRegion()
+{
+ DBG_TRACE( "OutputDevice::SetClipRegion()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaClipRegionAction( Region(), FALSE ) );
+
+ ImplSetClipRegion( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetClipRegion( const Region& rRegion )
+{
+ DBG_TRACE( "OutputDevice::SetClipRegion( rRegion )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaClipRegionAction( rRegion, TRUE ) );
+
+ if ( rRegion.GetType() == REGION_NULL )
+ ImplSetClipRegion( NULL );
+ else
+ {
+ Region aRegion = LogicToPixel( rRegion );
+ ImplSetClipRegion( &aRegion );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::GetClipRegion() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ return PixelToLogic( maRegion );
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::GetActiveClipRegion() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Region aRegion( REGION_NULL );
+ Window* pWindow = (Window*)this;
+ if ( pWindow->mbInPaint )
+ {
+ aRegion = *(pWindow->mpPaintRegion);
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+ }
+ if ( mbClipRegion )
+ aRegion.Intersect( maRegion );
+ return PixelToLogic( aRegion );
+ }
+ else
+ return GetClipRegion();
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::MoveClipRegion( long nHorzMove, long nVertMove )
+{
+ DBG_TRACE( "OutputDevice::MoveClipRegion()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbClipRegion )
+ {
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaMoveClipRegionAction( nHorzMove, nVertMove ) );
+
+ maRegion.Move( ImplLogicWidthToDevicePixel( nHorzMove ),
+ ImplLogicHeightToDevicePixel( nVertMove ) );
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::IntersectClipRegion( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::IntersectClipRegion( rRect )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaISectRectClipRegionAction( rRect ) );
+
+ Rectangle aRect = LogicToPixel( rRect );
+ maRegion.Intersect( aRect );
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::IntersectClipRegion( const Region& rRegion )
+{
+ DBG_TRACE( "OutputDevice::IntersectClipRegion( rRegion )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rRegion.GetType();
+
+ if ( eType != REGION_NULL )
+ {
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaISectRegionClipRegionAction( rRegion ) );
+
+ Region aRegion = LogicToPixel( rRegion );
+ maRegion.Intersect( aRegion );
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetDrawMode( ULONG nDrawMode )
+{
+ DBG_TRACE1( "OutputDevice::SetDrawMode( %lx )", nDrawMode );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ mnDrawMode = nDrawMode;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRasterOp( RasterOp eRasterOp )
+{
+ DBG_TRACE1( "OutputDevice::SetRasterOp( %d )", (int)eRasterOp );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) );
+
+ if ( meRasterOp != eRasterOp )
+ {
+ meRasterOp = eRasterOp;
+ mbInitLineColor = mbInitFillColor = TRUE;
+
+#ifndef REMOTE_APPSERVER
+ if( mpGraphics || ImplGetGraphics() )
+ mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp) );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if( pGraphics )
+ pGraphics->SetRasterOp( eRasterOp );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetLineColor()
+{
+ DBG_TRACE( "OutputDevice::SetLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineColorAction( Color(), FALSE ) );
+
+ if ( mbLineColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = FALSE;
+ maLineColor = Color( COL_TRANSPARENT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetLineColor( const Color& rColor )
+{
+ DBG_TRACE1( "OutputDevice::SetLineColor( %lx )", rColor.GetColor() );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKLINE )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITELINE )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80);
+ }
+ }
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineColorAction( aColor, TRUE ) );
+
+ if( ImplIsColorTransparent( aColor ) )
+ {
+ if ( mbLineColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = FALSE;
+ maLineColor = Color( COL_TRANSPARENT );
+ }
+ }
+ else
+ {
+ if( maLineColor != aColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = TRUE;
+ maLineColor = aColor;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetFillColor()
+{
+ DBG_TRACE( "OutputDevice::SetFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color(), FALSE ) );
+
+ if ( mbFillColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = FALSE;
+ maFillColor = Color( COL_TRANSPARENT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetFillColor( const Color& rColor )
+{
+ DBG_TRACE1( "OutputDevice::SetFillColor( %lx )", rColor.GetColor() );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL |
+ DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKFILL )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITEFILL )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+ else if( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aColor = Color( COL_TRANSPARENT );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDFILL )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80);
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFillColorAction( aColor, TRUE ) );
+
+ if ( ImplIsColorTransparent( aColor ) )
+ {
+ if ( mbFillColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = FALSE;
+ maFillColor = Color( COL_TRANSPARENT );
+ }
+ }
+ else
+ {
+ if ( maFillColor != aColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = TRUE;
+ maFillColor = aColor;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetBackground()
+{
+ DBG_TRACE( "OutputDevice::SetBackground()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ maBackground = Wallpaper();
+ mbBackground = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetBackground( const Wallpaper& rBackground )
+{
+ DBG_TRACE( "OutputDevice::SetBackground( rBackground )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ maBackground = rBackground;
+
+ if( rBackground.GetStyle() == WALLPAPER_NULL )
+ mbBackground = FALSE;
+ else
+ mbBackground = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRefPoint()
+{
+ DBG_TRACE( "OutputDevice::SetRefPoint()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRefPointAction( Point(), FALSE ) );
+
+ mbRefPoint = FALSE;
+ maRefPoint.X() = maRefPoint.Y() = 0L;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRefPoint( const Point& rRefPoint )
+{
+ DBG_TRACE( "OutputDevice::SetRefPoint( rRefPoint )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, TRUE ) );
+
+ mbRefPoint = TRUE;
+ maRefPoint = rRefPoint;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ Point aEndPt = ImplLogicToDevicePixel( rEndPt );
+
+ mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawLine( ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt,
+ const LineInfo& rLineInfo )
+{
+ DBG_TRACE( "OutputDevice::DrawLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rLineInfo.IsDefault() )
+ {
+ DrawLine( rStartPt, rEndPt );
+ return;
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt, rLineInfo ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || ( LINE_NONE == rLineInfo.GetStyle() ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( ( aInfo.GetWidth() > 1L ) || ( LINE_DASH == aInfo.GetStyle() ) )
+ {
+ Polygon aPoly( 2 ); aPoly[ 0 ] = rStartPt; aPoly[ 1 ] = rEndPt;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( aPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+
+ if ( aInfo.GetWidth() > 1 )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->ImplGetConstPointAry() );
+
+ SetFillColor( aOldFillColor );
+ SetLineColor( aOldLineColor );
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ for ( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawLine( (*pPoly)[ 0 ].X(), (*pPoly)[ 0 ].Y(), (*pPoly)[ 1 ].X(), (*pPoly)[ 1 ].Y() );
+ }
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) );
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y() );
+ }
+
+#else
+
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( ( aInfo.GetWidth() > 1L ) || ( LINE_DASH == aInfo.GetStyle() ) )
+ {
+ Polygon aPoly( 2 ); aPoly[ 0 ] = rStartPt; aPoly[ 1 ] = rEndPt;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( aPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+
+ if ( aInfo.GetWidth() > 1 )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolygon( *pPoly );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ for ( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() ) {
+ Point xPoint((*pPoly)[ 0 ].X(), (*pPoly)[ 0 ].Y());
+ Point yPoint((*pPoly)[ 1 ].X(), (*pPoly)[ 1 ].Y());
+ mpGraphics->DrawLine( xPoint, yPoint );
+ }
+ }
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ pGraphics->DrawLine( ImplLogicToDevicePixel( rStartPt ), ImplLogicToDevicePixel( rEndPt ) );
+ }
+ }
+
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawRect( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::DrawRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRectAction( rRect ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawRect( aRect );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyLine( const Polygon& rPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyLineAction( rPoly ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || (nPoints < 2) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Polygon aPoly = ImplLogicToDevicePixel( rPoly );
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolyLine( nPoints, pPtAry );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawPolyLine( ImplLogicToDevicePixel( rPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if ( rLineInfo.IsDefault() )
+ {
+ DrawPolyLine( rPoly );
+ return;
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( aInfo.GetWidth() > 1L )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->ImplGetConstPointAry() );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( LINE_DASH == aInfo.GetStyle() )
+ {
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolyLine( pPoly->GetSize(), (const SalPoint*)pPoly->ImplGetConstPointAry() );
+ }
+ else
+ mpGraphics->DrawPolyLine( nPoints, (const SalPoint*) ImplLogicToDevicePixel( rPoly ).ImplGetConstPointAry() );
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+
+ if ( pGraphics )
+ {
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( aInfo.GetWidth() > 1L )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolygon( *pPoly );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( LINE_DASH == aInfo.GetStyle() )
+ {
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolyLine( *pPoly );
+ }
+ else
+ pGraphics->DrawPolyLine( ImplLogicToDevicePixel( rPoly ) );
+ }
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolygon( const Polygon& rPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolygon()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ Polygon aPoly = ImplLogicToDevicePixel( rPoly );
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nPoints, pPtAry );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawPolygon( ImplLogicToDevicePixel( rPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyPolygon()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
+
+ USHORT nPoly = rPolyPoly.Count();
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ if ( nPoly == 1 )
+ {
+ Polygon aPoly = ImplLogicToDevicePixel( rPolyPoly.GetObject( 0 ) );
+ USHORT nSize = aPoly.GetSize();
+ if ( nSize >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nSize, pPtAry );
+ }
+ }
+ else
+ {
+ PolyPolygon aPolyPoly = ImplLogicToDevicePixel( rPolyPoly );
+ ULONG aStackAry1[OUTDEV_POLYPOLY_STACKBUF];
+ PCONSTSALPOINT aStackAry2[OUTDEV_POLYPOLY_STACKBUF];
+ ULONG* pPointAry;
+ PCONSTSALPOINT* pPointAryAry;
+ USHORT i = 0;
+ if ( nPoly > OUTDEV_POLYPOLY_STACKBUF )
+ {
+ pPointAry = new ULONG[nPoly];
+ pPointAryAry = new PCONSTSALPOINT[nPoly];
+ }
+ else
+ {
+ pPointAry = aStackAry1;
+ pPointAryAry = aStackAry2;
+ }
+ do
+ {
+ const Polygon& rPoly = aPolyPoly.GetObject( i );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize )
+ {
+ pPointAry[i] = nSize;
+ pPointAryAry[i] = (PCONSTSALPOINT)rPoly.ImplGetConstPointAry();
+ i++;
+ }
+ else
+ nPoly--;
+ }
+ while ( i < nPoly );
+
+ if ( nPoly == 1 )
+ mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry );
+ else
+ mpGraphics->DrawPolyPolygon( nPoly, pPointAry, pPointAryAry );
+
+ if ( pPointAry != aStackAry1 )
+ {
+ delete pPointAry;
+ delete pPointAryAry;
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ if ( nPoly == 1 )
+ {
+ Polygon aPoly = ImplLogicToDevicePixel( rPolyPoly.GetObject( 0 ) );
+ USHORT nSize = aPoly.GetSize();
+ if ( nSize >= 2 )
+ pGraphics->DrawPolygon( aPoly );
+ }
+ else
+ pGraphics->DrawPolyPolygon( ImplLogicToDevicePixel( rPolyPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Push( USHORT nFlags )
+{
+ DBG_TRACE( "OutputDevice::Push()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPushAction( nFlags ) );
+
+ ImplObjStack* pData = new ImplObjStack;
+ pData->mpPrev = mpObjStack;
+ mpObjStack = pData;
+
+ pData->mnFlags = nFlags;
+
+ if ( nFlags & PUSH_LINECOLOR )
+ {
+ if ( mbLineColor )
+ pData->mpLineColor = new Color( maLineColor );
+ else
+ pData->mpLineColor = NULL;
+ }
+ if ( nFlags & PUSH_FILLCOLOR )
+ {
+ if ( mbFillColor )
+ pData->mpFillColor = new Color( maFillColor );
+ else
+ pData->mpFillColor = NULL;
+ }
+ if ( nFlags & PUSH_FONT )
+ pData->mpFont = new Font( maFont );
+ if ( nFlags & PUSH_TEXTCOLOR )
+ pData->mpTextColor = new Color( GetTextColor() );
+ if ( nFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( IsTextFillColor() )
+ pData->mpTextFillColor = new Color( GetTextFillColor() );
+ else
+ pData->mpTextFillColor = NULL;
+ }
+ if ( nFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( IsTextLineColor() )
+ pData->mpTextLineColor = new Color( GetTextLineColor() );
+ else
+ pData->mpTextLineColor = NULL;
+ }
+ if ( nFlags & PUSH_TEXTALIGN )
+ pData->meTextAlign = GetTextAlign();
+ if ( nFlags & PUSH_RASTEROP )
+ pData->meRasterOp = GetRasterOp();
+ if ( nFlags & PUSH_MAPMODE )
+ {
+ if ( mbMap )
+ pData->mpMapMode = new MapMode( maMapMode );
+ else
+ pData->mpMapMode = NULL;
+ }
+ if ( nFlags & PUSH_CLIPREGION )
+ {
+ if ( mbClipRegion )
+ pData->mpClipRegion = new Region( maRegion );
+ else
+ pData->mpClipRegion = NULL;
+ }
+ if ( nFlags & PUSH_REFPOINT )
+ {
+ if ( mbRefPoint )
+ pData->mpRefPoint = new Point( maRefPoint );
+ else
+ pData->mpRefPoint = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Pop()
+{
+ DBG_TRACE( "OutputDevice::Pop()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPopAction() );
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplObjStack* pData = mpObjStack;
+ mpMetaFile = NULL;
+
+ if ( !pData )
+ {
+ DBG_ERRORFILE( "OutputDevice::Pop() without OutputDevice::Push()" );
+ return;
+ }
+
+ mpObjStack = pData->mpPrev;
+
+ if ( pData->mnFlags & PUSH_LINECOLOR )
+ {
+ if ( pData->mpLineColor )
+ SetLineColor( *pData->mpLineColor );
+ else
+ SetLineColor();
+ }
+ if ( pData->mnFlags & PUSH_FILLCOLOR )
+ {
+ if ( pData->mpFillColor )
+ SetFillColor( *pData->mpFillColor );
+ else
+ SetFillColor();
+ }
+ if ( pData->mnFlags & PUSH_FONT )
+ SetFont( *pData->mpFont );
+ if ( pData->mnFlags & PUSH_TEXTCOLOR )
+ SetTextColor( *pData->mpTextColor );
+ if ( pData->mnFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( pData->mpTextFillColor )
+ SetTextFillColor( *pData->mpTextFillColor );
+ else
+ SetTextFillColor();
+ }
+ if ( pData->mnFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( pData->mpTextLineColor )
+ SetTextLineColor( *pData->mpTextLineColor );
+ else
+ SetTextLineColor();
+ }
+ if ( pData->mnFlags & PUSH_TEXTALIGN )
+ SetTextAlign( pData->meTextAlign );
+ if ( pData->mnFlags & PUSH_RASTEROP )
+ SetRasterOp( pData->meRasterOp );
+ if ( pData->mnFlags & PUSH_MAPMODE )
+ {
+ if ( pData->mpMapMode )
+ SetMapMode( *pData->mpMapMode );
+ else
+ SetMapMode();
+ }
+ if ( pData->mnFlags & PUSH_CLIPREGION )
+ ImplSetClipRegion( pData->mpClipRegion );
+ if ( pData->mnFlags & PUSH_REFPOINT )
+ {
+ if ( pData->mpRefPoint )
+ SetRefPoint( *pData->mpRefPoint );
+ else
+ SetRefPoint();
+ }
+
+ ImplDeleteObjStack( pData );
+
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetBitCount() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( meOutDevType == OUTDEV_VIRDEV )
+ return ((VirtualDevice*)this)->mnBitCount;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !((OutputDevice*)this)->ImplGetGraphics() )
+ return 0;
+ }
+#endif
+
+ return (USHORT)mpGraphics->GetBitCount();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG OutputDevice::GetColorCount() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ const USHORT nBitCount = GetBitCount();
+ return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (ULONG) 1 ) << nBitCount) );
+}
+
+// -----------------------------------------------------------------------
+
+OpenGL* OutputDevice::GetOpenGL()
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+#ifndef REMOTE_APPSERVER
+ OpenGL* pOGL;
+
+ if( OUTDEV_PRINTER != meOutDevType )
+ {
+ pOGL = new OpenGL( this );
+
+ if( !pOGL->IsValid() )
+ {
+ delete pOGL;
+ pOGL = NULL;
+ }
+ }
+ else
+ pOGL = NULL;
+
+ return pOGL;
+#else
+ return NULL;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > OutputDevice::CreateUnoGraphics()
+{
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ return pWrapper ? pWrapper->CreateGraphics( this ) : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >();
+}
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx
new file mode 100644
index 000000000000..b454fe3632ff
--- /dev/null
+++ b/vcl/source/gdi/outdev2.cxx
@@ -0,0 +1,1928 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV2_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALBMP_HXX
+#include <salbmp.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifdef REMOTE_APPSERVER
+#include <rmoutdev.hxx>
+#endif
+
+#define BAND_MAX_SIZE 512000
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// =======================================================================
+
+// -----------
+// - Defines -
+// -----------
+
+#ifndef REMOTE_APPSERVER
+
+#define OUTDEV_INIT() \
+{ \
+ if ( !IsDeviceOutputNecessary() ) \
+ return; \
+ \
+ if ( !mpGraphics ) \
+ if ( !ImplGetGraphics() ) \
+ return; \
+ \
+ if ( mbInitClipRegion ) \
+ ImplInitClipRegion(); \
+ \
+ if ( mbOutputClipped ) \
+ return; \
+}
+
+#else // !REMOTE_APPSERVER
+
+#define OUTDEV_INIT() \
+{ \
+ if ( !IsDeviceOutputNecessary() ) \
+ return; \
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics(); \
+ if ( !pGraphics ) \
+ return; \
+}
+
+#endif // REMOTE_APPSERVER
+
+#ifndef REMOTE_APPSERVER
+#define TwoRect SalTwoRect
+#else
+#define TwoRect RemoteTwoRect
+#endif
+
+// -------------
+// - externals -
+// -------------
+
+extern ULONG nVCLRLut[ 6 ];
+extern ULONG nVCLGLut[ 6 ];
+extern ULONG nVCLBLut[ 6 ];
+extern ULONG nVCLDitherLut[ 256 ];
+extern ULONG nVCLLut[ 256 ];
+
+// =======================================================================
+
+ULONG ImplAdjustTwoRect( TwoRect& rTwoRect, const Size& rSizePix )
+{
+ ULONG nMirrFlags = 0;
+
+ if ( rTwoRect.mnDestWidth < 0 )
+ {
+ rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
+ rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
+ rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if ( rTwoRect.mnDestHeight < 0 )
+ {
+ rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
+ rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
+ rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ return nMirrFlags;
+}
+
+// =======================================================================
+
+void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, void* pVoidPosAry )
+{
+ TwoRect* pPosAry = (TwoRect*)pVoidPosAry;
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics2;
+#else
+ ImplServerGraphics* pGraphics2;
+#endif
+
+ if ( pPosAry->mnSrcWidth && pPosAry->mnSrcHeight && pPosAry->mnDestWidth && pPosAry->mnDestHeight )
+ {
+ if ( this == pSrcDev )
+ pGraphics2 = NULL;
+ else
+ {
+ if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
+ (GetOutDevType() != OUTDEV_WINDOW) )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( !pSrcDev->mpGraphics )
+ {
+ if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
+ return;
+ }
+#endif
+ pGraphics2 = pSrcDev->mpGraphics;
+ }
+ else
+ {
+ if ( ((Window*)this)->mpFrameWindow == ((Window*)pSrcDev)->mpFrameWindow )
+ pGraphics2 = NULL;
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ if ( !pSrcDev->mpGraphics )
+ {
+ if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
+ return;
+ }
+#endif
+ pGraphics2 = pSrcDev->mpGraphics;
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+ DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
+ "OutputDevice::DrawOutDev(): We need more than one Graphics" );
+#endif
+ }
+ }
+ }
+
+ Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
+ Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
+ Rectangle aSrcRect( Point( pPosAry->mnSrcX, pPosAry->mnSrcY ),
+ Size( pPosAry->mnSrcWidth, pPosAry->mnSrcHeight ) );
+ const long nOldRight = aSrcRect.Right();
+ const long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (pPosAry->mnSrcX+pPosAry->mnSrcWidth-1) > aSrcOutRect.Right() )
+ {
+ const long nOldWidth = pPosAry->mnSrcWidth;
+ pPosAry->mnSrcWidth -= (nOldRight - aSrcRect.Right());
+ pPosAry->mnDestWidth = pPosAry->mnDestWidth * pPosAry->mnSrcWidth / nOldWidth;
+ }
+
+ if ( (pPosAry->mnSrcY+pPosAry->mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ {
+ const long nOldHeight = pPosAry->mnSrcHeight;
+ pPosAry->mnSrcHeight -= (nOldBottom - aSrcRect.Bottom());
+ pPosAry->mnDestHeight = pPosAry->mnDestHeight * pPosAry->mnSrcHeight / nOldHeight;
+ }
+
+ mpGraphics->CopyBits( pPosAry, pGraphics2 );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPt, const Size& rSrcSize )
+{
+ DBG_TRACE( "OutputDevice::DrawOutDev()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+
+ if ( meOutDevType == OUTDEV_PRINTER )
+ return;
+
+ if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ }
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+ aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+
+ Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
+ long nOldRight = aSrcRect.Right();
+ long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
+ {
+ long nOldWidth = aPosAry.mnSrcWidth;
+ aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
+ aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth;
+ }
+
+ if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ {
+ long nOldHeight = aPosAry.mnSrcHeight;
+ aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
+ aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight;
+ }
+
+ mpGraphics->CopyBits( &aPosAry, NULL );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPt, const Size& rSrcSize,
+ const OutputDevice& rOutDev )
+{
+ DBG_TRACE( "OutputDevice::DrawOutDev()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+ DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+
+ if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) )
+ return;
+
+ if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ }
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ ImplDrawOutDevDirect( &rOutDev, &aPosAry );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::CopyArea( const Point& rDestPt,
+ const Point& rSrcPt, const Size& rSrcSize,
+ USHORT nFlags )
+{
+ DBG_TRACE( "OutputDevice::CopyArea()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
+
+ if ( meOutDevType == OUTDEV_PRINTER )
+ return;
+
+ RasterOp eOldRop = GetRasterOp();
+ SetRasterOp( ROP_OVERPAINT );
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
+ {
+ aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+
+ Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
+ long nOldRight = aSrcRect.Right();
+ long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
+ aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
+
+ if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
+
+ if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) )
+ {
+ ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect,
+ aPosAry.mnDestX-aPosAry.mnSrcX,
+ aPosAry.mnDestY-aPosAry.mnSrcY,
+ FALSE );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
+ aPosAry.mnSrcX, aPosAry.mnSrcY,
+ aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
+ SAL_COPYAREA_WINDOWINVALIDATE );
+#else
+ mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
+ aPosAry.mnSrcX, aPosAry.mnSrcY,
+ aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
+ COPYAREA_WINDOWINVALIDATE );
+#endif
+ }
+ else
+ {
+ aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
+ aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
+ mpGraphics->CopyBits( &aPosAry, NULL );
+ }
+ }
+ }
+
+ SetRasterOp( eOldRop );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
+ const OutputDevice& rOutDev, const Region& rRegion )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ BOOL bOldMap = mbMap;
+ RasterOp eOldROP = GetRasterOp();
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ SetRasterOp( ROP_OVERPAINT );
+
+#ifndef REMOTE_APPSERVER
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+#else
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#endif
+
+ // ClipRegion zuruecksetzen
+#ifndef REMOTE_APPSERVER
+ if ( rRegion.IsNull() )
+ mpGraphics->ResetClipRegion();
+ else
+ ImplSelectClipRegion( mpGraphics, rRegion );
+#else
+ if ( rRegion.IsNull() )
+ mpGraphics->SetClipRegion();
+ else
+ mpGraphics->SetClipRegion( rRegion );
+#endif
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcX = rDevPt.X();
+ aPosAry.mnSrcY = rDevPt.Y();
+ aPosAry.mnSrcWidth = rDevSize.Width();
+ aPosAry.mnSrcHeight = rDevSize.Height();
+ aPosAry.mnDestX = rPt.X();
+ aPosAry.mnDestY = rPt.Y();
+ aPosAry.mnDestWidth = rDevSize.Width();
+ aPosAry.mnDestHeight = rDevSize.Height();
+ ImplDrawOutDevDirect( &rOutDev, &aPosAry );
+
+ // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird
+ mbInitClipRegion = TRUE;
+
+ SetRasterOp( eOldROP );
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
+ OutputDevice& rDev )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+ rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
+ mbMap = bOldMap;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap()" );
+ const Size aSizePix( rBitmap.GetSizePixel() );
+ ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap( Size )" );
+ ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
+ ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
+}
+
+// -----------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Bitmap aBmp( rBitmap );
+
+ if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
+ return;
+ else if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+ else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
+ DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ Pop();
+ return;
+ }
+ else if( !!aBmp )
+ {
+ if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
+ aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
+ aBmp.Convert( BMP_CONVERSION_GHOSTED );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_BMP_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpScalePartAction(
+ rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+ if( ( OUTDEV_PRINTER == meOutDevType ) && mbClipRegion && ( REGION_COMPLEX == maRegion.GetType() ) )
+ {
+ Bitmap aMask;
+ ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+
+ if ( !( !aBmp ) )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+ if ( nMirrFlags )
+ aBmp.Mirror( nMirrFlags );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawBitmap( &aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap() );
+#else
+ aBmp.ImplDrawRemote( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ) );
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx()" );
+
+ if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
+ else
+ {
+ const Size aSizePix( rBitmapEx.GetSizePixel() );
+ ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
+
+ if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
+ else
+ ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
+
+ if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
+ else
+ ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const BitmapEx& rBitmapEx, const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BitmapEx aBmpEx( rBitmapEx );
+
+ if ( mnDrawMode & DRAWMODE_NOBITMAP )
+ return;
+ else if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+ else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
+ DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
+ {
+ Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
+
+ if( aBmpEx.IsAlpha() )
+ aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetAlpha() );
+ else
+ aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
+ }
+ else if( !!aBmpEx )
+ {
+ if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
+ aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
+ aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_BMPEX_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
+ rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() );
+ aBmp.Replace( aMask, Color( COL_WHITE ) );
+ ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#ifndef REMOTE_APPSERVER
+ else if( rBitmapEx.IsAlpha() )
+ {
+ ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#endif
+
+ if( !( !aBmpEx ) )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() );
+
+ if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( nMirrFlags )
+ aBmpEx.Mirror( nMirrFlags );
+
+ const ImpBitmap* pImpBmp = aBmpEx.ImplGetBitmapImpBitmap();
+ const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap();
+
+ if ( pMaskBmp )
+ mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), *pMaskBmp->ImplGetSalBitmap() );
+ else
+ mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap() );
+
+#else
+
+ if( nMirrFlags )
+ aBmpEx.Mirror( nMirrFlags );
+
+ aBmpEx.ImplDrawRemote( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ) );
+
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask()" );
+ const Size aSizePix( rBitmap.GetSizePixel() );
+ ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask( Size )" );
+ ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" );
+ ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const Color& rMaskColor,
+ const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_MASK_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
+ rBitmap, rMaskColor ) );
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
+ rDestSize, rBitmap, rMaskColor ) );
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
+ rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+#ifndef REMOTE_APPSERVER
+ if ( OUTDEV_PRINTER == meOutDevType )
+ {
+ ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#endif
+
+ const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
+
+ if ( pImpBmp )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ // spiegeln via Koordinaten wollen wir nicht
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
+
+ // check if output is necessary
+ if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( nMirrFlags )
+ {
+ Bitmap aTmp( rBitmap );
+ aTmp.Mirror( nMirrFlags );
+ mpGraphics->DrawMask( &aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
+ ImplColorToSal( rMaskColor ) );
+ }
+ else
+ mpGraphics->DrawMask( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
+ ImplColorToSal( rMaskColor ) );
+
+#else
+
+ if( nMirrFlags )
+ {
+ Bitmap aTmp( rBitmap );
+ aTmp.Mirror( nMirrFlags );
+ aTmp.ImplDrawRemoteMask( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ),
+ rMaskColor );
+ }
+ else
+ rBitmap.ImplDrawRemoteMask( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ),
+ rMaskColor );
+
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Bitmap aBmp;
+ long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
+ long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
+#endif
+ {
+ if ( nWidth && nHeight )
+ {
+#ifndef REMOTE_APPSERVER
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ BOOL bClipped = FALSE;
+
+ // X-Koordinate ausserhalb des Bereichs?
+ if ( nX < mnOutOffX )
+ {
+ nWidth -= ( mnOutOffX - nX );
+ nX = mnOutOffX;
+ bClipped = TRUE;
+ }
+
+ // Y-Koordinate ausserhalb des Bereichs?
+ if ( nY < mnOutOffY )
+ {
+ nHeight -= ( mnOutOffY - nY );
+ nY = mnOutOffY;
+ bClipped = TRUE;
+ }
+
+ // Breite ausserhalb des Bereichs?
+ if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
+ {
+ nWidth = mnOutOffX + mnOutWidth - nX;
+ bClipped = TRUE;
+ }
+
+ // Hoehe ausserhalb des Bereichs?
+ if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
+ {
+ nHeight = mnOutOffY + mnOutHeight - nY;
+ bClipped = TRUE;
+ }
+
+ if ( bClipped )
+ {
+ // Falls auf den sichtbaren Bereich geclipped wurde,
+ // muessen wir eine Bitmap in der rchtigen Groesse
+ // erzeugen, in die die geclippte Bitmap an die angepasste
+ // Position kopiert wird
+ VirtualDevice aVDev( *this );
+
+ if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
+ {
+ if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = nX;
+ aPosAry.mnSrcY = nY;
+ aPosAry.mnSrcWidth = nWidth;
+ aPosAry.mnSrcHeight = nHeight;
+ aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
+ aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
+ aPosAry.mnDestWidth = nWidth;
+ aPosAry.mnDestHeight = nHeight;
+
+ if ( (nWidth > 0) && (nHeight > 0) )
+ (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( &aPosAry, mpGraphics );
+
+ aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+ else
+ bClipped = FALSE;
+ }
+ else
+ bClipped = FALSE;
+ }
+
+ if ( !bClipped )
+ {
+ SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight );
+
+ if( pSalBmp )
+ {
+ ImpBitmap* pImpBmp = new ImpBitmap;
+ pImpBmp->ImplSetSalBitmap( pSalBmp );
+ aBmp.ImplSetImpBitmap( pImpBmp );
+ }
+ }
+#else
+ aBmp.ImplGetRemoteBmp( (OutputDevice*) this, Point( nX, nY ), Size( nWidth, nHeight ) );
+#endif
+ }
+ }
+
+ return aBmp;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize,
+ Bitmap& rBitmap ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bOldMap = mbMap;
+ ((OutputDevice*)this)->mbMap = FALSE;
+ rBitmap = GetBitmap( rDestPt, rSize );
+ ((OutputDevice*)this)->mbMap = bOldMap;
+}
+
+// ------------------------------------------------------------------
+
+Color OutputDevice::GetPixel( const Point& rPt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ((OutputDevice*)this)->ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ const long nX = ImplLogicXToDevicePixel( rPt.X() );
+ const long nY = ImplLogicYToDevicePixel( rPt.Y() );
+ const SalColor aSalCol = mpGraphics->GetPixel( nX, nY );
+ aColor.SetRed( SALCOLOR_RED( aSalCol ) );
+ aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
+ aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
+ }
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ( (OutputDevice*) this )->ImplGetServerGraphics();
+ if( pGraphics )
+ {
+ const long nX = ImplLogicXToDevicePixel( rPt.X() );
+ const long nY = ImplLogicYToDevicePixel( rPt.Y() );
+ aColor = pGraphics->GetPixel( Point( nX, nY ) );
+ }
+#endif // REMOTE_APPSERVER
+
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+Color* OutputDevice::GetPixel( const Polygon& rPts ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color* pColors = NULL;
+ const USHORT nSize = rPts.GetSize();
+
+ if( nSize )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ((OutputDevice*)this)->ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ pColors = new Color[ nSize ];
+
+ for( USHORT i = 0; i < nSize; i++ )
+ {
+ Color& rCol = pColors[ i ];
+ const Point& rPt = rPts[ i ];
+ const SalColor aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ),
+ ImplLogicYToDevicePixel( rPt.Y() ) ) );
+
+ rCol.SetRed( SALCOLOR_RED( aSalCol ) );
+ rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) );
+ rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) );
+ }
+ }
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ( (OutputDevice*) this )->ImplGetServerGraphics();
+ if( pGraphics )
+ {
+ pColors = pGraphics->GetPixel( ImplLogicToDevicePixel( rPts ) );
+ }
+#endif // REMOTE_APPSERVER
+ }
+
+ return pColors;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Point& rPt )
+{
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPointAction( rPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ Point aPt = ImplLogicToDevicePixel( rPt );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKLINE )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITELINE )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80 );
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
+
+ if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ Point aPt = ImplLogicToDevicePixel( rPt );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ) );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ), aColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
+{
+ if ( !pColors )
+ DrawPixel( rPts, GetLineColor() );
+ else
+ {
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
+
+ const USHORT nSize = rPts.GetSize();
+
+ if ( nSize )
+ {
+ if ( mpMetaFile )
+ for ( USHORT i = 0; i < nSize; i++ )
+ mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ for ( USHORT i = 0; i < nSize; i++ )
+ {
+ const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ) );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPts ), pColors );
+ }
+#endif
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
+{
+ if( rColor != COL_TRANSPARENT )
+ {
+ const USHORT nSize = rPts.GetSize();
+ Color* pColArray = new Color[ nSize ];
+
+ for( USHORT i = 0; i < nSize; i++ )
+ pColArray[ i ] = rColor;
+
+ DrawPixel( rPts, pColArray );
+ delete[] pColArray;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+ Point aPt;
+ Point aOutPt( LogicToPixel( rDestPt ) );
+ Size aOutSz( LogicToPixel( rDestSize ) );
+ Rectangle aDstRect( aPt, GetOutputSizePixel() );
+ const BOOL bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0;
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
+ }
+
+ if( bHMirr )
+ {
+ aOutSz.Width() = -aOutSz.Width();
+ aOutPt.X() -= ( aOutSz.Width() - 1L );
+ }
+
+ if( bVMirr )
+ {
+ aOutSz.Height() = -aOutSz.Height();
+ aOutPt.Y() -= ( aOutSz.Height() - 1L );
+ }
+
+ if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
+ {
+ Rectangle aBmpRect( aPt, rBmp.GetSizePixel() );
+
+ if( !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL;
+ const BOOL bOldMap = mbMap; mbMap = FALSE;
+ Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
+ BitmapColor aDstCol;
+ const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
+ const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
+ const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
+ const long nOffX = aDstRect.Left() - aOutPt.X(), nOffY = aDstRect.Top() - aOutPt.Y();
+ long nX, nOutX, nY, nOutY, nMirrOffX, nMirrOffY;
+ long* pMapX = new long[ nDstWidth ];
+ long* pMapY = new long[ nDstHeight ];
+
+ // create horizontal mapping table
+ if( bHMirr )
+ nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
+
+ for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
+ {
+ pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
+
+ if( bHMirr )
+ pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
+ }
+
+ // create vertical mapping table
+ if( bVMirr )
+ nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
+
+ for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
+ {
+ pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
+
+ if( bVMirr )
+ pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
+ }
+
+ if( GetBitCount() <= 8 )
+ {
+ Bitmap aDither( aBmp.GetSizePixel(), 8 );
+ BitmapColor aIndex( 0 );
+ BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
+ BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapReadAccess* pB = aBmp.AcquireReadAccess();
+ BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
+
+ if( pB && pP && pA && pW )
+ {
+ for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ const long nModY = ( nOutY & 0x0FL ) << 4L;
+
+ for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ const ULONG nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
+
+ aDstCol = pB->GetColor( nY, nX );
+ aDstCol.Merge( pP->GetColor( nMapY, nMapX ), (BYTE) pA->GetPixel( nMapY, nMapX ) );
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
+ nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
+ nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
+ pW->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ ( (Bitmap&) rBmp ).ReleaseAccess( pP );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
+ aBmp.ReleaseAccess( pB );
+ aDither.ReleaseAccess( pW );
+ DrawBitmap( aDstRect.TopLeft(), aDither );
+ }
+ else
+ {
+ BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
+ BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
+
+ if( pP && pA && pB )
+ {
+ if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ switch( pP->GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_8BIT_PAL ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ Scanline pTmp = pPScan + nMapX * 3;
+
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ Scanline pTmp = pPScan + nMapX * 3;
+
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
+ (BYTE) pA->GetPixel( nMapY, nMapX ) ) );
+ }
+ }
+ }
+ }
+
+ ( (Bitmap&) rBmp ).ReleaseAccess( pP );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
+ aBmp.ReleaseAccess( pB );
+ DrawBitmap( aDstRect.TopLeft(), aBmp );
+ }
+
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+static Pair* ImplGetMap( long nFromSize, long nToSize )
+{
+ DBG_ASSERT( nFromSize && nToSize, "ImplGetMap(): Invalid size!" );
+
+ Pair* pMap = new Pair[ nFromSize ];
+ const double fSize = (double) nToSize / nFromSize;
+ double fRealSum = 0.0;
+ const long nLastToPos = nToSize - 1L;
+ long nErrSum = 0L, nPos = 0L, nSize = 0L;
+
+ for( long i = 0L; i < nFromSize; i++ )
+ {
+ nPos = nPos + nSize;
+ nSize = Max( FRound( fSize - ( nErrSum - fRealSum ) ), 0L );
+
+ nErrSum += nSize;
+ fRealSum += fSize;
+
+ pMap[ i ].A() = nPos = Min( nPos, nLastToPos );
+ pMap[ i ].B() = Min( nPos + Max( nSize, 1L ) - 1L, nLastToPos );
+ }
+
+ return pMap;
+}
+
+// ------------------------------------------------------------------------
+
+static BOOL ImplCreateBandBitmaps( BitmapReadAccess* pPAcc, BitmapReadAccess* pMAcc,
+ long* pMapX, long* pMapY,
+ long nDstWidth, long nDstY1, long nDstY2,
+ Bitmap& rPaint, Bitmap& rMask )
+{
+ const Size aSz( nDstWidth, nDstY2 - nDstY1 + 1 );
+ BOOL bRet = FALSE;
+
+ rPaint = Bitmap( aSz, pPAcc->GetBitCount(), pPAcc->HasPalette() ? &pPAcc->GetPalette() : NULL );
+ rMask = Bitmap( aSz, pMAcc->GetBitCount(), pMAcc->HasPalette() ? &pMAcc->GetPalette() : NULL );
+
+ BitmapWriteAccess* pWPAcc = rPaint.AcquireWriteAccess();
+ BitmapWriteAccess* pWMAcc = rMask.AcquireWriteAccess();
+
+ if( pWPAcc && pWMAcc )
+ {
+ const long nWidth = pWPAcc->Width();
+ const long nHeight = pWPAcc->Width();
+ const long nPScanSize = pWPAcc->GetScanlineSize();
+ const long nMScanSize = pWMAcc->GetScanlineSize();
+ long nY = 0, nScanY = nDstY1;
+
+ while( nScanY <= nDstY2 )
+ {
+ const long nMapY = pMapY[ nScanY ];
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ pWPAcc->SetPixel( nY, nX, pPAcc->GetPixel( nMapY, nMapX ) );
+ pWMAcc->SetPixel( nY, nX, pMAcc->GetPixel( nMapY, nMapX ) );
+ }
+
+ while( ( nScanY < nDstY2 ) && ( pMapY[ nScanY + 1 ] == nMapY ) )
+ {
+ HMEMCPY( pWPAcc->GetScanline( nY + 1L ), pWPAcc->GetScanline( nY ), nPScanSize );
+ HMEMCPY( pWMAcc->GetScanline( nY + 1L ), pWMAcc->GetScanline( nY ), nMScanSize );
+ nY++, nScanY++;
+ }
+
+ nY++, nScanY++;
+ }
+
+ bRet = TRUE;
+ }
+
+ if( pWPAcc )
+ rPaint.ReleaseAccess( pWPAcc );
+
+ if( pWMAcc )
+ rMask.ReleaseAccess( pWMAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+ Point aPt;
+ Point aDestPt( LogicToPixel( rDestPt ) );
+ Size aDestSz( LogicToPixel( rDestSize ) );
+ Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
+
+ aSrcRect.Justify();
+
+ if( !!rBmp && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
+ {
+ ULONG nMirrFlags = 0UL;
+ Bitmap aPaint( rBmp );
+ Bitmap aMask( rMask );
+ Region aDstRgn;
+ BOOL bMask = !!aMask;
+
+ if( bMask && ( aMask.GetBitCount() > 1 ) )
+ aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ // mirrored horizontically
+ if( aDestSz.Width() < 0L )
+ {
+ aDestSz.Width() = -aDestSz.Width();
+ aDestPt.X() -= ( aDestSz.Width() - 1L );
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ // mirrored vertically
+ if( aDestSz.Height() < 0L )
+ {
+ aDestSz.Height() = -aDestSz.Height();
+ aDestPt.Y() -= ( aDestSz.Height() - 1L );
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ // source cropped?
+ if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
+ {
+ aPaint.Crop( aSrcRect );
+ if( bMask )
+ aMask.Crop( aSrcRect );
+ }
+
+ // destination mirrored
+ if( nMirrFlags )
+ {
+ aPaint.Mirror( nMirrFlags );
+ if( bMask )
+ aMask.Mirror( nMirrFlags );
+ }
+
+ const Rectangle aDstRect( aDestPt, aDestSz );
+
+ // create destination region
+ if( mbClipRegion && !maRegion.IsEmpty() )
+ {
+ aDstRgn = maRegion;
+ aDstRgn.Intersect( aDstRect );
+ }
+ else
+ aDstRgn = aDstRect;
+
+ aDstRgn.Move( -aDstRect.Left(), -aDstRect.Top() );
+
+ // we always want to have a mask
+ if( !bMask )
+ {
+ aMask = Bitmap( aSrcRect.GetSize(), 1 );
+ aMask.Erase( Color( COL_BLACK ) );
+ }
+
+ BitmapReadAccess* pPAcc = aPaint.AcquireReadAccess();
+ BitmapReadAccess* pMAcc = aMask.AcquireReadAccess();
+
+ if( pPAcc && pMAcc )
+ {
+ const long nWidth = aDestSz.Width();
+ const long nHeight = aDestSz.Height();
+ const long nWidth1 = nWidth - 1;
+ const long nHeight1 = nHeight - 1;
+ const long nOldWidth1 = aSrcRect.GetWidth() - 1;
+ const long nOldHeight1 = aSrcRect.GetHeight() - 1;
+ const long nScanByteCount = Max( nWidth * aPaint.GetBitCount() / 8L, 1L );
+ const long nBandHeight = BAND_MAX_SIZE / nScanByteCount + 1;
+ long* pMapX = new long[ nWidth ];
+ long* pMapY = new long[ nHeight ];
+ long nX, nY;
+ long nBandY1, nBandY2;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const BOOL bOldMap = mbMap;
+
+ mpMetaFile = NULL;
+ Push( PUSH_CLIPREGION );
+ SetClipRegion();
+ mbMap = FALSE;
+
+ // create mapping tables
+ for( nX = 0L; nX < nWidth; nX++ )
+ pMapX[ nX ] = nWidth1 ? ( nX * nOldWidth1 / nWidth1 ) : 0;
+
+ for( nY = 0L; nY < nHeight; nY++ )
+ pMapY[ nY ] = nHeight1 ? ( nY * nOldHeight1 / nHeight1 ) : 0;
+
+ // process bands
+ for( nBandY1 = 0, nBandY2 = nBandHeight; nBandY1 < nHeight; nBandY1 += nBandHeight, nBandY2 += nBandHeight )
+ {
+ Bitmap aWorkPaint, aWorkMask;
+
+ // don't walk over bounds
+ if( nBandY2 > nHeight1 )
+ nBandY2 = nHeight1;
+
+ if( ImplCreateBandBitmaps( pPAcc, pMAcc, pMapX, pMapY, nWidth, nBandY1, nBandY2, aWorkPaint, aWorkMask ) )
+ {
+ Region aWorkRgn( aDstRgn );
+ aWorkRgn.Move( 0, -nBandY1 );
+ aWorkRgn.Intersect( aWorkMask.CreateRegion( COL_BLACK, Rectangle( aPt, aWorkMask.GetSizePixel() ) ) );
+
+ ImplRegionInfo aInfo;
+ long nWorkX, nWorkY, nWorkWidth, nWorkHeight;
+ BOOL bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY,
+ nWorkWidth, nWorkHeight );
+
+ while( bRgnRect )
+ {
+ Bitmap aCropBmp( aWorkPaint );
+ const Point aOutPt( nWorkX + aDestPt.X(), nWorkY + nBandY1 + aDestPt.Y() );
+ const Size aOutSz( nWorkWidth, nWorkHeight );
+ const Size aOutSz1( nWorkWidth + 1, nWorkHeight + 1 );
+
+ aCropBmp.Crop( Rectangle( Point( nWorkX, nWorkY ), aOutSz ) );
+ ImplDrawBitmap( aOutPt, aOutSz1, Point(), aOutSz, aCropBmp, META_BMPSCALE_ACTION );
+ bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ }
+ }
+ }
+
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ Pop();
+ mpMetaFile = pOldMetaFile;
+ }
+
+ if( pPAcc )
+ aPaint.ReleaseAccess( pPAcc );
+
+ if( pMAcc )
+ aMask.ReleaseAccess( pMAcc );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+#ifndef REMOTE_APPSERVER
+
+ Point aPt;
+ Point aDestPt( LogicToPixel( rDestPt ) );
+ Size aDestSz( LogicToPixel( rDestSize ) );
+ Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
+
+ aSrcRect.Justify();
+
+ if( !!rMask &&
+ aSrcRect.GetWidth() && aSrcRect.GetHeight() &&
+ aDestSz.Width() && aDestSz.Height() )
+ {
+ ULONG nMirrFlags = 0UL;
+ Bitmap aMask( rMask );
+ Region aRegion;
+
+ if( aMask.GetBitCount() > 1 )
+ aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ if( aDestSz.Width() < 0L )
+ {
+ aDestSz.Width() = -aDestSz.Width();
+ aDestPt.X() -= ( aDestSz.Width() - 1L );
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if( aDestSz.Height() < 0L )
+ {
+ aDestSz.Height() = -aDestSz.Height();
+ aDestPt.Y() -= ( aDestSz.Height() - 1L );
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ // source cropped?
+ if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) )
+ aMask.Crop( aSrcRect );
+
+ // destination mirrored
+ if( nMirrFlags )
+ aMask.Mirror( nMirrFlags );
+
+ aRegion = aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) );
+
+ ImplRegionInfo aInfo;
+ const Size aSrcSz( aMask.GetSizePixel() );
+ long nSrcX, nSrcY, nSrcWidth, nSrcHeight;
+ long nDstX, nDstY, nDstWidth, nDstHeight;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ Pair* pMapX = ImplGetMap( aSrcSz.Width(), aDestSz.Width() );
+ Pair* pMapY = ImplGetMap( aSrcSz.Height(), aDestSz.Height() );
+ BOOL bOldMap = mbMap;
+ BOOL bRegionRect = aRegion.ImplGetFirstRect( aInfo, nSrcX, nSrcY, nSrcWidth, nSrcHeight );
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
+ SetLineColor( rMaskColor );
+ SetFillColor( rMaskColor );
+ ImplInitLineColor();
+ ImplInitFillColor();
+
+ while( bRegionRect )
+ {
+ nDstX = pMapX[ nSrcX ].A();
+ nDstY = pMapY[ nSrcY ].A();
+ nDstWidth = pMapX[ nSrcX + nSrcWidth - 1L ].B() - nDstX + 1L;
+ nDstHeight = pMapY[ nSrcY + nSrcHeight - 1L ].B() - nDstY + 1L;
+ mpGraphics->DrawRect( nDstX + aDestPt.X(), nDstY + aDestPt.Y(), nDstWidth, nDstHeight );
+ bRegionRect = aRegion.ImplGetNextRect( aInfo, nSrcX, nSrcY, nSrcWidth, nSrcHeight );
+ }
+
+ Pop();
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+ }
+
+#endif
+}
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
new file mode 100644
index 000000000000..4dbd5935f2ae
--- /dev/null
+++ b/vcl/source/gdi/outdev3.cxx
@@ -0,0 +1,6326 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <math.h>
+#include <string.h>
+
+#define _SV_OUTDEV_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <metric.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_EDIT_HXX
+#include <edit.hxx>
+#endif
+
+#include <unohelp.hxx>
+
+#ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
+#include <com/sun/star/text/XBreakIterator.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
+#include <com/sun/star/text/WordType.hpp>
+#endif
+
+#if defined UNX
+#define GLYPH_FONT_HEIGHT 128
+#elif defined OS2
+#define GLYPH_FONT_HEIGHT 176
+#else
+#define GLYPH_FONT_HEIGHT 256
+#endif
+
+#define WSstrcmp strcmp
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Font );
+
+// =======================================================================
+
+#define OUTDEV_CHARCONVERT_REPLACE FALSE
+
+using namespace ::com::sun::star;
+using namespace ::rtl;
+
+
+// =======================================================================
+
+#define MAX_DX_WORDS 120
+#define TEXT_DRAW_ELLIPSIS (TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_PATHELLIPSIS | TEXT_DRAW_NEWSELLIPSIS)
+
+// =======================================================================
+
+#define UNDERLINE_LAST UNDERLINE_BOLDWAVE
+#define STRIKEOUT_LAST STRIKEOUT_X
+
+// =======================================================================
+
+void OutputDevice::ImplUpdateFontData( BOOL bNewFontLists )
+{
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( bNewFontLists )
+ {
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ }
+
+ if ( GetOutDevType() == OUTDEV_PRINTER )
+ {
+ mpFontCache->Clear();
+
+ if ( bNewFontLists )
+ {
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( ImplGetGraphics() )
+#endif
+ {
+ mpFontList->Clear();
+ mpGraphics->GetDevFontList( mpFontList );
+ mpFontList->InitStdFonts();
+ }
+ }
+ }
+
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+
+ // Bei Fenstern auch alle Child-Fenster mit updaten
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pChild = ((Window*)this)->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateFontData( TRUE );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplUpdateAllFontData( BOOL bNewFontLists )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Alle Fenster updaten
+ Window* pFrame = pSVData->maWinData.mpFirstFrame;
+ while ( pFrame )
+ {
+ pFrame->ImplUpdateFontData( bNewFontLists );
+
+ Window* pSysWin = pFrame->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ pSysWin->ImplUpdateFontData( bNewFontLists );
+ pSysWin = pSysWin->mpNextOverlap;
+ }
+
+ pFrame = pFrame->mpFrameData->mpNextFrame;
+ }
+
+ // Alle VirDev's updaten
+ VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
+ while ( pVirDev )
+ {
+ pVirDev->ImplUpdateFontData( bNewFontLists );
+ pVirDev = pVirDev->mpNext;
+ }
+
+ // Alle Printer updaten
+ Printer* pPrinter = pSVData->maGDIData.mpFirstPrinter;
+ while ( pPrinter )
+ {
+ pPrinter->ImplUpdateFontData( bNewFontLists );
+ pPrinter = pPrinter->mpNext;
+ }
+
+ // Globale Fontlisten leeren, damit diese geupdatet werden
+ pSVData->maGDIData.mpScreenFontCache->Clear();
+ if ( bNewFontLists )
+ {
+ pSVData->maGDIData.mpScreenFontList->Clear();
+ pFrame = pSVData->maWinData.mpFirstFrame;
+ if ( pFrame )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFrame->ImplGetGraphics() )
+#endif
+ {
+ pFrame->mpGraphics->GetDevFontList( pFrame->mpFrameData->mpFontList );
+ pFrame->mpFrameData->mpFontList->InitStdFonts();
+ }
+ }
+ }
+}
+
+// =======================================================================
+
+struct ImplFontSubstEntry
+{
+ XubString maName;
+ XubString maReplaceName;
+ XubString maMatchName;
+ XubString maMatchReplaceName;
+ USHORT mnFlags;
+ ImplFontSubstEntry* mpNext;
+};
+
+// =======================================================================
+
+static void ImplStrEraseAllSymbols( XubString& rStr )
+{
+ xub_StrLen i = 0;
+ xub_Unicode c = rStr.GetChar( i );
+ while ( c )
+ {
+ // Alle Zeichen kleiner 0 zwischen 9-A, Z-a und z-127 loeschen
+ if ( (c < 48) || ((c > 57) && (c < 65)) || ((c > 90) && (c < 97)) ||
+ ((c > 122) && (c <= 127)) )
+ rStr.Erase( i, 1 );
+ else
+ i++;
+ c = rStr.GetChar( i );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static xub_StrLen ImplStrMatch( const XubString& rStr1, const XubString& rStr2 )
+{
+ xub_StrLen nMatch = 0;
+ const xub_Unicode* pStr1 = rStr1.GetBuffer();
+ const xub_Unicode* pStr2 = rStr2.GetBuffer();
+ while ( (*pStr1 == *pStr2) && *pStr1 )
+ {
+ pStr1++;
+ pStr2++;
+ nMatch++;
+ }
+ return nMatch;
+}
+
+// -----------------------------------------------------------------------
+
+static int ImplStrFullMatch( const XubString& rStr1, const char* pStr2 )
+{
+ const xub_Unicode* pStr1 = rStr1.GetBuffer();
+ while ( (*pStr1 == (xub_Unicode)(unsigned char)*pStr2) && *pStr1 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+ return !(*pStr1);
+}
+
+// =======================================================================
+
+#if 0
+
+#define FONT_ATTR_SYMBOL ((ULONG)0x00000001)
+#define FONT_ATTR_FIXED ((ULONG)0x00000002)
+#define FONT_ATTR_ITALIC ((ULONG)0x00000004)
+#define FONT_ATTR_NORMAL ((ULONG)0x00000008)
+#define FONT_ATTR_STANDARD ((ULONG)0x00000010)
+#define FONT_ATTR_SPECIAL ((ULONG)0x00000020)
+#define FONT_ATTR_TITLING ((ULONG)0x00000040)
+#define FONT_ATTR_SERIF ((ULONG)0x00000080)
+#define FONT_ATTR_NONSERIF ((ULONG)0x00000100)
+#define FONT_ATTR_ROUNDED ((ULONG)0x00000200)
+#define FONT_ATTR_OUTLINE ((ULONG)0x00000400)
+#define FONT_ATTR_SHADOW ((ULONG)0x00000800)
+#define FONT_ATTR_SCRIPT ((ULONG)0x00001000)
+#define FONT_ATTR_HANDWRITING ((ULONG)0x00002000)
+#define FONT_ATTR_DECORATION ((ULONG)0x00004000)
+#define FONT_ATTR_CHARSCRIPT ((ULONG)0x00008000)
+#define FONT_ATTR_CHANCERY ((ULONG)0x00010000)
+#define FONT_ATTR_OLDSTYLE ((ULONG)0x00020000)
+#define FONT_ATTR_FAVOR1 ((ULONG)0x01000000)
+#define FONT_ATTR_FAVOR2 ((ULONG)0x02000000)
+#define FONT_ATTR_FAVOR3 ((ULONG)0x04000000)
+#define FONT_ATTR_FAVOR4 ((ULONG)0x08000000)
+#define FONT_ATTR_FOUND ((ULONG)0x80000000)
+
+struct ImplFontAttrWidthSearchData
+{
+ const char* mpStr;
+ FontWidth meWidth;
+};
+
+static ImplFontAttrWidthSearchData const aImplWidthAttrSearchList[] =
+{
+{ "narrow", WIDTH_CONDENSED },
+{ "semicondensed", WIDTH_SEMI_CONDENSED },
+{ "ultracondensed", WIDTH_ULTRA_CONDENSED },
+{ "semiexpanded", WIDTH_SEMI_EXPANDED },
+{ "ultraexpanded", WIDTH_ULTRA_EXPANDED },
+{ "expanded", WIDTH_EXPANDED },
+{ "wide", WIDTH_ULTRA_EXPANDED },
+{ "condensed", WIDTH_CONDENSED },
+{ "cond", WIDTH_CONDENSED },
+{ "cn", WIDTH_CONDENSED },
+{ NULL, WIDTH_DONTKNOW },
+};
+
+struct ImplFontAttrWeightSearchData
+{
+ const char* mpStr;
+ FontWeight meWeight;
+};
+
+static ImplFontAttrWeightSearchData const aImplWeightAttrSearchList[] =
+{
+{ "extrablack", WEIGHT_BLACK },
+{ "ultrablack", WEIGHT_BLACK },
+{ "black", WEIGHT_BLACK },
+{ "heavy", WEIGHT_BLACK },
+{ "ultrabold", WEIGHT_ULTRABOLD },
+{ "semibold", WEIGHT_SEMIBOLD },
+{ "bold", WEIGHT_BOLD },
+{ "ultralight", WEIGHT_ULTRALIGHT },
+{ "semilight", WEIGHT_SEMILIGHT },
+{ "light", WEIGHT_LIGHT },
+{ "demi", WEIGHT_SEMIBOLD },
+{ "medium", WEIGHT_MEDIUM },
+{ NULL, WEIGHT_DONTKNOW },
+};
+
+struct ImplFontAttrTypeSearchData
+{
+ const char* mpStr;
+ ULONG mnType;
+};
+
+static ImplFontAttrTypeSearchData const aImplTypeAttrSearchList[] =
+{
+{ "titling", FONT_ATTR_TITLING },
+{ "outline", FONT_ATTR_OUTLINE },
+{ "shadow", FONT_ATTR_SHADOW },
+{ NULL, 0 },
+};
+
+// =======================================================================
+
+struct ImplFontNameAttr
+{
+ const char* mpName;
+ FontFamily meFamily;
+ FontWeight meWeight;
+ FontWidth meWidth;
+ ULONG mnType;
+};
+
+static const ImplFontNameAttr aImplFullList[] =
+{
+{ "Bookman", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NORMAL | FONT_ATTR_STANDARD | FONT_ATTR_SERIF },
+{ NULL, FAMILY_DONTKNOW,WEIGHT_DONTKNOW,WIDTH_DONTKNOW, 0 }
+};
+
+static const ImplFontNameAttr aImplMatchList[] =
+{
+{ "bookman", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NORMAL | FONT_ATTR_STANDARD | FONT_ATTR_SERIF },
+{ "comicsansms", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "kristenitc", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "maiandragd", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "arioso", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_ITALIC | FONT_ATTR_DECORATION | FONT_ATTR_OLDSTYLE | FONT_ATTR_FAVOR3 },
+{ "tempussansitc", FAMILY_SCRIPT, WEIGHT_LIGHT, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT },
+{ "papyrus", FAMILY_SCRIPT, WEIGHT_LIGHT, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT },
+{ "lucidashadowtitling", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "lucidaopenboldtitling",FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "lucidaopentitling", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "lucidaopen", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE },
+{ "lucidashadow", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "chevara", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_EXPANDED, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "colonnamt", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_SPECIAL | FONT_ATTR_OUTLINE },
+{ "imprintmtshadow", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "castellar", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "algerian", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_SPECIAL | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW | FONT_ATTR_OLDSTYLE },
+{ NULL, FAMILY_DONTKNOW,WEIGHT_DONTKNOW,WIDTH_DONTKNOW, 0 }
+};
+
+#endif
+
+static const char* aImplSwissMatchList[] =
+{
+ "arial",
+ "avantgarde",
+ "cgomega",
+ "centurygothic",
+ "charcoal",
+ "chicago",
+ "frutiger",
+ "geneva",
+ "haettenschweiler",
+ "helmet",
+ "helv",
+ "lucida",
+ "impact",
+ "tahoma",
+ "univers",
+ "vagrounded",
+ "verdana",
+ NULL
+};
+
+static const char* aImplSwissSearchList[] =
+{
+ "sansserif",
+ "swiss",
+ NULL
+};
+
+static const char* aImplRomanMatchList[] =
+{
+ "algerian",
+ "antiqua",
+ "caliso",
+ "clarendon",
+ "colonna",
+ "garamond",
+ "newyork",
+ "palatino",
+ "timmons",
+ NULL
+};
+
+static const char* aImplRomanSearchList[] =
+{
+ "book",
+ "times",
+ "roman",
+ "bright",
+ NULL
+};
+
+static const char* aImplFixedMatchList[] =
+{
+ "lineprinter",
+ "monaco",
+ "typewriter",
+ NULL
+};
+
+static const char* aImplFixedSearchList[] =
+{
+ "console",
+ "courier",
+ "fixed",
+ "letter",
+ "monospace",
+ "terminal",
+ NULL
+};
+
+static const char* aImplScriptMatchList[] =
+{
+ "arioso",
+ "coronet",
+ "cursive",
+ "marigold",
+ "zapfchancery",
+ NULL
+};
+
+static const char* aImplScriptSearchList[] =
+{
+ "script",
+ "signet",
+ "handwriting",
+ "calligraphy",
+ NULL
+};
+
+static const char* aImplSymbolMatchList[] =
+{
+ "marlett",
+ "monotypesorts",
+ "msoutlook",
+ NULL
+};
+
+static const char* aImplSymbolSearchList[] =
+{
+ "symbol",
+ "bats",
+ "dings",
+ "math",
+ NULL
+};
+
+static const char* aImplTypeList[] =
+{
+ "black",
+ "bold",
+ "condensed",
+ "expanded",
+ "narrow",
+ "outline",
+ NULL
+};
+
+// =======================================================================
+
+static const char* aImplSearchScriptList[] =
+{
+ "ce",
+ "we",
+ "cyr",
+ "tur",
+ "wt",
+ "greek",
+ "wl",
+ NULL
+};
+
+// -----------------------------------------------------------------------
+
+struct ImplScriptSearchList
+{
+ const char* mpScript;
+ rtl_Script meScript;
+};
+
+static void ImplCutScriptAndSpaces( XubString& rName )
+{
+ rName.EraseLeadingAndTrailingChars( ' ' );
+
+ USHORT nLen = rName.Len();
+ if ( nLen < 3 )
+ return;
+
+ // Scriptname must be the last part of the fontname and
+ // looks like "fontname (scriptname)". So there can only be a
+ // script name at the and of the fontname, when the last char is
+ // ')'.
+ if ( rName.GetChar( nLen-1 ) == ')' )
+ {
+ int nOpen = 1;
+ nLen -= 2;
+ while ( nLen )
+ {
+ if ( rName.GetChar( nLen ) == '(' )
+ {
+ nOpen--;
+ if ( !nOpen && nLen && (rName.GetChar( nLen-1 ) == ' ') )
+ {
+ XubString aScript = rName.Copy( nLen+1, rName.Len()-1-nLen-1 );
+ rName.Erase( nLen-1 );
+ return;
+ }
+ }
+ if ( rName.GetChar( nLen ) == ')' )
+ nOpen++;
+ nLen--;
+ }
+ }
+
+ // For compatibility with older version we must search for a
+ // script name at the end of a fontname without brakets
+ USHORT nSpacePos = rName.SearchBackward( ' ' );
+ if ( nSpacePos && (nSpacePos != STRING_NOTFOUND) )
+ {
+ XubString aScript = rName.Copy( nSpacePos+1 );
+ const char** pScript = aImplSearchScriptList;
+ while ( *pScript )
+ {
+ if ( aScript.EqualsAscii( *pScript ) )
+ {
+ rName.Erase( nSpacePos );
+ break;
+ }
+ pScript++;
+ }
+ }
+}
+
+// =======================================================================
+
+#if 0
+
+static const ImplFontNameAttr* ImplFindFontAttr( const XubString& rFontName )
+{
+ const ImplFontNameAttr* pList;
+
+ pList = aImplFullList;
+ while ( pList->mpName )
+ {
+ if ( rFontName.EqualsAscii( pList->mpName ) )
+ return pList;
+ pList++;
+ }
+
+ pList = aImplMatchList;
+ while ( pList->mpName )
+ {
+ if ( ImplStrFullMatch( rFontName, pList->mpName ) )
+ return pList;
+ pList++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetFontAttr( const XubString& rFontName,
+ FontFamily& rFamily, CharSet& rCharSet,
+ FontPitch& rPitch )
+{
+ if ( (rFamily == FAMILY_DONTKNOW) || (rPitch == PITCH_DONTKNOW) ||
+ (rCharSet == CHARSET_DONTKNOW) )
+ {
+ }
+}
+
+#endif
+
+// =======================================================================
+
+BOOL ImplTestFontName( const XubString& rName,
+ const sal_Char** pMatchList,
+ const sal_Char** pSearchList )
+{
+ const char** pAlias;
+
+ pAlias = pMatchList;
+ while ( *pAlias )
+ {
+ if ( ImplStrFullMatch( rName, *pAlias ) )
+ return TRUE;
+ pAlias++;
+ }
+
+ pAlias = pSearchList;
+ while ( *pAlias )
+ {
+ if ( rName.SearchAscii( *pAlias ) != STRING_NOTFOUND )
+ return TRUE;
+ pAlias++;
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+static void ImplFontAttrFromName( const XubString& rFontName,
+ FontFamily& rFamily, CharSet& rCharSet,
+ FontPitch& rPitch )
+{
+ if ( rFamily == FAMILY_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplRomanMatchList, aImplRomanSearchList ) )
+ rFamily = FAMILY_ROMAN;
+ else if ( ImplTestFontName( rFontName, aImplSwissMatchList, aImplSwissSearchList ) )
+ rFamily = FAMILY_SWISS;
+ else if ( ImplTestFontName( rFontName, aImplScriptMatchList, aImplScriptSearchList ) )
+ rFamily = FAMILY_SCRIPT;
+ }
+
+ if ( rPitch == PITCH_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplFixedMatchList, aImplFixedSearchList ) )
+ rPitch = PITCH_FIXED;
+ }
+
+ if ( rCharSet == RTL_TEXTENCODING_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplSymbolMatchList, aImplSymbolSearchList ) )
+ rCharSet = RTL_TEXTENCODING_SYMBOL;
+ }
+}
+
+// =======================================================================
+
+static const char* aImplStdSwissList[] =
+{
+ "helvetica",
+ "arial",
+ "lucida sans",
+ "lucidasans",
+ "lucida",
+ "geneva",
+ "helmet",
+ NULL
+};
+
+static const char* aImplStdRomanList[] =
+{
+ "times",
+ "times new roman",
+ "timesnewroman",
+ "roman",
+ "lucida serif",
+ "lucidaserif",
+ "lucida bright",
+ "lucidabright",
+ "bookman",
+ "garamond",
+ "timmons",
+ NULL
+};
+
+static const char* aImplStdFixedList[] =
+{
+ "courier",
+ "courier new",
+ "lucida typewriter",
+ "lucidatypewriter",
+ "lucida sans typewriter",
+ "lucidasanstypewriter",
+ NULL
+};
+
+static const char* aImplStdScriptList[] =
+{
+ "zapf chancery",
+ "zapfchancery",
+ "lucida calligraphy",
+ "lucidacalligraphy",
+ "lucida handwriting",
+ "lucidahandwriting",
+ "arioso",
+ "script",
+ "marigold",
+ NULL
+};
+
+static const char* aImplStdSymbolList[] =
+{
+ "starbats",
+ "symbol",
+ "zapf dingbats",
+ "zapfdingbats",
+ "wingdings",
+ "lucida dingbats",
+ "lucidadingbats",
+ "lucida sans dingbats",
+ "lucidasansdingbats",
+ NULL
+};
+
+// =======================================================================
+
+void ImplFreeOutDevFontData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ while ( pEntry )
+ {
+ ImplFontSubstEntry* pNext = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pNext;
+ }
+}
+
+// =======================================================================
+
+static ImplFontData* ImplFindScript( ImplDevFontListData* pData,
+ rtl_Script eScript )
+{
+ // Testen, ob ein Font mit einem entsprechendem
+ // Script vorhanden ist
+ ImplFontData* pCurFontData = pData->mpFirst;
+ while ( pCurFontData )
+ {
+ // Detect Unicode Font !!!
+ if ( pData->maMatchName.EqualsAscii( "arial unicode ms" ) )
+ return pCurFontData;
+ if ( eScript == pCurFontData->meScript )
+ return pCurFontData;
+ pCurFontData = pCurFontData->mpNext;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+/* !!! UNICODE - Duerfte nicht mehr gebraucht werden !!!
+static rtl_TextEncoding ImplGetFakeEncoding( rtl_TextEncoding eEncoding )
+{
+ rtl_TextEncoding eSystemEncoding = GetSystemCharSet();
+ // MS_1252 und 8859_1 sind kompatible
+ if ( ((eEncoding == RTL_TEXTENCODING_MS_1252) ||
+ (eEncoding == RTL_TEXTENCODING_ISO_8859_1)) &&
+ ((eSystemEncoding == RTL_TEXTENCODING_MS_1252) ||
+ (eSystemEncoding == RTL_TEXTENCODING_ISO_8859_1)) )
+ return eEncoding;
+ else
+ {
+ // Wir testen, ob beide Zeichensaetze dem gleichem Script
+ // entsprechen, um so der Applikation das gleiche Encoding
+ // vorzugaukeln. Dies ist beispielsweise bei Russisch wichtig
+ // da hier Fonts mit unterschiedlichem Encoding auftauchen
+ // koennen.
+ rtl_Script eSrcScript;
+ rtl_Script eSystemScript;
+ rtl_TextEncodingInfo aTEncInfo;
+ aTEncInfo.StructSize = sizeof( aTEncInfo );
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ if ( !rtl_getTextEncodingInfo( eEncoding, &aTEncInfo ) )
+ return eEncoding;
+ else
+ eSrcScript = aTEncInfo.Script;
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ if ( !rtl_getTextEncodingInfo( eSystemEncoding, &aTEncInfo ) )
+ return eEncoding;
+ else
+ eSystemScript = aTEncInfo.Script;
+ if ( eSrcScript == eSystemScript )
+ eEncoding = eSystemEncoding;
+ }
+
+ return eEncoding;
+}
+*/
+
+// =======================================================================
+
+void OutputDevice::BeginFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maGDIData.mbFontSubChanged = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::EndFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maGDIData.mbFontSubChanged )
+ {
+ ImplUpdateAllFontData( FALSE );
+
+ Application* pApp = GetpApp();
+ DataChangedEvent aDCEvt( DATACHANGED_FONTSUBSTITUTION );
+ pApp->DataChanged( aDCEvt );
+ pApp->NotifyAllWindows( aDCEvt );
+ pSVData->maGDIData.mbFontSubChanged = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddFontSubstitute( const XubString& rFontName,
+ const XubString& rReplaceFontName,
+ USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = new ImplFontSubstEntry;
+
+ pEntry->maName = rFontName;
+ pEntry->maReplaceName = rReplaceFontName;
+ pEntry->maMatchName = rFontName;
+ pEntry->maMatchReplaceName = rReplaceFontName;
+ pEntry->mnFlags = nFlags;
+ pEntry->mpNext = pSVData->maGDIData.mpFirstFontSubst;
+ pEntry->maMatchName.ToLowerAscii();
+ pEntry->maMatchReplaceName.ToLowerAscii();
+ ImplCutScriptAndSpaces( pEntry->maMatchName );
+ ImplCutScriptAndSpaces( pEntry->maMatchReplaceName );
+ pSVData->maGDIData.mpFirstFontSubst = pEntry;
+ pSVData->maGDIData.mbFontSubChanged = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::RemoveFontSubstitute( USHORT n )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ ImplFontSubstEntry* pPrev = NULL;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ if ( nCount == n )
+ {
+ pSVData->maGDIData.mbFontSubChanged = TRUE;
+ if ( pPrev )
+ pPrev->mpNext = pEntry->mpNext;
+ else
+ pSVData->maGDIData.mpFirstFontSubst = pEntry->mpNext;
+ delete pEntry;
+ break;
+ }
+
+ nCount++;
+ pPrev = pEntry;
+ pEntry = pEntry->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetFontSubstituteCount()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ nCount++;
+ pEntry = pEntry->mpNext;
+ }
+
+ return nCount;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetFontSubstitute( USHORT n,
+ XubString& rFontName,
+ XubString& rReplaceFontName,
+ USHORT& rFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ if ( nCount == n )
+ {
+ rFontName = pEntry->maName;
+ rReplaceFontName = pEntry->maReplaceName;
+ rFlags = pEntry->mnFlags;
+ break;
+ }
+
+ nCount++;
+ pEntry = pEntry->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplFontSubstitute( XubString& rFontName,
+ USHORT nFlags1, USHORT nFlags2 )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ while ( pEntry )
+ {
+ if ( ((pEntry->mnFlags & nFlags1) == nFlags2) &&
+ (pEntry->maMatchName == rFontName) )
+ {
+ rFontName = pEntry->maMatchReplaceName;
+ return TRUE;
+ }
+
+ pEntry = pEntry->mpNext;
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplDevFontList::ImplDevFontList() :
+ List( CONTAINER_MAXBLOCKSIZE, 96, 32 )
+{
+#if 0
+ mbIsInitMatchData = FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontList::~ImplDevFontList()
+{
+ // Alle Eintraege loeschen
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ // Liste der Font loeschen
+ ImplFontData* pFontData = pEntry->mpFirst;
+ do
+ {
+ ImplFontData* pTempFontData = pFontData;
+ pFontData = pFontData->mpNext;
+ delete pTempFontData;
+ }
+ while ( pFontData );
+ // Entry loeschen
+ delete pEntry;
+
+ pEntry = Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static StringCompare ImplCompareFontDataWithoutSize( const ImplFontData* pEntry1,
+ const ImplFontData* pEntry2 )
+{
+ // Vergleichen nach CharSet, Groesse, Breite, Weight, Italic, StyleName
+ if ( pEntry1->meCharSet < pEntry2->meCharSet )
+ return COMPARE_LESS;
+ else if ( pEntry1->meCharSet > pEntry2->meCharSet )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meWidthType < pEntry2->meWidthType )
+ return COMPARE_LESS;
+ else if ( pEntry1->meWidthType > pEntry2->meWidthType )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meWeight < pEntry2->meWeight )
+ return COMPARE_LESS;
+ else if ( pEntry1->meWeight > pEntry2->meWeight )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meItalic < pEntry2->meItalic )
+ return COMPARE_LESS;
+ else if ( pEntry1->meItalic > pEntry2->meItalic )
+ return COMPARE_GREATER;
+
+ return pEntry1->maStyleName.CompareTo( pEntry2->maStyleName );
+}
+
+// -----------------------------------------------------------------------
+
+static StringCompare ImplCompareFontData( const ImplFontData* pEntry1,
+ const ImplFontData* pEntry2 )
+{
+ StringCompare eComp = ImplCompareFontDataWithoutSize( pEntry1, pEntry2 );
+ if ( eComp != COMPARE_EQUAL )
+ return eComp;
+
+ if ( pEntry1->mnHeight < pEntry2->mnHeight )
+ return COMPARE_LESS;
+ else if ( pEntry1->mnHeight > pEntry2->mnHeight )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->mnWidth < pEntry2->mnWidth )
+ return COMPARE_LESS;
+ else if ( pEntry1->mnWidth > pEntry2->mnWidth )
+ return COMPARE_GREATER;
+
+ return COMPARE_EQUAL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::Add( ImplFontData* pNewData )
+{
+ XubString aSearchName = pNewData->maName;
+ aSearchName.ToLowerAscii();
+
+ // Query Script for FontTest
+ rtl_TextEncodingInfo aTEncInfo;
+ aTEncInfo.StructSize = sizeof( aTEncInfo );
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( pNewData->meCharSet, &aTEncInfo );
+ pNewData->meScript = aTEncInfo.Script;
+
+ // Add Font
+ ULONG nIndex;
+ ImplDevFontListData* pFoundData = ImplFind( aSearchName, &nIndex );
+ BOOL bDelete = FALSE;
+
+ if ( !pFoundData )
+ {
+ pFoundData = new ImplDevFontListData;
+ pFoundData->maName = pNewData->maName;
+ pFoundData->maMatchName = aSearchName;
+ pFoundData->maMatchName2 = aSearchName;
+ pFoundData->mpFirst = pNewData;
+#if 0
+ pFoundData->mbScalable = FALSE;
+ ImplStrEraseAllSymbols( pFoundData->maMatchName2 );
+/*
+ pFoundData->meMatchFamily = pNewData->meFamily;
+ pFoundData->meMatchPitch = pNewData->mePitch;
+ CharSet eCharSet = pNewData->meCharSet;
+ ImplFontAttrFromName( pFoundData->maMatchName2, pFoundData->meMatchFamily,
+ eCharSet, pFoundData->meMatchPitch );
+ pFoundData->mbSymbol = eCharSet == RTL_TEXTENCODING_SYMBOL;
+*/
+#else
+ pFoundData->meMatchFamily = pNewData->meFamily;
+ pFoundData->meMatchPitch = pNewData->mePitch;
+ pFoundData->mnMatch = 0;
+ CharSet eCharSet = pNewData->meCharSet;
+ ImplStrEraseAllSymbols( pFoundData->maMatchName2 );
+ ImplFontAttrFromName( pFoundData->maMatchName2, pFoundData->meMatchFamily,
+ eCharSet, pFoundData->meMatchPitch );
+ pFoundData->mbSymbol = eCharSet == RTL_TEXTENCODING_SYMBOL;
+#endif
+
+ pNewData->mpNext = NULL;
+ Insert( pFoundData, nIndex );
+ }
+ else
+ {
+ // Name ersetzen (spart Speicherplatz)
+ pNewData->maName = pFoundData->maName;
+
+ BOOL bInsert = TRUE;
+ ImplFontData* pPrev = NULL;
+ ImplFontData* pTemp = pFoundData->mpFirst;
+ do
+ {
+ StringCompare eComp = ImplCompareFontData( pNewData, pTemp );
+ if ( eComp != COMPARE_GREATER )
+ {
+ // Wenn Font gleich ist, nehmen wir einen Devicefont,
+ // oder ignorieren den Font
+ if ( eComp == COMPARE_EQUAL )
+ {
+ // Wir nehmen den Font mit der besseren Quality,
+ // ansonsten ziehen wir den Device-Font vor
+ if ( (pNewData->mnQuality > pTemp->mnQuality) ||
+ ((pNewData->mnQuality == pTemp->mnQuality) &&
+ (pNewData->mbDevice && !pTemp->mbDevice)) )
+ {
+ pNewData->mpNext = pTemp->mpNext;
+ if ( pPrev )
+ pPrev->mpNext = pNewData;
+ else
+ pFoundData->mpFirst = pNewData;
+ delete pTemp;
+ }
+ else
+ {
+ bDelete = TRUE;
+ delete pNewData;
+ }
+
+ bInsert = FALSE;
+ }
+ break;
+ }
+
+ pPrev = pTemp;
+ pTemp = pTemp->mpNext;
+ }
+ while ( pTemp );
+
+ if ( bInsert )
+ {
+ pNewData->mpNext = pTemp;
+ if ( pPrev )
+ pPrev->mpNext = pNewData;
+ else
+ pFoundData->mpFirst = pNewData;
+ }
+ }
+
+ // Match zusammenzaehlen
+ if ( !bDelete )
+ {
+#if 0
+ if ( (pNewData->meType == TYPE_SCALABLE) && (pNewData->mnHeight == 0) )
+ pFoundData->mbScalable = TRUE;
+#else
+ if ( (pNewData->meType == TYPE_SCALABLE) && (pNewData->mnHeight == 0) )
+ {
+ if ( pNewData->meWidthType == WIDTH_NORMAL )
+ pFoundData->mnMatch += 30;
+ else
+ pFoundData->mnMatch += 3;
+ if ( pNewData->meItalic == ITALIC_NONE )
+ pFoundData->mnMatch += 20;
+ else
+ pFoundData->mnMatch += 2;
+ if ( (pNewData->meWeight == WEIGHT_NORMAL) || (pNewData->meWeight == WEIGHT_MEDIUM) )
+ pFoundData->mnMatch += 10;
+ else
+ pFoundData->mnMatch += 1;
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::ImplFind( const XubString& rFontName, ULONG* pIndex ) const
+{
+ ULONG nCount = Count();
+ if ( !nCount )
+ {
+ if ( pIndex )
+ *pIndex = LIST_APPEND;
+ return NULL;
+ }
+
+ // Fonts in der Liste suchen
+ ImplDevFontListData* pCompareData;
+ ImplDevFontListData* pFoundData = NULL;
+ ULONG nLow = 0;
+ ULONG nHigh = nCount-1;
+ ULONG nMid;
+ StringCompare eCompare;
+
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ pCompareData = Get( nMid );
+ eCompare = rFontName.CompareTo( pCompareData->maMatchName );
+ if ( eCompare == COMPARE_LESS )
+ {
+ if ( !nMid )
+ break;
+ nHigh = nMid-1;
+ }
+ else
+ {
+ if ( eCompare == COMPARE_GREATER )
+ nLow = nMid + 1;
+ else
+ {
+ pFoundData = pCompareData;
+ break;
+ }
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( pIndex )
+ {
+ eCompare = rFontName.CompareTo( pCompareData->maMatchName );
+ if ( eCompare == COMPARE_GREATER )
+ *pIndex = (nMid+1);
+ else
+ *pIndex = nMid;
+ }
+
+ return pFoundData;
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::FindFont( const XubString& rFontName ) const
+{
+ XubString aName = rFontName;
+ aName.ToLowerAscii();
+ ImplCutScriptAndSpaces( aName );
+ return ImplFind( aName );
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::FindStdFont( const sal_Char** pStdFontNames,
+ rtl_Script eScript ) const
+{
+ // We want a scalable font with a system script
+ ImplDevFontListData* pRasterFoundData = NULL;
+ ImplDevFontListData* pWrongScriptRasterData = NULL;
+ ImplDevFontListData* pWrongScriptData = NULL;
+ while ( *pStdFontNames )
+ {
+ XubString aStdName( *pStdFontNames, RTL_TEXTENCODING_ASCII_US );
+ ImplDevFontListData* pFoundData = ImplFind( aStdName );
+ if ( pFoundData )
+ {
+ if ( (eScript == SCRIPT_SYMBOL) ||
+ ImplFindScript( pFoundData, eScript ) )
+ {
+ if ( pFoundData->mpFirst->meType != TYPE_RASTER )
+ return pFoundData;
+ else if ( !pRasterFoundData )
+ pRasterFoundData = pFoundData;
+ }
+ else
+ {
+ if ( pFoundData->mpFirst->meType != TYPE_RASTER )
+ {
+ if ( !pWrongScriptData )
+ pWrongScriptData = pFoundData;
+ }
+ else
+ {
+ if ( !pWrongScriptRasterData )
+ pWrongScriptRasterData = pFoundData;
+ }
+ }
+ }
+ pStdFontNames++;
+ }
+
+ // Wenn keine passende Schrift, dann die Reihenfolge:
+ // - passender Zeichensatz
+ // - Skalierbar
+ // - eine passende Schrift die nicht skalierbar und den
+ // falschen Zeichensatz hat
+ // - keine
+ if ( pRasterFoundData )
+ return pRasterFoundData;
+ else if ( pWrongScriptData )
+ return pWrongScriptData;
+ else
+ return pWrongScriptRasterData;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::Clear()
+{
+ // Alle Eintraege loeschen
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ // Liste der Font loeschen
+ ImplFontData* pFontData = pEntry->mpFirst;
+ do
+ {
+ ImplFontData* pTempFontData = pFontData;
+ pFontData = pFontData->mpNext;
+ delete pTempFontData;
+ }
+ while ( pFontData );
+ // Entry loeschen
+ delete pEntry;
+
+ pEntry = Next();
+ }
+ List::Clear();
+
+ // Standard-Fonts loeschen
+ for ( USHORT i = 0; i < IMPL_STDFONT_COUNT; i++ )
+ mpStdFontAry[i] = NULL;
+#if 0
+ mbIsInitMatchData = FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#if 0
+void ImplDevFontList::InitMatchData()
+{
+ if ( mbIsInitMatchData )
+ return;
+ mbIsInitMatchData = TRUE;
+/*
+ // Fuer alle Eintraege die Matchdaten ermitteln
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ ImplFontData* pFontData = pEntry->mpFirst;
+
+ pEntry = Next();
+ }
+*/
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::InitStdFonts()
+{
+ rtl_Script eSystemScript;
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ aTextEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( gsl_getSystemTextEncoding(), &aTextEncInfo );
+ eSystemScript = aTextEncInfo.Script;
+
+ mpStdFontAry[IMPL_STDFONT_SWISS] = FindStdFont( aImplStdSwissList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_ROMAN] = FindStdFont( aImplStdRomanList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_FIXED] = FindStdFont( aImplStdFixedList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_SCRIPT] = FindStdFont( aImplStdScriptList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_SYMBOL] = FindStdFont( aImplStdSymbolList, SCRIPT_SYMBOL );
+}
+
+// =======================================================================
+
+void ImplGetDevSizeList::Add( long nNewHeight )
+{
+ ULONG n = Count();
+ if ( !n || (nNewHeight > Get( n-1 )) )
+ Insert( (void*)nNewHeight, LIST_APPEND );
+ else
+ {
+ for ( ULONG i=0 ; i < n; i++ )
+ {
+ long nHeight = Get( i );
+
+ if ( nNewHeight <= nHeight )
+ {
+ if ( nNewHeight != nHeight )
+ Insert( (void*)nNewHeight, i );
+ break;
+ }
+ }
+ }
+}
+
+// =======================================================================
+
+ImplFontEntry::~ImplFontEntry()
+{
+ if ( mpWidthAry )
+ delete mpWidthAry;
+
+ if ( mpKernPairs )
+ delete mpKernPairs;
+
+ if ( mpKernInfo )
+ delete mpKernInfo;
+}
+
+// =======================================================================
+
+ImplFontCache::ImplFontCache( BOOL bPrinter )
+{
+ mpFirstEntry = NULL;
+ mnRef0Count = 0;
+ mbPrinter = bPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontCache::~ImplFontCache()
+{
+ // Alle Eintraege loeschen
+ ImplFontEntry* pTemp;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ pTemp = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pTemp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontEntry* ImplFontCache::Get( ImplDevFontList* pFontList,
+ const Font& rFont, const Size& rSize )
+{
+ const XubString& rName = rFont.GetName();
+ const XubString& rStyleName = rFont.GetStyleName();
+ long nWidth = rSize.Width();
+ long nHeight = rSize.Height();
+ FontFamily eFamily = rFont.GetFamily();
+ CharSet eCharSet = rFont.GetCharSet();
+ FontWeight eWeight = rFont.GetWeight();
+ FontItalic eItalic = rFont.GetItalic();
+ FontPitch ePitch = rFont.GetPitch();
+ short nOrientation = (short)(rFont.GetOrientation() % 3600);
+ BOOL bShadow = rFont.IsShadow();
+ BOOL bOutline = rFont.IsOutline();
+
+ // Groesse anpassen
+ if ( nHeight < 0 )
+ nHeight = -nHeight;
+ if ( nWidth < 0 )
+ nWidth = -nWidth;
+
+ // Eintrag suchen
+ ImplFontEntry* pPrevEntry = NULL;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ ImplFontSelectData* pFontSelData = &(pEntry->maFontSelData);
+ if ( (nHeight == pFontSelData->mnHeight) &&
+ (eWeight == pFontSelData->meWeight) &&
+ (eItalic == pFontSelData->meItalic) &&
+ (rName == pFontSelData->maName) &&
+ (rStyleName == pFontSelData->maStyleName) &&
+ (eCharSet == pFontSelData->meCharSet) &&
+ (eFamily == pFontSelData->meFamily) &&
+ (ePitch == pFontSelData->mePitch) &&
+ (nWidth == pFontSelData->mnWidth) &&
+ (nOrientation == pFontSelData->mnOrientation) )
+ {
+ if ( !pEntry->mnRefCount )
+ mnRef0Count--;
+
+ pEntry->mnRefCount++;
+
+ // Entry nach vorne bringen
+ if ( pPrevEntry )
+ {
+ pPrevEntry->mpNext = pEntry->mpNext;
+ pEntry->mpNext = mpFirstEntry;
+ mpFirstEntry = pEntry;
+ }
+
+ return pEntry;
+ }
+
+ pPrevEntry = pEntry;
+ pEntry = pEntry->mpNext;
+ }
+
+ // Wir suchen zuerst ueber den Namen den passenden Font
+ XubString aLowerFontName = rName;
+ XubString aFirstName;
+ XubString aTempName;
+ XubString aTempName2;
+ ImplDevFontListData* pFoundData;
+ ImplDevFontListData* pTempFoundData;
+ xub_StrLen nFirstNameIndex = 0;
+ xub_StrLen nIndex = 0;
+ USHORT nSubstFlags1 = FONT_SUBSTITUTE_ALWAYS;
+ USHORT nSubstFlags2 = FONT_SUBSTITUTE_ALWAYS;
+ rtl_Script eScript = SCRIPT_DONTKNOW;
+ rtl_Script eCharSetScript;
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ aTextEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( eCharSet, &aTextEncInfo );
+ eCharSetScript = aTextEncInfo.Script;
+ if ( mbPrinter )
+ nSubstFlags1 |= FONT_SUBSTITUTE_SCREENONLY;
+ aLowerFontName.ToLowerAscii();
+ pTempFoundData = NULL;
+ do
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( !aFirstName.Len() )
+ {
+ aFirstName = aTempName;
+ nFirstNameIndex = nIndex;
+ }
+ ImplFontSubstitute( aTempName, nSubstFlags1, nSubstFlags2 );
+ pFoundData = pFontList->ImplFind( aTempName );
+ if ( pFoundData )
+ {
+ if ( eCharSetScript != SCRIPT_DONTKNOW )
+ {
+ if ( !pTempFoundData )
+ {
+ aTempName2 = aTempName;
+ pTempFoundData = pFoundData;
+ }
+
+ // Testen, ob ein Font mit einem entsprechendem
+ // Script vorhanden ist
+ if ( ImplFindScript( pFoundData, eCharSetScript ) )
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ else
+ pFoundData = NULL;
+ }
+ else
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ }
+ }
+ while ( nIndex != STRING_NOTFOUND );
+ if ( !pFoundData && pTempFoundData )
+ {
+ pFoundData = pTempFoundData;
+ aLowerFontName = aTempName2;
+ }
+
+ // Danach versuchen wir es nocheinmal unter Beruecksichtigung
+ // der gloablen Fontersetzungstabelle, wobei wir jetzt auch
+ // die Fonts nehmen, die ersetzt werden sollen, wenn sie
+ // nicht vorhanden sind
+ if ( !pFoundData )
+ {
+ nSubstFlags1 &= ~FONT_SUBSTITUTE_ALWAYS;
+ nSubstFlags2 &= ~FONT_SUBSTITUTE_ALWAYS;
+ nIndex = 0;
+ do
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( ImplFontSubstitute( aTempName, nSubstFlags1, nSubstFlags2 ) )
+ {
+ pFoundData = pFontList->ImplFind( aTempName );
+ if ( pFoundData )
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ }
+ }
+ while ( nIndex != STRING_NOTFOUND );
+ }
+
+ // Wenn kein Font mit dem entsprechenden Namen existiert, versuchen
+ // wir ueber den Namen und die Attribute einen passenden Font zu
+ // finden
+ ULONG nFontCount = pFontList->Count();
+ if ( !pFoundData && nFontCount )
+ {
+#if 0
+ pFontList->InitMatchData();
+
+ // 1. Token vom Fontnamen nehmen und Sonderzeichen entfernen
+ XubString aNoSymbolName = aFirstName;
+ ImplCutScriptAndSpaces( aNoSymbolName );
+ ImplStrEraseAllSymbols( aNoSymbolName );
+
+ // Script evtl. aus CharSet gewinnen, wenn nicht ueber den Fontnamen
+ // ermittelt werden konnte
+ if ( eScript == SCRIPT_DONTKNOW )
+ eScript = eCharSetScript;
+
+ // wir versuchen zuerst einen Font zu finden, der ueber den Namen
+ // matched
+ ULONG nTestMatch;
+ ULONG nBestMatch = 0;
+ for ( ULONG i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+
+ nTestMatch = 0;
+
+ // Wir wollen schon Zeichen erkennen
+ if ( eScript != SCRIPT_DONTKNOW )
+ {
+ if ( ImplFindScript( pData, eScript ) )
+ nTestMatch += 1000000000;
+ }
+
+ // skalierbare Schriften haben schon einen echten Vorteil
+ // gegenueber nicht skalierbaren Schriften
+ if ( pData->mbScalable )
+ nTestMatch += 500000000;
+
+/*
+ // Wir gehen davon aus, wenn der Name groesstenteils matcht,
+ // das er schon zur richtigen Familie gehoert
+
+
+ // Beim matchen ignorieren wir alle Sonderzeichen
+ ULONG nTestMatch = ImplStrMatch( aNoSymbolName, pData->maMatchName2 );
+ if ( nTestMatch >= nBestMatch )
+ {
+ // Match nur erlaubt, wenn auch die Attribute uebereinstimmen
+ BOOL bTestFamily = pData->meMatchFamily != FAMILY_DONTKNOW;
+ BOOL bTestSymbol = pData->mbSymbol;
+ BOOL bTestFixed = pData->meMatchPitch == PITCH_FIXED;
+ if ( (bFixed == bTestFixed) && (bSymbol == bTestSymbol) &&
+ (!bFamily || !bTestFamily || (eSearchFamily == pData->meMatchFamily)) )
+ {
+ xub_StrLen nAttrMatch = 0;
+ // Die Anzahl der uebereinstimmenden Attribute zaehlen
+ const char** pTypeList = aImplTypeList;
+ while ( *pTypeList )
+ {
+ if ( (aNoSymbolName.Search( *pTypeList ) != STRING_NOTFOUND) &&
+ (pData->maMatchName2.Search( *pTypeList ) != STRING_NOTFOUND) )
+ nAttrMatch++;
+ pTypeList++;
+ }
+
+ // Wenn beide Matches gleich gut sind,
+ // entscheiden die uebereinstimmenden Attribute
+ if ( nBestMatch == nTestMatch )
+ {
+ if ( (nAttrMatch > nBestAttrMatch) ||
+ ((nAttrMatch == nBestAttrMatch) &&
+ (pData->maMatchName2.Len() < nBestStrLen)) )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ else
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ }
+*/
+
+ if ( nTestMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ }
+ }
+
+ if ( !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ // Wenn alles nichts hilft, nehmen wir den ersten
+ if ( !pFoundData )
+ pFontList->Get( 0 );
+ }
+#else
+ // 1. Token vom Fontnamen nehmen und Sonderzeichen entfernen
+ XubString aNoSymbolName = aFirstName;
+ ImplStrEraseAllSymbols( aNoSymbolName );
+
+ // Suchattribute ermitteln
+ BOOL bFamily;
+ BOOL bSymbol;
+ BOOL bFixed;
+ FontFamily eSearchFamily = eFamily;
+ CharSet eSearchCharSet = eCharSet;
+ FontPitch eSearchPitch = ePitch;
+ ImplFontAttrFromName( aNoSymbolName, eSearchFamily, eSearchCharSet, eSearchPitch );
+ bFamily = eSearchFamily != FAMILY_DONTKNOW;
+ bSymbol = eSearchCharSet == RTL_TEXTENCODING_SYMBOL;
+ bFixed = eSearchPitch == PITCH_FIXED;
+ // Solange in der Namesliste suchen, bis wir auswertbare
+ // Attribute gefunden haben
+ xub_StrLen nTempIndex = nFirstNameIndex;
+ while ( (nTempIndex != STRING_NOTFOUND) && !bFamily && !bFixed && !bSymbol )
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nTempIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( !aTempName.Len() )
+ break;
+ ImplStrEraseAllSymbols( aTempName );
+ ImplFontAttrFromName( aTempName, eSearchFamily, eSearchCharSet, eSearchPitch );
+ bFamily = eSearchFamily != FAMILY_DONTKNOW;
+ bSymbol = eSearchCharSet == RTL_TEXTENCODING_SYMBOL;
+ bFixed = eSearchPitch == PITCH_FIXED;
+ }
+ aLowerFontName = aFirstName;
+
+ // wir versuchen zuerst einen Font zu finden, der ueber den Namen
+ // matched
+ ULONG i;
+ xub_StrLen nBestMatch = 5;
+ xub_StrLen nBestAttrMatch = 0;
+ xub_StrLen nBestStrLen = 0xFFFF;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ // Beim matchen ignorieren wir alle Sonderzeichen
+ xub_StrLen nTestMatch = ImplStrMatch( aNoSymbolName, pData->maMatchName2 );
+ if ( nTestMatch >= nBestMatch )
+ {
+ // Match nur erlaubt, wenn auch die Attribute uebereinstimmen
+ BOOL bTestFamily = pData->meMatchFamily != FAMILY_DONTKNOW;
+ BOOL bTestSymbol = pData->mbSymbol;
+ BOOL bTestFixed = pData->meMatchPitch == PITCH_FIXED;
+ if ( (bFixed == bTestFixed) && (bSymbol == bTestSymbol) &&
+ (!bFamily || !bTestFamily || (eSearchFamily == pData->meMatchFamily)) )
+ {
+ xub_StrLen nAttrMatch = 0;
+ // Die Anzahl der uebereinstimmenden Attribute zaehlen
+ const char** pTypeList = aImplTypeList;
+ while ( *pTypeList )
+ {
+ if ( (aNoSymbolName.SearchAscii( *pTypeList ) != STRING_NOTFOUND) &&
+ (pData->maMatchName2.SearchAscii( *pTypeList ) != STRING_NOTFOUND) )
+ nAttrMatch++;
+ pTypeList++;
+ }
+
+ // Wenn beide Matches gleich gut sind,
+ // entscheiden die uebereinstimmenden Attribute
+ if ( nBestMatch == nTestMatch )
+ {
+ if ( (nAttrMatch > nBestAttrMatch) ||
+ ((nAttrMatch == nBestAttrMatch) &&
+ (pData->maMatchName2.Len() < nBestStrLen)) )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ else
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ }
+ }
+
+ // Wenn wir immer noch keinen passenden Font gefunden haben, versuchen
+ // wir es ueber die Attribute
+ if ( !pFoundData )
+ {
+ if ( bFixed )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_FIXED );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( (pData->meMatchPitch == PITCH_FIXED) &&
+ !pData->mbSymbol &&
+ (pData->meMatchFamily != FAMILY_DECORATIVE) )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bFamily && !pFoundData )
+ {
+ if ( eSearchFamily == FAMILY_SWISS )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SWISS );
+ else if ( eSearchFamily == FAMILY_ROMAN )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ else if ( eSearchFamily == FAMILY_SCRIPT )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SCRIPT );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( (pData->meMatchFamily == eSearchFamily) &&
+ !pData->mbSymbol &&
+ (pData->meMatchPitch != PITCH_FIXED) )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bSymbol && !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SYMBOL );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( pData->mbSymbol )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ // Wenn alles nichts hilft, nehmen wir den ersten
+ if ( !pFoundData )
+ pFontList->Get( 0 );
+ }
+ }
+#endif
+ }
+
+ // Script evtl. aus CharSet gewinnen, wenn nicht ueber den Fontnamen
+ // ermittelt werden konnte
+ if ( eScript == SCRIPT_DONTKNOW )
+ eScript = eCharSetScript;
+
+ // Jetzt suchen wir den Font ueber die Attribute
+ ImplFontData* pFontData = NULL;
+ if ( pFoundData )
+ {
+ ULONG nBestMatch = 0; // Der groessere Wert ist der bessere
+ ULONG nBestHeightMatch = 0; // Der kleinere Wert ist der bessere
+ ULONG nBestWidthMatch = 0; // Der kleinere Wert ist der bessere
+ ULONG nMatch;
+ ULONG nHeightMatch;
+ ULONG nWidthMatch;
+ ImplFontData* pCurFontData;
+
+// !!!!! Wegen Office-Fehler !!!!
+// XubString aCompareStyleName = rStyleName;
+// aCompareStyleName.ToLowerAscii();
+
+ // Vorallem wegen OS2-System-Standard-Fonts vergleichen wir
+ // den FontNamen mit FontName + StyleName, damit
+ // WarpSans Bold auch einen fetten Font ergibt
+ const xub_Unicode* pCompareStyleName = NULL;
+ if ( (aLowerFontName.Len() > pFoundData->maMatchName.Len()) &&
+ aLowerFontName.Equals( pFoundData->maMatchName, 0, pFoundData->maMatchName.Len() ) )
+ pCompareStyleName = aLowerFontName.GetBuffer()+pFoundData->maMatchName.Len()+1;
+
+ pCurFontData = pFoundData->mpFirst;
+ while ( pCurFontData )
+ {
+ nMatch = 0;
+ nHeightMatch = 0;
+ nWidthMatch = 0;
+
+// if ( aCompareStyleName.Len() &&
+// aCompareStyleName.EqualsIgnoreCaseAscii( pCurFontData->maStyleName ) )
+// nMatch += 120000;
+ if ( pCompareStyleName &&
+ pCurFontData->maStyleName.EqualsIgnoreCaseAscii( pCompareStyleName ) )
+ nMatch += 120000;
+
+ if ( eCharSet != RTL_TEXTENCODING_DONTKNOW )
+ {
+ if ( eCharSet == pCurFontData->meCharSet )
+ nMatch += 60000;
+ }
+
+ if ( eScript == pCurFontData->meScript )
+ nMatch += 30000;
+
+ if ( (ePitch != PITCH_DONTKNOW) && (ePitch == pCurFontData->mePitch) )
+ nMatch += 15000;
+
+ if ( (eFamily != FAMILY_DONTKNOW) && (eFamily == pCurFontData->meFamily) )
+ nMatch += 7500;
+
+ // Normale Schriftbreiten bevorzugen, da wir noch keine Daten
+ // von den Applikationen bekommen
+ if ( pCurFontData->meWidthType == WIDTH_NORMAL )
+ nMatch += 3750;
+
+ if ( eWeight != WEIGHT_DONTKNOW )
+ {
+ USHORT nReqWeight;
+ USHORT nGivenWeight;
+ USHORT nWeightDiff;
+ // schmale Fonts werden bei nicht Bold vor fetten
+ // Fonts bevorzugt
+ if ( eWeight > WEIGHT_MEDIUM )
+ nReqWeight = ((USHORT)eWeight)+100;
+ else
+ nReqWeight = (USHORT)eWeight;
+ if ( pCurFontData->meWeight > WEIGHT_MEDIUM )
+ nGivenWeight = ((USHORT)pCurFontData->meWeight)+100;
+ else
+ nGivenWeight = (USHORT)pCurFontData->meWeight;
+ if ( nReqWeight > nGivenWeight )
+ nWeightDiff = nReqWeight-nGivenWeight;
+ else
+ nWeightDiff = nGivenWeight-nReqWeight;
+
+ if ( nWeightDiff == 0 )
+ nMatch += 1000;
+ else if ( nWeightDiff == 1 )
+ nMatch += 700;
+ else if ( nWeightDiff < 50 )
+ nMatch += 200;
+ }
+ if ( eItalic == ITALIC_NONE )
+ {
+ if ( pCurFontData->meItalic == ITALIC_NONE )
+ nMatch += 900;
+ }
+ else
+ {
+ if ( eItalic == pCurFontData->meItalic )
+ nMatch += 900;
+ else if ( pCurFontData->meItalic != ITALIC_NONE )
+ nMatch += 600;
+ }
+
+ if ( pCurFontData->mbDevice )
+ nMatch += 40;
+ if ( pCurFontData->meType == TYPE_SCALABLE )
+ {
+ if ( nOrientation )
+ nMatch += 80;
+ else
+ {
+ if ( nWidth )
+ nMatch += 25;
+ else
+ nMatch += 5;
+ }
+ }
+ else
+ {
+ if ( nHeight == pCurFontData->mnHeight )
+ {
+ nMatch += 20;
+ if ( nWidth == pCurFontData->mnWidth )
+ nMatch += 10;
+ }
+ else
+ {
+ // Dann kommt die Size-Abweichung in die
+ // Bewertung rein. Hier bevorzugen wir
+ // nach Moeglichkeit den kleineren Font
+ if ( nHeight < pCurFontData->mnHeight )
+ nHeightMatch += pCurFontData->mnHeight-nHeight;
+ else
+ nHeightMatch += (nHeight-pCurFontData->mnHeight-nHeight)+10000;
+ if ( nWidth && pCurFontData->mnWidth && (nWidth != pCurFontData->mnWidth) )
+ {
+ if ( nWidth < pCurFontData->mnWidth )
+ nWidthMatch += pCurFontData->mnWidth-nWidth;
+ else
+ nWidthMatch += nWidth-pCurFontData->mnWidth-nWidth;
+ }
+ }
+ }
+
+ if ( nMatch > nBestMatch )
+ {
+ pFontData = pCurFontData;
+ nBestMatch = nMatch;
+ nBestHeightMatch = nHeightMatch;
+ nBestWidthMatch = nWidthMatch;
+ }
+ else if ( nMatch == nBestMatch )
+ {
+ // Wenn 2 gleichwertig sind, kommt die Size-Bewertung
+ // Hier gewinnt der jenige, der die niedrigere Abweichung
+ // in der Groesse hat (also den kleinsten Match)
+ if ( nHeightMatch < nBestHeightMatch )
+ {
+ pFontData = pCurFontData;
+ nBestHeightMatch = nHeightMatch;
+ nBestWidthMatch = nWidthMatch;
+ }
+ else if ( nHeightMatch == nBestHeightMatch )
+ {
+ if ( nWidthMatch < nBestWidthMatch )
+ {
+ pFontData = pCurFontData;
+ nBestWidthMatch = nWidthMatch;
+ }
+ }
+ }
+
+ pCurFontData = pCurFontData->mpNext;
+ }
+ }
+
+ // Daten initialisieren und in die Liste aufnehmen
+ pEntry = new ImplFontEntry;
+ pEntry->mbInit = FALSE;
+ pEntry->mnRefCount = 1;
+ pEntry->mpNext = mpFirstEntry;
+ pEntry->mnWidthAryCount = 0;
+ pEntry->mnWidthArySize = 0;
+ pEntry->mpWidthAry = NULL;
+ pEntry->mpKernPairs = NULL;
+ pEntry->mpKernInfo = NULL;
+ pEntry->mnOwnOrientation = 0;
+ pEntry->mnOrientation = 0;
+ mpFirstEntry = pEntry;
+
+ // Font-Selection-Daten setzen
+ ImplFontSelectData* pFontSelData = &(pEntry->maFontSelData);
+ pFontSelData->mpFontData = pFontData;
+ pFontSelData->mpSysSelData = NULL;
+ pFontSelData->maName = rName;
+ pFontSelData->maStyleName = rStyleName;
+ pFontSelData->mnWidth = nWidth;
+ pFontSelData->mnHeight = nHeight;
+ pFontSelData->meFamily = eFamily;
+ pFontSelData->meCharSet = eCharSet;
+ pFontSelData->meWidthType = WIDTH_DONTKNOW;
+ pFontSelData->meWeight = eWeight;
+ pFontSelData->meItalic = eItalic;
+ pFontSelData->mePitch = ePitch;
+ pFontSelData->mnOrientation = nOrientation;
+
+ return pEntry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFontCache::Release( ImplFontEntry* pEntry )
+{
+ pEntry->mnRefCount--;
+
+ if ( !pEntry->mnRefCount )
+ {
+ if ( mnRef0Count >= MAXFONT_CACHE )
+ {
+ // Letzten Entry mit RefCount 0 loeschen
+ ImplFontEntry* pPrevDelEntry = mpFirstEntry;
+ ImplFontEntry* pDelEntry = pPrevDelEntry->mpNext;
+ USHORT nCurRef0Count = !(pPrevDelEntry->mnRefCount);
+ while ( pDelEntry )
+ {
+ if ( !pDelEntry->mnRefCount )
+ nCurRef0Count++;
+
+ if ( nCurRef0Count >= MAXFONT_CACHE )
+ {
+ pPrevDelEntry->mpNext = pDelEntry->mpNext;
+ delete pDelEntry;
+ break;
+ }
+
+ pPrevDelEntry = pDelEntry;
+ pDelEntry = pDelEntry->mpNext;
+ }
+ }
+ else
+ mnRef0Count++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFontCache::Clear()
+{
+ // Alle Eintraege loeschen
+ ImplFontEntry* pTemp;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ DBG_ASSERT( !pEntry->mnRefCount, "ImplFontCache::Clear() - Font in use" );
+ pTemp = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pTemp;
+ }
+
+ mpFirstEntry = NULL;
+ mnRef0Count = 0;
+}
+
+// =======================================================================
+
+class ImplTextLineInfo
+{
+private:
+ long mnWidth;
+ xub_StrLen mnIndex;
+ xub_StrLen mnLen;
+
+public:
+ ImplTextLineInfo( long nWidth, xub_StrLen nIndex, xub_StrLen nLen )
+ {
+ mnWidth = nWidth;
+ mnIndex = nIndex;
+ mnLen = nLen;
+ }
+
+ long GetWidth() const { return mnWidth; }
+ xub_StrLen GetIndex() const { return mnIndex; }
+ xub_StrLen GetLen() const { return mnLen; }
+};
+
+#define MULTITEXTLINEINFO_RESIZE 16
+typedef ImplTextLineInfo* PImplTextLineInfo;
+
+class ImplMultiTextLineInfo
+{
+private:
+ PImplTextLineInfo* mpLines;
+ xub_StrLen mnLines;
+ xub_StrLen mnSize;
+
+public:
+ ImplMultiTextLineInfo();
+ ~ImplMultiTextLineInfo();
+
+ void AddLine( ImplTextLineInfo* pLine );
+ void Clear();
+
+ ImplTextLineInfo* GetLine( USHORT nLine ) const
+ { return mpLines[nLine]; }
+ xub_StrLen Count() const { return mnLines; }
+
+private:
+ ImplMultiTextLineInfo( const ImplMultiTextLineInfo& );
+ ImplMultiTextLineInfo& operator=( const ImplMultiTextLineInfo& );
+};
+
+ImplMultiTextLineInfo::ImplMultiTextLineInfo()
+{
+ mpLines = new PImplTextLineInfo[MULTITEXTLINEINFO_RESIZE];
+ mnLines = 0;
+ mnSize = MULTITEXTLINEINFO_RESIZE;
+}
+
+ImplMultiTextLineInfo::~ImplMultiTextLineInfo()
+{
+ for ( xub_StrLen i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ delete mpLines;
+}
+
+void ImplMultiTextLineInfo::AddLine( ImplTextLineInfo* pLine )
+{
+ if ( mnSize == mnLines )
+ {
+ mnSize += MULTITEXTLINEINFO_RESIZE;
+ PImplTextLineInfo* pNewLines = new PImplTextLineInfo[mnSize];
+ memcpy( pNewLines, mpLines, mnLines*sizeof(PImplTextLineInfo) );
+ mpLines = pNewLines;
+ }
+
+ mpLines[mnLines] = pLine;
+ mnLines++;
+}
+
+void ImplMultiTextLineInfo::Clear()
+{
+ for ( xub_StrLen i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ mnLines = 0;
+}
+
+// =======================================================================
+
+void OutputDevice::ImplInitFont()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mbInitFont )
+ {
+#ifndef REMOTE_APPSERVER
+ mpFontEntry->mnSetFontFlags = mpGraphics->SetFont( &(mpFontEntry->maFontSelData) );
+ mbInitFont = FALSE;
+#else
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ RemoteFont aFont;
+
+ if ( pFontEntry->maFontSelData.mpFontData )
+ {
+ aFont.maName = pFontEntry->maFontSelData.mpFontData->maName;
+ aFont.maStyleName = pFontEntry->maFontSelData.mpFontData->maStyleName;
+ }
+ else
+ {
+ aFont.maName = pFontEntry->maFontSelData.maName;
+ aFont.maStyleName = pFontEntry->maFontSelData.maStyleName;
+ }
+ aFont.mnWidth = pFontEntry->maFontSelData.mnWidth;
+ aFont.mnHeight = pFontEntry->maFontSelData.mnHeight;
+ aFont.meFamily = pFontEntry->maFontSelData.meFamily;
+ aFont.meCharSet = pFontEntry->maFontSelData.meCharSet;
+ aFont.meWidthType = pFontEntry->maFontSelData.meWidthType;
+ aFont.meWeight = pFontEntry->maFontSelData.meWeight;
+ aFont.meItalic = pFontEntry->maFontSelData.meItalic;
+ aFont.mePitch = pFontEntry->maFontSelData.mePitch;
+ aFont.mnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ mpGraphics->SetFont( aFont );
+ pFontEntry->mnSetFontFlags = 0;
+ mbInitFont = FALSE;
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitTextColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mbInitTextColor )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetTextColor( ImplColorToSal( GetTextColor() ) );
+#else
+ mpGraphics->SetTextColor( GetTextColor() );
+#endif
+ mbInitTextColor = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int OutputDevice::ImplNewFont()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !mbNewFont )
+ return TRUE;
+
+ mbNewFont = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return FALSE;
+ }
+ SalGraphics* pGraphics = mpGraphics;
+#else
+ // Da wegen Clipping hier NULL zurueckkommen kann, koennen wir nicht
+ // den Rueckgabewert nehmen
+ ImplGetServerGraphics();
+ ImplServerGraphics* pGraphics = mpGraphics;
+#endif
+
+ // Groesse umrechnen
+ Size aSize = ImplLogicToDevicePixel( maFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // Nur dann Defaultgroesse setzen, wenn Fonthoehe auch in logischen
+ // Koordinaaten 0 ist
+ if ( maFont.GetSize().Height() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*mnDPIY)/72;
+ }
+
+ // Neuen Font besorgen
+ ImplFontEntry* pOldEntry = mpFontEntry;
+ mpFontEntry = mpFontCache->Get( mpFontList, maFont, aSize );
+ ImplFontEntry* pFontEntry = mpFontEntry;
+
+ // Feststellen, ob Font neu selektiert werden muss
+ if ( pFontEntry != pOldEntry )
+ mbInitFont = TRUE;
+
+ // these two may be filled in remote version
+ ImplKernPairData* pKernPairs = NULL;
+ long nKernPairs = 0;
+ // Wenn Font nicht initialisiert ist, dann sofort selektieren
+ if ( !pFontEntry->mbInit )
+ {
+ ImplInitFont();
+
+ // und die Font-Daten besorgen
+ if ( pGraphics )
+ {
+ pFontEntry->mbInit = TRUE;
+
+ pFontEntry->maMetric.mnWidth = pFontEntry->maFontSelData.mnWidth;
+ pFontEntry->maMetric.meFamily = pFontEntry->maFontSelData.meFamily;
+ pFontEntry->maMetric.meCharSet = pFontEntry->maFontSelData.meCharSet;
+ pFontEntry->maMetric.meWeight = pFontEntry->maFontSelData.meWeight;
+ pFontEntry->maMetric.meItalic = pFontEntry->maFontSelData.meItalic;
+ pFontEntry->maMetric.mePitch = pFontEntry->maFontSelData.mePitch;
+ pFontEntry->maMetric.mnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ if ( pFontEntry->maFontSelData.mpFontData )
+ {
+ pFontEntry->maMetric.meType = pFontEntry->maFontSelData.mpFontData->meType;
+ pFontEntry->maMetric.maName = pFontEntry->maFontSelData.mpFontData->maName;
+ pFontEntry->maMetric.maStyleName= pFontEntry->maFontSelData.mpFontData->maStyleName;
+ pFontEntry->maMetric.mbDevice = pFontEntry->maFontSelData.mpFontData->mbDevice;
+ }
+ else
+ {
+ pFontEntry->maMetric.meType = TYPE_DONTKNOW;
+ pFontEntry->maMetric.maName = pFontEntry->maFontSelData.maName.GetToken( 0 );
+ pFontEntry->maMetric.maStyleName= pFontEntry->maFontSelData.maStyleName;
+ pFontEntry->maMetric.mbDevice = FALSE;
+ }
+ pFontEntry->maMetric.mnSuperscriptSize = 0;
+ pFontEntry->maMetric.mnSuperscriptOffset = 0;
+ pFontEntry->maMetric.mnSubscriptSize = 0;
+ pFontEntry->maMetric.mnSubscriptOffset = 0;
+ pFontEntry->maMetric.mnUnderlineSize = 0;
+ pFontEntry->maMetric.mnUnderlineOffset = 0;
+ pFontEntry->maMetric.mnBUnderlineSize = 0;
+ pFontEntry->maMetric.mnBUnderlineOffset = 0;
+ pFontEntry->maMetric.mnDUnderlineSize = 0;
+ pFontEntry->maMetric.mnDUnderlineOffset1 = 0;
+ pFontEntry->maMetric.mnDUnderlineOffset2 = 0;
+ pFontEntry->maMetric.mnWUnderlineSize = 0;
+ pFontEntry->maMetric.mnWUnderlineOffset = 0;
+ pFontEntry->maMetric.mnStrikeoutSize = 0;
+ pFontEntry->maMetric.mnStrikeoutOffset = 0;
+ pFontEntry->maMetric.mnBStrikeoutSize = 0;
+ pFontEntry->maMetric.mnBStrikeoutOffset = 0;
+ pFontEntry->maMetric.mnDStrikeoutSize = 0;
+ pFontEntry->maMetric.mnDStrikeoutOffset1 = 0;
+ pFontEntry->maMetric.mnDStrikeoutOffset2 = 0;
+#ifndef REMOTE_APPSERVER
+ pGraphics->GetFontMetric( &(pFontEntry->maMetric) );
+ pFontEntry->mnWidthFactor = pGraphics->GetCharWidth( 0, CHARCACHE_STD-1, pFontEntry->maWidthAry );
+#else
+ long nFactor = 0;
+
+ pGraphics->GetFontMetric(
+ pFontEntry->maMetric,
+ nFactor, 0, CHARCACHE_STD-1, pFontEntry->maWidthAry,
+ maFont.IsKerning(), &pKernPairs, nKernPairs
+ );
+ pFontEntry->mnWidthFactor = nFactor;
+#endif
+ if ( !pFontEntry->mnWidthFactor )
+ {
+ memset( pFontEntry->maWidthAry, 0, sizeof(long)*(CHARCACHE_STD-1) );
+ pFontEntry->mnWidthFactor = 1;
+ }
+
+ pFontEntry->mbFixedFont = pFontEntry->maMetric.mePitch == PITCH_FIXED;
+ pFontEntry->mnLineHeight = pFontEntry->maMetric.mnAscent+pFontEntry->maMetric.mnDescent;
+ pFontEntry->mbInitKernPairs = FALSE;
+ pFontEntry->mnKernPairs = nKernPairs;
+
+ if ( pFontEntry->maFontSelData.mnOrientation && !pFontEntry->maMetric.mnOrientation &&
+ (meOutDevType != OUTDEV_PRINTER) )
+ {
+ pFontEntry->mnOwnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ pFontEntry->mnOrientation = pFontEntry->mnOwnOrientation;
+ }
+ else
+ pFontEntry->mnOrientation = pFontEntry->maMetric.mnOrientation;
+ }
+ }
+
+ // Wenn Kerning gewuenscht ist, die Kerning-Werte ermitteln
+ if ( maFont.IsKerning() )
+ {
+ ImplInitKerningPairs( pKernPairs, nKernPairs );
+ mbKerning = (pFontEntry->mnKernPairs) != 0;
+ }
+ else
+ mbKerning = FALSE;
+
+ // Je nach TextAlign den TextOffset berechnen
+ TextAlign eAlign = maFont.GetAlign();
+ if ( eAlign == ALIGN_BASELINE )
+ {
+ mnTextOffX = 0;
+ mnTextOffY = 0;
+ }
+ else if ( eAlign == ALIGN_TOP )
+ {
+ long nOrientation = pFontEntry->mnOrientation;
+ if ( nOrientation )
+ {
+ double nRad = ((double)nOrientation * F_2PI) / 3600.0;
+ long nOff = pFontEntry->maMetric.mnAscent;
+ mnTextOffX = (long)(nOff * sin( nRad ));
+ mnTextOffY = (long)(nOff * cos( nRad ));
+ }
+ else
+ {
+ mnTextOffX = 0;
+ mnTextOffY = pFontEntry->maMetric.mnAscent;
+ }
+ }
+ else // eAlign == ALIGN_BOTTOM
+ {
+ long nOrientation = pFontEntry->mnOrientation;
+ if ( nOrientation )
+ {
+ double nRad = ((double)nOrientation * F_2PI) / 3600.0;
+ long nOff = pFontEntry->maMetric.mnDescent;
+ mnTextOffX = (long)(nOff - (nOff * sin( nRad )));
+ nOff = -nOff;
+ mnTextOffY = (long)(nOff * cos( nRad ));
+ }
+ else
+ {
+ mnTextOffX = 0;
+ mnTextOffY = -pFontEntry->maMetric.mnDescent;
+ }
+ }
+
+ mbTextLines = ((maFont.GetUnderline() != UNDERLINE_NONE) && (maFont.GetUnderline() != UNDERLINE_DONTKNOW)) ||
+ ((maFont.GetStrikeout() != STRIKEOUT_NONE) && (maFont.GetStrikeout() != STRIKEOUT_DONTKNOW));
+ mbTextSpecial = maFont.IsShadow() || maFont.IsOutline();
+
+ if ( pOldEntry )
+ mpFontCache->Release( pOldEntry );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetCharWidth( sal_Unicode c ) const
+{
+ USHORT nChar = (USHORT)c;
+ if ( nChar < CHARCACHE_STD )
+ return mpFontEntry->maWidthAry[nChar];
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ ImplWidthInfoData* pInfo;
+ ImplWidthInfoData* pWidthAry = pFontEntry->mpWidthAry;
+ USHORT nWidthCount = pFontEntry->mnWidthAryCount;
+ USHORT nInsIndex;
+
+ if ( nWidthCount )
+ {
+ USHORT nLow;
+ USHORT nHigh;
+ USHORT nMid;
+ USHORT nCompareChar;
+
+ nLow = 0;
+ nHigh = nWidthCount-1;
+ do
+ {
+ nMid = (nLow+nHigh)/2;
+ pInfo = pWidthAry+nMid;
+ nCompareChar = pInfo->mnChar;
+ if ( nChar < nCompareChar )
+ {
+ if ( !nMid )
+ break;
+ nHigh = nMid-1;
+ }
+ else
+ {
+ if ( nChar > nCompareChar )
+ nLow = nMid+1;
+ else
+ return pInfo->mnWidth;
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( nChar > nCompareChar )
+ nInsIndex = nMid+1;
+ else
+ nInsIndex = nMid;
+ }
+ else
+ {
+ pFontEntry->mnWidthArySize = WIDTHARY_INIT;
+ pFontEntry->mpWidthAry = new ImplWidthInfoData[pFontEntry->mnWidthArySize];
+ pWidthAry = pFontEntry->mpWidthAry;
+ nInsIndex = 0;
+ }
+
+ if ( nWidthCount == pFontEntry->mnWidthArySize )
+ {
+ USHORT nOldSize = pFontEntry->mnWidthArySize;
+ pFontEntry->mnWidthArySize += WIDTHARY_RESIZE;
+ pFontEntry->mpWidthAry = new ImplWidthInfoData[pFontEntry->mnWidthArySize];
+ memcpy( pFontEntry->mpWidthAry, pWidthAry, nOldSize*sizeof(ImplWidthInfoData) );
+ delete pWidthAry;
+ pWidthAry = pFontEntry->mpWidthAry;
+ }
+
+ // Um die Zeichenbreite zu ermitteln, brauchen wir einen Graphics und der
+ // Font muss natuerlich auch selektiert sein
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !((OutputDevice*)this)->ImplGetGraphics() )
+ return 0;
+ }
+#else
+ // Da wegen Clipping hier NULL zurueckkommen kann, koennen wir nicht
+ // den Rueckgabewert nehmen
+ ((OutputDevice*)this)->ImplGetServerGraphics();
+#endif
+
+ if ( mbNewFont )
+ ((OutputDevice*)this)->ImplNewFont();
+ if ( mbInitFont )
+ ((OutputDevice*)this)->ImplInitFont();
+
+ long nWidth;
+#ifndef REMOTE_APPSERVER
+ long nWidthFactor = mpGraphics->GetCharWidth( nChar, nChar, &nWidth );
+#else
+ long nWidthFactor = pFontEntry->mnWidthFactor;
+ mpGraphics->GetCharWidth( nChar, nChar, &nWidth );
+#endif
+ if ( !nWidthFactor )
+ return 0;
+
+ DBG_ASSERT( (nWidthFactor == pFontEntry->mnWidthFactor),
+ "OutputDevice::ImplGetCharWidth() - other WidthFactor" );
+
+ // Breite in Liste einfuegen und zurueckgeben
+ pInfo = pWidthAry+nInsIndex;
+ memmove( pInfo+1, pInfo, (nWidthCount-nInsIndex)*sizeof(ImplWidthInfoData) );
+ pFontEntry->mnWidthAryCount++;
+ pInfo->mnChar = nChar;
+ pInfo->mnWidth = nWidth;
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitKerningPairs( ImplKernPairData* pKernPairs, long nKernPairs )
+{
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ if ( !pFontEntry->mbInitKernPairs )
+ {
+ if ( mbInitFont )
+ ImplInitFont();
+ pFontEntry->mbInitKernPairs = TRUE;
+#ifndef REMOTE_APPSERVER
+ pFontEntry->mnKernPairs = mpGraphics->GetKernPairs( 0, NULL );
+ if ( pFontEntry->mnKernPairs )
+ {
+ ImplKernInfoData* pKernInfo = new ImplKernInfoData;
+ pKernPairs = new ImplKernPairData[pFontEntry->mnKernPairs];
+ memset( pKernPairs, 0, sizeof(ImplKernPairData)*pFontEntry->mnKernPairs );
+ pFontEntry->mnKernPairs = mpGraphics->GetKernPairs( pFontEntry->mnKernPairs, pKernPairs );
+ pFontEntry->mpKernInfo = pKernInfo;
+ pFontEntry->mpKernPairs = pKernPairs;
+
+ // Wir akzeptieren erstmal nur max. 65535-Paare
+ USHORT nMaxKernPairs;
+ if ( pFontEntry->mnKernPairs > 0xFFFF )
+ nMaxKernPairs = 0xFFFF;
+ else
+ nMaxKernPairs = (USHORT)pFontEntry->mnKernPairs;
+ memset( pKernInfo->maFirstAry, 0xFF, sizeof( pKernInfo->maFirstAry ) );
+ memset( pKernInfo->maLastAry, 0, sizeof( pKernInfo->maLastAry ) );
+ for ( USHORT i = 0; i < nMaxKernPairs; i++ )
+ {
+ USHORT nFirst = pKernPairs[i].mnChar1;
+ if ( nFirst < 0xFF )
+ {
+ if ( i < pKernInfo->maFirstAry[nFirst] )
+ pKernInfo->maFirstAry[nFirst] = i;
+ pKernInfo->maLastAry[nFirst] = i;
+ }
+ }
+ }
+#else
+ // Wir arbeiten erstmal nur mit USHORT
+ if( ! pKernPairs )
+ nKernPairs = mpGraphics->GetKernPairs( &pKernPairs );
+ if ( nKernPairs )
+ {
+ ImplKernInfoData* pKernInfo = new ImplKernInfoData;
+ pFontEntry->mpKernInfo = pKernInfo;
+ pFontEntry->mpKernPairs = pKernPairs;
+
+ // Wir akzeptieren erstmal nur max. 65535-Paare
+ USHORT nMaxKernPairs;
+ if( ! pFontEntry->mnKernPairs )
+ pFontEntry->mnKernPairs = nKernPairs;
+ if ( pFontEntry->mnKernPairs > 0xFFFF )
+ nMaxKernPairs = 0xFFFF;
+ else
+ nMaxKernPairs = (USHORT)pFontEntry->mnKernPairs;
+ memset( pKernInfo->maFirstAry, 0xFF, sizeof( pKernInfo->maFirstAry ) );
+ memset( pKernInfo->maLastAry, 0, sizeof( pKernInfo->maLastAry ) );
+ for ( USHORT i = 0; i < nMaxKernPairs; i++ )
+ {
+ USHORT nFirst = pKernPairs[i].mnChar1;
+ if ( nFirst < 0xFF )
+ {
+ if ( i < pKernInfo->maFirstAry[nFirst] )
+ pKernInfo->maFirstAry[nFirst] = i;
+ pKernInfo->maLastAry[nFirst] = i;
+ }
+ }
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplCalcKerning( const sal_Unicode* pStr, xub_StrLen nLen,
+ long* pDXAry, xub_StrLen nAryLen ) const
+{
+ if ( !nLen )
+ return 0;
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplKernPairData* pKernPairs = pEntry->mpKernPairs;
+ ImplKernInfoData* pKernInfo = pEntry->mpKernInfo;
+ long nWidth = 0;
+
+#ifdef DBG_UTIL
+ {
+ ImplKernPairData aTestPair;
+#ifdef __LITTLEENDIAN
+ ULONG nTestComp = ((ULONG)((USHORT)0xAABB) << 16) | (USHORT)0xCCDD;
+#else
+ ULONG nTestComp = ((ULONG)((USHORT)0xCCDD) << 16) | (USHORT)0xAABB;
+#endif
+ aTestPair.mnChar1 = 0xCCDD;
+ aTestPair.mnChar2 = 0xAABB;
+ DBG_ASSERT( nTestComp == *((ULONG*)&aTestPair), "Code doesn't work in this Version" );
+ }
+#endif
+
+ for ( USHORT i = 0; i < nLen-1; i++ )
+ {
+ USHORT nIndex = (USHORT)(unsigned char)pStr[i];
+ USHORT nFirst = pKernInfo->maFirstAry[nIndex];
+ USHORT nLast = pKernInfo->maLastAry[nIndex];
+#ifdef __LITTLEENDIAN
+ ULONG nComp = ((ULONG)((USHORT)(unsigned char)pStr[i+1]) << 16) | nIndex;
+#else
+ ULONG nComp = ((ULONG)nIndex << 16) | ((USHORT)(unsigned char)pStr[i+1]);
+#endif
+ for ( USHORT j = nFirst; j <= nLast; j++ )
+ {
+ if ( nComp == *((ULONG*)&(pKernPairs[j])) )
+ {
+ long nAmount = pKernPairs[j].mnKern;
+ nWidth += nAmount;
+ if ( pDXAry )
+ {
+ for ( USHORT n = i; n < nAryLen; n++ )
+ pDXAry[n] += nAmount;
+ }
+ }
+ }
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetTextWidth( const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDX )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nWidth = 0;
+
+ if ( nLen )
+ {
+ if ( pDX )
+ {
+ if ( nLen > 1 )
+ nWidth += pDX[nLen-2];
+ nWidth += ImplGetCharWidth( pStr[nLen-1] ) / nFactor;
+ }
+ else
+ {
+ // Bei Fixed-Fonts reicht eine Multiplikation
+ if ( pFontEntry->mbFixedFont )
+ nWidth = ImplGetCharWidth( 'A' ) * nLen;
+ else
+ {
+ const sal_Unicode* pTempStr = pStr;
+ xub_StrLen nTempLen = nLen;
+ while ( nTempLen )
+ {
+ nWidth += ImplGetCharWidth( *pTempStr );
+ nTempLen--;
+ pTempStr++;
+ }
+ }
+ nWidth /= nFactor;
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nWidth += ImplCalcKerning( pStr, nLen, NULL, 0 );
+ }
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplRotatePos( long nOriginX, long nOriginY, long& rX, long& rY,
+ short nOrientation )
+{
+ double nRealOrientation = nOrientation*F_PI1800;
+ double nCos = cos( nRealOrientation );
+ double nSin = sin( nRealOrientation );
+
+ // Translation...
+ long nX = rX-nOriginX;
+ long nY = rY-nOriginY;
+
+ // Rotation...
+ rX = ((long) ( nCos*nX + nSin*nY )) + nOriginX;
+ rY = ((long) - ( nSin*nX - nCos*nY )) + nOriginY;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextRect( long nBaseX, long nBaseY,
+ long nX, long nY, long nWidth, long nHeight )
+{
+ if ( mpFontEntry->mnOrientation )
+ {
+ if ( !(mpFontEntry->mnOrientation % 900) )
+ {
+ long nX2 = nX+nWidth;
+ long nY2 = nY+nHeight;
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nX2, nY2, mpFontEntry->mnOrientation );
+ nWidth = nX2-nX;
+ nHeight = nY2-nY;
+ }
+ else
+ {
+ // Da Polygone kleiner gezeichnet werden
+ nHeight++;
+ nWidth++;
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Polygon aPoly( aRect );
+ aPoly.Rotate( Point( nBaseX, nBaseY ), mpFontEntry->mnOrientation );
+#ifndef REMOTE_APPSERVER
+ ImplDrawPolygon( aPoly );
+#else
+ mpGraphics->DrawPolygon( aPoly );
+#endif
+ return;
+ }
+ }
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawRect( nX, nY, nWidth, nHeight );
+#else
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ mpGraphics->DrawRect( aRect );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextBackground( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( GetTextFillColor() ) );
+ mbInitFillColor = TRUE;
+
+ ImplDrawTextRect( nX, nY, nX, nY-mpFontEntry->maMetric.mnAscent,
+ ImplGetTextWidth( pStr, nLen, pDXAry ),
+ mpFontEntry->mnLineHeight );
+#else
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( GetTextFillColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ ImplDrawTextRect( nX, nY, nX, nY-mpFontEntry->maMetric.mnAscent,
+ ImplGetTextWidth( pStr, nLen, pDXAry ),
+ mpFontEntry->mnLineHeight );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplGetTextBoundRect( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ if( !nLen )
+ return Rectangle();
+
+ if ( mbNewFont )
+ ImplNewFont();
+
+ if ( mbInitFont )
+ ImplInitFont();
+
+ long nBaseX = nX, nBaseY = nY;
+ long nWidth = ImplGetTextWidth( pStr, nLen, pDXAry ), nHeight = mpFontEntry->mnLineHeight;
+
+ nY -= mpFontEntry->maMetric.mnAscent;
+
+ if ( mpFontEntry->mnOrientation )
+ {
+ if ( !(mpFontEntry->mnOrientation % 900) )
+ {
+ long nX2 = nX+nWidth;
+ long nY2 = nY+nHeight;
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nX2, nY2, mpFontEntry->mnOrientation );
+ nWidth = nX2-nX;
+ nHeight = nY2-nY;
+ }
+ else
+ {
+ // Da Polygone kleiner gezeichnet werden
+ nHeight++;
+ nWidth++;
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Polygon aPoly( aRect );
+ aPoly.Rotate( Point( nBaseX, nBaseY ), mpFontEntry->mnOrientation );
+ return aPoly.GetBoundRect();
+ }
+ }
+
+ return Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitTextLineSize()
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nLineHeight;
+ long nLineHeight2;
+ long nBLineHeight;
+ long nBLineHeight2;
+ long n2LineHeight;
+ long n2LineDY;
+ long n2LineDY2;
+ long nUnderlineOffset;
+ long nStrikeoutOffset;
+
+ nLineHeight = ((mpFontEntry->maMetric.mnDescent*25)+50) / 100;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+ nLineHeight2 = nLineHeight / 2;
+ if ( !nLineHeight2 )
+ nLineHeight2 = 1;
+
+ nBLineHeight = ((mpFontEntry->maMetric.mnDescent*50)+50) / 100;
+ if ( nBLineHeight == nLineHeight )
+ nBLineHeight++;
+ nBLineHeight2 = nBLineHeight/2;
+ if ( !nBLineHeight2 )
+ nBLineHeight2 = 1;
+
+ n2LineHeight = ((mpFontEntry->maMetric.mnDescent*16)+50) / 100;
+ if ( !n2LineHeight )
+ n2LineHeight = 1;
+ n2LineDY = n2LineHeight;
+ if ( n2LineDY <= 0 )
+ n2LineDY = 1;
+ n2LineDY2 = n2LineDY/2;
+ if ( !n2LineDY2 )
+ n2LineDY2 = 1;
+
+ nUnderlineOffset = mpFontEntry->maMetric.mnDescent/2 + 1;
+ nStrikeoutOffset = -((mpFontEntry->maMetric.mnAscent-mpFontEntry->maMetric.mnLeading)/3);
+
+ if ( !pFontEntry->maMetric.mnUnderlineSize )
+ {
+ pFontEntry->maMetric.mnUnderlineSize = nLineHeight;
+ pFontEntry->maMetric.mnUnderlineOffset = nUnderlineOffset - nLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnBUnderlineSize )
+ {
+ pFontEntry->maMetric.mnBUnderlineSize = nBLineHeight;
+ pFontEntry->maMetric.mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnDUnderlineSize )
+ {
+ pFontEntry->maMetric.mnDUnderlineSize = n2LineHeight;
+ pFontEntry->maMetric.mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight;
+ pFontEntry->maMetric.mnDUnderlineOffset2 = pFontEntry->maMetric.mnDUnderlineOffset1 + n2LineDY + n2LineHeight;
+ }
+ if ( !pFontEntry->maMetric.mnWUnderlineSize )
+ {
+ if ( mpFontEntry->maMetric.mnDescent < 6 )
+ {
+ if ( (mpFontEntry->maMetric.mnDescent == 1) ||
+ (mpFontEntry->maMetric.mnDescent == 2) )
+ pFontEntry->maMetric.mnWUnderlineSize = mpFontEntry->maMetric.mnDescent;
+ else
+ pFontEntry->maMetric.mnWUnderlineSize = 3;
+ }
+ else
+ pFontEntry->maMetric.mnWUnderlineSize = ((mpFontEntry->maMetric.mnDescent*50)+50) / 100;
+ pFontEntry->maMetric.mnWUnderlineOffset = nUnderlineOffset;
+ }
+ if ( !pFontEntry->maMetric.mnStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnStrikeoutSize = nLineHeight;
+ pFontEntry->maMetric.mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnBStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnBStrikeoutSize = nBLineHeight;
+ pFontEntry->maMetric.mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnDStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnDStrikeoutSize = n2LineHeight;
+ pFontEntry->maMetric.mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight;
+ pFontEntry->maMetric.mnDStrikeoutOffset2 = pFontEntry->maMetric.mnDStrikeoutOffset1 + n2LineDY + n2LineHeight;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawWavePixel( long nOriginX, long nOriginY,
+ long nCurX, long nCurY,
+ short nOrientation,
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics,
+#else
+ ImplServerGraphics* pGraphics,
+#endif
+ BOOL bDrawPixAsRect,
+ long nPixWidth, long nPixHeight )
+{
+ if ( nOrientation )
+ ImplRotatePos( nOriginX, nOriginY, nCurX, nCurY, nOrientation );
+
+ if ( bDrawPixAsRect )
+ {
+#ifndef REMOTE_APPSERVER
+ pGraphics->DrawRect( nCurX, nCurY, nPixWidth, nPixHeight );
+#else
+ Point aPos( nCurX, nCurY );
+ Size aSize( nPixWidth, nPixHeight );
+ Rectangle aRect( aPos, aSize );
+ pGraphics->DrawRect( aRect );
+#endif
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ pGraphics->DrawPixel( nCurX, nCurY );
+#else
+ Point aPos( nCurX, nCurY );
+ pGraphics->DrawPixel( aPos );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawWaveLine( long nBaseX, long nBaseY,
+ long nStartX, long nStartY,
+ long nWidth, long nHeight,
+ long nLineWidth, short nOrientation,
+ const Color& rColor )
+{
+ if ( !nHeight )
+ return;
+
+ // Bei Hoehe von 1 Pixel reicht es, eine Linie auszugeben
+ if ( (nLineWidth == 1) && (nHeight == 1) )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+ mbInitLineColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ SetLineColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+#endif
+
+ long nEndX = nStartX+nWidth;
+ long nEndY = nStartY;
+ if ( nOrientation )
+ {
+ ImplRotatePos( nBaseX, nBaseY, nStartX, nStartY, nOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nEndX, nEndY, nOrientation );
+ }
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawLine( nStartX, nStartY, nEndX, nEndY );
+#else
+ mpGraphics->DrawLine( Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+#endif
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+#endif
+ }
+ else
+ {
+ long nCurX = nStartX;
+ long nCurY = nStartY;
+ long nDiffX = 2;
+ long nDiffY = nHeight-1;
+ long nCount = nWidth;
+ long nOffY = -1;
+ long nFreq;
+ long i;
+ long nPixWidth;
+ long nPixHeight;
+ BOOL bDrawPixAsRect;
+#ifdef REMOTE_APPSERVER
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+#endif
+ // Auf Druckern die Pixel per DrawRect() ausgeben
+ if ( (GetOutDevType() == OUTDEV_PRINTER) || (nLineWidth > 1) )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( rColor ) );
+ mbInitFillColor = TRUE;
+#else
+ SetLineColor();
+ SetFillColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+#endif
+ bDrawPixAsRect = TRUE;
+ nPixWidth = nLineWidth;
+ nPixHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+ mbInitLineColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ SetLineColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+#endif
+ nPixWidth = 1;
+ nPixHeight = 1;
+ bDrawPixAsRect = FALSE;
+ }
+
+ if ( !nDiffY )
+ {
+ while ( nWidth )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nWidth--;
+ }
+ }
+ else
+ {
+ nCurY += nDiffY;
+ nFreq = nCount / (nDiffX+nDiffY);
+ while ( nFreq-- )
+ {
+ for( i = nDiffY; i; --i )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nCurY += nOffY;
+ }
+ for( i = nDiffX; i; --i )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ }
+ nOffY = -nOffY;
+ }
+ nFreq = nCount % (nDiffX+nDiffY);
+ if ( nFreq )
+ {
+ for( i = nDiffY; i && nFreq; --i, --nFreq )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nCurY += nOffY;
+ }
+ for( i = nDiffX; i && nFreq; --i, --nFreq )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ }
+ }
+ }
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextLine( long nBaseX,
+ long nX, long nY, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ Color aTextLineColor = GetTextLineColor();
+ long nBaseY = nY;
+ long nLineHeight;
+ long nLinePos;
+ long nLinePos2;
+ long nLeft;
+ BOOL bNormalLines = TRUE;
+
+ if ( !IsTextLineColor() )
+ aTextLineColor = GetTextColor();
+
+ if ( (eUnderline == UNDERLINE_SMALLWAVE) ||
+ (eUnderline == UNDERLINE_WAVE) ||
+ (eUnderline == UNDERLINE_DOUBLEWAVE) ||
+ (eUnderline == UNDERLINE_BOLDWAVE) )
+ {
+ if ( !pFontEntry->maMetric.mnWUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnWUnderlineSize;
+ if ( (eUnderline == UNDERLINE_SMALLWAVE) &&
+ (nLineHeight > 3) )
+ nLineHeight = 3;
+ long nLineWidth = (mnDPIX/300);
+ if ( !nLineWidth )
+ nLineWidth = 1;
+ if ( eUnderline == UNDERLINE_BOLDWAVE )
+ nLineWidth *= 2;
+ nLinePos = nY + pFontEntry->maMetric.mnWUnderlineOffset - (nLineHeight / 2);
+ long nLineWidthHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+ if ( eUnderline == UNDERLINE_DOUBLEWAVE )
+ {
+ long nOrgLineHeight = nLineHeight;
+ nLineHeight /= 3;
+ if ( nLineHeight < 2 )
+ {
+ if ( nOrgLineHeight > 1 )
+ nLineHeight = 2;
+ else
+ nLineHeight = 1;
+ }
+ long nLineDY = nOrgLineHeight-(nLineHeight*2);
+ if ( nLineDY < nLineWidthHeight )
+ nLineDY = nLineWidthHeight;
+ long nLineDY2 = nLineDY/2;
+ if ( !nLineDY2 )
+ nLineDY2 = 1;
+ nLinePos -= nLineWidthHeight-nLineDY2;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ nLinePos += nLineWidthHeight+nLineDY;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ }
+ else
+ {
+ nLinePos -= nLineWidthHeight/2;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ }
+
+ if ( (eStrikeout == STRIKEOUT_NONE) ||
+ (eStrikeout == STRIKEOUT_DONTKNOW) )
+ bNormalLines = FALSE;
+ }
+
+ if ( bNormalLines &&
+ ((eStrikeout == STRIKEOUT_SLASH) || (eStrikeout == STRIKEOUT_X)) )
+ {
+ BOOL bOldMap = IsMapModeEnabled();
+ EnableMapMode( FALSE );
+ Color aOldColor = GetTextColor();
+ SetTextColor( aTextLineColor );
+ ImplInitTextColor();
+ xub_Unicode c;
+ if ( eStrikeout == STRIKEOUT_SLASH )
+ c = '/';
+ else /* ( eStrikeout == STRIKEOUT_X ) */
+ c = 'X';
+ // Strikeout-String zusammenbauen
+ XubString aStrikeoutText( c );
+ aStrikeoutText += aStrikeoutText.GetChar( 0 );
+ long nStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ long nChars = nWidth/(nStrikeoutWidth/2);
+ aStrikeoutText.Fill( (USHORT)(nChars+1), c );
+ // String solange kuerzen, bis er nicht allzuweit uebersteht
+ long nMaxWidth = nStrikeoutWidth/4;
+ if ( nMaxWidth < 2 )
+ nMaxWidth = 2;
+ nMaxWidth += nWidth;
+ long nFullStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ while ( (nFullStrikeoutWidth > nMaxWidth) && aStrikeoutText.Len() )
+ {
+ aStrikeoutText.Erase( aStrikeoutText.Len()-1 );
+ nFullStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ }
+ if ( mpFontEntry->mnOrientation )
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplDrawTextDirect( nX, nY,
+ aStrikeoutText.GetBuffer(), aStrikeoutText.Len(),
+ NULL, FALSE );
+ SetTextColor( aOldColor );
+ ImplInitTextColor();
+ EnableMapMode( bOldMap );
+
+ if ( (eUnderline == UNDERLINE_NONE) ||
+ (eUnderline == UNDERLINE_DONTKNOW) ||
+ (eUnderline == UNDERLINE_SMALLWAVE) ||
+ (eUnderline == UNDERLINE_WAVE) ||
+ (eUnderline == UNDERLINE_DOUBLEWAVE) ||
+ (eUnderline == UNDERLINE_BOLDWAVE) )
+ bNormalLines = FALSE;
+ }
+
+ if ( bNormalLines )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( aTextLineColor ) );
+ mbInitFillColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( aTextLineColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+#endif
+
+ if ( eUnderline > UNDERLINE_LAST )
+ eUnderline = UNDERLINE_SINGLE;
+
+ if ( (eUnderline == UNDERLINE_SINGLE) ||
+ (eUnderline == UNDERLINE_DOTTED) ||
+ (eUnderline == UNDERLINE_DASH) ||
+ (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_DASHDOT) ||
+ (eUnderline == UNDERLINE_DASHDOTDOT) )
+ {
+ if ( !pFontEntry->maMetric.mnUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnUnderlineOffset;
+ }
+ else if ( (eUnderline == UNDERLINE_BOLD) ||
+ (eUnderline == UNDERLINE_BOLDDOTTED) ||
+ (eUnderline == UNDERLINE_BOLDDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOTDOT) )
+ {
+ if ( !pFontEntry->maMetric.mnBUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnBUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnBUnderlineOffset;
+ }
+ else if ( eUnderline == UNDERLINE_DOUBLE )
+ {
+ if ( !pFontEntry->maMetric.mnDUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnDUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnDUnderlineOffset1;
+ nLinePos2 = nY + pFontEntry->maMetric.mnDUnderlineOffset2;
+ }
+ else
+ nLineHeight = 0;
+
+ if ( nLineHeight )
+ {
+ nLeft = nX;
+
+ if ( (eUnderline == UNDERLINE_SINGLE) ||
+ (eUnderline == UNDERLINE_BOLD) )
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ else if ( eUnderline == UNDERLINE_DOUBLE )
+ {
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+ }
+ else if ( (eUnderline == UNDERLINE_DOTTED) ||
+ (eUnderline == UNDERLINE_BOLDDOTTED) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nTempWidth = nDotWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempWidth > nEnd )
+ nTempWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASH) ||
+ (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nMinDashWidth;
+ long nMinSpaceWidth;
+ long nSpaceWidth;
+ long nDashWidth;
+ if ( (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) )
+ {
+ nMinDashWidth = nDotWidth*6;
+ nMinSpaceWidth = nDotWidth*2;
+ nDashWidth = 200;
+ nSpaceWidth = 100;
+ }
+ else
+ {
+ nMinDashWidth = nDotWidth*4;
+ nMinSpaceWidth = (nDotWidth*150)/100;
+ nDashWidth = 100;
+ nSpaceWidth = 50;
+ }
+ nDashWidth = ((nDashWidth*mnDPIX)+1270)/2540;
+ nSpaceWidth = ((nSpaceWidth*mnDPIX)+1270)/2540;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ if ( nSpaceWidth < nMinSpaceWidth )
+ nSpaceWidth = nMinSpaceWidth;
+ long nTempWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempWidth > nEnd )
+ nTempWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+ nLeft += nDashWidth+nSpaceWidth;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASHDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOT) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nDashWidth = ((100*mnDPIX)+1270)/2540;
+ long nMinDashWidth = nDotWidth*4;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ long nTempDotWidth = nDotWidth;
+ long nTempDashWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDashWidth > nEnd )
+ nTempDashWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+ nLeft += nDashWidth+nDotWidth;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASHDOTDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOTDOT) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nDashWidth = ((100*mnDPIX)+1270)/2540;
+ long nMinDashWidth = nDotWidth*4;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ long nTempDotWidth = nDotWidth;
+ long nTempDashWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDashWidth > nEnd )
+ nTempDashWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+ nLeft += nDashWidth+nDotWidth;
+ }
+ }
+ }
+
+ if ( eStrikeout > STRIKEOUT_LAST )
+ eStrikeout = STRIKEOUT_SINGLE;
+
+ if ( eStrikeout == STRIKEOUT_SINGLE )
+ {
+ if ( !pFontEntry->maMetric.mnStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnStrikeoutOffset;
+ }
+ else if ( eStrikeout == STRIKEOUT_BOLD )
+ {
+ if ( !pFontEntry->maMetric.mnBStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnBStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnBStrikeoutOffset;
+ }
+ else if ( eStrikeout == STRIKEOUT_DOUBLE )
+ {
+ if ( !pFontEntry->maMetric.mnDStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnDStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnDStrikeoutOffset1;
+ nLinePos2 = nY + pFontEntry->maMetric.mnDStrikeoutOffset2;
+ }
+ else
+ nLineHeight = 0;
+
+ if ( nLineHeight )
+ {
+ nLeft = nX;
+
+ if ( (eStrikeout == STRIKEOUT_SINGLE) ||
+ (eStrikeout == STRIKEOUT_BOLD) )
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ else if ( eStrikeout == STRIKEOUT_DOUBLE )
+ {
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+ }
+ }
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextLines( long nX, long nY,
+ const sal_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline,
+ BOOL bWordLine )
+{
+ if ( bWordLine )
+ {
+ ::rtl::OUString aText( pStr, nLen );
+ uno::Reference < text::XBreakIterator > xBI = vcl::unohelper::CreateBreakIterator();
+ uno::Reference< linguistic::XHyphenator > xHyph;
+ text::LineBreakHyphenationOptions aHyphOptions( xHyph, 1 );
+ text::LineBreakUserOptions aUserOptions;
+
+ text::Boundary aBoundary = xBI->getWordBoundary( aText, 0, GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES, TRUE );
+ while ( ( aBoundary.startPos >= 0 ) && ( aBoundary.startPos < nLen ) )
+ {
+ xub_StrLen nWordEnd = Max( (xub_StrLen)aBoundary.endPos, nLen );
+ long nTempX = ImplGetTextWidth( pStr, aBoundary.startPos, pDXAry );
+ long nWidth = ImplGetTextWidth( pStr+aBoundary.startPos, aBoundary.endPos-aBoundary.startPos, pDXAry );
+ ImplDrawTextLine( nX, nX + nTempX, nY, nWidth, eStrikeout, eUnderline );
+ aBoundary = xBI->nextWord( aText, aBoundary.endPos, GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ }
+ }
+ else
+ {
+ ImplDrawTextLine( nX, nX, nY, ImplGetTextWidth( pStr, nLen, pDXAry ), eStrikeout, eUnderline );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawMnemonicLine( long nX, long nY, xub_Unicode c )
+{
+ ImplDrawTextLines( nX, nY, &c, 1, NULL, STRIKEOUT_NONE, UNDERLINE_SINGLE, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::ImplDrawRotateText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ if ( !mpOutDevData )
+ ImplInitOutDevData();
+ if ( !mpOutDevData->mpRotateDev )
+ mpOutDevData->mpRotateDev = new VirtualDevice( *this, 1 );
+ VirtualDevice* pVDev = mpOutDevData->mpRotateDev;
+ long nWidth = ImplGetTextWidth( pStr, nLen, pDXAry );
+ long nHeight = mpFontEntry->mnLineHeight;
+ Size aSize( nWidth, nHeight );
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Font aFont( GetFont() );
+ Bitmap aBmp;
+ long nOff;
+
+ nX -= mnTextOffX;
+ nY -= mnTextOffY;
+ if ( GetTextAlign() == ALIGN_TOP )
+ {
+ nOff = 0L;
+ nY += mpFontEntry->maMetric.mnAscent;
+ }
+ else if ( GetTextAlign() == ALIGN_BOTTOM )
+ {
+ nOff = mpFontEntry->maMetric.mnAscent;
+ nY += -mpFontEntry->maMetric.mnDescent;
+ }
+ else
+ nOff = mpFontEntry->maMetric.mnAscent;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( Size( mpFontEntry->maFontSelData.mnWidth, mpFontEntry->maFontSelData.mnHeight ) );
+ pVDev->SetFont( aFont );
+ // Da Farben und Alignment noch im Font haengen, muessen diese jedesmal
+ // gesetzt werden
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+ pVDev->ImplDrawText( 0, 0, pStr, nLen, pDXAry );
+
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ if ( !!aBmp && aBmp.Rotate( mpFontEntry->mnOwnOrientation, COL_WHITE ) )
+ {
+ Point aTempPoint;
+ Polygon aPoly( Rectangle( aTempPoint, aSize ) );
+ long nOldOffX = mnOutOffX;
+ long nOldOffY = mnOutOffY;
+ BOOL bOldMap = mbMap;
+
+ aTempPoint.Y() = nOff;
+ aPoly.Rotate( aTempPoint, mpFontEntry->mnOwnOrientation );
+ const Rectangle aBound( aPoly.GetBoundRect() );
+
+ mnOutOffX = 0L;
+ mnOutOffY = 0L;
+ mbMap = FALSE;
+
+ DrawMask( Point( nX + aBound.Left(),
+ nY + aBound.Top() - mpFontEntry->maMetric.mnAscent ),
+ aBmp, GetTextColor() );
+
+ mnOutOffX = nOldOffX;
+ mnOutOffY = nOldOffY;
+ mbMap = bOldMap;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextDirect( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry,
+ BOOL bTextLines )
+{
+ BOOL bDraw = FALSE;
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ if ( pFontEntry->mnOwnOrientation )
+ bDraw = ImplDrawRotateText( nX, nY, pStr, nLen, pDXAry );
+ if ( !bDraw )
+ {
+ if ( !pDXAry )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFontEntry->mnSetFontFlags & SAL_SETFONT_USEDRAWTEXTARRAY )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nOffset = 0;
+ long aStackAry[128];
+ long* pTempDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( USHORT i = 0; i < nLen-1; i++ )
+ {
+ nOffset += ImplGetCharWidth( pStr[i] );
+ pTempDXAry[i] = nOffset / nFactor;
+ }
+ mpGraphics->DrawTextArray( nX, nY, pStr, nLen, pTempDXAry );
+ ImplReleaseStackBuffer( pTempDXAry, aStackAry );
+ }
+ else
+#endif
+ mpGraphics->DrawText( nX, nY, pStr, nLen );
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFontEntry->mnSetFontFlags & SAL_SETFONT_USEDRAWTEXT )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nOffset = 0;
+ long nDiff;
+ long nTempX = nX;
+ const sal_Unicode* pTempStr = pStr;
+ xub_StrLen nCombineChars = 1;
+ for ( xub_StrLen i = 0; i < nLen-1; i++ )
+ {
+ nOffset += ImplGetCharWidth( pStr[i] );
+ nDiff = (nOffset/nFactor) - pDXAry[i];
+ if ( (nDiff < -1) || (nDiff > 0) )
+ {
+ mpGraphics->DrawText( nTempX, nY, pTempStr, nCombineChars );
+ nTempX = nX+pDXAry[i];
+ nOffset = pDXAry[i]*nFactor;
+ pTempStr += nCombineChars;
+ nCombineChars = 1;
+ }
+ else
+ nCombineChars++;
+ }
+ mpGraphics->DrawText( nTempX, nY, pTempStr, nCombineChars );
+ }
+ else
+#endif
+ mpGraphics->DrawTextArray( nX, nY, pStr, nLen, pDXAry );
+ }
+
+ if ( bTextLines )
+ {
+ ImplDrawTextLines( nX, nY, pStr, nLen, pDXAry,
+ maFont.GetStrikeout(),
+ maFont.GetUnderline(),
+ maFont.IsWordLineMode() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawSpecialText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ Color aOldColor = GetTextColor();
+ Color aOldTextLineColor = GetTextLineColor();
+
+ if ( maFont.IsShadow() )
+ {
+ long nOff = 1 + ((mpFontEntry->mnLineHeight-24)/24);
+ if ( maFont.IsOutline() )
+ nOff++;
+ SetTextLineColor();
+ if ( GetTextColor().GetColor() == COL_BLACK )
+ SetTextColor( Color( COL_LIGHTGRAY ) );
+ else
+ SetTextColor( Color( COL_BLACK ) );
+ ImplInitTextColor();
+ ImplDrawTextDirect( nX+nOff, nY+nOff, pStr, nLen, pDXAry, mbTextLines );
+ SetTextColor( aOldColor );
+ SetTextLineColor( aOldTextLineColor );
+ ImplInitTextColor();
+
+ if ( !maFont.IsOutline() )
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+ }
+
+ if ( maFont.IsOutline() )
+ {
+ ImplDrawTextDirect( nX-1, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX-1, nY, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX-1, nY-1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX, nY-1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY-1, pStr, nLen, pDXAry, mbTextLines );
+
+ SetTextColor( Color( COL_WHITE ) );
+ SetTextLineColor( Color( COL_WHITE ) );
+ ImplInitTextColor();
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+ SetTextColor( aOldColor );
+ SetTextLineColor( aOldTextLineColor );
+ ImplInitTextColor();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen, const long* pDXAry )
+{
+ nX += mnTextOffX;
+ nY += mnTextOffY;
+
+ if ( IsTextFillColor() )
+ ImplDrawTextBackground( nX, nY, pStr, nLen, pDXAry );
+
+ if ( mbTextSpecial )
+ ImplDrawSpecialText( nX, nY, pStr, nLen, pDXAry );
+ else
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplFillDXAry( long* pDXAry,
+ const xub_Unicode* pStr, xub_StrLen nLen, long nWidth )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+
+ // Breiten-Array fuer errechnete Werte mit den Breiten der einzelnen
+ // Character fuellen
+ xub_StrLen i;
+ long nSum = 0;
+ for ( i = 0; i < nLen; i++ )
+ {
+ // Characterbreiten ueber Array holen
+ nSum += ImplGetCharWidth( pStr[i] );
+ pDXAry[i] = nSum / nFactor;
+ }
+ nSum /= nFactor;
+
+ // Differenz zwischen Soll- und Ist-Laenge errechnen
+ // Zusaetzliche Pixel per Character errechnen
+ // Anzahl der zusaetzlich verbliebenen Pixel errechnen
+ long nDelta = (long)nWidth - nSum;
+ long nDeltaPerChar = 0;
+ long nDeltaRest = 0;
+ if ( nLen > 1 )
+ {
+ nDeltaPerChar = nDelta / (long)(nLen-1);
+ nDeltaRest = nDelta % (long)(nLen-1);
+ }
+ long nDeltaRestAbs = Abs( nDeltaRest );
+
+ long nErrorSum = nDeltaRestAbs;
+ long nDeltaSum = 0;
+ for ( i = 0; i < nLen-1; i++, nErrorSum += nDeltaRestAbs )
+ {
+ nDeltaSum += nDeltaPerChar;
+ if ( nErrorSum >= nLen-1 )
+ {
+ nErrorSum -= nLen-1;
+ if ( nDeltaRest > 0 )
+ nDeltaSum++;
+ else if ( nDeltaRest < 0 )
+ nDeltaSum--;
+ }
+ pDXAry[i] += nDeltaSum;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
+ long nWidth, const XubString& rStr,
+ USHORT nStyle ) const
+{
+ DBG_ASSERT( nWidth >= 0, "ImplGetTextLines: nWidth <= 0!" );
+
+ long nMaxLineWidth = 0;
+ rLineInfo.Clear();
+ if ( rStr.Len() && ( nWidth > 0 ) )
+ {
+ ::rtl::OUString aText( rStr );
+ uno::Reference < text::XBreakIterator > xBI;
+ uno::Reference< linguistic::XHyphenator > xHyph;
+ text::LineBreakHyphenationOptions aHyphOptions( xHyph, 1 );
+ text::LineBreakUserOptions aUserOptions;
+
+ USHORT nPos = 0;
+ USHORT nLen = rStr.Len();
+ while ( nPos < nLen )
+ {
+ xub_StrLen nBreakPos = nPos;
+ while ( ( nBreakPos < nLen ) && ( rStr.GetChar( nBreakPos ) != _CR ) && ( rStr.GetChar( nBreakPos ) != _LF ) )
+ nBreakPos++;
+
+ long nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ if ( ( nLineWidth > nWidth ) && ( nStyle & TEXT_DRAW_WORDBREAK ) )
+ {
+ if ( !xBI.is() )
+ xBI = vcl::unohelper::CreateBreakIterator();
+
+ xub_StrLen nSoftBreak = GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
+ DBG_ASSERT( nSoftBreak < nBreakPos, "Break?!" );
+ text::LineBreakResults aLBR = xBI->getLineBreak( aText, nSoftBreak, GetSettings().GetLocale(), nPos, aHyphOptions, aUserOptions );
+ nBreakPos = aLBR.breakIndex;
+ if ( nBreakPos <= nPos )
+ nBreakPos = nSoftBreak;
+ nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ }
+
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ if ( ( rStr.GetChar( nBreakPos ) == _CR ) || ( rStr.GetChar( nBreakPos ) == _LF ) )
+ {
+ nBreakPos++;
+ // CR/LF?
+ if ( ( nPos < nLen ) && ( rStr.GetChar( nBreakPos ) == _LF ) && ( rStr.GetChar( nBreakPos-1 ) == _CR ) )
+ nBreakPos++;
+ }
+
+ if ( nBreakPos == nPos )
+ nBreakPos++;
+
+ rLineInfo.AddLine( new ImplTextLineInfo( nLineWidth, nPos, nBreakPos-nPos ) );
+
+ nPos = nBreakPos;
+ }
+ }
+
+ return nMaxLineWidth;
+}
+
+// =======================================================================
+
+void OutputDevice::SetFont( const Font& rNewFont )
+{
+ DBG_TRACE( "OutputDevice::SetFont()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rNewFont, Font, NULL );
+
+ Font aFont( rNewFont );
+
+ if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
+ DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL) )
+ {
+ Color aTextColor( aFont.GetColor() );
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aTextColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aTextColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aTextColor.GetLuminance();
+ aTextColor = Color( cLum, cLum, cLum );
+ }
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aTextColor = Color( (aTextColor.GetRed() >> 1 ) | 0x80,
+ (aTextColor.GetGreen() >> 1 ) | 0x80,
+ (aTextColor.GetBlue() >> 1 ) | 0x80 );
+ }
+ aFont.SetColor( aTextColor );
+
+ BOOL bTransFill = aFont.IsTransparent();
+ if ( !bTransFill )
+ {
+ Color aTextFillColor( aFont.GetFillColor() );
+ if ( mnDrawMode & DRAWMODE_BLACKFILL )
+ aTextFillColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITEFILL )
+ aTextFillColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aTextFillColor.GetLuminance();
+ aTextFillColor = Color( cLum, cLum, cLum );
+ }
+ else if ( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aTextFillColor = Color( COL_TRANSPARENT );
+ bTransFill = TRUE;
+ }
+ if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
+ {
+ aTextFillColor = Color( (aTextFillColor.GetRed() >> 1) | 0x80,
+ (aTextFillColor.GetGreen() >> 1) | 0x80,
+ (aTextFillColor.GetBlue() >> 1) | 0x80 );
+ }
+ aFont.SetFillColor( aTextFillColor );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ const Color& rTextFillColor = aFont.GetFillColor();
+
+ mpMetaFile->AddAction( new MetaFontAction( aFont ) );
+ mpMetaFile->AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
+ mpMetaFile->AddAction( new MetaTextColorAction( aFont.GetColor() ) );
+ mpMetaFile->AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
+ }
+
+ if ( !maFont.IsSameInstance( aFont ) )
+ {
+ if ( maFont.GetColor() != aFont.GetColor() )
+ mbInitTextColor = TRUE;
+ maFont = aFont;
+ mbNewFont = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+ DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextColorAction( aColor ) );
+
+ if ( maFont.GetColor() != aColor )
+ {
+ maFont.SetColor( aColor );
+ mbInitTextColor = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextFillColor()
+{
+ DBG_TRACE( "OutputDevice::SetTextFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextFillColorAction( Color(), FALSE ) );
+
+ if ( maFont.GetColor() != Color( COL_TRANSPARENT ) )
+ maFont.SetFillColor( Color( COL_TRANSPARENT ) );
+ if ( !maFont.IsTransparent() )
+ maFont.SetTransparent( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextFillColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+ BOOL bTransFill = ImplIsColorTransparent( aColor );
+
+ if ( !bTransFill )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL |
+ DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKFILL )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITEFILL )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+ else if ( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aColor = Color( COL_TRANSPARENT );
+ bTransFill = TRUE;
+ }
+ if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextFillColorAction( aColor, TRUE ) );
+
+ if ( maFont.GetFillColor() != aColor )
+ maFont.SetFillColor( aColor );
+ if ( maFont.IsTransparent() != bTransFill )
+ maFont.SetTransparent( bTransFill );
+}
+
+// -----------------------------------------------------------------------
+
+Color OutputDevice::GetTextFillColor() const
+{
+ if ( maFont.IsTransparent() )
+ return Color( COL_TRANSPARENT );
+ else
+ return maFont.GetFillColor();
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextLineColor()
+{
+ DBG_TRACE( "OutputDevice::SetTextLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineColorAction( Color(), FALSE ) );
+
+ maTextLineColor = Color( COL_TRANSPARENT );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextLineColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+ DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, TRUE ) );
+
+ maTextLineColor = aColor;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextAlign( TextAlign eAlign )
+{
+ DBG_TRACE( "OutputDevice::SetTextAlign()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextAlignAction( eAlign ) );
+
+ if ( maFont.GetAlign() != eAlign )
+ {
+ maFont.SetAlign( eAlign );
+ mbNewFont = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTextLine( const Point& rPos, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline )
+{
+ DBG_TRACE( "OutputDevice::DrawTextLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline ) );
+
+ if ( ((eUnderline == UNDERLINE_NONE) || (eUnderline == UNDERLINE_DONTKNOW)) &&
+ ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
+ return;
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+
+ Point aPos = ImplLogicToDevicePixel( rPos );
+ nWidth = ImplLogicWidthToDevicePixel( nWidth );
+ aPos.X() += mnTextOffX;
+ aPos.Y() += mnTextOffY;
+ ImplDrawTextLine( aPos.X(), aPos.X(), aPos.Y(), nWidth, eStrikeout, eUnderline );
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos,
+ USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawWaveLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+#ifndef REMOTE_APPSERVER
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPos );
+ Point aEndPt = ImplLogicToDevicePixel( rEndPos );
+ long nStartX = aStartPt.X();
+ long nStartY = aStartPt.Y();
+ long nEndX = aEndPt.X();
+ long nEndY = aEndPt.Y();
+ short nOrientation = 0;
+
+ if ( (nStartY != nEndY) || (nStartX > nEndX) )
+ {
+ long nDX = nEndX - nStartX;
+ double nO = atan2( -nEndY + nStartY, ((nDX == 0L) ? 0.000000001 : nDX) );
+ nO /= F_PI1800;
+ nOrientation = (short)nO;
+ ImplRotatePos( nStartX, nStartY, nEndX, nEndY, -nOrientation );
+ }
+
+ long nWaveHeight;
+ if ( nStyle == WAVE_NORMAL )
+ {
+ nWaveHeight = 3;
+ nStartY++;
+ nEndY++;
+ }
+ else if( nStyle == WAVE_SMALL )
+ {
+ nWaveHeight = 2;
+ nStartY++;
+ nEndY++;
+ }
+ else // WAVE_FLAT
+ nWaveHeight = 1;
+
+ ImplDrawWaveLine( nStartX, nStartY, nStartX, nStartY,
+ nEndX-nStartX, nWaveHeight, 1,
+ nOrientation, GetLineColor() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Point aPos1 = ImplLogicToDevicePixel( rStartPos );
+ Point aPos2 = ImplLogicToDevicePixel( rEndPos );
+ pGraphics->DrawWaveLine( aPos1, aPos2, nStyle );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawText( const Point& rStartPt, const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextAction( rStartPt, rStr, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ if ( mbKerning )
+ {
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ USHORT i;
+
+ // DX-Array berechnen
+ long nOffset = 0;
+ long aStackAry[128];
+ long* pDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( i = 0; i < nLen-1; i++ )
+ {
+ nOffset += pCharWidthAry[(unsigned char)pStr[i]];
+ pDXAry[i] = nOffset / nFactor;
+ }
+ ImplCalcKerning( pStr, nLen, pDXAry, nLen-1 );
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+ ImplReleaseStackBuffer( pDXAry, aStackAry );
+ }
+ else
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextWidth( const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextWidth()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nWidth = 0;
+
+ if ( nIndex < rStr.Len() )
+ {
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+
+ if ( nLen )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+
+ // Bei Fixed-Fonts reicht eine Multiplikation
+ if ( pFontEntry->mbFixedFont )
+ {
+ nWidth = pCharWidthAry['A'] * nLen;
+ nWidth /= pFontEntry->mnWidthFactor;
+ }
+ else
+ {
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ const sal_Unicode* pTempStr;
+ USHORT nTempLen;
+ pStr += nIndex;
+ pTempStr = pStr;
+ nTempLen = nLen;
+ while ( nTempLen )
+ {
+ nWidth += ImplGetCharWidth( *pTempStr );
+ nTempLen--;
+ pTempStr++;
+ }
+ nWidth /= pFontEntry->mnWidthFactor;
+
+ // Kerning beruecksichtigen (tun wir nur bei Fonts ohne feste Breite)
+ if ( mbKerning )
+ nWidth += ImplCalcKerning( pStr, nLen, NULL, 0 );
+ }
+ }
+ }
+
+ if ( mbMap )
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextHeight() const
+{
+ DBG_TRACE( "OutputDevice::GetTextHeight()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ long nHeight = mpFontEntry->mnLineHeight;
+
+ if ( mbMap )
+ nHeight = ImplDevicePixelToLogicHeight( nHeight );
+
+ return nHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTextArray( const Point& rStartPt, const XubString& rStr,
+ const long* pDXAry,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawTextArray()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextArrayAction( rStartPt, rStr, pDXAry, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+ // Bei keinem Pos-Array, DrawText benutzen
+ if ( !pDXAry || (nLen < 2) )
+ {
+ // hier Aufrufen, damit keine doppelte MetaFile Aufzeichnung
+ DrawText( rStartPt, rStr, nIndex, nLen );
+ return;
+ }
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ if ( mbMap )
+ {
+ long nLogStartX = rStartPt.X();
+ long nPixStartX = aStartPt.X();
+ long aStackAry[128];
+ long* pPixDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( xub_StrLen i = 0; i < (nLen-1); i++ )
+ pPixDXAry[i] = ImplLogicXToDevicePixel( nLogStartX+pDXAry[i] )-nPixStartX;
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pPixDXAry );
+ ImplReleaseStackBuffer( pPixDXAry, aStackAry );
+ }
+ else
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextArray( const UniString& rStr, long* pDXAry,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextArray()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !pDXAry )
+ return GetTextWidth( rStr, nIndex, nLen );
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ if ( !nLen )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pTempStr;
+ const sal_Unicode* pStr;
+ long nOffset = 0;
+ xub_StrLen i;
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ pTempStr = pStr;
+
+ // Breiten ermitteln
+ for ( i = 0; i < nLen; i++ )
+ {
+ nOffset += ImplGetCharWidth( *pTempStr );
+ pDXAry[i] = nOffset / nFactor;
+ pTempStr++;
+ }
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ ImplCalcKerning( pStr, nLen, pDXAry, nLen );
+
+ // Breite und Hoehe ermitteln
+ long nWidth = pDXAry[nLen-1];
+
+ // Wenn MapMode gesetzt, dann Werte umrechnen
+ if ( mbMap )
+ {
+ for ( i = 0; i < nLen; i++ )
+ pDXAry[i] = ImplDevicePixelToLogicWidth( pDXAry[i] );
+
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawStretchText( const Point& rStartPt, ULONG nWidth,
+ const UniString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawStretchText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaStretchTextAction( rStartPt, nWidth, rStr, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ nWidth = ImplLogicWidthToDevicePixel( nWidth );
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ // Breiten-Array fuer errechnete Werte allocieren und
+ // mit den Breiten der einzelnen Character fuellen lassen
+ long aStackAry[128];
+ long* pDXAry = (long*)ImplGetStackBuffer( sizeof(long)*nLen, aStackAry, sizeof( aStackAry ) );
+ ImplFillDXAry( pDXAry, pStr, nLen, (long)nWidth );
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+ ImplReleaseStackBuffer( pDXAry, aStackAry );
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen OutputDevice::GetTextBreak( const XubString& rStr, long nTextWidth,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ long nCharExtra ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextBreak()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nIndex > rStr.Len() )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pStr;
+ long nCalcWidth = 0;
+ xub_StrLen nLastIndex;
+
+ if ( mbMap )
+ {
+ nTextWidth = ImplLogicWidthToDevicePixel( nTextWidth*10 );
+ nTextWidth *= nFactor;
+ nTextWidth /= 10;
+ if ( nCharExtra )
+ {
+ nCharExtra = ImplLogicWidthToDevicePixel( nCharExtra*10 );
+ nCharExtra *= nFactor;
+ nCharExtra /= 10;
+ }
+ }
+ else
+ {
+ nCharExtra *= nFactor;
+ nTextWidth *= nFactor;
+ }
+
+ // Letzte Index-Position ermitteln
+ if ( (ULONG)nIndex+nLen > rStr.Len() )
+ nLastIndex = rStr.Len();
+ else
+ nLastIndex = nIndex + nLen;
+
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ while ( nIndex < nLastIndex )
+ {
+ nCalcWidth += ImplGetCharWidth( *pStr );
+
+ if ( nCalcWidth > nTextWidth )
+ return nIndex;
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nCalcWidth += ImplCalcKerning( pStr, 2, NULL, 0 )*nFactor;
+ nCalcWidth += nCharExtra;
+
+ nIndex++;
+ pStr++;
+ }
+
+ return STRING_LEN;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen OutputDevice::GetTextBreak( const XubString& rStr, long nTextWidth,
+ sal_Unicode nExtraChar, xub_StrLen& rExtraCharPos,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ long nCharExtra ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextBreak()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nIndex > rStr.Len() )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pStr;
+ long nTextWidth2;
+ long nCalcWidth = 0;
+ xub_StrLen nIndex2 = STRING_LEN;
+ xub_StrLen nLastIndex;
+
+ if ( mbMap )
+ {
+ nTextWidth = ImplLogicWidthToDevicePixel( nTextWidth*10 );
+ nTextWidth *= nFactor;
+ nTextWidth /= 10;
+ if ( nCharExtra )
+ {
+ nCharExtra = ImplLogicWidthToDevicePixel( nCharExtra*10 );
+ nCharExtra *= nFactor;
+ nCharExtra /= 10;
+ }
+ }
+ else
+ {
+ nCharExtra *= nFactor;
+ nTextWidth *= nFactor;
+ }
+
+ // Letzte Index-Position ermitteln
+ if ( (ULONG)nIndex+nLen > rStr.Len() )
+ nLastIndex = rStr.Len();
+ else
+ nLastIndex = nIndex + nLen;
+
+ nTextWidth2 = nTextWidth - ImplGetCharWidth( nExtraChar ) - nCharExtra;
+
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ while ( nIndex < nLastIndex )
+ {
+ nCalcWidth += ImplGetCharWidth( *pStr );
+
+ if ( nCalcWidth > nTextWidth2 )
+ {
+ if ( nIndex2 == STRING_LEN )
+ nIndex2 = nIndex;
+ }
+ if ( nCalcWidth > nTextWidth )
+ {
+ if ( nIndex2 == STRING_LEN )
+ rExtraCharPos = nIndex;
+ else
+ rExtraCharPos = nIndex2;
+ return nIndex;
+ }
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nCalcWidth += ImplCalcKerning( pStr, 2, NULL, 0 )*nFactor;
+ nCalcWidth += nCharExtra;
+
+ nIndex++;
+ pStr++;
+ }
+
+ rExtraCharPos = nIndex2;
+ return STRING_LEN;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetCharWidth( sal_Unicode nFirstChar, sal_Unicode nLastChar,
+ long* pWidthAry ) const
+{
+ DBG_TRACE( "OutputDevice::GetCharWidth()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( nFirstChar <= nLastChar, "OutputDevice::GetCharWidth(): nFirst > nLast" );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return;
+ }
+
+ long nFactor = mpFontEntry->mnWidthFactor;
+ sal_Unicode nCharCount = nLastChar-nFirstChar+1;
+
+ if ( mbMap )
+ {
+ while ( nCharCount )
+ {
+ *pWidthAry = ImplDevicePixelToLogicWidth( ImplGetCharWidth( nFirstChar ) ) / nFactor;
+ pWidthAry++;
+ nFirstChar++;
+ nCharCount--;
+ }
+ }
+ else
+ {
+ while ( nCharCount )
+ {
+ *pWidthAry = ImplGetCharWidth( nFirstChar ) / nFactor;
+ pWidthAry++;
+ nFirstChar++;
+ nCharCount--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawText( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawText( const Rectangle& )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextRectAction( rRect, rStr, nStyle ) );
+
+ if ( !IsDeviceOutputNecessary() || !rStr.Len() || rRect.IsEmpty() )
+ return;
+
+ // Vorsichtshalber hier auch schon Aufrufen, da ImplDrawMnemonicLine()
+ // dies nicht macht
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ Color aOldTextColor;
+ Color aOldTextFillColor;
+ BOOL bRestoreFillColor;
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ aOldTextColor = GetTextColor();
+ if ( IsTextFillColor() )
+ {
+ bRestoreFillColor = TRUE;
+ aOldTextFillColor = GetTextFillColor();
+ }
+ else
+ bRestoreFillColor = FALSE;
+ SetTextColor( GetSettings().GetStyleSettings().GetLightColor() );
+ Rectangle aRect = rRect;
+ aRect.Move( 1, 1 );
+ DrawText( aRect, rStr, nStyle & ~TEXT_DRAW_DISABLE );
+ SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ }
+
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+
+ if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) )
+ return;
+
+ XubString aStr = rStr;
+ Point aPos = rRect.TopLeft();
+ long nTextHeight = GetTextHeight();
+ TextAlign eAlign = GetTextAlign();
+ xub_StrLen nMnemonicPos = STRING_NOTFOUND;
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ aStr = GetNonMnemonicString( aStr, nMnemonicPos );
+
+ // Mehrzeiligen Text behandeln wir anders
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ XubString aLastLine;
+ ImplMultiTextLineInfo aMultiLineInfo;
+ ImplTextLineInfo* pLineInfo;
+ long nMaxTextWidth;
+ xub_StrLen i;
+ xub_StrLen nLines;
+ xub_StrLen nFormatLines;
+
+ if ( nTextHeight )
+ {
+ nMaxTextWidth = ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nLines = (xub_StrLen)(nHeight/nTextHeight);
+ nFormatLines = aMultiLineInfo.Count();
+ if ( !nLines )
+ nLines = 1;
+ if ( nFormatLines > nLines )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ // Letzte Zeile zusammenbauen und kuerzen
+ nFormatLines = nLines-1;
+ pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
+ aLastLine = aStr.Copy( pLineInfo->GetIndex() );
+ aLastLine.ConvertLineEnd( LINEEND_LF );
+ // Alle LineFeed's durch Spaces ersetzen
+ xub_StrLen nLastLineLen = aLastLine.Len();
+ for ( i = 0; i < nLastLineLen; i++ )
+ {
+ if ( aLastLine.GetChar( i ) == _LF )
+ aLastLine.SetChar( i, ' ' );
+ }
+ aLastLine = GetEllipsisString( aLastLine, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
+ nStyle |= TEXT_DRAW_TOP;
+ }
+ }
+ else
+ {
+ if ( nMaxTextWidth <= nWidth )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Muss in der Hoehe geclippt werden?
+ if ( nFormatLines*nTextHeight > nHeight )
+ nStyle |= TEXT_DRAW_CLIP;
+
+ // Clipping setzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-(nFormatLines*nTextHeight);
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += nTextHeight;
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += GetFontMetric().GetAscent();
+
+ // Alle Zeilen ausgeben, bis auf die letzte
+ for ( i = 0; i < nFormatLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-pLineInfo->GetWidth();
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
+ xub_StrLen nIndex = pLineInfo->GetIndex();
+ xub_StrLen nLineLen = pLineInfo->GetLen();
+ DrawText( aPos, aStr, nIndex, nLineLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( (nMnemonicPos >= nIndex) && (nMnemonicPos < nIndex+nLineLen) )
+ {
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ Point aTempPos = LogicToPixel( aPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, nIndex, nMnemonicPos-nIndex ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+ aPos.Y() += nTextHeight;
+ aPos.X() = rRect.Left();
+ }
+
+ // Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
+ // da die Zeile gekuerzt wurde
+ if ( aLastLine.Len() )
+ DrawText( aPos, aLastLine );
+
+ // Clipping zuruecksetzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ Pop();
+ }
+ }
+ else
+ {
+ long nTextWidth = GetTextWidth( aStr );
+
+ // Evt. Text kuerzen
+ if ( nTextWidth > nWidth )
+ {
+ if ( nStyle & TEXT_DRAW_ELLIPSIS )
+ {
+ aStr = GetEllipsisString( aStr, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
+ nStyle |= TEXT_DRAW_LEFT;
+ nTextWidth = GetTextWidth( aStr );
+ }
+ }
+ else
+ {
+ if ( nTextHeight <= nHeight )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-nTextWidth;
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-nTextWidth)/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += nTextHeight;
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += GetFontMetric().GetAscent();
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-nTextHeight;
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-nTextHeight)/2;
+
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ Point aTempPos = LogicToPixel( aPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, 0, nMnemonicPos ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ }
+
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+ DrawText( aPos, aStr );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ Pop();
+ }
+ else
+ {
+ DrawText( aPos, aStr );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ SetTextColor( aOldTextColor );
+ if ( bRestoreFillColor )
+ SetTextFillColor( aOldTextFillColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle,
+ TextRectInfo* pInfo ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Rectangle aRect = rRect;
+ XubString aStr = rStr;
+ xub_StrLen nLines;
+ long nWidth = rRect.GetWidth();
+ long nMaxWidth;
+ long nTextHeight = GetTextHeight();
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ aStr = GetNonMnemonicString( aStr );
+
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ ImplMultiTextLineInfo aMultiLineInfo;
+ ImplTextLineInfo* pLineInfo;
+ xub_StrLen nFormatLines;
+ xub_StrLen i;
+
+ nMaxWidth = 0;
+ ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nFormatLines = aMultiLineInfo.Count();
+ if ( !nTextHeight )
+ nTextHeight = 1;
+ nLines = (USHORT)(aRect.GetHeight()/nTextHeight);
+ if ( pInfo )
+ pInfo->mnLineCount = nFormatLines;
+ if ( !nLines )
+ nLines = 1;
+ if ( nFormatLines <= nLines )
+ nLines = nFormatLines;
+ else
+ {
+ if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) )
+ nLines = nFormatLines;
+ else
+ {
+ if ( pInfo )
+ pInfo->mbEllipsis = TRUE;
+ nMaxWidth = nWidth;
+ }
+ }
+ if ( pInfo )
+ {
+ BOOL bMaxWidth = nMaxWidth == 0;
+ pInfo->mnMaxWidth = 0;
+ for ( i = 0; i < nLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( bMaxWidth && (pLineInfo->GetWidth() > nMaxWidth) )
+ nMaxWidth = pLineInfo->GetWidth();
+ if ( pLineInfo->GetWidth() > pInfo->mnMaxWidth )
+ pInfo->mnMaxWidth = pLineInfo->GetWidth();
+ }
+ }
+ else if ( !nMaxWidth )
+ {
+ for ( i = 0; i < nLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( pLineInfo->GetWidth() > nMaxWidth )
+ nMaxWidth = pLineInfo->GetWidth();
+ }
+ }
+ }
+ else
+ {
+ nLines = 1;
+ nMaxWidth = GetTextWidth( aStr );
+
+ if ( pInfo )
+ {
+ pInfo->mnLineCount = 1;
+ pInfo->mnMaxWidth = nMaxWidth;
+ }
+
+ if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ELLIPSIS) )
+ {
+ if ( pInfo )
+ pInfo->mbEllipsis = TRUE;
+ nMaxWidth = nWidth;
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aRect.Left() = aRect.Right()-nMaxWidth+1;
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ {
+ aRect.Left() += (nWidth-nMaxWidth)/2;
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+ }
+ else
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1;
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ {
+ aRect.Top() += (aRect.GetHeight()-(nTextHeight*nLines))/2;
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+ }
+ else
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplIsCharIn( xub_Unicode c, const sal_Char* pStr )
+{
+ while ( *pStr )
+ {
+ if ( *pStr == c )
+ return TRUE;
+ pStr++;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString OutputDevice::GetEllipsisString( const XubString& rStr, long nMaxWidth,
+ USHORT nStyle ) const
+{
+ DBG_TRACE( "OutputDevice::GetEllipsisString()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ XubString aStr = rStr;
+ xub_StrLen nIndex = GetTextBreak( aStr, nMaxWidth );
+
+ if ( nIndex != STRING_LEN )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ aStr.Erase( nIndex );
+ if ( nIndex > 1 )
+ {
+ aStr.AppendAscii( "..." );
+ while ( aStr.Len() && (GetTextWidth( aStr ) > nMaxWidth) )
+ {
+ if ( (nIndex > 1) || (nIndex == aStr.Len()) )
+ nIndex--;
+ aStr.Erase( nIndex, 1 );
+ }
+ }
+
+ if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) )
+ aStr += rStr.GetChar( 0 );
+ }
+ else if ( nStyle & (TEXT_DRAW_PATHELLIPSIS | TEXT_DRAW_NEWSELLIPSIS) )
+ {
+ static sal_Char const aPathSepChars[] = "\\/:";
+ static sal_Char const aNewsSepChars[] = ".";
+ const sal_Char* pSepChars;
+
+ if ( nStyle & TEXT_DRAW_PATHELLIPSIS )
+ pSepChars = aPathSepChars;
+ else
+ pSepChars = aNewsSepChars;
+
+ // Letztes Teilstueck ermitteln
+ xub_StrLen nLastContent = rStr.Len();
+ while ( nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( rStr.GetChar( nLastContent ), pSepChars ) )
+ break;
+ }
+ while ( nLastContent &&
+ ImplIsCharIn( rStr.GetChar( nLastContent-1 ), pSepChars ) )
+ nLastContent--;
+
+ XubString aLastStr( rStr, nLastContent, rStr.Len() );
+ XubString aTempLastStr( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
+ aTempLastStr += aLastStr;
+ if ( GetTextWidth( aTempLastStr ) > nMaxWidth )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ USHORT nFirstContent = 0;
+ while ( nFirstContent < nLastContent )
+ {
+ nFirstContent++;
+ if ( ImplIsCharIn( rStr.GetChar( nFirstContent ), pSepChars ) )
+ break;
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( rStr.GetChar( nFirstContent ), pSepChars ) )
+ nFirstContent++;
+
+ if ( nFirstContent >= nLastContent )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ if ( nFirstContent > 4 )
+ nFirstContent = 4;
+ XubString aFirstStr( rStr, 0, nFirstContent );
+ aFirstStr.AppendAscii( "..." );
+ XubString aTempStr = aFirstStr;
+ aTempStr += aLastStr;
+ if ( GetTextWidth( aTempStr ) > nMaxWidth )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ do
+ {
+ aStr = aTempStr;
+ while ( nFirstContent < nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( rStr.GetChar( nLastContent ), pSepChars ) )
+ break;
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( rStr.GetChar( nLastContent-1 ), pSepChars ) )
+ nLastContent--;
+
+ if ( nFirstContent < nLastContent )
+ {
+ XubString aTempLastStr( rStr, nLastContent, rStr.Len() );
+ aTempStr = aFirstStr;
+ aTempStr += aTempLastStr;
+ if ( GetTextWidth( aTempStr ) > nMaxWidth )
+ break;
+ }
+ }
+ while ( nFirstContent < nLastContent );
+ }
+ }
+ }
+ }
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawCtrlText( const Point& rPos, const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawCtrlText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !IsDeviceOutputNecessary() || (nIndex >= rStr.Len()) )
+ return;
+
+ // Vorsichtshalber hier auch schon Aufrufen, da ImplDrawMnemonicLine()
+ // dies nicht macht
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ XubString aStr = rStr;
+ xub_StrLen nMnemonicPos = STRING_NOTFOUND;
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aStr = GetNonMnemonicString( aStr, nMnemonicPos );
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ if ( nMnemonicPos < nIndex )
+ nIndex--;
+ else if ( (nLen < STRING_LEN) &&
+ (nMnemonicPos >= nIndex) && (nMnemonicPos < (ULONG)(nIndex+nLen)) )
+ nLen--;
+ Point aTempPos = LogicToPixel( rPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, 0, nMnemonicPos ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ Color aOldTextColor;
+ Color aOldTextFillColor;
+ BOOL bRestoreFillColor;
+ aOldTextColor = GetTextColor();
+ if ( IsTextFillColor() )
+ {
+ bRestoreFillColor = TRUE;
+ aOldTextFillColor = GetTextFillColor();
+ }
+ else
+ bRestoreFillColor = FALSE;
+ SetTextColor( GetSettings().GetStyleSettings().GetLightColor() );
+ DrawText( Point( rPos.X()+1, rPos.Y()+1 ), aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX+1, nMnemonicY+1, cMnemonic );
+ }
+ SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ DrawText( rPos, aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ SetTextColor( aOldTextColor );
+ if ( bRestoreFillColor )
+ SetTextFillColor( aOldTextFillColor );
+ }
+ else
+ {
+ DrawText( rPos, aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetCtrlTextWidth( const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ USHORT nStyle ) const
+{
+ DBG_TRACE( "OutputDevice::GetCtrlTextSize()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ {
+ xub_StrLen nMnemonicPos;
+ XubString aStr = GetNonMnemonicString( rStr, nMnemonicPos );
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ if ( nMnemonicPos < nIndex )
+ nIndex--;
+ else if ( (nLen < STRING_LEN) &&
+ (nMnemonicPos >= nIndex) && (nMnemonicPos < (ULONG)(nIndex+nLen)) )
+ nLen--;
+ }
+ return GetTextWidth( aStr, nIndex, nLen );
+ }
+ else
+ return GetTextWidth( rStr, nIndex, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+XubString OutputDevice::GetNonMnemonicString( const XubString& rStr, xub_StrLen& rMnemonicPos )
+{
+ XubString aStr = rStr;
+ xub_StrLen nLen = aStr.Len();
+ xub_StrLen i = 0;
+
+ rMnemonicPos = STRING_NOTFOUND;
+ while ( i < nLen )
+ {
+ if ( aStr.GetChar( i ) == '~' )
+ {
+ if ( aStr.GetChar( i+1 ) != '~' )
+ {
+ if ( rMnemonicPos == STRING_NOTFOUND )
+ rMnemonicPos = i;
+ aStr.Erase( i, 1 );
+ nLen--;
+ }
+ else
+ {
+ aStr.Erase( i, 1 );
+ nLen--;
+ i++;
+ }
+ }
+ else
+ i++;
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetDevFontCount() const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Wenn wir schon eine Liste der Fonts haben, dann nicht iterieren
+ if ( mpGetDevFontList )
+ return (USHORT)mpGetDevFontList->Count();
+
+ ((OutputDevice*)this)->mpGetDevFontList = new ImplGetDevFontList;
+
+ // Fill Fontlist
+ ImplDevFontListData* pFontListData = mpFontList->First();
+ while ( pFontListData )
+ {
+ ImplFontData* pLastData = NULL;
+ ImplFontData* pData = pFontListData->mpFirst;
+ while ( pData )
+ {
+ // Compare with the last font, because we wan't in the list
+ // only fonts, that have different attributes, but not
+ // different sizes
+ if ( !pLastData ||
+ (ImplCompareFontDataWithoutSize( pLastData, pData ) != 0) )
+ mpGetDevFontList->Add( pData );
+
+ pLastData = pData;
+ pData = pData->mpNext;
+ }
+
+ pFontListData = mpFontList->Next();
+ }
+
+ return (USHORT)mpGetDevFontList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo OutputDevice::GetDevFont( USHORT nDevFont ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFont()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ FontInfo aFontInfo;
+ USHORT nCount = GetDevFontCount();
+
+ // Wertebereich ueberpruefen
+ if ( nDevFont < nCount )
+ {
+ ImplFontData* pData = mpGetDevFontList->Get( nDevFont );
+ aFontInfo.SetName( pData->maName );
+ aFontInfo.SetStyleName( pData->maStyleName );
+// !!! UNICODE !!! aFontInfo.SetCharSet( ImplGetFakeEncoding( pData->meCharSet ) );
+ aFontInfo.SetCharSet( pData->meCharSet );
+ aFontInfo.SetFamily( pData->meFamily );
+ aFontInfo.SetPitch( pData->mePitch );
+ aFontInfo.SetWeight( pData->meWeight );
+ aFontInfo.SetItalic( pData->meItalic );
+ aFontInfo.mpImplMetric->meType = pData->meType;
+ aFontInfo.mpImplMetric->mbDevice = pData->mbDevice;
+ }
+
+ return aFontInfo;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetDevFontSizeCount( const Font& rFont ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontSizeCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ XubString aFontName = rFont.GetName();
+
+ // Wenn die Liste schon existiert und der FontName sich nicht
+ // unterscheidet, dann brauchen wir Sie nicht neu erzeugen
+ if ( mpGetDevSizeList )
+ {
+ if ( mpGetDevSizeList->GetFontName() == aFontName )
+ return (USHORT)mpGetDevSizeList->Count();
+ else
+ {
+ mpGetDevSizeList->Clear();
+ mpGetDevSizeList->SetFontName( aFontName );
+ }
+ }
+ else
+ ((OutputDevice*)this)->mpGetDevSizeList = new ImplGetDevSizeList( aFontName );
+
+ // Fonts aus unserer Fontliste in die GetDevFontSizeListe eintragen
+ ImplDevFontListData* pFontListData = mpFontList->FindFont( aFontName );
+ if ( pFontListData )
+ {
+ ImplFontData* pData = pFontListData->mpFirst;
+ do
+ {
+ mpGetDevSizeList->Add( pData->mnHeight );
+ pData = pData->mpNext;
+ }
+ while ( pData );
+ }
+
+ return (USHORT)mpGetDevSizeList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::GetDevFontSize( const Font& rFont, USHORT nSize ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontSize()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ USHORT nCount = GetDevFontSizeCount( rFont );
+
+ // Wertebereich ueberpruefen
+ if ( nSize >= nCount )
+ return Size();
+
+ // Wenn MapMode gesetzt ist, wird auf ,5-Points gerundet
+ Size aSize( 0, mpGetDevSizeList->Get( nSize ) );
+ if ( mbMap )
+ {
+ aSize.Height() *= 10;
+ MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
+ aSize = PixelToLogic( aSize, aMap );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ long nRound = aSize.Height() % 5;
+ if ( nRound >= 3 )
+ aSize.Height() += (5-nRound);
+ else
+ aSize.Height() -= nRound;
+ aSize.Height() *= 10;
+ aSize = LogicToPixel( aSize, aMap );
+ aSize = PixelToLogic( aSize );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ }
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::IsFontAvailable( const XubString& rFontName ) const
+{
+ DBG_TRACE( "OutputDevice::IsFontAvailable()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ return (mpFontList->FindFont( rFontName ) != 0);
+}
+
+// -----------------------------------------------------------------------
+
+FontMetric OutputDevice::GetFontMetric() const
+{
+ DBG_TRACE( "OutputDevice::GetFontMetric()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ FontMetric aMetric;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return aMetric;
+ }
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplFontMetricData* pMetric = &(pEntry->maMetric);
+
+ // Mappen und StarView Struktur fuellen
+ aMetric.Font::operator=( maFont );
+
+ // Fontdaten ermitteln und setzen
+ aMetric.SetName( pMetric->maName );
+ aMetric.SetStyleName( pMetric->maStyleName );
+ aMetric.SetSize( PixelToLogic( Size( pMetric->mnWidth, pMetric->mnAscent+pMetric->mnDescent-pMetric->mnLeading ) ) );
+ aMetric.SetCharSet( pMetric->meCharSet );
+ aMetric.SetFamily( pMetric->meFamily );
+ aMetric.SetPitch( pMetric->mePitch );
+ aMetric.SetWeight( pMetric->meWeight );
+ aMetric.SetItalic( pMetric->meItalic );
+ if ( pEntry->mnOwnOrientation )
+ aMetric.SetOrientation( pEntry->mnOwnOrientation );
+ else
+ aMetric.SetOrientation( pMetric->mnOrientation );
+ if ( !mbKerning )
+ aMetric.SetKerning( FALSE );
+
+ // restliche Metricen setzen
+ aMetric.mpImplMetric->meType = pMetric->meType;
+ aMetric.mpImplMetric->mbDevice = pMetric->mbDevice;
+ aMetric.mpImplMetric->mnAscent = ImplDevicePixelToLogicHeight( pMetric->mnAscent );
+ aMetric.mpImplMetric->mnDescent = ImplDevicePixelToLogicHeight( pMetric->mnDescent );
+ aMetric.mpImplMetric->mnLeading = ImplDevicePixelToLogicHeight( pMetric->mnLeading );
+ aMetric.mpImplMetric->mnLineHeight = ImplDevicePixelToLogicHeight( pMetric->mnAscent+pMetric->mnDescent );
+ aMetric.mpImplMetric->mnSlant = ImplDevicePixelToLogicHeight( pMetric->mnSlant );
+ aMetric.mpImplMetric->mnFirstChar = pMetric->mnFirstChar;
+ aMetric.mpImplMetric->mnLastChar = pMetric->mnLastChar;
+
+ return aMetric;
+}
+
+// -----------------------------------------------------------------------
+
+FontMetric OutputDevice::GetFontMetric( const Font& rFont ) const
+{
+ // Uebergebenen Font selektieren, Metric abfragen und alten wieder
+ // selektieren
+ Font aOldFont = GetFont();
+ ((OutputDevice*)this)->SetFont( rFont );
+ FontMetric aMetric( GetFontMetric() );
+ ((OutputDevice*)this)->SetFont( aOldFont );
+ return aMetric;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG OutputDevice::GetKerningPairCount() const
+{
+ DBG_TRACE( "OutputDevice::GetKerningPairCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ ((OutputDevice*)this)->ImplInitKerningPairs();
+ return mpFontEntry->mnKernPairs;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetKerningPairs( ULONG nPairs, KerningPair* pKernPairs ) const
+{
+ DBG_TRACE( "OutputDevice::GetKerningPairs()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ ((OutputDevice*)this)->ImplInitKerningPairs();
+ if ( nPairs > mpFontEntry->mnKernPairs )
+ nPairs = mpFontEntry->mnKernPairs;
+ if ( nPairs )
+ memcpy( pKernPairs, mpFontEntry->mpKernPairs, nPairs*sizeof( KerningPair ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::GetGlyphBoundRect( xub_Unicode cChar, Rectangle& rRect, BOOL bOptimize )
+{
+ DBG_TRACE( "OutputDevice::GetGlyphBoundRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ Font* pOldFont;
+ long nLeft, nTop, nWidth, nHeight;
+ long nFontWidth, nFontHeight;
+ long nOrgWidth, nOrgHeight;
+
+ if ( bOptimize )
+ {
+ pOldFont = new Font( GetFont() );
+
+ Font aFont( *pOldFont );
+ Size aFontSize( LogicToPixel( aFont.GetSize() ) );
+
+ if ( aFontSize.Width() && aFontSize.Height() )
+ {
+ const double fFactor = (double) aFontSize.Width() / aFontSize.Height();
+
+ if ( fFactor < 1.0 )
+ {
+ aFontSize.Width() = FRound( fFactor * 500. );
+ aFontSize.Height() = 500;
+ }
+ else
+ {
+ aFontSize.Width() = 500;
+ aFontSize.Height() = FRound( 500. / fFactor );
+ }
+
+ aFont.SetSize( PixelToLogic( aFontSize ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = aFont.GetSize().Width();
+ nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = pOldFont->GetSize().Width();
+ nOrgHeight = pOldFont->GetSize().Height();
+ }
+ else
+ {
+ aFont.SetSize( PixelToLogic( Size( 0, 500 ) ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = nOrgHeight = pOldFont->GetSize().Height();
+ }
+ }
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ if ( mpGraphics->GetGlyphBoundRect( cChar, &nLeft, &nTop, &nWidth, &nHeight ) )
+ {
+ if ( bOptimize )
+ {
+ nLeft = ImplDevicePixelToLogicWidth( nLeft ) * nOrgWidth / nFontWidth;
+ nTop = ImplDevicePixelToLogicHeight( nTop ) * nOrgHeight / nFontHeight;
+ nWidth = ImplDevicePixelToLogicWidth( nWidth ) * nOrgWidth / nFontWidth;
+ nHeight = ImplDevicePixelToLogicHeight( nHeight ) * nOrgHeight / nFontHeight;
+ }
+ else
+ {
+ nLeft = ImplDevicePixelToLogicWidth( nLeft );
+ nTop = ImplDevicePixelToLogicHeight( nTop );
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+ nHeight = ImplDevicePixelToLogicHeight( nHeight );
+ }
+
+ rRect = Rectangle( Point( nLeft, nTop ), Size( nWidth, nHeight ) );
+ bRet = TRUE;
+ }
+
+ if ( bOptimize )
+ {
+ ((OutputDevice*)this)->SetFont( *pOldFont );
+ delete pOldFont;
+ }
+
+ if ( !bRet && (OUTDEV_PRINTER != meOutDevType) )
+ {
+ if ( bOptimize )
+ {
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+ }
+
+ VirtualDevice* pVDev = new VirtualDevice( 1 );
+ long nWidth = ImplGetTextWidth( &cChar, 1, NULL );
+ long nHeight = mpFontEntry->mnLineHeight;
+ Point aOffset( nWidth >> 1, 8 );
+ Size aSize( nWidth + ( aOffset.X() << 1 ), nHeight + ( aOffset.Y() << 1 ) );
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Font aFont( GetFont() );
+ Bitmap aBmp;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( Size( mpFontEntry->maFontSelData.mnWidth, mpFontEntry->maFontSelData.mnHeight ) );
+
+ pVDev->SetFont( aFont );
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+ pVDev->ImplDrawText( aOffset.X(), aOffset.Y(), &cChar, 1, NULL );
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ delete pVDev;
+
+ BitmapReadAccess* pAcc = aBmp.AcquireReadAccess();
+
+ if ( pAcc )
+ {
+ const long nW = pAcc->Width();
+ const long nW1 = nW - 1L;
+ const long nH = pAcc->Height();
+ long nRight, nBottom;
+ const BitmapColor aBlack( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ BOOL bLineDone;
+
+ nLeft = nW;
+ nTop = nH;
+ nRight = nBottom = -1L;
+
+ for( long nY = 0L; nY < nH; nY++ )
+ {
+ bLineDone = FALSE;
+
+ for( long nX = 0L; ( nX < nW ) && !bLineDone; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ) == aBlack )
+ {
+ // find y minimum
+ if( nY < nTop )
+ nTop = nY;
+
+ // find y maximum
+ if( nY > nBottom )
+ nBottom = nY;
+
+ // find x minimum
+ if( nX < nLeft )
+ nLeft = nX;
+
+ // find x maximum (last pixel in line)
+ for( long nX2 = nW1; nX2 >= nX; nX2-- )
+ {
+ if( pAcc->GetPixel( nY, nX2 ) == aBlack )
+ {
+ if( nX2 > nRight )
+ nRight = nX2;
+
+ bLineDone = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( nLeft < nW && nTop < nH && nRight > -1L && nBottom > -1L )
+ {
+ nLeft -= aOffset.X(), nTop -= aOffset.Y();
+ nRight -= aOffset.X(), nBottom -= aOffset.Y();
+
+ nWidth = ImplDevicePixelToLogicWidth( nRight - nLeft + 1L );
+ nHeight = ImplDevicePixelToLogicHeight( nBottom - nTop + 1L );
+ nLeft = ImplDevicePixelToLogicWidth( nLeft );
+ nTop = ImplDevicePixelToLogicHeight( nTop );
+ rRect = Rectangle( Point( nLeft, nTop ), Size( nWidth, nHeight ) );
+ bRet = TRUE;
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ }
+ }
+ else
+ delete pVDev;
+ }
+ }
+#else
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ bRet = mpGraphics->GetGlyphBoundRect( cChar, rRect, bOptimize );
+
+ if ( bRet )
+ {
+ rRect = Rectangle( Point( ImplDevicePixelToLogicWidth( rRect.Left() ),
+ ImplDevicePixelToLogicHeight( rRect.Top() ) ),
+ Size( ImplDevicePixelToLogicWidth( rRect.GetWidth() ),
+ ImplDevicePixelToLogicHeight( rRect.GetHeight() ) ) );
+ }
+
+#endif
+
+ if ( !bRet )
+ rRect.SetEmpty();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::GetGlyphOutline( xub_Unicode cChar, PolyPolygon& rPolyPoly, BOOL bOptimize )
+{
+ DBG_TRACE( "OutputDevice::GetGlyphOutline()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ Font* pOldFont;
+ USHORT* pPolySizes = NULL;
+ SalPoint* pPoints = NULL;
+ BYTE* pFlags = NULL;
+ long nFontWidth, nFontHeight;
+ long nOrgWidth, nOrgHeight;
+ ULONG nPolyCount;
+
+ if ( bOptimize )
+ {
+ pOldFont = new Font( GetFont() );
+
+ Font aFont( *pOldFont );
+ Size aFontSize( LogicToPixel( aFont.GetSize() ) );
+
+ if ( aFontSize.Width() && aFontSize.Height() )
+ {
+ const double fFactor = (double) aFontSize.Width() / aFontSize.Height();
+
+ if ( fFactor < 1.0 )
+ {
+ aFontSize.Width() = FRound( fFactor * 500. );
+ aFontSize.Height() = 500;
+ }
+ else
+ {
+ aFontSize.Width() = 500;
+ aFontSize.Height() = FRound( 500. / fFactor );
+ }
+
+ aFont.SetSize( PixelToLogic( aFontSize ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = aFont.GetSize().Width();
+ nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = pOldFont->GetSize().Width();
+ nOrgHeight = pOldFont->GetSize().Height();
+ }
+ else
+ {
+ aFont.SetSize( PixelToLogic( Size( 0, 500 ) ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = nOrgHeight = pOldFont->GetSize().Height();
+ }
+ }
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ nPolyCount = mpGraphics->GetGlyphOutline( cChar, &pPolySizes, &pPoints, &pFlags );
+ if ( nPolyCount && pPolySizes && pPoints && pFlags )
+ {
+ ULONG nTotalPos = 0UL;
+
+ rPolyPoly.Clear();
+
+ for( ULONG i = 0UL; i < nPolyCount; i++ )
+ {
+ const USHORT nSize = pPolySizes[ i ];
+
+ if( nSize )
+ {
+ Polygon aPoly( nSize );
+ Point* pPt = aPoly.ImplGetPointAry();
+ BYTE* pFl = aPoly.ImplGetFlagAry();
+
+ memcpy( pFl, pFlags + nTotalPos, nSize );
+
+ for( USHORT n = 0; n < nSize; n++ )
+ {
+ const SalPoint& rSalPt = pPoints[ nTotalPos++ ];
+ Point& rPt = pPt[ n ];
+
+ if( bOptimize )
+ {
+ rPt.X() = ImplDevicePixelToLogicWidth( rSalPt.mnX ) *
+ nOrgWidth / nFontWidth;
+ rPt.Y() = ImplDevicePixelToLogicHeight( rSalPt.mnY ) *
+ nOrgHeight / nFontHeight;
+ }
+ else
+ {
+ rPt.X() = ImplDevicePixelToLogicWidth( rSalPt.mnX );
+ rPt.Y() = ImplDevicePixelToLogicHeight( rSalPt.mnY );
+ }
+ }
+
+ rPolyPoly.Insert( aPoly );
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ delete[] pPolySizes;
+ delete[] pPoints;
+ delete[] pFlags;
+
+ if ( bOptimize )
+ {
+ ((OutputDevice*)this)->SetFont( *pOldFont );
+ delete pOldFont;
+ }
+
+ if ( !bRet && (OUTDEV_PRINTER != meOutDevType) )
+ {
+ if ( bOptimize )
+ {
+ if( mbNewFont )
+ ImplNewFont();
+ if( mbInitFont )
+ ImplInitFont();
+ }
+
+ Font aFont( GetFont() );
+ VirtualDevice* pVDev = new VirtualDevice( 1 );
+ const Size aFontSize( pVDev->LogicToPixel( Size( 0, GLYPH_FONT_HEIGHT ), MAP_POINT ) );
+ const long nOrgWidth = ImplGetTextWidth( &cChar, 1, NULL );
+ const long nOrgHeight = mpFontEntry->mnLineHeight;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( aFontSize );
+ pVDev->SetFont( aFont );
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+
+ const long nWidth = pVDev->ImplGetTextWidth( &cChar, 1, NULL );
+ const long nHeight = pVDev->mpFontEntry->mnLineHeight;
+ const Point aOffset( nWidth >> 1, 8 );
+ const Size aSize( nWidth + ( aOffset.X() << 1 ), nHeight + ( aOffset.Y() << 1 ) );
+ const double fScaleX = ( nOrgWidth && nWidth ) ? ( (double) nOrgWidth / nWidth ) : 0.0;
+ const double fScaleY = ( nOrgHeight && nHeight ) ? ( (double) nOrgHeight / nHeight ) : 0.0;
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Bitmap aBmp;
+
+ pVDev->ImplDrawText( aOffset.X(), aOffset.Y(), &cChar, 1, NULL );
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ delete pVDev;
+
+ if( aBmp.Vectorize( rPolyPoly, BMP_VECTORIZE_OUTER | BMP_VECTORIZE_REDUCE_EDGES ) )
+ {
+ const long nOffX = aOffset.X(), nOffY = aOffset.Y();
+
+ for( USHORT i = 0UL, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ Polygon& rPoly = rPolyPoly[ i ];
+
+ for( USHORT n = 0, nSize = rPoly.GetSize(); n < nSize; n++ )
+ {
+ Point& rPt = rPoly[ n ];
+ rPt.X() = FRound( ImplDevicePixelToLogicWidth( rPt.X() - nOffX ) * fScaleX );
+ rPt.Y() = FRound( ImplDevicePixelToLogicHeight( rPt.Y() - nOffY ) * fScaleY );
+ }
+ }
+
+ bRet = TRUE;
+ }
+ }
+ else
+ delete pVDev;
+ }
+ }
+#else
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ bRet = mpGraphics->GetGlyphOutline( cChar, rPolyPoly, bOptimize );
+
+ if( bRet )
+ {
+ for( USHORT i = 0UL, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ Polygon& rPoly = rPolyPoly[ i ];
+
+ for( USHORT n = 0, nSize = rPoly.GetSize(); n < nSize; n++ )
+ {
+ Point& rPt = rPoly[ n ];
+ rPt.X() = ImplDevicePixelToLogicWidth( rPt.X() );
+ rPt.Y() = ImplDevicePixelToLogicHeight( rPt.Y() );
+ }
+ }
+ }
+
+#endif
+
+ if( !bRet )
+ rPolyPoly = PolyPolygon();
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/outdev4.cxx b/vcl/source/gdi/outdev4.cxx
new file mode 100644
index 000000000000..fc8e313b825d
--- /dev/null
+++ b/vcl/source/gdi/outdev4.cxx
@@ -0,0 +1,1634 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+
+#include <math.h>
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_LINE_HXX
+#include <line.hxx>
+#endif
+#ifndef _SV_HATCH_HXX
+#include <hatch.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define HATCH_MAXPOINTS 1024
+#define GRADIENT_DEFAULT_STEPCOUNT 0
+
+// ----------------
+// - Cmp-Function -
+// ----------------
+
+extern "C" int __LOADONCALLAPI ImplHatchCmpFnc( const void* p1, const void* p2 )
+{
+ const long nX1 = ( (Point*) p1 )->X();
+ const long nX2 = ( (Point*) p2 )->X();
+ const long nY1 = ( (Point*) p1 )->Y();
+ const long nY2 = ( (Point*) p2 )->Y();
+
+ return ( nX1 > nX2 ? 1 : nX1 == nX2 ? nY1 > nY2 ? 1: nY1 == nY2 ? 0 : -1 : -1 );
+}
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Gradient );
+
+// =======================================================================
+
+#ifndef REMOTE_APPSERVER
+
+void OutputDevice::ImplDrawPolygon( const Polygon& rPoly )
+{
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ const SalPoint* pPtAry = (const SalPoint*)rPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nPoints, pPtAry );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ USHORT nPoly = rPolyPoly.Count();
+
+ if ( !nPoly )
+ return;
+
+ if ( nPoly == 1 )
+ {
+ const Polygon rPoly = rPolyPoly.GetObject( 0 );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)rPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nSize, pPtAry );
+ }
+ }
+ else
+ {
+ ULONG* pPointAry = new ULONG[nPoly];
+ PCONSTSALPOINT* pPointAryAry = new PCONSTSALPOINT[nPoly];
+ USHORT i = 0;
+ do
+ {
+ const Polygon& rPoly = rPolyPoly.GetObject( i );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize )
+ {
+ pPointAry[i] = nSize;
+ pPointAryAry[i] = (PCONSTSALPOINT)rPoly.ImplGetConstPointAry();
+ i++;
+ }
+ else
+ nPoly--;
+ }
+ while ( i < nPoly );
+
+ if ( nPoly == 1 )
+ mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry );
+ else
+ mpGraphics->DrawPolyPolygon( nPoly, pPointAry, pPointAryAry );
+
+ delete pPointAry;
+ delete pPointAryAry;
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+inline UINT8 ImplGetGradientColorValue( long nValue )
+{
+ if ( nValue < 0 )
+ return 0;
+ else if ( nValue > 0xFF )
+ return 0xFF;
+ else
+ return (UINT8)nValue;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawLinearGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // rotiertes BoundRect ausrechnen
+ Rectangle aRect = rRect;
+ aRect.Left()--;
+ aRect.Top()--;
+ aRect.Right()++;
+ aRect.Bottom()++;
+ USHORT nAngle = rGradient.GetAngle();
+ double fAngle = (nAngle % 3600) * F_PI1800;
+ double fWidth = aRect.GetWidth();
+ double fHeight = aRect.GetHeight();
+ double fDX = fWidth * fabs( cos( fAngle ) ) +
+ fHeight * fabs( sin( fAngle ) );
+ double fDY = fHeight * fabs( cos( fAngle ) ) +
+ fWidth * fabs( sin( fAngle ) );
+ fDX = (fDX - fWidth) * 0.5 + 0.5;
+ fDY = (fDY - fHeight) * 0.5 + 0.5;
+ aRect.Left() -= (long)fDX;
+ aRect.Right() += (long)fDX;
+ aRect.Top() -= (long)fDY;
+ aRect.Bottom() += (long)fDY;
+
+ // Rand berechnen und Rechteck neu setzen
+ Point aCenter = rRect.Center();
+ Rectangle aFullRect = aRect;
+ long nBorder = (long)rGradient.GetBorder() * aRect.GetHeight() / 100;
+ BOOL bLinear;
+
+ // Rand berechnen und Rechteck neu setzen fuer linearen Farbverlauf
+ if ( rGradient.GetStyle() == GRADIENT_LINEAR )
+ {
+ bLinear = TRUE;
+ aRect.Top() += nBorder;
+ }
+ // Rand berechnen und Rechteck neu setzen fuer axiale Farbverlauf
+ else
+ {
+ bLinear = FALSE;
+ nBorder >>= 1;
+
+ aRect.Top() += nBorder;
+ aRect.Bottom() -= nBorder;
+ }
+
+ // Top darf nicht groesser als Bottom sein
+ aRect.Top() = Min( aRect.Top(), (long)(aRect.Bottom() - 1) );
+
+ long nMinRect = aRect.GetHeight();
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Bei nicht linearen Farbverlaeufen haben wir nur die halben Steps
+ // pro Farbe
+ if ( !bLinear )
+ {
+ nRedSteps <<= 1;
+ nGreenSteps <<= 1;
+ nBlueSteps <<= 1;
+ }
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Falls axialer Farbverlauf, muss die Schrittanzahl ungerade sein
+ if ( !bLinear && !(nSteps & 1) )
+ nSteps++;
+
+ // Berechnung ueber Double-Addition wegen Genauigkeit
+ double fScanLine = aRect.Top();
+ double fScanInc = (double)aRect.GetHeight() / (double)nSteps;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed;
+ UINT8 nGreen;
+ UINT8 nBlue;
+ long nSteps2;
+ long nStepsHalf;
+ if ( bLinear )
+ {
+ // Um 1 erhoeht, um die Border innerhalb der Schleife
+ // zeichnen zu koennen
+ nSteps2 = nSteps + 1;
+ nRed = (UINT8)nStartRed;
+ nGreen = (UINT8)nStartGreen;
+ nBlue = (UINT8)nStartBlue;
+ }
+ else
+ {
+ // Um 2 erhoeht, um die Border innerhalb der Schleife
+ // zeichnen zu koennen
+ nSteps2 = nSteps + 2;
+ nRed = (UINT8)nEndRed;
+ nGreen = (UINT8)nEndGreen;
+ nBlue = (UINT8)nEndBlue;
+ nStepsHalf = nSteps >> 1;
+ }
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Startpolygon erzeugen (== Borderpolygon)
+ Polygon aPoly( 4 );
+ Polygon aTempPoly( 2 );
+ aPoly[0] = aFullRect.TopLeft();
+ aPoly[1] = aFullRect.TopRight();
+ aPoly[2] = aRect.TopRight();
+ aPoly[3] = aRect.TopLeft();
+ aPoly.Rotate( aCenter, nAngle );
+
+ // Schleife, um rotierten Verlauf zu fuellen
+ for ( long i = 0; i < nSteps2; i++ )
+ {
+ // berechnetesPolygon ausgeben
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( aPoly );
+#endif
+
+ // neues Polygon berechnen
+ aRect.Top() = (long)(fScanLine += fScanInc);
+
+ // unteren Rand komplett fuellen
+ if ( i == nSteps )
+ {
+ aTempPoly[0] = aFullRect.BottomLeft();
+ aTempPoly[1] = aFullRect.BottomRight();
+ }
+ else
+ {
+ aTempPoly[0] = aRect.TopLeft();
+ aTempPoly[1] = aRect.TopRight();
+ }
+ aTempPoly.Rotate( aCenter, nAngle );
+
+ aPoly[0] = aPoly[3];
+ aPoly[1] = aPoly[2];
+ aPoly[2] = aTempPoly[1];
+ aPoly[3] = aTempPoly[0];
+
+ // Farbintensitaeten aendern...
+ // fuer lineare FV
+ if ( bLinear )
+ {
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps2) );
+ }
+ // fuer radiale FV
+ else
+ {
+ // fuer axiale FV muss die letzte Farbe der ersten
+ // Farbe entsprechen
+ if ( i > nSteps )
+ {
+ nRed = (UINT8)nEndRed;
+ nGreen = (UINT8)nEndGreen;
+ nBlue = (UINT8)nEndBlue;
+ }
+ else
+ {
+ if ( i <= nStepsHalf )
+ {
+ nRed = ImplGetGradientColorValue( nEndRed-((nRedSteps*i)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nEndGreen-((nGreenSteps*i)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nEndBlue-((nBlueSteps*i)/nSteps2) );
+ }
+ // genau die Mitte und hoeher
+ else
+ {
+ long i2 = i - nStepsHalf;
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i2)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i2)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i2)/nSteps2) );
+ }
+ }
+ }
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawRadialGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // Feststellen ob Ausgabe ueber Polygon oder PolyPolygon
+ // Bei Rasteroperationen ungleich Overpaint immer PolyPolygone,
+ // da es zu falschen Ergebnissen kommt, wenn man mehrfach uebereinander
+ // ausgibt
+ // Bei Druckern auch immer PolyPolygone, da nicht alle Drucker
+ // das Uebereinanderdrucken von Polygonen koennen
+ // Virtuelle Device werden auch ausgeklammert, da einige Treiber
+ // ansonsten zu langsam sind
+ PolyPolygon* pPolyPoly;
+ if ( (meRasterOp != ROP_OVERPAINT) || (meOutDevType != OUTDEV_WINDOW) || bMtf )
+ pPolyPoly = new PolyPolygon( 2 );
+ else
+ pPolyPoly = NULL;
+
+ // Radien-Berechnung fuer Kreisausgabe (Kreis schliesst Rechteck ein)
+ USHORT nAngle = rGradient.GetAngle();
+ Rectangle aFullRect = rRect;
+ Rectangle aRect = rRect;
+ long nZWidth = aRect.GetWidth() * (long)rGradient.GetOfsX() / 100;
+ long nZHeight= aRect.GetHeight() * (long)rGradient.GetOfsY() / 100;
+ Size aSize = aRect.GetSize();
+ Point aCenter( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
+ if ( rGradient.GetStyle() == GRADIENT_RADIAL )
+ {
+ aSize.Width() = (long)(0.5 + sqrt((double)aSize.Width()*(double)aSize.Width() +
+ (double)aSize.Height()*(double)aSize.Height()));
+ aSize.Height() = aSize.Width();
+ }
+ // Radien-Berechnung fuer Ellipse
+ else
+ {
+ aSize.Width() = (long)(0.5 + (double)aSize.Width() * 1.4142);
+ aSize.Height() = (long)(0.5 + (double)aSize.Height() * 1.4142);
+ }
+
+ // Border berechnen
+ long nBorderX = (long)rGradient.GetBorder() * aSize.Width() / 100;
+ long nBorderY = (long)rGradient.GetBorder() * aSize.Height() / 100;
+ aSize.Width() -= nBorderX;
+ aSize.Height() -= nBorderY;
+ aRect.Left() = aCenter.X() - (aSize.Width() >> 1);
+ aRect.Top() = aCenter.Y() - (aSize.Height() >> 1);
+ aRect.SetSize( aSize );
+
+ long nMinRect = Min( aRect.GetWidth(), aRect.GetHeight() );
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Ausgabebegrenzungen und Schrittweite fuer jede Richtung festlegen
+ double fScanLeft = aRect.Left();
+ double fScanTop = aRect.Top();
+ double fScanRight = aRect.Right();
+ double fScanBottom = aRect.Bottom();
+ double fScanInc = (double)nMinRect / (double)nSteps * 0.5;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed = (UINT8)nStartRed;
+ UINT8 nGreen = (UINT8)nStartGreen;
+ UINT8 nBlue = (UINT8)nStartBlue;
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Recteck erstmal ausgeben
+ aFullRect.Bottom()++;
+ aFullRect.Right()++;
+ Polygon aPoly( aFullRect );
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Schleife, um nacheinander die Polygone/PolyPolygone auszugeben
+ for ( long i = 0; i < nSteps; i++ )
+ {
+ // neues Polygon berechnen
+ aRect.Left() = (long)(fScanLeft += fScanInc);
+ aRect.Top() = (long)(fScanTop += fScanInc);
+ aRect.Right() = (long)(fScanRight -= fScanInc);
+ aRect.Bottom() = (long)(fScanBottom -= fScanInc);
+
+ if ( (aRect.GetWidth() < 2) || (aRect.GetHeight() < 2) )
+ break;
+
+ // ... Evt. eine maximale Anzahl von Stuetztstellen fuer W16
+ aPoly = Polygon( aRect.Center(),
+ aRect.GetWidth() >> 1,
+ aRect.GetHeight() >> 1 );
+ aPoly.Rotate( aCenter, nAngle );
+
+ // entweder langsame PolyPolygon-Ausgaben oder
+ // schnelles Polygon-Painting
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Farbe entsprechend anpassen
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps) );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+
+ // Falls PolyPolygon-Ausgabe, muessen wir noch ein letztes
+ // inneres Polygon zeichnen
+ if ( pPolyPoly )
+ {
+ const Polygon rPoly = pPolyPoly->GetObject( 1 );
+ if ( !rPoly.GetBoundRect().IsEmpty() )
+ {
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( rPoly );
+#endif
+ }
+ delete pPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawRectGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // Feststellen ob Ausgabe ueber Polygon oder PolyPolygon
+ // Bei Rasteroperationen ungleich Overpaint immer PolyPolygone,
+ // da es zu falschen Ergebnissen kommt, wenn man mehrfach uebereinander
+ // ausgibt
+ // Bei Druckern auch immer PolyPolygone, da nicht alle Drucker
+ // das Uebereinanderdrucken von Polygonen koennen
+ // Virtuelle Device werden auch ausgeklammert, da einige Treiber
+ // ansonsten zu langsam sind
+ PolyPolygon* pPolyPoly;
+ if ( (meRasterOp != ROP_OVERPAINT) || (meOutDevType != OUTDEV_WINDOW) || bMtf )
+ pPolyPoly = new PolyPolygon( 2 );
+ else
+ pPolyPoly = NULL;
+
+ // rotiertes BoundRect ausrechnen
+ Rectangle aRect( rRect );
+ aRect.Left()--;
+ aRect.Top()--;
+ aRect.Right()++;
+ aRect.Bottom()++;
+
+ Rectangle aFullRect( aRect );
+ USHORT nAngle = rGradient.GetAngle();
+ double fAngle = (nAngle % 3600) * F_PI1800;
+ double fWidth = aRect.GetWidth();
+ double fHeight = aRect.GetHeight();
+ double fDX = fWidth * fabs( cos( fAngle ) ) +
+ fHeight * fabs( sin( fAngle ) );
+ double fDY = fHeight * fabs( cos( fAngle ) ) +
+ fWidth * fabs( sin( fAngle ) );
+ fDX = (fDX - fWidth) * 0.5 + 0.5;
+ fDY = (fDY - fHeight) * 0.5 + 0.5;
+ aRect.Left() -= (long)fDX;
+ aRect.Right() += (long)fDX;
+ aRect.Top() -= (long)fDY;
+ aRect.Bottom() += (long)fDY;
+
+ // Quadratisch machen, wenn angefordert;
+ Size aSize = aRect.GetSize();
+ if ( rGradient.GetStyle() == GRADIENT_SQUARE )
+ {
+ if ( aSize.Width() > aSize.Height() )
+ aSize.Height() = aSize.Width();
+ else
+ aSize.Width() = aSize.Height();
+ }
+
+ // neue Mittelpunkte berechnen
+ long nZWidth = aRect.GetWidth() * (long)rGradient.GetOfsX() / 100;
+ long nZHeight = aRect.GetHeight() * (long)rGradient.GetOfsY() / 100;
+ long nBorderX = (long)rGradient.GetBorder() * aSize.Width() / 100;
+ long nBorderY = (long)rGradient.GetBorder() * aSize.Height() / 100;
+ Point aCenter( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
+
+ // Rand beruecksichtigen
+ aSize.Width() -= nBorderX;
+ aSize.Height() -= nBorderY;
+
+ // Ausgaberechteck neu setzen
+ aRect.Left() = aCenter.X() - (aSize.Width() >> 1);
+ aRect.Top() = aCenter.Y() - (aSize.Height() >> 1);
+ aRect.SetSize( aSize );
+
+ long nMinRect = Min( aRect.GetWidth(), aRect.GetHeight() );
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Ausgabebegrenzungen und Schrittweite fuer jede Richtung festlegen
+ double fScanLeft = aRect.Left();
+ double fScanTop = aRect.Top();
+ double fScanRight = aRect.Right();
+ double fScanBottom = aRect.Bottom();
+ double fScanInc = (double)nMinRect / (double)nSteps * 0.5;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed = (UINT8)nStartRed;
+ UINT8 nGreen = (UINT8)nStartGreen;
+ UINT8 nBlue = (UINT8)nStartBlue;
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Recteck erstmal ausgeben
+ Polygon aPoly( aFullRect );
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Schleife, um nacheinander die Polygone/PolyPolygone auszugeben
+ for ( long i = 0; i < nSteps; i++ )
+ {
+ // neues Polygon berechnen
+ aRect.Left() = (long)(fScanLeft += fScanInc);
+ aRect.Top() = (long)(fScanTop += fScanInc);
+ aRect.Right() = (long)(fScanRight -= fScanInc);
+ aRect.Bottom() = (long)(fScanBottom-= fScanInc);
+
+ if ( (aRect.GetWidth() < 2) || (aRect.GetHeight() < 2) )
+ break;
+
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+
+#ifndef REMOTE_APPSERVER
+ // entweder langsame PolyPolygon-Ausgaben oder
+ // schnelles Polygon-Painting
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Farbe entsprechend anpassen
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps) );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+
+ // Falls PolyPolygon-Ausgabe, muessen wir noch ein letztes
+ // inneres Polygon zeichnen
+ if ( pPolyPoly )
+ {
+ const Polygon rPoly = pPolyPoly->GetObject( 1 );
+ if ( !rPoly.GetBoundRect().IsEmpty() )
+ {
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( rPoly );
+#endif
+ }
+ delete pPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawGradient( const Rectangle& rRect,
+ const Gradient& rGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawGradient()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if ( mnDrawMode & DRAWMODE_NOGRADIENT )
+ return;
+ else if ( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawRect( rRect );
+ Pop();
+ return;
+ }
+
+ Gradient aGradient( rGradient );
+
+ if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
+ {
+ Color aStartCol( aGradient.GetStartColor() );
+ Color aEndCol( aGradient.GetEndColor() );
+
+ if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
+ {
+ BYTE cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
+ aStartCol = Color( cStartLum, cStartLum, cStartLum );
+ aEndCol = Color( cEndLum, cEndLum, cEndLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
+ {
+ aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
+ ( aStartCol.GetGreen() >> 1 ) | 0x80,
+ ( aStartCol.GetBlue() >> 1 ) | 0x80 );
+
+ aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
+ ( aEndCol.GetGreen() >> 1 ) | 0x80,
+ ( aEndCol.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aGradient.SetStartColor( aStartCol );
+ aGradient.SetEndColor( aEndCol );
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaGradientAction( rRect, aGradient ) );
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+ // Rechteck in Pixel umrechnen
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ aRect.Justify();
+
+ // Wenn Rechteck leer ist, brauchen wir nichts machen
+ if ( !aRect.IsEmpty() )
+ {
+#ifndef REMOTE_APPSERVER
+ // Clip Region sichern
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ // Gradienten werden ohne Umrandung gezeichnet
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+
+ mbInitFillColor = TRUE;
+
+ // calculate step count if neccessary
+ if ( !aGradient.GetSteps() )
+ aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
+
+ // Farbverlauf ausgeben
+ switch( aGradient.GetStyle() )
+ {
+ case GRADIENT_LINEAR:
+ case GRADIENT_AXIAL:
+ ImplDrawLinearGradient( aRect, aGradient, FALSE );
+ break;
+
+ case GRADIENT_RADIAL:
+ case GRADIENT_ELLIPTICAL:
+ ImplDrawRadialGradient( aRect, aGradient, FALSE );
+ break;
+
+ case GRADIENT_SQUARE:
+ case GRADIENT_RECT:
+ ImplDrawRectGradient( aRect, aGradient, FALSE );
+ break;
+ }
+ }
+
+ Pop();
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawGradient( aRect, aGradient );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
+ const Gradient& rGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawGradient()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if( rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() && !( mnDrawMode & DRAWMODE_NOGRADIENT ) )
+ {
+ if( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ return;
+ }
+
+ if( mpMetaFile )
+ {
+ const Rectangle aRect( rPolyPoly.GetBoundRect() );
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rPolyPoly );
+ DrawGradient( aRect, rGradient );
+ Pop();
+ }
+ else
+ {
+ const BOOL bOldOutput = IsOutputEnabled();
+
+ EnableOutput( FALSE );
+ Push( PUSH_RASTEROP );
+ SetRasterOp( ROP_XOR );
+ DrawGradient( aRect, rGradient );
+ SetFillColor( COL_BLACK );
+ SetRasterOp( ROP_0 );
+ DrawPolyPolygon( rPolyPoly );
+ SetRasterOp( ROP_XOR );
+ DrawGradient( aRect, rGradient );
+ Pop();
+ EnableOutput( bOldOutput );
+ }
+ }
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+ Gradient aGradient( rGradient );
+
+ if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
+ {
+ Color aStartCol( aGradient.GetStartColor() );
+ Color aEndCol( aGradient.GetEndColor() );
+
+ if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
+ {
+ BYTE cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
+ aStartCol = Color( cStartLum, cStartLum, cStartLum );
+ aEndCol = Color( cEndLum, cEndLum, cEndLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
+ {
+ aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
+ ( aStartCol.GetGreen() >> 1 ) | 0x80,
+ ( aStartCol.GetBlue() >> 1 ) | 0x80 );
+
+ aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
+ ( aEndCol.GetGreen() >> 1 ) | 0x80,
+ ( aEndCol.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aGradient.SetStartColor( aStartCol );
+ aGradient.SetEndColor( aEndCol );
+ }
+
+#ifndef REMOTE_APPSERVER
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rPolyPoly );
+ DrawGradient( rPolyPoly.GetBoundRect(), aGradient );
+ Pop();
+ }
+ else
+ {
+ const PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
+ const Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ aDstRect.Intersection( aBoundRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice aVDev;
+ const Size aDstSize( aDstRect.GetSize() );
+
+ if( aVDev.SetOutputSizePixel( aDstSize) )
+ {
+ MapMode aVDevMap;
+ const RasterOp eOldROP = GetRasterOp();
+ const BOOL bOldMap = mbMap;
+
+ mbMap = FALSE;
+
+ aVDev.DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
+ DrawGradient( aBoundRect, aGradient );
+ aVDev.SetRasterOp( ROP_XOR );
+ aVDev.DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
+ aVDev.SetFillColor( COL_BLACK );
+ aVDev.SetRasterOp( ROP_0 );
+ aVDevMap.SetOrigin( Point( -aDstRect.Left(), -aDstRect.Top() ) );
+ aVDev.SetMapMode( aVDevMap );
+ aVDev.DrawPolyPolygon( aPolyPoly );
+ aVDevMap.SetOrigin( Point() );
+ aVDev.SetMapMode( aVDevMap );
+ SetRasterOp( ROP_XOR );
+ DrawOutDev( aDstRect.TopLeft(), aDstSize, Point(), aDstSize, aVDev );
+ SetRasterOp( eOldROP );
+
+ mbMap = bOldMap;
+ }
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawGradient( ImplLogicToDevicePixel( rPolyPoly ), aGradient );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddGradientActions( const Rectangle& rRect, const Gradient& rGradient,
+ GDIMetaFile& rMtf )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ Rectangle aRect( rRect );
+
+ aRect.Justify();
+
+ // Wenn Rechteck leer ist, brauchen wir nichts machen
+ if ( !aRect.IsEmpty() )
+ {
+ Gradient aGradient( rGradient );
+ GDIMetaFile* pOldMtf = mpMetaFile;
+
+ mpMetaFile = &rMtf;
+ mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
+ mpMetaFile->AddAction( new MetaISectRectClipRegionAction( aRect ) );
+ mpMetaFile->AddAction( new MetaLineColorAction( Color(), FALSE ) );
+
+ // calculate step count if neccessary
+ if ( !aGradient.GetSteps() )
+ aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
+
+ // Farbverlaufactions aufzeichnen
+ switch( rGradient.GetStyle() )
+ {
+ case GRADIENT_LINEAR:
+ case GRADIENT_AXIAL:
+ ImplDrawLinearGradient( aRect, aGradient, TRUE );
+ break;
+
+ case GRADIENT_RADIAL:
+ case GRADIENT_ELLIPTICAL:
+ ImplDrawRadialGradient( aRect, aGradient, TRUE );
+ break;
+
+ case GRADIENT_SQUARE:
+ case GRADIENT_RECT:
+ ImplDrawRectGradient( aRect, aGradient, TRUE );
+ break;
+ }
+
+ mpMetaFile->AddAction( new MetaPopAction() );
+ mpMetaFile = pOldMtf;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch )
+{
+ DBG_TRACE( "OutputDevice::DrawHatch()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Hatch aHatch( rHatch );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ Color aColor( rHatch.GetColor() );
+
+ if ( mnDrawMode & DRAWMODE_BLACKLINE )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITELINE )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80);
+ }
+
+ aHatch.SetColor( aColor );
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaHatchAction( rPolyPoly, aHatch ) );
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+#endif
+
+ PolyPolygon aPolyPoly( rPolyPoly );
+ aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME | POLY_OPTIMIZE_CLOSE );
+
+ if( aPolyPoly.Count() )
+ {
+#ifndef REMOTE_APPSERVER
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+
+ mpMetaFile = NULL;
+ Push( PUSH_LINECOLOR );
+ SetLineColor( aHatch.GetColor() );
+ ImplInitLineColor();
+ ImplDrawHatch( aPolyPoly, aHatch, FALSE );
+ Pop();
+ mpMetaFile = pOldMetaFile;
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ aHatch.SetDistance( ImplLogicWidthToDevicePixel( aHatch.GetDistance() ) );
+ pGraphics->DrawHatch( ImplLogicToDevicePixel( aPolyPoly ), aHatch );
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddHatchActions( const PolyPolygon& rPolyPoly, const Hatch& rHatch,
+ GDIMetaFile& rMtf )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ PolyPolygon aPolyPoly( rPolyPoly );
+ aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME | POLY_OPTIMIZE_CLOSE );
+
+ if( aPolyPoly.Count() )
+ {
+ GDIMetaFile* pOldMtf = mpMetaFile;
+
+ mpMetaFile = &rMtf;
+ mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
+ mpMetaFile->AddAction( new MetaLineColorAction( rHatch.GetColor(), TRUE ) );
+ ImplDrawHatch( aPolyPoly, rHatch, TRUE );
+ mpMetaFile->AddAction( new MetaPopAction() );
+ mpMetaFile = pOldMtf;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch, BOOL bMtf )
+{
+ Rectangle aRect( rPolyPoly.GetBoundRect() );
+ const long nLogPixelWidth = ImplDevicePixelToLogicWidth( 1 );
+ const long nWidth = ImplDevicePixelToLogicWidth( Max( ImplLogicWidthToDevicePixel( rHatch.GetDistance() ), 5L ) );
+ Point* pPtBuffer = new Point[ HATCH_MAXPOINTS ];
+ Point aPt1, aPt2, aEndPt1;
+ Size aInc;
+
+ // Single hatch
+ aRect.Left() -= nLogPixelWidth; aRect.Top() -= nLogPixelWidth; aRect.Right() += nLogPixelWidth; aRect.Bottom() += nLogPixelWidth;
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle(), aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+
+ if( ( rHatch.GetStyle() == HATCH_DOUBLE ) || ( rHatch.GetStyle() == HATCH_TRIPLE ) )
+ {
+ // Double hatch
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 900, aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+
+ if( rHatch.GetStyle() == HATCH_TRIPLE )
+ {
+ // Triple hatch
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 450, aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+ }
+ }
+
+ delete[] pPtBuffer;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplCalcHatchValues( const Rectangle& rRect, long nDist, USHORT nAngle10,
+ Point& rPt1, Point& rPt2, Size& rInc, Point& rEndPt1 )
+{
+ Point aRef;
+ long nAngle = nAngle10 % 1800;
+ long nOffset = 0;
+
+ if( nAngle > 900 )
+ nAngle -= 1800;
+
+ aRef = ( !IsRefPoint() ? rRect.TopLeft() : GetRefPoint() );
+
+ if( 0 == nAngle )
+ {
+ rInc = Size( 0, nDist );
+ rPt1 = rRect.TopLeft();
+ rPt2 = rRect.TopRight();
+ rEndPt1 = rRect.BottomLeft();
+
+ if( aRef.Y() <= rRect.Top() )
+ nOffset = ( ( rRect.Top() - aRef.Y() ) % nDist );
+ else
+ nOffset = ( nDist - ( ( aRef.Y() - rRect.Top() ) % nDist ) );
+
+ rPt1.Y() -= nOffset;
+ rPt2.Y() -= nOffset;
+ }
+ else if( 900 == nAngle )
+ {
+ rInc = Size( nDist, 0 );
+ rPt1 = rRect.TopLeft();
+ rPt2 = rRect.BottomLeft();
+ rEndPt1 = rRect.TopRight();
+
+ if( aRef.X() <= rRect.Left() )
+ nOffset = ( rRect.Left() - aRef.X() ) % nDist;
+ else
+ nOffset = nDist - ( ( aRef.X() - rRect.Left() ) % nDist );
+
+ rPt1.X() -= nOffset;
+ rPt2.X() -= nOffset;
+ }
+ else if( nAngle >= -450 && nAngle <= 450 )
+ {
+ const double fAngle = F_PI1800 * labs( nAngle );
+ const double fTan = tan( fAngle );
+ const long nYOff = FRound( ( rRect.Right() - rRect.Left() ) * fTan );
+ long nPY;
+
+ rInc = Size( 0, nDist = FRound( nDist / cos( fAngle ) ) );
+
+ if( nAngle > 0 )
+ {
+ rPt1 = rRect.TopLeft();
+ rPt2 = Point( rRect.Right(), rRect.Top() - nYOff );
+ rEndPt1 = Point( rRect.Left(), rRect.Bottom() + nYOff );
+ nPY = FRound( aRef.Y() - ( ( rPt1.X() - aRef.X() ) * fTan ) );
+ }
+ else
+ {
+ rPt1 = rRect.TopRight();
+ rPt2 = Point( rRect.Left(), rRect.Top() - nYOff );
+ rEndPt1 = Point( rRect.Right(), rRect.Bottom() + nYOff );
+ nPY = FRound( aRef.Y() + ( ( rPt1.X() - aRef.X() ) * fTan ) );
+ }
+
+ if( nPY <= rPt1.Y() )
+ nOffset = ( rPt1.Y() - nPY ) % nDist;
+ else
+ nOffset = nDist - ( ( nPY - rPt1.Y() ) % nDist );
+
+ rPt1.Y() -= nOffset;
+ rPt2.Y() -= nOffset;
+ }
+ else
+ {
+ const double fAngle = F_PI1800 * labs( nAngle );
+ const double fTan = tan( fAngle );
+ const long nXOff = FRound( ( rRect.Bottom() - rRect.Top() ) / fTan );
+ long nPX;
+
+ rInc = Size( nDist = FRound( nDist / sin( fAngle ) ), 0 );
+
+ if( nAngle > 0 )
+ {
+ rPt1 = rRect.TopLeft();
+ rPt2 = Point( rRect.Left() - nXOff, rRect.Bottom() );
+ rEndPt1 = Point( rRect.Right() + nXOff, rRect.Top() );
+ nPX = FRound( aRef.X() - ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
+ }
+ else
+ {
+ rPt1 = rRect.BottomLeft();
+ rPt2 = Point( rRect.Left() - nXOff, rRect.Top() );
+ rEndPt1 = Point( rRect.Right() + nXOff, rRect.Bottom() );
+ nPX = FRound( aRef.X() + ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
+ }
+
+ if( nPX <= rPt1.X() )
+ nOffset = ( rPt1.X() - nPX ) % nDist;
+ else
+ nOffset = nDist - ( ( nPX - rPt1.X() ) % nDist );
+
+ rPt1.X() -= nOffset;
+ rPt2.X() -= nOffset;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawHatchLine( const Line& rLine, const PolyPolygon& rPolyPoly,
+ Point* pPtBuffer, BOOL bMtf )
+{
+#ifdef REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics;
+ if( !bMtf && !( pGraphics = ImplGetServerGraphics() ) )
+ return;
+#endif
+
+ double fSaveDist = 0.0;
+ long nPCounter = 0;
+
+ for( long nPoly = 0, nPolyCount = rPolyPoly.Count(); nPoly < nPolyCount; nPoly++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ (USHORT) nPoly ];
+
+ if( rPoly.GetSize() > 1 )
+ {
+ Point aIntersection;
+ Point aPt1( rPoly[0] );
+
+ for( long i = 1, nCount = rPoly.GetSize(); i < nCount; i++ )
+ {
+ const Point& rPt2 = rPoly[ (USHORT) i ];
+
+ if( rLine.Intersection( Line( aPt1, rPt2 ), aIntersection ) )
+ {
+ const BOOL bDifferent = !nPCounter || aIntersection != pPtBuffer[ nPCounter - 1 ];
+
+ if( aIntersection == aPt1 )
+ {
+ double fDist1 = rLine.GetDistance( rPoly[ ( i > 1 ) ? i - 2 : nCount - 2 ] );
+ double fDist2 = rLine.GetDistance( rPt2 );
+
+ if( 1 == i )
+ nCount--;
+
+ if( bDifferent )
+ {
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+
+ if( ( ( fDist1 < 0.0 && fDist2 < 0.0 ) || ( fDist1 > 0.0 && fDist2 > 0.0 ) ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ else if( fDist1 == 0.0 )
+ {
+ if( ( fSaveDist > 0.0 && fDist2 < 0.0 ) || ( fSaveDist < 0.0 && fDist2 > 0.0 ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ }
+ }
+ }
+ else if( aIntersection == rPt2 )
+ {
+ double fDist1 = rLine.GetDistance( aPt1 );
+ double fDist2 = rLine.GetDistance( rPoly[ ( i < nCount - 1 ) ? i + 1 : 1 ] );
+
+ if( bDifferent )
+ {
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+
+ if( ( ( fDist1 < 0.0 && fDist2 < 0.0 ) || ( fDist1 > 0.0 && fDist2 > 0.0 ) ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ else if( fDist2 == 0.0 )
+ fSaveDist = fDist1;
+ }
+ }
+ else
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ }
+
+ aPt1 = rPt2;
+ }
+ }
+ }
+
+ if( nPCounter > 1 )
+ {
+ qsort( pPtBuffer, nPCounter, sizeof( Point ), ImplHatchCmpFnc );
+
+ if( nPCounter & 1 )
+ nPCounter--;
+
+ if( bMtf )
+ {
+ for( long i = 0; i < nPCounter; i += 2 )
+ mpMetaFile->AddAction( new MetaLineAction( pPtBuffer[ i ], pPtBuffer[ i + 1 ] ) );
+ }
+ else
+ {
+ for( long i = 0; i < nPCounter; i += 2 )
+ {
+ const Point aPt1( ImplLogicToDevicePixel( pPtBuffer[ i ] ) );
+ const Point aPt2( ImplLogicToDevicePixel( pPtBuffer[ i + 1 ] ) );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawLine( aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y() );
+#else
+ pGraphics->DrawLine( aPt1, aPt2 );
+#endif
+ }
+ }
+ }
+}
diff --git a/vcl/source/gdi/outdev5.cxx b/vcl/source/gdi/outdev5.cxx
new file mode 100644
index 000000000000..f162b1196fd1
--- /dev/null
+++ b/vcl/source/gdi/outdev5.cxx
@@ -0,0 +1,430 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev5.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+#include <tools/ref.hxx>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// =======================================================================
+
+void OutputDevice::DrawRect( const Rectangle& rRect,
+ ULONG nHorzRound, ULONG nVertRound )
+{
+ DBG_TRACE( "OutputDevice::DrawRoundRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ const Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+
+ nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
+ nVertRound = ImplLogicHeightToDevicePixel( nVertRound );
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ if ( !nHorzRound && !nVertRound )
+ mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
+ else
+ {
+ const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );
+
+ if ( aRoundRectPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.ImplGetConstPointAry();
+
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry );
+ else
+ mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ if ( !nHorzRound || !nVertRound )
+ pGraphics->DrawRect( aRect );
+ else
+ pGraphics->DrawRect( aRect, nHorzRound, nVertRound );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawEllipse( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::DrawEllipse()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaEllipseAction( rRect ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Polygon aRectPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
+ if ( aRectPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aRectPoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aRectPoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aRectPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawEllipse( aRect );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawArc( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawArc()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaArcAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aArcPoly( aRect, aStart, aEnd, POLY_ARC );
+
+ if ( aArcPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aArcPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolyLine( aArcPoly.GetSize(), pPtAry );
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawArc( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPie( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawPie()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPieAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aPiePoly( aRect, aStart, aEnd, POLY_PIE );
+
+ if ( aPiePoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aPiePoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aPiePoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aPiePoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawPie( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawChord( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawChord()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaChordAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aChordPoly( aRect, aStart, aEnd, POLY_CHORD );
+
+ if ( aChordPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aChordPoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aChordPoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aChordPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawChord( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx
new file mode 100644
index 000000000000..371334530488
--- /dev/null
+++ b/vcl/source/gdi/outdev6.cxx
@@ -0,0 +1,1043 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev6.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WALL_CXX
+
+#include <math.h>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else // REMOTE_APPSERVER
+#include <tools/stream.hxx>
+#endif // REMOTE_APPSERVER
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+#ifdef REMOTE_APPSERVER
+#include <rmoutdev.hxx>
+#endif
+#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
+#include <com/sun/star/uno/Sequence.hxx>
+#endif
+
+// ========================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, ULONG nFlags )
+{
+ DBG_TRACE( "OutputDevice::DrawGrid()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
+ aDstRect.Intersection( rRect );
+
+ if( aDstRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+
+ if( !pGraphics )
+ return;
+#endif
+
+ const long nDistX = Max( rDist.Width(), 1L );
+ const long nDistY = Max( rDist.Height(), 1L );
+ long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
+ long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
+ const long nRight = aDstRect.Right();
+ const long nBottom = aDstRect.Bottom();
+ const long nStartX = ImplLogicXToDevicePixel( nX );
+ const long nEndX = ImplLogicXToDevicePixel( nRight );
+ const long nStartY = ImplLogicYToDevicePixel( nY );
+ const long nEndY = ImplLogicYToDevicePixel( nBottom );
+ long nHorzCount = 0L;
+ long nVertCount = 0L;
+
+ ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
+ ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
+ {
+ aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
+ aVertBuf[ nVertCount++ ] = nStartY;
+ while( ( nY += nDistY ) <= nBottom )
+ aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
+ }
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
+ {
+ aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
+ aHorzBuf[ nHorzCount++ ] = nStartX;
+ while( ( nX += nDistX ) <= nRight )
+ aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
+ }
+
+ if( mbInitLineColor )
+ ImplInitLineColor();
+
+ if( mbInitFillColor )
+ ImplInitFillColor();
+
+#ifndef REMOTE_APPSERVER
+ const BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+
+ if( nFlags & GRID_DOTS )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ for( long j = 0L, nY = aVertBuf[ i ]; j < nHorzCount; j++ )
+ mpGraphics->DrawPixel( aHorzBuf[ j ], nY );
+ }
+ else
+ {
+ if( nFlags & GRID_HORZLINES )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ {
+ nY = aVertBuf[ i ];
+ mpGraphics->DrawLine( nStartX, nY, nEndX, nY );
+ }
+ }
+
+ if( nFlags & GRID_VERTLINES )
+ {
+ for( long i = 0L; i < nHorzCount; i++ )
+ {
+ nX = aHorzBuf[ i ];
+ mpGraphics->DrawLine( nX, nStartY, nX, nEndY );
+ }
+ }
+ }
+
+ mbMap = bOldMap;
+#else // REMOTE_APPSERVER
+ aHorzBuf.realloc( nHorzCount );
+ aVertBuf.realloc( nVertCount );
+ pGraphics->DrawGrid( nStartX, nEndX, aHorzBuf, nStartY, nEndY, aVertBuf, nFlags );
+#endif // REMOTE_APPSERVER
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
+ USHORT nTransparencePercent )
+{
+ DBG_TRACE( "OutputDevice::DrawTransparent()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( !mbFillColor || ( 0 == nTransparencePercent ) )
+ DrawPolyPolygon( rPolyPoly );
+ else if( 100 == nTransparencePercent )
+ {
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ }
+ else
+ {
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
+
+ if( !IsDeviceOutputNecessary() || ( !mbLineColor && !mbFillColor ) )
+ return;
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ mpMetaFile = NULL;
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
+ const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
+ const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L );
+ long nMove;
+ const USHORT nTrans = ( nTransparencePercent < 13 ) ? 0 :
+ ( nTransparencePercent < 38 ) ? 25 :
+ ( nTransparencePercent < 63 ) ? 50 :
+ ( nTransparencePercent < 88 ) ? 75 : 100;
+
+ switch( nTrans )
+ {
+ case( 25 ): nMove = nBaseExtent * 3; break;
+ case( 50 ): nMove = nBaseExtent * 4; break;
+ case( 75 ): nMove = nBaseExtent * 6; break;
+ }
+
+ Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
+ IntersectClipRegion( rPolyPoly );
+ SetLineColor( GetFillColor() );
+
+ Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
+
+ const BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+
+ while( aRect.Top() <= aPolyRect.Bottom() )
+ {
+ DrawRect( aRect );
+ aRect.Move( 0, nMove );
+ }
+
+ aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
+ while( aRect.Left() <= aPolyRect.Right() )
+ {
+ DrawRect( aRect );
+ aRect.Move( nMove, 0 );
+ }
+
+ mbMap = bOldMap;
+ Pop();
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
+ Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ aDstRect.Intersection( aPolyRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice aVDev( *this, 1 );
+ const Size aDstSz( aDstRect.GetSize() );
+ const BYTE cTrans = (BYTE) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
+
+ if( aDstRect.Left() || aDstRect.Top() )
+ aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
+
+ if( aVDev.SetOutputSizePixel( aDstSz ) )
+ {
+ const BOOL bOldMap = mbMap;
+
+ mbMap = FALSE;
+
+ aVDev.SetLineColor( COL_BLACK );
+ aVDev.SetFillColor( COL_BLACK );
+ aVDev.DrawPolyPolygon( aPolyPoly );
+
+ Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
+ Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
+ BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
+ BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
+
+ if( pW && pR )
+ {
+ BitmapColor aPixCol;
+ const BitmapColor aFillCol( GetFillColor() );
+ const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const long nWidth = pW->Width(), nHeight = pW->Height();
+ const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
+ long nX, nY;
+
+ if( aPaint.GetBitCount() <= 8 )
+ {
+ const BitmapPalette& rPal = pW->GetPalette();
+ const USHORT nCount = rPal.GetEntryCount();
+ BitmapColor* pMap = (BitmapColor*) new BYTE[ nCount * sizeof( BitmapColor ) ];
+
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ BitmapColor aCol( rPal[ i ] );
+ pMap[ i ] = BitmapColor( (BYTE) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
+ }
+
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ const BYTE cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ BYTE cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ *pWScan = (BYTE) pMap[ *pWScan ].GetIndex();
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ for( nX = 0; nX < nWidth; nX++ )
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
+ }
+
+ delete[] (BYTE*) pMap;
+ }
+ else
+ {
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ const BYTE cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ BYTE cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ {
+ pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
+ pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
+ pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ {
+ aPixCol = pW->GetColor( nY, nX );
+ pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ aPolyMask.ReleaseAccess( pR );
+ aPaint.ReleaseAccess( pW );
+
+ DrawBitmap( aDstRect.TopLeft(), aPaint );
+
+ mbMap = bOldMap;
+
+ if( mbLineColor )
+ {
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ }
+ }
+ else
+ DrawPolyPolygon( rPolyPoly );
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawTransparent( ImplLogicToDevicePixel( rPolyPoly ), nTransparencePercent );
+ }
+#endif // REMOTE_APPSERVER
+ }
+
+ mpMetaFile = pOldMetaFile;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
+ const Size& rSize, const Gradient& rTransparenceGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawTransparent()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ const Color aBlack( COL_BLACK );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
+
+ if( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack )
+ {
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ }
+ else
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ mpMetaFile = NULL;
+ aDstRect.Intersection( aOutRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice* pVDev = new VirtualDevice;
+
+ pVDev->mnDPIX = mnDPIX;
+ pVDev->mnDPIY = mnDPIY;
+
+ if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
+ {
+ Bitmap aPaint, aMask;
+ AlphaMask aAlpha;
+ MapMode aMap( GetMapMode() );
+ Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
+ const BOOL bOldMap = mbMap;
+
+ aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
+ pVDev->SetMapMode( aMap );
+
+ // create paint bitmap
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( FALSE );
+ aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( TRUE );
+
+ // create mask bitmap
+ pVDev->SetLineColor( COL_BLACK );
+ pVDev->SetFillColor( COL_BLACK );
+ pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
+ pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
+ DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( FALSE );
+ aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( TRUE );
+
+ // create alpha mask from gradient
+ pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
+ pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
+ pVDev->SetDrawMode( DRAWMODE_DEFAULT );
+ pVDev->EnableMapMode( FALSE );
+ pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
+
+#ifndef REMOTE_APPSERVER
+ aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+#else
+ aAlpha.ImplSetBitmap( pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ) );
+#endif
+
+ delete pVDev;
+
+ mbMap = FALSE;
+ DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
+ mbMap = bOldMap;
+ }
+ else
+ delete pVDev;
+ }
+
+ mpMetaFile = pOldMetaFile;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ // Wallpaper ohne Umrandung zeichnen
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( rWallpaper.GetColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawRect( nX+mnOutOffX, nY+mnOutOffY, nWidth, nHeight );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( rWallpaper.GetColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawRect( Rectangle( Point( nX+mnOutOffX, nY+mnOutOffY ), Size( nWidth, nHeight ) ) );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ BitmapEx aBmpEx;
+ const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
+ Point aPos;
+ Size aSize;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const WallpaperStyle eStyle = rWallpaper.GetStyle();
+ const BOOL bOldMap = mbMap;
+ BOOL bDrawn = FALSE;
+ BOOL bDrawGradientBackground = FALSE;
+ BOOL bDrawColorBackground = FALSE;
+
+ if( pCached )
+ aBmpEx = *pCached;
+ else
+ aBmpEx = rWallpaper.GetBitmap();
+
+ const long nBmpWidth = aBmpEx.GetSizePixel().Width();
+ const long nBmpHeight = aBmpEx.GetSizePixel().Height();
+ const BOOL bTransparent = aBmpEx.IsTransparent();
+
+ // draw background
+ if( bTransparent )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = TRUE;
+ else
+ {
+ if( !pCached && !rWallpaper.GetColor().GetTransparency() )
+ {
+ VirtualDevice aVDev( *this );
+ aVDev.SetBackground( rWallpaper.GetColor() );
+ aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
+ aVDev.DrawBitmapEx( Point(), aBmpEx );
+ aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+
+ bDrawColorBackground = TRUE;
+ }
+ }
+ else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = TRUE;
+ else
+ bDrawColorBackground = TRUE;
+ }
+
+ // background of bitmap?
+ if( bDrawGradientBackground )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( bDrawColorBackground && bTransparent )
+ {
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ bDrawColorBackground = FALSE;
+ }
+
+ // calc pos and size
+ if( rWallpaper.IsRect() )
+ {
+ const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
+ aPos = aBound.TopLeft();
+ aSize = aBound.GetSize();
+ }
+ else
+ {
+ aPos = Point( nX, nY );
+ aSize = Size( nWidth, nHeight );
+ }
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ switch( eStyle )
+ {
+ case( WALLPAPER_SCALE ):
+ {
+ if( !pCached || ( pCached->GetSizePixel() != aSize ) )
+ {
+ if( pCached )
+ rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
+
+ aBmpEx = rWallpaper.GetBitmap();
+ aBmpEx.Scale( aSize );
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
+ }
+ }
+ break;
+
+ case( WALLPAPER_TOPLEFT ):
+ break;
+
+ case( WALLPAPER_TOP ):
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ break;
+
+ case( WALLPAPER_TOPRIGHT ):
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ break;
+
+ case( WALLPAPER_LEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ break;
+
+ case( WALLPAPER_CENTER ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_RIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMLEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ break;
+
+ case( WALLPAPER_BOTTOM ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMRIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ default:
+ {
+ const long nRight = nX + nWidth - 1L;
+ const long nBottom = nY + nHeight - 1L;
+ long nFirstX;
+ long nFirstY;
+
+ if( eStyle == WALLPAPER_TILE )
+ {
+ nFirstX = aPos.X();
+ nFirstY = aPos.Y();
+ }
+ else
+ {
+ nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
+ nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
+ }
+
+ const long nOffX = ( nFirstX - nX ) % nBmpWidth;
+ const long nOffY = ( nFirstY - nY ) % nBmpHeight;
+ long nStartX = nX + nOffX;
+ long nStartY = nY + nOffY;
+
+ if( nOffX > 0L )
+ nStartX -= nBmpWidth;
+
+ if( nOffY > 0L )
+ nStartY -= nBmpHeight;
+
+ for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
+ for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
+ DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
+
+ bDrawn = TRUE;
+ }
+ break;
+ }
+
+ if( !bDrawn )
+ {
+ // optimized for non-transparent bitmaps
+ if( bDrawColorBackground )
+ {
+ const Size aBmpSize( aBmpEx.GetSizePixel() );
+ const Point aTmpPoint;
+ const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
+ const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Rectangle aWorkRect;
+
+ aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+
+ DrawBitmapEx( aPos, aBmpEx );
+ }
+
+ rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
+
+ Pop();
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ Rectangle aBound;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const BOOL bOldMap = mbMap;
+
+/*
+ if ( rWallpaper.IsRect() )
+ aBound = LogicToPixel( rWallpaper.GetRect() );
+ else
+*/
+ aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ DrawGradient( aBound, rWallpaper.GetGradient() );
+
+ Pop();
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ if( rWallpaper.IsBitmap() )
+ ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( rWallpaper.IsGradient() )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawWallpaper( const Rectangle& rRect,
+ const Wallpaper& rWallpaper )
+{
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
+ {
+ Rectangle aRect = LogicToPixel( rRect );
+ aRect.Justify();
+
+ if ( !aRect.IsEmpty() )
+ {
+ ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Erase()
+{
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( mbBackground )
+ {
+ RasterOp eRasterOp = GetRasterOp();
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( ROP_OVERPAINT );
+ ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( eRasterOp );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect,
+ const Color& rLeftTopColor,
+ const Color& rRightBottomColor )
+{
+#ifndef REMOTE_APPSERVER
+ SetFillColor( rLeftTopColor );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
+ SetFillColor( rRightBottomColor );
+ DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
+ DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
+#else
+ if ( mpMetaFile )
+ {
+ BOOL bOutputEnabled = IsOutputEnabled();
+ EnableOutput( FALSE );
+ SetFillColor( rLeftTopColor );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
+ SetFillColor( rRightBottomColor );
+ DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
+ DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
+ EnableOutput( bOutputEnabled );
+ }
+
+ if ( IsDeviceOutputNecessary() && !rRect.IsEmpty() )
+ {
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ pGraphics->Draw2ColorFrame( aRect, rLeftTopColor, rRightBottomColor );
+ }
+ }
+ SetFillColor( rRightBottomColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
+ const GfxLink& rGfxLink, GDIMetaFile* pSubst )
+{
+ if ( mpMetaFile )
+ {
+ GDIMetaFile aSubst;
+
+ if( pSubst )
+ aSubst = *pSubst;
+
+ mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
+ }
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
+ BOOL bDrawn = FALSE;
+
+ if( !aRect.IsEmpty() )
+ {
+ aRect.Justify();
+
+ if( GetOutDevType() == OUTDEV_PRINTER )
+ {
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( !mbOutputClipped )
+ {
+ bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ (BYTE*) rGfxLink.GetData(), rGfxLink.GetDataSize() );
+ }
+#else
+ DBG_ERROR( "No direct EPS-support for remote appserver!" );
+#endif
+ }
+
+ if( !bDrawn && pSubst )
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+
+ mpMetaFile = NULL;
+ Graphic( *pSubst ).Draw( this, rPoint, rSize );
+ mpMetaFile = pOldMetaFile;
+ }
+ }
+}
diff --git a/vcl/source/gdi/outmap.cxx b/vcl/source/gdi/outmap.cxx
new file mode 100644
index 000000000000..c086efb92bbc
--- /dev/null
+++ b/vcl/source/gdi/outmap.cxx
@@ -0,0 +1,2106 @@
+/*************************************************************************
+ *
+ * $RCSfile: outmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <limits.h>
+
+#define _SV_OUTMAP_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef _BIGINT_HXX
+#include <tools/bigint.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+DBG_NAMEEX( Region );
+
+// =======================================================================
+
+static long aImplNumeratorAry[MAP_PIXEL+1] =
+ { 1, 1, 5, 50, 1, 1, 1, 1, 1, 1, 1 };
+static long aImplDenominatorAry[MAP_PIXEL+1] =
+ { 2540, 254, 127, 127, 1000, 100, 10, 1, 72, 1440, 1 };
+
+// -----------------------------------------------------------------------
+
+/*
+Reduziert die Genauigkeit bis eine Fraction draus wird (sollte mal
+ein Fraction ctor werden) koennte man dann auch mit BigInts machen
+*/
+
+static Fraction ImplMakeFraction( long nN1, long nN2, long nD1, long nD2 )
+{
+ long i = 1;
+
+ if ( nN1 < 0 ) { i = -i; nN1 = -nN1; }
+ if ( nN2 < 0 ) { i = -i; nN2 = -nN2; }
+ if ( nD1 < 0 ) { i = -i; nD1 = -nD1; }
+ if ( nD2 < 0 ) { i = -i; nD2 = -nD2; }
+ // alle positiv; i Vorzeichen
+
+ Fraction aF( i*nN1, nD1 );
+ aF *= Fraction( nN2, nD2 );
+
+ while ( aF.GetDenominator() == -1 )
+ {
+ if ( nN1 > nN2 )
+ nN1 = (nN1 + 1) / 2;
+ else
+ nN2 = (nN2 + 1) / 2;
+ if ( nD1 > nD2 )
+ nD1 = (nD1 + 1) / 2;
+ else
+ nD2 = (nD2 + 1) / 2;
+
+ aF = Fraction( i*nN1, nD1 );
+ aF *= Fraction( nN2, nD2 );
+ }
+
+ return aF;
+}
+
+// -----------------------------------------------------------------------
+
+// Fraction.GetNumerator()
+// Fraction.GetDenominator() > 0
+// rOutRes.nPixPerInch? > 0
+// rMapRes.nMapScNum?
+// rMapRes.nMapScDenom? > 0
+
+static void ImplCalcBigIntThreshold( long nDPIX, long nDPIY,
+ const ImplMapRes& rMapRes,
+ ImplThresholdRes& rThresRes )
+{
+ if ( LONG_MAX / nDPIX < Abs( rMapRes.mnMapScNumX ) )
+ {
+ rThresRes.mnThresLogToPixX = 0;
+ rThresRes.mnThresPixToLogX = 0;
+ }
+ else
+ {
+ // Schwellenwerte fuer BigInt Arithmetik berechnen
+ long nDenomHalfX = rMapRes.mnMapScDenomX / 2;
+ ULONG nDenomX = rMapRes.mnMapScDenomX;
+ long nProductX = nDPIX * rMapRes.mnMapScNumX;
+
+ if ( !nProductX )
+ rThresRes.mnThresLogToPixX = LONG_MAX;
+ else
+ rThresRes.mnThresLogToPixX = Abs( (LONG_MAX - nDenomHalfX) / nProductX );
+
+ if ( !nDenomX )
+ rThresRes.mnThresPixToLogX = LONG_MAX;
+ else if ( nProductX >= 0 )
+ rThresRes.mnThresPixToLogX = (long)(((ULONG)LONG_MAX - (ULONG)( nProductX/2)) / nDenomX);
+ else
+ rThresRes.mnThresPixToLogX = (long)(((ULONG)LONG_MAX + (ULONG)(-nProductX/2)) / nDenomX);
+ }
+
+ if ( LONG_MAX / nDPIY < Abs( rMapRes.mnMapScNumY ) )
+ {
+ rThresRes.mnThresLogToPixY = 0;
+ rThresRes.mnThresPixToLogY = 0;
+ }
+ else
+ {
+ // Schwellenwerte fuer BigInt Arithmetik berechnen
+ long nDenomHalfY = rMapRes.mnMapScDenomY / 2;
+ ULONG nDenomY = rMapRes.mnMapScDenomY;
+ long nProductY = nDPIY * rMapRes.mnMapScNumY;
+
+ if ( !nProductY )
+ rThresRes.mnThresLogToPixY = LONG_MAX;
+ else
+ rThresRes.mnThresLogToPixY = Abs( (LONG_MAX - nDenomHalfY) / nProductY );
+
+ if ( !nDenomY )
+ rThresRes.mnThresPixToLogY = LONG_MAX;
+ else if ( nProductY >= 0 )
+ rThresRes.mnThresPixToLogY = (long)(((ULONG)LONG_MAX - (ULONG)( nProductY/2)) / nDenomY);
+ else
+ rThresRes.mnThresPixToLogY = (long)(((ULONG)LONG_MAX + (ULONG)(-nProductY/2)) / nDenomY);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcMapResolution( const MapMode& rMapMode,
+ long nDPIX, long nDPIY, ImplMapRes& rMapRes )
+{
+ switch ( rMapMode.GetMapUnit() )
+ {
+ case MAP_RELATIVE:
+ break;
+ case MAP_100TH_MM:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 2540;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 2540;
+ break;
+ case MAP_10TH_MM:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 254;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 254;
+ break;
+ case MAP_MM:
+ rMapRes.mnMapScNumX = 5; // 10
+ rMapRes.mnMapScDenomX = 127; // 254
+ rMapRes.mnMapScNumY = 5; // 10
+ rMapRes.mnMapScDenomY = 127; // 254
+ break;
+ case MAP_CM:
+ rMapRes.mnMapScNumX = 50; // 100
+ rMapRes.mnMapScDenomX = 127; // 254
+ rMapRes.mnMapScNumY = 50; // 100
+ rMapRes.mnMapScDenomY = 127; // 254
+ break;
+ case MAP_1000TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1000;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1000;
+ break;
+ case MAP_100TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 100;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 100;
+ break;
+ case MAP_10TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 10;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 10;
+ break;
+ case MAP_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1;
+ break;
+ case MAP_POINT:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 72;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 72;
+ break;
+ case MAP_TWIP:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1440;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1440;
+ break;
+ case MAP_PIXEL:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = nDPIX;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = nDPIY;
+ break;
+ case MAP_SYSFONT:
+ case MAP_APPFONT:
+ case MAP_REALAPPFONT:
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maGDIData.mnAppFontX )
+ {
+ WorkWindow* pWin = new WorkWindow( NULL, 0 );
+ delete pWin;
+ }
+ if ( rMapMode.GetMapUnit() == MAP_REALAPPFONT )
+ rMapRes.mnMapScNumX = pSVData->maGDIData.mnRealAppFontX;
+ else
+ rMapRes.mnMapScNumX = pSVData->maGDIData.mnAppFontX;
+ rMapRes.mnMapScDenomX = nDPIX * 40;
+ rMapRes.mnMapScNumY = pSVData->maGDIData.mnAppFontY;;
+ rMapRes.mnMapScDenomY = nDPIY * 80;
+ }
+ break;
+ }
+
+ Fraction aScaleX = rMapMode.GetScaleX();
+ Fraction aScaleY = rMapMode.GetScaleY();
+
+ // Offset laut MapMode setzen
+ Point aOrigin = rMapMode.GetOrigin();
+ if ( rMapMode.GetMapUnit() != MAP_RELATIVE )
+ {
+ rMapRes.mnMapOfsX = aOrigin.X();
+ rMapRes.mnMapOfsY = aOrigin.Y();
+ }
+ else
+ {
+ BigInt aX( rMapRes.mnMapOfsX );
+ aX *= BigInt( aScaleX.GetDenominator() );
+ if ( rMapRes.mnMapOfsX >= 0 )
+ {
+ if ( aScaleX.GetNumerator() >= 0 )
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ else
+ aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
+ }
+ else
+ {
+ if ( aScaleX.GetNumerator() >= 0 )
+ aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
+ else
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ }
+ aX /= BigInt( aScaleX.GetNumerator() );
+ rMapRes.mnMapOfsX = (long)aX + aOrigin.X();
+ BigInt aY( rMapRes.mnMapOfsY );
+ aY *= BigInt( aScaleY.GetDenominator() );
+ if( rMapRes.mnMapOfsY >= 0 )
+ {
+ if ( aScaleY.GetNumerator() >= 0 )
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ else
+ aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
+ }
+ else
+ {
+ if ( aScaleY.GetNumerator() >= 0 )
+ aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
+ else
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ }
+ aY /= BigInt( aScaleY.GetNumerator() );
+ rMapRes.mnMapOfsY = (long)aY + aOrigin.Y();
+ }
+
+ // Scaling Faktor laut MapMode einberechnen
+ // aTemp? = rMapRes.mnMapSc? * aScale?
+ Fraction aTempX = ImplMakeFraction( rMapRes.mnMapScNumX,
+ aScaleX.GetNumerator(),
+ rMapRes.mnMapScDenomX,
+ aScaleX.GetDenominator() );
+ Fraction aTempY = ImplMakeFraction( rMapRes.mnMapScNumY,
+ aScaleY.GetNumerator(),
+ rMapRes.mnMapScDenomY,
+ aScaleY.GetDenominator() );
+ rMapRes.mnMapScNumX = aTempX.GetNumerator();
+ rMapRes.mnMapScDenomX = aTempX.GetDenominator();
+ rMapRes.mnMapScNumY = aTempY.GetNumerator();
+ rMapRes.mnMapScDenomY = aTempY.GetDenominator();
+
+ // hack: 0/n ungef"ahr 1/max
+ if ( !rMapRes.mnMapScNumX )
+ {
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = LONG_MAX;
+ }
+ if ( !rMapRes.mnMapScNumY )
+ {
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = LONG_MAX;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplCalcMapResolution( const MapMode& rMapMode,
+ long nDPIX, long nDPIY,
+ ImplMapRes& rMapRes,
+ ImplThresholdRes& rThresRes )
+{
+ ImplCalcMapResolution( rMapMode, nDPIX, nDPIY, rMapRes );
+ ImplCalcBigIntThreshold( nDPIX, nDPIY, rMapRes, rThresRes );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetMapMode()
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaMapModeAction( MapMode() ) );
+
+ if ( mbMap || !maMapMode.IsDefault() )
+ {
+ mbMap = FALSE;
+ maMapMode = MapMode();
+
+ // create new objects (clip region werden nicht neu skaliert)
+ mbNewFont = TRUE;
+ mbInitFont = TRUE;
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ if ( ((Window*)this)->mpCursor )
+ ((Window*)this)->mpCursor->ImplNew();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetMapMode( const MapMode& rNewMapMode )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRelMap = (rNewMapMode.GetMapUnit() == MAP_RELATIVE);
+
+ if ( mpMetaFile )
+ {
+ mpMetaFile->AddAction( new MetaMapModeAction( rNewMapMode ) );
+#ifdef DBG_UTIL
+ if ( GetOutDevType() != OUTDEV_PRINTER )
+ DBG_ASSERTWARNING( bRelMap, "Please record only relative MapModes!" );
+#endif
+ }
+
+ // Ist der MapMode der gleiche wie vorher, dann mache nichts
+ if ( maMapMode == rNewMapMode )
+ return;
+
+ // Ist Default-MapMode, dann bereche nichts
+ BOOL bOldMap = mbMap;
+ mbMap = !rNewMapMode.IsDefault();
+ if ( mbMap )
+ {
+ // Falls nur der Orign umgesetzt wird, dann scaliere nichts neu
+ if ( (rNewMapMode.GetMapUnit() == maMapMode.GetMapUnit()) &&
+ (rNewMapMode.GetScaleX() == maMapMode.GetScaleX()) &&
+ (rNewMapMode.GetScaleY() == maMapMode.GetScaleY()) &&
+ (bOldMap == mbMap) )
+ {
+ // Offset setzen
+ Point aOrigin = rNewMapMode.GetOrigin();
+ maMapRes.mnMapOfsX = aOrigin.X();
+ maMapRes.mnMapOfsY = aOrigin.Y();
+ maMapMode = rNewMapMode;
+ return;
+ }
+ if ( !bOldMap && bRelMap )
+ {
+ maMapRes.mnMapScNumX = 1;
+ maMapRes.mnMapScNumY = 1;
+ maMapRes.mnMapScDenomX = mnDPIX;
+ maMapRes.mnMapScDenomY = mnDPIY;
+ maMapRes.mnMapOfsX = 0;
+ maMapRes.mnMapOfsY = 0;
+ }
+
+ // Neue MapMode-Aufloesung berechnen
+ ImplCalcMapResolution( rNewMapMode, mnDPIX, mnDPIY, maMapRes, maThresRes );
+ }
+
+ // Neuen MapMode setzen
+ if ( bRelMap )
+ {
+ Point aOrigin( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY );
+ // aScale? = maMapMode.GetScale?() * rNewMapMode.GetScale?()
+ Fraction aScaleX = ImplMakeFraction( maMapMode.GetScaleX().GetNumerator(),
+ rNewMapMode.GetScaleX().GetNumerator(),
+ maMapMode.GetScaleX().GetDenominator(),
+ rNewMapMode.GetScaleX().GetDenominator() );
+ Fraction aScaleY = ImplMakeFraction( maMapMode.GetScaleY().GetNumerator(),
+ rNewMapMode.GetScaleY().GetNumerator(),
+ maMapMode.GetScaleY().GetDenominator(),
+ rNewMapMode.GetScaleY().GetDenominator() );
+ maMapMode.SetOrigin( aOrigin );
+ maMapMode.SetScaleX( aScaleX );
+ maMapMode.SetScaleY( aScaleY );
+ }
+ else
+ maMapMode = rNewMapMode;
+
+ // create new objects (clip region werden nicht neu skaliert)
+ mbNewFont = TRUE;
+ mbInitFont = TRUE;
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ if ( ((Window*)this)->mpCursor )
+ ((Window*)this)->mpCursor->ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRelativeMapMode( const MapMode& rNewMapMode )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist der MapMode der gleiche wie vorher, dann mache nichts
+ if ( maMapMode == rNewMapMode )
+ return;
+
+ MapUnit eOld = maMapMode.GetMapUnit();
+ MapUnit eNew = rNewMapMode.GetMapUnit();
+
+ // a?F = rNewMapMode.GetScale?() / maMapMode.GetScale?()
+ Fraction aXF = ImplMakeFraction( rNewMapMode.GetScaleX().GetNumerator(),
+ maMapMode.GetScaleX().GetDenominator(),
+ rNewMapMode.GetScaleX().GetDenominator(),
+ maMapMode.GetScaleX().GetNumerator() );
+ Fraction aYF = ImplMakeFraction( rNewMapMode.GetScaleY().GetNumerator(),
+ maMapMode.GetScaleY().GetDenominator(),
+ rNewMapMode.GetScaleY().GetDenominator(),
+ maMapMode.GetScaleY().GetNumerator() );
+
+ Point aPt( LogicToLogic( Point(), NULL, &rNewMapMode ) );
+ if ( eNew != eOld )
+ {
+ if ( eOld > MAP_PIXEL )
+ {
+ DBG_ERRORFILE( "Not implemented MapUnit" )
+ }
+ else if ( eNew > MAP_PIXEL )
+ {
+ DBG_ERRORFILE( "Not implemented MapUnit" )
+ }
+ else
+ {
+ Fraction aF( aImplNumeratorAry[eNew] * aImplDenominatorAry[eOld],
+ aImplNumeratorAry[eOld] * aImplDenominatorAry[eNew] );
+
+ // a?F = a?F * aF
+ aXF = ImplMakeFraction( aXF.GetNumerator(), aF.GetNumerator(),
+ aXF.GetDenominator(), aF.GetDenominator() );
+ aYF = ImplMakeFraction( aYF.GetNumerator(), aF.GetNumerator(),
+ aYF.GetDenominator(), aF.GetDenominator() );
+ if ( eOld == MAP_PIXEL )
+ {
+ aXF *= Fraction( mnDPIX, 1 );
+ aYF *= Fraction( mnDPIY, 1 );
+ }
+ else if ( eNew == MAP_PIXEL )
+ {
+ aXF *= Fraction( 1, mnDPIX );
+ aYF *= Fraction( 1, mnDPIY );
+ }
+ }
+ }
+
+ MapMode aNewMapMode( MAP_RELATIVE, Point( -aPt.X(), -aPt.Y() ), aXF, aYF );
+ SetMapMode( aNewMapMode );
+
+ if ( eNew != eOld )
+ maMapMode = rNewMapMode;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplLogicToPixel( long n, long nDPI, long nMapNum, long nMapDenom,
+ long nThres )
+{
+ if ( Abs( n ) < nThres )
+ {
+ n *= nDPI * nMapNum;
+ n += n >= 0 ? nMapDenom/2 : -((nMapDenom-1)/2);
+ return (n / nMapDenom);
+ }
+ else
+ {
+ BigInt aTemp( n );
+ aTemp *= BigInt( nDPI );
+ aTemp *= BigInt( nMapNum );
+
+ if ( aTemp.IsNeg() )
+ {
+ BigInt aMapScDenom2( (nMapDenom-1)/2 );
+ aTemp -= aMapScDenom2;
+ }
+ else
+ {
+ BigInt aMapScDenom2( nMapDenom/2 );
+ aTemp += aMapScDenom2;
+ }
+
+ aTemp /= BigInt( nMapDenom );
+ return (long)aTemp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplPixelToLogic( long n, long nDPI, long nMapNum, long nMapDenom,
+ long nThres )
+{
+ if ( Abs( n ) < nThres )
+ {
+ long nDenom = nDPI * nMapNum;
+ long nNum = n * nMapDenom;
+ if ( nNum >= 0 )
+ {
+ if ( nDenom >= 0 )
+ nNum += nDenom/2;
+ else
+ nNum -= (nDenom+1)/2;
+ }
+ else
+ {
+ if ( nDenom >= 0 )
+ nNum -= (nDenom-1)/2;
+ else
+ nNum += nDenom/2;
+ }
+ return (nNum / nDenom);
+ }
+ else
+ {
+ BigInt aDenom( nDPI );
+ aDenom *= BigInt( nMapNum );
+
+ BigInt aNum( n );
+ aNum *= BigInt( nMapDenom );
+
+ BigInt aDenom2( aDenom );
+ if ( aNum.IsNeg() )
+ {
+ if ( aDenom.IsNeg() )
+ {
+ aDenom2 /= BigInt(2);
+ aNum += aDenom2;
+ }
+ else
+ {
+ aDenom2 -= 1;
+ aDenom2 /= BigInt(2);
+ aNum -= aDenom2;
+ }
+ }
+ else
+ {
+ if ( aDenom.IsNeg() )
+ {
+ aDenom2 += 1;
+ aDenom2 /= BigInt(2);
+ aNum -= aDenom2;
+ }
+ else
+ {
+ aDenom2 /= BigInt(2);
+ aNum += aDenom2;
+ }
+ }
+
+ aNum /= aDenom;
+ return (long)aNum;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicXToDevicePixel( long nX ) const
+{
+ if ( !mbMap )
+ return nX+mnOutOffX;
+
+ return ImplLogicToPixel( nX + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicYToDevicePixel( long nY ) const
+{
+ if ( !mbMap )
+ return nY+mnOutOffY;
+
+ return ImplLogicToPixel( nY + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicWidthToDevicePixel( long nWidth ) const
+{
+ if ( !mbMap )
+ return nWidth;
+
+ return ImplLogicToPixel( nWidth, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicHeightToDevicePixel( long nHeight ) const
+{
+ if ( !mbMap )
+ return nHeight;
+
+ return ImplLogicToPixel( nHeight, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplDevicePixelToLogicWidth( long nWidth ) const
+{
+ if ( !mbMap )
+ return nWidth;
+
+ return ImplPixelToLogic( nWidth, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplDevicePixelToLogicHeight( long nHeight ) const
+{
+ if ( !mbMap )
+ return nHeight;
+
+ return ImplPixelToLogic( nHeight, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY );
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::ImplLogicToDevicePixel( const Point& rLogicPt ) const
+{
+ if ( !mbMap )
+ return Point( rLogicPt.X()+mnOutOffX, rLogicPt.Y()+mnOutOffY );
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::ImplLogicToDevicePixel( const Size& rLogicSize ) const
+{
+ if ( !mbMap )
+ return rLogicSize;
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplLogicToDevicePixel( const Rectangle& rLogicRect ) const
+{
+ if ( rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ if ( !mbMap )
+ {
+ return Rectangle( rLogicRect.Left()+mnOutOffX, rLogicRect.Top()+mnOutOffY,
+ rLogicRect.Right()+mnOutOffX, rLogicRect.Bottom()+mnOutOffY );
+ }
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicRect.Top()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY,
+ ImplLogicToPixel( rLogicRect.Right()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicRect.Bottom()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::ImplLogicToDevicePixel( const Polygon& rLogicPoly ) const
+{
+ if ( !mbMap && !mnOutOffX && !mnOutOffY )
+ return rLogicPoly;
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ if ( mbMap )
+ {
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX;
+ pPt->Y() = ImplLogicToPixel( pPt->Y()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY;
+ }
+ }
+ else
+ {
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() += mnOutOffX;
+ pPt->Y() += mnOutOffY;
+ }
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::ImplLogicToDevicePixel( const PolyPolygon& rLogicPolyPoly ) const
+{
+ if ( !mbMap && !mnOutOffX && !mnOutOffY )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = ImplLogicToDevicePixel( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo OutputDevice::ImplLogicToDevicePixel( const LineInfo& rLineInfo ) const
+{
+ LineInfo aInfo( rLineInfo );
+
+ if( aInfo.GetStyle() == LINE_DASH )
+ {
+ if( aInfo.GetDotCount() && aInfo.GetDotLen() )
+ aInfo.SetDotLen( Max( ImplLogicWidthToDevicePixel( aInfo.GetDotLen() ), 1L ) );
+ else
+ aInfo.SetDotCount( 0 );
+
+ if( aInfo.GetDashCount() && aInfo.GetDashLen() )
+ aInfo.SetDashLen( Max( ImplLogicWidthToDevicePixel( aInfo.GetDashLen() ), 1L ) );
+ else
+ aInfo.SetDashCount( 0 );
+
+ aInfo.SetDistance( ImplLogicWidthToDevicePixel( aInfo.GetDistance() ) );
+
+ if( ( !aInfo.GetDashCount() && !aInfo.GetDotCount() ) || !aInfo.GetDistance() )
+ aInfo.SetStyle( LINE_SOLID );
+ }
+
+ aInfo.SetWidth( ImplLogicWidthToDevicePixel( aInfo.GetWidth() ) );
+
+ return aInfo;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplDevicePixelToLogic( const Rectangle& rPixelRect ) const
+{
+ if ( rPixelRect.IsEmpty() )
+ return rPixelRect;
+
+ if ( !mbMap )
+ {
+ return Rectangle( rPixelRect.Left()-mnOutOffX, rPixelRect.Top()-mnOutOffY,
+ rPixelRect.Right()-mnOutOffX, rPixelRect.Bottom()-mnOutOffY );
+ }
+
+ return Rectangle( ImplPixelToLogic( rPixelRect.Left()-mnOutOffX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rPixelRect.Top()-mnOutOffY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY,
+ ImplPixelToLogic( rPixelRect.Right()-mnOutOffX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rPixelRect.Bottom()-mnOutOffY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::ImplPixelToDevicePixel( const Region& rRegion ) const
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ if ( !mnOutOffX && !mnOutOffY )
+ return rRegion;
+
+ Region aRegion( rRegion );
+ aRegion.Move( mnOutOffX, mnOutOffY );
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToPixel( const Point& rLogicPt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rLogicPt;
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToPixel( const Size& rLogicSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rLogicSize;
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToPixel( const Rectangle& rLogicRect ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap || rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Top() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ),
+ ImplLogicToPixel( rLogicRect.Right() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Bottom() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::LogicToPixel( const Polygon& rLogicPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPoly, Polygon, NULL );
+
+ if ( !mbMap )
+ return rLogicPoly;
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX );
+ pPt->Y() = ImplLogicToPixel( pPt->Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY );
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPolyPoly, PolyPolygon, NULL );
+
+ if ( !mbMap )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = LogicToPixel( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::LogicToPixel( const Region& rLogicRegion ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rLogicRegion.GetType();
+
+ if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rLogicRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rLogicRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( LogicToPixel( *pPolyPoly ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rLogicRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( LogicToPixel( aRect ) );
+ bRegionRect = rLogicRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToPixel( const Point& rLogicPt,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPt;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicPt.Y() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToPixel( const Size& rLogicSize,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicSize;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToPixel( const Rectangle& rLogicRect,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() || rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Top() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ),
+ ImplLogicToPixel( rLogicRect.Right() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Bottom() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::LogicToPixel( const Polygon& rLogicPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPoly, Polygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPoly;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX );
+ pPt->Y() = ImplLogicToPixel( pPt->Y() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY );
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = LogicToPixel( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::LogicToPixel( const Region& rLogicRegion,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rLogicRegion.GetType();
+
+ if ( rMapMode.IsDefault() || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rLogicRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rLogicRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if( pPolyPoly )
+ aRegion = Region( LogicToPixel( *pPolyPoly, rMapMode ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rLogicRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( LogicToPixel( aRect, rMapMode ) );
+ bRegionRect = rLogicRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::PixelToLogic( const Point& rDevicePt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rDevicePt;
+
+ return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::PixelToLogic( const Size& rDeviceSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rDeviceSize;
+
+ return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ),
+ ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::PixelToLogic( const Rectangle& rDeviceRect ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap || rDeviceRect.IsEmpty() )
+ return rDeviceRect;
+
+ return Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY,
+ ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::PixelToLogic( const Polygon& rDevicePoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePoly, Polygon, NULL );
+
+ if ( !mbMap )
+ return rDevicePoly;
+
+ USHORT i;
+ USHORT nPoints = rDevicePoly.GetSize();
+ Polygon aPoly( rDevicePoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplPixelToLogic( pPt->X(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX;
+ pPt->Y() = ImplPixelToLogic( pPt->Y(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY;
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePolyPoly, PolyPolygon, NULL );
+
+ if ( !mbMap )
+ return rDevicePolyPoly;
+
+ PolyPolygon aPolyPoly( rDevicePolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = PixelToLogic( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDeviceRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rDeviceRegion.GetType();
+
+ if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rDeviceRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( PixelToLogic( *pPolyPoly ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rDeviceRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( PixelToLogic( aRect ) );
+ bRegionRect = rDeviceRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::PixelToLogic( const Point& rDevicePt,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDevicePt;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::PixelToLogic( const Size& rDeviceSize,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDeviceSize;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ),
+ ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::PixelToLogic( const Rectangle& rDeviceRect,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() || rDeviceRect.IsEmpty() )
+ return rDeviceRect;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY,
+ ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::PixelToLogic( const Polygon& rDevicePoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePoly, Polygon, NULL );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDevicePoly;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ USHORT i;
+ USHORT nPoints = rDevicePoly.GetSize();
+ Polygon aPoly( rDevicePoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplPixelToLogic( pPt->X(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX;
+ pPt->Y() = ImplPixelToLogic( pPt->Y(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY;
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rDevicePolyPoly;
+
+ PolyPolygon aPolyPoly( rDevicePolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = PixelToLogic( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::PixelToLogic( const Region& rDeviceRegion,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDeviceRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rDeviceRegion.GetType();
+
+ if ( rMapMode.IsDefault() || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rDeviceRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( PixelToLogic( *pPolyPoly, rMapMode ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rDeviceRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( PixelToLogic( aRect, rMapMode ) );
+ bRegionRect = rDeviceRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+#define ENTER0( rSource, pMapModeSource, pMapModeDest ) \
+ if ( !pMapModeSource ) \
+ pMapModeSource = &maMapMode; \
+ if ( !pMapModeDest ) \
+ pMapModeDest = &maMapMode; \
+ if ( *pMapModeSource == *pMapModeDest ) \
+ return rSource
+
+// -----------------------------------------------------------------------
+
+#define ENTER1( rSource, pMapModeSource, pMapModeDest ) \
+ ENTER0( rSource, pMapModeSource, pMapModeDest ); \
+ \
+ ImplMapRes aMapResSource; \
+ ImplMapRes aMapResDest; \
+ \
+ if ( !mbMap || pMapModeSource != &maMapMode ) \
+ { \
+ if ( pMapModeSource->GetMapUnit() == MAP_RELATIVE ) \
+ aMapResSource = maMapRes; \
+ ImplCalcMapResolution( *pMapModeSource, \
+ mnDPIX, mnDPIY, aMapResSource ); \
+ } \
+ else \
+ aMapResSource = maMapRes; \
+ if ( !mbMap || pMapModeDest != &maMapMode ) \
+ { \
+ if ( pMapModeDest->GetMapUnit() == MAP_RELATIVE ) \
+ aMapResDest = maMapRes; \
+ ImplCalcMapResolution( *pMapModeDest, \
+ mnDPIX, mnDPIY, aMapResDest ); \
+ } \
+ else \
+ aMapResDest = maMapRes
+
+// -----------------------------------------------------------------------
+
+#define ENTER2( eUnitSource, eUnitDest ) \
+ DBG_ASSERT( eUnitSource != MAP_SYSFONT \
+ && eUnitSource != MAP_APPFONT \
+ && eUnitSource != MAP_RELATIVE, \
+ "Source MapUnit nicht erlaubt" ); \
+ DBG_ASSERT( eUnitDest != MAP_SYSFONT \
+ && eUnitDest != MAP_APPFONT \
+ && eUnitDest != MAP_RELATIVE, \
+ "Destination MapUnit nicht erlaubt" ); \
+ DBG_ASSERTWARNING( eUnitSource != MAP_PIXEL, \
+ "MAP_PIXEL mit 72dpi angenaehert" ); \
+ DBG_ASSERTWARNING( eUnitDest != MAP_PIXEL, \
+ "MAP_PIXEL mit 72dpi angenaehert" )
+
+// -----------------------------------------------------------------------
+
+#define ENTER3( eUnitSource, eUnitDest ) \
+ long nNumerator = aImplNumeratorAry[eUnitSource] * \
+ aImplDenominatorAry[eUnitDest]; \
+ long nDenominator = aImplNumeratorAry[eUnitDest] * \
+ aImplDenominatorAry[eUnitSource]; \
+ if ( eUnitSource == MAP_PIXEL ) \
+ nDenominator *= 72; \
+ else if( eUnitDest == MAP_PIXEL ) \
+ nNumerator *= 72
+
+// -----------------------------------------------------------------------
+
+#define ENTER4( rMapModeSource, rMapModeDest ) \
+ ImplMapRes aMapResSource; \
+ ImplMapRes aMapResDest; \
+ \
+ ImplCalcMapResolution( rMapModeSource, 72, 72, aMapResSource ); \
+ ImplCalcMapResolution( rMapModeDest, 72, 72, aMapResDest )
+
+// -----------------------------------------------------------------------
+
+// return (n1 * n2 * n3) / (n4 * n5)
+static long fn5( const long n1,
+ const long n2,
+ const long n3,
+ const long n4,
+ const long n5 )
+{
+ if ( n1 == 0 || n2 == 0 || n3 == 0 || n4 == 0 || n5 == 0 )
+ return 0;
+ if ( LONG_MAX / Abs(n2) < Abs(n3) )
+ {
+ // a6 wird "ubersprungen
+ BigInt a7 = n2;
+ a7 *= n3;
+ a7 *= n1;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ } // of if
+ else
+ {
+ long n8 = n4 * n5;
+
+ if ( a7.IsNeg() )
+ a7 -= n8 / 2;
+ else
+ a7 += n8 / 2;
+
+ a7 /= n8;
+ } // of else
+ return (long)a7;
+ } // of if
+ else
+ {
+ long n6 = n2 * n3;
+
+ if ( LONG_MAX / Abs(n1) < Abs(n6) )
+ {
+ BigInt a7 = n1;
+ a7 *= n6;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ } // of if
+ else
+ {
+ long n8 = n4 * n5;
+
+ if ( a7.IsNeg() )
+ a7 -= n8 / 2;
+ else
+ a7 += n8 / 2;
+
+ a7 /= n8;
+ } // of else
+ return (long)a7;
+ } // of if
+ else
+ {
+ long n7 = n1 * n6;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a7 = n7;
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ return (long)a7;
+ } // of if
+ else
+ {
+ const long n8 = n4 * n5;
+ const long n8_2 = n8 / 2;
+
+ if( n7 < 0 )
+ {
+ if( ( n7 - LONG_MIN ) >= n8_2 )
+ n7 -= n8_2;
+ }
+ else if( ( LONG_MAX - n7 ) >= n8_2 )
+ n7 += n8_2;
+
+ return n7 / n8;
+ } // of else
+ } // of else
+ } // of else
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+// return (n1 * n2) / n3
+static long fn3( const long n1, const long n2, const long n3 )
+{
+ if ( n1 == 0 || n2 == 0 || n3 == 0 )
+ return 0;
+ if ( LONG_MAX / Abs(n1) < Abs(n2) )
+ {
+ BigInt a4 = n1;
+ a4 *= n2;
+
+ if ( a4.IsNeg() )
+ a4 -= n3 / 2;
+ else
+ a4 += n3 / 2;
+
+ a4 /= n3;
+ return (long)a4;
+ } // of if
+ else
+ {
+ long n4 = n1 * n2;
+ const long n3_2 = n3 / 2;
+
+ if( n4 < 0 )
+ {
+ if( ( n4 - LONG_MIN ) >= n3_2 )
+ n4 -= n3_2;
+ }
+ else if( ( LONG_MAX - n4 ) >= n3_2 )
+ n4 += n3_2;
+
+ return n4 / n3;
+ } // of else
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToLogic( const Point& rPtSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rPtSource, pMapModeSource, pMapModeDest );
+
+ return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToLogic( const Size& rSzSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rSzSource, pMapModeSource, pMapModeDest );
+
+ return Size( fn5( rSzSource.Width(),
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
+ fn5( rSzSource.Height(),
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rRectSource, pMapModeSource, pMapModeDest );
+
+ return Rectangle( fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY,
+ fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+long* OutputDevice::LogicToLogic( long* pX, USHORT nCount,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( pX, pMapModeSource, pMapModeDest );
+
+ for( ; nCount; nCount--, pX++ )
+ {
+ *pX = fn5( *pX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToLogic( const Point& rPtSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rPtSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Point( fn3( rPtSource.X(), nNumerator, nDenominator ),
+ fn3( rPtSource.Y(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToLogic( const Size& rSzSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rSzSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Size( fn3( rSzSource.Width(), nNumerator, nDenominator ),
+ fn3( rSzSource.Height(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Size( fn5( rSzSource.Width(),
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
+ fn5( rSzSource.Height(),
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rRectSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Rectangle( fn3( rRectSource.Left(), nNumerator, nDenominator ),
+ fn3( rRectSource.Top(), nNumerator, nDenominator ),
+ fn3( rRectSource.Right(), nNumerator, nDenominator ),
+ fn3( rRectSource.Bottom(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Rectangle( fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY,
+ fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::LogicToLogic( long nLongSource,
+ MapUnit eUnitSource, MapUnit eUnitDest )
+{
+ if ( eUnitSource == eUnitDest )
+ return nLongSource;
+
+ ENTER2( eUnitSource, eUnitDest );
+ ENTER3( eUnitSource, eUnitDest );
+
+ return fn3( nLongSource, nNumerator, nDenominator );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::ImplLogicUnitToPixelX( long nX, MapUnit eUnit )
+{
+ if ( eUnit != MAP_PIXEL )
+ {
+ ImplFrameData* pFrameData = mpFrameData;
+
+ // Map-Einheit verschieden, dann neu berechnen
+ if ( pFrameData->meMapUnit != eUnit )
+ {
+ pFrameData->meMapUnit = eUnit;
+ ImplCalcMapResolution( MapMode( eUnit ), mnDPIX, mnDPIY,
+ pFrameData->maMapUnitRes );
+ }
+
+ // Es wird kein BigInt gebraucht, da diese Funktion nur zur Umrechnung
+ // von Fensterposition benutzt wird
+ nX = nX * mnDPIX * pFrameData->maMapUnitRes.mnMapScNumX;
+ nX += nX >= 0 ? (pFrameData->maMapUnitRes.mnMapScDenomX/2) :
+ -((pFrameData->maMapUnitRes.mnMapScDenomX-1)/2);
+ nX /= pFrameData->maMapUnitRes.mnMapScDenomX;
+ }
+
+ return nX;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::ImplLogicUnitToPixelY( long nY, MapUnit eUnit )
+{
+ if ( eUnit != MAP_PIXEL )
+ {
+ ImplFrameData* pFrameData = mpFrameData;
+
+ // Map-Einheit verschieden, dann neu berechnen
+ if ( pFrameData->meMapUnit != eUnit )
+ {
+ pFrameData->meMapUnit = eUnit;
+ ImplCalcMapResolution( MapMode( eUnit ), mnDPIX, mnDPIY,
+ pFrameData->maMapUnitRes );
+ }
+
+ // Es wird kein BigInt gebraucht, da diese Funktion nur zur Umrechnung
+ // von Fensterposition benutzt wird
+ nY = nY * mnDPIY * pFrameData->maMapUnitRes.mnMapScNumY;
+ nY += nY >= 0 ? (pFrameData->maMapUnitRes.mnMapScDenomY/2) :
+ -((pFrameData->maMapUnitRes.mnMapScDenomY-1)/2);
+ nY /= pFrameData->maMapUnitRes.mnMapScDenomY;
+ }
+
+ return nY;
+}
diff --git a/vcl/source/gdi/polyscan.cxx b/vcl/source/gdi/polyscan.cxx
new file mode 100644
index 000000000000..cb9714d51765
--- /dev/null
+++ b/vcl/source/gdi/polyscan.cxx
@@ -0,0 +1,389 @@
+/*************************************************************************
+ *
+ * $RCSfile: polyscan.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <tools/new.hxx>
+#include "salbtype.hxx"
+#include "poly.hxx"
+#include "polyscan.hxx"
+
+// ----------------
+// - PolyScanline -
+// ----------------
+
+PolyScanline::PolyScanline() :
+ mpFirst ( NULL ),
+ mpLast ( NULL ),
+ mpAct ( NULL ),
+ mnLeft ( 0L ),
+ mnRight ( 0L )
+{
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanline::~PolyScanline()
+{
+ ImplDelete();
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::ImplDelete()
+{
+ ScanlinePoint* pAct = mpFirst;
+
+ while( pAct )
+ {
+ ScanlinePoint* pNext = pAct->mpNext;
+ delete pAct;
+ pAct = pNext;
+ }
+
+ mnLeft = mnRight = 0L;
+ mpFirst = mpAct = mpLast = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::Insert( long nX )
+{
+ // first point to insert?
+ if( !mpFirst )
+ mpLast = mpFirst = new ScanlinePoint( mnLeft = mnRight = nX, NULL );
+ else
+ {
+ // insert at the beginning of the scanline
+ if( nX <= mpFirst->mnX )
+ mpFirst = new ScanlinePoint( mnLeft = nX, mpFirst );
+ else if( nX >= mnRight )
+ mpLast = mpLast->mpNext = new ScanlinePoint( mnRight = nX, NULL );
+ else
+ {
+ ScanlinePoint* pLast = mpFirst;
+ ScanlinePoint* pAct = mpFirst->mpNext;
+
+ while( pAct )
+ {
+ // insert in the midlle of the scanline?
+ if( nX <= pAct->mnX )
+ {
+ pLast->mpNext = new ScanlinePoint( nX, pAct );
+ break;
+ }
+
+ pLast = pAct;
+ pAct = pAct->mpNext;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::Set( long nStart, long nEnd )
+{
+ if( mpFirst )
+ ImplDelete();
+
+ if( nStart <= nEnd )
+ mpFirst = new ScanlinePoint( mnLeft = nStart, mpLast = new ScanlinePoint( mnRight = nEnd, NULL ) );
+ else
+ mpFirst = new ScanlinePoint( mnLeft = nEnd, mpLast = new ScanlinePoint( mnRight = nStart, NULL ) );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL PolyScanline::GetFirstSegment( PolyScanSegment& rSegment )
+{
+ BOOL bRet = GetFirstX( rSegment.mnStart );
+
+ if( bRet && !GetNextX( rSegment.mnEnd ) )
+ rSegment.mnEnd = rSegment.mnStart;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL PolyScanline::GetNextSegment( PolyScanSegment& rSegment )
+{
+ BOOL bRet = GetNextX( rSegment.mnStart );
+
+ if( bRet && !GetNextX( rSegment.mnEnd ) )
+ rSegment.mnEnd = rSegment.mnStart;
+
+ return bRet;
+}
+
+// ---------------
+// - PolyScanner -
+// ---------------
+
+PolyScanner::PolyScanner( const Rectangle& rRect )
+{
+ if( !rRect.IsEmpty() )
+ {
+ Rectangle aRect( rRect );
+ ULONG nHeight;
+
+ aRect.Justify();
+ mnLeft = aRect.Left();
+ mnTop = aRect.Top();
+ mnRight = aRect.Right();
+ mnBottom = aRect.Bottom();
+ mpArray = new PolyScanline[ nHeight = Height() ];
+
+ for( ULONG i = 0UL; i < nHeight; i++ )
+ mpArray[ i ].Set( mnLeft, mnRight );
+ }
+ else
+ {
+ mnLeft = mnTop = mnRight = mnBottom = 0L;
+ mpArray = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::PolyScanner( const Polygon& rPoly )
+{
+ const long nCount = rPoly.GetSize();
+
+ if( nCount )
+ {
+ long nLast = nCount - 1;
+ Point aFirst( rPoly[ 0 ] );
+ Point aLast( rPoly[ (USHORT) nLast ] );
+
+ while( nLast && ( aLast == aFirst ) )
+ aLast = rPoly[ (USHORT) --nLast ];
+
+ if( !nLast )
+ {
+ aLast = rPoly[ 0 ];
+ mnLeft = mnRight = aLast.X();
+ mnTop = mnBottom = aLast.Y();
+ mpArray = new PolyScanline[ 1UL ];
+ mpArray[ 0 ].Set( mnLeft, mnRight );
+ }
+ else
+ {
+ const Rectangle aRect( rPoly.GetBoundRect() );
+ ULONG nHeight;
+
+ mnLeft = aRect.Left();
+ mnTop = aRect.Top();
+ mnRight = aRect.Right();
+ mnBottom = aRect.Bottom();
+ aLast = aFirst;
+ mpArray = new PolyScanline[ nHeight = Height() ];
+
+ for( long i = 1L; i <= nLast; i++ )
+ {
+ const Point& rPt = rPoly[ (USHORT) i ];
+
+ if( rPt != aLast )
+ {
+ InsertLine( aLast, rPt );
+ aLast = rPt;
+ }
+ }
+
+ InsertLine( aLast, aFirst );
+ }
+ }
+ else
+ mpArray = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::PolyScanner( const PolyPolygon& rPolyPoly )
+{
+ mpArray = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::~PolyScanner()
+{
+ delete[] mpArray;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanline* PolyScanner::operator[]( ULONG nPos ) const
+{
+ DBG_ASSERT( nPos < Count(), "nPos out of range!" );
+ return( mpArray ? ( mpArray + nPos ) : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanner::InsertLine( const Point& rStart, const Point& rEnd )
+{
+ long nX, nY;
+
+ if( rStart.Y() == rEnd.Y() )
+ mpArray[ rStart.Y() - mnTop ].Insert( rStart.X() );
+ else if( rStart.X() == rEnd.X() )
+ {
+ // vertical line
+ const long nEndY = rEnd.Y();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if( nEndY > nY )
+ while( nY < nEndY )
+ mpArray[ nY++ - mnTop ].Insert( nX );
+ else
+ while( nY > nEndY )
+ mpArray[ nY-- - mnTop ].Insert( nX );
+ }
+ else
+ {
+ const long nDX = labs( rEnd.X() - rStart.X() );
+ const long nDY = labs( rEnd.Y() - rStart.Y() );
+ const long nStartX = rStart.X();
+ const long nStartY = rStart.Y();
+ const long nEndX = rEnd.X();
+ const long nEndY = rEnd.Y();
+ const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
+ const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
+ long nLastX = nStartX;
+ long nLastY = nStartY;
+ BOOL bLast = FALSE;
+
+ mpArray[ nStartY - mnTop ].Insert( nStartX );
+
+ if( nDX >= nDY )
+ {
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+
+ for( nX = nStartX, nY = nLastY = nStartY; nX != nEndX; )
+ {
+ if( nY != nLastY )
+ {
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+
+ mpArray[ nY - mnTop ].Insert( nX );
+ bLast = FALSE;
+ }
+ else
+ bLast = TRUE;
+
+ nLastX = nX;
+ nLastY = nY;
+
+ if( nD < 0L )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+ nY += nYInc;
+ }
+
+ nX += nXInc;
+ }
+ }
+ else
+ {
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+
+ for( nX = nStartX, nY = nStartY; nY != nEndY; )
+ {
+ if( nY != nLastY )
+ {
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+
+ mpArray[ nY - mnTop ].Insert( nX );
+ bLast = FALSE;
+ }
+ else
+ bLast = TRUE;
+
+ nLastX = nX;
+ nLastY = nY;
+
+ if( nD < 0L )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+ nX += nXInc;
+ }
+
+ nY += nYInc;
+ }
+ }
+
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+ }
+}
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
new file mode 100644
index 000000000000..84c54f0cc5b2
--- /dev/null
+++ b/vcl/source/gdi/print.cxx
@@ -0,0 +1,1979 @@
+/*************************************************************************
+ *
+ * $RCSfile: print.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_PRINT_CXX
+#define _SPOOLPRINTER_EXT
+#define _RMPRINTER_EXT
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#ifndef REMOTE_APPSERVER
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALPTYPE_HXX
+#include <salptype.hxx>
+#endif
+#ifndef _SV_SALPRN_HXX
+#include <salprn.hxx>
+#endif
+
+#else
+
+#include "rmoutdev.hxx"
+#include "rmprint.hxx"
+#include "rmwindow.hxx"
+#include "rvp.hxx"
+#include <vos/mutex.hxx>
+
+using namespace ::com::sun::star::uno;
+
+struct SalPrinterQueueInfo
+{
+ XubString maPrinterName;
+ XubString maDriver;
+ XubString maLocation;
+ XubString maComment;
+ ULONG mnStatus;
+ ULONG mnJobs;
+ void* mpSysData;
+
+ SalPrinterQueueInfo();
+ ~SalPrinterQueueInfo();
+};
+
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_JOBSET_H
+#include <jobset.h>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_IMPPRN_HXX
+#include <impprn.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+
+int nImplSysDialog = 0;
+
+#define PRINTERSEQ_GET( _def_Seq, _def_Obj ) \
+{ \
+ SvMemoryStream* _def_pStm = new SvMemoryStream( (char*)_def_Seq.getConstArray(), _def_Seq.getLength(), STREAM_READ ); \
+ _def_pStm->SetCompressMode( COMPRESSMODE_FULL ); \
+ *_def_pStm >> _def_Obj; \
+ delete _def_pStm; \
+}
+
+#define PRINTERSEQ_SET( _def_Obj, _def_Seq, _def_Type ) \
+{ \
+ SvMemoryStream* _def_pStm = new SvMemoryStream( 8192, 8192 ); \
+ _def_pStm->SetCompressMode( COMPRESSMODE_FULL ); \
+ *_def_pStm << _def_Obj; \
+ _def_Seq = _def_Type( (sal_Int8*) (_def_pStm)->GetData(), (_def_pStm)->Tell() ); \
+ delete _def_pStm; \
+}
+
+// =======================================================================
+
+#define PAPER_SLOPPY 20
+#define PAPER_COUNT 9
+
+static long ImplPaperFormats[PAPER_COUNT*2] =
+{
+ 29700, 42000, // A3
+ 21000, 29700, // A4
+ 14800, 21000, // A5
+ 25000, 35300, // B4
+ 17600, 25000, // B5
+ 21600, 27900, // Letter
+ 21600, 35600, // Legal
+ 27900, 43100, // Tabloid
+ 0, 0 // USER
+};
+
+// =======================================================================
+
+Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
+{
+ USHORT i;
+
+ for( i = 0; i < PAPER_COUNT; i++ )
+ {
+ if ( (ImplPaperFormats[i*2] == nWidth100thMM) &&
+ (ImplPaperFormats[i*2+1] == nHeight100thMM) )
+ return (Paper)i;
+ }
+
+ for( i = 0; i < PAPER_COUNT; i++ )
+ {
+ if ( (Abs( ImplPaperFormats[i*2]-nWidth100thMM ) < PAPER_SLOPPY) &&
+ (Abs( ImplPaperFormats[i*2+1]-nHeight100thMM ) < PAPER_SLOPPY) )
+ return (Paper)i;
+ }
+
+ return PAPER_USER;
+}
+
+// =======================================================================
+
+void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
+{
+ const ImplJobSetup* pConstData = rJobSetup.ImplGetConstData();
+
+ if ( !pConstData->mnPaperWidth || !pConstData->mnPaperHeight )
+ {
+ if ( pConstData->mePaperFormat != PAPER_USER )
+ {
+ ImplJobSetup* pData = rJobSetup.ImplGetData();
+ pData->mnPaperWidth = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2];
+ pData->mnPaperHeight = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2+1];
+ }
+ }
+ else if ( pConstData->mePaperFormat == PAPER_USER )
+ {
+ Paper ePaper = ImplGetPaperFormat( pConstData->mnPaperWidth, pConstData->mnPaperHeight );
+ if ( ePaper != PAPER_USER )
+ rJobSetup.ImplGetData()->mePaperFormat = ePaper;
+ }
+}
+
+// =======================================================================
+
+QueueInfo::QueueInfo()
+{
+ mnStatus = 0;
+ mnJobs = 0;
+}
+
+// -----------------------------------------------------------------------
+
+QueueInfo::QueueInfo( const QueueInfo& rInfo ) :
+ maPrinterName( rInfo.maPrinterName ),
+ maDriver( rInfo.maDriver ),
+ maLocation( rInfo.maLocation ),
+ maComment( rInfo.maComment ),
+ mnStatus( rInfo.mnStatus ),
+ mnJobs( rInfo.mnJobs )
+{
+}
+
+// -----------------------------------------------------------------------
+
+QueueInfo::~QueueInfo()
+{
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& QueueInfo::operator==( const QueueInfo& rInfo )
+{
+ maPrinterName = rInfo.maPrinterName;
+ maDriver = rInfo.maDriver;
+ maLocation = rInfo.maLocation;
+ maComment = rInfo.maComment;
+ mnStatus = rInfo.mnStatus;
+ mnJobs = rInfo.mnJobs;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const QueueInfo& rInfo )
+{
+ VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
+
+ rOStream.WriteByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
+ rOStream << rInfo.mnStatus;
+ rOStream << rInfo.mnJobs;
+
+ return rOStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, QueueInfo& rInfo )
+{
+ VersionCompat aCompat( rIStream, STREAM_READ );
+
+ rIStream.ReadByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
+ rIStream >> rInfo.mnStatus;
+ rIStream >> rInfo.mnJobs;
+
+ return rIStream;
+}
+
+// =======================================================================
+
+SalPrinterQueueInfo::SalPrinterQueueInfo()
+{
+ mnStatus = 0;
+ mnJobs = QUEUE_JOBS_DONTKNOW;
+ mpSysData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinterQueueInfo::~SalPrinterQueueInfo()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplPrnQueueList::Add( SalPrinterQueueInfo* pData )
+{
+ ImplPrnQueueData* pInfo = new ImplPrnQueueData;
+ pInfo->mpQueueInfo = NULL;
+ pInfo->mpSalQueueInfo = pData;
+ List::Insert( (void*)pInfo, LIST_APPEND );
+}
+
+// =======================================================================
+
+static void ImplInitPrnQueueList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pSVData->maGDIData.mpPrinterQueueList = new ImplPrnQueueList;
+
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->GetPrinterQueueInfo( pSVData->maGDIData.mpPrinterQueueList );
+#else
+ if ( pSVData->mpRemotePrinterList && pSVData->mpRemotePrinterList->GetPrinterCount() )
+ {
+ const ULONG nCount = pSVData->mpRemotePrinterList->GetPrinterCount();
+ for( ULONG i = 0; i < nCount; i++ )
+ {
+ NMSP_CLIENT::RmQueueInfo aRmQInfo;
+ QueueInfo aQInfo;
+ SalPrinterQueueInfo* pNewInfo = new SalPrinterQueueInfo;
+
+ RemotePrinterInfo* pPrinterInfo = pSVData->mpRemotePrinterList->GetPrinter( i );
+ REF( NMSP_CLIENT::XRmPrinterEnvironment ) xPrinterEnv( pSVData->mpRemotePrinterList->GetPrinterEnv( pPrinterInfo->aServerName ) );
+
+ if ( xPrinterEnv.is() && xPrinterEnv->GetPrinterInfo(
+ pPrinterInfo->aPrinterName.GetBuffer(), aRmQInfo ) )
+ {
+ PRINTERSEQ_GET( aRmQInfo, aQInfo );
+ pNewInfo->maPrinterName = pPrinterInfo->GetFullName();
+ pNewInfo->maDriver = aQInfo.GetDriver();
+ pNewInfo->maLocation = aQInfo.GetLocation();
+ pNewInfo->maComment = aQInfo.GetComment();
+ pNewInfo->mnStatus = aQInfo.GetStatus();
+ pNewInfo->mnJobs = aQInfo.GetJobs();
+ pNewInfo->mpSysData = NULL;
+ pSVData->maGDIData.mpPrinterQueueList->Add( pNewInfo );
+ }
+ }
+ }
+ if ( !pSVData->maGDIData.mpPrinterQueueList->Count() )
+ {
+ SalPrinterQueueInfo* pNewInfo = new SalPrinterQueueInfo;
+ pNewInfo->maPrinterName = String::CreateFromAscii("No Printer");
+ pNewInfo->mpSysData = NULL;
+ pSVData->maGDIData.mpPrinterQueueList->Add( pNewInfo );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDeletePrnQueueList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList;
+
+ if ( pPrnList )
+ {
+ ImplPrnQueueData* pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpQueueInfo )
+ delete pInfo->mpQueueInfo;
+
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->DeletePrinterQueueInfo( pInfo->mpSalQueueInfo );
+#else
+ delete pInfo->mpSalQueueInfo;
+#endif
+
+ delete pInfo;
+ pInfo = pPrnList->Next();
+ }
+
+ delete pPrnList;
+ pSVData->maGDIData.mpPrinterQueueList = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetQueueCount()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ return (USHORT)(pSVData->maGDIData.mpPrinterQueueList->Count());
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& Printer::GetQueueInfo( USHORT nQueue )
+{
+ return GetQueueInfo( nQueue, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& Printer::GetQueueInfo( USHORT nQueue, BOOL bStatus )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ DBG_ASSERT( nQueue < pSVData->maGDIData.mpPrinterQueueList->Count(),
+ "Printer::GetQueueInfo() - nQueue > QueueCount" );
+
+ ImplPrnQueueData* pInfo = pSVData->maGDIData.mpPrinterQueueList->Get( nQueue );
+
+#ifndef REMOTE_APPSERVER
+ if ( bStatus )
+ pSVData->mpDefInst->GetPrinterQueueState( pInfo->mpSalQueueInfo );
+#else
+ // ???
+#endif
+
+ if ( !pInfo->mpQueueInfo )
+ pInfo->mpQueueInfo = new QueueInfo;
+
+ pInfo->mpQueueInfo->maPrinterName = pInfo->mpSalQueueInfo->maPrinterName;
+ pInfo->mpQueueInfo->maDriver = pInfo->mpSalQueueInfo->maDriver;
+ pInfo->mpQueueInfo->maLocation = pInfo->mpSalQueueInfo->maLocation;
+ pInfo->mpQueueInfo->maComment = pInfo->mpSalQueueInfo->maComment;
+ pInfo->mpQueueInfo->mnStatus = pInfo->mpSalQueueInfo->mnStatus;
+ pInfo->mpQueueInfo->mnJobs = pInfo->mpSalQueueInfo->mnJobs;
+ return *pInfo->mpQueueInfo;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Printer::GetDefaultPrinterName()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+#ifndef REMOTE_APPSERVER
+ return pSVData->mpDefInst->GetDefaultPrinter();
+#else
+ XubString aDefPrinterName;
+ if ( pSVData->mpRemotePrinterList )
+ {
+ RemotePrinterInfo* pDefPrinter = pSVData->mpRemotePrinterList->GetDefaultPrinter();
+ if ( pDefPrinter )
+ aDefPrinterName = pDefPrinter->GetFullName();
+
+ }
+ return aDefPrinterName;
+#endif
+}
+
+// =======================================================================
+
+void Printer::ImplInitData()
+{
+ mbDevOutput = FALSE;
+ meOutDevType = OUTDEV_PRINTER;
+
+ mbDefPrinter = FALSE;
+ mnError = 0;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ mnPageQueueSize = 0;
+ mnCopyCount = 1;
+ mbCollateCopy = FALSE;
+ mbPrinting = FALSE;
+ mbJobActive = FALSE;
+ mbPrintFile = FALSE;
+ mbInPrintPage = FALSE;
+ mbNewJobSetup = FALSE;
+ mpInfoPrinter = NULL;
+ mpPrinter = NULL;
+ mpDisplayDev = NULL;
+ mpQPrinter = NULL;
+ mpQMtf = NULL;
+ mbIsQueuePrinter = FALSE;
+
+ // Printer in die Liste eintragen
+ ImplSVData* pSVData = ImplGetSVData();
+ mpNext = pSVData->maGDIData.mpFirstPrinter;
+ mpPrev = NULL;
+ if ( mpNext )
+ mpNext->mpPrev = this;
+ else
+ pSVData->maGDIData.mpLastPrinter = this;
+ pSVData->maGDIData.mpFirstPrinter = this;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplInit( SalPrinterQueueInfo* pInfo )
+{
+ // Testen, ob Treiber ueberhaupt mit dem JobSetup uebereinstimmt
+ ImplJobSetup* pJobSetup = maJobSetup.ImplGetData();
+
+ if ( pJobSetup->mpDriverData )
+ {
+ if ( (pJobSetup->maPrinterName != pInfo->maPrinterName) ||
+ (pJobSetup->maDriver != pInfo->maDriver) )
+ {
+ delete pJobSetup->mpDriverData;
+ pJobSetup->mpDriverData = NULL;
+ pJobSetup->mnDriverDataLen = 0;
+ }
+ }
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Printernamen merken
+ maPrinterName = pInfo->maPrinterName;
+ maDriver = pInfo->maDriver;
+
+ // In JobSetup den Printernamen eintragen
+ pJobSetup->maPrinterName = maPrinterName;
+ pJobSetup->maDriver = maDriver;
+
+#ifndef REMOTE_APPSERVER
+ mpInfoPrinter = pSVData->mpDefInst->CreateInfoPrinter( pInfo, pJobSetup );
+ mpPrinter = NULL;
+ mpJobPrinter = NULL;
+ mpJobGraphics = NULL;
+ ImplUpdateJobSetupPaper( maJobSetup );
+
+ if ( !mpInfoPrinter )
+ {
+ ImplInitDisplay( NULL );
+ return;
+ }
+
+ // we need a graphics
+ if ( !ImplGetGraphics() )
+ {
+ ImplInitDisplay( NULL );
+ return;
+ }
+#else
+
+ String aPrinterName( maPrinterName.GetToken( 0, '@' ) );
+ String aPrintServerName( maPrinterName.GetToken( 1, '@' ) );
+
+
+ mpInfoPrinter = new RmPrinter;
+
+ Reference< ::com::sun::star::lang::XMultiServiceFactory > xPrinterFactory;
+ Reference< NMSP_CLIENT::XRmPrinter > xPrinter;
+
+ if (pSVData->mpRemotePrinterList)
+ {
+// if ( !aPrintServerName.Len() )
+// aPrintServerName = pSVData->mpRemotePrinterList->FindLocalPrintServer( aPrinterName );
+
+ xPrinterFactory = pSVData->mpRemotePrinterList->GetServerFactory( aPrintServerName );
+ if( xPrinterFactory.is() )
+ {
+ xPrinter = Reference< NMSP_CLIENT::XRmPrinter >( xPrinterFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OfficePrinter.stardiv.de" ) ) ), NMSP_UNO::UNO_QUERY );
+ mpInfoPrinter->SetInterface( xPrinter );
+ }
+ }
+
+ if ( ! xPrinter.is() )
+ {
+ delete mpInfoPrinter;
+ mpInfoPrinter = NULL;
+ ImplInitDisplay( NULL );
+ return;
+ }
+ else
+ {
+ QueueInfo aQInfo;
+ NMSP_CLIENT::RmQueueInfo aRmQInfo;
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ const REF( NMSP_CLIENT::XRmPrinter )& rxPrinter = mpInfoPrinter->GetInterface();
+
+ aQInfo.maPrinterName = aPrinterName;
+ aQInfo.maDriver = pInfo->maDriver;
+ aQInfo.maLocation = pInfo->maLocation;
+ aQInfo.maComment = pInfo->maComment;
+ aQInfo.mnStatus = pInfo->mnStatus;
+ aQInfo.mnJobs = pInfo->mnJobs;
+
+ PRINTERSEQ_SET( aQInfo, aRmQInfo, NMSP_CLIENT::RmQueueInfo );
+ mpInfoPrinter->Create( aRmQInfo, aRmJobSetup );
+ PRINTERSEQ_GET( aRmJobSetup, maJobSetup );
+
+ if( rxPrinter.is() )
+ {
+ mpGraphics = new ImplServerGraphics( pSVData->mpRemotePrinterList->GetServerAtoms( aPrintServerName ) );
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )( rxPrinter, NMSP_UNO::UNO_QUERY ) );
+ }
+
+ if( !mpGraphics->GetInterface().is() )
+ {
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ ImplInitDisplay( NULL );
+ return;
+ }
+ }
+#endif
+
+ // Daten initialisieren
+ ImplUpdatePageData();
+ mpFontList = new ImplDevFontList;
+ mpFontCache = new ImplFontCache( TRUE );
+ mpGraphics->GetDevFontList( mpFontList );
+ mpFontList->InitStdFonts();
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplInitDisplay( const Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ mpInfoPrinter = NULL;
+ mpPrinter = NULL;
+ mpJobPrinter = NULL;
+ mpJobGraphics = NULL;
+
+ if ( pWindow )
+ mpDisplayDev = new VirtualDevice( *pWindow );
+ else
+ mpDisplayDev = new VirtualDevice();
+ mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mnDPIX = mpDisplayDev->mnDPIX;
+ mnDPIY = mpDisplayDev->mnDPIY;
+
+#ifdef REMOTE_APPSERVER
+ mpGraphics = mpDisplayDev->mpGraphics;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinterQueueInfo* Printer::ImplGetQueueInfo( const XubString& rPrinterName,
+ const XubString* pDriver )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList;
+ if ( pPrnList && pPrnList->Count() )
+ {
+ // Zuerst suchen wir nach dem Printer-Namen
+ ImplPrnQueueData* pBestInfo = NULL;
+ ImplPrnQueueData* pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName == rPrinterName )
+ {
+ pBestInfo = pInfo;
+ if ( !pDriver || (pInfo->mpSalQueueInfo->maDriver == *pDriver) )
+ return pInfo->mpSalQueueInfo;
+ }
+ pInfo = pPrnList->Next();
+ }
+
+ // Wenn wir einen PrinterNamen gefunden haben und nur der Treiber
+ // nicht passt, nehmen wir diesen
+ if ( pBestInfo )
+ return pBestInfo->mpSalQueueInfo;
+
+ // Dann suchen wir caseinsensitiv
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName.EqualsIgnoreCaseAscii( rPrinterName ) )
+ {
+ pBestInfo = pInfo;
+ if ( !pDriver || pInfo->mpSalQueueInfo->maDriver.EqualsIgnoreCaseAscii( *pDriver ) )
+ return pInfo->mpSalQueueInfo;
+ }
+ pInfo = pPrnList->Next();
+ }
+
+ // Wenn wir einen PrinterNamen gefunden haben und nur der Treiber
+ // nicht passt, nehmen wir diesen
+ if ( pBestInfo )
+ return pBestInfo->mpSalQueueInfo;
+
+ // Und wenn wir immer noch keinen gefunden haben, suchen wir
+ // noch nach einem passenden Treiber
+ if ( pDriver )
+ {
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maDriver == *pDriver )
+ return pInfo->mpSalQueueInfo;
+ pInfo = pPrnList->Next();
+ }
+ }
+
+ // Und wenn wir immer noch keinen gefunden, dann wir der
+ // Default-Drucker genommen
+ XubString aPrinterName = GetDefaultPrinterName();
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName == aPrinterName )
+ return pInfo->mpSalQueueInfo;
+ pInfo = pPrnList->Next();
+ }
+
+ // Und wenn wir diesen auch nicht finden, nehmen wir den ersten
+ // in der Liste, denn einige Installationen zerstoeren den
+ // Namen und andere Programme weichen dann normalerweise noch
+ // auf irgendeinen Drucker aus
+ pInfo = pPrnList->First();
+ if ( pInfo )
+ return pInfo->mpSalQueueInfo;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplUpdatePageData()
+{
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !ImplGetGraphics() )
+ return;
+
+ mpGraphics->GetResolution( mnDPIX, mnDPIY );
+ mpInfoPrinter->GetPageInfo( maJobSetup.ImplGetConstData(),
+ mnOutWidth, mnOutHeight,
+ maPageOffset.X(), maPageOffset.Y(),
+ maPaperSize.Width(), maPaperSize.Height() );
+#else
+ if ( mpInfoPrinter && mpGraphics )
+ {
+ mpGraphics->GetResolution( mnDPIX, mnDPIY );
+ mpInfoPrinter->GetPageInfo( mnOutWidth, mnOutHeight,
+ maPageOffset.X(), maPageOffset.Y(),
+ maPaperSize.Width(), maPaperSize.Height() );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplUpdateFontList()
+{
+ ImplUpdateFontData( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer()
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( GetDefaultPrinterName(), NULL );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ if ( !IsDisplayPrinter() )
+ mbDefPrinter = TRUE;
+ }
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const Window* pWindow )
+{
+ ImplInitData();
+ ImplInitDisplay( pWindow );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const JobSetup& rJobSetup ) :
+ maJobSetup( rJobSetup )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rJobSetup.mpData->maPrinterName,
+ &rJobSetup.mpData->maDriver );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ SetJobSetup( rJobSetup );
+ }
+ else
+ {
+ ImplInitDisplay( NULL );
+ maJobSetup = JobSetup();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const QueueInfo& rQueueInfo )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rQueueInfo.GetPrinterName(),
+ &rQueueInfo.GetDriver() );
+ if ( pInfo )
+ ImplInit( pInfo );
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const XubString& rPrinterName )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rPrinterName, NULL );
+ if ( pInfo )
+ ImplInit( pInfo );
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::~Printer()
+{
+ DBG_ASSERT( !IsPrinting(), "Printer::~Printer() - Job is printing" );
+ DBG_ASSERT( !IsJobActive(), "Printer::~Printer() - Job is active" );
+ DBG_ASSERT( !mpQPrinter, "Printer::~Printer() - QueuePrinter not destroyed" );
+ DBG_ASSERT( !mpQMtf, "Printer::~Printer() - QueueMetafile not destroyed" );
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter )
+ ImplGetSVData()->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+ if ( mpDisplayDev )
+ delete mpDisplayDev;
+ else
+ {
+ // OutputDevice-Dtor versucht das gleiche, deshalb muss hier
+ // der FontEntry auch auf NULL gesetzt werden
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ }
+
+ // Printer aus der Liste eintragen
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ pSVData->maGDIData.mpFirstPrinter = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ pSVData->maGDIData.mpLastPrinter = mpPrev;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Printer::GetCapabilities( USHORT nType ) const
+{
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ return mpInfoPrinter->GetCapabilities( maJobSetup.ImplGetConstData(), nType );
+#else
+ return mpInfoPrinter->GetCapabilities( nType );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::HasSupport( PrinterSupport eFeature, BOOL bInJob ) const
+{
+ switch ( eFeature )
+ {
+ case SUPPORT_SET_ORIENTATION:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETORIENTATION );
+ case SUPPORT_SET_PAPERBIN:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERBIN );
+ case SUPPORT_SET_PAPERSIZE:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERSIZE );
+ case SUPPORT_SET_PAPER:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPER );
+ case SUPPORT_COPY:
+ return (GetCapabilities( PRINTER_CAPABILITIES_COPIES ) != 0);
+ case SUPPORT_COLLATECOPY:
+ return (GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES ) != 0);
+ case SUPPORT_SETUPDIALOG:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SUPPORTDIALOG );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetJobSetup( const JobSetup& rSetup )
+{
+ if ( IsDisplayPrinter() || mbInPrintPage )
+ return FALSE;
+
+ JobSetup aJobSetup = rSetup;
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetPrinterData( aJobSetup.ImplGetData() ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+
+ return FALSE;
+#else
+ if ( mpInfoPrinter )
+ {
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetJobSetup( aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ return FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+IMPL_LINK( Printer, UserSetupCompleted, ::com::sun::star::uno::Any*, pResult )
+{
+ ::vos::OGuard guard( Application::GetSolarMutex( ) );
+
+ if( pResult->hasValue() )
+ {
+ mbUserSetupResult = TRUE;
+
+ ::com::sun::star::portal::client::RmJobSetup aRmJobSetup;
+ *pResult >>= aRmJobSetup;
+ JobSetup aJobSetup;
+ PRNSEQ_GET( aRmJobSetup, aJobSetup );
+
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ }
+ else
+ mbUserSetupResult = FALSE;
+
+ mbUserSetupCompleted = TRUE;
+ return 0;
+}
+#endif
+
+BOOL Printer::Setup( Window* pWindow )
+{
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ JobSetup aJobSetup = maJobSetup;
+ SalFrame* pFrame;
+ if ( !pWindow )
+ pFrame = ImplGetDefaultWindow()->ImplGetFrame();
+ else
+ pFrame = pWindow->ImplGetFrame();
+ ImplReleaseGraphics();
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mnModalMode++;
+ nImplSysDialog++;
+ BOOL bSetup = mpInfoPrinter->Setup( pFrame, aJobSetup.ImplGetData() );
+ pSVData->maAppData.mnModalMode--;
+ nImplSysDialog--;
+ if ( bSetup )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ return FALSE;
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRNSEQ_SET( aRmJobSetup, maJobSetup );
+ mpInfoPrinter->SetJobSetup( aRmJobSetup );
+ RmFrameWindow* pFrame;
+ if ( !pWindow )
+ pFrame = ImplGetDefaultWindow()->ImplGetFrame();
+ else
+ pFrame = pWindow->ImplGetFrame();
+ mbUserSetupCompleted = FALSE;
+ mpInfoPrinter->UserSetup( pFrame->GetFrameInterface(), pFrame->InsertUserEventLink( LINK( this, Printer, UserSetupCompleted ) ) );
+ while( ! mbUserSetupCompleted )
+ Application::Reschedule();
+ return mbUserSetupResult;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPrinterProps( const Printer* pPrinter )
+{
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ mbDefPrinter = pPrinter->mbDefPrinter;
+ maPrintFile = pPrinter->maPrintFile;
+ mbPrintFile = pPrinter->mbPrintFile;
+ mnCopyCount = pPrinter->mnCopyCount;
+ mbCollateCopy = pPrinter->mbCollateCopy;
+ mnPageQueueSize = pPrinter->mnPageQueueSize;
+
+ if ( pPrinter->IsDisplayPrinter() )
+ {
+ // Alten Printer zerstoeren
+ if ( !IsDisplayPrinter() )
+ {
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+ mpInfoPrinter = NULL;
+ }
+
+ // Neuen Printer bauen
+ ImplInitDisplay( NULL );
+ return TRUE;
+ }
+
+ // Alten Printer zerstoeren?
+ if ( GetName() != pPrinter->GetName() )
+ {
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+#endif
+ if ( mpDisplayDev )
+ {
+ delete mpDisplayDev;
+ mpDisplayDev = NULL;
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+ mpInfoPrinter = NULL;
+ }
+
+ // Neuen Printer bauen
+ XubString maDriver = pPrinter->GetDriverName();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( pPrinter->GetName(), &maDriver );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ SetJobSetup( pPrinter->GetJobSetup() );
+ }
+ else
+ ImplInitDisplay( NULL );
+ }
+ else
+ SetJobSetup( pPrinter->GetJobSetup() );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetOrientation( Orientation eOrientation )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( maJobSetup.ImplGetConstData()->meOrientation != eOrientation )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->meOrientation = eOrientation;
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_ORIENTATION, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetOrientation( (unsigned short)eOrientation, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Orientation Printer::GetOrientation() const
+{
+ return maJobSetup.ImplGetConstData()->meOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaperBin( USHORT nPaperBin )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( (maJobSetup.ImplGetConstData()->mnPaperBin != nPaperBin) &&
+ (nPaperBin < GetPaperBinCount()) )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mnPaperBin = nPaperBin;
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERBIN, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaperBin( nPaperBin, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetPaperBin() const
+{
+ return maJobSetup.ImplGetConstData()->mnPaperBin;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaper( Paper ePaper )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( maJobSetup.ImplGetConstData()->mePaperFormat != ePaper )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mePaperFormat = ePaper;
+ if ( ePaper != PAPER_USER )
+ {
+ pSetupData->mnPaperWidth = ImplPaperFormats[((USHORT)ePaper)*2];
+ pSetupData->mnPaperHeight = ImplPaperFormats[((USHORT)ePaper)*2+1];
+ }
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaper( (unsigned short)ePaper, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaperSizeUser( const Size& rSize )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ MapMode aMap100thMM( MAP_100TH_MM );
+ Size aPixSize = LogicToPixel( rSize );
+ Size aPageSize = PixelToLogic( aPixSize, aMap100thMM );
+ if ( (maJobSetup.ImplGetConstData()->mePaperFormat != PAPER_USER) ||
+ (maJobSetup.ImplGetConstData()->mnPaperWidth != aPageSize.Width()) ||
+ (maJobSetup.ImplGetConstData()->mnPaperHeight != aPageSize.Height()) )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mePaperFormat = PAPER_USER;
+ pSetupData->mnPaperWidth = aPageSize.Width();
+ pSetupData->mnPaperHeight = aPageSize.Height();
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaperSizeUser( aPixSize.Width(), aPixSize.Height(), aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Paper Printer::GetPaper() const
+{
+ return maJobSetup.ImplGetConstData()->mePaperFormat;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetPaperBinCount() const
+{
+ if ( IsDisplayPrinter() )
+ return 0;
+
+#ifndef REMOTE_APPSERVER
+ return (USHORT)mpInfoPrinter->GetPaperBinCount( maJobSetup.ImplGetConstData() );
+#else
+ if ( mpInfoPrinter )
+ return mpInfoPrinter->GetPaperBinCount();
+ else
+ return 0;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+XubString Printer::GetPaperBinName( USHORT nPaperBin ) const
+{
+ if ( IsDisplayPrinter() )
+ return ImplGetSVEmptyStr();
+
+#ifndef REMOTE_APPSERVER
+ if ( nPaperBin < GetPaperBinCount() )
+ return mpInfoPrinter->GetPaperBinName( maJobSetup.ImplGetConstData(), nPaperBin );
+ else
+ return ImplGetSVEmptyStr();
+#else
+ if ( mpInfoPrinter )
+ return (String)mpInfoPrinter->GetPaperBinName( nPaperBin );
+ else
+ return ImplGetSVEmptyStr();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetCopyCount( USHORT nCopy, BOOL bCollate )
+{
+ mnCopyCount = nCopy;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::Error()
+{
+ maErrorHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::StartPrint()
+{
+ maStartPrintHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::EndPrint()
+{
+ maEndPrintHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::PrintPage()
+{
+ maPrintPageHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+ULONG ImplSalPrinterErrorCodeToVCL( ULONG nError )
+{
+ ULONG nVCLError;
+ switch ( nError )
+ {
+ case 0:
+ nVCLError = PRINTER_OK;
+ break;
+ case SAL_PRINTER_ERROR_ABORT:
+ nVCLError = PRINTER_ABORT;
+ break;
+ default:
+ nVCLError = PRINTER_GENERALERROR;
+ break;
+ }
+
+ return nVCLError;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplEndPrint()
+{
+ mbPrinting = FALSE;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ EndPrint();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Printer, ImplDestroyPrinterAsync, void*, pSalPrinter )
+{
+ SalPrinter* pPrinter = (SalPrinter*)pSalPrinter;
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpDefInst->DestroyPrinter( pPrinter );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+#else
+
+// -----------------------------------------------------------------------
+
+static void ImplDeletePrintSpooler( PrintSpooler* pPrintSpooler )
+{
+ if( pPrintSpooler != 0 )
+ {
+ pPrintSpooler->mxPrintSpooler = REF( NMSP_CLIENT::XRmPrintSpooler )();
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::StartJob( const XubString& rJobName )
+{
+ mnError = PRINTER_OK;
+
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ ULONG nCopies = mnCopyCount;
+ BOOL bCollateCopy = mbCollateCopy;
+ BOOL bUserCopy = FALSE;
+ if ( IsQueuePrinter() )
+ {
+ if ( ((ImplQPrinter*)this)->IsUserCopy() )
+ {
+ nCopies = 1;
+ bCollateCopy = FALSE;
+ }
+ }
+ else if ( nCopies > 1 )
+ {
+ ULONG nDevCopy;
+ if ( bCollateCopy )
+ nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES );
+ else
+ nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COPIES );
+ // Muessen Kopien selber gemacht werden?
+ if ( nCopies > nDevCopy )
+ {
+ bUserCopy = TRUE;
+ nCopies = 1;
+ bCollateCopy = FALSE;
+ if ( !mnPageQueueSize )
+ mnPageQueueSize = 1;
+ }
+ }
+ else
+ bCollateCopy = FALSE;
+
+ if ( !mnPageQueueSize )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
+
+ if ( !mpPrinter )
+ return FALSE;
+
+ XubString* pPrintFile;
+ if ( mbPrintFile )
+ pPrintFile = &maPrintFile;
+ else
+ pPrintFile = NULL;
+
+ if ( !mpPrinter->StartJob( pPrintFile, rJobName, Application::GetDisplayName(),
+ nCopies, bCollateCopy,
+ maJobSetup.ImplGetConstData() ) )
+ {
+ mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() );
+ if ( !mnError )
+ mnError = PRINTER_GENERALERROR;
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpDefInst->DestroyPrinter( mpPrinter );
+ mpPrinter = NULL;
+ return FALSE;
+ }
+
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mnCurPrintPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ StartPrint();
+ }
+ else
+ {
+ mpQPrinter = new ImplQPrinter( this );
+ mpQPrinter->SetUserCopy( bUserCopy );
+ if ( mpQPrinter->StartJob( rJobName ) )
+ {
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ StartPrint();
+ mpQPrinter->StartQueuePrint();
+ }
+ else
+ {
+ mnError = mpQPrinter->GetErrorCode();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ return FALSE;
+ }
+ }
+#else
+ BOOL bResult = FALSE;
+ ImplSVData* pSVData = ImplGetSVData();
+
+ String aServerName( maPrinterName.GetToken( 1, '@' ) );
+
+ // build a new connection if not client
+ Reference< ::com::sun::star::lang::XMultiServiceFactory > xServerFactory;
+ Reference< ::com::sun::star::connection::XConnection > xConnection;
+ Reference< ::com::sun::star::bridge::XBridgeFactory > xBridgeFactory;
+
+ if( ! aServerName.EqualsAscii( RVP_CLIENT_SERVER_NAME ) )
+ pSVData->mpRemotePrinterList->CreateNewPrinterConnection( maPrinterName.GetToken( 1, '@' ), xServerFactory, xConnection, xBridgeFactory );
+ else
+ xServerFactory = pSVData->mxClientFactory;
+ if( xServerFactory.is() )
+ {
+ REF( NMSP_CLIENT::XRmSpoolLauncher ) xLauncher( xServerFactory->createInstance( ::rtl::OUString::createFromAscii( "OfficeSpoolLauncher.stardiv.de" ) ), NMSP_UNO::UNO_QUERY );
+ if( xLauncher.is() &&
+ xLauncher->LaunchSpooler( pSVData->mpUserInfo->sName,
+ pSVData->mpUserInfo->sPassword ) )
+ {
+ if( xBridgeFactory.is() ) // else this a the client connection
+ {
+ // get objects from transferred sospool connection
+ xServerFactory = Reference< ::com::sun::star::lang::XMultiServiceFactory >();
+ Reference< ::com::sun::star::bridge::XBridge >
+ xBridge( xBridgeFactory->createBridge( ::rtl::OUString(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "iiop" ) ), xConnection, Reference< ::com::sun::star::bridge::XInstanceProvider >() ) );
+ xServerFactory = Reference< ::com::sun::star::lang::XMultiServiceFactory >( xBridge->getInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpoolMultiServiceFactory.sprintd.daemons.stardiv.de" ) ) ), UNO_QUERY );
+ }
+
+ mpPrinter = new PrintSpooler();
+ mpPrinter->mxPrintSpooler = REF( NMSP_CLIENT::XRmPrintSpooler )( xServerFactory->createInstance( ::rtl::OUString::createFromAscii( "OfficePrintSpooler.stardiv.de" ) ), NMSP_UNO::UNO_QUERY );
+ if( mpPrinter->mxPrintSpooler.is() )
+ {
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRNSEQ_SET( aRmJobSetup, maJobSetup );
+ mpPrinter->mxPrintSpooler->Create( aRmJobSetup );
+ bResult = mpPrinter->mxPrintSpooler->StartJob( mnCopyCount, mbCollateCopy, rJobName, maPrintFile, mbPrintFile );
+ }
+ }
+
+ if ( bResult )
+ {
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mnCurPrintPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ }
+ else if ( mpPrinter && mpPrinter->mxPrintSpooler.is() )
+ {
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+ }
+ }
+
+ if ( !bResult )
+ mnError = PRINTER_GENERALERROR;
+
+ return bResult;
+#endif
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::EndJob()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+ DBG_ASSERT( !mbInPrintPage, "Printer::EndJob() - StartPage() without EndPage() called" );
+
+ mbJobActive = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ ImplReleaseGraphics();
+
+ mnCurPage = 0;
+
+ if ( mpPrinter )
+ {
+ mbPrinting = FALSE;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+
+ mbDevOutput = FALSE;
+ mpPrinter->EndJob();
+ // Hier den Drucker nicht asyncron zerstoeren, da es
+ // W95 nicht verkraftet, wenn gleichzeitig gedruckt wird
+ // und ein Druckerobjekt zerstoert wird
+ ImplGetSVData()->mpDefInst->DestroyPrinter( mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+ }
+ else
+ mpQPrinter->EndQueuePrint();
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpPrinter->mxPrintSpooler->EndJob();
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ EndPrint();
+
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::AbortJob()
+{
+ // Wenn wir einen Queue-Printer haben, kann man diesen noch mit
+ // AbortJob() abbrechen, solange dieser noch am Drucken ist
+ if ( !IsJobActive() && !IsPrinting() )
+ return FALSE;
+
+ mbJobActive = FALSE;
+ mbInPrintPage = FALSE;
+ mpJobGraphics = NULL;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+
+ if ( mpPrinter )
+ {
+ ImplReleaseGraphics();
+ mbDevOutput = FALSE;
+ mpPrinter->AbortJob();
+ Application::PostUserEvent( LINK( this, Printer, ImplDestroyPrinterAsync ), mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+ }
+ else
+ {
+ mpQPrinter->AbortQueuePrint();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ if ( mpQMtf )
+ {
+ mpQMtf->Clear();
+ delete mpQMtf;
+ mpQMtf = NULL;
+ }
+ EndPrint();
+ }
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpPrinter->mxPrintSpooler->AbortJob();
+ if ( mpQMtf )
+ {
+ mpQMtf->Clear();
+ delete mpQMtf;
+ mpQMtf = NULL;
+ }
+
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::StartPage()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ if ( mpPrinter )
+ {
+ SalGraphics* pGraphics = mpPrinter->StartPage( maJobSetup.ImplGetConstData(), mbNewJobSetup );
+ if ( pGraphics )
+ {
+ ImplReleaseGraphics();
+ mpJobGraphics = pGraphics;
+ }
+ mbDevOutput = TRUE;
+ }
+ else
+ {
+ ImplGetGraphics();
+ mpJobGraphics = mpGraphics;
+ }
+
+ // PrintJob not aborted ???
+ if ( IsJobActive() )
+ {
+ mbInPrintPage = TRUE;
+ mnCurPage++;
+ if ( mpQPrinter )
+ {
+ mpQMtf = new GDIMetaFile;
+ mpQMtf->Record( this );
+ mpQMtf->SaveStatus();
+ }
+ else
+ {
+ mnCurPrintPage++;
+ PrintPage();
+ }
+ }
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpQMtf = new GDIMetaFile;
+ mpQMtf->Record( this );
+ mpQMtf->SaveStatus();
+
+ mbInPrintPage = TRUE;
+ mnCurPage++;
+ mnCurPrintPage++;
+ PrintPage();
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::EndPage()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+ mbInPrintPage = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ if ( mpPrinter )
+ {
+ mpPrinter->EndPage();
+ ImplReleaseGraphics();
+ mbDevOutput = FALSE;
+ }
+ else if ( mpQPrinter )
+ {
+ // Eigentuemeruebergang an QPrinter
+ mpQMtf->Stop();
+ mpQMtf->WindStart();
+ GDIMetaFile* pPage = mpQMtf;
+ mpQMtf = NULL;
+ mpQPrinter->AddQueuePage( pPage, mnCurPage, mbNewJobSetup );
+ }
+
+ mpJobGraphics = NULL;
+ mbNewJobSetup = FALSE;
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter && mpQMtf )
+ {
+ mpQMtf->Stop();
+ mpQMtf->WindStart();
+
+ PrinterPage aPage( mpQMtf, mbNewJobSetup, GetJobSetup() );
+ NMSP_CLIENT::RmPrinterPage aRmPage;
+ PRINTERSEQ_SET( aPage, aRmPage, NMSP_CLIENT::RmPrinterPage );
+ mpPrinter->mxPrintSpooler->SpoolPage( aRmPage );
+ mpQMtf = NULL;
+ mbNewJobSetup = FALSE;
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx
new file mode 100644
index 000000000000..9e301b906012
--- /dev/null
+++ b/vcl/source/gdi/print2.cxx
@@ -0,0 +1,543 @@
+/*************************************************************************
+ *
+ * $RCSfile: print2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_PRINT_CXX
+#define _SPOOLPRINTER_EXT
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define MAX_BANDWIDTH 1000000
+
+// -----------
+// - statics -
+// -----------
+
+static USHORT aSpecialPrintActions[] =
+{
+ META_TRANSPARENT_ACTION,
+ META_FLOATTRANSPARENT_ACTION
+};
+
+// -----------------
+// - ImplCheckRect -
+// -----------------
+
+struct ImplCheckRect
+{
+ Rectangle* mpRect;
+ MetaAction* mpAct;
+ ImplCheckRect* mpNext;
+ BOOL mbSpecialOutput;
+
+ ImplCheckRect() { }
+ ~ImplCheckRect() { delete mpRect; }
+ void ImplCreate( MetaAction* pAct, OutputDevice* pOut, BOOL bSpecial );
+ BOOL Intersects( const ImplCheckRect& rRect )
+ {
+ return( mpRect && rRect.mpRect ) ? mpRect->IsOver( *rRect.mpRect ) : FALSE;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+void ImplCheckRect::ImplCreate( MetaAction* pAct, OutputDevice* pOut, BOOL bSpecial )
+{
+ mpAct = pAct;
+ mpNext = NULL;
+
+ switch( mpAct->GetType() )
+ {
+ case( META_PIXEL_ACTION ):
+ mpRect = new Rectangle( ( (MetaPixelAction*) mpAct )->GetPoint(), Size( 1, 1 ) );
+ break;
+
+ case( META_POINT_ACTION ):
+ mpRect = new Rectangle( ( (MetaPointAction*) mpAct )->GetPoint(), Size( 1, 1 ) );
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ MetaLineAction* pA = (MetaLineAction*) mpAct;
+ mpRect = new Rectangle( pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ mpRect = new Rectangle( ( (MetaRectAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ MetaRoundRectAction* pA = (MetaRoundRectAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetHorzRound(),
+ pA->GetVertRound() ).GetBoundRect() );
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ MetaEllipseAction* pA = (MetaEllipseAction*) mpAct;
+ const Rectangle& rRect = pA->GetRect();
+ mpRect = new Rectangle( Polygon( rRect.Center(),
+ rRect.GetWidth() >> 1,
+ rRect.GetHeight() >> 1 ).GetBoundRect() );
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ MetaArcAction* pA = (MetaArcAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_ARC ).GetBoundRect() );
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ MetaPieAction* pA = (MetaPieAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_PIE ).GetBoundRect() );
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ MetaChordAction* pA = (MetaChordAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_CHORD ).GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ MetaPolyLineAction* pA = (MetaPolyLineAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ MetaPolygonAction* pA = (MetaPolygonAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ MetaPolyPolygonAction* pA = (MetaPolyPolygonAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolyPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pA = (MetaBmpAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmap().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pA = (MetaBmpScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pA = (MetaBmpScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pA = (MetaBmpExAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pA = (MetaBmpExScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pA = (MetaBmpExScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pA = (MetaMaskAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmap().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pA = (MetaMaskScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pA = (MetaMaskScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ mpRect = new Rectangle( ( (MetaGradientAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_HATCH_ACTION ):
+ mpRect = new Rectangle( ( (MetaHatchAction*) mpAct )->GetPolyPolygon().GetBoundRect() );
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ mpRect = new Rectangle( ( (MetaWallpaperAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ mpRect = new Rectangle( ( (MetaTransparentAction*) mpAct )->GetPolyPolygon().GetBoundRect() );
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ MetaFloatTransparentAction* pA = (MetaFloatTransparentAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ MetaEPSAction* pA = (MetaEPSAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ MetaTextAction* pA = (MetaTextAction*) mpAct;
+ const Point aPt( pOut->LogicToPixel( pA->GetPoint() ) );
+ const XubString aString( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ mpRect = new Rectangle( pOut->PixelToLogic( pOut->ImplGetTextBoundRect( aPt.X(), aPt.Y(), aString.GetBuffer(), aString.Len(), NULL ) ) );
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ MetaTextArrayAction* pA = (MetaTextArrayAction*) mpAct;
+ const Point aPt( pOut->LogicToPixel( pA->GetPoint() ) );
+ const XubString aString( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ mpRect = new Rectangle( pOut->PixelToLogic( pOut->ImplGetTextBoundRect( aPt.X(), aPt.Y(), aString.GetBuffer(), aString.Len(), pA->GetDXArray() ) ) );
+ }
+ break;
+
+ case( META_TEXTRECT_ACTION ):
+ {
+ MetaTextRectAction* pA = (MetaTextRectAction*) mpAct;
+ mpRect = new Rectangle( pA->GetRect() );
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ case( META_TEXTLINE_ACTION ):
+ mpRect = NULL;
+ // !!! DBG_ERROR( "Missing" );
+ break;
+
+ default:
+ mpRect = NULL;
+ break;
+ }
+
+ if( mpRect )
+ {
+ *mpRect = pOut->LogicToPixel( *mpRect );
+ mbSpecialOutput = bSpecial;
+ }
+ else
+ mbSpecialOutput = FALSE;
+}
+
+// -----------
+// - Printer -
+// -----------
+
+void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutMtf, ULONG nFlags )
+{
+ const ULONG nSpecialCount = sizeof( aSpecialPrintActions ) / sizeof( aSpecialPrintActions[ 0 ] );
+ MetaAction* pAct;
+ ULONG i, j;
+ BOOL bSpecial = FALSE;
+
+ rOutMtf.Clear();
+
+ // look, if we've got special actions
+ for( pAct = ( (GDIMetaFile&) rInMtf ).FirstAction(); pAct && !bSpecial; pAct = ( (GDIMetaFile&) rInMtf ).NextAction() )
+ for( i = 0; i < nSpecialCount; i++ )
+ if( pAct->GetType() == aSpecialPrintActions[ i ] )
+ bSpecial = TRUE;
+
+ // separate actions which are special actions or which are affected by special actions
+ if( bSpecial )
+ {
+ Rectangle aBoundPixel;
+ const ULONG nCount = rInMtf.GetActionCount();
+ VirtualDevice aPaintVDev;
+ ImplCheckRect* pRects = new ImplCheckRect[ nCount ];
+ ImplCheckRect* pIListFirst = NULL;
+ ImplCheckRect* pIListPrev = NULL;
+ ImplCheckRect* pIListAct = NULL;
+ ImplCheckRect* pOListFirst = NULL;
+ ImplCheckRect* pOListLast = NULL;
+ ImplCheckRect* pOListAct = NULL;
+ ImplCheckRect* pO;
+
+ aPaintVDev.mnDPIX = mnDPIX;
+ aPaintVDev.mnDPIY = mnDPIY;
+ aPaintVDev.mbOutput = FALSE;
+
+ // create list of special action rects
+ for( i = 0, pO = pRects, pAct = ( (GDIMetaFile&) rInMtf ).FirstAction(); pAct;
+ pAct = ( (GDIMetaFile&) rInMtf ).NextAction(), i++, pO++ )
+ {
+ for( j = 0, bSpecial = FALSE; j < nSpecialCount && !bSpecial; j++ )
+ if( pAct->GetType() == aSpecialPrintActions[ j ] )
+ bSpecial = TRUE;
+
+ // execute action to get correct MapMode's etc.
+ pAct->Execute( &aPaintVDev );
+
+ // create (bounding) rect object
+ pO->ImplCreate( pAct, &aPaintVDev, bSpecial );
+
+ // add object to one of the lists
+ if( pO->mbSpecialOutput )
+ {
+ if( !pOListFirst )
+ pOListFirst = pOListAct = pOListLast = pO;
+ else
+ pOListAct = pOListAct->mpNext = pOListLast = pO;
+ }
+ else
+ {
+ if( !pIListFirst )
+ pIListFirst = pIListAct = pO;
+ else
+ pIListAct = pIListAct->mpNext = pO;
+ }
+ }
+
+ // find all intersections and create list of (bitmap)
+ for( pO = pOListFirst; pO; pO = pO->mpNext )
+ {
+ pIListPrev = NULL, pIListAct = pIListFirst;
+
+ while( pIListAct )
+ {
+ // move act object from in list to out list?
+ if( pIListAct->Intersects( *pO ) )
+ {
+ // mark it as special object
+ pIListAct->mbSpecialOutput = TRUE;
+
+ if( pIListPrev )
+ pIListPrev->mpNext = pIListAct->mpNext;
+ else
+ pIListFirst = pIListAct->mpNext;
+
+ pOListLast = pOListLast->mpNext = pIListAct;
+ }
+ else
+ pIListPrev = pIListAct;
+
+ pIListAct = pIListAct->mpNext;
+ pOListLast->mpNext = NULL;
+ }
+ }
+
+ // calculate bounding rectangle of special actions
+ for( pO = pOListFirst; pO; pO = pO->mpNext )
+ aBoundPixel.Union( *pO->mpRect );
+
+ const Size aSzPix( aBoundPixel.GetSize() );
+
+ // create new bitmap action first
+ if( aSzPix.Width() && aSzPix.Height() )
+ {
+ Point aDstPtPix( aBoundPixel.TopLeft() );
+ Size aDstSzPix( aSzPix.Width(), Max( MAX_BANDWIDTH / aSzPix.Width(), 2L ) );
+ const long nLastY = aDstPtPix.Y() + aSzPix.Height() - 1L;
+ VirtualDevice aMapVDev;
+
+ rOutMtf.AddAction( new MetaPushAction( PUSH_MAPMODE ) );
+ rOutMtf.AddAction( new MetaMapModeAction() );
+
+ aPaintVDev.mbOutput = TRUE;
+ aMapVDev.mbOutput = FALSE;
+
+ while( aDstPtPix.Y() <= nLastY )
+ {
+ if( ( aDstPtPix.Y() + aDstSzPix.Height() - 1L ) > nLastY )
+ aDstSzPix.Height() = nLastY - aDstPtPix.Y() + 1L;
+
+ if( aPaintVDev.SetOutputSizePixel( aDstSzPix ) )
+ {
+ aPaintVDev.Push();
+ aMapVDev.Push();
+
+ aMapVDev.mnDPIX = aPaintVDev.mnDPIX = mnDPIX;
+ aMapVDev.mnDPIY = aPaintVDev.mnDPIY = mnDPIY;
+
+ for( i = 0, pO = pRects; i < nCount; i++, pO++ )
+ {
+ MetaAction* pAction = pO->mpAct;
+ const USHORT nType = pAction->GetType();
+
+ if( META_MAPMODE_ACTION == nType )
+ {
+ pAction->Execute( &aMapVDev );
+
+ MapMode aMtfMap( aMapVDev.GetMapMode() );
+ const Point aNewOrg( aMapVDev.PixelToLogic( aDstPtPix ) );
+
+ aMtfMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) );
+ aPaintVDev.SetMapMode( aMtfMap );
+ }
+ else if( ( META_PUSH_ACTION == nType ) || ( META_POP_ACTION ) == nType )
+ {
+ pAction->Execute( &aMapVDev );
+ pAction->Execute( &aPaintVDev );
+ }
+ else
+ pAction->Execute( &aPaintVDev );
+
+ if( !( i % 4 ) )
+ Application::Reschedule();
+ }
+
+ aPaintVDev.mbMap = FALSE;
+ Bitmap aBandBmp( aPaintVDev.GetBitmap( Point(), aDstSzPix ) );
+#ifdef DEBUG
+ aBandBmp.Invert();
+#endif
+ rOutMtf.AddAction( new MetaBmpScaleAction( aDstPtPix, aDstSzPix, aBandBmp ) );
+ aPaintVDev.mbMap = TRUE;
+
+ aMapVDev.Pop();
+ aPaintVDev.Pop();
+ }
+
+ // overlapping bands to avoid missing lines (e.g. PostScript)
+ aDstPtPix.Y() += aDstSzPix.Height();
+ }
+
+ rOutMtf.AddAction( new MetaPopAction() );
+ }
+
+ // add normal actions
+ for( i = 0, pO = pRects; i < nCount; i++, pO++ )
+ if( !pO->mbSpecialOutput )
+ rOutMtf.AddAction( ( pO->mpAct->Duplicate(), pO->mpAct ) );
+
+ rOutMtf.SetPrefMapMode( rInMtf.GetPrefMapMode() );
+ rOutMtf.SetPrefSize( rInMtf.GetPrefSize() );
+ delete[] pRects;
+ }
+ else
+ rOutMtf = rInMtf;
+}
diff --git a/vcl/source/gdi/regband.cxx b/vcl/source/gdi/regband.cxx
new file mode 100644
index 000000000000..51a0a366727b
--- /dev/null
+++ b/vcl/source/gdi/regband.cxx
@@ -0,0 +1,785 @@
+/*************************************************************************
+ *
+ * $RCSfile: regband.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_REGBAND_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_REGBAND_HXX
+#include <regband.hxx>
+#endif
+
+// =======================================================================
+//
+// ImplRegionBand
+//
+// Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
+// enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
+// Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
+// Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
+//
+// Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
+//
+// Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
+// in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
+// Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
+// in Rechtecke umgewandelt und die Liste der Punkte geloescht.
+//
+// -----------------------------------------------------------------------
+
+ImplRegionBand::ImplRegionBand( long nTop, long nBottom )
+{
+ // save boundaries
+ mnYTop = nTop;
+ mnYBottom = nBottom;
+
+ // initialize lists
+ mpNextBand = NULL;
+ mpPrevBand = NULL;
+ mpFirstSep = NULL;
+ mpFirstBandPoint = NULL;
+ mbTouched = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegionBand::ImplRegionBand( const ImplRegionBand& rRegionBand )
+{
+ // copy boundaries
+ mnYTop = rRegionBand.mnYTop;
+ mnYBottom = rRegionBand.mnYBottom;
+ mbTouched = rRegionBand.mbTouched;
+
+ // initialisation
+ mpNextBand = NULL;
+ mpPrevBand = NULL;
+ mpFirstSep = NULL;
+ mpFirstBandPoint = NULL;
+
+ // copy all elements of the list with separations
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = rRegionBand.mpFirstSep;
+ while ( pSep )
+ {
+ // create new and copy data
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = pSep->mnXRight;
+ pNewSep->mbRemoved = pSep->mbRemoved;
+ pNewSep->mpNextSep = NULL;
+ if ( pSep == rRegionBand.mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+
+ pPrevSep = pNewSep;
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegionBand::~ImplRegionBand()
+{
+ DBG_ASSERT( mpFirstBandPoint == NULL, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
+
+ // delete elements of the list
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ ImplRegionBandSep* pTempSep = pSep->mpNextSep;
+ delete pSep;
+ pSep = pTempSep;
+ }
+
+ // delete elements of the list
+ ImplRegionBandPoint* pPoint = mpFirstBandPoint;
+ while ( pPoint )
+ {
+ ImplRegionBandPoint* pTempPoint = pPoint->mpNextBandPoint;
+ delete pPoint;
+ pPoint = pTempPoint;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// generate separations from lines and process union with existing
+// separations
+
+void ImplRegionBand::ProcessPoints()
+{
+ // check Pointlist
+ ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
+ while ( pRegionBandPoint )
+ {
+ // within list?
+ if ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
+ {
+ // start/stop?
+ if ( pRegionBandPoint->mbEndPoint && pRegionBandPoint->mpNextBandPoint->mbEndPoint )
+ {
+ // same direction? -> remove next point!
+ if ( pRegionBandPoint->meLineType == pRegionBandPoint->mpNextBandPoint->meLineType )
+ {
+ ImplRegionBandPoint* pSaveRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ pRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
+ delete pSaveRegionBandPoint;
+ }
+ }
+ }
+
+ // continue with next element in the list
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ pRegionBandPoint = mpFirstBandPoint;
+ while ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
+ {
+ Union( pRegionBandPoint->mnX, pRegionBandPoint->mpNextBandPoint->mnX );
+
+ ImplRegionBandPoint* pNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
+
+ // remove allready processed points
+ delete pRegionBandPoint->mpNextBandPoint;
+ delete pRegionBandPoint;
+
+ // continue with next element in the list
+ pRegionBandPoint = pNextBandPoint;
+ }
+
+ // remove last element if necessary
+ if ( pRegionBandPoint )
+ delete pRegionBandPoint;
+
+ // list is now empty
+ mpFirstBandPoint = NULL;
+}
+
+// -----------------------------------------------------------------------
+//
+// generate separations from lines and process union with existing
+// separations
+
+BOOL ImplRegionBand::InsertPoint( long nX, long nLineId,
+ BOOL bEndPoint, LineType eLineType )
+{
+ if ( !mpFirstBandPoint )
+ {
+ mpFirstBandPoint = new ImplRegionBandPoint;
+ mpFirstBandPoint->mnX = nX;
+ mpFirstBandPoint->mnLineId = nLineId;
+ mpFirstBandPoint->mbEndPoint = bEndPoint;
+ mpFirstBandPoint->meLineType = eLineType;
+ mpFirstBandPoint->mpNextBandPoint = NULL;
+ return TRUE;
+ }
+
+ // look if line allready touched the band
+ ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
+ ImplRegionBandPoint* pLastTestedRegionBandPoint = NULL;
+ while( pRegionBandPoint )
+ {
+ if ( pRegionBandPoint->mnLineId == nLineId )
+ {
+ if ( bEndPoint )
+ {
+ if( !pRegionBandPoint->mbEndPoint )
+ {
+ // remove old band point
+ if( !mpFirstBandPoint->mpNextBandPoint )
+ {
+ // if we've only got one point => replace first point
+ pRegionBandPoint->mnX = nX;
+ pRegionBandPoint->mbEndPoint = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ // remove current point
+ if( !pLastTestedRegionBandPoint )
+ {
+ // remove and delete old first point
+ ImplRegionBandPoint* pSaveBandPoint = mpFirstBandPoint;
+ mpFirstBandPoint = mpFirstBandPoint->mpNextBandPoint;
+ delete pSaveBandPoint;
+ }
+ else
+ {
+ // remove and delete current band point
+ pLastTestedRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint;
+ delete pRegionBandPoint;
+ }
+
+ break;
+ }
+ }
+ }
+ else
+ return FALSE;
+ }
+
+ // use next element
+ pLastTestedRegionBandPoint = pRegionBandPoint;
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ // search appropriate position and insert point into the list
+ ImplRegionBandPoint* pNewRegionBandPoint;
+
+ pRegionBandPoint = mpFirstBandPoint;
+ pLastTestedRegionBandPoint = NULL;
+ while ( pRegionBandPoint )
+ {
+ // new point completly left? -> insert as first point
+ if ( nX <= pRegionBandPoint->mnX )
+ {
+ pNewRegionBandPoint = new ImplRegionBandPoint;
+ pNewRegionBandPoint->mnX = nX;
+ pNewRegionBandPoint->mnLineId = nLineId;
+ pNewRegionBandPoint->mbEndPoint = bEndPoint;
+ pNewRegionBandPoint->meLineType = eLineType;
+ pNewRegionBandPoint->mpNextBandPoint = pRegionBandPoint;
+
+ // connections to the new point
+ if ( !pLastTestedRegionBandPoint )
+ mpFirstBandPoint = pNewRegionBandPoint;
+ else
+ pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
+
+ return TRUE;
+ }
+
+ // use next element
+ pLastTestedRegionBandPoint = pRegionBandPoint;
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ // not inserted -> add to the end of the list
+ pNewRegionBandPoint = new ImplRegionBandPoint;
+ pNewRegionBandPoint->mnX = nX;
+ pNewRegionBandPoint->mnLineId = nLineId;
+ pNewRegionBandPoint->mbEndPoint = bEndPoint;
+ pNewRegionBandPoint->meLineType = eLineType;
+ pNewRegionBandPoint->mpNextBandPoint = NULL;
+
+ // connections to the new point
+ pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::MoveX( long nHorzMove )
+{
+ // move all x-separations
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ pSep->mnXLeft += nHorzMove;
+ pSep->mnXRight += nHorzMove;
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::ScaleX( double fHorzScale )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ pSep->mnXLeft = FRound( pSep->mnXLeft * fHorzScale );
+ pSep->mnXRight = FRound( pSep->mnXRight * fHorzScale );
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// combine overlaping sparations
+
+BOOL ImplRegionBand::OptimizeBand()
+{
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // remove?
+ if ( pSep->mbRemoved || (pSep->mnXRight < pSep->mnXLeft) )
+ {
+ ImplRegionBandSep* pOldSep = pSep;
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pSep->mpNextSep;
+ else
+ pPrevSep->mpNextSep = pSep->mpNextSep;
+ pSep = pSep->mpNextSep;
+ delete pOldSep;
+ continue;
+ }
+
+ // overlaping separations? -> combine!
+ if ( pSep->mpNextSep )
+ {
+ if ( (pSep->mnXRight+1) >= pSep->mpNextSep->mnXLeft )
+ {
+ if ( pSep->mpNextSep->mnXRight > pSep->mnXRight )
+ pSep->mnXRight = pSep->mpNextSep->mnXRight;
+
+ ImplRegionBandSep* pOldSep = pSep->mpNextSep;
+ pSep->mpNextSep = pOldSep->mpNextSep;
+ delete pOldSep;
+ continue;
+ }
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Union( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Union(): nxLeft > nXRight" );
+
+ // band empty? -> add element
+ if ( !mpFirstSep )
+ {
+ mpFirstSep = new ImplRegionBandSep;
+ mpFirstSep->mnXLeft = nXLeft;
+ mpFirstSep->mnXRight = nXRight;
+ mpFirstSep->mbRemoved = FALSE;
+ mpFirstSep->mpNextSep = NULL;
+ return;
+ }
+
+ // process real union
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completely inside? nothing to do!
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ return;
+
+ // new separation completly left? -> new separation!
+ if ( nXRight < pSep->mnXLeft )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = nXLeft;
+ pNewSep->mnXRight = nXRight;
+ pNewSep->mbRemoved = FALSE;
+
+ pNewSep->mpNextSep = pSep;
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ break;
+ }
+
+ // new separation overlaping from left? -> extend boundary
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ pSep->mnXLeft = nXLeft;
+
+ // new separation overlaping from right? -> extend boundary
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXRight;
+ break;
+ }
+
+ // not inserted, but last element? -> add to the end of the list
+ if ( !pSep->mpNextSep && (nXLeft > pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = nXLeft;
+ pNewSep->mnXRight = nXRight;
+ pNewSep->mbRemoved = FALSE;
+
+ pSep->mpNextSep = pNewSep;
+ pNewSep->mpNextSep = NULL;
+ break;
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Intersect( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
+
+ // band has been touched
+ mbTouched = TRUE;
+
+ // band empty? -> nothing to do
+ if ( !mpFirstSep )
+ return;
+
+ // process real intersection
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completly outside? -> remove separation
+ if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
+ // will be removed from the optimizer
+ pSep->mbRemoved = TRUE;
+
+ // new separation overlaping from left? -> reduce right boundary
+ if ( (nXLeft <= pSep->mnXLeft) &&
+ (nXRight <= pSep->mnXRight) &&
+ (nXRight >= pSep->mnXLeft) )
+ pSep->mnXRight = nXRight;
+
+ // new separation overlaping from right? -> reduce right boundary
+ if ( (nXLeft >= pSep->mnXLeft) &&
+ (nXLeft <= pSep->mnXRight) &&
+ (nXRight >= pSep->mnXRight) )
+ pSep->mnXLeft = nXLeft;
+
+ // new separation within the actual one? -> reduce both boundaries
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXRight;
+ pSep->mnXLeft = nXLeft;
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Exclude( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
+
+ // band has been touched
+ mbTouched = TRUE;
+
+ // band empty? -> nothing to do
+ if ( !mpFirstSep )
+ return;
+
+ // process real exclusion
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ BOOL bSepProcessed = FALSE;
+
+ // new separation completely overlapping? -> remove separation
+ if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
+ {
+ // will be removed from the optimizer
+ pSep->mbRemoved = TRUE;
+ bSepProcessed = TRUE;
+ }
+
+ // new separation overlaping from left? -> reduce boundary
+ if ( !bSepProcessed )
+ {
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ {
+ pSep->mnXLeft = nXRight+1;
+ bSepProcessed = TRUE;
+ }
+ }
+
+ // new separation overlaping from right? -> reduce boundary
+ if ( !bSepProcessed )
+ {
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXLeft-1;
+ bSepProcessed = TRUE;
+ }
+ }
+
+ // new separation within the actual one? -> reduce boundary
+ // and add new entry for reminder
+ if ( !bSepProcessed )
+ {
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = nXLeft-1;
+ pNewSep->mbRemoved = FALSE;
+
+ pSep->mnXLeft = nXRight+1;
+
+ // connections from the new separation
+ pNewSep->mpNextSep = pSep;
+
+ // connections to the new separation
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ }
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::XOr( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::XOr(): nxLeft > nXRight" );
+
+ // band empty? -> add element
+ if ( !mpFirstSep )
+ {
+ mpFirstSep = new ImplRegionBandSep;
+ mpFirstSep->mnXLeft = nXLeft;
+ mpFirstSep->mnXRight = nXRight;
+ mpFirstSep->mbRemoved = FALSE;
+ mpFirstSep->mpNextSep = NULL;
+ return;
+ }
+
+ // process real xor
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completely overlapping?
+ // -> move boundaries to left remainder
+ // -> reduce boundaries of new separation
+ if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
+ {
+ int iOldXRight = pSep->mnXRight;
+ pSep->mnXRight = pSep->mnXLeft;
+ pSep->mnXLeft = nXLeft;
+ nXLeft = pSep->mnXRight;
+ }
+
+ // new separation overlaping from left?
+ // -> move boundaries to left remainder
+ // -> set boundaries of new separation to right remainder
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ {
+ int iOldXRight = pSep->mnXRight;
+ pSep->mnXRight = pSep->mnXLeft;
+ pSep->mnXLeft = nXLeft;
+ nXLeft = pSep->mnXRight;
+ }
+
+ // new separation overlaping from right? -> reduce boundary
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ pSep->mnXRight = nXLeft;
+
+ // new separation within the actual one? -> reduce boundary
+ // and add new entry for reminder
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = nXLeft;
+
+ pSep->mnXLeft = nXRight;
+
+ // connections from the new separation
+ pNewSep->mpNextSep = pSep;
+
+ // connections to the new separation
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsInside( long nX )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsOver( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft < nRight) && (pSep->mnXRight > nLeft) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsInside( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft >= nLeft) && (nRight <= pSep->mnXRight) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplRegionBand::GetXLeftBoundary() const
+{
+ DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
+
+ return mpFirstSep->mnXLeft;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplRegionBand::GetXRightBoundary() const
+{
+ DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XRightBoundary -> no separation in band!" );
+
+ // search last separation
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep->mpNextSep )
+ pSep = pSep->mpNextSep;
+ return pSep->mnXRight;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
+{
+ ImplRegionBandSep* pOwnRectBandSep = mpFirstSep;
+ ImplRegionBandSep* pSecondRectBandSep = rRegionBand.mpFirstSep;
+ while ( pOwnRectBandSep && pSecondRectBandSep )
+ {
+ // get boundaries of current rectangle
+ long nOwnXLeft = pOwnRectBandSep->mnXLeft;
+ long nSecondXLeft = pSecondRectBandSep->mnXLeft;
+ if ( nOwnXLeft != nSecondXLeft )
+ return FALSE;
+
+ long nOwnXRight = pOwnRectBandSep->mnXRight;
+ long nSecondXRight = pSecondRectBandSep->mnXRight;
+ if ( nOwnXRight != nSecondXRight )
+ return FALSE;
+
+ // get next separation from current band
+ pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+
+ // get next separation from current band
+ pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+ }
+
+ // differnt number of separations?
+ if ( pOwnRectBandSep || pSecondRectBandSep )
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
new file mode 100644
index 000000000000..000cad2a909b
--- /dev/null
+++ b/vcl/source/gdi/region.cxx
@@ -0,0 +1,2458 @@
+/*************************************************************************
+ *
+ * $RCSfile: region.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_REGION_CXX
+
+#include <limits.h>
+
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _REGION_H
+#include <region.h>
+#endif
+#ifndef _REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _REGBAND_HXX
+#include <regband.hxx>
+#endif
+
+// =======================================================================
+//
+// ImplRegionBand
+//
+// Die Klassen RegionBand/ImplRegionBand speichert Regionen in Form von
+// Rechtecken ab. Die Region ist in Y-Richtung in Baendern unterteilt, die
+// wiederum ein oder mehrere Rechtecke mit der Hoehe des Bandes enthalten.
+//
+// Leere Baender werden entfernt.
+//
+// Polygone und PolyPolygone werden ebenfalls in Rechtecke zerlegt und in
+// der Baendern abgelegt. Hierzu werden alle Punkte der einzelnen Polygone
+// mit dem Bresenham-Algorithmus berechnet und in die Baender eingetragen.
+// Nach der vollstaendigen Berechung aller Kanten werden die entsprechenden
+// Rechntecke berechnet
+
+// =======================================================================
+
+static ImplRegionBase aImplNullRegion = { 0, 0, NULL };
+static ImplRegionBase aImplEmptyRegion = { 0, 0, NULL };
+
+// =======================================================================
+
+DBG_NAME( Region );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgTestRegion( const void* pObj )
+{
+ Region* pRegion = (Region*)pObj;
+ ImplRegion* pImplRegion = pRegion->ImplGetImplRegion();
+
+ if ( aImplNullRegion.mnRefCount )
+ return "Null-Region-RefCount modified";
+ if ( aImplNullRegion.mnRectCount )
+ return "Null-Region-RectCount modified";
+ if ( aImplNullRegion.mpPolyPoly )
+ return "Null-Region-PolyPoly modified";
+ if ( aImplEmptyRegion.mnRefCount )
+ return "Emptry-Region-RefCount modified";
+ if ( aImplEmptyRegion.mnRectCount )
+ return "Emptry-Region-RectCount modified";
+ if ( aImplEmptyRegion.mpPolyPoly )
+ return "Emptry-Region-PolyPoly modified";
+
+ if ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
+ {
+ ULONG nCount = 0;
+ const ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
+ while ( pBand )
+ {
+ if ( pBand->mnYBottom < pBand->mnYTop )
+ return "YBottom < YTop";
+ if ( pBand->mpNextBand )
+ {
+ if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
+ return "overlapping bands in region";
+ }
+ if ( pBand->mbTouched > 1 )
+ return "Band-mbTouched overwrite";
+
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ if ( pSep->mnXRight < pSep->mnXLeft )
+ return "XLeft < XRight";
+ if ( pSep->mpNextSep )
+ {
+ if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
+ return "overlapping separations in region";
+ }
+ if ( pSep->mbRemoved > 1 )
+ return "Sep-mbRemoved overwrite";
+
+ nCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ if ( pImplRegion->mnRectCount != nCount )
+ return "mnRetCount is not valid";
+ }
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+inline void Region::ImplPolyPolyRegionToBandRegion()
+{
+ if ( mpImplRegion->mpPolyPoly )
+ ImplPolyPolyRegionToBandRegionFunc();
+}
+
+// =======================================================================
+
+ImplRegion::ImplRegion()
+{
+ mnRefCount = 1;
+ mnRectCount = 0;
+ mpPolyPoly = NULL;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
+{
+ mnRefCount = 1;
+ mnRectCount = 0;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+ mpPolyPoly = new PolyPolygon( rPolyPoly );
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
+{
+ mnRefCount = 1;
+ mnRectCount = rImplRegion.mnRectCount;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+ if ( rImplRegion.mpPolyPoly )
+ mpPolyPoly = new PolyPolygon( *rImplRegion.mpPolyPoly );
+ else
+ mpPolyPoly = NULL;
+
+ // insert band(s) into the list
+ ImplRegionBand* pNewBand;
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = rImplRegion.mpFirstBand;
+ while ( pBand )
+ {
+ pNewBand = new ImplRegionBand( *pBand );
+
+ // first element? -> set as first into the list
+ if ( pBand == rImplRegion.mpFirstBand )
+ mpFirstBand = pNewBand;
+ else
+ pPrevBand->mpNextBand = pNewBand;
+
+ pPrevBand = pNewBand;
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegion::~ImplRegion()
+{
+ DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
+ "ImplRegion::~ImplRegion() - Empty oder NULL-Region" )
+
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ ImplRegionBand* pTempBand = pBand->mpNextBand;
+ delete pBand;
+ pBand = pTempBand;
+ }
+
+ delete mpPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+//
+// create complete range of bands in single steps
+
+void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
+{
+ // add top band
+ mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
+
+ // begin first search from the first element
+ mpLastCheckedBand = mpFirstBand;
+
+ ImplRegionBand* pBand = mpFirstBand;
+ for ( int i = nYTop; i <= nYBottom+1; i++ )
+ {
+ // create new band
+ ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
+ pBand->mpNextBand = pNewBand;
+ if ( pBand != mpFirstBand )
+ pNewBand->mpPrevBand = pBand;
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegion::InsertLine( const Point& rStartPt, const Point& rEndPt,
+ long nLineId )
+{
+ long nX, nY;
+
+ // lines consisting of a single point do not interest here
+ if ( rStartPt == rEndPt )
+ return TRUE;
+
+ LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
+ if ( rStartPt.X() == rEndPt.X() )
+ {
+ // vertical line
+ const long nEndY = rEndPt.Y();
+
+ nX = rStartPt.X();
+ nY = rStartPt.Y();
+
+ if( nEndY > nY )
+ {
+ for ( ; nY <= nEndY; nY++ )
+ {
+ Point aNewPoint( nX, nY );
+ InsertPoint( aNewPoint, nLineId,
+ (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
+ eLineType );
+ }
+ }
+ else
+ {
+ for ( ; nY >= nEndY; nY-- )
+ {
+ Point aNewPoint( nX, nY );
+ InsertPoint( aNewPoint, nLineId,
+ (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
+ eLineType );
+ }
+ }
+ }
+ else if ( rStartPt.Y() != rEndPt.Y() )
+ {
+ const long nDX = labs( rEndPt.X() - rStartPt.X() );
+ const long nDY = labs( rEndPt.Y() - rStartPt.Y() );
+ const long nStartX = rStartPt.X();
+ const long nStartY = rStartPt.Y();
+ const long nEndX = rEndPt.X();
+ const long nEndY = rEndPt.Y();
+ const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
+ const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
+
+ if ( nDX >= nDY )
+ {
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+
+ for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
+ {
+ InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
+
+ if ( nD < 0L )
+ nD += nDY2;
+ else
+ nD += nDYX, nY += nYInc;
+ }
+ }
+ else
+ {
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+
+ for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
+ {
+ InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
+
+ if ( nD < 0L )
+ nD += nDY2;
+ else
+ nD += nDYX, nX += nXInc;
+ }
+ }
+
+ // last point
+ InsertPoint( Point( nEndX, nEndY ), nLineId, TRUE, eLineType );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+//
+// search for appropriate place for the new point
+
+BOOL ImplRegion::InsertPoint( const Point &rPoint, long nLineID,
+ BOOL bEndPoint, LineType eLineType )
+{
+ DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
+
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
+ {
+ // Search ascending
+ while ( mpLastCheckedBand )
+ {
+ // Insert point if possible
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint reached the end of the list!" );
+ }
+ else
+ {
+ // Search descending
+ while ( mpLastCheckedBand )
+ {
+ // Insert point if possible
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint reached the beginning of the list!" );
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint point not inserted!" );
+
+ // reinitialize pointer (should never be reached!)
+ mpLastCheckedBand = mpFirstBand;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+//
+// search for appropriate places for the new bands
+
+void ImplRegion::InsertBands( long nTop, long nBottom )
+{
+ // region empty? -> set rectagle as first entry!
+ if ( !mpFirstBand )
+ {
+ // add band with boundaries of the rectangle
+ mpFirstBand = new ImplRegionBand( nTop, nBottom );
+ return;
+ }
+
+ // find/insert bands for the boundaries of the rectangle
+ BOOL bTopBoundaryInserted = FALSE;
+ BOOL bTop2BoundaryInserted = FALSE;
+ BOOL bBottomBoundaryInserted = FALSE;
+
+ // special case: top boundary is above the first band
+ ImplRegionBand* pNewBand;
+ if ( nTop < mpFirstBand->mnYTop )
+ {
+ // create new band above the first in the list
+ pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
+ if ( nBottom < mpFirstBand->mnYTop )
+ pNewBand->mnYBottom = nBottom;
+
+ // insert band into the list
+ pNewBand->mpNextBand = mpFirstBand;
+ mpFirstBand = pNewBand;
+
+ bTopBoundaryInserted = TRUE;
+ }
+
+ // insert band(s) into the list
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ // Insert Bands if possible
+ if ( !bTopBoundaryInserted )
+ bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
+
+ if ( !bTop2BoundaryInserted )
+ bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
+
+ if ( !bBottomBoundaryInserted && (nTop != nBottom) )
+ bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
+
+ // both boundaries inserted? -> nothing more to do
+ if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
+ break;
+
+ // insert bands between two bands if neccessary
+ if ( pBand->mpNextBand )
+ {
+ if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( pBand->mnYBottom+1,
+ pBand->mpNextBand->mnYTop-1 );
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mpNextBand = pNewBand;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// create new band and insert it into the list
+
+BOOL ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
+ long nYBandPosition )
+{
+ // boundary already included in band with height 1? -> nothing to do!
+ if ( (pBand->mnYTop == pBand->mnYBottom) &&
+ (nYBandPosition == pBand->mnYTop) )
+ return TRUE;
+
+ // insert single height band on top?
+ ImplRegionBand* pNewBand;
+ if ( nYBandPosition == pBand->mnYTop )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition+1;
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition;
+ pBand->mpNextBand = pNewBand;
+
+ return TRUE;
+ }
+
+ // top of new rectangle within the current band? -> insert new band and copy data
+ if ( (nYBandPosition > pBand->mnYTop) &&
+ (nYBandPosition < pBand->mnYBottom) )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition;
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition;
+ pBand->mpNextBand = pNewBand;
+
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition;
+
+ // insert band into the list
+ pBand->mpNextBand->mnYTop = nYBandPosition+1;
+
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition - 1;
+ pBand->mpNextBand = pNewBand;
+
+ return TRUE;
+ }
+
+ // create new band behind the current in the list
+ if ( !pBand->mpNextBand )
+ {
+ if ( nYBandPosition == pBand->mnYBottom )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = pBand->mnYBottom;
+ pNewBand->mnYBottom = nYBandPosition;
+
+ pBand->mnYBottom = nYBandPosition-1;
+
+ // append band to the list
+ pBand->mpNextBand = pNewBand;
+ return TRUE;
+ }
+
+ if ( nYBandPosition > pBand->mnYBottom )
+ {
+ // create new band
+ pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
+
+ // append band to the list
+ pBand->mpNextBand = pNewBand;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
+
+ // process union
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->Union( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::Union() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegion::Exclude( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
+
+ // process exclude
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->Exclude( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::Exclude() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegion::XOr( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
+
+ // process xor
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->XOr( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::XOr() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// remove empty bands
+
+BOOL ImplRegion::OptimizeBandList()
+{
+ DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
+ "ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
+
+ mnRectCount = 0;
+
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ const BOOL bBTEqual = pBand->mpNextBand &&
+ (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
+
+ // no separation? -> remove!
+ if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
+ {
+ // save pointer
+ ImplRegionBand* pOldBand = pBand;
+
+ // previous element of the list
+ if ( pBand == mpFirstBand )
+ mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ else
+ {
+ // fixup
+ if ( bBTEqual )
+ pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
+
+ // this and next band with equal separations? -> combine!
+ if ( pBand->mpNextBand &&
+ ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
+ (*pBand == *pBand->mpNextBand) )
+ {
+ // expand current height
+ pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
+
+ // remove next band from list
+ ImplRegionBand* pDeletedBand = pBand->mpNextBand;
+ pBand->mpNextBand = pDeletedBand->mpNextBand;
+ delete pDeletedBand;
+
+ // check band again!
+ }
+ else
+ {
+ // count rectangles within band
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mnRectCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ pBand = mpFirstBand;
+ while ( pBand )
+ {
+ DBG_ASSERT( pBand->mpFirstSep != NULL,
+ "Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
+
+ if ( pBand->mnYBottom < pBand->mnYTop )
+ DBG_ERROR( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
+
+ if ( pBand->mpNextBand )
+ {
+ if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
+ DBG_ERROR( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+#endif
+
+ return (mnRectCount != 0);
+}
+
+// =======================================================================
+
+void Region::ImplCopyData()
+{
+ mpImplRegion->mnRefCount--;
+ mpImplRegion = new ImplRegion( *mpImplRegion );
+}
+
+// =======================================================================
+
+Region::Region()
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( RegionType eType )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_ASSERT( (eType == REGION_NULL) || (eType == REGION_EMPTY),
+ "Region( RegionType ) - RegionType != EMPTY/NULL" );
+
+ if ( eType == REGION_NULL )
+ mpImplRegion = (ImplRegion*)(&aImplNullRegion);
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Rectangle& rRect )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+
+ ImplCreateRectRegion( rRect );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Polygon& rPolygon )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rPolygon, Polygon, NULL );
+
+ ImplCreatePolyPolyRegion( rPolygon );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const PolyPolygon& rPolyPoly )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+
+ ImplCreatePolyPolyRegion( rPolyPoly );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Region& rRegion )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+ DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
+
+ // copy pointer to instance of implementation
+ mpImplRegion = rRegion.mpImplRegion;
+ if ( mpImplRegion->mnRefCount )
+ mpImplRegion->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Region::~Region()
+{
+ DBG_DTOR( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplCreateRectRegion( const Rectangle& rRect )
+{
+ if ( rRect.IsEmpty() )
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ else
+ {
+ // get justified rectangle
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+
+ // create instance of implementation class
+ mpImplRegion = new ImplRegion();
+
+ // add band with boundaries of the rectangle
+ mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
+
+ // Set left and right boundaries of the band
+ mpImplRegion->mpFirstBand->Union( nLeft, nRight );
+ mpImplRegion->mnRectCount = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
+{
+ const USHORT nPolyCount = rPolyPoly.Count();
+ if ( nPolyCount )
+ {
+ // polypolygon empty? -> empty region
+ const Rectangle aRect( rPolyPoly.GetBoundRect() );
+
+ if ( !aRect.IsEmpty() )
+ {
+ // width OR height == 1 ? => Rectangular region
+ if ( (aRect.GetWidth() == 1) || (aRect.GetHeight() == 1) )
+ ImplCreateRectRegion( aRect );
+ else
+ mpImplRegion = new ImplRegion( rPolyPoly );
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplPolyPolyRegionToBandRegionFunc()
+{
+ const PolyPolygon aPolyPoly( *mpImplRegion->mpPolyPoly );
+
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+
+ const USHORT nPolyCount = aPolyPoly.Count();
+ if ( nPolyCount )
+ {
+ // polypolygon empty? -> empty region
+ const Rectangle aRect( aPolyPoly.GetBoundRect() );
+
+ if ( !aRect.IsEmpty() )
+ {
+ long nLineID = 0L;
+
+ // initialisation and creation of Bands
+ mpImplRegion = new ImplRegion();
+ mpImplRegion->CreateBandRange( aRect.Top(), aRect.Bottom() );
+
+ // insert polygons
+ for ( USHORT nPoly = 0; nPoly < nPolyCount; nPoly++ )
+ {
+ // get reference to current polygon
+ const Polygon& aPoly = aPolyPoly.GetObject( nPoly );
+ const USHORT nSize = aPoly.GetSize();
+
+ // not enough points ( <= 2 )? -> nothing to do!
+ if ( nSize <= 2 )
+ continue;
+
+ // band the polygon
+ for ( USHORT nPoint = 1; nPoint < nSize; nPoint++ )
+ mpImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
+
+ // close polygon with line from first point to last point, if neccesary
+ const Point rLastPoint = aPoly.GetPoint(nSize-1);
+ const Point rFirstPoint = aPoly.GetPoint(0);
+ if ( rLastPoint != rFirstPoint )
+ mpImplRegion->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
+ }
+
+ // process bands with lines
+ ImplRegionBand* pRegionBand = mpImplRegion->mpFirstBand;
+ while ( pRegionBand )
+ {
+ // generate separations from the lines and process union
+ pRegionBand->ProcessPoints();
+ pRegionBand = pRegionBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::Move( long nHorzMove, long nVertMove )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no region data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ if ( mpImplRegion->mpPolyPoly )
+ mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
+ else
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // process the vertical move
+ if ( nVertMove != 0)
+ {
+ pBand->mnYTop = pBand->mnYTop + nVertMove;
+ pBand->mnYBottom = pBand->mnYBottom + nVertMove;
+ }
+
+ // process the horizontal move
+ if ( nHorzMove != 0)
+ pBand->MoveX( nHorzMove );
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::Scale( double fScaleX, double fScaleY )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no region data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ if ( mpImplRegion->mpPolyPoly )
+ mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
+ else
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // process the vertical move
+ if ( fScaleY != 0.0 )
+ {
+ pBand->mnYTop = FRound( pBand->mnYTop * fScaleY );
+ pBand->mnYBottom = FRound( pBand->mnYBottom * fScaleY );
+ }
+
+ // process the horizontal move
+ if ( fScaleX != 0.0 )
+ pBand->ScaleX( fScaleX );
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Union( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process union
+ mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Intersect( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ {
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return TRUE;
+ }
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // is region empty? -> nothing to do!
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return TRUE;
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // is own region NULL-region? -> copy data!
+ if ( mpImplRegion == &aImplNullRegion )
+ {
+ // create instance of implementation class
+ mpImplRegion = new ImplRegion();
+
+ // add band with boundaries of the rectangle
+ mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
+
+ // Set left and right boundaries of the band
+ mpImplRegion->mpFirstBand->Union( nLeft, nRight );
+ mpImplRegion->mnRectCount = 1;
+
+ return TRUE;
+ }
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process intersections
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // band within intersection boundary? -> process. otherwise remove
+ if ( (pBand->mnYTop >= nTop) &&
+ (pBand->mnYBottom <= nBottom) )
+ {
+ // process intersection
+ pBand->Intersect( nLeft, nRight );
+
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ else
+ {
+ ImplRegionBand* pOldBand = pBand;
+ if ( pBand == mpImplRegion->mpFirstBand )
+ mpImplRegion->mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Exclude( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process exclude
+ mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::XOr( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process xor
+ mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Union( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->Union( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Intersect( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // same instance data? -> nothing to do!
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return TRUE;
+
+ // is region null? -> nothing to do
+ if ( rRegion.mpImplRegion == &aImplNullRegion )
+ return TRUE;
+
+ // is rectangle empty? -> nothing to do
+ if ( rRegion.mpImplRegion == &aImplEmptyRegion )
+ {
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return TRUE;
+ }
+
+ // is own region NULL-region? -> copy data!
+ if ( mpImplRegion == &aImplNullRegion)
+ {
+ mpImplRegion = rRegion.mpImplRegion;
+ rRegion.mpImplRegion->mnRefCount++;
+ return TRUE;
+ }
+
+ // Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
+ if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
+ {
+ Region aTempRegion = rRegion;
+ aTempRegion.Intersect( *this );
+ *this = aTempRegion;
+ }
+ else
+ {
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // mark all bands as untouched
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ pBand->mbTouched = FALSE;
+ pBand = pBand->mpNextBand;
+ }
+
+ pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ // left boundary?
+ if ( pSep == pBand->mpFirstSep )
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( LONG_MIN+1, pBand->mnYTop,
+ pSep->mnXLeft-1, pBand->mnYBottom );
+ }
+
+ // right boundary?
+ if ( pSep->mpNextSep == NULL )
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
+ LONG_MAX-1, pBand->mnYBottom );
+ }
+ else
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
+ pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // remove all untouched bands if bands allready left
+ ImplRegionBand* pPrevBand;
+ pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ if ( !pBand->mbTouched )
+ {
+ // save pointer
+ ImplRegionBand* pOldBand = pBand;
+
+ // previous element of the list
+ if ( pBand == mpImplRegion->mpFirstBand )
+ mpImplRegion->mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ else
+ {
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Exclude( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->Exclude( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ // Wir optimieren schon in der Schleife, da wir davon
+ // ausgehen, das wir insgesammt weniger Baender ueberpruefen
+ // muessen
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ break;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::XOr( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->XOr( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Region::GetBoundRect() const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ Rectangle aRect;
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return aRect;
+
+ // PolyPolygon data im Imp structure?
+ if ( mpImplRegion->mpPolyPoly )
+ return mpImplRegion->mpPolyPoly->GetBoundRect();
+
+ // no band in the list? -> region is empty!
+ if ( !mpImplRegion->mpFirstBand )
+ return aRect;
+
+ // get the boundaries of the first band
+ long nYTop = mpImplRegion->mpFirstBand->mnYTop;
+ long nYBottom = mpImplRegion->mpFirstBand->mnYBottom;
+ long nXLeft = mpImplRegion->mpFirstBand->GetXLeftBoundary();
+ long nXRight = mpImplRegion->mpFirstBand->GetXRightBoundary();
+
+ // look in the band list (don't test first band again!)
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand->mpNextBand;
+ while ( pBand )
+ {
+ nYBottom = pBand->mnYBottom;
+ nXLeft = Min( nXLeft, pBand->GetXLeftBoundary() );
+ nXRight = Max( nXRight, pBand->GetXRightBoundary() );
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // set rectangle
+ aRect = Rectangle( nXLeft, nYTop, nXRight, nYBottom );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
+ long& rX, long& rY,
+ long& rWidth, long& rHeight ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // no band in the list? -> region is empty!
+ if ( mpImplRegion->mpFirstBand == NULL )
+ return FALSE;
+
+ // initialise pointer for first access
+ ImplRegionBand* pCurrRectBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pCurrRectBandSep = pCurrRectBand->mpFirstSep;
+
+ DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
+ if ( !pCurrRectBandSep )
+ return FALSE;
+
+ // get boundaries of current rectangle
+ rX = pCurrRectBandSep->mnXLeft;
+ rY = pCurrRectBand->mnYTop;
+ rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
+ rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
+
+ // save pointers
+ rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
+ rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
+ long& rX, long& rY,
+ long& rWidth, long& rHeight ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // get last pointers
+ ImplRegionBand* pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
+ ImplRegionBandSep* pCurrRectBandSep = (ImplRegionBandSep*)rImplRegionInfo.mpVoidCurrRectBandSep;
+
+ // get next separation from current band
+ pCurrRectBandSep = pCurrRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pCurrRectBandSep )
+ {
+ // get next band
+ pCurrRectBand = pCurrRectBand->mpNextBand;
+
+ // no band found? -> not further rectangles!
+ if( !pCurrRectBand )
+ return FALSE;
+
+ // get first separation in current band
+ pCurrRectBandSep = pCurrRectBand->mpFirstSep;
+ }
+
+ // get boundaries of current rectangle
+ rX = pCurrRectBandSep->mnXLeft;
+ rY = pCurrRectBand->mnYTop;
+ rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
+ rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
+
+ // save new pointers
+ rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
+ rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+RegionType Region::GetType() const
+{
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return REGION_EMPTY;
+ else if ( mpImplRegion == &aImplNullRegion )
+ return REGION_NULL;
+ else if ( mpImplRegion->mnRectCount == 1 )
+ return REGION_RECTANGLE;
+ else
+ return REGION_COMPLEX;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsInside( const Point& rPoint ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // PolyPolygon data im Imp structure?
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+/*
+ if ( mpImplRegion->mpPolyPoly )
+ return mpImplRegion->mpPolyPoly->IsInside( rPoint );
+*/
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // search band list
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // is point within band?
+ if ( (pBand->mnYTop <= rPoint.Y()) &&
+ (pBand->mnYBottom >= rPoint.Y()) )
+ {
+ // is point within separation of the band?
+ if ( pBand->IsInside( rPoint.X() ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsInside( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> not inside
+ if ( rRect.IsEmpty() )
+ return FALSE;
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // create region from rectangle and intersect own region
+ Region aRegion = rRect;
+ aRegion.Exclude( *this );
+
+ // rectangle is inside if exclusion is empty
+ return aRegion.IsEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsOver( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // Can we optimize this ??? - is used in StarDraw for brushes pointers
+ // Why we have no IsOver for Regions ???
+ // create region from rectangle and intersect own region
+ Region aRegion = rRect;
+ aRegion.Intersect( *this );
+
+ // rectangle is over if include is not empty
+ return !aRegion.IsEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+void Region::SetNull()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // set new type
+ mpImplRegion = (ImplRegion*)(&aImplNullRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::SetEmpty()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // set new type
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region& Region::operator=( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+ DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rRegion.mpImplRegion->mnRefCount )
+ rRegion.mpImplRegion->mnRefCount++;
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ mpImplRegion = rRegion.mpImplRegion;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Region& Region::operator=( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ ImplCreateRectRegion( rRect );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::operator==( const Region& rRegion ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ // reference to same object? -> equal!
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ if ( rRegion.mpImplRegion->mpPolyPoly && mpImplRegion->mpPolyPoly )
+ return *rRegion.mpImplRegion->mpPolyPoly == *mpImplRegion->mpPolyPoly;
+ else
+ {
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // Eine der beiden Regions kann jetzt Empty sein
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return FALSE;
+
+ if ( rRegion.mpImplRegion == &aImplEmptyRegion )
+ return FALSE;
+ }
+
+ // initialise pointers
+ ImplRegionBand* pOwnRectBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ ImplRegionBand* pSecondRectBand = rRegion.mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+ while ( pOwnRectBandSep && pSecondRectBandSep )
+ {
+ // get boundaries of current rectangle
+ long nOwnXLeft = pOwnRectBandSep->mnXLeft;
+ long nSecondXLeft = pSecondRectBandSep->mnXLeft;
+ if ( nOwnXLeft != nSecondXLeft )
+ return FALSE;
+
+ long nOwnYTop = pOwnRectBand->mnYTop;
+ long nSecondYTop = pSecondRectBand->mnYTop;
+ if ( nOwnYTop != nSecondYTop )
+ return FALSE;
+
+ long nOwnXRight = pOwnRectBandSep->mnXRight;
+ long nSecondXRight = pSecondRectBandSep->mnXRight;
+ if ( nOwnXRight != nSecondXRight )
+ return FALSE;
+
+ long nOwnYBottom = pOwnRectBand->mnYBottom;
+ long nSecondYBottom = pSecondRectBand->mnYBottom;
+ if ( nOwnYBottom != nSecondYBottom )
+ return FALSE;
+
+ // get next separation from current band
+ pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pOwnRectBandSep )
+ {
+ // get next band
+ pOwnRectBand = pOwnRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pOwnRectBand )
+ pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ }
+
+ // get next separation from current band
+ pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pSecondRectBandSep )
+ {
+ // get next band
+ pSecondRectBand = pSecondRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pSecondRectBand )
+ pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+ }
+
+ if ( pOwnRectBandSep && !pSecondRectBandSep )
+ return FALSE;
+
+ if ( !pOwnRectBandSep && pSecondRectBandSep )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
+
+SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ VersionCompat aCompat( rIStrm, STREAM_READ );
+ UINT16 nVersion;
+ UINT16 nTmp16;
+
+ // statische Object haben RefCount von 0
+ if ( rRegion.mpImplRegion->mnRefCount )
+ {
+ if ( rRegion.mpImplRegion->mnRefCount > 1 )
+ rRegion.mpImplRegion->mnRefCount--;
+ else
+ delete rRegion.mpImplRegion;
+ }
+
+ // get version of streamed region
+ rIStrm >> nVersion;
+
+ // get type of region
+ rIStrm >> nTmp16;
+
+ RegionType meStreamedType = (RegionType)nTmp16;
+
+ switch( meStreamedType )
+ {
+ case REGION_NULL:
+ rRegion.mpImplRegion = (ImplRegion*)&aImplNullRegion;
+ break;
+
+ case REGION_EMPTY:
+ rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
+ break;
+
+ default:
+ // create instance of implementation class
+ rRegion.mpImplRegion = new ImplRegion();
+
+ // get header from first element
+ rIStrm >> nTmp16;
+
+ // get all bands
+ rRegion.mpImplRegion->mnRectCount = 0;
+ ImplRegionBand* pCurrBand = NULL;
+ while ( (StreamEntryType)nTmp16 != STREAMENTRY_END )
+ {
+ // insert new band or new separation?
+ if ( (StreamEntryType)nTmp16 == STREAMENTRY_BANDHEADER )
+ {
+ long nYTop;
+ long nYBottom;
+
+ rIStrm >> nYTop;
+ rIStrm >> nYBottom;
+
+ // create band
+ ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
+
+ // first element? -> set as first into the list
+ if ( !pCurrBand )
+ rRegion.mpImplRegion->mpFirstBand = pNewBand;
+ else
+ pCurrBand->mpNextBand = pNewBand;
+
+ // save pointer for next creation
+ pCurrBand = pNewBand;
+ }
+ else
+ {
+ long nXLeft;
+ long nXRight;
+
+ rIStrm >> nXLeft;
+ rIStrm >> nXRight;
+
+ // add separation
+ if ( pCurrBand )
+ {
+ pCurrBand->Union( nXLeft, nXRight );
+ rRegion.mpImplRegion->mnRectCount++;
+ }
+ }
+
+ // get next header
+ rIStrm >> nTmp16;
+ }
+ break;
+ }
+
+ return rIStrm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStrm, const Region& rRegion )
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ VersionCompat aCompat( rOStrm, STREAM_WRITE );
+ UINT16 nVersion = 1;
+
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // put version
+ rOStrm << nVersion;
+
+ // put type
+ rOStrm << (UINT16)rRegion.GetType();
+
+ // put all bands if not null or empty
+ if ( (rRegion.mpImplRegion != &aImplEmptyRegion) && (rRegion.mpImplRegion != &aImplNullRegion) )
+ {
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // put boundaries
+ rOStrm << (UINT16) STREAMENTRY_BANDHEADER;
+ rOStrm << pBand->mnYTop;
+ rOStrm << pBand->mnYBottom;
+
+ // put separations of current band
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ // put separation
+ rOStrm << (UINT16) STREAMENTRY_SEPARATION;
+ rOStrm << pSep->mnXLeft;
+ rOStrm << pSep->mnXRight;
+
+ // next separation from current band
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // put endmarker
+ rOStrm << (UINT16) STREAMENTRY_END;
+ }
+
+ return rOStrm;
+}
+
+// -----------------------------------------------------------------------
+
+RegionOverlapType Region::GetOverlapType( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> not inside
+ if ( rRect.IsEmpty() )
+ return REGION_OUTSIDE;
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return REGION_OUTSIDE;
+
+ // resolve pointer
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ // complex region? don't check for now. This may change in the future...
+ if ( pBand->mpNextBand || pSep->mpNextSep )
+ return REGION_OVER;
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // check rectangle region
+ BOOL boLeft = (nLeft >= pSep->mnXLeft) && (nLeft < pSep->mnXRight);
+ BOOL boRight = (nRight <= pSep->mnXRight) && (nRight > pSep->mnXLeft);
+ BOOL boTop = (nTop >= pBand->mnYTop) && (nTop < pBand->mnYBottom);
+ BOOL boBottom = (nBottom <= pBand->mnYBottom) && (nBottom > pBand->mnYTop);
+ if ( boLeft && boRight && boTop && boBottom )
+ return REGION_INSIDE;
+ if ( boLeft || boRight || boTop || boBottom )
+ return REGION_OVER;
+
+ return REGION_OUTSIDE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplBeginAddRect()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // create fresh region
+ mpImplRegion = new ImplRegion();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplAddRect( const Rectangle& rRect )
+{
+ // Hier kein CheckThis, da nicht alle Daten auf Stand
+
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ // get justified rectangle
+ long nTop;
+ long nBottom;
+ long nLeft;
+ long nRight;
+ if ( rRect.Top() <= rRect.Bottom() )
+ {
+ nTop = rRect.Top();
+ nBottom = rRect.Bottom();
+ }
+ else
+ {
+ nTop = rRect.Bottom();
+ nBottom = rRect.Top();
+ }
+ if ( rRect.Left() <= rRect.Right() )
+ {
+ nLeft = rRect.Left();
+ nRight = rRect.Right();
+ }
+ else
+ {
+ nLeft = rRect.Right();
+ nRight = rRect.Left();
+ }
+
+ if ( !mpImplRegion->mpLastCheckedBand )
+ {
+ // create new band
+ mpImplRegion->mpLastCheckedBand = new ImplRegionBand( nTop, nBottom );
+
+ // set band as current
+ mpImplRegion->mpFirstBand = mpImplRegion->mpLastCheckedBand;
+ mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
+ }
+ else
+ {
+ DBG_ASSERT( nTop >= mpImplRegion->mpLastCheckedBand->mnYTop,
+ "Region::ImplAddRect() - nTopY < nLastTopY" );
+
+ // new band? create it!
+ if ( (nTop != mpImplRegion->mpLastCheckedBand->mnYTop) ||
+ (nBottom != mpImplRegion->mpLastCheckedBand->mnYBottom) )
+ {
+ // create new band
+ ImplRegionBand* pNewRegionBand = new ImplRegionBand( nTop, nBottom );
+
+ // append band to the end
+ mpImplRegion->mpLastCheckedBand->mpNextBand = pNewRegionBand;
+
+ // skip to the new band
+ mpImplRegion->mpLastCheckedBand = mpImplRegion->mpLastCheckedBand->mpNextBand;
+ }
+
+ // Insert Sep
+ mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplEndAddRect()
+{
+ // check if we are empty
+ if ( !mpImplRegion->mpFirstBand )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return;
+ }
+
+ // check if we have somthing to optimize
+ if ( !mpImplRegion->mpFirstBand->mpNextBand )
+ {
+ // update mpImplRegion->mnRectCount, because no OptimizeBandList is called
+ ImplRegionBandSep* pSep = mpImplRegion->mpFirstBand->mpFirstSep;
+ mpImplRegion->mnRectCount = 0;
+ while( pSep )
+ {
+ mpImplRegion->mnRectCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ // Erst hier testen, da hier die Daten wieder stimmen
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ return;
+ }
+
+ // have to revert list? -> do it now!
+ if ( mpImplRegion->mpFirstBand->mnYTop >
+ mpImplRegion->mpFirstBand->mpNextBand->mnYTop )
+ {
+ ImplRegionBand * pNewFirstRegionBand;
+
+ // initialize temp list with first element
+ pNewFirstRegionBand = mpImplRegion->mpFirstBand;
+ mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
+ pNewFirstRegionBand->mpNextBand = NULL;
+
+ // insert elements to the temp list
+ while ( mpImplRegion->mpFirstBand )
+ {
+ ImplRegionBand * pSavedRegionBand = pNewFirstRegionBand;
+ pNewFirstRegionBand = mpImplRegion->mpFirstBand;
+ mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
+ pNewFirstRegionBand->mpNextBand = pSavedRegionBand;
+ }
+
+ // set temp list as new list
+ mpImplRegion->mpFirstBand = pNewFirstRegionBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ // Erst hier testen, da hier die Daten wieder stimmen
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Region::GetRectCount() const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+#ifdef DBG_UTIL
+ ULONG nCount = 0;
+
+ // all bands if not null or empty
+ if ( (mpImplRegion != &aImplEmptyRegion) && (mpImplRegion != &aImplNullRegion) )
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while( pSep )
+ {
+ nCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ DBG_ASSERT( mpImplRegion->mnRectCount == nCount, "Region: invalid mnRectCount!" );
+#endif
+
+ return mpImplRegion->mnRectCount;
+}
+
+// -----------------------------------------------------------------------
+
+RegionHandle Region::BeginEnumRects()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return NULL;
+
+ // no band in the list? -> region is empty!
+ if ( mpImplRegion->mpFirstBand == NULL )
+ {
+ DBG_ASSERT( mpImplRegion->mpFirstBand, "Region::BeginEnumRects() First Band is Empty!" );
+ return NULL;
+ }
+
+ ImplRegionHandle* pData = new ImplRegionHandle;
+ pData->mpRegion = new Region( *this );
+ pData->mbFirst = TRUE;
+
+ // save pointers
+ pData->mpCurrRectBand = pData->mpRegion->mpImplRegion->mpFirstBand;
+ pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
+
+ return (RegionHandle)pData;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::GetEnumRects( RegionHandle pVoidData, Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
+ if ( !pData )
+ return FALSE;
+
+ if ( pData->mbFirst )
+ pData->mbFirst = FALSE;
+ else
+ {
+ // get next separation from current band
+ pData->mpCurrRectBandSep = pData->mpCurrRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pData->mpCurrRectBandSep )
+ {
+ // get next band
+ pData->mpCurrRectBand = pData->mpCurrRectBand->mpNextBand;
+
+ // no band found? -> not further rectangles!
+ if ( !pData->mpCurrRectBand )
+ return FALSE;
+
+ // get first separation in current band
+ pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
+ }
+ }
+
+ // get boundaries of current rectangle
+ rRect.Top() = pData->mpCurrRectBand->mnYTop;
+ rRect.Bottom() = pData->mpCurrRectBand->mnYBottom;
+ rRect.Left() = pData->mpCurrRectBandSep->mnXLeft;
+ rRect.Right() = pData->mpCurrRectBandSep->mnXRight;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::EndEnumRects( RegionHandle pVoidData )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
+ if ( !pData )
+ return;
+
+ // cleanup
+ delete pData->mpRegion;
+ delete pData;
+}
diff --git a/vcl/source/gdi/salmisc.cxx b/vcl/source/gdi/salmisc.cxx
new file mode 100644
index 000000000000..50af07d0eda9
--- /dev/null
+++ b/vcl/source/gdi/salmisc.cxx
@@ -0,0 +1,497 @@
+/*************************************************************************
+ *
+ * $RCSfile: salmisc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _RTL_MEMORY_H_
+#include <rtl/memory.h>
+#endif
+#include <bmpacc.hxx>
+#include <salbtype.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define IMPL_CASE_GET_FORMAT( Format ) \
+case( BMP_FORMAT##Format ): \
+ pFncGetPixel = BitmapReadAccess::GetPixelFor##Format; \
+break
+
+// -----------------------------------------------------------------------------
+
+#define IMPL_CASE_SET_FORMAT( Format, BitCount ) \
+case( BMP_FORMAT##Format ): \
+{ \
+ pFncSetPixel = BitmapReadAccess::SetPixelFor##Format; \
+ pDstBuffer->mnBitCount = BitCount; \
+} \
+break
+
+// -----------------------------------------------------------------------------
+
+#define DOUBLE_SCANLINES() \
+while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) ) \
+{ \
+ HMEMCPY( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize ); \
+ nActY++; \
+}
+
+// -----------
+// - Inlines -
+// -----------
+
+#define TC_TO_PAL_COLORS 4096
+
+static long ImplIndexFromColor( const BitmapColor& rCol )
+{
+#if TC_TO_PAL_COLORS == 4096
+
+ return( ( ( (long) rCol.GetBlue() >> 4L) << 8L ) |
+ ( ( (long) rCol.GetGreen() >> 4L ) << 4L ) |
+ ( (long) rCol.GetRed() >> 4L ) );
+
+#elif TC_TO_PAL_COLORS == 32768
+
+ return( ( ( (long) rCol.GetBlue() >> 3L) << 10L ) |
+ ( ( (long) rCol.GetGreen() >> 3L ) << 5L ) |
+ ( (long) rCol.GetRed() >> 3L ) );
+
+#endif
+}
+
+
+#define COLOR_TO_INDEX( _def_rCol )
+
+// ------------------------
+// - conversion functions -
+// ------------------------
+
+static void ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
+ BitmapColor* pColMapBuf = aColMap.ImplGetColorBuffer();
+ BitmapColor aIndex( 0 );
+
+ for( USHORT i = 0, nCount = aColMap.GetEntryCount(); i < nCount; i++ )
+ {
+ if( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] )
+ aIndex.SetIndex( i );
+ else
+ aIndex.SetIndex( rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] ) );
+
+ pColMapBuf[ i ] = aIndex;
+ }
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ const BitmapColor* pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer();
+
+ if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ const BitmapColor aCol0( pColBuf[ 0 ] );
+ const BitmapColor aCol1( pColBuf[ 1 ] );
+ long nMapX;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; )
+ {
+ nMapX = pMapX[ nX ];
+ pFncSetPixel( pDstScan, nX++,
+ pSrcScan[ nMapX >> 3 ] & ( 1 << ( 7 - ( nMapX & 7 ) ) ) ? aCol1 : aCol0,
+ rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_4BIT_MSN_PAL )
+ {
+ long nMapX;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; )
+ {
+ nMapX = pMapX[ nX ];
+ pFncSetPixel( pDstScan, nX++,
+ pColBuf[ ( pSrcScan[ nMapX >> 1 ] >> ( nMapX & 1 ? 0 : 4 ) ) & 0x0f ],
+ rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_8BIT_PAL )
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+
+ if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ BitmapColor aCol;
+ BYTE* pPixel;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol.SetBlue( *( pPixel = ( pSrcScan + pMapX[ nX ] * 3 ) )++ );
+ aCol.SetGreen( *pPixel++ );
+ aCol.SetRed( *pPixel );
+ pFncSetPixel( pDstScan, nX, aCol, rDstMask );
+ }
+
+ DOUBLE_SCANLINES()
+ }
+ }
+ else
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ), rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
+ BYTE* pColToPalMap = new BYTE[ TC_TO_PAL_COLORS ];
+ BitmapColor aIndex( 0 );
+
+ for( long nR = 0; nR < 16; nR++ )
+ {
+ for( long nG = 0; nG < 16; nG++ )
+ {
+ for( long nB = 0; nB < 16; nB++ )
+ {
+ BitmapColor aCol( nR << 4, nG << 4, nB << 4 );
+ pColToPalMap[ ImplIndexFromColor( aCol ) ] = (BYTE) rDstBuffer.maPalette.GetBestIndex( aCol );
+ }
+ }
+ }
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ) ) ] );
+ pFncSetPixel( pDstScan, nX, aIndex, rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+
+ delete[] pColToPalMap;
+}
+
+// ---------------------
+// - StretchAndConvert -
+// ---------------------
+
+BitmapBuffer* StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
+ ULONG nDstBitmapFormat, BitmapPalette* pDstPal, ColorMask* pDstMask )
+{
+ FncGetPixel pFncGetPixel;
+ FncSetPixel pFncSetPixel;
+ BitmapBuffer* pDstBuffer = new BitmapBuffer;
+ const ULONG nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
+ const long nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
+ const long nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
+ const long nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
+ Scanline* pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
+ Scanline* pDstScan = new Scanline[ nDstDY ];
+ long* pMapX = new long[ nDstDX ];
+ long* pMapY = new long[ nDstDY ];
+ Scanline pTmpScan;
+ long i, nTmp, nOffset;
+
+ // set function for getting pixels
+ switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
+ {
+ IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
+ IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
+ IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
+ IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
+ IMPL_CASE_GET_FORMAT( _8BIT_PAL );
+ IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _16BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
+
+ default:
+ DBG_ERROR( "unknown read format" );
+ break;
+ }
+
+ // set function for setting pixels
+ switch( nDstScanlineFormat )
+ {
+ IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
+ IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
+ IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
+ IMPL_CASE_SET_FORMAT( _16BIT_TC_MASK, 16 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
+
+ default:
+ DBG_ERROR( "unknown write format" );
+ break;
+ }
+
+ // fill destination buffer
+ pDstBuffer->mnFormat = nDstBitmapFormat;
+ pDstBuffer->mnWidth = nDstDX;
+ pDstBuffer->mnHeight = nDstDY;
+ pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * nDstDX );
+ pDstBuffer->mpBits = new BYTE[ pDstBuffer->mnScanlineSize * nDstDY ];
+ rtl_zeroMemory( pDstBuffer->mpBits, pDstBuffer->mnScanlineSize * nDstDY );
+
+ // do we need a destination palette or color mask?
+ if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
+ {
+ DBG_ASSERT( pDstPal, "destination buffer requires palette" );
+ pDstBuffer->maPalette = *pDstPal;
+ }
+ else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
+ {
+ DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
+ pDstBuffer->maColorMask = *pDstMask;
+ }
+
+ // horizontal mapping table
+ if( nDstDX != nSrcDX )
+ {
+ const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
+
+ for( i = 0L; i < nDstDX; i++ )
+ pMapX[ i ] = nSrcX + FRound( i * fFactorX );
+ }
+ else
+ {
+ for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
+ pMapX[ i ] = nTmp++;
+ }
+
+ // vertical mapping table
+ if( nDstDY != nSrcDY )
+ {
+ const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
+
+ for( i = 0L; i < nDstDY; i++ )
+ pMapY[ i ] = nSrcY + FRound( i * fFactorY );
+ }
+ else
+ {
+ for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
+ pMapY[ i ] = nTmp++;
+ }
+
+ // source scanline buffer
+ if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
+ else
+ {
+ pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
+ nOffset = -rSrcBuffer.mnScanlineSize;
+ }
+
+ for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
+ pSrcScan[ i ] = pTmpScan;
+
+ // destination scanline buffer
+ if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
+ else
+ {
+ pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
+ nOffset = -pDstBuffer->mnScanlineSize;
+ }
+
+ for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
+ pDstScan[ i ] = pTmpScan;
+
+ // do buffer scaling and conversion
+ if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
+ {
+ ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
+ {
+ ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
+ {
+ ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else
+ {
+ ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+
+ // cleanup
+ delete[] pSrcScan;
+ delete[] pDstScan;
+ delete[] pMapX;
+ delete[] pMapY;
+
+ return pDstBuffer;
+}
diff --git a/vcl/source/gdi/svcompat.cxx b/vcl/source/gdi/svcompat.cxx
new file mode 100644
index 000000000000..dc037185e064
--- /dev/null
+++ b/vcl/source/gdi/svcompat.cxx
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * $RCSfile: svcompat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_COMPAT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_SVCOMPAT_HXX
+#include <svcompat.hxx>
+#endif
+
+// --------------
+// - ImplCompat -
+// --------------
+
+ImplCompat::ImplCompat( SvStream& rStm, USHORT nStreamMode, USHORT nVersion ) :
+ mpRWStm ( &rStm ),
+ mnStmMode ( nStreamMode ),
+ mnVersion ( nVersion )
+{
+ if( !mpRWStm->GetError() )
+ {
+ if( STREAM_WRITE == mnStmMode )
+ {
+ *mpRWStm << mnVersion;
+ mnTotalSize = ( mnCompatPos = mpRWStm->Tell() ) + 4UL;
+ mpRWStm->SeekRel( 4L );
+ }
+ else
+ {
+ *mpRWStm >> mnVersion;
+ *mpRWStm >> mnTotalSize;
+ mnCompatPos = mpRWStm->Tell();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImplCompat::~ImplCompat()
+{
+ if( STREAM_WRITE == mnStmMode )
+ {
+ const UINT32 nEndPos = mpRWStm->Tell();
+
+ mpRWStm->Seek( mnCompatPos );
+ *mpRWStm << ( nEndPos - mnTotalSize );
+ mpRWStm->Seek( nEndPos );
+ }
+ else
+ {
+ const UINT32 nReadSize = mpRWStm->Tell() - mnCompatPos;
+
+ if( mnTotalSize > nReadSize )
+ mpRWStm->SeekRel( mnTotalSize - nReadSize );
+ }
+}
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
new file mode 100644
index 000000000000..ff8c7268c9fe
--- /dev/null
+++ b/vcl/source/gdi/virdev.cxx
@@ -0,0 +1,442 @@
+/*************************************************************************
+ *
+ * $RCSfile: virdev.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_VIRDEV_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _SV_SALVD_HXX
+#include <salvd.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+
+using namespace ::com::sun::star::uno;
+
+// appserver
+#ifdef REMOTE_APPSERVER
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#ifndef _SV_RMVIRDEV_HXX
+#include <rmvirdev.hxx>
+#endif
+#ifndef _VCL_RMCACHE_HXX_
+#include <rmcache.hxx>
+#endif
+#endif
+
+// =======================================================================
+
+// interface cache
+#ifdef REMOTE_APPSERVER
+
+static ::vcl::InterfacePairCache< ::com::sun::star::portal::client::XRmVirtualDevice, ::com::sun::star::portal::client::XRmOutputDevice >* pRemoteVirdevCache = NULL;
+
+typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::portal::client::XRmVirtualDevice >, ::com::sun::star::uno::Reference< ::com::sun::star::portal::client::XRmOutputDevice > > virdevInterfacePair;
+
+void eraseRemoteVirdevCache()
+{
+ if( pRemoteVirdevCache )
+ {
+ delete pRemoteVirdevCache;
+ pRemoteVirdevCache = NULL;
+ }
+}
+
+#endif
+
+// =======================================================================
+
+void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
+ long nDX, long nDY, USHORT nBitCount )
+{
+ DBG_ASSERT( nBitCount <= 1,
+ "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
+
+ if ( nDX < 1 )
+ nDX = 1;
+
+ if ( nDY < 1 )
+ nDY = 1;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pOutDev )
+ pOutDev = ImplGetDefaultWindow();
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+ if ( !pOutDev->mpGraphics )
+ ((OutputDevice*)pOutDev)->ImplGetGraphics();
+ pGraphics = pOutDev->mpGraphics;
+ if ( pGraphics )
+ mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount );
+ else
+ mpVirDev = NULL;
+ if ( !mpVirDev )
+ GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
+#else
+ if( ! pRemoteVirdevCache )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ pRemoteVirdevCache = new ::vcl::InterfacePairCache< ::com::sun::star::portal::client::XRmVirtualDevice, ::com::sun::star::portal::client::XRmOutputDevice >(
+ pSVData->mxMultiFactory,
+ ::rtl::OUString::createFromAscii( "OfficeVirtualDevice.stardiv.de" ),
+ 20, 10, 40 );
+ }
+
+ if( pOutDev->GetOutDevType() == OUTDEV_PRINTER || ! mpVirDev )
+ {
+ virdevInterfacePair aPair = pRemoteVirdevCache->takeInterface();
+ if( aPair.first.is() && aPair.second.is() )
+ {
+ if( ! mpVirDev )
+ mpVirDev = new RmVirtualDevice;
+ mpVirDev->SetInterface( aPair.first );
+ mpVirDev->Create( (ULONG) pOutDev, nDX, nDY, nBitCount );
+
+ if( ! mpGraphics )
+ mpGraphics = new ImplServerGraphics();
+ mpGraphics->SetInterface( aPair.second );
+ }
+ }
+ else
+ {
+ // this was done in ImpGetServerGraphics before
+ // and is now here because of interface caching
+ if( mpGraphics && mpGraphics->GetInterface().is() )
+ {
+ try
+ {
+ mpGraphics->GetInterface()->SetFillColor( mpGraphics->maFillColor.GetColor() );
+ }
+ catch (...)
+ {
+ if( mpGraphics )
+ delete mpGraphics, mpGraphics = NULL;
+
+ if( mpVirDev )
+ {
+ virdevInterfacePair aPair = pRemoteVirdevCache->takeInterface();
+ if( aPair.first.is() && aPair.second.is() )
+ {
+ mpVirDev->SetInterface( aPair.first );
+ mpVirDev->Create( (ULONG)NULL, mnOutWidth, mnOutHeight, mnBitCount );
+ mpGraphics = new ImplServerGraphics();
+ mpGraphics->SetInterface( aPair.second );
+ }
+ else
+ mpVirDev->SetInterface( REF( NMSP_CLIENT::XRmVirtualDevice )() );
+ }
+ }
+ }
+ ImplGetServerGraphics( TRUE );
+ }
+#endif
+
+ mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
+ mnOutWidth = nDX;
+ mnOutHeight = nDY;
+ mbScreenComp = TRUE;
+
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ mbScreenComp = FALSE;
+ else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
+ mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;
+
+ meOutDevType = OUTDEV_VIRDEV;
+ mbDevOutput = TRUE;
+ mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mnDPIX = pOutDev->mnDPIX;
+ mnDPIY = pOutDev->mnDPIY;
+ maFont = pOutDev->maFont;
+
+ // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
+ SetBackground( Wallpaper( Color( COL_WHITE ) ) );
+ Erase();
+
+ // VirDev in Liste eintragen
+ mpNext = pSVData->maGDIData.mpFirstVirDev;
+ mpPrev = NULL;
+ if ( mpNext )
+ mpNext->mpPrev = this;
+ else
+ pSVData->maGDIData.mpLastVirDev = this;
+ pSVData->maGDIData.mpFirstVirDev = this;
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::VirtualDevice( USHORT nBitCount )
+ : mpVirDev( NULL )
+{
+ DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );
+
+ ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
+ : mpVirDev( NULL )
+{
+ DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );
+
+ ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::~VirtualDevice()
+{
+ DBG_TRACE( "VirtualDevice::~VirtualDevice()" );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+
+ if ( mpVirDev )
+ pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
+#else
+ if ( pRemoteVirdevCache && mpVirDev && mpGraphics )
+ {
+ virdevInterfacePair aPair( mpVirDev->GetInterface(), mpGraphics->GetInterface() );
+ aPair.first->Create( 0, 0, 0, 0 );
+ pRemoteVirdevCache->putInterface( aPair );
+ }
+
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+ ImplReleaseServerGraphics();
+ delete mpVirDev;
+ delete mpGraphics;
+#endif
+
+ // VirDev aus der Liste eintragen
+ if( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ pSVData->maGDIData.mpFirstVirDev = mpNext;
+
+ if( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ pSVData->maGDIData.mpLastVirDev = mpPrev;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
+{
+ DBG_TRACE3( "VirtualDevice::SetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );
+
+ if ( !mpVirDev )
+ return FALSE;
+ else if ( rNewSize == GetOutputSizePixel() )
+ {
+ if ( bErase )
+ Erase();
+ return TRUE;
+ }
+
+#ifdef REMOTE_APPSERVER
+ long nOldWidth = mnOutWidth, nOldHeight = mnOutHeight;
+
+ try
+ {
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ mpVirDev->ResizeOutputSizePixel( mnOutWidth, mnOutHeight );
+ }
+ catch (...)
+ {
+ delete mpVirDev, mpVirDev = NULL;
+ ImplInitVirDev( NULL, mnOutWidth, mnOutHeight, mnBitCount );
+ }
+
+ if( bErase )
+ Erase();
+ else
+ {
+ if ( nOldWidth < mnOutWidth )
+ Erase( Rectangle( Point( nOldWidth, 0 ), Size( mnOutWidth-nOldWidth, Max( nOldHeight, mnOutHeight ) ) ) );
+ if ( nOldHeight< mnOutHeight )
+ Erase( Rectangle( Point( 0, nOldHeight ), Size( Max( nOldWidth, mnOutWidth ), mnOutHeight-nOldHeight ) ) );
+ }
+
+ return TRUE;
+#else
+ BOOL bRet;
+ long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();
+
+ if ( nNewWidth < 1 )
+ nNewWidth = 1;
+
+ if ( nNewHeight < 1 )
+ nNewHeight = 1;
+
+ if ( bErase )
+ {
+ bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );
+
+ if ( bRet )
+ {
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ Erase();
+ }
+ }
+ else
+ {
+ SalVirtualDevice* pNewVirDev;
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return FALSE;
+ }
+
+ pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
+ if ( pNewVirDev )
+ {
+ SalGraphics* pGraphics = pNewVirDev->GetGraphics();
+ if ( pGraphics )
+ {
+ SalTwoRect aPosAry;
+ long nWidth;
+ long nHeight;
+ if ( mnOutWidth < nNewWidth )
+ nWidth = mnOutWidth;
+ else
+ nWidth = nNewWidth;
+ if ( mnOutHeight < nNewHeight )
+ nHeight = mnOutHeight;
+ else
+ nHeight = nNewHeight;
+ aPosAry.mnSrcX = 0;
+ aPosAry.mnSrcY = 0;
+ aPosAry.mnSrcWidth = nWidth;
+ aPosAry.mnSrcHeight = nHeight;
+ aPosAry.mnDestX = 0;
+ aPosAry.mnDestY = 0;
+ aPosAry.mnDestWidth = nWidth;
+ aPosAry.mnDestHeight = nHeight;
+
+ pGraphics->CopyBits( &aPosAry, mpGraphics );
+ pNewVirDev->ReleaseGraphics( pGraphics );
+ ImplReleaseGraphics();
+ pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
+ mpVirDev = pNewVirDev;
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ bRet = TRUE;
+ }
+ else
+ {
+ bRet = FALSE;
+ pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
+ }
+ }
+ else
+ bRet = FALSE;
+ }
+
+ return bRet;
+#endif
+}
+
diff --git a/vcl/source/gdi/wall.cxx b/vcl/source/gdi/wall.cxx
new file mode 100644
index 000000000000..64eb82b23585
--- /dev/null
+++ b/vcl/source/gdi/wall.cxx
@@ -0,0 +1,616 @@
+/*************************************************************************
+ *
+ * $RCSfile: wall.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WALL_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_WALL_HXX
+#include <wall.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Wallpaper );
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::ImplWallpaper() :
+ maColor( COL_TRANSPARENT )
+{
+ mnRefCount = 1;
+ mpBitmap = NULL;
+ mpCache = NULL;
+ mpGradient = NULL;
+ mpRect = NULL;
+ meStyle = WALLPAPER_NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::ImplWallpaper( const ImplWallpaper& rImplWallpaper ) :
+ maColor( rImplWallpaper.maColor )
+{
+ mnRefCount = 1;
+ meStyle = rImplWallpaper.meStyle;
+
+ if ( rImplWallpaper.mpBitmap )
+ mpBitmap = new BitmapEx( *rImplWallpaper.mpBitmap );
+ else
+ mpBitmap = NULL;
+ if( rImplWallpaper.mpCache )
+ mpCache = new BitmapEx( *rImplWallpaper.mpCache );
+ else
+ mpCache = NULL;
+ if ( rImplWallpaper.mpGradient )
+ mpGradient = new Gradient( *rImplWallpaper.mpGradient );
+ else
+ mpGradient = NULL;
+ if ( rImplWallpaper.mpRect )
+ mpRect = new Rectangle( *rImplWallpaper.mpRect );
+ else
+ mpRect = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::~ImplWallpaper()
+{
+ delete mpBitmap;
+ delete mpCache;
+ delete mpGradient;
+ delete mpRect;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWallpaper::ImplSetCachedBitmap( BitmapEx& rBmp )
+{
+ if( !mpCache )
+ mpCache = new BitmapEx( rBmp );
+ else
+ *mpCache = rBmp;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWallpaper::ImplReleaseCachedBitmap()
+{
+ delete mpCache;
+ mpCache = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplWallpaper& rImplWallpaper )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ delete rImplWallpaper.mpRect;
+ rImplWallpaper.mpRect = NULL;
+
+ delete rImplWallpaper.mpGradient;
+ rImplWallpaper.mpGradient = NULL;
+
+ delete rImplWallpaper.mpBitmap;
+ rImplWallpaper.mpBitmap = NULL;
+
+ // version 1
+ rIStm >> rImplWallpaper.maColor;
+ rIStm >> nTmp16; rImplWallpaper.meStyle = (WallpaperStyle) nTmp16;
+
+ // version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ BOOL bRect, bGrad, bBmp, bDummy;
+
+ rIStm >> bRect >> bGrad >> bBmp >> bDummy >> bDummy >> bDummy;
+
+ if( bRect )
+ {
+ rImplWallpaper.mpRect = new Rectangle;
+ rIStm >> *rImplWallpaper.mpRect;
+ }
+
+ if( bGrad )
+ {
+ rImplWallpaper.mpGradient = new Gradient;
+ rIStm >> *rImplWallpaper.mpGradient;
+ }
+
+ if( bBmp )
+ {
+ rImplWallpaper.mpBitmap = new BitmapEx;
+ rIStm >> *rImplWallpaper.mpBitmap;
+ }
+
+ // version 3 (new color format)
+ if( aCompat.GetVersion() >= 3 )
+ {
+ rImplWallpaper.maColor.Read( rIStm, TRUE );
+ }
+ }
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplWallpaper& rImplWallpaper )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 3 );
+ BOOL bRect = ( rImplWallpaper.mpRect != NULL );
+ BOOL bGrad = ( rImplWallpaper.mpGradient != NULL );
+ BOOL bBmp = ( rImplWallpaper.mpBitmap != NULL );
+ BOOL bDummy = FALSE;
+
+ // version 1
+ rOStm << rImplWallpaper.maColor << (UINT16) rImplWallpaper.meStyle;
+
+ // version 2
+ rOStm << bRect << bGrad << bBmp << bDummy << bDummy << bDummy;
+
+ if( bRect )
+ rOStm << *rImplWallpaper.mpRect;
+
+ if( bGrad )
+ rOStm << *rImplWallpaper.mpGradient;
+
+ if( bBmp )
+ rOStm << *rImplWallpaper.mpBitmap;
+
+ // version 3 (new color format)
+ ( (Color&) rImplWallpaper.maColor ).Write( rOStm, TRUE );
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+inline void Wallpaper::ImplMakeUnique( BOOL bReleaseCache )
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplWallpaper->mnRefCount != 1 )
+ {
+ if ( mpImplWallpaper->mnRefCount )
+ mpImplWallpaper->mnRefCount--;
+ mpImplWallpaper = new ImplWallpaper( *(mpImplWallpaper) );
+ }
+
+ if( bReleaseCache )
+ mpImplWallpaper->ImplReleaseCachedBitmap();
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper()
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+#ifdef WIN
+ static ImplWallpaper _near aStaticImplWallpaper;
+#else
+ static ImplWallpaper aStaticImplWallpaper;
+#endif
+
+ aStaticImplWallpaper.mnRefCount = 0;
+ mpImplWallpaper = &aStaticImplWallpaper;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Wallpaper& rWallpaper )
+{
+ DBG_CTOR( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+ DBG_ASSERT( rWallpaper.mpImplWallpaper->mnRefCount < 0xFFFE, "Wallpaper: RefCount overflow" );
+
+ // Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplWallpaper = rWallpaper.mpImplWallpaper;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplWallpaper->mnRefCount )
+ mpImplWallpaper->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Color& rColor )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->maColor = rColor;
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const BitmapEx& rBmpEx )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->mpBitmap = new BitmapEx( rBmpEx );
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Gradient& rGradient )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->mpGradient = new Gradient( rGradient );
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::~Wallpaper()
+{
+ DBG_DTOR( Wallpaper, NULL );
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplWallpaper->mnRefCount )
+ {
+ if ( mpImplWallpaper->mnRefCount == 1 )
+ delete mpImplWallpaper;
+ else
+ mpImplWallpaper->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique();
+ mpImplWallpaper->maColor = rColor;
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetStyle( WallpaperStyle eStyle )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique( FALSE );
+ mpImplWallpaper->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetBitmap( const BitmapEx& rBitmap )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( !rBitmap )
+ {
+ if ( mpImplWallpaper->mpBitmap )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpBitmap;
+ mpImplWallpaper->mpBitmap = NULL;
+ }
+ }
+ else
+ {
+ ImplMakeUnique();
+ if ( mpImplWallpaper->mpBitmap )
+ *(mpImplWallpaper->mpBitmap) = rBitmap;
+ else
+ mpImplWallpaper->mpBitmap = new BitmapEx( rBitmap );
+ }
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetBitmap()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpBitmap )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpBitmap;
+ mpImplWallpaper->mpBitmap = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BitmapEx Wallpaper::GetBitmap() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpBitmap )
+ return *(mpImplWallpaper->mpBitmap);
+ else
+ {
+ BitmapEx aBmp;
+ return aBmp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetGradient( const Gradient& rGradient )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique();
+
+ if ( mpImplWallpaper->mpGradient )
+ *(mpImplWallpaper->mpGradient) = rGradient;
+ else
+ mpImplWallpaper->mpGradient = new Gradient( rGradient );
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetGradient()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpGradient )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpGradient;
+ mpImplWallpaper->mpGradient = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Gradient Wallpaper::GetGradient() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpGradient )
+ return *(mpImplWallpaper->mpGradient);
+ else
+ {
+ Gradient aGradient;
+ return aGradient;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetRect( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique( FALSE );
+
+ if ( rRect.IsEmpty() )
+ {
+ if ( mpImplWallpaper->mpRect )
+ {
+ delete mpImplWallpaper->mpRect;
+ mpImplWallpaper->mpRect = NULL;
+ }
+ }
+ else
+ {
+ if ( mpImplWallpaper->mpRect )
+ *(mpImplWallpaper->mpRect) = rRect;
+ else
+ mpImplWallpaper->mpRect = new Rectangle( rRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetRect()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpRect )
+ {
+ ImplMakeUnique( FALSE );
+ delete mpImplWallpaper->mpRect;
+ mpImplWallpaper->mpRect = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Wallpaper::GetRect() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpRect )
+ return *(mpImplWallpaper->mpRect);
+ else
+ {
+ Rectangle aRect;
+ return aRect;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::IsFixed() const
+{
+ if ( mpImplWallpaper->meStyle == WALLPAPER_NULL )
+ return FALSE;
+ else
+ return (!mpImplWallpaper->mpBitmap && !mpImplWallpaper->mpGradient);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::IsScrollable() const
+{
+ if ( mpImplWallpaper->meStyle == WALLPAPER_NULL )
+ return FALSE;
+ else if ( !mpImplWallpaper->mpBitmap && !mpImplWallpaper->mpGradient )
+ return TRUE;
+ else if ( mpImplWallpaper->mpBitmap )
+ return (mpImplWallpaper->meStyle == WALLPAPER_TILE);
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper& Wallpaper::operator=( const Wallpaper& rWallpaper )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+ DBG_ASSERT( rWallpaper.mpImplWallpaper->mnRefCount < 0xFFFE, "Wallpaper: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rWallpaper.mpImplWallpaper->mnRefCount )
+ rWallpaper.mpImplWallpaper->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplWallpaper->mnRefCount )
+ {
+ if ( mpImplWallpaper->mnRefCount == 1 )
+ delete mpImplWallpaper;
+ else
+ mpImplWallpaper->mnRefCount--;
+ }
+
+ mpImplWallpaper = rWallpaper.mpImplWallpaper;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::operator==( const Wallpaper& rWallpaper ) const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+
+ if ( mpImplWallpaper == rWallpaper.mpImplWallpaper )
+ return TRUE;
+
+ if ( ( mpImplWallpaper->meStyle != rWallpaper.mpImplWallpaper->meStyle ) ||
+ ( mpImplWallpaper->maColor != rWallpaper.mpImplWallpaper->maColor ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpRect != rWallpaper.mpImplWallpaper->mpRect
+ && ( !mpImplWallpaper->mpRect
+ || !rWallpaper.mpImplWallpaper->mpRect
+ || *(mpImplWallpaper->mpRect) != *(rWallpaper.mpImplWallpaper->mpRect) ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpBitmap != rWallpaper.mpImplWallpaper->mpBitmap
+ && ( !mpImplWallpaper->mpBitmap
+ || !rWallpaper.mpImplWallpaper->mpBitmap
+ || *(mpImplWallpaper->mpBitmap) != *(rWallpaper.mpImplWallpaper->mpBitmap) ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpGradient != rWallpaper.mpImplWallpaper->mpGradient
+ && ( !mpImplWallpaper->mpGradient
+ || !rWallpaper.mpImplWallpaper->mpGradient
+ || *(mpImplWallpaper->mpGradient) != *(rWallpaper.mpImplWallpaper->mpGradient) ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Wallpaper& rWallpaper )
+{
+ rWallpaper.ImplMakeUnique();
+ return( rIStm >> *rWallpaper.mpImplWallpaper );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Wallpaper& rWallpaper )
+{
+ return( rOStm << *rWallpaper.mpImplWallpaper );
+}
diff --git a/vcl/source/helper/evntpost.cxx b/vcl/source/helper/evntpost.cxx
new file mode 100644
index 000000000000..b19c5b190a1a
--- /dev/null
+++ b/vcl/source/helper/evntpost.cxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * $RCSfile: evntpost.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#pragma hdrstop
+
+#include "evntpost.hxx"
+#include "svapp.hxx"
+
+namespace vcl
+{
+
+EventPoster::EventPoster( const Link& rLink )
+ : m_aLink(rLink)
+ , m_nId(0)
+{
+}
+
+EventPoster::~EventPoster()
+{
+ if ( m_nId )
+ GetpApp()->RemoveUserEvent( m_nId );
+}
+
+void EventPoster::Post( UserEvent* pEvent )
+
+{
+ m_nId = GetpApp()->PostUserEvent( ( LINK( this, EventPoster, DoEvent_Impl ) ), pEvent );
+}
+
+IMPL_LINK_INLINE_START( EventPoster, DoEvent_Impl, UserEvent*, pEvent )
+{
+ m_nId = 0;
+ m_aLink.Call( pEvent );
+ return 0;
+}
+IMPL_LINK_INLINE_END( EventPoster, DoEvent_Impl, UserEvent*, pEvent )
+
+};
diff --git a/vcl/source/helper/makefile.mk b/vcl/source/helper/makefile.mk
new file mode 100644
index 000000000000..eeec5a8f0a1d
--- /dev/null
+++ b/vcl/source/helper/makefile.mk
@@ -0,0 +1,100 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+ENABLE_EXCEPTIONS=TRUE
+PRJNAME=vcl
+TARGET=helper
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES=\
+ $(SLO)$/sunowrap.obj \
+ $(SLO)$/atom.obj \
+ $(SLO)$/threadex.obj
+
+.IF "$(GUI)" == "UNX"
+SLOFILES+=\
+ $(SLO)$/ppdparser.obj \
+ $(SLO)$/strhelper.obj
+.ENDIF
+
+# NETBSD: somewhere we have to instantiate the static data members.
+# NETBSD-1.2.1 doesn't know about weak symbols so the default mechanism for GCC won't work.
+# SCO and MACOSX: the linker does know about weak symbols, but we can't ignore multiple defined symbols
+.IF "$(OS)"=="NETBSD" || "$(OS)"=="SCO" || "$(OS)$(COM)"=="OS2GCC" || "$(OS)"=="MACOSX"
+SLOFILES+=$(SLO)$/staticmbhelper.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
diff --git a/vcl/source/helper/threadex.cxx b/vcl/source/helper/threadex.cxx
new file mode 100644
index 000000000000..d33be4f6f355
--- /dev/null
+++ b/vcl/source/helper/threadex.cxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * $RCSfile: threadex.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <threadex.hxx>
+#include <svapp.hxx>
+
+using namespace vcl;
+
+ThreadExecutor::ThreadExecutor()
+{
+ m_aFinish = osl_createCondition();
+ m_aThread = NULL;
+}
+
+ThreadExecutor::~ThreadExecutor()
+{
+ osl_destroyCondition( m_aFinish );
+ if( m_aThread )
+ osl_freeThreadHandle( m_aThread );
+}
+
+void ThreadExecutor::worker( void* pInstance )
+{
+ ThreadExecutor* pThis = ((ThreadExecutor*)pInstance);
+ pThis->m_nReturn = pThis->doIt();
+ osl_setCondition( pThis->m_aFinish );
+}
+
+long ThreadExecutor::execute()
+{
+ osl_resetCondition( m_aFinish );
+ if( m_aThread )
+ osl_freeThreadHandle( m_aThread ), m_aThread = NULL;
+ m_aThread = osl_createThread( worker, this );
+ while( ! osl_checkCondition( m_aFinish ) )
+ Application::Reschedule();
+ return m_nReturn;
+}
+
+
+SolarThreadExecutor::SolarThreadExecutor()
+{
+ m_aFinish = osl_createCondition();
+}
+
+SolarThreadExecutor::~SolarThreadExecutor()
+{
+ osl_destroyCondition( m_aFinish );
+}
+
+IMPL_LINK( SolarThreadExecutor, worker, void*, pDummy )
+{
+ m_nReturn = doIt();
+ osl_setCondition( m_aFinish );
+ return m_nReturn;
+}
+
+long SolarThreadExecutor::execute()
+{
+ if( ::vos::OThread::getCurrentIdentifier() == Application::GetMainThreadIdentifier() )
+ {
+ m_nReturn = doIt();
+ osl_setCondition( m_aFinish );
+ }
+ else
+ {
+ osl_resetCondition( m_aFinish );
+ Application::PostUserEvent( LINK( this, SolarThreadExecutor, worker ) );
+ osl_waitCondition( m_aFinish, NULL );
+ }
+ return m_nReturn;
+}
diff --git a/vcl/source/src/btntext.src b/vcl/source/src/btntext.src
new file mode 100644
index 000000000000..51f9d9df8bd0
--- /dev/null
+++ b/vcl/source/src/btntext.src
@@ -0,0 +1,290 @@
+/*************************************************************************
+ *
+ * $RCSfile: btntext.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BTNTEXT_SRC
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+
+String SV_BUTTONTEXT_OK
+{
+ Text = "OK";
+ Text [ English ] = "OK";
+ TEXT[ italian ] = "OK";
+ TEXT[ portuguese_brazilian ] = "OK";
+ TEXT[ portuguese ] = "OK";
+ TEXT[ danish ] = "OK";
+ TEXT[ french ] = "OK";
+ TEXT[ swedish ] = "OK";
+ TEXT[ dutch ] = "OK";
+ TEXT[ spanish ] = "Aceptar";
+ TEXT[ english_us ] = "OK";
+ TEXT[ russian ] = "OK";
+ TEXT[ polish ] = "OK";
+ TEXT[ japanese ] = "OK";
+ TEXT[ chinese_simplified ] = "È·¶¨";
+ TEXT[ chinese_traditional ] = "½T©w";
+ TEXT[ arabic ] = "ÍÓäÇð";
+ TEXT[ dutch ] = "OK";
+ TEXT[ chinese_simplified ] = "È·¶¨";
+ TEXT[ greek ] = "OK";
+ TEXT[ korean ] = "È®ÀÎ";
+ TEXT[ turkish ] = "Tamam";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_CANCEL
+{
+ Text = "Abbrechen" ;
+ Text [ English ] = "Cancel" ;
+ TEXT[ italian ] = "Annulla";
+ TEXT[ portuguese_brazilian ] = "Cancelar";
+ TEXT[ portuguese ] = "Cancelar";
+ TEXT[ danish ] = "Annuller";
+ TEXT[ french ] = "Annuler";
+ TEXT[ swedish ] = "Avbryt";
+ TEXT[ dutch ] = "Annuleren";
+ TEXT[ spanish ] = "Cancelar";
+ TEXT[ english_us ] = "Cancel";
+ TEXT[ russian ] = "Îòìåíà";
+ TEXT[ polish ] = "Anuluj";
+ TEXT[ japanese ] = "·¬Ý¾Ù";
+ TEXT[ chinese_simplified ] = "È¡Ïû";
+ TEXT[ chinese_traditional ] = "¨ú®ø";
+ TEXT[ arabic ] = "ÅáÛÇÁ ÇáÃãÑ";
+ TEXT[ dutch ] = "Annuleren";
+ TEXT[ chinese_simplified ] = "È¡Ïû";
+ TEXT[ greek ] = "Áêýñùóç";
+ TEXT[ korean ] = "Ãë¼Ò";
+ TEXT[ turkish ] = "Ýptal";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_YES
+{
+ Text = "~Ja";
+ Text [ English ] = "~Yes";
+ TEXT[ italian ] = "Sì";
+ TEXT[ portuguese_brazilian ] = "~Sim";
+ TEXT[ portuguese ] = "~Sim";
+ TEXT[ danish ] = "~Ja";
+ TEXT[ french ] = "~Oui";
+ TEXT[ swedish ] = "~Ja";
+ TEXT[ dutch ] = "~Ja";
+ TEXT[ spanish ] = "~Sí";
+ TEXT[ english_us ] = "~Yes";
+ TEXT[ russian ] = "Äà";
+ TEXT[ polish ] = "~Tak";
+ TEXT[ japanese ] = "‚Í‚¢(~Y)";
+ TEXT[ chinese_simplified ] = "ÊÇ(~Y)";
+ TEXT[ chinese_traditional ] = "¬O(~Y)";
+ TEXT[ arabic ] = "äÚã";
+ TEXT[ dutch ] = "~Ja";
+ TEXT[ chinese_simplified ] = "ÊÇ(~Y)";
+ TEXT[ greek ] = "Íáé";
+ TEXT[ korean ] = "³×(~Y)";
+ TEXT[ turkish ] = "~Evet";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_NO
+{
+ Text = "~Nein";
+ Text [ English ] = "~No";
+ TEXT[ italian ] = "No";
+ TEXT[ portuguese_brazilian ] = "~Não";
+ TEXT[ portuguese ] = "~Não";
+ TEXT[ danish ] = "~Nej";
+ TEXT[ french ] = "~Non";
+ TEXT[ swedish ] = "~Nej";
+ TEXT[ dutch ] = "~Nee";
+ TEXT[ spanish ] = "~No";
+ TEXT[ english_us ] = "~No";
+ TEXT[ russian ] = "Íåò";
+ TEXT[ polish ] = "~Nie";
+ TEXT[ japanese ] = "‚¢‚¢‚¦(~N)";
+ TEXT[ chinese_simplified ] = "·ñ(~N)";
+ TEXT[ chinese_traditional ] = "§_(~N)";
+ TEXT[ arabic ] = "áÇ";
+ TEXT[ dutch ] = "~Nee";
+ TEXT[ chinese_simplified ] = "·ñ(~N)";
+ TEXT[ greek ] = "¼÷é";
+ TEXT[ korean ] = "¾Æ´Ï¿À(~N)";
+ TEXT[ turkish ] = "~Hayýr";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_RETRY
+{
+ Text = "~Wiederholen";
+ Text [ English ] = "~Retry";
+ TEXT[ italian ] = "Riprova";
+ TEXT[ portuguese_brazilian ] = "~Repetir";
+ TEXT[ portuguese ] = "~Repetir";
+ TEXT[ danish ] = "Prøv igen";
+ TEXT[ french ] = "~Réessayer";
+ TEXT[ swedish ] = "~Upprepa";
+ TEXT[ dutch ] = "H~erhalen";
+ TEXT[ spanish ] = "~Reintentar";
+ TEXT[ english_us ] = "~Retry";
+ TEXT[ russian ] = "Ïîâòîðèòü";
+ TEXT[ polish ] = "P~onów";
+ TEXT[ japanese ] = "‚â‚è’¼‚µ(~R)";
+ TEXT[ chinese_simplified ] = "ÖØÊÔ(~R)";
+ TEXT[ chinese_traditional ] = "­«¸Õ(~R)";
+ TEXT[ arabic ] = "ÅÚÇÏÉ ÇáãÍÇæáÉ";
+ TEXT[ dutch ] = "H~erhalen";
+ TEXT[ chinese_simplified ] = "ÖØÊÔ(~R)";
+ TEXT[ greek ] = "ÅðáíÜëçøç";
+ TEXT[ korean ] = "´Ù½Ã ½Ãµµ(~R)";
+ TEXT[ turkish ] = "Y~inele";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_HELP
+{
+ Text = "~Hilfe";
+ Text [ English ] = "~Help";
+ TEXT[ italian ] = "?";
+ TEXT[ portuguese_brazilian ] = "Aj~uda";
+ TEXT[ portuguese ] = "Aj~uda";
+ TEXT[ danish ] = "~Hjælp";
+ TEXT[ french ] = "Ai~de";
+ TEXT[ swedish ] = "~Hjälp";
+ TEXT[ dutch ] = "~Help";
+ TEXT[ spanish ] = "Ay~uda";
+ TEXT[ english_us ] = "~Help";
+ TEXT[ russian ] = "Ñï~ðàâêà";
+ TEXT[ polish ] = "~Pomoc";
+ TEXT[ japanese ] = "ÍÙÌß(~H)";
+ TEXT[ chinese_simplified ] = "ÇóÖú(~H)";
+ TEXT[ chinese_traditional ] = "»¡©ú(~H)";
+ TEXT[ arabic ] = "ãÓÇÚÏÉ";
+ TEXT[ dutch ] = "~Help";
+ TEXT[ chinese_simplified ] = "ÇóÖú(~H)";
+ TEXT[ greek ] = "ÂïÞèåéá";
+ TEXT[ korean ] = "µµ¿ò¸»(~H)";
+ TEXT[ turkish ] = "~Yardým";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_BUTTONTEXT_MORE
+{
+ Text = "~Zusätze";
+ Text [ English ] = "~More";
+ TEXT[ italian ] = "E~xtra";
+ TEXT[ portuguese_brazilian ] = "~Mais";
+ TEXT[ portuguese ] = "~Opções";
+ TEXT[ danish ] = "~Flere";
+ TEXT[ french ] = "O~ptions";
+ TEXT[ swedish ] = "~Fler";
+ TEXT[ dutch ] = "~Overige";
+ TEXT[ spanish ] = "~Opciones";
+ TEXT[ english_us ] = "~More";
+ TEXT[ russian ] = "Áîëüøå";
+ TEXT[ polish ] = "~Dodatki";
+ TEXT[ japanese ] = "’ljÁ(~M)";
+ TEXT[ chinese_simplified ] = "ÆäËû(~M)";
+ TEXT[ chinese_traditional ] = "¨ä¥L(~M)";
+ TEXT[ arabic ] = "ÅÖÇÝÇÊ";
+ TEXT[ dutch ] = "~Overige";
+ TEXT[ chinese_simplified ] = "ÆäËû(~M)";
+ TEXT[ greek ] = "Ðñüóèåôá";
+ TEXT[ korean ] = "ÀÚ¼¼È÷(~M)";
+ TEXT[ turkish ] = "A~yrýntýlar";
+ TEXT[ language_user1 ] = " ";
+};
+
+/* HelpTexte, die wir derzeit nicht mehr verwenden:
+SV_BUTTONHELPTEXT_OK
+{
+ Text = "Schließt dieses Dialogfeld und speichert alle vorgenommenen Änderungen." ;
+ Text [ English ] = "Closes this dialog box and save any changes you have made." ;
+};
+
+SV_BUTTONHELPTEXT_CANCEL
+{
+ Text = "Schließt dieses Dialogfeld, ohne Ihre Änderungen zu speichern." ;
+ Text [ English ] = "Closes this dialog box without saving any changes you have made." ;
+};
+
+SV_BUTTONHELPTEXT_HELP
+{
+ Text = "Zeigt Hilfe zu diesem Fenster an." ;
+ Text [ English ] = "Shows help for the current window." ;
+};
+
+SV_BUTTONHELPTEXT_MORE
+{
+ Text = "Zeigt weitere EinstellmÖglichkeiten an oder versteckt diese wieder." ;
+ Text [ English ] = "Shows more Options or hide these options again." ;
+};
+
+Finnische-Texte:
+OK OK
+CANCEL Peruuta
+HELP ~Ohje
+MORE ~Enemmän
+YES ~Kyllä
+NO ~Ei
+RETRY ~Yritäuudelleen
+*/
diff --git a/vcl/source/src/helptext.src b/vcl/source/src/helptext.src
new file mode 100644
index 000000000000..41f6eccace76
--- /dev/null
+++ b/vcl/source/src/helptext.src
@@ -0,0 +1,367 @@
+/*************************************************************************
+ *
+ * $RCSfile: helptext.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_HELPTEXT_SRC
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+
+String SV_HELPTEXT_CLOSE
+{
+ Text = "Schließen" ;
+ Text [ English ] = "Close" ;
+ TEXT[ italian ] = "Chiudi";
+ TEXT[ portuguese_brazilian ] = "Schließen";
+ TEXT[ portuguese ] = "Fechar";
+ TEXT[ danish ] = "Luk";
+ TEXT[ french ] = "Fermer";
+ TEXT[ swedish ] = "Stäng";
+ TEXT[ dutch ] = "Sluiten";
+ TEXT[ spanish ] = "Cerrar";
+ TEXT[ english_us ] = "Close";
+ TEXT[ russian ] = "Çàêðûòü";
+ TEXT[ polish ] = "Zamknij";
+ TEXT[ japanese ] = "I—¹";
+ TEXT[ chinese_simplified ] = "¹Ø±Õ";
+ TEXT[ chinese_traditional ] = "Ãö³¬";
+ TEXT[ greek ] = "Êëåßóéìï";
+ TEXT[ korean ] = "´Ý±â";
+ TEXT[ arabic ] = "ÅÛáÇÞ";
+ TEXT[ turkish ] = "Kapat";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_MINIMIZE
+{
+ Text = "Minimieren" ;
+ Text [ English ] = "Minimize" ;
+ TEXT[ italian ] = "Riduci";
+ TEXT[ portuguese_brazilian ] = "Minimieren";
+ TEXT[ portuguese ] = "Minimizar";
+ TEXT[ danish ] = "Minimer";
+ TEXT[ french ] = "Réduire";
+ TEXT[ swedish ] = "Minimera";
+ TEXT[ dutch ] = "Minimaliseren";
+ TEXT[ spanish ] = "Minimizar";
+ TEXT[ english_us ] = "Minimize";
+ TEXT[ russian ] = "Ñâåðíóòü";
+ TEXT[ polish ] = "Minimalizuj";
+ TEXT[ japanese ] = "Ŭ‰»";
+ TEXT[ chinese_simplified ] = "×îС»¯";
+ TEXT[ chinese_traditional ] = "³Ì¤p¤Æ";
+ TEXT[ greek ] = "Åëá÷éóôïðïßçóç";
+ TEXT[ korean ] = "ÃÖ¼ÒÈ­";
+ TEXT[ arabic ] = "ÇáÍÏ ÇáÃÏäì";
+ TEXT[ turkish ] = "Simge durumuna küçült";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_MAXIMIZE
+{
+ Text = "Maximieren" ;
+ Text [ English ] = "Maximize" ;
+ TEXT[ italian ] = "Ingrandire";
+ TEXT[ portuguese_brazilian ] = "Maximieren";
+ TEXT[ portuguese ] = "Maximizar";
+ TEXT[ danish ] = "Maksimer";
+ TEXT[ french ] = "Agrandir";
+ TEXT[ swedish ] = "Maximera";
+ TEXT[ dutch ] = "Maximeren";
+ TEXT[ spanish ] = "Maximizar";
+ TEXT[ english_us ] = "Maximize";
+ TEXT[ russian ] = "Ðàçâåðíóòü";
+ TEXT[ polish ] = "Maksymalizuj";
+ TEXT[ japanese ] = "ő剻";
+ TEXT[ chinese_simplified ] = "×î´ó»¯";
+ TEXT[ chinese_traditional ] = "³Ì¤j¤Æ";
+ TEXT[ greek ] = "Ìåãéóôïðïßçóç";
+ TEXT[ korean ] = "ÃÖ´ëÈ­";
+ TEXT[ arabic ] = "ÇáÍÏ ÇáÃÞÕì";
+ TEXT[ turkish ] = "Ekraný kapla";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_RESTORE
+{
+ Text = "Wiederherstellen" ;
+ Text [ English ] = "Restore" ;
+ TEXT[ italian ] = "Ripristina";
+ TEXT[ portuguese_brazilian ] = "Wiederherstellen";
+ TEXT[ portuguese ] = "Restaurar";
+ TEXT[ danish ] = "Gendan";
+ TEXT[ french ] = "Restaurer";
+ TEXT[ swedish ] = "Återställ";
+ TEXT[ dutch ] = "Herstellen";
+ TEXT[ spanish ] = "Restaurar";
+ TEXT[ english_us ] = "Restore";
+ TEXT[ russian ] = "Âîññòàíîâèòü";
+ TEXT[ polish ] = "Przywróæ";
+ TEXT[ japanese ] = "Œ³‚Ìó‘Ô‚É–ß‚·";
+ TEXT[ chinese_simplified ] = "»Ö¸´";
+ TEXT[ chinese_traditional ] = "«ì´_";
+ TEXT[ greek ] = "ÅðáíáöïñÜ";
+ TEXT[ korean ] = "º¹±¸";
+ TEXT[ arabic ] = "ÇÓÊÚÇÏÉ";
+ TEXT[ turkish ] = "Baþa al";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_ROLLDOWN
+{
+ Text = "Aufklappen" ;
+ Text [ English ] = "Roll Down" ;
+ TEXT[ italian ] = "Mostra";
+ TEXT[ portuguese_brazilian ] = "Aufklappen";
+ TEXT[ portuguese ] = "Abrir";
+ TEXT[ danish ] = "Klap ud";
+ TEXT[ french ] = "Agrandir";
+ TEXT[ swedish ] = "Visa";
+ TEXT[ dutch ] = "Openslaan";
+ TEXT[ spanish ] = "Mostrar";
+ TEXT[ english_us ] = "Drop down";
+ TEXT[ russian ] = "Ðàñêðûòü";
+ TEXT[ polish ] = "Otwórz";
+ TEXT[ japanese ] = "ŠJ‚¯‚é";
+ TEXT[ chinese_simplified ] = "ÏÔʾ";
+ TEXT[ chinese_traditional ] = "Åã¥Ü";
+ TEXT[ greek ] = "¢íïéãìá";
+ TEXT[ korean ] = "º¸À̱â";
+ TEXT[ arabic ] = "ÝÊÍ";
+ TEXT[ turkish ] = "Aç";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_ROLLUP
+{
+ Text = "Zuklappen" ;
+ Text [ English ] = "Roll Up" ;
+ TEXT[ italian ] = "Nascondi";
+ TEXT[ portuguese_brazilian ] = "Zuklappen";
+ TEXT[ portuguese ] = "Fechar";
+ TEXT[ danish ] = "Minimer";
+ TEXT[ french ] = "Réduire";
+ TEXT[ swedish ] = "Dölj";
+ TEXT[ dutch ] = "Dichtslaan";
+ TEXT[ spanish ] = "Ocultar";
+ TEXT[ english_us ] = "Roll up";
+ TEXT[ language_user1 ] = " ";
+ TEXT[ russian ] = "Çàêðûòü";
+ TEXT[ polish ] = "Ukryj";
+ TEXT[ japanese ] = "•Â‚¶‚é";
+ TEXT[ chinese_simplified ] = "ÒþÈë";
+ TEXT[ chinese_traditional ] = "Áô¤J";
+ TEXT[ greek ] = "Áðüêñõøç";
+ TEXT[ korean ] = "¼û±â±â";
+ TEXT[ arabic ] = "Øí";
+ TEXT[ turkish ] = "Kapat";
+};
+
+String SV_HELPTEXT_HELP
+{
+ Text = "Hilfe" ;
+ Text [ English ] = "Help" ;
+ TEXT[ italian ] = "Guida";
+ TEXT[ portuguese_brazilian ] = "Hilfe";
+ TEXT[ portuguese ] = "Ajuda";
+ TEXT[ danish ] = "Hjælp";
+ TEXT[ french ] = "Aide";
+ TEXT[ swedish ] = "Hjälp";
+ TEXT[ dutch ] = "Help";
+ TEXT[ spanish ] = "Ayuda";
+ TEXT[ english_us ] = "Help";
+ TEXT[ russian ] = "Ñïðàâêà";
+ TEXT[ polish ] = "Pomoc";
+ TEXT[ japanese ] = "ƒwƒ‹ƒv";
+ TEXT[ chinese_simplified ] = "ÇóÖú";
+ TEXT[ chinese_traditional ] = "»¡©ú";
+ TEXT[ greek ] = "ÂïÞèåéá";
+ TEXT[ korean ] = "µµ¿ò¸»";
+ TEXT[ arabic ] = "ãÓÇÚÏÉ";
+ TEXT[ turkish ] = "Yardým";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_ALWAYSVISIBLE
+{
+ Text = "Immer sichtbar" ;
+ Text [ English ] = "Always Visible" ;
+ TEXT[ italian ] = "Sempre visibile";
+ TEXT[ portuguese_brazilian ] = "Immer sichtbar";
+ TEXT[ portuguese ] = "Sempre visível";
+ TEXT[ danish ] = "Altid synlig";
+ TEXT[ french ] = "Toujours visible";
+ TEXT[ swedish ] = "Alltid synlig";
+ TEXT[ dutch ] = "Steeds zichtbaar";
+ TEXT[ spanish ] = "Siempre visible";
+ TEXT[ english_us ] = "Always visible";
+ TEXT[ russian ] = "Ïîêàçûâàòü âñåãäà";
+ TEXT[ polish ] = "Zawsze widoczny";
+ TEXT[ japanese ] = "‚¢‚Â‚àŒ©‚¦‚é";
+ TEXT[ chinese_simplified ] = "×ÜÊÇÏÔʾ";
+ TEXT[ chinese_traditional ] = "Á`¬OÅã¥Ü";
+ TEXT[ greek ] = "ÐÜíôá ïñáôÜ";
+ TEXT[ korean ] = "Ç×»ó º¸ÀÓ";
+ TEXT[ arabic ] = "ãÑÆí ÏÇÆãÇð";
+ TEXT[ turkish ] = "Daima görünür";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_FADEIN
+{
+ Text = "Einblenden" ;
+ Text [ English ] = "Fade In" ;
+ TEXT[ italian ] = "Mostra";
+ TEXT[ portuguese_brazilian ] = "Einblenden";
+ TEXT[ portuguese ] = "Mostrar";
+ TEXT[ danish ] = "Vis";
+ TEXT[ french ] = "Afficher";
+ TEXT[ swedish ] = "Visa";
+ TEXT[ dutch ] = "Weergeven";
+ TEXT[ spanish ] = "Mostrar";
+ TEXT[ english_us ] = "Show";
+ TEXT[ russian ] = "Ïîêàçàòü";
+ TEXT[ polish ] = "Poka¿";
+ TEXT[ japanese ] = "•\\Ž¦";
+ TEXT[ chinese_simplified ] = "ÏÔʾ";
+ TEXT[ chinese_traditional ] = "Åã¥Ü";
+ TEXT[ greek ] = "ÅìöÜíéóç";
+ TEXT[ korean ] = "º¸À̱â";
+ TEXT[ arabic ] = "ÅÙåÇÑ";
+ TEXT[ turkish ] = "Göster";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_FADEOUT
+{
+ Text = "Ausblenden" ;
+ Text [ English ] = "Fade Out" ;
+ TEXT[ italian ] = "Nascondi";
+ TEXT[ portuguese_brazilian ] = "Ausblenden";
+ TEXT[ portuguese ] = "Ocultar";
+ TEXT[ danish ] = "Skjul";
+ TEXT[ french ] = "Masquer";
+ TEXT[ swedish ] = "Dölj";
+ TEXT[ dutch ] = "Verbergen";
+ TEXT[ spanish ] = "Ocultar";
+ TEXT[ english_us ] = "Hide";
+ TEXT[ russian ] = "Ñêðûòü";
+ TEXT[ polish ] = "Ukryj";
+ TEXT[ japanese ] = "”ñ•\\Ž¦";
+ TEXT[ chinese_simplified ] = "ÒþÈë";
+ TEXT[ chinese_traditional ] = "Áô¤J";
+ TEXT[ greek ] = "Áðüêñõøç";
+ TEXT[ korean ] = "¼û±â±â";
+ TEXT[ arabic ] = "ÅÎÝÇÁ";
+ TEXT[ turkish ] = "Gizle";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_SPLITFLOATING
+{
+ Text = "Schwebend" ;
+ Text [ English ] = "Floating" ;
+ TEXT[ italian ] = "Fluttuante";
+ TEXT[ portuguese_brazilian ] = "Schwebend";
+ TEXT[ portuguese ] = "Flutuante";
+ TEXT[ danish ] = "Flydende";
+ TEXT[ french ] = "Flottante";
+ TEXT[ swedish ] = "Svävande";
+ TEXT[ dutch ] = "Zwevend";
+ TEXT[ spanish ] = "Flotando";
+ TEXT[ english_us ] = "Floating";
+ TEXT[ russian ] = "Çàâèñøèé";
+ TEXT[ polish ] = "P³ywaj¹cy";
+ TEXT[ japanese ] = "•‚“®";
+ TEXT[ chinese_simplified ] = "¸¡¶¯";
+ TEXT[ chinese_traditional ] = "¯B°Ê";
+ TEXT[ greek ] = "Êéíçôü";
+ TEXT[ korean ] = "°íÁ¤µÇÁö ¾ÊÀº";
+ TEXT[ arabic ] = "ÚÇÆã";
+ TEXT[ turkish ] = "Serbest";
+ TEXT[ language_user1 ] = " ";
+};
+
+String SV_HELPTEXT_SPLITFIXED
+{
+ Text = "Fixieren" ;
+ Text [ English ] = "Fixed" ;
+ TEXT[ italian ] = "Fissa";
+ TEXT[ portuguese_brazilian ] = "Fixieren";
+ TEXT[ portuguese ] = "Fixar";
+ TEXT[ danish ] = "Frys";
+ TEXT[ french ] = "Ancrée";
+ TEXT[ swedish ] = "Fixera";
+ TEXT[ dutch ] = "Fixeren";
+ TEXT[ spanish ] = "Fijar";
+ TEXT[ english_us ] = "Stick";
+ TEXT[ russian ] = "Ôèêñèðîâàòü";
+ TEXT[ polish ] = "Przytwierdzony";
+ TEXT[ japanese ] = "΁Տ";
+ TEXT[ chinese_simplified ] = "¹Ì¶¨";
+ TEXT[ chinese_traditional ] = "©T©w";
+ TEXT[ greek ] = "Ðáãßùóç";
+ TEXT[ korean ] = "°íÁ¤";
+ TEXT[ arabic ] = "ÊËÈíÊ";
+ TEXT[ turkish ] = "Sabitle";
+ TEXT[ language_user1 ] = " ";
+};
+
diff --git a/vcl/source/src/images.src b/vcl/source/src/images.src
new file mode 100644
index 000000000000..163cb4dc6e00
--- /dev/null
+++ b/vcl/source/src/images.src
@@ -0,0 +1,167 @@
+/*************************************************************************
+ *
+ * $RCSfile: images.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMAGES_SRC
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+
+// =======================================================================
+
+Bitmap (SV_RESID_BITMAP_CHECK + SV_RESID_STDOFFSET)
+{
+ File = "check.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_CHECK + SV_RESID_WINOFFSET)
+{
+ File = "checkwin.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_CHECK + SV_RESID_OS2OFFSET)
+{
+ File = "checkos2.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_CHECK + SV_RESID_MACOFFSET)
+{
+ File = "checkmac.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_CHECK + SV_RESID_UNIXOFFSET)
+{
+ File = "checkunx.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_SCROLLBMP)
+{
+ File = "scrbmp.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_SCROLLMSK)
+{
+ File = "scrmsk.bmp";
+};
+
+// -----------------------------------------------------------------------
+
+Bitmap (SV_RESID_BITMAP_RADIO + SV_RESID_STDOFFSET)
+{
+ File = "radio.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_RADIO + SV_RESID_WINOFFSET)
+{
+ File = "radiowin.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_RADIO + SV_RESID_OS2OFFSET)
+{
+ File = "radioos2.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_RADIO + SV_RESID_MACOFFSET)
+{
+ File = "radiomac.bmp";
+};
+
+Bitmap (SV_RESID_BITMAP_RADIO + SV_RESID_UNIXOFFSET)
+{
+ File = "radiounx.bmp";
+};
+
+// -----------------------------------------------------------------------
+
+Bitmap SV_RESID_BITMAP_MSGBOX
+{
+ File = "msgbox.bmp";
+};
+
+// -----------------------------------------------------------------------
+
+Bitmap SV_RESID_BITMAP_PIN
+{
+ File = "pin.bmp";
+};
+
+// -----------------------------------------------------------------------
+
+Bitmap SV_RESID_BITMAP_SPLITHPIN
+{
+ File = "splhpin.bmp";
+};
+
+Bitmap SV_RESID_BITMAP_SPLITVPIN
+{
+ File = "splvpin.bmp";
+};
+
+Bitmap SV_RESID_BITMAP_SPLITHARW
+{
+ File = "splharw.bmp";
+};
+
+Bitmap SV_RESID_BITMAP_SPLITVARW
+{
+ File = "splvarw.bmp";
+};
+
diff --git a/vcl/source/src/makefile.mk b/vcl/source/src/makefile.mk
new file mode 100644
index 000000000000..8520005b59d8
--- /dev/null
+++ b/vcl/source/src/makefile.mk
@@ -0,0 +1,106 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=svsrc
+RESTARGET=vcl
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SRCFILES= images.src \
+ menu.src \
+ stdtext.src \
+ helptext.src \
+ btntext.src
+
+RESLIB1NAME= $(RESTARGET)
+RESLIB1SRSFILES= $(SRS)$/svsrc.srs
+RESLIB1BMPS= check.bmp \
+ checkwin.bmp \
+ checkos2.bmp \
+ checkmac.bmp \
+ checkunx.bmp \
+ radio.bmp \
+ radiowin.bmp \
+ radioos2.bmp \
+ radiomac.bmp \
+ radiounx.bmp \
+ msgbox.bmp \
+ scrbmp.bmp \
+ scrmsk.bmp \
+ pin.bmp \
+ splhpin.bmp \
+ splvpin.bmp \
+ splharw.bmp \
+ splvarw.bmp
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/source/src/menu.src b/vcl/source/src/menu.src
new file mode 100644
index 000000000000..a3294770dff7
--- /dev/null
+++ b/vcl/source/src/menu.src
@@ -0,0 +1,284 @@
+/*************************************************************************
+ *
+ * $RCSfile: menu.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#define _SV_MENU_SRC
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+
+String SV_RESID_STRING_NOSELECTIONPOSSIBLE
+{
+ Text ="<Keine Auswahl möglich>";
+ Text[English] ="<No selection possible>";
+ Text[ english_us ] = "<No selection possible>";
+ Text[ portuguese ] = "<Selecção impossível>";
+ Text[ russian ] = "<Âûáîð íåâîçìîæåí>";
+ Text[ greek ] = "<Äåí åßíáé äõíáôüí íá ãßíåé åðéëïãÞ>";
+ Text[ dutch ] = "<Geen selectie mogelijk>";
+ Text[ french ] = "<Aucune sélection possible>";
+ Text[ spanish ] = "<Ninguna selección posible>";
+ Text[ italian ] = "<Impossibile selezionare>";
+ Text[ danish ] = "<Intet udvalg muligt>";
+ Text[ swedish ] = "<Inget urval möjligt>";
+ Text[ polish ] = "<Selekcja niemo¿liwa>";
+ Text[ portuguese_brazilian ] = "<No selection possible>";
+ Text[ japanese ] = "<‰½‚à‘I‘ð‚Å‚«‚Ü‚¹‚ñ>";
+ Text[ korean ] = "<¼±Åà ºÒ°¡´É>";
+ Text[ chinese_simplified ] = "<ÎÞ·¨Ñ¡Ôñ>";
+ Text[ chinese_traditional ] = "<µLªk¿ï¾Ü>";
+ Text[ arabic ] = "<áÇ íãßä ÇáÊÍÏíÏ>";
+ Text[ turkish ] = "<Seçim yapýlamaz>";
+};
+
+Menu SV_RESID_MENU_EDIT
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_UNDO ;
+ Text = "~Rückgängig" ;
+ Text [ English ] = "~Undo" ;
+ Text [ portuguese ] = "~Anular" ;
+ Text [ english_us ] = "~Undo" ;
+ Text [ portuguese_brazilian ] = "~Rückgängig" ;
+ Text [ swedish ] = "~Ångra" ;
+ Text [ danish ] = "Fo~rtryd" ;
+ Text [ italian ] = "~Annulla" ;
+ Text [ spanish ] = "~Deshacer" ;
+ Text [ french ] = "~Annuler" ;
+ Text [ dutch ] = "~Ongedaan maken" ;
+ Text[ russian ] = "Îòìåíèòü";
+ Text[ polish ] = "Cofnij";
+ Text[ japanese ] = "Œ³‚É–ß‚·(~U)";
+ Text[ chinese_simplified ] = "³·ÏûÃüÁî(~U)";
+ Text[ chinese_traditional ] = "´_­ì(~U)";
+ Text[ greek ] = "Áíáß~ñåóç";
+ Text[ korean ] = "ÀÛ¾÷Ãë¼Ò(~U)";
+ Text[ arabic ] = "ÊÑÇÌÚ";
+ Text[ turkish ] = "Geri al";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem { Separator = TRUE ; };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_CUT ;
+ Text = "~Ausschneiden" ;
+ Text [ English ] = "Cu~t" ;
+ Text [ norwegian ] = "Klipp~ut" ;
+ Text [ italian ] = "~Taglia" ;
+ Text [ portuguese_brazilian ] = "Co~rtar" ;
+ Text [ portuguese ] = "Co~rtar" ;
+ Text [ finnish ] = "~Leikkaa" ;
+ Text [ danish ] = "~Klip" ;
+ Text [ french ] = "~Couper" ;
+ Text [ swedish ] = "~Klipp ut" ;
+ Text [ dutch ] = "K~nippen" ;
+ Text [ spanish ] = "C~ortar" ;
+ Text [ english_us ] = "Cu~t" ;
+ Text[ russian ] = "~Âûðåçàòü";
+ Text[ polish ] = "Wytnij";
+ Text[ japanese ] = "Ø‚èŽæ‚è(~T)";
+ Text[ chinese_simplified ] = "¼ô³ý(~T)";
+ Text[ chinese_traditional ] = "°Å¤U(~T)";
+ Text[ greek ] = "~ÁðïêïðÞ";
+ Text[ korean ] = "À߶󳻱â(~T)";
+ Text[ arabic ] = "ÞÕ";
+ Text[ turkish ] = "~Kes";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_COPY ;
+ Text = "~Kopieren" ;
+ Text [ English ] = "~Copy" ;
+ Text [ norwegian ] = "~Kopier" ;
+ Text [ italian ] = "~Copia" ;
+ Text [ portuguese_brazilian ] = "~Copiar" ;
+ Text [ portuguese ] = "~Copiar" ;
+ Text [ finnish ] = "~Kopioi" ;
+ Text [ danish ] = "K~opier" ;
+ Text [ french ] = "Co~pier" ;
+ Text [ swedish ] = "K~opiera" ;
+ Text [ dutch ] = "~Kopiëren" ;
+ Text [ spanish ] = "~Copiar" ;
+ Text [ english_us ] = "~Copy" ;
+ Text[ russian ] = "~Êîïèðîâàòü";
+ Text[ polish ] = "Kopiuj";
+ Text[ japanese ] = "ºËß°(~C)";
+ Text[ chinese_simplified ] = "¸´ÖÆ(~C)";
+ Text[ chinese_traditional ] = "½Æ»s(~C)";
+ Text[ greek ] = "Áíôé~ãñáöÞ";
+ Text[ korean ] = "º¹»ç(~C)";
+ Text[ arabic ] = "äÓÎ";
+ Text[ turkish ] = "K~opyala";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_PASTE ;
+ Text = "~Einfügen" ;
+ Text [ English ] = "~Paste" ;
+ Text [ norwegian ] = "~Paste" ;
+ Text [ italian ] = "~Incolla" ;
+ Text [ portuguese_brazilian ] = "~Colar" ;
+ Text [ portuguese ] = "Co~lar" ;
+ Text [ finnish ] = "L~iitä" ;
+ Text [ danish ] = "~Indsæt" ;
+ Text [ french ] = "C~oller" ;
+ Text [ swedish ] = "K~listra in" ;
+ Text [ dutch ] = "~Plakken" ;
+ Text [ spanish ] = "~Pegar" ;
+ Text [ english_us ] = "~Paste" ;
+ Text[ russian ] = "Âñò~àâêà";
+ Text[ polish ] = "W~staw";
+ Text[ japanese ] = "“\\‚è•t‚¯(~P)";
+ Text[ chinese_simplified ] = "²åÈë(~P)";
+ Text[ chinese_traditional ] = "´¡¤J(~P)";
+ Text[ greek ] = "~Åðéêüëëçóç";
+ Text[ korean ] = "ºÙ¿©³Ö±â(~P)";
+ Text[ arabic ] = "áÕÞ";
+ Text[ turkish ] = "~Yapýþtýr";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_DELETE ;
+ Text = "~Löschen" ;
+ Text [ English ] = "~Delete" ;
+ Text [ norwegian ] = "~Slett" ;
+ Text [ italian ] = "Cancella" ;
+ Text [ portuguese_brazilian ] = "~Apagar" ;
+ Text [ portuguese ] = "E~liminar" ;
+ Text [ finnish ] = "~Poista" ;
+ Text [ danish ] = "~Slet" ;
+ Text [ french ] = "~Supprimer" ;
+ Text [ swedish ] = "~Radera" ;
+ Text [ dutch ] = "~Wissen" ;
+ Text [ spanish ] = "~Eliminar" ;
+ Text [ english_us ] = "~Delete" ;
+ Text[ russian ] = "~Óäàëèòü";
+ Text[ polish ] = "Usuñ";
+ Text[ japanese ] = "íœ(~D)";
+ Text[ chinese_simplified ] = "ɾ³ý(~D)";
+ Text[ chinese_traditional ] = "§R°£(~D)";
+ Text[ greek ] = "Äéáãñá~öÞ";
+ Text[ korean ] = "»èÁ¦(~D)";
+ Text[ arabic ] = "ÍÐÝ";
+ Text[ turkish ] = "~Sil";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem { Separator = TRUE ; };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_SELECTALL ;
+ Text = "Alles aus~wählen" ;
+ Text [ English ] = "Select ~All" ;
+ Text [ norwegian ] = "Select ~All" ;
+ Text [ italian ] = "Seleziona tutto" ;
+ Text [ portuguese_brazilian ] = "Selecionar ~Tudo" ;
+ Text [ portuguese ] = "Seleccionar ~tudo" ;
+ Text [ finnish ] = "Valitse ~kaikki" ;
+ Text [ danish ] = "~Marker alt" ;
+ Text [ french ] = "Sélectio~nner tout" ;
+ Text [ swedish ] = "Markera ~allt" ;
+ Text [ dutch ] = "~Alles selecteren" ;
+ Text [ spanish ] = "Seleccionar ~todo" ;
+ Text [ english_us ] = "Select ~All" ;
+ Text[ russian ] = "Âûäåëèòü âñå";
+ Text[ polish ] = "Zaznacz wszystko";
+ Text[ japanese ] = "‚·‚ׂđI‘ð(~A)";
+ Text[ chinese_simplified ] = "È«²¿Ñ¡ÖÐ(~A)";
+ Text[ chinese_traditional ] = "¥þ³¡¿ï¨ú(~A)";
+ Text[ greek ] = "ÅðéëïãÞ üë~ùí";
+ Text[ korean ] = "Àüü¼±ÅÃ(~A)";
+ Text[ arabic ] = "ÊÍÏíÏ Çáßá";
+ Text[ turkish ] = "Tümünü seç";
+ Text[ language_user1 ] = " ";
+ };
+ MenuItem { Separator = TRUE ; };
+ MenuItem
+ {
+ Identifier = SV_MENU_EDIT_INSERTSYMBOL;
+ Text = "~Sonderzeichen einfügen...";
+ Text [ English ] = "insert ~symbol...";
+ TEXT[ italian ] = "Inserisci caratteri speciali...";
+ TEXT[ portuguese_brazilian ] = "~Sonderzeichen einfügen...";
+ TEXT[ portuguese ] = "~Inserir carácter especial...";
+ TEXT[ danish ] = "Indsæt ~specialtegn...";
+ TEXT[ french ] = "~Insérer des caractères spéciaux...";
+ TEXT[ swedish ] = "Infoga ~specialtecken...";
+ TEXT[ dutch ] = "~Speciaal teken invoegen...";
+ TEXT[ spanish ] = "Insertar ~símbolo...";
+ TEXT[ english_us ] = "~Special Character...";
+ TEXT[ russian ] = "~Âñòàâèòü ñïåöèàëüíûå ñèìâîëû...";
+ TEXT[ polish ] = "Wstaw znaki specjalne...";
+ TEXT[ japanese ] = "‹L†‚Æ“ÁŽê•¶Žš‚Ì‘}“ü(~S)...";
+
+ TEXT[ chinese_simplified ] = "²åÈëÌØÊâ×Ö·û(~S)...";
+ TEXT[ chinese_traditional ] = "´¡¤J¯S®í¦r¤¸(~S)...";
+ TEXT[ greek ] = "Åé~óáãùãÞ åéäéêïý ÷áñáêôÞñá...";
+ TEXT[ korean ] = "Ư¼ö±âÈ£(~S)...";
+ TEXT[ arabic ] = "ÅÏÑÇÌ ÑãæÒ ÎÇÕÉ";
+ TEXT[ turkish ] = "Özel karakter ekle...";
+ TEXT[ language_user1 ] = " ";
+ };
+ };
+};
diff --git a/vcl/source/src/stdtext.src b/vcl/source/src/stdtext.src
new file mode 100644
index 000000000000..2a7ca53c68fd
--- /dev/null
+++ b/vcl/source/src/stdtext.src
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * $RCSfile: stdtext.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_STDTEXT_SRC
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+
+String SV_STDTEXT_SERVICENOTAVAILABLE
+{
+ Text = "Eine Komponente (%s) konnte nicht geladen werden.\nBitte starten Sie das Setup und führen Sie eine Reparatur durch.";
+ Text [ English ] = "The component (%s) could not be loaded.\nPlease start setup in repair mode." ;
+ Text[ english_us ] = "The component (%s) could not be loaded.\nPlease start setup with the repair option.";
+ Text[ portuguese ] = "Impossível carregar o componente (%s).\nReinicie o setup com a opção 'Reparação'.";
+ Text[ russian ] = "Çàãðóçèòü îäèí èç êîìïîíåíòîâ (%s) íå óäàåòñÿ.\nÇàïóñòèòå èíñòàëëÿöèþ ñ âîññòàíîâëåíèåì.";
+ Text[ dutch ] = "Een component (%s) kon niet worden geladen.\nStart setup opnieuw met de optie Reparatie.";
+ Text[ french ] = "Impossible de charger l'un des composants (%s).\nVeuillez redémarrer le programme d'installation (Setup) et exécuter une réparation.";
+ Text[ spanish ] = "No se pudo cargar un componente (%s).\nInicie por favor el programa de instalación y ejecute una Reparación.";
+ Text[ italian ] = "Impossibile caricare il componente (%s).\nRiavviate il setup e eseguite la riparazione.";
+ Text[ danish ] = "Det var ikke muligt at indlæse en komponent (%s).\nStart venligst installationsprogrammet (Setup) og udfør en reparation.";
+ Text[ swedish ] = "Komponenten (%s) kunde inte laddas.\nVar vänlig och starta setupen och gör en reparation.";
+ Text[ polish ] = "Sk³adnika (%s) nie mo¿na za³adowaæ.\nProszê rozpocznij program instalacyjny i przeprowadŸ naprawê.";
+ Text[ portuguese_brazilian ] = "The component (%s) could not be loaded.\nPlease start setup with the option -repair.";
+ Text[ japanese ] = "ºÝÎß°ÈÝÄ(%s)‚Í“Ç‚Ýž‚Ý‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½B\n¾¯Ä±¯Ìß‚ðŠJŽn‚µ‚ÄC•œ‚ðŽÀs‚µ‚ĉº‚³‚¢B";
+ Text[ chinese_simplified ] = "ÎÞ·¨×°ÔسÌÐò²¿¼þ(%s)¡£\nÇëÄúÑ¡Ôñ°²×°³ÌÐòµÄÑ¡ÏîÐÞ²¹¡£";
+ Text[ chinese_traditional ] = "µLªk¸Ë¸üµ{¦¡³¡¥ó(%s)¡C\n½Ð±z¿ï¾Ü¦w¸Ëµ{¦¡ªº­×½Æ¿ï¶µ¡C";
+ Text[ arabic ] = "ÊÚÐÑ ÊÍãíá Çáãßæä (%s).\n ÇáÑÌÇÁ ÈÏÁ ÈÑäÇãÌ ÇáÅÚÏÇÏ¡ Ëã ÇáÞíÇã ÈÚãáíÉ ÇáÅÕáÇÍ ÇááÇÒãÉ.";
+ Text[ greek ] = "Äåí Þôáí äõíáôüí íá öïñôùèåß ôï óôïé÷åßï (%s)\nÐáñáêáëþ åêêéíÞóôå îáíÜ ôï ðñüãñáììá åãêáôÜóôáóçò êáé åêôåëÝóôå ôçí åðéóêåõÞ.";
+ Text[ korean ] = "ÄÄÆ÷³ÍÆ® (%s)°¡ ·Îµå µÇÁö ¾Ê¾Ò½À´Ï´Ù.\n¼³Á¤¿¡¼­ ¿É¼Ç°íħÀ» ½ÃÀÛÇϽʽÿÀ.";
+ Text[ turkish ] = "Bir bileþen (%s) yüklenemedi.\nSetup programýný çalýþtýrýp onarýnýz.";
+ Text[ language_user1 ] = " ";
+};
diff --git a/vcl/source/window/accel.cxx b/vcl/source/window/accel.cxx
new file mode 100644
index 000000000000..f039c311ef28
--- /dev/null
+++ b/vcl/source/window/accel.cxx
@@ -0,0 +1,775 @@
+/*************************************************************************
+ *
+ * $RCSfile: accel.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ACCEL_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _TABLE_HXX
+#include <tools/table.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_ACCEL_H
+#include <accel.h>
+#endif
+#ifndef _SV_ACCEL_HXX
+#include <accel.hxx>
+#endif
+#ifndef _RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+DECLARE_TABLE( ImplAccelTable, ImplAccelEntry* );
+DECLARE_LIST( ImplAccelList, ImplAccelEntry* );
+
+#define ACCELENTRY_NOTFOUND ((USHORT)0xFFFF)
+
+// =======================================================================
+
+class ImplAccelData
+{
+public:
+ ImplAccelTable maKeyTable; // Fuer KeyCodes, die mit einem Code erzeugt wurden
+ ImplAccelList maIdList; // Id-List
+};
+
+// =======================================================================
+
+DBG_NAME( Accelerator );
+
+// =======================================================================
+
+USHORT ImplAccelEntryGetIndex( ImplAccelList* pList, USHORT nId,
+ USHORT* pIndex = NULL )
+{
+ ULONG nLow;
+ ULONG nHigh;
+ ULONG nMid;
+ ULONG nCount = pList->Count();
+ USHORT nCompareId;
+
+ // Abpruefen, ob der erste Key groesser als der Vergleichskey ist
+ if ( !nCount || (nId < pList->GetObject( 0 )->mnId) )
+ {
+ if ( pIndex )
+ *pIndex = 0;
+ return ACCELENTRY_NOTFOUND;
+ }
+
+ // Binaeres Suchen
+ nLow = 0;
+ nHigh = nCount-1;
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareId = pList->GetObject( nMid )->mnId;
+ if ( nId < nCompareId )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nId > nCompareId )
+ nLow = nMid + 1;
+ else
+ return (USHORT)nMid;
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( pIndex )
+ {
+ if ( nId > nCompareId )
+ *pIndex = (USHORT)(nMid+1);
+ else
+ *pIndex = (USHORT)nMid;
+ }
+
+ return ACCELENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplAccelEntryInsert( ImplAccelList* pList, ImplAccelEntry* pEntry )
+{
+ USHORT nInsIndex;
+ USHORT nIndex = ImplAccelEntryGetIndex( pList, pEntry->mnId, &nInsIndex );
+
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ do
+ {
+ nIndex++;
+ ImplAccelEntry* pTempEntry = pList->GetObject( nIndex );
+ if ( !pTempEntry || (pTempEntry->mnId != pEntry->mnId) )
+ break;
+ }
+ while ( nIndex < pList->Count() );
+
+ pList->Insert( pEntry, (ULONG)nIndex );
+ }
+ else
+ pList->Insert( pEntry, (ULONG)nInsIndex );
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplAccelEntryGetFirstPos( ImplAccelList* pList, USHORT nId )
+{
+ USHORT nIndex = ImplAccelEntryGetIndex( pList, nId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ while ( nIndex )
+ {
+ nIndex--;
+ if ( pList->GetObject( nIndex )->mnId != nId )
+ break;
+ }
+
+ if ( pList->GetObject( nIndex )->mnId != nId )
+ nIndex++;
+ }
+
+ return nIndex;
+}
+
+// =======================================================================
+
+void Accelerator::ImplInit()
+{
+ mnCurId = 0;
+ mnCurRepeat = 0;
+ mbIsCancel = FALSE;
+ mpDel = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplAccelEntry* Accelerator::ImplGetAccelData( const KeyCode& rKeyCode ) const
+{
+ return mpData->maKeyTable.Get( rKeyCode.GetFullKeyCode() );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplCopyData( ImplAccelData& rAccelData )
+{
+ // Tabellen kopieren
+ ImplAccelEntry* pEntry = rAccelData.maIdList.First();
+ while ( pEntry )
+ {
+ pEntry = new ImplAccelEntry( *pEntry );
+
+ // Folge-Accelerator, dann auch kopieren
+ if ( pEntry->mpAccel )
+ {
+ pEntry->mpAccel = new Accelerator( *(pEntry->mpAccel) );
+ pEntry->mpAutoAccel = pEntry->mpAccel;
+ }
+ else
+ pEntry->mpAutoAccel = NULL;
+
+ mpData->maKeyTable.Insert( (ULONG)pEntry->maKeyCode.GetFullKeyCode(), pEntry );
+ mpData->maIdList.Insert( pEntry, LIST_APPEND );
+
+ pEntry = rAccelData.maIdList.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplDeleteData()
+{
+ // Accelerator-Eintraege ueber die Id-Tabelle loeschen
+ ImplAccelEntry* pEntry = mpData->maIdList.First();
+ while ( pEntry )
+ {
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+ delete pEntry;
+
+ pEntry = mpData->maIdList.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplInsertAccel( USHORT nItemId, const KeyCode& rKeyCode,
+ BOOL bEnable, Accelerator* pAutoAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+ DBG_ASSERT( nItemId, "Accelerator::InsertItem(): ItemId == 0" );
+
+ if ( rKeyCode.IsFunction() )
+ {
+ USHORT nCode1;
+ USHORT nCode2;
+ USHORT nCode3;
+ ImplGetKeyCode( rKeyCode.GetFunction(), nCode1, nCode2, nCode3 );
+ if ( nCode1 )
+ ImplInsertAccel( nItemId, KeyCode( nCode1, nCode1 ), bEnable, pAutoAccel );
+ if ( nCode2 )
+ {
+ if ( pAutoAccel )
+ pAutoAccel = new Accelerator( *pAutoAccel );
+ ImplInsertAccel( nItemId, KeyCode( nCode2, nCode2 ), bEnable, pAutoAccel );
+ if ( nCode3 )
+ {
+ if ( pAutoAccel )
+ pAutoAccel = new Accelerator( *pAutoAccel );
+ ImplInsertAccel( nItemId, KeyCode( nCode3, nCode3 ), bEnable, pAutoAccel );
+ }
+ }
+ return;
+ }
+
+ // Neuen Eintrag holen und fuellen
+ ImplAccelEntry* pEntry = new ImplAccelEntry;
+ pEntry->mnId = nItemId;
+ pEntry->maKeyCode = rKeyCode;
+ pEntry->mpAccel = pAutoAccel;
+ pEntry->mpAutoAccel = pAutoAccel;
+ pEntry->mbEnabled = bEnable;
+
+ // Ab in die Tabellen
+ ULONG nCode = rKeyCode.GetFullKeyCode();
+ if ( !nCode )
+ {
+ DBG_ERROR( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
+ delete pEntry;
+ }
+ else if ( !mpData->maKeyTable.Insert( nCode, pEntry ) )
+ {
+ DBG_ERROR1( "Accelerator::InsertItem(): KeyCode (Key: %lx) already exists", nCode );
+ delete pEntry;
+ }
+ else
+ ImplAccelEntryInsert( &(mpData->maIdList), pEntry );
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator()
+{
+ DBG_CTOR( Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator( const Accelerator& rAccel ) :
+ maHelpStr( rAccel.maHelpStr ),
+ maCurKeyCode( rAccel.maCurKeyCode )
+{
+ DBG_CTOR( Accelerator, NULL );
+ DBG_CHKOBJ( &rAccel, Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+ ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::Accelerator( const ResId& rResId )
+{
+ DBG_CTOR( Accelerator, NULL );
+
+ ImplInit();
+ mpData = new ImplAccelData;
+ rResId.SetRT( RSC_ACCEL );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::ImplLoadRes( const ResId& rResId )
+{
+ GetRes( rResId );
+
+ maHelpStr = ReadStringRes();
+ USHORT nObjFollows = ReadShortRes();
+
+ for( USHORT i = 0; i < nObjFollows; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator::~Accelerator()
+{
+ DBG_DTOR( Accelerator, NULL );
+
+ // AccelManager benachrichtigen, das Accelrator geloescht wurde
+ if ( mpDel )
+ *mpDel = TRUE;
+
+ ImplDeleteData();
+ delete mpData;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Activate()
+{
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Deactivate()
+{
+ maDeactivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::InsertItem( USHORT nItemId, const KeyCode& rKeyCode )
+{
+ ImplInsertAccel( nItemId, rKeyCode, TRUE, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::InsertItem( const ResId& rResId )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nObjMask;
+ USHORT nAccelKeyId;
+ USHORT bDisable;
+ KeyCode aKeyCode;
+ BOOL bEnable = FALSE;
+ Accelerator* pAutoAccel = NULL;
+
+ GetRes( rResId.SetRT( RSC_ACCELITEM ) );
+ nObjMask = ReadShortRes();
+ nAccelKeyId = ReadShortRes();
+ bDisable = ReadShortRes();
+
+ if ( nObjMask & ACCELITEM_KEY )
+ {
+ // es wird ein neuer Kontext aufgespannt
+ RSHEADER_TYPE * pKeyCodeRes = (RSHEADER_TYPE *)GetClassRes();
+ ResId aResId( pKeyCodeRes );
+ aKeyCode = KeyCode( aResId );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ if ( nObjMask & ACCELITEM_ACCEL )
+ {
+ pAutoAccel = new Accelerator( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+
+ ImplInsertAccel( nAccelKeyId, aKeyCode, !bDisable, pAutoAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::RemoveItem( USHORT nItemId )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ // Aus der Id-Liste entfernen
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry && pEntry->mnId == nItemId )
+ {
+ mpData->maKeyTable.Remove( pEntry->maKeyCode.GetFullKeyCode() );
+ mpData->maIdList.Remove( (ULONG)nIndex );
+
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+
+ delete pEntry;
+ }
+ else
+ break;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::RemoveItem( const KeyCode rKeyCode )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ // Aus der Id-Liste entfernen
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), pEntry->mnId );
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ if ( mpData->maIdList.GetObject( (ULONG)nIndex ) == pEntry )
+ break;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+
+ mpData->maKeyTable.Remove( rKeyCode.GetFullKeyCode() );
+ mpData->maIdList.Remove( (ULONG)nIndex );
+
+ // AutoResAccel zerstoeren
+ if ( pEntry->mpAutoAccel )
+ delete pEntry->mpAutoAccel;
+
+ delete pEntry;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::Clear()
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplDeleteData();
+ mpData->maKeyTable.Clear();
+ mpData->maIdList.Clear();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemCount() const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ return (USHORT)mpData->maIdList.Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemId( USHORT nPos ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nPos );
+ if ( pEntry )
+ return pEntry->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode Accelerator::GetItemKeyCode( USHORT nPos ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nPos );
+ if ( pEntry )
+ return pEntry->maKeyCode;
+ else
+ return KeyCode();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Accelerator::GetItemId( const KeyCode& rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode Accelerator::GetKeyCode( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->maKeyCode;
+ else
+ return KeyCode();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsIdValid( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ return (nIndex != ACCELENTRY_NOTFOUND);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsKeyCodeValid( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ return (pEntry != NULL);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::Call( const KeyCode& rKeyCode, USHORT nRepeat )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ if ( pEntry->mbEnabled )
+ {
+ BOOL bDel = FALSE;
+ mnCurId = pEntry->mnId;
+ maCurKeyCode = rKeyCode;
+ mnCurRepeat = nRepeat;
+ mpDel = &bDel;
+ Select();
+ if ( !bDel )
+ {
+ mnCurId = 0;
+ maCurKeyCode = KeyCode();
+ mnCurRepeat = 0;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::SetAccel( USHORT nItemId, Accelerator* pAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry->mnId != nItemId )
+ break;
+
+ pEntry->mpAccel = pAccel;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator* Accelerator::GetAccel( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->mpAccel;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::SetAccel( const KeyCode rKeyCode, Accelerator* pAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ pEntry->mpAccel = pAccel;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator* Accelerator::GetAccel( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mpAccel;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ {
+ USHORT nItemCount = GetItemCount();
+ do
+ {
+ ImplAccelEntry* pEntry = mpData->maIdList.GetObject( (ULONG)nIndex );
+ if ( pEntry->mnId != nItemId )
+ break;
+
+ pEntry->mbEnabled = bEnable;
+ nIndex++;
+ }
+ while ( nIndex < nItemCount );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsItemEnabled( USHORT nItemId ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ USHORT nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
+ if ( nIndex != ACCELENTRY_NOTFOUND )
+ return mpData->maIdList.GetObject( (ULONG)nIndex )->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Accelerator::EnableItem( const KeyCode rKeyCode, BOOL bEnable )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ pEntry->mbEnabled = bEnable;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Accelerator::IsItemEnabled( const KeyCode rKeyCode ) const
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+
+ ImplAccelEntry* pEntry = ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ return pEntry->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Accelerator& Accelerator::operator=( const Accelerator& rAccel )
+{
+ DBG_CHKTHIS( Accelerator, NULL );
+ DBG_CHKOBJ( &rAccel, Accelerator, NULL );
+
+ // Neue Daten zuweisen
+ maHelpStr = rAccel.maHelpStr;
+ maCurKeyCode = KeyCode();
+ mnCurId = 0;
+ mnCurRepeat = 0;
+ mbIsCancel = FALSE;
+
+ // Tabellen loeschen und kopieren
+ ImplDeleteData();
+ mpData->maKeyTable.Clear();
+ mpData->maIdList.Clear();
+ ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
+
+ return *this;
+}
diff --git a/vcl/source/window/accmgr.cxx b/vcl/source/window/accmgr.cxx
new file mode 100644
index 000000000000..2cf39ae4cd9c
--- /dev/null
+++ b/vcl/source/window/accmgr.cxx
@@ -0,0 +1,318 @@
+/*************************************************************************
+ *
+ * $RCSfile: accmgr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ACCMGR_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_ACCEL_H
+#include <accel.h>
+#endif
+#ifndef _SV_ACCEL_HXX
+#include <accel.hxx>
+#endif
+#ifndef _SV_ACCMGR_HXX
+#include <accmgr.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+DECLARE_LIST( ImplAccelList, Accelerator* );
+
+// =======================================================================
+
+DBG_NAMEEX( Accelerator );
+
+// =======================================================================
+
+ImplAccelManager::~ImplAccelManager()
+{
+ if ( mpAccelList )
+ delete mpAccelList;
+ if ( mpSequenceList )
+ delete mpSequenceList;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplAccelManager::InsertAccel( Accelerator* pAccel )
+{
+ if ( !mpAccelList )
+ mpAccelList = new ImplAccelList;
+ else
+ {
+ // Gibts den schon ?
+ if ( mpAccelList->GetPos( pAccel ) != LIST_ENTRY_NOTFOUND )
+ return FALSE;
+ }
+
+ // Am Anfang der Liste einfuegen
+ mpAccelList->Insert( pAccel, (ULONG)0 );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplAccelManager::RemoveAccel( Accelerator* pAccel )
+{
+ // Haben wir ueberhaupt eine Liste ?
+ if ( !mpAccelList )
+ return;
+
+ // Raus damit
+ mpAccelList->Remove( pAccel );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplAccelManager::EndSequence( BOOL bCancel )
+{
+ // Sind wir ueberhaupt in einer Sequenz ?
+ if ( !mpSequenceList )
+ return;
+
+ // Alle Deactivate-Handler der Acceleratoren in der Sequenz rufen
+ Accelerator* pTempAccel = mpSequenceList->First();
+ while( pTempAccel )
+ {
+ BOOL bDel = FALSE;
+ pTempAccel->mbIsCancel = bCancel;
+ pTempAccel->mpDel = &bDel;
+ pTempAccel->Deactivate();
+ if ( !bDel )
+ {
+ pTempAccel->mbIsCancel = FALSE;
+ pTempAccel->mpDel = NULL;
+ }
+
+ pTempAccel = mpSequenceList->Next();
+ }
+
+ // Sequenz-Liste loeschen
+ delete mpSequenceList;
+ mpSequenceList = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplAccelManager::IsAccelKey( const KeyCode& rKeyCode, USHORT nRepeat )
+{
+ Accelerator* pAccel;
+
+ // Haben wir ueberhaupt Acceleratoren ??
+ if ( !mpAccelList )
+ return FALSE;
+ if ( !mpAccelList->Count() )
+ return FALSE;
+
+ // Sind wir in einer Sequenz ?
+ if ( mpSequenceList )
+ {
+ pAccel = mpSequenceList->GetObject( 0 );
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+
+ // Nicht Gefunden ?
+ if ( !pAccel )
+ {
+ // Sequenz abbrechen
+ FlushAccel();
+ return FALSE;
+ }
+
+ // Ist der Eintrag da drin ?
+ ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ Accelerator* pNextAccel = pEntry->mpAccel;
+
+ // Ist da ein Accelerator hinter ?
+ if ( pNextAccel )
+ {
+ DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
+
+ mpSequenceList->Insert( pNextAccel, (ULONG)0 );
+
+ // Activate-Handler vom Neuen rufen
+ pNextAccel->Activate();
+ return TRUE;
+ }
+ else
+ {
+ // Hat ihn schon !
+ if ( pEntry->mbEnabled )
+ {
+ // Sequence beenden (Deactivate-Handler vorher rufen)
+ EndSequence();
+
+ // Dem Accelerator das aktuelle Item setzen
+ // und Handler rufen
+ BOOL bDel = FALSE;
+ pAccel->maCurKeyCode = rKeyCode;
+ pAccel->mnCurId = pEntry->mnId;
+ pAccel->mnCurRepeat = nRepeat;
+ pAccel->mpDel = &bDel;
+ pAccel->Select();
+
+ // Hat Accel den Aufruf ueberlebt
+ if ( !bDel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+ pAccel->maCurKeyCode = KeyCode();
+ pAccel->mnCurId = 0;
+ pAccel->mnCurRepeat = 0;
+ pAccel->mpDel = NULL;
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ // Sequenz abbrechen, weil Acceleraor disabled
+ // Taste wird weitergeleitet (ans System)
+ FlushAccel();
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ // Sequenz abbrechen wegen falscher Taste
+ FlushAccel();
+ return FALSE;
+ }
+ }
+
+ // Durch die Liste der Acceleratoren wuehlen
+ pAccel = mpAccelList->First();
+ while ( pAccel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+
+ // Ist der Eintrag da drin ?
+ ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
+ if ( pEntry )
+ {
+ Accelerator* pNextAccel = pEntry->mpAccel;
+
+ // Ist da ein Accelerator hinter ?
+ if ( pNextAccel )
+ {
+ DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
+
+ // Sequenz-Liste erzeugen
+ mpSequenceList = new ImplAccelList;
+ mpSequenceList->Insert( pAccel, (ULONG)0 );
+ mpSequenceList->Insert( pNextAccel, (ULONG)0 );
+
+ // Activate-Handler vom Neuen rufen
+ pNextAccel->Activate();
+
+ return TRUE;
+ }
+ else
+ {
+ // Hat ihn schon !
+ if ( pEntry->mbEnabled )
+ {
+ // Activate/Deactivate-Handler vorher rufen
+ pAccel->Activate();
+ pAccel->Deactivate();
+
+ // Dem Accelerator das aktuelle Item setzen
+ // und Handler rufen
+ BOOL bDel = FALSE;
+ pAccel->maCurKeyCode = rKeyCode;
+ pAccel->mnCurId = pEntry->mnId;
+ pAccel->mnCurRepeat = nRepeat;
+ pAccel->mpDel = &bDel;
+ pAccel->Select();
+
+ // Hat Accel den Aufruf ueberlebt
+ if ( !bDel )
+ {
+ DBG_CHKOBJ( pAccel, Accelerator, NULL );
+ pAccel->maCurKeyCode = KeyCode();
+ pAccel->mnCurId = 0;
+ pAccel->mnCurRepeat = 0;
+ pAccel->mpDel = NULL;
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+
+ // Nicht gefunden, vielleicht im naechsten Accelerator
+ pAccel = mpAccelList->Next();
+ }
+
+ return FALSE;
+}
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx
new file mode 100644
index 000000000000..651306cf1e3b
--- /dev/null
+++ b/vcl/source/window/brdwin.cxx
@@ -0,0 +1,3808 @@
+/*************************************************************************
+ *
+ * $RCSfile: brdwin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BRDWIN_CXX
+
+#ifdef REMOTE_APPSERVER
+#include <rmwindow.hxx>
+#endif
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SYSWIN_HXX
+#include <syswin.hxx>
+#endif
+#ifndef _SV_DOCKWIN_HXX
+#include <dockwin.hxx>
+#endif
+#ifndef _SV_FLOATWIN_HXX
+#include <floatwin.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+
+#include <tools/debug.hxx>
+
+#include <rvp.hxx>
+
+#pragma hdrstop
+
+using namespace ::com::sun::star::uno;
+
+// =======================================================================
+
+// -----------------------
+// - ImplBorderFrameData -
+// -----------------------
+
+struct ImplBorderFrameData
+{
+ ImplBorderWindow* mpBorderWindow;
+ OutputDevice* mpOutDev;
+ Rectangle maTitleRect;
+ Rectangle maPinRect;
+ Rectangle maCloseRect;
+ Rectangle maRollRect;
+ Rectangle maDockRect;
+ Rectangle maHideRect;
+ Rectangle maHelpRect;
+ Point maMouseOff;
+ long mnWidth;
+ long mnHeight;
+ long mnTrackX;
+ long mnTrackY;
+ long mnTrackWidth;
+ long mnTrackHeight;
+ long mnLeftBorder;
+ long mnTopBorder;
+ long mnRightBorder;
+ long mnBottomBorder;
+ long mnNoTitleTop;
+ long mnBorderSize;
+ long mnTitleHeight;
+ long mnTitleOff;
+ USHORT mnHitTest;
+ USHORT mnPinState;
+ USHORT mnCloseState;
+ USHORT mnRollState;
+ USHORT mnDockState;
+ USHORT mnHideState;
+ USHORT mnHelpState;
+ USHORT mnTitleType;
+ BOOL mbFloatWindow;
+ BOOL mbDragFull;
+};
+
+// =======================================================================
+
+static void ImplGetPinImage( USHORT nStyle, BOOL bPinIn, Image& rImage )
+{
+ // ImageListe laden, wenn noch nicht vorhanden
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maCtrlData.mpPinImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_PIN, ImplGetResMgr() ) );
+ pSVData->maCtrlData.mpPinImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 4 );
+ }
+
+ // Image ermitteln und zurueckgeben
+ USHORT nId;
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ if ( bPinIn )
+ nId = 4;
+ else
+ nId = 3;
+ }
+ else
+ {
+ if ( bPinIn )
+ nId = 2;
+ else
+ nId = 1;
+ }
+ rImage = pSVData->maCtrlData.mpPinImgList->GetImage( nId );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcSymbolRect( Rectangle& rRect )
+{
+ // Den Rand den der Button in der nicht Default-Darstellung freilaesst,
+ // dazuaddieren, da wir diesen bei kleinen Buttons mit ausnutzen wollen
+ rRect.Left()--;
+ rRect.Top()--;
+ rRect.Right()++;
+ rRect.Bottom()++;
+
+ // Zwischen dem Symbol und dem Button-Rand lassen wir 5% Platz
+ long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000;
+ long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000;
+ rRect.Left() += nExtraWidth;
+ rRect.Right() -= nExtraWidth;
+ rRect.Top() += nExtraHeight;
+ rRect.Bottom() -= nExtraHeight;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBrdWinSymbol( OutputDevice* pDev,
+ const Rectangle& rRect, SymbolType eSymbol )
+{
+ // Zwischen dem Symbol und dem Button lassen wir 5% Platz
+ DecorationView aDecoView( pDev );
+ Rectangle aTempRect = rRect;
+ Window::ImplCalcSymbolRect( aTempRect );
+ aDecoView.DrawSymbol( aTempRect, eSymbol,
+ pDev->GetSettings().GetStyleSettings().GetButtonTextColor(), 0 );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBrdWinSymbolButton( OutputDevice* pDev,
+ const Rectangle& rRect,
+ SymbolType eSymbol, USHORT nState )
+{
+ DecorationView aDecoView( pDev );
+ Rectangle aTempRect = aDecoView.DrawButton( rRect, nState );
+ ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol );
+}
+
+// =======================================================================
+
+// ------------------------
+// - ImplBorderWindowView -
+// ------------------------
+
+class ImplBorderWindowView
+{
+public:
+ virtual ~ImplBorderWindowView();
+
+ virtual BOOL MouseMove( const MouseEvent& rMEvt );
+ virtual BOOL MouseButtonDown( const MouseEvent& rMEvt );
+ virtual BOOL Tracking( const TrackingEvent& rTEvt );
+ virtual USHORT RequestHelp( const Point& rPos, Rectangle& rHelpRect );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight ) = 0;
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const = 0;
+ virtual long CalcTitleWidth() const = 0;
+ virtual void DrawWindow( USHORT nDrawFlags ) = 0;
+
+ void ImplInitTitle( ImplBorderFrameData* pData );
+ USHORT ImplHitTest( ImplBorderFrameData* pData, const Point& rPos );
+ BOOL ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt );
+ BOOL ImplMouseButtonDown( ImplBorderFrameData* pData, const MouseEvent& rMEvt );
+ BOOL ImplTracking( ImplBorderFrameData* pData, const TrackingEvent& rTEvt );
+ USHORT ImplRequestHelp( ImplBorderFrameData* pData, const Point& rPos, Rectangle& rHelpRect );
+ long ImplCalcTitleWidth( const ImplBorderFrameData* pData ) const;
+};
+
+// -----------------------------------------------------------------------
+
+ImplBorderWindowView::~ImplBorderWindowView()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplBorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindowView::ImplInitTitle( ImplBorderFrameData* pData )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) ||
+ (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ {
+ pData->mnTitleType = BORDERWINDOW_TITLE_NONE;
+ pData->mnTitleHeight = 0;
+ }
+ else
+ {
+ const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
+ if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnTitleHeight = rStyleSettings.GetTearOffTitleHeight();
+ else
+ {
+ if ( pData->mnTitleType == BORDERWINDOW_TITLE_SMALL )
+ {
+ pBorderWindow->SetPointFont( rStyleSettings.GetFloatTitleFont() );
+ pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight();
+ }
+ else // pData->mnTitleType == BORDERWINDOW_TITLE_NORMAL
+ {
+ pBorderWindow->SetPointFont( rStyleSettings.GetTitleFont() );
+ pData->mnTitleHeight = rStyleSettings.GetTitleHeight();
+ }
+ long nTextHeight = pBorderWindow->GetTextHeight();
+ if ( nTextHeight > pData->mnTitleHeight )
+ pData->mnTitleHeight = nTextHeight;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplBorderWindowView::ImplHitTest( ImplBorderFrameData* pData, const Point& rPos )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( pData->maTitleRect.IsInside( rPos ) )
+ {
+ if ( pData->maCloseRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_CLOSE;
+ else if ( pData->maRollRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_ROLL;
+ else if ( pData->maDockRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_DOCK;
+ else if ( pData->maHideRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_HIDE;
+ else if ( pData->maHelpRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_HELP;
+ else if ( pData->maPinRect.IsInside( rPos ) )
+ return BORDERWINDOW_HITTEST_PIN;
+ else
+ return BORDERWINDOW_HITTEST_TITLE;
+ }
+
+ if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) &&
+ !pBorderWindow->mbRollUp )
+ {
+ long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight;
+ if ( nSizeWidth < 16 )
+ nSizeWidth = 16;
+ if ( rPos.X() < pData->mnLeftBorder )
+ {
+ if ( rPos.Y() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPLEFT;
+ else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMLEFT;
+ else
+ return BORDERWINDOW_HITTEST_LEFT;
+ }
+ else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder )
+ {
+ if ( rPos.Y() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPRIGHT;
+ else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_RIGHT;
+ }
+ else if ( rPos.Y() < pData->mnNoTitleTop )
+ {
+ if ( rPos.X() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPLEFT;
+ else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
+ return BORDERWINDOW_HITTEST_TOPRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_TOP;
+ }
+ else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder )
+ {
+ if ( rPos.X() < nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMLEFT;
+ else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
+ return BORDERWINDOW_HITTEST_BOTTOMRIGHT;
+ else
+ return BORDERWINDOW_HITTEST_BOTTOM;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT nHitTest = ImplHitTest( pData, aMousePos );
+ PointerStyle ePtrStyle = POINTER_ARROW;
+ if ( nHitTest & BORDERWINDOW_HITTEST_LEFT )
+ ePtrStyle = POINTER_WINDOW_WSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_RIGHT )
+ ePtrStyle = POINTER_WINDOW_ESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOP )
+ ePtrStyle = POINTER_WINDOW_NSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOM )
+ ePtrStyle = POINTER_WINDOW_SSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOPLEFT )
+ ePtrStyle = POINTER_WINDOW_NWSIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOMRIGHT )
+ ePtrStyle = POINTER_WINDOW_SESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_TOPRIGHT )
+ ePtrStyle = POINTER_WINDOW_NESIZE;
+ else if ( nHitTest & BORDERWINDOW_HITTEST_BOTTOMLEFT )
+ ePtrStyle = POINTER_WINDOW_SWSIZE;
+ pData->mpBorderWindow->SetPointer( Pointer( ePtrStyle ) );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplMouseButtonDown( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( rMEvt.IsLeft() || rMEvt.IsRight() )
+ {
+ pData->maMouseOff = rMEvt.GetPosPixel();
+ pData->mnHitTest = ImplHitTest( pData, pData->maMouseOff );
+ USHORT nDragFullTest = 0;
+ if ( pData->mnHitTest )
+ {
+ BOOL bTracking = TRUE;
+ BOOL bHitTest = TRUE;
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ pData->mnCloseState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ pData->mnRollState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ pData->mnDockState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ pData->mnHideState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ pData->mnHelpState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ pData->mnPinState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ else
+ {
+ if ( rMEvt.GetClicks() == 1 )
+ {
+ // Bei DockingWindows wollen wir Docking
+ if ( (pData->mnHitTest & BORDERWINDOW_HITTEST_TITLE) &&
+ pBorderWindow->ImplGetClientWindow()->ImplGetClientWindow() &&
+ pBorderWindow->ImplGetClientWindow()->ImplGetClientWindow()->ImplIsDockingWindow() )
+ {
+ if ( !pBorderWindow->mbRollUp )
+ {
+ Point aMousePos = pData->maMouseOff;
+ aMousePos.X() -= pData->mnLeftBorder;
+ aMousePos.Y() -= pData->mnTopBorder;
+ bTracking = !(((DockingWindow*)(pBorderWindow->ImplGetClientWindow()->ImplGetClientWindow()))->ImplStartDocking( aMousePos ));
+ }
+ }
+
+ if ( bTracking )
+ {
+ Point aPos = pBorderWindow->GetPosPixel();
+ Size aSize = pBorderWindow->GetOutputSizePixel();
+ pData->mnTrackX = aPos.X();
+ pData->mnTrackY = aPos.Y();
+ pData->mnTrackWidth = aSize.Width();
+ pData->mnTrackHeight = aSize.Height();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_TITLE )
+ nDragFullTest = DRAGFULL_OPTION_WINDOWMOVE;
+ else
+ nDragFullTest = DRAGFULL_OPTION_WINDOWSIZE;
+ }
+ }
+ else
+ {
+ bTracking = FALSE;
+
+ if ( (pData->mnHitTest & BORDERWINDOW_DRAW_TITLE) &&
+ ((rMEvt.GetClicks() % 2) == 0) )
+ {
+ pData->mnHitTest = 0;
+ bHitTest = FALSE;
+
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ if ( pBorderWindow->mbDockBtn )
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_DOCKING );
+ else if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ if ( pClientWindow->IsRollUp() )
+ pClientWindow->RollDown();
+ else
+ pClientWindow->RollUp();
+ pClientWindow->Roll();
+ }
+ }
+ }
+ }
+ }
+
+ if ( bTracking )
+ {
+ pData->mbDragFull = FALSE;
+ if ( nDragFullTest )
+ {
+ if ( pBorderWindow->GetSettings().GetStyleSettings().GetDragFullOptions() & nDragFullTest )
+ pData->mbDragFull = TRUE;
+ else
+ {
+ pBorderWindow->ImplUpdateAll();
+ pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
+ }
+ }
+ pBorderWindow->StartTracking();
+ }
+ else if ( bHitTest )
+ pData->mnHitTest = 0;
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplBorderWindowView::ImplTracking( ImplBorderFrameData* pData, const TrackingEvent& rTEvt )
+{
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ USHORT nHitTest = pData->mnHitTest;
+ pData->mnHitTest = 0;
+
+ if ( nHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ if ( pData->mnCloseState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnCloseState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ ((SystemWindow*)pBorderWindow->ImplGetClientWindow())->Close();
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->mnRollState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnRollState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ if ( pClientWindow->IsRollUp() )
+ pClientWindow->RollDown();
+ else
+ pClientWindow->RollUp();
+ pClientWindow->Roll();
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ if ( pData->mnDockState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnDockState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_DOCKING );
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ if ( pData->mnHideState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHideState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->TitleButtonClick( TITLE_BUTTON_HIDE );
+ }
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ if ( pData->mnHelpState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHelpState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ }
+ }
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ if ( pData->mnPinState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnPinState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+
+ // Bei Abbruch kein Click-Handler rufen
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ SystemWindow* pClientWindow = (SystemWindow*)(pBorderWindow->ImplGetClientWindow());
+ pClientWindow->SetPin( !pClientWindow->IsPined() );
+ pClientWindow->Pin();
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pData->mbDragFull )
+ {
+ // Bei Abbruch alten Zustand wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ pBorderWindow->SetPosSizePixel( Point( pData->mnTrackX, pData->mnTrackY ), Size( pData->mnTrackWidth, pData->mnTrackHeight ) );
+ }
+ else
+ {
+ pBorderWindow->HideTracking();
+ if ( !rTEvt.IsTrackingCanceled() )
+ pBorderWindow->SetPosSizePixel( Point( pData->mnTrackX, pData->mnTrackY ), Size( pData->mnTrackWidth, pData->mnTrackHeight ) );
+ }
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() )
+ {
+ if ( ((FloatingWindow*)pBorderWindow->ImplGetClientWindow())->IsInPopupMode() )
+ ((FloatingWindow*)pBorderWindow->ImplGetClientWindow())->EndPopupMode( FLOATWIN_POPUPMODEEND_TEAROFF );
+ }
+ }
+ }
+ }
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ if ( pData->maCloseRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnCloseState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnCloseState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ }
+ else
+ {
+ if ( pData->mnCloseState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnCloseState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_CLOSE );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->maRollRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnRollState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnRollState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ }
+ else
+ {
+ if ( pData->mnRollState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnRollState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_ROLL );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ if ( pData->maDockRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnDockState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnDockState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ }
+ else
+ {
+ if ( pData->mnDockState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnDockState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_DOCK );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ if ( pData->maHideRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnHideState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnHideState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ }
+ else
+ {
+ if ( pData->mnHideState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHideState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HIDE );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ if ( pData->maHelpRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnHelpState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnHelpState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ }
+ else
+ {
+ if ( pData->mnHelpState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnHelpState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_HELP );
+ }
+ }
+ }
+ else if ( pData->mnHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ if ( pData->maPinRect.IsInside( aMousePos ) )
+ {
+ if ( !(pData->mnPinState & BUTTON_DRAW_PRESSED) )
+ {
+ pData->mnPinState |= BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ }
+ else
+ {
+ if ( pData->mnPinState & BUTTON_DRAW_PRESSED )
+ {
+ pData->mnPinState &= ~BUTTON_DRAW_PRESSED;
+ DrawWindow( BORDERWINDOW_DRAW_PIN );
+ }
+ }
+ }
+ else
+ {
+ Point aFrameMousePos = pBorderWindow->ImplOutputToFrame( aMousePos );
+ Size aFrameSize = pBorderWindow->ImplGetFrameWindow()->GetOutputSizePixel();
+ if ( aFrameMousePos.X() < 0 )
+ aFrameMousePos.X() = 0;
+ if ( aFrameMousePos.Y() < 0 )
+ aFrameMousePos.Y() = 0;
+ if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
+ aFrameMousePos.X() = aFrameSize.Width()-1;
+ if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
+ aFrameMousePos.Y() = aFrameSize.Height()-1;
+ aMousePos = pBorderWindow->ImplFrameToOutput( aFrameMousePos );
+
+ aMousePos.X() -= pData->maMouseOff.X();
+ aMousePos.Y() -= pData->maMouseOff.Y();
+
+ if ( pData->mnHitTest & BORDERWINDOW_HITTEST_TITLE )
+ {
+ Point aPos = pBorderWindow->GetPosPixel();
+ aPos.X() += aMousePos.X();
+ aPos.Y() += aMousePos.Y();
+ if ( pData->mbDragFull )
+ {
+ pBorderWindow->SetPosPixel( aPos );
+ pBorderWindow->ImplUpdateAll();
+ pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
+ }
+ else
+ {
+ pData->mnTrackX = aPos.X();
+ pData->mnTrackY = aPos.Y();
+ pBorderWindow->ShowTracking( Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), SHOWTRACK_BIG );
+ }
+ }
+ else
+ {
+ Point aPos = pBorderWindow->GetPosPixel();
+ Size aSize = pBorderWindow->GetSizePixel();
+ Rectangle aNewRect( aPos, aSize );
+ long nOldWidth = aSize.Width();
+ long nOldHeight = aSize.Height();
+ long nBorderWidth = pData->mnLeftBorder+pData->mnRightBorder;
+ long nBorderHeight = pData->mnTopBorder+pData->mnBottomBorder;
+ long nMinWidth = pBorderWindow->mnMinWidth+nBorderWidth;
+ long nMinHeight = pBorderWindow->mnMinHeight+nBorderHeight;
+ long nMinWidth2 = nBorderWidth;
+
+ if ( pData->mnTitleHeight )
+ {
+ nMinWidth2 += 4;
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ nMinWidth2 += pData->maCloseRect.GetWidth();
+ }
+ if ( nMinWidth2 > nMinWidth )
+ nMinWidth = nMinWidth2;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_LEFT | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_BOTTOMLEFT) )
+ {
+ aNewRect.Left() += aMousePos.X();
+ if ( aNewRect.GetWidth() < nMinWidth )
+ aNewRect.Left() = aNewRect.Right()-nMinWidth+1;
+ }
+ else if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_RIGHT | BORDERWINDOW_HITTEST_TOPRIGHT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ {
+ aNewRect.Right() += aMousePos.X();
+ if ( aNewRect.GetWidth() < nMinWidth )
+ aNewRect.Right() = aNewRect.Left()+nMinWidth+1;
+ }
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_TOP | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_TOPRIGHT) )
+ {
+ aNewRect.Top() += aMousePos.Y();
+ if ( aNewRect.GetHeight() < nMinHeight )
+ aNewRect.Top() = aNewRect.Bottom()-nMinHeight+1;
+ }
+ else if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_BOTTOM | BORDERWINDOW_HITTEST_BOTTOMLEFT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ {
+ aNewRect.Bottom() += aMousePos.Y();
+ if ( aNewRect.GetHeight() < nMinHeight )
+ aNewRect.Bottom() = aNewRect.Top()+nMinHeight+1;
+ }
+
+ // Bei SystemWindows rufen wir den Resizing-Handler
+ if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
+ {
+ // Groesse fuer Resizing-Aufruf anpassen
+ aSize = aNewRect.GetSize();
+ aSize.Width() -= nBorderWidth;
+ aSize.Height() -= nBorderHeight;
+ ((SystemWindow*)pBorderWindow->ImplGetClientWindow())->Resizing( aSize );
+ aSize.Width() += nBorderWidth;
+ aSize.Height() += nBorderHeight;
+ if ( aSize.Width() < nMinWidth )
+ aSize.Width() = nMinWidth;
+ if ( aSize.Height() < nMinHeight )
+ aSize.Height() = nMinHeight;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_LEFT | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_BOTTOMLEFT) )
+ aNewRect.Left() = aNewRect.Right()-aSize.Width()+1;
+ else
+ aNewRect.Right() = aNewRect.Left()+aSize.Width()-1;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_TOP | BORDERWINDOW_HITTEST_TOPLEFT | BORDERWINDOW_HITTEST_TOPRIGHT) )
+ aNewRect.Top() = aNewRect.Bottom()-aSize.Height()+1;
+ else
+ aNewRect.Bottom() = aNewRect.Top()+aSize.Height()-1;
+ }
+
+ if ( pData->mbDragFull )
+ {
+ pBorderWindow->SetPosSizePixel( aNewRect.Left(), aNewRect.Top(),
+ aNewRect.GetWidth(), aNewRect.GetHeight(), WINDOW_POSSIZE_POSSIZE );
+ pBorderWindow->ImplUpdateAll();
+ pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_RIGHT | BORDERWINDOW_HITTEST_TOPRIGHT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ pData->maMouseOff.X() += aNewRect.GetWidth()-nOldWidth;
+ if ( pData->mnHitTest & (BORDERWINDOW_HITTEST_BOTTOM | BORDERWINDOW_HITTEST_BOTTOMLEFT | BORDERWINDOW_HITTEST_BOTTOMRIGHT) )
+ pData->maMouseOff.Y() += aNewRect.GetHeight()-nOldHeight;
+ }
+ else
+ {
+ pData->mnTrackX = aNewRect.Left();
+ pData->mnTrackY = aNewRect.Top();
+ pData->mnTrackWidth = aNewRect.GetWidth();
+ pData->mnTrackHeight = aNewRect.GetHeight();
+ pBorderWindow->ShowTracking( Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), SHOWTRACK_BIG );
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData* pData,
+ const Point& rPos,
+ Rectangle& rHelpRect )
+{
+ USHORT nHelpId = 0;
+ USHORT nHitTest = ImplHitTest( pData, rPos );
+ if ( nHitTest )
+ {
+ if ( nHitTest & BORDERWINDOW_HITTEST_CLOSE )
+ {
+ nHelpId = SV_HELPTEXT_CLOSE;
+ rHelpRect = pData->maCloseRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_ROLL )
+ {
+ if ( pData->mpBorderWindow->mbRollUp )
+ nHelpId = SV_HELPTEXT_ROLLDOWN;
+ else
+ nHelpId = SV_HELPTEXT_ROLLUP;
+ rHelpRect = pData->maRollRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_DOCK )
+ {
+ nHelpId = SV_HELPTEXT_MAXIMIZE;
+ rHelpRect = pData->maDockRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HIDE )
+ {
+ nHelpId = SV_HELPTEXT_MINIMIZE;
+ rHelpRect = pData->maHideRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_HELP )
+ {
+ nHelpId = SV_HELPTEXT_HELP;
+ rHelpRect = pData->maHelpRect;
+ }
+ else if ( nHitTest & BORDERWINDOW_HITTEST_PIN )
+ {
+ nHelpId = SV_HELPTEXT_ALWAYSVISIBLE;
+ rHelpRect = pData->maPinRect;
+ }
+ }
+
+ return nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData ) const
+{
+ // kein sichtbarer Title, dann auch keine Breite
+ if ( !pData->mnTitleHeight )
+ return 0;
+
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6;
+ nTitleWidth += pData->maPinRect.GetWidth();
+ nTitleWidth += pData->maCloseRect.GetWidth();
+ nTitleWidth += pData->maRollRect.GetWidth();
+ nTitleWidth += pData->maDockRect.GetWidth();
+ nTitleWidth += pData->maHideRect.GetWidth();
+ nTitleWidth += pData->maHelpRect.GetWidth();
+ nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder;
+ return nTitleWidth;
+}
+
+// =======================================================================
+
+// --------------------------
+// - ImplNoBorderWindowView -
+// --------------------------
+
+class ImplNoBorderWindowView : public ImplBorderWindowView
+{
+public:
+ ImplNoBorderWindowView( ImplBorderWindow* pBorderWindow );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+};
+
+// =======================================================================
+
+ImplNoBorderWindowView::ImplNoBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = 0;
+ rTopBorder = 0;
+ rRightBorder = 0;
+ rBottomBorder = 0;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplNoBorderWindowView::CalcTitleWidth() const
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplNoBorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+}
+
+// =======================================================================
+
+// -----------------------------
+// - ImplSmallBorderWindowView -
+// -----------------------------
+
+class ImplSmallBorderWindowView : public ImplBorderWindowView
+{
+ ImplBorderWindow* mpBorderWindow;
+ OutputDevice* mpOutDev;
+ long mnWidth;
+ long mnHeight;
+ long mnLeftBorder;
+ long mnTopBorder;
+ long mnRightBorder;
+ long mnBottomBorder;
+
+public:
+ ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow );
+
+ virtual void Init( OutputDevice* pOutDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+};
+
+// =======================================================================
+
+ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ mpBorderWindow = pBorderWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ mpOutDev = pDev;
+ mnWidth = nWidth;
+ mnHeight = nHeight;
+
+ USHORT nBorderStyle = mpBorderWindow->GetBorderStyle();
+ if ( nBorderStyle & WINDOW_BORDER_NOBORDER )
+ {
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ }
+ else
+ {
+ USHORT nStyle = FRAME_DRAW_NODRAW;
+ // Wenn Border umgesetzt wurde oder BorderWindow ein Frame-Fenster
+ // ist, dann Border nach aussen
+ if ( (nBorderStyle & WINDOW_BORDER_DOUBLEOUT) || mpBorderWindow->mbSmallOutBorder )
+ nStyle |= FRAME_DRAW_DOUBLEOUT;
+ else
+ nStyle |= FRAME_DRAW_DOUBLEIN;
+ if ( nBorderStyle & WINDOW_BORDER_MONO )
+ nStyle |= FRAME_DRAW_MONO;
+
+ DecorationView aDecoView( mpOutDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, nStyle );
+ mnLeftBorder = aCalcRect.Left();
+ mnTopBorder = aCalcRect.Top();
+ mnRightBorder = aRect.Right()-aCalcRect.Right();
+ mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = mnLeftBorder;
+ rTopBorder = mnTopBorder;
+ rRightBorder = mnRightBorder;
+ rBottomBorder = mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplSmallBorderWindowView::CalcTitleWidth() const
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSmallBorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+ USHORT nBorderStyle = mpBorderWindow->GetBorderStyle();
+ if ( nBorderStyle & WINDOW_BORDER_NOBORDER )
+ return;
+
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ {
+ if ( nBorderStyle & WINDOW_BORDER_ACTIVE )
+ {
+ Color aColor = mpOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
+ mpOutDev->SetLineColor();
+ mpOutDev->SetFillColor( aColor );
+ mpOutDev->DrawRect( Rectangle( 0, 0, mnWidth-1, mnTopBorder ) );
+ mpOutDev->DrawRect( Rectangle( 0, mnHeight-mnBottomBorder, mnWidth-1, mnHeight-1 ) );
+ mpOutDev->DrawRect( Rectangle( 0, 0, mnLeftBorder, mnHeight-1 ) );
+ mpOutDev->DrawRect( Rectangle( mnWidth-mnRightBorder, 0, mnWidth-1, mnHeight-1 ) );
+ }
+ else
+ {
+ USHORT nStyle = 0;
+ // Wenn Border umgesetzt wurde oder BorderWindow ein Frame-Fenster
+ // ist, dann Border nach aussen
+ if ( (nBorderStyle & WINDOW_BORDER_DOUBLEOUT) || mpBorderWindow->mbSmallOutBorder )
+ nStyle |= FRAME_DRAW_DOUBLEOUT;
+ else
+ nStyle |= FRAME_DRAW_DOUBLEIN;
+ if ( nBorderStyle & WINDOW_BORDER_MONO )
+ nStyle |= FRAME_DRAW_MONO;
+
+ DecorationView aDecoView( mpOutDev );
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( mnWidth, mnHeight ) );
+ aDecoView.DrawFrame( aInRect, nStyle );
+ }
+ }
+}
+
+// =======================================================================
+
+// ---------------------------
+// - ImplStdBorderWindowView -
+// ---------------------------
+
+class ImplStdBorderWindowView : public ImplBorderWindowView
+{
+ ImplBorderFrameData maFrameData;
+ VirtualDevice* mpATitleVirDev;
+ VirtualDevice* mpDTitleVirDev;
+
+public:
+ ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow );
+ ~ImplStdBorderWindowView();
+
+ virtual BOOL MouseMove( const MouseEvent& rMEvt );
+ virtual BOOL MouseButtonDown( const MouseEvent& rMEvt );
+ virtual BOOL Tracking( const TrackingEvent& rTEvt );
+ virtual USHORT RequestHelp( const Point& rPos, Rectangle& rHelpRect );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+};
+
+// =======================================================================
+
+ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ maFrameData.mpBorderWindow = pBorderWindow;
+ maFrameData.mbDragFull = FALSE;
+ maFrameData.mnHitTest = 0;
+ maFrameData.mnPinState = 0;
+ maFrameData.mnCloseState = 0;
+ maFrameData.mnRollState = 0;
+ maFrameData.mnDockState = 0;
+ maFrameData.mnHideState = 0;
+ maFrameData.mnHelpState = 0;
+
+ mpATitleVirDev = NULL;
+ mpDTitleVirDev = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplStdBorderWindowView::~ImplStdBorderWindowView()
+{
+ if ( mpATitleVirDev )
+ delete mpATitleVirDev;
+ if ( mpDTitleVirDev )
+ delete mpDTitleVirDev;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return ImplMouseMove( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return ImplMouseButtonDown( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return ImplTracking( &maFrameData, rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplStdBorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEOUT | FRAME_DRAW_NODRAW );
+
+ pData->mpOutDev = pDev;
+ pData->mnWidth = nWidth;
+ pData->mnHeight = nHeight;
+
+ pData->mnTitleType = pBorderWindow->mnTitleType;
+ pData->mbFloatWindow = pBorderWindow->mbFloatWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) || (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ pData->mnBorderSize = 0;
+ else if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnBorderSize = 0;
+ else
+ pData->mnBorderSize = rStyleSettings.GetBorderSize();
+ pData->mnLeftBorder = aCalcRect.Left();
+ pData->mnTopBorder = aCalcRect.Top();
+ pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
+ pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ pData->mnLeftBorder += pData->mnBorderSize;
+ pData->mnTopBorder += pData->mnBorderSize;
+ pData->mnRightBorder += pData->mnBorderSize;
+ pData->mnBottomBorder += pData->mnBorderSize;
+ pData->mnNoTitleTop = pData->mnTopBorder;
+
+ ImplInitTitle( &maFrameData );
+ if ( pData->mnTitleHeight )
+ {
+ pData->maTitleRect.Left() = pData->mnLeftBorder;
+ pData->maTitleRect.Right() = nWidth-pData->mnRightBorder-1;
+ pData->maTitleRect.Top() = pData->mnTopBorder;
+ pData->maTitleRect.Bottom() = pData->maTitleRect.Top()+pData->mnTitleHeight-1;
+
+ if ( pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL) )
+ {
+ long nLeft = pData->maTitleRect.Left();
+ long nRight = pData->maTitleRect.Right();
+ long nItemTop = pData->maTitleRect.Top();
+ long nItemBottom = pData->maTitleRect.Bottom();
+ nLeft += 1;
+ nRight -= 3;
+ nItemTop += 2;
+ nItemBottom -= 2;
+
+ if ( pBorderWindow->GetStyle() & WB_PINABLE )
+ {
+ Image aImage;
+ ImplGetPinImage( 0, 0, aImage );
+ pData->maPinRect.Top() = nItemTop;
+ pData->maPinRect.Bottom() = nItemBottom;
+ pData->maPinRect.Left() = nLeft;
+ pData->maPinRect.Right() = pData->maPinRect.Left()+aImage.GetSizePixel().Width();
+ nLeft += pData->maPinRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ {
+ pData->maCloseRect.Top() = nItemTop;
+ pData->maCloseRect.Bottom() = nItemBottom;
+ pData->maCloseRect.Right() = nRight;
+ pData->maCloseRect.Left() = pData->maCloseRect.Right()-pData->maCloseRect.GetHeight()+1;
+ nRight -= pData->maCloseRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->mbDockBtn )
+ {
+ pData->maDockRect.Top() = nItemTop;
+ pData->maDockRect.Bottom() = nItemBottom;
+ pData->maDockRect.Right() = nRight;
+ pData->maDockRect.Left() = pData->maDockRect.Right()-pData->maDockRect.GetHeight()+1;
+ nRight -= pData->maDockRect.GetWidth();
+ if ( !pBorderWindow->mbHideBtn &&
+ !(pBorderWindow->GetStyle() & WB_ROLLABLE) )
+ nRight -= 3;
+ }
+
+ if ( pBorderWindow->mbHideBtn )
+ {
+ pData->maHideRect.Top() = nItemTop;
+ pData->maHideRect.Bottom() = nItemBottom;
+ pData->maHideRect.Right() = nRight;
+ pData->maHideRect.Left() = pData->maHideRect.Right()-pData->maHideRect.GetHeight()+1;
+ nRight -= pData->maHideRect.GetWidth();
+ if ( !(pBorderWindow->GetStyle() & WB_ROLLABLE) )
+ nRight -= 3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ pData->maRollRect.Top() = nItemTop;
+ pData->maRollRect.Bottom() = nItemBottom;
+ pData->maRollRect.Right() = nRight;
+ pData->maRollRect.Left() = pData->maRollRect.Right()-pData->maRollRect.GetHeight()+1;
+ nRight -= pData->maRollRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbHelpBtn )
+ {
+ pData->maHelpRect.Top() = nItemTop;
+ pData->maHelpRect.Bottom() = nItemBottom;
+ pData->maHelpRect.Right() = nRight;
+ pData->maHelpRect.Left() = pData->maHelpRect.Right()-pData->maHelpRect.GetHeight()+1;
+ nRight -= pData->maHelpRect.GetWidth()+3;
+ }
+ }
+ else
+ {
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+
+ pData->mnTopBorder += pData->mnTitleHeight;
+ }
+ else
+ {
+ pData->maTitleRect.SetEmpty();
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = maFrameData.mnLeftBorder;
+ rTopBorder = maFrameData.mnTopBorder;
+ rRightBorder = maFrameData.mnRightBorder;
+ rBottomBorder = maFrameData.mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplStdBorderWindowView::CalcTitleWidth() const
+{
+ return ImplCalcTitleWidth( &maFrameData );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplStdBorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ OutputDevice* pDev = pData->mpOutDev;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ USHORT nStyle;
+ BOOL bActive = pBorderWindow->IsDisplayActive();
+
+ // Draw Frame
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ nStyle = 0;
+ else
+ nStyle = FRAME_DRAW_NODRAW;
+ aInRect = aDecoView.DrawFrame( aInRect, FRAME_DRAW_DOUBLEOUT | nStyle );
+
+ // Draw Border
+ pDev->SetLineColor();
+ long nBorderSize = pData->mnBorderSize;
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize )
+ {
+ if ( bActive )
+ pDev->SetFillColor( rStyleSettings.GetActiveBorderColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top() ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Bottom()-nBorderSize+1 ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Right()-nBorderSize+1, aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ }
+
+ // Draw Title
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_TITLE) && !pData->maTitleRect.IsEmpty() )
+ {
+ aInRect = pData->maTitleRect;
+
+ Color aColor2;
+ if ( bActive )
+ {
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetActiveTextColor() );
+ aColor2 = rStyleSettings.GetActiveColor2();
+ }
+ else
+ {
+ pDev->SetFillColor( rStyleSettings.GetDeactiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetDeactiveTextColor() );
+ aColor2 = rStyleSettings.GetDeactiveColor2();
+ }
+#ifndef REMOTE_APPSERVER
+ BOOL bDrawRect;
+ if ( pDev->GetColorCount() >= 256 )
+ {
+ Point aTempPoint;
+ Size aRectSize = aInRect.GetSize();
+ VirtualDevice* pVirDev;
+ if ( bActive )
+ pVirDev = mpATitleVirDev;
+ else
+ pVirDev = mpDTitleVirDev;
+ bDrawRect = FALSE;
+ if ( !pVirDev || (aRectSize != pVirDev->GetOutputSizePixel()) )
+ {
+ if ( !pVirDev )
+ {
+ pVirDev = new VirtualDevice( *pDev );
+ if ( bActive )
+ mpATitleVirDev = pVirDev;
+ else
+ mpDTitleVirDev = pVirDev;
+ }
+
+ Gradient aGradient( GRADIENT_LINEAR, pDev->GetFillColor(), aColor2 );
+ aGradient.SetAngle( 900 );
+ aGradient.SetBorder( 50 );
+ if ( pVirDev->SetOutputSizePixel( aRectSize ) )
+ pVirDev->DrawGradient( Rectangle( aTempPoint, aRectSize ), aGradient );
+ else
+ bDrawRect = TRUE;
+ }
+
+ if ( !bDrawRect )
+ {
+ pDev->DrawOutDev( aInRect.TopLeft(), aRectSize,
+ aTempPoint, aRectSize, *pVirDev );
+ }
+ }
+ else
+ bDrawRect = TRUE;
+
+ if ( bDrawRect )
+#endif
+ pDev->DrawRect( aInRect );
+
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ aInRect.Left() += 2;
+ aInRect.Right() -= 2;
+
+ if ( !pData->maPinRect.IsEmpty() )
+ aInRect.Left() = pData->maPinRect.Right()+2;
+
+ if ( !pData->maHelpRect.IsEmpty() )
+ aInRect.Right() = pData->maHelpRect.Left()-2;
+ else if ( !pData->maRollRect.IsEmpty() )
+ aInRect.Right() = pData->maRollRect.Left()-2;
+ else if ( !pData->maHideRect.IsEmpty() )
+ aInRect.Right() = pData->maHideRect.Left()-2;
+ else if ( !pData->maDockRect.IsEmpty() )
+ aInRect.Right() = pData->maDockRect.Left()-2;
+ else if ( !pData->maCloseRect.IsEmpty() )
+ aInRect.Right() = pData->maCloseRect.Left()-2;
+ pDev->DrawText( aInRect, pBorderWindow->GetText(),
+ TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER |
+ TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_CLIP );
+ }
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_CLOSE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maCloseRect.IsEmpty() )
+ ImplDrawBrdWinSymbolButton( pDev, pData->maCloseRect, SYMBOL_CLOSE, pData->mnCloseState );
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_DOCK) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maDockRect.IsEmpty() )
+ ImplDrawBrdWinSymbolButton( pDev, pData->maDockRect, SYMBOL_DOCK, pData->mnDockState );
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HIDE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHideRect.IsEmpty() )
+ ImplDrawBrdWinSymbolButton( pDev, pData->maHideRect, SYMBOL_HIDE, pData->mnHideState );
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_ROLL) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maRollRect.IsEmpty() )
+ {
+ SymbolType eType;
+ if ( pBorderWindow->mbRollUp )
+ eType = SYMBOL_ROLLDOWN;
+ else
+ eType = SYMBOL_ROLLUP;
+ ImplDrawBrdWinSymbolButton( pDev, pData->maRollRect, eType, pData->mnRollState );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HELP) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHelpRect.IsEmpty() )
+ ImplDrawBrdWinSymbolButton( pDev, pData->maHelpRect, SYMBOL_HELP, pData->mnHelpState );
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_PIN) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maPinRect.IsEmpty() )
+ {
+ Image aImage;
+ ImplGetPinImage( pData->mnPinState, pBorderWindow->mbPined, aImage );
+ Size aImageSize = aImage.GetSizePixel();
+ long nRectHeight = pData->maPinRect.GetHeight();
+ if ( nRectHeight < aImageSize.Height() )
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(), pData->maPinRect.Top() ),
+ Size( aImageSize.Width(), nRectHeight ),
+ aImage );
+ }
+ else
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(),
+ pData->maPinRect.Top()+(nRectHeight-aImageSize.Height())/2 ),
+ aImage );
+ }
+ }
+}
+
+// =======================================================================
+
+// ---------------------------
+// - ImplOS2BorderWindowView -
+// ---------------------------
+
+class ImplOS2BorderWindowView : public ImplBorderWindowView
+{
+ ImplBorderFrameData maFrameData;
+
+public:
+ ImplOS2BorderWindowView( ImplBorderWindow* pBorderWindow );
+ ~ImplOS2BorderWindowView();
+
+ virtual BOOL MouseMove( const MouseEvent& rMEvt );
+ virtual BOOL MouseButtonDown( const MouseEvent& rMEvt );
+ virtual BOOL Tracking( const TrackingEvent& rTEvt );
+ virtual USHORT RequestHelp( const Point& rPos, Rectangle& rHelpRect );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+
+ Rectangle DrawOS2TitleButton( const Rectangle& rRect, USHORT nStyle );
+};
+
+// Aus decoview.cxx
+void ImplDrawOS2Symbol( OutputDevice* pDev, const Rectangle& rRect,
+ USHORT nStyle, BOOL bClose );
+
+// =======================================================================
+
+ImplOS2BorderWindowView::ImplOS2BorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ maFrameData.mpBorderWindow = pBorderWindow;
+ maFrameData.mbDragFull = FALSE;
+ maFrameData.mnHitTest = 0;
+ maFrameData.mnPinState = 0;
+ maFrameData.mnCloseState = 0;
+ maFrameData.mnRollState = 0;
+ maFrameData.mnDockState = 0;
+ maFrameData.mnHideState = 0;
+ maFrameData.mnHelpState = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplOS2BorderWindowView::~ImplOS2BorderWindowView()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplOS2BorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return ImplMouseMove( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplOS2BorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return ImplMouseButtonDown( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplOS2BorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return ImplTracking( &maFrameData, rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplOS2BorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplOS2BorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEOUT | FRAME_DRAW_NODRAW );
+
+ pData->mpOutDev = pDev;
+ pData->mnWidth = nWidth;
+ pData->mnHeight = nHeight;
+
+ pData->mnTitleType = pBorderWindow->mnTitleType;
+ pData->mbFloatWindow = pBorderWindow->mbFloatWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) || (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ pData->mnBorderSize = 0;
+ else if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnBorderSize = 0;
+ else
+ pData->mnBorderSize = rStyleSettings.GetBorderSize();
+ pData->mnLeftBorder = aCalcRect.Left();
+ pData->mnTopBorder = aCalcRect.Top();
+ pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
+ pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ pData->mnLeftBorder += pData->mnBorderSize;
+ pData->mnTopBorder += pData->mnBorderSize;
+ pData->mnRightBorder += pData->mnBorderSize;
+ pData->mnBottomBorder += pData->mnBorderSize;
+ pData->mnNoTitleTop = pData->mnTopBorder;
+
+ ImplInitTitle( &maFrameData );
+ if ( pData->mnTitleHeight )
+ {
+ // Wegen 3D-Border bei aktiver Darstellung
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ long nTextHeight = pBorderWindow->GetTextHeight();
+ nTextHeight += 2;
+ if ( nTextHeight > pData->mnTitleHeight )
+ pData->mnTitleHeight = nTextHeight;
+ }
+
+ pData->maTitleRect.Left() = pData->mnLeftBorder;
+ pData->maTitleRect.Right() = nWidth-pData->mnRightBorder-1;
+ pData->maTitleRect.Top() = pData->mnTopBorder;
+ pData->maTitleRect.Bottom() = pData->maTitleRect.Top()+pData->mnTitleHeight-1;
+
+ if ( pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL) )
+ {
+ long nLeft = pData->maTitleRect.Left();
+ long nRight = pData->maTitleRect.Right();
+ long nItemTop = pData->maTitleRect.Top();
+ long nItemBottom = pData->maTitleRect.Bottom();
+
+ if ( pBorderWindow->mbHelpBtn )
+ {
+ pData->maHelpRect.Top() = nItemTop;
+ pData->maHelpRect.Bottom() = nItemBottom;
+ pData->maHelpRect.Left() = nLeft;
+ pData->maHelpRect.Right() = pData->maHelpRect.Left()+pData->maHelpRect.GetHeight()-1;
+ nLeft += pData->maHelpRect.GetWidth();
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_PINABLE )
+ {
+ nLeft += 2;
+ Image aImage;
+ ImplGetPinImage( 0, 0, aImage );
+ pData->maPinRect.Top() = nItemTop;
+ pData->maPinRect.Bottom() = nItemBottom;
+ pData->maPinRect.Left() = nLeft;
+ pData->maPinRect.Right() = pData->maPinRect.Left()+aImage.GetSizePixel().Width();
+ nLeft += pData->maPinRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbDockBtn )
+ {
+ pData->maDockRect.Top() = nItemTop;
+ pData->maDockRect.Bottom() = nItemBottom;
+ pData->maDockRect.Right() = nRight;
+ pData->maDockRect.Left() = pData->maDockRect.Right()-pData->maDockRect.GetHeight()+1;
+ nRight -= pData->maDockRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbHideBtn )
+ {
+ pData->maHideRect.Top() = nItemTop;
+ pData->maHideRect.Bottom() = nItemBottom;
+ pData->maHideRect.Right() = nRight;
+ pData->maHideRect.Left() = pData->maHideRect.Right()-pData->maHideRect.GetHeight()+1;
+ nRight -= pData->maHideRect.GetWidth();
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ pData->maRollRect.Top() = nItemTop;
+ pData->maRollRect.Bottom() = nItemBottom;
+ pData->maRollRect.Right() = nRight;
+ pData->maRollRect.Left() = pData->maRollRect.Right()-pData->maRollRect.GetHeight()+1;
+ nRight -= pData->maRollRect.GetWidth();
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ {
+ pData->maCloseRect.Top() = nItemTop;
+ pData->maCloseRect.Bottom() = nItemBottom;
+ pData->maCloseRect.Right() = nRight;
+ pData->maCloseRect.Left() = pData->maCloseRect.Right()-pData->maCloseRect.GetHeight()+1;
+ nRight -= pData->maCloseRect.GetWidth();
+ }
+ }
+ else
+ {
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+
+ pData->mnTopBorder += pData->mnTitleHeight;
+ }
+ else
+ {
+ pData->maTitleRect.SetEmpty();
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplOS2BorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = maFrameData.mnLeftBorder;
+ rTopBorder = maFrameData.mnTopBorder;
+ rRightBorder = maFrameData.mnRightBorder;
+ rBottomBorder = maFrameData.mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplOS2BorderWindowView::CalcTitleWidth() const
+{
+ return ImplCalcTitleWidth( &maFrameData );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplOS2BorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ OutputDevice* pDev = pData->mpOutDev;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ USHORT nStyle;
+ BOOL bActive = pBorderWindow->IsDisplayActive();
+
+ // Draw Frame
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ nStyle = 0;
+ else
+ nStyle = FRAME_DRAW_NODRAW;
+ aInRect = aDecoView.DrawFrame( aInRect, FRAME_DRAW_DOUBLEOUT | nStyle );
+
+ // Draw Border
+ pDev->SetLineColor();
+ long nBorderSize = pData->mnBorderSize;
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize )
+ {
+ if ( bActive )
+ pDev->SetFillColor( rStyleSettings.GetActiveBorderColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top() ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Bottom()-nBorderSize+1 ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Right()-nBorderSize+1, aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ }
+
+ // Draw Title
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_TITLE) && !pData->maTitleRect.IsEmpty() )
+ {
+ aInRect = pData->maTitleRect;
+
+ if ( !pData->maHelpRect.IsEmpty() )
+ aInRect.Left() = pData->maHelpRect.Right()+1;
+
+ if ( !pData->maCloseRect.IsEmpty() )
+ aInRect.Right() = pData->maCloseRect.Left()-1;
+ else if ( !pData->maRollRect.IsEmpty() )
+ aInRect.Right() = pData->maRollRect.Left()-1;
+ else if ( !pData->maHideRect.IsEmpty() )
+ aInRect.Right() = pData->maHideRect.Left()-1;
+ else if ( !pData->maDockRect.IsEmpty() )
+ aInRect.Right() = pData->maDockRect.Left()-1;
+
+ if ( bActive )
+ {
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetActiveTextColor() );
+ }
+ else
+ {
+ pDev->SetFillColor( rStyleSettings.GetDeactiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetDeactiveTextColor() );
+ }
+ pDev->DrawRect( aInRect );
+
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ Rectangle aOrgInRect = aInRect;
+
+ if ( !pData->maPinRect.IsEmpty() )
+ aInRect.Left() = pData->maPinRect.Right();
+
+ aInRect.Left() += 2;
+ aInRect.Right() -= 2;
+
+ pDev->DrawText( aInRect, pBorderWindow->GetText(),
+ TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER |
+ TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_CLIP );
+
+ if ( bActive )
+ aDecoView.DrawFrame( aOrgInRect, rStyleSettings.GetShadowColor(), rStyleSettings.GetLightColor() );
+ }
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_CLOSE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maCloseRect.IsEmpty() )
+ {
+ Rectangle aRect = DrawOS2TitleButton( pData->maCloseRect, pData->mnCloseState );
+ ImplDrawOS2Symbol( pDev, aRect, pData->mnCloseState, TRUE );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_DOCK) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maDockRect.IsEmpty() )
+ {
+ Rectangle aRect = DrawOS2TitleButton( pData->maDockRect, pData->mnDockState );
+ ImplDrawOS2Symbol( pDev, aRect, pData->mnDockState, FALSE );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HIDE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHideRect.IsEmpty() )
+ {
+ Rectangle aRect = DrawOS2TitleButton( pData->maHideRect, pData->mnHideState );
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+ ImplDrawOS2Symbol( pDev, aRect, pData->mnHideState, FALSE );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_ROLL) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maRollRect.IsEmpty() )
+ {
+ Rectangle aRect = DrawOS2TitleButton( pData->maRollRect, pData->mnRollState );
+ if ( !pBorderWindow->mbRollUp )
+ aRect.Bottom() = aRect.Top()+6;
+ ImplDrawOS2Symbol( pDev, aRect, pData->mnRollState, FALSE );
+ if ( pBorderWindow->mbRollUp )
+ {
+ aRect.Left() += 3;
+ aRect.Top() += 3;
+ aRect.Right() -= 3;
+ aRect.Bottom() -= 3;
+ pDev->SetFillColor();
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ aRect.Top()++;
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ }
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HELP) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHelpRect.IsEmpty() )
+ {
+ Rectangle aRect = DrawOS2TitleButton( pData->maHelpRect, pData->mnHelpState );
+ ImplDrawBrdWinSymbol( pDev, aRect, SYMBOL_HELP );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_PIN) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maPinRect.IsEmpty() )
+ {
+ Image aImage;
+ ImplGetPinImage( pData->mnPinState, pBorderWindow->mbPined, aImage );
+ Size aImageSize = aImage.GetSizePixel();
+ long nRectHeight = pData->maPinRect.GetHeight();
+ if ( nRectHeight < aImageSize.Height() )
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(), pData->maPinRect.Top() ),
+ Size( aImageSize.Width(), nRectHeight ),
+ aImage );
+ }
+ else
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(),
+ pData->maPinRect.Top()+(nRectHeight-aImageSize.Height())/2 ),
+ aImage );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplOS2BorderWindowView::DrawOS2TitleButton( const Rectangle& rRect, USHORT )
+{
+ OutputDevice* pDev = maFrameData.mpOutDev;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = rRect;
+
+ pDev->SetLineColor();
+ pDev->SetFillColor( rStyleSettings.GetFaceColor() );
+ pDev->DrawRect( aRect );
+
+ long nExtraWidth = ((aRect.GetWidth()*150)+500)/1000;
+ long nExtraHeight = ((aRect.GetHeight()*150)+500)/1000;
+ if ( !nExtraWidth )
+ nExtraWidth = 1;
+ if ( !nExtraHeight )
+ nExtraHeight = 1;
+ aRect.Left() += nExtraWidth;
+ aRect.Right() -= nExtraWidth;
+ aRect.Top() += nExtraHeight;
+ aRect.Bottom() -= nExtraHeight;
+ return aRect;
+}
+
+// =======================================================================
+
+// ---------------------------
+// - ImplUnxBorderWindowView -
+// ---------------------------
+
+class ImplUnxBorderWindowView : public ImplBorderWindowView
+{
+ ImplBorderFrameData maFrameData;
+
+public:
+ ImplUnxBorderWindowView( ImplBorderWindow* pBorderWindow );
+ ~ImplUnxBorderWindowView();
+
+ virtual BOOL MouseMove( const MouseEvent& rMEvt );
+ virtual BOOL MouseButtonDown( const MouseEvent& rMEvt );
+ virtual BOOL Tracking( const TrackingEvent& rTEvt );
+ virtual USHORT RequestHelp( const Point& rPos, Rectangle& rHelpRect );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+
+ Rectangle DrawUnxTitleButton( const Rectangle& rRect, USHORT nStyle );
+};
+
+// =======================================================================
+
+ImplUnxBorderWindowView::ImplUnxBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ maFrameData.mpBorderWindow = pBorderWindow;
+ maFrameData.mbDragFull = FALSE;
+ maFrameData.mnHitTest = 0;
+ maFrameData.mnPinState = 0;
+ maFrameData.mnCloseState = 0;
+ maFrameData.mnRollState = 0;
+ maFrameData.mnDockState = 0;
+ maFrameData.mnHideState = 0;
+ maFrameData.mnHelpState = 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplUnxBorderWindowView::~ImplUnxBorderWindowView()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplUnxBorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return ImplMouseMove( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplUnxBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return ImplMouseButtonDown( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplUnxBorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return ImplTracking( &maFrameData, rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplUnxBorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplUnxBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ Rectangle aRect( 0, 0, 10, 10 );
+ Rectangle aCalcRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEOUT | FRAME_DRAW_NODRAW );
+
+ pData->mpOutDev = pDev;
+ pData->mnWidth = nWidth;
+ pData->mnHeight = nHeight;
+
+ pData->mnTitleType = pBorderWindow->mnTitleType;
+ pData->mbFloatWindow = pBorderWindow->mbFloatWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) ||
+ (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ pData->mnBorderSize = 0;
+ else if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnBorderSize = 0;
+ else
+ {
+ pData->mnBorderSize = rStyleSettings.GetBorderSize();
+ if ( pData->mnBorderSize < 3 )
+ pData->mnBorderSize = 3;
+ aCalcRect = aRect;
+ }
+ pData->mnLeftBorder = aCalcRect.Left();
+ pData->mnTopBorder = aCalcRect.Top();
+ pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
+ pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
+ pData->mnLeftBorder += pData->mnBorderSize;
+ pData->mnTopBorder += pData->mnBorderSize;
+ pData->mnRightBorder += pData->mnBorderSize;
+ pData->mnBottomBorder += pData->mnBorderSize;
+ pData->mnNoTitleTop = pData->mnTopBorder;
+
+ ImplInitTitle( &maFrameData );
+ if ( pData->mnTitleHeight )
+ {
+ pData->maTitleRect.Left() = pData->mnLeftBorder;
+ pData->maTitleRect.Right() = nWidth-pData->mnRightBorder-1;
+ pData->maTitleRect.Top() = pData->mnTopBorder;
+ pData->maTitleRect.Bottom() = pData->maTitleRect.Top() + pData->mnTitleHeight - 1;
+
+ if ( pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL) )
+ {
+ long nLeft = pData->maTitleRect.Left();
+ long nRight = pData->maTitleRect.Right();
+ long nItemTop = pData->maTitleRect.Top();
+ long nItemBottom = pData->maTitleRect.Bottom();
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ {
+ pData->maCloseRect.Top() = nItemTop;
+ pData->maCloseRect.Bottom() = nItemBottom;
+ pData->maCloseRect.Left() = nLeft;
+ pData->maCloseRect.Right() = nLeft + pData->maCloseRect.GetHeight();
+ nLeft += pData->maCloseRect.GetWidth() + 2;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_PINABLE )
+ {
+ Image aImage;
+ ImplGetPinImage( 0, 0, aImage );
+ pData->maPinRect.Top() = nItemTop;
+ pData->maPinRect.Bottom() = nItemBottom;
+ pData->maPinRect.Left() = nLeft;
+ pData->maPinRect.Right() = pData->maPinRect.Left() + aImage.GetSizePixel().Width();
+ nLeft += pData->maPinRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbDockBtn )
+ {
+ pData->maDockRect.Top() = nItemTop;
+ pData->maDockRect.Bottom() = nItemBottom;
+ pData->maDockRect.Right() = nRight;
+ pData->maDockRect.Left() = pData->maDockRect.Right()-pData->maDockRect.GetHeight()+1;
+ nRight -= pData->maDockRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbHideBtn )
+ {
+ pData->maHideRect.Top() = nItemTop;
+ pData->maHideRect.Bottom() = nItemBottom;
+ pData->maHideRect.Right() = nRight;
+ pData->maHideRect.Left() = pData->maHideRect.Right()-pData->maHideRect.GetHeight()+1;
+ nRight -= pData->maHideRect.GetWidth();
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ pData->maRollRect.Top() = nItemTop;
+ pData->maRollRect.Bottom() = nItemBottom;
+ pData->maRollRect.Right() = nRight;
+ pData->maRollRect.Left() = pData->maRollRect.Right()-pData->maRollRect.GetHeight()+1;
+ nRight -= pData->maRollRect.GetWidth();
+ }
+
+ if ( pBorderWindow->mbHelpBtn )
+ {
+ pData->maHelpRect.Top() = nItemTop;
+ pData->maHelpRect.Bottom() = nItemBottom;
+ pData->maHelpRect.Right() = nRight;
+ pData->maHelpRect.Left() = pData->maHelpRect.Right()-pData->maHelpRect.GetHeight()+1;
+ nRight -= pData->maHelpRect.GetWidth();
+ }
+ }
+ else
+ {
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+
+ pData->mnTopBorder += pData->mnTitleHeight;
+ }
+ else
+ {
+ pData->maTitleRect.SetEmpty();
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplUnxBorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = maFrameData.mnLeftBorder;
+ rTopBorder = maFrameData.mnTopBorder;
+ rRightBorder = maFrameData.mnRightBorder;
+ rBottomBorder = maFrameData.mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplUnxBorderWindowView::CalcTitleWidth() const
+{
+ return ImplCalcTitleWidth( &maFrameData );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplUnxBorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ OutputDevice* pDev = pData->mpOutDev;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ DecorationView aDecoView( pDev );
+ USHORT nStyle;
+ BOOL bActive = pBorderWindow->IsDisplayActive();
+
+ // Color-Management for 3D-like Border
+ Color aLineColor;
+ Color aFillColor;
+ Color aLightColor;
+ Color aDarkColor;
+ Color aTextColor;
+ if ( bActive )
+ {
+ aLineColor = rStyleSettings.GetActiveBorderColor();
+ aFillColor = rStyleSettings.GetActiveColor();
+ aTextColor = rStyleSettings.GetActiveTextColor();
+ }
+ else
+ {
+ aLineColor = rStyleSettings.GetDeactiveBorderColor();
+ aFillColor = rStyleSettings.GetDeactiveColor();
+ aTextColor = rStyleSettings.GetDeactiveTextColor();
+ }
+ aLightColor = aLineColor;
+ aDarkColor = aLineColor;
+ aLightColor.IncreaseLuminance( 64 );
+ aDarkColor.DecreaseLuminance( 64 );
+
+ // Draw Frame
+ long nBorderSize = pData->mnBorderSize;
+ if ( !nBorderSize )
+ {
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ nStyle = 0;
+ else
+ nStyle = FRAME_DRAW_NODRAW;
+ aInRect = aDecoView.DrawFrame( aInRect, FRAME_DRAW_DOUBLEOUT | nStyle );
+ }
+ else
+ {
+ // Draw Border
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize )
+ {
+ // Geometry Presettings
+ long nOffset = 0;
+ long nEffBorderSize;
+ long nLeft = aInRect.Left();
+ long nRight = aInRect.Right();
+ long nTop = aInRect.Top();
+ long nBottom = aInRect.Bottom();
+
+ nEffBorderSize = nBorderSize > 2 ? nBorderSize - 2 : 1;
+
+ // outer border
+ pDev->SetLineColor( aLightColor );
+ pDev->DrawLine( Point( nLeft, nTop ), Point( nLeft, nBottom ) );
+ pDev->DrawLine( Point( nLeft, nTop ), Point( nRight, nTop ) );
+
+ pDev->SetLineColor( aDarkColor );
+ nTop++; nLeft++;
+ pDev->DrawLine( Point( nRight, nTop ), Point( nRight, nBottom ) );
+ pDev->DrawLine( Point( nLeft, nBottom ), Point( nRight, nBottom ) );
+
+ // middle border
+ pDev->SetLineColor();
+ pDev->SetFillColor( aLineColor );
+ nRight--; nBottom--;
+ pDev->DrawRect( Rectangle( Point( nLeft, nTop ),
+ Size( nRight - nLeft, nEffBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( nLeft, nTop ),
+ Size( nEffBorderSize, nBottom - nTop ) ) );
+ nRight -= nEffBorderSize;
+ nBottom -= nEffBorderSize;
+ pDev->DrawRect( Rectangle( Point( nRight + 1, nTop ),
+ Size( nEffBorderSize, nBottom - nTop + 1) ) );
+ pDev->DrawRect( Rectangle( Point( nLeft, nBottom + 1),
+ Size( nRight - nLeft + 1, nEffBorderSize ) ) );
+
+ // inner Border
+ pDev->SetLineColor( aDarkColor );
+ nTop += nEffBorderSize; nLeft += nEffBorderSize;
+ pDev->DrawLine( Point( nLeft, nTop ), Point( nLeft, nBottom ) );
+ pDev->DrawLine( Point( nLeft, nTop ), Point( nRight, nTop ) );
+
+ pDev->SetLineColor( aLightColor );
+ nTop++; nLeft++;
+ pDev->DrawLine( Point( nRight, nTop ), Point( nRight, nBottom ) );
+ pDev->DrawLine( Point( nLeft, nBottom ), Point( nRight, nBottom ) );
+
+ // edge intersections
+ if ( pBorderWindow->GetStyle() & WB_SIZEABLE )
+ {
+ nLeft = aInRect.Left();
+ nRight = aInRect.Right();
+ nTop = aInRect.Top();
+ nBottom = aInRect.Bottom();
+
+ if ( !pData->maTitleRect.IsEmpty() )
+ nOffset = pData->maTitleRect.GetHeight() + nEffBorderSize + 2;
+
+ pDev->SetLineColor( aDarkColor );
+ pDev->DrawLine( Point( nLeft + 1, nTop + nOffset ),
+ Point( nLeft + nEffBorderSize, nTop + nOffset ));
+ pDev->DrawLine( Point( nLeft + nOffset, nTop + 1 ),
+ Point( nLeft + nOffset, nTop + nEffBorderSize));
+ pDev->DrawLine( Point( nRight - 1, nTop + nOffset ),
+ Point( nRight - nEffBorderSize,nTop + nOffset ));
+ pDev->DrawLine( Point( nRight - nOffset, nTop + 1 ),
+ Point( nRight - nOffset, nTop + nEffBorderSize));
+
+ pDev->DrawLine( Point( nLeft + 1, nBottom - nOffset ),
+ Point( nLeft + nEffBorderSize, nBottom - nOffset ));
+ pDev->DrawLine( Point( nLeft + nOffset, nBottom - 1 ),
+ Point( nLeft + nOffset, nBottom - nEffBorderSize));
+ pDev->DrawLine( Point( nRight - 1, nBottom - nOffset ),
+ Point( nRight - nEffBorderSize,nBottom - nOffset ));
+ pDev->DrawLine( Point( nRight - nOffset, nBottom - 1 ),
+ Point( nRight - nOffset, nBottom - nEffBorderSize));
+ pDev->SetLineColor( aLightColor );
+ nEffBorderSize = nBorderSize > 1 ? nBorderSize - 1 : 1;
+ nOffset += 1;
+
+ pDev->DrawLine( Point( nLeft, nTop + nOffset ),
+ Point( nLeft + nEffBorderSize, nTop + nOffset ));
+ pDev->DrawLine( Point( nLeft + nOffset, nTop ),
+ Point( nLeft + nOffset, nTop + nEffBorderSize));
+ pDev->DrawLine( Point( nRight, nTop + nOffset ),
+ Point( nRight - nEffBorderSize,nTop + nOffset ));
+ pDev->DrawLine( Point( nLeft + nOffset, nBottom ),
+ Point( nLeft + nOffset, nBottom - nEffBorderSize));
+ nOffset -= 2;
+ pDev->DrawLine( Point( nRight - nOffset, nTop ),
+ Point( nRight - nOffset, nTop + nEffBorderSize));
+ pDev->DrawLine( Point( nLeft, nBottom - nOffset ),
+ Point( nLeft + nEffBorderSize, nBottom - nOffset ));
+ pDev->DrawLine( Point( nRight, nBottom - nOffset ),
+ Point( nRight - nEffBorderSize,nBottom - nOffset ));
+ pDev->DrawLine( Point( nRight - nOffset, nBottom ),
+ Point( nRight - nOffset, nBottom - nEffBorderSize));
+ }
+
+ // Reset Linecolor
+ pDev->SetLineColor();
+ }
+ }
+
+ // Draw Title
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_TITLE) && !pData->maTitleRect.IsEmpty() )
+ {
+ // Title Rect
+ aInRect = pData->maTitleRect;
+
+ pDev->SetFillColor( aFillColor );
+ pDev->SetTextColor( aTextColor );
+ pDev->DrawRect( aInRect );
+
+ // Title Rect Decoration
+ pDev->SetLineColor( aDarkColor );
+ pDev->DrawLine( Point( aInRect.Left(), aInRect.Bottom() ),
+ Point( aInRect.Right(), aInRect.Bottom() ) );
+ pDev->DrawLine( Point( aInRect.Right(), aInRect.Top() ),
+ Point( aInRect.Right(), aInRect.Bottom() ) );
+ pDev->SetLineColor( aLightColor );
+ pDev->DrawLine( Point( aInRect.Left(), aInRect.Top() ),
+ Point( aInRect.Right(), aInRect.Top() ) );
+ pDev->DrawLine( Point( aInRect.Left(), aInRect.Top() ),
+ Point( aInRect.Left(), aInRect.Bottom() ) );
+
+ long nLeft;
+ if ( !pData->maCloseRect.IsEmpty() )
+ nLeft = pData->maCloseRect.Right()+1;
+ else
+ nLeft = aInRect.Left()+1;
+
+ // Title Text
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ if ( !pData->maPinRect.IsEmpty() )
+ aInRect.Left() = pData->maPinRect.Right()+1;
+ else if ( !pData->maCloseRect.IsEmpty() )
+ aInRect.Left() = pData->maCloseRect.Right()+1;
+
+ if ( !pData->maHelpRect.IsEmpty() )
+ aInRect.Right() = pData->maHelpRect.Left()-1;
+ else if ( !pData->maRollRect.IsEmpty() )
+ aInRect.Right() = pData->maRollRect.Left()-1;
+ else if ( !pData->maHideRect.IsEmpty() )
+ aInRect.Right() = pData->maHideRect.Left()-1;
+ else if ( !pData->maDockRect.IsEmpty() )
+ aInRect.Right() = pData->maDockRect.Left()-1;
+
+ pDev->DrawText( aInRect, pBorderWindow->GetText(),
+ TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER |
+ TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_CLIP );
+ }
+
+ // more Title Rect Decoration
+ pDev->SetLineColor( aLightColor );
+ pDev->DrawLine( Point( nLeft, aInRect.Bottom() ),
+ Point( nLeft, aInRect.Top() ));
+ pDev->SetLineColor( aDarkColor );
+ pDev->DrawLine( Point( aInRect.Right(), aInRect.Top() ),
+ Point( aInRect.Right(), aInRect.Bottom() ) );
+ }
+
+ // Draw the buttons
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_CLOSE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maCloseRect.IsEmpty() )
+ {
+ Rectangle aInCloseRect = DrawUnxTitleButton( pData->maCloseRect,
+ pData->mnCloseState );
+ aDecoView.DrawSymbol( aInCloseRect, SYMBOL_CLOSE, aTextColor, 0 );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_DOCK) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maDockRect.IsEmpty() )
+ {
+ Rectangle aInDockRect = DrawUnxTitleButton( pData->maDockRect,
+ pData->mnDockState );
+ aDecoView.DrawSymbol( aInDockRect, SYMBOL_DOCK, aTextColor, 0 );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HIDE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHideRect.IsEmpty() )
+ {
+ Rectangle aInHideRect = DrawUnxTitleButton( pData->maHideRect,
+ pData->mnHideState );
+ aDecoView.DrawSymbol( aInHideRect, SYMBOL_HIDE, aTextColor, 0 );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_ROLL) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maRollRect.IsEmpty() )
+ {
+ Rectangle aInRollRect = DrawUnxTitleButton( pData->maRollRect,
+ pData->mnRollState );
+ SymbolType eType;
+ if ( pBorderWindow->mbRollUp )
+ eType = SYMBOL_ROLLDOWN;
+ else
+ eType = SYMBOL_ROLLUP;
+ aDecoView.DrawSymbol( aInRollRect, eType, aTextColor, 0 );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HELP) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHelpRect.IsEmpty() )
+ {
+ Rectangle aInHelpRect = DrawUnxTitleButton( pData->maHelpRect,
+ pData->mnHelpState );
+ aDecoView.DrawSymbol( aInHelpRect, SYMBOL_HELP, aTextColor, 0 );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_PIN) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maPinRect.IsEmpty() )
+ {
+ Image aImage;
+ ImplGetPinImage( pData->mnPinState, pBorderWindow->mbPined, aImage );
+ Size aImageSize = aImage.GetSizePixel();
+ long nRectHeight = pData->maPinRect.GetHeight();
+ if ( nRectHeight < aImageSize.Height() )
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(),
+ pData->maPinRect.Top() ),
+ Size( aImageSize.Width(), nRectHeight ),
+ aImage );
+ }
+ else
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(),
+ pData->maPinRect.Top()+(nRectHeight-aImageSize.Height())/2 ),
+ aImage );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplUnxBorderWindowView::DrawUnxTitleButton( const Rectangle& rRect, USHORT nStyle )
+{
+ Rectangle aFillRect = rRect;
+ OutputDevice* pDev = maFrameData.mpOutDev;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ BOOL bActive = pBorderWindow->IsDisplayActive();
+
+ // Color-Management for 3D-like Border
+ Color aLineColor;
+ Color aLightColor;
+ Color aDarkColor;
+ if ( bActive )
+ aLineColor = rStyleSettings.GetActiveBorderColor();
+ else
+ aLineColor = rStyleSettings.GetDeactiveBorderColor();
+ aLightColor = aLineColor;
+ aDarkColor = aLineColor;
+ aLightColor.IncreaseLuminance( 64 );
+ aDarkColor.DecreaseLuminance( 64 );
+
+ // Draw Button
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ // left and upper button-border
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( aDarkColor );
+ else
+ pDev->SetLineColor( aLightColor );
+ pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Top() ),
+ Point( aFillRect.Right(), aFillRect.Top() ) );
+ pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Top() ),
+ Point( aFillRect.Left(), aFillRect.Bottom() ) );
+
+ aFillRect.Left()++;
+ aFillRect.Top()++;
+
+ // right and bottom button-border
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( aLightColor );
+ else
+ pDev->SetLineColor( aDarkColor );
+ pDev->DrawLine( Point( aFillRect.Right(), aFillRect.Top() ),
+ Point( aFillRect.Right(), aFillRect.Bottom() ) );
+ pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Bottom() ),
+ Point( aFillRect.Right(), aFillRect.Bottom() ) );
+
+ aFillRect.Right()--;
+ aFillRect.Bottom()--;
+
+ // button area
+ pDev->SetFillColor( aLineColor );
+ pDev->SetLineColor();
+
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Top(),
+ aFillRect.Right(), aFillRect.Bottom() ) );
+ }
+
+ aFillRect.Left() += 3;
+ aFillRect.Top() += 3;
+ aFillRect.Right() -= 2;
+ aFillRect.Bottom() -= 2;
+ return aFillRect;
+}
+
+// =======================================================================
+
+// ---------------------------
+// - ImplMacBorderWindowView -
+// ---------------------------
+
+class ImplMacBorderWindowView : public ImplBorderWindowView
+{
+ ImplBorderFrameData maFrameData;
+ VirtualDevice maVirDev;
+ BOOL mbPressed;
+
+public:
+ ImplMacBorderWindowView( ImplBorderWindow* pBorderWindow );
+ ~ImplMacBorderWindowView();
+
+ virtual BOOL MouseMove( const MouseEvent& rMEvt );
+ virtual BOOL MouseButtonDown( const MouseEvent& rMEvt );
+ virtual BOOL Tracking( const TrackingEvent& rTEvt );
+ virtual USHORT RequestHelp( const Point& rPos, Rectangle& rHelpRect );
+
+ virtual void Init( OutputDevice* pDev, long nWidth, long nHeight );
+ virtual void GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const;
+ virtual long CalcTitleWidth() const;
+ virtual void DrawWindow( USHORT nDrawFlags );
+
+ Rectangle DrawMacTitleButton( const Rectangle& rRect, USHORT nStyle );
+};
+
+// =======================================================================
+
+ImplMacBorderWindowView::ImplMacBorderWindowView( ImplBorderWindow* pBorderWindow )
+{
+ maFrameData.mpBorderWindow = pBorderWindow;
+ maFrameData.mbDragFull = FALSE;
+ maFrameData.mnHitTest = 0;
+ maFrameData.mnPinState = 0;
+ maFrameData.mnCloseState = 0;
+ maFrameData.mnRollState = 0;
+ maFrameData.mnDockState = 0;
+ maFrameData.mnHideState = 0;
+ maFrameData.mnHelpState = 0;
+
+ mbPressed = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMacBorderWindowView::~ImplMacBorderWindowView()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplMacBorderWindowView::MouseMove( const MouseEvent& rMEvt )
+{
+ return ImplMouseMove( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplMacBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ return ImplMouseButtonDown( &maFrameData, rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplMacBorderWindowView::Tracking( const TrackingEvent& rTEvt )
+{
+ return ImplTracking( &maFrameData, rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplMacBorderWindowView::RequestHelp( const Point& rPos, Rectangle& rHelpRect )
+{
+ return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplMacBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+
+ pData->mpOutDev = pDev;
+ pData->mnWidth = nWidth;
+ pData->mnHeight = nHeight;
+
+ pData->mnTitleType = pBorderWindow->mnTitleType;
+ pData->mbFloatWindow = pBorderWindow->mbFloatWindow;
+
+ if ( !(pBorderWindow->GetStyle() & WB_MOVEABLE) || (pData->mnTitleType == BORDERWINDOW_TITLE_NONE) )
+ pData->mnBorderSize = 0;
+ else if ( pData->mnTitleType == BORDERWINDOW_TITLE_TEAROFF )
+ pData->mnBorderSize = 1;
+ else
+ pData->mnBorderSize = rStyleSettings.GetBorderSize();
+ pData->mnLeftBorder = 2;
+ pData->mnTopBorder = 2;
+ pData->mnRightBorder = 2;
+ pData->mnBottomBorder = 2;
+ pData->mnLeftBorder += pData->mnBorderSize;
+ pData->mnTopBorder += pData->mnBorderSize;
+ pData->mnRightBorder += pData->mnBorderSize;
+ pData->mnBottomBorder += pData->mnBorderSize;
+ pData->mnNoTitleTop = pData->mnTopBorder;
+ pData->mnTitleOff = 0;
+
+ ImplInitTitle( &maFrameData );
+ if ( pData->mnTitleHeight )
+ {
+ if ( (pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL)) &&
+ pData->mnBorderSize )
+ pData->mnTitleOff = 3; // 3 damit Hoehe auf dem MAC stimmt, ansonsten waere 2 richtig
+ pData->mnTitleHeight -= pData->mnTitleOff;
+ pData->maTitleRect.Left() = pData->mnLeftBorder;
+ pData->maTitleRect.Right() = nWidth-pData->mnRightBorder-1;
+ pData->maTitleRect.Top() = pData->mnTopBorder;
+ pData->maTitleRect.Bottom() = pData->maTitleRect.Top()+pData->mnTitleHeight-1;
+
+ if ( pData->mnTitleType & (BORDERWINDOW_TITLE_NORMAL | BORDERWINDOW_TITLE_SMALL) )
+ {
+ long nLeft = pData->maTitleRect.Left();
+ long nRight = pData->maTitleRect.Right();
+ long nItemTop = pData->maTitleRect.Top();
+ long nItemBottom = pData->maTitleRect.Bottom();
+
+ if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
+ {
+ pData->maCloseRect.Top() = nItemTop;
+ pData->maCloseRect.Bottom() = nItemBottom;
+ pData->maCloseRect.Left() = nLeft;
+ pData->maCloseRect.Right() = pData->maCloseRect.Left()+pData->maCloseRect.GetHeight()-1;
+ nLeft += pData->maCloseRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_PINABLE )
+ {
+ Image aImage;
+ ImplGetPinImage( 0, 0, aImage );
+ pData->maPinRect.Top() = nItemTop;
+ pData->maPinRect.Bottom() = nItemBottom;
+ pData->maPinRect.Left() = nLeft;
+ pData->maPinRect.Right() = pData->maPinRect.Left()+aImage.GetSizePixel().Width();
+ nLeft += pData->maPinRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->mbDockBtn )
+ {
+ pData->maDockRect.Top() = nItemTop;
+ pData->maDockRect.Bottom() = nItemBottom;
+ pData->maDockRect.Right() = nRight;
+ pData->maDockRect.Left() = pData->maDockRect.Right()-pData->maDockRect.GetHeight()+1;
+ nRight -= pData->maDockRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->mbHideBtn )
+ {
+ pData->maHideRect.Top() = nItemTop;
+ pData->maHideRect.Bottom() = nItemBottom;
+ pData->maHideRect.Right() = nRight;
+ pData->maHideRect.Left() = pData->maHideRect.Right()-pData->maHideRect.GetHeight()+1;
+ nRight -= pData->maHideRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
+ {
+ pData->maRollRect.Top() = nItemTop;
+ pData->maRollRect.Bottom() = nItemBottom;
+ pData->maRollRect.Right() = nRight;
+ pData->maRollRect.Left() = pData->maRollRect.Right()-pData->maRollRect.GetHeight()+1;
+ nRight -= pData->maRollRect.GetWidth()+3;
+ }
+
+ if ( pBorderWindow->mbHelpBtn )
+ {
+ pData->maHelpRect.Top() = nItemTop;
+ pData->maHelpRect.Bottom() = nItemBottom;
+ pData->maHelpRect.Right() = nRight;
+ pData->maHelpRect.Left() = pData->maHelpRect.Right()-pData->maHelpRect.GetHeight()+1;
+ nRight -= pData->maHelpRect.GetWidth()+3;
+ }
+ }
+ else
+ {
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+
+ pData->mnTopBorder += pData->mnTitleHeight;
+
+ // Innerer Border nur, wenn wir auch eine TitleBar haben
+ if ( !pBorderWindow->mbRollUp || pBorderWindow->mnRollHeight )
+ {
+ pData->mnTopBorder += 3+pData->mnBorderSize;
+ pData->mnBottomBorder += 3;
+ }
+ pData->mnLeftBorder += 3;
+ pData->mnRightBorder += 3;
+ }
+ else
+ {
+ pData->maTitleRect.SetEmpty();
+ pData->maPinRect.SetEmpty();
+ pData->maCloseRect.SetEmpty();
+ pData->maDockRect.SetEmpty();
+ pData->maHideRect.SetEmpty();
+ pData->maRollRect.SetEmpty();
+ pData->maHelpRect.SetEmpty();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplMacBorderWindowView::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ rLeftBorder = maFrameData.mnLeftBorder;
+ rTopBorder = maFrameData.mnTopBorder;
+ rRightBorder = maFrameData.mnRightBorder;
+ rBottomBorder = maFrameData.mnBottomBorder;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplMacBorderWindowView::CalcTitleWidth() const
+{
+ return ImplCalcTitleWidth( &maFrameData );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplMacBorderWindowView::DrawWindow( USHORT nDrawFlags )
+{
+ ImplBorderFrameData* pData = &maFrameData;
+ OutputDevice* pDev = pData->mpOutDev;
+ ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
+ Point aTmpPoint;
+ Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ BOOL bActive = pBorderWindow->IsDisplayActive();
+
+ // DrawFrame
+ pBorderWindow->SetFillColor();
+ if ( nDrawFlags & BORDERWINDOW_DRAW_FRAME )
+ {
+ if ( bActive )
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawRect( aInRect );
+ aInRect.Left()++;
+ aInRect.Top()++;
+ aInRect.Right()--;
+ aInRect.Bottom()--;
+ if ( bActive )
+ {
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Left(), aInRect.Bottom() ) );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Right(), aInRect.Top() ) );
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( aInRect.Left()+1, aInRect.Bottom() ), aInRect.BottomRight() );
+ pDev->DrawLine( Point( aInRect.Right(), aInRect.Top()+1 ), aInRect.BottomRight() );
+ }
+ else
+ {
+ pDev->SetLineColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( aInRect );
+ }
+ aInRect.Left()++;
+ aInRect.Top()++;
+ aInRect.Right()--;
+ aInRect.Bottom()--;
+ }
+ else
+ {
+ aInRect.Left() += 2;
+ aInRect.Top() += 2;
+ aInRect.Right() -= 2;
+ aInRect.Bottom() -= 2;
+ }
+
+ pBorderWindow->SetLineColor();
+ long nBorderSize = pData->mnBorderSize;
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize )
+ {
+ if ( bActive )
+ pDev->SetFillColor( rStyleSettings.GetActiveBorderColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top() ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Bottom()-nBorderSize+1 ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ pDev->DrawRect( Rectangle( Point( aInRect.Right()-nBorderSize+1, aInRect.Top()+nBorderSize ),
+ Size( nBorderSize, aInRect.GetHeight()-nBorderSize ) ) );
+ }
+ aInRect.Left() += nBorderSize;
+ aInRect.Top() += nBorderSize;
+ aInRect.Right() -= nBorderSize;
+ aInRect.Bottom() -= nBorderSize;
+
+ Rectangle aTitleRect = pData->maTitleRect;
+ XubString aText = pBorderWindow->GetText();
+ BOOL bDrawText = FALSE;
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_TITLE) && !pData->maTitleRect.IsEmpty() )
+ {
+ Rectangle aTextRect;
+ if ( bActive )
+ {
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetActiveTextColor() );
+ }
+ else
+ {
+ pDev->SetFillColor( rStyleSettings.GetDeactiveColor() );
+ pDev->SetTextColor( rStyleSettings.GetDeactiveTextColor() );
+ }
+ pDev->DrawRect( aTitleRect );
+
+ if ( pData->mnTitleType != BORDERWINDOW_TITLE_TEAROFF )
+ {
+ if ( !pData->maPinRect.IsEmpty() )
+ aTitleRect.Left() = pData->maPinRect.Right()+3;
+ else if ( !pData->maCloseRect.IsEmpty() )
+ aTitleRect.Left() = pData->maCloseRect.Right()+3;
+
+ if ( !pData->maHelpRect.IsEmpty() )
+ aTitleRect.Right() = pData->maHelpRect.Left()-3;
+ else if ( !pData->maHideRect.IsEmpty() )
+ aTitleRect.Right() = pData->maHideRect.Left()-3;
+ else if ( !pData->maDockRect.IsEmpty() )
+ aTitleRect.Right() = pData->maDockRect.Left()-3;
+ else if ( !pData->maRollRect.IsEmpty() )
+ aTitleRect.Right() = pData->maRollRect.Left()-3;
+
+ if ( aText.Len() )
+ {
+ aTextRect = pDev->GetTextRect( aTitleRect, aText,
+ TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER |
+ TEXT_DRAW_ENDELLIPSIS );
+ bDrawText = TRUE;
+ }
+ }
+
+ if ( bActive )
+ {
+ long nY = aTitleRect.Top();
+ long nYMax = nY+pData->mnTitleHeight-2+(pData->mnTitleHeight%2);
+ long nX1 = aTitleRect.Left();
+ long nX2;
+ long nX3;
+ long nX4;
+ BOOL bLines;
+ BOOL b2Lines;
+ if ( aTextRect.IsEmpty() )
+ {
+ nX2 = aTitleRect.Right();
+ bLines = nX2-2 > nX1;
+ b2Lines = FALSE;
+ }
+ else
+ {
+ aTextRect.Left() -= 4;
+ aTextRect.Right() += 4;
+ if ( (aTextRect.Left() > aTitleRect.Left()) &&
+ (aTextRect.Right() < aTitleRect.Right()) )
+ {
+ nX2 = aTextRect.Left();
+ nX3 = aTextRect.Right();
+ nX4 = aTitleRect.Right();
+ bLines = TRUE;
+ b2Lines = TRUE;
+ }
+ else
+ bLines = FALSE;
+ }
+
+ if ( bLines )
+ {
+ for ( ; nY < nYMax; nY += 2 )
+ {
+ if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ else
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( Point( nX1, nY ), Point( nX2-1, nY ) );
+ if ( b2Lines )
+ pDev->DrawLine( Point( nX3, nY ), Point( nX4-1, nY ) );
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( nX1+1, nY+1 ), Point( nX2, nY+1 ) );
+ if ( b2Lines )
+ pDev->DrawLine( Point( nX3+1, nY+1 ), Point( nX4, nY+1 ) );
+ }
+ }
+ }
+ }
+ }
+ aInRect.Top() += pData->mnTitleHeight;
+
+ if ( bActive )
+ {
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_CLOSE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maCloseRect.IsEmpty() )
+ DrawMacTitleButton( pData->maCloseRect, pData->mnCloseState );
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_PIN) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maPinRect.IsEmpty() )
+ {
+ Image aImage;
+ ImplGetPinImage( pData->mnPinState, pBorderWindow->mbPined, aImage );
+ Size aImageSize = aImage.GetSizePixel();
+ long nRectHeight = pData->maPinRect.GetHeight();
+ if ( nRectHeight < aImageSize.Height() )
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(), pData->maPinRect.Top() ),
+ Size( aImageSize.Width(), nRectHeight ),
+ aImage );
+ }
+ else
+ {
+ pDev->DrawImage( Point( pData->maPinRect.Left(),
+ pData->maPinRect.Top()+(nRectHeight-aImageSize.Height())/2 ),
+ aImage );
+ }
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_DOCK) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maDockRect.IsEmpty() )
+ {
+ Rectangle aInDockRect = DrawMacTitleButton( pData->maDockRect, pData->mnDockState );
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pDev->SetFillColor();
+ aInDockRect.Left()++;
+ aInDockRect.Top()++;
+ aInDockRect.Right()--;
+ aInDockRect.Bottom()--;
+ pDev->DrawRect( aInDockRect );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HIDE) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHideRect.IsEmpty() )
+ {
+ Rectangle aInHideRect = DrawMacTitleButton( pData->maHideRect, pData->mnHideState );
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pDev->DrawLine( Point( aInHideRect.Left(), aInHideRect.Bottom()-1 ), Point( aInHideRect.Right(), aInHideRect.Bottom()-1 ) );
+ pDev->DrawLine( Point( aInHideRect.Left(), aInHideRect.Bottom() ), Point( aInHideRect.Right(), aInHideRect.Bottom() ) );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_ROLL) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maRollRect.IsEmpty() )
+ {
+ Rectangle aInRollRect = DrawMacTitleButton( pData->maRollRect, pData->mnRollState );
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ long nY = aInRollRect.Center().Y();
+ pDev->DrawLine( Point( aInRollRect.Left(), nY-1 ), Point( aInRollRect.Right(), nY-1 ) );
+ pDev->DrawLine( Point( aInRollRect.Left(), nY+1 ), Point( aInRollRect.Right(), nY+1 ) );
+ }
+
+ if ( ((nDrawFlags & BORDERWINDOW_DRAW_HELP) || (nDrawFlags & BORDERWINDOW_DRAW_TITLE)) &&
+ !pData->maHelpRect.IsEmpty() )
+ {
+ Rectangle aInHelpRect = DrawMacTitleButton( pData->maHelpRect, pData->mnHelpState );
+ // ...
+ }
+ }
+
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_BORDER) && nBorderSize && !pData->maTitleRect.IsEmpty() )
+ {
+ pBorderWindow->SetLineColor();
+ if ( bActive )
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetDeactiveColor() );
+ pDev->DrawRect( Rectangle( Point( aInRect.Left(), aInRect.Top() ),
+ Size( aInRect.GetWidth(), nBorderSize ) ) );
+ }
+ aInRect.Top() += nBorderSize;
+
+ if ( (nDrawFlags & BORDERWINDOW_DRAW_FRAME) && !pData->maTitleRect.IsEmpty() &&
+ (!pBorderWindow->mbRollUp || pBorderWindow->mnRollHeight) )
+ {
+ pBorderWindow->SetFillColor();
+ if ( bActive )
+ {
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Left(), aInRect.Bottom() ) );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Right(), aInRect.Top() ) );
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( Point( aInRect.Left()+1, aInRect.Bottom() ), aInRect.BottomRight() );
+ pDev->DrawLine( Point( aInRect.Right(), aInRect.Top()+1 ), aInRect.BottomRight() );
+ }
+ else
+ {
+ pDev->SetLineColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( aInRect );
+ }
+ aInRect.Left()++;
+ aInRect.Top()++;
+ aInRect.Right()--;
+ aInRect.Bottom()--;
+ if ( bActive )
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawRect( aInRect );
+ aInRect.Left()++;
+ aInRect.Top()++;
+ aInRect.Right()--;
+ aInRect.Bottom()--;
+ if ( bActive )
+ {
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Left(), aInRect.Bottom() ) );
+ pDev->DrawLine( aInRect.TopLeft(), Point( aInRect.Right(), aInRect.Top() ) );
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( aInRect.Left()+1, aInRect.Bottom() ), aInRect.BottomRight() );
+ pDev->DrawLine( Point( aInRect.Right(), aInRect.Top()+1 ), aInRect.BottomRight() );
+ }
+ else
+ {
+ pDev->SetLineColor( rStyleSettings.GetDeactiveBorderColor() );
+ pDev->DrawRect( aInRect );
+ }
+ }
+
+ // Text als letztes zeichen, da auf dem MAC unter/ober-Laengen in
+ // den Border gezeichnet werden
+ if ( bDrawText )
+ {
+ pDev->DrawText( aTitleRect, aText,
+ TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER |
+ TEXT_DRAW_ENDELLIPSIS );
+ }
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BRWDIN_SEG1
+#endif
+
+// -----------------------------------------------------------------------
+
+Rectangle ImplMacBorderWindowView::DrawMacTitleButton( const Rectangle& rRect, USHORT nStyle )
+{
+ OutputDevice* pDev = maFrameData.mpOutDev;
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = rRect;
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( Point( aRect.Left()+1, aRect.Bottom() ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top()+1 ), aRect.BottomRight() );
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ BOOL bDrawRect;
+ if ( pDev->GetColorCount() >= 256 )
+ {
+ Point aTempPoint;
+ Size aRectSize = aRect.GetSize();
+ BOOL bNewPressed = (nStyle & BUTTON_DRAW_PRESSED) != 0;
+ bDrawRect = FALSE;
+ if ( (aRectSize != maVirDev.GetOutputSizePixel()) ||
+ (bNewPressed != mbPressed) )
+ {
+ Gradient aGradient( GRADIENT_LINEAR,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetLightColor() );
+ if ( bNewPressed )
+ {
+ aGradient.SetStartColor( rStyleSettings.GetDarkShadowColor() );
+ aGradient.SetEndColor( rStyleSettings.GetFaceColor() );
+ }
+ aGradient.SetAngle( 450 );
+ if ( maVirDev.SetOutputSizePixel( aRectSize ) )
+ maVirDev.DrawGradient( Rectangle( aTempPoint, aRectSize ), aGradient );
+ else
+ bDrawRect = TRUE;
+ mbPressed = bNewPressed;
+ }
+ if ( !bDrawRect )
+ {
+ pDev->DrawOutDev( aRect.TopLeft(), aRectSize,
+ aTempPoint, aRectSize, maVirDev );
+ pDev->SetFillColor();
+ }
+ }
+ else
+ bDrawRect = TRUE;
+ if ( bDrawRect )
+ {
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ pDev->SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ }
+ pDev->DrawRect( aRect );
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( aRect.Left()+1, aRect.Bottom() ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top()+1 ), aRect.BottomRight() );
+ }
+ else
+ {
+ pDev->SetLineColor( Color( COL_BLACK ) );
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ pDev->SetFillColor( Color( COL_BLACK ) );
+ else
+ pDev->SetFillColor( rStyleSettings.GetActiveColor() );
+ pDev->DrawRect( aRect );
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ }
+
+ return aRect;
+}
+
+// =======================================================================
+#ifdef REMOTE_APPSERVER
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ SystemParentData* pSystemParentData
+ )
+{
+ static ::com::sun::star::uno::Any aVoid;
+
+ DBG_ASSERT( pSystemParentData, "remote and non remote confusion, please clarify" );
+ ImplInit( pParent, nStyle, nTypeStyle, aVoid );
+}
+#else
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ const ::com::sun::star::uno::Any& aSystemToken )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, NULL );
+}
+#endif
+
+#ifndef REMOTE_APPSERVER
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ SystemParentData* pSystemParentData
+ )
+#else
+void ImplBorderWindow::ImplInit( Window* pParent,
+ WinBits nStyle,
+ USHORT nTypeStyle,
+ const ::com::sun::star::uno::Any& aSystemToken
+ )
+#endif
+{
+ // Alle WindowBits entfernen, die wir nicht haben wollen
+ WinBits nOrgStyle = nStyle;
+ WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL);
+ if ( nTypeStyle & BORDERWINDOW_STYLE_APP )
+ nTestStyle |= WB_APP;
+ nStyle &= nTestStyle;
+
+ mbBorderWin = TRUE;
+ mbSmallOutBorder = FALSE;
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FRAME )
+ {
+ mbOverlapWin = TRUE;
+ mbFrame = TRUE;
+ mbFrameBorder = FALSE;
+ if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER )
+ mbSmallOutBorder = TRUE;
+ }
+ else if ( nTypeStyle & BORDERWINDOW_STYLE_OVERLAP )
+ {
+ mbOverlapWin = TRUE;
+ mbFrameBorder = TRUE;
+ }
+ else
+ mbFrameBorder = FALSE;
+
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FLOAT )
+ mbFloatWindow = TRUE;
+ else
+ mbFloatWindow = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ Window::ImplInit( pParent, nStyle, pSystemParentData );
+#else
+ Window::ImplInit( pParent, nStyle, aSystemToken );
+#endif
+ SetBackground();
+ SetTextFillColor();
+
+ mpMenuBarWindow = NULL;
+ mnMinWidth = 0;
+ mnMinHeight = 0;
+ mnRollHeight = 0;
+ mnOrgMenuHeight = 0;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbMenuHide = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+ mbHelpBtn = FALSE;
+ mbDisplayActive = IsActive();
+
+ if ( nTypeStyle & BORDERWINDOW_STYLE_FLOAT )
+ mnTitleType = BORDERWINDOW_TITLE_SMALL;
+ else
+ mnTitleType = BORDERWINDOW_TITLE_NORMAL;
+ mnBorderStyle = WINDOW_BORDER_NORMAL;
+ InitView();
+}
+
+// =======================================================================
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent,
+ SystemParentData* pSystemParentData,
+ WinBits nStyle, USHORT nTypeStyle
+ ) : Window( WINDOW_BORDERWINDOW )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData );
+}
+
+// -----------------------------------------------------------------------
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent, WinBits nStyle ,
+ USHORT nTypeStyle ) :
+ Window( WINDOW_BORDERWINDOW )
+{
+ Reference< ::com::sun::star::portal::client::XRmFrameWindow > rxFrameWin;
+ ImplInit( pParent, nStyle, nTypeStyle, ::com::sun::star::uno::Any() );
+}
+
+ImplBorderWindow::ImplBorderWindow( Window* pParent,
+ WinBits nStyle, USHORT nTypeStyle,
+ const ::com::sun::star::uno::Any& aSystemToken ) :
+ Window( WINDOW_BORDERWINDOW )
+{
+ ImplInit( pParent, nStyle, nTypeStyle, aSystemToken );
+}
+
+// -----------------------------------------------------------------------
+
+ImplBorderWindow::~ImplBorderWindow()
+{
+ delete mpBorderView;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ mpBorderView->MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ mpBorderView->MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ mpBorderView->Tracking( rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Paint( const Rectangle& rRect )
+{
+ mpBorderView->DrawWindow( BORDERWINDOW_DRAW_ALL );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Activate()
+{
+ SetDisplayActive( TRUE );
+ Window::Activate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Deactivate()
+{
+ // Fenster die immer Active sind, nehmen wir von dieser Regel aus,
+ // genauso, wenn ein Menu aktiv wird, ignorieren wir das Deactivate
+ if ( GetActivateMode() && !ImplGetSVData()->maWinData.mbNoDeactivate )
+ SetDisplayActive( FALSE );
+ Window::Deactivate();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
+ Rectangle aHelpRect;
+ USHORT nHelpResId = mpBorderView->RequestHelp( aMousePosPixel, aHelpRect );
+
+ // Rechteck ermitteln
+ if ( nHelpResId )
+ {
+ Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
+ aHelpRect.Left() = aPt.X();
+ aHelpRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
+ aHelpRect.Right() = aPt.X();
+ aHelpRect.Bottom() = aPt.Y();
+
+ // Text ermitteln und anzeigen
+ XubString aStr( ResId( nHelpResId, ImplGetResMgr() ) );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aHelpRect, aStr );
+ return;
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+
+ if ( !mbRollUp )
+ {
+ Window* pClientWindow = ImplGetClientWindow();
+
+ if ( mpMenuBarWindow )
+ {
+ long nLeftBorder;
+ long nTopBorder;
+ long nRightBorder;
+ long nBottomBorder;
+ long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height();
+ if ( mbMenuHide )
+ {
+ if ( nMenuHeight )
+ mnOrgMenuHeight = nMenuHeight;
+ nMenuHeight = 0;
+ }
+ else
+ {
+ if ( !nMenuHeight )
+ nMenuHeight = mnOrgMenuHeight;
+ }
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ mpMenuBarWindow->SetPosSizePixel( nLeftBorder,
+ nTopBorder,
+ aSize.Width()-nLeftBorder-nRightBorder,
+ nMenuHeight,
+ WINDOW_POSSIZE_POS |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ }
+
+ GetBorder( pClientWindow->mnLeftBorder, pClientWindow->mnTopBorder,
+ pClientWindow->mnRightBorder, pClientWindow->mnBottomBorder );
+ pClientWindow->ImplPosSizeWindow( pClientWindow->mnLeftBorder,
+ pClientWindow->mnTopBorder,
+ aSize.Width()-pClientWindow->mnLeftBorder-pClientWindow->mnRightBorder,
+ aSize.Height()-pClientWindow->mnTopBorder-pClientWindow->mnBottomBorder,
+ WINDOW_POSSIZE_X | WINDOW_POSSIZE_Y |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ }
+
+ // UpdateView
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+
+ Window::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::StateChanged( StateChangedType nType )
+{
+ if ( (nType == STATE_CHANGE_TEXT) ||
+ (nType == STATE_CHANGE_IMAGE) ||
+ (nType == STATE_CHANGE_DATA) )
+ {
+ if ( IsReallyVisible() && mbFrameBorder )
+ {
+ if ( HasPaintEvent() )
+ InvalidateBorder();
+ else
+ mpBorderView->DrawWindow( BORDERWINDOW_DRAW_TITLE );
+ }
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ if ( !mbFrame )
+ UpdateView( TRUE, ImplGetWindow()->GetOutputSizePixel() );
+ }
+
+ Window::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::InitView()
+{
+ if ( mbSmallOutBorder )
+ mpBorderView = new ImplSmallBorderWindowView( this );
+ else if ( mbFrame )
+ mpBorderView = new ImplNoBorderWindowView( this );
+ else if ( !mbFrameBorder )
+ mpBorderView = new ImplSmallBorderWindowView( this );
+ else if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MACSTYLE )
+ mpBorderView = new ImplMacBorderWindowView( this );
+ else if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_OS2STYLE )
+ mpBorderView = new ImplOS2BorderWindowView( this );
+ else if ( GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_UNIXSTYLE )
+ mpBorderView = new ImplUnxBorderWindowView( this );
+ else
+ mpBorderView = new ImplStdBorderWindowView( this );
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::UpdateView( BOOL bNewView, const Size& rNewOutSize )
+{
+ long nLeftBorder;
+ long nTopBorder;
+ long nRightBorder;
+ long nBottomBorder;
+ Size aOldSize = GetSizePixel();
+ Size aOutputSize = rNewOutSize;
+
+ if ( bNewView )
+ {
+ delete mpBorderView;
+ InitView();
+ }
+ else
+ {
+ Size aSize = aOutputSize;
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ aSize.Width() += nLeftBorder+nRightBorder;
+ aSize.Height() += nTopBorder+nBottomBorder;
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ }
+
+ Window* pClientWindow = ImplGetClientWindow();
+ if ( pClientWindow )
+ {
+ GetBorder( pClientWindow->mnLeftBorder, pClientWindow->mnTopBorder,
+ pClientWindow->mnRightBorder, pClientWindow->mnBottomBorder );
+ }
+ GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ if ( aOldSize.Width() || aOldSize.Height() )
+ {
+ aOutputSize.Width() += nLeftBorder+nRightBorder;
+ aOutputSize.Height() += nTopBorder+nBottomBorder;
+ if ( aOutputSize == GetSizePixel() )
+ InvalidateBorder();
+ else
+ SetSizePixel( aOutputSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::InvalidateBorder()
+{
+ if ( IsReallyVisible() )
+ {
+ // Nur wenn wir einen Border haben, muessen wir auch invalidieren
+ long nLeftBorder;
+ long nTopBorder;
+ long nRightBorder;
+ long nBottomBorder;
+ mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ if ( nLeftBorder || nTopBorder || nRightBorder || nBottomBorder )
+ {
+ Rectangle aWinRect( Point( 0, 0 ), GetOutputSizePixel() );
+ Region aRegion( aWinRect );
+ aWinRect.Left() += nLeftBorder;
+ aWinRect.Top() += nTopBorder;
+ aWinRect.Right() -= nRightBorder;
+ aWinRect.Bottom() -= nBottomBorder;
+ // kein Output-Bereich mehr, dann alles invalidieren
+ if ( (aWinRect.Right() < aWinRect.Left()) ||
+ (aWinRect.Bottom() < aWinRect.Top()) )
+ Invalidate( INVALIDATE_NOCHILDREN );
+ else
+ {
+ aRegion.Exclude( aWinRect );
+ Invalidate( aRegion, INVALIDATE_NOCHILDREN );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetDisplayActive( BOOL bActive )
+{
+ if ( mbDisplayActive != bActive )
+ {
+ mbDisplayActive = bActive;
+ if ( mbFrameBorder )
+ InvalidateBorder();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetTitleType( USHORT nTitleType, const Size& rSize )
+{
+ mnTitleType = nTitleType;
+ UpdateView( FALSE, rSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetBorderStyle( USHORT nStyle )
+{
+ if ( !mbFrameBorder && (mnBorderStyle != nStyle) )
+ {
+ mnBorderStyle = nStyle;
+ UpdateView( FALSE, ImplGetWindow()->GetOutputSizePixel() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetPin( BOOL bPin )
+{
+ mbPined = bPin;
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetRollUp( BOOL bRollUp, const Size& rSize )
+{
+ mbRollUp = bRollUp;
+ mnRollHeight = rSize.Height();
+ UpdateView( FALSE, rSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetCloser()
+{
+ SetStyle( GetStyle() | WB_CLOSEABLE );
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetDockButton( BOOL bDockButton )
+{
+ mbDockBtn = bDockButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetHideButton( BOOL bHideButton )
+{
+ mbHideBtn = bHideButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetHelpButton( BOOL bHelpButton )
+{
+ mbHelpBtn = bHelpButton;
+ Size aSize = GetOutputSizePixel();
+ mpBorderView->Init( this, aSize.Width(), aSize.Height() );
+ InvalidateBorder();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::UpdateMenuHeight()
+{
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetMenuBarWindow( Window* pWindow )
+{
+ mpMenuBarWindow = pWindow;
+ UpdateMenuHeight();
+ if ( pWindow )
+ pWindow->Show();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::SetMenuBarMode( BOOL bHide )
+{
+ mbMenuHide = bHide;
+ UpdateMenuHeight();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplBorderWindow::GetBorder( long& rLeftBorder, long& rTopBorder,
+ long& rRightBorder, long& rBottomBorder ) const
+{
+ mpBorderView->GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
+ if ( mpMenuBarWindow && !mbMenuHide )
+ rTopBorder += mpMenuBarWindow->GetSizePixel().Height();
+}
+
+// -----------------------------------------------------------------------
+
+long ImplBorderWindow::CalcTitleWidth() const
+{
+ return mpBorderView->CalcTitleWidth();
+}
diff --git a/vcl/source/window/btndlg.cxx b/vcl/source/window/btndlg.cxx
new file mode 100644
index 000000000000..185da6bd83e0
--- /dev/null
+++ b/vcl/source/window/btndlg.cxx
@@ -0,0 +1,584 @@
+/*************************************************************************
+ *
+ * $RCSfile: btndlg.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BTNDLG_CXX
+#include <tools/ref.hxx>
+#ifndef _TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_BTNDLG_HXX
+#include <btndlg.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+
+#pragma hdrstop
+
+// =======================================================================
+
+struct ImplBtnDlgItem
+{
+ USHORT mnId;
+ BOOL mbOwnButton;
+ BOOL mbDummyAlign;
+ long mnSepSize;
+ PushButton* mpPushButton;
+};
+
+DECLARE_LIST( ImplBtnDlgItemList, ImplBtnDlgItem* );
+
+// =======================================================================
+
+void ButtonDialog::ImplInitData()
+{
+ mpItemList = new ImplBtnDlgItemList( 8, 8 );
+ mnButtonSize = 0;
+ mnCurButtonId = 0;
+ mnFocusButtonId = BUTTONDIALOG_BUTTON_NOTFOUND;
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( WindowType nType ) :
+ Dialog( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_TABDIALOG )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::ButtonDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_BUTTONDIALOG )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_DIALOG ); // !!!!!!!!!! RSC_BUTTONDIALOG !!!!!!!!
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+ButtonDialog::~ButtonDialog()
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mpPushButton && pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ButtonDialog::ImplCreatePushButton( USHORT nBtnFlags )
+{
+ PushButton* pBtn;
+ WinBits nStyle = 0;
+
+ if ( nBtnFlags & BUTTONDIALOG_DEFBUTTON )
+ nStyle |= WB_DEFBUTTON;
+ if ( nBtnFlags & BUTTONDIALOG_CANCELBUTTON )
+ pBtn = new CancelButton( this, nStyle );
+ else if ( nBtnFlags & BUTTONDIALOG_OKBUTTON )
+ pBtn = new OKButton( this, nStyle );
+ else if ( nBtnFlags & BUTTONDIALOG_HELPBUTTON )
+ pBtn = new HelpButton( this, nStyle );
+ else
+ pBtn = new PushButton( this, nStyle );
+
+ if ( !(nBtnFlags & BUTTONDIALOG_HELPBUTTON) )
+ pBtn->SetClickHdl( LINK( this, ButtonDialog, ImplClickHdl ) );
+
+ return pBtn;
+}
+
+// -----------------------------------------------------------------------
+
+ImplBtnDlgItem* ButtonDialog::ImplGetItem( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nId )
+ return pItem;
+
+ pItem = mpItemList->Next();
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+long ButtonDialog::ImplGetButtonSize()
+{
+ if ( !mbFormat )
+ return mnButtonSize;
+
+ // Calculate ButtonSize
+ long nLastSepSize = 0;
+ long nSepSize = 0;
+ long nButtonCount = 0;
+ maCtrlSize = Size( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ nSepSize += nLastSepSize;
+
+ long nTxtWidth = pItem->mpPushButton->GetCtrlTextWidth( pItem->mpPushButton->GetText() );
+ nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
+ if ( nTxtWidth > maCtrlSize.Width() )
+ maCtrlSize.Width() = nTxtWidth;
+ long nTxtHeight = pItem->mpPushButton->GetTextHeight();
+ nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
+ if ( nTxtHeight > maCtrlSize.Height() )
+ maCtrlSize.Height() = nTxtHeight;
+
+ nSepSize += pItem->mnSepSize;
+
+ if ( GetStyle() & WB_HORZ )
+ nLastSepSize = IMPL_SEP_BUTTON_X;
+ else
+ nLastSepSize = IMPL_SEP_BUTTON_Y;
+
+ nButtonCount++;
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( GetStyle() & WB_HORZ )
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Width());
+ else
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Height());
+
+ return mnButtonSize;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::ImplPosControls()
+{
+ if ( !mbFormat )
+ return;
+
+ // Create PushButtons and determine Sizes
+ ImplGetButtonSize();
+
+ // determine dialog size
+ ImplBtnDlgItem* pItem;
+ Size aDlgSize = maPageSize;
+ long nX;
+ long nY;
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Width() )
+ aDlgSize.Width() = mnButtonSize+(IMPL_DIALOG_OFFSET*2);
+ if ( GetStyle() & WB_LEFT )
+ nX = IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_RIGHT )
+ nX = aDlgSize.Width()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else
+ nX = (aDlgSize.Width()-mnButtonSize)/2;
+
+ aDlgSize.Height() += IMPL_DIALOG_OFFSET+maCtrlSize.Height();
+ nY = aDlgSize.Height()-maCtrlSize.Height()-IMPL_DIALOG_OFFSET;
+ }
+ else
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Height() )
+ aDlgSize.Height() = mnButtonSize+(IMPL_DIALOG_OFFSET*2);
+ if ( GetStyle() & WB_BOTTOM )
+ nY = aDlgSize.Height()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_VCENTER )
+ nY = (aDlgSize.Height()-mnButtonSize)/2;
+ else
+ nY = IMPL_DIALOG_OFFSET;
+
+ aDlgSize.Width() += IMPL_DIALOG_OFFSET+maCtrlSize.Width();
+ nX = aDlgSize.Width()-maCtrlSize.Width()-IMPL_DIALOG_OFFSET;
+ }
+
+ // Arrange PushButtons
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( GetStyle() & WB_HORZ )
+ nX += pItem->mnSepSize;
+ else
+ nY += pItem->mnSepSize;
+ pItem->mpPushButton->SetPosSizePixel( Point( nX, nY ), maCtrlSize );
+ pItem->mpPushButton->Show();
+ if ( GetStyle() & WB_HORZ )
+ nX += maCtrlSize.Width()+IMPL_SEP_BUTTON_X;
+ else
+ nY += maCtrlSize.Height()+IMPL_SEP_BUTTON_Y;
+
+ pItem = mpItemList->Next();
+ }
+
+ SetOutputSizePixel( aDlgSize );
+
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ButtonDialog, ImplClickHdl, PushButton*, pBtn )
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mpPushButton == pBtn )
+ {
+ mnCurButtonId = pItem->mnId;
+ Click();
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Resize()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ ImplPosControls();
+
+ // Focus evt. auf den entsprechenden Button setzen
+ if ( mnFocusButtonId != BUTTONDIALOG_BUTTON_NOTFOUND )
+ {
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == mnFocusButtonId )
+ {
+ if ( pItem->mpPushButton->IsVisible() )
+ pItem->mpPushButton->GrabFocus();
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+ }
+
+ Dialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Click()
+{
+ if ( !maClickHdl )
+ {
+ if ( IsInExecute() )
+ EndDialog( GetCurButtonId() );
+ }
+ else
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( const XubString& rText, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = TRUE;
+ pItem->mnSepSize = nSepPixel;
+ pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
+ if ( rText.Len() )
+ pItem->mpPushButton->SetText( rText );
+
+ // In die StarView-Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( StandardButtonType eType, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = TRUE;
+ pItem->mnSepSize = nSepPixel;
+
+ if ( eType == BUTTON_HELP )
+ nBtnFlags |= BUTTONDIALOG_HELPBUTTON;
+ else if ( (eType == BUTTON_CANCEL) || (eType == BUTTON_CLOSE) )
+ nBtnFlags |= BUTTONDIALOG_CANCELBUTTON;
+ pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
+ pItem->mpPushButton->SetText( Button::GetStandardText( eType ) );
+ pItem->mpPushButton->SetHelpText( Button::GetStandardHelpText( eType ) );
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ // In die StarView-Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::AddButton( PushButton* pBtn, USHORT nId,
+ USHORT nBtnFlags, long nSepPixel )
+{
+ // PageItem anlegen
+ ImplBtnDlgItem* pItem = new ImplBtnDlgItem;
+ pItem->mnId = nId;
+ pItem->mbOwnButton = FALSE;
+ pItem->mnSepSize = nSepPixel;
+ pItem->mpPushButton = pBtn;
+
+ if ( nBtnFlags & BUTTONDIALOG_FOCUSBUTTON )
+ mnFocusButtonId = nId;
+
+ // In die StarView-Liste eintragen
+ mpItemList->Insert( pItem, LIST_APPEND );
+
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::RemoveButton( USHORT nId )
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nId )
+ {
+ pItem->mpPushButton->Hide();
+ if ( pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ mpItemList->Remove();
+ mbFormat = TRUE;
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ DBG_ERRORFILE( "ButtonDialog::RemoveButton(): ButtonId invalid" );
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::Clear()
+{
+ ImplBtnDlgItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ pItem->mpPushButton->Hide();
+ if ( pItem->mbOwnButton )
+ delete pItem->mpPushButton;
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ mpItemList->Clear();
+ mbFormat = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ButtonDialog::GetButtonCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ButtonDialog::GetButtonId( USHORT nButton ) const
+{
+ if ( nButton < mpItemList->Count() )
+ return (USHORT)mpItemList->GetObject( nButton )->mnId;
+ else
+ return BUTTONDIALOG_BUTTON_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ButtonDialog::GetPushButton( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonText( USHORT nId, const XubString& rText )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ {
+ pItem->mpPushButton->SetText( rText );
+ mbFormat = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString ButtonDialog::GetButtonText( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetText();
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonHelpText( USHORT nId, const XubString& rText )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ pItem->mpPushButton->SetHelpText( rText );
+}
+
+// -----------------------------------------------------------------------
+
+XubString ButtonDialog::GetButtonHelpText( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetHelpText();
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ButtonDialog::SetButtonHelpId( USHORT nId, ULONG nHelpId )
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ pItem->mpPushButton->SetHelpId( nHelpId );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ButtonDialog::GetButtonHelpId( USHORT nId ) const
+{
+ ImplBtnDlgItem* pItem = ImplGetItem( nId );
+
+ if ( pItem )
+ return pItem->mpPushButton->GetHelpId();
+ else
+ return 0;
+}
diff --git a/vcl/source/window/cursor.cxx b/vcl/source/window/cursor.cxx
new file mode 100644
index 000000000000..ec2bb1c80506
--- /dev/null
+++ b/vcl/source/window/cursor.cxx
@@ -0,0 +1,449 @@
+/*************************************************************************
+ *
+ * $RCSfile: cursor.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CURSOR_CXX
+
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+struct ImplCursorData
+{
+ AutoTimer maTimer; // Timer
+ Point maPixPos; // Pixel-Position
+ Point maPixRotOff; // Pixel-Offset-Position
+ Size maPixSize; // Pixel-Size
+ long mnPixSlant; // Pixel-Slant
+ short mnOrientation; // Pixel-Orientation
+ USHORT mnStyle; // Cursor-Style
+ BOOL mbCurVisible; // Ist Cursor aktuell sichtbar
+ Window* mpWindow; // Zugeordnetes Windows
+};
+
+// =======================================================================
+
+static void ImplCursorInvert( ImplCursorData* pData )
+{
+ Window* pWindow = pData->mpWindow;
+ BOOL bMapMode = pWindow->IsMapModeEnabled();
+ pWindow->EnableMapMode( FALSE );
+ USHORT nInvertStyle;
+ if ( pData->mnStyle & CURSOR_SHADOW )
+ nInvertStyle = INVERT_50;
+ else
+ nInvertStyle = 0;
+ Rectangle aRect( pData->maPixPos, pData->maPixSize );
+ if ( pData->mnOrientation || pData->mnPixSlant )
+ {
+ Polygon aPoly( aRect );
+ if ( pData->mnPixSlant )
+ {
+ Point aPoint = aPoly.GetPoint( 0 );
+ aPoint.X() += pData->mnPixSlant;
+ aPoly.SetPoint( aPoint, 0 );
+ aPoly.SetPoint( aPoint, 4 );
+ aPoint = aPoly.GetPoint( 1 );
+ aPoint.X() += pData->mnPixSlant;
+ aPoly.SetPoint( aPoint, 1 );
+ }
+ if ( pData->mnOrientation )
+ aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
+ pWindow->Invert( aPoly, nInvertStyle );
+ }
+ else
+ pWindow->Invert( aRect, nInvertStyle );
+ pWindow->EnableMapMode( bMapMode );
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplDraw()
+{
+ if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
+ {
+ Window* pWindow = mpData->mpWindow;
+ mpData->maPixPos = pWindow->LogicToPixel( maPos );
+ mpData->maPixSize = pWindow->LogicToPixel( maSize );
+ mpData->mnPixSlant = pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
+ mpData->mnOrientation = mnOrientation;
+ long nOffsetY = pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();
+
+ // Position um den Offset korrigieren
+ mpData->maPixPos.Y() -= nOffsetY;
+ mpData->maPixRotOff = mpData->maPixPos;
+ mpData->maPixRotOff.Y() += nOffsetY;
+
+ // Wenn groesse 0 ist, nehmen wir die breite, die in den
+ // Settings eingestellt ist
+ if ( !mpData->maPixSize.Width() )
+ mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();
+
+ // Ausgabeflaeche berechnen und ausgeben
+ ImplCursorInvert( mpData );
+ mpData->mbCurVisible = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplRestore()
+{
+ if ( mpData && mpData->mbCurVisible )
+ {
+ ImplCursorInvert( mpData );
+ mpData->mbCurVisible = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplShow( BOOL bDrawDirect )
+{
+ if ( mbVisible )
+ {
+ Window* pWindow;
+ if ( mpWindow )
+ pWindow = mpWindow;
+ else
+ {
+ // Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
+ // selektiert, dann zeige den Cursor an
+ pWindow = Application::GetFocusWindow();
+ if ( !pWindow || (pWindow->mpCursor != this) || pWindow->mbInPaint )
+ pWindow = NULL;
+ }
+
+ if ( pWindow )
+ {
+ if ( !mpData )
+ {
+ mpData = new ImplCursorData;
+ mpData->mbCurVisible = FALSE;
+ mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
+ }
+
+ mpData->mpWindow = pWindow;
+ mpData->mnStyle = mnStyle;
+ if ( bDrawDirect )
+ ImplDraw();
+
+ if ( !mpWindow )
+ {
+ mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
+ if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
+ mpData->maTimer.Start();
+ else if ( !mpData->mbCurVisible )
+ ImplDraw();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplHide()
+{
+ if ( mpData && mpData->mpWindow )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ mpData->maTimer.Stop();
+ mpData->mpWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::ImplNew()
+{
+ if ( mbVisible && mpData && mpData->mpWindow )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ ImplDraw();
+ if ( !mpWindow )
+ {
+ if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
+ mpData->maTimer.Start();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
+{
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+ else
+ ImplDraw();
+ return 0;
+}
+
+// =======================================================================
+
+Cursor::Cursor()
+{
+ mpData = NULL;
+ mpWindow = NULL;
+ mnSlant = 0;
+ mnOffsetY = 0;
+ mnOrientation = 0;
+ mnStyle = 0;
+ mbVisible = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Cursor::Cursor( const Cursor& rCursor ) :
+ maPos( rCursor.maPos ),
+ maSize( rCursor.maSize )
+{
+ mpData = NULL;
+ mpWindow = NULL;
+ mnSlant = rCursor.mnSlant;
+ mnOrientation = rCursor.mnOrientation;
+ mnStyle = 0;
+ mbVisible = rCursor.mbVisible;
+}
+
+// -----------------------------------------------------------------------
+
+Cursor::~Cursor()
+{
+ if ( mpData )
+ {
+ if ( mpData->mbCurVisible )
+ ImplRestore();
+
+ delete mpData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetStyle( USHORT nStyle )
+{
+ if ( mnStyle != nStyle )
+ {
+ mnStyle = nStyle;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::Show()
+{
+ if ( !mbVisible )
+ {
+ mbVisible = TRUE;
+ ImplShow();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::Hide()
+{
+ if ( mbVisible )
+ {
+ mbVisible = FALSE;
+ ImplHide();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetWindow( Window* pWindow )
+{
+ if ( mpWindow != pWindow )
+ {
+ mpWindow = pWindow;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetPos( const Point& rPoint )
+{
+ if ( maPos != rPoint )
+ {
+ maPos = rPoint;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetOffsetY( long nNewOffsetY )
+{
+ if ( mnOffsetY != nNewOffsetY )
+ {
+ mnOffsetY = nNewOffsetY;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetSize( const Size& rSize )
+{
+ if ( maSize != rSize )
+ {
+ maSize = rSize;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetWidth( long nNewWidth )
+{
+ if ( maSize.Width() != nNewWidth )
+ {
+ maSize.Width() = nNewWidth;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetHeight( long nNewHeight )
+{
+ if ( maSize.Height() != nNewHeight )
+ {
+ maSize.Height() = nNewHeight;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetSlant( long nNewSlant )
+{
+ if ( mnSlant != nNewSlant )
+ {
+ mnSlant = nNewSlant;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Cursor::SetOrientation( short nNewOrientation )
+{
+ if ( mnOrientation != nNewOrientation )
+ {
+ mnOrientation = nNewOrientation;
+ ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Cursor& Cursor::operator=( const Cursor& rCursor )
+{
+ maPos = rCursor.maPos;
+ maSize = rCursor.maSize;
+ mnSlant = rCursor.mnSlant;
+ mnOrientation = rCursor.mnOrientation;
+ mbVisible = rCursor.mbVisible;
+ ImplNew();
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Cursor::operator==( const Cursor& rCursor ) const
+{
+ if ( (maPos == rCursor.maPos) &&
+ (maSize == rCursor.maSize) &&
+ (mnSlant == rCursor.mnSlant) &&
+ (mnOrientation == rCursor.mnOrientation) &&
+ (mbVisible == rCursor.mbVisible) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/window/decoview.cxx b/vcl/source/window/decoview.cxx
new file mode 100644
index 000000000000..e7169fee2131
--- /dev/null
+++ b/vcl/source/window/decoview.cxx
@@ -0,0 +1,1297 @@
+/*************************************************************************
+ *
+ * $RCSfile: decoview.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_DECOVIEW_CXX
+
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define BUTTON_DRAW_FLATTEST (BUTTON_DRAW_FLAT | \
+ BUTTON_DRAW_PRESSED | \
+ BUTTON_DRAW_CHECKED | \
+ BUTTON_DRAW_HIGHLIGHT)
+
+// =======================================================================
+
+void ImplDrawOS2Symbol( OutputDevice* pDev, const Rectangle& rRect,
+ USHORT nStyle, BOOL bClose )
+{
+ DecorationView aView( pDev );
+ const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = rRect;
+ Color aColor1;
+ Color aColor2;
+
+ pDev->SetFillColor();
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetShadowColor();
+ aColor2 = rStyleSettings.GetLightColor();
+ }
+ else
+ {
+ aColor1 = rStyleSettings.GetLightColor();
+ aColor2 = rStyleSettings.GetShadowColor();
+ }
+ aView.DrawFrame( aRect, aColor1, aColor2 );
+
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( bClose )
+ {
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom()-2 ) );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right()-2, aRect.Top() ) );
+ pDev->DrawLine( Point( aRect.Left()+2, aRect.Bottom()-1 ),
+ Point( aRect.Right()-1, aRect.Top()+2 ) );
+ }
+ else
+ {
+ pDev->DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) );
+ }
+
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ if ( bClose )
+ {
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top()+2 ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Left()+2, aRect.Bottom() ), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Right()-2, aRect.Top()+1 ),
+ Point( aRect.Left()+1, aRect.Bottom()-2 ) );
+ }
+ else
+ {
+ pDev->DrawLine( aRect.TopRight(), aRect.BottomRight() );
+ pDev->DrawLine( Point( aRect.Left()+1, aRect.Bottom() ), aRect.BottomRight() );
+ }
+}
+
+// =======================================================================
+
+static void ImplDrawSymbol( OutputDevice* pDev, const Rectangle& rRect,
+ SymbolType eType )
+{
+ // Groessen vorberechnen
+ long n;
+ long nHeight = rRect.GetHeight();
+ long nWidth = rRect.GetWidth();
+ if ( nWidth < nHeight )
+ n = nWidth;
+ else
+ n = nHeight;
+ if ( n & 0x01 )
+ n--;
+ Point aCenter = rRect.Center();
+ long nCenterX = aCenter.X();
+ long nCenterY = aCenter.Y();
+ long n2 = n / 2;
+ long n4 = n / 4;
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+ long nTemp;
+ long i;
+
+ switch ( eType )
+ {
+ case SYMBOL_ARROW_UP:
+ {
+ if ( !(n & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nTop = nCenterY-n2;
+ nBottom = nCenterY;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nCenterX-n4, nBottom,
+ nCenterX+n4, nBottom+n2 ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_DOWN:
+ {
+ if ( !(n & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nTop = nCenterY;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nCenterX-n4, nTop-n2,
+ nCenterX+n4, nTop ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_LEFT:
+ {
+ if ( !(n & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nLeft = nCenterX-n2;
+ nRight = nCenterX;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nRight, nCenterY-n4,
+ nRight+n2, nCenterY+n4 ) );
+ }
+ break;
+
+ case SYMBOL_ARROW_RIGHT:
+ {
+ if ( !(n & 0x01) )
+ {
+ n2--;
+ n4--;
+ }
+ nLeft = nCenterX;
+ nRight = nCenterX+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ pDev->DrawRect( Rectangle( nLeft-n2, nCenterY-n4,
+ nLeft, nCenterY+n4 ) );
+ }
+ break;
+
+
+ case SYMBOL_SPIN_UP:
+ {
+ if ( !(n & 0x01) )
+ n2--;
+ nTop = nCenterY-n4;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_DOWN:
+ {
+ if ( !(n & 0x01) )
+ n2--;
+ nTop = nCenterY-n4;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_LEFT:
+ case SYMBOL_FIRST:
+ case SYMBOL_PREV:
+ case SYMBOL_REVERSEPLAY:
+ {
+ if ( !(n & 0x01) )
+ n2--;
+ nLeft = nCenterX-n4;
+ if ( eType == SYMBOL_FIRST )
+ nLeft++;
+ nRight = nLeft+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_FIRST )
+ {
+ pDev->DrawRect( Rectangle( nCenterX-n4-1, nCenterY-n2,
+ nCenterX-n4-1, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_RIGHT:
+ case SYMBOL_LAST:
+ case SYMBOL_NEXT:
+ case SYMBOL_PLAY:
+ {
+ if ( !(n & 0x01) )
+ n2--;
+ nLeft = nCenterX-n4;
+ if ( eType == SYMBOL_LAST )
+ nLeft--;
+ nRight = nLeft+n2;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_LAST )
+ {
+ pDev->DrawRect( Rectangle( nCenterX+n4+1, nCenterY-n2,
+ nCenterX+n4+1, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_PAGEUP:
+ {
+ nTop = nCenterY-n2;
+ nBottom = nCenterY-1;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ pDev->DrawRect( Rectangle( nCenterX, nTop+n2+1, nCenterX, nBottom+n2+1 ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_PAGEDOWN:
+ {
+ nTop = nCenterY-n2;
+ nBottom = nCenterY-1;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ pDev->DrawRect( Rectangle( nCenterX, nTop+n2+1, nCenterX, nBottom+n2+1 ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ pDev->DrawRect( Rectangle( nTemp, nTop+n2+1, nTemp, nBottom+n2+1 ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_RADIOCHECKMARK:
+ case SYMBOL_RECORD:
+ {
+ const long nExt = ( n2 << 1 ) + 1;
+ Bitmap aBmp( Size( nExt, nExt ), 1 );
+ BitmapWriteAccess* pWAcc = aBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const Color aWhite( COL_WHITE );
+ const Color aBlack( COL_BLACK );
+
+ pWAcc->Erase( aWhite );
+ pWAcc->SetLineColor( aBlack );
+ pWAcc->SetFillColor( aBlack );
+ pWAcc->DrawPolygon( Polygon( Point( n2, n2 ), n2, n2 ) );
+ aBmp.ReleaseAccess( pWAcc );
+ pDev->DrawMask( Point( nCenterX - n2, nCenterY - n2 ), aBmp, pDev->GetFillColor() );
+ }
+ else
+ pDev->DrawPolygon( Polygon( Point( nCenterX, nCenterY ), n2, n2 ) );
+ }
+ break;
+
+ case SYMBOL_STOP:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX+n2;
+ nTop = nCenterY-n2;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nLeft, nTop, nRight, nBottom ) );
+ }
+ break;
+
+ case SYMBOL_PAUSE:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX+n2-1;
+ nTop = nCenterY-n2;
+ nBottom = nCenterY+n2;
+ pDev->DrawRect( Rectangle( nLeft, nTop, nCenterX-2, nBottom ) );
+ pDev->DrawRect( Rectangle( nCenterX+1, nTop, nRight, nBottom ) );
+ }
+ break;
+
+ case SYMBOL_WINDSTART:
+ case SYMBOL_WINDBACKWARD:
+ {
+ nLeft = nCenterX-n2+1;
+ nRight = nCenterX;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nCenterY, nRight+n2, nCenterY ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nLeft++;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_WINDSTART )
+ {
+ pDev->DrawRect( Rectangle( nCenterX-n2, nCenterY-n2,
+ nCenterX-n2, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_WINDEND:
+ case SYMBOL_WINDFORWARD:
+ {
+ nLeft = nCenterX-n2;
+ nRight = nCenterX-1;
+ pDev->DrawRect( Rectangle( nLeft, nCenterY, nRight, nCenterY ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nCenterY, nRight+n2, nCenterY ) );
+ i = 1;
+ while ( i < n2 )
+ {
+ nRight--;
+ nTemp = nCenterY-i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ nTemp = nCenterY+i;
+ pDev->DrawRect( Rectangle( nLeft, nTemp, nRight, nTemp ) );
+ pDev->DrawRect( Rectangle( nLeft+n2, nTemp, nRight+n2, nTemp ) );
+ i++;
+ }
+ if ( eType == SYMBOL_WINDEND )
+ {
+ pDev->DrawRect( Rectangle( nCenterX+n2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 ) );
+ }
+ }
+ break;
+
+ case SYMBOL_CLOSE:
+ {
+ Size aRectSize( 2, 1 );
+ if ( n < 8 )
+ aRectSize.Width() = 1;
+ else if ( n > 20 )
+ aRectSize.Width() = n/10;
+ nLeft = nCenterX-n2+1;
+ nTop = nCenterY-n2+1;
+ nBottom = nCenterY-n2+n-aRectSize.Width()+1;
+ i = 0;
+ while ( i < n-aRectSize.Width()+1 )
+ {
+ pDev->DrawRect( Rectangle( Point( nLeft+i, nTop+i ), aRectSize ) );
+ pDev->DrawRect( Rectangle( Point( nLeft+i, nBottom-i ), aRectSize ) );
+ i++;
+ }
+ }
+ break;
+
+ case SYMBOL_ROLLUP:
+ case SYMBOL_ROLLDOWN:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2+1 );
+ pDev->DrawRect( aRect );
+ if ( eType == SYMBOL_ROLLDOWN )
+ {
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ }
+ break;
+ case SYMBOL_CHECKMARK:
+ {
+ Point aPos1( rRect.Left(), rRect.Bottom() - rRect.GetHeight() / 3 );
+ Point aPos2( rRect.Left() + rRect.GetWidth()/3, rRect.Bottom() );
+ Point aPos3( rRect.TopRight() );
+ Size aRectSize( 1, 2 );
+ long nStepsY = aPos2.Y()-aPos1.Y();
+ long nX = aPos1.X();
+ long nY = aPos1.Y();
+ for ( long n = 0; n <= nStepsY; n++ )
+ {
+ pDev->DrawRect( Rectangle( Point( nX, nY++ ), aRectSize ) );
+ nX++;
+ }
+ nStepsY = aPos2.Y()-aPos3.Y();
+ nX = aPos2.X();
+ nY = aPos2.Y();
+ for ( n = 0; n <= nStepsY; n++ )
+ {
+ pDev->DrawRect( Rectangle( Point( nX, nY-- ), aRectSize ) );
+ nX++;
+ if ( nX > rRect.Right() )
+ break;
+ }
+ }
+ break;
+
+ case SYMBOL_SPIN_UPDOWN:
+ {
+ nTop = nCenterY-n2-1;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nTop++;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ nTop = nCenterY+1;
+ nBottom = nTop+n2;
+ pDev->DrawRect( Rectangle( nCenterX, nTop, nCenterX, nBottom ) );
+ i = 1;
+ while ( i <= n2 )
+ {
+ nBottom--;
+ nTemp = nCenterX-i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ nTemp = nCenterX+i;
+ pDev->DrawRect( Rectangle( nTemp, nTop, nTemp, nBottom ) );
+ i++;
+ }
+ }
+ break;
+
+
+ case SYMBOL_FLOAT:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2+3,
+ nCenterX+n2-2, nCenterY-n2+4 );
+ pDev->DrawRect( aRect );
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aRect = Rectangle( nCenterX-n2+2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2+1 );
+ pDev->DrawRect( aRect );
+ aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2-3;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ break;
+ case SYMBOL_DOCK:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY-n2 );
+ pDev->DrawRect( aRect );
+ Rectangle aTempRect = aRect;
+ aTempRect.Bottom() = nCenterY+n2;
+ aTempRect.Right() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Left() = aRect.Right();
+ aTempRect.Right() = aRect.Right();
+ pDev->DrawRect( aTempRect );
+ aTempRect.Top() = aTempRect.Bottom();
+ aTempRect.Left() = aRect.Left();
+ pDev->DrawRect( aTempRect );
+ }
+ break;
+ case SYMBOL_HIDE:
+ {
+ long nExtra = n / 8;
+ Rectangle aRect( nCenterX-n2+nExtra, nCenterY+n2-1,
+ nCenterX+n2-nExtra, nCenterY+n2 );
+ pDev->DrawRect( aRect );
+ }
+ break;
+
+ case SYMBOL_OS2CLOSE:
+ {
+ Rectangle aRect( nCenterX-n2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, TRUE );
+ }
+ break;
+
+ case SYMBOL_OS2FLOAT:
+ {
+ Rectangle aRect( nCenterX-n2+4, nCenterY-n2+4,
+ nCenterX+n2-4, nCenterY+n2-3 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, FALSE );
+ DecorationView aDecoView( pDev );
+ Rectangle aRect2( nCenterX-n2, nCenterY-n2,
+ nCenterX-n2+2, nCenterY+n2 );
+ aDecoView.DrawFrame( aRect2,
+ pDev->GetSettings().GetStyleSettings().GetLightColor(),
+ pDev->GetSettings().GetStyleSettings().GetShadowColor() );
+ Rectangle aRect3( nCenterX+n2-2, nCenterY-n2,
+ nCenterX+n2, nCenterY+n2 );
+ aDecoView.DrawFrame( aRect3,
+ pDev->GetSettings().GetStyleSettings().GetLightColor(),
+ pDev->GetSettings().GetStyleSettings().GetShadowColor() );
+ }
+ break;
+
+ case SYMBOL_OS2HIDE:
+ {
+ Rectangle aRect( nCenterX-n2+3, nCenterY-n2+3,
+ nCenterX+n2-3, nCenterY+n2-3 );
+ ImplDrawOS2Symbol( pDev, aRect, 0, FALSE );
+ }
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DecorationView::DrawSymbol( const Rectangle& rRect, SymbolType eType,
+ const Color& rColor, USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+ Rectangle aRect = mpOutDev->LogicToPixel( rRect );
+ Color aOldLineColor = mpOutDev->GetLineColor();
+ Color aOldFillColor = mpOutDev->GetFillColor();
+ BOOL bOldMapMode = mpOutDev->IsMapModeEnabled();
+ mpOutDev->SetLineColor();
+ mpOutDev->SetFillColor( rColor );
+ mpOutDev->EnableMapMode( FALSE );
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
+ nStyle |= BUTTON_DRAW_MONO;
+
+ if ( nStyle & SYMBOL_DRAW_MONO )
+ {
+ if ( nStyle & SYMBOL_DRAW_DISABLE )
+ mpOutDev->SetFillColor( Color( COL_GRAY ) );
+ else
+ mpOutDev->SetFillColor( Color( COL_BLACK ) );
+ }
+ else
+ {
+ if ( nStyle & SYMBOL_DRAW_DISABLE )
+ {
+ // Als Embosed ausgeben
+ mpOutDev->SetFillColor( rStyleSettings.GetLightColor() );
+ Rectangle aTempRect = aRect;
+ aTempRect.Move( 1, 1 );
+ ImplDrawSymbol( mpOutDev, aTempRect, eType );
+ mpOutDev->SetFillColor( rStyleSettings.GetShadowColor() );
+ }
+ else
+ mpOutDev->SetFillColor( rColor );
+ }
+
+ ImplDrawSymbol( mpOutDev, aRect, eType );
+
+ mpOutDev->SetLineColor( aOldLineColor );
+ mpOutDev->SetFillColor( aOldFillColor );
+ mpOutDev->EnableMapMode( bOldMapMode );
+}
+
+// =======================================================================
+
+void DecorationView::DrawFrame( const Rectangle& rRect,
+ const Color& rLeftTopColor,
+ const Color& rRightBottomColor )
+{
+ Rectangle aRect = mpOutDev->LogicToPixel( rRect );
+ Color aOldLineColor = mpOutDev->GetLineColor();
+ Color aOldFillColor = mpOutDev->GetFillColor();
+ BOOL bOldMapMode = mpOutDev->IsMapModeEnabled();
+ mpOutDev->EnableMapMode( FALSE );
+ mpOutDev->SetLineColor();
+ mpOutDev->ImplDraw2ColorFrame( aRect, rLeftTopColor, rRightBottomColor );
+ mpOutDev->SetLineColor( aOldLineColor );
+ mpOutDev->SetFillColor( aOldFillColor );
+ mpOutDev->EnableMapMode( bOldMapMode );
+}
+
+// =======================================================================
+
+void DecorationView::DrawHighlightFrame( const Rectangle& rRect,
+ USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+ Color aLightColor = rStyleSettings.GetLightColor();
+ Color aShadowColor = rStyleSettings.GetShadowColor();
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
+ {
+ aLightColor = Color( COL_BLACK );
+ aShadowColor = Color( COL_BLACK );
+ }
+ else if ( nStyle & FRAME_HIGHLIGHT_TESTBACKGROUND )
+ {
+ Wallpaper aBackground = mpOutDev->GetBackground();
+ if ( aBackground.IsBitmap() || aBackground.IsGradient() )
+ {
+ aLightColor = rStyleSettings.GetFaceColor();
+ aShadowColor = Color( COL_BLACK );
+ }
+ else
+ {
+ Color aBackColor = aBackground.GetColor();
+ if ( (aLightColor.GetColorError( aBackColor ) < 32) ||
+ (aShadowColor.GetColorError( aBackColor ) < 32) )
+ {
+ aLightColor = Color( COL_WHITE );
+ aShadowColor = Color( COL_BLACK );
+
+ if ( aLightColor.GetColorError( aBackColor ) < 32 )
+ aLightColor.DecreaseLuminance( 64 );
+ if ( aShadowColor.GetColorError( aBackColor ) < 32 )
+ aShadowColor.IncreaseLuminance( 64 );
+ }
+ }
+ }
+
+ if ( (nStyle & FRAME_HIGHLIGHT_STYLE) == FRAME_HIGHLIGHT_IN )
+ {
+ Color aTempColor = aLightColor;
+ aLightColor = aShadowColor;
+ aShadowColor = aTempColor;
+ }
+
+ DrawFrame( rRect, aLightColor, aShadowColor );
+}
+
+// =======================================================================
+
+static void ImplDrawDPILineRect( OutputDevice* pDev, Rectangle& rRect,
+ const Color* pColor )
+{
+ long nLineWidth = pDev->ImplGetDPIX()/300;
+ long nLineHeight = pDev->ImplGetDPIY()/300;
+ if ( !nLineWidth )
+ nLineWidth = 1;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+
+ if ( pColor )
+ {
+ if ( (nLineWidth == 1) && (nLineHeight == 1) )
+ {
+ pDev->SetLineColor( *pColor );
+ pDev->SetFillColor();
+ pDev->DrawRect( rRect );
+ }
+ else
+ {
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ pDev->SetLineColor();
+ pDev->SetFillColor( *pColor );
+ pDev->DrawRect( Rectangle( rRect.TopLeft(), Size( nWidth, nLineHeight ) ) );
+ pDev->DrawRect( Rectangle( rRect.TopLeft(), Size( nLineWidth, nHeight ) ) );
+ pDev->DrawRect( Rectangle( Point( rRect.Left(), rRect.Bottom()-nLineHeight ),
+ Size( nWidth, nLineHeight ) ) );
+ pDev->DrawRect( Rectangle( Point( rRect.Right()-nLineWidth, rRect.Top() ),
+ Size( nLineWidth, nHeight ) ) );
+ }
+ }
+
+ rRect.Left() += nLineWidth;
+ rRect.Top() += nLineHeight;
+ rRect.Right() -= nLineWidth;
+ rRect.Bottom() -= nLineHeight;
+}
+
+// =======================================================================
+
+static void ImplDrawFrame( OutputDevice* pDev, Rectangle& rRect,
+ const StyleSettings& rStyleSettings, USHORT nStyle )
+{
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (pDev->GetOutDevType() == OUTDEV_PRINTER) )
+ nStyle |= FRAME_DRAW_MONO;
+
+ if ( nStyle & FRAME_DRAW_NODRAW )
+ {
+ if ( nStyle & FRAME_DRAW_MONO )
+ ImplDrawDPILineRect( pDev, rRect, NULL );
+ else
+ {
+ USHORT nFrameStyle = nStyle & FRAME_DRAW_STYLE;
+
+ if ( nFrameStyle == FRAME_DRAW_GROUP )
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ else if ( (nFrameStyle == FRAME_DRAW_IN) ||
+ (nFrameStyle == FRAME_DRAW_OUT) )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ else // FRAME_DRAW_DOUBLEIN || FRAME_DRAW_DOUBLEOUT
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ }
+ }
+ else
+ {
+ if ( nStyle & FRAME_DRAW_MONO )
+ {
+ Color aColor( COL_BLACK );
+ ImplDrawDPILineRect( pDev, rRect, &aColor );
+ }
+ else
+ {
+ USHORT nFrameStyle = nStyle & FRAME_DRAW_STYLE;
+ if ( nFrameStyle == FRAME_DRAW_GROUP )
+ {
+ pDev->SetFillColor();
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ rRect.Top()++;
+ rRect.Left()++;
+ pDev->DrawRect( rRect );
+ rRect.Top()--;
+ rRect.Left()--;
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ rRect.Right()--;
+ rRect.Bottom()--;
+ pDev->DrawRect( rRect );
+ rRect.Right()++;
+ rRect.Bottom()++;
+ }
+ else
+ {
+ pDev->SetLineColor();
+
+ if ( (nFrameStyle == FRAME_DRAW_IN) ||
+ (nFrameStyle == FRAME_DRAW_OUT) )
+ {
+ if ( nFrameStyle == FRAME_DRAW_IN )
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetLightColor() );
+ }
+ else
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetLightColor(),
+ rStyleSettings.GetShadowColor() );
+ }
+
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ else // FRAME_DRAW_DOUBLEIN || FRAME_DRAW_DOUBLEOUT
+ {
+ if ( nFrameStyle == FRAME_DRAW_DOUBLEIN )
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetShadowColor(),
+ rStyleSettings.GetLightColor() );
+ }
+ else
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetLightBorderColor(),
+ rStyleSettings.GetDarkShadowColor() );
+ }
+
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+
+ if ( nFrameStyle == FRAME_DRAW_DOUBLEIN )
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetDarkShadowColor(),
+ rStyleSettings.GetLightBorderColor() );
+ }
+ else
+ {
+ pDev->ImplDraw2ColorFrame( rRect,
+ rStyleSettings.GetLightColor(),
+ rStyleSettings.GetShadowColor() );
+ }
+
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle DecorationView::DrawFrame( const Rectangle& rRect, USHORT nStyle )
+{
+ Rectangle aRect = rRect;
+ BOOL bOldMap = mpOutDev->IsMapModeEnabled();
+ if ( bOldMap )
+ {
+ aRect = mpOutDev->LogicToPixel( aRect );
+ mpOutDev->EnableMapMode( FALSE );
+ }
+
+ if ( !rRect.IsEmpty() )
+ {
+ if ( nStyle & FRAME_DRAW_NODRAW )
+ ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle );
+ else
+ {
+ Color maOldLineColor = mpOutDev->GetLineColor();
+ Color maOldFillColor = mpOutDev->GetFillColor();
+ ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle );
+ mpOutDev->SetLineColor( maOldLineColor );
+ mpOutDev->SetFillColor( maOldFillColor );
+ }
+ }
+
+ if ( bOldMap )
+ {
+ mpOutDev->EnableMapMode( bOldMap );
+ aRect = mpOutDev->PixelToLogic( aRect );
+ }
+
+ return aRect;
+}
+
+// =======================================================================
+
+static void ImplDrawButton( OutputDevice* pDev, Rectangle& rRect,
+ const StyleSettings& rStyleSettings, USHORT nStyle )
+{
+ Rectangle aFillRect = rRect;
+
+ if ( nStyle & BUTTON_DRAW_MONO )
+ {
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ Color aBlackColor( COL_BLACK );
+
+ if ( nStyle & BUTTON_DRAW_DEFAULT )
+ ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
+
+ ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
+
+ Size aBrdSize( 1, 1 );
+ if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
+ {
+ MapMode aResMapMode( MAP_100TH_MM );
+ aBrdSize = pDev->LogicToPixel( Size( 20, 20 ), aResMapMode );
+ if ( !aBrdSize.Width() )
+ aBrdSize.Width() = 1;
+ if ( !aBrdSize.Height() )
+ aBrdSize.Height() = 1;
+ }
+ pDev->SetLineColor();
+ pDev->SetFillColor( aBlackColor );
+ Rectangle aRect1;
+ Rectangle aRect2;
+ aRect1.Left() = aFillRect.Left();
+ aRect1.Right() = aFillRect.Right(),
+ aRect2.Top() = aFillRect.Top();
+ aRect2.Bottom() = aFillRect.Bottom();
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aRect1.Top() = aFillRect.Top();
+ aRect1.Bottom() = aBrdSize.Height()-1;
+ aRect2.Left() = aFillRect.Left();
+ aRect2.Right() = aFillRect.Left()+aBrdSize.Width()-1;
+ aFillRect.Left() += aBrdSize.Width();
+ aFillRect.Top() += aBrdSize.Height();
+ }
+ else
+ {
+ aRect1.Top() = aFillRect.Bottom()-aBrdSize.Height()+1;
+ aRect1.Bottom() = aFillRect.Bottom();
+ aRect2.Left() = aFillRect.Right()-aBrdSize.Width()+1;
+ aRect2.Right() = aFillRect.Right(),
+ aFillRect.Right() -= aBrdSize.Width();
+ aFillRect.Bottom() -= aBrdSize.Height();
+ }
+ pDev->DrawRect( aRect1 );
+ pDev->DrawRect( aRect2 );
+ }
+ }
+ else
+ {
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ if ( nStyle & BUTTON_DRAW_DEFAULT )
+ {
+ Color aDefBtnColor = rStyleSettings.GetDarkShadowColor();
+ ImplDrawDPILineRect( pDev, aFillRect, &aDefBtnColor );
+ }
+ }
+
+ if ( !(nStyle & BUTTON_DRAW_NODRAW) )
+ {
+ pDev->SetLineColor();
+ if ( nStyle & BUTTON_DRAW_NOLEFTLIGHTBORDER )
+ {
+ pDev->SetFillColor( rStyleSettings.GetLightBorderColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Top(),
+ aFillRect.Left(), aFillRect.Bottom() ) );
+ aFillRect.Left()++;
+ }
+ if ( (nStyle & BUTTON_DRAW_NOTOPLIGHTBORDER) &&
+ !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED)) )
+ {
+ pDev->SetFillColor( rStyleSettings.GetLightBorderColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Top(),
+ aFillRect.Right(), aFillRect.Top() ) );
+ aFillRect.Top()++;
+ }
+ if ( ((nStyle & BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT) == (BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT)) &&
+ !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED | BUTTON_DRAW_HIGHLIGHT)) )
+ {
+ pDev->SetFillColor( rStyleSettings.GetDarkShadowColor() );
+ pDev->DrawRect( Rectangle( aFillRect.Left(), aFillRect.Bottom(),
+ aFillRect.Right(), aFillRect.Bottom() ) );
+ aFillRect.Bottom()--;
+ }
+
+ Color aColor1;
+ Color aColor2;
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetDarkShadowColor();
+ aColor2 = rStyleSettings.GetLightColor();
+ }
+ else
+ {
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ aColor1 = rStyleSettings.GetLightBorderColor();
+ else
+ aColor1 = rStyleSettings.GetLightColor();
+ if ( (nStyle & BUTTON_DRAW_FLATTEST) == BUTTON_DRAW_FLAT )
+ aColor2 = rStyleSettings.GetShadowColor();
+ else
+ aColor2 = rStyleSettings.GetDarkShadowColor();
+ }
+ pDev->ImplDraw2ColorFrame( aFillRect, aColor1, aColor2 );
+ aFillRect.Left()++;
+ aFillRect.Top()++;
+ aFillRect.Right()--;
+ aFillRect.Bottom()--;
+
+ if ( !((nStyle & BUTTON_DRAW_FLATTEST) == BUTTON_DRAW_FLAT) )
+ {
+ if ( nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED) )
+ {
+ aColor1 = rStyleSettings.GetShadowColor();
+ aColor2 = rStyleSettings.GetLightBorderColor();
+ }
+ else
+ {
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ aColor1 = rStyleSettings.GetLightColor();
+ else
+ aColor1 = rStyleSettings.GetLightBorderColor();
+ aColor2 = rStyleSettings.GetShadowColor();
+ }
+ pDev->ImplDraw2ColorFrame( aFillRect, aColor1, aColor2 );
+ aFillRect.Left()++;
+ aFillRect.Top()++;
+ aFillRect.Right()--;
+ aFillRect.Bottom()--;
+ }
+ }
+ }
+
+ if ( !(nStyle & (BUTTON_DRAW_NOFILL | BUTTON_DRAW_NODRAW)) )
+ {
+ pDev->SetLineColor();
+ if ( nStyle & BUTTON_DRAW_MONO )
+ {
+ // Hack: Auf Druckern wollen wir im MonoChrom-Modus trotzdem
+ // erstmal graue Buttons haben
+ if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
+ pDev->SetFillColor( Color( COL_LIGHTGRAY ) );
+ else
+ pDev->SetFillColor( Color( COL_WHITE ) );
+ }
+ else
+ {
+ if ( nStyle & (BUTTON_DRAW_CHECKED | BUTTON_DRAW_DONTKNOW) )
+ pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ else
+ pDev->SetFillColor( rStyleSettings.GetFaceColor() );
+ }
+ pDev->DrawRect( aFillRect );
+ }
+
+ // Ein Border freilassen, der jedoch bei Default-Darstellung
+ // mitbenutzt wird
+ rRect.Left()++;
+ rRect.Top()++;
+ rRect.Right()--;
+ rRect.Bottom()--;
+
+ if ( nStyle & BUTTON_DRAW_NOLIGHTBORDER )
+ {
+ rRect.Left()++;
+ rRect.Top()++;
+ }
+ else if ( nStyle & BUTTON_DRAW_NOLEFTLIGHTBORDER )
+ rRect.Left()++;
+
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ if ( (rRect.GetHeight() > 10) && (rRect.GetWidth() > 10) )
+ {
+ rRect.Left() += 4;
+ rRect.Top() += 4;
+ rRect.Right() -= 1;
+ rRect.Bottom() -= 1;
+ }
+ else
+ {
+ rRect.Left() += 3;
+ rRect.Top() += 3;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ }
+ else if ( nStyle & BUTTON_DRAW_CHECKED )
+ {
+ rRect.Left() += 3;
+ rRect.Top() += 3;
+ rRect.Right() -= 2;
+ rRect.Bottom() -= 2;
+ }
+ else
+ {
+ rRect.Left() += 2;
+ rRect.Top() += 2;
+ rRect.Right() -= 3;
+ rRect.Bottom() -= 3;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle DecorationView::DrawButton( const Rectangle& rRect, USHORT nStyle )
+{
+ Rectangle aRect = rRect;
+ BOOL bOldMap = mpOutDev->IsMapModeEnabled();
+ if ( bOldMap )
+ {
+ aRect = mpOutDev->LogicToPixel( aRect );
+ mpOutDev->EnableMapMode( FALSE );
+ }
+
+ if ( !rRect.IsEmpty() )
+ {
+ const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ||
+ (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
+ nStyle |= BUTTON_DRAW_MONO;
+
+ if ( nStyle & BUTTON_DRAW_NODRAW )
+ ImplDrawButton( mpOutDev, aRect, rStyleSettings, nStyle );
+ else
+ {
+ Color maOldLineColor = mpOutDev->GetLineColor();
+ Color maOldFillColor = mpOutDev->GetFillColor();
+ ImplDrawButton( mpOutDev, aRect, rStyleSettings, nStyle );
+ mpOutDev->SetLineColor( maOldLineColor );
+ mpOutDev->SetFillColor( maOldFillColor );
+ }
+ }
+
+ if ( bOldMap )
+ {
+ mpOutDev->EnableMapMode( bOldMap );
+ aRect = mpOutDev->PixelToLogic( aRect );
+ }
+
+ return aRect;
+}
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
new file mode 100644
index 000000000000..9a76a9a38923
--- /dev/null
+++ b/vcl/source/window/dialog.cxx
@@ -0,0 +1,847 @@
+/*************************************************************************
+ *
+ * $RCSfile: dialog.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_DIALOG_CXX
+
+#ifndef _TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_MNEMONIC_HXX
+#include <mnemonic.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_DIALOG_HXX
+#include <dialog.hxx>
+#endif
+
+#ifdef DBG_UTIL
+#ifndef _SV_MSGBOX_HXX
+#include <msgbox.hxx>
+#endif
+#endif
+
+#include <unowrap.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+#ifdef DBG_UTIL
+
+static ByteString ImplGetDialogText( Dialog* pDialog )
+{
+ ByteString aErrorStr( pDialog->GetText(), RTL_TEXTENCODING_UTF8 );
+ if ( (pDialog->GetType() == WINDOW_MESSBOX) ||
+ (pDialog->GetType() == WINDOW_INFOBOX) ||
+ (pDialog->GetType() == WINDOW_WARNINGBOX) ||
+ (pDialog->GetType() == WINDOW_ERRORBOX) ||
+ (pDialog->GetType() == WINDOW_QUERYBOX) )
+ {
+ aErrorStr += ", ";
+ aErrorStr += ByteString( ((MessBox*)pDialog)->GetMessText(), RTL_TEXTENCODING_UTF8 );
+ }
+ return aErrorStr;
+}
+
+#endif
+
+// =======================================================================
+
+static BOOL ImplIsMnemonicCtrl( Window* pWindow )
+{
+ if ( (pWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return TRUE;
+
+ if ( pWindow->GetType() == WINDOW_FIXEDTEXT )
+ {
+ if ( pWindow->GetStyle() & (WB_INFO | WB_NOLABEL) )
+ return FALSE;
+ Window* pNextWindow = pWindow->GetWindow( WINDOW_NEXT );
+ if ( !pNextWindow )
+ return FALSE;
+ pNextWindow = pNextWindow->GetWindow( WINDOW_CLIENT );
+ if ( !(pNextWindow->GetStyle() & WB_TABSTOP) ||
+ (pNextWindow->GetType() == WINDOW_FIXEDTEXT) ||
+ (pNextWindow->GetType() == WINDOW_GROUPBOX) ||
+ (pNextWindow->GetType() == WINDOW_RADIOBUTTON) ||
+ (pNextWindow->GetType() == WINDOW_CHECKBOX) ||
+ (pNextWindow->GetType() == WINDOW_TRISTATEBOX) ||
+ (pNextWindow->GetType() == WINDOW_PUSHBUTTON) )
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWindowAutoMnemonic( Window* pWindow )
+{
+ ImplMnemonicGenerator aMnemonicGenerator;
+ Window* pGetChild;
+ Window* pChild;
+
+ // Die schon vergebenen Mnemonics registieren
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+
+ // Bei TabPages auch noch die Controls vom Dialog beruecksichtigen
+ if ( pWindow->GetType() == WINDOW_TABPAGE )
+ {
+ Window* pParent = pWindow->GetParent();
+ if ( pParent->GetType() == WINDOW_TABCONTROL )
+ pParent = pParent->GetParent();
+
+ if ( (pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
+ {
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+ }
+ }
+
+ // Die Mnemonics an die Controls vergeben, die noch keinen haben
+ pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pGetChild )
+ {
+ pChild = pGetChild->ImplGetWindow();
+ if ( ImplIsMnemonicCtrl( pChild ) )
+ {
+ XubString aText = pChild->GetText();
+ if ( aMnemonicGenerator.CreateMnemonic( aText ) )
+ pChild->SetText( aText );
+ }
+
+ pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
+ }
+}
+
+// =======================================================================
+
+static PushButton* ImplGetDefaultButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->ImplIsPushButton() )
+ {
+ PushButton* pPushButton = (PushButton*)pChild;
+ if ( pPushButton->ImplIsDefButton() )
+ return pPushButton;
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetOKButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_OKBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static PushButton* ImplGetCancelButton( Dialog* pDialog )
+{
+ Window* pChild = pDialog->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->GetType() == WINDOW_CANCELBUTTON )
+ return (PushButton*)pChild;
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplMouseAutoPos( Dialog* pDialog )
+{
+ ULONG nMouseOptions = pDialog->GetSettings().GetMouseSettings().GetOptions();
+ if ( nMouseOptions & MOUSE_OPTION_AUTOCENTERPOS )
+ {
+ Size aSize = pDialog->GetOutputSizePixel();
+ pDialog->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+ else if ( nMouseOptions & MOUSE_OPTION_AUTODEFBTNPOS )
+ {
+ Window* pWindow = ImplGetDefaultButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetOKButton( pDialog );
+ if ( !pWindow )
+ pWindow = ImplGetCancelButton( pDialog );
+ if ( !pWindow )
+ pWindow = pDialog;
+ Size aSize = pWindow->GetOutputSizePixel();
+ pWindow->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
+ }
+}
+
+// =======================================================================
+
+void Dialog::ImplInitData()
+{
+ mbDialog = TRUE;
+
+ mpDialogParent = NULL;
+ mpResult = NULL;
+ mpPrevExecuteDlg = NULL;
+ mbInExecute = FALSE;
+ mbOldSaveBack = FALSE;
+ mbInClose = FALSE;
+ mbModalMode = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInit( Window* pParent, WinBits nStyle )
+{
+ USHORT nSysWinMode = Application::GetSystemWindowMode();
+
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+ nStyle |= WB_ROLLABLE;
+
+ if ( !pParent )
+ {
+ pParent = Application::GetDefDialogParent();
+ if ( !pParent && !(nStyle & WB_SYSTEMWINDOW) )
+ pParent = Application::GetAppWindow();
+
+ // If Parent is disabled, then we search for a modal dialog
+ // in this frame
+ if ( pParent && !pParent->IsInputEnabled() )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ // Nur wenn er sichtbar und enabled ist
+ if ( pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg, TRUE ) &&
+ pExeDlg->IsReallyVisible() &&
+ pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() )
+ {
+ pParent = pExeDlg;
+ break;
+ }
+
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ }
+ }
+
+ if ( pParent && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE) )
+ {
+ if ( !pParent->mpFrameWindow->IsVisible() )
+ pParent = NULL;
+ else
+ {
+ if ( pParent->mpFrameWindow->IsDialog() )
+ {
+ Size aOutSize = pParent->mpFrameWindow->GetOutputSizePixel();
+ if ( (aOutSize.Width() < 210) ||(aOutSize.Height() < 160) )
+ nStyle |= WB_SYSTEMWINDOW;
+ }
+ }
+ }
+
+ if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
+ (pParent->mpFrameData->mbNeedSysWindow && !(nSysWinMode & SYSTEMWINDOW_MODE_NOAUTOMODE)) ||
+ (nSysWinMode & SYSTEMWINDOW_MODE_DIALOG) )
+ {
+ // Fenster mit einem schmallen Border anlegen?
+ if ( (nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER )
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_FRAME );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpBorderWindow = pBorderWin;
+ mpRealParent = pParent;
+ }
+ else
+ {
+ mbFrame = TRUE;
+ mbOverlapWin = TRUE;
+ SystemWindow::ImplInit( pParent, nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE), NULL );
+ // Jetzt alle StyleBits setzen
+ mnStyle = nStyle;
+ }
+ }
+ else
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_OVERLAP | BORDERWINDOW_STYLE_BORDER );
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpBorderWindow = pBorderWin;
+ mpRealParent = pParent;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplInitSettings()
+{
+ // Wir haben graue Dialoge
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( GetSettings().GetStyleSettings().GetDialogColor() );
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::ImplCenterDialog()
+{
+ Rectangle aDeskRect = ImplGetFrameWindow()->GetDesktopRectPixel();
+ Point aDeskPos = aDeskRect.TopLeft();
+ Size aDeskSize = aDeskRect.GetSize();
+ Size aWinSize = GetSizePixel();
+ Point aWinPos( ((aDeskSize.Width() - aWinSize.Width()) / 2) + aDeskPos.X(),
+ ((aDeskSize.Height() - aWinSize.Height()) / 2) + aDeskPos.Y() );
+
+ // Pruefen, ob Dialogbox ausserhalb des Desks liegt
+ if ( (aWinPos.X() + aWinSize.Width()) > (aDeskPos.X()+aDeskSize.Width()) )
+ aWinPos.X() = aDeskPos.X()+aDeskSize.Width() - aWinSize.Width();
+ if ( (aWinPos.Y()+aWinSize.Height()) > (aDeskPos.Y()+aDeskSize.Height()) )
+ aWinPos.Y() = aDeskPos.Y()+aDeskSize.Height() - aWinSize.Height();
+ // Linke Ecke bevorzugen, da Titelbar oben ist
+ if ( aWinPos.X() < aDeskPos.X() )
+ aWinPos.X() = aDeskPos.X();
+ if ( aWinPos.Y() < aDeskPos.Y() )
+ aWinPos.Y() = aDeskPos.Y();
+
+ SetPosPixel( aWinPos );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( WindowType nType ) :
+ SystemWindow( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Dialog::Dialog( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_DIALOG )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_DIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+long Dialog::Notify( NotifyEvent& rNEvt )
+{
+ // Zuerst Basisklasse rufen wegen TabSteuerung
+ long nRet = SystemWindow::Notify( rNEvt );
+ if ( !nRet )
+ {
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_ESCAPE) &&
+ ((GetStyle() & WB_CLOSEABLE) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
+ {
+ Close();
+ return TRUE;
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::StateChanged( StateChangedType nType )
+{
+ SystemWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( Application::IsAutoMnemonicEnabled() )
+ ImplWindowAutoMnemonic( this );
+
+ if ( IsDefaultPos() && !mbFrame )
+ ImplCenterDialog();
+ if ( !HasChildPathFocus() || HasFocus() )
+ GrabFocusToFirstControl();
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
+ {
+ if ( ImplGetBorderWindow() )
+ ((ImplBorderWindow*)ImplGetBorderWindow())->SetCloser();
+ else
+ {
+ // ... missing implementation, if we are a frame window,
+ // because it is currently impossible to implement.
+ SetStyle( GetStyle() | WB_CLOSEABLE );
+ }
+ }
+ }
+
+ ImplMouseAutoPos( this );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SystemWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Dialog::Close()
+{
+ if ( mxWindowPeer.is() )
+ {
+ Application::GetUnoWrapper()->WindowEvent_Close( this );
+ if ( IsCreatedWithToolkit() )
+ return FALSE;
+ }
+
+ mbInClose = TRUE;
+
+ if ( !(GetStyle() & WB_CLOSEABLE) )
+ {
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ PushButton* pButton = ImplGetCancelButton( this );
+ if ( pButton )
+ pButton->Click();
+ else
+ {
+ pButton = ImplGetOKButton( this );
+ if ( pButton )
+ pButton->Click();
+ }
+ if ( aDelData.IsDelete() )
+ return TRUE;
+ ImplRemoveDel( &aDelData );
+ }
+
+ if ( IsInExecute() )
+ {
+ EndDialog( FALSE );
+ mbInClose = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ mbInClose = FALSE;
+ return SystemWindow::Close();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+short Dialog::Execute()
+{
+ if ( mbInExecute )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::Execute() is called in Dialoh::Execute(): " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return 0;
+ }
+
+ if ( Application::IsDialogCancelEnabled() )
+ {
+#ifdef DBG_UTIL
+ ByteString aErrorStr( "Dialog::Execute() is called in a none UI application: " );
+ aErrorStr += ImplGetDialogText( this );
+ DBG_ERROR( aErrorStr.GetBuffer() );
+#endif
+ return 0;
+ }
+
+#ifdef DBG_UTIL
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ pParent = pParent->ImplGetFirstOverlapWindow();
+ DBG_ASSERT( pParent->IsReallyVisible(),
+ "Dialog::Execute() - Parent not visible" );
+ }
+#endif
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Dialoge, die sich in Execute befinden, miteinander verketten
+ mpPrevExecuteDlg = pSVData->maWinData.mpLastExecuteDlg;
+ pSVData->maWinData.mpLastExecuteDlg = this;
+
+ // Capture beenden, damit der Dialog bedient werden kann
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ if ( pSVData->maWinData.mpCaptureWin )
+ pSVData->maWinData.mpCaptureWin->ReleaseMouse();
+ EnableInput( TRUE, TRUE );
+
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_EXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+ long nRet;
+ mpResult = &nRet;
+ mbInExecute = TRUE;
+ SetModalInputMode( TRUE );
+ mbOldSaveBack = IsSaveBackgroundEnabled();
+ EnableSaveBackground();
+ Show();
+
+ if ( Application::GetAccessHdlCount() )
+ {
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_MODALDIALOG_START, this ) );
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_DLGCONTROLS, this ) );
+ }
+
+ // Solange Yielden, bis EndDialog aufgerufen wird, oder der Dialog
+ // zerstoert wird (sollte nicht sein und ist nur vorsichtsmassnahme)
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ pSVData->maAppData.mnModalMode++;
+ while ( !aDelData.IsDelete() && mbInExecute )
+ Application::Yield();
+ pSVData->maAppData.mnModalMode--;
+ if ( !aDelData.IsDelete() )
+ ImplRemoveDel( &aDelData );
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR( "Dialog::Execute() - Dialog destroyed in Execute()" );
+ }
+#endif
+
+ return (short)nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::EndDialog( long nResult )
+{
+ if ( mbInExecute )
+ {
+ SetModalInputMode( FALSE );
+
+ // Dialog aus der Kette der Dialoge die in Execute stehen entfernen
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pPrevDlg = NULL;
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while ( pExeDlg )
+ {
+ if ( pExeDlg == this )
+ {
+ if ( pPrevDlg )
+ pPrevDlg->mpPrevExecuteDlg = mpPrevExecuteDlg;
+ else
+ pSVData->maWinData.mpLastExecuteDlg = mpPrevExecuteDlg;
+ break;
+ }
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ mpPrevExecuteDlg = NULL;
+
+ Hide();
+ EnableSaveBackground( mbOldSaveBack );
+ if ( GetParent() )
+ {
+ NotifyEvent aNEvt( EVENT_ENDEXECUTEDIALOG, this );
+ GetParent()->Notify( aNEvt );
+ }
+ if ( Application::GetAccessHdlCount() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_MODALDIALOG_END, this ) );
+ if ( mpResult )
+ *mpResult = nResult;
+ mpResult = NULL;
+ mbInExecute = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal )
+{
+ if ( bModal == mbModalMode )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ mbModalMode = bModal;
+ if ( bModal )
+ {
+ pSVData->maAppData.mnModalDialog++;
+
+ // Diable the prev Modal Dialog, because our dialog must close at first,
+ // before the other dialog can be closed (because the other dialog
+ // is on stack since our dialog returns)
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ mpPrevExecuteDlg->EnableInput( FALSE, TRUE, TRUE, this );
+
+ // determine next overlap dialog parent
+ Window* pParent = GetParent();
+ if ( pParent )
+ {
+ mpDialogParent = pParent->ImplGetFirstOverlapWindow();
+ if ( mpDialogParent )
+ mpDialogParent->EnableInput( FALSE, TRUE, TRUE, this );
+ }
+ }
+ else
+ {
+ pSVData->maAppData.mnModalDialog--;
+
+ if ( mpDialogParent )
+ mpDialogParent->EnableInput( TRUE, TRUE, TRUE, this );
+
+ // Enable the prev Modal Dialog
+ if ( mpPrevExecuteDlg && !mpPrevExecuteDlg->IsWindowOrChild( this, TRUE ) )
+ mpPrevExecuteDlg->EnableInput( TRUE, TRUE, TRUE, this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::SetModalInputMode( BOOL bModal, BOOL bSubModalDialogs )
+{
+ if ( bSubModalDialogs )
+ {
+ Window* pOverlap = ImplGetFirstOverlapWindow();
+ pOverlap = pOverlap->mpFirstOverlap;
+ while ( pOverlap )
+ {
+ if ( pOverlap->IsDialog() )
+ ((Dialog*)pOverlap)->SetModalInputMode( bModal, TRUE );
+ pOverlap = pOverlap->mpNext;
+ }
+ }
+
+ SetModalInputMode( bModal );
+}
+
+// -----------------------------------------------------------------------
+
+void Dialog::GrabFocusToFirstControl()
+{
+ Window* pFocusControl;
+
+ // Wenn Dialog den Focus hat, versuchen wr trotzdem
+ // ein Focus-Control zu finden
+ if ( HasFocus() )
+ pFocusControl = NULL;
+ else
+ {
+ // Wenn schon ein Child-Fenster mal den Focus hatte,
+ // dann dieses bevorzugen
+ pFocusControl = ImplGetFirstOverlapWindow()->mpLastFocusWindow;
+ // Control aus der Dialog-Steuerung suchen
+ if ( pFocusControl )
+ pFocusControl = ImplFindDlgCtrlWindow( pFocusControl );
+ }
+ // Kein Control hatte vorher den Focus, oder das Control
+ // befindet sich nicht in der Tab-Steuerung, dann das erste
+ // Control in der TabSteuerung den Focus geben
+ if ( !pFocusControl ||
+ !(pFocusControl->GetStyle() & WB_TABSTOP) ||
+ !pFocusControl->IsVisible() ||
+ !pFocusControl->IsEnabled() || !pFocusControl->IsInputEnabled() )
+ {
+ USHORT n = 0;
+ pFocusControl = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ }
+ if ( pFocusControl )
+ pFocusControl->ImplControlFocus( GETFOCUS_INIT );
+}
+
+// =======================================================================
+
+ModelessDialog::ModelessDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModelessDialog::ModelessDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODELESSDIALOG )
+{
+ rResId.SetRT( RSC_MODELESSDIALOG );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// =======================================================================
+
+ModalDialog::ModalDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ModalDialog::ModalDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_MODALDIALOG )
+{
+ rResId.SetRT( RSC_MODALDIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
diff --git a/vcl/source/window/dlgctrl.cxx b/vcl/source/window/dlgctrl.cxx
new file mode 100644
index 000000000000..a8c45e6d7f3b
--- /dev/null
+++ b/vcl/source/window/dlgctrl.cxx
@@ -0,0 +1,968 @@
+/*************************************************************************
+ *
+ * $RCSfile: dlgctrl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_DLGCTRL_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_TABPAGE_HXX
+#include <tabpage.hxx>
+#endif
+#ifndef _SV_TABCTRL_HXX
+#include <tabctrl.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+
+#include <unohelp.hxx>
+
+#ifndef _COM_SUN_STAR_LANG_XCHARACTERCLASSIFICATION_HPP_
+#include <com/sun/star/lang/XCharacterClassification.hpp>
+#endif
+
+using namespace ::com::sun::star;
+
+
+#pragma hdrstop
+
+// =======================================================================
+
+static Window* ImplGetSubChildWindow( Window* pParent, USHORT n, USHORT& nIndex )
+{
+ Window* pTabPage = NULL;
+ Window* pFoundWindow = NULL;
+ Window* pWindow = pParent->GetWindow( WINDOW_FIRSTCHILD );
+ Window* pNextWindow = pWindow;
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ // Unsichtbare und disablte Fenster werden uebersprungen
+ if ( pTabPage || pWindow->IsVisible() )
+ {
+ // Wenn das letzte Control ein TabControl war, wird von
+ // diesem die TabPage genommen
+ if ( pTabPage )
+ {
+ pFoundWindow = ImplGetSubChildWindow( pTabPage, n, nIndex );
+ pTabPage = NULL;
+ }
+ else
+ {
+ pFoundWindow = pWindow;
+
+ // Bei einem TabControl sich die aktuelle TabPage merken,
+ // damit diese dann genommen wird
+ if ( pWindow->GetType() == WINDOW_TABCONTROL )
+ {
+ TabControl* pTabControl = ((TabControl*)pWindow);
+ // Feststellen, ob TabPage Child vom TabControl ist
+ // und auch noch existiert (deshalb durch Vergleich,
+ // indem alle ChildFenster getestet werden). Denn es
+ // kann sein, das TabPages schon in einem Dialog-Dtor
+ // zerstoert wurden, obwohl das TabControl noch
+ // existiert.
+ TabPage* pTempTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
+ if ( pTempTabPage )
+ {
+ Window* pTempWindow = pTabControl->GetWindow( WINDOW_FIRSTCHILD );
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->ImplGetWindow() == pTempTabPage )
+ {
+ pTabPage = pTempTabPage;
+ break;
+ }
+ pTempWindow = pTempWindow->GetWindow( WINDOW_NEXT );
+ }
+ }
+ }
+ else if ( pWindow->GetStyle() & WB_DIALOGCONTROL )
+ pFoundWindow = ImplGetSubChildWindow( pWindow, n, nIndex );
+ }
+
+ if ( n == nIndex )
+ return pFoundWindow;
+ nIndex++;
+ }
+
+ if ( pTabPage )
+ pWindow = pTabPage;
+ else
+ {
+ pWindow = pNextWindow->GetWindow( WINDOW_NEXT );
+ pNextWindow = pWindow;
+ }
+ }
+
+ nIndex--;
+ return pFoundWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetChildWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
+{
+ nIndex = 0;
+ Window* pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
+ if ( bTestEnable )
+ {
+ USHORT n2 = nIndex;
+ while ( pWindow && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) )
+ {
+ n2 = nIndex+1;
+ nIndex = 0;
+ pWindow = ImplGetSubChildWindow( pParent, n2, nIndex );
+ if ( nIndex < n2 )
+ break;
+ }
+
+ if ( (nIndex < n2) && n )
+ {
+ do
+ {
+ n--;
+ nIndex = 0;
+ pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
+ }
+ while ( pWindow && n && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) );
+ }
+ }
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetNextWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
+{
+ Window* pWindow = ImplGetChildWindow( pParent, n+1, nIndex, bTestEnable );
+ if ( n == nIndex )
+ {
+ n = 0;
+ pWindow = ImplGetChildWindow( pParent, n, nIndex, bTestEnable );
+ }
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplGetDlgWindow( USHORT nIndex, USHORT nType,
+ USHORT nFormStart, USHORT nFormEnd,
+ USHORT* pIndex )
+{
+ DBG_ASSERT( (nIndex >= nFormStart) && (nIndex <= nFormEnd),
+ "Window::ImplGetDlgWindow() - nIndex not in Form" );
+
+ Window* pWindow = NULL;
+ USHORT i;
+ USHORT nTemp;
+ USHORT nStartIndex;
+
+ if ( nType == DLGWINDOW_PREV )
+ {
+ i = nIndex;
+ do
+ {
+ if ( i > nFormStart )
+ i--;
+ else
+ i = nFormEnd;
+ pWindow = ImplGetChildWindow( this, i, nTemp, TRUE );
+ if ( !pWindow )
+ break;
+ if ( (i == nTemp) && (pWindow->GetStyle() & WB_TABSTOP) )
+ break;
+ }
+ while ( i != nIndex );
+ }
+ else
+ {
+ i = nIndex;
+ pWindow = ImplGetChildWindow( this, i, i, (nType == DLGWINDOW_FIRST) );
+ if ( pWindow )
+ {
+ nStartIndex = i;
+
+ if ( nType == DLGWINDOW_NEXT )
+ {
+ if ( i < nFormEnd )
+ {
+ pWindow = ImplGetNextWindow( this, i, i, TRUE );
+ if ( (i > nFormEnd) || (i < nFormStart) )
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ }
+ else
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ }
+
+ if ( i <= nFormEnd )
+ {
+ // 2ten Index mitfuehren, falls alle Controls disablte
+ USHORT nStartIndex2 = i;
+
+ do
+ {
+ if ( pWindow->GetStyle() & WB_TABSTOP )
+ break;
+ if ( (i >= nFormEnd) || (i < nFormStart) )
+ pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
+ else
+ pWindow = ImplGetNextWindow( this, i, i, TRUE );
+ }
+ while ( (i != nStartIndex) && (i != nStartIndex2) );
+
+ if ( (i == nStartIndex2) &&
+ (!(pWindow->GetStyle() & WB_TABSTOP) || !pWindow->IsEnabled()) )
+ i = nStartIndex;
+ }
+ }
+
+ if ( nType == DLGWINDOW_FIRST )
+ {
+ if ( pWindow )
+ {
+ if ( pWindow->GetType() == WINDOW_TABCONTROL )
+ {
+ Window* pNextWindow = ImplGetDlgWindow( i, DLGWINDOW_NEXT );
+ if ( pNextWindow )
+ {
+ if ( pWindow->IsChild( pNextWindow ) )
+ pWindow = pNextWindow;
+ }
+ }
+
+ if ( !(pWindow->GetStyle() & WB_TABSTOP) )
+ pWindow = NULL;
+ }
+ }
+ }
+
+ if ( pIndex )
+ *pIndex = i;
+
+ return pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplFindAccelWindow( Window* pParent, USHORT& rIndex, xub_Unicode cCharCode,
+ USHORT nFormStart, USHORT nFormEnd )
+{
+ DBG_ASSERT( (rIndex >= nFormStart) && (rIndex <= nFormEnd),
+ "Window::ImplFindAccelWindow() - rIndex not in Form" );
+
+ xub_Unicode cCompareChar;
+ USHORT nStart = rIndex;
+ USHORT i = rIndex;
+ int bSearch = TRUE;
+ Window* pWindow;
+
+ // MT: Where can we keep the CharClass?!
+ static uno::Reference< lang::XCharacterClassification > xCharClass;
+ if ( !xCharClass.is() )
+ xCharClass = vcl::unohelper::CreateCharacterClassification();
+
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
+
+ cCharCode = xCharClass->toUpper( String(cCharCode), 0, 1, rLocale )[0];
+
+ if ( i < nFormEnd )
+ pWindow = ImplGetNextWindow( pParent, i, i, TRUE );
+ else
+ pWindow = ImplGetChildWindow( pParent, nFormStart, i, TRUE );
+ while ( bSearch )
+ {
+ const XubString aStr = pWindow->GetText();
+ USHORT nPos = aStr.Search( '~' );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ cCompareChar = aStr.GetChar( nPos+1 );
+ cCompareChar = xCharClass->toUpper( String(cCompareChar), 0, 1, rLocale )[0];
+ if ( cCompareChar == cCharCode )
+ {
+ // Bei Static-Controls auf das naechste Controlm weiterschalten
+ if ( (pWindow->GetType() == WINDOW_FIXEDTEXT) ||
+ (pWindow->GetType() == WINDOW_FIXEDLINE) ||
+ (pWindow->GetType() == WINDOW_GROUPBOX) )
+ pWindow = pParent->ImplGetDlgWindow( i, DLGWINDOW_NEXT );
+ rIndex = i;
+ return pWindow;
+ }
+ nPos = aStr.Search( '~', nPos+1 );
+ }
+
+ if ( i == nStart )
+ break;
+
+ if ( i < nFormEnd )
+ pWindow = ImplGetNextWindow( pParent, i, i, TRUE );
+ else
+ pWindow = ImplGetChildWindow( pParent, nFormStart, i, TRUE );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& rIndex,
+ USHORT& rFormStart, USHORT& rFormEnd )
+{
+ Window* pSWindow;
+ Window* pSecondWindow = NULL;
+ Window* pTempWindow = NULL;
+ USHORT i;
+ USHORT nSecond_i;
+ USHORT nFormStart = 0;
+ USHORT nSecondFormStart;
+ USHORT nFormEnd;
+
+ // Focus-Fenster in der Child-Liste suchen
+ pSWindow = ImplGetChildWindow( pParent, 0, i, FALSE );
+ while ( pSWindow )
+ {
+ if ( pSWindow->ImplGetWindow()->IsDialogControlStart() )
+ nFormStart = i;
+
+ // SecondWindow wegen zusammengesetzten Controls wie
+ // ComboBoxen und Feldern
+ if ( pSWindow->ImplIsWindowOrChild( pWindow ) )
+ {
+ pSecondWindow = pSWindow;
+ nSecond_i = i;
+ nSecondFormStart = nFormStart;
+ if ( pSWindow == pWindow )
+ break;
+ }
+
+ pSWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+ if ( !i )
+ pSWindow = NULL;
+ }
+
+ if ( !pSWindow )
+ {
+ // Fenster nicht gefunden, dann koennen wir auch keine
+ // Steuerung uebernehmen
+ if ( !pSecondWindow )
+ return NULL;
+ else
+ {
+ pSWindow = pSecondWindow;
+ i = nSecond_i;
+ nFormStart = nSecondFormStart;
+ }
+ }
+
+ // Start-Daten setzen
+ rIndex = i;
+ rFormStart = nFormStart;
+
+ // Formularende suchen
+ nFormEnd = nFormStart;
+ pTempWindow = pSWindow;
+ do
+ {
+ nFormEnd = i;
+ pTempWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+ if ( !i || (pTempWindow && pTempWindow->ImplGetWindow()->IsDialogControlStart()) )
+ break;
+ }
+ while ( pTempWindow );
+ rFormEnd = nFormEnd;
+
+ return pSWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplControlFocus( USHORT nFlags )
+{
+ if ( nFlags & GETFOCUS_MNEMONIC )
+ {
+ if ( GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( !((RadioButton*)this)->IsChecked() )
+ ((RadioButton*)this)->ImplCallClick( TRUE, nFlags );
+ else
+ ImplGrabFocus( nFlags );
+ }
+ else
+ {
+ ImplGrabFocus( nFlags );
+ if ( nFlags & GETFOCUS_UNIQUEMNEMONIC )
+ {
+ if ( GetType() == WINDOW_CHECKBOX )
+ ((CheckBox*)this)->ImplCheck();
+ else if ( mbPushButton )
+ {
+ ((PushButton*)this)->SetPressed( TRUE );
+ ((PushButton*)this)->SetPressed( FALSE );
+ ((PushButton*)this)->Click();
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( GetType() == WINDOW_RADIOBUTTON )
+ {
+ if ( !((RadioButton*)this)->IsChecked() )
+ ((RadioButton*)this)->ImplCallClick( TRUE, nFlags );
+ else
+ ImplGrabFocus( nFlags );
+ }
+ else
+ ImplGrabFocus( nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplDlgCtrl( const KeyEvent& rKEvt, BOOL bKeyInput )
+{
+ KeyCode aKeyCode = rKEvt.GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+ Window* pSWindow;
+ Window* pTempWindow;
+ Window* pButtonWindow;
+ USHORT i;
+ USHORT iButton;
+ USHORT iButtonStart;
+ USHORT iTemp;
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+ USHORT nDlgCtrlFlags;
+
+ // Ohne Focus-Window koennen wir auch keine Steuerung uebernehmen
+ Window* pFocusWindow = Application::GetFocusWindow();
+ if ( !pFocusWindow || !ImplIsWindowOrChild( pFocusWindow ) )
+ return FALSE;
+
+ // Focus-Fenster in der Child-Liste suchen
+ pSWindow = ::ImplFindDlgCtrlWindow( this, pFocusWindow,
+ nIndex, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ return FALSE;
+ i = nIndex;
+
+ nDlgCtrlFlags = 0;
+ pTempWindow = pSWindow;
+ do
+ {
+ nDlgCtrlFlags |= pTempWindow->GetDialogControlFlags();
+ if ( pTempWindow == this )
+ break;
+ pTempWindow = pTempWindow->ImplGetParent();
+ }
+ while ( pTempWindow );
+
+ pButtonWindow = NULL;
+
+ if ( nKeyCode == KEY_RETURN )
+ {
+ // Wir suchen zuerst nach einem DefPushButton/CancelButton
+ pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, TRUE );
+ iButtonStart = iButton;
+ while ( pButtonWindow )
+ {
+ if ( (pButtonWindow->GetStyle() & WB_DEFBUTTON) &&
+ pButtonWindow->mbPushButton )
+ break;
+
+ pButtonWindow = ImplGetNextWindow( this, iButton, iButton, TRUE );
+ if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
+ pButtonWindow = NULL;
+ }
+
+ if ( bKeyInput && !pButtonWindow && (nDlgCtrlFlags & WINDOW_DLGCTRL_RETURN) )
+ {
+ USHORT nType;
+ USHORT nGetFocusFlags = GETFOCUS_TAB;
+ USHORT nNewIndex;
+ USHORT iStart;
+ if ( aKeyCode.IsShift() )
+ {
+ nType = DLGWINDOW_PREV;
+ nGetFocusFlags |= GETFOCUS_BACKWARD;
+ }
+ else
+ {
+ nType = DLGWINDOW_NEXT;
+ nGetFocusFlags |= GETFOCUS_FORWARD;
+ }
+ iStart = i;
+ pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ while ( pTempWindow && (pTempWindow != pSWindow) )
+ {
+ if ( !pTempWindow->mbPushButton )
+ {
+ // Around-Flag ermitteln
+ if ( nType == DLGWINDOW_PREV )
+ {
+ if ( nNewIndex > iStart )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ else
+ {
+ if ( nNewIndex < iStart )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ pTempWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ else
+ {
+ i = nNewIndex;
+ pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ }
+ if ( (i <= iStart) || (i > nFormEnd) )
+ pTempWindow = NULL;
+ }
+ // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
+ // simulieren, falls AROUND ausgewertet wird
+ if ( pTempWindow && (pTempWindow == pSWindow) )
+ {
+ NotifyEvent aNEvt1( EVENT_LOSEFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt1 ) )
+ pSWindow->LoseFocus();
+ pSWindow->mnGetFocusFlags = nGetFocusFlags | GETFOCUS_AROUND;
+ NotifyEvent aNEvt2( EVENT_GETFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt2 ) )
+ pSWindow->GetFocus();
+ pSWindow->mnGetFocusFlags = 0;
+ return TRUE;
+ }
+ }
+ }
+ else if ( nKeyCode == KEY_ESCAPE )
+ {
+ // Wir suchen zuerst nach einem DefPushButton/CancelButton
+ pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, TRUE );
+ iButtonStart = iButton;
+ while ( pButtonWindow )
+ {
+ if ( pButtonWindow->GetType() == WINDOW_CANCELBUTTON )
+ break;
+
+ pButtonWindow = ImplGetNextWindow( this, iButton, iButton, TRUE );
+ if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
+ pButtonWindow = NULL;
+ }
+
+ if ( bKeyInput && mpDlgCtrlDownWindow )
+ {
+ if ( mpDlgCtrlDownWindow != pButtonWindow )
+ {
+ ((PushButton*)mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpDlgCtrlDownWindow = NULL;
+ return TRUE;
+ }
+ }
+ }
+ else if ( bKeyInput )
+ {
+ if ( nKeyCode == KEY_TAB )
+ {
+ // keine Alt-Taste abfangen, wegen Windows
+ if ( !aKeyCode.IsMod2() )
+ {
+ USHORT nType;
+ USHORT nGetFocusFlags = GETFOCUS_TAB;
+ USHORT nNewIndex;
+ BOOL bFormular = FALSE;
+
+ // Bei Ctrl-Tab erstmal testen, ob zwischen Formularen
+ // gesprungen werden soll
+ if ( aKeyCode.IsMod1() )
+ {
+ // Gruppe suchen
+ Window* pFormularFirstWindow = NULL;
+ Window* pLastFormularFirstWindow = NULL;
+ pTempWindow = ImplGetChildWindow( this, 0, iTemp, FALSE );
+ Window* pPrevFirstFormularFirstWindow = NULL;
+ Window* pFirstFormularFirstWindow = pTempWindow;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->ImplGetWindow()->IsDialogControlStart() )
+ {
+ if ( iTemp != 0 )
+ bFormular = TRUE;
+ if ( aKeyCode.IsShift() )
+ {
+ if ( iTemp <= nIndex )
+ pFormularFirstWindow = pPrevFirstFormularFirstWindow;
+ pPrevFirstFormularFirstWindow = pTempWindow;
+ }
+ else
+ {
+ if ( (iTemp > nIndex) && !pFormularFirstWindow )
+ pFormularFirstWindow = pTempWindow;
+ }
+ pLastFormularFirstWindow = pTempWindow;
+ }
+
+ pTempWindow = ImplGetNextWindow( this, iTemp, iTemp, FALSE );
+ if ( !iTemp )
+ pTempWindow = NULL;
+ }
+
+ if ( bFormular )
+ {
+ if ( !pFormularFirstWindow )
+ {
+ if ( aKeyCode.IsShift() )
+ pFormularFirstWindow = pLastFormularFirstWindow;
+ else
+ pFormularFirstWindow = pFirstFormularFirstWindow;
+ }
+
+ USHORT nFoundFormStart = 0;
+ USHORT nFoundFormEnd = 0;
+ USHORT nTempIndex = 0;
+ if ( ::ImplFindDlgCtrlWindow( this, pFormularFirstWindow, nTempIndex,
+ nFoundFormStart, nFoundFormEnd ) )
+ {
+ nTempIndex = nFoundFormStart;
+ pFormularFirstWindow = ImplGetDlgWindow( nTempIndex, DLGWINDOW_FIRST, nFoundFormStart, nFoundFormEnd );
+ if ( pFormularFirstWindow )
+ {
+ pFormularFirstWindow->ImplControlFocus();
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ if ( !bFormular )
+ {
+ // Nur mit Ctrl+Tab zwischen Controls springen, wenn
+ // es erlaubt wurde
+ if ( !aKeyCode.IsMod1() || (nDlgCtrlFlags & WINDOW_DLGCTRL_MOD1TAB) )
+ {
+ if ( aKeyCode.IsShift() )
+ {
+ nType = DLGWINDOW_PREV;
+ nGetFocusFlags |= GETFOCUS_BACKWARD;
+ }
+ else
+ {
+ nType = DLGWINDOW_NEXT;
+ nGetFocusFlags |= GETFOCUS_FORWARD;
+ }
+ Window* pWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
+ // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
+ // simulieren, falls AROUND ausgewertet wird
+ if ( pWindow == pSWindow )
+ {
+ NotifyEvent aNEvt1( EVENT_LOSEFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt1 ) )
+ pSWindow->LoseFocus();
+ pSWindow->mnGetFocusFlags = nGetFocusFlags | GETFOCUS_AROUND;
+ NotifyEvent aNEvt2( EVENT_GETFOCUS, pSWindow );
+ if ( !ImplCallPreNotify( aNEvt2 ) )
+ pSWindow->GetFocus();
+ pSWindow->mnGetFocusFlags = 0;
+ return TRUE;
+ }
+ else if ( pWindow )
+ {
+ // Around-Flag ermitteln
+ if ( nType == DLGWINDOW_PREV )
+ {
+ if ( nNewIndex > i )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ else
+ {
+ if ( nNewIndex < i )
+ nGetFocusFlags |= GETFOCUS_AROUND;
+ }
+ pWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ else if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_UP) )
+ {
+ Window* pWindow = pSWindow;
+ WinBits nStyle = pSWindow->GetStyle();
+ if ( !(nStyle & WB_GROUP) )
+ {
+ pWindow = pWindow->GetWindow( WINDOW_PREV );
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ nStyle = pWindow->GetStyle();
+
+ if ( pWindow->IsVisible() && pWindow->IsEnabled() && pWindow->IsInputEnabled() )
+ {
+ if ( pWindow != pSWindow )
+ pWindow->ImplControlFocus( GETFOCUS_CURSOR | GETFOCUS_BACKWARD );
+ return TRUE;
+ }
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ pWindow = pWindow->GetWindow( WINDOW_PREV );
+ }
+ }
+ }
+ else if ( (nKeyCode == KEY_RIGHT) || (nKeyCode == KEY_DOWN) )
+ {
+ Window* pWindow;
+ WinBits nStyle;
+ pWindow = pSWindow->GetWindow( WINDOW_NEXT );
+ while ( pWindow )
+ {
+ pWindow = pWindow->ImplGetWindow();
+
+ nStyle = pWindow->GetStyle();
+
+ if ( nStyle & WB_GROUP )
+ break;
+
+ if ( pWindow->IsVisible() && pWindow->IsEnabled() && pWindow->IsInputEnabled() )
+ {
+ pWindow->ImplControlFocus( GETFOCUS_CURSOR | GETFOCUS_BACKWARD );
+ return TRUE;
+ }
+
+ pWindow = pWindow->GetWindow( WINDOW_NEXT );
+ }
+ }
+ else
+ {
+ xub_Unicode c = rKEvt.GetCharCode();
+ if ( c )
+ {
+ pSWindow = ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd );
+ if ( pSWindow )
+ {
+ USHORT nGetFocusFlags = GETFOCUS_MNEMONIC;
+ if ( pSWindow == ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd ) )
+ nGetFocusFlags |= GETFOCUS_UNIQUEMNEMONIC;
+ pSWindow->ImplControlFocus( nGetFocusFlags );
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ if ( pButtonWindow && pButtonWindow->IsVisible() && pButtonWindow->IsEnabled() && pButtonWindow->IsInputEnabled() )
+ {
+ if ( bKeyInput )
+ {
+ if ( mpDlgCtrlDownWindow && (mpDlgCtrlDownWindow != pButtonWindow) )
+ {
+ ((PushButton*)mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpDlgCtrlDownWindow = NULL;
+ }
+
+ ((PushButton*)pButtonWindow)->SetPressed( TRUE );
+ mpDlgCtrlDownWindow = pButtonWindow;
+ }
+ else if ( mpDlgCtrlDownWindow == pButtonWindow )
+ {
+ mpDlgCtrlDownWindow = NULL;
+ ((PushButton*)pButtonWindow)->SetPressed( FALSE );
+ ((PushButton*)pButtonWindow)->Click();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDlgCtrlNextWindow()
+{
+ Window* pDlgCtrlParent;
+ Window* pDlgCtrl;
+ Window* pSWindow;
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // Fenster fuer Dialog-Steuerung suchen
+ pDlgCtrl = this;
+ pDlgCtrlParent = ImplGetParent();
+ while ( pDlgCtrlParent &&
+ !pDlgCtrlParent->ImplIsOverlapWindow() &&
+ ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ pDlgCtrlParent = pDlgCtrlParent->ImplGetParent();
+
+ if ( !pDlgCtrlParent || ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ return;
+
+ // Fenster in der Child-Liste suchen
+ pSWindow = ::ImplFindDlgCtrlWindow( pDlgCtrlParent, pDlgCtrl,
+ nIndex, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ return;
+
+ Window* pWindow = pDlgCtrlParent->ImplGetDlgWindow( nIndex, DLGWINDOW_NEXT, nFormStart, nFormEnd );
+ if ( pWindow && (pWindow != pSWindow) )
+ pWindow->ImplControlFocus();
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDlgCtrlUpdateDefButton( Window* pParent, Window* pFocusWindow,
+ BOOL bGetFocus )
+{
+ PushButton* pOldDefButton = NULL;
+ PushButton* pNewDefButton = NULL;
+ Window* pSWindow;
+ USHORT i;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // Formular suchen
+ pSWindow = ::ImplFindDlgCtrlWindow( pParent, pFocusWindow, i, nFormStart, nFormEnd );
+ if ( !pSWindow )
+ {
+ nFormStart = 0;
+ nFormEnd = 0xFFFF;
+ }
+
+ pSWindow = ImplGetChildWindow( pParent, nFormStart, i, FALSE );
+ while ( pSWindow )
+ {
+ if ( pSWindow->ImplIsPushButton() )
+ {
+ PushButton* pPushButton = (PushButton*)pSWindow;
+ if ( pPushButton->ImplIsDefButton() )
+ pOldDefButton = pPushButton;
+ if ( pPushButton->HasChildPathFocus() )
+ pNewDefButton = pPushButton;
+ else if ( !pNewDefButton && (pPushButton->GetStyle() & WB_DEFBUTTON) )
+ pNewDefButton = pPushButton;
+ }
+
+ pSWindow = ImplGetNextWindow( pParent, i, i, FALSE );
+ if ( !i || (i > nFormEnd) )
+ pSWindow = NULL;
+ }
+
+ if ( !bGetFocus )
+ {
+ USHORT nDummy;
+ Window* pNewFocusWindow = Application::GetFocusWindow();
+ if ( !pNewFocusWindow || !pParent->ImplIsWindowOrChild( pNewFocusWindow ) )
+ pNewDefButton = NULL;
+ else if ( !::ImplFindDlgCtrlWindow( pParent, pNewFocusWindow, i, nDummy, nDummy ) ||
+ (i < nFormStart) || (i > nFormEnd) )
+ pNewDefButton = NULL;
+ }
+
+ if ( pOldDefButton != pNewDefButton )
+ {
+ if ( pOldDefButton )
+ pOldDefButton->ImplSetDefButton( FALSE );
+ if ( pNewDefButton )
+ pNewDefButton->ImplSetDefButton( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDlgCtrlFocusChanged( Window* pWindow, BOOL bGetFocus )
+{
+ if ( mpDlgCtrlDownWindow && !bGetFocus )
+ {
+ ((PushButton*)mpDlgCtrlDownWindow)->SetPressed( FALSE );
+ mpDlgCtrlDownWindow = NULL;
+ }
+
+ ImplDlgCtrlUpdateDefButton( this, pWindow, bGetFocus );
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplFindDlgCtrlWindow( Window* pWindow )
+{
+ USHORT nIndex;
+ USHORT nFormStart;
+ USHORT nFormEnd;
+
+ // Focus-Fenster in der Child-Liste suchen und zurueckgeben
+ return ::ImplFindDlgCtrlWindow( this, pWindow, nIndex, nFormStart, nFormEnd );
+}
diff --git a/vcl/source/window/dockwin.cxx b/vcl/source/window/dockwin.cxx
new file mode 100644
index 000000000000..5a27ed7e75ef
--- /dev/null
+++ b/vcl/source/window/dockwin.cxx
@@ -0,0 +1,857 @@
+/*************************************************************************
+ *
+ * $RCSfile: dockwin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_DOCKWIN_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_FLOATWIN_HXX
+#include <floatwin.hxx>
+#endif
+#ifndef _SV_DOCKWIN_HXX
+#include <dockwin.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+#include <unowrap.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE | WB_PINABLE | WB_ROLLABLE)
+
+// =======================================================================
+
+class ImplDockFloatWin : public FloatingWindow
+{
+private:
+ DockingWindow* mpDockWin;
+
+public:
+ ImplDockFloatWin( Window* pParent, WinBits nWinBits,
+ DockingWindow* pDockingWin );
+
+ virtual void Move();
+ virtual void TitleButtonClick( USHORT nButton );
+ virtual void Pin();
+ virtual void Roll();
+ virtual void PopupModeEnd();
+ virtual void Resizing( Size& rSize );
+ virtual BOOL Close();
+};
+
+// -----------------------------------------------------------------------
+
+ImplDockFloatWin::ImplDockFloatWin( Window* pParent, WinBits nWinBits,
+ DockingWindow* pDockingWin ) :
+ FloatingWindow( pParent, nWinBits )
+{
+ mpDockWin = pDockingWin;
+
+ // Daten vom DockingWindow uebernehmen
+ if ( pDockingWin )
+ {
+ SetSettings( pDockingWin->GetSettings() );
+ Enable( pDockingWin->IsEnabled(), FALSE );
+ EnableInput( pDockingWin->IsInputEnabled(), FALSE );
+ AlwaysEnableInput( pDockingWin->IsAlwaysEnableInput(), FALSE );
+ EnableAlwaysOnTop( pDockingWin->IsAlwaysOnTopEnabled() );
+ EnableDrop( pDockingWin->IsDropEnabled() );
+ SetActivateMode( pDockingWin->GetActivateMode() );
+ }
+
+ SetBackground();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Move()
+{
+ FloatingWindow::Move();
+ mpDockWin->Move();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::TitleButtonClick( USHORT nButton )
+{
+ FloatingWindow::TitleButtonClick( nButton );
+ mpDockWin->TitleButtonClick( nButton );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Pin()
+{
+ FloatingWindow::Pin();
+ mpDockWin->Pin();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Roll()
+{
+ FloatingWindow::Roll();
+ mpDockWin->Roll();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::PopupModeEnd()
+{
+ FloatingWindow::PopupModeEnd();
+ mpDockWin->PopupModeEnd();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDockFloatWin::Resizing( Size& rSize )
+{
+ FloatingWindow::Resizing( rSize );
+ mpDockWin->Resizing( rSize );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplDockFloatWin::Close()
+{
+ return mpDockWin->Close();
+}
+
+// =======================================================================
+
+BOOL DockingWindow::ImplStartDocking( const Point& rPos )
+{
+ if ( !mbDockable )
+ return FALSE;
+
+ maMouseOff = rPos;
+ maMouseStart = maMouseOff;
+ mbDocking = TRUE;
+ mbLastFloatMode = IsFloatingMode();
+ mbStartFloat = mbLastFloatMode;
+
+ // FloatingBorder berechnen
+ FloatingWindow* pWin;
+ if ( mpFloatWin )
+ pWin = mpFloatWin;
+ else
+ pWin = new ImplDockFloatWin( mpParent, mnFloatBits, NULL );
+ pWin->GetBorder( mnDockLeft, mnDockTop, mnDockRight, mnDockBottom );
+ if ( !mpFloatWin )
+ delete pWin;
+
+ Point aPos = ImplOutputToFrame( Point() );
+ Size aSize = Window::GetOutputSizePixel();
+ mnTrackX = aPos.X();
+ mnTrackY = aPos.Y();
+ mnTrackWidth = aSize.Width();
+ mnTrackHeight = aSize.Height();
+
+ if ( mbLastFloatMode )
+ {
+ maMouseOff.X() += mnDockLeft;
+ maMouseOff.Y() += mnDockTop;
+ mnTrackX -= mnDockLeft;
+ mnTrackY -= mnDockTop;
+ mnTrackWidth += mnDockLeft+mnDockRight;
+ mnTrackHeight += mnDockTop+mnDockBottom;
+ }
+
+ if ( GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_DOCKING )
+ mbDragFull = TRUE;
+ else
+ {
+ StartDocking();
+ mbDragFull = FALSE;
+ ImplUpdateAll();
+ ImplGetFrameWindow()->ImplUpdateAll();
+ }
+
+ StartTracking( STARTTRACK_KEYMOD );
+ return TRUE;
+}
+
+// =======================================================================
+
+void DockingWindow::ImplInitData()
+{
+ mbDockWin = TRUE;
+
+ mpFloatWin = NULL;
+ mbDockCanceled = FALSE;
+ mbDockPrevented = FALSE;
+ mbFloatPrevented = FALSE;
+ mbDocking = FALSE;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ mpParent = pParent;
+ mbDockable = (nStyle & WB_DOCKABLE) != 0;
+ mnFloatBits = WB_BORDER | (nStyle & DOCKWIN_FLOATSTYLES);
+ nStyle &= ~(DOCKWIN_FLOATSTYLES | WB_BORDER);
+ if ( nStyle & WB_DOCKBORDER )
+ nStyle |= WB_BORDER;
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplInitSettings()
+{
+ // Hack, damit man auch DockingWindows ohne Hintergrund bauen kann
+ // und noch nicht alles umgestellt ist
+ if ( IsBackground() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ImplLoadRes( const ResId& rResId )
+{
+ Window::ImplLoadRes( rResId );
+
+ USHORT nMask = ReadShortRes();
+
+ if ( (RSC_DOCKINGWINDOW_XYMAPMODE | RSC_DOCKINGWINDOW_X |
+ RSC_DOCKINGWINDOW_Y) & nMask )
+ {
+ // Groessenangabe aus der Resource verwenden
+ Point aPos;
+ MapUnit ePosMap = MAP_PIXEL;
+
+ if ( RSC_DOCKINGWINDOW_XYMAPMODE & nMask )
+ ePosMap = (MapUnit)ReadShortRes();
+
+ if ( RSC_DOCKINGWINDOW_X & nMask )
+ {
+ aPos.X() = ReadShortRes();
+ aPos.X() = ImplLogicUnitToPixelX( aPos.X(), ePosMap );
+ }
+
+ if ( RSC_DOCKINGWINDOW_Y & nMask )
+ {
+ aPos.Y() = ReadShortRes();
+ aPos.Y() = ImplLogicUnitToPixelY( aPos.Y(), ePosMap );
+ }
+
+ SetFloatingPos( aPos );
+ }
+
+ if ( nMask & RSC_DOCKINGWINDOW_FLOATING )
+ {
+ if ( (BOOL)ReadShortRes() )
+ SetFloatingMode( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( WindowType nType ) :
+ Window( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_DOCKINGWINDOW )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::DockingWindow( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_DOCKINGWINDOW )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_DOCKINGWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+DockingWindow::~DockingWindow()
+{
+ if ( IsFloatingMode() )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( mbDocking )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbDocking = FALSE;
+ if ( mbDragFull )
+ {
+ // Bei Abbruch alten Zustand wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ StartDocking();
+ Rectangle aRect( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) );
+ EndDocking( aRect, mbStartFloat );
+ }
+ }
+ else
+ {
+ HideTracking();
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mbDockCanceled = TRUE;
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ mbDockCanceled = FALSE;
+ }
+ else
+ EndDocking( Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
+ }
+ }
+ // Docking nur bei nicht synthetischen MouseEvents
+ else if ( !rTEvt.GetMouseEvent().IsSynthetic() || rTEvt.GetMouseEvent().IsModifierChanged() )
+ {
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+ Point aFrameMousePos = ImplOutputToFrame( aMousePos );
+ Size aFrameSize = mpFrameWindow->GetOutputSizePixel();
+ if ( aFrameMousePos.X() < 0 )
+ aFrameMousePos.X() = 0;
+ if ( aFrameMousePos.Y() < 0 )
+ aFrameMousePos.Y() = 0;
+ if ( aFrameMousePos.X() > aFrameSize.Width()-1 )
+ aFrameMousePos.X() = aFrameSize.Width()-1;
+ if ( aFrameMousePos.Y() > aFrameSize.Height()-1 )
+ aFrameMousePos.Y() = aFrameSize.Height()-1;
+ aMousePos = ImplFrameToOutput( aFrameMousePos );
+ aMousePos.X() -= maMouseOff.X();
+ aMousePos.Y() -= maMouseOff.Y();
+ Point aPos = ImplOutputToFrame( aMousePos );
+ Rectangle aTrackRect( aPos, Size( mnTrackWidth, mnTrackHeight ) );
+ Rectangle aCompRect = aTrackRect;
+ aPos.X() += maMouseOff.X();
+ aPos.Y() += maMouseOff.Y();
+ if ( mbDragFull )
+ StartDocking();
+ if ( !rTEvt.GetMouseEvent().IsMod1() )
+ mbDockPrevented = TRUE;
+ BOOL bFloatMode = Docking( aPos, aTrackRect );
+ mbDockPrevented = FALSE;
+ mbFloatPrevented = FALSE;
+ if ( mbLastFloatMode != bFloatMode )
+ {
+ if ( bFloatMode )
+ {
+ aTrackRect.Left() -= mnDockLeft;
+ aTrackRect.Top() -= mnDockTop;
+ aTrackRect.Right() += mnDockRight;
+ aTrackRect.Bottom() += mnDockBottom;
+ }
+ else
+ {
+ if ( aCompRect == aTrackRect )
+ {
+ aTrackRect.Left() += mnDockLeft;
+ aTrackRect.Top() += mnDockTop;
+ aTrackRect.Right() -= mnDockRight;
+ aTrackRect.Bottom() -= mnDockBottom;
+ }
+ }
+ mbLastFloatMode = bFloatMode;
+ }
+ if ( mbDragFull )
+ {
+ Point aPos;
+ Point aOldPos = OutputToScreenPixel( aPos );
+ EndDocking( aTrackRect, mbLastFloatMode );
+ // Wenn der Status bzw. die Position sich
+ // geaendert hat, dann neu ausgeben
+ if ( aOldPos != OutputToScreenPixel( aPos ) )
+ {
+ ImplUpdateAll();
+ ImplGetFrameWindow()->ImplUpdateAll();
+ }
+// EndDocking( aTrackRect, mbLastFloatMode );
+ }
+ else
+ {
+ USHORT nTrackStyle;
+ if ( bFloatMode )
+ nTrackStyle = SHOWTRACK_BIG;
+ else
+ nTrackStyle = SHOWTRACK_SMALL;
+ Rectangle aShowTrackRect = aTrackRect;
+ aShowTrackRect.SetPos( ImplFrameToOutput( aShowTrackRect.TopLeft() ) );
+ ShowTracking( aShowTrackRect, nTrackStyle );
+
+ // Maus-Offset neu berechnen, da Rechteck veraendert werden
+ // konnte
+ maMouseOff.X() = aPos.X() - aTrackRect.Left();
+ maMouseOff.Y() = aPos.Y() - aTrackRect.Top();
+ }
+
+ mnTrackX = aTrackRect.Left();
+ mnTrackY = aTrackRect.Top();
+ mnTrackWidth = aTrackRect.GetWidth();
+ mnTrackHeight = aTrackRect.GetHeight();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long DockingWindow::Notify( NotifyEvent& rNEvt )
+{
+ if ( mbDockable )
+ {
+ if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
+ if ( pMEvt->IsLeft() )
+ {
+ if ( pMEvt->GetClicks() == 2 )
+ {
+ if ( pMEvt->IsMod1() )
+ SetFloatingMode( !IsFloatingMode() );
+ return TRUE;
+ }
+ else if ( pMEvt->GetClicks() == 1 )
+ {
+ Point aPos = pMEvt->GetPosPixel();
+ Window* pWindow = rNEvt.GetWindow();
+ if ( pWindow != this )
+ {
+ aPos = pWindow->OutputToScreenPixel( aPos );
+ aPos = ScreenToOutputPixel( aPos );
+ }
+ if ( IsFloatingMode() || pMEvt->IsMod1() )
+ ImplStartDocking( aPos );
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::StartDocking()
+{
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::Docking( const Point&, Rectangle& )
+{
+ return IsFloatingMode();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
+{
+ if ( !IsDockingCanceled() )
+ {
+ BOOL bShow = FALSE;
+ if ( bFloatMode != IsFloatingMode() )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ SetFloatingMode( bFloatMode );
+ bShow = TRUE;
+ }
+ if ( bFloatMode )
+ mpFloatWin->SetPosSizePixel( rRect.TopLeft(), rRect.GetSize() );
+ else
+ {
+ Point aPos = rRect.TopLeft();
+ aPos = GetParent()->ScreenToOutputPixel( aPos );
+ Window::SetPosSizePixel( aPos, rRect.GetSize() );
+ }
+
+ if ( bShow )
+ Show();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::PrepareToggleFloatingMode()
+{
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::Close()
+{
+ if ( mxWindowPeer.is() )
+ {
+ Application::GetUnoWrapper()->WindowEvent_Close( this );
+ if ( IsCreatedWithToolkit() )
+ return FALSE;
+ }
+
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ToggleFloatingMode()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::TitleButtonClick( USHORT )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Pin()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Roll()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::PopupModeEnd()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::Resizing( Size& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else
+ Window::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::ShowTitleButton( USHORT nButton, BOOL bVisible )
+{
+ if ( mpFloatWin )
+ mpFloatWin->ShowTitleButton( nButton, bVisible );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ mbDockBtn = bVisible;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ mbHideBtn = bVisible;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL DockingWindow::IsTitleButtonVisible( USHORT nButton ) const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->IsTitleButtonVisible( nButton );
+ else
+ {
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ return mbDockBtn;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ return mbHideBtn;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetFloatingMode( BOOL bFloatMode )
+{
+ if ( IsFloatingMode() != bFloatMode )
+ {
+ if ( PrepareToggleFloatingMode() )
+ {
+ BOOL bVisible = IsVisible();
+
+ if ( bFloatMode )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ maDockPos = Window::GetPosPixel();
+
+ Window* pRealParent = mpRealParent;
+ mpOldBorderWin = mpBorderWindow;
+ ImplDockFloatWin* pWin = new ImplDockFloatWin( mpParent, mnFloatBits, this );
+ mpFloatWin = pWin;
+ mpBorderWindow = NULL;
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ // Falls Parent zerstoert wird, muessen wir auch vom
+ // BorderWindow den Parent umsetzen
+ if ( mpOldBorderWin )
+ mpOldBorderWin->SetParent( pWin );
+ SetParent( pWin );
+ SetPosPixel( Point() );
+ mpBorderWindow = pWin;
+ pWin->mpClientWindow = this;
+ mpRealParent = pRealParent;
+ pWin->SetText( Window::GetText() );
+ pWin->SetOutputSizePixel( Window::GetSizePixel() );
+ pWin->SetPosPixel( maFloatPos );
+ // DockingDaten ans FloatingWindow weiterreichen
+ pWin->ShowTitleButton( TITLE_BUTTON_DOCKING, mbDockBtn );
+ pWin->ShowTitleButton( TITLE_BUTTON_HIDE, mbHideBtn );
+ pWin->SetPin( mbPined );
+ if ( mbRollUp )
+ pWin->RollUp();
+ else
+ pWin->RollDown();
+ pWin->SetRollUpOutputSizePixel( maRollUpOutSize );
+ pWin->SetMinOutputSizePixel( maMinOutSize );
+
+ ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ else
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // FloatingDaten wird im FloatingWindow speichern
+ maFloatPos = mpFloatWin->GetPosPixel();
+ mbDockBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_DOCKING );
+ mbHideBtn = mpFloatWin->IsTitleButtonVisible( TITLE_BUTTON_HIDE );
+ mbPined = mpFloatWin->IsPined();
+ mbRollUp = mpFloatWin->IsRollUp();
+ maRollUpOutSize = mpFloatWin->GetRollUpOutputSizePixel();
+ maMinOutSize = mpFloatWin->GetMinOutputSizePixel();
+
+ Window* pRealParent = mpRealParent;
+ mpBorderWindow = NULL;
+ if ( mpOldBorderWin )
+ {
+ SetParent( mpOldBorderWin );
+ ((ImplBorderWindow*)mpOldBorderWin)->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpOldBorderWin->Resize();
+ }
+ mpBorderWindow = mpOldBorderWin;
+ SetParent( pRealParent );
+ mpRealParent = pRealParent;
+ delete mpFloatWin;
+ mpFloatWin = NULL;
+ SetPosPixel( maDockPos );
+
+ ToggleFloatingMode();
+
+ if ( bVisible )
+ Show();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetFloatStyle( WinBits nStyle )
+{
+ mnFloatBits = nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+WinBits DockingWindow::GetFloatStyle() const
+{
+ return mnFloatBits;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetTabStop()
+{
+ mnStyle |= WB_GROUP | WB_TABSTOP;
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight,
+ USHORT nFlags )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+ else
+ Window::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+Point DockingWindow::GetPosPixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetPosPixel();
+ else
+ return Window::GetPosPixel();
+}
+
+// -----------------------------------------------------------------------
+
+Size DockingWindow::GetSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetSizePixel();
+ else
+ return Window::GetSizePixel();
+}
+
+// -----------------------------------------------------------------------
+
+void DockingWindow::SetOutputSizePixel( const Size& rNewSize )
+{
+ if ( mpFloatWin )
+ mpFloatWin->SetOutputSizePixel( rNewSize );
+ else
+ Window::SetOutputSizePixel( rNewSize );
+}
+
+// -----------------------------------------------------------------------
+
+Size DockingWindow::GetOutputSizePixel() const
+{
+ if ( mpFloatWin )
+ return mpFloatWin->GetOutputSizePixel();
+ else
+ return Window::GetOutputSizePixel();
+}
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
new file mode 100644
index 000000000000..800734aadf86
--- /dev/null
+++ b/vcl/source/window/floatwin.cxx
@@ -0,0 +1,748 @@
+/*************************************************************************
+ *
+ * $RCSfile: floatwin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FLOATWIN_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_TOOLBOX_HXX
+#include <toolbox.hxx>
+#endif
+#ifndef _SV_FLOATWIN_HXX
+#include <floatwin.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ mbFloatWin = TRUE;
+
+ if ( !pParent )
+ pParent = Application::GetAppWindow();
+
+ DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
+
+ // no Border, then we dont need a border window
+ if ( !nStyle )
+ {
+ mbOverlapWin = TRUE;
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+ SystemWindow::ImplInit( pParent, nStyle, NULL );
+ }
+ else
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, BORDERWINDOW_STYLE_OVERLAP | BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT );
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+ SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
+ pBorderWin->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ pBorderWin->SetDisplayActive( TRUE );
+ mpBorderWindow = pBorderWin;
+ mpRealParent = pParent;
+ }
+ SetActivateMode( 0 );
+
+ mpNextFloat = NULL;
+ mpFirstPopupModeWin = NULL;
+ mpBox = NULL;
+ mnPostId = 0;
+ mnTitle = (nStyle & WB_MOVEABLE) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
+ mnOldTitle = mnTitle;
+ mnPopupModeFlags = 0;
+ mbInPopupMode = FALSE;
+ mbPopupMode = FALSE;
+ mbPopupModeCanceled = FALSE;
+ mbPopupModeTearOff = FALSE;
+ mbMouseDown = FALSE;
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplInitSettings()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+}
+
+// =======================================================================
+
+FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_FLOATINGWINDOW )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_FLOATINGWINDOW )
+{
+ rResId.SetRT( RSC_FLOATINGWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplLoadRes( const ResId& rResId )
+{
+ SystemWindow::ImplLoadRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
+ RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
+ {
+ // Groessenangabe aus der Resource verwenden
+ Size aSize;
+ MapUnit eSizeMap = MAP_PIXEL;
+
+ if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
+ eSizeMap = (MapUnit) ReadShortRes();
+ if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
+ aSize.Width() = ReadShortRes();
+ if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
+ aSize.Height() = ReadShortRes();
+
+ SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
+ }
+
+ if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
+ {
+ if ( ReadShortRes() )
+ RollUp();
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+FloatingWindow::~FloatingWindow()
+{
+ if ( IsInPopupMode() )
+ EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
+
+ if ( mnPostId )
+ Application::RemoveUserEvent( mnPostId );
+}
+
+// -----------------------------------------------------------------------
+
+Point FloatingWindow::ImplCalcPos( Window* pWindow,
+ const Rectangle& rRect, ULONG nFlags,
+ USHORT& rArrangeIndex )
+{
+ // Fenster-Position ermitteln
+ Point aPos;
+ Size aSize = pWindow->GetSizePixel();
+ Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
+ USHORT nArrangeAry[5];
+ USHORT nArrangeIndex;
+ BOOL bLeft;
+ BOOL bTop;
+ BOOL bBreak;
+ if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_LEFT;
+ }
+ else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_RIGHT;
+ }
+ else if ( nFlags & FLOATWIN_POPUPMODE_UP )
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_UP;
+ }
+ else
+ {
+ nArrangeAry[0] = FLOATWIN_POPUPMODE_DOWN;
+ nArrangeAry[1] = FLOATWIN_POPUPMODE_UP;
+ nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
+ nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
+ nArrangeAry[4] = FLOATWIN_POPUPMODE_DOWN;
+ }
+ if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
+ nArrangeIndex = 4;
+ else
+ nArrangeIndex = 0;
+ for ( ; nArrangeIndex < 5; nArrangeIndex++ )
+ {
+ bLeft = FALSE;
+ bTop = FALSE;
+ bBreak = TRUE;
+ switch ( nArrangeAry[nArrangeIndex] )
+ {
+ case FLOATWIN_POPUPMODE_LEFT:
+ aPos.X() = rRect.Left()-aSize.Width();
+ aPos.Y() = rRect.Top();
+ aPos.Y() -= pWindow->mnTopBorder;
+ if ( aPos.X() < aScreenRect.Left() )
+ bBreak = FALSE;
+ break;
+ case FLOATWIN_POPUPMODE_RIGHT:
+ aPos = rRect.TopRight();
+ aPos.Y() -= pWindow->mnTopBorder;
+ if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
+ bBreak = FALSE;
+ break;
+ case FLOATWIN_POPUPMODE_UP:
+ aPos.X() = rRect.Left();
+ aPos.Y() = rRect.Top()-aSize.Height();
+ if ( aPos.Y() < aScreenRect.Top() )
+ bBreak = FALSE;
+ break;
+ case FLOATWIN_POPUPMODE_DOWN:
+ aPos = rRect.BottomLeft();
+ if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
+ bBreak = FALSE;
+ break;
+ }
+
+ // Evt. noch anpassen
+ if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
+ {
+ if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT) ||
+ (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
+ {
+ if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
+ {
+ bTop = TRUE;
+ aPos.Y() = rRect.Bottom()-aSize.Height();
+ if ( aPos.Y() < aScreenRect.Top() )
+ aPos.Y() = aScreenRect.Top();
+ }
+ }
+ else
+ {
+ if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
+ {
+ bLeft = TRUE;
+ aPos.X() = rRect.Right()-aSize.Width();
+ if ( aPos.X() < aScreenRect.Left() )
+ aPos.X() = aScreenRect.Left();
+ }
+ }
+ }
+
+ if ( bBreak )
+ break;
+ }
+ if ( nArrangeIndex > 4 )
+ nArrangeIndex = 4;
+
+ // Ansonsten soweit wie moeglich in den Bildschirm einpassen
+ if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
+ aPos.X() = aScreenRect.Right()-aSize.Width();
+ if ( aPos.X() < aScreenRect.Left() )
+ aPos.X() = aScreenRect.Left();
+ if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
+ aPos.Y() = aScreenRect.Bottom()-aSize.Height();
+ if ( aPos.Y() < aScreenRect.Top() )
+ aPos.Y() = aScreenRect.Top();
+
+ rArrangeIndex = nArrangeIndex;
+ return aPos;
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow* FloatingWindow::ImplFloatHitTest( const Point& rPos, USHORT& rHitTest )
+{
+ FloatingWindow* pWin = this;
+
+ do
+ {
+ Rectangle aRect( pWin->GetPosPixel(), pWin->GetSizePixel() );
+ if ( aRect.IsInside( rPos ) )
+ {
+ rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
+ return pWin;
+ }
+
+ // Testen, ob Maus im Rechteck
+ if ( pWin->maFloatRect.IsInside( rPos ) )
+ {
+ rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
+ return pWin;
+ }
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
+{
+ FloatingWindow* pWin = this;
+ FloatingWindow* pLastFoundWin = pWin;
+
+ do
+ {
+ if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
+ pLastFoundWin = pWin;
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ return pLastFoundWin;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
+{
+ FloatingWindow* pWin = this;
+
+ do
+ {
+ if ( pWin->mpFirstPopupModeWin == pWindow )
+ return TRUE;
+
+ pWin = pWin->mpNextFloat;
+ }
+ while ( pWin );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( FloatingWindow, ImplEndPopupModeHdl, void*, EMPTYARG )
+{
+ mnPostId = 0;
+ mnPopupModeFlags = 0;
+ mbPopupMode = FALSE;
+ PopupModeEnd();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long FloatingWindow::Notify( NotifyEvent& rNEvt )
+{
+ // Zuerst Basisklasse rufen wegen TabSteuerung
+ long nRet = SystemWindow::Notify( rNEvt );
+ if ( !nRet )
+ {
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ KeyCode aKeyCode = pKEvt->GetKeyCode();
+ USHORT nKeyCode = aKeyCode.GetCode();
+
+ if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
+ {
+ Close();
+ return TRUE;
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StateChanged( StateChangedType nType )
+{
+ SystemWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ SystemWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplCallPopupModeEnd()
+{
+ // PopupMode wurde beendet
+ mbInPopupMode = FALSE;
+
+ // Handler asyncron rufen
+ if ( !mnPostId )
+ Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::PopupModeEnd()
+{
+ maPopupModeEndHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::SetTitleType( USHORT nTitle )
+{
+ if ( (mnTitle != nTitle) && mpBorderWindow )
+ {
+ mnTitle = nTitle;
+ Size aOutSize = GetOutputSizePixel();
+ USHORT nTitleStyle;
+ if ( nTitle == FLOATWIN_TITLE_NORMAL )
+ nTitleStyle = BORDERWINDOW_TITLE_SMALL;
+ else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
+ nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
+ else // nTitle == FLOATWIN_TITLE_NONE
+ nTitleStyle = BORDERWINDOW_TITLE_NONE;
+ ((ImplBorderWindow*)mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
+ ((ImplBorderWindow*)mpBorderWindow)->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StartPopupMode( const Rectangle& rRect, ULONG nFlags )
+{
+ DBG_ASSERT( (GetStyle() & WB_MOVEABLE) || !(nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF),
+ "TearOff only allowed, when FloatingWindow moveable" );
+
+ // Wenn Fenster sichtbar, dann vorher hiden, da es sonst flackert
+ if ( IsVisible() )
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // Wenn Fenster klein, dann vorher aufklappen
+ if ( IsRollUp() )
+ RollDown();
+
+ // Title wegnehmen
+ mnOldTitle = mnTitle;
+ if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
+ SetTitleType( FLOATWIN_TITLE_TEAROFF );
+ else
+ SetTitleType( FLOATWIN_TITLE_NONE );
+
+ // Fenster-Position ermitteln und setzen
+ USHORT nArrangeIndex;
+ SetPosPixel( ImplCalcPos( this, rRect, nFlags, nArrangeIndex ) );
+
+ // Daten seten und Fenster anzeigen
+ maFloatRect = rRect;
+ maFloatRect.Left() -= 2;
+ maFloatRect.Top() -= 2;
+ maFloatRect.Right() += 2;
+ maFloatRect.Bottom() += 2;
+ mnPopupModeFlags = nFlags;
+ mbInPopupMode = TRUE;
+ mbPopupMode = TRUE;
+ mbPopupModeCanceled = FALSE;
+ mbPopupModeTearOff = FALSE;
+ mbMouseDown = FALSE;
+
+ mbOldSaveBackMode = IsSaveBackgroundEnabled();
+ EnableSaveBackground();
+
+/*
+ // Abfragen, ob Animation eingeschaltet ist
+ if ( (Application::GetSettings().GetAnimationOptions() & ANIMATION_OPTION_POPUP) &&
+ !(nFlags & FLOATWIN_POPUPMODE_NOANIMATION) )
+ {
+ USHORT nAniFlags;
+ switch ( nArrangeAry[nArrangeIndex] )
+ {
+ case FLOATWIN_POPUPMODE_LEFT:
+ nAniFlags = STARTANIMATION_LEFT;
+ break;
+ case FLOATWIN_POPUPMODE_RIGHT:
+ nAniFlags = STARTANIMATION_RIGHT;
+ break;
+ case FLOATWIN_POPUPMODE_UP:
+ nAniFlags = STARTANIMATION_UP;
+ break;
+ case FLOATWIN_POPUPMODE_DOWN:
+ nAniFlags = STARTANIMATION_DOWN;
+ break;
+ }
+ if ( !(nFlags & FLOATWIN_POPUPMODE_ANIMATIONSLIDE) )
+ {
+ if ( bLeft )
+ nAniFlags |= STARTANIMATION_LEFT;
+ else
+ nAniFlags |= STARTANIMATION_RIGHT;
+ if ( bTop )
+ nAniFlags |= STARTANIMATION_UP;
+ else
+ nAniFlags |= STARTANIMATION_DOWN;
+ }
+
+ ImpStartAnimation( this, nAniFlags );
+ }
+ else
+*/
+ Show();
+
+ // FloatingWindow in Liste der Fenster aufnehmen, die sich im PopupModus
+ // befinden
+ ImplSVData* pSVData = ImplGetSVData();
+ mpNextFloat = pSVData->maWinData.mpFirstFloat;
+ pSVData->maWinData.mpFirstFloat = this;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::StartPopupMode( ToolBox* pBox, ULONG nFlags )
+{
+ // Selektieten Button ermitteln
+ USHORT nItemId = pBox->GetDownItemId();
+ if ( !nItemId )
+ return;
+
+ mpBox = pBox;
+ pBox->ImplFloatControl( TRUE, this );
+
+ // Daten von der ToolBox holen
+ Rectangle aRect = pBox->GetItemRect( nItemId );
+ Point aPos = pBox->OutputToScreenPixel( aRect.TopLeft() );
+ aRect.SetPos( aPos );
+
+ // Flags fuer Positionierung bestimmen
+ if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
+ FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
+ FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
+ {
+ WindowAlign eAlign = pBox->GetAlign();
+ if ( pBox->IsHorizontal() )
+ {
+ if ( pBox->IsFloatingMode() || (eAlign == WINDOWALIGN_TOP) )
+ nFlags |= FLOATWIN_POPUPMODE_DOWN;
+ else
+ nFlags |= FLOATWIN_POPUPMODE_UP;
+ }
+ else
+ {
+ if ( eAlign == WINDOWALIGN_LEFT )
+ nFlags |= FLOATWIN_POPUPMODE_RIGHT;
+ else
+ nFlags |= FLOATWIN_POPUPMODE_LEFT;
+ }
+ }
+
+ // FloatingModus starten
+ StartPopupMode( aRect, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::ImplEndPopupMode( USHORT nFlags, ULONG nFocusId )
+{
+ if ( !mbInPopupMode )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
+ while ( pSVData->maWinData.mpFirstFloat != this )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+
+ // Fenster aus der Liste austragen
+ pSVData->maWinData.mpFirstFloat = mpNextFloat;
+ mpNextFloat = NULL;
+
+ ULONG nPopupModeFlags = mnPopupModeFlags;
+
+ // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
+ if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
+ !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
+ {
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
+ if ( nFocusId )
+ Window::EndSaveFocus( nFocusId );
+ else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
+ ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
+ pSVData->maWinData.mpFirstFloat->GrabFocus();
+ mbPopupModeTearOff = FALSE;
+ }
+ else
+ {
+ mbPopupModeTearOff = TRUE;
+ if ( nFocusId )
+ Window::EndSaveFocus( nFocusId, FALSE );
+ }
+ EnableSaveBackground( mbOldSaveBackMode );
+
+ mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
+
+ // Gegebenenfalls den Title wieder herstellen
+ SetTitleType( mnOldTitle );
+
+ // ToolBox wieder auf normal schalten
+ if ( mpBox )
+ {
+ mpBox->ImplFloatControl( FALSE, this );
+ mpBox = NULL;
+ }
+
+ // Je nach Parameter den PopupModeEnd-Handler rufen
+ if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
+ ImplCallPopupModeEnd();
+
+ // Je nach Parameter die restlichen Fenster auch noch schliessen
+ if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
+ {
+ if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
+ {
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::EndPopupMode( USHORT nFlags )
+{
+ ImplEndPopupMode( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::AddPopupModeWindow( Window* pWindow )
+{
+ // !!! bisher erst 1 Fenster und noch keine Liste
+ mpFirstPopupModeWin = pWindow;
+}
+
+// -----------------------------------------------------------------------
+
+void FloatingWindow::RemovePopupModeWindow( Window* pWindow )
+{
+ // !!! bisher erst 1 Fenster und noch keine Liste
+ if ( mpFirstPopupModeWin == pWindow )
+ mpFirstPopupModeWin = NULL;
+}
+
diff --git a/vcl/source/window/keycod.cxx b/vcl/source/window/keycod.cxx
new file mode 100644
index 000000000000..34d5a997648e
--- /dev/null
+++ b/vcl/source/window/keycod.cxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * $RCSfile: keycod.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_KEYCOD_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_KEYCOD_HXX
+#include <keycod.hxx>
+#endif
+
+#ifndef _RC_H
+#include <rc.h>
+#endif
+
+#ifdef REMOTE_APPSERVER
+#include <rmwindow.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+static USHORT aImplKeyFuncTab[(KEYFUNC_FRONT+1)*3] =
+{
+ 0, 0, 0, // KEYFUNC_DONTKNOW
+ KEY_N | KEY_MOD1, 0, 0, // KEYFUNC_NEW
+ KEY_O | KEY_MOD1, KEY_OPEN, 0, // KEYFUNC_OPEN
+ KEY_S | KEY_MOD1, 0, 0, // KEYFUNC_SAVE
+ 0, 0, 0, // KEYFUNC_SAVEAS
+ KEY_P | KEY_MOD1, 0, 0, // KEYFUNC_PRINT
+ KEY_W | KEY_MOD1, KEY_F4 | KEY_MOD1, 0, // KEYFUNC_CLOSE
+ KEY_Q | KEY_MOD1, KEY_F4 | KEY_MOD2, 0, // KEYFUNC_QUIT
+ KEY_X | KEY_MOD1, KEY_DELETE | KEY_SHIFT, KEY_CUT, // KEYFUNC_CUT
+ KEY_C | KEY_MOD1, KEY_INSERT | KEY_MOD1, KEY_COPY, // KEYFUNC_COPY
+ KEY_V | KEY_MOD1, KEY_INSERT | KEY_SHIFT, KEY_PASTE, // KEYFUNC_PASTE
+ KEY_Z | KEY_MOD1, KEY_BACKSPACE | KEY_MOD2, KEY_UNDO, // KEYFUNC_UNDO
+ 0, 0, 0, // KEYFUNC_REDO
+ KEY_DELETE, 0, 0, // KEYFUNC_DELETE
+ KEY_REPEAT, 0, 0, // KEYFUNC_REPEAT
+ KEY_F | KEY_MOD1, KEY_FIND, 0, // KEYFUNC_FIND
+ KEY_F | KEY_SHIFT | KEY_MOD1, KEY_SHIFT | KEY_FIND, 0, // KEYFUNC_FINDBACKWARD
+ KEY_RETURN | KEY_MOD2, 0, 0, // KEYFUNC_PROPERTIES
+ 0, 0, 0 // KEYFUNC_FRONT
+};
+
+// -----------------------------------------------------------------------
+
+void ImplGetKeyCode( KeyFuncType eFunc, USHORT& rCode1, USHORT& rCode2, USHORT& rCode3 )
+{
+ USHORT nIndex = (USHORT)eFunc;
+ nIndex *= 3;
+ rCode1 = aImplKeyFuncTab[nIndex];
+ rCode2 = aImplKeyFuncTab[nIndex+1];
+ rCode3 = aImplKeyFuncTab[nIndex+2];
+}
+
+// =======================================================================
+
+KeyCode::KeyCode( KeyFuncType eFunction )
+{
+ USHORT nDummy;
+ ImplGetKeyCode( eFunction, nCode, nDummy, nDummy );
+ eFunc = eFunction;
+}
+
+// -----------------------------------------------------------------------
+
+KeyCode::KeyCode( const ResId& rResId )
+{
+ rResId.SetRT( RSC_KEYCODE );
+
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr && pResMgr->GetResource( rResId ) )
+ {
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ USHORT nKeyCode = pResMgr->ReadShort();
+ USHORT nModifier = pResMgr->ReadShort();
+ USHORT nKeyFunc = pResMgr->ReadShort();
+
+ eFunc = (KeyFuncType)nKeyFunc;
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ USHORT nDummy;
+ ImplGetKeyCode( eFunc, nCode, nDummy, nDummy );
+ }
+ else
+ nCode = nKeyCode | nModifier;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString KeyCode::GetName( Window* pWindow ) const
+{
+ if ( !pWindow )
+ pWindow = ImplGetDefaultWindow();
+#ifndef REMOTE_APPSERVER
+ return pWindow->ImplGetFrame()->GetKeyName( GetFullCode() );
+#else
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->mpKeyNames )
+ {
+ pSVData->mpKeyNames = new KeyNames;
+ NMSP_CLIENT::KeyNameSequence aKeyNames;
+ pWindow->ImplGetFrame()->GetKeyNames( aKeyNames );
+ ULONG nNames = aKeyNames.getLength();
+ for ( USHORT n = 0; n < nNames; n++ )
+ {
+ const NMSP_CLIENT::IDLKeyNameInfo& rInfo = aKeyNames.getConstArray()[n];
+ pSVData->mpKeyNames->Insert( rInfo.nCode, new String( rInfo.aName ) );
+ }
+ }
+
+ String aName;
+ const int nMods = 3;
+ USHORT nKeyCode = GetFullCode();
+ USHORT aModifiers[nMods] = { KEY_MOD2, KEY_MOD1, KEY_SHIFT };
+ for ( USHORT n = 0; n < nMods; n++ )
+ {
+ USHORT nMod = aModifiers[n];
+ if ( nKeyCode & nMod )
+ {
+ String* pMod = pSVData->mpKeyNames->Get( nMod );
+ if ( pMod )
+ {
+ aName += *pMod;
+ aName += '+';
+ }
+ }
+ }
+
+ USHORT nCode = GetCode();
+ if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
+ aName += (sal_Unicode)'0'+(nCode-KEY_0);
+ else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
+ aName += (sal_Unicode)'A'+(nCode-KEY_A);
+ else if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
+ {
+ aName += (sal_Unicode)'F';
+ aName += (sal_Unicode)'1' + (nCode-KEY_F1);
+ }
+ else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
+ {
+ aName += (sal_Unicode)'F';
+ aName += (sal_Unicode)'1';
+ aName += (sal_Unicode)'0' + (nCode-KEY_F10);
+ }
+ else if ( (nCode >= KEY_F20) && (nCode <= KEY_F26) )
+ {
+ aName += (sal_Unicode)'F';
+ aName += (sal_Unicode)'2';
+ aName += (sal_Unicode)'0' + (nCode-KEY_F20);
+ }
+ else
+ {
+ String* pName = pSVData->mpKeyNames->Get( GetFullCode() );
+ if ( pName )
+ aName += *pName;
+ }
+ return aName;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+XubString KeyCode::GetSymbolName( const XubString& rFontName, Window* pWindow ) const
+{
+#ifndef REMOTE_APPSERVER
+ if ( !pWindow )
+ pWindow = ImplGetDefaultWindow();
+ return pWindow->ImplGetFrame()->GetSymbolKeyName( rFontName, GetFullCode() );
+#else
+ return GetName( pWindow );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+KeyFuncType KeyCode::GetFunction() const
+{
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ return eFunc;
+
+ USHORT nCompCode = GetModifier() | GetCode();
+ if ( nCompCode )
+ {
+ for ( USHORT i = (USHORT)KEYFUNC_NEW; i < (USHORT)KEYFUNC_FRONT; i++ )
+ {
+ USHORT nKeyCode1;
+ USHORT nKeyCode2;
+ USHORT nKeyCode3;
+ ImplGetKeyCode( (KeyFuncType)i, nKeyCode1, nKeyCode2, nKeyCode3 );
+ if ( (nCompCode == nKeyCode1) || (nCompCode == nKeyCode2) || (nCompCode == nKeyCode3) )
+ return (KeyFuncType)i;
+ }
+ }
+
+ return KEYFUNC_DONTKNOW;
+}
diff --git a/vcl/source/window/makefile.mk b/vcl/source/window/makefile.mk
new file mode 100644
index 000000000000..e65826da0a46
--- /dev/null
+++ b/vcl/source/window/makefile.mk
@@ -0,0 +1,139 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=win
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/accel.obj \
+ $(SLO)$/accmgr.obj \
+ $(SLO)$/brdwin.obj \
+ $(SLO)$/btndlg.obj \
+ $(SLO)$/cursor.obj \
+ $(SLO)$/dockwin.obj \
+ $(SLO)$/decoview.obj \
+ $(SLO)$/dialog.obj \
+ $(SLO)$/dlgctrl.obj \
+ $(SLO)$/filedlg.obj \
+ $(SLO)$/floatwin.obj \
+ $(SLO)$/keycod.obj \
+ $(SLO)$/menu.obj \
+ $(SLO)$/mnemonic.obj \
+ $(SLO)$/msgbox.obj \
+ $(SLO)$/seleng.obj \
+ $(SLO)$/split.obj \
+ $(SLO)$/splitwin.obj \
+ $(SLO)$/status.obj \
+ $(SLO)$/syschild.obj \
+ $(SLO)$/syswin.obj \
+ $(SLO)$/tabdlg.obj \
+ $(SLO)$/tabpage.obj \
+ $(SLO)$/toolbox.obj \
+ $(SLO)$/toolbox2.obj \
+ $(SLO)$/window.obj \
+ $(SLO)$/window2.obj \
+ $(SLO)$/winproc.obj \
+ $(SLO)$/wrkwin.obj \
+ $(SLO)$/scrwnd.obj
+
+.IF "$(remote)"!=""
+EXCEPTIONSFILES= \
+ $(SLO)$/brdwin.obj \
+ $(SLO)$/keycod.obj \
+ $(SLO)$/window.obj \
+ $(SLO)$/winproc.obj \
+ $(SLO)$/wrkwin.obj \
+ $(SLO)$/accel.obj \
+ $(SLO)$/cursor.obj \
+ $(SLO)$/dlgctrl.obj \
+ $(SLO)$/floatwin.obj \
+ $(SLO)$/menu.obj \
+ $(SLO)$/msgbox.obj \
+ $(SLO)$/split.obj \
+ $(SLO)$/status.obj \
+ $(SLO)$/syschild.obj \
+ $(SLO)$/syswin.obj \
+ $(SLO)$/tabpage.obj \
+ $(SLO)$/toolbox.obj \
+ $(SLO)$/toolbox2.obj \
+ $(SLO)$/dialog.obj
+.ELSE
+EXCEPTIONSFILES= \
+ $(SLO)$/window.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
new file mode 100644
index 000000000000..9df101095121
--- /dev/null
+++ b/vcl/source/window/menu.cxx
@@ -0,0 +1,3444 @@
+/*************************************************************************
+ *
+ * $RCSfile: menu.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MENU_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_MNEMONIC_HXX
+#include <mnemonic.hxx>
+#endif
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_FLOATWIN_HXX
+#include <floatwin.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _SV_BUTTON_HXX
+#include <button.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+
+#ifndef _ISOLANG_HXX
+#include <tools/isolang.hxx>
+#endif
+
+#pragma hdrstop
+
+#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
+#include <com/sun/star/uno/Reference.h>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_XCHARACTERCLASSIFICATION_HPP_
+#include <com/sun/star/lang/XCharacterClassification.hpp>
+#endif
+
+#include <unohelp.hxx>
+
+using namespace ::com::sun::star;
+
+DBG_NAME( Menu );
+
+#define ITEMPOS_INVALID 0xFFFF
+
+#define EXTRASPACEY 2
+#define EXTRAITEMHEIGHT 4
+
+DropEvent ImplTranslateDropEvent( const DropEvent& rE, Window* pSource, Window* pDest )
+{
+ Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
+ aPos = pDest->ScreenToOutputPixel( aPos );
+ return DropEvent( aPos, rE.GetData(), rE.GetAction(), rE.GetSourceOptions(),
+ rE.GetWindowType(), rE.IsDefaultAction() );
+}
+
+inline BOOL ImplIsMouseFollow()
+{
+ return ( Application::GetSettings().GetMouseSettings().GetFollow() & MOUSE_FOLLOW_MENU ) ? TRUE : FALSE;
+}
+
+
+struct MenuItemData
+{
+ USHORT nId; // SV Id
+ MenuItemType eType; // MenuItem-Type
+ MenuItemBits nBits; // MenuItem-Bits
+ Menu* pSubMenu; // Pointer auf das SubMenu
+ Menu* pAutoSubMenu; // Pointer auf SubMenu aus Resource
+ XubString aText; // Menu-Text
+ XubString aHelpText; // Help-String
+ XubString aCommandStr; // CommandString
+ ULONG nHelpId; // Help-Id
+ Image aImage; // Image
+ KeyCode aAccelKey; // Accelerator-Key
+ BOOL bChecked; // Checked
+ BOOL bEnabled; // Enabled
+ BOOL bIsTemporary; // Temporary inserted ('No selection possible')
+
+ Size aSz; // nur temporaer gueltig
+
+ MenuItemData() {}
+ MenuItemData( const XubString& rStr, const Image& rImage ) :
+ aText( rStr ),
+ aImage( rImage )
+ {}
+ ~MenuItemData() { delete pAutoSubMenu; }
+};
+
+
+class MenuItemList : public List
+{
+ uno::Reference< lang::XCharacterClassification > xCharClass;
+public:
+ MenuItemList() : List( 16, 4 ) {}
+ ~MenuItemList();
+
+ MenuItemData* Insert( USHORT nId, MenuItemType eType, MenuItemBits nBits,
+ const XubString& rStr, const Image& rImage,
+ Menu* pMenu, USHORT nPos );
+ void InsertSeparator( USHORT nPos );
+ void Remove( USHORT nPos );
+
+
+ MenuItemData* GetData( USHORT nSVId, USHORT& rPos ) const;
+ MenuItemData* GetData( USHORT nSVId ) const
+ { USHORT nTemp; return GetData( nSVId, nTemp ); }
+ MenuItemData* GetDataFromPos( ULONG nPos ) const
+ { return (MenuItemData*)List::GetObject( nPos ); }
+
+ MenuItemData* SearchItem( xub_Unicode cSelectChar, USHORT& rPos ) const;
+ uno::Reference< lang::XCharacterClassification > GetCharClass() const;
+};
+
+
+
+MenuItemList::~MenuItemList()
+{
+ for ( ULONG n = Count(); n; )
+ {
+ MenuItemData* pData = GetDataFromPos( --n );
+ delete pData;
+ }
+}
+
+MenuItemData* MenuItemList::Insert( USHORT nId, MenuItemType eType,
+ MenuItemBits nBits,
+ const XubString& rStr, const Image& rImage,
+ Menu* pMenu, USHORT nPos )
+{
+ MenuItemData* pData = new MenuItemData( rStr, rImage );
+ pData->nId = nId;
+ pData->eType = eType;
+ pData->nBits = nBits;
+ pData->pSubMenu = NULL;
+ pData->pAutoSubMenu = NULL;
+ pData->nHelpId = 0;
+ pData->bChecked = FALSE;
+ pData->bEnabled = TRUE;
+ pData->bIsTemporary = FALSE;
+ List::Insert( (void*)pData, nPos );
+ return pData;
+}
+
+void MenuItemList::InsertSeparator( USHORT nPos )
+{
+ MenuItemData* pData = new MenuItemData;
+ pData->nId = 0;
+ pData->eType = MENUITEM_SEPARATOR;
+ pData->nBits = 0;
+ pData->pSubMenu = NULL;
+ pData->pAutoSubMenu = NULL;
+ pData->nHelpId = 0;
+ pData->bChecked = FALSE;
+ pData->bEnabled = TRUE;
+ pData->bIsTemporary = FALSE;
+ List::Insert( (void*)pData, nPos );
+}
+
+void MenuItemList::Remove( USHORT nPos )
+{
+ MenuItemData* pData = (MenuItemData*)List::Remove( (ULONG)nPos );
+ if ( pData )
+ delete pData;
+}
+
+MenuItemData* MenuItemList::GetData( USHORT nSVId, USHORT& rPos ) const
+{
+ rPos = 0;
+ MenuItemData* pData = (MenuItemData*)GetObject( rPos );
+ while ( pData )
+ {
+ if ( pData->nId == nSVId )
+ return pData;
+
+ rPos++;
+ pData = (MenuItemData*)GetObject( rPos );
+ }
+
+ return NULL;
+}
+
+MenuItemData* MenuItemList::SearchItem( xub_Unicode cSelectChar, USHORT& rPos ) const
+{
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
+ xub_Unicode cCharCode = GetCharClass()->toUpper( String(cSelectChar), 0, 1, rLocale )[0];
+ for ( rPos = (USHORT)Count(); rPos; )
+ {
+ MenuItemData* pData = GetDataFromPos( --rPos );
+ if ( pData->bEnabled )
+ {
+ USHORT n = pData->aText.Search( '~' );
+ if ( n != STRING_NOTFOUND )
+ {
+ xub_Unicode cCompareChar = pData->aText.GetChar( n+1 );
+ cCompareChar = GetCharClass()->toUpper( String(cCompareChar), 0, 1, rLocale )[0];
+ if ( cCompareChar == cCharCode )
+ return pData;
+ }
+ }
+ }
+
+ return 0;
+}
+
+uno::Reference< lang::XCharacterClassification > MenuItemList::GetCharClass() const
+{
+ if ( !xCharClass.is() )
+ ((MenuItemList*)this)->xCharClass = vcl::unohelper::CreateCharacterClassification();
+ return xCharClass;
+}
+
+
+
+class MenuFloatingWindow : public FloatingWindow
+{
+private:
+ Menu* pMenu;
+ PopupMenu* pActivePopup;
+ Timer aHighlightChangedTimer;
+ Timer aScrollTimer;
+ ULONG nSaveFocusId;
+ long nStartY;
+ USHORT nHighlightedItem; // gehighlightetes/selektiertes Item
+ USHORT nMBDownPos;
+ USHORT nScrollerHeight;
+ USHORT nFirstEntry;
+ USHORT nBorder;
+ BOOL bInExecute;
+
+ BOOL bScrollMenu;
+ BOOL bScrollUp;
+ BOOL bScrollDown;
+
+ DECL_LINK( PopupEnd, FloatingWindow* );
+ DECL_LINK( HighlightChanged, Timer* );
+ DECL_LINK( AutoScroll, Timer* );
+
+ void StateChanged( StateChangedType nType );
+ void DataChanged( const DataChangedEvent& rDCEvt );
+
+protected:
+ Region ImplCalcClipRegion( BOOL bIncludeLogo = TRUE ) const;
+ void ImplInitClipRegion();
+ void ImplDrawScroller( BOOL bUp );
+ void ImplScroll( const Point& rMousePos );
+ void ImplScroll( BOOL bUp );
+ void ImplCursorUpDown( BOOL bUp );
+ void ImplHighlightItem( const MouseEvent& rMEvt, BOOL bMBDown );
+
+public:
+ MenuFloatingWindow( Menu* pMenu, Window* pParent, WinBits nStyle );
+ ~MenuFloatingWindow();
+
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+ virtual void KeyInput( const KeyEvent& rKEvent );
+ virtual void Command( const CommandEvent& rCEvt );
+ virtual void Paint( const Rectangle& rRect );
+ virtual void RequestHelp( const HelpEvent& rHEvt );
+ virtual void Resize();
+
+ void SetFocusId( ULONG nId ) { nSaveFocusId = nId; }
+ ULONG GetFocusId() const { return nSaveFocusId; }
+
+ void EnableScrollMenu( BOOL b );
+ BOOL IsScrollMenu() const { return bScrollMenu; }
+ USHORT GetScrollerHeight() const { return nScrollerHeight; }
+
+ void Execute();
+ void StopExecute( ULONG nFocusId = 0 );
+ void EndExecute();
+ void EndExecute( USHORT nSelectId );
+
+ PopupMenu* GetActivePopup() const { return pActivePopup; }
+ void KillActivePopup( PopupMenu* pThisOnly = NULL );
+
+ void HighlightItem( USHORT nPos, BOOL bHighlight );
+ void ChangeHighlightItem( USHORT n, BOOL bStartPopupTimer );
+};
+
+
+// Eine Basicklasse fuer beide (wegen pActivePopup, Timer, ...) waere nett,
+// aber dann musste eine 'Container'-Klasse gemacht werden, da von
+// unterschiedlichen Windows abgeleitet...
+// In den meisten Funktionen muessen dann sowieso Sonderbehandlungen fuer
+// MenuBar, PopupMenu gemacht werden, also doch zwei verschiedene Klassen.
+
+class MenuBarWindow : public Window
+{
+ friend class MenuBar;
+
+private:
+ Menu* pMenu;
+ PopupMenu* pActivePopup;
+ USHORT nHighlightedItem;
+ ULONG nSaveFocusId;
+ BOOL mbAutoPopup;
+
+ PushButton aCloser;
+ PushButton aFloatBtn;
+ PushButton aHideBtn;
+
+ void HighlightItem( USHORT nPos, BOOL bHighlight );
+ void ChangeHighlightItem( USHORT n, BOOL bSelectPopupEntry, BOOL bAllowRestoreFocus = TRUE );
+
+ USHORT ImplFindEntry( const Point& rMousePos ) const;
+ void ImplCreatePopup( BOOL bPreSelectFirst );
+ BOOL ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu = TRUE );
+
+ DECL_LINK( CloserHdl, PushButton* );
+ DECL_LINK( FloatHdl, PushButton* );
+ DECL_LINK( HideHdl, PushButton* );
+
+ void StateChanged( StateChangedType nType );
+ void DataChanged( const DataChangedEvent& rDCEvt );
+ void LoseFocus();
+
+public:
+ MenuBarWindow( Window* pParent );
+ ~MenuBarWindow();
+
+ void ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide );
+
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+ virtual void KeyInput( const KeyEvent& rKEvent );
+ virtual void Paint( const Rectangle& rRect );
+ virtual void Resize();
+ virtual void RequestHelp( const HelpEvent& rHEvt );
+ virtual BOOL QueryDrop( DropEvent& rDEvt );
+ virtual BOOL Drop( const DropEvent& rDEvt );
+
+ void SetFocusId( ULONG nId ) { nSaveFocusId = nId; }
+ ULONG GetFocusId() const { return nSaveFocusId; }
+
+ void SetMenu( MenuBar* pMenu );
+ void KillActivePopup();
+ PopupMenu* GetActivePopup() const { return pActivePopup; }
+ void PopupClosed( Menu* pMenu );
+};
+
+
+
+static void ImplSetMenuItemData( MenuItemData* pData, USHORT nPos )
+{
+ // Daten umsetzen
+ if ( !pData->aImage )
+ pData->eType = MENUITEM_STRING;
+ else if ( !pData->aText.Len() )
+ pData->eType = MENUITEM_IMAGE;
+ else
+ pData->eType = MENUITEM_STRINGIMAGE;
+}
+
+static BOOL ImplHandleHelpEvent( Window* pMenuWindow, Menu* pMenu, USHORT nHighlightedItem, const HelpEvent& rHEvt )
+{
+ BOOL bDone = FALSE;
+ USHORT nId = 0;
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ MenuItemData* pItemData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pItemData )
+ nId = pItemData->nId;
+ }
+
+ if ( ( rHEvt.GetMode() & HELPMODE_BALLOON ) && pMenuWindow )
+ {
+ Point aPos = rHEvt.GetMousePosPixel();
+ // Pos etwas nach unter-rechts korrigieren, wegen Pointer
+ aPos.X() += 15;
+// aPos.Y() += 20;
+ Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
+ bDone = TRUE;
+ }
+ else if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ {
+ // Ist eine Hilfe in die Applikation selektiert
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ {
+ // Ist eine ID vorhanden, dann Hilfe mit der ID aufrufen, sonst
+ // den Hilfe-Index
+ ULONG nHelpId = pMenu->GetHelpId( nId );
+ if ( nHelpId )
+ pHelp->Start( nHelpId );
+ else
+ pHelp->Start( HELP_INDEX );
+ }
+ bDone = TRUE;
+ }
+ return bDone;
+}
+
+
+Menu::Menu()
+{
+ DBG_CTOR( Menu, NULL );
+ ImplInit();
+}
+
+Menu::~Menu()
+{
+ DBG_DTOR( Menu, NULL );
+
+ if ( nEventId )
+ Application::RemoveUserEvent( nEventId );
+
+ bKilled = TRUE;
+
+ delete pItemList;
+ delete pLogo;
+}
+
+void Menu::ImplInit()
+{
+ nMenuFlags = 0;
+ nDefaultItem = 0;
+ bIsMenuBar = FALSE;
+ nSelectedId = 0;
+ pItemList = new MenuItemList;
+ pLogo = NULL;
+ pStartedFrom = NULL;
+ pWindow = NULL;
+ nEventId = 0;
+ bCanceled = FALSE;
+ bInCallback = FALSE;
+ bKilled = FALSE;
+}
+
+void Menu::ImplLoadRes( const ResId& rResId )
+{
+ rResId.SetRT( RSC_MENU );
+ GetRes( rResId );
+
+ USHORT nObjMask = ReadShortRes();
+
+ if( nObjMask & RSC_MENU_ITEMS )
+ {
+ USHORT nObjFollows = ReadShortRes();
+ // MenuItems einfuegen
+ for( USHORT i = 0; i < nObjFollows; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ }
+
+ if( nObjMask & RSC_MENU_TEXT )
+ {
+ if( bIsMenuBar ) // Kein Titel im Menubar
+ ReadStringRes();
+ else
+ aTitleText = ReadStringRes();
+ }
+ if( nObjMask & RSC_MENU_DEFAULTITEMID )
+ SetDefaultItem( ReadShortRes() );
+}
+
+void Menu::Activate()
+{
+ bInCallback = TRUE;
+ if ( !aActivateHdl.Call( this ) )
+ {
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->bInCallback = TRUE;
+ pStartMenu->aActivateHdl.Call( this );
+ pStartMenu->bInCallback = FALSE;
+ }
+ }
+ bInCallback = FALSE;
+}
+
+void Menu::Deactivate()
+{
+ for ( USHORT n = pItemList->Count(); n; )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( --n );
+ if ( pData->bIsTemporary )
+ pItemList->Remove( n );
+ }
+
+ bInCallback = TRUE;
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( !aDeactivateHdl.Call( this ) )
+ {
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->bInCallback = TRUE;
+ pStartMenu->aDeactivateHdl.Call( this );
+ pStartMenu->bInCallback = FALSE;
+ }
+ }
+ bInCallback = FALSE;
+
+ if ( this == pStartMenu )
+ GetpApp()->HideHelpStatusText();
+}
+
+void Menu::Highlight()
+{
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( !aHighlightHdl.Call( this ) )
+ {
+ if ( pStartMenu && ( pStartMenu != this ) )
+ pStartMenu->aHighlightHdl.Call( this );
+ }
+
+ if ( GetCurItemId() )
+ GetpApp()->ShowHelpStatusText( GetHelpText( GetCurItemId() ) );
+}
+
+void Menu::ImplSelect()
+{
+ MenuItemData* pData = GetItemList()->GetData( nSelectedId );
+ if ( pData && (pData->nBits & MIB_AUTOCHECK) )
+ {
+ BOOL bChecked = IsItemChecked( nSelectedId );
+ if ( pData->nBits & MIB_RADIOCHECK )
+ {
+ if ( !bChecked )
+ CheckItem( nSelectedId, TRUE );
+ }
+ else
+ CheckItem( nSelectedId, !bChecked );
+ }
+
+ // Select rufen
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mpActivePopupMenu = NULL; // Falls neues Execute im Select()
+ Application::PostUserEvent( nEventId, LINK( this, Menu, ImplCallSelect ) );
+}
+
+void Menu::Select()
+{
+ if ( !aSelectHdl.Call( this ) )
+ {
+ Menu* pStartMenu = ImplGetStartMenu();
+ if ( pStartMenu && ( pStartMenu != this ) )
+ {
+ pStartMenu->nSelectedId = nSelectedId;
+ pStartMenu->aSelectHdl.Call( this );
+ }
+ }
+}
+
+void Menu::RequestHelp( const HelpEvent& rHEvt )
+{
+}
+
+void Menu::InsertItem( USHORT nItemId, const XubString& rStr, MenuItemBits nItemBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
+ "Menu::InsertItem(): ItemId already exists" );
+
+ // Falls Position > ItemCount, dann anheangen
+ if ( nPos >= (USHORT)pItemList->Count() )
+ nPos = MENU_APPEND;
+
+ // Item in die MenuItemListe aufnehmen
+ MenuItemData* pData = pItemList->Insert( nItemId, MENUITEM_STRING,
+ nItemBits, rStr, Image(), this, nPos );
+
+ Window* pWin = ImplGetWindow();
+ if ( pWin )
+ {
+ ImplCalcSize( pWin );
+ if ( pWin->IsVisible() )
+ pWin->Invalidate();
+ }
+}
+
+void Menu::InsertItem( USHORT nItemId, const Image& rImage,
+ MenuItemBits nItemBits, USHORT nPos )
+{
+ InsertItem( nItemId, ImplGetSVEmptyStr(), nItemBits, nPos );
+ SetItemImage( nItemId, rImage );
+}
+
+void Menu::InsertItem( USHORT nItemId,
+ const XubString& rStr, const Image& rImage,
+ MenuItemBits nItemBits, USHORT nPos )
+{
+ InsertItem( nItemId, rStr, nItemBits, nPos );
+ SetItemImage( nItemId, rImage );
+}
+
+void Menu::InsertItem( const ResId& rResId, USHORT nPos )
+{
+ USHORT nObjMask;
+
+ GetRes( rResId.SetRT( RSC_MENUITEM ) );
+ nObjMask = ReadShortRes();
+
+ BOOL bSep = FALSE;
+ if ( nObjMask & RSC_MENUITEM_SEPARATOR )
+ bSep = (BOOL)ReadShortRes();
+
+ USHORT nItemId = 1;
+ if ( nObjMask & RSC_MENUITEM_ID )
+ nItemId = ReadShortRes();
+
+ USHORT nStatus = 0;
+ if ( nObjMask & RSC_MENUITEM_STATUS )
+ nStatus = ReadShortRes();
+
+ String aText;
+ if ( nObjMask & RSC_MENUITEM_TEXT )
+ aText = ReadStringRes();
+
+ // Item erzeugen
+ if ( nObjMask & RSC_MENUITEM_BITMAP )
+ {
+ if ( !bSep )
+ {
+ Bitmap aBmp( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ if ( aText.Len() )
+ InsertItem( nItemId, aText, aBmp, nStatus, nPos );
+ else
+ InsertItem( nItemId, aBmp, nStatus, nPos );
+ }
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ else if ( !bSep )
+ InsertItem( nItemId, aText, nStatus, nPos );
+ if ( bSep )
+ InsertSeparator( nPos );
+
+ String aHelpText;
+ if ( nObjMask & RSC_MENUITEM_HELPTEXT )
+ {
+ aHelpText = ReadStringRes();
+ if( !bSep )
+ SetHelpText( nItemId, aHelpText );
+ }
+
+ ULONG nHelpId = 0;
+ if ( nObjMask & RSC_MENUITEM_HELPID )
+ {
+ nHelpId = ReadLongRes();
+ if ( !bSep )
+ SetHelpId( nItemId, nHelpId );
+ }
+
+ if( !bSep /* && SvHelpSettings::HelpText( aHelpText, nHelpId ) */ )
+ SetHelpText( nItemId, aHelpText );
+
+ if ( nObjMask & RSC_MENUITEM_KEYCODE )
+ {
+ if ( !bSep )
+ SetAccelKey( nItemId, KeyCode( ResId( (RSHEADER_TYPE*)GetClassRes() ) ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+ if( nObjMask & RSC_MENUITEM_CHECKED )
+ {
+ if ( !bSep )
+ CheckItem( nItemId, (BOOL)ReadShortRes() );
+ }
+ if ( nObjMask & RSC_MENUITEM_DISABLE )
+ {
+ if ( !bSep )
+ EnableItem( nItemId, !(BOOL)ReadShortRes() );
+ }
+ if ( nObjMask & RSC_MENUITEM_COMMAND )
+ {
+ String aCommandStr = ReadStringRes();
+ if ( !bSep )
+ SetItemCommand( nItemId, aCommandStr );
+ }
+ if ( nObjMask & RSC_MENUITEM_MENU )
+ {
+ if ( !bSep )
+ {
+ MenuItemData* pData = GetItemList()->GetData( nItemId );
+ if ( pData )
+ {
+ PopupMenu* pSubMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ pData->pAutoSubMenu = pSubMenu;
+ SetPopupMenu( nItemId, pSubMenu );
+ }
+ }
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+}
+
+void Menu::InsertSeparator( USHORT nPos )
+{
+ // Handelt es sich um einen MenuBar, dann mache nichts
+ if ( bIsMenuBar )
+ return;
+
+ // Falls Position > ItemCount, dann anheangen
+ if ( nPos >= (USHORT)pItemList->Count() )
+ nPos = MENU_APPEND;
+
+ // Separator in die Item-Liste einfuegen
+ pItemList->InsertSeparator( nPos );
+}
+
+void Menu::RemoveItem( USHORT nPos )
+{
+ if ( nPos < GetItemCount() )
+ pItemList->Remove( nPos );
+
+ Window* pWin = ImplGetWindow();
+ if ( pWin )
+ {
+ ImplCalcSize( pWin );
+ if ( pWin->IsVisible() )
+ pWin->Invalidate();
+ }
+}
+
+void ImplCopyItem( Menu* pThis, const Menu& rMenu, USHORT nPos, USHORT nNewPos,
+ USHORT nMode = 0 )
+{
+ MenuItemType eType = rMenu.GetItemType( nPos );
+
+ if ( eType == MENUITEM_DONTKNOW )
+ return;
+
+ if ( eType == MENUITEM_SEPARATOR )
+ pThis->InsertSeparator( nNewPos );
+ else
+ {
+ USHORT nId = rMenu.GetItemId( nPos );
+
+ DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
+ "Menu::CopyItem(): ItemId already exists" );
+
+ MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
+
+ if ( eType == MENUITEM_STRINGIMAGE )
+ pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, nNewPos );
+ else if ( eType == MENUITEM_STRING )
+ pThis->InsertItem( nId, pData->aText, pData->nBits, nNewPos );
+ else
+ pThis->InsertItem( nId, pData->aImage, pData->nBits, nNewPos );
+
+ if ( rMenu.IsItemChecked( nId ) )
+ pThis->CheckItem( nId, TRUE );
+ if ( !rMenu.IsItemEnabled( nId ) )
+ pThis->EnableItem( nId, FALSE );
+ pThis->SetHelpId( nId, pData->nHelpId );
+ pThis->SetHelpText( nId, pData->aHelpText );
+ pThis->SetAccelKey( nId, pData->aAccelKey );
+
+ PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
+ if ( pSubMenu )
+ {
+ // AutoKopie anlegen
+ if ( nMode == 1 )
+ {
+ PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
+ pThis->SetPopupMenu( nId, pNewMenu );
+// SetAutoMenu( pThis, nId, pNewMenu );
+ }
+ else
+ pThis->SetPopupMenu( nId, pSubMenu );
+ }
+ }
+}
+
+void Menu::CopyItem( const Menu& rMenu, USHORT nPos, USHORT nNewPos )
+{
+ ImplCopyItem( this, rMenu, nPos, nNewPos );
+}
+
+void Menu::Clear()
+{
+ for ( USHORT i = GetItemCount(); i; i-- )
+ RemoveItem( 0 );
+}
+
+USHORT Menu::GetItemCount() const
+{
+ return (USHORT)pItemList->Count();
+}
+
+USHORT Menu::ImplGetVisibleItemCount() const
+{
+ USHORT nItems = 0;
+ for ( USHORT n = (USHORT)pItemList->Count(); n; )
+ {
+ if ( ImplIsVisible( --n ) )
+ nItems++;
+ }
+ return nItems;
+}
+
+USHORT Menu::GetItemId( USHORT nPos ) const
+{
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+
+ if ( pData )
+ return pData->nId;
+ else
+ return 0;
+}
+
+USHORT Menu::GetItemPos( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ return nPos;
+ else
+ return MENU_ITEM_NOTFOUND;
+}
+
+MenuItemType Menu::GetItemType( USHORT nPos ) const
+{
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+
+ if ( pData )
+ return pData->eType;
+ else
+ return MENUITEM_DONTKNOW;
+}
+
+USHORT Menu::GetCurItemId() const
+{
+ return nSelectedId;
+}
+
+void Menu::SetItemBits( USHORT nItemId, MenuItemBits nBits )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if ( pData )
+ pData->nBits = nBits;
+}
+
+MenuItemBits Menu::GetItemBits( USHORT nItemId ) const
+{
+ MenuItemBits nBits = 0;
+ MenuItemData* pData = pItemList->GetData( nItemId );
+ if ( pData )
+ nBits = pData->nBits;
+ return nBits;
+}
+
+void Menu::SetPopupMenu( USHORT nItemId, PopupMenu* pMenu )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ // Item nicht vorhanden, dann NULL zurueckgeben
+ if ( !pData )
+ return;
+
+ // Gleiches Menu, danmn brauchen wir nichts machen
+ if ( (PopupMenu*)pData->pSubMenu == pMenu )
+ return;
+
+ // Daten austauschen
+ pData->pSubMenu = pMenu;
+}
+
+PopupMenu* Menu::GetPopupMenu( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return (PopupMenu*)(pData->pSubMenu);
+ else
+ return NULL;
+}
+
+void Menu::SetAccelKey( USHORT nItemId, const KeyCode& rKeyCode )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ if ( pData->aAccelKey == rKeyCode )
+ return;
+
+ pData->aAccelKey = rKeyCode;
+}
+
+KeyCode Menu::GetAccelKey( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aAccelKey;
+ else
+ return KeyCode();
+}
+
+void Menu::CheckItem( USHORT nItemId, BOOL bCheck )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ // Wenn RadioCheck, dann vorherigen unchecken
+ if ( bCheck && (pData->nBits & MIB_AUTOCHECK) &&
+ (pData->nBits & MIB_RADIOCHECK) )
+ {
+ MenuItemData* pGroupData;
+ USHORT nGroupPos;
+ USHORT nItemCount = GetItemCount();
+ BOOL bFound = FALSE;
+
+ nGroupPos = nPos;
+ while ( nGroupPos )
+ {
+ pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
+ if ( pGroupData->nBits & MIB_RADIOCHECK )
+ {
+ if ( IsItemChecked( pGroupData->nId ) )
+ {
+ CheckItem( pGroupData->nId, FALSE );
+ bFound = TRUE;
+ break;
+ }
+ }
+ else
+ break;
+ nGroupPos--;
+ }
+
+ if ( !bFound )
+ {
+ nGroupPos = nPos+1;
+ while ( nGroupPos < nItemCount )
+ {
+ pGroupData = pItemList->GetDataFromPos( nGroupPos );
+ if ( pGroupData->nBits & MIB_RADIOCHECK )
+ {
+ if ( IsItemChecked( pGroupData->nId ) )
+ {
+ CheckItem( pGroupData->nId, FALSE );
+ break;
+ }
+ }
+ else
+ break;
+ nGroupPos++;
+ }
+ }
+ }
+
+ pData->bChecked = bCheck;
+}
+
+BOOL Menu::IsItemChecked( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return FALSE;
+
+ return pData->bChecked;
+}
+
+void Menu::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData && ( pData->bEnabled != bEnable ) )
+ {
+ pData->bEnabled = bEnable;
+
+ Window* pWin = ImplGetWindow();
+ if ( pWin && pWin->IsVisible() )
+ {
+ DBG_ASSERT( bIsMenuBar, "Menu::EnableItem - Popup visible!" );
+ long nX = 0;
+ ULONG nCount = pItemList->Count();
+ for ( ULONG n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
+ break;
+ }
+ nX += pData->aSz.Width();
+ }
+ }
+ }
+}
+
+BOOL Menu::IsItemEnabled( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return FALSE;
+
+ return pData->bEnabled;
+}
+
+void Menu::SetItemText( USHORT nItemId, const XubString& rStr )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ pData->aText = rStr;
+ ImplSetMenuItemData( pData, nPos );
+}
+
+XubString Menu::GetItemText( USHORT nItemId ) const
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ return pData->aText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT nPos;
+ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( !pData )
+ return;
+
+ pData->aImage = rImage;
+ ImplSetMenuItemData( pData, nPos );
+}
+
+Image Menu::GetItemImage( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aImage;
+ else
+ return Image();
+}
+
+void Menu::SetItemCommand( USHORT nItemId, const String& rCommand )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aCommandStr = rCommand;
+}
+
+const XubString& Menu::GetItemCommand( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->aCommandStr;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetHelpText( USHORT nItemId, const XubString& rStr )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->aHelpText = rStr;
+}
+
+const XubString& Menu::GetHelpText( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ {
+ if ( !pData->aHelpText.Len() && pData->nHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pData->aHelpText = pHelp->GetHelpText( pData->nHelpId );
+ }
+
+ return pData->aHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+void Menu::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ pData->nHelpId = nHelpId;
+}
+
+ULONG Menu::GetHelpId( USHORT nItemId ) const
+{
+ MenuItemData* pData = pItemList->GetData( nItemId );
+
+ if ( pData )
+ return pData->nHelpId;
+ else
+ return 0;
+}
+
+Menu& Menu::operator=( const Menu& rMenu )
+{
+ // Aufraeumen
+ Clear();
+
+ // Items kopieren
+ USHORT nCount = rMenu.GetItemCount();
+ for ( USHORT i = 0; i < nCount; i++ )
+ ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
+
+ nDefaultItem = rMenu.nDefaultItem;
+ aActivateHdl = rMenu.aActivateHdl;
+ aDeactivateHdl = rMenu.aDeactivateHdl;
+ aHighlightHdl = rMenu.aHighlightHdl;
+ aSelectHdl = rMenu.aSelectHdl;
+ aTitleText = rMenu.aTitleText;
+ bIsMenuBar = rMenu.bIsMenuBar;
+
+ return *this;
+}
+
+BOOL Menu::ImplIsVisible( USHORT nPos ) const
+{
+ BOOL bVisible = TRUE;
+
+ // Fuer den Menubar nicht erlaubt, weil ich nicht mitbekomme
+ // ob dadurch ein Eintrag verschwindet oder wieder da ist.
+ if ( !bIsMenuBar && ( nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES ) )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( nPos );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( TRUE ) );
+ bVisible = pData->bEnabled; // SubMenus nicht pruefen, weil sie ggf. erst im Activate() gefuellt werden.
+ }
+ else
+ {
+ // Ein Separator ist nur dann visible, wenn davor sichtbare Eintraege stehen.
+ USHORT nCount = (USHORT) pItemList->Count();
+ USHORT n;
+ BOOL bPrevVisible = FALSE;
+ BOOL bNextVisible = FALSE;
+ for ( n = nPos; !bPrevVisible && n; )
+ {
+ pData = pItemList->GetDataFromPos( --n );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ bPrevVisible = pData->bEnabled; // && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( TRUE ) );
+ else
+ break;
+ }
+ if ( bPrevVisible )
+ {
+ for ( n = nPos+1; !bNextVisible && ( n < nCount ); n++ )
+ {
+ pData = pItemList->GetDataFromPos( n );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ bNextVisible = pData->bEnabled; // && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( TRUE ) );
+ // nicht beim naechsten Separator abbrechen...
+ }
+ }
+ bVisible = bPrevVisible && bNextVisible;
+ }
+ }
+
+ return bVisible;
+}
+
+Size Menu::ImplCalcSize( Window* pWin )
+{
+ // | Checked| Image| Text| Accel/Popup|
+
+ // Fuer Symbole: nFontHeight x nFontHeight
+ long nFontHeight = pWin->GetTextHeight();
+ long nExtra = nFontHeight/4;
+
+ Size aSz;
+ Size aMaxImgSz;
+ long nMaxTextWidth = 0;
+ long nMaxAccWidth = 0;
+
+ for ( USHORT n = (USHORT)pItemList->Count(); n; )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( --n );
+
+ pData->aSz.Height() = 0;
+ pData->aSz.Width() = 0;
+
+ if ( ImplIsVisible( n ) )
+ {
+
+ // Separator
+ if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
+ {
+ DBG_ASSERT( !bIsMenuBar, "Separator in MenuBar ?! " );
+ pData->aSz.Height() = 4;
+ }
+
+ // Image:
+ if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ {
+ Size aImgSz = pData->aImage.GetSizePixel();
+ if ( aImgSz.Width() > aMaxImgSz.Width() )
+ aMaxImgSz.Width() = aImgSz.Width();
+ if ( aImgSz.Height() > aMaxImgSz.Height() )
+ aMaxImgSz.Height() = aImgSz.Height();
+ if ( aImgSz.Height() > pData->aSz.Height() )
+ pData->aSz.Height() = aImgSz.Height();
+ }
+
+ // Text:
+ if ( (pData->eType == MENUITEM_STRING) || (pData->eType == MENUITEM_STRINGIMAGE) )
+ {
+ long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
+ if ( nTextWidth > nMaxTextWidth )
+ nMaxTextWidth = nTextWidth;
+ long nTextHeight = pWin->GetTextHeight();
+ if ( nTextHeight > pData->aSz.Height() )
+ pData->aSz.Height() = nTextHeight;
+
+ if ( bIsMenuBar )
+ {
+ pData->aSz.Width() = nTextWidth + 4*nExtra;
+ aSz.Width() += pData->aSz.Width();
+ }
+ }
+
+ // Accel
+ if ( !bIsMenuBar && pData->aAccelKey.GetCode() )
+ {
+ String aName = pData->aAccelKey.GetName();
+ long nAccWidth = pWin->GetTextWidth( aName );
+ nAccWidth += nExtra;
+ if ( nAccWidth > nMaxAccWidth )
+ nMaxAccWidth = nAccWidth;
+ }
+
+ // SubMenu?
+ if ( !bIsMenuBar && pData->pSubMenu )
+ {
+ if ( nFontHeight > nMaxAccWidth )
+ nMaxAccWidth = nFontHeight;
+ if ( nFontHeight > pData->aSz.Height() )
+ pData->aSz.Height() = nFontHeight;
+ }
+
+ pData->aSz.Height() += EXTRAITEMHEIGHT; // Etwas mehr Abstand:
+
+ if ( !bIsMenuBar )
+ aSz.Height() += (long)pData->aSz.Height();
+ }
+ }
+
+ if ( !bIsMenuBar )
+ {
+ nCheckPos = (USHORT)nExtra;
+ nImagePos = (USHORT)(nCheckPos + nFontHeight/2 + nExtra );
+ nTextPos = (USHORT)(nImagePos+aMaxImgSz.Width());
+ if ( aMaxImgSz.Width() )
+ nTextPos += (USHORT)nExtra;
+
+ aSz.Width() = nTextPos + nMaxTextWidth + nExtra + nMaxAccWidth;
+ aSz.Width() += 10*nExtra; // etwas mehr...
+ }
+ else
+ {
+ nTextPos = (USHORT)(2*nExtra);
+ aSz.Height() = nFontHeight+6;
+ }
+
+ if ( pLogo )
+ aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
+
+ return aSz;
+}
+
+void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData* pThisItemOnly, BOOL bHighlighted )
+{
+ // Fuer Symbole: nFontHeight x nFontHeight
+ long nFontHeight = pWin->GetTextHeight();
+ long nExtra = nFontHeight/4;
+
+ DecorationView aDecoView( pWin );
+ const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
+
+ Point aTopLeft, aTmpPos;
+
+ if ( pLogo )
+ aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
+
+ Size aOutSz = pWin->GetOutputSizePixel();
+ long nMaxY = aOutSz.Height() - nBorder;
+ USHORT nCount = (USHORT)pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( ImplIsVisible( n ) && ( !pThisItemOnly || ( pData == pThisItemOnly ) ) )
+ {
+ if ( pThisItemOnly && bHighlighted )
+ pWin->SetTextColor( rSettings.GetMenuHighlightTextColor() );
+
+ Point aPos( aTopLeft );
+ aPos.Y() += nBorder;
+ aPos.Y() += nStartY;
+
+ if ( aPos.Y() >= 0 )
+ {
+ long nTextOffsetY = ((pData->aSz.Height()-nFontHeight)/2);
+ USHORT nTextStyle = 0;
+ USHORT nSymbolStyle = 0;
+ USHORT nImageStyle = 0;
+ // SubMenus ohne Items werden nicht mehr disablte dargestellt,
+ // wenn keine Items enthalten sind, da die Anwendung selber
+ // darauf achten muss. Ansonsten gibt es Faelle, wo beim
+ // asyncronen laden die Eintraege disablte dargestellt werden.
+ if ( !pData->bEnabled )
+ {
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ nSymbolStyle |= SYMBOL_DRAW_DISABLE;
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+ }
+
+ // Separator
+ if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
+ {
+ aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height()-2)/2);
+ aTmpPos.X() = aPos.X() + 1;
+ pWin->SetLineColor( rSettings.GetShadowColor() );
+ pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 1, aTmpPos.Y() ) );
+ aTmpPos.Y()++;
+ pWin->SetLineColor( rSettings.GetLightColor() );
+ pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 1, aTmpPos.Y() ) );
+ pWin->SetLineColor();
+ }
+
+ // Image:
+ if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
+ {
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.X() = aPos.X() + nImagePos;
+ aTmpPos.Y() += (pData->aSz.Height()-pData->aImage.GetSizePixel().Height())/2;
+ pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle );
+ }
+
+ // Text:
+ if ( ( pData->eType == MENUITEM_STRING ) || ( pData->eType == MENUITEM_STRINGIMAGE ) )
+ {
+ aTmpPos.X() = aPos.X() + nTextPos;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ USHORT nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
+ if ( pData->bIsTemporary )
+ nStyle |= TEXT_DRAW_DISABLE;
+ pWin->DrawCtrlText( aTmpPos, pData->aText, 0, pData->aText.Len(), nStyle );
+ }
+
+ // Accel
+ if ( !bIsMenuBar && pData->aAccelKey.GetCode() )
+ {
+ XubString aAccText = pData->aAccelKey.GetName();
+ aTmpPos.X() = aOutSz.Width() - pWin->GetTextWidth( aAccText );
+ aTmpPos.X() -= 3*nExtra;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
+ }
+
+ // CheckMark
+ if ( !bIsMenuBar && pData->bChecked )
+ {
+ Rectangle aRect;
+ SymbolType eSymbol;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nExtra/2;
+ aTmpPos.Y() += pData->aSz.Height() / 2;
+ if ( pData->nBits & MIB_RADIOCHECK )
+ {
+ aTmpPos.X() = aPos.X() + nCheckPos;
+ eSymbol = SYMBOL_RADIOCHECKMARK;
+ aTmpPos.Y() -= nFontHeight/4;
+ aRect = Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) );
+ }
+ else
+ {
+ aTmpPos.X() = aPos.X() + nCheckPos;
+ eSymbol = SYMBOL_CHECKMARK;
+ aTmpPos.Y() -= nFontHeight/4;
+ aRect = Rectangle( aTmpPos, Size( (nFontHeight*25)/40, nFontHeight/2 ) );
+ }
+ aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle );
+ }
+
+ // SubMenu?
+ if ( !bIsMenuBar && pData->pSubMenu )
+ {
+ aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nExtra/2;
+ aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ Point aTmpPos2( aPos );
+ aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
+ aDecoView.DrawFrame(
+ Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
+ }
+ aDecoView.DrawSymbol(
+ Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
+ SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
+// if ( pData->nBits & MIB_POPUPSELECT )
+// {
+// aTmpPos.Y() += nFontHeight/2 ;
+// pWin->SetLineColor( rSettings.GetShadowColor() );
+// pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// pWin->SetLineColor( rSettings.GetLightColor() );
+// aTmpPos.Y()++;
+// pWin->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// pWin->SetLineColor();
+// }
+ }
+
+ if ( pThisItemOnly && bHighlighted )
+ pWin->SetTextColor( rSettings.GetMenuTextColor() );
+ }
+ }
+
+ if ( !bIsMenuBar )
+ {
+ aTopLeft.Y() += pData->aSz.Height();
+ }
+ else
+ {
+ aTopLeft.X() += pData->aSz.Width();
+ }
+ }
+
+ if ( !pThisItemOnly && pLogo )
+ {
+ Size aLogoSz = pLogo->aBitmap.GetSizePixel();
+
+ Rectangle aRect( Point( 0, 0 ), Point( aLogoSz.Width()-1, aOutSz.Height() ) );
+ if ( pWin->GetColorCount() >= 256 )
+ {
+ Gradient aGrad( GRADIENT_LINEAR, pLogo->aStartColor, pLogo->aEndColor );
+ aGrad.SetAngle( 1800 );
+ aGrad.SetBorder( 15 );
+ pWin->DrawGradient( aRect, aGrad );
+ }
+ else
+ {
+ pWin->SetFillColor( pLogo->aStartColor );
+ pWin->DrawRect( aRect );
+ }
+
+ Point aLogoPos( 0, aOutSz.Height() - aLogoSz.Height() );
+ pLogo->aBitmap.Draw( pWin, aLogoPos );
+ }
+}
+
+Menu* Menu::ImplGetStartMenu()
+{
+ Menu* pStart = this;
+ while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
+ pStart = pStart->pStartedFrom;
+ return pStart;
+}
+
+void Menu::ImplCallHighlight( USHORT nHighlightedItem )
+{
+ nSelectedId = 0;
+ MenuItemData* pData = pItemList->GetDataFromPos( nHighlightedItem );
+ if ( pData )
+ nSelectedId = pData->nId;
+ Highlight();
+ nSelectedId = 0;
+}
+
+IMPL_LINK( Menu, ImplCallSelect, Menu*, EMPTYARG )
+{
+ nEventId = 0;
+ Select();
+ return 0;
+}
+
+Menu* Menu::ImplFindSelectMenu()
+{
+ Menu* pSelMenu = nEventId ? this : NULL;
+
+ for ( ULONG n = GetItemList()->Count(); n && !pSelMenu; )
+ {
+ MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
+
+ if ( pData->pSubMenu )
+ pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
+ }
+
+ return pSelMenu;
+}
+
+void Menu::RemoveDisabledEntries( BOOL bCheckPopups, BOOL bRemoveEmptyPopups )
+{
+ for ( USHORT n = 0; n < GetItemCount(); n++ )
+ {
+ BOOL bRemove = FALSE;
+ MenuItemData* pItem = pItemList->GetDataFromPos( n );
+ if ( pItem->eType == MENUITEM_SEPARATOR )
+ {
+ if ( !n || ( GetItemType( n-1 ) == MENUITEM_SEPARATOR ) )
+ bRemove = TRUE;
+ }
+ else
+ bRemove = !pItem->bEnabled;
+
+ if ( bCheckPopups && pItem->pSubMenu )
+ {
+ pItem->pSubMenu->RemoveDisabledEntries( TRUE );
+ if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
+ bRemove = TRUE;
+ }
+
+ if ( bRemove )
+ RemoveItem( n-- );
+ }
+
+ if ( GetItemCount() )
+ {
+ USHORT nLast = GetItemCount() - 1;
+ MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
+ if ( pItem->eType == MENUITEM_SEPARATOR )
+ RemoveItem( nLast );
+ }
+}
+
+BOOL Menu::HasValidEntries( BOOL bCheckPopups )
+{
+ BOOL bValidEntries = FALSE;
+ USHORT nCount = GetItemCount();
+ for ( USHORT n = 0; !bValidEntries && ( n < nCount ); n++ )
+ {
+ MenuItemData* pItem = pItemList->GetDataFromPos( n );
+ if ( pItem->bEnabled && ( pItem->eType != MENUITEM_SEPARATOR ) )
+ {
+ if ( bCheckPopups && pItem->pSubMenu )
+ bValidEntries = pItem->pSubMenu->HasValidEntries( TRUE );
+ else
+ bValidEntries = TRUE;
+ }
+ }
+ return bValidEntries;
+}
+
+void Menu::SetLogo( const MenuLogo& rLogo )
+{
+ delete pLogo;
+ pLogo = new MenuLogo( rLogo );
+}
+
+void Menu::SetLogo()
+{
+ delete pLogo;
+ pLogo = NULL;
+}
+
+MenuLogo Menu::GetLogo() const
+{
+ MenuLogo aLogo;
+ if ( pLogo )
+ aLogo = *pLogo;
+ return aLogo;
+}
+
+void Menu::GetAccessObject( AccessObjectRef& rAcc ) const
+{
+ rAcc = new AccessObject( (void*) this, bIsMenuBar? ACCESS_TYPE_MENUBAR : ACCESS_TYPE_MENU );
+}
+
+// -----------
+// - MenuBar -
+// -----------
+
+MenuBar::MenuBar()
+{
+ bIsMenuBar = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+}
+
+MenuBar::MenuBar( const MenuBar& rMenu )
+{
+ bIsMenuBar = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+ *this = rMenu;
+ bIsMenuBar = TRUE;
+}
+
+MenuBar::MenuBar( const ResId& rResId )
+{
+ bIsMenuBar = TRUE;
+ mbCloserVisible = FALSE;
+ mbFloatBtnVisible = FALSE;
+ mbHideBtnVisible = FALSE;
+ ImplLoadRes( rResId );
+}
+
+MenuBar::~MenuBar()
+{
+ ImplDestroy( this, TRUE );
+}
+
+void MenuBar::ShowCloser( BOOL bShow )
+{
+ ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
+}
+
+void MenuBar::ShowFloatButton( BOOL bShow )
+{
+ ShowButtons( mbCloserVisible, bShow, mbHideBtnVisible );
+}
+
+void MenuBar::ShowHideButton( BOOL bShow )
+{
+ ShowButtons( mbCloserVisible, mbFloatBtnVisible, bShow );
+}
+
+void MenuBar::ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide )
+{
+ if ( (bClose != mbCloserVisible) ||
+ (bFloat != mbFloatBtnVisible) ||
+ (bHide != mbHideBtnVisible) )
+ {
+ mbCloserVisible = bClose;
+ mbFloatBtnVisible = bFloat;
+ mbHideBtnVisible = bHide;
+ if ( ImplGetWindow() )
+ ((MenuBarWindow*)ImplGetWindow())->ShowButtons( bClose, bFloat, bHide );
+ }
+}
+
+Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
+{
+ if ( !pWindow )
+ pWindow = new MenuBarWindow( pParent );
+
+ pMenu->pStartedFrom = 0;
+ pMenu->pWindow = pWindow;
+ ((MenuBarWindow*)pWindow)->SetMenu( pMenu );
+ long nHeight = pMenu->ImplCalcSize( pWindow ).Height();
+ pWindow->SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
+ return pWindow;
+}
+
+void MenuBar::ImplDestroy( MenuBar* pMenu, BOOL bDelete )
+{
+ MenuBarWindow* pWindow = (MenuBarWindow*) pMenu->ImplGetWindow();
+ if ( pWindow && bDelete )
+ {
+ pWindow->KillActivePopup();
+ delete pWindow;
+ }
+ pMenu->pWindow = NULL;
+}
+
+BOOL MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu )
+{
+ BOOL bDone = FALSE;
+ // Enabled-Abfragen, falls diese Methode von einem anderen Fenster gerufen wurde...
+ Window* pWin = ImplGetWindow();
+ if ( pWin && pWin->IsEnabled() && pWin->IsInputEnabled() )
+ bDone = ((MenuBarWindow*)pWin)->ImplHandleKeyEvent( rKEvent, bFromMenu );
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+void MenuBar::SelectEntry( USHORT nId )
+{
+ if( ImplGetWindow() )
+ {
+ MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
+
+ pMenuWin->GrabFocus();
+ nId = GetItemPos( nId );
+
+ if( ITEMPOS_INVALID == pMenuWin->nHighlightedItem )
+ {
+ if( ( nId != ITEMPOS_INVALID ) && ( nId != pMenuWin->nHighlightedItem ) )
+ pMenuWin->ChangeHighlightItem( nId, FALSE );
+ }
+ else
+ {
+ pMenuWin->KillActivePopup();
+ pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+ }
+}
+
+// BOOL PopupMenu::bAnyPopupInExecute = FALSE;
+
+PopupMenu::PopupMenu()
+{
+}
+
+PopupMenu::PopupMenu( const ResId& rResId )
+{
+ ImplLoadRes( rResId );
+}
+
+PopupMenu::PopupMenu( const PopupMenu& rMenu )
+{
+ *this = rMenu;
+}
+
+PopupMenu::~PopupMenu()
+{
+}
+
+BOOL PopupMenu::IsInExecute()
+{
+ return GetActivePopupMenu() ? TRUE : FALSE;
+}
+
+PopupMenu* PopupMenu::GetActivePopupMenu()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ return pSVData->maAppData.mpActivePopupMenu;
+}
+
+void PopupMenu::EndExecute( USHORT nSelectId )
+{
+ if ( ImplGetWindow() )
+ ImplGetFloatingWindow()->EndExecute( nSelectId );
+}
+
+void PopupMenu::SelectEntry( USHORT nId )
+{
+ if ( ImplGetWindow() )
+ {
+ USHORT nPos;
+ MenuItemData* pData = GetItemList()->GetData( nId, nPos );
+ if ( pData->pSubMenu )
+ ImplGetFloatingWindow()->ChangeHighlightItem( nPos, TRUE );
+ else
+ ImplGetFloatingWindow()->EndExecute( nId );
+ }
+}
+
+USHORT PopupMenu::Execute( Window* pWindow, const Point& rPopupPos )
+{
+ return Execute( pWindow, Rectangle( rPopupPos, rPopupPos ), POPUPMENU_EXECUTE_DOWN );
+}
+
+USHORT PopupMenu::Execute( Window* pWindow, const Rectangle& rRect, USHORT nFlags )
+{
+ ULONG nPopupModeFlags = 0;
+ if ( nFlags & POPUPMENU_EXECUTE_DOWN )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
+ else if ( nFlags & POPUPMENU_EXECUTE_UP )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_UP;
+ else if ( nFlags & POPUPMENU_EXECUTE_LEFT )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_LEFT;
+ else if ( nFlags & POPUPMENU_EXECUTE_RIGHT )
+ nPopupModeFlags = FLOATWIN_POPUPMODE_RIGHT;
+ else
+ nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
+ return ImplExecute( pWindow, rRect, nPopupModeFlags, 0, FALSE );
+}
+
+USHORT PopupMenu::ImplExecute( Window* pW, const Rectangle& rRect, ULONG nPopupModeFlags, Menu* pSFrom, BOOL bPreSelectFirst )
+{
+ // #59614# Mit TH abgesprochen dass die ASSERTION raus kommt,
+ // weil es evtl. legitim ist...
+// DBG_ASSERT( !PopupMenu::IsInExecute() || pSFrom, "PopupMenu::Execute() called in PopupMenu::Execute()" );
+
+ if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
+ return 0;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pStartedFrom = pSFrom;
+ nSelectedId = 0;
+ bCanceled = FALSE;
+
+ ULONG nFocusId = 0;
+ BOOL bRealExecute = FALSE;
+ if ( !pStartedFrom )
+ {
+ pSVData->maWinData.mbNoDeactivate = TRUE;
+ nFocusId = Window::SaveFocus();
+ bRealExecute = TRUE;
+ }
+
+ DBG_ASSERT( !ImplGetWindow(), "Win?!" );
+ Rectangle aRect( rRect );
+ aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
+
+ WinBits nStyle = WB_BORDER;
+ if ( bRealExecute )
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_NEWLEVEL;
+ if ( !pStartedFrom || !pStartedFrom->bIsMenuBar )
+ nPopupModeFlags |= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK | FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE;
+
+ // Kann beim Debuggen hilfreich sein.
+ // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
+
+ ImplDelData aDelData;
+ pW->ImplAddDel( &aDelData );
+
+ bInCallback = TRUE; // hier schon setzen, falls Activate ueberladen
+ Activate();
+ bInCallback = FALSE;
+
+ if ( aDelData.IsDelete() )
+ return 0; // Error
+
+ pW->ImplRemoveDel( &aDelData );
+
+ if ( bCanceled || bKilled )
+ return 0;
+
+ if ( !GetItemCount() )
+ return 0;
+
+ // Das Flag MENU_FLAG_HIDEDISABLEDENTRIES wird vererbt.
+ if ( pSFrom )
+ {
+ if ( pSFrom->nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES )
+ nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
+ else
+ nMenuFlags &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
+ }
+
+ USHORT nVisibleEntries = ImplGetVisibleItemCount();
+ if ( !nVisibleEntries )
+ {
+ String aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, ImplGetResMgr() ) );
+ MenuItemData* pData = pItemList->Insert(
+ 0xFFFF, MENUITEM_STRING, 0, aTmpEntryText, Image(), NULL, 0xFFFF );
+ pData->bIsTemporary = TRUE;
+ }
+ else if ( pSVData->maAppData.mbAutoMnemonics && !( nMenuFlags & MENU_FLAG_NOAUTOMNEMONICS ) )
+ {
+ ImplMnemonicGenerator aMnemonicGenerator;
+ ULONG n;
+ for ( n = 0; n < pItemList->Count(); n++ )
+ aMnemonicGenerator.RegisterMnemonic( pItemList->GetDataFromPos(n)->aText );
+ for ( n = 0; n < pItemList->Count(); n++ )
+ aMnemonicGenerator.CreateMnemonic( pItemList->GetDataFromPos(n)->aText );
+ }
+
+ MenuFloatingWindow* pWin = new MenuFloatingWindow( this, pW, nStyle );
+ pWindow = pWin;
+
+ Size aSz = ImplCalcSize( pWin );
+
+ long nMaxHeight = pWin->GetDesktopRectPixel().GetHeight();
+ if ( pStartedFrom && pStartedFrom->bIsMenuBar )
+ nMaxHeight -= pW->GetSizePixel().Height();
+ long nLeft, nTop, nRight, nBottom;
+ pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
+ nMaxHeight -= nTop+nBottom;
+ if ( aSz.Height() > nMaxHeight )
+ {
+ pWin->EnableScrollMenu( TRUE );
+ USHORT nEntries = ImplCalcVisEntries( nMaxHeight );
+ aSz.Height() = ImplCalcHeight( nEntries );
+ }
+
+ pWin->SetFocusId( nFocusId );
+ pWin->SetOutputSizePixel( aSz );
+ pWin->GrabFocus();
+ if ( GetItemCount() )
+ {
+ pWin->StartPopupMode( aRect, nPopupModeFlags );
+ }
+ if ( bPreSelectFirst )
+ {
+ USHORT nCount = (USHORT)pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ if ( ( pData->eType != MENUITEM_SEPARATOR ) && ImplIsVisible( n ) )
+ {
+ pWin->ChangeHighlightItem( n, FALSE );
+ break;
+ }
+ }
+ }
+ if ( bRealExecute )
+ {
+ pWin->Execute();
+
+ // Focus wieder herstellen (kann schon im Select wieder
+ // hergestellt wurden sein
+ nFocusId = pWin->GetFocusId();
+ if ( nFocusId )
+ {
+ pWin->SetFocusId( 0 );
+ pSVData->maWinData.mbNoDeactivate = FALSE;
+ }
+ pWin->ImplEndPopupMode( 0, nFocusId );
+
+ if ( nSelectedId ) // Dann abraeumen... ( sonst macht TH das )
+ {
+ PopupMenu* pSub = pWin->GetActivePopup();
+ while ( pSub )
+ {
+ pSub->ImplGetFloatingWindow()->EndPopupMode();
+ pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
+ }
+ }
+ delete pWindow;
+ pWindow = NULL;
+
+ // Steht noch ein Select aus?
+ Menu* pSelect = ImplFindSelectMenu();
+ if ( pSelect )
+ {
+ // Beim Popup-Menu muss das Select vor dem Verlassen von Execute gerufen werden!
+ Application::RemoveUserEvent( pSelect->nEventId );
+ pSelect->nEventId = 0;
+ pSelect->Select();
+ }
+ }
+
+ return bRealExecute ? nSelectedId : 0;
+}
+
+USHORT PopupMenu::ImplCalcVisEntries( long nMaxHeight, USHORT nStartEntry ) const
+{
+ nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
+
+ long nHeight = 0;
+ USHORT nEntries = (USHORT) pItemList->Count();
+ USHORT nVisEntries = 0;
+ for ( USHORT n = nStartEntry; n < nEntries; n++ )
+ {
+ if ( ImplIsVisible( n ) )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ nHeight += pData->aSz.Height();
+ if ( nHeight > nMaxHeight )
+ break;
+ nVisEntries++;
+ }
+ }
+ return nVisEntries;
+}
+
+long PopupMenu::ImplCalcHeight( USHORT nEntries ) const
+{
+ long nHeight = 0;
+
+ if ( nEntries > pItemList->Count() )
+ nEntries = (USHORT) pItemList->Count();
+
+ for ( ULONG n = 0; n < nEntries; n++ )
+ {
+ MenuItemData* pData = pItemList->GetDataFromPos( n );
+ nHeight += pData->aSz.Height();
+ }
+
+ nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
+
+ return nHeight;
+}
+
+
+static void ImplInitMenuWindow( Window* pWin, BOOL bFont )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ pWin->SetPointFont( rStyleSettings.GetMenuFont() );
+ pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
+ pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
+ pWin->SetTextFillColor();
+ pWin->SetLineColor();
+}
+
+MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, Window* pParent, WinBits nStyle ) :
+ FloatingWindow( pParent, nStyle )
+{
+ pMenu = pMen;
+ pActivePopup = 0;
+ nSaveFocusId = 0;
+ bInExecute = FALSE;
+ bScrollMenu = FALSE;
+ nHighlightedItem = ITEMPOS_INVALID;
+ nMBDownPos = ITEMPOS_INVALID;
+ nScrollerHeight = 0;
+ nStartY = 0;
+ nBorder = EXTRASPACEY;
+ nFirstEntry = 0;
+ bScrollUp = FALSE;
+ bScrollDown = FALSE;
+
+ EnableSaveBackground();
+ ImplInitMenuWindow( this, TRUE );
+
+ SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
+
+ aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
+ aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
+ aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
+
+ if ( Application::GetAccessHdlCount() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_POPUPMENU_START, pMenu ) );
+}
+
+MenuFloatingWindow::~MenuFloatingWindow()
+{
+ if( Application::GetAccessHdlCount() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_POPUPMENU_END, pMenu ) );
+
+ aHighlightChangedTimer.Stop();
+}
+
+void MenuFloatingWindow::Resize()
+{
+ ImplInitClipRegion();
+}
+
+Region MenuFloatingWindow::ImplCalcClipRegion( BOOL bIncludeLogo ) const
+{
+ Size aOutSz = GetOutputSizePixel();
+ Point aPos;
+ Rectangle aRect( aPos, aOutSz );
+ long nBorder = nScrollerHeight;
+ aRect.Top() += nBorder;
+ aRect.Bottom() -= nBorder;
+
+ if ( pMenu->pLogo && !bIncludeLogo )
+ aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
+
+ Region aRegion = aRect;
+ if ( pMenu->pLogo && bIncludeLogo && nScrollerHeight )
+ aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
+
+ return aRegion;
+}
+
+void MenuFloatingWindow::ImplInitClipRegion()
+{
+ if ( IsScrollMenu() )
+ {
+ SetClipRegion( ImplCalcClipRegion() );
+ }
+ else
+ {
+ SetClipRegion();
+ }
+}
+
+void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, BOOL bMBDown )
+{
+ long nY = nScrollerHeight;
+ long nMouseY = rMEvt.GetPosPixel().Y();
+ Size aOutSz = GetOutputSizePixel();
+ if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() - nY ) ) )
+ {
+ BOOL bHighlighted = FALSE;
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ nY += nStartY; // ggf. gescrollt.
+ for ( USHORT n = 0; !bHighlighted && ( n < nCount ); n++ )
+ {
+ if ( pMenu->ImplIsVisible( n ) )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ long nOldY = nY;
+ nY += pData->aSz.Height();
+ if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) )
+ {
+ BOOL bPopupArea = TRUE;
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ // Nur wenn ueber dem Pfeil geklickt wurde...
+ Size aSz = GetOutputSizePixel();
+ long nFontHeight = GetTextHeight();
+ bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
+ }
+
+ if ( bMBDown )
+ {
+ if ( n != nHighlightedItem )
+ ChangeHighlightItem( (USHORT)n, FALSE );
+
+ if ( pActivePopup )
+ KillActivePopup();
+ else if ( bPopupArea )
+ HighlightChanged( NULL );
+ }
+ else
+ {
+ if ( n != nHighlightedItem )
+ {
+ ChangeHighlightItem( (USHORT)n, TRUE );
+ }
+ else if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ if ( bPopupArea && ( pActivePopup != pData->pSubMenu ) )
+ HighlightChanged( NULL );
+ }
+ }
+ bHighlighted = TRUE;
+ }
+ }
+ }
+ if ( !bHighlighted )
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+ }
+ else
+ {
+ ImplScroll( rMEvt.GetPosPixel() );
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+ }
+}
+
+IMPL_LINK( MenuFloatingWindow, PopupEnd, FloatingWindow*, pPopup )
+{
+ if ( bInExecute )
+ {
+ if ( pActivePopup )
+ {
+ DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
+ pActivePopup->bCanceled = TRUE;
+ }
+ bInExecute = FALSE;
+ pMenu->bInCallback = TRUE;
+ pMenu->Deactivate();
+ pMenu->bInCallback = FALSE;
+ }
+ else
+ {
+ // Wenn dies Fenster von TH geschlossen wurde, hat noch ein anderes
+ // Menu dieses Fenster als pActivePopup.
+ if ( pMenu->pStartedFrom )
+ {
+ // Das pWin am 'Parent' kann aber schon 0 sein, falls die Kette von
+ // vorne abgeraeumt wurde und jetzt die EndPopup-Events eintrudeln
+ if ( pMenu->pStartedFrom->bIsMenuBar )
+ {
+ MenuBarWindow* p = (MenuBarWindow*) pMenu->pStartedFrom->ImplGetWindow();
+ if ( p )
+ p->PopupClosed( pMenu );
+ }
+ else
+ {
+ MenuFloatingWindow* p = (MenuFloatingWindow*) pMenu->pStartedFrom->ImplGetWindow();
+ if ( p )
+ p->KillActivePopup( (PopupMenu*)pMenu );
+ }
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( MenuFloatingWindow, AutoScroll, Timer*, EMPTYARG )
+{
+ ImplScroll( GetPointerPosPixel() );
+ return 1;
+}
+
+IMPL_LINK( MenuFloatingWindow, HighlightChanged, Timer*, pTimer )
+{
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+ if ( pData )
+ {
+ if ( pActivePopup && ( pActivePopup != pData->pSubMenu ) )
+ {
+ KillActivePopup();
+ }
+ if ( pData->bEnabled && pData->pSubMenu && pData->pSubMenu->GetItemCount() && ( pData->pSubMenu != pActivePopup ) )
+ {
+ pActivePopup = (PopupMenu*)pData->pSubMenu;
+ long nY = nScrollerHeight+nStartY;
+ MenuItemData* pData = 0;
+ for ( ULONG n = 0; n < nHighlightedItem; n++ )
+ {
+ pData = pMenu->pItemList->GetDataFromPos( n );
+ nY += pData->aSz.Height();
+ }
+ pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+ Size MySize = GetOutputSizePixel();
+// Point MyPos = GetPosPixel();
+// Point aItemTopLeft( MyPos.X(), MyPos.Y()+nY );
+ Point aItemTopLeft( 0, nY );
+ Point aItemBottomRight( aItemTopLeft );
+ aItemBottomRight.X() += MySize.Width();
+ aItemBottomRight.Y() += pData->aSz.Height();
+
+ // Popups leicht versetzen:
+ aItemTopLeft.X() += 2;
+ aItemBottomRight.X() -= 2;
+ if ( nHighlightedItem )
+ aItemTopLeft.Y() -= 2;
+ else
+ {
+ long nL, nT, nR, nB;
+ GetBorder( nL, nT, nR, nB );
+ aItemTopLeft.Y() -= nT;
+ }
+
+ // pTest: Wegen Abstuerzen durch Reschedule() im Aufruf von Activate()
+ // Ausserdem wird damit auch verhindert, dass SubMenus angezeigt werden,
+ // die lange im Activate Rescheduled haben und jetzt schon nicht mehr
+ // angezeigt werden sollen.
+ Menu* pTest = pActivePopup;
+ USHORT nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_RIGHT, pMenu, pTimer ? FALSE : TRUE );
+
+ // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
+ if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
+ pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
+ }
+ }
+
+ return 0;
+}
+
+void MenuFloatingWindow::EnableScrollMenu( BOOL b )
+{
+ bScrollMenu = b;
+ nScrollerHeight = b ? (USHORT) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
+ bScrollDown = TRUE;
+ ImplInitClipRegion();
+}
+
+void MenuFloatingWindow::Execute()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pSVData->maAppData.mpActivePopupMenu = (PopupMenu*)pMenu;
+
+ bInExecute = TRUE;
+// bCallingSelect = FALSE;
+
+ while ( bInExecute )
+ Application::Yield();
+
+ pSVData->maAppData.mpActivePopupMenu = NULL;
+
+// while ( bCallingSelect )
+// Application::Yield();
+}
+
+void MenuFloatingWindow::StopExecute( ULONG nFocusId )
+{
+ // Focus wieder herstellen
+ // (kann schon im Select wieder hergestellt wurden sein)
+ if ( nSaveFocusId )
+ {
+ Window::EndSaveFocus( nFocusId, FALSE );
+ nFocusId = nSaveFocusId;
+ if ( nFocusId )
+ {
+ nSaveFocusId = 0;
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ }
+ }
+ ImplEndPopupMode( 0, nFocusId );
+
+ aHighlightChangedTimer.Stop();
+ bInExecute = FALSE;
+ if ( pActivePopup )
+ {
+ KillActivePopup();
+ }
+}
+
+void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
+{
+ if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
+ {
+ if ( pActivePopup->bInCallback )
+ pActivePopup->bCanceled = TRUE;
+
+ // Vor allen Aktionen schon pActivePopup = 0, falls z.B.
+ // PopupModeEndHdl des zu zerstoerenden Popups mal synchron gerufen wird.
+ PopupMenu* pPopup = pActivePopup;
+ pActivePopup = NULL;
+ pPopup->bInCallback = TRUE;
+ pPopup->Deactivate();
+ pPopup->bInCallback = FALSE;
+ if ( pPopup->ImplGetWindow() )
+ {
+ pPopup->ImplGetFloatingWindow()->StopExecute();
+ delete pPopup->pWindow;
+ pPopup->pWindow = NULL;
+ Update();
+ }
+ }
+}
+
+void MenuFloatingWindow::EndExecute()
+{
+ Menu* pStart = pMenu->ImplGetStartMenu();
+ ULONG nFocusId = 0;
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ nFocusId = ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->GetFocusId();
+ if ( nFocusId )
+ {
+ ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->SetFocusId( 0 );
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ }
+ }
+ // Wenn von woanders gestartet, dann ab dort aufraumen:
+ MenuFloatingWindow* pCleanUpFrom = this;
+ MenuFloatingWindow* pWin = this;
+ while ( pWin && !pWin->bInExecute &&
+ pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->bIsMenuBar )
+ {
+ pWin = ((PopupMenu*)pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
+ }
+ if ( pWin )
+ pCleanUpFrom = pWin;
+
+ // Dies Fenster wird gleich zerstoert => Daten lokal merken...
+ Menu* pM = pMenu;
+ USHORT nItem = nHighlightedItem;
+
+ pCleanUpFrom->StopExecute( nFocusId );
+
+ if ( nItem != ITEMPOS_INVALID )
+ {
+ MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
+ if ( pItemData && !pItemData->bIsTemporary )
+ {
+ pM->nSelectedId = pItemData->nId;
+ if ( pStart )
+ pStart->nSelectedId = pItemData->nId;
+
+ pM->ImplSelect();
+ }
+ }
+}
+
+void MenuFloatingWindow::EndExecute( USHORT nId )
+{
+ USHORT nPos;
+ if ( pMenu->GetItemList()->GetData( nId, nPos ) )
+ nHighlightedItem = nPos;
+ else
+ nHighlightedItem = ITEMPOS_INVALID;
+
+ EndExecute();
+}
+
+void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // TH macht ein ToTop auf dieses Fenster, aber das aktive Popup
+ // soll oben bleiben...
+ if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
+ pActivePopup->ImplGetFloatingWindow()->ToTop();
+
+ if ( !ImplIsMouseFollow() )
+ {
+ ImplHighlightItem( rMEvt, TRUE );
+ }
+
+ nMBDownPos = nHighlightedItem;
+}
+
+void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ // nMBDownPos in lokaler Variable merken und gleich zuruecksetzen,
+ // weil nach EndExecute zu spaet
+ USHORT _nMBDownPos = nMBDownPos;
+ nMBDownPos = ITEMPOS_INVALID;
+ if ( pData && pData->bEnabled && ( pData->eType != MENUITEM_SEPARATOR ) )
+ {
+ if ( !pData->pSubMenu )
+ {
+ EndExecute();
+ }
+ else if ( ( pData->nBits & MIB_POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
+ {
+ // Nicht wenn ueber dem Pfeil geklickt wurde...
+ Size aSz = GetOutputSizePixel();
+ long nFontHeight = GetTextHeight();
+ if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
+ EndExecute();
+ }
+ }
+
+}
+
+void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !IsVisible() || rMEvt.IsSynthetic() )
+ return;
+
+ if ( rMEvt.IsLeaveWindow() )
+ {
+ if ( ImplIsMouseFollow() || ( rMEvt.GetButtons() == MOUSE_LEFT ) )
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ if ( IsScrollMenu() )
+ ImplScroll( rMEvt.GetPosPixel() );
+ }
+ else if ( ImplIsMouseFollow() || ( rMEvt.GetButtons() == MOUSE_LEFT ) )
+ {
+ ImplHighlightItem( rMEvt, FALSE );
+ }
+}
+
+void MenuFloatingWindow::ImplScroll( BOOL bUp )
+{
+ KillActivePopup();
+ Update();
+
+ HighlightItem( nHighlightedItem, FALSE );
+
+ if ( bScrollUp && bUp )
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( --nFirstEntry );
+ long nEntryHeight = pData->aSz.Height();
+
+ nStartY += nEntryHeight;
+
+ if ( !bScrollDown )
+ {
+ bScrollDown = TRUE;
+ ImplDrawScroller( FALSE );
+ }
+
+ if ( nFirstEntry == 0 )
+ {
+ bScrollUp = FALSE;
+ ImplDrawScroller( TRUE );
+ }
+ Scroll( 0, nEntryHeight, ImplCalcClipRegion( FALSE ).GetBoundRect(), SCROLL_CLIP );
+ }
+ else if ( bScrollDown && !bUp )
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nFirstEntry++ );
+ long nEntryHeight = pData->aSz.Height();
+
+ if ( !bScrollUp )
+ {
+ bScrollUp = TRUE;
+ ImplDrawScroller( TRUE );
+ }
+
+ Size aOutSz = GetOutputSizePixel();
+ USHORT nVisible = ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry );
+ if ( ( nFirstEntry + nVisible ) >= (USHORT) pMenu->GetItemList()->Count() )
+ {
+ bScrollDown = FALSE;
+ ImplDrawScroller( FALSE );
+ }
+
+ nStartY -= nEntryHeight;
+ Scroll( 0, -nEntryHeight, ImplCalcClipRegion( FALSE ).GetBoundRect(), SCROLL_CLIP );
+ }
+
+ HighlightItem( nHighlightedItem, TRUE );
+}
+
+void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
+{
+ Size aOutSz = GetOutputSizePixel();
+
+ long nY = nScrollerHeight;
+ long nMouseY = rMousePos.Y();
+ long nDelta = 0;
+
+ if ( bScrollUp && ( nMouseY < nY ) )
+ {
+ ImplScroll( TRUE );
+ nDelta = nY - nMouseY;
+ }
+ else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
+ {
+ ImplScroll( FALSE );
+ nDelta = nMouseY - ( aOutSz.Height() - nY );
+ }
+
+ if ( nDelta )
+ {
+ aScrollTimer.Stop(); // Falls durch MouseMove gescrollt.
+ long nTimeout;
+ if ( nDelta < 3 )
+ nTimeout = 200;
+ else if ( nDelta < 5 )
+ nTimeout = 100;
+ else if ( nDelta < 8 )
+ nTimeout = 70;
+ else if ( nDelta < 12 )
+ nTimeout = 40;
+ else
+ nTimeout = 20;
+ aScrollTimer.SetTimeout( nTimeout );
+ aScrollTimer.Start();
+ }
+}
+void MenuFloatingWindow::ChangeHighlightItem( USHORT n, BOOL bStartPopupTimer )
+{
+ // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
+ // #65750# Dann verzichten wir lieber auf den schmalen Streifen Hintergrundsicherung.
+ // Sonst lassen sich die Menus schlecht bedienen.
+// MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
+// if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
+// KillActivePopup();
+
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, FALSE );
+
+ nHighlightedItem = (USHORT)n;
+ DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
+ HighlightItem( nHighlightedItem, TRUE );
+ pMenu->ImplCallHighlight( nHighlightedItem );
+
+ if ( bStartPopupTimer )
+ aHighlightChangedTimer.Start();
+}
+
+void MenuFloatingWindow::HighlightItem( USHORT nPos, BOOL bHighlight )
+{
+ Size aSz = GetOutputSizePixel();
+ USHORT nBorder = nScrollerHeight;
+ long nY = nBorder+nStartY;
+ long nX = 0;
+
+ if ( pMenu->pLogo )
+ nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
+
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ DBG_ASSERT( pMenu->ImplIsVisible( n ), "Highlight: Item not visible!" );
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ if ( bHighlight )
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ else
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+
+ Rectangle aRect( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
+ if ( pData->nBits & MIB_POPUPSELECT )
+ {
+ long nFontHeight = GetTextHeight();
+ aRect.Right() -= nFontHeight + nFontHeight/4;
+ }
+ DrawRect( aRect );
+ pMenu->ImplPaint( this, nBorder, nStartY, pData, bHighlight );
+ }
+ return;
+ }
+
+ nY += pData->aSz.Height();
+ }
+}
+
+void MenuFloatingWindow::ImplCursorUpDown( BOOL bUp )
+{
+ USHORT n = nHighlightedItem;
+ if ( n == ITEMPOS_INVALID )
+ {
+ if ( bUp )
+ n = 0;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+
+ USHORT nLoop = n;
+ do
+ {
+ if ( bUp )
+ {
+ if ( n )
+ n--;
+ else
+ if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ n = pMenu->GetItemCount()-1;
+ else
+ break;
+ }
+ else
+ {
+ n++;
+ if ( n >= pMenu->GetItemCount() )
+ if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ n = 0;
+ else
+ break;
+ }
+
+ MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
+ if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
+ {
+ // Selektion noch im sichtbaren Bereich?
+ if ( IsScrollMenu() )
+ {
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+
+ while ( n < nFirstEntry )
+ ImplScroll( TRUE );
+
+ Size aOutSz = GetOutputSizePixel();
+ while ( n >= ( nFirstEntry + ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry ) ) )
+ ImplScroll( FALSE );
+ }
+ ChangeHighlightItem( n, FALSE );
+ break;
+ }
+ } while ( n != nLoop );
+}
+
+void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
+{
+ USHORT nCode = rKEvent.GetKeyCode().GetCode();
+ switch ( nCode )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ {
+ ImplCursorUpDown( nCode == KEY_UP );
+ }
+ break;
+ case KEY_LEFT:
+ {
+ if ( pMenu->pStartedFrom )
+ {
+ StopExecute();
+ if ( pMenu->pStartedFrom->bIsMenuBar )
+ {
+ // Weiterkeiten...
+ ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
+ }
+ else
+ {
+ MenuFloatingWindow* pFloat = ((PopupMenu*)pMenu->pStartedFrom)->ImplGetFloatingWindow();
+ pFloat->GrabFocus();
+ pFloat->KillActivePopup();
+ }
+ }
+ }
+ break;
+ case KEY_RIGHT:
+ {
+ BOOL bDone = FALSE;
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pData && pData->pSubMenu )
+ {
+ HighlightChanged( 0 );
+ bDone = TRUE;
+ }
+ }
+ if ( !bDone )
+ {
+ Menu* pStart = pMenu->ImplGetStartMenu();
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ // Weiterkeiten...
+ pStart->ImplGetWindow()->KeyInput( rKEvent );
+ }
+ }
+ }
+ break;
+ case KEY_RETURN:
+ {
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pData && pData->bEnabled )
+ {
+ if ( pData->pSubMenu )
+ HighlightChanged( 0 );
+ else
+ EndExecute();
+ }
+ else
+ StopExecute();
+ }
+ break;
+ case KEY_MENU:
+ {
+ Menu* pStart = pMenu->ImplGetStartMenu();
+ if ( pStart && pStart->bIsMenuBar )
+ {
+ // Weiterkeiten...
+ pStart->ImplGetWindow()->KeyInput( rKEvent );
+ }
+ }
+ break;
+ default:
+ {
+ xub_Unicode nCharCode = rKEvent.GetCharCode();
+ USHORT nPos;
+ MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, nPos );
+ if ( pData )
+ {
+ if ( pData->pSubMenu )
+ {
+ ChangeHighlightItem( nPos, FALSE );
+ HighlightChanged( 0 );
+ }
+ else
+ {
+ nHighlightedItem = nPos;
+ EndExecute();
+ }
+ }
+ else
+ {
+ // Bei ungueltigen Tasten Beepen, aber nicht bei HELP und F-Tasten
+ if ( !rKEvent.GetKeyCode().IsControlMod() && ( nCode != KEY_HELP ) && ( rKEvent.GetKeyCode().GetGroup() != KEYGROUP_FKEYS ) )
+ Sound::Beep();
+ FloatingWindow::KeyInput( rKEvent );
+ }
+ }
+ }
+}
+
+void MenuFloatingWindow::Paint( const Rectangle& rRect )
+{
+ if ( IsScrollMenu() )
+ {
+ ImplDrawScroller( TRUE );
+ ImplDrawScroller( FALSE );
+ }
+ pMenu->ImplPaint( this, nScrollerHeight, nStartY );
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, TRUE );
+}
+
+void MenuFloatingWindow::ImplDrawScroller( BOOL bUp )
+{
+ SetClipRegion();
+
+ Size aOutSz = GetOutputSizePixel();
+ long nY = bUp ? 0 : ( aOutSz.Height() - nScrollerHeight );
+ long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
+ Rectangle aRect( Point( nX, nY ), Size( aOutSz.Width()-nX, nScrollerHeight ) );
+
+ DecorationView aDecoView( this );
+ SymbolType eSymbol = bUp ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN;
+
+ USHORT nStyle = 0;
+ if ( ( bUp && !bScrollUp ) || ( !bUp && !bScrollDown ) )
+ nStyle |= SYMBOL_DRAW_DISABLE;
+
+ aDecoView.DrawSymbol( aRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
+
+ ImplInitClipRegion();
+}
+
+void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nId = nHighlightedItem;
+ Menu* pM = pMenu;
+ Window* pW = this;
+ if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ {
+ nHighlightedItem = ITEMPOS_INVALID;
+ EndExecute();
+ pW = NULL;
+ }
+ if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt ) )
+ Window::RequestHelp( rHEvt );
+}
+
+void MenuFloatingWindow::StateChanged( StateChangedType nType )
+{
+ FloatingWindow::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
+ {
+ ImplInitMenuWindow( this, FALSE );
+ Invalidate();
+ }
+}
+
+void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ FloatingWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitMenuWindow( this, FALSE );
+ Invalidate();
+ }
+}
+
+void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
+ {
+// ImplCursorUpDown( pData->GetDelta() > 0L );
+ ImplScroll( pData->GetDelta() > 0L );
+ MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
+ }
+ }
+}
+
+
+
+MenuBarWindow::MenuBarWindow( Window* pParent ) :
+ Window( pParent, 0 ),
+ aCloser( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
+ aFloatBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
+ aHideBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE )
+{
+ pMenu = NULL;
+ pActivePopup = NULL;
+ nSaveFocusId = 0;
+ nHighlightedItem = ITEMPOS_INVALID;
+ mbAutoPopup = TRUE;
+ nSaveFocusId = 0;
+
+ ResMgr* pResMgr = ImplGetResMgr();
+ aCloser.SetClickHdl( LINK( this, MenuBarWindow, CloserHdl ) );
+ aCloser.SetSymbol( SYMBOL_CLOSE );
+ aCloser.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_CLOSE, pResMgr ) ) );
+ aFloatBtn.SetClickHdl( LINK( this, MenuBarWindow, FloatHdl ) );
+ aFloatBtn.SetSymbol( SYMBOL_FLOAT );
+ aFloatBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_RESTORE, pResMgr ) ) );
+ aHideBtn.SetClickHdl( LINK( this, MenuBarWindow, HideHdl ) );
+ aHideBtn.SetSymbol( SYMBOL_HIDE );
+ aHideBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_MINIMIZE, pResMgr ) ) );
+}
+
+MenuBarWindow::~MenuBarWindow()
+{
+}
+
+void MenuBarWindow::SetMenu( MenuBar* pMen )
+{
+ pMenu = pMen;
+ KillActivePopup();
+ nHighlightedItem = ITEMPOS_INVALID;
+ ImplInitMenuWindow( this, TRUE );
+ if ( pMen )
+ {
+ aCloser.Show( pMen->HasCloser() );
+ aFloatBtn.Show( pMen->HasFloatButton() );
+ aHideBtn.Show( pMen->HasHideButton() );
+ }
+ Invalidate();
+}
+
+void MenuBarWindow::ShowButtons( BOOL bClose, BOOL bFloat, BOOL bHide )
+{
+ aCloser.Show( bClose );
+ aFloatBtn.Show( bFloat );
+ aHideBtn.Show( bHide );
+ Resize();
+}
+
+IMPL_LINK( MenuBarWindow, CloserHdl, PushButton*, EMPTYARG )
+{
+ return ((MenuBar*)pMenu)->GetCloserHdl().Call( pMenu );
+}
+
+IMPL_LINK( MenuBarWindow, FloatHdl, PushButton*, EMPTYARG )
+{
+ return ((MenuBar*)pMenu)->GetFloatButtonClickHdl().Call( pMenu );
+}
+
+IMPL_LINK( MenuBarWindow, HideHdl, PushButton*, EMPTYARG )
+{
+ return ((MenuBar*)pMenu)->GetHideButtonClickHdl().Call( pMenu );
+}
+
+void MenuBarWindow::ImplCreatePopup( BOOL bPreSelectFirst )
+{
+ MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
+ if ( pData )
+ {
+ if ( pActivePopup && ( pActivePopup != pData->pSubMenu ) )
+ {
+ KillActivePopup();
+ }
+ if ( pData->bEnabled && pData->pSubMenu && ( nHighlightedItem != ITEMPOS_INVALID ) && ( pData->pSubMenu != pActivePopup ) )
+ {
+ pActivePopup = (PopupMenu*)pData->pSubMenu;
+ long nX = 0;
+ MenuItemData* pData = 0;
+ for ( ULONG n = 0; n < nHighlightedItem; n++ )
+ {
+ pData = pMenu->GetItemList()->GetDataFromPos( n );
+ nX += pData->aSz.Width();
+ }
+ pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
+// Point MyPos = GetPosPixel();
+ Point aItemTopLeft( nX, 0 );
+ Point aItemBottomRight( aItemTopLeft );
+ aItemBottomRight.X() += pData->aSz.Width();
+
+ // Im Vollbild-Modus hat die MenuBar ggf. die Hoehe 0:
+ // Nicht immer einfach die Window-Hoehe nehmen, weil ItemHeight < WindowHeight.
+ if ( GetSizePixel().Height() )
+ aItemBottomRight.Y() += pData->aSz.Height();
+
+ // ImplExecute ist doch nicht modal...
+ GrabFocus();
+ pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_DOWN, pMenu, bPreSelectFirst );
+ if ( pActivePopup )
+ {
+ // Hat kein Window, wenn vorher abgebrochen oder keine Eintraege
+ if ( pActivePopup->ImplGetFloatingWindow() )
+ pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
+ else
+ pActivePopup = NULL;
+ }
+ }
+ }
+}
+
+
+void MenuBarWindow::KillActivePopup()
+{
+ if ( pActivePopup )
+ {
+ if ( pActivePopup->bInCallback )
+ pActivePopup->bCanceled = TRUE;
+
+ pActivePopup->bInCallback = TRUE;
+ pActivePopup->Deactivate();
+ pActivePopup->bInCallback = FALSE;
+ // Abfrage auf pActivePopup, falls im Deactivate abgeschossen...
+ if ( pActivePopup && pActivePopup->ImplGetWindow() )
+ {
+ pActivePopup->ImplGetFloatingWindow()->StopExecute();
+ delete pActivePopup->pWindow;
+ pActivePopup->pWindow = NULL;
+ }
+ pActivePopup = 0;
+ }
+}
+
+void MenuBarWindow::PopupClosed( Menu* pPopup )
+{
+ if ( pPopup == pActivePopup )
+ {
+ KillActivePopup();
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+}
+
+void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ mbAutoPopup = TRUE;
+ USHORT nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
+ if ( ( nEntry != ITEMPOS_INVALID ) && ( nEntry != nHighlightedItem ) )
+ {
+ ChangeHighlightItem( nEntry, ImplIsMouseFollow() ? FALSE : TRUE );
+ }
+ else
+ {
+ KillActivePopup();
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ }
+}
+
+void MenuBarWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+}
+
+void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ // Im Move nur Highlighten, wenn schon eins gehighlightet.
+ if ( rMEvt.IsSynthetic() || rMEvt.IsLeaveWindow() || ( nHighlightedItem == ITEMPOS_INVALID ) )
+ return;
+
+ USHORT nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
+ if ( ( nEntry != ITEMPOS_INVALID ) && ( nEntry != nHighlightedItem )
+ && ( ImplIsMouseFollow() || ( rMEvt.GetButtons() == MOUSE_LEFT ) ) )
+ ChangeHighlightItem( nEntry, FALSE );
+}
+
+void MenuBarWindow::ChangeHighlightItem( USHORT n, BOOL bSelectEntry, BOOL bAllowRestoreFocus )
+{
+ // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
+ MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
+ if ( pActivePopup && pActivePopup->ImplGetWindow() && ( !pNextData || ( pActivePopup != pNextData->pSubMenu ) ) )
+ KillActivePopup(); // pActivePopup ggf. ohne pWin, wenn in Activate() Rescheduled wurde
+
+ // Activate am MenuBar immer nur einmal pro Vorgang...
+ BOOL bJustActivated = FALSE;
+ if ( ( nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
+ {
+ ImplGetSVData()->maWinData.mbNoDeactivate = TRUE;
+ nSaveFocusId = Window::SaveFocus();
+ pMenu->bInCallback = TRUE; // hier schon setzen, falls Activate ueberladen
+ pMenu->Activate();
+ pMenu->bInCallback = FALSE;
+ bJustActivated = TRUE;
+ }
+ else if ( ( nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
+ {
+ pMenu->bInCallback = TRUE;
+ pMenu->Deactivate();
+ pMenu->bInCallback = FALSE;
+ ULONG nTempFocusId = nSaveFocusId;
+ nSaveFocusId = 0;
+ ImplGetSVData()->maWinData.mbNoDeactivate = FALSE;
+ Window::EndSaveFocus( nTempFocusId, bAllowRestoreFocus );
+ }
+
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, FALSE );
+
+ nHighlightedItem = (USHORT)n;
+ DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
+ HighlightItem( nHighlightedItem, TRUE );
+ pMenu->ImplCallHighlight( nHighlightedItem );
+
+ if ( mbAutoPopup )
+ ImplCreatePopup( bSelectEntry );
+
+ // #58935# #73659# Focus, wenn kein Popup drunter haengt...
+ if ( bJustActivated && !pActivePopup )
+ GrabFocus();
+}
+
+void MenuBarWindow::HighlightItem( USHORT nPos, BOOL bHighlight )
+{
+ long nX = 0;
+ ULONG nCount = pMenu->pItemList->Count();
+ for ( ULONG n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( n == nPos )
+ {
+ if ( pData->eType != MENUITEM_SEPARATOR )
+ {
+ if ( bHighlight )
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ else
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+
+ DrawRect( Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), pData->aSz.Height()-2 ) ) );
+ pMenu->ImplPaint( this, 0, 0, pData, bHighlight );
+ }
+ return;
+ }
+
+ nX += pData->aSz.Width();
+ }
+}
+
+void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
+{
+ if ( !ImplHandleKeyEvent( rKEvent ) )
+ Window::KeyInput( rKEvent );
+}
+
+BOOL MenuBarWindow::ImplHandleKeyEvent( const KeyEvent& rKEvent, BOOL bFromMenu )
+{
+ if ( pMenu->bInCallback )
+ return TRUE; // schlucken
+
+ BOOL bDone = FALSE;
+ USHORT nCode = rKEvent.GetKeyCode().GetCode();
+ if ( nCode == KEY_MENU )
+ {
+ mbAutoPopup = FALSE;
+ if ( nHighlightedItem == ITEMPOS_INVALID )
+ {
+ ChangeHighlightItem( 0, FALSE );
+ GrabFocus();
+ }
+ else
+ {
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ nSaveFocusId = 0;
+ }
+ bDone = TRUE;
+ }
+ else if ( bFromMenu )
+ {
+ if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
+ {
+ USHORT n = nHighlightedItem;
+ if ( n == ITEMPOS_INVALID )
+ {
+ if ( nCode == KEY_LEFT)
+ n = 0;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+
+ USHORT nLoop = n;
+ do
+ {
+ if ( nCode == KEY_LEFT )
+ {
+ if ( n )
+ n--;
+ else
+ n = pMenu->GetItemCount()-1;
+ }
+ else
+ {
+ n++;
+ if ( n >= pMenu->GetItemCount() )
+ n = 0;
+ }
+
+ MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
+ if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
+ {
+ ChangeHighlightItem( n, TRUE );
+ break;
+ }
+ } while ( n != nLoop );
+ bDone = TRUE;
+ }
+ else if ( nCode == KEY_RETURN )
+ {
+ KillActivePopup();
+ bDone = TRUE;
+ }
+ else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
+ {
+ if ( !mbAutoPopup )
+ {
+ ImplCreatePopup( TRUE );
+ mbAutoPopup = TRUE;
+ }
+ bDone = TRUE;
+ }
+ else if ( nCode == KEY_ESCAPE)
+ {
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE );
+ bDone = TRUE;
+ }
+ }
+
+ if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsControlMod() ) )
+ {
+ xub_Unicode nCharCode = rKEvent.GetCharCode();
+ if ( nCharCode )
+ {
+ USHORT nEntry;
+ MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, nEntry );
+ if ( pData && (nEntry != ITEMPOS_INVALID) )
+ {
+ mbAutoPopup = TRUE;
+ ChangeHighlightItem( nEntry, TRUE );
+ bDone = TRUE;
+ }
+ else
+ {
+ // Wegen Systemmenu und anderen System-HotKeys, nur
+ // eigenstaendige Character-Kombinationen auswerten
+ USHORT nKeyCode = rKEvent.GetKeyCode().GetCode();
+ if ( !nKeyCode ||
+ ((nKeyCode >= KEY_A) && (nKeyCode <= KEY_Z)) )
+ Sound::Beep();
+ }
+ }
+ }
+ return bDone;
+}
+
+void MenuBarWindow::Paint( const Rectangle& rRect )
+{
+ pMenu->ImplPaint( this, 0 );
+ if ( nHighlightedItem != ITEMPOS_INVALID )
+ HighlightItem( nHighlightedItem, TRUE );
+}
+
+void MenuBarWindow::Resize()
+{
+ Size aOutSz = GetOutputSizePixel();
+ long n = aOutSz.Height()-4;
+ long nX = aOutSz.Width()-3;
+ long nY = 2;
+
+ ULONG nStyle = GetSettings().GetStyleSettings().GetOptions();
+ if ( nStyle & (STYLE_OPTION_OS2STYLE | STYLE_OPTION_UNIXSTYLE | STYLE_OPTION_MACSTYLE) )
+ {
+ if ( nStyle & STYLE_OPTION_OS2STYLE )
+ {
+ nX += 3;
+ nY -= 2;
+ n += 4;
+ }
+
+ if ( aFloatBtn.IsVisible() )
+ {
+ nX -= n;
+ aFloatBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+ if ( aHideBtn.IsVisible() )
+ {
+ nX -= n;
+ aHideBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+ if ( nStyle & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE) )
+ {
+ if ( aFloatBtn.IsVisible() || aHideBtn.IsVisible() )
+ nX -= 3;
+ }
+ if ( aCloser.IsVisible() )
+ {
+ nX -= n;
+ aCloser.SetPosSizePixel( nX, nY, n, n );
+ }
+ }
+ else
+ {
+ if ( aCloser.IsVisible() )
+ {
+ nX -= n;
+ aCloser.SetPosSizePixel( nX, nY, n, n );
+ nX -= 3;
+ }
+ if ( aFloatBtn.IsVisible() )
+ {
+ nX -= n;
+ aFloatBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+ if ( aHideBtn.IsVisible() )
+ {
+ nX -= n;
+ aHideBtn.SetPosSizePixel( nX, nY, n, n );
+ }
+ }
+
+ if ( nStyle & STYLE_OPTION_OS2STYLE )
+ aFloatBtn.SetSymbol( SYMBOL_OS2FLOAT );
+ else
+ aFloatBtn.SetSymbol( SYMBOL_FLOAT );
+ if ( nStyle & STYLE_OPTION_OS2STYLE )
+ aHideBtn.SetSymbol( SYMBOL_OS2HIDE );
+ else
+ aHideBtn.SetSymbol( SYMBOL_HIDE );
+ if ( nStyle & STYLE_OPTION_OS2STYLE )
+ aCloser.SetSymbol( SYMBOL_OS2CLOSE );
+ else
+ aCloser.SetSymbol( SYMBOL_CLOSE );
+}
+
+USHORT MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
+{
+ long nX = 0;
+ USHORT nCount = (USHORT)pMenu->pItemList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
+ if ( pMenu->ImplIsVisible( n ) )
+ {
+ nX += pData->aSz.Width();
+ if ( nX > rMousePos.X() )
+ return (USHORT)n;
+ }
+ }
+ return ITEMPOS_INVALID;
+}
+
+void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nId = nHighlightedItem;
+ if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
+ ChangeHighlightItem( ITEMPOS_INVALID, TRUE );
+ if( !ImplHandleHelpEvent( this, pMenu, nId, rHEvt ) )
+ Window::RequestHelp( rHEvt );
+}
+
+BOOL MenuBarWindow::QueryDrop( DropEvent& rDEvt )
+{
+ Window* pW = GetParent()->ImplGetWindow();
+ DropEvent aEvent( ImplTranslateDropEvent( rDEvt, this, pW ) );
+ BOOL bRet = pW->QueryDrop( aEvent );
+ rDEvt = aEvent;
+ return bRet;
+}
+
+BOOL MenuBarWindow::Drop( const DropEvent& rDEvt )
+{
+ Window* pW = GetParent()->ImplGetWindow();
+ return pW->Drop( ImplTranslateDropEvent( rDEvt, this, pW ) );
+}
+
+
+void MenuBarWindow::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) ||
+ ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
+ {
+ ImplInitMenuWindow( this, FALSE );
+ Invalidate();
+ }
+}
+
+void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitMenuWindow( this, TRUE );
+ // Falls sich der Font geaendert hat.
+ long nHeight = pMenu->ImplCalcSize( this ).Height();
+ SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
+ GetParent()->Resize();
+ Invalidate();
+ Resize();
+ }
+}
+
+void MenuBarWindow::LoseFocus()
+{
+ if ( !HasChildPathFocus( TRUE ) )
+ ChangeHighlightItem( ITEMPOS_INVALID, FALSE, FALSE );
+}
diff --git a/vcl/source/window/mnemonic.cxx b/vcl/source/window/mnemonic.cxx
new file mode 100644
index 000000000000..ea1b7b0cea29
--- /dev/null
+++ b/vcl/source/window/mnemonic.cxx
@@ -0,0 +1,260 @@
+/*************************************************************************
+ *
+ * $RCSfile: mnemonic.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MNEMONIC_CXX
+
+#include <string.h>
+#include <svapp.hxx>
+#include <settings.hxx>
+#include <mnemonic.hxx>
+
+#include <unohelp.hxx>
+
+#ifndef _COM_SUN_STAR_LANG_XCHARACTERCLASSIFICATION_HPP_
+#include <com/sun/star/lang/XCharacterClassification.hpp>
+#endif
+
+using namespace ::com::sun::star;
+
+
+// =======================================================================
+
+ImplMnemonicGenerator::ImplMnemonicGenerator()
+{
+ memset( maMnemonics, 1, sizeof( maMnemonics ) );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImplMnemonicGenerator::ImplGetMnemonicIndex( sal_Unicode c )
+{
+ static USHORT const aImplMnemonicRangeTab[MNEMONIC_RANGES*2] =
+ {
+ MNEMONIC_RANGE_1_START, MNEMONIC_RANGE_1_END,
+ MNEMONIC_RANGE_2_START, MNEMONIC_RANGE_2_END,
+ MNEMONIC_RANGE_3_START, MNEMONIC_RANGE_3_END,
+ MNEMONIC_RANGE_4_START, MNEMONIC_RANGE_4_END
+ };
+
+ USHORT nMnemonicIndex = 0;
+ for ( USHORT i = 0; i < MNEMONIC_RANGES; i++ )
+ {
+ if ( (c >= aImplMnemonicRangeTab[i*2]) &&
+ (c <= aImplMnemonicRangeTab[i*2+1]) )
+ return nMnemonicIndex+c-aImplMnemonicRangeTab[i*2];
+
+ nMnemonicIndex += aImplMnemonicRangeTab[i*2+1]-aImplMnemonicRangeTab[i*2];
+ }
+
+ return MNEMONIC_INDEX_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Unicode ImplMnemonicGenerator::ImplFindMnemonic( const XubString& rKey )
+{
+ xub_StrLen nIndex = 0;
+ while ( (nIndex = rKey.Search( MNEMONIC_CHAR, nIndex )) != STRING_NOTFOUND )
+ {
+ sal_Unicode cMnemonic = rKey.GetChar( nIndex+1 );
+ if ( cMnemonic != MNEMONIC_CHAR )
+ return cMnemonic;
+ nIndex += 2;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplMnemonicGenerator::RegisterMnemonic( const XubString& rKey )
+{
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
+ uno::Reference < lang::XCharacterClassification > xCharClass = GetCharClass();
+
+ XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
+
+ // If we find a Mnemonic, set the flag. In other case count the
+ // characters, because we need this to set most as possible
+ // Mnemonics
+ sal_Unicode cMnemonic = ImplFindMnemonic( aKey );
+ if ( cMnemonic )
+ {
+ USHORT nMnemonicIndex = ImplGetMnemonicIndex( cMnemonic );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ maMnemonics[nMnemonicIndex] = 0;
+ }
+ else
+ {
+ xub_StrLen nIndex = 0;
+ xub_StrLen nLen = aKey.Len();
+ while ( nIndex < nLen )
+ {
+ sal_Unicode c = aKey.GetChar( nIndex );
+
+ USHORT nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] && (maMnemonics[nMnemonicIndex] < 0xFF) )
+ maMnemonics[nMnemonicIndex]++;
+ }
+
+ nIndex++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplMnemonicGenerator::CreateMnemonic( XubString& rKey )
+{
+ if ( !rKey.Len() || ImplFindMnemonic( rKey ) )
+ return FALSE;
+
+ const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
+ uno::Reference < lang::XCharacterClassification > xCharClass = GetCharClass();
+
+ XubString aKey = xCharClass->toUpper( rKey, 0, rKey.Len(), rLocale );
+
+ BOOL bChanged = FALSE;
+ xub_StrLen nLen = aKey.Len();
+
+ // 1) Anfangsbuchstaben werden bevorzugt
+ USHORT nMnemonicIndex;
+ sal_Unicode c;
+ xub_StrLen nIndex = 0;
+ do
+ {
+ c = aKey.GetChar( nIndex );
+ nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] )
+ {
+ maMnemonics[nMnemonicIndex] = 0;
+ rKey.Insert( MNEMONIC_CHAR, nIndex );
+ bChanged = TRUE;
+ break;
+ }
+ }
+
+ // Search for next word
+ do
+ {
+ nIndex++;
+ c = aKey.GetChar( nIndex );
+ if ( c == ' ' )
+ break;
+ }
+ while ( nIndex < nLen );
+ nIndex++;
+ }
+ while ( nIndex < nLen );
+
+ // 2) Eindeutiger/seltender Buchstabe enthalten?
+ if ( !bChanged )
+ {
+ USHORT nBestCount = 0xFFFF;
+ USHORT nBestMnemonicIndex;
+ xub_StrLen nBestIndex;
+ nIndex = 0;
+ do
+ {
+ c = aKey.GetChar( nIndex );
+ nMnemonicIndex = ImplGetMnemonicIndex( c );
+ if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND )
+ {
+ if ( maMnemonics[nMnemonicIndex] )
+ {
+ if ( maMnemonics[nMnemonicIndex] < nBestCount )
+ {
+ nBestCount = maMnemonics[nMnemonicIndex];
+ nBestIndex = nIndex;
+ nBestMnemonicIndex = nMnemonicIndex;
+ if ( nBestCount == 2 )
+ break;
+ }
+ }
+ }
+
+ nIndex++;
+ }
+ while ( nIndex < nLen );
+
+ if ( nBestCount != 0xFFFF )
+ {
+ maMnemonics[nBestMnemonicIndex] = 0;
+ rKey.Insert( MNEMONIC_CHAR, nBestIndex );
+ bChanged = TRUE;
+ }
+ }
+
+ return bChanged;
+}
+
+uno::Reference< lang::XCharacterClassification > ImplMnemonicGenerator::GetCharClass()
+{
+ if ( !xCharClass.is() )
+ xCharClass = vcl::unohelper::CreateCharacterClassification();
+ return xCharClass;
+}
+
+
diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx
new file mode 100644
index 000000000000..ce045114c1ae
--- /dev/null
+++ b/vcl/source/window/msgbox.cxx
@@ -0,0 +1,548 @@
+/*************************************************************************
+ *
+ * $RCSfile: msgbox.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MSGBOX_CXX
+
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <metric.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_FIXED_HXX
+#include <fixed.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_MSGBOX_HXX
+#include <msgbox.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+static void ImplInitMsgBoxImageList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maWinData.mpMsgBoxImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_MSGBOX, ImplGetResMgr() ) );
+ pSVData->maWinData.mpMsgBoxImgList = new ImageList( aBmp, Color( 0xC0, 0xC0, 0xC0 ), 4 );
+ }
+}
+
+// =======================================================================
+
+void MessBox::ImplInitData()
+{
+ mpFixedText = NULL;
+ mpFixedImage = NULL;
+ mnSoundType = 0;
+ mbHelpBtn = FALSE;
+ mbSound = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplInitButtons()
+{
+ WinBits nStyle = GetStyle();
+ USHORT nOKFlags = 0;
+ USHORT nCancelFlags = BUTTONDIALOG_CANCELBUTTON;
+ USHORT nRetryFlags = 0;
+ USHORT nYesFlags = 0;
+ USHORT nNoFlags = 0;
+
+ if ( nStyle & WB_OK_CANCEL )
+ {
+ if ( nStyle & WB_DEF_CANCEL )
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_OK
+ nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+ }
+ else if ( nStyle & WB_YES_NO )
+ {
+ if ( nStyle & WB_DEF_YES )
+ nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_NO
+ nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ nNoFlags |= BUTTONDIALOG_CANCELBUTTON;
+
+ AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
+ AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
+ }
+ else if ( nStyle & WB_YES_NO_CANCEL )
+ {
+ if ( nStyle & WB_DEF_YES )
+ nYesFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else if ( nStyle & WB_DEF_NO )
+ nNoFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_YES, BUTTONID_YES, nYesFlags );
+ AddButton( BUTTON_NO, BUTTONID_NO, nNoFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+ }
+ else if ( nStyle & WB_RETRY_CANCEL )
+ {
+ if ( nStyle & WB_DEF_CANCEL )
+ nCancelFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+ else // WB_DEF_RETRY
+ nRetryFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_RETRY, BUTTONID_RETRY, nRetryFlags );
+ AddButton( BUTTON_CANCEL, BUTTONID_CANCEL, nCancelFlags );
+
+ }
+ else if ( nStyle & WB_OK )
+ {
+ nOKFlags |= BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_CANCELBUTTON | BUTTONDIALOG_FOCUSBUTTON;
+
+ AddButton( BUTTON_OK, BUTTONID_OK, nOKFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( WindowType nType ) :
+ ButtonDialog( WINDOW_MESSBOX )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( Window* pParent, WinBits nStyle,
+ const XubString& rTitle, const XubString& rMessage ) :
+ ButtonDialog( WINDOW_MESSBOX ),
+ maMessText( rMessage )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER );
+ ImplInitButtons();
+
+ if ( rTitle.Len() )
+ SetText( rTitle );
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::MessBox( Window* pParent, const ResId& rResId ) :
+ ButtonDialog( WINDOW_MESSBOX )
+{
+ ImplInitData();
+
+ GetRes( rResId.SetRT( RSC_MESSBOX ) );
+ USHORT nHiButtons = ReadShortRes();
+ USHORT nLoButtons = ReadShortRes();
+ USHORT nHiDefButton = ReadShortRes();
+ USHORT nLoDefButton = ReadShortRes();
+ USHORT nHiHelpId = ReadShortRes();
+ USHORT nLoHelpId = ReadShortRes();
+ USHORT bSysModal = ReadShortRes();
+ SetHelpId( ((ULONG)nHiHelpId << 16) + nLoHelpId );
+ WinBits nBits = (((ULONG)nHiButtons << 16) + nLoButtons) |
+ (((ULONG)nHiDefButton << 16) + nLoDefButton);
+ ImplInit( pParent, nBits | WB_MOVEABLE | WB_HORZ | WB_CENTER );
+
+ ImplLoadRes( rResId );
+ ImplInitButtons();
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplLoadRes( const ResId& rResId )
+{
+ SetText( ReadStringRes() );
+ SetMessText( ReadStringRes() );
+ SetHelpText( ReadStringRes() );
+}
+
+// -----------------------------------------------------------------------
+
+MessBox::~MessBox()
+{
+ if ( mpFixedText )
+ delete mpFixedText;
+ if ( mpFixedImage )
+ delete mpFixedImage;
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::ImplPosControls()
+{
+ if ( GetHelpId() )
+ {
+ if ( !mbHelpBtn )
+ {
+ AddButton( BUTTON_HELP, BUTTONID_HELP, BUTTONDIALOG_HELPBUTTON, 3 );
+ mbHelpBtn = TRUE;
+ }
+ }
+ else
+ {
+ if ( mbHelpBtn )
+ {
+ RemoveButton( BUTTONID_HELP );
+ mbHelpBtn = FALSE;
+ }
+ }
+
+ XubString aMessText( maMessText );
+ TextRectInfo aTextInfo;
+ Rectangle aRect( 0, 0, 30000, 30000 );
+ Rectangle aFormatRect;
+ Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
+ Size aImageSize;
+ Size aPageSize;
+ Size aFixedSize;
+ long nTitleWidth;
+ long nButtonSize = ImplGetButtonSize();
+ long nMaxWidth = GetDesktopRectPixel().GetWidth()-8;
+ long nMaxLineWidth;
+ long nWidth;
+ WinBits nWinStyle = WB_LEFT | WB_WORDBREAK | WB_NOLABEL | WB_INFO;
+ USHORT nTextStyle = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP | TEXT_DRAW_LEFT;
+
+ if ( mpFixedText )
+ delete mpFixedText;
+ if ( mpFixedImage )
+ {
+ delete mpFixedImage;
+ mpFixedImage = NULL;
+ }
+
+ // Message-Text um Tabs bereinigen
+ XubString aTabStr( RTL_CONSTASCII_USTRINGPARAM( " " ) );
+ USHORT nIndex = 0;
+ while ( nIndex != STRING_NOTFOUND )
+ nIndex = aMessText.SearchAndReplace( '\t', aTabStr, nIndex );
+
+ // Wenn Fenster zu schmall, machen wir Dialog auch breiter
+ if ( mbFrame )
+ nMaxWidth = 630;
+ else if ( nMaxWidth < 120 )
+ nMaxWidth = 120;
+
+ nMaxWidth -= mnLeftBorder+mnRightBorder+4;
+
+ // MessageBox sollte min. so breit sein, das auch Title sichtbar ist
+ // Extra-Width for Closer, because Closer is set after this call
+ nTitleWidth = CalcTitleWidth();
+ nTitleWidth += mnTopBorder;
+
+ nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
+
+ // Wenn wir ein Image haben, dann deren Groesse ermitteln und das
+ // entsprechende Control anlegen und positionieren
+ aImageSize = maImage.GetSizePixel();
+ if ( aImageSize.Width() )
+ {
+ aImageSize.Width() += 4;
+ aImageSize.Height() += 4;
+ aTextPos.X() += aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
+ mpFixedImage = new FixedImage( this );
+ mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
+ IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
+ aImageSize );
+ mpFixedImage->SetImage( maImage );
+ mpFixedImage->Show();
+ nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
+ }
+ else
+ aTextPos.X() += IMPL_MSGBOX_OFFSET_EXTRA_X;
+
+ // Maximale Zeilenlaenge ohne Wordbreak ermitteln
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ nMaxLineWidth = aFormatRect.GetWidth();
+ nTextStyle |= TEXT_DRAW_WORDBREAK;
+
+ // Breite fuer Textformatierung ermitteln
+ if ( nMaxLineWidth > 450 )
+ nWidth = 450;
+ else if ( nMaxLineWidth > 300 )
+ nWidth = nMaxLineWidth+5;
+ else
+ nWidth = 300;
+ if ( nButtonSize > nWidth )
+ nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
+ if ( nWidth > nMaxWidth )
+ nWidth = nMaxWidth;
+
+ aRect.Right() = nWidth;
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ if ( aTextInfo.GetMaxLineWidth() > nWidth )
+ {
+ nWidth = aTextInfo.GetMaxLineWidth()+8;
+ aRect.Right() = nWidth;
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ }
+
+ // Style fuer FixedText ermitteln
+ aPageSize.Width() = aImageSize.Width();
+ aFixedSize.Width() = aTextInfo.GetMaxLineWidth()+1;
+ aFixedSize.Height() = aFormatRect.GetHeight();
+ if ( aFixedSize.Height() < aImageSize.Height() )
+ {
+ nWinStyle |= WB_VCENTER;
+ aPageSize.Height() = aImageSize.Height();
+ aFixedSize.Height() = aImageSize.Height();
+ }
+ else
+ {
+ nWinStyle |= WB_TOP;
+ aPageSize.Height() = aFixedSize.Height();
+ }
+ if ( aImageSize.Width() )
+ aPageSize.Width() += IMPL_SEP_MSGBOX_IMAGE;
+ aPageSize.Width() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
+ aPageSize.Width() += aFixedSize.Width()+1;
+ aPageSize.Height() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2);
+ if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
+ aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH;
+ if ( aPageSize.Width() < nTitleWidth )
+ aPageSize.Width() = nTitleWidth;
+ mpFixedText = new FixedText( this, nWinStyle );
+ mpFixedText->SetPosSizePixel( aTextPos, aFixedSize );
+ mpFixedText->SetText( aMessText );
+ mpFixedText->Show();
+ SetPageSizePixel( aPageSize );
+}
+
+// -----------------------------------------------------------------------
+
+void MessBox::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ ImplPosControls();
+ if ( mbSound && mnSoundType )
+ Sound::Beep( (SoundType)(mnSoundType-1), this );
+ }
+ ButtonDialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void InfoBox::ImplInitData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( InfoBox::GetStandardImage() );
+}
+
+// -----------------------------------------------------------------------
+
+InfoBox::InfoBox( Window* pParent, const XubString& rMessage ) :
+ MessBox( pParent, WB_OK | WB_DEF_OK, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+InfoBox::InfoBox( Window* pParent, const ResId & rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_INFOBOX ) )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Image InfoBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 4 );
+}
+
+// -----------------------------------------------------------------------
+
+void WarningBox::ImplInitData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( WarningBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_WARNING)+1;
+}
+
+// -----------------------------------------------------------------------
+
+WarningBox::WarningBox( Window* pParent, WinBits nStyle,
+ const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+WarningBox::WarningBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_WARNINGBOX ) )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Image WarningBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 3 );
+}
+
+// -----------------------------------------------------------------------
+
+void ErrorBox::ImplInitData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( ErrorBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_ERROR)+1;
+}
+
+// -----------------------------------------------------------------------
+
+ErrorBox::ErrorBox( Window* pParent, WinBits nStyle,
+ const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+ErrorBox::ErrorBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_ERRORBOX ) )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Image ErrorBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 1 );
+}
+
+// -----------------------------------------------------------------------
+
+void QueryBox::ImplInitData()
+{
+ // Default Text is the display title from the application
+ if ( !GetText().Len() )
+ SetText( Application::GetDisplayName() );
+
+ SetImage( QueryBox::GetStandardImage() );
+ mnSoundType = ((USHORT)SOUND_QUERY)+1;
+}
+
+// -----------------------------------------------------------------------
+
+QueryBox::QueryBox( Window* pParent, WinBits nStyle, const XubString& rMessage ) :
+ MessBox( pParent, nStyle, ImplGetSVEmptyStr(), rMessage )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+QueryBox::QueryBox( Window* pParent, const ResId& rResId ) :
+ MessBox( pParent, rResId.SetRT( RSC_QUERYBOX ) )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+Image QueryBox::GetStandardImage()
+{
+ ImplInitMsgBoxImageList();
+ return ImplGetSVData()->maWinData.mpMsgBoxImgList->GetImage( 2 );
+}
diff --git a/vcl/source/window/scrwnd.cxx b/vcl/source/window/scrwnd.cxx
new file mode 100644
index 000000000000..13b6a1075e91
--- /dev/null
+++ b/vcl/source/window/scrwnd.cxx
@@ -0,0 +1,420 @@
+/*************************************************************************
+ *
+ * $RCSfile: scrwnd.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <math.h>
+#include <limits.h>
+#include <tools/debug.hxx>
+#include "svids.hrc"
+#include "svdata.hxx"
+#include "timer.hxx"
+#include "scrwnd.hxx"
+
+// -----------
+// - Defines -
+// -----------
+
+#define WHEEL_WIDTH 25
+#define WHEEL_RADIUS ((WHEEL_WIDTH) >> 1 )
+#define MAX_TIME 300
+#define MIN_TIME 20
+#define DEF_TIMEOUT 50
+
+// -------------------
+// - ImplWheelWindow -
+// -------------------
+
+ImplWheelWindow::ImplWheelWindow( Window* pParent ) :
+ FloatingWindow ( pParent, 0 ),
+ mnRepaintTime ( 1UL ),
+ mnActDist ( 0UL ),
+ mnWheelMode ( WHEELMODE_NONE ),
+ mnActDeltaX ( 0L ),
+ mnActDeltaY ( 0L ),
+ mnTimeout ( DEF_TIMEOUT )
+{
+ // we need a parent
+ DBG_ASSERT( pParent, "ImplWheelWindow::ImplWheelWindow(): Parent not set!" );
+
+ const Size aSize( pParent->GetOutputSizePixel() );
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+
+ // calculate maximum speed distance
+ mnMaxWidth = (ULONG) ( 0.4 * hypot( (double) aSize.Width(), aSize.Height() ) );
+
+ // create wheel window
+ SetTitleType( FLOATWIN_TITLE_NONE );
+ ImplCreateImageList();
+ ImplSetRegion( Bitmap( ResId( SV_RESID_BITMAP_SCROLLMSK, ImplGetResMgr() ) ) );
+
+ // set wheel mode
+ if( bHorz && bVert )
+ ImplSetWheelMode( WHEELMODE_VH );
+ else if( bHorz )
+ ImplSetWheelMode( WHEELMODE_H );
+ else
+ ImplSetWheelMode( WHEELMODE_V );
+
+ // init timer
+ mpTimer = new Timer;
+ mpTimer->SetTimeoutHdl( LINK( this, ImplWheelWindow, ImplScrollHdl ) );
+ mpTimer->SetTimeout( mnTimeout );
+ mpTimer->Start();
+
+ CaptureMouse();
+}
+
+// ------------------------------------------------------------------------
+
+ImplWheelWindow::~ImplWheelWindow()
+{
+ ReleaseMouse();
+ mpTimer->Stop();
+ delete mpTimer;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplSetRegion( const Bitmap& rRegionBmp )
+{
+ Point aPos( GetPointerPosPixel() );
+ const Size aSize( rRegionBmp.GetSizePixel() );
+ Point aPoint;
+ const Rectangle aRect( aPoint, aSize );
+
+ maCenter = maLastMousePos = aPos;
+ aPos.X() -= aSize.Width() >> 1;
+ aPos.Y() -= aSize.Height() >> 1;
+
+ SetPosSizePixel( aPos, aSize );
+ SetWindowRegionPixel( rRegionBmp.CreateRegion( COL_BLACK, aRect ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplCreateImageList()
+{
+ Bitmap aImgBmp( ResId( SV_RESID_BITMAP_SCROLLBMP, ImplGetResMgr() ) );
+ maImgList = ImageList( aImgBmp, 6 );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplSetWheelMode( ULONG nWheelMode )
+{
+ if( nWheelMode != mnWheelMode )
+ {
+ mnWheelMode = nWheelMode;
+
+ if( WHEELMODE_NONE == mnWheelMode )
+ {
+ if( IsVisible() )
+ Hide();
+ }
+ else
+ {
+ if( !IsVisible() )
+ Show();
+
+ ImplDrawWheel();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplDrawWheel()
+{
+ USHORT nId;
+
+ switch( mnWheelMode )
+ {
+ case( WHEELMODE_VH ): nId = 1; break;
+ case( WHEELMODE_V ): nId = 2; break;
+ case( WHEELMODE_H ): nId = 3; break;
+ case( WHEELMODE_SCROLL_VH ):nId = 4; break;
+ case( WHEELMODE_SCROLL_V ): nId = 5; break;
+ case( WHEELMODE_SCROLL_H ): nId = 6; break;
+ default: nId = 0; break;
+ }
+
+ if( nId )
+ DrawImage( Point(), maImgList.GetImage( nId ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::ImplRecalcScrollValues()
+{
+ if( mnActDist < WHEEL_RADIUS )
+ {
+ mnActDeltaX = mnActDeltaY = 0L;
+ mnTimeout = DEF_TIMEOUT;
+ }
+ else
+ {
+ ULONG nCurTime;
+
+ // calc current time
+ if( mnMaxWidth )
+ {
+ const double fExp = ( (double) mnActDist / mnMaxWidth ) * log10( (double) MAX_TIME / MIN_TIME );
+ nCurTime = (ULONG) ( MAX_TIME / pow( 10., fExp ) );
+ }
+ else
+ nCurTime = MAX_TIME;
+
+ if( !nCurTime )
+ nCurTime = 1UL;
+
+ if( mnRepaintTime <= nCurTime )
+ mnTimeout = nCurTime - mnRepaintTime;
+ else
+ {
+ long nMult = mnRepaintTime / nCurTime;
+
+ if( !( mnRepaintTime % nCurTime ) )
+ mnTimeout = 0UL;
+ else
+ mnTimeout = ++nMult * nCurTime - mnRepaintTime;
+
+ double fValX = (double) mnActDeltaX * nMult;
+ double fValY = (double) mnActDeltaY * nMult;
+
+ if( fValX > LONG_MAX )
+ mnActDeltaX = LONG_MAX;
+ else if( fValX < LONG_MIN )
+ mnActDeltaX = LONG_MIN;
+ else
+ mnActDeltaX = (long) fValX;
+
+ if( fValY > LONG_MAX )
+ mnActDeltaY = LONG_MAX;
+ else if( fValY < LONG_MIN )
+ mnActDeltaY = LONG_MIN;
+ else
+ mnActDeltaY = (long) fValY;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+PointerStyle ImplWheelWindow::ImplGetMousePointer( long nDistX, long nDistY )
+{
+ PointerStyle eStyle;
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+
+ if( bHorz || bVert )
+ {
+ if( mnActDist < WHEEL_RADIUS )
+ {
+ if( bHorz && bVert )
+ eStyle = POINTER_AUTOSCROLL_NSWE;
+ else if( bHorz )
+ eStyle = POINTER_AUTOSCROLL_WE;
+ else
+ eStyle = POINTER_AUTOSCROLL_NS;
+ }
+ else
+ {
+ double fAngle = atan2( (double) -nDistY, nDistX ) / F_PI180;
+
+ if( fAngle < 0.0 )
+ fAngle += 360.;
+
+ if( bHorz && bVert )
+ {
+ if( fAngle >= 22.5 && fAngle <= 67.5 )
+ eStyle = POINTER_AUTOSCROLL_NE;
+ else if( fAngle >= 67.5 && fAngle <= 112.5 )
+ eStyle = POINTER_AUTOSCROLL_N;
+ else if( fAngle >= 112.5 && fAngle <= 157.5 )
+ eStyle = POINTER_AUTOSCROLL_NW;
+ else if( fAngle >= 157.5 && fAngle <= 202.5 )
+ eStyle = POINTER_AUTOSCROLL_W;
+ else if( fAngle >= 202.5 && fAngle <= 247.5 )
+ eStyle = POINTER_AUTOSCROLL_SW;
+ else if( fAngle >= 247.5 && fAngle <= 292.5 )
+ eStyle = POINTER_AUTOSCROLL_S;
+ else if( fAngle >= 292.5 && fAngle <= 337.5 )
+ eStyle = POINTER_AUTOSCROLL_SE;
+ else
+ eStyle = POINTER_AUTOSCROLL_E;
+ }
+ else if( bHorz )
+ {
+ if( fAngle >= 270. || fAngle <= 90. )
+ eStyle = POINTER_AUTOSCROLL_E;
+ else
+ eStyle = POINTER_AUTOSCROLL_W;
+ }
+ else
+ {
+ if( fAngle >= 0. && fAngle <= 180. )
+ eStyle = POINTER_AUTOSCROLL_N;
+ else
+ eStyle = POINTER_AUTOSCROLL_S;
+ }
+ }
+ }
+ else
+ eStyle = POINTER_ARROW;
+
+ return eStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::Paint( const Rectangle& rRect )
+{
+ ImplDrawWheel();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ FloatingWindow::MouseMove( rMEvt );
+
+ const Point aMousePos( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
+ const long nDistX = aMousePos.X() - maCenter.X();
+ const long nDistY = aMousePos.Y() - maCenter.Y();
+
+ mnActDist = (ULONG) hypot( (double) nDistX, nDistY );
+
+ const PointerStyle eActStyle = ImplGetMousePointer( nDistX, nDistY );
+ const USHORT nFlags = ImplGetSVData()->maWinData.mnAutoScrollFlags;
+ const BOOL bHorz = ( nFlags & AUTOSCROLL_HORZ ) != 0;
+ const BOOL bVert = ( nFlags & AUTOSCROLL_VERT ) != 0;
+ const BOOL bOuter = mnActDist > WHEEL_RADIUS;
+
+ if( bOuter && ( maLastMousePos != aMousePos ) )
+ {
+ switch( eActStyle )
+ {
+ case( POINTER_AUTOSCROLL_N ): mnActDeltaX = +0L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_S ): mnActDeltaX = +0L, mnActDeltaY = -1L; break;
+ case( POINTER_AUTOSCROLL_W ): mnActDeltaX = +1L, mnActDeltaY = +0L; break;
+ case( POINTER_AUTOSCROLL_E ): mnActDeltaX = -1L, mnActDeltaY = +0L; break;
+ case( POINTER_AUTOSCROLL_NW ): mnActDeltaX = +1L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_NE ): mnActDeltaX = -1L, mnActDeltaY = +1L; break;
+ case( POINTER_AUTOSCROLL_SW ): mnActDeltaX = +1L, mnActDeltaY = -1L; break;
+ case( POINTER_AUTOSCROLL_SE ): mnActDeltaX = -1L, mnActDeltaY = -1L; break;
+
+ default:
+ break;
+ }
+ }
+
+ ImplRecalcScrollValues();
+ maLastMousePos = aMousePos;
+ SetPointer( eActStyle );
+
+ if( bHorz && bVert )
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_VH : WHEELMODE_VH );
+ else if( bHorz )
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_H : WHEELMODE_H );
+ else
+ ImplSetWheelMode( bOuter ? WHEELMODE_SCROLL_V : WHEELMODE_V );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWheelWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if( mnActDist > WHEEL_RADIUS )
+ GetParent()->EndAutoScroll();
+ else
+ FloatingWindow::MouseButtonUp( rMEvt );
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK( ImplWheelWindow, ImplScrollHdl, Timer*, pTimer )
+{
+ if ( mnActDeltaX || mnActDeltaY )
+ {
+ Window* pWindow = GetParent();
+ const Point aMousePos( pWindow->OutputToScreenPixel( pWindow->GetPointerPosPixel() ) );
+ Point aCmdMousePos( pWindow->ImplFrameToOutput( aMousePos ) );
+ CommandScrollData aScrollData( mnActDeltaX, mnActDeltaY );
+ CommandEvent aCEvt( aCmdMousePos, COMMAND_AUTOSCROLL, TRUE, &aScrollData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
+
+ if ( !ImplCallPreNotify( aNCmdEvt ) )
+ {
+ const ULONG nTime = Time::GetSystemTicks();
+ pWindow->Command( aCEvt );
+ mnRepaintTime = Max( Time::GetSystemTicks() - nTime, 1UL );
+ ImplRecalcScrollValues();
+ }
+ }
+
+ if ( mnTimeout != mpTimer->GetTimeout() )
+ mpTimer->SetTimeout( mnTimeout );
+ mpTimer->Start();
+
+ return 0L;
+}
diff --git a/vcl/source/window/scrwnd.hxx b/vcl/source/window/scrwnd.hxx
new file mode 100644
index 000000000000..885c55267b18
--- /dev/null
+++ b/vcl/source/window/scrwnd.hxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * $RCSfile: scrwnd.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <floatwin.hxx>
+#include <bitmap.hxx>
+#include <image.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define WHEELMODE_NONE 0x00000000UL
+#define WHEELMODE_VH 0x00000001UL
+#define WHEELMODE_V 0x00000002UL
+#define WHEELMODE_H 0x00000004UL
+#define WHEELMODE_SCROLL_VH 0x00000008UL
+#define WHEELMODE_SCROLL_V 0x00000010UL
+#define WHEELMODE_SCROLL_H 0x00000020UL
+
+// -------------------
+// - ImplWheelWindow -
+// -------------------
+
+class Timer;
+
+class ImplWheelWindow : public FloatingWindow
+{
+private:
+
+ ImageList maImgList;
+ Bitmap maWheelBmp;
+ CommandScrollData maCommandScrollData;
+ Point maLastMousePos;
+ Point maCenter;
+ Timer* mpTimer;
+ ULONG mnRepaintTime;
+ ULONG mnTimeout;
+ ULONG mnWheelMode;
+ ULONG mnMaxWidth;
+ ULONG mnActWidth;
+ ULONG mnActDist;
+ long mnActDeltaX;
+ long mnActDeltaY;
+
+ void ImplCreateImageList();
+ void ImplSetRegion( const Bitmap& rRegionBmp );
+ PointerStyle ImplGetMousePointer( long nDistX, long nDistY );
+ void ImplDrawWheel();
+ void ImplRecalcScrollValues();
+
+ DECL_LINK( ImplScrollHdl, Timer* pTimer );
+
+protected:
+
+ virtual void Paint( const Rectangle& rRect );
+ virtual void MouseMove( const MouseEvent& rMEvt );
+ virtual void MouseButtonUp( const MouseEvent& rMEvt );
+
+public:
+
+ ImplWheelWindow( Window* pParent );
+ ~ImplWheelWindow();
+
+ void ImplSetWheelMode( ULONG nWheelMode );
+ ULONG ImplGetWheelMode() const { return mnWheelMode; }
+};
diff --git a/vcl/source/window/seleng.cxx b/vcl/source/window/seleng.cxx
new file mode 100644
index 000000000000..8fd3b665aa8a
--- /dev/null
+++ b/vcl/source/window/seleng.cxx
@@ -0,0 +1,506 @@
+/*************************************************************************
+ *
+ * $RCSfile: seleng.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <tools/ref.hxx>
+#include <window.hxx>
+#include <seleng.hxx>
+#include <tools/debug.hxx>
+
+#pragma hdrstop
+
+// TODO: FunctionSet::SelectAtPoint raus
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelectionEngine()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+SelectionEngine::SelectionEngine( Window* pWindow, FunctionSet* pFuncSet ) :
+ pWin( pWindow )
+{
+ eSelMode = SINGLE_SELECTION;
+ pFunctionSet = pFuncSet;
+ nFlags = SELENG_EXPANDONMOVE;
+ nLockedMods = 0;
+
+ aWTimer.SetTimeoutHdl( LINK( this, SelectionEngine, ImpWatchDog ) );
+ aWTimer.SetTimeout( SELENG_AUTOREPEAT_INTERVAL );
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::~SelectionEngine()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+SelectionEngine::~SelectionEngine()
+{
+ aWTimer.Stop();
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::ImpWatchDog()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+IMPL_LINK( SelectionEngine, ImpWatchDog, Timer*, EMPTYARG )
+{
+ if ( !aArea.IsInside( aLastMove.GetPosPixel() ) )
+ SelMouseMove( aLastMove );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SetSelectionMode()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::SetSelectionMode( SelectionMode eMode )
+{
+ eSelMode = eMode;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::ActivateDragMode()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::ActivateDragMode()
+{
+ DBG_ERRORFILE( "SelectionEngine::ActivateDragMode not implemented" );
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::CursorPosChanging()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::CursorPosChanging( BOOL bShift, BOOL /* bMod1 */ )
+{
+ if ( !pFunctionSet )
+ return;
+
+ if ( bShift && eSelMode != SINGLE_SELECTION )
+ {
+ if ( IsAddMode() )
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+ else
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->DeselectAll();
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+ }
+ else
+ {
+ if ( IsAddMode() )
+ {
+ if ( nFlags & SELENG_HAS_ANCH )
+ {
+ // pFunctionSet->CreateCursor();
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ }
+ else
+ {
+ pFunctionSet->DeselectAll();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseButtonDown()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 07.06.95
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseButtonDown( const MouseEvent& rMEvt )
+{
+ nFlags &= (~SELENG_CMDEVT);
+ if ( !pFunctionSet || !pWin || rMEvt.GetClicks() > 1 || rMEvt.IsRight() )
+ return FALSE;
+
+ USHORT nModifier = rMEvt.GetModifier() | nLockedMods;
+ if ( nModifier & KEY_MOD2 )
+ return FALSE;
+ // in SingleSelection: Control-Taste filtern (damit auch
+ // mit Ctrl-Click ein D&D gestartet werden kann)
+ if ( nModifier == KEY_MOD1 && eSelMode == SINGLE_SELECTION )
+ nModifier = 0;
+
+ Point aPos = rMEvt.GetPosPixel();
+ aLastMove = rMEvt;
+
+ pWin->CaptureMouse();
+ nFlags |= SELENG_IN_SEL;
+
+ switch ( nModifier )
+ {
+ case 0: // KEY_NO_KEY
+ {
+ BOOL bSelAtPoint = pFunctionSet->IsSelectionAtPoint( aPos );
+ nFlags &= (~SELENG_IN_ADD);
+ if ( (nFlags & SELENG_DRG_ENAB) && bSelAtPoint )
+ {
+ nFlags |= SELENG_WAIT_UPEVT;
+ nFlags &= ~(SELENG_IN_SEL);
+ pWin->ReleaseMouse();
+ return TRUE; //auf STARTDRAG-Command-Event warten
+ }
+ if ( eSelMode != SINGLE_SELECTION )
+ {
+ if( !IsAddMode() )
+ pFunctionSet->DeselectAll();
+ else
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH); // bHasAnchor = FALSE;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ // Sonderbehandlung Single-Selection, damit Select+Drag
+ // in einem Zug moeglich ist
+ if (eSelMode == SINGLE_SELECTION && (nFlags & SELENG_DRG_ENAB))
+ nFlags |= SELENG_WAIT_UPEVT;
+ return TRUE;
+ }
+
+ case KEY_SHIFT:
+ if ( eSelMode == SINGLE_SELECTION )
+ {
+ pWin->ReleaseMouse();
+ nFlags &= (~SELENG_IN_SEL);
+ return FALSE;
+ }
+ if ( nFlags & SELENG_ADD_ALW )
+ nFlags |= SELENG_IN_ADD;
+ else
+ nFlags &= (~SELENG_IN_ADD);
+
+ if( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ if ( !(nFlags & SELENG_IN_ADD) )
+ pFunctionSet->DeselectAll();
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ return TRUE;
+
+ case KEY_MOD1:
+ // Control nur bei Mehrfachselektion erlaubt
+ if ( eSelMode != MULTIPLE_SELECTION )
+ {
+ nFlags &= (~SELENG_IN_SEL);
+ pWin->ReleaseMouse();
+ return TRUE; // Mausclick verschlucken
+ }
+ if ( nFlags & SELENG_HAS_ANCH )
+ {
+ // pFunctionSet->CreateCursor();
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH);
+ }
+ if ( pFunctionSet->IsSelectionAtPoint( aPos ) )
+ {
+ pFunctionSet->DeselectAtPoint( aPos );
+ pFunctionSet->SetCursorAtPoint( aPos, TRUE );
+ }
+ else
+ {
+ pFunctionSet->SetCursorAtPoint( aPos );
+ }
+ return TRUE;
+
+ case KEY_SHIFT + KEY_MOD1:
+ if ( eSelMode != MULTIPLE_SELECTION )
+ {
+ pWin->ReleaseMouse();
+ nFlags &= (~SELENG_IN_SEL);
+ return FALSE;
+ }
+ nFlags |= SELENG_IN_ADD; //bIsInAddMode = TRUE;
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ pFunctionSet->SetCursorAtPoint( aPos );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseButtonUp()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseButtonUp( const MouseEvent& /* rMEvt */ )
+{
+ aWTimer.Stop();
+ //DbgOut("Up");
+ if( !pFunctionSet || !pWin )
+ {
+ nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL);
+ return FALSE;
+ }
+ pWin->ReleaseMouse();
+
+ if( (nFlags & SELENG_WAIT_UPEVT) && !(nFlags & SELENG_CMDEVT) &&
+ eSelMode != SINGLE_SELECTION)
+ {
+ // MouseButtonDown in Sel aber kein CommandEvent eingetrudelt
+ // ==> deselektieren
+ USHORT nModifier = aLastMove.GetModifier() | nLockedMods;
+ if( nModifier == KEY_MOD1 || IsAlwaysAdding() )
+ {
+ if( !(nModifier & KEY_SHIFT) )
+ {
+ pFunctionSet->DestroyAnchor();
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ }
+ pFunctionSet->DeselectAtPoint( aLastMove.GetPosPixel() );
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel(), TRUE );
+ }
+ else
+ {
+ pFunctionSet->DeselectAll();
+ nFlags &= (~SELENG_HAS_ANCH); // nix Anker
+ pFunctionSet->SetCursorAtPoint( aLastMove.GetPosPixel() );
+ }
+ }
+
+ nFlags &= ~(SELENG_CMDEVT | SELENG_WAIT_UPEVT | SELENG_IN_SEL);
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SelMouseMove()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+BOOL SelectionEngine::SelMouseMove( const MouseEvent& rMEvt )
+{
+
+ if ( !pFunctionSet || !(nFlags & SELENG_IN_SEL) ||
+ (nFlags & (SELENG_CMDEVT | SELENG_WAIT_UPEVT)) )
+ return FALSE;
+
+ if( !(nFlags & SELENG_EXPANDONMOVE) )
+ return FALSE; // auf DragEvent warten!
+
+ aLastMove = rMEvt;
+ // wenn die Maus ausserhalb der Area steht, dann wird die
+ // Frequenz des SetCursorAtPoint() nur durch den Timer bestimmt
+ if( aWTimer.IsActive() && !aArea.IsInside( rMEvt.GetPosPixel() ))
+ return TRUE;
+
+
+ aWTimer.Start();
+ if ( eSelMode != SINGLE_SELECTION )
+ {
+ if ( !(nFlags & SELENG_HAS_ANCH) )
+ {
+ pFunctionSet->CreateAnchor();
+ //DbgOut("Move:Creating anchor");
+ nFlags |= SELENG_HAS_ANCH;
+ }
+ }
+
+ //DbgOut("Move:SetCursor");
+ pFunctionSet->SetCursorAtPoint( rMEvt.GetPosPixel() );
+
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::SetWindow()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 10.10.94
+|* Letzte Aenderung OV 10.10.94
+|*
+*************************************************************************/
+
+void SelectionEngine::SetWindow( Window* pNewWin )
+{
+ if( pNewWin != pWin )
+ {
+ if ( pWin && (nFlags & SELENG_IN_SEL) )
+ pWin->ReleaseMouse();
+ pWin = pNewWin;
+ if ( pWin && ( nFlags & SELENG_IN_SEL ) )
+ pWin->CaptureMouse();
+ }
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::Reset()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 07.07.95
+|* Letzte Aenderung OV 07.07.95
+|*
+*************************************************************************/
+
+void SelectionEngine::Reset()
+{
+ aWTimer.Stop();
+ if ( nFlags & SELENG_IN_SEL )
+ pWin->ReleaseMouse();
+ nFlags &= ~(SELENG_HAS_ANCH | SELENG_IN_SEL);
+ nLockedMods = 0;
+}
+
+/*************************************************************************
+|*
+|* SelectionEngine::Command()
+|*
+|* Beschreibung SELENG.SDW
+|* Ersterstellung OV 07.07.95
+|* Letzte Aenderung OV 07.07.95
+|*
+*************************************************************************/
+
+void SelectionEngine::Command( const CommandEvent& rCEvt )
+{
+ // Timer aWTimer ist beim Aufspannen einer Selektion aktiv
+ if ( !pFunctionSet || !pWin || aWTimer.IsActive() )
+ return;
+ aWTimer.Stop();
+ nFlags |= SELENG_CMDEVT;
+ if ( rCEvt.GetCommand() == COMMAND_STARTDRAG )
+ {
+ if ( nFlags & SELENG_DRG_ENAB )
+ {
+ DBG_ASSERT( rCEvt.IsMouseEvent(), "STARTDRAG: Not a MouseEvent" );
+ if ( pFunctionSet->IsSelectionAtPoint( rCEvt.GetMousePosPixel() ) )
+ {
+ aLastMove = MouseEvent( rCEvt.GetMousePosPixel(),
+ aLastMove.GetClicks(), aLastMove.GetMode(),
+ aLastMove.GetButtons(), aLastMove.GetModifier() );
+ pFunctionSet->BeginDrag();
+ nFlags &= ~(SELENG_CMDEVT|SELENG_WAIT_UPEVT|SELENG_IN_SEL);
+ }
+ else
+ nFlags &= ~SELENG_CMDEVT;
+ }
+ else
+ nFlags &= ~SELENG_CMDEVT;
+ }
+}
diff --git a/vcl/source/window/split.cxx b/vcl/source/window/split.cxx
new file mode 100644
index 000000000000..440b550b720a
--- /dev/null
+++ b/vcl/source/window/split.cxx
@@ -0,0 +1,365 @@
+/*************************************************************************
+ *
+ * $RCSfile: split.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SPLIT_CXX
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SPLIT_HXX
+#include <split.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void Splitter::ImplInitData()
+{
+ mpRefWin = NULL;
+ mnSplitPos = 0;
+ mnLastSplitPos = 0;
+ mnStartSplitPos = 0;
+ mbDragFull = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplInit( Window* pParent, WinBits nWinStyle )
+{
+ Window::ImplInit( pParent, nWinStyle, NULL );
+
+ mpRefWin = pParent;
+
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ long nA = rSettings.GetScrollBarSize();
+ long nB = rSettings.GetSplitSize();
+
+ PointerStyle ePointerStyle;
+
+ if ( nWinStyle & WB_HSCROLL )
+ {
+ ePointerStyle = POINTER_HSPLIT;
+ mbHorzSplit = TRUE;
+ SetSizePixel( Size( nB, nA ) );
+ }
+ else
+ {
+ ePointerStyle = POINTER_VSPLIT;
+ mbHorzSplit = FALSE;
+ SetSizePixel( Size( nA, nB ) );
+ }
+
+ SetPointer( Pointer( ePointerStyle ) );
+ SetBackground( Wallpaper( Color( COL_BLACK ) ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplSplitMousePos( Point& rPos )
+{
+ if ( mbHorzSplit )
+ {
+ if ( rPos.X() > maDragRect.Right()-1 )
+ rPos.X() = maDragRect.Right()-1;
+ if ( rPos.X() < maDragRect.Left()+1 )
+ rPos.X() = maDragRect.Left()+1;
+ }
+ else
+ {
+ if ( rPos.Y() > maDragRect.Bottom()-1 )
+ rPos.Y() = maDragRect.Bottom()-1;
+ if ( rPos.Y() < maDragRect.Top()+1 )
+ rPos.Y() = maDragRect.Top()+1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::ImplDrawSplitter()
+{
+ Rectangle aInvRect( maDragRect );
+
+ if ( mbHorzSplit )
+ {
+ aInvRect.Left() = maDragPos.X() - 1;
+ aInvRect.Right() = maDragPos.X() + 1;
+ }
+ else
+ {
+ aInvRect.Top() = maDragPos.Y() - 1;
+ aInvRect.Bottom() = maDragPos.Y() + 1;
+ }
+
+ mpRefWin->InvertTracking( aInvRect, SHOWTRACK_SPLIT );
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::Splitter( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SPLITTER )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::Splitter( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SPLITTER )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_SPLITTER );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+Splitter::~Splitter()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ if ( mnLastSplitPos != mnSplitPos )
+ {
+ StartSplit();
+ Point aPos = rMEvt.GetPosPixel();
+ if ( mbHorzSplit )
+ aPos.X() = mnLastSplitPos;
+ else
+ aPos.Y() = mnLastSplitPos;
+ ImplSplitMousePos( aPos );
+ Splitting( aPos );
+ ImplSplitMousePos( aPos );
+ long nTemp = mnSplitPos;
+ if ( mbHorzSplit )
+ SetSplitPosPixel( aPos.X() );
+ else
+ SetSplitPosPixel( aPos.Y() );
+ mnLastSplitPos = nTemp;
+ Split();
+ }
+ }
+ else
+ StartDrag();
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( !mbDragFull )
+ ImplDrawSplitter();
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnStartSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+ }
+ else if ( mbDragFull )
+ {
+ SetSplitPosPixel( mnStartSplitPos );
+ Split();
+ }
+ mnStartSplitPos = 0;
+ }
+ else
+ {
+ Point aNewPos = mpRefWin->ScreenToOutputPixel( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
+ ImplSplitMousePos( aNewPos );
+ Splitting( aNewPos );
+ ImplSplitMousePos( aNewPos );
+
+ if ( mbHorzSplit )
+ {
+ if ( aNewPos.X() == maDragPos.X() )
+ return;
+ }
+ else
+ {
+ if ( aNewPos.Y() == maDragPos.Y() )
+ return;
+ }
+
+ if ( mbDragFull )
+ {
+ maDragPos = aNewPos;
+ long nNewPos;
+ if ( mbHorzSplit )
+ nNewPos = maDragPos.X();
+ else
+ nNewPos = maDragPos.Y();
+ if ( nNewPos != mnSplitPos )
+ {
+ SetSplitPosPixel( nNewPos );
+ mnLastSplitPos = 0;
+ Split();
+ }
+
+ GetParent()->Update();
+ }
+ else
+ {
+ ImplDrawSplitter();
+ maDragPos = aNewPos;
+ ImplDrawSplitter();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::StartSplit()
+{
+ maStartSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Split()
+{
+ maSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::Splitting( Point& /* rSplitPos */ )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetDragRectPixel( const Rectangle& rDragRect, Window* _pRefWin )
+{
+ maDragRect = rDragRect;
+ if ( !_pRefWin )
+ mpRefWin = GetParent();
+ else
+ mpRefWin = _pRefWin;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetSplitPosPixel( long nNewPos )
+{
+ mnSplitPos = nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::SetLastSplitPosPixel( long nNewPos )
+{
+ mnLastSplitPos = nNewPos;
+}
+
+// -----------------------------------------------------------------------
+
+void Splitter::StartDrag()
+{
+ if ( IsTracking() )
+ return;
+
+ StartSplit();
+
+ // Tracking starten
+ StartTracking();
+
+ // Start-Positon ermitteln
+ maDragPos = mpRefWin->GetPointerPosPixel();
+ ImplSplitMousePos( maDragPos );
+ Splitting( maDragPos );
+ ImplSplitMousePos( maDragPos );
+ if ( mbHorzSplit )
+ mnStartSplitPos = maDragPos.X();
+ else
+ mnStartSplitPos = maDragPos.Y();
+
+ mbDragFull = (Application::GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
+ if ( !mbDragFull )
+ ImplDrawSplitter();
+}
diff --git a/vcl/source/window/splitwin.cxx b/vcl/source/window/splitwin.cxx
new file mode 100644
index 000000000000..907c98f56d4e
--- /dev/null
+++ b/vcl/source/window/splitwin.cxx
@@ -0,0 +1,3647 @@
+/*************************************************************************
+ *
+ * $RCSfile: splitwin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SPLITWIN_CXX
+
+#include <string.h>
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RCID_H
+#include <rcid.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_WALL_HXX
+#include <wall.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SYMBOL_HXX
+#include <symbol.hxx>
+#endif
+#ifndef _SV_SVIDS_HRC
+#include <svids.hrc>
+#endif
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#define private public
+#ifndef _SV_SPLITWIN_HXX
+#include <splitwin.hxx>
+#endif
+#undef private
+
+#pragma hdrstop
+
+// =======================================================================
+
+// Achtung: Darf keine Objekte enthalten, da mit memmove/memcpy gearbeitet wird
+struct ImplSplitItem
+{
+ long mnSize;
+ long mnPixSize;
+ long mnLeft;
+ long mnTop;
+ long mnWidth;
+ long mnHeight;
+ long mnSplitPos;
+ long mnSplitSize;
+ long mnOldSplitPos;
+ long mnOldSplitSize;
+ long mnOldWidth;
+ long mnOldHeight;
+ ImplSplitSet* mpSet;
+ Window* mpWindow;
+ Window* mpOrgParent;
+ USHORT mnId;
+ SplitWindowItemBits mnBits;
+ BOOL mbFixed;
+ BOOL mbSubSize;
+};
+
+struct ImplSplitSet
+{
+ ImplSplitItem* mpItems;
+ Wallpaper* mpWallpaper;
+ Bitmap* mpBitmap;
+ long mnLastSize;
+ long mnSplitSize;
+ USHORT mnItems;
+ USHORT mnId;
+ BOOL mbCalcPix;
+};
+
+#define SPLITWIN_SPLITSIZE 6
+#define SPLITWIN_SPLITSIZEEX 6
+#define SPLITWIN_SPLITSIZEAUTOHIDE 40
+#define SPLITWIN_SPLITSIZEFADE 40
+
+#define SPLIT_HORZ ((USHORT)0x0001)
+#define SPLIT_VERT ((USHORT)0x0002)
+#define SPLIT_WINDOW ((USHORT)0x0004)
+#define SPLIT_NOSPLIT ((USHORT)0x8000)
+
+// -----------------------------------------------------------------------
+
+DECLARE_LIST( ImplSplitList, SplitWindow* );
+
+// =======================================================================
+
+static void ImplCalcBorder( WindowAlign eAlign, BOOL bNoAlign,
+ long& rLeft, long& rTop,
+ long& rRight, long& rBottom )
+{
+ if ( bNoAlign )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 2;
+ }
+ else
+ {
+ if ( eAlign == WINDOWALIGN_TOP )
+ {
+ rLeft = 0;
+ rTop = 2;
+ rRight = 0;
+ rBottom = 0;
+ }
+ else if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 0;
+ rBottom = 2;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ rLeft = 0;
+ rTop = 0;
+ rRight = 0;
+ rBottom = 2;
+ }
+ else
+ {
+ rLeft = 0;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 2;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBorder( SplitWindow* pWin )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+ long nDX = pWin->mnDX;
+ long nDY = pWin->mnDY;
+
+ if ( pWin->mbNoAlign )
+ {
+ DecorationView aDecoView( pWin );
+ Point aTmpPoint;
+ Rectangle aRect( aTmpPoint, Size( nDX, nDY ) );
+ aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
+ }
+ else
+ {
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
+ if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
+ {
+ if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static ImplSplitSet* ImplFindSet( ImplSplitSet* pSet, USHORT nId )
+{
+ if ( pSet->mnId == nId )
+ return pSet;
+
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnId == nId )
+ return pItems[i].mpSet;
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ ImplSplitSet* pFindSet = ImplFindSet( pItems[i].mpSet, nId );
+ if ( pFindSet )
+ return pFindSet;
+ }
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static ImplSplitSet* ImplFindItem( ImplSplitSet* pSet, USHORT nId, USHORT& rPos )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnId == nId )
+ {
+ rPos = i;
+ return pSet;
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ ImplSplitSet* pFindSet = ImplFindItem( pItems[i].mpSet, nId, rPos );
+ if ( pFindSet )
+ return pFindSet;
+ }
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplFindItem( ImplSplitSet* pSet, Window* pWindow )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpWindow == pWindow )
+ return pItems[i].mnId;
+ else
+ {
+ if ( pItems[i].mpSet )
+ {
+ USHORT nId = ImplFindItem( pItems[i].mpSet, pWindow );
+ if ( nId )
+ return nId;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplFindItem( ImplSplitSet* pSet, const Point& rPos,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnWidth && pItems[i].mnHeight )
+ {
+ // Wegen ICC auftrennen
+ Point aPoint( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ Rectangle aRect( aPoint, aSize );
+ if ( bRows )
+ {
+ if ( bDown )
+ aRect.Bottom() += pSet->mnSplitSize;
+ else
+ aRect.Top() -= pSet->mnSplitSize;
+ }
+ else
+ {
+ if ( bDown )
+ aRect.Right() += pSet->mnSplitSize;
+ else
+ aRect.Left() -= pSet->mnSplitSize;
+ }
+
+ if ( aRect.IsInside( rPos ) )
+ {
+ if ( pItems[i].mpSet && pItems[i].mpSet->mpItems )
+ {
+ return ImplFindItem( pItems[i].mpSet, rPos,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ else
+ return pItems[i].mnId;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDeleteSet( ImplSplitSet* pSet )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ ImplDeleteSet( pItems[i].mpSet );
+ }
+
+ if ( pSet->mpWallpaper )
+ delete pSet->mpWallpaper;
+
+ if ( pSet->mpBitmap )
+ delete pSet->mpBitmap;
+
+ delete pItems;
+ delete pSet;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSetSplitSize( ImplSplitSet* pSet, long nNewSize )
+{
+ pSet->mnSplitSize = nNewSize;
+ for ( USHORT i = 0; i < pSet->mnItems; i++ )
+ {
+ if ( pSet->mpItems[i].mpSet )
+ ImplSetSplitSize( pSet->mpItems[i].mpSet, nNewSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcSet( ImplSplitSet* pSet,
+ long nSetLeft, long nSetTop,
+ long nSetWidth, long nSetHeight,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ if ( !pSet->mpItems )
+ return;
+
+ USHORT i;
+ USHORT j;
+ USHORT nMins;
+ USHORT nCalcItems;
+ USHORT nItems = pSet->mnItems;
+ USHORT nVisItems;
+ USHORT nAbsItems;
+ long nCalcSize;
+ long nSizeDelta;
+ long nCurSize;
+ long nSizeWinSize;
+ long nNewSizeWinSize;
+ long nTemp;
+ long nTempErr;
+ long nErrorSum;
+ long nCurSizeDelta;
+ long nPos;
+ long nMaxPos;
+ long* pSize;
+ ImplSplitItem* pItems = pSet->mpItems;
+ BOOL bEmpty;
+
+ // Anzahl sichtbarer Items ermitteln
+ nVisItems = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ nVisItems++;
+ }
+
+ // Groessen berechnen
+ if ( bRows )
+ nCalcSize = nSetHeight;
+ else
+ nCalcSize = nSetWidth;
+ nCalcSize -= (nVisItems-1)*pSet->mnSplitSize;
+ nCurSize = 0;
+ if ( pSet->mbCalcPix || (pSet->mnLastSize != nCalcSize) )
+ {
+ long nPercentFactor = 10;
+ long nRelCount = 0;
+ long nPercent = 0;
+ long nRelPercent = 0;
+ long nAbsSize = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ nRelCount += pItems[i].mnSize;
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ nPercent += pItems[i].mnSize;
+ else
+ nAbsSize += pItems[i].mnSize;
+ }
+ }
+ // Relative-Werte auf prozentual mappen (Percent bei uns 10tel Prozent)
+ nPercent *= nPercentFactor;
+ if ( nRelCount )
+ {
+ long nRelPercentBase = 1000;
+ while ( (nRelCount > nRelPercentBase) && (nPercentFactor < 100000) )
+ {
+ nRelPercentBase *= 10;
+ nPercentFactor *= 10;
+ }
+ if ( nPercent < nRelPercentBase )
+ {
+ nRelPercent = (nRelPercentBase-nPercent)/nRelCount;
+ nPercent += nRelPercent*nRelCount;
+ }
+ else
+ nRelPercent = 0;
+ }
+ if ( !nPercent )
+ nPercent = 1;
+ nSizeDelta = nCalcSize-nAbsSize;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ pItems[i].mnPixSize = 0;
+ else if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ {
+ if ( nSizeDelta <= 0 )
+ pItems[i].mnPixSize = 0;
+ else
+ pItems[i].mnPixSize = (nSizeDelta*pItems[i].mnSize*nRelPercent)/nPercent;
+ }
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ {
+ if ( nSizeDelta <= 0 )
+ pItems[i].mnPixSize = 0;
+ else
+ pItems[i].mnPixSize = (nSizeDelta*pItems[i].mnSize*nPercentFactor)/nPercent;
+ }
+ else
+ pItems[i].mnPixSize = pItems[i].mnSize;
+ nCurSize += pItems[i].mnPixSize;
+ }
+
+ pSet->mbCalcPix = FALSE;
+ pSet->mnLastSize = nCalcSize;
+
+ // Fenster einpassen
+ nSizeDelta = nCalcSize-nCurSize;
+ if ( nSizeDelta )
+ {
+ nAbsItems = 0;
+ nSizeWinSize = 0;
+ nNewSizeWinSize = 0;
+
+ // Zuerst die absoluten Items relativ resizen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !(pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ {
+ nAbsItems++;
+ nSizeWinSize += pItems[i].mnPixSize;
+ }
+ }
+ }
+ // Rundungsfehler werden hier nicht ausgelichen
+ if ( (nAbsItems < (USHORT)(Abs( nSizeDelta ))) && nSizeWinSize )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !(pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ {
+ pItems[i].mnPixSize += (nSizeDelta*pItems[i].mnPixSize)/nSizeWinSize;
+ nNewSizeWinSize += pItems[i].mnPixSize;
+ }
+ }
+ }
+ nSizeDelta -= nNewSizeWinSize-nSizeWinSize;
+ }
+
+ // Jetzt die Rundunsfehler ausgleichen
+ j = 0;
+ nMins = 0;
+ while ( nSizeDelta && (nItems != nMins) )
+ {
+ // Feststellen, welche Items berechnet werden duerfen
+ nCalcItems = 0;
+ while ( !nCalcItems )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mbSubSize = FALSE;
+
+ if ( j >= 2 )
+ pItems[i].mbSubSize = TRUE;
+ else
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( (nSizeDelta > 0) || pItems[i].mnPixSize )
+ {
+ if ( j >= 1 )
+ pItems[i].mbSubSize = TRUE;
+ else
+ {
+ if ( (j == 0) && (pItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE)) )
+ pItems[i].mbSubSize = TRUE;
+ }
+ }
+ }
+ }
+
+ if ( pItems[i].mbSubSize )
+ nCalcItems++;
+ }
+
+ j++;
+ }
+
+ // Groessen von den einzelnen Items abziehen
+ nErrorSum = nSizeDelta % nCalcItems;
+ nCurSizeDelta = nSizeDelta / nCalcItems;
+ nMins = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ nMins++;
+ else if ( pItems[i].mbSubSize )
+ {
+ pSize = &(pItems[i].mnPixSize);
+
+ if ( nErrorSum )
+ {
+ if ( nErrorSum < 0 )
+ nTempErr = -1;
+ else
+ nTempErr = 1;
+ }
+ else
+ nTempErr = 0;
+
+ if ( (*pSize+nCurSizeDelta+nTempErr) <= 0 )
+ {
+ nTemp = *pSize;
+ if ( nTemp )
+ {
+ *pSize -= nTemp;
+ nSizeDelta += nTemp;
+ }
+ nMins++;
+ }
+ else
+ {
+ *pSize += nCurSizeDelta;
+ nSizeDelta -= nCurSizeDelta;
+ if ( nTempErr && (*pSize || (nTempErr > 0)) )
+ {
+ *pSize += nTempErr;
+ nSizeDelta -= nTempErr;
+ nErrorSum -= nTempErr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ nCurSize += pItems[i].mnPixSize;
+ }
+ }
+
+ // Maximale Groesse berechnen
+ if ( bRows )
+ {
+ nPos = nSetTop;
+ if ( !bDown )
+ nMaxPos = nSetTop-nSetHeight;
+ else
+ nMaxPos = nSetTop+nSetHeight;
+ }
+ else
+ {
+ nPos = nSetLeft;
+ if ( !bDown )
+ nMaxPos = nSetLeft-nSetWidth;
+ else
+ nMaxPos = nSetLeft+nSetWidth;
+ }
+
+ // Fenster anordnen und Werte anpassen
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mnOldSplitPos = pItems[i].mnSplitPos;
+ pItems[i].mnOldSplitSize = pItems[i].mnSplitSize;
+ pItems[i].mnOldWidth = pItems[i].mnWidth;
+ pItems[i].mnOldHeight = pItems[i].mnHeight;
+
+ if ( pItems[i].mnBits & SWIB_INVISIBLE )
+ bEmpty = TRUE;
+ else
+ {
+ bEmpty = FALSE;
+ if ( bDown )
+ {
+ if ( nPos+pItems[i].mnPixSize > nMaxPos )
+ bEmpty = TRUE;
+ }
+ else
+ {
+ nPos -= pItems[i].mnPixSize;
+ if ( nPos < nMaxPos )
+ bEmpty = TRUE;
+ }
+ }
+
+ if ( bEmpty )
+ {
+ pItems[i].mnWidth = 0;
+ pItems[i].mnHeight = 0;
+ pItems[i].mnSplitSize = 0;
+ }
+ else
+ {
+ if ( bRows )
+ {
+ pItems[i].mnLeft = nSetLeft;
+ pItems[i].mnTop = nPos;
+ pItems[i].mnWidth = nSetWidth;
+ pItems[i].mnHeight = pItems[i].mnPixSize;
+ }
+ else
+ {
+ pItems[i].mnLeft = nPos;
+ pItems[i].mnTop = nSetTop;
+ pItems[i].mnWidth = pItems[i].mnPixSize;
+ pItems[i].mnHeight = nSetHeight;
+ }
+
+ if ( i > nItems-1 )
+ pItems[i].mnSplitSize = 0;
+ else
+ {
+ pItems[i].mnSplitSize = pSet->mnSplitSize;
+ if ( bDown )
+ {
+ pItems[i].mnSplitPos = nPos+pItems[i].mnPixSize;
+ if ( pItems[i].mnSplitPos+pItems[i].mnSplitSize > nMaxPos )
+ pItems[i].mnSplitSize = nMaxPos-pItems[i].mnSplitPos;
+ }
+ else
+ {
+ pItems[i].mnSplitPos = nPos-pSet->mnSplitSize;
+ if ( pItems[i].mnSplitPos < nMaxPos )
+ pItems[i].mnSplitSize = pItems[i].mnSplitPos+pSet->mnSplitSize-nMaxPos;
+ }
+ }
+ }
+
+ if ( !(pItems[i].mnBits & SWIB_INVISIBLE) )
+ {
+ if ( !bDown )
+ nPos -= pSet->mnSplitSize;
+ else
+ nPos += pItems[i].mnPixSize+pSet->mnSplitSize;
+ }
+ }
+
+ // Sub-Set's berechnen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet && pItems[i].mnWidth && pItems[i].mnHeight )
+ {
+ ImplCalcSet( pItems[i].mpSet,
+ pItems[i].mnLeft, pItems[i].mnTop,
+ pItems[i].mnWidth, pItems[i].mnHeight,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ }
+
+ // Fixed setzen
+ for ( i = 0; i < nItems; i++ )
+ {
+ pItems[i].mbFixed = FALSE;
+ if ( pItems[i].mnBits & SWIB_FIXED )
+ pItems[i].mbFixed = TRUE;
+ else
+ {
+ // Wenn Child-Set vorhanden, ist dieses Item auch Fixed, wenn
+ // ein Child fixed ist
+ if ( pItems[i].mpSet )
+ {
+ for ( j = 0; j < pItems[i].mpSet->mnItems; j++ )
+ {
+ if ( pItems[i].mpSet->mpItems[j].mbFixed )
+ {
+ pItems[i].mbFixed = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcSet2( SplitWindow* pWindow, ImplSplitSet* pSet, BOOL bHide,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ if ( pWindow->IsReallyVisible() && pWindow->IsUpdateMode() && pWindow->mbInvalidate )
+ {
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ // Evt. alles invalidieren oder nur einen kleinen Teil
+ if ( (pItems[i].mnOldSplitPos != pItems[i].mnSplitPos) ||
+ (pItems[i].mnOldSplitSize != pItems[i].mnSplitSize) ||
+ (pItems[i].mnOldWidth != pItems[i].mnWidth) ||
+ (pItems[i].mnOldHeight != pItems[i].mnHeight) )
+ {
+ Rectangle aRect;
+
+ // Old Rect invalidieren
+ if ( bRows )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnOldWidth-1;
+ aRect.Top() = pItems[i].mnOldSplitPos;
+ aRect.Bottom() = aRect.Top() + pItems[i].mnOldSplitSize;
+ }
+ else
+ {
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnOldHeight-1;
+ aRect.Left() = pItems[i].mnOldSplitPos;
+ aRect.Right() = aRect.Left() + pItems[i].mnOldSplitSize;
+ }
+ pWindow->Invalidate( aRect );
+ // New Rect invalidieren
+ if ( bRows )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ aRect.Top() = pItems[i].mnSplitPos;
+ aRect.Bottom() = aRect.Top() + pItems[i].mnSplitSize;
+ }
+ else
+ {
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnHeight-1;
+ aRect.Left() = pItems[i].mnSplitPos;
+ aRect.Right() = aRect.Left() + pItems[i].mnSplitSize;
+ }
+ pWindow->Invalidate( aRect );
+
+ // Leere Sets komplett invalidieren, da diese Flaechen
+ // nicht von Fenstern ueberladen werden
+ if ( pItems[i].mpSet && !pItems[i].mpSet->mpItems )
+ {
+ aRect.Left() = pItems[i].mnLeft;
+ aRect.Top() = pItems[i].mnTop;
+ aRect.Right() = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ aRect.Bottom() = pItems[i].mnTop+pItems[i].mnHeight-1;
+ pWindow->Invalidate( aRect );
+ }
+ }
+ }
+ }
+ }
+
+ // Fenster positionieren
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ BOOL bTempHide = bHide;
+ if ( !pItems[i].mnWidth || !pItems[i].mnHeight )
+ bTempHide = TRUE;
+ ImplCalcSet2( pWindow, pItems[i].mpSet, bTempHide,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+ else
+ {
+ if ( pItems[i].mnWidth && pItems[i].mnHeight && !bHide )
+ {
+ Point aPos( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ pItems[i].mpWindow->SetPosSizePixel( aPos, aSize );
+ }
+ else
+ pItems[i].mpWindow->Hide();
+ }
+ }
+
+ // Fenster anzeigen und Flag zuruecksetzen
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpWindow && pItems[i].mnWidth && pItems[i].mnHeight && !bHide )
+ pItems[i].mpWindow->Show();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcLogSize( ImplSplitItem* pItems, USHORT nItems )
+{
+ // Original-Groessen updaten
+ USHORT i;
+ long nRelSize = 0;
+ long nPerSize = 0;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ nRelSize += pItems[i].mnPixSize;
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ nPerSize += pItems[i].mnPixSize;
+ }
+ nPerSize += nRelSize;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mnBits & SWIB_RELATIVESIZE )
+ {
+ if ( nRelSize )
+ pItems[i].mnSize = (pItems[i].mnPixSize+(nRelSize/2))/nRelSize;
+ else
+ pItems[i].mnSize = 1;
+ }
+ else if ( pItems[i].mnBits & SWIB_PERCENTSIZE )
+ {
+ if ( nPerSize )
+ pItems[i].mnSize = (pItems[i].mnPixSize*100)/nPerSize;
+ else
+ pItems[i].mnSize = 1;
+ }
+ else
+ pItems[i].mnSize = pItems[i].mnPixSize;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBack( SplitWindow* pWindow, const Rectangle& rRect,
+ const Wallpaper* pWall, const Bitmap* pBitmap )
+{
+ if ( pBitmap )
+ {
+ Point aPos = rRect.TopLeft();
+ Size aBmpSize = pBitmap->GetSizePixel();
+ pWindow->Push( PUSH_CLIPREGION );
+ pWindow->IntersectClipRegion( rRect );
+ do
+ {
+ aPos.X() = rRect.Left();
+ do
+ {
+ pWindow->DrawBitmap( aPos, *pBitmap );
+ aPos.X() += aBmpSize.Width();
+ }
+ while ( aPos.X() < rRect.Right() );
+ aPos.Y() += aBmpSize.Height();
+ }
+ while ( aPos.Y() < rRect.Bottom() );
+ pWindow->Pop();
+ }
+ else
+ pWindow->DrawWallpaper( rRect, *pWall );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBack( SplitWindow* pWindow, ImplSplitSet* pSet )
+{
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ // Beim Mainset auch den Hintergrund zeichnen
+ if ( pSet->mnId == 0 )
+ {
+ if ( pSet->mpBitmap )
+ {
+ Rectangle aRect( pWindow->mnLeftBorder,
+ pWindow->mnTopBorder,
+ pWindow->mnDX-pWindow->mnRightBorder-1,
+ pWindow->mnDY-pWindow->mnBottomBorder-1 );
+ ImplDrawBack( pWindow, aRect, pSet->mpWallpaper, pSet->mpBitmap );
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ pSet = pItems[i].mpSet;
+ if ( pSet )
+ {
+ if ( pSet->mpBitmap || pSet->mpWallpaper )
+ {
+ // Wegen ICC auftrennen
+ Point aPoint( pItems[i].mnLeft, pItems[i].mnTop );
+ Size aSize( pItems[i].mnWidth, pItems[i].mnHeight );
+ Rectangle aRect( aPoint, aSize );
+ ImplDrawBack( pWindow, aRect, pSet->mpWallpaper, pSet->mpBitmap );
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ ImplDrawBack( pWindow, pItems[i].mpSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawSplit( SplitWindow* pWindow, ImplSplitSet* pSet,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ if ( !pSet->mpItems )
+ return;
+
+ USHORT i;
+ USHORT nItems = pSet->mnItems;
+ long nPos;
+ long nTop;
+ long nBottom;
+ ImplSplitItem* pItems = pSet->mpItems;
+ const StyleSettings& rStyleSettings = pWindow->GetSettings().GetStyleSettings();
+
+ BOOL bFlat = (pWindow->GetStyle() & WB_FLATSPLITDRAW) == WB_FLATSPLITDRAW;
+
+ for ( i = 0; i < nItems-1; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ nPos = pItems[i].mnSplitPos;
+
+ long nItemSplitSize = pItems[i].mnSplitSize;
+ long nSplitSize = pSet->mnSplitSize;
+ if ( bRows )
+ {
+ nTop = pItems[i].mnLeft;
+ nBottom = pItems[i].mnLeft+pItems[i].mnWidth-1;
+
+ if ( bFlat ) nPos--;
+
+ if ( bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetLightColor() );
+ pWindow->DrawLine( Point( nTop, nPos+1 ), Point( nBottom, nPos+1 ) );
+ }
+ nPos += nSplitSize-2;
+ if ( bFlat ) nPos+=2;
+ if ( (!bDown && (nItemSplitSize >= 2)) ||
+ (bDown && (nItemSplitSize >= nSplitSize-1)) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWindow->DrawLine( Point( nTop, nPos ), Point( nBottom, nPos ) );
+ }
+ if ( !bFlat )
+ {
+ nPos++;
+ if ( !bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pWindow->DrawLine( Point( nTop, nPos ), Point( nBottom, nPos ) );
+ }
+ }
+ }
+ else
+ {
+ nTop = pItems[i].mnTop;
+ nBottom = pItems[i].mnTop+pSet->mpItems[i].mnHeight-1;
+
+ if ( bFlat ) nPos--;
+ if ( bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetLightColor() );
+ pWindow->DrawLine( Point( nPos+1, nTop ), Point( nPos+1, nBottom ) );
+ }
+ nPos += pSet->mnSplitSize-2;
+ if ( bFlat ) nPos+=2;
+ if ( (!bDown && (nItemSplitSize >= 2)) ||
+ (bDown && (nItemSplitSize >= nSplitSize-1)) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWindow->DrawLine( Point( nPos, nTop ), Point( nPos, nBottom ) );
+ }
+ if( !bFlat )
+ {
+ nPos++;
+ if ( !bDown || (nItemSplitSize >= nSplitSize) )
+ {
+ pWindow->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pWindow->DrawLine( Point( nPos, nTop ), Point( nPos, nBottom ) );
+ }
+ }
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet && pItems[i].mnWidth && pItems[i].mnHeight )
+ ImplDrawSplit( pWindow, pItems[i].mpSet, ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplTestSplit( ImplSplitSet* pSet, const Point& rPos,
+ long& rMouseOff, ImplSplitSet** ppFoundSet, USHORT& rFoundPos,
+ BOOL bRows, BOOL bDown = TRUE )
+{
+ if ( !pSet->mpItems )
+ return 0;
+
+ USHORT i;
+ USHORT nSplitTest;
+ USHORT nItems = pSet->mnItems;
+ long nMPos1;
+ long nMPos2;
+ long nPos;
+ long nTop;
+ long nBottom;
+ ImplSplitItem* pItems = pSet->mpItems;
+
+ if ( bRows )
+ {
+ nMPos1 = rPos.X();
+ nMPos2 = rPos.Y();
+ }
+ else
+ {
+ nMPos1 = rPos.Y();
+ nMPos2 = rPos.X();
+ }
+
+ for ( i = 0; i < nItems-1; i++ )
+ {
+ if ( pItems[i].mnSplitSize )
+ {
+ if ( bRows )
+ {
+ nTop = pItems[i].mnLeft;
+ nBottom = pItems[i].mnLeft+pItems[i].mnWidth-1;
+ }
+ else
+ {
+ nTop = pItems[i].mnTop;
+ nBottom = pItems[i].mnTop+pItems[i].mnHeight-1;
+ }
+ nPos = pItems[i].mnSplitPos;
+
+ if ( (nMPos1 >= nTop) && (nMPos1 <= nBottom) &&
+ (nMPos2 >= nPos) && (nMPos2 <= nPos+pItems[i].mnSplitSize) )
+ {
+ if ( !pItems[i].mbFixed && !pItems[i+1].mbFixed )
+ {
+ rMouseOff = nMPos2-nPos;
+ *ppFoundSet = pSet;
+ rFoundPos = i;
+ if ( bRows )
+ return SPLIT_VERT;
+ else
+ return SPLIT_HORZ;
+ }
+ else
+ return SPLIT_NOSPLIT;
+ }
+ }
+ }
+
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mpSet )
+ {
+ nSplitTest = ImplTestSplit( pItems[i].mpSet, rPos,
+ rMouseOff, ppFoundSet, rFoundPos,
+ ((pItems[i].mnBits & SWIB_COLSET) == 0) );
+ if ( nSplitTest )
+ return nSplitTest;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplTestSplit( SplitWindow* pWindow, const Point& rPos,
+ long& rMouseOff, ImplSplitSet** ppFoundSet, USHORT& rFoundPos )
+{
+ // Resizeable SplitWindow muss anders behandelt werden
+ if ( pWindow->mnWinStyle & WB_SIZEABLE )
+ {
+ long nTPos;
+ long nPos;
+ long nBorder;
+
+ if ( pWindow->mbHorz )
+ {
+ if ( pWindow->mbBottomRight )
+ {
+ nBorder = pWindow->mnBottomBorder;
+ nPos = 0;
+ }
+ else
+ {
+ nBorder = pWindow->mnTopBorder;
+ nPos = pWindow->mnDY-nBorder;
+ }
+ nTPos = rPos.Y();
+ }
+ else
+ {
+ if ( pWindow->mbBottomRight )
+ {
+ nBorder = pWindow->mnRightBorder;
+ nPos = 0;
+ }
+ else
+ {
+ nBorder = pWindow->mnLeftBorder;
+ nPos = pWindow->mnDX-nBorder;
+ }
+ nTPos = rPos.X();
+ }
+ long nSplitSize = pWindow->mpMainSet->mnSplitSize-2;
+ if ( pWindow->mbAutoHide || pWindow->mbFadeOut )
+ nSplitSize += SPLITWIN_SPLITSIZEEX;
+ if ( !pWindow->mbBottomRight )
+ nPos -= nSplitSize;
+ if ( (nTPos >= nPos) && (nTPos <= nPos+nSplitSize+nBorder) )
+ {
+ rMouseOff = nTPos-nPos;
+ *ppFoundSet = pWindow->mpMainSet;
+ if ( pWindow->mpMainSet->mpItems )
+ rFoundPos = pWindow->mpMainSet->mnItems-1;
+ else
+ rFoundPos = 0;
+ if ( pWindow->mbHorz )
+ return SPLIT_VERT | SPLIT_WINDOW;
+ else
+ return SPLIT_HORZ | SPLIT_WINDOW;
+ }
+ }
+
+ return ImplTestSplit( pWindow->mpMainSet, rPos, rMouseOff, ppFoundSet, rFoundPos,
+ pWindow->mbHorz, !pWindow->mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawSplitTracking( SplitWindow* pThis, const Point& rPos )
+{
+ Rectangle aRect;
+
+ if ( pThis->mnSplitTest & SPLIT_HORZ )
+ {
+ aRect.Top() = pThis->maDragRect.Top();
+ aRect.Bottom() = pThis->maDragRect.Bottom();
+ aRect.Left() = rPos.X();
+ aRect.Right() = aRect.Left()+pThis->mpSplitSet->mnSplitSize-1;
+ if ( !(pThis->mnWinStyle & WB_NOSPLITDRAW) )
+ aRect.Right()--;
+ if ( (pThis->mnSplitTest & SPLIT_WINDOW) &&
+ (pThis->mbAutoHide || pThis->mbFadeOut) )
+ {
+ aRect.Left() += SPLITWIN_SPLITSIZEEX;
+ aRect.Right() += SPLITWIN_SPLITSIZEEX;
+ }
+ }
+ else
+ {
+ aRect.Left() = pThis->maDragRect.Left();
+ aRect.Right() = pThis->maDragRect.Right();
+ aRect.Top() = rPos.Y();
+ aRect.Bottom() = aRect.Top()+pThis->mpSplitSet->mnSplitSize-1;
+ if ( !(pThis->mnWinStyle & WB_NOSPLITDRAW) )
+ aRect.Bottom()--;
+ if ( (pThis->mnSplitTest & SPLIT_WINDOW) &&
+ (pThis->mbAutoHide || pThis->mbFadeOut) )
+ {
+ aRect.Top() += SPLITWIN_SPLITSIZEEX;
+ aRect.Bottom() += SPLITWIN_SPLITSIZEEX;
+ }
+ }
+ pThis->ShowTracking( aRect, SHOWTRACK_SPLIT );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+ ImplSplitSet* pNewSet = new ImplSplitSet;
+ pNewSet->mpItems = NULL;
+ pNewSet->mpWallpaper = NULL;
+ pNewSet->mpBitmap = NULL;
+ pNewSet->mnLastSize = 0;
+ pNewSet->mnItems = 0;
+ pNewSet->mnId = 0;
+ pNewSet->mnSplitSize = SPLITWIN_SPLITSIZE;
+ pNewSet->mbCalcPix = TRUE;
+
+ mpMainSet = pNewSet;
+ mpBaseSet = pNewSet;
+ mpSplitSet = NULL;
+ mpLastSizes = NULL;
+ mnDX = 0;
+ mnDY = 0;
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ mnMaxSize = 0;
+ mnMouseOff = 0;
+ meAlign = WINDOWALIGN_TOP;
+ mnWinStyle = nStyle;
+ mnSplitTest = 0;
+ mnSplitPos = 0;
+ mnMouseModifier = 0;
+ mnMStartPos = 0;
+ mnMSplitPos = 0;
+ mbDragFull = FALSE;
+ mbHorz = TRUE;
+ mbBottomRight = FALSE;
+ mbCalc = FALSE;
+ mbRecalc = TRUE;
+ mbInvalidate = TRUE;
+ mbAutoHide = FALSE;
+ mbFadeIn = FALSE;
+ mbFadeOut = FALSE;
+ mbAutoHideIn = FALSE;
+ mbAutoHideDown = FALSE;
+ mbFadeInDown = FALSE;
+ mbFadeOutDown = FALSE;
+ mbAutoHidePressed = FALSE;
+ mbFadeInPressed = FALSE;
+ mbFadeOutPressed = FALSE;
+ mbFadeNoButtonMode = FALSE;
+ mbNoAlign = FALSE;
+
+ if ( nStyle & WB_NOSPLITDRAW )
+ {
+ pNewSet->mnSplitSize -= 2;
+ mbInvalidate = FALSE;
+ }
+
+ if ( nStyle & WB_BORDER )
+ {
+ ImplCalcBorder( meAlign, mbNoAlign, mnLeftBorder, mnTopBorder,
+ mnRightBorder, mnBottomBorder );
+ }
+ else
+ {
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ }
+
+ DockingWindow::ImplInit( pParent, (nStyle | WB_CLIPCHILDREN) & ~(WB_BORDER | WB_SIZEABLE) );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplInitSettings()
+{
+ // Wenn fuer das MainSet eine Bitmap gesetzt wird, dann
+ // brauchen wir nicht mehr den Hintergrund loeschen
+ // Wenn MainSet Wallpaper hat, dann ist das der Hintergrund, ansonsten
+ // sind es die Standard-Farben
+ if ( mpMainSet->mpBitmap )
+ SetBackground();
+ else if ( mpMainSet->mpWallpaper )
+ SetBackground( *mpMainSet->mpWallpaper );
+ else
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ }
+}
+
+// =======================================================================
+
+SplitWindow::SplitWindow( Window* pParent, WinBits nStyle ) :
+ DockingWindow( WINDOW_SPLITWINDOW )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindow::SplitWindow( Window* pParent, const ResId& rResId ) :
+ DockingWindow( WINDOW_SPLITWINDOW )
+{
+ rResId.SetRT( RSC_SPLITWINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindow::~SplitWindow()
+{
+ // Sets loeschen
+ ImplDeleteSet( mpMainSet );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplSetWindowSize( long nDelta )
+{
+ if ( !nDelta )
+ return;
+
+ Size aSize = GetSizePixel();
+ if ( meAlign == WINDOWALIGN_TOP )
+ {
+ aSize.Height() += nDelta;
+ SetSizePixel( aSize );
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ Point aPos = GetPosPixel();
+ aPos.Y() -= nDelta;
+ aSize.Height() += nDelta;
+ SetPosSizePixel( aPos, aSize );
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ aSize.Width() += nDelta;
+ SetSizePixel( aSize );
+ }
+ else // meAlign == WINDOWALIGN_RIGHT
+ {
+ Point aPos = GetPosPixel();
+ aPos.X() -= nDelta;
+ aSize.Width() += nDelta;
+ SetPosSizePixel( aPos, aSize );
+ }
+
+ SplitResize();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplCalcLayout()
+{
+ if ( !mbCalc || !mbRecalc || !mpMainSet->mpItems )
+ return;
+
+ long nSplitSize = mpMainSet->mnSplitSize-2;
+ if ( mbAutoHide || mbFadeOut )
+ nSplitSize += SPLITWIN_SPLITSIZEEX;
+
+ // Wenn Fenster sizeable ist, wird die groesse automatisch nach
+ // dem MainSet festgelegt, wenn kein relatives Fenster enthalten
+ // ist
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ long nCurSize;
+ long nCalcSize = 0;
+ USHORT i;
+
+ for ( i = 0; i < mpMainSet->mnItems; i++ )
+ {
+ if ( mpMainSet->mpItems[i].mnBits & (SWIB_RELATIVESIZE | SWIB_PERCENTSIZE) )
+ break;
+ else
+ nCalcSize += mpMainSet->mpItems[i].mnSize;
+ }
+
+ if ( i == mpMainSet->mnItems )
+ {
+ if ( mbHorz )
+ nCurSize = mnDY-mnTopBorder-mnBottomBorder;
+ else
+ nCurSize = mnDX-mnLeftBorder-mnRightBorder;
+ nCurSize -= nSplitSize;
+ nCurSize -= (mpMainSet->mnItems-1)*mpMainSet->mnSplitSize;
+
+ mbRecalc = FALSE;
+ ImplSetWindowSize( nCalcSize-nCurSize );
+ mbRecalc = TRUE;
+ }
+ }
+
+ if ( (mnDX <= 0) || (mnDY <= 0) )
+ return;
+
+ // Groessen/Position vorberechnen
+ long nL;
+ long nT;
+ long nW;
+ long nH;
+
+ if ( mbHorz )
+ {
+ if ( mbBottomRight )
+ nT = mnDY-mnBottomBorder;
+ else
+ nT = mnTopBorder;
+ nL = mnLeftBorder;
+ }
+ else
+ {
+ if ( mbBottomRight )
+ nL = mnDX-mnRightBorder;
+ else
+ nL = mnLeftBorder;
+ nT = mnTopBorder;
+ }
+ nW = mnDX-mnLeftBorder-mnRightBorder;
+ nH = mnDY-mnTopBorder-mnBottomBorder;
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ if ( mbHorz )
+ nH -= nSplitSize;
+ else
+ nW -= nSplitSize;
+ }
+
+ // Sets rekursiv berechnen
+ ImplCalcSet( mpMainSet, nL, nT, nW, nH, mbHorz, !mbBottomRight );
+ ImplCalcSet2( this, mpMainSet, FALSE, mbHorz, !mbBottomRight );
+ mbCalc = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplUpdate()
+{
+ mbCalc = TRUE;
+
+ if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
+ {
+ if ( mpMainSet->mpItems )
+ ImplCalcLayout();
+ else
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplUpdateSet( ImplSplitSet* pSet )
+{
+ if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
+ {
+ // Wenn wir noch berechnen muessen, dann alles invalidieren.
+ if ( mbCalc )
+ {
+ // Wenn nicht NOSPLITDRAW gesetzt ist, koennen wir uns das
+ // invalidieren sparen, da bei ImplCalcSet2() die freien flaechen
+ // sowieso invalidiert werden
+ if ( !mpMainSet->mpItems || (mnWinStyle & WB_NOSPLITDRAW) )
+ pSet = mpMainSet;
+ else
+ return;
+ }
+
+ Rectangle aRect;
+ if ( pSet == mpMainSet )
+ {
+ aRect.Left() = mnLeftBorder;
+ aRect.Top() = mnTopBorder;
+ aRect.Right() = mnDX-mnRightBorder-1;
+ aRect.Bottom() = mnDY-mnBottomBorder-1;
+ }
+ else
+ {
+ ImplSplitItem* pItem;
+ USHORT nPos;
+
+ pSet = ImplFindItem( mpMainSet, pSet->mnId, nPos );
+ pItem = &(pSet->mpItems[nPos]);
+ aRect.Left() = pItem->mnLeft;
+ aRect.Top() = pItem->mnTop;
+ aRect.Right() = aRect.Left()+pItem->mnWidth;
+ aRect.Bottom() = aRect.Top()+pItem->mnHeight;
+ }
+ Invalidate( aRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplSplitMousePos( Point& rMousePos )
+{
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ rMousePos.X() -= mnMouseOff;
+ if ( rMousePos.X() < maDragRect.Left() )
+ rMousePos.X() = maDragRect.Left();
+ else if ( rMousePos.X()+mpSplitSet->mnSplitSize+1 > maDragRect.Right() )
+ rMousePos.X() = maDragRect.Right()-mpSplitSet->mnSplitSize+1;
+ // Wegen FullDrag in Screen-Koordinaaten merken
+ mnMSplitPos = OutputToScreenPixel( rMousePos ).X();
+ }
+ else
+ {
+ rMousePos.Y() -= mnMouseOff;
+ if ( rMousePos.Y() < maDragRect.Top() )
+ rMousePos.Y() = maDragRect.Top();
+ else if ( rMousePos.Y()+mpSplitSet->mnSplitSize+1 > maDragRect.Bottom() )
+ rMousePos.Y() = maDragRect.Bottom()-mpSplitSet->mnSplitSize+1;
+ mnMSplitPos = OutputToScreenPixel( rMousePos ).Y();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetButtonRect( Rectangle& rRect, long nEx, BOOL bTest ) const
+{
+ long nSplitSize = mpMainSet->mnSplitSize-2;
+ if ( mbAutoHide || mbFadeOut || mbFadeIn )
+ nSplitSize += SPLITWIN_SPLITSIZEEX;
+
+/* Wir wollen doch erstmal nicht zentrieren
+ long nButtonSize = 0;
+ if ( mbFadeIn )
+ nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
+ if ( mbFadeOut )
+ nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
+ if ( mbAutoHide )
+ nButtonSize += SPLITWIN_SPLITSIZEAUTOHIDE+1;
+ long nCenterEx = 0;
+ if ( mbHorz )
+ nCenterEx += ((mnDX-mnLeftBorder-mnRightBorder)-nButtonSize)/2;
+ else
+ nCenterEx += ((mnDY-mnTopBorder-mnBottomBorder)-nButtonSize)/2;
+ if ( nCenterEx > 0 )
+ nEx += nCenterEx;
+*/
+
+ if ( meAlign == WINDOWALIGN_TOP )
+ {
+ rRect.Left() = mnLeftBorder+nEx;
+ rRect.Top() = mnDY-mnBottomBorder-nSplitSize;
+ rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ rRect.Bottom() = mnDY-mnBottomBorder-1;
+ if ( bTest )
+ {
+ rRect.Top() -= mnTopBorder;
+ rRect.Bottom() += mnBottomBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ rRect.Left() = mnLeftBorder+nEx;
+ rRect.Top() = mnTopBorder;
+ rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ rRect.Bottom() = mnTopBorder+nSplitSize-1;
+ if ( bTest )
+ {
+ rRect.Top() -= mnTopBorder;
+ rRect.Bottom() += mnBottomBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ rRect.Left() = mnDX-mnRightBorder-nSplitSize;
+ rRect.Top() = mnTopBorder+nEx;
+ rRect.Right() = mnDX-mnRightBorder-1;
+ rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ if ( bTest )
+ {
+ rRect.Left() -= mnLeftBorder;
+ rRect.Right() += mnRightBorder;
+ }
+ }
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ {
+ rRect.Left() = mnLeftBorder;
+ rRect.Top() = mnTopBorder+nEx;
+ rRect.Right() = mnLeftBorder+nSplitSize-1;
+ rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
+ if ( bTest )
+ {
+ rRect.Left() -= mnLeftBorder;
+ rRect.Right() += mnRightBorder;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetAutoHideRect( Rectangle& rRect, BOOL bTest ) const
+{
+ Rectangle aRect;
+
+ if ( mbAutoHide )
+ {
+ long nEx = 0;
+ if ( mbFadeIn || mbFadeOut )
+ nEx = SPLITWIN_SPLITSIZEFADE+1;
+ ImplGetButtonRect( aRect, nEx, bTest && mbFadeIn );
+ }
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetFadeInRect( Rectangle& rRect, BOOL bTest ) const
+{
+ Rectangle aRect;
+
+ if ( mbFadeIn )
+ ImplGetButtonRect( aRect, 0, bTest );
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplGetFadeOutRect( Rectangle& rRect, BOOL ) const
+{
+ Rectangle aRect;
+
+ if ( mbFadeOut )
+ ImplGetButtonRect( aRect, 0, FALSE );
+
+ rRect = aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawButtonRect( const Rectangle& rRect, long nSize )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( mbHorz )
+ {
+ long nLeft = rRect.Left();
+ long nRight = rRect.Right();
+ long nCenter = rRect.Center().Y();
+ long nEx1 = nLeft+((rRect.GetWidth()-nSize)/2)-2;
+ long nEx2 = nEx1+nSize+3;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
+ long i = nLeft+2;
+ while ( i < nRight-3 )
+ {
+ if ( (i < nEx1) || (i > nEx2 ) )
+ {
+ DrawPixel( Point( i, nCenter-2 ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( i+1, nCenter-2+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i++;
+ if ( (i < nEx1) || (i > nEx2 ) && (i < nRight-3) )
+ {
+ DrawPixel( Point( i, nCenter+2 ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( i+1, nCenter+2+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i += 2;
+ }
+ }
+ else
+ {
+ long nTop = rRect.Top();
+ long nBottom = rRect.Bottom();
+ long nCenter = rRect.Center().X();
+ long nEx1 = nTop+((rRect.GetHeight()-nSize)/2)-2;
+ long nEx2 = nEx1+nSize+3;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
+ DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
+ DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
+ long i = nTop+2;
+ while ( i < nBottom-3 )
+ {
+ if ( (i < nEx1) || (i > nEx2 ) )
+ {
+ DrawPixel( Point( nCenter-2, i ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( nCenter-2+1, i+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i++;
+ if ( (i < nEx1) || (i > nEx2 ) && (i < nBottom-3) )
+ {
+ DrawPixel( Point( nCenter+2, i ), rStyleSettings.GetLightColor() );
+ DrawPixel( Point( nCenter+2+1, i+1 ), rStyleSettings.GetShadowColor() );
+ }
+ i += 2;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawAutoHide( BOOL bInPaint )
+{
+ if ( mbAutoHide )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aTempRect;
+ ImplGetAutoHideRect( aTempRect );
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ // ImageListe laden, wenn noch nicht vorhanden
+ ImplSVData* pSVData = ImplGetSVData();
+ ImageList* pImageList;
+ if ( mbHorz )
+ {
+ if ( !pSVData->maCtrlData.mpSplitHPinImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_SPLITHPIN, ImplGetResMgr() ) );
+ pSVData->maCtrlData.mpSplitHPinImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 4 );
+ }
+ pImageList = pSVData->maCtrlData.mpSplitHPinImgList;
+ }
+ else
+ {
+ if ( !pSVData->maCtrlData.mpSplitVPinImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_SPLITVPIN, ImplGetResMgr() ) );
+ pSVData->maCtrlData.mpSplitVPinImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 4 );
+ }
+ pImageList = pSVData->maCtrlData.mpSplitVPinImgList;
+ }
+
+ // Image ermitteln und zurueckgeben
+ USHORT nId;
+ if ( mbAutoHidePressed )
+ {
+ if ( mbAutoHideIn )
+ nId = 3;
+ else
+ nId = 4;
+ }
+ else
+ {
+ if ( mbAutoHideIn )
+ nId = 1;
+ else
+ nId = 2;
+ }
+
+ Image aImage = pImageList->GetImage( nId );
+ Size aImageSize = aImage.GetSizePixel();
+ Point aPos( aTempRect.Left()+((aTempRect.GetWidth()-aImageSize.Width())/2),
+ aTempRect.Top()+((aTempRect.GetHeight()-aImageSize.Height())/2) );
+ long nSize;
+ if ( mbHorz )
+ nSize = aImageSize.Width();
+ else
+ nSize = aImageSize.Height();
+ ImplDrawButtonRect( aTempRect, nSize );
+ DrawImage( aPos, aImage );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetSplitArrowImage( BOOL bHorz, BOOL bLeft, BOOL bPressed,
+ Image& rImage )
+{
+ // ImageListe laden, wenn noch nicht vorhanden
+ ImplSVData* pSVData = ImplGetSVData();
+ ImageList* pImageList;
+ if ( bHorz )
+ {
+ if ( !pSVData->maCtrlData.mpSplitHArwImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_SPLITHARW, ImplGetResMgr() ) );
+ pSVData->maCtrlData.mpSplitHArwImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 4 );
+ }
+ pImageList = pSVData->maCtrlData.mpSplitHArwImgList;
+ }
+ else
+ {
+ if ( !pSVData->maCtrlData.mpSplitVArwImgList )
+ {
+ Bitmap aBmp( ResId( SV_RESID_BITMAP_SPLITVARW, ImplGetResMgr() ) );
+ pSVData->maCtrlData.mpSplitVArwImgList = new ImageList( aBmp, Color( 0x00, 0x00, 0xFF ), 4 );
+ }
+ pImageList = pSVData->maCtrlData.mpSplitVArwImgList;
+ }
+
+ // Image ermitteln und zurueckgeben
+ USHORT nId = 1;
+ if ( !bLeft )
+ nId += 2;
+ if ( bPressed )
+ nId++;
+
+ rImage = pImageList->GetImage( nId );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawFadeIn( BOOL bInPaint )
+{
+ if ( mbFadeIn )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aTempRect;
+ Image aImage;
+ ImplGetFadeInRect( aTempRect );
+
+ BOOL bLeft;
+ if ( meAlign == WINDOWALIGN_TOP )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ bLeft = TRUE;
+ ImplGetSplitArrowImage( mbHorz, bLeft, mbFadeInPressed, aImage );
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ Size aImageSize = aImage.GetSizePixel();
+ Point aPos( aTempRect.Left()+((aTempRect.GetWidth()-aImageSize.Width())/2),
+ aTempRect.Top()+((aTempRect.GetHeight()-aImageSize.Height())/2) );
+ long nSize;
+ if ( mbHorz )
+ nSize = aImageSize.Width();
+ else
+ nSize = aImageSize.Height();
+ ImplDrawButtonRect( aTempRect, nSize );
+ DrawImage( aPos, aImage );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplDrawFadeOut( BOOL bInPaint )
+{
+ if ( mbFadeOut )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aTempRect;
+ Image aImage;
+ ImplGetFadeOutRect( aTempRect );
+
+ BOOL bLeft;
+ if ( meAlign == WINDOWALIGN_TOP )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ bLeft = FALSE;
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ bLeft = TRUE;
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ bLeft = FALSE;
+ ImplGetSplitArrowImage( mbHorz, bLeft, mbFadeOutPressed, aImage );
+
+ if ( !bInPaint )
+ Erase( aTempRect );
+
+ Size aImageSize = aImage.GetSizePixel();
+ Point aPos( aTempRect.Left()+((aTempRect.GetWidth()-aImageSize.Width())/2),
+ aTempRect.Top()+((aTempRect.GetHeight()-aImageSize.Height())/2) );
+ long nSize;
+ if ( mbHorz )
+ nSize = aImageSize.Width();
+ else
+ nSize = aImageSize.Height();
+ ImplDrawButtonRect( aTempRect, nSize );
+ DrawImage( aPos, aImage );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::StartSplit()
+{
+ maStartSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Split()
+{
+ maSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SplitResize()
+{
+ maSplitResizeHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::AutoHide()
+{
+ maAutoHideHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::FadeIn()
+{
+ maFadeInHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::FadeOut()
+{
+ maFadeOutHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsLeft() || rMEvt.IsMod2() )
+ {
+ DockingWindow::MouseButtonDown( rMEvt );
+ return;
+ }
+
+ Point aMousePosPixel = rMEvt.GetPosPixel();
+ Rectangle aTestRect;
+
+ mbFadeNoButtonMode = FALSE;
+ ImplGetAutoHideRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbAutoHideDown = TRUE;
+ mbAutoHidePressed = TRUE;
+ ImplDrawAutoHide( FALSE );
+ }
+ else
+ {
+ ImplGetFadeOutRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbFadeOutDown = TRUE;
+ mbFadeOutPressed = TRUE;
+ ImplDrawFadeOut( FALSE );
+ }
+ else
+ {
+ ImplGetFadeInRect( aTestRect, TRUE );
+ if ( aTestRect.IsInside( aMousePosPixel ) )
+ {
+ mbFadeInDown = TRUE;
+ mbFadeInPressed = TRUE;
+ ImplDrawFadeIn( FALSE );
+ }
+ else if ( !aTestRect.IsEmpty() && !(mnWinStyle & WB_SIZEABLE) )
+ {
+ mbFadeNoButtonMode = TRUE;
+ FadeIn();
+ return;
+ }
+ }
+ }
+
+ if ( mbAutoHideDown || mbFadeInDown || mbFadeOutDown )
+ StartTracking();
+ else
+ {
+ mnSplitTest = ImplTestSplit( this, aMousePosPixel, mnMouseOff, &mpSplitSet, mnSplitPos );
+ if ( mnSplitTest && !(mnSplitTest & SPLIT_NOSPLIT) )
+ {
+ ImplSplitItem* pSplitItem;
+ long nCurMaxSize;
+ USHORT nTemp;
+ BOOL bDown;
+ BOOL bPropSmaller;
+
+ mnMouseModifier = rMEvt.GetModifier();
+ if ( !(mnMouseModifier & KEY_SHIFT) || (mnSplitPos+1 >= mpSplitSet->mnItems) )
+ bPropSmaller = FALSE;
+ else
+ bPropSmaller = TRUE;
+
+ // Hier kann noch die maximale Groesse gesetzt werden
+ StartSplit();
+
+ if ( mnMaxSize )
+ nCurMaxSize = mnMaxSize;
+ else
+ {
+ Size aSize = GetParent()->GetOutputSizePixel();
+ if ( mbHorz )
+ nCurMaxSize = aSize.Height();
+ else
+ nCurMaxSize = aSize.Width();
+ }
+
+ if ( mpSplitSet->mpItems )
+ {
+ bDown = TRUE;
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ bDown = FALSE;
+
+ pSplitItem = &(mpSplitSet->mpItems[mnSplitPos]);
+ maDragRect.Left() = pSplitItem->mnLeft;
+ maDragRect.Top() = pSplitItem->mnTop;
+ maDragRect.Right() = pSplitItem->mnLeft+pSplitItem->mnWidth-1;
+ maDragRect.Bottom() = pSplitItem->mnTop+pSplitItem->mnHeight-1;
+
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Right() += mpSplitSet->mnSplitSize;
+ else
+ maDragRect.Left() -= mpSplitSet->mnSplitSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Bottom() += mpSplitSet->mnSplitSize;
+ else
+ maDragRect.Top() -= mpSplitSet->mnSplitSize;
+ }
+
+ if ( mnSplitPos )
+ {
+ nTemp = mnSplitPos;
+ while ( nTemp )
+ {
+ pSplitItem = &(mpSplitSet->mpItems[nTemp-1]);
+ if ( pSplitItem->mbFixed )
+ break;
+ else
+ {
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Left() -= pSplitItem->mnPixSize;
+ else
+ maDragRect.Right() += pSplitItem->mnPixSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Top() -= pSplitItem->mnPixSize;
+ else
+ maDragRect.Bottom() += pSplitItem->mnPixSize;
+ }
+ }
+ nTemp--;
+ }
+ }
+
+ if ( (mpSplitSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) && !bPropSmaller )
+ {
+ if ( bDown )
+ {
+ if ( mbHorz )
+ maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
+ else
+ maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
+ }
+ else
+ {
+ if ( mbHorz )
+ maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
+ else
+ maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
+ }
+ }
+ else
+ {
+ nTemp = mnSplitPos+1;
+ while ( nTemp < mpSplitSet->mnItems )
+ {
+ pSplitItem = &(mpSplitSet->mpItems[nTemp]);
+ if ( pSplitItem->mbFixed )
+ break;
+ else
+ {
+ if ( mnSplitTest & SPLIT_HORZ )
+ {
+ if ( bDown )
+ maDragRect.Right() += pSplitItem->mnPixSize;
+ else
+ maDragRect.Left() -= pSplitItem->mnPixSize;
+ }
+ else
+ {
+ if ( bDown )
+ maDragRect.Bottom() += pSplitItem->mnPixSize;
+ else
+ maDragRect.Top() -= pSplitItem->mnPixSize;
+ }
+ }
+ nTemp++;
+ }
+ }
+ }
+ else
+ {
+ maDragRect.Left() = mnLeftBorder;
+ maDragRect.Top() = mnTopBorder;
+ maDragRect.Right() = mnDX-mnRightBorder-1;
+ maDragRect.Bottom() = mnDY-mnBottomBorder-1;
+ if ( mbHorz )
+ {
+ if ( mbBottomRight )
+ maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
+ else
+ maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
+ }
+ else
+ {
+ if ( mbBottomRight )
+ maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
+ else
+ maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
+ }
+ }
+
+ StartTracking();
+
+ mbDragFull = (GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
+ ImplSplitMousePos( aMousePosPixel );
+ if ( !mbDragFull )
+ ImplDrawSplitTracking( this, aMousePosPixel );
+ else
+ {
+ ImplSplitItem* pItems = mpSplitSet->mpItems;
+ USHORT nItems = mpSplitSet->mnItems;
+ mpLastSizes = new long[nItems*2];
+ for ( USHORT i = 0; i < nItems; i++ )
+ {
+ mpLastSizes[i*2] = pItems[i].mnSize;
+ mpLastSizes[i*2+1] = pItems[i].mnPixSize;
+ }
+ }
+ mnMStartPos = mnMSplitPos;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !IsTracking() )
+ {
+ Point aPos = rMEvt.GetPosPixel();
+ long nTemp;
+ ImplSplitSet* pTempSplitSet;
+ USHORT nTempSplitPos;
+ USHORT nSplitTest = ImplTestSplit( this, aPos, nTemp, &pTempSplitSet, nTempSplitPos );
+ PointerStyle eStyle = POINTER_ARROW;
+ Rectangle aAutoHideRect;
+ Rectangle aFadeInRect;
+ Rectangle aFadeOutRect;
+
+ ImplGetAutoHideRect( aAutoHideRect );
+ ImplGetFadeInRect( aFadeInRect );
+ ImplGetFadeOutRect( aFadeOutRect );
+ if ( !aAutoHideRect.IsInside( aPos ) &&
+ !aFadeInRect.IsInside( aPos ) &&
+ !aFadeOutRect.IsInside( aPos ) )
+ {
+ if ( nSplitTest && !(nSplitTest & SPLIT_NOSPLIT) )
+ {
+ if ( nSplitTest & SPLIT_HORZ )
+ eStyle = POINTER_HSPLIT;
+ else if ( nSplitTest & SPLIT_VERT )
+ eStyle = POINTER_VSPLIT;
+ }
+ }
+
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aMousePosPixel = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( mbAutoHideDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbAutoHideDown = FALSE;
+ if ( mbAutoHidePressed )
+ {
+ mbAutoHidePressed = FALSE;
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ {
+ mbAutoHideIn = !mbAutoHideIn;
+ ImplDrawAutoHide( FALSE );
+ AutoHide();
+ }
+ else
+ ImplDrawAutoHide( FALSE );
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetAutoHideRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed != mbAutoHidePressed )
+ {
+ mbAutoHidePressed = bNewPressed;
+ ImplDrawAutoHide( FALSE );
+ }
+ }
+ }
+ else if ( mbFadeInDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbFadeInDown = FALSE;
+ if ( mbFadeInPressed )
+ {
+ mbFadeInPressed = FALSE;
+ ImplDrawFadeIn( FALSE );
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ FadeIn();
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetFadeInRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed != mbFadeInPressed )
+ {
+ mbFadeInPressed = bNewPressed;
+ ImplDrawFadeIn( FALSE );
+ }
+ }
+ }
+ else if ( mbFadeOutDown )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ mbFadeOutDown = FALSE;
+ if ( mbFadeOutPressed )
+ {
+ mbFadeOutPressed = FALSE;
+ ImplDrawFadeOut( FALSE );
+
+ if ( !rTEvt.IsTrackingCanceled() )
+ FadeOut();
+ }
+ }
+ else
+ {
+ Rectangle aTestRect;
+ ImplGetFadeOutRect( aTestRect, TRUE );
+ BOOL bNewPressed = aTestRect.IsInside( aMousePosPixel );
+ if ( bNewPressed != mbFadeOutPressed )
+ {
+ mbFadeOutPressed = bNewPressed;
+ ImplDrawFadeOut( FALSE );
+ }
+ }
+ }
+ else
+ {
+ ImplSplitMousePos( aMousePosPixel );
+ BOOL bSplit = TRUE;
+ if ( mbDragFull )
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ ImplSplitItem* pItems = mpSplitSet->mpItems;
+ USHORT nItems = mpSplitSet->mnItems;
+ for ( USHORT i = 0; i < nItems; i++ )
+ {
+ pItems[i].mnSize = mpLastSizes[i*2];
+ pItems[i].mnPixSize = mpLastSizes[i*2+1];
+ }
+ ImplUpdate();
+ Split();
+ }
+ bSplit = FALSE;
+ }
+ }
+ else
+ {
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ HideTracking();
+ bSplit = !rTEvt.IsTrackingCanceled();
+ }
+ else
+ {
+ ImplDrawSplitTracking( this, aMousePosPixel );
+ bSplit = FALSE;
+ }
+ }
+
+ if ( bSplit )
+ {
+ BOOL bPropSmaller = (mnMouseModifier & KEY_SHIFT) ? TRUE : FALSE;
+ BOOL bPropGreater = (mnMouseModifier & KEY_MOD1) ? TRUE : FALSE;
+ long nDelta = mnMSplitPos-mnMStartPos;
+
+ if ( (mnSplitTest & SPLIT_WINDOW) && !mpMainSet->mpItems )
+ {
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ nDelta *= -1;
+ ImplSetWindowSize( nDelta );
+ }
+ else
+ {
+ long nNewSize = mpSplitSet->mpItems[mnSplitPos].mnPixSize;
+ if ( (mpSplitSet == mpMainSet) && mbBottomRight )
+ nNewSize -= nDelta;
+ else
+ nNewSize += nDelta;
+ SplitItem( mpSplitSet->mpItems[mnSplitPos].mnId, nNewSize,
+ bPropSmaller, bPropGreater );
+ }
+
+ Split();
+
+ if ( mbDragFull )
+ {
+ Update();
+ mnMStartPos = mnMSplitPos;
+ }
+ }
+
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( mpLastSizes )
+ delete mpLastSizes;
+ mpLastSizes = NULL;
+ mpSplitSet = NULL;
+ mnMouseOff = 0;
+ mnMStartPos = 0;
+ mnMSplitPos = 0;
+ mnMouseModifier = 0;
+ mnSplitTest = 0;
+ mnSplitPos = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Paint( const Rectangle& )
+{
+ if ( mnWinStyle & WB_BORDER )
+ ImplDrawBorder( this );
+
+ ImplDrawFadeOut( TRUE );
+ ImplDrawFadeIn( TRUE );
+ ImplDrawAutoHide( TRUE );
+
+ // FrameSet-Hintergruende zeichnen
+ ImplDrawBack( this, mpMainSet );
+
+ // Splitter zeichnen
+ if ( !(mnWinStyle & WB_NOSPLITDRAW) )
+ ImplDrawSplit( this, mpMainSet, mbHorz, !mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Move()
+{
+ DockingWindow::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+
+ ImplUpdate();
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
+ Rectangle aHelpRect;
+ USHORT nHelpResId = 0;
+
+ ImplGetAutoHideRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ {
+ if ( mbAutoHideIn )
+ nHelpResId = SV_HELPTEXT_SPLITFIXED;
+ else
+ nHelpResId = SV_HELPTEXT_SPLITFLOATING;
+ }
+ else
+ {
+ ImplGetFadeInRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ nHelpResId = SV_HELPTEXT_FADEIN;
+ else
+ {
+ ImplGetFadeOutRect( aHelpRect, TRUE );
+ if ( aHelpRect.IsInside( aMousePosPixel ) )
+ nHelpResId = SV_HELPTEXT_FADEOUT;
+ }
+ }
+
+ // Rechteck ermitteln
+ if ( nHelpResId )
+ {
+ Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
+ aHelpRect.Left() = aPt.X();
+ aHelpRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
+ aHelpRect.Right() = aPt.X();
+ aHelpRect.Bottom() = aPt.Y();
+
+ // Text ermitteln und anzeigen
+ XubString aStr( ResId( nHelpResId, ImplGetResMgr() ) );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aHelpRect, aStr );
+ return;
+ }
+ }
+
+ DockingWindow::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( IsUpdateMode() )
+ ImplCalcLayout();
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() && IsReallyShown() )
+ ImplCalcLayout();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+
+ DockingWindow::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else
+ DockingWindow::DataChanged( rDCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::InsertItem( USHORT nId, Window* pWindow, long nSize,
+ USHORT nPos, USHORT nSetId,
+ SplitWindowItemBits nBits )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindSet( mpMainSet, nSetId ), "SplitWindow::InsertItem() - Set not exists" );
+ DBG_ASSERT( !ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::InsertItem() - Id already exists" );
+#endif
+
+ // Size muss min. 1 sein
+ if ( nSize < 1 )
+ nSize = 1;
+
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ ImplSplitSet* pNewSet;
+ ImplSplitItem* pItem;
+
+ // Platz fuer neues Item schaffen
+ if ( nPos > pSet->mnItems )
+ nPos = pSet->mnItems;
+ ImplSplitItem* pNewItems = new ImplSplitItem[pSet->mnItems+1];
+ if ( nPos )
+ memcpy( pNewItems, pSet->mpItems, sizeof( ImplSplitItem )*nPos );
+ if ( nPos < pSet->mnItems )
+ memcpy( pNewItems+nPos+1, pSet->mpItems+nPos, sizeof( ImplSplitItem )*(pSet->mnItems-nPos) );
+ delete pSet->mpItems;
+ pSet->mpItems = pNewItems;
+ pSet->mnItems++;
+ pSet->mbCalcPix = TRUE;
+
+ // Item anlegen und erweitern
+ pItem = &(pSet->mpItems[nPos]);
+ memset( pItem, 0, sizeof( ImplSplitItem ) );
+ pItem->mnSize = nSize;
+ pItem->mnId = nId;
+ pItem->mnBits = nBits;
+
+ if ( pWindow )
+ {
+ pItem->mpWindow = pWindow;
+ pItem->mpOrgParent = pWindow->GetParent();
+
+ // Window mit SplitWindow verbinden
+ pWindow->Hide();
+ pWindow->SetParent( this );
+ }
+ else
+ {
+ pNewSet = new ImplSplitSet;
+ pNewSet->mpItems = NULL;
+ pNewSet->mpWallpaper = NULL;
+ pNewSet->mpBitmap = NULL;
+ pNewSet->mnLastSize = 0;
+ pNewSet->mnItems = 0;
+ pNewSet->mnId = nId;
+ pNewSet->mnSplitSize = pSet->mnSplitSize;
+ pNewSet->mbCalcPix = TRUE;
+
+ pItem->mpSet = pNewSet;
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::InsertItem( USHORT nId, long nSize,
+ USHORT nPos, USHORT nSetId,
+ SplitWindowItemBits nBits )
+{
+ InsertItem( nId, NULL, nSize, nPos, nSetId, nBits );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::MoveItem( USHORT nId, USHORT nNewPos, USHORT nNewSetId )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::MoveItem() - Id not found" );
+ DBG_ASSERT( ImplFindSet( mpMainSet, nNewSetId ), "SplitWindow::MoveItem() - Set not exists" );
+#endif
+
+ USHORT nPos;
+ ImplSplitSet* pNewSet = ImplFindSet( mpMainSet, nNewSetId );
+ ImplSplitSet* pSet = ImplFindItem( mpMainSet, nId, nPos );
+ ImplSplitItem aTempItem;
+
+ if ( pNewSet == pSet )
+ {
+ if ( nNewPos >= pNewSet->mnItems )
+ nNewPos = pNewSet->mnItems-1;
+ if ( nPos != nNewPos )
+ {
+ memcpy( &aTempItem, &(pSet->mpItems[nPos]), sizeof( aTempItem ) );
+ if ( nPos < nNewPos )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (nNewPos-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ memmove( pSet->mpItems+nNewPos+1, pSet->mpItems+nNewPos,
+ (nPos-nNewPos)*sizeof( ImplSplitItem ) );
+ }
+ memcpy( &(pSet->mpItems[nNewPos]), &aTempItem, sizeof( aTempItem ) );
+
+ ImplUpdate();
+ }
+ }
+ else
+ {
+ if ( nNewPos >= pNewSet->mnItems )
+ nNewPos = pNewSet->mnItems;
+ memcpy( &aTempItem, &(pSet->mpItems[nPos]), sizeof( aTempItem ) );
+ pSet->mnItems--;
+ pSet->mbCalcPix = TRUE;
+ if ( pSet->mnItems )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (pSet->mnItems-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ delete pSet->mpItems;
+ pSet->mpItems = NULL;
+ }
+ ImplSplitItem* pNewItems = new ImplSplitItem[pNewSet->mnItems+1];
+ if ( nNewPos )
+ memcpy( pNewItems, pNewSet->mpItems, sizeof( ImplSplitItem )*nNewPos );
+ if ( nNewPos < pNewSet->mnItems )
+ {
+ memcpy( pNewItems+nNewPos+1, pNewSet->mpItems+nNewPos,
+ sizeof( ImplSplitItem )*(pNewSet->mnItems-nNewPos) );
+ }
+ delete pNewSet->mpItems;
+ pNewSet->mpItems = pNewItems;
+ pNewSet->mnItems++;
+ pNewSet->mbCalcPix = TRUE;
+ memcpy( &(pNewSet->mpItems[nNewPos]), &aTempItem, sizeof( aTempItem ) );
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::RemoveItem( USHORT nId, BOOL bHide )
+{
+#ifdef DBG_UTIL
+ USHORT nDbgDummy;
+ DBG_ASSERT( ImplFindItem( mpMainSet, nId, nDbgDummy ), "SplitWindow::RemoveItem() - Id not found" );
+#endif
+
+ // Set suchen
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpMainSet, nId, nPos );
+ ImplSplitItem* pItem = &(pSet->mpItems[nPos]);
+ Window* pWindow = pItem->mpWindow;
+ Window* pOrgParent = pItem->mpOrgParent;
+
+ // Evt. Set loeschen
+ if ( !pWindow )
+ ImplDeleteSet( pItem->mpSet );
+
+ // Item entfernen
+ pSet->mnItems--;
+ pSet->mbCalcPix = TRUE;
+ if ( pSet->mnItems )
+ {
+ memmove( pSet->mpItems+nPos, pSet->mpItems+nPos+1,
+ (pSet->mnItems-nPos)*sizeof( ImplSplitItem ) );
+ }
+ else
+ {
+ delete pSet->mpItems;
+ pSet->mpItems = NULL;
+ }
+
+ ImplUpdate();
+
+ // Window erst hier loeschen, um weniger Paints zu haben
+ if ( pWindow )
+ {
+ // Fenster wieder herstellen
+ if ( bHide || (pOrgParent != this) )
+ {
+ pWindow->Hide();
+ pWindow->SetParent( pOrgParent );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::Clear()
+{
+ // Alle Sets loeschen
+ ImplDeleteSet( mpMainSet );
+
+ // Main-Set wieder anlegen
+ mpMainSet = new ImplSplitSet;
+ mpMainSet->mpItems = NULL;
+ mpMainSet->mpWallpaper = NULL;
+ mpMainSet->mpBitmap = NULL;
+ mpMainSet->mnLastSize = 0;
+ mpMainSet->mnItems = 0;
+ mpMainSet->mnId = 0;
+ mpMainSet->mnSplitSize = SPLITWIN_SPLITSIZE;
+ mpMainSet->mbCalcPix = TRUE;
+ if ( mnWinStyle & WB_NOSPLITDRAW )
+ mpMainSet->mnSplitSize -= 2;
+ mpBaseSet = mpMainSet;
+
+ // Und neu invalidieren
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetBaseSet( USHORT nSetId )
+{
+ mpBaseSet = ImplFindSet( mpMainSet, nSetId );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetBaseSet() const
+{
+ return mpBaseSet->mnId;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetSplitSize( USHORT nSetId, long nSplitSize,
+ BOOL bWithChilds )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ if ( pSet )
+ {
+ if ( bWithChilds )
+ ImplSetSplitSize( pSet, nSplitSize );
+ else
+ pSet->mnSplitSize = nSplitSize;
+ }
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetSplitSize( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+ if ( pSet )
+ return pSet->mnSplitSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBackground( USHORT nSetId )
+{
+ Wallpaper aWall;
+ SetItemBackground( nSetId, aWall );
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBackground( USHORT nSetId, const Wallpaper& rWallpaper )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet )
+ {
+ BOOL bUpdate = TRUE;
+
+ if ( rWallpaper.GetStyle() == WALLPAPER_NULL )
+ {
+ if ( pSet->mpWallpaper )
+ {
+ delete pSet->mpWallpaper;
+ pSet->mpWallpaper = NULL;
+ }
+ else
+ bUpdate = FALSE;
+ }
+ else
+ {
+ // Ab jetzt muss immer invalidiert werden
+ mbInvalidate = TRUE;
+
+ if ( !pSet->mpWallpaper )
+ pSet->mpWallpaper = new Wallpaper( rWallpaper );
+ else
+ *(pSet->mpWallpaper) = rWallpaper;
+ }
+
+ // Beim MainSet koennen wir den Background umsetzen
+ if ( pSet == mpMainSet )
+ ImplInitSettings();
+
+ if ( bUpdate )
+ ImplUpdateSet( pSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper SplitWindow::GetItemBackground( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpWallpaper )
+ return *(pSet->mpWallpaper);
+ else
+ {
+ Wallpaper aWall;
+ return aWall;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::IsItemBackground( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpWallpaper )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBitmap( USHORT nSetId, const Bitmap& rBitmap )
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet )
+ {
+ BOOL bUpdate = TRUE;
+
+ if ( !rBitmap )
+ {
+ if ( pSet->mpBitmap )
+ {
+ delete pSet->mpBitmap;
+ pSet->mpBitmap = NULL;
+ }
+ else
+ bUpdate = FALSE;
+ }
+ else
+ {
+ // Ab jetzt muss immer invalidiert werden
+ mbInvalidate = TRUE;
+
+ if ( !pSet->mpBitmap )
+ pSet->mpBitmap = new Bitmap( rBitmap );
+ else
+ *(pSet->mpBitmap) = rBitmap;
+ }
+
+ // Beim MainSet koennen wir den Background umsetzen
+ if ( pSet == mpMainSet )
+ ImplInitSettings();
+
+ if ( bUpdate )
+ ImplUpdateSet( pSet );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap SplitWindow::GetItemBitmap( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpMainSet, nSetId );
+
+ if ( pSet && pSet->mpBitmap )
+ return *(pSet->mpBitmap);
+ else
+ {
+ Bitmap aBitmap;
+ return aBitmap;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SplitItem( USHORT nId, long nNewSize,
+ BOOL bPropSmall, BOOL bPropGreat )
+{
+ USHORT nItems;
+ USHORT nPos;
+ USHORT nMin;
+ USHORT nMax;
+ USHORT i;
+ USHORT n;
+ long nDelta;
+ long nTempDelta;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItems;
+
+ if ( !pSet )
+ return;
+
+ nItems = pSet->mnItems;
+ pItems = pSet->mpItems;
+
+ if ( mbCalc )
+ {
+ pItems[nPos].mnSize = nNewSize;
+ return;
+ }
+
+ nDelta = nNewSize-pItems[nPos].mnPixSize;
+ if ( !nDelta )
+ return;
+
+ // Bereich berechnen, der beim Splitten betroffen sein kann
+ nMin = 0;
+ nMax = nItems;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( pItems[i].mbFixed )
+ {
+ if ( i < nPos )
+ nMin = i+1;
+ else
+ nMax = i;
+ }
+ }
+
+ // Wenn das Fenster sizeable ist, wird das TopSet anders behandelt
+ BOOL bSmall = TRUE;
+ BOOL bGreat = TRUE;
+ if ( (pSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) )
+ {
+ if ( nPos < pSet->mnItems-1 )
+ {
+ if ( !((bPropSmall && bPropGreat) ||
+ ((nDelta > 0) && bPropSmall) ||
+ ((nDelta < 0) && bPropGreat)) )
+ {
+ if ( nDelta < 0 )
+ bGreat = FALSE;
+ else
+ bSmall = FALSE;
+ }
+ }
+ else
+ {
+ if ( nDelta < 0 )
+ bGreat = FALSE;
+ else
+ bSmall = FALSE;
+ }
+ }
+ else if ( nPos >= nMax )
+ {
+ bSmall = FALSE;
+ bGreat = FALSE;
+ }
+ else if ( nPos && (nPos >= pSet->mnItems-1) )
+ {
+ nPos--;
+ nDelta *= -1;
+ BOOL bTemp = bPropSmall;
+ bPropSmall = bPropGreat;
+ bPropGreat = bTemp;
+ }
+
+ // Jetzt die Fenster splitten
+ if ( nDelta < 0 )
+ {
+ if ( bGreat )
+ {
+ if ( bPropGreat )
+ {
+ nTempDelta = nDelta;
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nTempDelta )
+ {
+ pItems[n].mnPixSize++;
+ nTempDelta++;
+ }
+ n++;
+ }
+ while ( n < nMax );
+ }
+ while ( nTempDelta );
+ }
+ else
+ pItems[nPos+1].mnPixSize -= nDelta;
+ }
+
+ if ( bSmall )
+ {
+ if ( bPropSmall )
+ {
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nDelta && pItems[n-1].mnPixSize )
+ {
+ pItems[n-1].mnPixSize--;
+ nDelta++;
+ }
+
+ n--;
+ }
+ while ( n > nMin );
+ }
+ while ( nDelta );
+ }
+ else
+ {
+ n = nPos+1;
+ do
+ {
+ if ( pItems[n-1].mnPixSize+nDelta < 0 )
+ {
+ nDelta += pItems[n-1].mnPixSize;
+ pItems[n-1].mnPixSize = 0;
+ }
+ else
+ {
+ pItems[n-1].mnPixSize += nDelta;
+ break;
+ }
+ n--;
+ }
+ while ( n > nMin );
+ }
+ }
+ }
+ else
+ {
+ if ( bGreat )
+ {
+ if ( bPropGreat )
+ {
+ nTempDelta = nDelta;
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nTempDelta )
+ {
+ pItems[n-1].mnPixSize++;
+ nTempDelta--;
+ }
+ n--;
+ }
+ while ( n > nMin );
+ }
+ while ( nTempDelta );
+ }
+ else
+ pItems[nPos].mnPixSize += nDelta;
+ }
+
+ if ( bSmall )
+ {
+ if ( bPropSmall )
+ {
+ do
+ {
+ n = nPos+1;
+ do
+ {
+ if ( nDelta && pItems[n].mnPixSize )
+ {
+ pItems[n].mnPixSize--;
+ nDelta--;
+ }
+
+ n++;
+ }
+ while ( n < nMax );
+ }
+ while ( nDelta );
+ }
+ else
+ {
+ n = nPos+1;
+ do
+ {
+ if ( pItems[n].mnPixSize-nDelta < 0 )
+ {
+ nDelta -= pItems[n].mnPixSize;
+ pItems[n].mnPixSize = 0;
+ }
+ else
+ {
+ pItems[n].mnPixSize -= nDelta;
+ break;
+ }
+ n++;
+ }
+ while ( n < nMax );
+ }
+ }
+ }
+
+ // Original-Groessen updaten
+ ImplCalcLogSize( pItems, nItems );
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemSize( USHORT nId, long nNewSize )
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItem;
+
+ if ( !pSet )
+ return;
+
+ // Testen, ob sich Groesse aendert
+ pItem = &(pSet->mpItems[nPos]);
+ if ( pItem->mnSize != nNewSize )
+ {
+ // Neue Groesse setzen und neu durchrechnen
+ pItem->mnSize = nNewSize;
+ pSet->mbCalcPix = TRUE;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetItemSize( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mnSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetItemSize( USHORT nId, SplitWindowItemBits nBits ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ {
+ if ( nBits == pSet->mpItems[nPos].mnBits )
+ return pSet->mpItems[nPos].mnSize;
+ else
+ {
+ ((SplitWindow*)this)->ImplCalcLayout();
+
+ long nRelSize = 0;
+ long nPerSize = 0;
+ ImplSplitItem* pItems;
+ USHORT nItems;
+ SplitWindowItemBits nTempBits;
+ USHORT i;
+ nItems = pSet->mnItems;
+ pItems = pSet->mpItems;
+ for ( i = 0; i < nItems; i++ )
+ {
+ if ( i == nPos )
+ nTempBits = nBits;
+ else
+ nTempBits = pItems[i].mnBits;
+ if ( nTempBits & SWIB_RELATIVESIZE )
+ nRelSize += pItems[i].mnPixSize;
+ else if ( nTempBits & SWIB_PERCENTSIZE )
+ nPerSize += pItems[i].mnPixSize;
+ }
+ nPerSize += nRelSize;
+ if ( nBits & SWIB_RELATIVESIZE )
+ {
+ if ( nRelSize )
+ return (pItems[nPos].mnPixSize+(nRelSize/2))/nRelSize;
+ else
+ return 1;
+ }
+ else if ( nBits & SWIB_PERCENTSIZE )
+ {
+ if ( nPerSize )
+ return (pItems[nPos].mnPixSize*100)/nPerSize;
+ else
+ return 1;
+ }
+ else
+ return pItems[nPos].mnPixSize;
+ }
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetItemBits( USHORT nId, SplitWindowItemBits nNewBits )
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+ ImplSplitItem* pItem;
+
+ if ( !pSet )
+ return;
+
+ pItem = &(pSet->mpItems[nPos]);
+ if ( pItem->mpWindow )
+ nNewBits &= ~SWIB_COLSET;
+
+ if ( pItem->mnBits != nNewBits )
+ {
+ // Neue Bits setzen und neu durchrechnen
+ pItem->mnBits = nNewBits;
+ pSet->mbCalcPix = TRUE;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SplitWindowItemBits SplitWindow::GetItemBits( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Window* SplitWindow::GetItemWindow( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mpItems[nPos].mpWindow;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetSet( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return pSet->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::GetSet( USHORT nId, USHORT& rSetId, USHORT& rPos ) const
+{
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, rPos );
+ if ( pSet )
+ {
+ rSetId = pSet->mnId;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SplitWindow::IsItemValid( USHORT nId ) const
+{
+ USHORT nPos;
+ ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
+
+ if ( pSet )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( Window* pWindow ) const
+{
+ return ImplFindItem( mpBaseSet, pWindow );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( const Point& rPos ) const
+{
+ return ImplFindItem( mpBaseSet, rPos, mbHorz, !mbBottomRight );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemPos( USHORT nId, USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ USHORT nPos = SPLITWINDOW_ITEM_NOTFOUND;
+
+ if ( pSet )
+ {
+ for ( USHORT i = 0; i < pSet->mnItems; i++ )
+ {
+ if ( pSet->mpItems[i].mnId == nId )
+ {
+ nPos = i;
+ break;
+ }
+ }
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemId( USHORT nPos, USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ if ( pSet && (nPos < pSet->mnItems) )
+ return pSet->mpItems[nPos].mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SplitWindow::GetItemCount( USHORT nSetId ) const
+{
+ ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
+ if ( pSet )
+ return pSet->mnItems;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ImplNewAlign()
+{
+ if ( mbNoAlign )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_TOP )
+ {
+ mbHorz = TRUE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_BOTTOM )
+ {
+ mbHorz = TRUE;
+ mbBottomRight = TRUE;
+ }
+ else if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = FALSE;
+ }
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ {
+ mbHorz = FALSE;
+ mbBottomRight = TRUE;
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ ImplCalcBorder( meAlign, mbNoAlign, mnLeftBorder, mnTopBorder,
+ mnRightBorder, mnBottomBorder );
+ }
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetNoAlign( BOOL bNoAlign )
+{
+ bNoAlign = bNoAlign != 0;
+ if ( mbNoAlign != bNoAlign )
+ {
+ mbNoAlign = bNoAlign;
+ ImplNewAlign();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetAlign( WindowAlign eNewAlign )
+{
+ if ( meAlign != eNewAlign )
+ {
+ meAlign = eNewAlign;
+ ImplNewAlign();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size SplitWindow::CalcWindowSizePixel( const Size& rSize, WindowAlign eAlign,
+ WinBits nWinStyle, BOOL bExtra )
+{
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+ Size aSize = rSize;
+
+ ImplCalcBorder( eAlign, FALSE, nLeft, nTop, nRight, nBottom );
+ aSize.Width() += nLeft+nRight;
+ aSize.Height() += nTop+nBottom;
+
+ if ( nWinStyle & WB_SIZEABLE )
+ {
+ if ( (eAlign == WINDOWALIGN_TOP) || (eAlign == WINDOWALIGN_BOTTOM) )
+ {
+ aSize.Height() += SPLITWIN_SPLITSIZE-2;
+ if ( bExtra )
+ aSize.Height() += SPLITWIN_SPLITSIZEEX;
+ }
+ else
+ {
+ aSize.Width() += SPLITWIN_SPLITSIZE-2;
+ if ( bExtra )
+ aSize.Width() += SPLITWIN_SPLITSIZEEX;
+ }
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowAutoHideButton( BOOL bShow )
+{
+ mbAutoHide = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowFadeInHideButton( BOOL bShow )
+{
+ mbFadeIn = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::ShowFadeOutButton( BOOL bShow )
+{
+ mbFadeOut = bShow;
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void SplitWindow::SetAutoHideState( BOOL bAutoHide )
+{
+ mbAutoHideIn = bAutoHide;
+ if ( IsReallyVisible() )
+ {
+ Rectangle aRect;
+ ImplGetAutoHideRect( aRect );
+ Invalidate( aRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long SplitWindow::GetFadeInSize() const
+{
+ long n = 0;
+
+ if ( mbHorz )
+ n = mnTopBorder+mnBottomBorder;
+ else
+ n = mnLeftBorder+mnRightBorder;
+
+ return n+SPLITWIN_SPLITSIZE+SPLITWIN_SPLITSIZEEX-2;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetAutoHideRect() const
+{
+ Rectangle aRect;
+ ImplGetAutoHideRect( aRect, TRUE );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetFadeInRect() const
+{
+ Rectangle aRect;
+ ImplGetFadeInRect( aRect, TRUE );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle SplitWindow::GetFadeOutRect() const
+{
+ Rectangle aRect;
+ ImplGetFadeOutRect( aRect, TRUE );
+ return aRect;
+}
diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx
new file mode 100644
index 000000000000..e96593eb6cfd
--- /dev/null
+++ b/vcl/source/window/status.cxx
@@ -0,0 +1,1411 @@
+/*************************************************************************
+ *
+ * $RCSfile: status.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_STATUS_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_STATUS_HXX
+#include <status.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define STATUSBAR_OFFSET_X STATUSBAR_OFFSET
+#define STATUSBAR_OFFSET_Y 2
+#define STATUSBAR_OFFSET_TEXTY 3
+
+#define STATUSBAR_PRGS_OFFSET 3
+#define STATUSBAR_PRGS_COUNT 100
+#define STATUSBAR_PRGS_MIN 5
+
+// -----------------------------------------------------------------------
+
+struct ImplStatusItem
+{
+ USHORT mnId;
+ StatusBarItemBits mnBits;
+ long mnWidth;
+ long mnOffset;
+ long mnExtraWidth;
+ long mnX;
+ XubString maText;
+ XubString maHelpText;
+ ULONG mnHelpId;
+ void* mpUserData;
+ BOOL mbVisible;
+};
+
+DECLARE_LIST( ImplStatusItemList, ImplStatusItem* );
+
+// =======================================================================
+
+inline long ImplCalcProgessWidth( USHORT nMax, long nSize )
+{
+ return ((nMax*(nSize+(nSize/2)))-(nSize/2)+(STATUSBAR_PRGS_OFFSET*2));
+}
+
+// -----------------------------------------------------------------------
+
+static Point ImplGetItemTextPos( const Size& rRectSize, const Size& rTextSize,
+ USHORT nStyle )
+{
+ long nX;
+ long nY;
+
+ if ( nStyle & SIB_LEFT )
+ nX = 0;
+ else if ( nStyle & SIB_RIGHT )
+ nX = rRectSize.Width()-rTextSize.Width();
+ else // SIB_CENTER
+ nX = (rRectSize.Width()-rTextSize.Width())/2;
+ nY = (rRectSize.Height()-rTextSize.Height())/2 + 1;
+ return Point( nX, nY );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL StatusBar::ImplIsItemUpdate()
+{
+ if ( !mbProgressMode && mbVisibleItems && IsReallyVisible() && IsUpdateMode() )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplInit( Window* pParent, WinBits nStyle )
+{
+ // Default ist RightAlign
+ if ( !(nStyle & (WB_LEFT | WB_RIGHT)) )
+ nStyle |= WB_RIGHT;
+
+ Window::ImplInit( pParent, nStyle & ~WB_BORDER, NULL );
+
+ // WinBits merken
+ mpItemList = new ImplStatusItemList;
+ mpVirDev = new VirtualDevice( *this );
+ mnCurItemId = 0;
+ mbFormat = TRUE;
+ mbVisibleItems = TRUE;
+ mbProgressMode = FALSE;
+ mbInUserDraw = FALSE;
+ mbBottomBorder = FALSE;
+ mnDX = 0;
+ mnDY = 0;
+ mnCalcHeight = 0;
+ mnItemY = STATUSBAR_OFFSET_Y;
+ mnTextY = STATUSBAR_OFFSET_TEXTY;
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ SetLineColor();
+
+ SetSizePixel( CalcWindowSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::StatusBar( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_STATUSBAR )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::StatusBar( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_STATUSBAR )
+{
+ rResId.SetRT( RSC_STATUSBAR );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+StatusBar::~StatusBar()
+{
+ // Alle Items loeschen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+
+ // VirtualDevice loeschen
+ delete mpVirDev;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else if ( GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetButtonTextColor();
+ else
+ aColor = rStyleSettings.GetWindowTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+
+ mpVirDev->SetFont( GetFont() );
+ mpVirDev->SetTextColor( GetTextColor() );
+ mpVirDev->SetTextAlign( GetTextAlign() );
+ mpVirDev->SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ mpVirDev->SetBackground( GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplFormat()
+{
+ ImplStatusItem* pItem;
+ long nExtraWidth;
+ long nExtraWidth2;
+ long nX;
+ USHORT nAutoSizeItems = 0;
+
+ // Breiten zusammenrechnen
+ mnItemsWidth = STATUSBAR_OFFSET_X;
+ long nOffset = 0;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( pItem->mnBits & SIB_AUTOSIZE )
+ nAutoSizeItems++;
+
+ mnItemsWidth += pItem->mnWidth + nOffset;
+ nOffset = pItem->mnOffset;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( GetStyle() & WB_RIGHT )
+ {
+ // Bei rechtsbuendiger Ausrichtung wird kein AutoSize ausgewertet,
+ // da wir links den Text anzeigen, der mit SetText gesetzt wird
+ nX = mnDX - mnItemsWidth;
+ nExtraWidth = 0;
+ nExtraWidth2 = 0;
+ }
+ else
+ {
+ mnItemsWidth += STATUSBAR_OFFSET_X;
+
+ // Bei linksbuendiger Ausrichtung muessen wir gegebenenfalls noch
+ // AutoSize auswerten
+ if ( nAutoSizeItems && (mnDX > (mnItemsWidth - STATUSBAR_OFFSET)) )
+ {
+ nExtraWidth = (mnDX - mnItemsWidth - 1) / nAutoSizeItems;
+ nExtraWidth2 = (mnDX - mnItemsWidth - 1) % nAutoSizeItems;
+ }
+ else
+ {
+ nExtraWidth = 0;
+ nExtraWidth2 = 0;
+ }
+ nX = STATUSBAR_OFFSET_X;
+ }
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( pItem->mnBits & SIB_AUTOSIZE )
+ {
+ pItem->mnExtraWidth = nExtraWidth;
+ if ( nExtraWidth2 )
+ {
+ pItem->mnExtraWidth++;
+ nExtraWidth2--;
+ }
+ }
+ else
+ pItem->mnExtraWidth = 0;
+
+ pItem->mnX = nX;
+ nX += pItem->mnWidth + pItem->mnExtraWidth + pItem->mnOffset;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle StatusBar::ImplGetItemRectPos( USHORT nPos ) const
+{
+ Rectangle aRect;
+ ImplStatusItem* pItem;
+
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ aRect.Left() = pItem->mnX;
+ aRect.Right() = aRect.Left() + pItem->mnWidth + pItem->mnExtraWidth;
+ aRect.Top() = mnItemY;
+ aRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y;
+ }
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawText( BOOL bOffScreen, long nOldTextWidth )
+{
+ // Das ueberschreiben der Item-Box verhindern
+ Rectangle aTextRect;
+ aTextRect.Left() = STATUSBAR_OFFSET_X+1;
+ aTextRect.Top() = mnTextY;
+ if ( mbVisibleItems && (GetStyle() & WB_RIGHT) )
+ aTextRect.Right() = mnDX - mnItemsWidth - 1;
+ else
+ aTextRect.Right() = mnDX - 1;
+ if ( aTextRect.Right() > aTextRect.Left() )
+ {
+ // Position ermitteln
+ XubString aStr = GetText();
+ USHORT nPos = aStr.Search( _LF );
+ if ( nPos != STRING_NOTFOUND )
+ aStr.Erase( nPos );
+
+ aTextRect.Bottom() = aTextRect.Top()+GetTextHeight()+1;
+
+ if ( bOffScreen )
+ {
+ long nMaxWidth = Max( nOldTextWidth, GetTextWidth( aStr ) );
+ Size aVirDevSize( nMaxWidth, aTextRect.GetHeight() );
+ mpVirDev->SetOutputSizePixel( aVirDevSize );
+ Rectangle aTempRect = aTextRect;
+ aTempRect.SetPos( Point( 0, 0 ) );
+ mpVirDev->DrawText( aTempRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
+ DrawOutDev( aTextRect.TopLeft(), aVirDevSize, Point(), aVirDevSize, *mpVirDev );
+ }
+ else
+ DrawText( aTextRect, aStr, TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawItem( BOOL bOffScreen, USHORT nPos, BOOL bDrawText, BOOL bDrawFrame )
+{
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+
+ if ( aRect.IsEmpty() )
+ return;
+
+ // Ausgabebereich berechnen
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ Rectangle aTextRect( aRect.Left()+1, aRect.Top()+1,
+ aRect.Right()-1, aRect.Bottom()-1 );
+ Size aTextRectSize( aTextRect.GetSize() );
+
+ if ( bOffScreen )
+ mpVirDev->SetOutputSizePixel( aTextRectSize );
+ else
+ {
+ Region aRegion( aTextRect );
+ SetClipRegion( aRegion );
+ }
+
+ // Text ausgeben
+ if ( bDrawText )
+ {
+ Size aTextSize( GetTextWidth( pItem->maText ), GetTextHeight() );
+ Point aTextPos = ImplGetItemTextPos( aTextRectSize, aTextSize, pItem->mnBits );
+ if ( bOffScreen )
+ mpVirDev->DrawText( aTextPos, pItem->maText );
+ else
+ {
+ aTextPos.X() += aTextRect.Left();
+ aTextPos.Y() += aTextRect.Top();
+ DrawText( aTextPos, pItem->maText );
+ }
+ }
+
+ // Gegebenenfalls auch DrawItem aufrufen
+ if ( pItem->mnBits & SIB_USERDRAW )
+ {
+ if ( bOffScreen )
+ {
+ mbInUserDraw = TRUE;
+ UserDrawEvent aODEvt( mpVirDev, Rectangle( Point(), aTextRectSize ), pItem->mnId );
+ UserDraw( aODEvt );
+ mbInUserDraw = FALSE;
+ }
+ else
+ {
+ UserDrawEvent aODEvt( this, aTextRect, pItem->mnId );
+ UserDraw( aODEvt );
+ }
+ }
+
+ if ( bOffScreen )
+ DrawOutDev( aTextRect.TopLeft(), aTextRectSize, Point(), aTextRectSize, *mpVirDev );
+ else
+ SetClipRegion();
+
+ // Frame ausgeben
+ if ( bDrawFrame && !(pItem->mnBits & SIB_FLAT) )
+ {
+ USHORT nStyle;
+
+ if ( pItem->mnBits & SIB_IN )
+ nStyle = FRAME_DRAW_IN;
+ else
+ nStyle = FRAME_DRAW_OUT;
+
+ DecorationView aDecoView( this );
+ aDecoView.DrawFrame( aRect, nStyle );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma optimize( "", off )
+#endif
+
+void DrawProgress( Window* pWindow, const Point& rPos,
+ long nOffset, long nPrgsWidth, long nPrgsHeight,
+ USHORT nPercent1, USHORT nPercent2, USHORT nPercentCount )
+{
+ // Werte vorberechnen
+ USHORT nPerc1 = nPercent1 / nPercentCount;
+ USHORT nPerc2 = nPercent2 / nPercentCount;
+
+ // Percent-Rechtecke malen
+ if ( nPerc1 < nPerc2 )
+ {
+ // Wenn Percent2 ueber 100%, Werte anpassen
+ if ( nPercent2 > 10000 )
+ {
+ nPerc2 = 10000 / nPercentCount;
+ if ( nPerc1 >= nPerc2 )
+ nPerc1 = nPerc2-1;
+ }
+
+ // Rechteck berechnen
+ long nDX = nPrgsWidth + nOffset;
+ long nLeft = rPos.X()+(nPerc1*nDX);
+ Rectangle aRect( nLeft, rPos.Y(), nLeft+nPrgsWidth, rPos.Y()+nPrgsHeight );
+
+ do
+ {
+ pWindow->DrawRect( aRect );
+ aRect.Left() += nDX;
+ aRect.Right() += nDX;
+ nPerc1++;
+ }
+ while ( nPerc1 < nPerc2 );
+
+ // Bei mehr als 100%, lassen wir das Rechteck blinken
+ if ( nPercent2 > 10000 )
+ {
+ // an/aus-Status festlegen
+ if ( ((nPercent2 / nPercentCount) & 0x01) == (nPercentCount & 0x01) )
+ {
+ aRect.Left() -= nDX;
+ aRect.Right() -= nDX;
+ pWindow->Erase( aRect );
+ }
+ }
+
+ pWindow->Flush();
+ }
+}
+
+#ifdef _MSC_VER
+#pragma optimize( "", on )
+#endif
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplDrawProgress( BOOL bPaint,
+ USHORT nPercent1, USHORT nPercent2 )
+{
+ // Wenn Paint, dann muss auch Text und Frame gemalt werden
+ if ( bPaint )
+ {
+ DrawText( maPrgsTxtPos, maPrgsTxt );
+ DecorationView aDecoView( this );
+ aDecoView.DrawFrame( maPrgsFrameRect, FRAME_DRAW_IN );
+ }
+
+ Point aPos( maPrgsFrameRect.Left()+STATUSBAR_PRGS_OFFSET,
+ maPrgsFrameRect.Top()+STATUSBAR_PRGS_OFFSET );
+ DrawProgress( this, aPos, mnPrgsSize/2, mnPrgsSize, mnPrgsSize,
+ nPercent1*100, nPercent2*100, mnPercentCount );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ImplCalcProgressRect()
+{
+ // Groessen berechnen
+ Size aPrgsTxtSize( GetTextWidth( maPrgsTxt ), GetTextHeight() );
+ maPrgsTxtPos.X() = STATUSBAR_OFFSET_X+1;
+ maPrgsTxtPos.Y() = mnTextY;
+
+ // Progress-Frame berechnen
+ maPrgsFrameRect.Left() = maPrgsTxtPos.X()+aPrgsTxtSize.Width()+STATUSBAR_OFFSET;
+ maPrgsFrameRect.Top() = mnItemY;
+ maPrgsFrameRect.Bottom() = mnCalcHeight - STATUSBAR_OFFSET_Y;
+
+ // Dabei die Breite des Fensters berechnen
+ mnPrgsSize = maPrgsFrameRect.Bottom()-maPrgsFrameRect.Top()-(STATUSBAR_PRGS_OFFSET*2);
+ USHORT nMaxPercent = STATUSBAR_PRGS_COUNT;
+
+ long nMaxWidth = mnDX-STATUSBAR_OFFSET-1;
+
+ // Wenn es zu viele Percent-Rects sind, verkuerzen wir
+ while ( maPrgsFrameRect.Left()+ImplCalcProgessWidth( nMaxPercent, mnPrgsSize ) > nMaxWidth )
+ {
+ nMaxPercent--;
+ if ( nMaxPercent <= STATUSBAR_PRGS_MIN )
+ break;
+ }
+ maPrgsFrameRect.Right() = maPrgsFrameRect.Left() + ImplCalcProgessWidth( nMaxPercent, mnPrgsSize );
+ // Fuer die weitere Berechnung brauchen wir den Teiler
+ mnPercentCount = 10000 / nMaxPercent;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // Nur bei linker Maustaste ToolBox ausloesen
+ if ( rMEvt.IsLeft() )
+ {
+ if ( mbVisibleItems )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT i = 0;
+
+ // Item suchen, das geklickt wurde
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Ist es dieses Item
+ if ( ImplGetItemRectPos( i ).IsInside( aMousePos ) )
+ {
+ mnCurItemId = pItem->mnId;
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ mnCurItemId = 0;
+
+ // Item wurde gefunden
+ return;
+ }
+
+ i++;
+ pItem = mpItemList->Next();
+ }
+ }
+
+ // Kein Item, dann nur Click oder DoubleClick
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Paint( const Rectangle& )
+{
+ if ( mbFormat )
+ ImplFormat();
+
+ USHORT nItemCount = (USHORT)mpItemList->Count();
+
+ if ( mbProgressMode )
+ ImplDrawProgress( TRUE, 0, mnPercent );
+ else
+ {
+ // Text zeichen
+ if ( !mbVisibleItems || (GetStyle() & WB_RIGHT) )
+ ImplDrawText( FALSE, 0 );
+
+ // Items zeichnen
+ if ( mbVisibleItems )
+ {
+ // Items zeichnen
+ for ( USHORT i = 0; i < nItemCount; i++ )
+ ImplDrawItem( FALSE, i, TRUE, TRUE );
+ }
+ }
+
+ if ( mbBottomBorder )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( 0, mnDY-2 ), Point( mnDX-1, mnDY-2 ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Move()
+{
+ Window::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Resize()
+{
+ // Breite und Hoehe abfragen und merken
+ long nOldDY = mnDX;
+ Size aSize = GetOutputSizePixel();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+ mnCalcHeight = mnDY;
+ if ( mbBottomBorder )
+ mnCalcHeight -= 2;
+
+ // Evt. neue Textposition berechnen
+ if ( nOldDY && (nOldDY < mnDY) )
+ {
+ mnTextY = 0;
+ mnTextY += (mnCalcHeight-GetTextHeight()-mnTextY)/2;
+ }
+
+ // Formatierung neu ausloesen
+ mbFormat = TRUE;
+
+ if ( mbProgressMode )
+ ImplCalcProgressRect();
+
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ XubString aStr = GetHelpText( nItemId );
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ return;
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ XubString aStr = GetItemText( nItemId );
+ // Wir zeigen die Quick-Hilfe nur an, wenn Text nicht
+ // vollstaendig sichtbar
+ if ( GetTextWidth( aStr ) > aItemRect.GetWidth() )
+ {
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ return;
+ }
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ ULONG nHelpId = GetHelpId( nItemId );
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId );
+ return;
+ }
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ Invalidate();
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Click()
+{
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::InsertItem( USHORT nItemId, ULONG nWidth,
+ StatusBarItemBits nBits,
+ long nOffset, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "StatusBar::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == STATUSBAR_ITEM_NOTFOUND,
+ "StatusBar::InsertItem(): ItemId already exists" );
+
+ // IN und CENTER sind Default
+ if ( !(nBits & (SIB_IN | SIB_OUT | SIB_FLAT)) )
+ nBits |= SIB_IN;
+ if ( !(nBits & (SIB_LEFT | SIB_RIGHT | SIB_CENTER)) )
+ nBits |= SIB_CENTER;
+
+ // Item anlegen
+ ImplStatusItem* pItem = new ImplStatusItem;
+ pItem->mnId = nItemId;
+ pItem->mnBits = nBits;
+ pItem->mnWidth = (long)nWidth+2;
+ pItem->mnOffset = nOffset;
+ pItem->mnHelpId = 0;
+ pItem->mpUserData = 0;
+ pItem->mbVisible = TRUE;
+
+ // Item in die Liste einfuegen
+ mpItemList->Insert( pItem, nPos );
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::RemoveItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->Remove( nPos );
+ delete pItem;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ShowItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->mbVisible )
+ {
+ pItem->mbVisible = TRUE;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::HideItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mbVisible )
+ {
+ pItem->mbVisible = FALSE;
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL StatusBar::IsItemVisible( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mbVisible;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::ShowItems()
+{
+ if ( !mbVisibleItems )
+ {
+ mbVisibleItems = TRUE;
+ if ( !mbProgressMode )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::HideItems()
+{
+ if ( mbVisibleItems )
+ {
+ mbVisibleItems = FALSE;
+ if ( !mbProgressMode )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::CopyItems( const StatusBar& rStatusBar )
+{
+ // Alle Items entfernen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ // Items kopieren
+ ULONG i = 0;
+ pItem = rStatusBar.mpItemList->GetObject( i );
+ while ( pItem )
+ {
+ mpItemList->Insert( new ImplStatusItem( *pItem ), LIST_APPEND );
+ i++;
+ pItem = rStatusBar.mpItemList->GetObject( i );
+ }
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::Clear()
+{
+ // Alle Item loeschen
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ mbFormat = TRUE;
+ if ( ImplIsItemUpdate() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemId( USHORT nPos ) const
+{
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemPos( USHORT nItemId ) const
+{
+ ImplStatusItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (USHORT)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return STATUSBAR_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT StatusBar::GetItemId( const Point& rPos ) const
+{
+ if ( AreItemsVisible() && !mbFormat )
+ {
+ USHORT nItemCount = GetItemCount();
+ USHORT nPos;
+ for ( nPos = 0; nPos < nItemCount; nPos++ )
+ {
+ // Rechteck holen
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+ if ( aRect.IsInside( rPos ) )
+ return mpItemList->GetObject( nPos )->mnId;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle StatusBar::GetItemRect( USHORT nItemId ) const
+{
+ Rectangle aRect;
+
+ if ( AreItemsVisible() && !mbFormat )
+ {
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ // Rechteck holen und Rahmen abziehen
+ aRect = ImplGetItemRectPos( nPos );
+ aRect.Left()++;
+ aRect.Right()--;
+ return aRect;
+ }
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+Point StatusBar::GetItemTextPos( USHORT nItemId ) const
+{
+ if ( !mbFormat )
+ {
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ // Rechteck holen
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ Rectangle aRect = ImplGetItemRectPos( nPos );
+ Rectangle aTextRect( aRect.Left()+1, aRect.Top()+1,
+ aRect.Right()-1, aRect.Bottom()-1 );
+ Point aPos = ImplGetItemTextPos( aTextRect.GetSize(),
+ Size( GetTextWidth( pItem->maText ), GetTextHeight() ),
+ pItem->mnBits );
+ if ( !mbInUserDraw )
+ {
+ aPos.X() += aTextRect.Left();
+ aPos.Y() += aTextRect.Top();
+ }
+ return aPos;
+ }
+ }
+
+ return Point();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG StatusBar::GetItemWidth( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnWidth;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+StatusBarItemBits StatusBar::GetItemBits( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long StatusBar::GetItemOffset( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnOffset;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->maText != rText )
+ {
+ pItem->maText = rText;
+
+ // Item neu Zeichen, wenn StatusBar sichtbar und
+ // UpdateMode gesetzt ist
+ if ( pItem->mbVisible && !mbFormat && ImplIsItemUpdate() )
+ {
+ Update();
+ ImplDrawItem( TRUE, nPos, TRUE, FALSE );
+ Flush();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetItemText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetItemData( USHORT nItemId, void* pNewData )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ pItem->mpUserData = pNewData;
+
+ // Wenn es ein User-Item ist, DrawItem-Aufrufen
+ if ( (pItem->mnBits & SIB_USERDRAW) && pItem->mbVisible &&
+ !mbFormat && ImplIsItemUpdate() )
+ {
+ Update();
+ ImplDrawItem( TRUE, nPos, FALSE, FALSE );
+ Flush();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* StatusBar::GetItemData( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetHelpText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& StatusBar::GetHelpText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG StatusBar::GetHelpId( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != STATUSBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetBottomBorder( BOOL bBottomBorder )
+{
+ if ( mbBottomBorder != bBottomBorder )
+ {
+ mbBottomBorder = bBottomBorder;
+ mnCalcHeight = mnDY;
+ if ( mbBottomBorder )
+ mnCalcHeight -= 2;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::StartProgressMode( const XubString& rText )
+{
+ DBG_ASSERT( !mbProgressMode, "StatusBar::StartProgressMode(): progress mode is active" );
+
+ mbProgressMode = TRUE;
+ mnPercent = 0;
+ maPrgsTxt = rText;
+
+ // Groessen berechnen
+ ImplCalcProgressRect();
+
+ // Paint ausloesen (dort wird der Text und der Frame gemalt)
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aPrgsColor = rStyleSettings.GetHighlightColor();
+ if ( aPrgsColor == rStyleSettings.GetFaceColor() )
+ aPrgsColor = rStyleSettings.GetDarkShadowColor();
+ SetLineColor();
+ SetFillColor( aPrgsColor );
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetProgressValue( USHORT nNewPercent )
+{
+ DBG_ASSERT( mbProgressMode, "StatusBar::SetProgressValue(): no progrss mode" );
+ DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
+
+ if ( mbProgressMode && IsReallyVisible() )
+ {
+ Update();
+ SetLineColor();
+ ImplDrawProgress( FALSE, mnPercent, nNewPercent );
+ Flush();
+ }
+ mnPercent = nNewPercent;
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::EndProgressMode()
+{
+ DBG_ASSERT( mbProgressMode, "StatusBar::EndProgressMode(): no progress mode" );
+
+ mbProgressMode = FALSE;
+ maPrgsTxt.Erase();
+
+ // Paint neu ausloesen um StatusBar wieder herzustellen
+ SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ Flush();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void StatusBar::SetText( const XubString& rText )
+{
+ if ( (!mbVisibleItems || (GetStyle() & WB_RIGHT)) && !mbProgressMode &&
+ IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( mbFormat )
+ {
+ Invalidate();
+ Window::SetText( rText );
+ }
+ else
+ {
+ Update();
+ long nOldTextWidth = GetTextWidth( GetText() );
+ Window::SetText( rText );
+ ImplDrawText( TRUE, nOldTextWidth );
+ Flush();
+ }
+ }
+ else
+ Window::SetText( rText );
+}
+
+// -----------------------------------------------------------------------
+
+Size StatusBar::CalcWindowSizePixel() const
+{
+ ULONG i = 0;
+ ULONG nCount = mpItemList->Count();
+ long nOffset = 0;
+ long nCalcWidth = (STATUSBAR_OFFSET_X*2);
+ long nCalcHeight;
+
+ while ( i < nCount )
+ {
+ ImplStatusItem* pItem = mpItemList->GetObject( i );
+ nCalcWidth += pItem->mnWidth + nOffset;
+ nOffset = pItem->mnOffset;
+ i++;
+ }
+
+ nCalcHeight = GetTextHeight()+(STATUSBAR_OFFSET_TEXTY*2);
+ if ( mbBottomBorder )
+ nCalcHeight += 2;
+
+ return Size( nCalcWidth, nCalcHeight );
+}
diff --git a/vcl/source/window/syschild.cxx b/vcl/source/window/syschild.cxx
new file mode 100644
index 000000000000..99991bc91b3e
--- /dev/null
+++ b/vcl/source/window/syschild.cxx
@@ -0,0 +1,221 @@
+/*************************************************************************
+ *
+ * $RCSfile: syschild.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SYSCHILD_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#include <window.hxx>
+#ifndef _SV_SALOBJ_HXX
+#include <salobj.hxx>
+#endif
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WIDNOW_H
+#include <window.h>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_SYSCHILD_HXX
+#include <syschild.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+#ifndef REMOTE_APPSERVER
+
+long ImplSysChildProc( void* pInst, SalObject* /* pObject */,
+ USHORT nEvent, const void* /* pEvent */ )
+{
+ SystemChildWindow* pWindow = (SystemChildWindow*)pInst;
+ long nRet = 0;
+
+ switch ( nEvent )
+ {
+ case SALOBJ_EVENT_GETFOCUS:
+ // Focus holen und zwar so, das alle Handler gerufen
+ // werden, als ob dieses Fenster den Focus bekommt,
+ // ohne das der Frame den Focus wieder klaut
+ pWindow->ImplGetFrameData()->mbSysObjFocus = TRUE;
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = TRUE;
+ pWindow->ToTop( TOTOP_NOGRABFOCUS );
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = FALSE;
+ pWindow->ImplGetFrameData()->mbInSysObjFocusHdl = TRUE;
+ pWindow->GrabFocus();
+ pWindow->ImplGetFrameData()->mbInSysObjFocusHdl = FALSE;
+ break;
+
+ case SALOBJ_EVENT_LOSEFOCUS:
+ // Hintenrum einen LoseFocus ausloesen, das der Status
+ // der Fenster dem entsprechenden Activate-Status
+ // entspricht
+ pWindow->ImplGetFrameData()->mbSysObjFocus = FALSE;
+ if ( !pWindow->ImplGetFrameData()->mnFocusId )
+ {
+ pWindow->ImplGetFrameData()->mbStartFocusState = TRUE;
+ Application::PostUserEvent( pWindow->ImplGetFrameData()->mnFocusId, LINK( pWindow->ImplGetFrameWindow(), Window, ImplAsyncFocusHdl ) );
+ }
+ break;
+
+ case SALOBJ_EVENT_TOTOP:
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = TRUE;
+ if ( !Application::GetFocusWindow() || pWindow->HasChildPathFocus() )
+ pWindow->ToTop( TOTOP_NOGRABFOCUS );
+ else
+ pWindow->ToTop();
+ pWindow->GrabFocus();
+ pWindow->ImplGetFrameData()->mbInSysObjToTopHdl = FALSE;
+ break;
+ }
+
+ return nRet;
+}
+
+#endif
+
+// =======================================================================
+
+void SystemChildWindow::ImplInit( Window* pParent, WinBits nStyle )
+{
+#ifndef REMOTE_APPSERVER
+ mpSysObj = ImplGetSVData()->mpDefInst->CreateObject( pParent->ImplGetFrame() );
+#endif
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+#ifndef REMOTE_APPSERVER
+ // Wenn es ein richtiges SysChild ist, dann painten wir auch nicht
+ if ( GetSystemData() )
+ {
+ mpSysObj->SetCallback( this, ImplSysChildProc );
+ SetParentClipMode( PARENTCLIPMODE_CLIP );
+ SetBackground();
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::SystemChildWindow( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_SYSTEMCHILDWINDOW )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::SystemChildWindow( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_SYSTEMCHILDWINDOW )
+{
+ rResId.SetRT( RSC_WINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+SystemChildWindow::~SystemChildWindow()
+{
+#ifndef REMOTE_APPSERVER
+ Hide();
+ if ( mpSysObj )
+ {
+ ImplGetSVData()->mpDefInst->DestroyObject( mpSysObj );
+ mpSysObj = NULL;
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+const SystemEnvData* SystemChildWindow::GetSystemData() const
+{
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ return mpSysObj->GetSystemData();
+ else
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
diff --git a/vcl/source/window/syswin.cxx b/vcl/source/window/syswin.cxx
new file mode 100644
index 000000000000..786f1af2b15a
--- /dev/null
+++ b/vcl/source/window/syswin.cxx
@@ -0,0 +1,389 @@
+/*************************************************************************
+ *
+ * $RCSfile: syswin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_SYSWIN_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_SYSWIN_HXX
+#include <syswin.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+#include <unowrap.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+SystemWindow::SystemWindow( WindowType nType ) :
+ Window( nType )
+{
+ mbSysWin = TRUE;
+ mnActivateMode = ACTIVATE_MODE_GRABFOCUS;
+
+ mpMenuBar = NULL;
+ mbPined = FALSE;
+ mbRollUp = FALSE;
+ mbRollFunc = FALSE;
+ mbDockBtn = FALSE;
+ mbHideBtn = FALSE;
+ mnMenuBarMode = MENUBAR_MODE_NORMAL;
+}
+
+// -----------------------------------------------------------------------
+
+long SystemWindow::Notify( NotifyEvent& rNEvt )
+{
+ // Abfangen von KeyEvents fuer Menu-Steuerung
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ MenuBar* pMBar = mpMenuBar;
+ if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
+ {
+ SystemWindow* pW = (SystemWindow*)ImplGetFrameWindow()->ImplGetWindow();
+ if ( pW )
+ pMBar = pW->GetMenuBar();
+ }
+ if ( pMBar && pMBar->ImplHandleKeyEvent( *rNEvt.GetKeyEvent(), FALSE ) )
+ return TRUE;
+ }
+
+ return Window::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::Close()
+{
+ if ( mxWindowPeer.is() )
+ {
+ // #76482# This window can be destroyed in WindowEvent_Close.
+ // => Don't use members after calling WindowEvent_Close
+ BOOL bCreatedWithToolkit = IsCreatedWithToolkit();
+ Application::GetUnoWrapper()->WindowEvent_Close( this );
+ if ( bCreatedWithToolkit )
+ return FALSE;
+ }
+
+ Hide();
+
+ // Ist es das Applikationsfenster, dann beende die Applikation
+ if ( Application::GetAppWindow() == (const WorkWindow*)this )
+ GetpApp()->Quit();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::TitleButtonClick( USHORT )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Pin()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Roll()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::Resizing( Size& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetZLevel( BYTE nLevel )
+{
+ Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+ if ( pWindow->mbOverlapWin && !pWindow->mbFrame )
+ {
+ BYTE nOldLevel = pWindow->mpOverlapData->mnTopLevel;
+ pWindow->mpOverlapData->mnTopLevel = nLevel;
+ // Wenn der neue Level groesser als der alte ist, schieben
+ // wir das Fenster nach hinten
+ if ( !IsReallyVisible() && (nLevel > nOldLevel) && pWindow->mpNext )
+ {
+ // Fenster aus der Liste entfernen
+ if ( pWindow->mpPrev )
+ pWindow->mpPrev->mpNext = pWindow->mpNext;
+ else
+ pWindow->mpOverlapWindow->mpFirstOverlap = pWindow->mpNext;
+ pWindow->mpNext->mpPrev = pWindow->mpPrev;
+ pWindow->mpNext = NULL;
+ // und Fenster wieder in die Liste am Ende eintragen
+ pWindow->mpPrev = pWindow->mpOverlapWindow->mpLastOverlap;
+ pWindow->mpOverlapWindow->mpLastOverlap = pWindow;
+ pWindow->mpPrev->mpNext = pWindow;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BYTE SystemWindow::GetZLevel() const
+{
+ const Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+ if ( pWindow->mpOverlapData )
+ return pWindow->mpOverlapData->mnTopLevel;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::EnableSaveBackground( BOOL bSave )
+{
+ Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+ if ( pWindow->mbOverlapWin && !pWindow->mbFrame )
+ {
+ pWindow->mpOverlapData->mbSaveBack = bSave;
+ if ( !bSave )
+ pWindow->ImplDeleteOverlapBackground();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::IsSaveBackgroundEnabled() const
+{
+ const Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+ if ( pWindow->mpOverlapData )
+ return pWindow->mpOverlapData->mbSaveBack;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::ShowTitleButton( USHORT nButton, BOOL bVisible )
+{
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ {
+ if ( mbDockBtn != bVisible )
+ {
+ mbDockBtn = bVisible;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetDockButton( bVisible );
+ }
+ }
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ {
+ if ( mbHideBtn != bVisible )
+ {
+ mbHideBtn = bVisible;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetHideButton( bVisible );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SystemWindow::IsTitleButtonVisible( USHORT nButton ) const
+{
+ if ( nButton == TITLE_BUTTON_DOCKING )
+ return mbDockBtn;
+ else /* if ( nButton == TITLE_BUTTON_HIDE ) */
+ return mbHideBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetPin( BOOL bPin )
+{
+ if ( bPin != mbPined )
+ {
+ mbPined = bPin;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetPin( bPin );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::RollUp()
+{
+ if ( !mbRollUp )
+ {
+ maOrgSize = GetOutputSizePixel();
+ mbRollFunc = TRUE;
+ Size aSize = maRollUpOutSize;
+ if ( !aSize.Width() )
+ aSize.Width() = GetOutputSizePixel().Width();
+ mbRollUp = TRUE;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetRollUp( TRUE, aSize );
+ else
+ SetOutputSizePixel( aSize );
+ mbRollFunc = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::RollDown()
+{
+ if ( mbRollUp )
+ {
+ mbRollUp = FALSE;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetRollUp( FALSE, maOrgSize );
+ else
+ SetOutputSizePixel( maOrgSize );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
+{
+ maMinOutSize = rSize;
+ if ( mpBorderWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->SetMinOutputSize( rSize.Width(), rSize.Height() );
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMenuBar( MenuBar* pMenuBar )
+{
+ if ( mpMenuBar != pMenuBar )
+ {
+ MenuBar* pOldMenuBar = mpMenuBar;
+ Window* pOldWindow;
+ mpMenuBar = pMenuBar;
+
+ if ( mpBorderWindow && (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
+ {
+ if ( pOldMenuBar )
+ pOldWindow = pOldMenuBar->ImplGetWindow();
+ else
+ pOldWindow = NULL;
+ if ( pMenuBar )
+ {
+ DBG_ASSERT( !pMenuBar->pWindow, "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
+ ((ImplBorderWindow*)mpBorderWindow)->SetMenuBarWindow( MenuBar::ImplCreate( mpBorderWindow, pOldWindow, pMenuBar ) );
+ }
+ else
+ ((ImplBorderWindow*)mpBorderWindow)->SetMenuBarWindow( NULL );
+ ImplToBottomChild();
+ if ( pOldMenuBar )
+ MenuBar::ImplDestroy( pOldMenuBar, pMenuBar == 0 );
+ }
+
+ Application::GenerateAccessEvent( ACCESS_EVENT_MENUBAR );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SystemWindow::SetMenuBarMode( USHORT nMode )
+{
+ if ( mnMenuBarMode != nMode )
+ {
+ mnMenuBarMode = nMode;
+ if ( mpBorderWindow && (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
+ {
+ if ( nMode == MENUBAR_MODE_HIDE )
+ ((ImplBorderWindow*)mpBorderWindow)->SetMenuBarMode( TRUE );
+ else
+ ((ImplBorderWindow*)mpBorderWindow)->SetMenuBarMode( FALSE );
+ }
+ }
+}
diff --git a/vcl/source/window/tabdlg.cxx b/vcl/source/window/tabdlg.cxx
new file mode 100644
index 000000000000..b4b212d90ec1
--- /dev/null
+++ b/vcl/source/window/tabdlg.cxx
@@ -0,0 +1,315 @@
+/*************************************************************************
+ *
+ * $RCSfile: tabdlg.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TABDLG_CXX
+
+#ifndef _SV_FIXED_HXX
+#include <fixed.hxx>
+#endif
+#ifndef _SV_TABCTRL_HXX
+#include <tabctrl.hxx>
+#endif
+#ifndef _SV_TABDLG_HXX
+#include <tabdlg.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void TabDialog::ImplInitData()
+{
+ mpFixedLine = NULL;
+ mpViewWindow = NULL;
+ meViewAlign = WINDOWALIGN_LEFT;
+ mbPosControls = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::ImplPosControls()
+{
+ Size aCtrlSize( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
+ long nDownCtrl = 0;
+ long nOffY = 0;
+ TabControl* pTabControl = NULL;
+
+ Window* pChild = GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->IsVisible() && (pChild != mpViewWindow) )
+ {
+ if ( pChild->GetType() == WINDOW_TABCONTROL )
+ pTabControl = (TabControl*)pChild;
+ else if ( pTabControl )
+ {
+ long nTxtWidth = pChild->GetCtrlTextWidth( pChild->GetText() );
+ nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
+ if ( nTxtWidth > aCtrlSize.Width() )
+ aCtrlSize.Width() = nTxtWidth;
+ long nTxtHeight = pChild->GetTextHeight();
+ nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
+ if ( nTxtHeight > aCtrlSize.Height() )
+ aCtrlSize.Height() = nTxtHeight;
+ nDownCtrl++;
+ }
+ else
+ {
+ long nHeight = pChild->GetSizePixel().Height();
+ if ( nHeight > nOffY )
+ nOffY = nHeight;
+ }
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ // Haben wir ueberhaupt ein TabControl
+ if ( pTabControl )
+ {
+ // Offset bei weiteren Controls um einen weiteren Abstand anpassen
+ if ( nOffY )
+ nOffY += IMPL_DIALOG_BAR_OFFSET*2 + 2;
+
+ Point aTabOffset( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+nOffY );
+ Size aTabSize = pTabControl->GetSizePixel();
+ Size aDlgSize( aTabSize.Width() + IMPL_DIALOG_OFFSET*2,
+ aTabSize.Height() + IMPL_DIALOG_OFFSET*2 + nOffY );
+ long nBtnEx = 0;
+
+ // Preview-Fenster beruecksichtigen und die Groessen/Offsets anpassen
+ if ( mpViewWindow && mpViewWindow->IsVisible() )
+ {
+ long nViewOffX = 0;
+ long nViewOffY = 0;
+ long nViewWidth = 0;
+ long nViewHeight = 0;
+ USHORT nViewPosFlags = WINDOW_POSSIZE_POS;
+ Size aViewSize = mpViewWindow->GetSizePixel();
+ if ( meViewAlign == WINDOWALIGN_TOP )
+ {
+ nViewOffX = aTabOffset.X();
+ nViewOffY = nOffY+IMPL_DIALOG_OFFSET;
+ nViewWidth = aTabSize.Width();
+ nViewPosFlags |= WINDOW_POSSIZE_WIDTH;
+ aTabOffset.Y() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ aDlgSize.Height() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ }
+ else if ( meViewAlign == WINDOWALIGN_BOTTOM )
+ {
+ nViewOffX = aTabOffset.X();
+ nViewOffY = aTabOffset.Y()+aTabSize.Height()+IMPL_DIALOG_OFFSET;
+ nViewWidth = aTabSize.Width();
+ nViewPosFlags |= WINDOW_POSSIZE_WIDTH;
+ aDlgSize.Height() += aViewSize.Height()+IMPL_DIALOG_OFFSET;
+ }
+ else if ( meViewAlign == WINDOWALIGN_RIGHT )
+ {
+ nViewOffX = aTabOffset.X()+aTabSize.Width()+IMPL_DIALOG_OFFSET;
+ nViewOffY = aTabOffset.Y();
+ nViewHeight = aTabSize.Height();
+ nViewPosFlags |= WINDOW_POSSIZE_HEIGHT;
+ aDlgSize.Width() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ nBtnEx = aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+ else // meViewAlign == WINDOWALIGN_LEFT
+ {
+ nViewOffX = IMPL_DIALOG_OFFSET;
+ nViewOffY = aTabOffset.Y();
+ nViewHeight = aTabSize.Height();
+ nViewPosFlags |= WINDOW_POSSIZE_HEIGHT;
+ aTabOffset.X() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ aDlgSize.Width() += aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ nBtnEx = aViewSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+
+ mpViewWindow->SetPosSizePixel( nViewOffX, nViewOffY,
+ nViewWidth, nViewHeight,
+ nViewPosFlags );
+ }
+
+ // Positionierung vornehmen
+ pTabControl->SetPosPixel( aTabOffset );
+
+ // Alle anderen Childs positionieren
+ BOOL bTabCtrl = FALSE;
+ int nLines = 0;
+ long nX;
+ long nY = aDlgSize.Height();
+ long nTopX = IMPL_DIALOG_OFFSET;
+
+ // Unter Windows 95 werden die Buttons rechtsbuendig angeordnet
+ nX = IMPL_DIALOG_OFFSET;
+ long nCtrlBarWidth = ((aCtrlSize.Width()+IMPL_DIALOG_OFFSET)*nDownCtrl)-IMPL_DIALOG_OFFSET;
+ if ( nCtrlBarWidth <= (aTabSize.Width()+nBtnEx) )
+ nX = (aTabSize.Width()+nBtnEx) - nCtrlBarWidth + IMPL_DIALOG_OFFSET;
+
+ pChild = pChild = GetWindow( WINDOW_FIRSTCHILD );
+ while ( pChild )
+ {
+ if ( pChild->IsVisible() && (pChild != mpViewWindow) )
+ {
+ if ( pChild == pTabControl )
+ bTabCtrl = TRUE;
+ else if ( bTabCtrl )
+ {
+ if ( !nLines )
+ nLines = 1;
+
+ if ( nX+aCtrlSize.Width()-IMPL_DIALOG_OFFSET > (aTabSize.Width()+nBtnEx) )
+ {
+ nY += aCtrlSize.Height()+IMPL_DIALOG_OFFSET;
+ nX = IMPL_DIALOG_OFFSET;
+ nLines++;
+ }
+
+ pChild->SetPosSizePixel( Point( nX, nY ), aCtrlSize );
+ nX += aCtrlSize.Width()+IMPL_DIALOG_OFFSET;
+ }
+ else
+ {
+ Size aChildSize = pChild->GetSizePixel();
+ pChild->SetPosPixel( Point( nTopX, (nOffY-aChildSize.Height())/2 ) );
+ nTopX += aChildSize.Width()+2;
+ }
+ }
+
+ pChild = pChild->GetWindow( WINDOW_NEXT );
+ }
+
+ aDlgSize.Height() += nLines * (aCtrlSize.Height()+IMPL_DIALOG_OFFSET);
+ SetOutputSizePixel( aDlgSize );
+ }
+
+ // Offset merken
+ if ( nOffY )
+ {
+ Size aDlgSize = GetOutputSizePixel();
+ if ( !mpFixedLine )
+ mpFixedLine = new FixedLine( this );
+ mpFixedLine->SetPosSizePixel( Point( 0, nOffY ),
+ Size( aDlgSize.Width(), 2 ) );
+ mpFixedLine->Show();
+ }
+
+ mbPosControls = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::TabDialog( Window* pParent, WinBits nStyle ) :
+ Dialog( WINDOW_TABDIALOG )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::TabDialog( Window* pParent, const ResId& rResId ) :
+ Dialog( WINDOW_TABDIALOG )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_TABDIALOG );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+TabDialog::~TabDialog()
+{
+ if ( mpFixedLine )
+ delete mpFixedLine;
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::Resize()
+{
+// !!! In the future the controls should be automaticly rearrange
+// !!! if the window is resized
+// !!! if ( !IsRollUp() )
+// !!! ImplPosControls();
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ // Calculate the Layout only for the initialized state
+ if ( mbPosControls )
+ ImplPosControls();
+ }
+ Dialog::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void TabDialog::AdjustLayout()
+{
+ ImplPosControls();
+}
diff --git a/vcl/source/window/tabpage.cxx b/vcl/source/window/tabpage.cxx
new file mode 100644
index 000000000000..af9d5b0a6f4b
--- /dev/null
+++ b/vcl/source/window/tabpage.cxx
@@ -0,0 +1,182 @@
+/*************************************************************************
+ *
+ * $RCSfile: tabpage.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TABPAGE_CXX
+
+#include <tools/ref.hxx>
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_TABPAGE_HXX
+#include <tabpage.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+void TabPage::ImplInit( Window* pParent, WinBits nStyle )
+{
+ if ( !(nStyle & WB_NODIALOGCONTROL) )
+ nStyle |= WB_DIALOGCONTROL;
+
+ Window::ImplInit( pParent, nStyle, NULL );
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::ImplInitSettings()
+{
+ Window* pParent = GetParent();
+ if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
+ {
+ EnableChildTransparentMode( TRUE );
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ SetPaintTransparent( TRUE );
+ SetBackground();
+ }
+ else
+ {
+ EnableChildTransparentMode( FALSE );
+ SetParentClipMode( 0 );
+ SetPaintTransparent( FALSE );
+
+ if ( IsControlBackground() )
+ SetBackground( GetControlBackground() );
+ else
+ SetBackground( pParent->GetBackground() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabPage::TabPage( Window* pParent, WinBits nStyle ) :
+ Window( WINDOW_TABPAGE )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabPage::TabPage( Window* pParent, const ResId& rResId ) :
+ Window( WINDOW_TABPAGE )
+{
+ rResId.SetRT( RSC_TABPAGE );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( Application::IsAutoMnemonicEnabled() )
+ ImplWindowAutoMnemonic( this );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::ActivatePage()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void TabPage::DeactivatePage()
+{
+}
diff --git a/vcl/source/window/toolbox.cxx b/vcl/source/window/toolbox.cxx
new file mode 100644
index 000000000000..fcc618cba323
--- /dev/null
+++ b/vcl/source/window/toolbox.cxx
@@ -0,0 +1,4176 @@
+/*************************************************************************
+ *
+ * $RCSfile: toolbox.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TOOLBOX_CXX
+
+#include <string.h>
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_DECOVIEW_HXX
+#include <decoview.hxx>
+#endif
+#ifndef _SV_ACCEL_HXX
+#include <accel.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_SPIN_H
+#include <spin.h>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#define private public
+#ifndef _SV_TOOLBOX_HXX
+#include <toolbox.hxx>
+#endif
+#undef private
+#ifndef _SV_TOOLBOX_H
+#include <toolbox.h>
+#endif
+
+// =======================================================================
+
+DBG_NAMEEX( Window );
+
+// =======================================================================
+
+#define SMALLBUTTON_HSIZE 7
+#define SMALLBUTTON_VSIZE 7
+
+#define SMALLBUTTON_OFF_NORMAL_X 3
+#define SMALLBUTTON_OFF_NORMAL_Y 3
+#define SMALLBUTTON_OFF_CHECKED_X 4
+#define SMALLBUTTON_OFF_CHECKED_Y 4
+#define SMALLBUTTON_OFF_PRESSED_X 5
+#define SMALLBUTTON_OFF_PRESSED_Y 5
+
+#define OUTBUTTON_SIZE 6
+#define OUTBUTTON_BORDER 4
+#define OUTBUTTON_OFF_NORMAL_X 1
+#define OUTBUTTON_OFF_NORMAL_Y 1
+
+// -----------------------------------------------------------------------
+
+#define DEF_MIN_WIDTH 8
+#define DEF_MIN_HEIGHT 8
+#define DEF_IMAGE_WIDTH 16
+#define DEF_IMAGE_HEIGHT 15
+#define DEF_TEXT_WIDTH 40
+
+#define TB_TEXTOFFSET 2
+#define TB_LINESPACING 3
+#define TB_SPIN_SIZE 14
+#define TB_SPIN_OFFSET 2
+#define TB_BORDER_OFFSET1 4
+#define TB_BORDER_OFFSET2 2
+#define TB_CUSTOMIZE_OFFSET 2
+#define TB_RESIZE_OFFSET 3
+#define TB_MAXLINES 5
+#define TB_MAXNOSCROLL 32765
+
+#define TB_MIN_WIN_WIDTH 20
+
+#define TB_CALCMODE_HORZ 1
+#define TB_CALCMODE_VERT 2
+#define TB_CALCMODE_FLOAT 3
+
+#define TB_WBLINESIZING (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
+
+#define TB_MAX_GROUPS 100
+
+#define DOCK_LINEHSIZE ((USHORT)0x0001)
+#define DOCK_LINEVSIZE ((USHORT)0x0002)
+#define DOCK_LINERIGHT ((USHORT)0x1000)
+#define DOCK_LINEBOTTOM ((USHORT)0x2000)
+#define DOCK_LINELEFT ((USHORT)0x4000)
+#define DOCK_LINETOP ((USHORT)0x8000)
+#define DOCK_LINEOFFSET 3
+
+// -----------------------------------------------------------------------
+
+struct ImplToolSize
+{
+ long mnWidth;
+ long mnHeight;
+ USHORT mnLines;
+};
+
+// -----------------------------------------------------------------------
+
+struct ImplButtonData
+{
+ VirtualDevice* mpBtnDev;
+ long mnWidth;
+ long mnHeight;
+ USHORT mnRefCount;
+};
+
+DECLARE_LIST( ImplButtonList, ImplButtonData* );
+
+// -----------------------------------------------------------------------
+
+DECLARE_LIST( ImplTBList, ToolBox* );
+
+class ImplTBDragMgr
+{
+private:
+ ImplTBList* mpBoxList;
+ ToolBox* mpDragBox;
+ Point maMouseOff;
+ Rectangle maRect;
+ Rectangle maStartRect;
+ Accelerator maAccel;
+ long mnMinWidth;
+ long mnMaxWidth;
+ USHORT mnLineMode;
+ USHORT mnStartLines;
+ void* mpCustomizeData;
+ BOOL mbCustomizeMode;
+ BOOL mbResizeMode;
+ BOOL mbShowDragRect;
+
+public:
+ ImplTBDragMgr();
+ ~ImplTBDragMgr();
+
+ void Insert( ToolBox* pBox )
+ { mpBoxList->Insert( pBox ); }
+ void Remove( ToolBox* pBox )
+ { mpBoxList->Remove( pBox ); }
+ ULONG Count() const
+ { return mpBoxList->Count(); }
+
+ ToolBox* FindToolBox( const Rectangle& rRect );
+
+ void StartDragging( ToolBox* pDragBox,
+ const Point& rPos, const Rectangle& rRect,
+ USHORT nLineMode, BOOL bResizeItem,
+ void* pData = NULL );
+ void Dragging( const Point& rPos );
+ void EndDragging( BOOL bOK = TRUE );
+ void HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
+ void UpdateDragRect();
+ DECL_LINK( SelectHdl, Accelerator* );
+
+ void StartCustomizeMode();
+ void EndCustomizeMode();
+ BOOL IsCustomizeMode() { return mbCustomizeMode; }
+ BOOL IsResizeMode() { return mbResizeMode; }
+};
+
+// -----------------------------------------------------------------------
+
+static ImplTBDragMgr* ImplGetTBDragMgr()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maCtrlData.mpTBDragMgr )
+ pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
+ return pSVData->maCtrlData.mpTBDragMgr;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawConfigFrame( ToolBox* pThis, const Rectangle& rRect )
+{
+/*
+ Color aBlackColor( COL_BLACK );
+ Pen aOldPen;
+ Brush aOldBrush;
+ Pen aNullPen( PEN_NULL );
+
+ aOldPen = pThis->GetPen();
+ pThis->SetPen( aNullPen );
+ if ( pThis->IsSVLook() )
+ {
+ Color aFaceColor( COL_3DFACE );
+ Brush aBrush( aFaceColor, aBlackColor, BRUSH_50 );
+ aOldBrush = pThis->GetFillInBrush();
+ pThis->SetFillInBrush( aBrush );
+ }
+ else
+ {
+ Color aWhiteColor( COL_WHITE );
+ Brush aBrush( aBlackColor, aWhiteColor, BRUSH_50 );
+ aOldBrush = pThis->GetFillInBrush();
+ pThis->SetFillInBrush( aBrush );
+ }
+ pThis->DrawRect( Rectangle( rRect.Left(), rRect.Top(),
+ rRect.Right(), rRect.Top()+2 ) );
+ pThis->DrawRect( Rectangle( rRect.Left(), rRect.Top(),
+ rRect.Left()+2, rRect.Bottom() ) );
+ pThis->DrawRect( Rectangle( rRect.Left(), rRect.Bottom()-2,
+ rRect.Right(), rRect.Bottom() ) );
+ pThis->DrawRect( Rectangle( rRect.Right()-2, rRect.Top(),
+ rRect.Right(), rRect.Bottom() ) );
+
+ pThis->SetPen( aOldPen );
+ pThis->SetFillInBrush( aOldBrush );
+*/
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
+ long& rRight, long& rBottom )
+{
+ if ( eAlign == WINDOWALIGN_TOP )
+ {
+ rLeft = 0;
+ rTop = 2;
+ rRight = 0;
+ rBottom = 0;
+ }
+ else if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ rLeft = 2;
+ rTop = 2;
+ rRight = 0;
+ rBottom = 2;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ rLeft = 0;
+ rTop = 0;
+ rRight = 0;
+ rBottom = 2;
+ }
+ else
+ {
+ rLeft = 0;
+ rTop = 2;
+ rRight = 2;
+ rBottom = 2;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawBorder( ToolBox* pWin )
+{
+ const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
+ long nDX = pWin->mnDX;
+ long nDY = pWin->mnDY;
+
+ if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
+ if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
+ {
+ if ( pWin->meAlign == WINDOWALIGN_LEFT )
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ else
+ {
+ pWin->SetLineColor( rStyleSettings.GetShadowColor() );
+ pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
+ pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
+ pWin->SetLineColor( rStyleSettings.GetLightColor() );
+ pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
+ pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static Size ImplCalcSize( const ToolBox* pThis,
+ USHORT nCalcLines, USHORT nCalcMode = 0 )
+{
+ long nMax;
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+ Size aSize;
+ WindowAlign eOldAlign;
+ BOOL bOldHorz;
+
+ // Gegebenenfalls neu durchrechnen
+ if ( nCalcMode )
+ {
+ eOldAlign = pThis->meAlign;
+ bOldHorz = pThis->mbHorz;
+
+ if ( nCalcMode == TB_CALCMODE_HORZ )
+ {
+ ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom );
+ ((ToolBox*)pThis)->mbHorz = TRUE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
+ }
+ else if ( nCalcMode == TB_CALCMODE_FLOAT )
+ {
+ nLeft = nTop = nRight = nBottom = 0;
+ ((ToolBox*)pThis)->mbHorz = TRUE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
+ }
+ else
+ {
+ ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom );
+ ((ToolBox*)pThis)->mbHorz = FALSE;
+ if ( pThis->mbHorz != bOldHorz )
+ ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
+ }
+
+ if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
+ ((ToolBox*)pThis)->mbCalc = TRUE;
+ }
+ else
+ ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom );
+
+ ((ToolBox*)pThis)->ImplCalcItem();
+
+ if ( pThis->mbHorz )
+ {
+ if ( pThis->mnWinHeight-2 > pThis->mnItemHeight )
+ aSize.Height() = nCalcLines * pThis->mnWinHeight-2;
+ else
+ aSize.Height() = nCalcLines * pThis->mnItemHeight;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
+
+ if ( !(pThis->mnWinStyle & WB_SCROLL) )
+ {
+ nMax = 0;
+ ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
+ if ( nMax )
+ aSize.Width() += nMax;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
+ }
+ }
+ else
+ {
+ aSize.Width() = nCalcLines * pThis->mnItemWidth;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
+
+ if ( !(pThis->mnWinStyle & WB_SCROLL) )
+ {
+ nMax = 0;
+ ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
+ if ( nMax )
+ aSize.Height() += nMax;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
+ }
+ }
+
+ // Gegebenenfalls wieder alte Werte herstellen
+ if ( nCalcMode )
+ {
+ if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
+ {
+ ((ToolBox*)pThis)->meAlign = eOldAlign;
+ ((ToolBox*)pThis)->mbHorz = bOldHorz;
+ ((ToolBox*)pThis)->mbCalc = TRUE;
+ }
+ }
+
+ if ( aSize.Width() )
+ aSize.Width() += pThis->mnBorderX*2;
+ if ( aSize.Height() )
+ aSize.Height() += pThis->mnBorderY*2;
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcFloatSizes( ToolBox* pThis )
+{
+ if ( pThis->mpFloatSizeAry )
+ return;
+
+ // min. Groesse berechnen
+ long nCalcSize = pThis->mnItemWidth;
+ ImplToolItem* pItem;
+ pItem = pThis->mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( pItem->mpWindow )
+ {
+ long nTempSize = pItem->mpWindow->GetSizePixel().Width();
+ if ( nTempSize > nCalcSize )
+ nCalcSize = nTempSize;
+ }
+ else if ( pItem->mnNonStdSize )
+ {
+ if ( pItem->mnNonStdSize > nCalcSize )
+ nCalcSize = pItem->mnNonStdSize;
+ }
+ }
+
+ pItem = pThis->mpItemList->Next();
+ }
+
+ USHORT i;
+ USHORT nLines;
+ USHORT nCalcLines;
+ USHORT nTempLines;
+ long nHeight;
+ long nMaxLineWidth;
+ long nDesktopWidth = pThis->GetDesktopRectPixel().GetWidth()-10;
+ nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
+ pThis->mpFloatSizeAry = new ImplToolSize[nCalcLines];
+ memset( pThis->mpFloatSizeAry, 0, sizeof( ImplToolSize )*nCalcLines );
+ i = 0;
+ nLines = nCalcLines;
+ while ( nLines )
+ {
+ nHeight = ImplCalcSize( pThis, nLines, TB_CALCMODE_FLOAT ).Height();
+ pThis->mpFloatSizeAry[i].mnHeight = nHeight;
+ pThis->mpFloatSizeAry[i].mnLines = nLines;
+ if ( nCalcSize >= nDesktopWidth )
+ {
+ pThis->mpFloatSizeAry[i].mnWidth = nDesktopWidth;
+ nLines--;
+ }
+ else
+ {
+ pThis->mpFloatSizeAry[i].mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
+ nLines--;
+ if ( nLines )
+ {
+ do
+ {
+ nCalcSize += pThis->mnItemWidth;
+ nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
+ }
+ while ( (nLines < nTempLines) && (nTempLines != 1) && (nCalcSize < nDesktopWidth) );
+ if ( nTempLines < nLines )
+ nLines = nTempLines;
+ }
+ }
+ i++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static Size ImplCalcFloatSize( ToolBox* pThis, USHORT& rLines )
+{
+ ImplCalcFloatSizes( pThis );
+
+ if ( !rLines )
+ {
+ rLines = pThis->mnFloatLines;
+ if ( !rLines )
+ rLines = pThis->mnLines;
+ }
+
+ USHORT i = 0;
+ while ( rLines < pThis->mpFloatSizeAry[i].mnLines )
+ i++;
+
+ Size aSize( pThis->mpFloatSizeAry[i].mnWidth,
+ pThis->mpFloatSizeAry[i].mnHeight );
+ rLines = pThis->mpFloatSizeAry[i].mnLines;
+ if ( pThis->maNextToolBoxStr.Len() && pThis->mbScroll )
+ aSize.Width() += TB_SPIN_SIZE-TB_SPIN_OFFSET;
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplCalcLines( ToolBox* pThis, long nToolSize )
+{
+ long nLineHeight;
+
+ if ( pThis->mbHorz )
+ {
+ if ( pThis->mnWinHeight-2 > pThis->mnItemHeight )
+ nLineHeight = pThis->mnWinHeight-2;
+ else
+ nLineHeight = pThis->mnItemHeight;
+ }
+ else
+ nLineHeight = pThis->mnItemWidth;
+
+ if ( pThis->mnWinStyle & WB_BORDER )
+ nToolSize -= TB_BORDER_OFFSET2*2;
+
+ if ( pThis->mnWinStyle & WB_LINESPACING )
+ {
+ nLineHeight += TB_LINESPACING;
+ nToolSize += TB_LINESPACING;
+ }
+
+ return (USHORT)(nToolSize/nLineHeight);
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplTestLineSize( ToolBox* pThis, const Point& rPos )
+{
+ if ( !pThis->IsFloatingMode() &&
+ (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
+ {
+ WindowAlign eAlign = pThis->GetAlign();
+
+ if ( eAlign == WINDOWALIGN_LEFT )
+ {
+ if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
+ return DOCK_LINEHSIZE | DOCK_LINERIGHT;
+ }
+ else if ( eAlign == WINDOWALIGN_TOP )
+ {
+ if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
+ return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
+ }
+ else if ( eAlign == WINDOWALIGN_RIGHT )
+ {
+ if ( rPos.X() < DOCK_LINEOFFSET )
+ return DOCK_LINEHSIZE | DOCK_LINELEFT;
+ }
+ else if ( eAlign == WINDOWALIGN_BOTTOM )
+ {
+ if ( rPos.Y() < DOCK_LINEOFFSET )
+ return DOCK_LINEVSIZE | DOCK_LINETOP;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
+ USHORT nLineMode )
+{
+ BOOL mbHorz;
+ long nOneLineSize;
+ long nCurSize;
+ long nMaxSize;
+ long nSize;
+ Size aSize;
+
+ if ( nLineMode & DOCK_LINERIGHT )
+ {
+ nCurSize = rPos.X() - rRect.Left();
+ mbHorz = FALSE;
+ }
+ else if ( nLineMode & DOCK_LINEBOTTOM )
+ {
+ nCurSize = rPos.Y() - rRect.Top();
+ mbHorz = TRUE;
+ }
+ else if ( nLineMode & DOCK_LINELEFT )
+ {
+ nCurSize = rRect.Right() - rPos.X();
+ mbHorz = FALSE;
+ }
+ else if ( nLineMode & DOCK_LINETOP )
+ {
+ nCurSize = rRect.Bottom() - rPos.Y();
+ mbHorz = TRUE;
+ }
+
+ Size aWinSize = pThis->GetSizePixel();
+ USHORT nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
+ if ( nMaxLines > TB_MAXLINES )
+ nMaxLines = TB_MAXLINES;
+ if ( mbHorz )
+ {
+ nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
+ nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
+ if ( nMaxSize < aWinSize.Height() )
+ nMaxSize = aWinSize.Height();
+ }
+ else
+ {
+ nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
+ nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
+ if ( nMaxSize < aWinSize.Width() )
+ nMaxSize = aWinSize.Width();
+ }
+
+ USHORT i = 1;
+ if ( nCurSize <= nOneLineSize )
+ nSize = nOneLineSize;
+ else
+ {
+ nSize = 0;
+ while ( (nSize < nCurSize) && (i < nMaxLines) )
+ {
+ i++;
+ aSize = ImplCalcSize( pThis, i );
+ if ( mbHorz )
+ nSize = aSize.Height();
+ else
+ nSize = aSize.Width();
+ if ( nSize > nMaxSize )
+ {
+ i--;
+ aSize = ImplCalcSize( pThis, i );
+ if ( mbHorz )
+ nSize = aSize.Height();
+ else
+ nSize = aSize.Width();
+ break;
+ }
+ }
+ }
+
+ if ( nLineMode & DOCK_LINERIGHT )
+ rRect.Right() = rRect.Left()+nSize-1;
+ else if ( nLineMode & DOCK_LINEBOTTOM )
+ rRect.Bottom() = rRect.Top()+nSize-1;
+ else if ( nLineMode & DOCK_LINELEFT )
+ rRect.Left() = rRect.Right()-nSize;
+ else if ( nLineMode & DOCK_LINETOP )
+ rRect.Top() = rRect.Bottom()-nSize;
+
+ pThis->mnDockLines = i;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplFindItemPos( ToolBox* pBox, const Point& rPos )
+{
+ USHORT nPos = 0;
+ long nLast = 0;
+ Point aPos = rPos;
+ Size aSize( pBox->mnDX, pBox->mnDY );
+
+ if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
+ aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
+ if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
+ aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
+
+ // Item suchen, das geklickt wurde
+ ImplToolItem* pItem = pBox->mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbVisible )
+ {
+ if ( nLast || !pItem->maRect.IsEmpty() )
+ {
+ if ( pBox->mbHorz )
+ {
+ if ( nLast &&
+ ((nLast < pItem->maRect.Top()) || pItem->maRect.IsEmpty()) )
+ return nPos;
+
+ if ( aPos.Y() <= pItem->maRect.Bottom() )
+ {
+ if ( aPos.X() < pItem->maRect.Left() )
+ return nPos;
+ else if ( aPos.X() < pItem->maRect.Right() )
+ return nPos+1;
+ else if ( !nLast )
+ nLast = pItem->maRect.Bottom();
+ }
+ }
+ else
+ {
+ if ( nLast &&
+ ((nLast < pItem->maRect.Left()) || pItem->maRect.IsEmpty()) )
+ return nPos;
+
+ if ( aPos.X() <= pItem->maRect.Right() )
+ {
+ if ( aPos.Y() < pItem->maRect.Top() )
+ return nPos;
+ else if ( aPos.Y() < pItem->maRect.Bottom() )
+ return nPos+1;
+ else if ( !nLast )
+ nLast = pItem->maRect.Right();
+ }
+ }
+ }
+ }
+
+ nPos++;
+ pItem = pBox->mpItemList->Next();
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+ImplTBDragMgr::ImplTBDragMgr()
+{
+ mpBoxList = new ImplTBList( 4, 4 );
+ mnLineMode = 0;
+ mnStartLines = 0;
+ mbCustomizeMode = FALSE;
+ mbResizeMode = FALSE;
+ mbShowDragRect = FALSE;
+ mpDragBox = NULL;
+
+ maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
+ maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
+ maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+ImplTBDragMgr::~ImplTBDragMgr()
+{
+ delete mpBoxList;
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
+{
+ // ToolBox suchen
+ Point aPos = rRect.Center();
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ if ( pBox->IsReallyVisible() )
+ {
+ Window* pWindow = pBox->ImplGetFrameWindow()->FindWindow( aPos );
+ if ( pWindow && pBox->IsWindowOrChild( pWindow ) )
+ return pBox;
+ }
+ pBox = mpBoxList->Next();
+ }
+
+ // Falls so nicht gefunden wurde, suchen wir die ToolBox ueber das Rechteck
+ pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ if ( pBox->IsReallyVisible() )
+ {
+ if ( pBox->IsFloatingMode() )
+ {
+ Rectangle aTempRect( pBox->GetPosPixel(), pBox->GetSizePixel() );
+ if ( aTempRect.IsOver( rRect ) )
+ return pBox;
+ }
+ }
+
+ pBox = mpBoxList->Next();
+ }
+
+ pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ if ( pBox->IsReallyVisible() )
+ {
+ if ( !pBox->IsFloatingMode() )
+ {
+ Point aPos = pBox->GetPosPixel();
+ aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
+ Rectangle aTempRect( aPos, pBox->GetSizePixel() );
+ if ( aTempRect.IsOver( rRect ) )
+ return pBox;
+ }
+ }
+
+ pBox = mpBoxList->Next();
+ }
+
+ return pBox;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
+ const Point& rPos, const Rectangle& rRect,
+ USHORT nDragLineMode, BOOL bResizeItem,
+ void* pData )
+{
+ mpDragBox = pToolBox;
+ pToolBox->CaptureMouse();
+ pToolBox->mbDragging = TRUE;
+ Application::InsertAccel( &maAccel );
+
+ if ( nDragLineMode )
+ {
+ mnLineMode = nDragLineMode;
+ mnStartLines = pToolBox->mnDockLines;
+ }
+ else
+ {
+ mpCustomizeData = pData;
+ mbResizeMode = bResizeItem;
+ pToolBox->Activate();
+ pToolBox->mnCurItemId = pToolBox->mnConfigItem;
+ pToolBox->Highlight();
+ pToolBox->mnCurItemId = 0;
+ if ( !mbResizeMode )
+ ImplDrawConfigFrame( pToolBox, rRect );
+ else
+ {
+ if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
+ mnMinWidth = rRect.GetWidth();
+ else
+ mnMinWidth = TB_MIN_WIN_WIDTH;
+ mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
+ TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
+ }
+ }
+
+ // MouseOffset berechnen
+ maMouseOff.X() = rRect.Left() - rPos.X();
+ maMouseOff.Y() = rRect.Top() - rPos.Y();
+ maRect = rRect;
+ maStartRect = rRect;
+ mbShowDragRect = TRUE;
+ pToolBox->ShowTracking( maRect );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::Dragging( const Point& rPos )
+{
+ if ( mnLineMode )
+ {
+ ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
+ Point aPos = mpDragBox->OutputToScreenPixel( rPos );
+ Point aOff = mpDragBox->OutputToScreenPixel( Point() );
+ maRect.Move( aOff.X(), aOff.Y() );
+ mpDragBox->Docking( rPos, maRect );
+ maRect.Move( -aOff.X(), -aOff.Y() );
+ mpDragBox->ShowTracking( maRect );
+ }
+ else
+ {
+ if ( mbResizeMode )
+ {
+ long nXOff = rPos.X()-maStartRect.Left();
+ nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
+ if ( nXOff < mnMinWidth )
+ nXOff = mnMinWidth;
+ if ( nXOff > mnMaxWidth )
+ nXOff = mnMaxWidth;
+ maRect.Right() = maStartRect.Left()+nXOff;
+ }
+ else
+ {
+ maRect.SetPos( rPos );
+ maRect.Move( maMouseOff.X(), maMouseOff.Y() );
+ }
+ mpDragBox->ShowTracking( maRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::EndDragging( BOOL bOK )
+{
+ mpDragBox->HideTracking();
+ mpDragBox->ReleaseMouse();
+ mpDragBox->mbDragging = FALSE;
+ mbShowDragRect = FALSE;
+ Application::RemoveAccel( &maAccel );
+
+ if ( mnLineMode )
+ {
+ if ( !bOK )
+ {
+ mpDragBox->mnDockLines = mnStartLines;
+ mpDragBox->EndDocking( maStartRect, FALSE );
+ }
+ else
+ mpDragBox->EndDocking( maRect, FALSE );
+ mnLineMode = 0;
+ mnStartLines = 0;
+ }
+ else
+ {
+ USHORT nTempItem = mpDragBox->mnConfigItem;
+ if ( nTempItem )
+ {
+ mpDragBox->mnConfigItem = 0;
+ if ( !mbResizeMode )
+ mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
+ }
+
+ if ( bOK && (maRect != maStartRect) )
+ {
+ if ( mbResizeMode )
+ {
+ ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
+ Size aSize = pItem->mpWindow->GetSizePixel();
+ aSize.Width() = maRect.GetWidth();
+ pItem->mpWindow->SetSizePixel( aSize );
+
+ // ToolBox neu brechnen und neu ausgeben
+ mpDragBox->ImplInvalidate( TRUE );
+ mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
+ TOOLBOX_CUSTOMIZE_RESIZE,
+ mpCustomizeData ) );
+ }
+ else
+ {
+ Point aOff = mpDragBox->OutputToScreenPixel( Point() );
+ Rectangle aScreenRect( maRect );
+ aScreenRect.Move( aOff.X(), aOff.Y() );
+ ToolBox* pDropBox = FindToolBox( aScreenRect );
+ if ( pDropBox )
+ {
+ // Such-Position bestimmen
+ Point aPos;
+ if ( pDropBox->mbHorz )
+ {
+ aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
+ aPos.Y() = aScreenRect.Center().Y();
+ }
+ else
+ {
+ aPos.X() = aScreenRect.Center().X();
+ aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
+ }
+
+ aPos = pDropBox->ScreenToOutputPixel( aPos );
+ USHORT nPos = ImplFindItemPos( pDropBox, aPos );
+ mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
+ nPos, mpCustomizeData ) );
+ }
+ else
+ {
+ mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
+ 0, mpCustomizeData ) );
+ }
+ }
+ }
+ mpCustomizeData = NULL;
+ mbResizeMode = FALSE;
+ mpDragBox->Deactivate();
+ }
+
+ mpDragBox = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::UpdateDragRect()
+{
+ // Nur Updaten, wenn wir schon im Dragging sind
+ if ( !mbShowDragRect )
+ return;
+
+ if ( !mbResizeMode )
+ ImplDrawConfigFrame( mpDragBox, maStartRect );
+
+ mpDragBox->ShowTracking( maRect );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
+{
+ if ( pAccel->GetCurItemId() == KEY_ESCAPE )
+ EndDragging( FALSE );
+ else
+ EndDragging( TRUE );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::StartCustomizeMode()
+{
+ mbCustomizeMode = TRUE;
+
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ pBox->ImplStartCustomizeMode();
+ pBox = mpBoxList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTBDragMgr::EndCustomizeMode()
+{
+ mbCustomizeMode = FALSE;
+
+ ToolBox* pBox = mpBoxList->First();
+ while ( pBox )
+ {
+ pBox->ImplEndCustomizeMode();
+ pBox = mpBoxList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static ImplButtonList* ImplGetButtonList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maCtrlData.mpButtonList )
+ pSVData->maCtrlData.mpButtonList = new ImplButtonList;
+ return pSVData->maCtrlData.mpButtonList;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawOutButton( OutputDevice* pOutDev, const Rectangle& rRect,
+ USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
+ Color aShadowColor = rStyleSettings.GetShadowColor();
+ Point aPos( rRect.TopLeft() );
+ Size aSize( rRect.GetSize() );
+ long nOffset = 0;
+
+ if ( pOutDev->GetBackground().GetColor() == aShadowColor )
+ aShadowColor = rStyleSettings.GetDarkShadowColor();
+
+ if ( nStyle & BUTTON_DRAW_PRESSED )
+ {
+ aPos.X()++;
+ aPos.Y()++;
+ nOffset++;
+ }
+
+ // Hintergrund loeschen
+ pOutDev->Erase( rRect );
+
+ // Button zeichnen
+ pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pOutDev->DrawLine( aPos,
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ) );
+ pOutDev->DrawLine( aPos,
+ Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ pOutDev->SetLineColor( aShadowColor );
+ pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ),
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ pOutDev->DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ),
+ Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
+ for ( long i = 0; i < OUTBUTTON_BORDER-1-nOffset; i++ )
+ {
+ pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+OUTBUTTON_BORDER ),
+ Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+aSize.Height()-1 ) );
+ pOutDev->DrawLine( Point( aPos.X()+OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ),
+ Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplInitButtonVirDev( const Window* pBox, VirtualDevice* pVirDev )
+{
+ // Farben/Settings vom Window am virtuellen Device setzen
+ pVirDev->SetSettings( pBox->GetSettings() );
+ const Wallpaper& rWallpaper = pBox->GetBackground();
+ if ( rWallpaper.GetStyle() == WALLPAPER_NULL )
+ pVirDev->SetBackground( Wallpaper( pBox->GetSettings().GetStyleSettings().GetFaceColor() ) );
+ else
+ pVirDev->SetBackground( rWallpaper );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawButtons( VirtualDevice* pVirDev, long nWidth, long nHeight,
+ USHORT nType )
+{
+ // Button Frames ausgeben
+ long nY = 0;
+ if ( nType & TOOLBOX_STYLE_OUTBUTTON )
+ {
+ for ( USHORT i = 0; i < 6; i++ )
+ {
+ USHORT nStyle = 0;
+ if ( i & 0x01 )
+ nStyle = BUTTON_DRAW_PRESSED;
+ ImplDrawOutButton( pVirDev, Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ), nStyle );
+ nY += nHeight;
+ }
+ }
+ else
+ {
+ DecorationView aDecoView( pVirDev );
+
+ aDecoView.DrawButton( Rectangle( 0, 0, nWidth-1, nHeight-1 ), 0 );
+ nY += nHeight;
+ aDecoView.DrawButton( Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ),
+ BUTTON_DRAW_PRESSED );
+ nY += nHeight;
+ aDecoView.DrawButton( Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ),
+ BUTTON_DRAW_CHECKED );
+ nY += nHeight;
+ aDecoView.DrawButton( Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ),
+ BUTTON_DRAW_CHECKED | BUTTON_DRAW_PRESSED );
+ nY += nHeight;
+ aDecoView.DrawButton( Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ),
+ BUTTON_DRAW_DONTKNOW );
+ nY += nHeight;
+ aDecoView.DrawButton( Rectangle( 0, nY, nWidth-1, nY+nHeight-1 ),
+ BUTTON_DRAW_DONTKNOW | BUTTON_DRAW_PRESSED );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplButtonSysChange( ToolBox* pBox, VirtualDevice* pVirDev, USHORT nType )
+{
+ ImplButtonList* pBtnList = ImplGetButtonList();
+ ImplButtonData* pBtnData;
+
+ pBtnData = pBtnList->First();
+ while ( pBtnData )
+ {
+ if ( pBtnData->mpBtnDev == pVirDev )
+ {
+ ImplInitButtonVirDev( pBox, pVirDev );
+ ImplDrawButtons( pVirDev, pBtnData->mnWidth, pBtnData->mnHeight, nType );
+ break;
+ }
+
+ pBtnData = pBtnList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static VirtualDevice* ImplGetButtonDevice( ToolBox* pBox,
+ long nWidth, long nHeight, USHORT nType )
+{
+ ImplButtonList* pBtnList = ImplGetButtonList();
+ ImplButtonData* pBtnData;
+
+ pBtnData = pBtnList->First();
+ while ( pBtnData )
+ {
+ if ( (pBtnData->mnWidth == nWidth) &&
+ (pBtnData->mnHeight == nHeight) )
+ {
+ pBtnData->mnRefCount++;
+ return pBtnData->mpBtnDev;
+ }
+
+ pBtnData = pBtnList->Next();
+ }
+
+ VirtualDevice* pVirDev = new VirtualDevice( *pBox );
+
+ // Neue Groesse vom virtuellen Device setzen
+ pVirDev->SetOutputSizePixel( Size( nWidth, nHeight*6 ), TRUE );
+ ImplInitButtonVirDev( pBox, pVirDev );
+ ImplDrawButtons( pVirDev, nWidth, nHeight, nType );
+
+ pBtnData = new ImplButtonData;
+ pBtnData->mpBtnDev = pVirDev;
+ pBtnData->mnWidth = nWidth;
+ pBtnData->mnHeight = nHeight;
+ pBtnData->mnRefCount = 1;
+ pBtnList->Insert( pBtnData, LIST_APPEND );
+
+ return pVirDev;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplFreeButtonDevice( VirtualDevice* pVirDev )
+{
+ ImplButtonList* pBtnList = ImplGetButtonList();
+ ImplButtonData* pBtnData;
+
+ // Virtuelles Device suchen und loeschen
+ pBtnData = pBtnList->First();
+ while ( pBtnData )
+ {
+ if ( pBtnData->mpBtnDev == pVirDev )
+ {
+ pBtnData->mnRefCount--;
+ if ( !pBtnData->mnRefCount )
+ {
+ delete pBtnData->mpBtnDev;
+ delete pBtnData;
+ pBtnList->Remove();
+ }
+
+ return;
+ }
+
+ pBtnData = pBtnList->Next();
+ }
+
+ DBG_ERRORFILE( "ImplFreeButtonDevice(): Button-Device not in list" );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
+{
+ // Variablen initialisieren
+ mpBtnDev = NULL;
+ mpFloatSizeAry = NULL;
+ mpItemList = new ImplToolItemList;
+ mpFloatWin = NULL;
+ mnDX = 0;
+ mnDY = 0;
+ mnItemWidth = 0;
+ mnItemHeight = 0;
+ mnWinHeight = 0;
+ mnBorderX = 0;
+ mnBorderY = 0;
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ mnLastResizeDY = 0;
+ mnOutStyle = 0;
+ mnHighItemId = 0;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnLines = 1;
+ mnCurLine = 1;
+ mnCurLines = 1;
+ mnVisLines = 1;
+ mnFloatLines = 0;
+ mnConfigItem = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ mbCommandDrag = FALSE;
+ mbUpper = FALSE;
+ mbLower = FALSE;
+ mbNextTool = FALSE;
+ mbIn = FALSE;
+ mbCalc = TRUE;
+ mbFormat = FALSE;
+ mbFullPaint = FALSE;
+ mbHorz = TRUE;
+ mbScroll = (nStyle & WB_SCROLL) != 0;
+ mbCustomize = FALSE;
+ mbCustomizeMode = FALSE;
+ mbDragging = FALSE;
+ mbHideStatusText = FALSE;
+ mbMenuStrings = FALSE;
+ meButtonType = BUTTON_SYMBOL;
+ meAlign = WINDOWALIGN_TOP;
+ meLastStyle = POINTER_ARROW;
+ mnWinStyle = nStyle;
+ maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
+
+ DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
+
+ ImplInitSettings( TRUE, TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInitSettings( BOOL bFont,
+ BOOL bForeground, BOOL bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetButtonTextColor();
+ else
+ aColor = rStyleSettings.GetWindowTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplLoadRes( const ResId& rResId )
+{
+ DockingWindow::ImplLoadRes( rResId );
+
+ USHORT nObjMask;
+
+ nObjMask = ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
+ SetButtonType( (ButtonType)ReadShortRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_ALIGN )
+ SetAlign( (WindowAlign)ReadShortRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
+ SetLineCount( ReadShortRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
+ {
+ BOOL bCust = (BOOL)ReadShortRes();
+ EnableCustomize( bCust );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
+ {
+ BOOL bCust = (BOOL)ReadShortRes();
+ EnableMenuStrings( bCust );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
+ SetFloatingLines( ReadShortRes() );
+
+ if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
+ {
+ maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ }
+
+ if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
+ {
+ USHORT nEle = ReadShortRes();
+
+ // Item hinzufuegen
+ for ( USHORT i = 0; i < nEle; i++ )
+ {
+ InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
+ DockingWindow( WINDOW_TOOLBOX )
+{
+ ImplInit( pParent, nStyle );
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
+ DockingWindow( WINDOW_TOOLBOX )
+{
+ rResId.SetRT( RSC_TOOLBOX );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle );
+ ImplLoadRes( rResId );
+
+ // Groesse des FloatingWindows berechnen und umschalten, wenn die
+ // ToolBox initial im FloatingModus ist
+ if ( IsFloatingMode() )
+ mbHorz = TRUE;
+ else
+ Resize();
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+ToolBox::~ToolBox()
+{
+ // Falls noch ein Floating-Window connected ist, dann den
+ // PopupModus beenden
+ if ( mpFloatWin )
+ mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+
+ // Items aus der Liste loeschen
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Itemlist loeschen
+ delete mpItemList;
+
+ // FloatSizeAry gegebenenfalls loeschen
+ if ( mpFloatSizeAry )
+ delete mpFloatSizeAry;
+
+ // Wenn keine ToolBox-Referenzen mehr auf die Listen bestehen, dann
+ // Listen mit wegloeschen
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maCtrlData.mpTBDragMgr )
+ {
+ // Wenn im TBDrag-Manager, dann wieder rausnehmen
+ if ( mbCustomize )
+ pSVData->maCtrlData.mpTBDragMgr->Remove( this );
+
+ if ( !pSVData->maCtrlData.mpTBDragMgr->Count() )
+ {
+ delete pSVData->maCtrlData.mpTBDragMgr;
+ pSVData->maCtrlData.mpTBDragMgr = NULL;
+ }
+ }
+
+ // Button-Device freigeben
+ if ( mpBtnDev )
+ ImplFreeButtonDevice( mpBtnDev );
+
+ if ( pSVData->maCtrlData.mpButtonList )
+ {
+ if ( !pSVData->maCtrlData.mpButtonList->Count() )
+ {
+ delete pSVData->maCtrlData.mpButtonList;
+ pSVData->maCtrlData.mpButtonList = NULL;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem* ToolBox::ImplGetItem( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return pItem;
+
+ pItem = mpItemList->Next();
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplCalcItem()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // Muss Itemgroesse ueberhaupt neu berechnet werden
+ if ( !mbCalc )
+ return FALSE;
+
+ ImplToolItem* pItem;
+ long nDefWidth;
+ long nDefHeight;
+ long nDefLeftWidth;
+ long nDefLeftHeight;
+ long nMaxWidth;
+ long nMaxHeight;
+ long nHeight;
+ BOOL bImage;
+ BOOL bText;
+ Size aItemSize;
+
+ if ( meButtonType == BUTTON_SYMBOL )
+ {
+ nDefWidth = DEF_IMAGE_WIDTH;
+ nDefHeight = DEF_IMAGE_HEIGHT;
+ nDefLeftWidth = nDefWidth;
+ nDefLeftHeight = nDefHeight;
+ }
+ else if ( meButtonType == BUTTON_TEXT )
+ {
+ nDefWidth = DEF_TEXT_WIDTH;
+ nDefHeight = GetTextHeight();
+ nDefLeftWidth = nDefWidth;
+ nDefLeftHeight = nDefHeight;
+ }
+ else
+ {
+ nDefWidth = DEF_TEXT_WIDTH;
+ nDefHeight = DEF_IMAGE_HEIGHT + GetTextHeight();
+ nDefLeftWidth = nDefWidth;
+ nDefLeftHeight = nDefHeight-DEF_IMAGE_HEIGHT;
+ }
+
+ if ( mpItemList->Count() )
+ {
+ nMaxWidth = DEF_MIN_WIDTH;
+ nMaxHeight = DEF_MIN_HEIGHT;
+ mnWinHeight = 0;
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->meType == TOOLBOXITEM_BUTTON )
+ {
+ if ( !(pItem->maImage) )
+ bImage = FALSE;
+ else
+ bImage = TRUE;
+ if ( !pItem->maText.Len() )
+ bText = FALSE;
+ else
+ bText = TRUE;
+
+ if ( bImage || bText )
+ {
+ pItem->mbEmptyBtn = FALSE;
+
+ if ( meButtonType == BUTTON_SYMBOL )
+ {
+ if ( bImage || !bText )
+ {
+ aItemSize = pItem->maImage.GetSizePixel();
+ pItem->mnNonStdSize = 0;
+ }
+ else
+ {
+ aItemSize.Width() = 0;
+ aItemSize.Height() = GetTextHeight();
+ pItem->mnNonStdSize = GetCtrlTextWidth( pItem->maText )+TB_TEXTOFFSET;
+ }
+ }
+ else if ( meButtonType == BUTTON_TEXT )
+ {
+ if ( bText || !bImage )
+ {
+ aItemSize.Width() = GetCtrlTextWidth( pItem->maText )+TB_TEXTOFFSET;
+ aItemSize.Height() = GetTextHeight();
+ pItem->mnNonStdSize = 0;
+ }
+ else
+ {
+ Size aImageSize = pItem->maImage.GetSizePixel();
+ if ( mbHorz )
+ {
+ aItemSize.Width() = 0;
+ aItemSize.Height() = aImageSize.Height();
+ pItem->mnNonStdSize = aImageSize.Width();
+ }
+ else
+ {
+ aItemSize.Width() = aImageSize.Width();
+ aItemSize.Height() = 0;
+ pItem->mnNonStdSize = aImageSize.Height();
+ }
+ }
+ }
+ else
+ {
+ aItemSize.Width() = GetCtrlTextWidth( pItem->maText )+TB_TEXTOFFSET;
+ aItemSize.Height() = GetTextHeight();
+ Size aImageSize = pItem->maImage.GetSizePixel();
+ if ( pItem->mnBits & TIB_LEFT )
+ {
+ aItemSize.Width() += aImageSize.Width();
+ if ( aImageSize.Height() > aItemSize.Height() )
+ aItemSize.Height() = aImageSize.Height();
+ }
+ else
+ {
+ aItemSize.Height() += aImageSize.Height();
+ if ( aImageSize.Width() > aItemSize.Width() )
+ aItemSize.Width() = aImageSize.Width();
+ }
+ pItem->mnNonStdSize = 0;
+ }
+
+ if ( !pItem->mnNonStdSize && (pItem->mnBits & TIB_AUTOSIZE) )
+ {
+ pItem->mnNonStdSize = aItemSize.Width();
+ aItemSize.Width() = 0;
+ }
+ }
+ else
+ {
+ if ( pItem->mnBits & TIB_LEFT )
+ {
+ aItemSize.Width() = nDefLeftWidth;
+ aItemSize.Height() = nDefLeftHeight;
+ }
+ else
+ {
+ aItemSize.Width() = nDefWidth;
+ aItemSize.Height() = nDefHeight;
+ }
+ pItem->mbEmptyBtn = TRUE;
+ }
+
+ if ( aItemSize.Width() > nMaxWidth )
+ nMaxWidth = aItemSize.Width();
+ if ( aItemSize.Height() > nMaxHeight )
+ nMaxHeight = aItemSize.Height();
+
+ if ( pItem->mnNonStdSize )
+ {
+ if ( mbHorz )
+ pItem->mnNonStdSize += SMALLBUTTON_HSIZE;
+ else
+ pItem->mnNonStdSize += SMALLBUTTON_VSIZE;
+ }
+
+ // Gegebenenfalls die Fensterhoehe mit beruecksichtigen
+ if ( pItem->mpWindow )
+ {
+ nHeight = pItem->mpWindow->GetSizePixel().Height();
+ if ( nHeight > mnWinHeight )
+ mnWinHeight = nHeight;
+ }
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+ else
+ {
+ nMaxWidth = nDefWidth;
+ nMaxHeight = nDefHeight;
+ }
+
+ mbCalc = FALSE;
+ mbFormat = TRUE;
+
+ // Button-Umrandung dazurechnen
+ if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ {
+ nMaxWidth += OUTBUTTON_SIZE;
+ nMaxHeight += OUTBUTTON_SIZE;
+ }
+ else
+ {
+ nMaxWidth += SMALLBUTTON_HSIZE;
+ nMaxHeight += SMALLBUTTON_VSIZE;
+ }
+
+ // Muessen die groessen neu berechnet werden
+ if ( (nMaxWidth != mnItemWidth) || (nMaxHeight != mnItemHeight) )
+ {
+ // Neue Werte zuweisen
+ mnItemWidth = nMaxWidth;
+ mnItemHeight = nMaxHeight;
+
+ // Button-Device freigeben
+ if ( mpBtnDev )
+ {
+ ImplFreeButtonDevice( mpBtnDev );
+ mpBtnDev = NULL;
+ }
+ if ( !(mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ mpBtnDev = ImplGetButtonDevice( this, mnItemWidth, mnItemHeight, mnOutStyle );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, BOOL bCalcHorz )
+{
+ ImplToolItem* pItem;
+ ULONG nLineStart = 0;
+ ULONG nGroupStart = 0;
+ long nLineWidth = 0;
+ long nCurWidth;
+ long nLastGroupLineWidth = 0;
+ long nMaxLineWidth = 0;
+ USHORT nLines = 1;
+ BOOL bWindow;
+ BOOL bBreak = FALSE;
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ pItem->mbBreak = bBreak;
+ bBreak = FALSE;
+
+ if ( pItem->mbVisible )
+ {
+ bWindow = FALSE;
+ bBreak = FALSE;
+ nCurWidth = 0;
+
+ if ( pItem->meType == TOOLBOXITEM_BUTTON )
+ {
+ if ( pItem->mnNonStdSize )
+ nCurWidth = pItem->mnNonStdSize;
+ else
+ {
+ if ( bCalcHorz )
+ nCurWidth = mnItemWidth;
+ else
+ nCurWidth = mnItemHeight;
+ }
+
+ if ( pItem->mpWindow && bCalcHorz )
+ {
+ long nWinItemWidth = pItem->mpWindow->GetSizePixel().Width();
+ if ( !mbScroll || (nWinItemWidth <= nWidth) )
+ {
+ nCurWidth = nWinItemWidth;
+ bWindow = TRUE;
+ }
+ else
+ {
+ if ( pItem->mbEmptyBtn )
+ {
+ nCurWidth = 0;
+ }
+ }
+ }
+
+ if ( (nLineWidth+nCurWidth > nWidth) && mbScroll )
+ bBreak = TRUE;
+ }
+ else if ( pItem->meType == TOOLBOXITEM_SPACE )
+ nCurWidth = mnItemWidth;
+ else if ( pItem->meType == TOOLBOXITEM_SEPARATOR )
+ nCurWidth = pItem->mnSepSize;
+ else if ( pItem->meType == TOOLBOXITEM_BREAK )
+ bBreak = TRUE;
+
+ if ( bBreak )
+ {
+ nLines++;
+
+ // Gruppe auseinanderbrechen oder ganze Gruppe umbrechen?
+ if ( (pItem->meType == TOOLBOXITEM_BREAK) ||
+ (nLineStart == nGroupStart) )
+ {
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ nLineWidth = 0;
+ nLineStart = mpItemList->GetCurPos();
+ nGroupStart = nLineStart;
+ pItem->mbBreak = TRUE;
+ bBreak = FALSE;
+ }
+ else
+ {
+ if ( nLastGroupLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLastGroupLineWidth;
+
+ // Wenn ganze Gruppe umgebrochen wird, diese auf
+ // Zeilenanfang setzen und wieder neu berechnen
+ nLineWidth = 0;
+ nLineStart = nGroupStart;
+ pItem = mpItemList->Seek( nGroupStart );
+ continue;
+ }
+ }
+ else
+ {
+ if ( (pItem->meType != TOOLBOXITEM_BUTTON) || bWindow )
+ {
+ nLastGroupLineWidth = nLineWidth;
+ nGroupStart = mpItemList->GetCurPos();
+ if ( !bWindow )
+ nGroupStart++;
+ }
+ }
+
+ nLineWidth += nCurWidth;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( pMaxLineWidth )
+ {
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+ // Wegen Separatoren kann MaxLineWidth > Width werden, hat aber
+ // auf die Umbrueche keine Auswirkung
+ if ( nMaxLineWidth > nWidth )
+ nMaxLineWidth = nWidth;
+ *pMaxLineWidth = nMaxLineWidth;
+ }
+
+ return nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplFormat( BOOL bResize )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ // Muss ueberhaupt neu formatiert werden
+ if ( !mbFormat )
+ return;
+
+ // Positionen/Groessen berechnen
+ Rectangle aEmptyRect;
+ ImplToolItem* pItem;
+ ImplToolItem* pTempItem;
+ long nLineSize;
+ long nLeft;
+ long nTop;
+ long nMax;
+ long nX;
+ long nY;
+ long nCurWidth;
+ long nCurHeight;
+ USHORT nFormatLine;
+ BOOL bMustFullPaint;
+ BOOL bLastSep;
+
+ // FloatSizeAry gegebenenfalls loeschen
+ if ( mpFloatSizeAry )
+ {
+ delete mpFloatSizeAry;
+ mpFloatSizeAry = NULL;
+ }
+
+ // Borderbreite berechnen
+ if ( IsFloatingMode() || !(mnWinStyle & WB_BORDER) )
+ {
+ mnLeftBorder = 0;
+ mnTopBorder = 0;
+ mnRightBorder = 0;
+ mnBottomBorder = 0;
+ }
+ else
+ ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+
+ // Itemgroesse gegebenenfalls neu berechnet werden
+ if ( ImplCalcItem() )
+ bMustFullPaint = TRUE;
+ else
+ bMustFullPaint = FALSE;
+
+ // Im FloatingMode die Fenstergroesse immer neu setzen oder im Resize
+ // die neue Anzahl der FloatingLines berechnen
+ if ( IsFloatingMode() )
+ {
+ if ( bResize )
+ mnFloatLines = ImplCalcLines( this, mnDY );
+ else
+ SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
+ }
+
+ // Horizontal
+ if ( mbHorz )
+ {
+ nLineSize = mnItemHeight;
+
+ if ( mnWinHeight-2 > mnItemHeight )
+ nLineSize = mnWinHeight-2;
+
+ if ( mbScroll )
+ {
+ mnVisLines = ImplCalcLines( this, mnDY );
+ nMax = mnDX;
+ }
+ else
+ {
+ mnVisLines = mnLines;
+ nMax = TB_MAXNOSCROLL;
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ nLeft = TB_BORDER_OFFSET1 + mnLeftBorder;
+ nTop = TB_BORDER_OFFSET2 + mnTopBorder;
+ nMax -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
+ }
+ else
+ {
+ nLeft = 0;
+ nTop = 0;
+ }
+
+ nLeft += mnBorderX;
+ nTop += mnBorderY;
+ nMax -= mnBorderX*2;
+ }
+ else
+ {
+ nLineSize = mnItemWidth;
+
+ if ( mbScroll )
+ {
+ mnVisLines = ImplCalcLines( this, mnDX );
+ nMax = mnDY;
+ }
+ else
+ {
+ mnVisLines = mnLines;
+ nMax = TB_MAXNOSCROLL;
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ nTop = TB_BORDER_OFFSET1 + mnTopBorder;
+ nLeft = TB_BORDER_OFFSET2 + mnLeftBorder;
+ nMax -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
+ }
+ else
+ {
+ nLeft = 0;
+ nTop = 0;
+ }
+
+ nLeft += mnBorderX;
+ nTop += mnBorderY;
+ nMax -= mnBorderY*2;
+ }
+
+ // Wenn Fenster keine Groesse hat, dann nichts berechnen. Fuer alle
+ // ToolBoxen ohne Scroll muss hier schon die Groesse berechnet werden.
+ if ( (nMax <= 0) && mbScroll )
+ {
+ mnVisLines = 1;
+ mnCurLine = 1;
+ mnCurLines = 1;
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ pItem->maRect = aEmptyRect;
+ pItem = mpItemList->Next();
+ }
+
+ maLowerRect = aEmptyRect;
+ maUpperRect = aEmptyRect;
+ maNextToolRect = aEmptyRect;
+ }
+ else
+ {
+ // Anfangswerte setzen
+ nX = nLeft;
+ nY = nTop;
+ nFormatLine = 1;
+ bLastSep = TRUE;
+
+ // Scroll-Rectangles merken und zuruecksetzen
+ Rectangle aOldLowerRect = maLowerRect;
+ Rectangle aOldUpperRect = maUpperRect;
+ Rectangle aOldNextToolRect = maNextToolRect;
+ maUpperRect = aEmptyRect;
+ maLowerRect = aEmptyRect;
+ maNextToolRect = aEmptyRect;
+
+ if ( maNextToolBoxStr.Len() && mbScroll )
+ {
+ nMax -= TB_SPIN_SIZE-TB_SPIN_OFFSET;
+ if ( mbHorz )
+ {
+ maNextToolRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
+ maNextToolRect.Right() = maNextToolRect.Left()+TB_SPIN_SIZE-1;
+ maNextToolRect.Top() = nTop;
+ maNextToolRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ }
+ else
+ {
+ maNextToolRect.Top() = nTop+nMax+TB_SPIN_OFFSET;;
+ maNextToolRect.Bottom() = maNextToolRect.Top()+TB_SPIN_SIZE-1;
+ maNextToolRect.Left() = nLeft;
+ maNextToolRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ }
+ }
+
+ // Haben wir ueberhaupt Items
+ if ( mpItemList->GetObject( 0 ) )
+ {
+ // Umbrueche und sichtbare Zeilen berechnen
+ mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
+ if ( (mnCurLines > mnVisLines) && mbScroll )
+ {
+ nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
+ mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
+ // Wenn wir umbrechen muessen, dann Scroll-Rectangles neu setzen
+ if ( mbHorz )
+ {
+ maUpperRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
+ maUpperRect.Right() = maUpperRect.Left()+TB_SPIN_SIZE-1;
+ maUpperRect.Top() = nTop;
+ maLowerRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
+ maLowerRect.Left() = maUpperRect.Left();
+ maLowerRect.Right() = maUpperRect.Right();
+ maUpperRect.Bottom() = maUpperRect.Top() +
+ (maLowerRect.Bottom()-maUpperRect.Top())/2;
+ maLowerRect.Top() = maUpperRect.Bottom();
+ }
+ else
+ {
+ maUpperRect.Top() = nTop+nMax+TB_SPIN_OFFSET;;
+ maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
+ maUpperRect.Left() = nLeft;
+ maLowerRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
+ maLowerRect.Top() = maUpperRect.Top();
+ maLowerRect.Bottom() = maUpperRect.Bottom();
+ maUpperRect.Right() = maUpperRect.Left() +
+ (maLowerRect.Right()-maUpperRect.Left())/2;
+ maLowerRect.Left() = maUpperRect.Right();
+ }
+ }
+ if ( mnVisLines >= mnCurLines )
+ mnCurLine = 1;
+ else if ( mnCurLine+mnVisLines-1 > mnCurLines )
+ mnCurLine = mnCurLines - (mnVisLines-1);
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Doppelte Separatoren hiden
+ if ( mbCustomize )
+ {
+ if ( pItem->meType == TOOLBOXITEM_SEPARATOR )
+ {
+ pItem->mbVisible = FALSE;
+ if ( !bLastSep )
+ {
+ // Feststellen ob dahinter ueberhaupt noch
+ // ein Item sichtbar ist
+ ULONG nTempPos = mpItemList->GetCurPos()+1;
+ ULONG nCount = mpItemList->Count();
+ while ( nTempPos < nCount )
+ {
+ pTempItem = mpItemList->GetObject( nTempPos );
+ if ( (pTempItem->meType == TOOLBOXITEM_SEPARATOR) ||
+ ((pTempItem->meType == TOOLBOXITEM_BUTTON) &&
+ pTempItem->mbVisible) )
+ {
+ pItem->mbVisible = TRUE;
+ break;
+ }
+ nTempPos++;
+ }
+ }
+ bLastSep = TRUE;
+ }
+ else if ( pItem->mbVisible )
+ bLastSep = FALSE;
+ }
+
+ pItem->mbShowWindow = FALSE;
+
+ if ( pItem->mbBreak )
+ {
+ nFormatLine++;
+
+ // Ab der zweiten Zeile erhoehen
+ if ( nFormatLine > mnCurLine )
+ {
+ if ( mbHorz )
+ {
+ nX = nLeft;
+ if ( mnWinStyle & WB_LINESPACING )
+ nY += nLineSize+TB_LINESPACING;
+ else
+ nY += nLineSize;
+ }
+ else
+ {
+ nY = nTop;
+ if ( mnWinStyle & WB_LINESPACING )
+ nX += nLineSize+TB_LINESPACING;
+ else
+ nX += nLineSize;
+ }
+ }
+ }
+
+ if ( !pItem->mbVisible || (nFormatLine < mnCurLine) ||
+ (nFormatLine > mnCurLine+mnVisLines-1) )
+ pItem->maCalcRect = aEmptyRect;
+ else
+ {
+ if ( (pItem->meType == TOOLBOXITEM_BUTTON) ||
+ (pItem->meType == TOOLBOXITEM_SPACE) )
+ {
+ if ( pItem->mnNonStdSize )
+ {
+ if ( mbHorz )
+ {
+ nCurWidth = pItem->mnNonStdSize;
+ nCurHeight = mnItemHeight;
+ }
+ else
+ {
+ nCurWidth = mnItemWidth;
+ nCurHeight = pItem->mnNonStdSize;
+ }
+ }
+ else
+ {
+ nCurWidth = mnItemWidth;
+ nCurHeight = mnItemHeight;
+ }
+
+ if ( pItem->mpWindow && mbHorz )
+ {
+ Size aWinSize = pItem->mpWindow->GetSizePixel();
+ if ( !mbScroll || (aWinSize.Width() <= nMax) )
+ {
+ nCurWidth = aWinSize.Width();
+ nCurHeight = aWinSize.Height();
+ pItem->mbShowWindow = TRUE;
+ }
+ else
+ {
+ if ( pItem->mbEmptyBtn )
+ {
+ nCurWidth = 0;
+ nCurHeight = 0;
+ }
+ }
+ }
+ }
+ else if ( pItem->meType == TOOLBOXITEM_SEPARATOR )
+ {
+ if ( mbHorz )
+ {
+ nCurWidth = pItem->mnSepSize;
+ nCurHeight = mnItemHeight;
+ }
+ else
+ {
+ nCurWidth = mnItemWidth;
+ nCurHeight = pItem->mnSepSize;
+ }
+ }
+ else if ( pItem->meType == TOOLBOXITEM_BREAK )
+ {
+ nCurWidth = 0;
+ nCurHeight = 0;
+ }
+
+ if ( mbHorz )
+ {
+ pItem->maCalcRect.Left() = nX;
+ pItem->maCalcRect.Top() = nY+(nLineSize-nCurHeight)/2;
+ pItem->maCalcRect.Right() = nX+nCurWidth-1;
+ pItem->maCalcRect.Bottom() = pItem->maCalcRect.Top()+nCurHeight-1;
+ nX += nCurWidth;
+ }
+ else
+ {
+ pItem->maCalcRect.Left() = nX+(nLineSize-nCurWidth)/2;;
+ pItem->maCalcRect.Top() = nY;
+ pItem->maCalcRect.Right() = pItem->maCalcRect.Left()+nCurWidth-1;
+ pItem->maCalcRect.Bottom() = nY+nCurHeight-1;
+ nY += nCurHeight;
+ }
+ }
+
+ if ( pItem->mpWindow )
+ {
+ if ( pItem->mbShowWindow )
+ {
+ Point aPos( pItem->maCalcRect.Left(), pItem->maCalcRect.Top() );
+ pItem->mpWindow->SetPosPixel( aPos );
+ if ( !mbCustomizeMode )
+ pItem->mpWindow->Show();
+ }
+ else
+ pItem->mpWindow->Hide();
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+ else
+ mnCurLines = 1;
+
+ // Wenn ToolBox sichtbar, Paint fuer geaenderte Bereiche ausloesen
+ if ( IsVisible() && !mbFullPaint )
+ {
+ if ( bMustFullPaint )
+ {
+ maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder, mnDY-mnBottomBorder );
+ }
+ else
+ {
+ if ( aOldLowerRect != maLowerRect )
+ {
+ maPaintRect.Union( maLowerRect );
+ maPaintRect.Union( aOldLowerRect );
+ }
+ if ( aOldUpperRect != maUpperRect )
+ {
+ maPaintRect.Union( maUpperRect );
+ maPaintRect.Union( aOldUpperRect );
+ }
+ if ( aOldNextToolRect != maNextToolRect )
+ {
+ maPaintRect.Union( maNextToolRect );
+ maPaintRect.Union( aOldNextToolRect );
+ }
+
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->maRect != pItem->maCalcRect )
+ {
+ maPaintRect.Union( pItem->maRect );
+ maPaintRect.Union( pItem->maCalcRect );
+ }
+ pItem = mpItemList->Next();
+ }
+ }
+
+ Invalidate( maPaintRect );
+ }
+
+ // Neu berechnete Rectangles uebertragen
+ maPaintRect = aEmptyRect;
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ pItem->maRect = pItem->maCalcRect;
+ pItem = mpItemList->Next();
+ }
+ }
+
+ // Es wurde die Leiste neu durchformatiert
+ maTimer.Stop();
+ mbFormat = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ToolBox, ImplUpdateHdl, void*, EMPTYARG )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbFormat )
+ ImplFormat();
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawToolArrow( ToolBox* pBox, long nX, long nY, BOOL bBlack,
+ BOOL bLeft = FALSE, BOOL bTop = FALSE )
+{
+ Color aOldFillColor = pBox->GetFillColor();
+ WindowAlign eAlign = pBox->meAlign;
+ if ( bLeft )
+ eAlign = WINDOWALIGN_RIGHT;
+ else if ( bTop )
+ eAlign = WINDOWALIGN_BOTTOM;
+
+ switch ( eAlign )
+ {
+ case WINDOWALIGN_LEFT:
+ if ( bBlack )
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ pBox->DrawRect( Rectangle( nX+0, nY+0, nX+0, nY+6 ) );
+ pBox->DrawRect( Rectangle( nX+1, nY+1, nX+1, nY+5 ) );
+ pBox->DrawRect( Rectangle( nX+2, nY+2, nX+2, nY+4 ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ pBox->DrawRect( Rectangle( nX+1, nY+2, nX+1, nY+4 ) );
+ pBox->DrawRect( Rectangle( nX+2, nY+3, nX+2, nY+3 ) );
+ }
+ break;
+ case WINDOWALIGN_TOP:
+ if ( bBlack )
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ pBox->DrawRect( Rectangle( nX+0, nY+0, nX+6, nY+0 ) );
+ pBox->DrawRect( Rectangle( nX+1, nY+1, nX+5, nY+1 ) );
+ pBox->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+3, nX+3, nY+3 ) );
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ pBox->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+2, nX+3, nY+2 ) );
+ }
+ break;
+ case WINDOWALIGN_RIGHT:
+ if ( bBlack )
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+0, nX+3, nY+6 ) );
+ pBox->DrawRect( Rectangle( nX+2, nY+1, nX+2, nY+5 ) );
+ pBox->DrawRect( Rectangle( nX+1, nY+2, nX+1, nY+4 ) );
+ pBox->DrawRect( Rectangle( nX+0, nY+3, nX+0, nY+3 ) );
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ pBox->DrawRect( Rectangle( nX+2, nY+2, nX+2, nY+4 ) );
+ pBox->DrawRect( Rectangle( nX+1, nY+3, nX+1, nY+3 ) );
+ }
+ break;
+ case WINDOWALIGN_BOTTOM:
+ if ( bBlack )
+ pBox->SetFillColor( Color( COL_BLACK ) );
+ pBox->DrawRect( Rectangle( nX+0, nY+3, nX+6, nY+3 ) );
+ pBox->DrawRect( Rectangle( nX+1, nY+2, nX+5, nY+2 ) );
+ pBox->DrawRect( Rectangle( nX+2, nY+1, nX+4, nY+1 ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+0, nX+3, nY+0 ) );
+ if ( bBlack )
+ {
+ pBox->SetFillColor( aOldFillColor );
+ pBox->DrawRect( Rectangle( nX+2, nY+2, nX+4, nY+2 ) );
+ pBox->DrawRect( Rectangle( nX+3, nY+1, nX+3, nY+1 ) );
+ }
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawSpin( BOOL bUpperIn, BOOL bLowerIn )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bTmpUpper;
+ BOOL bTmpLower;
+
+ if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
+ return;
+
+ if ( mnCurLine > 1 )
+ bTmpUpper = TRUE;
+ else
+ bTmpUpper = FALSE;
+
+ if ( mnCurLine+mnVisLines-1 < mnCurLines )
+ bTmpLower = TRUE;
+ else
+ bTmpLower = FALSE;
+
+ if ( !IsEnabled() )
+ {
+ bTmpUpper = FALSE;
+ bTmpLower = FALSE;
+ }
+
+ ImplDrawSpinButton( this, maUpperRect, maLowerRect,
+ bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawNext( BOOL bIn )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( maNextToolRect.IsEmpty() )
+ return;
+
+ DecorationView aDecoView( this );
+
+ // Button malen
+ long nX = SMALLBUTTON_OFF_NORMAL_X;
+ long nY = SMALLBUTTON_OFF_NORMAL_Y;
+ USHORT nStyle = 0;
+ if ( bIn == 1 )
+ {
+ nStyle |= BUTTON_DRAW_PRESSED;
+ nX = SMALLBUTTON_OFF_PRESSED_X;
+ nY = SMALLBUTTON_OFF_PRESSED_Y;
+ }
+ aDecoView.DrawButton( maNextToolRect, nStyle );
+
+ // Inhalt ausgeben
+ BOOL bLeft = FALSE;
+ BOOL bTop = FALSE;
+ if ( mbHorz )
+ {
+ bLeft = TRUE;
+ nX++;
+ nY += (maNextToolRect.GetHeight()-12)/2;
+ }
+ else
+ {
+ bTop = TRUE;
+ nY++;
+ nX += (maNextToolRect.GetWidth()-12)/2;
+ }
+
+ nX += maNextToolRect.Left();
+ nY += maNextToolRect.Top();
+ SetLineColor();
+ SetFillColor( COL_LIGHTBLUE );
+ ImplDrawToolArrow( this, nX, nY, TRUE, bLeft, bTop );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplDrawItem( USHORT nPos, BOOL bHighlight, BOOL bPaint )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+
+ // Falls Rechteck ausserhalb des sichbaren Bereichs liegt
+ if ( pItem->maRect.IsEmpty() )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ // Im flachen Style werden auch Separatoren gezeichnet
+ if ( (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
+ (pItem->meType == TOOLBOXITEM_SEPARATOR) )
+ {
+ // Strich wird nicht gemalt, wenn vor oder hinter Fenstern
+ // oder bei einem Umbruch
+ ImplToolItem* pTempItem = mpItemList->GetObject( nPos );
+ pTempItem = mpItemList->GetObject( nPos-1 );
+ if ( pTempItem && !pTempItem->mbShowWindow )
+ {
+ pTempItem = mpItemList->GetObject( nPos+1 );
+ if ( pTempItem && !pTempItem->mbShowWindow && !pTempItem->mbBreak )
+ {
+ long nCenterPos;
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( IsHorizontal() )
+ {
+ nCenterPos = pItem->maRect.Center().X()-1;
+ DrawLine( Point( nCenterPos, pItem->maRect.Top() ),
+ Point( nCenterPos, pItem->maRect.Bottom() ) );
+ nCenterPos++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( nCenterPos, pItem->maRect.Top() ),
+ Point( nCenterPos, pItem->maRect.Bottom() ) );
+ }
+ else
+ {
+ nCenterPos = pItem->maRect.Center().Y()-1;
+ DrawLine( Point( pItem->maRect.Left(), nCenterPos ),
+ Point( pItem->maRect.Right(), nCenterPos ) );
+ nCenterPos++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( pItem->maRect.Left(), nCenterPos ),
+ Point( pItem->maRect.Right(), nCenterPos ) );
+ }
+ }
+ }
+ }
+
+ // Ist es kein Button oder wird er als Fenster dargestellt,
+ // dann mache nichts
+ if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
+ (pItem->mbShowWindow && !mbCustomizeMode) )
+ return;
+
+ // Wenn wir das Configurations-Item zeichen, brauchen wir dazu ein
+ // TBDragMananger
+ ImplTBDragMgr* pMgr;
+ if ( pItem->mnId == mnConfigItem )
+ {
+ pMgr = ImplGetTBDragMgr();
+ pMgr->HideDragRect();
+ }
+ else
+ pMgr = NULL;
+
+ // Im Konfigurationsmodus werden sichtbare Fenster durch eine andere
+ // Darstellung ersetzt
+ if ( mbCustomizeMode && pItem->mbShowWindow )
+ {
+ Font aOldFont = GetFont();
+ Color aOldTextColor = GetTextColor();
+
+ SetFont( rStyleSettings.GetAppFont() );
+ SetLineColor( Color( COL_BLACK ) );
+ SetFillColor( rStyleSettings.GetFieldColor() );
+ SetTextColor( rStyleSettings.GetFieldTextColor() );
+ DrawRect( pItem->maRect );
+
+ Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
+ Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
+ aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
+ BOOL bClip;
+ if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
+ (aSize.Height() > pItem->maRect.GetHeight()-2) )
+ {
+ bClip = TRUE;
+ Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
+ pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
+ Region aTempRegion( aTempRect );
+ SetClipRegion( aTempRegion );
+ }
+ else
+ bClip = FALSE;
+ DrawCtrlText( aPos, pItem->maText );
+ if ( bClip )
+ SetClipRegion();
+ SetFont( aOldFont );
+ SetTextColor( aOldTextColor );
+
+ // Gegebenenfalls noch Config-Frame zeichnen
+ if ( pMgr )
+ pMgr->UpdateDragRect();
+ return;
+ }
+
+ // Button malen
+ Point aBtnPos;
+ Size aBtnSize = pItem->maRect.GetSize();
+ long nOffX = SMALLBUTTON_OFF_NORMAL_X;
+ long nOffY = SMALLBUTTON_OFF_NORMAL_Y;
+ long nTempOffX;
+ long nTempOffY;
+ USHORT nStyle = 0;
+ if ( pItem->meState == STATE_CHECK )
+ {
+ aBtnPos.Y() = aBtnSize.Height() * 2;
+ nStyle |= BUTTON_DRAW_CHECKED;
+ nOffX = SMALLBUTTON_OFF_CHECKED_X;
+ nOffY = SMALLBUTTON_OFF_CHECKED_Y;
+ }
+ else if ( pItem->meState == STATE_DONTKNOW )
+ {
+ aBtnPos.Y() = aBtnSize.Height() * 4;
+ nStyle |= BUTTON_DRAW_DONTKNOW;
+ }
+ if ( bHighlight == 1 )
+ {
+ aBtnPos.Y() += aBtnSize.Height();
+ nStyle |= BUTTON_DRAW_PRESSED;
+ nOffX = SMALLBUTTON_OFF_PRESSED_X;
+ nOffY = SMALLBUTTON_OFF_PRESSED_Y;
+ }
+
+ if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ {
+ nOffX = OUTBUTTON_OFF_NORMAL_X;
+ nOffY = OUTBUTTON_OFF_NORMAL_Y;
+ if ( bHighlight )
+ {
+ nOffX++;
+ nOffY++;
+ }
+ }
+
+ if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
+ {
+ if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
+ {
+ if ( pItem->meState != STATE_NOCHECK )
+ {
+ SetLineColor();
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ DrawRect( pItem->maRect );
+ }
+ else
+ Erase( pItem->maRect );
+ }
+ }
+ else
+ {
+ if ( !pItem->mnNonStdSize )
+ DrawOutDev( pItem->maRect.TopLeft(), aBtnSize, aBtnPos, aBtnSize, *mpBtnDev );
+ else
+ {
+ if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
+ ImplDrawOutButton( this, pItem->maRect, nStyle );
+ else
+ {
+ DecorationView aDecoView( this );
+ aDecoView.DrawButton( pItem->maRect, nStyle );
+ }
+ }
+ }
+
+ nOffX += pItem->maRect.Left();
+ nOffY += pItem->maRect.Top();
+
+ // Feststellen, was gemalt werden soll
+ BOOL bImage;
+ BOOL bText;
+ if ( meButtonType == BUTTON_SYMBOL )
+ {
+ if ( pItem->mnNonStdSize )
+ {
+ bImage = FALSE;
+ bText = TRUE;
+ }
+ else
+ {
+ bImage = TRUE;
+ bText = FALSE;
+ }
+ }
+ else if ( meButtonType == BUTTON_TEXT )
+ {
+ if ( pItem->mnNonStdSize )
+ {
+ bImage = TRUE;
+ bText = FALSE;
+ }
+ else
+ {
+ bImage = FALSE;
+ bText = TRUE;
+ }
+ }
+ else
+ {
+ bImage = TRUE;
+ bText = TRUE;
+ }
+
+ // Werte fuer die Ausgabe bestimmen
+ long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
+ long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
+ Size aImageSize;
+ Size aTxtSize;
+
+ if ( bText )
+ {
+ aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
+ aTxtSize.Height() = GetTextHeight();
+ }
+
+ if ( bImage )
+ {
+ const Image* pImage;
+ if ( bHighlight && (!(pItem->maHighImage)) == FALSE )
+ pImage = &(pItem->maHighImage);
+ else
+ pImage = &(pItem->maImage);
+
+ aImageSize = pImage->GetSizePixel();
+
+ // Ausgabeflags bestimmen
+ USHORT nImageStyle = 0;
+
+ if ( !pItem->mbEnabled || !IsEnabled() )
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+
+ if ( pItem->meState == STATE_DONTKNOW )
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+
+ // Image ausgeben
+ nTempOffX = nOffX;
+ nTempOffY = nOffY;
+ if ( pItem->mnBits & TIB_LEFT )
+ nTempOffY += (nBtnHeight-aImageSize.Height())/2;
+ else
+ {
+ nTempOffX += (nBtnWidth-aImageSize.Width())/2;
+ if ( bText )
+ nTempOffY += (nBtnHeight-aTxtSize.Height()-aImageSize.Height())/2;
+ else
+ nTempOffY += (nBtnHeight-aImageSize.Height())/2;
+ }
+ DrawImage( Point( nTempOffX, nTempOffY ), *pImage, nImageStyle );
+ }
+
+ // Text ausgeben
+ if ( bText )
+ {
+ nTempOffX = nOffX;
+ nTempOffY = nOffY;
+
+ // Muss Text gegebenenfalls gedreht werden
+ Font aOldFont = GetFont();
+ BOOL bRotate = FALSE;
+ if ( pItem->mnNonStdSize && !bImage && !IsFloatingMode() &&
+ ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
+ {
+ bRotate = TRUE;
+
+ Font aRotateFont = aOldFont;
+ if ( meAlign == WINDOWALIGN_LEFT )
+ {
+ aRotateFont.SetOrientation( 900 );
+ nTempOffX += (nBtnWidth-aTxtSize.Height())/2;
+ nTempOffY += aTxtSize.Width();
+ nTempOffY += (nBtnHeight-aTxtSize.Width())/2;
+ }
+ else
+ {
+ aRotateFont.SetOrientation( 2700 );
+ nTempOffX += aTxtSize.Height();
+ nTempOffX += (nBtnWidth-aTxtSize.Height())/2;
+ nTempOffY += (nBtnHeight-aTxtSize.Width())/2;
+ }
+
+ SetFont( aRotateFont );
+ }
+ else
+ {
+ if ( pItem->mnBits & TIB_LEFT )
+ {
+ nTempOffX += aImageSize.Width();
+ nTempOffY += (nBtnHeight-aTxtSize.Height())/2;
+ }
+ else
+ {
+ nTempOffX += (nBtnWidth-aTxtSize.Width())/2;
+ if ( bImage )
+ nTempOffY += nBtnHeight-aTxtSize.Height();
+ else
+ nTempOffY += (nBtnHeight-aTxtSize.Height())/2;
+ }
+ }
+
+ USHORT nTextStyle = 0;
+ if ( !pItem->mbEnabled )
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ DrawCtrlText( Point( nTempOffX, nTempOffY ), pItem->maText,
+ 0, STRING_LEN, nTextStyle );
+
+ if ( bRotate )
+ SetFont( aOldFont );
+ }
+
+ // Evt. noch Pfeil rechts/oben in der Ecke zeichnen
+ if ( pItem->mnBits & TIB_DROPDOWN )
+ {
+ Point aArrowPos( nOffX, nOffY );
+ aArrowPos.X() += nBtnWidth-6;
+
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ Rectangle aClearRect( aArrowPos.X()-1, aArrowPos.Y(),
+ aArrowPos.X()+3, aArrowPos.Y()+4 );
+ SetLineColor();
+
+ if ( (meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT) )
+ {
+ aArrowPos.X() += 2;
+ aClearRect.Left() += 2;
+ aClearRect.Right() += 2;
+ aClearRect.Bottom() += 2;
+ }
+ else
+ aClearRect.Right() += 2;
+
+ Erase( aClearRect );
+ BOOL bBlack = FALSE;
+
+ if ( !pItem->mbEnabled || !IsEnabled() )
+ SetFillColor( rStyleSettings.GetShadowColor() );
+ else
+ {
+ SetFillColor( COL_LIGHTGREEN );
+ bBlack = TRUE;
+ }
+ ImplDrawToolArrow( this, aArrowPos.X(), aArrowPos.Y(), bBlack );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ }
+
+ if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
+ {
+ if ( bHighlight || (pItem->meState == STATE_CHECK) )
+ {
+ Point aPos( pItem->maRect.TopLeft() );
+ Size aSize( pItem->maRect.GetSize() );
+
+ if ( bHighlight == 2 )
+ SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( aPos, Point( aPos.X()+aSize.Width()-1, aPos.Y() ) );
+ DrawLine( aPos, Point( aPos.X(), aPos.Y()+aSize.Height()-1 ) );
+ if ( bHighlight == 2 )
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( aPos.X()+aSize.Width()-1, aPos.Y() ),
+ Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1 ) );
+ DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-1 ),
+ Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1 ) );
+ }
+ }
+
+ // Gegebenenfalls noch Config-Frame zeichnen
+ if ( pMgr )
+ pMgr->UpdateDragRect();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplStartCustomizeMode()
+{
+ mbCustomizeMode = TRUE;
+
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbShowWindow )
+ {
+ pItem->mpWindow->Hide();
+
+ if ( !(pItem->maRect.IsEmpty()) )
+ Invalidate( pItem->maRect );
+ }
+
+ pItem = mpItemList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplEndCustomizeMode()
+{
+ mbCustomizeMode = FALSE;
+
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbShowWindow )
+ {
+ if ( !(pItem->maRect.IsEmpty()) )
+ Invalidate( pItem->maRect );
+
+ pItem->mpWindow->Show();
+ }
+
+ pItem = mpItemList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplFloatControl( BOOL bStart, FloatingWindow* pFloatWindow )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( bStart )
+ {
+ mpFloatWin = pFloatWindow;
+
+ // Wenn Button nicht gedrueckt dargestellt wird, dann den
+ // Button neu malen
+ if ( mnCurItemId != mnDownItemId )
+ ImplDrawItem( mnCurPos, TRUE );
+ mbDrag = FALSE;
+ EndTracking();
+ ReleaseMouse();
+ }
+ else
+ {
+ mpFloatWin = NULL;
+
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( mnCurPos );
+ Deactivate();
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ShowLine( BOOL bNext )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mbFormat = TRUE;
+ if ( bNext )
+ mnCurLine++;
+ else
+ mnCurLine--;
+ ImplFormat();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, BOOL bRepeat )
+{
+ Point aMousePos = rMEvt.GetPosPixel();
+
+ // Ist ToolBox aktiv
+ if ( mbDrag )
+ {
+ // Befindet sich Maus ueber dem Item
+ ImplToolItem* pItem = mpItemList->GetObject( mnCurPos );
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ if ( !mnCurItemId )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ mnCurItemId = pItem->mnId;
+ Highlight();
+ }
+
+ if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
+ Select();
+ }
+ else
+ {
+ if ( mnCurItemId )
+ {
+ ImplDrawItem( mnCurPos );
+ mnCurItemId = 0;
+ ImplDrawItem( mnCurPos );
+ Highlight();
+ }
+ }
+
+ return TRUE;
+ }
+
+ if ( mbUpper )
+ {
+ BOOL bNewIn = maUpperRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawSpin( mbIn, FALSE );
+ }
+ return TRUE;
+ }
+
+ if ( mbLower )
+ {
+ BOOL bNewIn = maLowerRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawSpin( FALSE, mbIn );
+ }
+ return TRUE;
+ }
+
+ if ( mbNextTool )
+ {
+ BOOL bNewIn = maNextToolRect.IsInside( aMousePos );
+ if ( bNewIn != mbIn )
+ {
+ mbIn = bNewIn;
+ ImplDrawNext( mbIn );
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, BOOL bCancel )
+{
+ if ( mbDrag || mbSelection )
+ {
+ // Hier die MouseDaten setzen, wenn Selection-Modus, da dann kein
+ // MouseButtonDown-Handler gerufen wird
+ if ( mbSelection )
+ {
+ mnMouseClicks = rMEvt.GetClicks();
+ mnMouseModifier = rMEvt.GetModifier();
+ }
+
+ Deactivate();
+
+ if ( mbDrag )
+ mbDrag = FALSE;
+ else
+ {
+ mbSelection = FALSE;
+ if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
+ return TRUE;
+ }
+
+ // Wurde Maus ueber dem Item losgelassen
+ ImplToolItem* pItem = mpItemList->GetObject( mnCurPos );
+ if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
+ {
+ mnCurItemId = pItem->mnId;
+ if ( !bCancel )
+ {
+ // Gegebenenfalls ein AutoCheck durchfuehren
+ if ( pItem->mnBits & TIB_AUTOCHECK )
+ {
+ if ( pItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pItem->meState != STATE_CHECK )
+ SetItemState( pItem->mnId, STATE_CHECK );
+ }
+ else
+ {
+ if ( pItem->meState != STATE_CHECK )
+ pItem->meState = STATE_CHECK;
+ else
+ pItem->meState = STATE_NOCHECK;
+ }
+ }
+
+ // Select nicht bei Repeat ausloesen, da dies schon im
+ // MouseButtonDown ausgeloest wurde
+ if ( !(pItem->mnBits & TIB_REPEAT) )
+ {
+ // Gegen zerstoeren im Select-Handler sichern
+ ImplDelData aDelData;
+ ImplAddDel( &aDelData );
+ Select();
+ if ( aDelData.IsDelete() )
+ return TRUE;
+ ImplRemoveDel( &aDelData );
+ }
+ }
+
+ {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ // Items nicht geloescht, im Select-Handler
+ if ( mnCurItemId )
+ {
+ BOOL bHighlight;
+ if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ bHighlight = 2;
+ else
+ bHighlight = FALSE;
+ ImplDrawItem( mnCurPos, bHighlight );
+ }
+ }
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ return TRUE;
+ }
+ else if ( mbUpper || mbLower )
+ {
+ if ( mbIn )
+ ShowLine( !mbUpper );
+ mbUpper = FALSE;
+ mbLower = FALSE;
+ mbIn = FALSE;
+ ImplDrawSpin( FALSE, FALSE );
+ return TRUE;
+ }
+ else if ( mbNextTool )
+ {
+ mbNextTool = FALSE;
+ mbIn = FALSE;
+ ImplDrawNext( FALSE );
+ NextToolBox();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( ImplHandleMouseMove( rMEvt ) )
+ return;
+
+ Point aMousePos = rMEvt.GetPosPixel();
+
+ if ( mbSelection )
+ {
+ USHORT i = 0;
+ USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
+
+ // Item suchen, das geklickt wurde
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Wenn Mausposition in diesem Item vorhanden, kann die
+ // Suche abgebrochen werden
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ // Wenn es ein Button ist, dann wird er selektiert
+ if ( pItem->meType == TOOLBOXITEM_BUTTON )
+ {
+ // Wenn er disablet ist, findet keine Aenderung
+ // statt
+ if ( !pItem->mbEnabled || pItem->mbShowWindow )
+ nNewPos = mnCurPos;
+ else
+ nNewPos = i;
+ }
+
+ break;
+ }
+
+ i++;
+ pItem = mpItemList->Next();
+ }
+
+ // Wurde ein neuer Eintrag selektiert
+ if ( nNewPos != mnCurPos )
+ {
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( mnCurPos );
+
+ mnCurPos = nNewPos;
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ mnCurItemId = pItem->mnId;
+ ImplDrawItem( mnCurPos, TRUE );
+ }
+ else
+ mnCurItemId = 0;
+
+ Highlight();
+ }
+ return;
+ }
+
+ if ( mbDragging )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->Dragging( aMousePos );
+ return;
+ }
+
+ PointerStyle eStyle = POINTER_ARROW;
+ if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
+ {
+ if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
+ {
+ USHORT nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
+ if ( nLinePtr & DOCK_LINEHSIZE )
+ {
+ if ( meAlign == WINDOWALIGN_LEFT )
+ eStyle = POINTER_WINDOW_ESIZE;
+ else
+ eStyle = POINTER_WINDOW_WSIZE;
+ }
+ else if ( nLinePtr & DOCK_LINEVSIZE )
+ {
+ if ( meAlign == WINDOWALIGN_TOP )
+ eStyle = POINTER_WINDOW_SSIZE;
+ else
+ eStyle = POINTER_WINDOW_NSIZE;
+ }
+ }
+ }
+
+ if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
+ {
+ // Item suchen, das geklickt wurde
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Wenn es ein Customize-Window ist, gegebenenfalls den
+ // Resize-Pointer anzeigen
+ if ( pItem->mbShowWindow )
+ {
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ if ( pItem->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
+ eStyle = POINTER_HSIZEBAR;
+ break;
+ }
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+
+ if ( ((eStyle == POINTER_ARROW) && (mnOutStyle & TOOLBOX_STYLE_HANDPOINTER)) ||
+ (mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ {
+ BOOL bClearHigh = TRUE;
+ if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ if ( (pItem->meType == TOOLBOXITEM_BUTTON) && pItem->mbEnabled )
+ {
+ if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
+ {
+ bClearHigh = FALSE;
+ if ( mnHighItemId != pItem->mnId )
+ {
+ USHORT nTempPos = (USHORT)mpItemList->GetCurPos();
+ if ( mnHighItemId )
+ ImplDrawItem( GetItemPos( mnHighItemId ) );
+ mnHighItemId = pItem->mnId;
+ ImplDrawItem( nTempPos, 2 );
+ }
+ }
+ if ( mnOutStyle & TOOLBOX_STYLE_HANDPOINTER )
+ eStyle = POINTER_REFHAND;
+ }
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+
+ if ( bClearHigh && mnHighItemId )
+ {
+ USHORT nClearPos = GetItemPos( mnHighItemId );
+ if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? TRUE : FALSE );
+ mnHighItemId = 0;
+ }
+ }
+
+ if ( meLastStyle != eStyle )
+ {
+ meLastStyle = eStyle;
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+ }
+
+ DockingWindow::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // Nur bei linker Maustaste ToolBox ausloesen und wenn wir uns nicht
+ // noch in der normalen Bearbeitung befinden
+ if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ // Activate schon hier rufen, da gegebenenfalls noch Items
+ // ausgetauscht werden
+ Activate();
+
+ // ToolBox hier updaten, damit der Anwender weiss, was Sache ist
+ if ( mbFormat )
+ {
+ ImplFormat();
+ Update();
+ }
+
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT i = 0;
+ USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
+
+ // Item suchen, das geklickt wurde
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Ist es dieses Item
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ // Ist es ein Separator oder ist das Item disabled,
+ // dann mache nichts
+ if ( (pItem->meType == TOOLBOXITEM_BUTTON) &&
+ (!pItem->mbShowWindow || mbCustomizeMode) )
+ nNewPos = i;
+
+ break;
+ }
+
+ i++;
+ pItem = mpItemList->Next();
+ }
+
+ // Item gefunden
+ if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ if ( mbCustomize )
+ {
+ if ( rMEvt.IsMod2() || mbCustomizeMode )
+ {
+ Deactivate();
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ Rectangle aItemRect = GetItemRect( pItem->mnId );
+ mnConfigItem = pItem->mnId;
+
+ BOOL bResizeItem;
+ if ( mbCustomizeMode && pItem->mbShowWindow &&
+ (pItem->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
+ bResizeItem = TRUE;
+ else
+ bResizeItem = FALSE;
+ pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
+ return;
+ }
+ }
+
+ if ( !pItem->mbEnabled )
+ {
+ Sound::Beep( SOUND_DISABLE, this );
+ Deactivate();
+ return;
+ }
+
+ // Aktuelle Daten setzen
+ USHORT nTrackFlags = 0;
+ mnCurPos = i;
+ mnCurItemId = pItem->mnId;
+ mnDownItemId = mnCurItemId;
+ mnMouseClicks = rMEvt.GetClicks();
+ mnMouseModifier = rMEvt.GetModifier();
+ if ( pItem->mnBits & TIB_REPEAT )
+ nTrackFlags |= STARTTRACK_BUTTONREPEAT;
+
+ if ( mbSelection )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ Highlight();
+ }
+ else
+ {
+ // Hier schon bDrag setzen, da in EndSelection ausgewertet wird
+ mbDrag = TRUE;
+
+ // Bei Doppelklick nur den Handler rufen, aber bevor der
+ // Button gehiltet wird, da evt. in diesem Handler der
+ // Drag-Vorgang abgebrochen wird
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+
+ if ( mbDrag )
+ {
+ ImplDrawItem( mnCurPos, TRUE );
+ Highlight();
+ }
+
+ // Click-Handler aufrufen
+ if ( rMEvt.GetClicks() != 2 )
+ Click();
+
+ // Bei Repeat auch den Select-Handler rufen
+ if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
+ Select();
+
+ // Wenn die Aktion nicht im Click-Handler abgebrochen wurde
+ if ( mbDrag )
+ StartTracking( nTrackFlags );
+ }
+
+ // Wenn Maus ueber einem Item gedrueckt wurde, koennen wir
+ // die Bearbeitung abbrechen
+ return;
+ }
+
+ Deactivate();
+
+ // Gegebenenfalls noch Scroll- und Next-Buttons ueberpruefen
+ if ( maUpperRect.IsInside( aMousePos ) )
+ {
+ if ( mnCurLine > 1 )
+ {
+ StartTracking();
+ mbUpper = TRUE;
+ mbIn = TRUE;
+ ImplDrawSpin( TRUE, FALSE );
+ }
+ return;
+ }
+ if ( maLowerRect.IsInside( aMousePos ) )
+ {
+ if ( mnCurLine+mnVisLines-1 < mnCurLines )
+ {
+ StartTracking();
+ mbLower = TRUE;
+ mbIn = TRUE;
+ ImplDrawSpin( FALSE, TRUE );
+ }
+ return;
+ }
+ if ( maNextToolRect.IsInside( aMousePos ) )
+ {
+ StartTracking();
+ mbNextTool = TRUE;
+ mbIn = TRUE;
+ ImplDrawNext( TRUE );
+ return;
+ }
+
+ // Linesizing testen
+ if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
+ {
+ USHORT nLineMode = ImplTestLineSize( this, aMousePos );
+ if ( nLineMode )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+
+ // Handler rufen, damit die Dock-Rectangles gesetzt werden
+ // koenen
+ StartDocking();
+
+ Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() );
+ Size aSize = GetSizePixel();
+ aPos = ScreenToOutputPixel( aPos );
+
+ // Dragging starten
+ pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
+ nLineMode, FALSE );
+ return;
+ }
+ }
+
+ // Kein Item, dann nur Click oder DoubleClick
+ if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+ else
+ Click();
+ }
+
+ if ( !mbDrag && !mbSelection )
+ DockingWindow::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if ( ImplHandleMouseButtonUp( rMEvt ) )
+ return;
+
+ if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
+ {
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->EndDragging();
+ return;
+ }
+ mbCommandDrag = FALSE;
+
+ DockingWindow::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
+ else
+ ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
+
+ DockingWindow::Tracking( rTEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Paint( const Rectangle& rPaintRect )
+{
+ if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
+ mbFullPaint = TRUE;
+ ImplFormat();
+ mbFullPaint = FALSE;
+
+ if ( (mnWinStyle & WB_BORDER) && !IsFloatingMode() )
+ ImplDrawBorder( this );
+
+ // SpinButtons zeichnen
+ if ( mnWinStyle & WB_SCROLL )
+ {
+ if ( mnCurLines > mnLines )
+ ImplDrawSpin( FALSE, FALSE );
+ }
+
+ // NextButton zeichnen
+ ImplDrawNext( FALSE );
+
+ // Buttons zeichnen
+ USHORT nHighPos;
+ if ( mnHighItemId )
+ nHighPos = GetItemPos( mnHighItemId );
+ else
+ nHighPos = TOOLBOX_ITEM_NOTFOUND;
+ USHORT nCount = (USHORT)mpItemList->Count();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( i );
+
+ // Nur malen, wenn Rechteck im PaintRectangle liegt
+ if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
+ {
+ BOOL bHighlight = FALSE;
+ if ( i == mnCurPos )
+ bHighlight = 1;
+ else if ( i == nHighPos )
+ bHighlight = 2;
+ ImplDrawItem( i, bHighlight );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Move()
+{
+ DockingWindow::Move();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Resize()
+{
+ long nOldDX = mnDX;
+ long nOldDY = mnDY;
+ Size aSize = GetOutputSizePixel();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+ mnLastResizeDY = 0;
+
+ // Evt. neu formatieren oder neu painten
+ if ( mbScroll )
+ {
+ if ( !mbFormat )
+ {
+ mbFormat = TRUE;
+ if ( IsReallyVisible() )
+ ImplFormat( TRUE );
+ }
+ }
+
+ // Border muss neu ausgegeben werden
+ if ( mnWinStyle & WB_BORDER )
+ {
+ // Da wir sonst beim Paint denken, das alles neu gepaintet wird
+ if ( mbFormat && IsReallyVisible() )
+ Invalidate();
+ else
+ {
+ if ( mnRightBorder )
+ {
+ if ( nOldDX > mnDX )
+ Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
+ else
+ Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
+ }
+
+ if ( mnBottomBorder )
+ {
+ if ( nOldDY > mnDY )
+ Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
+ else
+ Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ // Rechteck ermitteln
+ Rectangle aTempRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
+ aTempRect.Left() = aPt.X();
+ aTempRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aTempRect.BottomRight() );
+ aTempRect.Right() = aPt.X();
+ aTempRect.Bottom() = aPt.Y();
+
+ // Text ermitteln und anzeigen
+ XubString aStr = GetQuickHelpText( nItemId );
+ const XubString& rHelpStr = GetHelpText( nItemId );
+ if ( !aStr.Len() )
+ aStr = GetItemText( nItemId );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ if ( rHelpStr.Len() )
+ aStr = rHelpStr;
+ else
+ aStr.EraseAllChars( '~' );
+ Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aTempRect, aStr );
+ }
+ else
+ Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
+ return;
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ ULONG nHelpId = GetHelpId( nItemId );
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId );
+ return;
+ }
+ }
+ }
+ else if ( maNextToolRect.IsInside( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ) )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ // Rechteck ermitteln
+ Rectangle aTempRect = maNextToolRect;
+ Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
+ aTempRect.Left() = aPt.X();
+ aTempRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aTempRect.BottomRight() );
+ aTempRect.Right() = aPt.X();
+ aTempRect.Bottom() = aPt.Y();
+
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aTempRect.Center(), aTempRect, maNextToolBoxStr );
+ else
+ Help::ShowQuickHelp( this, aTempRect, maNextToolBoxStr );
+ return;
+ }
+ }
+
+ DockingWindow::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+long ToolBox::Notify( NotifyEvent& rNEvt )
+{
+ return DockingWindow::Notify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Command( const CommandEvent& rCEvt )
+{
+ // StartDrag auf MouseButton/Left/Alt abbilden
+ if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
+ mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
+ (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
+ {
+ // Wir erlauben nur das Draggen von Items. Deshalb muessen wir
+ // testen, ob auch ein Item angeklickt wurde, ansonsten wuerden
+ // wir evt. das Fenster verschieben, was nicht gewollt waere.
+ // Wir machen dieses jedoch nur im Customize-Mode, da ansonsten
+ // Items zuhaeufig ausversehen verschoben werden.
+ if ( mbCustomizeMode )
+ {
+ Point aMousePos = rCEvt.GetMousePosPixel();
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Ist es dieses Item
+ if ( pItem->maRect.IsInside( aMousePos ) )
+ {
+ // Ist es ein Separator oder ist das Item disabled,
+ // dann mache nichts
+ if ( (pItem->meType == TOOLBOXITEM_BUTTON) &&
+ !pItem->mbShowWindow )
+ mbCommandDrag = TRUE;
+ break;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( mbCommandDrag )
+ {
+ MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
+ MOUSE_LEFT, KEY_MOD2 );
+ ToolBox::MouseButtonDown( aMEvt );
+ return;
+ }
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
+ {
+ if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
+ ShowLine( FALSE );
+ else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
+ ShowLine( TRUE );
+ ImplDrawSpin( FALSE, FALSE );
+ return;
+ }
+ }
+ }
+
+ DockingWindow::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StateChanged( StateChangedType nType )
+{
+ DockingWindow::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+ else if ( nType == STATE_CHANGE_ENABLE )
+ ImplUpdateItem();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ DockingWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ if ( mpBtnDev )
+ ImplButtonSysChange( this, mpBtnDev, mnOutStyle );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::PrepareToggleFloatingMode()
+{
+ return DockingWindow::PrepareToggleFloatingMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ToggleFloatingMode()
+{
+ DockingWindow::ToggleFloatingMode();
+
+ if ( IsFloatingMode() )
+ {
+ mbHorz = TRUE;
+ mbScroll = TRUE;
+ SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
+ }
+ else
+ {
+ mbScroll = (mnWinStyle & WB_SCROLL) ? TRUE : FALSE;
+ if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
+ mbHorz = TRUE;
+ else
+ mbHorz = FALSE;
+ }
+
+ mbFormat = TRUE;
+ ImplFormat();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartDocking()
+{
+ meDockAlign = meAlign;
+ mnDockLines = mnLines;
+ mbLastFloatMode = IsFloatingMode();
+ DockingWindow::StartDocking();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::Docking( const Point& rPos, Rectangle& rRect )
+{
+ // Wenn Dragging, dann nicht machen, da vorher schon berechnet
+ if ( mbDragging )
+ return FALSE;
+
+ BOOL bFloatMode = FALSE;
+
+ DockingWindow::Docking( rPos, rRect );
+
+ // Befindet sich die Maus ausserhalb des Bereichs befindet, kann es nur ein
+ // FloatWindow werden
+ if ( maOutDockRect.IsInside( rPos ) && !IsDockingPrevented() )
+ {
+ Rectangle aInRect = maInDockRect;
+ Size aDockSize;
+ aDockSize.Width() = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
+ aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
+ aInRect.Left() += aDockSize.Width()/2;
+ aInRect.Top() += aDockSize.Height()/2;
+ aInRect.Right() -= aDockSize.Width()/2;
+ aInRect.Bottom() -= aDockSize.Height()/2;
+
+ // Auf den Dockbereich eine halbe Breite der ToolBox dazurechnen
+ if ( !IsFloatingMode() )
+ {
+ if ( meAlign == WINDOWALIGN_LEFT )
+ aInRect.Left() -= aDockSize.Width()/2;
+ else if ( meAlign == WINDOWALIGN_TOP )
+ aInRect.Top() -= aDockSize.Height()/2;
+ else if ( meAlign == WINDOWALIGN_RIGHT )
+ aInRect.Right() += aDockSize.Width()/2;
+ else
+ aInRect.Bottom() += aDockSize.Height()/2;
+ }
+
+ // Wenn Fenster zu klein, wird das gesammte InDock-Rect genommen
+ if ( aInRect.Left() >= aInRect.Right() )
+ {
+ aInRect.Left() = maInDockRect.Left();
+ aInRect.Right() = maInDockRect.Right();
+ }
+ if ( aInRect.Top() >= aInRect.Bottom() )
+ {
+ aInRect.Top() = maInDockRect.Top();
+ aInRect.Bottom() = maInDockRect.Bottom();
+ }
+
+ // Wenn Maus nicht im Dock-Bereich, dann kann es nur zum
+ // FloatWindow werden
+ if ( aInRect.IsInside( rPos ) )
+ bFloatMode = TRUE;
+ else
+ {
+ // Wird befinden uns im Dock-Bereich. Jetzt muessen wir
+ // feststellen, an welcher Kante angedockt werden soll
+ Point aInPos( rPos.X()-aInRect.Left(), rPos.Y()-aInRect.Top() );
+ Size aInSize = aInRect.GetSize();
+ Size aOutSize = maOutDockRect.GetSize();
+ USHORT nQuadrant = 0;
+
+ if ( aInPos.Y() > aInSize.Height()/2 )
+ nQuadrant += 2;
+ if ( aInPos.X() > aInSize.Width()/2 )
+ nQuadrant++;
+
+ if ( nQuadrant == 0 )
+ {
+ if ( aInPos.X() >= aInPos.Y() )
+ meDockAlign = WINDOWALIGN_TOP;
+ else
+ meDockAlign = WINDOWALIGN_LEFT;
+ }
+ else if ( nQuadrant == 1 )
+ {
+ if ( aInSize.Width()-aInPos.X() >= aInPos.Y() )
+ meDockAlign = WINDOWALIGN_TOP;
+ else
+ meDockAlign = WINDOWALIGN_RIGHT;
+ }
+ else if ( nQuadrant == 2 )
+ {
+ if ( aInPos.X() <= aInSize.Height()-aInPos.Y() )
+ meDockAlign = WINDOWALIGN_LEFT;
+ else
+ meDockAlign = WINDOWALIGN_BOTTOM;
+ }
+ else
+ {
+ if ( (rPos.X() >= aInRect.Right()) &&
+ (rPos.Y() >= aInRect.Bottom()) )
+ {
+ if ( aInSize.Height()-aInPos.Y() <
+ aInSize.Width()-aInPos.X() )
+ meDockAlign = WINDOWALIGN_RIGHT;
+ else
+ meDockAlign = WINDOWALIGN_BOTTOM;
+ }
+ else
+ {
+ if ( rPos.X() >= aInRect.Right() )
+ meDockAlign = WINDOWALIGN_RIGHT;
+ else
+ meDockAlign = WINDOWALIGN_BOTTOM;
+ }
+ }
+
+ // Wenn sich Dock-Align geaendert hat, muessen wir die
+ // neue Dock-Groesse setzen
+ if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
+ aDockSize.Width() = aOutSize.Width();
+ else
+ aDockSize.Height() = aOutSize.Height();
+ rRect.SetSize( aDockSize );
+ }
+ }
+ else
+ bFloatMode = TRUE;
+
+ if ( bFloatMode )
+ {
+ meDockAlign = meAlign;
+ if ( !mbLastFloatMode )
+ {
+ USHORT nTemp = 0;
+ rRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
+ }
+ }
+
+ // Ist Pointer nicht mehr im Rechteck
+ if ( !rRect.IsInside( rPos ) )
+ {
+ Point aMouseOff;
+ aMouseOff.X() = rRect.Left() - rPos.X();
+ aMouseOff.Y() = rRect.Top() - rPos.Y();
+
+ if ( (rPos.X() < rRect.Left()) || (rPos.X() > rRect.Right()) )
+ {
+ rRect.SetPos( rPos );
+ rRect.Move( -5, aMouseOff.Y() );
+ }
+ if ( (rPos.Y() < rRect.Top()) || (rPos.Y() > rRect.Bottom()) )
+ {
+ rRect.SetPos( rPos );
+ rRect.Move( aMouseOff.X(), -5 );
+ }
+ }
+
+ mbLastFloatMode = bFloatMode;
+
+ return bFloatMode;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
+{
+ if ( !IsDockingCanceled() )
+ {
+ if ( mnLines != mnDockLines )
+ SetLineCount( mnDockLines );
+ if ( meAlign != meDockAlign )
+ SetAlign( meDockAlign );
+ }
+
+ if ( bFloatMode || (bFloatMode != IsFloatingMode()) )
+ DockingWindow::EndDocking( rRect, bFloatMode );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Resizing( Size& rSize )
+{
+ USHORT nCalcLines;
+ USHORT nTemp;
+
+ // Alle Floatinggroessen berechnen
+ ImplCalcFloatSizes( this );
+
+ if ( !mnLastResizeDY )
+ mnLastResizeDY = mnDY;
+
+ // Ist vertikales Resizing angesagt
+ if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
+ {
+ nCalcLines = ImplCalcLines( this, rSize.Height() );
+ if ( nCalcLines < 1 )
+ nCalcLines = 1;
+ rSize = ImplCalcFloatSize( this, nCalcLines );
+ }
+ else
+ {
+ nCalcLines = 1;
+ nTemp = nCalcLines;
+ Size aTempSize = ImplCalcFloatSize( this, nTemp );
+ while ( (aTempSize.Width() > rSize.Width()) &&
+ (nCalcLines <= mpFloatSizeAry[0].mnLines) )
+ {
+ nCalcLines++;
+ nTemp = nCalcLines;
+ aTempSize = ImplCalcFloatSize( this, nTemp );
+ }
+ rSize = aTempSize;
+ }
+
+ mnLastResizeDY = rSize.Height();
+}
+
+// -----------------------------------------------------------------------
+
+Size ToolBox::CalcWindowSizePixel( USHORT nCalcLines ) const
+{
+ return ImplCalcSize( this, nCalcLines );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EnableCustomize( BOOL bEnable )
+{
+ if ( bEnable != mbCustomize )
+ {
+ mbCustomize = bEnable;
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ if ( bEnable )
+ pMgr->Insert( this );
+ else
+ pMgr->Remove( this );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartCustomize( const Rectangle& rRect, void* pData )
+{
+ DBG_ASSERT( mbCustomize,
+ "ToolBox::StartCustomize(): ToolBox must be customized" );
+
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ Point aMousePos = GetPointerPosPixel();
+ Point aPos = ScreenToOutputPixel( rRect.TopLeft() );
+ Rectangle aRect( aPos.X(), aPos.Y(),
+ aPos.X()+rRect.GetWidth()+SMALLBUTTON_HSIZE,
+ aPos.Y()+rRect.GetHeight()+SMALLBUTTON_VSIZE );
+ aMousePos = ScreenToOutputPixel( aPos );
+ Pointer aPtr;
+ SetPointer( aPtr );
+ pMgr->StartDragging( this, aMousePos, aRect, 0, FALSE, pData );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->StartCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ pMgr->EndCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsCustomizeMode()
+{
+ ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
+ return pMgr->IsCustomizeMode();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::GetAccessObject( AccessObjectRef& rAcc ) const
+{
+ rAcc = new AccessObject( (void*) this, ACCESS_TYPE_TOOLBOX );
+}
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
new file mode 100644
index 000000000000..c55da3f278ad
--- /dev/null
+++ b/vcl/source/window/toolbox2.cxx
@@ -0,0 +1,1401 @@
+/*************************************************************************
+ *
+ * $RCSfile: toolbox2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_TOOLBOX_CXX
+
+#ifndef _LIST_HXX
+#include <tools/list.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#define private public
+#ifndef _SV_TOOLBOX_HXX
+#include <toolbox.hxx>
+#endif
+#undef private
+#ifndef _SV_TOOLBOX_H
+#include <toolbox.h>
+#endif
+
+// =======================================================================
+
+#define TB_SEP_SIZE 8
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem()
+{
+ mnId = 0;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = 0;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = TRUE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnNonStdSize = 0;
+ mnSepSize = TB_SEP_SIZE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const Image& rImage,
+ ToolBoxItemBits nItemBits ) :
+ maImage( rImage )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnNonStdSize = 0;
+ mnSepSize = TB_SEP_SIZE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const XubString& rText,
+ ToolBoxItemBits nItemBits ) :
+ maText( rText )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnNonStdSize = 0;
+ mnSepSize = TB_SEP_SIZE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::ImplToolItem( USHORT nItemId, const Image& rImage,
+ const XubString& rText, ToolBoxItemBits nItemBits ) :
+ maImage( rImage ),
+ maText( rText )
+{
+ mnId = nItemId;
+ mpWindow = NULL;
+ mpUserData = NULL;
+ mnHelpId = 0;
+ meType = TOOLBOXITEM_BUTTON;
+ mnBits = nItemBits;
+ meState = STATE_NOCHECK;
+ mbEnabled = TRUE;
+ mbVisible = TRUE;
+ mbEmptyBtn = FALSE;
+ mbShowWindow = FALSE;
+ mbBreak = FALSE;
+ mnNonStdSize = 0;
+ mnSepSize = TB_SEP_SIZE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplToolItem::~ImplToolItem()
+{
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::ImplConvertMenuString( const XubString& rStr )
+{
+ if ( mbMenuStrings )
+ {
+ maCvtStr = rStr;
+ maCvtStr.EraseTrailingChars( '.' );
+ maCvtStr.EraseAllChars( '~' );
+ return maCvtStr;
+ }
+ else
+ return rStr;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplInvalidate( BOOL bNewCalc, BOOL bFullPaint )
+{
+ if ( bNewCalc )
+ mbCalc = TRUE;
+
+ if ( bFullPaint )
+ {
+ mbFormat = TRUE;
+
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
+ maTimer.Stop();
+ }
+ }
+ else
+ {
+ if ( !mbFormat )
+ {
+ mbFormat = TRUE;
+
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ maTimer.Start();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ImplUpdateItem( USHORT nIndex )
+{
+ // Muss ueberhaupt eine neue Ausgabe erfolgen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( nIndex == 0xFFFF )
+ {
+ // Nur direkt neu ausgeben, wenn nicht neu formatiert
+ // werden muss
+ if ( !mbFormat )
+ {
+ USHORT nItemCount = (USHORT)mpItemList->Count();
+ for ( USHORT i = 0; i < nItemCount; i++ )
+ ImplDrawItem( i, (i == mnCurPos) ? TRUE : FALSE );
+ }
+ else
+ {
+ Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
+ mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
+ }
+ }
+ else
+ {
+ // Nur direkt neu ausgeben, wenn nicht neu formatiert
+ // werden muss
+ if ( !mbFormat )
+ ImplDrawItem( nIndex, (nIndex == mnCurPos) ? TRUE : FALSE );
+ else
+ maPaintRect.Union( mpItemList->GetObject( nIndex )->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Click()
+{
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Activate()
+{
+ maActivateHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Deactivate()
+{
+ maDeactivateHdl.Call( this );
+
+ if ( mbHideStatusText )
+ {
+ GetpApp()->HideHelpStatusText();
+ mbHideStatusText = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Highlight()
+{
+ maHighlightHdl.Call( this );
+
+ XubString aStr = GetHelpText( mnCurItemId );
+ if ( aStr.Len() || mbHideStatusText )
+ {
+ GetpApp()->ShowHelpStatusText( aStr );
+ mbHideStatusText = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::NextToolBox()
+{
+ maNextToolBoxHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Customize( const ToolBoxCustomizeEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::UserDraw( const UserDrawEvent& rUDEvt )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( const ResId& rResId, USHORT nPos )
+{
+ USHORT nObjMask;
+ BOOL bImage = FALSE; // Wurde Image gesetzt
+
+ // Item anlegen
+ ImplToolItem* pItem = new ImplToolItem;
+
+ GetRes( rResId.SetRT( RSC_TOOLBOXITEM ) );
+ nObjMask = ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_ID )
+ pItem->mnId = ReadShortRes();
+ else
+ pItem->mnId = 1;
+
+ if ( nObjMask & RSC_TOOLBOXITEM_TYPE )
+ pItem->meType = (ToolBoxItemType)ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_STATUS )
+ pItem->mnBits = (ToolBoxItemBits)ReadShortRes();
+
+ if( nObjMask & RSC_TOOLBOXITEM_HELPID )
+ pItem->mnHelpId = ReadLongRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_TEXT )
+ {
+ pItem->maText = ReadStringRes();
+ pItem->maText = ImplConvertMenuString( pItem->maText );
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_HELPTEXT )
+ pItem->maHelpText = ReadStringRes();
+
+/*
+#ifndef WIN
+ static
+#endif
+ short nHelpMode = -1;
+ if( nHelpMode == -1 ) {
+ SvHelpSettings aHelpSettings;
+
+ GetpApp()->Property( aHelpSettings );
+ nHelpMode = aHelpSettings.nHelpMode;
+ }
+
+ if( (nHelpMode & HELPTEXTMODE_EXTERN) && pItem->aHelpText.Len() )
+ pItem->aHelpText.Erase();
+ if( (nHelpMode & HELPTEXTMODE_DEBUG) && !pItem->nHelpId )
+ pItem->aHelpText = "??? !pItem->nHelpId MP/W.P. ???";
+*/
+
+ if ( nObjMask & RSC_TOOLBOXITEM_BITMAP )
+ {
+ Bitmap aBmp = Bitmap( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ pItem->maImage = Image( aBmp, IMAGE_STDBTN_COLOR );
+ bImage = TRUE;
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_IMAGE )
+ {
+ pItem->maImage = Image( ResId( (RSHEADER_TYPE*)GetClassRes() ) );
+ IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
+ bImage = TRUE;
+ }
+ if ( nObjMask & RSC_TOOLBOXITEM_DISABLE )
+ pItem->mbEnabled = !(BOOL)ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_STATE )
+ pItem->meState = (TriState)ReadShortRes();
+
+ if ( nObjMask & RSC_TOOLBOXITEM_HIDE )
+ pItem->mbVisible = !((BOOL)ReadShortRes());
+
+ if ( nObjMask & RSC_TOOLBOXITEM_COMMAND )
+ pItem->maCommandStr = ReadStringRes();
+
+ // Wenn kein Image geladen wurde, versuchen wir das Image aus der
+ // Image-Liste zu holen
+ if ( !bImage && pItem->mnId )
+ pItem->maImage = maImageList.GetImage( pItem->mnId );
+
+ // Wenn es sich um ein ButtonItem handelt, die ID ueberpruefen
+ BOOL bNewCalc;
+ if ( pItem->meType != TOOLBOXITEM_BUTTON )
+ {
+ bNewCalc = FALSE;
+ pItem->mnId = 0;
+ }
+ else
+ {
+ bNewCalc = TRUE;
+
+ DBG_ASSERT( pItem->mnId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( pItem->mnId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+ }
+
+ // Item anlegen und in die Liste einfuegen
+ mpItemList->Insert( pItem, nPos );
+
+ // ToolBox neu brechnen und neu ausgeben
+ ImplInvalidate( bNewCalc );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const Image& rImage,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpItemList->Insert( new ImplToolItem( nItemId, rImage, nBits ), nPos );
+
+ ImplInvalidate( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const Image& rImage,
+ const XubString& rText,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpItemList->Insert( new ImplToolItem( nItemId, rImage, ImplConvertMenuString( rText ), nBits ), nPos );
+
+ ImplInvalidate( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertItem( USHORT nItemId, const XubString& rText,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ mpItemList->Insert( new ImplToolItem( nItemId, ImplConvertMenuString( rText ), nBits ), nPos );
+
+ ImplInvalidate( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertWindow( USHORT nItemId, Window* pWindow,
+ ToolBoxItemBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nItemId, "ToolBox::InsertWindow(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::InsertWindow(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem* pItem = new ImplToolItem;
+ pItem->mnId = nItemId;
+ pItem->meType = TOOLBOXITEM_BUTTON;
+ pItem->mnBits = nBits;
+ pItem->mpWindow = pWindow;
+ mpItemList->Insert( pItem, nPos );
+
+ if ( pWindow )
+ pWindow->Hide();
+
+ ImplInvalidate( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertSpace( USHORT nPos )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem* pItem = new ImplToolItem;
+ pItem->meType = TOOLBOXITEM_SPACE;
+ pItem->mbEnabled = FALSE;
+ mpItemList->Insert( pItem, nPos );
+
+ ImplInvalidate( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertSeparator( USHORT nPos, USHORT nPixSize )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem* pItem = new ImplToolItem;
+ pItem->meType = TOOLBOXITEM_SEPARATOR;
+ pItem->mbEnabled = FALSE;
+ if ( nPixSize )
+ pItem->mnSepSize = nPixSize;
+ mpItemList->Insert( pItem, nPos );
+
+ ImplInvalidate( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::InsertBreak( USHORT nPos )
+{
+ // Item anlegen und in die Liste einfuegen
+ ImplToolItem* pItem = new ImplToolItem;
+ pItem->meType = TOOLBOXITEM_BREAK;
+ pItem->mbEnabled = FALSE;
+ mpItemList->Insert( pItem, nPos );
+
+ ImplInvalidate( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RemoveItem( USHORT nPos )
+{
+ ImplToolItem* pItem = mpItemList->Remove( nPos );
+
+ // Item entfernen
+ if ( pItem )
+ {
+ BOOL bMustCalc;
+ if ( pItem->meType == TOOLBOXITEM_BUTTON )
+ bMustCalc = TRUE;
+ else
+ bMustCalc = FALSE;
+
+ if ( pItem->mpWindow )
+ pItem->mpWindow->Hide();
+
+ // PaintRect um das removete Item erweitern
+ maPaintRect.Union( pItem->maRect );
+
+ // Absichern gegen das Loeschen im Select-Handler
+ if ( pItem->mnId == mnCurItemId )
+ mnCurItemId = 0;
+ if ( pItem->mnId == mnHighItemId )
+ mnHighItemId = 0;
+
+ ImplInvalidate( bMustCalc );
+
+ delete pItem;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::MoveItem( USHORT nItemId, USHORT nNewPos )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos < nNewPos )
+ nNewPos--;
+
+ if ( nPos == nNewPos )
+ return;
+
+ // Existiert Item
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ // ToolBox-Item in der Liste verschieben
+ ImplToolItem* pItem = mpItemList->Remove( nPos );
+ mpItemList->Insert( pItem, nNewPos );
+
+ // ToolBox neu ausgeben
+ ImplInvalidate( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::CopyItem( const ToolBox& rToolBox, USHORT nItemId,
+ USHORT nNewPos )
+{
+ DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
+ "ToolBox::CopyItem(): ItemId already exists" );
+
+ USHORT nPos = rToolBox.GetItemPos( nItemId );
+
+ // Existiert Item
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ // ToolBox-Item in der Liste verschieben
+ ImplToolItem* pItem = rToolBox.mpItemList->GetObject( nPos );
+ ImplToolItem* pNewItem = new ImplToolItem( *pItem );
+ mpItemList->Insert( pNewItem, nNewPos );
+ // Bestimme Daten zuruecksetzen
+ pNewItem->mpWindow = NULL;
+ pNewItem->mbShowWindow = FALSE;
+
+ // ToolBox neu ausgeben
+ ImplInvalidate( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::CopyItems( const ToolBox& rToolBox )
+{
+ ImplToolItem* pItem;
+
+ // Alle Items entfernen
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ // Absichern gegen das Loeschen im Select-Handler
+ mnCurItemId = 0;
+ mnHighItemId = 0;
+
+ // Items kopieren
+ ULONG i = 0;
+ pItem = rToolBox.mpItemList->GetObject( i );
+ while ( pItem )
+ {
+ ImplToolItem* pNewItem = new ImplToolItem( *pItem );
+ mpItemList->Insert( pNewItem, LIST_APPEND );
+ // Bestimme Daten zuruecksetzen
+ pNewItem->mpWindow = NULL;
+ pNewItem->mbShowWindow = FALSE;
+ i++;
+ pItem = rToolBox.mpItemList->GetObject( i );
+ }
+
+ ImplInvalidate( TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::Clear()
+{
+ ImplToolItem* pItem;
+
+ // Alle Item loeschen
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+
+ // Absichern gegen das Loeschen im Select-Handler
+ mnCurItemId = 0;
+ mnHighItemId = 0;
+
+ ImplInvalidate( TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetButtonType( ButtonType eNewType )
+{
+ if ( meButtonType != eNewType )
+ {
+ meButtonType = eNewType;
+
+ // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
+ // mit den per CopyBits kopierten Bereichen geben kann
+ ImplInvalidate( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetAlign( WindowAlign eNewAlign )
+{
+ if ( meAlign != eNewAlign )
+ {
+ meAlign = eNewAlign;
+
+ if ( !IsFloatingMode() )
+ {
+ // Setzen, ob Items horizontal oder vertikal angeordnet werden sollen
+ if ( (eNewAlign == WINDOWALIGN_LEFT) || (eNewAlign == WINDOWALIGN_RIGHT) )
+ mbHorz = FALSE;
+ else
+ mbHorz = TRUE;
+
+ // Hier alles neu ausgeben, da sich Border auch aendert
+ mbCalc = TRUE;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetLineCount( USHORT nNewLines )
+{
+ if ( !nNewLines )
+ nNewLines = 1;
+
+ if ( mnLines != nNewLines )
+ {
+ mnLines = nNewLines;
+
+ // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
+ // mit den per CopyBits kopierten Bereichen geben kann
+ ImplInvalidate( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetNextToolBox( const XubString& rStr )
+{
+ BOOL bCalcNew = (!maNextToolBoxStr.Len() != !rStr.Len());
+ maNextToolBoxStr = rStr;
+ if ( bCalcNew )
+ ImplInvalidate( TRUE, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+ToolBoxItemType ToolBox::GetItemType( USHORT nPos ) const
+{
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->meType;
+ else
+ return TOOLBOXITEM_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemPos( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (USHORT)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return TOOLBOX_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemId( USHORT nPos ) const
+{
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ToolBox::GetItemId( const Point& rPos ) const
+{
+ // Item suchen, das geklickt wurde
+ ImplToolItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Ist es dieses Item
+ if ( pItem->maRect.IsInside( rPos ) )
+ {
+ if ( pItem->meType == TOOLBOXITEM_BUTTON )
+ return pItem->mnId;
+ else
+ return 0;
+ }
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ToolBox::GetItemRect( USHORT nItemId ) const
+{
+ if ( mbCalc || mbFormat )
+ ((ToolBox*)this)->ImplFormat();
+
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemBits( USHORT nItemId, ToolBoxItemBits nBits )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ ToolBoxItemBits nOldBits = pItem->mnBits;
+ pItem->mnBits = nBits;
+ nBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
+ nOldBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
+ if ( nBits != nOldBits )
+ ImplInvalidate( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ToolBoxItemBits ToolBox::GetItemBits( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemData( USHORT nItemId, void* pNewData )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ pItem->mpUserData = pNewData;
+ ImplUpdateItem( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* ToolBox::GetItemData( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ // Nur wenn alles berechnet ist, mehr Aufwand treiben
+ if ( !mbCalc )
+ {
+ Size aOldSize = pItem->maImage.GetSizePixel();
+ pItem->maImage = rImage;
+ if ( aOldSize != pItem->maImage.GetSizePixel() )
+ ImplInvalidate( TRUE );
+ else
+ ImplUpdateItem( nPos );
+ }
+ else
+ pItem->maImage = rImage;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ToolBox::GetItemImage( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemHighImage( USHORT nItemId, const Image& rImage )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+ if ( pItem )
+ {
+ DBG_ASSERT( (pItem->maImage.GetSizePixel() == rImage.GetSizePixel()) ||
+ ((!rImage) == TRUE), "ToolBox::SetItemHighImage() - ImageSize != HighImageSize" );
+ pItem->maHighImage = rImage;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ToolBox::GetItemHighImage( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maHighImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ // Nur wenn alles berechnet ist, mehr Aufwand treiben
+ if ( !mbCalc &&
+ ((meButtonType != BUTTON_SYMBOL) || !pItem->maImage) )
+ {
+ long nOldWidth = GetCtrlTextWidth( pItem->maText );
+ pItem->maText = ImplConvertMenuString( rText );
+ if ( nOldWidth != GetCtrlTextWidth( pItem->maText ) )
+ ImplInvalidate( TRUE );
+ else
+ ImplUpdateItem( nPos );
+ }
+ else
+ pItem->maText = ImplConvertMenuString( rText );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetItemText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemWindow( USHORT nItemId, Window* pNewWindow )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ pItem->mpWindow = pNewWindow;
+ if ( pNewWindow )
+ pNewWindow->Hide();
+ ImplInvalidate( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Window* ToolBox::GetItemWindow( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mpWindow;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::StartSelection()
+{
+ if ( mbDrag )
+ EndSelection();
+
+ if ( !mbSelection )
+ {
+ mbSelection = TRUE;
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ Activate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EndSelection()
+{
+ mbCommandDrag = FALSE;
+
+ if ( mbDrag || mbSelection )
+ {
+ // Daten zuruecksetzen
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
+ ImplDrawItem( mnCurPos );
+ EndTracking();
+ ReleaseMouse();
+ Deactivate();
+ }
+
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemDown( USHORT nItemId, BOOL bDown, BOOL bRelease )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ if ( bDown )
+ {
+ if ( nPos != mnCurPos )
+ {
+ mnCurPos = nPos;
+ ImplDrawItem( mnCurPos );
+ }
+ }
+ else
+ {
+ if ( nPos == mnCurPos )
+ {
+ ImplDrawItem( mnCurPos );
+ mnCurPos = TOOLBOX_ITEM_NOTFOUND;
+ }
+ }
+
+ if ( bRelease )
+ {
+ if ( mbDrag || mbSelection )
+ {
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ EndTracking();
+ ReleaseMouse();
+ Deactivate();
+ }
+
+ mnCurItemId = 0;
+ mnDownItemId = 0;
+ mnMouseClicks = 0;
+ mnMouseModifier = 0;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemDown( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ return (nPos == mnCurPos);
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemState( USHORT nItemId, TriState eState )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+
+ // Hat sich der Status geaendert
+ if ( pItem->meState != eState )
+ {
+ // Wenn RadioCheck, dann vorherigen unchecken
+ if ( (eState == STATE_CHECK) && (pItem->mnBits & TIB_AUTOCHECK) &&
+ (pItem->mnBits & TIB_RADIOCHECK) )
+ {
+ ImplToolItem* pGroupItem;
+ USHORT nGroupPos;
+ USHORT nItemCount = GetItemCount();
+
+ nGroupPos = nPos;
+ while ( nGroupPos )
+ {
+ pGroupItem = mpItemList->GetObject( nGroupPos-1 );
+ if ( pGroupItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pGroupItem->meState != STATE_NOCHECK )
+ SetItemState( pGroupItem->mnId, STATE_NOCHECK );
+ }
+ else
+ break;
+ nGroupPos--;
+ }
+
+ nGroupPos = nPos+1;
+ while ( nGroupPos < nItemCount )
+ {
+ pGroupItem = mpItemList->GetObject( nGroupPos );
+ if ( pGroupItem->mnBits & TIB_RADIOCHECK )
+ {
+ if ( pGroupItem->meState != STATE_NOCHECK )
+ SetItemState( pGroupItem->mnId, STATE_NOCHECK );
+ }
+ else
+ break;
+ nGroupPos++;
+ }
+ }
+
+ pItem->meState = eState;
+ ImplUpdateItem( nPos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TriState ToolBox::GetItemState( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->meState;
+ else
+ return STATE_NOCHECK;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::EnableItem( USHORT nItemId, BOOL bEnable )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ if ( bEnable )
+ bEnable = TRUE;
+ if ( pItem->mbEnabled != bEnable )
+ {
+ pItem->mbEnabled = bEnable;
+
+ // Gegebenenfalls das Fenster mit updaten
+ if ( pItem->mpWindow )
+ pItem->mpWindow->Enable( pItem->mbEnabled );
+
+ // Item updaten
+ ImplUpdateItem( nPos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemEnabled( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mbEnabled;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::ShowItem( USHORT nItemId, BOOL bVisible )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != TOOLBOX_ITEM_NOTFOUND )
+ {
+ ImplToolItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mbVisible != bVisible )
+ {
+ pItem->mbVisible = bVisible;
+ ImplInvalidate( FALSE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ToolBox::IsItemVisible( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mbVisible;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetItemCommand( USHORT nItemId, const XubString& rCommand )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maCommandStr = rCommand;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetItemCommand( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maCommandStr;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetQuickHelpText( USHORT nItemId, const XubString& rText )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maQuickHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetQuickHelpText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->maQuickHelpText;
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetHelpText( USHORT nItemId, const XubString& rText )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& ToolBox::GetHelpText( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ {
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return ImplGetSVEmptyStr();
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ pItem->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ToolBox::GetHelpId( USHORT nItemId ) const
+{
+ ImplToolItem* pItem = ImplGetItem( nItemId );
+
+ if ( pItem )
+ return pItem->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetBorder( long nX, long nY )
+{
+ mnBorderX = nX;
+ mnBorderY = nY;
+
+ ImplInvalidate( TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::SetOutStyle( USHORT nNewStyle )
+{
+ if ( mnOutStyle != nNewStyle )
+ {
+ mnOutStyle = nNewStyle;
+
+ // Damit das ButtonDevice neu angelegt wird
+ if ( !(mnOutStyle & TOOLBOX_STYLE_FLAT) )
+ {
+ mnItemWidth = 1;
+ mnItemHeight = 1;
+ }
+
+ ImplInvalidate( TRUE, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolBox::RecalcItems()
+{
+ ImplInvalidate( TRUE );
+}
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
new file mode 100644
index 000000000000..af07c5df38c1
--- /dev/null
+++ b/vcl/source/window/window.cxx
@@ -0,0 +1,6539 @@
+/*************************************************************************
+ *
+ * $RCSfile: window.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WINDOW_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _SV_SALOBJ_HXX
+#include <salobj.hxx>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALGTYPE_HXX
+#include <salgtype.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_WINDATA_HXX
+#include <windata.hxx>
+#endif
+#ifndef _SV_DBGGUI_HXX
+#include <dbggui.hxx>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SYSWIN_HXX
+#include <syswin.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_HELPWIN_HXX
+#include <helpwin.hxx>
+#endif
+#ifndef _SV_MENU_HXX
+#include <menu.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+
+#define SYSDATA_ONLY_BASETYPE
+#include <sysdata.hxx>
+
+#include <com/sun/star/awt/XWindowPeer.hpp>
+
+#ifdef REMOTE_APPSERVER
+#include "rmwindow.hxx"
+#include "xevthdl.hxx"
+#include "rmevents.hxx"
+#include "rmoutdev.hxx"
+#endif
+
+#include <unowrap.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+DBG_NAME( Window );
+
+// =======================================================================
+
+#define IMPL_PAINT_PAINT ((USHORT)0x0001)
+#define IMPL_PAINT_PAINTALL ((USHORT)0x0002)
+#define IMPL_PAINT_PAINTALLCHILDS ((USHORT)0x0004)
+#define IMPL_PAINT_PAINTCHILDS ((USHORT)0x0008)
+#define IMPL_PAINT_ERASE ((USHORT)0x0010)
+
+// -----------------------------------------------------------------------
+
+typedef Window* PWINDOW;
+
+// -----------------------------------------------------------------------
+
+struct ImplCalcToTopData
+{
+ ImplCalcToTopData* mpNext;
+ Window* mpWindow;
+ Region* mpInvalidateRegion;
+};
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgCheckWindow( const void* pObj )
+{
+ DBG_TESTSOLARMUTEX();
+
+ const Window* pWindow = (Window*)pObj;
+
+ if ( (pWindow->GetType() < WINDOW_FIRST) || (pWindow->GetType() > WINDOW_LAST) )
+ return "Window data overwrite";
+
+ // Fenster-Verkettung ueberpruefen
+ Window* pChild = pWindow->mpFirstChild;
+ while ( pChild )
+ {
+ if ( pChild->mpParent != pWindow )
+ return "Child-Window-Parent wrong";
+ pChild = pChild->mpNext;
+ }
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+static void ImplInitAppFontData( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ long nTextHeight = pWindow->GetTextHeight();
+ long nTextWidth = pWindow->GetTextWidth( XubString( RTL_CONSTASCII_USTRINGPARAM( "aemnnxEM" ) ) );
+ long nSymHeight = nTextHeight*4;
+ // Falls Font zu schmal ist, machen wir die Basis breiter,
+ // damit die Dialoge symetrisch aussehen und nicht zu schmal
+ // werden. Wenn der Dialog die gleiche breite hat, geben wir
+ // noch etwas Spielraum dazu, da etwas mehr Platz besser ist.
+ if ( nSymHeight > nTextWidth )
+ nTextWidth = nSymHeight;
+ else if ( nSymHeight+5 > nTextWidth )
+ nTextWidth = nSymHeight+5;
+ pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
+ pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
+
+ pSVData->maGDIData.mnRealAppFontX = pSVData->maGDIData.mnAppFontX;
+ if ( pSVData->maAppData.mnDialogScaleX )
+ pSVData->maGDIData.mnAppFontX += (pSVData->maGDIData.mnAppFontX*pSVData->maAppData.mnDialogScaleX)/100;
+}
+
+// -----------------------------------------------------------------------
+
+MouseEvent ImplTranslateMouseEvent( const MouseEvent& rE, Window* pSource, Window* pDest )
+{
+ Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
+ aPos = pDest->ScreenToOutputPixel( aPos );
+ return MouseEvent( aPos, rE.GetClicks(), rE.GetMode(), rE.GetButtons(), rE.GetModifier() );
+}
+
+// =======================================================================
+
+void Window::ImplInitData( WindowType nType )
+{
+ meOutDevType = OUTDEV_WINDOW;
+
+ mpWinData = NULL; // Extra Window Data, that we dont need for all windows
+ mpOverlapData = NULL; // Overlap Data
+ mpFrameData = NULL; // Frame Data
+ mpFrame = NULL; // Pointer to frame window
+ mpSysObj = NULL;
+ mpFrameWindow = NULL; // window to top level parent (same as frame window)
+ mpOverlapWindow = NULL; // first overlap parent
+ mpBorderWindow = NULL; // Border-Window
+ mpClientWindow = NULL; // Client-Window of a FrameWindow
+ mpParent = NULL; // parent (inkl. BorderWindow)
+ mpRealParent = NULL; // real parent (exkl. BorderWindow)
+ mpFirstChild = NULL; // first child window
+ mpLastChild = NULL; // last child window
+ mpFirstOverlap = NULL; // first overlap window (only set in overlap windows)
+ mpLastOverlap = NULL; // last overlap window (only set in overlap windows)
+ mpPrev = NULL; // prev window
+ mpNext = NULL; // next window
+ mpNextOverlap = NULL; // next overlap window of frame
+ mpLastFocusWindow = NULL; // window for focus restore
+ mpDlgCtrlDownWindow = NULL; // window for dialog control
+ mpFirstDel = NULL; // Dtor notification list
+ mpUserData = NULL; // user data
+ mpCursor = NULL; // cursor
+ mpControlFont = NULL; // font propertie
+ mpVCLXWindow = NULL;
+ maControlForeground = Color( COL_TRANSPARENT ); // kein Foreground gesetzt
+ maControlBackground = Color( COL_TRANSPARENT ); // kein Background gesetzt
+ mnLeftBorder = 0; // left border
+ mnTopBorder = 0; // top border
+ mnRightBorder = 0; // right border
+ mnBottomBorder = 0; // bottom border
+ mnX = 0; // X-Position to Parent
+ mnY = 0; // Y-Position to Parent
+ mnHelpId = 0; // help id
+ mnUniqId = 0; // unique id
+ mpChildClipRegion = NULL; // Child-Clip-Region when ClipChildren
+ mpPaintRegion = NULL; // Paint-ClipRegion
+ mnStyle = 0; // style (init in ImplInitWindow)
+ mnPrevStyle = 0; // prevstyle (set in SetStyle)
+ mnExtendedStyle = 0; // extended style (init in ImplInitWindow)
+ mnPrevExtendedStyle = 0; // prevstyle (set in SetExtendedStyle)
+ mnType = nType; // type
+ mnGetFocusFlags = 0; // Flags fuer GetFocus()-Aufruf
+ mnWaitCount = 0; // Wait-Count (>1 == Warte-MousePointer)
+ mnPaintFlags = 0; // Flags for ImplCallPaint
+ mnParentClipMode = 0; // Flags for Parent-ClipChildren-Mode
+ mnActivateMode = 0; // Wird bei System/Overlap-Windows umgesetzt
+ mnDlgCtrlFlags = 0; // DialogControl-Flags
+ mbFrame = FALSE; // TRUE: Window is a frame window
+ mbBorderWin = FALSE; // TRUE: Window is a border window
+ mbOverlapWin = FALSE; // TRUE: Window is a overlap window
+ mbSysWin = FALSE; // TRUE: SystemWindow is the base class
+ mbDialog = FALSE; // TRUE: Dialog is the base class
+ mbDockWin = FALSE; // TRUE: DockingWindow is the base class
+ mbFloatWin = FALSE; // TRUE: FloatingWindow is the base class
+ mbPushButton = FALSE; // TRUE: PushButton is the base class
+ mbVisible = FALSE; // TRUE: Show( TRUE ) called
+ mbOverlapVisible = FALSE; // TRUE: Hide called for visible window from ImplHideAllOverlapWindow()
+ mbDisabled = FALSE; // TRUE: Enable( FALSE ) called
+ mbInputDisabled = FALSE; // TRUE: EnableInput( FALSE ) called
+ mbAlwaysEnableInput = FALSE; // TRUE: AlwaysEnableInput( TRUE ) called
+ mbDropDisabled = FALSE; // TRUE: Drop is enabled
+ mbNoUpdate = FALSE; // TRUE: SetUpdateMode( FALSE ) called
+ mbNoParentUpdate = FALSE; // TRUE: SetParentUpdateMode( FALSE ) called
+ mbActive = FALSE; // TRUE: Window Active
+ mbParentActive = FALSE; // TRUE: OverlapActive from Parent
+ mbReallyVisible = FALSE; // TRUE: this and all parents to an overlaped window are visible
+ mbReallyShown = FALSE; // TRUE: this and all parents to an overlaped window are shown
+ mbInInitShow = FALSE; // TRUE: we are in InitShow
+ mbChildNotify = FALSE; // TRUE: ChildNotify
+ mbChildPtrOverwrite = FALSE; // TRUE: PointerStyle overwrites Child-Pointer
+ mbNoPtrVisible = FALSE; // TRUE: ShowPointer( FALSE ) called
+ mbMouseMove = FALSE; // TRUE: BaseMouseMove called
+ mbPaintFrame = FALSE; // TRUE: Paint is visible, but not painted
+ mbInPaint = FALSE; // TRUE: Inside PaintHdl
+ mbMouseButtonDown = FALSE; // TRUE: BaseMouseButtonDown called
+ mbMouseButtonUp = FALSE; // TRUE: BaseMouseButtonUp called
+ mbKeyInput = FALSE; // TRUE: BaseKeyInput called
+ mbKeyUp = FALSE; // TRUE: BaseKeyUp called
+ mbCommand = FALSE; // TRUE: BaseCommand called
+ mbDefPos = TRUE; // TRUE: Position is not Set
+ mbDefSize = TRUE; // TRUE: Size is not Set
+ mbCallMove = TRUE; // TRUE: Move must be called by Show
+ mbCallResize = TRUE; // TRUE: Resize must be called by Show
+ mbWaitSystemResize = TRUE; // TRUE: Wait for System-Resize
+ mbInitWinClipRegion = TRUE; // TRUE: Calc Window Clip Region
+ mbInitChildRegion = FALSE; // TRUE: InitChildClipRegion
+ mbWinRegion = FALSE; // TRUE: Window Region
+ mbClipChildren = FALSE; // TRUE: Child-Fenster muessen evt. geclippt werden
+ mbClipSiblings = FALSE; // TRUE: Nebeneinanderliegende Child-Fenster muessen evt. geclippt werden
+ mbChildTransparent = FALSE; // TRUE: Child-Fenster duerfen transparent einschalten (inkl. Parent-CLIPCHILDREN)
+ mbPaintTransparent = FALSE; // TRUE: Paints muessen auf Parent ausgeloest werden
+ mbMouseTransparent = FALSE; // TRUE: Window is transparent for Mouse
+ mbDlgCtrlStart = FALSE; // TRUE: Ab hier eigenes Dialog-Control
+ mbFocusVisible = FALSE; // TRUE: Focus Visible
+ mbTrackVisible = FALSE; // TRUE: Tracking Visible
+ mbControlForeground = FALSE; // TRUE: Foreground-Property set
+ mbControlBackground = FALSE; // TRUE: Background-Property set
+ mbAlwaysOnTop = FALSE; // TRUE: immer vor allen anderen normalen Fenstern sichtbar
+ mbCompoundControl = FALSE; // TRUE: Zusammengesetztes Control => Listener...
+ mbCompoundControlHasFocus = FALSE; // TRUE: Zusammengesetztes Control hat irgendwo den Focus
+ mbPaintDisabled = FALSE; // TRUE: Paint soll nicht ausgefuehrt werden
+ mbAllResize = FALSE; // TRUE: Auch ResizeEvents mit 0,0 schicken
+ mbInDtor = FALSE; // TRUE: Wir befinden uns im Window-Dtor
+ mbExtTextInput = FALSE; // TRUE: ExtTextInput-Mode is active
+ mbInFocusHdl = FALSE; // TRUE: Innerhalb vom GetFocus-Handler
+ mbCreatedWithToolkit = FALSE;
+
+#ifdef REMOTE_APPSERVER
+ mpRmEvents = NULL;
+
+ Font aFont = maInputContext.GetFont();
+ aFont.SetCharSet( gsl_getSystemTextEncoding() );
+ maInputContext.SetFont( aFont );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
+{
+ static ::com::sun::star::uno::Any aVoid;
+ ImplInit( pParent, nStyle, aVoid );
+}
+#else
+void Window::ImplInit( Window* pParent, WinBits nStyle, const ::com::sun::star::uno::Any& aSystemWorkWindowToken )
+{
+ ImplInit( pParent, nStyle, NULL );
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
+#else
+void Window::ImplInit( Window* pParent, WinBits nStyle, const ::com::sun::star::uno::Any& aSystemWorkWindowToken )
+#endif
+{
+ DBG_ASSERT( mbFrame || pParent, "Window::Window(): pParent == NULL" );
+
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pRealParent = pParent;
+
+ // 3D-Look vererben
+ if ( !mbOverlapWin && (pParent->GetStyle() & WB_3DLOOK) )
+ nStyle |= WB_3DLOOK;
+
+ // Wenn wir einen Border haben, muessen wir ein BorderWindow anlegen
+ if ( !mbFrame && !mbBorderWin && !mpBorderWindow && (nStyle & WB_BORDER) )
+ {
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL) );
+ ((Window*)pBorderWin)->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpBorderWindow = pBorderWin;
+ pParent = mpBorderWindow;
+ }
+
+ // insert window in list
+ ImplInsertWindow( pParent );
+ mnStyle = nStyle;
+
+ // Overlap-Window-Daten
+ if ( mbOverlapWin )
+ {
+ mpOverlapData = new ImplOverlapData;
+ mpOverlapData->mpSaveBackDev = NULL;
+ mpOverlapData->mpSaveBackRgn = NULL;
+ mpOverlapData->mpNextBackWin = NULL;
+ mpOverlapData->mnSaveBackSize = 0;
+ mpOverlapData->mbSaveBack = FALSE;
+ mpOverlapData->mnTopLevel = 1;
+ }
+
+ // test for frame creation
+ if ( mbFrame )
+ {
+ // create frame
+#ifndef REMOTE_APPSERVER
+ ULONG nFrameStyle = 0;
+
+ if ( nStyle & WB_MOVEABLE )
+ nFrameStyle |= SAL_FRAME_STYLE_MOVEABLE;
+ if ( nStyle & WB_SIZEABLE )
+ {
+ nFrameStyle |= SAL_FRAME_STYLE_SIZEABLE |
+ SAL_FRAME_STYLE_MINABLE |
+ SAL_FRAME_STYLE_MAXABLE;
+ }
+ if ( nStyle & WB_CLOSEABLE )
+ nFrameStyle |= SAL_FRAME_STYLE_CLOSEABLE;
+ if ( nStyle & WB_APP )
+ nFrameStyle |= SAL_FRAME_STYLE_DEFAULT;
+
+ SalFrame* pParentFrame = NULL;
+ if ( pParent )
+ pParentFrame = pParent->mpFrame;
+ SalFrame* pFrame;
+ if ( pSystemParentData )
+ pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SAL_FRAME_STYLE_CHILD );
+ else
+ pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
+ if ( !pFrame )
+ GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
+ pFrame->SetCallback( this, ImplWindowFrameProc );
+
+ // initialize system-Drag&Drop-interface
+ DragManager::SystemEnableDrop( pFrame, TRUE );
+#else
+ RmFrameWindow* pParentFrame = pParent ? pParent->mpFrame : NULL;;
+ RmFrameWindow* pFrame = new RmFrameWindow( this );
+ if ( !pFrame->IsValid() )
+ {
+ delete pFrame, pFrame = NULL;
+ GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
+ }
+ else
+ {
+ pFrame->Create( nStyle, pFrame->GetEventHdlInterface(),
+ aSystemWorkWindowToken,
+ pParentFrame ? pParentFrame->GetFrameInterface() : REF( NMSP_CLIENT::XRmFrameWindow )() );
+ }
+#endif
+
+ // set window frame data
+ mpFrameData = new ImplFrameData;
+ mpFrame = pFrame;
+ mpFrameWindow = this;
+ mpOverlapWindow = this;
+
+ // set frame data
+ mpFrameData->mpNextFrame = pSVData->maWinData.mpFirstFrame;
+ pSVData->maWinData.mpFirstFrame = this;
+ mpFrameData->mpFirstOverlap = NULL;
+ mpFrameData->mpFocusWin = NULL;
+ mpFrameData->mpMouseMoveWin = NULL;
+ mpFrameData->mpMouseDownWin = NULL;
+ mpFrameData->mpFirstBackWin = NULL;
+ mpFrameData->mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpFrameData->mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mpFrameData->mnAllSaveBackSize = 0;
+ mpFrameData->mnFocusId = 0;
+ mpFrameData->mnMouseMoveId = 0;
+ mpFrameData->mnLastMouseX = -1;
+ mpFrameData->mnLastMouseY = -1;
+ mpFrameData->mnFirstMouseX = -1;
+ mpFrameData->mnFirstMouseY = -1;
+ mpFrameData->mnLastMouseWinX = -1;
+ mpFrameData->mnLastMouseWinY = -1;
+ mpFrameData->mnMouseDownTime = 0;
+ mpFrameData->mnClickCount = 0;
+ mpFrameData->mnFirstMouseCode = 0;
+ mpFrameData->mnMouseCode = 0;
+ mpFrameData->mnMouseMode = 0;
+ mpFrameData->meMapUnit = MAP_PIXEL;
+ mpFrameData->mbHasFocus = FALSE;
+ mpFrameData->mbInMouseMove = FALSE;
+ mpFrameData->mbMouseIn = FALSE;
+ mpFrameData->mbStartDragCalled = FALSE;
+ mpFrameData->mbNeedSysWindow = FALSE;
+ mpFrameData->mbMinimized = FALSE;
+ mpFrameData->mbStartFocusState = FALSE;
+ mpFrameData->mbInSysObjFocusHdl = FALSE;
+ mpFrameData->mbInSysObjToTopHdl = FALSE;
+ mpFrameData->mbSysObjFocus = FALSE;
+
+ mpFrameData->mpDragTimer = NULL;
+ mpFrameData->maPaintTimer.SetTimeout( 30 );
+ mpFrameData->maPaintTimer.SetTimeoutHdl( LINK( this, Window, ImplHandlePaintHdl ) );
+
+#ifndef REMOTE_APPSERVER
+ // Muessen Application-Settings noch upgedatet werden
+ if ( !pSVData->maAppData.mbSettingsInit )
+ {
+ mpFrame->UpdateSettings( *pSVData->maAppData.mpSettings );
+ GetpApp()->SystemSettingsChanging( *pSVData->maAppData.mpSettings, this );
+#ifdef DBG_UTIL
+ // Evt. AppFont auf Fett schalten, damit man feststellen kann,
+ // ob fuer die Texte auf anderen Systemen genuegend Platz
+ // vorhanden ist
+ if ( DbgIsBoldAppFont() )
+ {
+ StyleSettings aStyleSettings = pSVData->maAppData.mpSettings->GetStyleSettings();
+ Font aFont = aStyleSettings.GetAppFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetAppFont( aFont );
+ aFont = aStyleSettings.GetGroupFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetGroupFont( aFont );
+ aFont = aStyleSettings.GetLabelFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetLabelFont( aFont );
+ aFont = aStyleSettings.GetRadioCheckFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetRadioCheckFont( aFont );
+ aFont = aStyleSettings.GetPushButtonFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetPushButtonFont( aFont );
+ aFont = aStyleSettings.GetFieldFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetFieldFont( aFont );
+ aFont = aStyleSettings.GetIconFont();
+ aFont.SetWeight( WEIGHT_BOLD );
+ aStyleSettings.SetIconFont( aFont );
+ pSVData->maAppData.mpSettings->SetStyleSettings( aStyleSettings );
+ }
+#endif
+ OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
+ pSVData->maAppData.mbSettingsInit = TRUE;
+ }
+#endif
+ }
+
+ // init data
+ mpRealParent = pRealParent;
+
+ if ( mbFrame )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pParent )
+ {
+ mpFrameData->mnDPIX = pParent->mpFrameData->mnDPIX;
+ mpFrameData->mnDPIY = pParent->mpFrameData->mnDPIY;
+ mpFrameData->mnFontDPIX = pParent->mpFrameData->mnFontDPIX;
+ mpFrameData->mnFontDPIY = pParent->mpFrameData->mnFontDPIY;
+ }
+ else
+ {
+ if ( ImplGetGraphics() )
+ {
+ mpGraphics->GetResolution( mpFrameData->mnDPIX, mpFrameData->mnDPIY );
+ mpGraphics->GetScreenFontResolution( mpFrameData->mnFontDPIX, mpFrameData->mnFontDPIY );
+ if ( !mpFrameData->mpFontList->Count() )
+ {
+ mpGraphics->GetDevFontList( mpFrameData->mpFontList );
+ mpFrameData->mpFontList->InitStdFonts();
+ }
+ }
+ }
+#else
+ const REF( NMSP_CLIENT::XRmFrameWindow )& rxWindow = mpFrame->GetFrameInterface();
+ REF( NMSP_CLIENT::XRmOutputDevice ) xOutDev( mpFrame->GetOutdevInterface() );
+
+ if ( rxWindow.is() && xOutDev.is() )
+ {
+ mpGraphics = new ImplServerGraphics;
+ mpGraphics->SetInterface( xOutDev );
+ if ( pParent )
+ {
+ mpFrameData->mnDPIX = pParent->mpFrameData->mnDPIX;
+ mpFrameData->mnDPIY = pParent->mpFrameData->mnDPIY;
+ mpFrameData->mnFontDPIX = pParent->mpFrameData->mnFontDPIX;
+ mpFrameData->mnFontDPIY = pParent->mpFrameData->mnFontDPIY;
+ }
+ else
+ {
+ // We currently assume, that we have only one display
+ static NMSP_CLIENT::RmFrameResolutions aResl = mpFrame->GetFrameResolutions();
+ mpFrameData->mnDPIX = aResl.DPIx;
+ mpFrameData->mnDPIY = aResl.DPIy;
+ mpFrameData->mnFontDPIX = aResl.FontDPIx;
+ mpFrameData->mnFontDPIY = aResl.FontDPIy;
+ mpGraphics->SetWindowResolution( aResl.DPIx, aResl.DPIy, aResl.Depth );
+ if ( !mpFrameData->mpFontList->Count() )
+ {
+ mpGraphics->GetDevFontList( mpFrameData->mpFontList );
+ mpFrameData->mpFontList->InitStdFonts();
+ }
+ }
+ }
+#endif
+
+ // If we create a Window with default size, query this
+ // size directly, because we want resize all Controls to
+ // the correct size before we display the window
+ if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
+ mpFrame->GetClientSize( mnOutWidth, mnOutHeight );
+ }
+ else
+ {
+ if ( pParent )
+ {
+ if ( !ImplIsOverlapWindow() )
+ {
+ mbDisabled = pParent->mbDisabled;
+ mbInputDisabled = pParent->mbInputDisabled;
+ mbAlwaysEnableInput = pParent->mbAlwaysEnableInput;
+ }
+
+ OutputDevice::SetSettings( pParent->GetSettings() );
+ }
+ }
+
+ const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
+ USHORT nScreenZoom = rStyleSettings.GetScreenZoom();
+ mnDPIX = (mpFrameData->mnDPIX*nScreenZoom)/100;
+ mnDPIY = (mpFrameData->mnDPIY*nScreenZoom)/100;
+ mpFontList = mpFrameData->mpFontList;
+ mpFontCache = mpFrameData->mpFontCache;
+ maFont = rStyleSettings.GetAppFont();
+ ImplPointToLogic( maFont );
+
+ if ( nStyle & WB_3DLOOK )
+ {
+ SetTextColor( rStyleSettings.GetButtonTextColor() );
+ SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
+ }
+ else
+ {
+ SetTextColor( rStyleSettings.GetWindowTextColor() );
+ SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
+ }
+
+ ImplUpdatePos();
+
+ // AppFont-Aufloesung berechnen
+ if ( mbFrame && !pSVData->maGDIData.mnAppFontX )
+ ImplInitAppFontData( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInsertWindow( Window* pParent )
+{
+ mpParent = pParent;
+ mpRealParent = pParent;
+
+ if ( pParent && !mbFrame )
+ {
+ // search frame window and set window frame data
+ Window* pFrameParent = pParent->mpFrameWindow;
+ mpFrameData = pFrameParent->mpFrameData;
+ mpFrame = pFrameParent->mpFrame;
+ mpFrameWindow = pFrameParent;
+ mbFrame = FALSE;
+#ifdef REMOTE_APPSERVER
+ mpGraphics = mpFrameWindow->mpGraphics;
+#endif
+
+ // search overlap window and insert window in list
+ if ( ImplIsOverlapWindow() )
+ {
+ Window* pFirstOverlapParent = pParent;
+ while ( !pFirstOverlapParent->ImplIsOverlapWindow() )
+ pFirstOverlapParent = pFirstOverlapParent->ImplGetParent();
+ mpOverlapWindow = pFirstOverlapParent;
+
+ mpNextOverlap = mpFrameData->mpFirstOverlap;
+ mpFrameData->mpFirstOverlap = this;
+
+ // Overlap-Windows sind per default die obersten
+ mpNext = pFirstOverlapParent->mpFirstOverlap;
+ pFirstOverlapParent->mpFirstOverlap = this;
+ if ( !pFirstOverlapParent->mpLastOverlap )
+ pFirstOverlapParent->mpLastOverlap = this;
+ else
+ mpNext->mpPrev = this;
+ }
+ else
+ {
+ if ( pParent->ImplIsOverlapWindow() )
+ mpOverlapWindow = pParent;
+ else
+ mpOverlapWindow = pParent->mpOverlapWindow;
+ mpPrev = pParent->mpLastChild;
+ pParent->mpLastChild = this;
+ if ( !pParent->mpFirstChild )
+ pParent->mpFirstChild = this;
+ else
+ mpPrev->mpNext = this;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplRemoveWindow( BOOL bRemoveFrameData )
+{
+ // Fenster aus den Listen austragen
+ if ( !mbFrame )
+ {
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpFrameData->mpFirstOverlap == this )
+ mpFrameData->mpFirstOverlap = mpNextOverlap;
+ else
+ {
+ Window* pTempWin = mpFrameData->mpFirstOverlap;
+ while ( pTempWin->mpNextOverlap != this )
+ pTempWin = pTempWin->mpNextOverlap;
+ pTempWin->mpNextOverlap = mpNextOverlap;
+ }
+
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpOverlapWindow->mpFirstOverlap = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpOverlapWindow->mpLastOverlap = mpPrev;
+ }
+ else
+ {
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpParent->mpFirstChild = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpParent->mpLastChild = mpPrev;
+ }
+
+ mpPrev = NULL;
+ mpNext = NULL;
+ }
+
+ if ( bRemoveFrameData )
+ {
+ // Graphic freigeben
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+#else
+ ImplReleaseServerGraphics();
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static ULONG ImplAutoHelpID()
+{
+ if ( !Application::IsAutoHelpIdEnabled() )
+ return 0;
+
+ ULONG nHID = 0;
+
+ ResMgr *pResMgr = Resource::GetResManager();
+
+ DBG_ASSERT( pResMgr, "MM hat gesagt, dass wir immer einen haben" );
+ DBG_ASSERT( pResMgr->nTopRes, "MM hat gesagt, dass der Stack nie leer ist" );
+ if( !pResMgr || pResMgr->nTopRes < 1 || pResMgr->nTopRes > 2 )
+ return 0;
+
+ const ImpRCStack *pRC = pResMgr->StackTop( pResMgr->nTopRes==1 ? 0 : 1 );
+
+ DBG_ASSERT( pRC->pResource, "MM hat gesagt, dass der immer einen hat" );
+ ULONG nGID = pRC->pResource->GetId();
+
+ if( !nGID || nGID > 32767 )
+ return 0;
+
+ // GGGg gggg::gggg gggg::ggLL LLLl::llll llll
+ switch( pRC->pResource->GetRT() ) { // maximal 7
+ case RSC_DOCKINGWINDOW:
+ nHID += 0x20000000L;
+ case RSC_WORKWIN:
+ nHID += 0x20000000L;
+ case RSC_MODELESSDIALOG:
+ nHID += 0x20000000L;
+ case RSC_FLOATINGWINDOW:
+ nHID += 0x20000000L;
+ case RSC_MODALDIALOG:
+ nHID += 0x20000000L;
+ case RSC_TABPAGE:
+ nHID += 0x20000000L;
+
+ if( pResMgr->nTopRes == 2 ) {
+ pRC = pResMgr->StackTop();
+ ULONG nLID = pRC->pResource->GetId();
+
+ if( !nLID || nLID > 511 )
+ return 0;
+
+ switch( pRC->pResource->GetRT() ) { // maximal 32
+ case RSC_TABCONTROL: nHID |= 0x0000; break;
+ case RSC_RADIOBUTTON: nHID |= 0x0200; break;
+ case RSC_CHECKBOX: nHID |= 0x0400; break;
+ case RSC_TRISTATEBOX: nHID |= 0x0600; break;
+ case RSC_EDIT: nHID |= 0x0800; break;
+ case RSC_MULTILINEEDIT: nHID |= 0x0A00; break;
+ case RSC_MULTILISTBOX: nHID |= 0x0C00; break;
+ case RSC_LISTBOX: nHID |= 0x0E00; break;
+ case RSC_COMBOBOX: nHID |= 0x1000; break;
+ case RSC_PUSHBUTTON: nHID |= 0x1200; break;
+ case RSC_SPINFIELD: nHID |= 0x1400; break;
+ case RSC_PATTERNFIELD: nHID |= 0x1600; break;
+ case RSC_NUMERICFIELD: nHID |= 0x1800; break;
+ case RSC_METRICFIELD: nHID |= 0x1A00; break;
+ case RSC_CURRENCYFIELD: nHID |= 0x1C00; break;
+ case RSC_DATEFIELD: nHID |= 0x1E00; break;
+ case RSC_TIMEFIELD: nHID |= 0x2000; break;
+ case RSC_IMAGERADIOBUTTON: nHID |= 0x2200; break;
+ case RSC_NUMERICBOX: nHID |= 0x2400; break;
+ case RSC_METRICBOX: nHID |= 0x2600; break;
+ case RSC_CURRENCYBOX: nHID |= 0x2800; break;
+ case RSC_DATEBOX: nHID |= 0x2A00; break;
+ case RSC_TIMEBOX: nHID |= 0x2C00; break;
+ case RSC_IMAGEBUTTON: nHID |= 0x2E00; break;
+ case RSC_MENUBUTTON: nHID |= 0x3000; break;
+ case RSC_MOREBUTTON: nHID |= 0x3200; break;
+ default:
+ return 0;
+ } // of switch
+ nHID |= nLID;
+ } // of if
+ break;
+ default:
+ return 0;
+ } // of switch
+ nHID |= nGID << 14;
+ return nHID;
+}
+
+// -----------------------------------------------------------------------
+
+WinBits Window::ImplInitRes( const ResId& rResId )
+{
+ GetRes( rResId );
+
+ char* pRes = (char*)GetClassRes();
+ pRes += 4;
+ ULONG nStyle = GetLongRes( (void*)pRes );
+ ((ResId&)rResId).aWinBits = nStyle;
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplLoadRes( const ResId& rResId )
+{
+ // newer move this line after IncrementRes
+ char* pRes = (char*)GetClassRes();
+ pRes += 8;
+ ULONG nHelpId = (ULONG)GetLongRes( (void*)pRes );
+ if ( !nHelpId )
+ nHelpId = ImplAutoHelpID();
+ SetHelpId( nHelpId );
+
+ USHORT nObjMask = (USHORT)ReadShortRes();
+
+ // ResourceStyle
+ USHORT nRSStyle = ReadShortRes();
+ // WinBits
+ ReadLongRes();
+ // HelpId
+ ReadLongRes();
+
+ BOOL bPos = FALSE;
+ BOOL bSize = FALSE;
+ Point aPos;
+ Size aSize;
+
+ if ( nObjMask & (WINDOW_XYMAPMODE | WINDOW_X | WINDOW_Y) )
+ {
+ // Groessenangabe aus der Resource verwenden
+ MapUnit ePosMap = MAP_PIXEL;
+
+ bPos = TRUE;
+
+ if ( nObjMask & WINDOW_XYMAPMODE )
+ ePosMap = (MapUnit)(USHORT)ReadShortRes();
+ if ( nObjMask & WINDOW_X )
+ aPos.X() = ImplLogicUnitToPixelX( ReadLongRes(), ePosMap );
+ if ( nObjMask & WINDOW_Y )
+ aPos.Y() = ImplLogicUnitToPixelY( ReadLongRes(), ePosMap );
+ }
+
+ if ( nObjMask & (WINDOW_WHMAPMODE | WINDOW_WIDTH | WINDOW_HEIGHT) )
+ {
+ // Groessenangabe aus der Resource verwenden
+ MapUnit eSizeMap = MAP_PIXEL;
+
+ bSize = TRUE;
+
+ if ( nObjMask & WINDOW_WHMAPMODE )
+ eSizeMap = (MapUnit)(USHORT)ReadShortRes();
+ if ( nObjMask & WINDOW_WIDTH )
+ aSize.Width() = ImplLogicUnitToPixelX( ReadLongRes(), eSizeMap );
+ if ( nObjMask & WINDOW_HEIGHT )
+ aSize.Height() = ImplLogicUnitToPixelY( ReadLongRes(), eSizeMap );
+ }
+
+ // Wegen Optimierung so schlimm aussehend
+ if ( nRSStyle & RSWND_CLIENTSIZE )
+ {
+ if ( bPos )
+ SetPosPixel( aPos );
+ if ( bSize )
+ SetOutputSizePixel( aSize );
+ }
+ else if ( bPos && bSize )
+ SetPosSizePixel( aPos, aSize );
+ else if ( bPos )
+ SetPosPixel( aPos );
+ else if ( bSize )
+ SetSizePixel( aSize );
+
+ if ( nRSStyle & RSWND_DISABLED )
+ Enable( FALSE );
+
+ if ( nObjMask & WINDOW_TEXT )
+ SetText( ReadStringRes() );
+ if ( nObjMask & WINDOW_HELPTEXT )
+ SetHelpText( ReadStringRes() );
+ if ( nObjMask & WINDOW_QUICKTEXT )
+ SetQuickHelpText( ReadStringRes() );
+ if ( nObjMask & WINDOW_EXTRALONG )
+ SetData( (void*)ReadLongRes() );
+ if ( nObjMask & WINDOW_UNIQUEID )
+ SetUniqueId( (ULONG)ReadLongRes() );
+}
+
+// -----------------------------------------------------------------------
+
+ImplWinData* Window::ImplGetWinData() const
+{
+ if ( !mpWinData )
+ {
+ ((Window*)this)->mpWinData = new ImplWinData;
+ mpWinData->mpExtPosAry = NULL;
+ mpWinData->mnExtPosStart = 0;
+ mpWinData->mnExtPosCount = 0;
+ mpWinData->mnExtOldTextLen = 0;
+ mpWinData->mpFocusRect = NULL;
+ mpWinData->mpTrackRect = NULL;
+ mpWinData->mnTrackFlags = 0;
+ }
+
+ return mpWinData;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+SalGraphics* Window::ImplGetFrameGraphics() const
+{
+ if ( mpFrameWindow->mpGraphics )
+ mpFrameWindow->mbInitClipRegion = TRUE;
+ else
+ mpFrameWindow->ImplGetGraphics();
+ mpFrameWindow->mpGraphics->ResetClipRegion();
+ return mpFrameWindow->mpGraphics;
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplFindWindow( const Point& rFramePos )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pTempWindow;
+ Window* pFindWindow;
+
+ // Zuerst alle ueberlappenden Fenster ueberpruefen
+ pTempWindow = mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
+ if ( pFindWindow )
+ return pFindWindow;
+ pTempWindow = pTempWindow->mpNext;
+ }
+
+ // dann testen wir unser Fenster
+ if ( !mbVisible )
+ return NULL;
+
+ USHORT nHitTest = ImplHitTest( rFramePos );
+ if ( nHitTest & WINDOW_HITTEST_INSIDE )
+ {
+ // und danach gehen wir noch alle Child-Fenster durch
+ pTempWindow = mpFirstChild;
+ while ( pTempWindow )
+ {
+ pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
+ if ( pFindWindow )
+ return pFindWindow;
+ pTempWindow = pTempWindow->mpNext;
+ }
+
+ if ( nHitTest & WINDOW_HITTEST_TRANSPARENT )
+ return NULL;
+ else
+ return this;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::ImplHitTest( const Point& rFramePos )
+{
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ if ( !aRect.IsInside( rFramePos ) )
+ return 0;
+ if ( mbWinRegion )
+ {
+ Point aTempPos = rFramePos;
+ aTempPos.X() -= mnOutOffX;
+ aTempPos.Y() -= mnOutOffY;
+ if ( !maWinRegion.IsInside( aTempPos ) )
+ return 0;
+ }
+
+ USHORT nHitTest = WINDOW_HITTEST_INSIDE;
+ if ( mbMouseTransparent )
+ nHitTest |= WINDOW_HITTEST_TRANSPARENT;
+ return nHitTest;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsRealParentPath( const Window* pWindow ) const
+{
+ pWindow = pWindow->GetParent();
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ return TRUE;
+ pWindow = pWindow->GetParent();
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ do
+ {
+ if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+
+ if ( pWindow == this )
+ return TRUE;
+ }
+ while ( pWindow );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplIsWindowOrChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ if ( this == pWindow )
+ return TRUE;
+ return ImplIsChild( pWindow, bSystemWindow );
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::ImplGetSameParent( const Window* pWindow ) const
+{
+ if ( mpFrameWindow != pWindow->mpFrameWindow )
+ return NULL;
+ else
+ {
+ if ( pWindow->ImplIsChild( this ) )
+ return (Window*)pWindow;
+ else
+ {
+ Window* pTestWindow = (Window*)this;
+ while ( (pTestWindow == pWindow) || pTestWindow->ImplIsChild( pWindow ) )
+ pTestWindow = pTestWindow->ImplGetParent();
+ return pTestWindow;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int Window::ImplTestMousePointerSet()
+{
+ // Wenn Mouse gecaptured ist, dann soll MousePointer umgeschaltet werden
+ if ( IsMouseCaptured() )
+ return TRUE;
+
+ // Wenn sich Mouse ueber dem Fenster befindet, dann soll MousePointer
+ // umgeschaltet werden
+ Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
+ if ( aClientRect.IsInside( GetPointerPosPixel() ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+PointerStyle Window::ImplGetMousePointer() const
+{
+ PointerStyle ePointerStyle;
+ BOOL bWait = FALSE;
+
+ if ( IsEnabled() && IsInputEnabled() )
+ ePointerStyle = GetPointer().GetStyle();
+ else
+ ePointerStyle = POINTER_ARROW;
+
+ const Window* pWindow = this;
+ do
+ {
+ // Wenn Pointer nicht sichtbar, dann wird suche abgebrochen, da
+ // dieser Status nicht ueberschrieben werden darf
+ if ( pWindow->mbNoPtrVisible )
+ return POINTER_NULL;
+
+ if ( !bWait )
+ {
+ if ( pWindow->mnWaitCount )
+ {
+ ePointerStyle = POINTER_WAIT;
+ bWait = TRUE;
+ }
+ else
+ {
+ if ( pWindow->mbChildPtrOverwrite )
+ ePointerStyle = pWindow->GetPointer().GetStyle();
+ }
+ }
+
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+
+ return ePointerStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplResetReallyVisible()
+{
+ mbDevOutput = FALSE;
+ mbReallyVisible = FALSE;
+ mbReallyShown = FALSE;
+
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ pWindow->ImplResetReallyVisible();
+ pWindow = pWindow->mpNext;
+ }
+
+ pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ pWindow->ImplResetReallyVisible();
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplSetReallyVisible()
+{
+ mbDevOutput = TRUE;
+ mbReallyVisible = TRUE;
+ mbReallyShown = TRUE;
+
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mbVisible )
+ pWindow->ImplSetReallyVisible();
+ pWindow = pWindow->mpNext;
+ }
+
+ pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbVisible )
+ pWindow->ImplSetReallyVisible();
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallInitShow()
+{
+ mbReallyShown = TRUE;
+ mbInInitShow = TRUE;
+ StateChanged( STATE_CHANGE_INITSHOW );
+ mbInInitShow = FALSE;
+
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mbVisible )
+ pWindow->ImplCallInitShow();
+ pWindow = pWindow->mpNext;
+ }
+
+ pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbVisible )
+ pWindow->ImplCallInitShow();
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplAddDel( ImplDelData* pDel )
+{
+ pDel->mpNext = mpFirstDel;
+ mpFirstDel = pDel;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplRemoveDel( ImplDelData* pDel )
+{
+ if ( mpFirstDel == pDel )
+ mpFirstDel = pDel->mpNext;
+ else
+ {
+ ImplDelData* pData = mpFirstDel;
+ while ( pData->mpNext != pDel )
+ pData = pData->mpNext;
+ pData->mpNext = pDel->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitResolutionSettings()
+{
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ if ( mbFrame )
+ {
+ const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
+ USHORT nScreenZoom = rStyleSettings.GetScreenZoom();
+ mnDPIX = (mpFrameData->mnDPIX*nScreenZoom)/100;
+ mnDPIY = (mpFrameData->mnDPIY*nScreenZoom)/100;
+ SetPointFont( rStyleSettings.GetAppFont() );
+
+ if ( !ImplGetSVData()->maGDIData.mnAppFontX )
+ ImplInitAppFontData( this );
+ }
+ else if ( mpParent )
+ {
+ mnDPIX = mpParent->mnDPIX;
+ mnDPIY = mpParent->mnDPIY;
+ }
+
+ // Vorberechnete Werte fuer logische Einheiten updaten und auch
+ // die entsprechenden Tools dazu
+ if ( IsMapMode() )
+ {
+ MapMode aMapMode = GetMapMode();
+ SetMapMode();
+ SetMapMode( aMapMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplPointToLogic( Font& rFont ) const
+{
+ Size aSize = rFont.GetSize();
+ USHORT nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
+
+ if ( aSize.Width() )
+ {
+ aSize.Width() *= mpFrameData->mnFontDPIX;
+ aSize.Width() += 72/2;
+ aSize.Width() /= 72;
+ aSize.Width() *= nScreenFontZoom;
+ aSize.Width() /= 100;
+ }
+ aSize.Height() *= mpFrameData->mnFontDPIY;
+ aSize.Height() += 72/2;
+ aSize.Height() /= 72;
+ aSize.Height() *= nScreenFontZoom;
+ aSize.Height() /= 100;
+
+ if ( IsMapModeEnabled() )
+ aSize = PixelToLogic( aSize );
+
+ rFont.SetSize( aSize );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplLogicToPoint( Font& rFont ) const
+{
+ Size aSize = rFont.GetSize();
+ USHORT nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
+
+ if ( IsMapModeEnabled() )
+ aSize = LogicToPixel( aSize );
+
+ if ( aSize.Width() )
+ {
+ aSize.Width() *= 100;
+ aSize.Width() /= nScreenFontZoom;
+ aSize.Width() *= 72;
+ aSize.Width() += mpFrameData->mnFontDPIX/2;
+ aSize.Width() /= mpFrameData->mnFontDPIX;
+ }
+ aSize.Height() *= 100;
+ aSize.Height() /= nScreenFontZoom;
+ aSize.Height() *= 72;
+ aSize.Height() += mpFrameData->mnFontDPIY/2;
+ aSize.Height() /= mpFrameData->mnFontDPIY;
+
+ rFont.SetSize( aSize );
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+BOOL Window::ImplSysObjClip( const Region* pOldRegion )
+{
+ BOOL bUpdate = TRUE;
+
+ if ( mpSysObj )
+ {
+ BOOL bVisibleState = mbReallyVisible;
+
+ if ( bVisibleState )
+ {
+ Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
+
+ if ( !pWinChildClipRegion->IsEmpty() )
+ {
+ if ( pOldRegion )
+ {
+ Region aNewRegion = *pWinChildClipRegion;
+ pWinChildClipRegion->Intersect( *pOldRegion );
+ bUpdate = aNewRegion == *pWinChildClipRegion;
+ }
+
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ Region aRegion = *pWinChildClipRegion;
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aWinRectRegion( aWinRect );
+ USHORT nClipFlags = mpSysObj->GetClipRegionType();
+
+ if ( aRegion == aWinRectRegion )
+ mpSysObj->ResetClipRegion();
+ else
+ {
+ if ( nClipFlags & SAL_OBJECT_CLIP_EXCLUDERECTS )
+ {
+ aWinRectRegion.Exclude( aRegion );
+ aRegion = aWinRectRegion;
+ }
+ if ( !(nClipFlags & SAL_OBJECT_CLIP_ABSOLUTE) )
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+
+ // ClipRegion setzen/updaten
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ULONG nRectCount;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ nRectCount = aRegion.GetRectCount();
+ mpSysObj->BeginSetClipRegion( nRectCount );
+ bRegionRect = aRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ mpSysObj->UnionClipRegion( nX, nY, nWidth, nHeight );
+ bRegionRect = aRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ mpSysObj->EndSetClipRegion();
+ }
+ }
+ else
+ bVisibleState = FALSE;
+ }
+
+ // Visible-Status updaten
+ mpSysObj->Show( bVisibleState );
+ }
+
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjChildsClip()
+{
+ if ( mpSysObj && mbInitWinClipRegion )
+ ImplSysObjClip( NULL );
+
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjChildsClip();
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjOverlapsClip()
+{
+ ImplUpdateSysObjChildsClip();
+
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjOverlapsClip();
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateSysObjClip()
+{
+ if ( !ImplIsOverlapWindow() )
+ {
+ ImplUpdateSysObjChildsClip();
+
+ // Schwestern muessen ihre ClipRegion auch neu berechnen
+ if ( mbClipSiblings )
+ {
+ Window* pWindow = mpNext;
+ while ( pWindow )
+ {
+ pWindow->ImplUpdateSysObjChildsClip();
+ pWindow = pWindow->mpNext;
+ }
+ }
+ }
+ else
+ mpFrameWindow->ImplUpdateSysObjOverlapsClip();
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlagChilds( BOOL bSysObjOnlySmaller )
+{
+ BOOL bUpdate = TRUE;
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ {
+ Region* pOldRegion = NULL;
+ if ( bSysObjOnlySmaller && !mbInitWinClipRegion )
+ pOldRegion = new Region( maWinClipRegion );
+
+ mbInitClipRegion = TRUE;
+ mbInitWinClipRegion = TRUE;
+
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpNext;
+ }
+
+ if ( !ImplSysObjClip( pOldRegion ) )
+ {
+ mbInitClipRegion = TRUE;
+ mbInitWinClipRegion = TRUE;
+ bUpdate = FALSE;
+ }
+
+ if ( pOldRegion )
+ delete pOldRegion;
+ }
+ else
+#endif
+ {
+ mbInitClipRegion = TRUE;
+ mbInitWinClipRegion = TRUE;
+
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpNext;
+ }
+ }
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlagOverlapWindows( BOOL bSysObjOnlySmaller )
+{
+ BOOL bUpdate = ImplSetClipFlagChilds( bSysObjOnlySmaller );
+
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpNext;
+ }
+
+ return bUpdate;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplSetClipFlag( BOOL bSysObjOnlySmaller )
+{
+ if ( !ImplIsOverlapWindow() )
+ {
+ BOOL bUpdate = ImplSetClipFlagChilds( bSysObjOnlySmaller );
+
+ Window* pParent = ImplGetParent();
+ if ( pParent &&
+ ((pParent->GetStyle() & WB_CLIPCHILDREN) || (mnParentClipMode & PARENTCLIPMODE_CLIP)) )
+ {
+ pParent->mbInitClipRegion = TRUE;
+ pParent->mbInitChildRegion = TRUE;
+ }
+
+ // Schwestern muessen ihre ClipRegion auch neu berechnen
+ if ( mbClipSiblings )
+ {
+ Window* pWindow = mpNext;
+ while ( pWindow )
+ {
+ if ( !pWindow->ImplSetClipFlagChilds( bSysObjOnlySmaller ) )
+ bUpdate = FALSE;
+ pWindow = pWindow->mpNext;
+ }
+ }
+
+ return bUpdate;
+ }
+ else
+ return mpFrameWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectWindowClipRegion( Region& rRegion )
+{
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ rRegion.Intersect( maWinClipRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectWindowRegion( Region& rRegion )
+{
+ rRegion.Intersect( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ) );
+ if ( mbWinRegion )
+ rRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeWindowRegion( Region& rRegion )
+{
+ if ( mbWinRegion )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ aRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+ rRegion.Exclude( aRegion );
+ }
+ else
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ rRegion.Exclude( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeOverlapWindows( Region& rRegion )
+{
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ {
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ pWindow->ImplExcludeOverlapWindows( rRegion );
+ }
+
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplExcludeOverlapWindows2( Region& rRegion )
+{
+ if ( mbReallyVisible )
+ ImplExcludeWindowRegion( rRegion );
+
+ ImplExcludeOverlapWindows( rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipBoundaries( Region& rRegion, BOOL bThis, BOOL bOverlaps )
+{
+ if ( bThis )
+ ImplIntersectWindowClipRegion( rRegion );
+ else if ( ImplIsOverlapWindow() )
+ {
+ // Evt. noch am Frame clippen
+ if ( !mbFrame )
+ rRegion.Intersect( Rectangle( Point( 0, 0 ), Size( mpFrameWindow->mnOutWidth, mpFrameWindow->mnOutHeight ) ) );
+
+ if ( bOverlaps && !rRegion.IsEmpty() )
+ {
+ // Clip Overlap Siblings
+ Window* pStartOverlapWindow = this;
+ while ( !pStartOverlapWindow->mbFrame )
+ {
+ Window* pOverlapWindow = pStartOverlapWindow->mpOverlapWindow->mpFirstOverlap;
+ while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
+ {
+ pOverlapWindow->ImplExcludeOverlapWindows2( rRegion );
+ pOverlapWindow = pOverlapWindow->mpNext;
+ }
+ pStartOverlapWindow = pStartOverlapWindow->mpOverlapWindow;
+ }
+
+ // Clip Child Overlap Windows
+ ImplExcludeOverlapWindows( rRegion );
+ }
+ }
+ else
+ ImplGetParent()->ImplIntersectWindowClipRegion( rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplClipChilds( Region& rRegion )
+{
+ BOOL bOtherClip = FALSE;
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ {
+ // ParentClipMode-Flags auswerten
+ USHORT nClipMode = pWindow->GetParentClipMode();
+ if ( !(nClipMode & PARENTCLIPMODE_NOCLIP) &&
+ ((nClipMode & PARENTCLIPMODE_CLIP) || (GetStyle() & WB_CLIPCHILDREN)) )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ else
+ bOtherClip = TRUE;
+ }
+
+ pWindow = pWindow->mpNext;
+ }
+
+ return bOtherClip;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipAllChilds( Region& rRegion )
+{
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplClipSiblings( Region& rRegion )
+{
+ Window* pWindow = ImplGetParent()->mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ break;
+
+ if ( pWindow->mbReallyVisible )
+ pWindow->ImplExcludeWindowRegion( rRegion );
+
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitWinClipRegion()
+{
+ // Build Window Region
+ maWinClipRegion = Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ if ( mbWinRegion )
+ maWinClipRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+
+ // ClipSiblings
+ if ( mbClipSiblings && !ImplIsOverlapWindow() )
+ ImplClipSiblings( maWinClipRegion );
+
+ // Clip Parent Boundaries
+ ImplClipBoundaries( maWinClipRegion, FALSE, TRUE );
+
+ // Clip Children
+ if ( (GetStyle() & WB_CLIPCHILDREN) || mbClipChildren )
+ mbInitChildRegion = TRUE;
+
+ mbInitWinClipRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInitWinChildClipRegion()
+{
+ if ( !mpFirstChild )
+ {
+ if ( mpChildClipRegion )
+ {
+ delete mpChildClipRegion;
+ mpChildClipRegion = NULL;
+ }
+ }
+ else
+ {
+ if ( !mpChildClipRegion )
+ mpChildClipRegion = new Region( maWinClipRegion );
+ else
+ *mpChildClipRegion = maWinClipRegion;
+
+ ImplClipChilds( *mpChildClipRegion );
+ }
+
+ mbInitChildRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Region* Window::ImplGetWinChildClipRegion()
+{
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+ if ( mbInitChildRegion )
+ ImplInitWinChildClipRegion();
+ if ( mpChildClipRegion )
+ return mpChildClipRegion;
+ else
+ return &maWinClipRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectAndUnionOverlapWindows( const Region& rInterRegion, Region& rRegion )
+{
+ Window* pWindow = mpFirstOverlap;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ {
+ Region aTempRegion( rInterRegion );
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ pWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+ }
+
+ pWindow = pWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplIntersectAndUnionOverlapWindows2( const Region& rInterRegion, Region& rRegion )
+{
+ if ( mbReallyVisible )
+ {
+ Region aTempRegion( rInterRegion );
+ ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+
+ ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcOverlapRegionOverlaps( const Region& rInterRegion, Region& rRegion )
+{
+ // Clip Overlap Siblings
+ Window* pStartOverlapWindow;
+ if ( !ImplIsOverlapWindow() )
+ pStartOverlapWindow = mpOverlapWindow;
+ else
+ pStartOverlapWindow = this;
+ while ( !pStartOverlapWindow->mbFrame )
+ {
+ Window* pOverlapWindow = pStartOverlapWindow->mpOverlapWindow->mpFirstOverlap;
+ while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
+ {
+ pOverlapWindow->ImplIntersectAndUnionOverlapWindows2( rInterRegion, rRegion );
+ pOverlapWindow = pOverlapWindow->mpNext;
+ }
+ pStartOverlapWindow = pStartOverlapWindow->mpOverlapWindow;
+ }
+
+ // Clip Child Overlap Windows
+ if ( !ImplIsOverlapWindow() )
+ mpOverlapWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+ else
+ ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcOverlapRegion( const Rectangle& rSourceRect, Region& rRegion,
+ BOOL bChilds, BOOL bParent, BOOL bSiblings )
+{
+ Region aRegion( rSourceRect );
+ if ( mbWinRegion )
+ rRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+ Region aTempRegion;
+ Window* pWindow;
+
+ ImplCalcOverlapRegionOverlaps( aRegion, rRegion );
+
+ // Parent-Boundaries
+ if ( bParent )
+ {
+ pWindow = this;
+ if ( !ImplIsOverlapWindow() )
+ {
+ pWindow = ImplGetParent();
+ do
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplExcludeWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+ }
+ if ( !pWindow->mbFrame )
+ {
+ aTempRegion = aRegion;
+ aTempRegion.Exclude( Rectangle( Point( 0, 0 ), Size( mpFrameWindow->mnOutWidth, mpFrameWindow->mnOutHeight ) ) );
+ rRegion.Union( aTempRegion );
+ }
+ }
+
+ // Siblings
+ if ( bSiblings && !ImplIsOverlapWindow() )
+ {
+ pWindow = mpParent->mpFirstChild;
+ do
+ {
+ if ( pWindow->mbReallyVisible && (pWindow != this) )
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+ pWindow = pWindow->mpNext;
+ }
+ while ( pWindow );
+ }
+
+ // Childs
+ if ( bChilds )
+ {
+ pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ if ( pWindow->mbReallyVisible )
+ {
+ aTempRegion = aRegion;
+ pWindow->ImplIntersectWindowRegion( aTempRegion );
+ rRegion.Union( aTempRegion );
+ }
+ pWindow = pWindow->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallPaint( const Region* pRegion, USHORT nPaintFlags )
+{
+ mbPaintFrame = FALSE;
+
+ if ( nPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ mnPaintFlags |= IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALLCHILDS | (nPaintFlags & IMPL_PAINT_PAINTALL);
+ if ( nPaintFlags & IMPL_PAINT_PAINTCHILDS )
+ mnPaintFlags |= IMPL_PAINT_PAINTCHILDS;
+ if ( nPaintFlags & IMPL_PAINT_ERASE )
+ mnPaintFlags |= IMPL_PAINT_ERASE;
+ if ( !mpFirstChild )
+ mnPaintFlags &= ~IMPL_PAINT_PAINTALLCHILDS;
+
+ if ( mbPaintDisabled )
+ {
+ if ( mnPaintFlags & IMPL_PAINT_PAINTALL )
+ Invalidate( INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
+ else if ( pRegion )
+ Invalidate( *pRegion, INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
+ return;
+ }
+
+ nPaintFlags = mnPaintFlags & ~(IMPL_PAINT_PAINT);
+
+ Region* pChildRegion = NULL;
+ if ( mnPaintFlags & IMPL_PAINT_PAINT )
+ {
+ Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
+ if ( mnPaintFlags & IMPL_PAINT_PAINTALL )
+ maInvalidateRegion = *pWinChildClipRegion;
+ else
+ {
+ if ( pRegion )
+ maInvalidateRegion.Union( *pRegion );
+ if ( mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ pChildRegion = new Region( maInvalidateRegion );
+ maInvalidateRegion.Intersect( *pWinChildClipRegion );
+ }
+ mnPaintFlags = 0;
+ if ( !maInvalidateRegion.IsEmpty() )
+ {
+ if ( mpCursor )
+ mpCursor->ImplHide();
+
+ mbInitClipRegion = TRUE;
+ mbInPaint = TRUE;
+
+ // Paint-Region zuruecksetzen
+ Region aPaintRegion( maInvalidateRegion );
+ Rectangle aPaintRect = ImplDevicePixelToLogic( aPaintRegion.GetBoundRect() );
+ mpPaintRegion = &aPaintRegion;
+ maInvalidateRegion.SetEmpty();
+
+ if ( (nPaintFlags & IMPL_PAINT_ERASE) && IsBackground() )
+ {
+ if ( IsClipRegion() )
+ {
+ Region aOldRegion = GetClipRegion();
+ SetClipRegion();
+ Erase();
+ SetClipRegion( aOldRegion );
+ }
+ else
+ Erase();
+ }
+ Paint( aPaintRect );
+
+ if ( mpWinData )
+ {
+ if ( mbFocusVisible )
+ ImplInvertFocus( *(mpWinData->mpFocusRect) );
+ if ( mbTrackVisible && (mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(mpWinData->mpTrackRect), mpWinData->mnTrackFlags );
+ }
+ mbInPaint = FALSE;
+ mbInitClipRegion = TRUE;
+ mpPaintRegion = NULL;
+ if ( mpCursor )
+ mpCursor->ImplShow( FALSE );
+ }
+ }
+ else
+ mnPaintFlags = 0;
+
+ if ( nPaintFlags & (IMPL_PAINT_PAINTALLCHILDS | IMPL_PAINT_PAINTCHILDS) )
+ {
+ // die Childfenster ausgeben
+ Window* pTempWindow = mpFirstChild;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->mbVisible )
+ pTempWindow->ImplCallPaint( pChildRegion, nPaintFlags );
+ pTempWindow = pTempWindow->mpNext;
+ }
+ }
+
+ if ( pChildRegion )
+ delete pChildRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallOverlapPaint()
+{
+ // Zuerst geben wir die ueberlappenden Fenster aus
+ Window* pTempWindow = mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->mbReallyVisible )
+ pTempWindow->ImplCallOverlapPaint();
+ pTempWindow = pTempWindow->mpNext;
+ }
+
+ // und dann erst uns selber
+ if ( mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ ImplCallPaint( NULL, mnPaintFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplPostPaint()
+{
+ if ( !mpFrameData->maPaintTimer.IsActive() )
+ mpFrameData->maPaintTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplHandlePaintHdl, void*, EMPTYARG )
+{
+ if ( mbReallyVisible )
+ ImplCallOverlapPaint();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateFrameRegion( const Region* pRegion, USHORT nFlags )
+{
+ // PAINTCHILDS bei allen Parent-Fenster bis zum ersten OverlapWindow
+ // setzen
+ if ( !ImplIsOverlapWindow() )
+ {
+ Window* pTempWindow = this;
+ do
+ {
+ pTempWindow = pTempWindow->ImplGetParent();
+ if ( pTempWindow->mnPaintFlags & IMPL_PAINT_PAINTCHILDS )
+ break;
+ pTempWindow->mnPaintFlags |= IMPL_PAINT_PAINTCHILDS;
+ }
+ while ( !pTempWindow->ImplIsOverlapWindow() );
+ }
+
+ // Paint-Flags setzen
+ mnPaintFlags |= IMPL_PAINT_PAINT;
+ if ( nFlags & INVALIDATE_CHILDREN )
+ mnPaintFlags |= IMPL_PAINT_PAINTALLCHILDS;
+ if ( !(nFlags & INVALIDATE_NOERASE) )
+ mnPaintFlags |= IMPL_PAINT_ERASE;
+ if ( !pRegion )
+ mnPaintFlags |= IMPL_PAINT_PAINTALL;
+
+ // Wenn nicht alles neu ausgegeben werden muss, dann die Region
+ // dazupacken
+ if ( !(mnPaintFlags & IMPL_PAINT_PAINTALL) )
+ maInvalidateRegion.Union( *pRegion );
+
+ ImplPostPaint();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateOverlapFrameRegion( const Region& rRegion )
+{
+ Region aRegion = rRegion;
+ ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
+
+ // Dann invalidieren wir die ueberlappenden Fenster
+ Window* pTempWindow = mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( pTempWindow->IsVisible() )
+ pTempWindow->ImplInvalidateOverlapFrameRegion( rRegion );
+
+ pTempWindow = pTempWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateParentFrameRegion( Region& rRegion )
+{
+ if ( mbOverlapWin )
+ mpFrameWindow->ImplInvalidateOverlapFrameRegion( rRegion );
+ else
+ ImplGetParent()->ImplInvalidateFrameRegion( &rRegion, INVALIDATE_CHILDREN );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidate( const Region* pRegion, USHORT nFlags )
+{
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ // Feststellen, was neu ausgegeben werden muss
+ BOOL bInvalidateAll = !pRegion;
+
+ // Transparent-Invalidate beruecksichtigen
+ Window* pWindow = this;
+ if ( (mbPaintTransparent && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) )
+ {
+ Window* pTempWindow = pWindow->ImplGetParent();
+ while ( pTempWindow )
+ {
+ if ( !pTempWindow->IsPaintTransparent() )
+ {
+ pWindow = pTempWindow;
+ nFlags |= INVALIDATE_CHILDREN;
+ bInvalidateAll = FALSE;
+ break;
+ }
+
+ if ( pTempWindow->ImplIsOverlapWindow() )
+ break;
+
+ pTempWindow = pTempWindow->ImplGetParent();
+ }
+ }
+
+ // Region zusammenbauen
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (INVALIDATE_CHILDREN | INVALIDATE_NOCHILDREN)) )
+ {
+ if ( pWindow->GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= INVALIDATE_NOCHILDREN;
+ else
+ nFlags |= INVALIDATE_CHILDREN;
+ }
+ if ( (nFlags & INVALIDATE_NOCHILDREN) && pWindow->mpFirstChild )
+ bInvalidateAll = FALSE;
+ if ( bInvalidateAll )
+ pWindow->ImplInvalidateFrameRegion( NULL, nFlags );
+ else
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ if ( pRegion )
+ aRegion.Intersect( *pRegion );
+ pWindow->ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( nFlags & INVALIDATE_NOCHILDREN )
+ {
+ nFlags &= ~INVALIDATE_CHILDREN;
+ if ( !(nFlags & INVALIDATE_NOCLIPCHILDREN) )
+ {
+ if ( nOrgFlags & INVALIDATE_NOCHILDREN )
+ pWindow->ImplClipAllChilds( aRegion );
+ else
+ {
+ if ( pWindow->ImplClipChilds( aRegion ) )
+ nFlags |= INVALIDATE_CHILDREN;
+ }
+ }
+ }
+ if ( !aRegion.IsEmpty() )
+ pWindow->ImplInvalidateFrameRegion( &aRegion, nFlags );
+ }
+
+ if ( nFlags & INVALIDATE_UPDATE )
+ pWindow->Update();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplMoveInvalidateRegion( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll,
+ BOOL bChilds )
+{
+ if ( (mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALL)) == IMPL_PAINT_PAINT )
+ {
+ Region aTempRegion = maInvalidateRegion;
+ aTempRegion.Intersect( rRect );
+ aTempRegion.Move( nHorzScroll, nVertScroll );
+ maInvalidateRegion.Union( aTempRegion );
+ }
+
+ if ( bChilds && (mnPaintFlags & IMPL_PAINT_PAINTCHILDS) )
+ {
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ pWindow->ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, TRUE );
+ pWindow = pWindow->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplMoveAllInvalidateRegions( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll,
+ BOOL bChilds )
+{
+ // Paint-Region auch verschieben, wenn noch Paints anstehen
+ ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, bChilds );
+ // Paint-Region muss bei uns verschoben gesetzt werden, die durch
+ // die Parents gezeichnet werden
+ if ( !ImplIsOverlapWindow() )
+ {
+ Region aPaintAllRegion;
+ Window* pPaintAllWindow = this;
+ do
+ {
+ pPaintAllWindow = pPaintAllWindow->ImplGetParent();
+ if ( pPaintAllWindow->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ {
+ if ( pPaintAllWindow->mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ aPaintAllRegion.SetEmpty();
+ break;
+ }
+ else
+ aPaintAllRegion.Union( pPaintAllWindow->maInvalidateRegion );
+ }
+ }
+ while ( !pPaintAllWindow->ImplIsOverlapWindow() );
+ if ( !aPaintAllRegion.IsEmpty() )
+ {
+ aPaintAllRegion.Move( nHorzScroll, nVertScroll );
+ USHORT nPaintFlags = 0;
+ if ( bChilds )
+ mnPaintFlags |= INVALIDATE_CHILDREN;
+ ImplInvalidateFrameRegion( &aPaintAllRegion, nPaintFlags );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplValidateFrameRegion( const Region* pRegion, USHORT nFlags )
+{
+ if ( !pRegion )
+ maInvalidateRegion.SetEmpty();
+ else
+ {
+ // Wenn alle Childfenster neu ausgegeben werden muessen,
+ // dann invalidieren wir diese vorher
+ if ( (mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS) && mpFirstChild )
+ {
+ Region aChildRegion = maInvalidateRegion;
+ if ( mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ aChildRegion = aRect;
+ }
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->Invalidate( aChildRegion, INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ pChild = pChild->mpNext;
+ }
+ }
+ if ( mnPaintFlags & IMPL_PAINT_PAINTALL )
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ maInvalidateRegion = aRect;
+ }
+ maInvalidateRegion.Exclude( *pRegion );
+ }
+ mnPaintFlags &= ~IMPL_PAINT_PAINTALL;
+
+ if ( nFlags & VALIDATE_CHILDREN )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplValidateFrameRegion( pRegion, nFlags );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplValidate( const Region* pRegion, USHORT nFlags )
+{
+ // Region zusammenbauen
+ BOOL bValidateAll = !pRegion;
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (VALIDATE_CHILDREN | VALIDATE_NOCHILDREN)) )
+ {
+ if ( GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= VALIDATE_NOCHILDREN;
+ else
+ nFlags |= VALIDATE_CHILDREN;
+ }
+ if ( (nFlags & VALIDATE_NOCHILDREN) && mpFirstChild )
+ bValidateAll = FALSE;
+ if ( bValidateAll )
+ ImplValidateFrameRegion( NULL, nFlags );
+ else
+ {
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ if ( pRegion )
+ aRegion.Intersect( *pRegion );
+ ImplClipBoundaries( aRegion, TRUE, TRUE );
+ if ( nFlags & VALIDATE_NOCHILDREN )
+ {
+ nFlags &= ~VALIDATE_CHILDREN;
+ if ( nOrgFlags & VALIDATE_NOCHILDREN )
+ ImplClipAllChilds( aRegion );
+ else
+ {
+ if ( ImplClipChilds( aRegion ) )
+ nFlags |= VALIDATE_CHILDREN;
+ }
+ }
+ if ( !aRegion.IsEmpty() )
+ ImplValidateFrameRegion( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplScroll( const Rectangle& rRect,
+ long nHorzScroll, long nVertScroll, USHORT nFlags )
+{
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ nHorzScroll = ImplLogicWidthToDevicePixel( nHorzScroll );
+ nVertScroll = ImplLogicHeightToDevicePixel( nVertScroll );
+
+ if ( !nHorzScroll && !nVertScroll )
+ return;
+
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ if ( mpCursor )
+ mpCursor->ImplHide();
+
+ USHORT nOrgFlags = nFlags;
+ if ( !(nFlags & (SCROLL_CHILDREN | SCROLL_NOCHILDREN)) )
+ {
+ if ( GetStyle() & WB_CLIPCHILDREN )
+ nFlags |= SCROLL_NOCHILDREN;
+ else
+ nFlags |= SCROLL_CHILDREN;
+ }
+
+ Region aInvalidateRegion;
+ BOOL bScrollChilds = (nFlags & SCROLL_CHILDREN) != 0;
+ BOOL bErase = (nFlags & SCROLL_NOERASE) == 0;
+
+ if ( !mpFirstChild )
+ bScrollChilds = FALSE;
+
+ // Paint-Bereiche anpassen
+ ImplMoveAllInvalidateRegions( rRect, nHorzScroll, nVertScroll, bScrollChilds );
+
+ if ( !(nFlags & SCROLL_NOINVALIDATE) )
+ {
+ ImplCalcOverlapRegion( rRect, aInvalidateRegion, !bScrollChilds, TRUE, FALSE );
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ aInvalidateRegion.Move( nHorzScroll, nVertScroll );
+ bErase = TRUE;
+ }
+ if ( !(nFlags & SCROLL_NOWINDOWINVALIDATE) )
+ {
+ Rectangle aDestRect( rRect );
+ aDestRect.Move( nHorzScroll, nVertScroll );
+ Region aWinInvalidateRegion( rRect );
+ aWinInvalidateRegion.Exclude( aDestRect );
+ aInvalidateRegion.Union( aWinInvalidateRegion );
+ }
+ }
+
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ if ( nFlags & SCROLL_CLIP )
+ aRegion.Intersect( rRect );
+ if ( mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+ aRegion.Exclude( aInvalidateRegion );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !bScrollChilds )
+ {
+ if ( nOrgFlags & SCROLL_NOCHILDREN )
+ ImplClipAllChilds( aRegion );
+ else
+ ImplClipChilds( aRegion );
+ }
+ if ( mbClipRegion && (nFlags & SCROLL_USECLIPREGION) )
+ aRegion.Intersect( maRegion );
+ if ( !aRegion.IsEmpty() )
+ {
+ if ( mpWinData )
+ {
+ if ( mbFocusVisible )
+ ImplInvertFocus( *(mpWinData->mpFocusRect) );
+ if ( mbTrackVisible && (mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(mpWinData->mpTrackRect), mpWinData->mnTrackFlags );
+ }
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics = ImplGetFrameGraphics();
+ if ( pGraphics )
+ {
+ ImplSelectClipRegion( pGraphics, aRegion );
+ pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll,
+ rRect.Left(), rRect.Top(),
+ rRect.GetWidth(), rRect.GetHeight(),
+ SAL_COPYAREA_WINDOWINVALIDATE );
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics( TRUE );
+ if ( pGraphics )
+ {
+ pGraphics->SetClipRegion( aRegion );
+ pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll,
+ rRect.Left(), rRect.Top(),
+ rRect.GetWidth(), rRect.GetHeight(),
+ COPYAREA_WINDOWINVALIDATE );
+ }
+#endif
+
+ if ( mpWinData )
+ {
+ if ( mbFocusVisible )
+ ImplInvertFocus( *(mpWinData->mpFocusRect) );
+ if ( mbTrackVisible && (mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(mpWinData->mpTrackRect), mpWinData->mnTrackFlags );
+ }
+ }
+
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ USHORT nPaintFlags = INVALIDATE_CHILDREN;
+ if ( !bErase )
+ nPaintFlags |= INVALIDATE_NOERASE;
+ if ( !bScrollChilds )
+ {
+ if ( nOrgFlags & SCROLL_NOCHILDREN )
+ ImplClipAllChilds( aInvalidateRegion );
+ else
+ ImplClipChilds( aInvalidateRegion );
+ }
+ ImplInvalidateFrameRegion( &aInvalidateRegion, nPaintFlags );
+ }
+
+ if ( bScrollChilds )
+ {
+ Rectangle aDestRect( rRect );
+ Window* pWindow = mpFirstChild;
+ while ( pWindow )
+ {
+ Rectangle aWinRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ if ( aDestRect.IsOver( aWinRect ) )
+ {
+ pWindow->mnX += nHorzScroll;
+ pWindow->maPos.X() += nHorzScroll;
+ pWindow->mnY += nVertScroll;
+ pWindow->maPos.Y() += nVertScroll;
+#ifndef REMOTE_APPSERVER
+ if ( pWindow->ImplUpdatePos() )
+ pWindow->ImplUpdateSysObjPos();
+#else
+ pWindow->ImplUpdatePos();
+#endif
+ if ( pWindow->IsReallyVisible() )
+ pWindow->ImplSetClipFlag();
+ if ( pWindow->mpClientWindow )
+ pWindow->mpClientWindow->maPos = pWindow->maPos;
+ if ( pWindow->IsVisible() )
+ {
+ pWindow->mbCallMove = FALSE;
+ pWindow->Move();
+ }
+ else
+ pWindow->mbCallMove = TRUE;
+ }
+ pWindow = pWindow->mpNext;
+ }
+ }
+
+ if ( nFlags & SCROLL_UPDATE )
+ Update();
+
+ if ( mpCursor )
+ mpCursor->ImplShow( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateAll( BOOL bOverlapWindows )
+{
+ if ( !mbReallyVisible )
+ return;
+
+ BOOL bFlush = FALSE;
+ if ( mpFrameWindow->mbPaintFrame )
+ {
+ Point aPoint( 0, 0 );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ ImplInvalidateOverlapFrameRegion( aRegion );
+ if ( mbFrame || (mpBorderWindow && mpBorderWindow->mbFrame) )
+ bFlush = TRUE;
+ }
+
+ // Ein Update wirkt immer auf das OverlapWindow, damit bei spaeteren
+ // Paints nicht zuviel gemalt wird, wenn dort ALLCHILDREN usw. gesetzt
+ // ist
+ Window* pWindow = ImplGetFirstOverlapWindow();
+ if ( bOverlapWindows )
+ pWindow->ImplCallOverlapPaint();
+ else
+ {
+ if ( pWindow->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ pWindow->ImplCallPaint( NULL, pWindow->mnPaintFlags );
+ }
+
+ if ( bFlush )
+ Flush();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateWindowPtr( Window* pWindow )
+{
+ if ( mpFrameWindow != pWindow->mpFrameWindow )
+ {
+ // Graphic freigeben
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+#else
+ ImplReleaseServerGraphics();
+ mpGraphics = pWindow->mpFrameWindow->mpGraphics;
+#endif
+ }
+
+ mpFrameData = pWindow->mpFrameData;
+ mpFrame = pWindow->mpFrame;
+ mpFrameWindow = pWindow->mpFrameWindow;
+ if ( pWindow->ImplIsOverlapWindow() )
+ mpOverlapWindow = pWindow;
+ else
+ mpOverlapWindow = pWindow->mpOverlapWindow;
+
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateWindowPtr( pWindow );
+ pChild = pChild->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateWindowPtr()
+{
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateWindowPtr( this );
+ pChild = pChild->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplUpdateOverlapWindowPtr( BOOL bNewFrame )
+{
+ BOOL bVisible = IsVisible();
+ Show( FALSE );
+ ImplRemoveWindow( bNewFrame );
+ Window* pRealParent = mpRealParent;
+ ImplInsertWindow( ImplGetParent() );
+ mpRealParent = pRealParent;
+ ImplUpdateWindowPtr();
+#ifndef REMOTE_APPSERVER
+ if ( ImplUpdatePos() )
+ ImplUpdateSysObjPos();
+#else
+ ImplUpdatePos();
+#endif
+
+ if ( bNewFrame )
+ {
+ Window* pOverlapWindow = mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpNext;
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+ }
+
+ if ( bVisible )
+ Show( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplUpdatePos()
+{
+ BOOL bSysChild = FALSE;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ mnOutOffX = mnX;
+ mnOutOffY = mnY;
+ }
+ else
+ {
+ Window* pParent = ImplGetParent();
+ mnOutOffX = mnX+pParent->mnOutOffX;
+ mnOutOffY = mnY+pParent->mnOutOffY;
+ }
+
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ if ( pChild->ImplUpdatePos() )
+ bSysChild = TRUE;
+ pChild = pChild->mpNext;
+ }
+
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ bSysChild = TRUE;
+#endif
+
+ return bSysChild;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+void Window::ImplUpdateSysObjPos()
+{
+ if ( mpSysObj )
+ mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
+
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateSysObjPos();
+ pChild = pChild->mpNext;
+ }
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+/* --- RTL ---
+void Window::ImplAlignChilds()
+{
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplPosSizeWindow( pChild->maPos.X(), 0, 0, 0, WINDOW_POSSIZE_X );
+ pChild = pChild->mpNext;
+ }
+}
+*/
+
+// -----------------------------------------------------------------------
+
+void Window::ImplPosSizeWindow( long nX, long nY,
+ long nWidth, long nHeight, USHORT nFlags )
+{
+ BOOL bNewPos = FALSE;
+ BOOL bNewSize = FALSE;
+ BOOL bNewWidth = FALSE;
+ BOOL bCopyBits = FALSE;
+ long nOldOutOffX = mnOutOffX;
+ long nOldOutOffY = mnOutOffY;
+ long nOldOutWidth = mnOutWidth;
+ long nOldOutHeight = mnOutHeight;
+ Region* pOverlapRegion = NULL;
+ Region* pOldRegion = NULL;
+
+ if ( IsReallyVisible() )
+ {
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
+ Size( nOldOutWidth, nOldOutHeight ) );
+ pOldRegion = new Region( aOldWinRect );
+ if ( mbWinRegion )
+ pOldRegion->Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+
+ if ( mnOutWidth && mnOutHeight && !mbPaintTransparent &&
+ !mbInitWinClipRegion && !maWinClipRegion.IsEmpty() &&
+ !HasPaintEvent() )
+ bCopyBits = TRUE;
+ }
+
+ if ( nFlags & WINDOW_POSSIZE_WIDTH )
+ {
+ if ( nWidth < 0 )
+ nWidth = 0;
+ if ( nWidth != mnOutWidth )
+ {
+/* --- RTL ---
+ if ( !ImplIsOverlapWindow() )
+ {
+ if ( !(nFlags & WINDOW_POSSIZE_X) )
+ {
+ nFlags |= WINDOW_POSSIZE_X;
+ nX = mnX;
+ }
+ }
+*/
+ mnOutWidth = nWidth;
+ bNewSize = TRUE;
+ bCopyBits = FALSE;
+ bNewWidth = TRUE;
+ }
+ }
+ if ( nFlags & WINDOW_POSSIZE_HEIGHT )
+ {
+ if ( nHeight < 0 )
+ nHeight = 0;
+ if ( nHeight != mnOutHeight )
+ {
+ mnOutHeight = nHeight;
+ bNewSize = TRUE;
+ bCopyBits = FALSE;
+ }
+ }
+
+ if ( nFlags & WINDOW_POSSIZE_X )
+ {
+ if ( nX != mnX )
+ {
+ long nOrgX = nX;
+/* --- RTL ---
+ if ( !ImplIsOverlapWindow() )
+ nX = mpParent->mnOutWidth-mnOutWidth-nX;
+*/
+
+ if ( bCopyBits && !pOverlapRegion )
+ {
+ pOverlapRegion = new Region();
+ ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ *pOverlapRegion, FALSE, TRUE, TRUE );
+ }
+ mnX = nX;
+ maPos.X() = nOrgX;
+ bNewPos = TRUE;
+ }
+ }
+ if ( nFlags & WINDOW_POSSIZE_Y )
+ {
+ if ( nY != mnY )
+ {
+ if ( bCopyBits && !pOverlapRegion )
+ {
+ pOverlapRegion = new Region();
+ ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ *pOverlapRegion, FALSE, TRUE, TRUE );
+ }
+ mnY = nY;
+ maPos.Y() = nY;
+ bNewPos = TRUE;
+ }
+ }
+
+ if ( bNewPos || bNewSize )
+ {
+#ifndef REMOTE_APPSERVER
+ BOOL bUpdateSysObjPos = FALSE;
+ if ( bNewPos )
+ bUpdateSysObjPos = ImplUpdatePos();
+#else
+ if ( bNewPos )
+ ImplUpdatePos();
+#endif
+
+ if ( mpClientWindow )
+ {
+ mpClientWindow->ImplPosSizeWindow( mpClientWindow->mnLeftBorder,
+ mpClientWindow->mnTopBorder,
+ mnOutWidth-mpClientWindow->mnLeftBorder-mpClientWindow->mnRightBorder,
+ mnOutHeight-mpClientWindow->mnTopBorder-mpClientWindow->mnBottomBorder,
+ WINDOW_POSSIZE_X | WINDOW_POSSIZE_Y |
+ WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
+ // Wenn wir ein ClientWindow haben, dann hat dieses fuer die
+ // Applikation auch die Position des FloatingWindows
+ mpClientWindow->maPos = maPos;
+ if ( bNewPos )
+ {
+ if ( mpClientWindow->IsVisible() )
+ {
+ mpClientWindow->mbCallMove = FALSE;
+ mpClientWindow->Move();
+ }
+ else
+ mpClientWindow->mbCallMove = TRUE;
+ }
+ }
+ else
+ {
+ if ( mpBorderWindow )
+ maPos = mpBorderWindow->maPos;
+ }
+
+/* --- RTL ---
+ if ( bNewWidth && !ImplIsOverlapWindow() )
+ ImplAlignChilds();
+*/
+
+ // Move()/Resize() werden erst bei Show() gerufen, damit min. eins vor
+ // einem Show() kommt
+ if ( IsVisible() )
+ {
+ if ( bNewPos )
+ {
+ mbCallMove = FALSE;
+ Move();
+ }
+ if ( bNewSize )
+ {
+ mbCallResize = FALSE;
+ Resize();
+ }
+ }
+ else
+ {
+ if ( bNewPos )
+ mbCallMove = TRUE;
+ if ( bNewSize )
+ mbCallResize = TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ BOOL bUpdateSysObjClip = FALSE;
+#endif
+ if ( IsReallyVisible() )
+ {
+ if ( bNewPos || bNewSize )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpOverlapData && mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ // Clip-Flag neu setzen
+#ifndef REMOTE_APPSERVER
+ bUpdateSysObjClip = !ImplSetClipFlag( TRUE );
+#else
+ ImplSetClipFlag();
+#endif
+ }
+
+ // Fensterinhalt invalidieren ?
+ if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
+ {
+ if ( bNewPos )
+ {
+ BOOL bInvalidate = FALSE;
+ BOOL bParentPaint = TRUE;
+ if ( !ImplIsOverlapWindow() )
+ bParentPaint = mpParent->IsPaintEnabled();
+ if ( bCopyBits && bParentPaint && !HasPaintEvent() )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ if ( mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !pOverlapRegion->IsEmpty() )
+ {
+ pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
+ aRegion.Exclude( *pOverlapRegion );
+ }
+ if ( !aRegion.IsEmpty() )
+ {
+ // Paint-Bereiche anpassen
+ ImplMoveAllInvalidateRegions( Rectangle( Point( nOldOutOffX, nOldOutOffY ),
+ Size( nOldOutWidth, nOldOutHeight ) ),
+ mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
+ TRUE );
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics = ImplGetFrameGraphics();
+ if ( pGraphics )
+ {
+ BOOL bSelectClipRegion = ImplSelectClipRegion( pGraphics, aRegion );
+ if ( bSelectClipRegion )
+ {
+ pGraphics->CopyArea( mnOutOffX, mnOutOffY,
+ nOldOutOffX, nOldOutOffY,
+ nOldOutWidth, nOldOutHeight,
+ SAL_COPYAREA_WINDOWINVALIDATE );
+ }
+ else
+ bInvalidate = TRUE;
+ }
+ else
+ bInvalidate = TRUE;
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics( TRUE );
+ if ( pGraphics )
+ {
+ pGraphics->SetClipRegion( aRegion );
+ pGraphics->CopyArea( mnOutOffX, mnOutOffY,
+ nOldOutOffX, nOldOutOffY,
+ nOldOutWidth, nOldOutHeight,
+ COPYAREA_WINDOWINVALIDATE );
+ }
+ else
+ bInvalidate = TRUE;
+#endif
+ if ( !bInvalidate )
+ {
+ if ( !pOverlapRegion->IsEmpty() )
+ ImplInvalidateFrameRegion( pOverlapRegion, INVALIDATE_CHILDREN );
+ }
+ }
+ }
+ else
+ bInvalidate = TRUE;
+ if ( bInvalidate )
+ ImplInvalidateFrameRegion( NULL, INVALIDATE_CHILDREN );
+ }
+ else
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ aRegion.Exclude( *pOldRegion );
+ if ( mbWinRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( maWinRegion ) );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
+ }
+ }
+
+ // Parent oder Overlaps invalidieren
+ if ( bNewPos ||
+ (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
+ {
+ Region aRegion( *pOldRegion );
+ if ( !mbPaintTransparent )
+ ImplExcludeWindowRegion( aRegion );
+ ImplClipBoundaries( aRegion, FALSE, TRUE );
+ if ( !aRegion.IsEmpty() && !mpBorderWindow )
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+
+#ifndef REMOTE_APPSERVER
+ // System-Objekte anpassen
+ if ( bUpdateSysObjClip )
+ ImplUpdateSysObjClip();
+ if ( bUpdateSysObjPos )
+ ImplUpdateSysObjPos();
+ if ( bNewSize && mpSysObj )
+ mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
+#endif
+ }
+
+ if ( pOverlapRegion )
+ delete pOverlapRegion;
+ if ( pOldRegion )
+ delete pOldRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplToBottomChild()
+{
+ if ( !ImplIsOverlapWindow() && !mbReallyVisible && (mpParent->mpLastChild != this) )
+ {
+ // Fenster an das Ende der Liste setzen
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpParent->mpFirstChild = mpNext;
+ mpNext->mpPrev = mpPrev;
+ mpPrev = mpParent->mpLastChild;
+ mpParent->mpLastChild = this;
+ mpPrev->mpNext = this;
+ mpNext = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcToTop( ImplCalcToTopData* pPrevData )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplCalcToTop(): Is not a OverlapWindow" );
+
+ if ( !mbFrame )
+ {
+ if ( IsReallyVisible() )
+ {
+ // Region berechnen, wo das Fenster mit anderen Fenstern ueberlappt
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ Region aInvalidateRegion;
+ ImplCalcOverlapRegionOverlaps( aRegion, aInvalidateRegion );
+
+ if ( !aInvalidateRegion.IsEmpty() )
+ {
+ ImplCalcToTopData* pData = new ImplCalcToTopData;
+ pPrevData->mpNext = pData;
+ pData->mpNext = NULL;
+ pData->mpWindow = this;
+ pData->mpInvalidateRegion = new Region( aInvalidateRegion );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCalcChildOverlapToTop( ImplCalcToTopData* pPrevData )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplCalcChildOverlapToTop(): Is not a OverlapWindow" );
+
+ ImplCalcToTop( pPrevData );
+ if ( pPrevData->mpNext )
+ pPrevData = pPrevData->mpNext;
+
+ Window* pOverlap = mpFirstOverlap;
+ while ( pOverlap )
+ {
+ pOverlap->ImplCalcToTop( pPrevData );
+ if ( pPrevData->mpNext )
+ pPrevData = pPrevData->mpNext;
+ pOverlap = pOverlap->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplToTop( USHORT nFlags )
+{
+ DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplToTop(): Is not a OverlapWindow" );
+
+ if ( mbFrame )
+ {
+ // Wenn in das externe Fenster geklickt wird, ist dieses
+ // dafuer zustaendig dafuer zu sorgen, das unser Frame
+ // nach vorne kommt
+ if ( !mpFrameData->mbHasFocus &&
+ !mpFrameData->mbSysObjFocus &&
+ !mpFrameData->mbInSysObjFocusHdl &&
+ !mpFrameData->mbInSysObjToTopHdl )
+ {
+#ifndef REMOTE_APPSERVER
+ USHORT nSysFlags = 0;
+ if ( nFlags & TOTOP_RESTOREWHENMIN )
+ nSysFlags = SAL_FRAME_TOTOP_RESTOREWHENMIN;
+ if ( nFlags & TOTOP_FOREGROUNDTASK )
+ nSysFlags = SAL_FRAME_TOTOP_FOREGROUNDTASK;
+ mpFrame->ToTop( nSysFlags );
+#else
+ mpFrame->ToTop( nFlags );
+#endif
+ }
+ }
+ else
+ {
+ if ( mpOverlapWindow->mpFirstOverlap != this )
+ {
+ // Fenster aus der Liste entfernen
+ mpPrev->mpNext = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpOverlapWindow->mpLastOverlap = mpPrev;
+
+ // AlwaysOnTop beruecksichtigen
+ BOOL bOnTop = IsAlwaysOnTopEnabled();
+ Window* pNextWin = mpOverlapWindow->mpFirstOverlap;
+ if ( !bOnTop )
+ {
+ while ( pNextWin )
+ {
+ if ( !pNextWin->IsAlwaysOnTopEnabled() )
+ break;
+ pNextWin = pNextWin->mpNext;
+ }
+ }
+
+ // TopLevel abpruefen
+ BYTE nTopLevel = mpOverlapData->mnTopLevel;
+ while ( pNextWin )
+ {
+ if ( (bOnTop != pNextWin->IsAlwaysOnTopEnabled()) ||
+ (nTopLevel <= pNextWin->mpOverlapData->mnTopLevel) )
+ break;
+ pNextWin = pNextWin->mpNext;
+ }
+
+ // Fenster in die Liste wieder eintragen
+ mpNext = pNextWin;
+ if ( pNextWin )
+ {
+ mpPrev = pNextWin->mpPrev;
+ pNextWin->mpPrev = this;
+ }
+ else
+ {
+ mpPrev = mpOverlapWindow->mpLastOverlap;
+ mpOverlapWindow->mpLastOverlap = this;
+ }
+ if ( mpPrev )
+ mpPrev->mpNext = this;
+ else
+ mpOverlapWindow->mpFirstOverlap = this;
+
+ // ClipRegion muss von diesem Fenster und allen weiteren
+ // ueberlappenden Fenstern neu berechnet werden.
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ mpOverlapWindow->ImplSetClipFlagOverlapWindows();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplStartToTop( USHORT nFlags )
+{
+ ImplCalcToTopData aStartData;
+ ImplCalcToTopData* pCurData;
+ ImplCalcToTopData* pNextData;
+ Window* pOverlapWindow;
+ if ( ImplIsOverlapWindow() )
+ pOverlapWindow = this;
+ else
+ pOverlapWindow = mpOverlapWindow;
+
+ // Zuerst die Paint-Bereiche berechnen
+ Window* pTempOverlapWindow = pOverlapWindow;
+ aStartData.mpNext = NULL;
+ pCurData = &aStartData;
+ do
+ {
+ pTempOverlapWindow->ImplCalcToTop( pCurData );
+ if ( pCurData->mpNext )
+ pCurData = pCurData->mpNext;
+ pTempOverlapWindow = pTempOverlapWindow->mpOverlapWindow;
+ }
+ while ( !pTempOverlapWindow->mbFrame );
+ // Dann die Paint-Bereiche der ChildOverlap-Windows berechnen
+ pTempOverlapWindow = mpFirstOverlap;
+ while ( pTempOverlapWindow )
+ {
+ pTempOverlapWindow->ImplCalcToTop( pCurData );
+ if ( pCurData->mpNext )
+ pCurData = pCurData->mpNext;
+ pTempOverlapWindow = pTempOverlapWindow->mpNext;
+ }
+
+ // Dann die Fenster-Verkettung aendern
+ pTempOverlapWindow = pOverlapWindow;
+ do
+ {
+ pTempOverlapWindow->ImplToTop( nFlags );
+ pTempOverlapWindow = pTempOverlapWindow->mpOverlapWindow;
+ }
+ while ( !pTempOverlapWindow->mbFrame );
+ // Und zum Schluss invalidieren wir die ungueltigen Bereiche
+ pCurData = aStartData.mpNext;
+ while ( pCurData )
+ {
+ pCurData->mpWindow->ImplInvalidateFrameRegion( pCurData->mpInvalidateRegion, INVALIDATE_CHILDREN );
+ pNextData = pCurData->mpNext;
+ delete pCurData->mpInvalidateRegion;
+ delete pCurData;
+ pCurData = pNextData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplFocusToTop( USHORT nFlags, BOOL bReallyVisible )
+{
+ // Soll Focus auch geholt werden?
+ if ( !(nFlags & TOTOP_NOGRABFOCUS) )
+ {
+ // Erstes Fenster mit GrabFocus-Activate bekommt den Focus
+ Window* pFocusWindow = this;
+ while ( !pFocusWindow->ImplIsOverlapWindow() )
+ {
+ // Nur wenn Fenster kein Border-Fenster hat, da wir
+ // immer das dazugehoerende BorderFenster finden wollen
+ if ( !pFocusWindow->mpBorderWindow )
+ {
+ if ( pFocusWindow->mnActivateMode & ACTIVATE_MODE_GRABFOCUS )
+ break;
+ }
+ pFocusWindow = pFocusWindow->ImplGetParent();
+ }
+ if ( (pFocusWindow->mnActivateMode & ACTIVATE_MODE_GRABFOCUS) &&
+ !pFocusWindow->HasChildPathFocus( TRUE ) )
+ pFocusWindow->GrabFocus();
+ }
+
+ if ( bReallyVisible )
+ ImplGenerateMouseMove();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplShowAllOverlaps()
+{
+ Window* pOverlapWindow = mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ if ( pOverlapWindow->mbOverlapVisible )
+ {
+ pOverlapWindow->Show( TRUE, SHOW_NOACTIVATE );
+ pOverlapWindow->mbOverlapVisible = FALSE;
+ }
+
+ pOverlapWindow = pOverlapWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplHideAllOverlaps()
+{
+ Window* pOverlapWindow = mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ if ( pOverlapWindow->IsVisible() )
+ {
+ pOverlapWindow->mbOverlapVisible = TRUE;
+ pOverlapWindow->Show( FALSE );
+ }
+
+ pOverlapWindow = pOverlapWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallMouseMove( USHORT nMouseCode, BOOL bModChanged )
+{
+ if ( mpFrameData->mbMouseIn && mpFrameWindow->mbReallyVisible )
+ {
+ ULONG nTime = Time::GetSystemTicks();
+ long nX = mpFrameData->mnLastMouseX;
+ long nY = mpFrameData->mnLastMouseY;
+ USHORT nCode = nMouseCode;
+ USHORT nMode = mpFrameData->mnMouseMode;
+ BOOL bLeave;
+ // Auf MouseLeave testen
+ if ( ((nX < 0) || (nY < 0) ||
+ (nX >= mpFrameWindow->mnOutWidth) ||
+ (nY >= mpFrameWindow->mnOutHeight)) &&
+ !ImplGetSVData()->maWinData.mpCaptureWin )
+ bLeave = TRUE;
+ else
+ bLeave = FALSE;
+ nMode |= MOUSE_SYNTHETIC;
+ if ( bModChanged )
+ nMode |= MOUSE_MODIFIERCHANGED;
+ ImplHandleMouseEvent( mpFrameWindow, EVENT_MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplGenerateMouseMove()
+{
+ if ( !mpFrameData->mnMouseMoveId )
+ Application::PostUserEvent( mpFrameData->mnMouseMoveId, LINK( mpFrameWindow, Window, ImplGenerateMouseMoveHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplGenerateMouseMoveHdl, void*, EMPTYARG )
+{
+ mpFrameData->mnMouseMoveId = 0;
+ ImplCallMouseMove( mpFrameData->mnMouseCode );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvertFocus( const Rectangle& rRect )
+{
+ InvertTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallFocusChangeActivate( Window* pNewOverlapWindow,
+ Window* pOldOverlapWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pNewRealWindow;
+ Window* pOldRealWindow;
+ Window* pLastRealWindow;
+ BOOL bCallActivate = TRUE;
+ BOOL bCallDeactivate = TRUE;
+
+ pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
+ pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
+ if ( (pOldRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
+ pOldRealWindow->GetActivateMode() )
+ {
+ if ( (pNewRealWindow->GetType() == WINDOW_FLOATINGWINDOW) &&
+ !pNewRealWindow->GetActivateMode() )
+ {
+ pSVData->maWinData.mpLastDeacWin = pOldOverlapWindow;
+ bCallDeactivate = FALSE;
+ }
+ }
+ else if ( (pNewRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
+ pNewRealWindow->GetActivateMode() )
+ {
+ if ( pSVData->maWinData.mpLastDeacWin )
+ {
+ if ( pSVData->maWinData.mpLastDeacWin == pNewOverlapWindow )
+ bCallActivate = FALSE;
+ else
+ {
+ pLastRealWindow = pSVData->maWinData.mpLastDeacWin->ImplGetWindow();
+ pSVData->maWinData.mpLastDeacWin->mbActive = FALSE;
+ pSVData->maWinData.mpLastDeacWin->Deactivate();
+ if ( pLastRealWindow != pSVData->maWinData.mpLastDeacWin )
+ {
+ pLastRealWindow->mbActive = TRUE;
+ pLastRealWindow->Activate();
+ }
+ }
+ pSVData->maWinData.mpLastDeacWin = NULL;
+ }
+ }
+
+ if ( bCallDeactivate )
+ {
+ pOldOverlapWindow->mbActive = FALSE;
+ pOldOverlapWindow->Deactivate();
+ if ( pOldRealWindow != pOldOverlapWindow )
+ {
+ pOldRealWindow->mbActive = FALSE;
+ pOldRealWindow->Deactivate();
+ }
+ }
+ if ( bCallActivate )
+ {
+ pNewOverlapWindow->mbActive = TRUE;
+ pNewOverlapWindow->Activate();
+ if ( pNewRealWindow != pNewOverlapWindow )
+ {
+ pNewRealWindow->mbActive = TRUE;
+ pNewRealWindow->Activate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplGrabFocus( USHORT nFlags )
+{
+ // Es soll immer das Client-Fenster den Focus bekommen. Falls
+ // wir mal auch Border-Fenstern den Focus geben wollen,
+ // muessten wir bei allen GrabFocus()-Aufrufen in VCL dafuer
+ // sorgen, das es an der Stelle gemacht wird. Dies wuerde
+ // beispielsweise bei ToTop() der Fall sein.
+ if ( mpClientWindow )
+ {
+ // Wegen nicht ganz durchdachtem Konzept muessen wir hier
+ // leider noch einen Hack einbauen, damit wenn Dialoge
+ // geschlossen werden der Focus wieder auf das richtige
+ // Fenster zurueckgesetzt wird
+ if ( mpLastFocusWindow && (mpLastFocusWindow != this) &&
+ !(mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
+ mpLastFocusWindow->IsEnabled() )
+ mpLastFocusWindow->GrabFocus();
+ else
+ mpClientWindow->GrabFocus();
+ return;
+ }
+ else if ( mbFrame )
+ {
+ // Wegen nicht ganz durchdachtem Konzept muessen wir hier
+ // leider noch einen Hack einbauen, damit wenn Dialoge
+ // geschlossen werden der Focus wieder auf das richtige
+ // Fenster zurueckgesetzt wird
+ if ( mpLastFocusWindow && (mpLastFocusWindow != this) &&
+ !(mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
+ mpLastFocusWindow->IsEnabled() )
+ {
+ mpLastFocusWindow->GrabFocus();
+ return;
+ }
+ }
+
+ // Wir brauchen Focus nur setzen, wenn es diesen noch nicht hat
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpFocusWin != this )
+ {
+ // Dieses Fenster als letztes FocusWindow merken
+ Window* pOverlapWindow = ImplGetFirstOverlapWindow();
+ pOverlapWindow->mpLastFocusWindow = this;
+ mpFrameData->mpFocusWin = this;
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpSysObj && !mpFrameData->mbHasFocus )
+#else
+ if ( !mpFrameData->mbHasFocus )
+#endif
+ {
+ // Hier setzen wir schon den Focus um, da ToTop() den Focus
+ // nicht auf ein anderes Fenster setzen darf
+ DBG_WARNING( "Window::GrabFocus() - Frame doesn't have the focus" );
+ mpFrame->ToTop( 0 );
+ return;
+ }
+
+ Window* pOldFocusWindow = pSVData->maWinData.mpFocusWin;
+ pSVData->maWinData.mpFocusWin = this;
+
+ if ( pOldFocusWindow )
+ {
+ // Cursor hiden
+ if ( pOldFocusWindow->mpCursor )
+ pOldFocusWindow->mpCursor->ImplHide();
+ }
+
+ // !!!!! Wegen altem SV-Office Activate/Deavtivate Handling
+ // !!!!! erstmal so wie frueher
+ if ( pOldFocusWindow )
+ {
+ // Focus merken
+ Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
+ Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ if ( pOldOverlapWindow != pNewOverlapWindow )
+ ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
+ }
+ else
+ {
+ Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
+ pNewOverlapWindow->mbActive = TRUE;
+ pNewOverlapWindow->Activate();
+ if ( pNewRealWindow != pNewOverlapWindow )
+ {
+ pNewRealWindow->mbActive = TRUE;
+ pNewRealWindow->Activate();
+ }
+ }
+/*
+ // call Deactivate and Activate
+ Window* pDeactivateParent;
+ Window* pActivateParent;
+ Window* pParent;
+ Window* pLastParent;
+ pDeactivateParent = pOldFocusWindow;
+ while ( pDeactivateParent )
+ {
+ pParent = pDeactivateParent;
+ if ( pParent->ImplIsChild( this ) )
+ break;
+
+ if ( pDeactivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pDeactivateParent->mbParentActive )
+ break;
+ }
+
+ pDeactivateParent = pDeactivateParent->ImplGetParent();
+ }
+ if ( pOldFocusWindow )
+ {
+ pActivateParent = this;
+ while ( pActivateParent )
+ {
+ pParent = pActivateParent;
+ if ( pParent->ImplIsChild( pOldFocusWindow ) )
+ break;
+
+ if ( pActivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pActivateParent->mbParentActive )
+ break;
+ }
+
+ pActivateParent = pActivateParent->ImplGetParent();
+ }
+ }
+ else
+ {
+ if ( ImplIsOverlapWindow() )
+ pActivateParent = this;
+ else
+ pActivateParent = mpOverlapWindow;
+ while ( pActivateParent )
+ {
+ if ( pActivateParent->ImplIsOverlapWindow() )
+ {
+ if ( !pActivateParent->mbParentActive )
+ break;
+ }
+
+ pActivateParent = pActivateParent->ImplGetParent();
+ }
+ }
+ if ( pDeactivateParent )
+ {
+ do
+ {
+ pLastParent = pOldFocusWindow;
+ if ( pLastParent != pDeactivateParent )
+ {
+ pParent = pLastParent->ImplGetParent();
+ while ( pParent )
+ {
+ if ( pParent == pDeactivateParent )
+ break;
+ pLastParent = pParent;
+ pParent = pParent->ImplGetParent();
+ }
+ }
+ else
+ pParent = pLastParent;
+
+ pParent->mbActive = FALSE;
+ pParent->Deactivate();
+ pDeactivateParent = pLastParent;
+ }
+ while ( pDeactivateParent != pOldFocusWindow );
+ }
+ do
+ {
+ pLastParent = this;
+ if ( pLastParent != pActivateParent )
+ {
+ pParent = pLastParent->ImplGetParent();
+ while ( pParent )
+ {
+ if ( pParent == pActivateParent )
+ break;
+ pLastParent = pParent;
+ pParent = pParent->ImplGetParent();
+ }
+ }
+ else
+ pParent = pLastParent;
+
+ pParent->mbActive = TRUE;
+ pParent->Activate();
+ pActivateParent = pLastParent;
+ }
+ while ( pActivateParent != this );
+*/
+ // call Get- and LoseFocus
+ if ( pOldFocusWindow )
+ {
+ if ( pOldFocusWindow->IsTracking() &&
+ (pSVData->maWinData.mnTrackFlags & STARTTRACK_FOCUSCANCEL) )
+ pOldFocusWindow->EndTracking( ENDTRACK_CANCEL | ENDTRACK_FOCUS );
+ pOldFocusWindow->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, pOldFocusWindow );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ pOldFocusWindow->LoseFocus();
+ pOldFocusWindow->ImplCallDeactivateListeners( this );
+ }
+
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ {
+ mpFrameData->mpFocusWin = this;
+ if ( !mpFrameData->mbInSysObjFocusHdl )
+ mpSysObj->GrabFocus();
+ }
+#endif
+
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ if ( mpCursor )
+ mpCursor->ImplShow();
+ mbInFocusHdl = TRUE;
+ mnGetFocusFlags = nFlags;
+ NotifyEvent aNEvt( EVENT_GETFOCUS, this );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ GetFocus();
+ ImplCallActivateListeners( pOldFocusWindow );
+ mnGetFocusFlags = 0;
+ mbInFocusHdl = FALSE;
+ }
+ }
+
+ GetpApp()->FocusChanged();
+ ImplNewInputContext();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplNewInputContext()
+{
+#ifndef REMOTE_APPSERVER
+ SalInputContext aNewContext;
+ const InputContext& rInputContext = GetInputContext();
+ const Font& rFont = rInputContext.GetFont();
+ const XubString& rFontName = rFont.GetName();
+ ImplFontEntry* pFontEntry = NULL;
+ if ( rFontName.Len() )
+ {
+ Size aSize = ImplLogicToDevicePixel( rFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // Nur dann Defaultgroesse setzen, wenn Fonthoehe auch in logischen
+ // Koordinaaten 0 ist
+ if ( rFont.GetSize().Height() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*mnDPIY)/72;
+ }
+ pFontEntry = mpFontCache->Get( mpFontList, rFont, aSize );
+ aNewContext.mpFont = &(mpFontEntry->maFontSelData);
+ }
+ else
+ aNewContext.mpFont = NULL;
+ aNewContext.meCharSet = rFont.GetCharSet();
+ aNewContext.meLanguage = rFont.GetLanguage();
+ aNewContext.mnOptions = rInputContext.GetOptions();
+ ImplGetFrame()->SetInputContext( &aNewContext );
+
+ if ( pFontEntry )
+ mpFontCache->Release( pFontEntry );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( WindowType nType ) :
+ maZoom( 1, 1 ),
+ maWinRegion( REGION_NULL ),
+ maWinClipRegion( REGION_NULL )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitData( nType );
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( Window* pParent, WinBits nStyle ) :
+ maZoom( 1, 1 ),
+ maWinRegion( REGION_NULL ),
+ maWinClipRegion( REGION_NULL )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitData( WINDOW_WINDOW );
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Window::Window( Window* pParent, const ResId& rResId ) :
+ maZoom( 1, 1 ),
+ maWinRegion( REGION_NULL ),
+ maWinClipRegion( REGION_NULL )
+{
+ DBG_CTOR( Window, ImplDbgCheckWindow );
+
+ ImplInitData( WINDOW_WINDOW );
+ rResId.SetRT( RSC_WINDOW );
+ WinBits nStyle = ImplInitRes( rResId );
+ ImplInit( pParent, nStyle, NULL );
+ ImplLoadRes( rResId );
+
+ if ( !(nStyle & WB_HIDE) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+Window::~Window()
+{
+ DBG_DTOR( Window, ImplDbgCheckWindow );
+
+ mbInDtor = TRUE;
+
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ pWrapper->WindowDestroyed( this );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
+ ImplDestroyHelpWindow( FALSE );
+
+ DBG_ASSERT( pSVData->maWinData.mpTrackWin != this,
+ "Window::~Window(): Window is in TrackingMode" );
+ DBG_ASSERT( pSVData->maWinData.mpCaptureWin != this,
+ "Window::~Window(): Window has the mouse captured" );
+ DBG_ASSERT( pSVData->maWinData.mpDefDialogParent != this,
+ "Window::~Window(): Window is DefModalDialogParent" );
+
+ // Wegen alter kompatibilitaet
+ if ( pSVData->maWinData.mpTrackWin == this )
+ EndTracking();
+ if ( pSVData->maWinData.mpCaptureWin == this )
+ ReleaseMouse();
+ if ( pSVData->maWinData.mpDefDialogParent == this )
+ pSVData->maWinData.mpDefDialogParent = NULL;
+
+#ifdef DBG_UTIL
+ if ( DbgIsAssert() )
+ {
+ ByteString aErrorStr;
+ BOOL bError = FALSE;
+ Window* pTempWin = mpFrameData->mpFirstOverlap;
+ while ( pTempWin )
+ {
+ if ( ImplIsRealParentPath( pTempWin ) )
+ {
+ bError = TRUE;
+ if ( aErrorStr.Len() )
+ aErrorStr += "; ";
+ aErrorStr += ByteString( pTempWin->GetText(), RTL_TEXTENCODING_UTF8 );
+ }
+ pTempWin = pTempWin->mpNextOverlap;
+ }
+ if ( bError )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living SystemWindow(s) destroyed: ";
+ aTempStr += aErrorStr;
+ DBG_ERROR( aTempStr.GetBuffer() );
+ }
+
+ if ( mpFirstChild )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living Child(s) destroyed: ";
+ Window* pTempWin = mpFirstChild;
+ while ( pTempWin )
+ {
+ aTempStr += ByteString( pTempWin->GetText(), RTL_TEXTENCODING_UTF8 );
+ pTempWin = pTempWin->mpNext;
+ if ( pTempWin )
+ aTempStr += "; ";
+ }
+ DBG_ERROR( aTempStr.GetBuffer() );
+ }
+
+ if ( mpFirstOverlap )
+ {
+ ByteString aTempStr( "Window (" );
+ aTempStr += ByteString( GetText(), RTL_TEXTENCODING_UTF8 );
+ aTempStr += ") with living SystemWindow(s) destroyed: ";
+ Window* pTempWin = mpFirstOverlap;
+ while ( pTempWin )
+ {
+ aTempStr += ByteString( pTempWin->GetText(), RTL_TEXTENCODING_UTF8 );
+ pTempWin = pTempWin->mpNext;
+ if ( pTempWin )
+ aTempStr += "; ";
+ }
+ DBG_ERROR( aTempStr.GetBuffer() );
+ }
+ }
+#endif
+
+ // Fenster hiden, um das entsprechende Paint-Handling auszuloesen
+ Hide();
+
+ // Mitteilen, das Fenster zerstoert wird
+ {
+ NotifyEvent aNEvt( EVENT_DESTROY, this );
+ Notify( aNEvt );
+ }
+
+ // Wenn wir den Focus haben, dann den Focus auf ein anderes Fenster setzen
+ Window* pOverlapWindow = ImplGetFirstOverlapWindow();
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ if ( mbFrame )
+ {
+ pSVData->maWinData.mpFocusWin = NULL;
+ pOverlapWindow->mpLastFocusWindow = NULL;
+ GetpApp()->FocusChanged();
+ }
+ else
+ {
+ Window* pParent = GetParent();
+ Window* pBorderWindow = mpBorderWindow;
+ // Bei ueberlappenden Fenstern wird der Focus auf den
+ // Parent vom naechsten FrameWindow gesetzt
+ if ( pBorderWindow )
+ {
+ if ( pBorderWindow->ImplIsOverlapWindow() )
+ pParent = pBorderWindow->mpOverlapWindow;
+ }
+ else if ( ImplIsOverlapWindow() )
+ pParent = mpOverlapWindow;
+ if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() )
+ pParent->GrabFocus();
+ else
+ mpFrameWindow->GrabFocus();
+ // Falls der Focus wieder auf uns gesetzt wurde, dann wird er
+ // auf nichts gesetzt
+ if ( pSVData->maWinData.mpFocusWin == this )
+ {
+ pSVData->maWinData.mpFocusWin = NULL;
+ pOverlapWindow->mpLastFocusWindow = NULL;
+ GetpApp()->FocusChanged();
+ }
+ }
+ }
+ if ( pOverlapWindow->mpLastFocusWindow == this )
+ pOverlapWindow->mpLastFocusWindow = NULL;
+
+ // gemerkte Fenster zuruecksetzen
+ if ( mpFrameData->mpFocusWin == this )
+ mpFrameData->mpFocusWin = NULL;
+ if ( mpFrameData->mpMouseMoveWin == this )
+ mpFrameData->mpMouseMoveWin = NULL;
+ if ( mpFrameData->mpMouseDownWin == this )
+ mpFrameData->mpMouseDownWin = NULL;
+
+ // Deactivate-Window zuruecksetzen
+ if ( pSVData->maWinData.mpLastDeacWin == this )
+ pSVData->maWinData.mpLastDeacWin = NULL;
+
+#ifdef REMOTE_APPSERVER
+ {
+ // Events als ungueltig markieren...
+ VOS_NAMESPACE(OGuard,vos) aGuard( pSVData->mpWindowObjectMutex );
+ if ( mpRmEvents )
+ {
+ ExtRmEvent* p = mpRmEvents;
+ while ( p )
+ {
+ p->MarkInvalid();
+ p = p->GetNextWindowEvent();
+ }
+ }
+ }
+#endif
+
+ if ( mbFrame )
+ {
+#ifndef REMOTE_APPSERVER
+ DragManager::SystemEnableDrop( mpFrame, FALSE);
+#endif
+ if ( mpFrameData->mnFocusId )
+ Application::RemoveUserEvent( mpFrameData->mnFocusId );
+ if ( mpFrameData->mnMouseMoveId )
+ Application::RemoveUserEvent( mpFrameData->mnMouseMoveId );
+ }
+
+ // Graphic freigeben
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+#else
+ ImplReleaseServerGraphics();
+#endif
+
+ // Evt. anderen Funktion mitteilen, das das Fenster geloescht
+ // wurde
+ ImplDelData* pDelData = mpFirstDel;
+ while ( pDelData )
+ {
+ pDelData->mbDel = TRUE;
+ pDelData = pDelData->mpNext;
+ }
+
+ // Fenster aus den Listen austragen
+ ImplRemoveWindow( TRUE );
+
+ // Extra Window Daten loeschen
+ if ( mpWinData )
+ {
+ if ( mpWinData->mpExtPosAry )
+ delete [] mpWinData->mpExtPosAry;
+ if ( mpWinData->mpFocusRect )
+ delete mpWinData->mpFocusRect;
+ if ( mpWinData->mpTrackRect )
+ delete mpWinData->mpTrackRect;
+ delete mpWinData;
+ }
+
+ // Overlap-Window-Daten loeschen
+ if ( mpOverlapData )
+ {
+ delete mpOverlapData;
+ }
+
+ // Evt. noch BorderWindow oder Frame zerstoeren
+ if ( mpBorderWindow )
+ delete mpBorderWindow;
+ else if ( mbFrame )
+ {
+ if ( pSVData->maWinData.mpFirstFrame == this )
+ pSVData->maWinData.mpFirstFrame = mpFrameData->mpNextFrame;
+ else
+ {
+ Window* pSysWin = pSVData->maWinData.mpFirstFrame;
+ while ( pSysWin->mpFrameData->mpNextFrame != this )
+ pSysWin = pSysWin->mpFrameData->mpNextFrame;
+ pSysWin->mpFrameData->mpNextFrame = mpFrameData->mpNextFrame;
+ }
+#ifndef REMOTE_APPSERVER
+ mpFrame->SetCallback( NULL, NULL );
+ pSVData->mpDefInst->DestroyFrame( mpFrame );
+#else
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+ delete mpFrame;
+#endif
+ if ( mpFrameData->mpDragTimer )
+ delete mpFrameData->mpDragTimer;
+ delete mpFrameData;
+#ifdef REMOTE_APPSERVER
+ delete mpGraphics;
+#endif
+ }
+
+ if ( mpChildClipRegion )
+ delete mpChildClipRegion;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseMove( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEMOVE, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mbMouseMove = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEBUTTONDOWN, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mbMouseButtonDown = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_MOUSEBUTTONUP, this, &rMEvt );
+ if ( !Notify( aNEvt ) )
+ mbMouseButtonUp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::KeyInput( const KeyEvent& rKEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_KEYINPUT, this, &rKEvt );
+ if ( !Notify( aNEvt ) )
+ mbKeyInput = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::KeyUp( const KeyEvent& rKEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_KEYUP, this, &rKEvt );
+ if ( !Notify( aNEvt ) )
+ mbKeyUp = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Paint( const Rectangle& rRect )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Paint( this, rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Draw( OutputDevice*, const Point&, const Size&, ULONG )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Move()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Move( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Resize()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Resize( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Activate()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Deactivate()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetFocus()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( HasFocus() && mpLastFocusWindow && !(mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
+ mpLastFocusWindow->GrabFocus();
+
+ NotifyEvent aNEvt( EVENT_GETFOCUS, this );
+ Notify( aNEvt );
+
+ if ( Application::GetAccessHdlCount() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_GETFOCUS, this ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::LoseFocus()
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, this );
+ Notify( aNEvt );
+
+ if ( Application::GetAccessHdlCount() )
+ Application::AccessNotify( AccessNotification( ACCESS_EVENT_LOSEFOCUS, this ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RequestHelp( const HelpEvent& rHEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ // Wenn Balloon-Help angefordert wird, dann den Balloon mit dem
+ // gesetzten Hilfetext anzeigen
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ const XubString* pStr = &(GetHelpText());
+ if ( !pStr->Len() )
+ pStr = &(GetQuickHelpText());
+ if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), *pStr );
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ const XubString* pStr = &(GetQuickHelpText());
+ if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ {
+ Point aPos = GetPosPixel();
+ if ( ImplGetParent() && !ImplIsOverlapWindow() )
+ aPos = ImplGetParent()->OutputToScreenPixel( aPos );
+ Rectangle aRect( aPos, GetSizePixel() );
+ String aHelpText;
+ if ( pStr->Len() )
+ aHelpText = GetHelpText();
+ Help::ShowQuickHelp( this, aRect, *pStr, aHelpText, QUICKHELP_CTRLTEXT );
+ }
+ }
+ else
+ {
+ ULONG nStartHelpId = GetHelpId();
+
+ if ( !nStartHelpId && ImplGetParent() )
+ ImplGetParent()->RequestHelp( rHEvt );
+ else
+ {
+ if ( !nStartHelpId )
+ nStartHelpId = HELP_INDEX;
+
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nStartHelpId );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Command( const CommandEvent& rCEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Command( this, rCEvt );
+
+ NotifyEvent aNEvt( EVENT_COMMAND, this, &rCEvt );
+ if ( !Notify( aNEvt ) )
+ mbCommand = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Tracking( const TrackingEvent& )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::QueryDrop( DropEvent& rDEvt )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ NotifyEvent aNEvt( EVENT_QUERYDROP, this, &rDEvt, FALSE );
+ Notify( aNEvt );
+ return (BOOL)aNEvt.GetReturnValue();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::Drop( const DropEvent& rDEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ NotifyEvent aNEvt( EVENT_DROP, this, &rDEvt, FALSE );
+ Notify( aNEvt );
+ return (BOOL)aNEvt.GetReturnValue();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::UserEvent( ULONG, void* )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StateChanged( StateChangedType )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::DataChanged( const DataChangedEvent& )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::PreNotify( NotifyEvent& rNEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ BOOL bDone = FALSE;
+ if ( mpParent && !ImplIsOverlapWindow() )
+ bDone = mpParent->PreNotify( rNEvt );
+
+ if ( !bDone )
+ {
+ if( rNEvt.GetType() == EVENT_GETFOCUS )
+ {
+ BOOL bCompoundFocusChanged = FALSE;
+ if ( mbCompoundControl && !mbCompoundControlHasFocus && HasChildPathFocus() )
+ {
+ mbCompoundControlHasFocus = TRUE;
+ bCompoundFocusChanged = TRUE;
+ }
+
+ if ( mxWindowPeer.is() && ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) ) )
+ Application::GetUnoWrapper()->WindowEvent_GetFocus( this );
+ }
+ else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ {
+ BOOL bCompoundFocusChanged = FALSE;
+ if ( mbCompoundControl && mbCompoundControlHasFocus && !HasChildPathFocus() )
+ {
+ mbCompoundControlHasFocus = FALSE ;
+ bCompoundFocusChanged = TRUE;
+ }
+
+ if ( mxWindowPeer.is() && ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) ) )
+ Application::GetUnoWrapper()->WindowEvent_LoseFocus( this );
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEMOVE )
+ {
+ if ( mxWindowPeer.is() && ( mbCompoundControl || ( rNEvt.GetWindow() == this ) ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ Application::GetUnoWrapper()->WindowEvent_MouseMove( this, *rNEvt.GetMouseEvent() );
+ else
+ Application::GetUnoWrapper()->WindowEvent_MouseMove( this, ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONUP )
+ {
+ if ( mxWindowPeer.is() && ( mbCompoundControl || ( rNEvt.GetWindow() == this ) ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ Application::GetUnoWrapper()->WindowEvent_MouseButtonUp( this, *rNEvt.GetMouseEvent() );
+ else
+ Application::GetUnoWrapper()->WindowEvent_MouseButtonUp( this, ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( mxWindowPeer.is() && ( mbCompoundControl || ( rNEvt.GetWindow() == this ) ) )
+ {
+ if ( rNEvt.GetWindow() == this )
+ Application::GetUnoWrapper()->WindowEvent_MouseButtonDown( this, *rNEvt.GetMouseEvent() );
+ else
+ Application::GetUnoWrapper()->WindowEvent_MouseButtonDown( this, ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this ) );
+ }
+ }
+ else if( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ if ( mxWindowPeer.is() && ( mbCompoundControl || ( rNEvt.GetWindow() == this ) ) )
+ Application::GetUnoWrapper()->WindowEvent_KeyInput( this, *rNEvt.GetKeyEvent() );
+ }
+ else if( rNEvt.GetType() == EVENT_KEYUP )
+ {
+ if ( mxWindowPeer.is() && ( mbCompoundControl || ( rNEvt.GetWindow() == this ) ) )
+ Application::GetUnoWrapper()->WindowEvent_KeyUp( this, *rNEvt.GetKeyEvent() );
+ }
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::Notify( NotifyEvent& rNEvt )
+{
+ { // Klammerung, da in diesem Handler das Window zerstoert werden darf
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ }
+
+ long nRet = FALSE;
+
+ // Dialog-Steuerung
+ if ( (GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
+ {
+ // Wenn Parent auch DialogSteuerung aktiviert hat, uebernimmt dieser die Steuerung
+ if ( (rNEvt.GetType() == EVENT_KEYINPUT) || (rNEvt.GetType() == EVENT_KEYUP) )
+ {
+ if ( ImplIsOverlapWindow() ||
+ ((ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
+ {
+ nRet = ImplDlgCtrl( *rNEvt.GetKeyEvent(), rNEvt.GetType() == EVENT_KEYINPUT );
+ }
+ }
+ else if ( (rNEvt.GetType() == EVENT_GETFOCUS) || (rNEvt.GetType() == EVENT_LOSEFOCUS) )
+ {
+ ImplDlgCtrlFocusChanged( rNEvt.GetWindow(), rNEvt.GetType() == EVENT_GETFOCUS );
+ if ( (rNEvt.GetWindow() == this) && (rNEvt.GetType() == EVENT_GETFOCUS) &&
+ !(GetStyle() & WB_TABSTOP) && !(mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
+ {
+ USHORT n = 0;
+ Window* pFirstChild = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
+ if ( pFirstChild )
+ pFirstChild->ImplControlFocus();
+ }
+ }
+ }
+
+ if ( !nRet )
+ {
+ if ( mpParent && !ImplIsOverlapWindow() )
+ nRet = mpParent->Notify( rNEvt );
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::PostUserEvent( ULONG nEvent, void* pEventData )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, nEvent, pEventData );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::PostUserEvent( const Link& rLink, void* pCaller )
+{
+ ULONG nEventId;
+ PostUserEvent( nEventId, rLink, pCaller );
+ return nEventId;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::PostUserEvent( ULONG& rEventId, ULONG nEvent, void* pEventData )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = nEvent;
+ pSVEvent->mpData = pEventData;
+ pSVEvent->mpLink = NULL;
+ pSVEvent->mpWindow = this;
+ pSVEvent->mbCall = TRUE;
+ ImplAddDel( &(pSVEvent->maDelData) );
+ rEventId = (ULONG)pSVEvent;
+#ifndef REMOTE_APPSERVER
+ if ( mpFrame->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ ImplRemoveDel( &(pSVEvent->maDelData) );
+ delete pSVEvent;
+ return FALSE;
+ }
+#else
+ ExtRmEvent* pEvt = new ExtRmEvent( RMEVENT_USEREVENT, NULL, pSVEvent );
+ ImplPostEvent( pEvt );
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::PostUserEvent( ULONG& rEventId, const Link& rLink, void* pCaller )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = new ImplSVEvent;
+ pSVEvent->mnEvent = 0;
+ pSVEvent->mpData = pCaller;
+ pSVEvent->mpLink = new Link( rLink );
+ pSVEvent->mpWindow = this;
+ pSVEvent->mbCall = TRUE;
+ ImplAddDel( &(pSVEvent->maDelData) );
+ rEventId = (ULONG)pSVEvent;
+#ifndef REMOTE_APPSERVER
+ if ( mpFrame->PostEvent( pSVEvent ) )
+ return TRUE;
+ else
+ {
+ rEventId = 0;
+ ImplRemoveDel( &(pSVEvent->maDelData) );
+ delete pSVEvent;
+ return FALSE;
+ }
+#else
+ ExtRmEvent* pEvt = new ExtRmEvent( RMEVENT_USEREVENT, NULL, pSVEvent );
+ ImplPostEvent( pEvt );
+ return TRUE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::RemoveUserEvent( ULONG nUserEvent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVEvent* pSVEvent = (ImplSVEvent*)nUserEvent;
+
+ DBG_ASSERT( pSVEvent->mpWindow == this,
+ "Window::RemoveUserEvent(): Event doesn't send to this window or is already removed" );
+ DBG_ASSERT( pSVEvent->mbCall,
+ "Window::RemoveUserEvent(): Event is already removed" );
+
+ if ( pSVEvent->mpWindow )
+ {
+ pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
+ pSVEvent->mpWindow = NULL;
+ }
+
+ pSVEvent->mbCall = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplAsyncStateChangedHdl, void*, pState )
+{
+ StateChanged( (StateChangedType)(ULONG)pState );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::PostStateChanged( StateChangedType nState )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ PostUserEvent( LINK( this, Window, ImplAsyncStateChangedHdl ), (void*)(ULONG)nState );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetStyle( WinBits nStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mnStyle != nStyle )
+ {
+ mnPrevStyle = mnStyle;
+ mnStyle = nStyle;
+ StateChanged( STATE_CHANGE_STYLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetExtendedStyle( WinBits nExtendedStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mnExtendedStyle != nExtendedStyle )
+ {
+ mnPrevExtendedStyle = mnExtendedStyle;
+ mnExtendedStyle = nExtendedStyle;
+ StateChanged( STATE_CHANGE_EXTENDEDSTYLE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+SystemWindow* Window::GetSystemWindow() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Window* pWin = this;
+ while ( !pWin->IsSystemWindow() )
+ pWin = pWin->GetParent();
+ return (SystemWindow*)pWin;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetBorderStyle( USHORT nBorderStyle )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ if ( mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ ((ImplBorderWindow*)mpBorderWindow)->SetBorderStyle( nBorderStyle );
+ else
+ mpBorderWindow->SetBorderStyle( nBorderStyle );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetBorderStyle() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ if ( mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ return ((ImplBorderWindow*)mpBorderWindow)->GetBorderStyle();
+ else
+ return mpBorderWindow->GetBorderStyle();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::CalcTitleWidth() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ if ( mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
+ return ((ImplBorderWindow*)mpBorderWindow)->CalcTitleWidth();
+ else
+ return mpBorderWindow->CalcTitleWidth();
+ }
+ else if ( mbFrame && (mnStyle & WB_MOVEABLE) )
+ {
+ // Fuer Frame-Fenster raten wir die Breite, da wir den Border fuer
+ // externe Dialoge nicht kennen
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Font aFont = GetFont();
+ ((Window*)this)->SetPointFont( rStyleSettings.GetTitleFont() );
+ long nTitleWidth = GetTextWidth( GetText() );
+ ((Window*)this)->SetFont( aFont );
+ nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
+ nTitleWidth += rStyleSettings.GetBorderSize() * 2;
+ nTitleWidth += 10;
+ return nTitleWidth;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableClipSiblings( BOOL bClipSiblings )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->EnableClipSiblings( bClipSiblings );
+
+ mbClipSiblings = bClipSiblings;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetMouseTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetMouseTransparent( bTransparent );
+
+ mbMouseTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPaintTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetPaintTransparent( bTransparent );
+
+ mbPaintTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetInputContext( const InputContext& rInputContext )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ maInputContext = rInputContext;
+ if ( !mbInFocusHdl && HasFocus() )
+ ImplNewInputContext();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::UpdateExtTextInputArea()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+#ifndef REMOTE_APPSERVER
+ if ( mbExtTextInput )
+ ImplGetFrame()->UpdateExtTextInputArea();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndExtTextInput( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+#ifndef REMOTE_APPSERVER
+ if ( mbExtTextInput )
+ ImplGetFrame()->EndExtTextInput( nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetExtTextInputPos( USHORT nStart, USHORT nCount, const Rectangle* pPosAry )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( pWinData->mpExtPosAry )
+ delete [] pWinData->mpExtPosAry;
+ if ( nCount )
+ {
+ pWinData->mpExtPosAry = new Rectangle[nCount];
+ pWinData->mnExtPosStart = nStart;
+ pWinData->mnExtPosCount = nCount;
+ memcpy( pWinData->mpExtPosAry, pPosAry, nCount*sizeof( Rectangle ) );
+ }
+ else
+ pWinData->mpExtPosAry = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+const Rectangle* Window::GetExtTextInputPosAry() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ return pWinData->mpExtPosAry;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetExtTextInputPosStart() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ return pWinData->mnExtPosStart;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetExtTextInputPosCount() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+ return pWinData->mnExtPosCount;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetSettings( const AllSettings& rSettings, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->SetSettings( rSettings, FALSE );
+ if ( (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow->SetSettings( rSettings, TRUE );
+ }
+
+ AllSettings aOldSettings = maSettings;
+ OutputDevice::SetSettings( rSettings );
+ ULONG nChangeFlags = aOldSettings.GetChangeFlags( rSettings );
+ if ( nChangeFlags )
+ {
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
+ DataChanged( aDCEvt );
+ }
+
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ ImplInitResolutionSettings();
+
+ if ( bChild || mbChildNotify )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->SetSettings( rSettings, bChild );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::UpdateSettings( const AllSettings& rSettings, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->UpdateSettings( rSettings, FALSE );
+ if ( (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow->UpdateSettings( rSettings, TRUE );
+ }
+
+ AllSettings aOldSettings = maSettings;
+ ULONG nChangeFlags = maSettings.Update( maSettings.GetWindowUpdate(), rSettings );
+ if ( nChangeFlags )
+ {
+ DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
+ DataChanged( aDCEvt );
+ }
+
+ // AppFont-Aufloesung und DPI-Aufloesung neu berechnen
+ ImplInitResolutionSettings();
+
+ if ( bChild || mbChildNotify )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->UpdateSettings( rSettings, bChild );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::NotifyAllChilds( DataChangedEvent& rDCEvt )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ DataChanged( rDCEvt );
+
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->NotifyAllChilds( rDCEvt );
+ pChild = pChild->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = rFont;
+ ImplPointToLogic( aFont );
+ SetFont( aFont );
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetPointFont() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = GetFont();
+ ImplLogicToPoint( aFont );
+ return aFont;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetFontResolution( long& nDPIX, long& nDPIY ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ nDPIX = mpFrameData->mnFontDPIX;
+ nDPIY = mpFrameData->mnFontDPIY;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetParentClipMode( USHORT nMode )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetParentClipMode( nMode );
+ else
+ {
+ if ( !ImplIsOverlapWindow() )
+ {
+ mnParentClipMode = nMode;
+ if ( nMode & PARENTCLIPMODE_CLIP )
+ mpParent->mbClipChildren = TRUE;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetParentClipMode() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ return mpBorderWindow->GetParentClipMode();
+ else
+ return mnParentClipMode;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowRegionPixel()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetWindowRegionPixel();
+ else
+ {
+ if ( mbWinRegion )
+ {
+ maWinRegion = Region( REGION_NULL );
+ mbWinRegion = FALSE;
+ ImplSetClipFlag();
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpOverlapData && mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowRegionPixel( const Region& rRegion )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetWindowRegionPixel( rRegion );
+ else
+ {
+ BOOL bInvalidate = FALSE;
+
+ if ( rRegion.GetType() == REGION_NULL )
+ {
+ if ( mbWinRegion )
+ {
+ maWinRegion = Region( REGION_NULL );
+ mbWinRegion = FALSE;
+ ImplSetClipFlag();
+ bInvalidate = TRUE;
+ }
+ }
+ else
+ {
+ maWinRegion = rRegion;
+ mbWinRegion = TRUE;
+ ImplSetClipFlag();
+ bInvalidate = TRUE;
+ }
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpOverlapData && mpOverlapData->mpSaveBackDev )
+ ImplDeleteOverlapBackground();
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+ Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aRegion( aRect );
+ ImplInvalidateParentFrameRegion( aRegion );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+const Region& Window::GetWindowRegionPixel() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ return mpBorderWindow->GetWindowRegionPixel();
+ else
+ return maWinRegion;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsWindowRegionPixel() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ return mpBorderWindow->IsWindowRegionPixel();
+ else
+ return mbWinRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Region Window::GetWindowClipRegionPixel( USHORT nFlags ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Region aWinClipRegion;
+
+ if ( nFlags & WINDOW_GETCLIPREGION_NOCHILDREN )
+ {
+ if ( mbInitWinClipRegion )
+ ((Window*)this)->ImplInitWinClipRegion();
+ aWinClipRegion = maWinClipRegion;
+ }
+ else
+ {
+ Region* pWinChildClipRegion = ((Window*)this)->ImplGetWinChildClipRegion();
+ aWinClipRegion = *pWinChildClipRegion;
+ }
+
+ if ( nFlags & WINDOW_GETCLIPREGION_NULL )
+ {
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Region aWinRegion( aWinRect );
+
+ if ( aWinRegion == aWinClipRegion )
+ aWinClipRegion.SetNull();
+ }
+
+ aWinClipRegion.Move( -mnOutOffX, -mnOutOffY );
+
+ return aWinClipRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Region Window::GetPaintRegion() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpPaintRegion )
+ {
+ Region aRegion = *mpPaintRegion;
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+ return PixelToLogic( aRegion );
+ }
+ else
+ {
+ Region aPaintRegion( REGION_NULL );
+ return aPaintRegion;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetParent( Window* pNewParent )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_ASSERT( pNewParent, "Window::SetParent(): pParent == NULL" );
+
+ if ( mbFrame )
+ return;
+
+ if ( mpBorderWindow )
+ {
+ mpRealParent = pNewParent;
+ mpBorderWindow->SetParent( pNewParent );
+ return;
+ }
+
+ if ( mpParent == pNewParent )
+ return;
+
+ BOOL bVisible = IsVisible();
+ Show( FALSE, SHOW_NOFOCUSCHANGE );
+
+ // Testen, ob sich das Overlap-Window aendert
+ Window* pOldOverlapWindow;
+ Window* pNewOverlapWindow;
+ if ( ImplIsOverlapWindow() )
+ pOldOverlapWindow = NULL;
+ else
+ {
+ pNewOverlapWindow = pNewParent->ImplGetFirstOverlapWindow();
+ if ( mpOverlapWindow != pNewOverlapWindow )
+ pOldOverlapWindow = mpOverlapWindow;
+ else
+ pOldOverlapWindow = NULL;
+ }
+
+ // Fenster in der Hirachie umsetzen
+ BOOL bFocusOverlapWin = HasChildPathFocus( TRUE );
+ BOOL bFocusWin = HasChildPathFocus();
+ BOOL bNewFrame = pNewParent->mpFrameWindow != mpFrameWindow;
+ if ( bNewFrame )
+ {
+ if ( mpFrameData->mpFocusWin )
+ {
+ if ( IsWindowOrChild( mpFrameData->mpFocusWin ) )
+ mpFrameData->mpFocusWin = NULL;
+ }
+ if ( mpFrameData->mpMouseMoveWin )
+ {
+ if ( IsWindowOrChild( mpFrameData->mpMouseMoveWin ) )
+ mpFrameData->mpMouseMoveWin = NULL;
+ }
+ if ( mpFrameData->mpMouseDownWin )
+ {
+ if ( IsWindowOrChild( mpFrameData->mpMouseDownWin ) )
+ mpFrameData->mpMouseDownWin = NULL;
+ }
+ }
+ ImplRemoveWindow( bNewFrame );
+ ImplInsertWindow( pNewParent );
+ if ( mnParentClipMode & PARENTCLIPMODE_CLIP )
+ pNewParent->mbClipChildren = TRUE;
+ ImplUpdateWindowPtr();
+#ifndef REMOTE_APPSERVER
+ if ( ImplUpdatePos() )
+ ImplUpdateSysObjPos();
+#else
+ ImplUpdatePos();
+#endif
+
+ // Wenn sich das Overlap-Window geaendert hat, dann muss getestet werden,
+ // ob auch OverlapWindow die das Child-Fenster als Parent gehabt haben
+ // in der Window-Hirachie umgesetzt werden muessen
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( bNewFrame )
+ {
+ Window* pOverlapWindow = mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpNext;
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+ }
+ }
+ else if ( pOldOverlapWindow )
+ {
+ // Focus-Save zuruecksetzen
+ if ( bFocusWin ||
+ (pOldOverlapWindow->mpLastFocusWindow &&
+ IsWindowOrChild( pOldOverlapWindow->mpLastFocusWindow )) )
+ pOldOverlapWindow->mpLastFocusWindow = NULL;
+
+ Window* pOverlapWindow = pOldOverlapWindow->mpFirstOverlap;
+ while ( pOverlapWindow )
+ {
+ Window* pNextOverlapWindow = pOverlapWindow->mpNext;
+ if ( ImplIsRealParentPath( pOverlapWindow->ImplGetWindow() ) )
+ pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
+ pOverlapWindow = pNextOverlapWindow;
+ }
+
+ // Activate-Status beim naechsten Overlap-Window updaten
+ if ( HasChildPathFocus( TRUE ) )
+ ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
+ }
+
+ // Activate-Status mit umsetzen
+ if ( bNewFrame )
+ {
+ if ( (GetType() == WINDOW_BORDERWINDOW) &&
+ (ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
+ ((ImplBorderWindow*)this)->SetDisplayActive( mpFrameData->mbHasFocus );
+ }
+
+ // Focus evtl. auf den neuen Frame umsetzen, wenn FocusWindow mit
+ // SetParent() umgesetzt wird
+ if ( bFocusOverlapWin )
+ {
+ mpFrameData->mpFocusWin = Application::GetFocusWindow();
+ if ( !mpFrameData->mbHasFocus )
+ {
+ mpFrame->ToTop( 0 );
+ }
+ }
+
+ if ( bVisible )
+ Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Show( BOOL bVisible, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbVisible == bVisible )
+ return;
+
+ mbVisible = bVisible != 0;
+
+ if ( !bVisible )
+ {
+ ImplHideAllOverlaps();
+
+ if ( mpBorderWindow )
+ {
+ BOOL bOldUpdate = mpBorderWindow->mbNoParentUpdate;
+ if ( mbNoParentUpdate )
+ mpBorderWindow->mbNoParentUpdate = TRUE;
+ mpBorderWindow->Show( FALSE, nFlags );
+ mpBorderWindow->mbNoParentUpdate = bOldUpdate;
+ }
+ else if ( mbFrame )
+ mpFrame->Show( FALSE );
+
+ StateChanged( STATE_CHANGE_VISIBLE );
+
+ if ( mbReallyVisible )
+ {
+ Region aInvRegion( REGION_EMPTY );
+ BOOL bSaveBack = FALSE;
+
+ if ( ImplIsOverlapWindow() && !mbFrame )
+ {
+ if ( ImplRestoreOverlapBackground( aInvRegion ) )
+ bSaveBack = TRUE;
+ }
+
+ if ( !bSaveBack )
+ {
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+ aInvRegion = maWinClipRegion;
+ }
+
+ ImplResetReallyVisible();
+ ImplSetClipFlag();
+
+ if ( ImplIsOverlapWindow() && !mbFrame )
+ {
+ // Focus umsetzen
+ if ( !(nFlags & SHOW_NOFOCUSCHANGE) && HasChildPathFocus() )
+ {
+ if ( mpOverlapWindow->IsEnabled() && mpOverlapWindow->IsInputEnabled() )
+ mpOverlapWindow->GrabFocus();
+ }
+ }
+
+ if ( !mbFrame )
+ {
+ if ( !mbNoParentUpdate && !(nFlags & SHOW_NOPARENTUPDATE) )
+ {
+ if ( !aInvRegion.IsEmpty() )
+ ImplInvalidateParentFrameRegion( aInvRegion );
+ }
+ ImplGenerateMouseMove();
+ }
+ }
+ }
+ else
+ {
+ if ( mbCallMove )
+ {
+ mbCallMove = FALSE;
+ Move();
+ }
+ if ( mbCallResize )
+ {
+ mbCallResize = FALSE;
+ Resize();
+ }
+
+ StateChanged( STATE_CHANGE_VISIBLE );
+
+ Window* pTestParent;
+ if ( ImplIsOverlapWindow() )
+ pTestParent = mpOverlapWindow;
+ else
+ pTestParent = ImplGetParent();
+ if ( mbFrame || pTestParent->mbReallyVisible )
+ {
+ // Wenn ein Window gerade sichtbar wird, schicken wir allen
+ // Child-Fenstern ein StateChanged, damit diese sich
+ // initialisieren koennen
+ ImplCallInitShow();
+
+ // Wenn es ein SystemWindow ist, dann kommt es auch automatisch
+ // nach vorne, wenn es gewuenscht ist
+ if ( ImplIsOverlapWindow() && !(nFlags & SHOW_NOACTIVATE) )
+ {
+ ImplStartToTop( 0 );
+ ImplFocusToTop( 0, FALSE );
+ }
+
+ // Hintergrund sichern
+ if ( mpOverlapData && mpOverlapData->mbSaveBack )
+ ImplSaveOverlapBackground();
+ // Dafuer sorgen, das Clip-Rechtecke neu berechnet werden
+ ImplSetReallyVisible();
+ ImplSetClipFlag();
+
+ if ( !mbFrame )
+ {
+ ImplInvalidate( NULL, INVALIDATE_NOTRANSPARENT | INVALIDATE_CHILDREN );
+ ImplGenerateMouseMove();
+ }
+ }
+
+ if ( mpBorderWindow )
+ mpBorderWindow->Show( TRUE, nFlags );
+ else if ( mbFrame )
+ {
+ mbPaintFrame = TRUE;
+ mpFrame->Show( TRUE );
+
+ // Query the correct size of the window, if we are waiting for
+ // a system resize
+ if ( mbWaitSystemResize )
+ {
+ long nOutWidth;
+ long nOutHeight;
+ mpFrame->GetClientSize( nOutWidth, nOutHeight );
+ ImplHandleResize( this, nOutWidth, nOutHeight );
+ }
+ }
+
+#ifdef DBG_UTIL
+ if ( IsDialog() || (GetType() == WINDOW_TABPAGE) )
+ {
+ DBG_DIALOGTEST( this );
+ }
+#endif
+
+ ImplShowAllOverlaps();
+ }
+
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Show( this, mbVisible );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Enable( BOOL bEnable, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !bEnable )
+ {
+ // Wenn ein Fenster disablte wird, wird automatisch der Tracking-Modus
+ // beendet oder der Capture geklaut
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+ if ( IsMouseCaptured() )
+ ReleaseMouse();
+ // Wenn Fenster den Focus hat und in der Dialog-Steuerung enthalten,
+ // wird versucht, den Focus auf das naechste Control weiterzuschalten
+ // mbDisabled darf erst nach Aufruf von ImplDlgCtrlNextWindow() gesetzt
+ // werden. Ansonsten muss ImplDlgCtrlNextWindow() umgestellt werden
+ if ( HasFocus() )
+ ImplDlgCtrlNextWindow();
+ }
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->Enable( bEnable, FALSE );
+ if ( (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow->Enable( bEnable, TRUE );
+ }
+
+ if ( mbDisabled != !bEnable )
+ {
+ mbDisabled = !bEnable;
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ mpSysObj->Enable( bEnable && !mbInputDisabled );
+#endif
+// if ( mbFrame )
+// mpFrame->Enable( bEnable && !mbInputDisabled );
+ StateChanged( STATE_CHANGE_ENABLE );
+ }
+
+ if ( bChild || mbChildNotify )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->Enable( bEnable, bChild );
+ pChild = pChild->mpNext;
+ }
+ }
+
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableInput( BOOL bEnable, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->EnableInput( bEnable, FALSE );
+ if ( (mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow )
+ ((ImplBorderWindow*)mpBorderWindow)->mpMenuBarWindow->EnableInput( bEnable, TRUE );
+ }
+
+ if ( !mbAlwaysEnableInput || bEnable )
+ {
+ // Wenn ein Fenster disablte wird, wird automatisch der
+ // Tracking-Modus beendet oder der Capture geklaut
+ if ( !bEnable )
+ {
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+ if ( IsMouseCaptured() )
+ ReleaseMouse();
+ }
+
+ if ( mbInputDisabled != !bEnable )
+ {
+ mbInputDisabled = !bEnable;
+#ifndef REMOTE_APPSERVER
+ if ( mpSysObj )
+ mpSysObj->Enable( !mbDisabled && bEnable );
+#endif
+// if ( mbFrame )
+// mpFrame->Enable( !mbDisabled && bEnable );
+ }
+ }
+
+ if ( bChild || mbChildNotify )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->EnableInput( bEnable, bChild );
+ pChild = pChild->mpNext;
+ }
+ }
+
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableInput( BOOL bEnable, BOOL bChild, BOOL bSysWin,
+ const Window* pExcludeWindow )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ EnableInput( bEnable, bChild );
+ if ( bSysWin )
+ {
+ // pExculeWindow is the first Overlap-Frame --> if this
+ // shouldn't be the case, than this must be changed in dialog.cxx
+ pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
+ Window* pSysWin = mpFrameWindow->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ // Is Window in the path from this window
+ if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, TRUE ) )
+ {
+ // Is Window not in the exclude window path or not the
+ // exclude window, than change the status
+ if ( !pExcludeWindow->ImplIsWindowOrChild( pSysWin, TRUE ) )
+ pSysWin->EnableInput( bEnable, bChild );
+ }
+ pSysWin = pSysWin->mpNextOverlap;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::AlwaysEnableInput( BOOL bAlways, BOOL bChild )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->AlwaysEnableInput( bAlways, FALSE );
+
+ if ( mbAlwaysEnableInput != bAlways )
+ {
+ mbAlwaysEnableInput = bAlways;
+
+ if ( bAlways )
+ EnableInput( TRUE, FALSE );
+ }
+
+ if ( bChild || mbChildNotify )
+ {
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ pChild->AlwaysEnableInput( bAlways, bChild );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetActivateMode( USHORT nMode )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetActivateMode( nMode );
+
+ if ( mnActivateMode != nMode )
+ {
+ mnActivateMode = nMode;
+
+ // Evtl. ein Decativate/Activate ausloesen
+ if ( mnActivateMode )
+ {
+ if ( (mbActive || (GetType() == WINDOW_BORDERWINDOW)) &&
+ !HasChildPathFocus( TRUE ) )
+ {
+ mbActive = FALSE;
+ Deactivate();
+ }
+ }
+ else
+ {
+ if ( !mbActive || (GetType() == WINDOW_BORDERWINDOW) )
+ {
+ mbActive = TRUE;
+ Activate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ToTop( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplStartToTop( nFlags );
+ ImplFocusToTop( nFlags, IsReallyVisible() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZOrder( Window* pRefWindow, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->SetZOrder( pRefWindow, nFlags );
+ return;
+ }
+
+ if ( nFlags & WINDOW_ZORDER_FIRST )
+ {
+ if ( ImplIsOverlapWindow() )
+ pRefWindow = mpOverlapWindow->mpFirstOverlap;
+ else
+ pRefWindow = mpParent->mpFirstChild;
+ nFlags |= WINDOW_ZORDER_BEFOR;
+ }
+ else if ( nFlags & WINDOW_ZORDER_LAST )
+ {
+ if ( ImplIsOverlapWindow() )
+ pRefWindow = mpOverlapWindow->mpLastOverlap;
+ else
+ pRefWindow = mpParent->mpLastChild;
+ nFlags |= WINDOW_ZORDER_BEHIND;
+ }
+
+ while ( pRefWindow->mpBorderWindow )
+ pRefWindow = pRefWindow->mpBorderWindow;
+ if ( (pRefWindow == this) || mbFrame )
+ return;
+
+ DBG_ASSERT( pRefWindow->mpParent == mpParent, "Window::SetZOrder() - pRefWindow has other parent" );
+ if ( nFlags & WINDOW_ZORDER_BEFOR )
+ {
+ if ( pRefWindow->mpPrev == this )
+ return;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpOverlapWindow->mpFirstOverlap = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpOverlapWindow->mpLastOverlap = mpPrev;
+ if ( !pRefWindow->mpPrev )
+ mpOverlapWindow->mpFirstOverlap = this;
+ }
+ else
+ {
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpParent->mpFirstChild = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpParent->mpLastChild = mpPrev;
+ if ( !pRefWindow->mpPrev )
+ mpParent->mpFirstChild = this;
+ }
+
+ mpPrev = pRefWindow->mpPrev;
+ mpNext = pRefWindow;
+ if ( mpPrev )
+ mpPrev->mpNext = this;
+ mpNext->mpPrev = this;
+ }
+ else if ( nFlags & WINDOW_ZORDER_BEHIND )
+ {
+ if ( pRefWindow->mpNext == this )
+ return;
+
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpOverlapWindow->mpFirstOverlap = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpOverlapWindow->mpLastOverlap = mpPrev;
+ if ( !pRefWindow->mpNext )
+ mpOverlapWindow->mpLastOverlap = this;
+ }
+ else
+ {
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ mpParent->mpFirstChild = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ mpParent->mpLastChild = mpPrev;
+ if ( !pRefWindow->mpNext )
+ mpParent->mpLastChild = this;
+ }
+
+ mpPrev = pRefWindow;
+ mpNext = pRefWindow->mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = this;
+ mpPrev->mpNext = this;
+ }
+
+ if ( IsReallyVisible() )
+ {
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( mpFrameData->mpFirstBackWin )
+ ImplInvalidateAllOverlapBackgrounds();
+
+ if ( mbInitWinClipRegion || !maWinClipRegion.IsEmpty() )
+ {
+ BOOL bInitWinClipRegion = mbInitWinClipRegion;
+ ImplSetClipFlag();
+
+ // Wenn ClipRegion noch nicht initalisiert wurde, dann
+ // gehen wir davon aus, das das Fenster noch nicht
+ // ausgegeben wurde und loesen somit auch keine
+ // Invalidates aus. Dies ist eine Optimierung fuer
+ // HTML-Dokumenten mit vielen Controls. Wenn es mal
+ // Probleme mit dieser Abfrage gibt, sollte man ein
+ // Flag einfuehren, ob das Fenster nach Show schon
+ // einmal ausgegeben wurde.
+ if ( !bInitWinClipRegion )
+ {
+ // Alle nebeneinanderliegen Fenster invalidieren
+ // Noch nicht komplett implementiert !!!
+ Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ Window* pWindow = NULL;
+ if ( ImplIsOverlapWindow() )
+ {
+ if ( mpOverlapWindow )
+ pWindow = mpOverlapWindow->mpFirstOverlap;
+ }
+ else
+ pWindow = ImplGetParent()->mpFirstChild;
+ // Alle Fenster, die vor uns liegen und von uns verdeckt wurden,
+ // invalidieren
+ while ( pWindow )
+ {
+ if ( pWindow == this )
+ break;
+ Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ if ( aWinRect.IsOver( aCompRect ) )
+ pWindow->Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ pWindow = pWindow->mpNext;
+ }
+ // Wenn uns ein Fenster welches im Hinterund liegt verdeckt hat,
+ // dann muessen wir uns neu ausgeben
+ while ( pWindow )
+ {
+ if ( pWindow != this )
+ {
+ Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ if ( aWinRect.IsOver( aCompRect ) )
+ {
+ Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
+ break;
+ }
+ }
+ pWindow = pWindow->mpNext;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableAlwaysOnTop( BOOL bEnable )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mbAlwaysOnTop = bEnable;
+
+ if ( mpBorderWindow )
+ mpBorderWindow->EnableAlwaysOnTop( bEnable );
+ else if ( bEnable && IsReallyVisible() )
+ ToTop();
+
+ if ( mbFrame )
+ mpFrame->SetAlwaysOnTop( bEnable );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPosSizePixel( long nX, long nY,
+ long nWidth, long nHeight, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( nFlags & WINDOW_POSSIZE_POS )
+ mbDefPos = FALSE;
+ if ( nFlags & WINDOW_POSSIZE_SIZE )
+ mbDefSize = FALSE;
+
+ // Oberstes BorderWindow ist das Window, welches positioniert werden soll
+ Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+
+ if ( pWindow->mbFrame )
+ {
+ // Nur Groessenaenderungen werden beruecksichtig
+ if ( (nFlags & WINDOW_POSSIZE_SIZE) == WINDOW_POSSIZE_SIZE )
+ {
+ if ( !(nFlags & WINDOW_POSSIZE_WIDTH) )
+ nWidth = pWindow->mnOutWidth;
+ if ( !(nFlags & WINDOW_POSSIZE_HEIGHT) )
+ nHeight = pWindow->mnOutHeight;
+
+ pWindow->mpFrame->SetClientSize( nWidth, nHeight );
+ // Resize should be called directly. If we havn't
+ // set the correct size, we get a second resize from
+ // the system with the correct size. This can be happend
+ // if the size is to small or to lare.
+ ImplHandleResize( pWindow, nWidth, nHeight );
+ }
+ }
+ else
+ {
+ pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
+ if ( IsReallyVisible() )
+ ImplGenerateMouseMove();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::OutputToScreenPixel( const Point& rPos ) const
+{
+ return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::ScreenToOutputPixel( const Point& rPos ) const
+{
+ return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Scroll( long nHorzScroll, long nVertScroll, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplScroll( Rectangle( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) ),
+ nHorzScroll, nVertScroll, nFlags & ~SCROLL_CLIP );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Scroll( long nHorzScroll, long nVertScroll,
+ const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ aRect.Intersection( Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
+ if ( !aRect.IsEmpty() )
+ ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ ImplInvalidate( NULL, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ if ( !aRect.IsEmpty() )
+ {
+ Region aRegion( aRect );
+ ImplInvalidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invalidate( const Region& rRegion, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ if ( rRegion.IsNull() )
+ ImplInvalidate( NULL, nFlags );
+ else
+ {
+ Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
+ if ( !aRegion.IsEmpty() )
+ ImplInvalidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ ImplValidate( NULL, nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ Rectangle aRect = ImplLogicToDevicePixel( rRect );
+ if ( !aRect.IsEmpty() )
+ {
+ Region aRegion( aRect );
+ ImplValidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Validate( const Region& rRegion, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
+ return;
+
+ if ( rRegion.IsNull() )
+ ImplValidate( NULL, nFlags );
+ else
+ {
+ Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
+ if ( !aRegion.IsEmpty() )
+ ImplValidate( &aRegion, nFlags );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasPaintEvent() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !mbReallyVisible )
+ return FALSE;
+
+ if ( mpFrameWindow->mbPaintFrame )
+ return TRUE;
+
+ if ( mnPaintFlags & IMPL_PAINT_PAINT )
+ return TRUE;
+
+ if ( !ImplIsOverlapWindow() )
+ {
+ const Window* pTempWindow = this;
+ do
+ {
+ pTempWindow = pTempWindow->ImplGetParent();
+ if ( pTempWindow->mnPaintFlags & (IMPL_PAINT_PAINTCHILDS | IMPL_PAINT_PAINTALLCHILDS) )
+ return TRUE;
+ }
+ while ( !pTempWindow->ImplIsOverlapWindow() );
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Update()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpBorderWindow )
+ {
+ mpBorderWindow->Update();
+ return;
+ }
+
+ if ( !mbReallyVisible )
+ return;
+
+ BOOL bFlush = FALSE;
+ if ( mpFrameWindow->mbPaintFrame )
+ {
+ Point aPoint( 0, 0 );
+ Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
+ ImplInvalidateOverlapFrameRegion( aRegion );
+ if ( mbFrame || (mpBorderWindow && mpBorderWindow->mbFrame) )
+ bFlush = TRUE;
+ }
+
+ // Zuerst muessen wir alle Fenster ueberspringen, die Paint-Transparent
+ // sind
+ Window* pUpdateWindow = this;
+ Window* pWindow = pUpdateWindow;
+ while ( !pWindow->ImplIsOverlapWindow() )
+ {
+ if ( !pWindow->mbPaintTransparent )
+ {
+ pUpdateWindow = pWindow;
+ break;
+ }
+ pWindow = pWindow->ImplGetParent();
+ }
+ // Ein Update wirkt immer auf das Window, wo PAINTALLCHILDS gesetzt
+ // ist, damit nicht zuviel gemalt wird
+ pWindow = pUpdateWindow;
+ do
+ {
+ if ( pWindow->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDS )
+ pUpdateWindow = pWindow;
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+
+ // Wenn es etwas zu malen gibt, dann ein Paint ausloesen
+ if ( pUpdateWindow->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDS) )
+ {
+ // und fuer alle ueber uns stehende System-Fenster auch ein Update
+ // ausloesen, damit nicht die ganze Zeit luecken stehen bleiben
+ Window* pUpdateOverlapWindow = ImplGetFirstOverlapWindow()->mpFirstOverlap;
+ while ( pUpdateOverlapWindow )
+ {
+ pUpdateOverlapWindow->Update();
+ pUpdateOverlapWindow = pUpdateOverlapWindow->mpNext;
+ }
+
+ pUpdateWindow->ImplCallPaint( NULL, pUpdateWindow->mnPaintFlags );
+ }
+
+ if ( bFlush )
+ Flush();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Flush()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+#ifdef REMOTE_APPSERVER
+ // !!!!!
+#else
+ mpFrame->Flush();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Sync()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+#ifdef REMOTE_APPSERVER
+ // Wir rufen eine syncrone Funktion, um uns zu syncronisieren
+ long nDummy;
+ mpFrame->GetClientSize( nDummy, nDummy );
+#else
+ mpFrame->Sync();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetUpdateMode( BOOL bUpdate )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mbNoUpdate = !bUpdate;
+ StateChanged( STATE_CHANGE_UPDATEMODE );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GrabFocus()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplGrabFocus( 0 );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasFocus() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (this == ImplGetSVData()->maWinData.mpFocusWin);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HasChildPathFocus( BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pWindow = ImplGetSVData()->maWinData.mpFocusWin;
+ if ( pWindow )
+ return ImplIsWindowOrChild( pWindow, bSystemWindow );
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::CaptureMouse()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Tracking evt. beenden
+ if ( pSVData->maWinData.mpTrackWin != this )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ if ( pSVData->maWinData.mpCaptureWin != this )
+ {
+ pSVData->maWinData.mpCaptureWin = this;
+ mpFrame->CaptureMouse( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ReleaseMouse()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ DBG_ASSERTWARNING( pSVData->maWinData.mpCaptureWin == this,
+ "Window::ReleaseMouse(): window doesn't have the mouse capture" );
+
+ if ( pSVData->maWinData.mpCaptureWin == this )
+ {
+ pSVData->maWinData.mpCaptureWin = NULL;
+ mpFrame->CaptureMouse( FALSE );
+ ImplGenerateMouseMove();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsMouseCaptured() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (this == ImplGetSVData()->maWinData.mpCaptureWin);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointer( const Pointer& rPointer )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( maPointer == rPointer )
+ return;
+
+ maPointer = rPointer;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpFrame->SetPointer( ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnableChildPointerOverwrite( BOOL bOverwrite )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbChildPtrOverwrite == bOverwrite )
+ return;
+
+ mbChildPtrOverwrite = bOverwrite;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpFrame->SetPointer( ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetPointerPosPixel( const Point& rPos )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos = ImplOutputToFrame( rPos );
+ mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
+}
+
+// -----------------------------------------------------------------------
+
+Point Window::GetPointerPosPixel()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return ImplFrameToOutput( Point( mpFrameData->mnLastMouseX, mpFrameData->mnLastMouseY ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowPointer( BOOL bVisible )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbNoPtrVisible != !bVisible )
+ {
+ mbNoPtrVisible = !bVisible;
+
+ // Pointer evt. direkt umsetzen
+ if ( !mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EnterWait()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ mnWaitCount++;
+
+ if ( mnWaitCount == 1 )
+ {
+ // Pointer evt. direkt umsetzen
+ if ( !mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::LeaveWait()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mnWaitCount )
+ {
+ mnWaitCount--;
+
+ if ( !mnWaitCount )
+ {
+ // Pointer evt. direkt umsetzen
+ if ( !mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetCursor( Cursor* pCursor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpCursor != pCursor )
+ {
+ if ( mpCursor )
+ mpCursor->ImplHide();
+ mpCursor = pCursor;
+ if ( pCursor )
+ pCursor->ImplShow();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetText( const XubString& rStr )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ maText = rStr;
+
+ if ( mpBorderWindow )
+ mpBorderWindow->SetText( rStr );
+ else if ( mbFrame )
+ mpFrame->SetTitle( rStr );
+
+ StateChanged( STATE_CHANGE_TEXT );
+}
+
+// -----------------------------------------------------------------------
+
+XubString Window::GetText() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return maText;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& Window::GetHelpText() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !maHelpText.Len() && mnHelpId )
+ {
+ if ( !IsDialog() && (mnType != WINDOW_TABPAGE) && (mnType != WINDOW_FLOATINGWINDOW) )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ ((Window*)this)->maHelpText = pHelp->GetHelpText( GetHelpId() );
+ }
+ }
+
+ return maHelpText;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::FindWindow( const Point& rPos ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Point aPos = OutputToScreenPixel( rPos );
+ return ((Window*)this)->ImplFindWindow( aPos );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Window::GetChildCount() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nChildCount = 0;
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ nChildCount++;
+ pChild = pChild->mpNext;
+ }
+
+ return nChildCount;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetChild( USHORT nChild ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nChildCount = 0;
+ Window* pChild = mpFirstChild;
+ while ( pChild )
+ {
+ if ( nChild == nChildCount )
+ return pChild;
+ pChild = pChild->mpNext;
+ nChildCount++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Window* Window::GetWindow( USHORT nType ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ switch ( nType )
+ {
+ case WINDOW_PARENT:
+ return mpRealParent;
+
+ case WINDOW_FIRSTCHILD:
+ return mpFirstChild;
+
+ case WINDOW_LASTCHILD:
+ return mpLastChild;
+
+ case WINDOW_PREV:
+ return mpPrev;
+
+ case WINDOW_NEXT:
+ return mpNext;
+
+ case WINDOW_FIRSTOVERLAP:
+ return mpFirstOverlap;
+
+ case WINDOW_LASTOVERLAP:
+ return mpLastOverlap;
+
+ case WINDOW_OVERLAP:
+ if ( ImplIsOverlapWindow() )
+ return (Window*)this;
+ else
+ return mpOverlapWindow;
+
+ case WINDOW_PARENTOVERLAP:
+ if ( ImplIsOverlapWindow() )
+ return mpOverlapWindow;
+ else
+ return mpOverlapWindow->mpOverlapWindow;
+
+ case WINDOW_CLIENT:
+ return ((Window*)this)->ImplGetWindow();
+
+ case WINDOW_REALPARENT:
+ return ImplGetParent();
+
+ case WINDOW_FRAME:
+ return mpFrameWindow;
+
+ case WINDOW_BORDER:
+ if ( mpBorderWindow )
+ return mpBorderWindow->GetWindow( WINDOW_BORDER );
+ return (Window*)this;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
+
+ do
+ {
+ if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+
+ if ( pWindow == this )
+ return TRUE;
+ }
+ while ( pWindow );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsWindowOrChild( const Window* pWindow, BOOL bSystemWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
+
+ if ( this == pWindow )
+ return TRUE;
+ return ImplIsChild( pWindow, bSystemWindow );
+}
+
+// -----------------------------------------------------------------------
+
+const SystemEnvData* Window::GetSystemData() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+#ifndef REMOTE_APPSERVER
+ return mpFrame->GetSystemData();
+#else
+ return NULL;
+#endif
+}
+
+::com::sun::star::uno::Any Window::GetSystemDataAny() const
+{
+ ::com::sun::star::uno::Any aRet;
+ const SystemEnvData* pSysData = GetSystemData();
+ if( pSysData )
+ {
+ ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)pSysData, pSysData->nSize );
+ aRet <<= aSeq;
+ }
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetWindowPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xPeer, VCLXWindow* pVCLXWindow )
+{
+ mxWindowPeer = xPeer;
+ mpVCLXWindow = pVCLXWindow;
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > Window::GetComponentInterface( BOOL bCreate )
+{
+ if ( !mxWindowPeer.is() && bCreate )
+ {
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ mxWindowPeer = pWrapper->GetWindowInterface( this, sal_True );
+ }
+ return mxWindowPeer;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetComponentInterface( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xIFace )
+{
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ DBG_ASSERT( pWrapper, "SetComponentInterface: No Wrapper!" );
+ if ( pWrapper )
+ pWrapper->SetWindowInterface( this, xIFace );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallDeactivateListeners( Window *pNew )
+{
+ // Ich werde nicht deaktiviert, wenn das neu aktivierte Window ein Child von mir ist
+ if ( !pNew || !ImplIsChild( pNew ) )
+ {
+ if ( mxWindowPeer.is() )
+ Application::GetUnoWrapper()->WindowEvent_Activate( this, FALSE );
+ if ( ImplGetParent() )
+ ImplGetParent()->ImplCallDeactivateListeners( pNew );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplCallActivateListeners( Window *pOld )
+{
+ // Ich werde nicht aktiviert, wenn das alte aktive Fenster ein Child von mir ist
+ if ( !pOld || !ImplIsChild( pOld ) )
+ {
+ if ( mxWindowPeer.is() )
+ // Hier muss noch irgendwie pOld mitgeschickt werden!
+ Application::GetUnoWrapper()->WindowEvent_Activate( this, TRUE );
+ if ( ImplGetParent() )
+ ImplGetParent()->ImplCallActivateListeners( pOld );
+ }
+}
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
new file mode 100644
index 000000000000..6fc297a1cfa0
--- /dev/null
+++ b/vcl/source/window/window2.cxx
@@ -0,0 +1,1384 @@
+/*************************************************************************
+ *
+ * $RCSfile: window2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WINDOW_CXX
+
+#include <limits.h>
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include <rmoutdev.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <metric.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SCRBAR_HXX
+#include <scrbar.hxx>
+#endif
+#ifndef _SV_SCRWND_HXX
+#include <scrwnd.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+DBG_NAMEEX( Window );
+
+// =======================================================================
+
+#define IMPL_MAXSAVEBACKSIZE (640*480)
+#define IMPL_MAXALLSAVEBACKSIZE (800*600*2)
+
+// =======================================================================
+
+struct ImplFocusDelData : public ImplDelData
+{
+ Window* mpFocusWin;
+};
+
+// =======================================================================
+
+BOOL Window::ImplIsWindowInFront( const Window* pTestWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pTestWindow, Window, ImplDbgCheckWindow );
+
+ // Testen, ob es Fenster untereinander liegen
+ pTestWindow = pTestWindow->ImplGetFirstOverlapWindow();
+ const Window* pTempWindow = pTestWindow;
+ const Window* pThisWindow = ImplGetFirstOverlapWindow();
+ if ( pTempWindow == pThisWindow )
+ return FALSE;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ if ( pTempWindow->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+ pTempWindow = pThisWindow;
+ do
+ {
+ if ( pTempWindow == pTestWindow )
+ return FALSE;
+ if ( pTempWindow->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+
+ // Fenster auf gleiche Ebene bringen
+ if ( pThisWindow->mpOverlapWindow != pTestWindow->mpOverlapWindow )
+ {
+ USHORT nThisLevel = 0;
+ USHORT nTestLevel = 0;
+ pTempWindow = pThisWindow;
+ do
+ {
+ nThisLevel++;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mbFrame );
+ pTempWindow = pTestWindow;
+ do
+ {
+ nTestLevel++;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mbFrame );
+
+ if ( nThisLevel < nTestLevel )
+ {
+ do
+ {
+ if ( pTestWindow->mpOverlapWindow == pThisWindow->mpOverlapWindow )
+ break;
+ if ( pTestWindow->mbFrame )
+ break;
+ pTestWindow = pTestWindow->mpOverlapWindow;
+ }
+ while ( pTestWindow );
+ }
+ else
+ {
+ do
+ {
+ if ( pThisWindow->mpOverlapWindow == pTempWindow->mpOverlapWindow )
+ break;
+ if ( pThisWindow->mbFrame )
+ break;
+ pThisWindow = pThisWindow->mpOverlapWindow;
+ }
+ while ( pThisWindow );
+ }
+ }
+
+ // Wenn TestWindow vor ThisWindow kommt, liegt es vorne
+ pTempWindow = pTestWindow;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ pTempWindow = pTempWindow->mpNext;
+ }
+ while ( pTempWindow );
+
+ return FALSE;
+}
+
+// =======================================================================
+
+void Window::ImplSaveOverlapBackground()
+{
+ DBG_ASSERT( !mpOverlapData->mpSaveBackDev, "Window::ImplSaveOverlapBackground() - Background already saved" );
+
+ if ( !mbFrame )
+ {
+ ULONG nSaveBackSize = mnOutWidth*mnOutHeight;
+ if ( nSaveBackSize <= IMPL_MAXSAVEBACKSIZE )
+ {
+ if ( nSaveBackSize+mpFrameData->mnAllSaveBackSize <= IMPL_MAXALLSAVEBACKSIZE )
+ {
+ Size aOutSize( mnOutWidth, mnOutHeight );
+ mpOverlapData->mpSaveBackDev = new VirtualDevice( *mpFrameWindow );
+ if ( mpOverlapData->mpSaveBackDev->SetOutputSizePixel( aOutSize ) )
+ {
+ mpFrameWindow->ImplUpdateAll();
+
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ mpOverlapData->mnSaveBackSize = nSaveBackSize;
+ mpFrameData->mnAllSaveBackSize += nSaveBackSize;
+ Point aDevPt;
+ mpFrameWindow->ImplGetFrameDev( Point( mnOutOffX, mnOutOffY ),
+ aDevPt, aOutSize,
+ *(mpOverlapData->mpSaveBackDev) );
+ mpOverlapData->mpNextBackWin = mpFrameData->mpFirstBackWin;
+ mpFrameData->mpFirstBackWin = this;
+ }
+ else
+ {
+ delete mpOverlapData->mpSaveBackDev;
+ mpOverlapData->mpSaveBackDev = NULL;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplRestoreOverlapBackground( Region& rInvRegion )
+{
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ Point aDevPt;
+ Point aDestPt( mnOutOffX, mnOutOffY );
+ Size aDevSize = mpOverlapData->mpSaveBackDev->GetOutputSizePixel();
+ if ( mpOverlapData->mpSaveBackRgn )
+ {
+ mpOverlapData->mpSaveBackRgn->Intersect( maWinClipRegion );
+ rInvRegion = maWinClipRegion;
+ rInvRegion.Exclude( *mpOverlapData->mpSaveBackRgn );
+ mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpOverlapData->mpSaveBackDev),
+ *mpOverlapData->mpSaveBackRgn );
+ }
+ else
+ {
+ mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpOverlapData->mpSaveBackDev),
+ maWinClipRegion );
+ }
+ ImplDeleteOverlapBackground();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDeleteOverlapBackground()
+{
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ mpFrameData->mnAllSaveBackSize -= mpOverlapData->mnSaveBackSize;
+ delete mpOverlapData->mpSaveBackDev;
+ mpOverlapData->mpSaveBackDev = NULL;
+ if ( mpOverlapData->mpSaveBackRgn )
+ {
+ delete mpOverlapData->mpSaveBackRgn;
+ mpOverlapData->mpSaveBackRgn = NULL;
+ }
+
+ // Fenster aus der Liste entfernen
+ if ( mpFrameData->mpFirstBackWin == this )
+ mpFrameData->mpFirstBackWin = mpOverlapData->mpNextBackWin;
+ else
+ {
+ Window* pTemp = mpFrameData->mpFirstBackWin;
+ while ( pTemp->mpOverlapData->mpNextBackWin != this )
+ pTemp = pTemp->mpOverlapData->mpNextBackWin;
+ pTemp->mpOverlapData->mpNextBackWin = mpOverlapData->mpNextBackWin;
+ }
+ mpOverlapData->mpNextBackWin = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateAllOverlapBackgrounds()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pWindow = mpFrameData->mpFirstBackWin;
+ while ( pWindow )
+ {
+ // Naechstes Fenster schon hier merken, da dieses Fenster in
+ // der if-Abfrage aus der Liste entfernt werden kann
+ Window* pNext = pWindow->mpOverlapData->mpNextBackWin;
+
+ if ( ImplIsWindowInFront( pWindow ) )
+ {
+ Rectangle aRect1( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aRect2( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ aRect1.Intersection( aRect2 );
+ if ( !aRect1.IsEmpty() )
+ {
+ if ( !pWindow->mpOverlapData->mpSaveBackRgn )
+ pWindow->mpOverlapData->mpSaveBackRgn = new Region( aRect2 );
+ pWindow->mpOverlapData->mpSaveBackRgn->Exclude( aRect1 );
+ if ( pWindow->mpOverlapData->mpSaveBackRgn->IsEmpty() )
+ pWindow->ImplDeleteOverlapBackground();
+ }
+
+ }
+
+ pWindow = pNext;
+ }
+}
+
+// =======================================================================
+
+Bitmap Window::SnapShot() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Bitmap aBmp;
+
+ if ( mpBorderWindow )
+ aBmp = mpBorderWindow->SnapShot();
+ else if ( IsReallyVisible() )
+ mpFrameWindow->ImplGetFrameBitmap( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ), aBmp );
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowFocus( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( !mbInPaint )
+ {
+ if ( mbFocusVisible )
+ {
+ if ( *(pWinData->mpFocusRect) == rRect )
+ return;
+
+ ImplInvertFocus( *(pWinData->mpFocusRect) );
+ }
+
+ ImplInvertFocus( rRect );
+ }
+
+ if ( !pWinData->mpFocusRect )
+ pWinData->mpFocusRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpFocusRect) = rRect;
+ mbFocusVisible = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideFocus()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !mbFocusVisible )
+ return;
+
+ if ( !mbInPaint )
+ ImplInvertFocus( *(ImplGetWinData()->mpFocusRect) );
+ mbFocusVisible = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->Invert( aRect, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->Invert( nPoints, pPtAry, nSalFlags );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->Invert( aPoly, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( !mbInPaint || !(nFlags & SHOWTRACK_WINDOW) )
+ {
+ if ( mbTrackVisible )
+ {
+ if ( (*(pWinData->mpTrackRect) == rRect) &&
+ (pWinData->mnTrackFlags == nFlags) )
+ return;
+
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ }
+
+ InvertTracking( rRect, nFlags );
+ }
+
+ if ( !pWinData->mpTrackRect )
+ pWinData->mpTrackRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpTrackRect) = rRect;
+ pWinData->mnTrackFlags = nFlags;
+ mbTrackVisible = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideTracking()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbTrackVisible )
+ {
+ ImplWinData* pWinData = ImplGetWinData();
+ if ( !mbInPaint || !(pWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ mbTrackVisible = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( pGraphics, aRegion );
+ }
+ }
+
+ USHORT nStyle = nFlags & SHOWTRACK_STYLE;
+ if ( nStyle == SHOWTRACK_OBJECT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_TRACKFRAME );
+ else if ( nStyle == SHOWTRACK_SPLIT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_50 );
+ else
+ {
+ long nBorder = 1;
+ if ( nStyle == SHOWTRACK_BIG )
+ nBorder = 3;
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), nBorder, SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Left(), aRect.Bottom()-nBorder+1, aRect.GetWidth(), nBorder, SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Left(), aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Right()-nBorder+1, aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50 );
+ }
+#else
+ ImplServerGraphics* pGraphics;
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ pGraphics = ImplGetServerGraphics();
+ }
+ else
+ {
+ pGraphics = ImplGetServerGraphics( TRUE );
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aTmpPoint( mnOutOffX, mnOutOffY );
+ Size aTmpSize( mnOutWidth, mnOutHeight );
+ Rectangle aTmpRect( aTmpPoint, aTmpSize );
+ Region aRegion( aTmpRect );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ pGraphics->SetClipRegion( aRegion );
+ }
+ }
+
+ if ( pGraphics )
+ pGraphics->InvertTracking( aRect, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( pGraphics, aRegion );
+ }
+ }
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ pGraphics->Invert( nPoints, pPtAry, SAL_INVERT_TRACKFRAME );
+#else
+ ImplServerGraphics* pGraphics;
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ pGraphics = ImplGetServerGraphics();
+ }
+ else
+ {
+ pGraphics = ImplGetServerGraphics( TRUE );
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aTmpPoint( mnOutOffX, mnOutOffY );
+ Size aTmpSize( mnOutWidth, mnOutHeight );
+ Rectangle aTmpRect( aTmpPoint, aTmpSize );
+ Region aRegion( aTmpRect );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ pGraphics->SetClipRegion( aRegion );
+ }
+ }
+
+ if ( pGraphics )
+ pGraphics->InvertTracking( aPoly, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplTrackTimerHdl, Timer*, pTimer )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Bei Button-Repeat muessen wir den Timeout umsetzen
+ if ( pSVData->maWinData.mnTrackFlags & STARTTRACK_BUTTONREPEAT )
+ pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
+
+ // Tracking-Event erzeugen
+ Point aMousePos( mpFrameData->mnLastMouseX, mpFrameData->mnLastMouseY );
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpFrameData->mnClickCount, 0,
+ mpFrameData->mnMouseCode, mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, TRACKING_REPEAT );
+ Tracking( aTEvt );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartTracking( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin != this )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ if ( nFlags & (STARTTRACK_SCROLLREPEAT | STARTTRACK_BUTTONREPEAT) )
+ {
+ pSVData->maWinData.mpTrackTimer = new AutoTimer;
+
+ if ( nFlags & STARTTRACK_SCROLLREPEAT )
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
+ else
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
+ pSVData->maWinData.mpTrackTimer->SetTimeoutHdl( LINK( this, Window, ImplTrackTimerHdl ) );
+ pSVData->maWinData.mpTrackTimer->Start();
+ }
+
+ pSVData->maWinData.mpTrackWin = this;
+ pSVData->maWinData.mnTrackFlags = nFlags;
+ CaptureMouse();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndTracking( USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin == this )
+ {
+ // Hier wegen DbgChkThis geklammert, da Window im Handler zerstoert
+ // werden kann
+ {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( pSVData->maWinData.mpTrackTimer )
+ {
+ delete pSVData->maWinData.mpTrackTimer;
+ pSVData->maWinData.mpTrackTimer = NULL;
+ }
+
+ pSVData->maWinData.mpTrackWin = NULL;
+ pSVData->maWinData.mnTrackFlags = 0;
+ ReleaseMouse();
+ }
+
+ // EndTracking rufen, wenn es gerufen werden soll
+ if ( !(nFlags & ENDTRACK_DONTCALLHDL) )
+ {
+ Point aMousePos( mpFrameData->mnLastMouseX, mpFrameData->mnLastMouseY );
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpFrameData->mnClickCount, 0,
+ mpFrameData->mnMouseCode, mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, nFlags | ENDTRACK_END );
+ Tracking( aTEvt );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsTracking() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpTrackWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartAutoScroll( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin != this )
+ {
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ }
+
+ pSVData->maWinData.mpAutoScrollWin = this;
+ pSVData->maWinData.mnAutoScrollFlags = nFlags;
+ pSVData->maAppData.mpWheelWindow = new ImplWheelWindow( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndAutoScroll()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin == this )
+ {
+ pSVData->maWinData.mpAutoScrollWin = NULL;
+ pSVData->maWinData.mnAutoScrollFlags = 0;
+ delete pSVData->maAppData.mpWheelWindow;
+ pSVData->maAppData.mpWheelWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsAutoScroll() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpAutoScrollWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SaveBackground( const Point& rPos, const Size& rSize,
+ const Point& rDestOff, VirtualDevice& rSaveDevice )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpPaintRegion )
+ {
+ Region aClip( *mpPaintRegion );
+ const Point aPixPos( LogicToPixel( rPos ) );
+
+ aClip.Move( -mnOutOffX, -mnOutOffY );
+ aClip.Intersect( Rectangle( aPixPos, LogicToPixel( rSize ) ) );
+
+ if ( !aClip.IsEmpty() )
+ {
+ const Region aOldClip( rSaveDevice.GetClipRegion() );
+ const Point aPixOffset( rSaveDevice.LogicToPixel( rDestOff ) );
+ const Point aPixTopLeft( aClip.GetBoundRect().TopLeft() );
+ const BOOL bMap = rSaveDevice.IsMapModeEnabled();
+
+ // move clip region to have the same distance to DestOffset
+ aClip.Move( aPixOffset.X() - aPixPos.X(), aPixOffset.Y() - aPixPos.Y() );
+
+ // set pixel clip region
+ rSaveDevice.EnableMapMode( FALSE );
+ rSaveDevice.SetClipRegion( aClip );
+ rSaveDevice.EnableMapMode( bMap );
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+ rSaveDevice.SetClipRegion( aOldClip );
+ }
+ }
+ else
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::SaveFocus()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpFocusWin )
+ {
+ ImplFocusDelData* pDelData = new ImplFocusDelData;
+ pSVData->maWinData.mpFocusWin->ImplAddDel( pDelData );
+ pDelData->mpFocusWin = pSVData->maWinData.mpFocusWin;
+ return (ULONG)(void*)pDelData;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::EndSaveFocus( ULONG nSaveId, BOOL bRestore )
+{
+ if ( !nSaveId )
+ return FALSE;
+ else
+ {
+ BOOL bOK = TRUE;
+ ImplFocusDelData* pDelData = (ImplFocusDelData*)(void*)nSaveId;
+ if ( !pDelData->IsDelete() )
+ {
+ pDelData->mpFocusWin->ImplRemoveDel( pDelData );
+ if ( bRestore )
+ pDelData->mpFocusWin->GrabFocus();
+ }
+ else
+ bOK = !bRestore;
+ delete pDelData;
+ return bOK;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoom( const Fraction& rZoom )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( maZoom != rZoom )
+ {
+ maZoom = rZoom;
+ StateChanged( STATE_CHANGE_ZOOM );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline long WinFloatRound( double fVal )
+{
+ return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoomedPointFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ Font aFont( rFont );
+ Size aSize = aFont.GetSize();
+ double n = (double)aSize.Width();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Width() = WinFloatRound( n );
+ n = (double)aSize.Height();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Height() = WinFloatRound( n );
+ aFont.SetSize( aSize );
+ SetPointFont( aFont );
+
+ // Wenn Darstellung skaliert wird, nehmen wir gegebenenfalls
+ // einen anderen Font, wenn der aktuelle nicht skalierbar ist
+ FontMetric aMetric = GetFontMetric();
+ long nFontDiff = Abs( GetFont().GetSize().Height()-aMetric.GetSize().Height() );
+ if ( (aMetric.GetType() == TYPE_RASTER) && (nFontDiff >= 2) )
+ {
+ ImplDevFontListData* pStdFont = NULL;
+ USHORT nStdFont = 0xFFFF;
+ if ( aMetric.GetPitch() == PITCH_FIXED )
+ nStdFont = PITCH_FIXED;
+ else if ( aMetric.GetFamily() == FAMILY_SWISS )
+ nStdFont = IMPL_STDFONT_SWISS;
+ else if ( aMetric.GetFamily() == FAMILY_ROMAN )
+ nStdFont = IMPL_STDFONT_ROMAN;
+ if ( nStdFont != 0xFFFF )
+ {
+ if ( mpFontList )
+ pStdFont = mpFontList->GetStandardFont( nStdFont );
+ if ( pStdFont && (aFont.GetName() != pStdFont->maName) )
+ {
+ aFont.SetName( pStdFont->maName );
+ SetPointFont( aFont );
+ }
+ }
+ }
+ }
+ else
+ SetPointFont( rFont );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::CalcZoom( long nCalc ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ double n = (double)nCalc;
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ nCalc = WinFloatRound( n );
+ }
+ return nCalc;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpControlFont )
+ {
+ delete mpControlFont;
+ mpControlFont = NULL;
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rFont == Font() )
+ {
+ SetControlFont();
+ return;
+ }
+
+ if ( mpControlFont )
+ {
+ if ( *mpControlFont == rFont )
+ return;
+ *mpControlFont = rFont;
+ }
+ else
+ mpControlFont = new Font( rFont );
+
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetControlFont() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpControlFont )
+ return *mpControlFont;
+ else
+ {
+ Font aFont;
+ return aFont;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbControlForeground )
+ {
+ maControlForeground = Color( COL_TRANSPARENT );
+ mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbControlForeground )
+ {
+ maControlForeground = Color( COL_TRANSPARENT );
+ mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+ else
+ {
+ if ( maControlForeground != rColor )
+ {
+ maControlForeground = rColor;
+ mbControlForeground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbControlBackground )
+ {
+ maControlBackground = Color( COL_TRANSPARENT );
+ mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbControlBackground )
+ {
+ maControlBackground = Color( COL_TRANSPARENT );
+ mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+ else
+ {
+ if ( maControlBackground != rColor )
+ {
+ maControlBackground = rColor;
+ mbControlBackground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcWindowSize( const Size& rOutSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rOutSz;
+ aSz.Width() += mnLeftBorder+mnRightBorder;
+ aSz.Height() += mnTopBorder+mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcOutputSize( const Size& rWinSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rWinSz;
+ aSz.Width() -= mnLeftBorder+mnRightBorder;
+ aSz.Height() -= mnTopBorder+mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetDrawPixelFont( OutputDevice* pDev ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = GetPointFont();
+ Size aFontSize = aFont.GetSize();
+ MapMode aPtMapMode( MAP_POINT );
+ aFontSize = pDev->LogicToPixel( aFontSize, aPtMapMode );
+ aFont.SetSize( aFontSize );
+ return aFont;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::GetDrawPixel( OutputDevice* pDev, long nPixels ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ long nP = nPixels;
+ if ( pDev->GetOutDevType() != OUTDEV_WINDOW )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ Size aSz( nP, 0 );
+ aSz = PixelToLogic( aSz, aMap );
+ aSz = pDev->LogicToPixel( aSz, aMap );
+ nP = aSz.Width();
+ }
+ return nP;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HandleScrollCommand( const CommandEvent& rCmd,
+ ScrollBar* pHScrl, ScrollBar* pVScrl )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bRet = FALSE;
+
+ if ( pHScrl || pVScrl )
+ {
+ switch( rCmd.GetCommand() )
+ {
+ case COMMAND_STARTAUTOSCROLL:
+ {
+ USHORT nFlags = 0;
+ if ( pHScrl )
+ {
+ if ( (pHScrl->GetVisibleSize() < pHScrl->GetRangeMax()) &&
+ pHScrl->IsEnabled() && pHScrl->IsInputEnabled() )
+ nFlags |= AUTOSCROLL_HORZ;
+ }
+ if ( pVScrl )
+ {
+ if ( (pVScrl->GetVisibleSize() < pVScrl->GetRangeMax()) &&
+ pVScrl->IsEnabled() && pVScrl->IsInputEnabled() )
+ nFlags |= AUTOSCROLL_VERT;
+ }
+
+ if ( nFlags )
+ {
+ StartAutoScroll( nFlags );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ const CommandWheelData* pData = rCmd.GetWheelData();
+
+ if ( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
+ {
+ ULONG nScrollLines = pData->GetScrollLines();
+ long nLines;
+ if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ {
+ if ( pData->GetDelta() < 0 )
+ nLines = -LONG_MAX;
+ else
+ nLines = LONG_MAX;
+ }
+ else
+ nLines = pData->GetNotchDelta() * (long)nScrollLines;
+ if ( nLines )
+ {
+ ImplHandleScroll( NULL, 0L, pVScrl, nLines );
+ bRet = TRUE;
+ }
+ }
+ }
+ break;
+
+ case COMMAND_AUTOSCROLL:
+ {
+ const CommandScrollData* pData = rCmd.GetAutoScrollData();
+ if ( pData && (pData->GetDeltaX() || pData->GetDeltaY()) )
+ {
+ ImplHandleScroll( pHScrl, pData->GetDeltaX(),
+ pVScrl, pData->GetDeltaY() );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplHandleScroll( ScrollBar* pHScrl, long nX,
+ ScrollBar* pVScrl, long nY )
+{
+ if ( pHScrl && nX && pHScrl->IsEnabled() && pHScrl->IsInputEnabled() )
+ {
+ long nNewPos = pHScrl->GetThumbPos();
+
+ if ( nX == -LONG_MAX )
+ nNewPos += pHScrl->GetPageSize();
+ else if ( nX == LONG_MAX )
+ nNewPos -= pHScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nX * pHScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pHScrl->DoScroll( nNewPos );
+ }
+
+ if ( pVScrl && nY && pVScrl->IsEnabled() && pVScrl->IsInputEnabled() )
+ {
+ long nNewPos = pVScrl->GetThumbPos();
+
+ if ( nY == -LONG_MAX )
+ nNewPos += pVScrl->GetPageSize();
+ else if ( nY == LONG_MAX )
+ nNewPos -= pVScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nY * pVScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pVScrl->DoScroll( nNewPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetAccessObject( AccessObjectRef& rAcc ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ rAcc = new AccessObject( (void*) this, ACCESS_TYPE_WND );
+}
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
new file mode 100644
index 000000000000..db3382df3f88
--- /dev/null
+++ b/vcl/source/window/winproc.cxx
@@ -0,0 +1,2151 @@
+/*************************************************************************
+ *
+ * $RCSfile: winproc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WINPROC_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALWTYPE_HXX
+#include <salwtype.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include <rmwindow.hxx>
+#include <rmevents.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _INTN_HXX
+#include <tools/intn.hxx>
+#endif
+
+#define private public
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_DBGGUI_HXX
+#include <dbggui.hxx>
+#endif
+#ifndef _SV_WINDATA_HXX
+#include <windata.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_SOUND_HXX
+#include <sound.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+#ifndef _SV_ACCMGR_HXX
+#include <accmgr.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_FLOATWIN_HXX
+#include <floatwin.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+#ifndef _SV_GETSYS_HXX
+#include <getsys.hxx>
+#endif
+#ifndef _SV_HELP_HXX
+#include <help.hxx>
+#endif
+#ifndef _SV_HELPWIN_HXX
+#include <helpwin.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#undef private
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define IMPL_MIN_NEEDSYSWIN 49
+
+// =======================================================================
+
+long ImplCallPreNotify( NotifyEvent& rEvt )
+{
+ long nRet = Application::CallEventHooks( rEvt );
+ if ( !nRet )
+ nRet = rEvt.GetWindow()->PreNotify( rEvt );
+ return nRet;
+}
+
+// =======================================================================
+
+long ImplCallEvent( NotifyEvent& rEvt )
+{
+ long nRet = ImplCallPreNotify( rEvt );
+ if ( !nRet )
+ {
+ Window* pWindow = rEvt.GetWindow();
+ switch ( rEvt.GetType() )
+ {
+ case EVENT_MOUSEBUTTONDOWN:
+ pWindow->MouseButtonDown( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_MOUSEBUTTONUP:
+ pWindow->MouseButtonUp( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_MOUSEMOVE:
+ pWindow->MouseMove( *rEvt.GetMouseEvent() );
+ break;
+ case EVENT_KEYINPUT:
+ pWindow->KeyInput( *rEvt.GetKeyEvent() );
+ break;
+ case EVENT_KEYUP:
+ pWindow->KeyUp( *rEvt.GetKeyEvent() );
+ break;
+ case EVENT_GETFOCUS:
+ pWindow->GetFocus();
+ break;
+ case EVENT_LOSEFOCUS:
+ pWindow->LoseFocus();
+ break;
+ case EVENT_COMMAND:
+ pWindow->Command( *rEvt.GetCommandEvent() );
+ break;
+ case EVENT_QUERYDROP:
+ nRet = pWindow->QueryDrop( *rEvt.GetDropEvent() );
+ break;
+ case EVENT_DROP:
+ nRet = pWindow->QueryDrop( *rEvt.GetDropEvent() );
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// =======================================================================
+
+class ImplDragTimer : public AutoTimer
+{
+ Window* mpWindow;
+
+public:
+ ImplDragTimer( Window* pWindow );
+
+ virtual void Timeout();
+};
+
+static BOOL mbImplDragTimeoutHdl = FALSE;
+
+// -----------------------------------------------------------------------
+
+ImplDragTimer::ImplDragTimer( Window* pWindow )
+{
+ mpWindow = pWindow;
+ SetTimeout( 45 );
+ Start();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDragTimer::Timeout()
+{
+ if ( DragManager::GetDragManager() )
+ {
+ mbImplDragTimeoutHdl = TRUE;
+ mpWindow->ImplCallMouseMove( mpWindow->mpFrameData->mnMouseCode );
+ mbImplDragTimeoutHdl = FALSE;
+ }
+ else
+ {
+ mpWindow->mpFrameData->mpDragTimer = NULL;
+ delete this;
+ }
+}
+
+// =======================================================================
+
+static BOOL ImplHandleMouseFloatMode( Window* pChild, const Point& rMousePos,
+ USHORT nCode, USHORT nSVEvent,
+ BOOL bMouseLeave )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpFirstFloat && !pSVData->maWinData.mpCaptureWin &&
+ !pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( pChild ) )
+ {
+ USHORT nHitTest;
+ FloatingWindow* pFloat = pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( rMousePos, nHitTest );
+ FloatingWindow* pLastLevelFloat;
+ ULONG nPopupFlags;
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( bMouseLeave )
+ return TRUE;
+
+ if ( !pFloat || (nHitTest & IMPL_FLOATWIN_HITTEST_RECT) )
+ {
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+ pChild->mpFrame->SetPointer( POINTER_ARROW );
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ( nCode & MOUSE_LEFT )
+ {
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( !pFloat )
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+// Erstmal ausgebaut als Hack fuer Bug 53378
+// if ( nPopupFlags & FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK )
+// return FALSE;
+// else
+ return TRUE;
+ }
+ else if ( nHitTest & IMPL_FLOATWIN_HITTEST_RECT )
+ {
+ if ( !(pFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE) )
+ pFloat->ImplSetMouseDown();
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ( pFloat )
+ {
+ if ( nHitTest & IMPL_FLOATWIN_HITTEST_RECT )
+ {
+ if ( pFloat->ImplIsMouseDown() )
+ pFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+ return TRUE;
+ }
+ }
+ else
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ if ( !(nPopupFlags & FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE) )
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ return TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( !pFloat )
+ {
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
+ if ( nPopupFlags & FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE )
+ {
+ if ( (nPopupFlags & FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE) &&
+ (nSVEvent == EVENT_MOUSEBUTTONDOWN) )
+ return TRUE;
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ if ( nPopupFlags & FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK )
+ return FALSE;
+ else
+ return TRUE;
+ }
+ else
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleMouseHelpRequest( Window* pChild, const Point& rMousePos )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( ( pChild != pSVData->maHelpData.mpHelpWin ) && !DragManager::GetDragManager() )
+ {
+ USHORT nHelpMode = 0;
+ if ( pSVData->maHelpData.mbQuickHelp )
+ nHelpMode = HELPMODE_QUICK;
+ if ( pSVData->maHelpData.mbBalloonHelp )
+ nHelpMode |= HELPMODE_BALLOON;
+ if ( nHelpMode )
+ {
+ if ( pChild->IsInputEnabled() )
+ {
+ HelpEvent aHelpEvent( rMousePos, nHelpMode );
+ pSVData->maHelpData.mbRequestingHelp = TRUE;
+ pChild->RequestHelp( aHelpEvent );
+ pSVData->maHelpData.mbRequestingHelp = FALSE;
+ }
+ else if ( pSVData->maHelpData.mpHelpWin )
+ {
+ ImplDestroyHelpWindow( FALSE );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplSetMousePointer( Window* pChild )
+{
+ // Drag&Drop active?
+ DragManager* pDragManager = DragManager::GetDragManager();
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if( pDragManager && pDragManager->isModifyPointer() )
+ pChild->mpFrame->SetPointer( pDragManager->GetDragPointer().GetStyle() );
+ else if ( pSVData->maHelpData.mbExtHelpMode )
+ pChild->mpFrame->SetPointer( POINTER_HELP );
+ else
+ pChild->mpFrame->SetPointer( pChild->ImplGetMousePointer() );
+}
+
+// -----------------------------------------------------------------------
+
+long ImplHandleMouseEvent( Window* pWindow, USHORT nSVEvent, BOOL bMouseLeave,
+ long nX, long nY, ULONG nMsgTime,
+ USHORT nCode, USHORT nMode )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Point aMousePos( nX, nY );
+ Window* pChild;
+ long nRet;
+ USHORT nClicks;
+ USHORT nOldCode = pWindow->mpFrameData->mnMouseCode;
+
+ // we need a mousemove event, befor we get a mousebuttondown or a
+ // mousebuttonup event
+ if ( (nSVEvent == EVENT_MOUSEBUTTONDOWN) ||
+ (nSVEvent == EVENT_MOUSEBUTTONUP) )
+ {
+ if ( (nSVEvent == EVENT_MOUSEBUTTONUP) && pSVData->maHelpData.mbExtHelpMode )
+ Help::EndExtHelp();
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+
+ if ( (pWindow->mpFrameData->mnLastMouseX != nX) ||
+ (pWindow->mpFrameData->mnLastMouseY != nY) )
+ {
+ ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, FALSE, nX, nY, nMsgTime, nCode, nMode );
+ }
+ }
+
+ // update frame data
+ pWindow->mpFrameData->mnLastMouseX = nX;
+ pWindow->mpFrameData->mnLastMouseY = nY;
+ pWindow->mpFrameData->mnMouseCode = nCode;
+ pWindow->mpFrameData->mnMouseMode = nMode & ~(MOUSE_SYNTHETIC | MOUSE_MODIFIERCHANGED);
+ if ( bMouseLeave )
+ {
+ pWindow->mpFrameData->mbMouseIn = FALSE;
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+
+ // If Drag&Drop is active try to start System-Drag&Drop
+ DragManager* pDragManager = DragManager::GetDragManager();
+ if ( pDragManager )
+ {
+ if ( pWindow->mpFrameData->mpDragTimer )
+ {
+ delete pWindow->mpFrameData->mpDragTimer;
+ pWindow->mpFrameData->mpDragTimer = NULL;
+ }
+ pDragManager->AppWindowLeaved();
+ }
+ }
+ else
+ {
+ // Handle Drag&Drop if window is (re)entered
+ if ( !pWindow->mpFrameData->mbMouseIn )
+ {
+ // Drag&Drop active?
+ DragManager* pDragManager = DragManager::GetDragManager();
+
+ // HRO: Nur Escape rufen, wenn es unser eigenes Drag & Drop war
+ if ( pDragManager && pDragManager->bOwnDragDrop )
+ {
+ // break Drag&Drop, if mouse button is not pressed
+ if( !( nCode & MOUSE_LEFT ) )
+ pDragManager->Escape( pWindow );
+ }
+ }
+
+ pWindow->mpFrameData->mbMouseIn = TRUE;
+ }
+
+ DBG_ASSERT( !pSVData->maWinData.mpTrackWin ||
+ (pSVData->maWinData.mpTrackWin == pSVData->maWinData.mpCaptureWin),
+ "ImplHandleMouseEvent: TrackWin != CaptureWin" );
+
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin && (nSVEvent == EVENT_MOUSEBUTTONDOWN) )
+ {
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ return 1;
+ }
+
+ // find mouse window
+ if ( pSVData->maWinData.mpCaptureWin )
+ {
+ pChild = pSVData->maWinData.mpCaptureWin;
+
+ DBG_ASSERT( !bMouseLeave || (pWindow != pChild->mpFrameWindow),
+ "ImplHandleMouseEvent: MouseLeave is send and Mouse is captured" );
+ DBG_ASSERT( pWindow == pChild->mpFrameWindow,
+ "ImplHandleMouseEvent: mouse event is not sent to capture window" );
+
+ if ( bMouseLeave )
+ return 0;
+ }
+ else
+ {
+ if ( bMouseLeave )
+ pChild = NULL;
+ else
+ pChild = pWindow->ImplFindWindow( aMousePos );
+ }
+
+ // test this because mouse events are buffered in the remote version
+ // and size may not be in sync
+ if ( !pChild && !bMouseLeave )
+ return 0;
+
+ // Ein paar Test ausfuehren und Message abfangen oder Status umsetzen
+ if ( pChild )
+ {
+ // no mouse messages to system object windows
+#ifndef REMOTE_APPSERVER
+ if ( pChild->mpSysObj )
+ return 0;
+#endif
+
+ // no mouse messages to disabled windows
+ if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() )
+ {
+ ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave );
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ ImplHandleMouseHelpRequest( pChild, aMousePos );
+
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ Sound::Beep( SOUND_DISABLE, pChild );
+ return 1;
+ }
+ else
+ {
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ ImplSetMousePointer( pChild );
+ return 0;
+ }
+ }
+
+ // ExtTextInput-Modus beenden, wenn in das Fenster geklickt wird
+ if ( pChild->IsExtTextInput() )
+ {
+ if ( (nSVEvent == EVENT_MOUSEBUTTONDOWN) ||
+ (nSVEvent == EVENT_MOUSEBUTTONUP) )
+ pChild->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+ }
+ }
+
+ // determine mouse event data
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ // Testen, ob MouseMove an das gleiche Fenster geht und sich der
+ // Status nicht geaendert hat
+ if ( pChild )
+ {
+ Point aChildMousePos = pChild->ImplFrameToOutput( aMousePos );
+ if ( !bMouseLeave &&
+ (pChild == pWindow->mpFrameData->mpMouseMoveWin) &&
+ (aChildMousePos.X() == pWindow->mpFrameData->mnLastMouseWinX) &&
+ (aChildMousePos.Y() == pWindow->mpFrameData->mnLastMouseWinY) &&
+ (nOldCode == pWindow->mpFrameData->mnMouseCode) &&
+ !mbImplDragTimeoutHdl )
+ {
+ // Mouse-Pointer neu setzen, da er sich geaendet haben
+ // koennte, da ein Modus umgesetzt wurde
+ ImplSetMousePointer( pChild );
+ return 0;
+ }
+
+ pWindow->mpFrameData->mnLastMouseWinX = aChildMousePos.X();
+ pWindow->mpFrameData->mnLastMouseWinY = aChildMousePos.Y();
+ }
+
+ // mouse click
+ nClicks = pWindow->mpFrameData->mnClickCount;
+
+ // Gegebenenfalls den Start-Drag-Handler rufen.
+ // Achtung: Muss vor Move gerufen werden, da sonst bei schnellen
+ // Mausbewegungen die Applikationen in den Selektionszustand gehen.
+ Window* pMouseDownWin = pWindow->mpFrameData->mpMouseDownWin;
+ if ( pMouseDownWin )
+ {
+ // Testen, ob StartDrag-Modus uebereinstimmt. Wir vergleichen nur
+ // den Status der Maustasten, damit man mit Mod1 z.B. sofort
+ // in den Kopiermodus gehen kann.
+ const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
+ if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
+ {
+ if ( !pMouseDownWin->mpFrameData->mbStartDragCalled )
+ {
+ long nDragW = rMSettings.GetStartDragWidth();
+ long nDragH = rMSettings.GetStartDragWidth();
+ long nMouseX = nX;
+ long nMouseY = nY;
+ if ( !(((nMouseX-nDragW) <= pMouseDownWin->mpFrameData->mnFirstMouseX) &&
+ ((nMouseX+nDragW) >= pMouseDownWin->mpFrameData->mnFirstMouseX)) ||
+ !(((nMouseY-nDragH) <= pMouseDownWin->mpFrameData->mnFirstMouseY) &&
+ ((nMouseY+nDragH) >= pMouseDownWin->mpFrameData->mnFirstMouseY)) )
+ {
+ pMouseDownWin->mpFrameData->mbStartDragCalled = TRUE;
+ Point aCmdMousePos( pMouseDownWin->mpFrameData->mnFirstMouseX,
+ pMouseDownWin->mpFrameData->mnFirstMouseY );
+ aCmdMousePos = pMouseDownWin->ImplFrameToOutput( aCmdMousePos );
+ CommandEvent aCEvt( aCmdMousePos, COMMAND_STARTDRAG, TRUE );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pMouseDownWin, &aCEvt );
+ ImplDelData aDelData;
+ pMouseDownWin->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) )
+ pMouseDownWin->Command( aCEvt );
+ if ( aDelData.IsDelete() )
+ return 1;
+ pMouseDownWin->ImplRemoveDel( &aDelData );
+ }
+ }
+ }
+ else
+ pMouseDownWin->mpFrameData->mbStartDragCalled = TRUE;
+ }
+
+ // test for mouseleave and mouseenter
+ Window* pMouseMoveWin = pWindow->mpFrameData->mpMouseMoveWin;
+ if ( pChild != pMouseMoveWin )
+ {
+ if ( pMouseMoveWin )
+ {
+ Point aLeaveMousePos = pMouseMoveWin->ImplFrameToOutput( aMousePos );
+ MouseEvent aMLeaveEvt( aLeaveMousePos, nClicks, nMode | MOUSE_LEAVEWINDOW, nCode, nCode );
+ NotifyEvent aNLeaveEvt( EVENT_MOUSEMOVE, pMouseMoveWin, &aMLeaveEvt );
+ ImplDelData aDelData;
+ ImplDelData aDelData2;
+ pWindow->mpFrameData->mbInMouseMove = TRUE;
+ pMouseMoveWin->ImplAddDel( &aDelData );
+ // Durch MouseLeave kann auch dieses Fenster zerstoert
+ // werden
+ if ( pChild )
+ pChild->ImplAddDel( &aDelData2 );
+ if ( !ImplCallPreNotify( aNLeaveEvt ) )
+ {
+ DragManager* pDragManager = DragManager::GetDragManager();
+ if ( pDragManager )
+ pDragManager->MouseMove( aMLeaveEvt, pMouseMoveWin );
+ else
+ pMouseMoveWin->MouseMove( aMLeaveEvt );
+ }
+
+ pWindow->mpFrameData->mpMouseMoveWin = NULL;
+ pWindow->mpFrameData->mbInMouseMove = FALSE;
+
+ if ( pChild )
+ {
+ if ( aDelData2.IsDelete() )
+ pChild = NULL;
+ else
+ pChild->ImplRemoveDel( &aDelData2 );
+ }
+ if ( aDelData.IsDelete() )
+ return 1;
+ pMouseMoveWin->ImplRemoveDel( &aDelData );
+ }
+
+ nMode |= MOUSE_ENTERWINDOW;
+ }
+ pWindow->mpFrameData->mpMouseMoveWin = pChild;
+
+ // MouseLeave
+ if ( !pChild )
+ return 0;
+ }
+ else
+ {
+ // mouse click
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
+ ULONG nDblClkTime = rMSettings.GetDoubleClickTime();
+ long nDblClkW = rMSettings.GetDoubleClickWidth();
+ long nDblClkH = rMSettings.GetDoubleClickHeight();
+ long nMouseX = nX;
+ long nMouseY = nY;
+
+ if ( (pChild == pChild->mpFrameData->mpMouseDownWin) &&
+ (nCode == pChild->mpFrameData->mnFirstMouseCode) &&
+ ((nMsgTime-pChild->mpFrameData->mnMouseDownTime) < nDblClkTime) &&
+ ((nMouseX-nDblClkW) <= pChild->mpFrameData->mnFirstMouseX) &&
+ ((nMouseX+nDblClkW) >= pChild->mpFrameData->mnFirstMouseX) &&
+ ((nMouseY-nDblClkH) <= pChild->mpFrameData->mnFirstMouseY) &&
+ ((nMouseY+nDblClkH) >= pChild->mpFrameData->mnFirstMouseY) )
+ {
+ pChild->mpFrameData->mnClickCount++;
+ pChild->mpFrameData->mbStartDragCalled = TRUE;
+ }
+ else
+ {
+ pChild->mpFrameData->mpMouseDownWin = pChild;
+ pChild->mpFrameData->mnClickCount = 1;
+ pChild->mpFrameData->mnFirstMouseX = nMouseX;
+ pChild->mpFrameData->mnFirstMouseY = nMouseY;
+ pChild->mpFrameData->mnFirstMouseCode = nCode;
+ pChild->mpFrameData->mbStartDragCalled = !((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
+ (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)));
+ }
+ pChild->mpFrameData->mnMouseDownTime = nMsgTime;
+ }
+ nClicks = pChild->mpFrameData->mnClickCount;
+
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+ }
+
+ DBG_ASSERT( pChild, "ImplHandleMouseEvent: pChild == NULL" );
+
+ // create mouse event
+ Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
+ MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
+
+ // tracking window gets the mouse events
+ BOOL bTracking = FALSE;
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ pChild = pSVData->maWinData.mpTrackWin;
+ bTracking = TRUE;
+ }
+
+ // handle FloatingMode
+ if ( !pSVData->maWinData.mpTrackWin && pSVData->maWinData.mpFirstFloat )
+ {
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+ if ( ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ) )
+ {
+ if ( !aDelData.IsDelete() )
+ {
+ pChild->ImplRemoveDel( &aDelData );
+ pChild->mpFrameData->mbStartDragCalled = TRUE;
+ }
+ return 1;
+ }
+ else
+ pChild->ImplRemoveDel( &aDelData );
+ }
+
+ // call handler
+ BOOL bDrag = FALSE;
+ BOOL bCallHelpRequest = TRUE;
+ DBG_ASSERT( pChild, "ImplHandleMouseEvent: pChild is NULL" );
+
+ ImplDelData aDelData;
+ NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
+ pChild->ImplAddDel( &aDelData );
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ pChild->mpFrameData->mbInMouseMove = TRUE;
+ // D&D im Gange?
+ DragManager* pDragManager = DragManager::GetDragManager();
+ if ( pDragManager )
+ {
+ bDrag = TRUE;
+ nRet = 1;
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( !pChild->mpFrameData->mpDragTimer )
+ pChild->mpFrameData->mpDragTimer = new ImplDragTimer( pChild->ImplGetFrameWindow() );
+ pDragManager->MouseMove( aMEvt, pChild );
+ }
+ else if ( nSVEvent == EVENT_MOUSEBUTTONUP )
+ {
+ pChild->ImplGenerateMouseMove();
+ pDragManager->ButtonUp( aMEvt, pChild );
+ }
+ }
+ else
+ {
+ // Fenster bei Klick nach vorne bringen
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ pChild->ToTop();
+ if ( aDelData.IsDelete() )
+ return 1;
+ }
+
+ if ( ImplCallPreNotify( aNEvt ) || aDelData.IsDelete() )
+ nRet = 1;
+ else
+ {
+ nRet = 0;
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( bTracking )
+ {
+ TrackingEvent aTEvt( aMEvt );
+ pChild->Tracking( aTEvt );
+ if ( !aDelData.IsDelete() )
+ {
+ // When ScrollRepeat, we restart the timer
+ if ( pSVData->maWinData.mpTrackTimer &&
+ (pSVData->maWinData.mnTrackFlags & STARTTRACK_SCROLLREPEAT) )
+ pSVData->maWinData.mpTrackTimer->Start();
+ }
+ bCallHelpRequest = FALSE;
+ nRet = 1;
+ }
+ else
+ {
+ // Auto-ToTop
+ if ( !pSVData->maWinData.mpCaptureWin &&
+ (pChild->GetSettings().GetMouseSettings().GetOptions() & MOUSE_OPTION_AUTOFOCUS) )
+ pChild->ToTop( TOTOP_NOGRABFOCUS );
+
+ // Wenn Hilfe-Fenster im MouseMove angezeigt/gehidet wird,
+ // wird danach nicht mehr der HelpRequest-Handler gerufen
+ Window* pOldHelpTextWin = pSVData->maHelpData.mpHelpWin;
+ pChild->mbMouseMove = FALSE;
+ pChild->MouseMove( aMEvt );
+ if ( pOldHelpTextWin != pSVData->maHelpData.mpHelpWin )
+ bCallHelpRequest = FALSE;
+ }
+ }
+ else if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( bTracking &&
+ !(pSVData->maWinData.mnTrackFlags & STARTTRACK_MOUSEBUTTONDOWN) )
+ nRet = 1;
+ else
+ {
+ pChild->mbMouseButtonDown = FALSE;
+ pChild->MouseButtonDown( aMEvt );
+ }
+ }
+ else
+ {
+ if ( bTracking )
+ {
+ pChild->EndTracking();
+ nRet = 1;
+ }
+ else
+ {
+ pChild->mbMouseButtonUp = FALSE;
+ pChild->MouseButtonUp( aMEvt );
+ }
+ }
+ }
+ }
+
+ if ( aDelData.IsDelete() )
+ return 1;
+
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ pChild->mpFrameData->mbInMouseMove = FALSE;
+
+ if ( nSVEvent == EVENT_MOUSEMOVE )
+ {
+ if ( bCallHelpRequest )
+ ImplHandleMouseHelpRequest( pChild, pChild->OutputToScreenPixel( aMEvt.GetPosPixel() ) );
+ nRet = 1;
+ }
+ else if ( !nRet )
+ {
+ if ( nSVEvent == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( !pChild->mbMouseButtonDown )
+ nRet = 1;
+ }
+ else
+ {
+ if ( !pChild->mbMouseButtonUp )
+ nRet = 1;
+ }
+ }
+
+ pChild->ImplRemoveDel( &aDelData );
+
+ // ContextMenu
+ if ( !bDrag && ((nSVEvent == EVENT_MOUSEBUTTONDOWN) || (nSVEvent == EVENT_MOUSEBUTTONUP)) )
+ {
+ // StartAutoScrollMode-Command-Event
+ if ( /*(nRet == 0) &&*/ (nClicks == 1) && (nSVEvent == EVENT_MOUSEBUTTONDOWN) &&
+ (nCode == MOUSE_MIDDLE) )
+ {
+ BOOL bPreNotify;
+ CommandEvent aCEvt( aChildPos, COMMAND_STARTAUTOSCROLL, TRUE );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pChild, &aCEvt );
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ pChild->mbCommand = FALSE;
+ pChild->Command( aCEvt );
+ }
+ else
+ bPreNotify = TRUE;
+ if ( aDelData.IsDelete() )
+ return 1;
+ pChild->ImplRemoveDel( &aDelData );
+ if ( !bPreNotify && pChild->mbCommand )
+ nRet = 0;
+ else
+ nRet = 1;
+ }
+ else
+ {
+ const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
+ if ( (nCode == rMSettings.GetContextMenuCode()) &&
+ (nClicks == rMSettings.GetContextMenuClicks()) )
+ {
+ BOOL bContextMenu;
+ if ( rMSettings.GetContextMenuDown() )
+ bContextMenu = (nSVEvent == EVENT_MOUSEBUTTONDOWN);
+ else
+ bContextMenu = (nSVEvent == EVENT_MOUSEBUTTONUP);
+ if ( bContextMenu )
+ {
+ BOOL bPreNotify;
+ CommandEvent aCEvt( aChildPos, COMMAND_CONTEXTMENU, TRUE );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pChild, &aCEvt );
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ pChild->mbCommand = FALSE;
+ pChild->Command( aCEvt );
+ }
+ else
+ bPreNotify = TRUE;
+ if ( aDelData.IsDelete() )
+ return 1;
+ pChild->ImplRemoveDel( &aDelData );
+ if ( !bPreNotify && pChild->mbCommand )
+ nRet = 0;
+ else
+ nRet = 1;
+ }
+ }
+ }
+ }
+
+ // set new mouse pointer
+ if ( (nSVEvent == EVENT_MOUSEMOVE) && !bMouseLeave )
+ ImplSetMousePointer( pChild );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplGetKeyInputWindow( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // determine last input time
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+
+ // find window
+ Window* pChild = pWindow->mpFrameData->mpFocusWin;
+
+ // Nur KeyInput an das Focus-Window auswerten
+ if ( !pChild || (pChild != pSVData->maWinData.mpFocusWin) )
+ return 0;
+ DBG_ASSERT( pChild == pSVData->maWinData.mpFocusWin,
+ "ImplHandleKey: Keyboard-Input is sent to the wrong frame" );
+
+ // no keyinput to disabled windows
+ if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() )
+ return 0;
+
+ return pChild;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleKey( Window* pWindow, USHORT nSVEvent,
+ USHORT nKeyCode, USHORT nCharCode, USHORT nRepeat )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ KeyCode aKeyCode( nKeyCode, nKeyCode );
+ USHORT nCode = aKeyCode.GetCode();
+
+ // determine last input time
+ pSVData->maAppData.mnLastInputTime = Time::GetSystemTicks();
+
+ // handle tracking window
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+#ifdef DBG_UTIL
+#ifdef REMOTE_APPSERVER
+ if ( aKeyCode.IsShift() && aKeyCode.IsMod2() && (aKeyCode.GetCode() == KEY_D) )
+#else
+ if ( aKeyCode.IsShift() && aKeyCode.IsMod1() && (aKeyCode.GetCode() == KEY_D) )
+#endif
+ {
+ DBGGUI_START();
+ return 1;
+ }
+#endif
+
+ if ( pSVData->maHelpData.mbExtHelpMode )
+ {
+ Help::EndExtHelp();
+ if ( nCode == KEY_ESCAPE )
+ return 1;
+ }
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ {
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ if ( nCode == KEY_ESCAPE )
+ return 1;
+ }
+
+ // D&D im Gange und Escape?
+ if ( nCode == KEY_ESCAPE )
+ {
+ DragManager* pDragManager = DragManager::GetDragManager();
+ if ( pDragManager )
+ {
+ // Ist pWindow immer das TargetWindow?
+ // Nicht unbedingt. Aktuelles TargetWindow im DragManager merken?
+ pWindow->ImplGenerateMouseMove();
+ pDragManager->Escape( pWindow );
+ return 1;
+ }
+ }
+
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ if ( (nCode == KEY_ESCAPE) && !(pSVData->maWinData.mnTrackFlags & STARTTRACK_NOKEYCANCEL) )
+ {
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL | ENDTRACK_KEY );
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ if ( !(pLastLevelFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOKEYCLOSE) )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ if ( nCode == KEY_ESCAPE )
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ }
+ return 1;
+ }
+ else if ( nCode == KEY_RETURN )
+ {
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_KEY );
+ return 1;
+ }
+ else if ( !(pSVData->maWinData.mnTrackFlags & STARTTRACK_KEYINPUT) )
+ return 1;
+ }
+
+ // handle FloatingMode
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ if ( !(pLastLevelFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOKEYCLOSE) )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ if ( nCode == KEY_ESCAPE )
+ {
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ return 1;
+ }
+ }
+ }
+
+ // test for accel
+ if ( pSVData->maAppData.mpAccelMgr )
+ {
+ if ( pSVData->maAppData.mpAccelMgr->IsAccelKey( aKeyCode, nRepeat ) )
+ return 1;
+ }
+ }
+
+ // find window
+ Window* pChild = pWindow->mpFrameData->mpFocusWin;
+
+ // Nur KeyInput an das Focus-Window auswerten
+ if ( !pChild || (pChild != pSVData->maWinData.mpFocusWin) )
+ return 0;
+ DBG_ASSERT( pChild == pSVData->maWinData.mpFocusWin,
+ "ImplHandleKey: Keyboard-Input is sent to the wrong frame" );
+
+ // no keyinput to disabled windows
+ if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() )
+ return 0;
+
+ // call handler
+ ImplDelData aDelData;
+ KeyEvent aKEvt( (xub_Unicode)nCharCode, aKeyCode, nRepeat );
+ NotifyEvent aNEvt( nSVEvent, pChild, &aKEvt );
+ BOOL bPreNotify;
+ long nRet = 1;
+
+ pChild->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+ pChild->mbKeyInput = FALSE;
+ pChild->KeyInput( aKEvt );
+ }
+ else
+ {
+ pChild->mbKeyUp = FALSE;
+ pChild->KeyUp( aKEvt );
+ }
+ }
+ else
+ bPreNotify = TRUE;
+
+ if ( aDelData.IsDelete() )
+ return 1;
+
+ pChild->ImplRemoveDel( &aDelData );
+
+ if ( nSVEvent == EVENT_KEYINPUT )
+ {
+ if ( !bPreNotify && pChild->mbKeyInput )
+ {
+ USHORT nCode = aKeyCode.GetCode();
+
+ // ContextMenu
+ if ( (nCode == KEY_CONTEXTMENU) || ((nCode == KEY_F10) && aKeyCode.IsShift()) )
+ {
+ CommandEvent aCEvt( pChild->GetPointerPosPixel(), COMMAND_CONTEXTMENU, FALSE );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pChild, &aCEvt );
+ ImplDelData aDelData;
+ pChild->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ pChild->mbCommand = FALSE;
+ pChild->Command( aCEvt );
+ }
+ else
+ bPreNotify = TRUE;
+ if ( aDelData.IsDelete() )
+ return 1;
+ pChild->ImplRemoveDel( &aDelData );
+ if ( !bPreNotify && pChild->mbCommand )
+ nRet = 0;
+ }
+ else if ( (nCode == KEY_F1) || (nCode == KEY_HELP) )
+ {
+ if ( !aKeyCode.GetModifier() )
+ {
+ if ( pSVData->maHelpData.mbContextHelp )
+ {
+ Point aMousePos = pChild->OutputToScreenPixel( pChild->GetPointerPosPixel() );
+ HelpEvent aHelpEvent( aMousePos, HELPMODE_CONTEXT );
+ pChild->RequestHelp( aHelpEvent );
+ }
+ else
+ nRet = 0;
+ }
+ else if ( aKeyCode.IsShift() )
+ {
+ if ( pSVData->maHelpData.mbExtHelp )
+ Help::StartExtHelp();
+ else
+ nRet = 0;
+ }
+ }
+ else
+ {
+ if ( ImplCallHotKey( aKeyCode ) )
+ nRet = 1;
+ else
+ nRet = 0;
+ }
+ }
+ }
+ else
+ {
+ if ( !bPreNotify && pChild->mbKeyUp )
+ nRet = 0;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplCallExtTextInput( Window* pChild, USHORT nEvt,
+ void* pData = NULL )
+{
+ CommandEvent aCEvt( pChild->GetPointerPosPixel(), nEvt, FALSE, pData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pChild, &aCEvt );
+ ImplDelData aDelData;
+ BOOL bPreNotify;
+ pChild->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ pChild->mbCommand = FALSE;
+ pChild->Command( aCEvt );
+ }
+ else
+ bPreNotify = TRUE;
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ pChild->ImplRemoveDel( &aDelData );
+ if ( !bPreNotify && pChild->mbCommand )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleStartExtTextInput( Window* pWindow )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ long nRet = 0;
+ if ( pChild )
+ {
+ pChild->mbExtTextInput = TRUE;
+ pChild->ImplGetWinData()->mnExtOldTextLen = 0;
+ nRet = ImplCallExtTextInput( pChild, COMMAND_STARTEXTTEXTINPUT );
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleEndExtTextInput( Window* pWindow )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ long nRet = 0;
+ if ( pChild )
+ {
+ pChild->mbExtTextInput = FALSE;
+ pChild->ImplGetWinData()->mnExtOldTextLen = 0;
+ nRet = ImplCallExtTextInput( pChild, COMMAND_ENDEXTTEXTINPUT );
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleExtTextInput( Window* pWindow, ULONG nTime,
+ const XubString& rText,
+ const USHORT* pTextAttr,
+ ULONG nCursorPos, BOOL bCursorVisible,
+ ULONG nDeltaStart, BOOL bOnlyCursor )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ long nRet = 0;
+ if ( pChild )
+ {
+ BOOL bSmartMode = FALSE;
+ if ( !pChild->mbExtTextInput )
+ {
+ bSmartMode = TRUE;
+ ImplHandleStartExtTextInput( pWindow );
+ }
+ CommandExtTextInputData aData( rText, pTextAttr,
+ (USHORT)nCursorPos, bCursorVisible,
+ (USHORT)nDeltaStart,
+ pChild->ImplGetWinData()->mnExtOldTextLen,
+ bOnlyCursor );
+ pChild->ImplGetWinData()->mnExtOldTextLen = rText.Len();
+ nRet = ImplCallExtTextInput( pChild, COMMAND_EXTTEXTINPUT, &aData );
+ if ( bSmartMode )
+ {
+ // TextAttribute muessen zum Schluss restauriert ausgegeben werden
+ if ( pTextAttr )
+ {
+ ImplHandleExtTextInput( pWindow, nTime, rText, NULL,
+ nCursorPos, bCursorVisible,
+ nDeltaStart, bOnlyCursor );
+ }
+ ImplHandleEndExtTextInput( pWindow );
+ }
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+static Window* ImplHandleExtTextInputPos( Window* pWindow, ULONG nFirst,
+ ULONG nChars )
+{
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if ( pChild )
+ {
+ CommandExtTextInputPosData aData( (USHORT)nFirst, (USHORT)nChars, EXTTEXTINPUTPOS_NOSHOWPOS );
+ ImplCallExtTextInput( pChild, COMMAND_EXTTEXTINPUTPOS, &aData );
+ }
+ return pChild;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplHandleInputContextChange( Window* pWindow )
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleICursorPos( Window* pWindow, long& rX, long& rY,
+ long& rWidth, long& rHeight )
+{
+ rX = 0;
+ rY = 0;
+ rWidth = 0;
+ rHeight = 0;
+
+ Window* pChild = ImplGetKeyInputWindow( pWindow );
+ if ( pChild )
+ {
+ ImplCallExtTextInput( pChild, COMMAND_CURSORPOS );
+ Cursor* pCursor = pChild->GetCursor();
+ if ( pCursor )
+ {
+ Point aPos = pChild->ImplLogicToDevicePixel( pCursor->GetPos() );
+ rX = aPos.X();
+ rY = aPos.Y();
+ Size aSize = pChild->LogicToPixel( pCursor->GetSize() );
+ rWidth = aSize.Width();
+ rHeight = aSize.Height();
+ if ( !aSize.Width() )
+ rWidth = pChild->GetSettings().GetStyleSettings().GetCursorSize();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplCallWheelCommand( Window* pWindow, const Point& rPos,
+ const CommandWheelData* pWheelData )
+{
+ Point aCmdMousePos = pWindow->ImplFrameToOutput( rPos );
+ CommandEvent aCEvt( aCmdMousePos, COMMAND_WHEEL, TRUE, pWheelData );
+ NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
+ ImplDelData aDelData;
+ BOOL bPreNotify;
+ pWindow->ImplAddDel( &aDelData );
+ if ( !ImplCallPreNotify( aNCmdEvt ) && !aDelData.IsDelete() )
+ {
+ bPreNotify = FALSE;
+
+ pWindow->mbCommand = FALSE;
+ pWindow->Command( aCEvt );
+ }
+ else
+ bPreNotify = TRUE;
+ if ( aDelData.IsDelete() )
+ return FALSE;
+ pWindow->ImplRemoveDel( &aDelData );
+ if ( !bPreNotify && pWindow->mbCommand )
+ return TRUE;
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplHandleWheelEvent( Window* pWindow,
+ long nX, long nY, ULONG nMsgTime,
+ long nDelta, long nNotchDelta,
+ ULONG nScrollLines, USHORT nCode, BOOL bHorz )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ USHORT nMode;
+
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+
+ if ( nCode & KEY_MOD1 )
+ nMode = COMMAND_WHEEL_ZOOM;
+ else if ( nCode & KEY_SHIFT )
+ nMode = COMMAND_WHEEL_DATAZOOM;
+ else
+ nMode = COMMAND_WHEEL_SCROLL;
+
+ Point aMousePos( nX, nY );
+ CommandWheelData aWheelData( nDelta, nNotchDelta, nScrollLines, nMode, nCode, bHorz );
+ BOOL bRet = TRUE;
+
+ // Zuerst rufen wir den Command an dem Fenster, worueber die Maus steht
+ Window* pMouseWindow = pWindow->ImplFindWindow( aMousePos );
+ if ( pMouseWindow &&
+ pMouseWindow->IsEnabled() && pMouseWindow->IsInputEnabled() )
+ bRet = ImplCallWheelCommand( pMouseWindow, aMousePos, &aWheelData );
+
+ // Wenn das Fenster ueber dem die Maus steht, den Event nicht
+ // verarbeitet hat, rufen wir Command an dem Focus-Window
+ if ( bRet )
+ {
+ Window* pFocusWindow = pWindow->mpFrameData->mpFocusWin;
+ if ( pFocusWindow && (pFocusWindow != pMouseWindow) &&
+ (pFocusWindow == pSVData->maWinData.mpFocusWin) )
+ {
+ // no wheel-messages to disabled windows
+ if ( pFocusWindow->IsEnabled() && pFocusWindow->IsInputEnabled() )
+ bRet = ImplCallWheelCommand( pFocusWindow, aMousePos, &aWheelData );
+ }
+ }
+
+ return !bRet;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandlePaint( Window* pWindow, const Rectangle& rBoundRect )
+{
+ // Bei Paints vom System, auch Hintergrund-Sicherung aufgeben
+ Window* pSaveBackWin = pWindow->mpFrameData->mpFirstBackWin;
+ while ( pSaveBackWin )
+ {
+ Window* pNext = pSaveBackWin->mpOverlapData->mpNextBackWin;
+ Rectangle aRect( Point( pSaveBackWin->mnOutOffX, pSaveBackWin->mnOutOffY ),
+ Size( pSaveBackWin->mnOutWidth, pSaveBackWin->mnOutHeight ) );
+ if ( aRect.IsOver( rBoundRect ) )
+ pSaveBackWin->ImplDeleteOverlapBackground();
+ pSaveBackWin = pNext;
+ }
+
+ // Paint fuer alle Fenster ausloesen, die im neu zu malenden Bereich
+ // liegen
+ Region aRegion( rBoundRect );
+ pWindow->ImplInvalidateOverlapFrameRegion( aRegion );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplHandleResize( Window* pWindow, long nNewWidth, long nNewHeight )
+{
+ if ( (nNewWidth > 0) && (nNewHeight > 0) ||
+ pWindow->ImplGetWindow()->mbAllResize )
+ {
+ if ( (nNewWidth != pWindow->mnOutWidth) || (nNewHeight != pWindow->mnOutHeight) )
+ {
+ pWindow->mnOutWidth = nNewWidth;
+ pWindow->mnOutHeight = nNewHeight;
+ pWindow->mbWaitSystemResize = FALSE;
+ if ( pWindow->IsReallyVisible() )
+ pWindow->ImplSetClipFlag();
+ if ( pWindow->IsVisible() || pWindow->ImplGetWindow()->mbAllResize )
+ pWindow->Resize();
+ else
+ pWindow->mbCallResize = TRUE;
+ }
+ }
+
+ pWindow->mpFrameData->mbNeedSysWindow = (nNewWidth < IMPL_MIN_NEEDSYSWIN) ||
+ (nNewHeight < IMPL_MIN_NEEDSYSWIN);
+ pWindow->mpFrameData->mbMinimized = (nNewWidth <= 0) || (nNewHeight <= 0);
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplActivateFloatingWindows( Window* pWindow, BOOL bActive )
+{
+ // Zuerst alle ueberlappenden Fenster ueberpruefen
+ Window* pTempWindow = pWindow->mpFirstOverlap;
+ while ( pTempWindow )
+ {
+ if ( !pTempWindow->GetActivateMode() )
+ {
+ if ( (pTempWindow->GetType() == WINDOW_BORDERWINDOW) &&
+ (pTempWindow->ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
+ ((ImplBorderWindow*)pTempWindow)->SetDisplayActive( bActive );
+ }
+
+ ImplActivateFloatingWindows( pTempWindow, bActive );
+ pTempWindow = pTempWindow->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplAsyncFocusHdl, void*, EMPTYARG )
+{
+ mpFrameData->mnFocusId = 0;
+
+ // Wenn Status erhalten geblieben ist, weil wir den Focus in der
+ // zwischenzeit schon wiederbekommen haben, brauchen wir auch
+ // nichts machen
+ BOOL bHasFocus = mpFrameData->mbHasFocus || mpFrameData->mbSysObjFocus;
+
+ // Dann die zeitverzoegerten Funktionen ausfuehren
+ if ( bHasFocus )
+ {
+ // Alle FloatingFenster deaktiv zeichnen
+ if ( mpFrameData->mbStartFocusState != bHasFocus )
+ ImplActivateFloatingWindows( this, bHasFocus );
+
+ if ( mpFrameData->mpFocusWin )
+ {
+ if ( mpFrameData->mpFocusWin->IsEnabled() )
+ mpFrameData->mpFocusWin->GrabFocus();
+ else
+ mpFrameData->mpFocusWin->ImplGetFirstOverlapWindow()->GrabFocus();
+ }
+ else
+ GrabFocus();
+ }
+ else
+ {
+ Window* pFocusWin = mpFrameData->mpFocusWin;
+ if ( pFocusWin )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpFocusWin == pFocusWin )
+ {
+ // FocusWindow umsetzen
+ Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
+ pOverlapWindow->mpLastFocusWindow = pFocusWin;
+ pSVData->maWinData.mpFocusWin = NULL;
+
+ if ( pFocusWin->mpCursor )
+ pFocusWin->mpCursor->ImplHide();
+
+ // Deaktivate rufen
+ Window* pOldFocusWindow = pFocusWin;
+ if ( pOldFocusWindow )
+ {
+ Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
+ Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
+
+ pOldOverlapWindow->mbActive = FALSE;
+ pOldOverlapWindow->Deactivate();
+ if ( pOldRealWindow != pOldOverlapWindow )
+ {
+ pOldRealWindow->mbActive = FALSE;
+ pOldRealWindow->Deactivate();
+ }
+ }
+
+ // TrackingMode is ended in ImplHandleLoseFocus
+ pFocusWin->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
+ NotifyEvent aNEvt( EVENT_LOSEFOCUS, pFocusWin );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ pFocusWin->LoseFocus();
+ pFocusWin->ImplCallDeactivateListeners( NULL );
+ GetpApp()->FocusChanged();
+ }
+ }
+
+ // Alle FloatingFenster deaktiv zeichnen
+ if ( mpFrameData->mbStartFocusState != bHasFocus )
+ ImplActivateFloatingWindows( this, bHasFocus );
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleGetFocus( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ InvalidateSystemClipboard();
+
+ pWindow->mpFrameData->mbHasFocus = TRUE;
+
+ // Focus-Events zeitverzoegert ausfuehren, damit bei SystemChildFenstern
+ // nicht alles flackert, wenn diese den Focus bekommen
+ if ( !pWindow->mpFrameData->mnFocusId )
+ {
+ pWindow->mpFrameData->mbStartFocusState = !pWindow->mpFrameData->mbHasFocus;
+ Application::PostUserEvent( pWindow->mpFrameData->mnFocusId, LINK( pWindow, Window, ImplAsyncFocusHdl ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleLoseFocus( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Wenn wir den Focus verlieren gehen wir erst mal davon aus, dass sich das
+ // Systemclipboard aendert.
+ UpdateSystemClipboard();
+
+ // Wenn Frame den Focus verliert, brechen wir auch ein AutoScroll ab
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+
+ // Wenn Frame den Focus verliert, brechen wir auch ein Tracking ab
+ if ( pSVData->maWinData.mpTrackWin )
+ {
+ if ( pSVData->maWinData.mpTrackWin->mpFrameWindow == pWindow )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ // handle FloatingMode
+ // hier beenden wir immer den PopupModus, auch dann, wenn NOFOCUSCLOSE
+ // gesetzt ist, damit wir nicht beim Wechsel noch Fenster stehen lassen
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) )
+ pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+
+ pWindow->mpFrameData->mbHasFocus = FALSE;
+
+ // Focus-Events zeitverzoegert ausfuehren, damit bei SystemChildFenstern
+ // nicht alles flackert, wenn diese den Focus bekommen
+ if ( !pWindow->mpFrameData->mnFocusId )
+ {
+ pWindow->mpFrameData->mbStartFocusState = !pWindow->mpFrameData->mbHasFocus;
+ Application::PostUserEvent( pWindow->mpFrameData->mnFocusId, LINK( pWindow, Window, ImplAsyncFocusHdl ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplHandleClose( Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Bei Close schliessen wir erstmal alle FloatingModi mit
+ // und brechen auch sonstige Ablaeufe
+ if ( pSVData->maWinData.mpFirstFloat )
+ {
+ FloatingWindow* pLastLevelFloat;
+ pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
+ pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
+ }
+ if ( pSVData->maHelpData.mbExtHelpMode )
+ Help::EndExtHelp();
+ if ( pSVData->maHelpData.mpHelpWin )
+ ImplDestroyHelpWindow();
+ // AutoScrollMode
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ DragManager* pDragManager = DragManager::GetDragManager();
+ if ( pDragManager )
+ {
+ pWindow->ImplGenerateMouseMove();
+ pDragManager->Escape( pWindow );
+ }
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL | ENDTRACK_KEY );
+
+ // Dann stellen wir fest, ob Close ueberhaupt erlaubt ist
+ SystemWindow* pSysWindow = (SystemWindow*)pWindow->ImplGetWindow();
+ if ( !pSysWindow->IsEnabled() || !pSysWindow->IsInputEnabled() )
+ Sound::Beep( SOUND_DISABLE, pSysWindow );
+ else
+ pSysWindow->Close();
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleUserEvent( ImplSVEvent* pSVEvent )
+{
+ if ( pSVEvent )
+ {
+ if ( pSVEvent->mbCall && !pSVEvent->maDelData.IsDelete() )
+ {
+ if ( pSVEvent->mpWindow )
+ {
+ pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
+ if ( pSVEvent->mpLink )
+ pSVEvent->mpLink->Call( pSVEvent->mpData );
+ else
+ pSVEvent->mpWindow->UserEvent( pSVEvent->mnEvent, pSVEvent->mpData );
+ }
+ else
+ {
+ if ( pSVEvent->mpLink )
+ pSVEvent->mpLink->Call( pSVEvent->mpData );
+ else
+ GetpApp()->UserEvent( pSVEvent->mnEvent, pSVEvent->mpData );
+ }
+ }
+
+ delete pSVEvent->mpLink;
+ delete pSVEvent;
+ }
+}
+
+// =======================================================================
+
+#ifndef REMOTE_APPSERVER
+
+static USHORT ImplGetMouseMoveMode( SalMouseEvent* pEvent )
+{
+ USHORT nMode = 0;
+ if ( !pEvent->mnCode )
+ nMode |= MOUSE_SIMPLEMOVE;
+ if ( (pEvent->mnCode & MOUSE_LEFT) && !(pEvent->mnCode & KEY_MOD1) )
+ nMode |= MOUSE_DRAGMOVE;
+ if ( (pEvent->mnCode & MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) )
+ nMode |= MOUSE_DRAGCOPY;
+ return nMode;
+}
+
+// -----------------------------------------------------------------------
+
+static USHORT ImplGetMouseButtonMode( SalMouseEvent* pEvent )
+{
+ USHORT nMode = 0;
+ if ( pEvent->mnButton == MOUSE_LEFT )
+ nMode |= MOUSE_SIMPLECLICK;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT)) )
+ nMode |= MOUSE_SELECT;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) &&
+ !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_SHIFT)) )
+ nMode |= MOUSE_MULTISELECT;
+ if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_SHIFT) &&
+ !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_MOD1)) )
+ nMode |= MOUSE_RANGESELECT;
+ return nMode;
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseLeave( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, TRUE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime, pEvent->mnCode,
+ ImplGetMouseMoveMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseMove( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEMOVE, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime, pEvent->mnCode,
+ ImplGetMouseMoveMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseButtonDown( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEBUTTONDOWN, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime,
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
+ ImplGetMouseButtonMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+inline long ImplHandleSalMouseButtonUp( Window* pWindow, SalMouseEvent* pEvent )
+{
+ return ImplHandleMouseEvent( pWindow, EVENT_MOUSEBUTTONUP, FALSE,
+ pEvent->mnX, pEvent->mnY,
+ pEvent->mnTime,
+ pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
+ ImplGetMouseButtonMode( pEvent ) );
+}
+
+// -----------------------------------------------------------------------
+
+long ImplHandleSalMouseActivate( Window* pWindow, SalMouseActivateEvent* pEvent )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalKeyMod( Window* pWindow, SalKeyModEvent* pEvent )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ Window* pTrackWin = pSVData->maWinData.mpTrackWin;
+ if ( pTrackWin )
+ pWindow = pTrackWin;
+ USHORT nOldCode = pWindow->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
+ USHORT nNewCode = pEvent->mnCode;
+ if ( nOldCode != nNewCode )
+ {
+ nNewCode |= pWindow->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
+ pWindow->mpFrameWindow->ImplCallMouseMove( nNewCode, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalSettings( Window* pWindow, USHORT nEvent )
+{
+ // Application Notification werden nur fuer das AppWindow ausgeloest
+ SystemWindow* pSysWindow = (SystemWindow*)pWindow->ImplGetWindow();
+ WorkWindow* pAppWin = Application::GetAppWindow();
+
+ if ( pAppWin && (pSysWindow != pAppWin) )
+ return;
+
+ Application* pApp = GetpApp();
+ if ( nEvent == SALEVENT_SETTINGSCHANGED )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ AllSettings aSettings = pApp->GetSettings();
+ // International so umsetzen, das Daten durch
+ // UpdateInternationalSystemTables() nicht geaendert werden,
+ // damit wir feststellen koennen, ob sich Einstellungen
+ // geaendert haben
+ International aIntn = aSettings.GetInternational();
+ aIntn.SetQuotationMarkStart( aIntn.GetQuotationMarkStart() );
+ aIntn.SetDateFormat( aIntn.GetDateFormat() );
+ UpdateInternationalSystemTables();
+ if ( aIntn != aSettings.GetInternational() )
+ pSVData->maAppData.mbIntnChanged = TRUE;
+ pApp->MergeSystemSettings( aSettings );
+ pApp->SystemSettingsChanging( aSettings, pWindow );
+ pApp->SetSettings( aSettings );
+ pSVData->maAppData.mbIntnChanged = FALSE;
+ }
+ else
+ {
+ USHORT nType;
+ switch ( nEvent )
+ {
+ case SALEVENT_VOLUMECHANGED:
+ nType = 0;
+ break;
+ case SALEVENT_PRINTERCHANGED:
+ ImplDeletePrnQueueList();
+ nType = DATACHANGED_PRINTER;
+ break;
+ case SALEVENT_DISPLAYCHANGED:
+ nType = DATACHANGED_DISPLAY;
+ break;
+ case SALEVENT_FONTCHANGED:
+ OutputDevice::ImplUpdateAllFontData( TRUE );
+ nType = DATACHANGED_FONTS;
+ break;
+ case SALEVENT_DATETIMECHANGED:
+ nType = DATACHANGED_DATETIME;
+ break;
+ case SALEVENT_KEYBOARDCHANGED:
+ nType = 0;
+ break;
+ default:
+ nType = 0;
+ break;
+ }
+
+ if ( nType )
+ {
+ DataChangedEvent aDCEvt( nType );
+ pApp->DataChanged( aDCEvt );
+ pApp->NotifyAllWindows( aDCEvt );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplHandleSalExtTextInputPos( Window* pWindow, SalExtTextInputPosEvent* pEvt )
+{
+ Window* pChild = ImplHandleExtTextInputPos( pWindow, pEvt->mnFirstPos, pEvt->mnChars );
+ if ( pChild )
+ {
+ USHORT nStart = pChild->GetExtTextInputPosStart();
+ USHORT nCount = pChild->GetExtTextInputPosCount();
+ const Rectangle* pAry = pChild->GetExtTextInputPosAry();
+ USHORT nPos;
+ for ( USHORT i = 0; i < pEvt->mnChars; i++ )
+ {
+ nPos = i+(USHORT)pEvt->mnFirstPos;
+ if ( (nPos >= nStart) && (nPos < nStart+nCount) )
+ {
+ SalExtCharPos* pSalPos = pEvt->mpPosAry+i;
+ const Rectangle* pPos = pAry+(nPos-nStart);
+ pSalPos->mnX = pChild->ImplLogicXToDevicePixel( pPos->Left() );
+ pSalPos->mnY = pChild->ImplLogicYToDevicePixel( pPos->Top() );
+ pSalPos->mnWidth = pChild->ImplLogicWidthToDevicePixel( pPos->GetWidth() );
+ pSalPos->mnHeight = pChild->ImplLogicHeightToDevicePixel( pPos->GetHeight() );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ImplWindowFrameProc( void* pInst, SalFrame* pFrame,
+ USHORT nEvent, const void* pEvent )
+{
+ DBG_TESTSOLARMUTEX();
+
+ long nRet = 0;
+
+ switch ( nEvent )
+ {
+ case SALEVENT_MOUSEMOVE:
+ nRet = ImplHandleSalMouseMove( (Window*)pInst, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_MOUSELEAVE:
+ nRet = ImplHandleSalMouseLeave( (Window*)pInst, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_MOUSEBUTTONDOWN:
+ nRet = ImplHandleSalMouseButtonDown( (Window*)pInst, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_MOUSEBUTTONUP:
+ nRet = ImplHandleSalMouseButtonUp( (Window*)pInst, (SalMouseEvent*)pEvent );
+ break;
+ case SALEVENT_MOUSEACTIVATE:
+ nRet = ImplHandleSalMouseActivate( (Window*)pInst, (SalMouseActivateEvent*)pEvent );
+ break;
+
+ case SALEVENT_KEYINPUT:
+ {
+ SalKeyEvent* pKeyEvt = (SalKeyEvent*)pEvent;
+ nRet = ImplHandleKey( (Window*)pInst, EVENT_KEYINPUT,
+ pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat );
+ }
+ break;
+ case SALEVENT_KEYUP:
+ {
+ SalKeyEvent* pKeyEvt = (SalKeyEvent*)pEvent;
+ nRet = ImplHandleKey( (Window*)pInst, EVENT_KEYUP,
+ pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat );
+ }
+ break;
+ case SALEVENT_KEYMODCHANGE:
+ ImplHandleSalKeyMod( (Window*)pInst, (SalKeyModEvent*)pEvent );
+ break;
+
+ case SALEVENT_WHEELMOUSE:
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+
+ SalWheelMouseEvent* pWheelEvt = (SalWheelMouseEvent*)pEvent;
+ nRet = ImplHandleWheelEvent( (Window*)pInst,
+ pWheelEvt->mnX, pWheelEvt->mnY,
+ pWheelEvt->mnTime,
+ pWheelEvt->mnDelta,
+ pWheelEvt->mnNotchDelta,
+ pWheelEvt->mnScrollLines,
+ pWheelEvt->mnCode, pWheelEvt->mbHorz );
+ }
+ break;
+
+ case SALEVENT_PAINT:
+ {
+ SalPaintEvent* pPaintEvt = (SalPaintEvent*)pEvent;
+ Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
+ Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
+ ImplHandlePaint( (Window*)pInst, aBoundRect );
+ }
+ break;
+
+ case SALEVENT_RESIZE:
+ {
+ long nNewWidth;
+ long nNewHeight;
+ ((Window*)pInst)->mpFrame->GetClientSize( nNewWidth, nNewHeight );
+ ImplHandleResize( (Window*)pInst, nNewWidth, nNewHeight );
+ }
+ break;
+
+ case SALEVENT_GETFOCUS:
+ ImplHandleGetFocus( (Window*)pInst );
+ break;
+ case SALEVENT_LOSEFOCUS:
+ ImplHandleLoseFocus( (Window*)pInst );
+ break;
+
+ case SALEVENT_CLOSE:
+ ImplHandleClose( (Window*)pInst );
+ break;
+
+ case SALEVENT_SHUTDOWN:
+ if ( Application::GetAppWindow() == ((WorkWindow*)pInst)->ImplGetWindow() )
+ {
+ if ( GetpApp()->QueryExit() )
+ {
+ // Message-Schleife beenden
+ Application::Quit();
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ break;
+
+ case SALEVENT_SETTINGSCHANGED:
+ case SALEVENT_VOLUMECHANGED:
+ case SALEVENT_PRINTERCHANGED:
+ case SALEVENT_DISPLAYCHANGED:
+ case SALEVENT_FONTCHANGED:
+ case SALEVENT_DATETIMECHANGED:
+ case SALEVENT_KEYBOARDCHANGED:
+ ImplHandleSalSettings( (Window*)pInst, nEvent );
+ break;
+
+ case SALEVENT_USEREVENT:
+ ImplHandleUserEvent( (ImplSVEvent*)pEvent );
+ break;
+
+ case SALEVENT_STARTEXTTEXTINPUT:
+ ImplHandleStartExtTextInput( (Window*)pInst );
+ break;
+ case SALEVENT_EXTTEXTINPUT:
+ {
+ SalExtTextInputEvent* pEvt = (SalExtTextInputEvent*)pEvent;
+ ImplHandleExtTextInput( (Window*)pInst, pEvt->mnTime,
+ pEvt->maText, pEvt->mpTextAttr,
+ pEvt->mnCursorPos, pEvt->mbCursorVisible,
+ pEvt->mnDeltaStart, pEvt->mbOnlyCursor );
+ }
+ break;
+ case SALEVENT_ENDEXTTEXTINPUT:
+ ImplHandleEndExtTextInput( (Window*)pInst );
+ break;
+ case SALEVENT_EXTTEXTINPUTPOS:
+ ImplHandleSalExtTextInputPos( (Window*)pInst, (SalExtTextInputPosEvent*)pEvent );
+ break;
+ case SALEVENT_INPUTCONTEXTCHANGE:
+ {
+ ImplHandleInputContextChange( (Window*)pInst );
+ }
+ break;
+
+ case SALEVENT_CURSORPOS:
+ {
+ SalCursorPosEvent* pEvt = (SalCursorPosEvent*)pEvent;
+ ImplHandleICursorPos( (Window*)pInst,
+ pEvt->mnX, pEvt->mnY,
+ pEvt->mnWidth, pEvt->mnHeight );
+ }
+ break;
+
+#ifdef DBG_UTIL
+ default:
+ DBG_ERROR1( "ImplWindowFrameProc(): unknown event (%lu)", (ULONG)nEvent );
+ break;
+#endif
+ }
+
+ return nRet;
+}
+
+#else // => REMOTE_APPSERVER
+
+void ImplRemoteWindowFrameProc( ExtRmEvent* pEvent )
+{
+ DBG_TESTSOLARMUTEX();
+
+ ULONG nId = pEvent->GetId();
+ switch ( nId )
+ {
+ case RMEVENT_KEYINPUT:
+ {
+ RmKeyEventData* pData = (RmKeyEventData*)pEvent->GetData();
+ ImplHandleKey( pEvent->GetWindow(), EVENT_KEYINPUT,
+ pData->nKeyCode, pData->nChar, pData->nCount );
+ }
+ break;
+ case RMEVENT_KEYUP:
+ {
+ RmKeyEventData* pData = (RmKeyEventData*)pEvent->GetData();
+ ImplHandleKey( pEvent->GetWindow(), EVENT_KEYUP,
+ pData->nKeyCode, pData->nChar, 0 );
+ }
+ break;
+ case RMEVENT_MOUSEBUTTONDOWN:
+ case RMEVENT_MOUSEBUTTONUP:
+ case RMEVENT_MOUSEMOVE:
+ {
+ USHORT nSVEvent;
+ if ( nId == RMEVENT_MOUSEBUTTONDOWN )
+ nSVEvent = EVENT_MOUSEBUTTONDOWN;
+ else if ( nId == RMEVENT_MOUSEBUTTONUP )
+ nSVEvent = EVENT_MOUSEBUTTONUP;
+ else
+ nSVEvent = EVENT_MOUSEMOVE;
+ RmMouseEventData* pData = (RmMouseEventData*)pEvent->GetData();
+ BOOL bMouseLeave = ( pData->nMode & MOUSE_LEAVEWINDOW ) ? TRUE : FALSE;
+ pData->nMode &= ~(MOUSE_ENTERWINDOW|MOUSE_LEAVEWINDOW);
+
+ // Bei MOUSE_MOVE eine Bestaetigung zurueckschicken, damit der
+ // RClient solange verzoegert...
+ // Vorm ImplHandleMouseEvent, falls dort z.B. ein modaler Dialog
+ // aufgemacht wird.
+ if ( nId == RMEVENT_MOUSEMOVE )
+ {
+ DBG_ASSERT( pEvent->GetWindow()->ImplGetFrame(), "RemoteWindowProc: Frame?" );
+ if ( pEvent->GetWindow()->ImplGetFrame() )
+ pEvent->GetWindow()->ImplGetFrame()->MouseMoveProcessed();
+ }
+
+ ImplHandleMouseEvent( pEvent->GetWindow(), nSVEvent, bMouseLeave,
+ pData->nX, pData->nY, pData->nSysTime,
+ pData->nCode, pData->nMode );
+
+ }
+ break;
+ case RMEVENT_PAINT:
+ {
+ Rectangle* pRect = (Rectangle*)pEvent->GetData();
+ ImplHandlePaint( pEvent->GetWindow(), *pRect );
+ }
+ break;
+ case RMEVENT_RESIZE:
+ {
+ Size* pSize = (Size*)pEvent->GetData();
+ ImplHandleResize( pEvent->GetWindow(), pSize->Width(), pSize->Height() );
+ }
+ break;
+ case RMEVENT_USEREVENT:
+ {
+ ImplHandleUserEvent( (ImplSVEvent*)pEvent->GetData() );
+ }
+ break;
+ case RMEVENT_CLOSE:
+ {
+ ImplHandleClose( pEvent->GetWindow() );
+ }
+ break;
+ case RMEVENT_GETFOCUS:
+ {
+ ImplHandleGetFocus( pEvent->GetWindow() );
+ };
+ break;
+ case RMEVENT_LOSEFOCUS:
+ {
+ ImplHandleLoseFocus( pEvent->GetWindow() );
+ };
+ break;
+ case RMEVENT_MOUSEWHEEL:
+ {
+ RmMouseWheelEventData* pData = (RmMouseWheelEventData*)pEvent->GetData();
+ ImplHandleWheelEvent( pEvent->GetWindow(),
+ pData->nX,
+ pData->nY,
+ pData->nSysTime,
+ pData->nDelta,
+ pData->nNotchDelta,
+ pData->nScrollLines,
+ pData->nCode,
+ pData->bHorz );
+ };
+ break;
+ }
+}
+
+#endif
diff --git a/vcl/source/window/wrkwin.cxx b/vcl/source/window/wrkwin.cxx
new file mode 100644
index 000000000000..1dd4d2a4e632
--- /dev/null
+++ b/vcl/source/window/wrkwin.cxx
@@ -0,0 +1,424 @@
+/*************************************************************************
+ *
+ * $RCSfile: wrkwin.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WRKWIN_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include <rmwindow.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_BRDWIN_HXX
+#include <brdwin.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+
+#include <rvp.hxx>
+
+#pragma hdrstop
+
+// =======================================================================
+
+#define WORKWIN_WINDOWSTATE_FULLSCREEN ((ULONG)0x00010000)
+#define WORKWIN_WINDOWSTATE_ALL ((ULONG)0x00FF0000)
+
+// =======================================================================
+
+void WorkWindow::ImplInitData()
+{
+ mnIcon = 0;
+ mnPresentationFlags = 0;
+ mbPresentationMode = FALSE;
+ mbPresentationVisible = FALSE;
+ mbPresentationFull = FALSE;
+ mbFullScreenMode = FALSE;
+ mbSysChild = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
+{
+#ifdef REMOTE_APPSERVER
+ static ::com::sun::star::uno::Any aVoid;
+ DBG_ASSERT( ! pSystemParentData, "SystemParentData not implemented in remote vcl" );
+ ImplInit( pParent, nStyle, aVoid );
+#else
+ USHORT nFrameStyle = BORDERWINDOW_STYLE_FRAME;
+ if ( nStyle & WB_APP )
+ nFrameStyle |= BORDERWINDOW_STYLE_APP;
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, pSystemParentData, nStyle, nFrameStyle );
+ Window::ImplInit( pBorderWin, nStyle & (WB_3DLOOK | WB_CLIPCHILDREN | WB_DIALOGCONTROL), NULL );
+ pBorderWin->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpBorderWindow = pBorderWin;
+// mpRealParent = pParent; // !!! Muesste eigentlich gesetzt werden, aber wegen Fehlern mit dem MenuBar erstmal nicht gesetzt !!!
+
+ if ( nStyle & WB_APP )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ DBG_ASSERT( !pSVData->maWinData.mpAppWin, "WorkWindow::WorkWindow(): More than one window with style WB_APP" );
+ pSVData->maWinData.mpAppWin = this;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplInit( Window* pParent, WinBits nStyle, const ::com::sun::star::uno::Any& aSystemWorkWindowToken )
+{
+#ifndef REMOTE_APPSERVER
+ if( aSystemWorkWindowToken.hasValue() )
+ {
+ ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
+ aSystemWorkWindowToken >>= aSeq;
+ SystemParentData* pData = (SystemParentData*)aSeq.getArray();
+ DBG_ASSERT( aSeq.getLength() == sizeof( SystemParentData ) && pData->nSize == sizeof( SystemParentData ), "WorkWindow::WorkWindow( Window*, const Any&, WinBits ) called with invalid Any" );
+ // init with style 0 as does WorkWindow::WorkWindow( SystemParentData* );
+ ImplInit( pParent, 0, pData );
+ }
+ else
+ ImplInit( pParent, nStyle, NULL );
+#else
+ USHORT nFrameStyle = BORDERWINDOW_STYLE_FRAME;
+ if ( nStyle & WB_APP )
+ nFrameStyle |= BORDERWINDOW_STYLE_APP;
+ ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle, nFrameStyle, aSystemWorkWindowToken );
+ Window::ImplInit( pBorderWin, nStyle & (WB_3DLOOK | WB_CLIPCHILDREN | WB_DIALOGCONTROL), aSystemWorkWindowToken );
+ pBorderWin->mpClientWindow = this;
+ pBorderWin->GetBorder( mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder );
+ mpBorderWindow = pBorderWin;
+// mpRealParent = pParent; // !!! Muesste eigentlich gesetzt werden, aber wegen Fehlern mit dem MenuBar erstmal nicht gesetzt !!!
+
+ if ( nStyle & WB_APP )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ DBG_ASSERT( !pSVData->maWinData.mpAppWin, "WorkWindow::WorkWindow(): More than one window with style WB_APP" );
+ pSVData->maWinData.mpAppWin = this;
+ }
+
+ SetActivateMode( ACTIVATE_MODE_GRABFOCUS );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( WindowType nType ) :
+ SystemWindow( nType )
+{
+ ImplInitData();
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, WinBits nStyle ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitData();
+ ImplInit( pParent, nStyle, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, const ResId& rResId ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitData();
+ rResId.SetRT( RSC_WORKWIN );
+ ImplInit( pParent, ImplInitRes( rResId ) );
+ ImplLoadRes( rResId );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( Window* pParent, const ::com::sun::star::uno::Any& aSystemWorkWindowToken, WinBits nStyle ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitData();
+ mbSysChild = TRUE;
+ ImplInit( pParent, nStyle, aSystemWorkWindowToken );
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::WorkWindow( SystemParentData* pParent ) :
+ SystemWindow( WINDOW_WORKWINDOW )
+{
+ ImplInitData();
+ mbSysChild = TRUE;
+ ImplInit( NULL, 0, pParent );
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ImplLoadRes( const ResId& rResId )
+{
+ SystemWindow::ImplLoadRes( rResId );
+
+ USHORT nShowStyle = ReadShortRes();
+ if ( !(rResId.aWinBits & WB_HIDE) && (RSC_WORKWIN == rResId.GetRT()) )
+ Show();
+}
+
+// -----------------------------------------------------------------------
+
+WorkWindow::~WorkWindow()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpAppWin == this )
+ {
+ pSVData->maWinData.mpAppWin = NULL;
+ Application::Quit();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::SetIcon( USHORT nIcon )
+{
+ if ( mnIcon == nIcon )
+ return;
+
+ mnIcon = nIcon;
+ if ( !mbSysChild )
+ mpFrame->SetIcon( nIcon );
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::SetWindowState( const ByteString& rStr )
+{
+ if ( mbSysChild )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ SalFrameState aState;
+ USHORT nIndex = 0;
+ aState.mnX = rStr.GetToken( 0, ',', nIndex ).ToInt32();
+ aState.mnY = rStr.GetToken( 0, ',', nIndex ).ToInt32();
+ aState.mnWidth = rStr.GetToken( 0, ',', nIndex ).ToInt32();
+ aState.mnHeight = rStr.GetToken( 0, ';', nIndex ).ToInt32();
+ if ( nIndex != STRING_NOTFOUND )
+ {
+ if ( IsFullScreenMode() )
+ ShowFullScreenMode( FALSE );
+
+ ULONG nState = rStr.Copy( nIndex ).ToInt32();
+ aState.mnState = nState & ~WORKWIN_WINDOWSTATE_ALL;
+ mpFrame->SetWindowState( &aState );
+
+ if ( nState & WORKWIN_WINDOWSTATE_FULLSCREEN )
+ ShowFullScreenMode( TRUE );
+ }
+#else
+ mpFrame->SetWindowState( String::CreateFromAscii(rStr.GetBuffer()) );
+#endif
+
+ // Syncrones Resize ausloesen, damit wir nach Moeglichkeit gleich
+ // mit der richtigen Groesse rechnen
+ // Oberstes BorderWindow ist das Window, welches positioniert werden soll
+ Window* pWindow = this;
+ while ( pWindow->mpBorderWindow )
+ pWindow = pWindow->mpBorderWindow;
+
+ // Syncrones Resize ausloesen, damit wir nach Moeglichkeit gleich
+ // mit der richtigen Groesse rechnen
+ long nNewWidth;
+ long nNewHeight;
+ pWindow->mpFrame->GetClientSize( nNewWidth, nNewHeight );
+ ImplHandleResize( pWindow, nNewWidth, nNewHeight );
+}
+
+// -----------------------------------------------------------------------
+
+ByteString WorkWindow::GetWindowState() const
+{
+ if ( mbSysChild )
+ return ImplGetSVEmptyByteStr();
+
+#ifndef REMOTE_APPSERVER
+ ByteString aStr;
+ SalFrameState aState;
+ if ( mpFrame->GetWindowState( &aState ) )
+ {
+ // FullScreen merken wir uns auch
+ if ( IsFullScreenMode() )
+ aState.mnState |= WORKWIN_WINDOWSTATE_FULLSCREEN;
+
+ aStr.Append( ByteString::CreateFromInt32( aState.mnX ) );
+ aStr.Append( ',' );
+ aStr.Append( ByteString::CreateFromInt32( aState.mnY ) );
+ aStr.Append( ',' );
+ aStr.Append( ByteString::CreateFromInt32( aState.mnWidth ) );
+ aStr.Append( ',' );
+ aStr.Append( ByteString::CreateFromInt32( aState.mnHeight ) );
+ aStr.Append( ';' );
+ aStr.Append( ByteString::CreateFromInt32( aState.mnState ) );
+ }
+ return aStr;
+#else
+ return (ByteString)::rtl::OUStringToOString( mpFrame->GetWindowState() , RTL_TEXTENCODING_ASCII_US );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::ShowFullScreenMode( BOOL bFullScreenMode )
+{
+ if ( !mbFullScreenMode == !bFullScreenMode )
+ return;
+
+ mbFullScreenMode = bFullScreenMode != 0;
+ if ( !mbSysChild )
+ {
+ mpFrameWindow->mbWaitSystemResize = TRUE;
+ ImplGetFrame()->ShowFullScreen( bFullScreenMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WorkWindow::StartPresentationMode( BOOL bPresentation, USHORT nFlags )
+{
+ if ( !bPresentation == !mbPresentationMode )
+ return;
+
+ if ( bPresentation )
+ {
+ mbPresentationMode = TRUE;
+ mbPresentationVisible = IsVisible();
+ mbPresentationFull = mbFullScreenMode;
+ mnPresentationFlags = nFlags;
+
+ if ( !(mnPresentationFlags & PRESENTATION_NOFULLSCREEN) )
+ ShowFullScreenMode( TRUE );
+#ifndef REMOTE_APPSERVER
+ if ( !mbSysChild )
+ {
+ if ( mnPresentationFlags & PRESENTATION_HIDEALLAPPS )
+ mpFrame->SetAlwaysOnTop( TRUE );
+ if ( !(mnPresentationFlags & PRESENTATION_NOAUTOSHOW) )
+ ToTop();
+ mpFrame->StartPresentation( TRUE );
+ }
+#else
+ if ( !mbSysChild )
+ mpFrame->StartPresentation( TRUE, nFlags | PRESENTATION_NOFULLSCREEN | PRESENTATION_NOAUTOSHOW );
+#endif
+
+ if ( !(mnPresentationFlags & PRESENTATION_NOAUTOSHOW) )
+ Show();
+ }
+ else
+ {
+ Show( mbPresentationVisible );
+#ifndef REMOTE_APPSERVER
+ if ( !mbSysChild )
+ {
+ mpFrame->StartPresentation( FALSE );
+ if ( mnPresentationFlags & PRESENTATION_HIDEALLAPPS )
+ mpFrame->SetAlwaysOnTop( FALSE );
+ }
+#else
+ if ( !mbSysChild )
+ mpFrame->StartPresentation( FALSE, mnPresentationFlags | PRESENTATION_NOFULLSCREEN | PRESENTATION_NOAUTOSHOW );
+#endif
+ ShowFullScreenMode( mbPresentationFull );
+
+ mbPresentationMode = FALSE;
+ mbPresentationVisible = FALSE;
+ mbPresentationFull = FALSE;
+ mnPresentationFlags = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL WorkWindow::IsMinimized() const
+{
+ return mpFrameData->mbMinimized;
+}