summaryrefslogtreecommitdiff
path: root/app/wlib/mswlib
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/mswlib')
-rw-r--r--app/wlib/mswlib/CMakeLists.txt39
-rw-r--r--app/wlib/mswlib/ChangeLog146
-rw-r--r--app/wlib/mswlib/checksum.c42
-rw-r--r--app/wlib/mswlib/dynarr.h40
-rw-r--r--app/wlib/mswlib/getopt.c87
-rw-r--r--app/wlib/mswlib/gwin32.c146
-rw-r--r--app/wlib/mswlib/mswbitmap.c508
-rw-r--r--app/wlib/mswlib/mswbox.c119
-rw-r--r--app/wlib/mswlib/mswbutt.c387
-rw-r--r--app/wlib/mswlib/mswchksm.c125
-rw-r--r--app/wlib/mswlib/mswchoic.c423
-rw-r--r--app/wlib/mswlib/mswcolor.c362
-rw-r--r--app/wlib/mswlib/mswdraw.c1783
-rw-r--r--app/wlib/mswlib/mswedit.c726
-rw-r--r--app/wlib/mswlib/mswint.h193
-rw-r--r--app/wlib/mswlib/mswlines.c98
-rw-r--r--app/wlib/mswlib/mswlist.c1173
-rw-r--r--app/wlib/mswlib/mswmenu.c1062
-rw-r--r--app/wlib/mswlib/mswmisc.c2778
-rw-r--r--app/wlib/mswlib/mswmsg.c212
-rw-r--r--app/wlib/mswlib/mswpref.c274
-rw-r--r--app/wlib/mswlib/mswprint.c387
-rw-r--r--app/wlib/mswlib/mswsplash.c266
-rw-r--r--app/wlib/mswlib/mswtext.c383
-rw-r--r--app/wlib/mswlib/simple-gettext.c522
-rw-r--r--app/wlib/mswlib/square10.bmp6
26 files changed, 12287 insertions, 0 deletions
diff --git a/app/wlib/mswlib/CMakeLists.txt b/app/wlib/mswlib/CMakeLists.txt
new file mode 100644
index 0000000..0c69610
--- /dev/null
+++ b/app/wlib/mswlib/CMakeLists.txt
@@ -0,0 +1,39 @@
+FILE(GLOB HEADERS *.h)
+
+SET(SOURCES
+# checksum.c
+ getopt.c
+ mswbox.c
+ mswbutt.c
+ mswbitmap.c
+ mswchksm.c
+ mswchoic.c
+ mswcolor.c
+ mswdraw.c
+ mswedit.c
+ mswlines.c
+ mswlist.c
+ mswmenu.c
+ mswmisc.c
+ mswmsg.c
+ mswpref.c
+ mswprint.c
+ mswsplash.c
+ mswtext.c
+ gwin32.c
+ simple-gettext.c
+ )
+
+INCLUDE_DIRECTORIES(${XTrkCAD_BINARY_DIR})
+# INCLUDE_DIRECTORIES(${XTRKCAD_BINARY_DIR})
+
+IF(XTRKCAD_USE_GETTEXT)
+ IF(WIN32)
+ ADD_DEFINITIONS(-DUSE_SIMPLE_GETTEXT )
+ ENDIF(WIN32)
+ENDIF(XTRKCAD_USE_GETTEXT)
+
+ADD_LIBRARY(xtrkcad-wlib ${HEADERS} ${SOURCES})
+
+TARGET_LINK_LIBRARIES(xtrkcad-wlib Htmlhelp msimg32 shlwapi)
+
diff --git a/app/wlib/mswlib/ChangeLog b/app/wlib/mswlib/ChangeLog
new file mode 100644
index 0000000..84c17a7
--- /dev/null
+++ b/app/wlib/mswlib/ChangeLog
@@ -0,0 +1,146 @@
+Apr 28, 2010
+ FIX: Daniel Spagnol
+ mswmisc.c: now, wGetAppLibDir can be called before wWinMainCreate is
+ called.
+
+Jan 09, 2010
+ ENH: Martin Fischer
+ mswmisc.c: get command line parameter handling correct
+ plus some refactoring
+
+Dec 12, 2009
+ FIX: Martin Fischer
+ mswmisc.c: minor refactoring to stay compatible with the
+ work on gtkwindow.c
+
+Sep 20. 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ CMakeLists.txt, mswbitmap.c, mswmisc.c, mswint.h:
+ new source file for bitmap functions, added bitmap
+ control to controls available to the application
+
+Sep 02, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswbutt.c, mswint.h, mswlist.c mswmisc.c:
+ improved XPM reading including true transparency
+
+Aug 16, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ gwin32.c mswchoic.c mswint.h simple-gettext.c CMakeLists.txt:
+ add simple gettext support
+
+Jul 24, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: correct initialization for argv, add option
+ to select configuration file, remove obsolete Win16 code
+
+Jul 10, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: initialize the argument array properly
+ CMakeLists.txt, getopt.c: add getopt()
+
+Version 4.0.3a
+==============
+
+Jun 05, 2009
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: GPF when loading XPM icons fixed
+
+May 28, 2009
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: wrong options for wNotice fixed
+
+May 15, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswdraw.c, mswmisc.c, mswpref.c: more message boxes with icon
+
+ May 08, 2009
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c, wlib.h: add new message box with icon
+
+Sep 05, 2008
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: enhance look of tooltip
+
+Jul 11, 2008
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswchoic.c: i18n support
+ mswmenu.c, mswmisc.c: code cleanup and added comments
+
+Jul 10, 2008
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: allow user to cancel window close request
+
+Jun 12, 2008
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmsg.c: redraw problem for large font fixed
+
+Apr 05, 2008
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc,.c mswint.c: improved XPM support
+
+Mar 29, 2008
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswbutt.c: new look for toolbar buttons
+
+Mar 17, 2008
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswchoic.c: Label size was not calculated correctly for radio button
+ options.
+
+Feb 23,2008
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswpref.c: Create the correct full path for shared data directory
+
+Jan 24,2008
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswdraw.c, mswmisc.c: fixed some compiler warnings
+
+Jan 28, 2008
+ FIX: Mikko Nissinen <mni77@users.sourceforge.net>
+ mswmisc.c: Dynamically allocate and form some global translatable
+ strings.
+
+Jan 24,2008
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswpref.c: increase floting point precision when storing floats in INI
+ file
+
+Jan 22, 2008
+ ENH: Mikko Nissinen <mni77@users.sourceforge.net>
+ mswmisc.c: WinMain(): Free user locale before exit.
+
+Dec 16, 2007
+ IMPROVMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswpref.c: use XTrackCad as directory name for configuration files
+
+Aug 03, 2007
+ IMPROVMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c: use HTML Help as the help system
+
+Jul 22, 2007
+ IMPROVMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswdraw.c, mswmisc.c: added support for mouse wheel in
+ the drawing area
+
+Jun 17, 2007
+ IMPROVMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswpref.c: added wGetUserHomeDir()
+
+Jun, 16 2007
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswpref.c working directory is in the user profile directory tree now
+
+Feb, 05th 2007
+ BUGFIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c fixed protection fault when pressing ESC in describe dialog
+
+Feb, 04th 2007
+ BUGFIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ mswmisc.c fixed protection fault when Tabbing through describe dialog
+ See xtrkcad-fork Bug 1651117
+
+Oct, 13 2006 mswmisc.c
+ BUGFIX Bob Blackwell
+ Fixed a problem with 'No' and 'Cancel' buttons being mixed up
+
diff --git a/app/wlib/mswlib/checksum.c b/app/wlib/mswlib/checksum.c
new file mode 100644
index 0000000..f19d15b
--- /dev/null
+++ b/app/wlib/mswlib/checksum.c
@@ -0,0 +1,42 @@
+#include "mswchksm.c"
+#include <stdlib.h>
+
+int main( int argc, char *argv[] )
+{
+ int set;
+ FILE * fp;
+ long FileSize;
+ unsigned short sum16computed, sum16stored = 0xb8dd;
+ unsigned long sum32computed, sum32stored = 0xa25ce7ac;
+ long sum32off;
+ if (argc < 2) {
+ fprintf( stderr, "Usage: %s [-s] file.exe\n", argv[0] );
+ exit(1);
+ }
+ if (argc > 2) {
+ set = 1;
+ fp = openfile( argv[2], "r+b", &FileSize );
+ } else {
+ set = 0;
+ fp = openfile( argv[1], "rb", &FileSize );
+ }
+ if (fp == NULL)
+ exit(1);
+
+ fprintf( stderr, "File Size = %ld (%lx)\n", FileSize, FileSize );
+ sum16computed = mswCheck16( fp, FileSize, &sum16stored );
+ if (!mswCheck32( fp, FileSize, &sum32off, &sum32computed, &sum32stored ))
+ fprintf( stderr, "mswCheck32 error\n" );
+ fprintf( stderr, "sum16: stored = %x, computed = %x, sum = %x, expected FFFF\n", sum16stored, sum16computed, sum16stored+sum16computed );
+ fprintf( stderr, "sum32: stored = %lx, computed = %lx, expected %lx\n", sum32stored, sum32computed, sum32stored );
+ if (set) {
+ fseek( fp, 0x12, SEEK_SET );
+ sum16computed = 0xFFFF - sum16computed;
+ fwrite( &sum16computed, sizeof sum16computed, 1, fp );
+ fseek( fp, sum32off, SEEK_SET );
+ /*fwrite( &sum32computed, sizeof sum32computed, 1, fp );*/
+ fflush( fp );
+ }
+ fclose(fp);
+ exit(0);
+}
diff --git a/app/wlib/mswlib/dynarr.h b/app/wlib/mswlib/dynarr.h
new file mode 100644
index 0000000..5bd7a8e
--- /dev/null
+++ b/app/wlib/mswlib/dynarr.h
@@ -0,0 +1,40 @@
+typedef struct {
+ int cnt;
+ int max;
+ void * ptr;
+ } dynArr_t;
+
+#define DYNARR_APPEND(T,DA,INCR) \
+ { if ((DA).cnt >= (DA).max) { \
+ (DA).max += INCR; \
+ (DA).ptr = realloc( (DA).ptr, (DA).max * sizeof *(T*)NULL ); \
+ if ( (DA).ptr == NULL ) \
+ abort(); \
+ } \
+ (DA).cnt++; }
+#define DYNARR_ADD(T,DA,INCR) DYNARR_APPEND(T,DA,INCR)
+
+#define DYNARR_LAST(T,DA) \
+ (((T*)(DA).ptr)[(DA).cnt-1])
+#define DYNARR_N(T,DA,N) \
+ (((T*)(DA).ptr)[N])
+#define DYNARR_RESET(T,DA) \
+ (DA).cnt=0
+#define DYNARR_SET(T,DA,N) \
+ { if ((DA).max < N) { \
+ (DA).max = N; \
+ (DA).ptr = realloc( (DA).ptr, (DA).max * sizeof *(T*)NULL ); \
+ if ( (DA).ptr == NULL ) \
+ abort(); \
+ } \
+ (DA).cnt = 0; }
+
+
+#ifdef WINDOWS
+#ifndef WIN32
+#define FAR _far
+#endif
+#define M_PI 3.14159
+#define strcasecmp _stricmp
+#else
+#endif
diff --git a/app/wlib/mswlib/getopt.c b/app/wlib/mswlib/getopt.c
new file mode 100644
index 0000000..888f5f8
--- /dev/null
+++ b/app/wlib/mswlib/getopt.c
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------
+
+ Replacement for Unix "getopt()", for DOS/Windows/etc.
+
+ getopt.c 1.3 2003/09/17 16:17:59
+
+ Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved
+
+ This file is part of ASPEX.
+
+ ASPEX is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ ASPEX 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ASPEX; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+----------------------------------------------------------------------*/
+
+#include "string.h"
+#include "stdio.h"
+#include "getopt.h"
+
+#ifdef WINDOWS
+#define OPTCHAR '/'
+#else
+#define OPTCHAR '-'
+#endif
+
+char *optarg;
+int optind = 1, opterr, optopt;
+
+int getopt(int argc, char *argv[], const char *optstring)
+{
+ static int pos = 0;
+ char *str;
+
+ if (pos == 0) {
+ if ((optind >= argc) || (*argv[optind] != OPTCHAR))
+ return EOF;
+ pos = 1;
+ if (argv[optind][pos] == '\0')
+ return EOF;
+ }
+
+ str = strchr(optstring, argv[optind][pos]);
+ if (str == NULL) {
+ optopt = argv[optind][pos];
+ if (opterr)
+ fprintf(stderr, "%s: illegal option -- %c\n", argv[0],
+ optopt);
+ return '?';
+ }
+
+ if (str[1] == ':') {
+ if (argv[optind][pos+1] != '\0') {
+ optarg = &argv[optind][pos+1];
+ return *str;
+ }
+ optind++;
+ if (optind >= argc) {
+ optopt = *str;
+ if (opterr)
+ fprintf(stderr, "%s: option requires an argument -- %c\n",
+ argv[0], optopt);
+ return '?';
+ }
+ optarg = argv[optind];
+ optind++; pos = 0;
+ return *str;
+ }
+ else {
+ pos++;
+ if (argv[optind][pos] == '\0') {
+ optind++;
+ pos = 0;
+ }
+ return *str;
+ }
+}
diff --git a/app/wlib/mswlib/gwin32.c b/app/wlib/mswlib/gwin32.c
new file mode 100644
index 0000000..6b0c7f3
--- /dev/null
+++ b/app/wlib/mswlib/gwin32.c
@@ -0,0 +1,146 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1998-1999 Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ *
+ * Ported to standard C by Martin Fischer 2009
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <errno.h>
+
+#define STRICT /* Strict typing, please */
+#include <windows.h>
+#undef STRICT
+#include <errno.h>
+#include <ctype.h>
+#if defined(_MSC_VER) || defined(__DMC__)
+# include <io.h>
+#endif /* _MSC_VER || __DMC__ */
+
+#ifndef SUBLANG_SERBIAN_LATIN_BA
+#define SUBLANG_SERBIAN_LATIN_BA 0x06
+#endif
+
+#if _MSC_VER > 1300
+ #define stricmp _stricmp
+ #define strnicmp _strnicmp
+ #define strdup _strdup
+#endif
+
+/**
+ * This function gets the current thread locale from Windows - without any
+ * encoding info - and returns it as a string of the above form for use in forming
+ * file names etc. The setlocale() function in the Microsoft C library uses locale
+ * names of the form "English_United States.1252" etc. We want the
+ * UNIXish standard form "en_US", "zh_TW" etc. The returned string should be
+ * deallocated with free().
+ *
+ * \return newly-allocated locale name.
+ */
+
+char *
+g_win32_getlocale (void)
+{
+ LCID lcid;
+ LANGID langid;
+ char *ev;
+ char *loc;
+ int primary, sub;
+ char iso639[10];
+ char iso3166[10];
+ const char *script = NULL;
+
+ /* Let the user override the system settings through environment
+ * variables, as on POSIX systems. Note that in GTK+ applications
+ * since GTK+ 2.10.7 setting either LC_ALL or LANG also sets the
+ * Win32 locale and C library locale through code in gtkmain.c.
+ */
+ if (((ev = getenv ("LC_ALL")) != NULL && ev[0] != '\0')
+ || ((ev = getenv ("LC_MESSAGES")) != NULL && ev[0] != '\0')
+ || ((ev = getenv ("LANG")) != NULL && ev[0] != '\0'))
+ return strdup (ev);
+
+ lcid = GetThreadLocale ();
+
+ if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) ||
+ !GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
+ return strdup ("C");
+
+ /* Strip off the sorting rules, keep only the language part. */
+ langid = LANGIDFROMLCID (lcid);
+
+ /* Split into language and territory part. */
+ primary = PRIMARYLANGID (langid);
+ sub = SUBLANGID (langid);
+
+ /* Handle special cases */
+ switch (primary)
+ {
+ case LANG_AZERI:
+ switch (sub)
+ {
+ case SUBLANG_AZERI_LATIN:
+ script = "@Latn";
+ break;
+ case SUBLANG_AZERI_CYRILLIC:
+ script = "@Cyrl";
+ break;
+ }
+ break;
+ case LANG_SERBIAN: /* LANG_CROATIAN == LANG_SERBIAN */
+ switch (sub)
+ {
+ case SUBLANG_SERBIAN_LATIN:
+ case 0x06: /* Serbian (Latin) - Bosnia and Herzegovina */
+ script = "@Latn";
+ break;
+ }
+ break;
+ case LANG_UZBEK:
+ switch (sub)
+ {
+ case SUBLANG_UZBEK_LATIN:
+ script = "@Latn";
+ break;
+ case SUBLANG_UZBEK_CYRILLIC:
+ script = "@Cyrl";
+ break;
+ }
+ break;
+ }
+
+ loc = malloc( strlen( iso639 ) + strlen( iso3166 ) + (script ? strlen( script ) : 0) + 2 );
+ strcpy( loc, iso639 );
+ strcat( loc, "_" );
+ strcat( loc, iso3166 );
+ if( script )
+ strcat( loc, script );
+ return loc;
+}
+
diff --git a/app/wlib/mswlib/mswbitmap.c b/app/wlib/mswlib/mswbitmap.c
new file mode 100644
index 0000000..7371834
--- /dev/null
+++ b/app/wlib/mswlib/mswbitmap.c
@@ -0,0 +1,508 @@
+/** \file mswbitmap.c
+ * Bitmap handling functions
+ *
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswbitmap.c,v 1.1 2009-09-20 14:55:54 m_fischer Exp $
+ */
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2009 Martin Fischer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <stdio.h>
+#include <assert.h>
+#include "mswint.h"
+#include "i18n.h"
+
+#if _MSC_VER > 1300
+ #define stricmp _stricmp
+ #define strnicmp _strnicmp
+ #define strdup _strdup
+#endif
+
+struct wBitmap_t {
+ WOBJ_COMMON
+ };
+
+HPALETTE hOldPal;
+
+HBITMAP mswCreateBitMap(
+ COLORREF fgCol1,
+ COLORREF fgCol2,
+ COLORREF bgCol,
+ wPos_t w,
+ wPos_t h,
+ const char * bits )
+{
+ HDC hDc;
+ HDC hButtDc;
+ HBRUSH oldBrush, newBrush;
+ RECT rect;
+ HBITMAP hBitMap;
+ HBITMAP hOldBitMap;
+ const char * byts_p;
+ int byt, i, j;
+
+ hDc = GetDC( mswHWnd );
+ hButtDc = CreateCompatibleDC( hDc );
+ hBitMap = CreateCompatibleBitmap( hDc, w, h );
+ ReleaseDC( mswHWnd, hDc );
+ hOldBitMap = SelectObject( hButtDc, hBitMap );
+ if (mswPalette) {
+ hOldPal = SelectPalette( hButtDc, mswPalette, 0 );
+ }
+
+ /*PatBlt( hButtDc, 0, 0, w, h, WHITENESS );*/
+ newBrush = CreateSolidBrush( bgCol );
+ oldBrush = SelectObject( hButtDc, newBrush );
+ rect.top = 0;
+ rect.left = 0;
+ rect.bottom = h;
+ rect.right = w;
+ FillRect( hButtDc, &rect, newBrush );
+ DeleteObject( SelectObject( hButtDc, oldBrush ) );
+
+ byts_p = bits;
+ for ( j = 0; j < h; j++ ) {
+ byt = (0xFF & *byts_p++) | 0x100;
+ for ( i = 0; i < w; i++ ) {
+ if (byt == 1)
+ byt = (0xFF & *byts_p++) | 0x100;
+ if ( byt & 0x1 ) {
+ SetPixel( hButtDc, i, j, fgCol1 );
+ SetPixel( hButtDc, i+1, j+1, fgCol2 );
+ }
+ byt >>= 1;
+ }
+ }
+
+ SelectObject( hButtDc, hOldBitMap );
+ DeleteDC( hButtDc );
+ return hBitMap;
+}
+
+dynArr_t bitmap_da;
+#define controlMap(N) DYNARR_N(controlMap_t,controlMap_da,N)
+#define bitmap(N) DYNARR_N(HBITMAP,bitmap_da,N)
+
+void mswRegisterBitMap(
+ HBITMAP hBm )
+{
+ DYNARR_APPEND( HBITMAP, bitmap_da, 10 );
+ bitmap(bitmap_da.cnt-1) = hBm;
+}
+
+void deleteBitmaps( void )
+{
+ int inx;
+ for ( inx=0; inx<bitmap_da.cnt; inx++ )
+ DeleteObject( bitmap(inx) );
+}
+
+/**
+ * Draw a bitmap to the screen.
+ *
+ * \param hDc IN device context
+ * \param offw IN horizontal offset
+ * \param offh IN vertical offset
+ * \param bm IN icon to draw
+ * \param disabled IN draw in disabled state
+ * \param color1 IN for two color bitmaps: foreground color enabled state
+ * \param color2 IN for two color bitmaps: foreground color disabled state
+ *
+ */
+
+void mswDrawIcon(
+ HDC hDc,
+ int offw,
+ int offh,
+ wIcon_p bm,
+ int disabled,
+ COLORREF color1,
+ COLORREF color2 )
+{
+ int i;
+ int byt;
+ BITMAPINFO *bmiInfo;
+ COLORREF col;
+
+ /* draw the bitmap by dynamically creating a Windows DIB in memory */
+
+ bmiInfo = malloc( sizeof( BITMAPINFO ) + (bm->colorcnt - 1) * sizeof( RGBQUAD ));
+ if( !bmiInfo ) {
+ fprintf( stderr, "could not allocate memory for bmiInfo\n" );
+ abort();
+ }
+
+ /* initialize bitmap header from XPM information */
+ bmiInfo->bmiHeader.biSize = sizeof( bmiInfo->bmiHeader );
+ bmiInfo->bmiHeader.biWidth = bm->w;
+ bmiInfo->bmiHeader.biHeight = bm->h;
+ bmiInfo->bmiHeader.biPlanes = 1;
+ if( bm->type == mswIcon_bitmap )
+ bmiInfo->bmiHeader.biBitCount = 1;
+ else
+ bmiInfo->bmiHeader.biBitCount = 8; /* up to 256 colors */
+ bmiInfo->bmiHeader.biCompression = BI_RGB; /* no compression */
+ bmiInfo->bmiHeader.biSizeImage = 0;
+ bmiInfo->bmiHeader.biXPelsPerMeter = 0;
+ bmiInfo->bmiHeader.biYPelsPerMeter = 0;
+ bmiInfo->bmiHeader.biClrUsed = bm->colorcnt; /* number of colors used */
+ bmiInfo->bmiHeader.biClrImportant = bm->colorcnt;
+
+ /*
+ * create a transparency mask and paint to screen
+ */
+ if( bm->type == mswIcon_bitmap ) {
+ memset( &bmiInfo->bmiColors[ 0 ], 0xFF, sizeof( RGBQUAD ));
+ memset( &bmiInfo->bmiColors[ 1 ], 0, sizeof( RGBQUAD ));
+ } else {
+ memset( bmiInfo->bmiColors, 0, bm->colorcnt * sizeof( RGBQUAD ));
+ memset( &bmiInfo->bmiColors[ bm->transparent ], 0xFF, sizeof( RGBQUAD ));
+ }
+ StretchDIBits(hDc, offw, offh,
+ bmiInfo->bmiHeader.biWidth,
+ bmiInfo->bmiHeader.biHeight,
+ 0, 0,
+ bmiInfo->bmiHeader.biWidth,
+ bmiInfo->bmiHeader.biHeight,
+ bm->pixels, bmiInfo,
+ DIB_RGB_COLORS, SRCAND);
+
+ /* now paint the bitmap with transparent set to black */
+ if( bm->type == mswIcon_bitmap ) {
+ if( disabled ) {
+ col = color2;
+ } else {
+ col = color1;
+ }
+ memset( &bmiInfo->bmiColors[ 0 ], 0, sizeof( RGBQUAD ));
+ bmiInfo->bmiColors[ 1 ].rgbRed = GetRValue( col );
+ bmiInfo->bmiColors[ 1 ].rgbGreen = GetGValue( col );
+ bmiInfo->bmiColors[ 1 ].rgbBlue = GetBValue( col );
+ } else {
+ if( disabled ) {
+ /* create a gray scale palette */
+ for( i = 0; i < bm->colorcnt; i ++ ) {
+ byt = ( 30 * bm->colormap[ i ].rgbRed +
+ 59 * bm->colormap[ i ].rgbGreen +
+ 11 * bm->colormap[ i ].rgbBlue )/100;
+
+ /* if totally black, use a dark gray */
+ if( byt == 0 )
+ byt = 0x66;
+
+ bmiInfo->bmiColors[ i ].rgbRed = byt;
+ bmiInfo->bmiColors[ i ].rgbGreen = byt;
+ bmiInfo->bmiColors[ i ].rgbBlue = byt;
+ }
+ } else {
+ /* copy the palette */
+ memcpy( (void *)bmiInfo->bmiColors, (void *)bm->colormap, bm->colorcnt * sizeof( RGBQUAD ));
+ }
+ memset( &bmiInfo->bmiColors[ bm->transparent ], 0, sizeof( RGBQUAD ));
+ }
+
+ /* show the bitmap */
+ StretchDIBits(hDc, offw, offh,
+ bmiInfo->bmiHeader.biWidth,
+ bmiInfo->bmiHeader.biHeight,
+ 0, 0,
+ bmiInfo->bmiHeader.biWidth,
+ bmiInfo->bmiHeader.biHeight,
+ bm->pixels, bmiInfo,
+ DIB_RGB_COLORS, SRCPAINT);
+
+ /* forget the data */
+ free( bmiInfo );
+}
+
+/**
+ * Create a two color bitmap. This creates a two color icon. Pixels set to 1 are painted
+ * in the specified color, pixels set to 0 are transparent
+ * in order to convert the format, a lot of bit fiddling is necessary. The order of
+ * scanlines needs to be reversed and the bit order (high order - low order) is reversed
+ * as well.
+ * \param w IN width in pixels
+ * \param h IN height in pixels
+ * \param bits IN pixel data
+ * \param color IN color for foreground
+ * \return pointer to icon
+ */
+
+wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color )
+{
+ int lineLength;
+ int i, j;
+ unsigned char *dest;
+ static unsigned char revbits[] = { 0, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F };
+ unsigned long col = wDrawGetRGB( color );
+
+ wIcon_p ip;
+ ip = (wIcon_p)malloc( sizeof *ip );
+ if( !ip ) {
+ fprintf( stderr, "Couldn't allocate memory for bitmap header.\n" );
+ abort();
+ }
+
+ memset( ip, 0, sizeof *ip );
+ ip->type = mswIcon_bitmap;
+ ip->w = w;
+ ip->h = h;
+ ip->colorcnt = 2;
+
+ /* set up our two color palette */
+ ip->colormap = malloc( 2 * sizeof( RGBQUAD ));
+
+ ip->colormap[ 1 ].rgbBlue = col & 0xFF;
+ ip->colormap[ 1 ].rgbRed = (col>>16) & 0xFF;
+ ip->colormap[ 1 ].rgbGreen = (col>>8) & 0xFF;
+ ip->colormap[ 1 ].rgbReserved = 0;
+
+ color = GetSysColor( COLOR_BTNFACE );
+ ip->colormap[ 0 ].rgbBlue = GetBValue( color );
+ ip->colormap[ 0 ].rgbRed = GetRValue( color );
+ ip->colormap[ 0 ].rgbGreen = GetGValue( color );
+ ip->colormap[ 0 ].rgbReserved = 0;
+
+ lineLength = (((( ip->w + 7 ) / 8 ) + 3 ) >> 2 ) << 2;
+ ip->pixels = malloc( lineLength * ip->h );
+ if( !ip->pixels ) {
+ fprintf( stderr, "Couldn't allocate memory for pixel data.\n" );
+ abort();
+ }
+
+ /*
+ * copy the bits from source to the buffer, at this time the order of
+ * scanlines is reversed by starting with the last source line.
+ */
+ for( i = 0; i < ip->h; i++ ) {
+ dest = ip->pixels + i * lineLength;
+ memcpy( dest, bits + ( ip->h - i - 1 ) * (( ip->w + 7) / 8), ( ip->w + 7 ) / 8 );
+
+ /*
+ * and now, the bit order is changed, this is done via a lookup table
+ */
+ for( j = 0; j < lineLength; j++ )
+ {
+ unsigned byte = dest[ j ];
+ unsigned low = byte & 0x0F;
+ unsigned high = (byte & 0xF0) >> 4;
+ dest[ j ] = revbits[ low ]<<4 | revbits[ high ];
+ }
+ }
+
+ return ip;
+}
+
+/**
+ * Create a pixmap. This functions interprets a XPM icon contained in a
+ * char array. Supported format are one or two byte per pixel and #rrggbb
+ * or #rrrrggggbbbb color specification. Color 'None' is interpreted as
+ * transparency, other symbolic names are not supported.
+ *
+ * \param pm IN XPM variable
+ * \return pointer to icon, call free() if not needed anymore.
+ */
+
+wIcon_p wIconCreatePixMap( char *pm[])
+{
+ wIcon_p ip;
+ int col, r, g, b, len;
+ int width, height;
+ char buff[3];
+ char * cp, * cq, * ptr;
+ int i, j, k;
+ int lineLength;
+ unsigned *keys;
+ unsigned numchars;
+ unsigned pixel;
+
+ ip = (wIcon_p)malloc( sizeof *ip );
+ if( !ip ) {
+ fprintf( stderr, "Couldn't allocate memory for bitmap header.\n" );
+ abort();
+ }
+
+ memset( ip, 0, sizeof *ip );
+ ip->type = mswIcon_pixmap;
+
+ /* extract values */
+ cp = pm[0];
+ width = (int)strtol(cp, &cq, 10 ); /* width of image */
+ height = (int)strtol(cq, &cq, 10 ); /* height of image */
+ col = (int)strtol(cq, &cq, 10 ); /* number of colors used */
+ numchars = (int)strtol(cq, &cq, 10 ); /* get number of chars per pixel */
+
+ ip->colormap = malloc( col * sizeof( RGBQUAD ));
+ ip->w = width;
+ ip->h = height;
+ ip->colorcnt = col; /* number of colors used */
+
+ keys = malloc( sizeof( unsigned ) * col );
+
+ for ( col=0; col<(int)ip->colorcnt; col++ ) {
+ ptr = strdup( pm[col+1] ); /* create duplicate for input string*/
+
+ if( numchars == 1 ) {
+ keys[ col ] = (unsigned)ptr[0];
+ }
+ else if( numchars == 2 ) {
+ keys[ col ] = (unsigned) ( ptr[ 0 ] + ptr[ 1 ] * 256 );
+ }
+
+ cp = strtok( ptr + numchars, "\t " ); /* cp points to color type */
+ assert( *cp == 'c' ); /* should always be color */
+
+ cp = strtok( NULL, "\t " ); /* go to next token, the color definition itself */
+
+ if( *cp == '#' ) { /* is this a hex RGB specification? */
+ len = strlen( cp+1 ) / 3;
+ assert( len == 4 || len == 2 ); /* expecting three 2 char or 4 char values */
+ buff[2] = 0; /* if yes, extract the values */
+ memcpy( buff, cp + 1, 2 );
+ r = (int)strtol(buff, &cq, 16);
+ memcpy( buff, cp + 1 + len, 2 );
+ g = (int)strtol(buff, &cq, 16);
+ memcpy( buff, cp + 1 + 2 * len, 2 );
+ b = (int)strtol(buff, &cq, 16);
+
+ ip->colormap[ col ].rgbBlue = b;
+ ip->colormap[ col ].rgbGreen = g;
+ ip->colormap[ col ].rgbRed = r;
+ ip->colormap[ col ].rgbReserved = 0;
+
+ } else {
+ if( !stricmp( cp, "none" )) { /* special case transparency*/
+ ip->transparent = col;
+ }
+ else
+ assert( *cp == '#' ); /* if no, abort for the moment */
+ }
+ free( ptr );
+ }
+
+ /* get memory for the pixel data */
+ /* dword align begin of line */
+ lineLength = ((ip->w + 3 ) >> 2 ) << 2;
+ ip->pixels = malloc( lineLength * ip->h );
+ if( !ip->pixels ) {
+ fprintf( stderr, "Couldn't allocate memory for pixel data.\n" );
+ abort();
+ }
+
+ /*
+ convert the XPM pixel data to indexes into color table
+ at the same time the order of rows is reversed
+ Win32 should be able to do that but I couldn't find out
+ how, so this is coded by hand.
+ */
+
+ /* for all rows */
+ for( i = 0; i < ip->h; i++ ) {
+
+ cq = ip->pixels + lineLength * i;
+ /* get the next row */
+ cp = pm[ ip->h - i + ip->colorcnt ];
+ /* for all pixels in row */
+ for( j = 0; j < ip->w; j++ ) {
+ /* get the pixel info */
+ if( numchars == 1 )
+ pixel = ( unsigned )*cp;
+ else
+ pixel = (unsigned) (*cp + *(cp+1)*256);
+ cp += numchars;
+
+ /* look up pixel info in color table */
+ k = 0;
+ while( pixel != keys[ k ] )
+ k++;
+
+ /* save the index into color table */
+ *(cq + j) = k;
+ }
+ }
+ free( keys );
+
+ return ip;
+}
+
+void wIconSetColor( wIcon_p ip, wDrawColor color )
+{
+ unsigned long col = wDrawGetRGB( color );
+
+ if( ip->type == mswIcon_bitmap ) {
+ ip->colormap[ 1 ].rgbBlue = col & 0xFF;
+ ip->colormap[ 1 ].rgbRed = (col>>16) & 0xFF;
+ ip->colormap[ 1 ].rgbGreen = (col>>8) & 0xFF;
+ }
+}
+
+/**
+ * Draw icon to screen.
+ *
+ * \param d IN drawing area
+ * \param bm IN bitmap to draw
+ * \param x IN x position
+ * \param y IN y position
+ */
+
+void
+wIconDraw( wDraw_p d, wIcon_p bm, wPos_t x, wPos_t y )
+{
+ mswDrawIcon( d->hDc, (int)x, (int)y, bm, FALSE, 0, 0 );
+}
+
+/**
+ * Create a static control for displaying a bitmap.
+ *
+ * \param parent IN parent window
+ * \param x, y IN position in parent window
+ * \param option IN ignored for now
+ * \param iconP IN icon to use
+ * \return the control
+ */
+
+wControl_p
+wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long option, wIcon_p iconP )
+{
+ wBitmap_p control;
+ int index;
+ DWORD style = SS_OWNERDRAW | WS_VISIBLE | WS_CHILD;
+
+ control = mswAlloc( parent, B_BITMAP, NULL, sizeof( struct wBitmap_t ), NULL, &index );
+ mswComputePos( (wControl_p)control, x, y );
+ control->option = option;
+
+ control->hWnd = CreateWindow( "STATIC", NULL,
+ style, control->x, control->y,
+ iconP->w, iconP->h,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+
+ if (control->hWnd == NULL) {
+ mswFail("CreateWindow(BITMAP)");
+ return (wControl_p)control;
+ }
+ control->h = iconP->h;
+ control->w = iconP->w;
+ control->data = iconP;
+
+ return (wControl_p)control;
+} \ No newline at end of file
diff --git a/app/wlib/mswlib/mswbox.c b/app/wlib/mswlib/mswbox.c
new file mode 100644
index 0000000..04b3656
--- /dev/null
+++ b/app/wlib/mswlib/mswbox.c
@@ -0,0 +1,119 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wBox_t {
+ WOBJ_COMMON
+ wBoxType_e boxTyp;
+ };
+
+#define B (1)
+#define W (2)
+#define SETCOLOR( S, N ) \
+ if ( lastColor != colors[bb->boxTyp][S][N] ) { \
+ lastColor = colors[bb->boxTyp][S][N]; \
+ SetROP2( hDc, (lastColor==B?R2_BLACK:R2_WHITE) ); \
+ }
+
+
+void wBoxSetSize(
+ wBox_p bb,
+ wPos_t w,
+ wPos_t h )
+{
+ bb->w = w;
+ bb->h = h;
+}
+
+
+static void repaintBox( HWND hWnd, wControl_p b )
+{
+ HDC hDc;
+ wBox_p bb = (wBox_p)(b);
+ wPos_t x0, y0, x1, y1;
+ char lastColor;
+ int lastRop;
+ static char colors[8][4][2] = {
+ { /* ThinB */ {B,0}, {B,0}, {B,0}, {B,0} },
+ { /* ThinW */ {W,0}, {W,0}, {W,0}, {W,0} },
+ { /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} },
+ { /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} },
+ { /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} },
+ { /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} },
+ { /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} },
+ { /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} } };
+
+ x0 = bb->x;
+ x1 = bb->x+bb->w;
+ y0 = bb->y;
+ y1 = bb->y+bb->h;
+ hDc = GetDC( hWnd );
+ MoveTo( hDc, x0, y1 );
+ /*SETCOLOR( 0, 0 );*/
+ lastColor = colors[bb->boxTyp][0][0];
+ lastRop = SetROP2( hDc, (lastColor==B?R2_BLACK:R2_WHITE) );
+ LineTo( hDc, x0, y0 );
+ SETCOLOR( 1, 0 );
+ LineTo( hDc, x1, y0 );
+ SETCOLOR( 2, 0 );
+ LineTo( hDc, x1, y1 );
+ SETCOLOR( 3, 0 );
+ LineTo( hDc, x0, y1 );
+ if (bb->boxTyp >= wBoxThickB) {
+ x0++; y0++; x1--; y1--;
+ MoveTo( hDc, x0, y1 );
+ SETCOLOR( 0, 1 );
+ LineTo( hDc, x0, y0 );
+ SETCOLOR( 1, 1 );
+ LineTo( hDc, x1, y0 );
+ SETCOLOR( 2, 1 );
+ LineTo( hDc, x1, y1 );
+ SETCOLOR( 3, 1 );
+ LineTo( hDc, x0, y1 );
+ }
+ SetROP2( hDc, lastRop );
+ ReleaseDC( hWnd, hDc );
+}
+
+
+static callBacks_t boxCallBacks = {
+ repaintBox,
+ NULL,
+ NULL };
+
+wBox_p wBoxCreate(
+ wWin_p parent,
+ wPos_t origX,
+ wPos_t origY,
+ const char * labelStr,
+ wBoxType_e typ,
+ wPos_t width,
+ wPos_t height )
+{
+ wBox_p b;
+ int index;
+
+ b = (wBox_p)mswAlloc( parent, B_BOX, labelStr, sizeof *b, NULL, &index );
+ b->boxTyp = typ;
+
+ b->x = origX;
+ b->y = origY;
+ b->w = width;
+ b->h = height;
+ mswAddButton( (wControl_p)b, FALSE, NULL );
+ mswCallBacks[B_BOX] = &boxCallBacks;
+ repaintBox( ((wControl_p)parent)->hWnd, (wControl_p)b );
+ return b;
+}
diff --git a/app/wlib/mswlib/mswbutt.c b/app/wlib/mswlib/mswbutt.c
new file mode 100644
index 0000000..b5d7b49
--- /dev/null
+++ b/app/wlib/mswlib/mswbutt.c
@@ -0,0 +1,387 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+int kludge12 = 0;
+
+/*
+ *****************************************************************************
+ *
+ * Simple Buttons
+ *
+ *****************************************************************************
+ */
+
+
+
+static XWNDPROC oldButtProc = NULL;
+static XWNDPROC newButtProc;
+
+
+struct wButton_t {
+ WOBJ_COMMON
+ wButtonCallBack_p action;
+ wBool_t busy;
+ wBool_t selected;
+ wIcon_p icon;
+ };
+
+
+
+void mswButtPush(
+ wControl_p b )
+{
+ if ( ((wButton_p)b)->action )
+ ((wButton_p)b)->action( ((wButton_p)b)->data );
+}
+
+/**
+ * Paint function for toolbar buttons
+ *
+ * \param hButtDc IN valid device context
+ * \param bm IN bitmap to add to button
+ * \param selected IN selected state of button
+ * \param disabled IN disabled state of button
+ */
+
+static void drawButton(
+ HDC hButtDc,
+ wIcon_p bm,
+ BOOL_T selected,
+ BOOL_T disabled )
+{
+ HGDIOBJ oldBrush, newBrush;
+ HPEN oldPen, newPen;
+ RECT rect;
+ COLORREF color1, color2;
+ POS_T offw=5, offh=5;
+ TRIVERTEX vert[2] ;
+ GRADIENT_RECT gRect;
+
+ COLORREF colL;
+ COLORREF colD;
+ COLORREF colF;
+
+#define LEFT (0)
+#define RIGHT (bm->w+10)
+#define TOP (0)
+#define BOTTOM (bm->h+10)
+
+ /* get the lightest and the darkest color to use */
+ colL = GetSysColor( COLOR_BTNHIGHLIGHT );
+ colD = GetSysColor( COLOR_BTNSHADOW );
+ colF = GetSysColor( COLOR_BTNFACE );
+
+ /* define the rectangle for the button */
+ rect.top = TOP;
+ rect.left = LEFT;
+ rect.right = RIGHT;
+ rect.bottom = BOTTOM;
+
+ /* fill the button with the face color */
+ newBrush = CreateSolidBrush( colF );
+ oldBrush = SelectObject( hButtDc, newBrush );
+ FillRect( hButtDc, &rect, newBrush );
+ DeleteObject( SelectObject( hButtDc, oldBrush ) );
+
+ /* disabled button remain flat */
+ if( !disabled )
+ {
+ /* select colors for the gradient */
+ if( selected ) {
+ color1 = colD;
+ color2 = colL;
+ } else {
+ color1 = colL;
+ color2 = colD;
+ }
+
+#define GRADIENT_WIDTH 6
+
+ /*
+ first draw the top gradient
+ this always ends in the button face color
+ starting color depends on button state (selected or not)
+ */
+ vert [0] .x = LEFT;
+ vert [0] .y = TOP;
+ vert [0] .Red = GetRValue( color1 )* 256;
+ vert [0] .Green = GetGValue( color1 )* 256;
+ vert [0] .Blue = GetBValue( color1 )* 256;
+ vert [0] .Alpha = 0x0000;
+ vert [1] .x = RIGHT;
+ vert [1] .y = TOP + GRADIENT_WIDTH;
+ vert [1] .Red = GetRValue( colF )* 256;
+ vert [1] .Green = GetGValue( colF )* 256;
+ vert [1] .Blue = GetBValue( colF )* 256;
+ vert [1] .Alpha = 0x0000;
+
+ gRect.UpperLeft = 0;
+ gRect.LowerRight = 1;
+
+ GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
+
+ /*
+ now draw the bottom gradient
+ this always starts with the button face color
+ ending color depends on button state (selected or not)
+ */
+ vert [0] .x = LEFT;
+ vert [0] .y = BOTTOM - GRADIENT_WIDTH;
+ vert [0] .Red = GetRValue( colF )* 256;
+ vert [0] .Green = GetGValue( colF )* 256;
+ vert [0] .Blue = GetBValue( colF )* 256;
+ vert [0] .Alpha = 0x0000;
+ vert [1] .x = RIGHT;
+ vert [1] .y = BOTTOM;
+ vert [1] .Red = GetRValue( color2 )* 256;
+ vert [1] .Green = GetGValue( color2 )* 256;
+ vert [1] .Blue = GetBValue( color2 )* 256;
+ vert [1] .Alpha = 0x0000;
+ gRect.UpperLeft = 0;
+ gRect.LowerRight = 1;
+ GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
+
+ }
+
+ /* draw delimiting lines in shadow color */
+ newPen = CreatePen( PS_SOLID, 0, colD );
+ oldPen = SelectObject( hButtDc, newPen );
+
+ MoveTo( hButtDc, LEFT, TOP );
+ LineTo( hButtDc, LEFT, BOTTOM );
+ MoveTo( hButtDc, RIGHT, TOP );
+ LineTo( hButtDc, RIGHT, BOTTOM );
+
+ DeleteObject( SelectObject( hButtDc, oldPen ) );
+
+ color2 = GetSysColor( COLOR_BTNSHADOW );
+ color1 = RGB( bm->colormap[ 1 ].rgbRed, bm->colormap[ 1 ].rgbGreen, bm->colormap[ 1 ].rgbBlue );
+
+ if (selected) {
+ offw++; offh++;
+ }
+ mswDrawIcon( hButtDc, offw, offh, bm, disabled, color1, color2 );
+}
+
+
+static void buttDrawIcon(
+ wButton_p b,
+ HDC butt_hDc )
+{
+ wIcon_p bm = b->icon;
+ POS_T offw=5, offh=5;
+
+ if (b->selected || b->busy) {
+ offw++; offh++;
+ } else if ( (b->option & BO_DISABLED) != 0 ) {
+ ;
+ } else {
+ ;
+ }
+ drawButton( butt_hDc, bm, b->selected || b->busy, (b->option & BO_DISABLED) != 0 );
+}
+
+void wButtonSetBusy(
+ wButton_p b,
+ int value )
+{
+ b->busy = value;
+ if (!value)
+ b->selected = FALSE;
+ /*SendMessage( b->hWnd, BM_SETSTATE, (WPARAM)value, 0L );*/
+ InvalidateRgn( b->hWnd, NULL, FALSE );
+}
+
+
+void wButtonSetLabel(
+ wButton_p b,
+ const char * label )
+{
+ if ((b->option&BO_ICON) == 0) {
+ /*b->labelStr = label;*/
+ SetWindowText( b->hWnd, label );
+ } else {
+ b->icon = (wIcon_p)label;
+ }
+ InvalidateRgn( b->hWnd, NULL, FALSE );
+}
+
+
+static LRESULT buttPush( wControl_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ wButton_p bb = (wButton_p)b;
+ DRAWITEMSTRUCT * di = (DRAWITEMSTRUCT *)lParam;
+ wBool_t selected;
+
+ switch (message) {
+ case WM_COMMAND:
+ if (bb->action /*&& !bb->busy*/) {
+ bb->action( bb->data );
+ return 0L;
+ }
+ break;
+
+ case WM_MEASUREITEM: {
+ MEASUREITEMSTRUCT * mi = (MEASUREITEMSTRUCT *)lParam;
+ if (bb->type != B_BUTTON || (bb->option & BO_ICON) == 0)
+ break;
+ mi->CtlType = ODT_BUTTON;
+ mi->CtlID = wParam;
+ mi->itemWidth = bb->w;
+ mi->itemHeight = bb->h;
+ } return 0L;
+
+ case WM_DRAWITEM:
+ if (bb->type == B_BUTTON && (bb->option & BO_ICON) != 0) {
+ selected = ((di->itemState & ODS_SELECTED) != 0);
+ if (bb->selected != selected) {
+ bb->selected = selected;
+ InvalidateRgn( bb->hWnd, NULL, FALSE );
+ }
+ return TRUE;
+ }
+ break;
+
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static void buttDone(
+ wControl_p b )
+{
+ free(b);
+}
+
+long FAR PASCAL _export pushButt(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+ /* Catch <Return> and cause focus to leave control */
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+ wButton_p b = (wButton_p)mswMapIndex( inx );
+ PAINTSTRUCT ps;
+
+ switch (message) {
+ case WM_PAINT:
+ if ( b && b->type == B_BUTTON && (b->option & BO_ICON) != 0 ) {
+ BeginPaint( hWnd, &ps );
+ buttDrawIcon( (wButton_p)b, ps.hdc );
+ EndPaint( hWnd, &ps );
+ return 1L;
+ }
+ break;
+ case WM_CHAR:
+ if ( b != NULL ) {
+ switch( wParam ) {
+ case 0x0D:
+ case 0x1B:
+ case 0x09:
+ /*SetFocus( ((wControl_p)(b->parent))->hWnd );*/
+ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR,
+ wParam, lParam );
+ /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND,
+ inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/
+ return 0L;
+ }
+ }
+ break;
+ case WM_KILLFOCUS:
+ if ( b )
+ InvalidateRect( b->hWnd, NULL, TRUE );
+ return 0L;
+ break;
+ case WM_ERASEBKGND:
+ if (kludge12)
+ return 1L;
+ }
+ return CallWindowProc( oldButtProc, hWnd, message, wParam, lParam );
+}
+
+static callBacks_t buttonCallBacks = {
+ mswRepaintLabel,
+ buttDone,
+ buttPush };
+
+wButton_p wButtonCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ wButtonCallBack_p action,
+ void * data )
+{
+ wButton_p b;
+ RECT rect;
+ int h=20;
+ int index;
+ DWORD style;
+ HDC hDc;
+ wIcon_p bm;
+
+ if (width <= 0)
+ width = 80;
+ if ((option&BO_ICON) == 0) {
+ labelStr = mswStrdup( labelStr );
+ } else {
+ bm = (wIcon_p)labelStr;
+ labelStr = NULL;
+ }
+ b = (wButton_p)mswAlloc( parent, B_BUTTON, NULL, sizeof *b, data, &index );
+ b->option = option;
+ b->busy = 0;
+ b->selected = 0;
+ mswComputePos( (wControl_p)b, x, y );
+ if (b->option&BO_ICON) {
+ width = bm->w+10;
+ h = bm->h+10;
+ b->icon = bm;
+ } else {
+ width = (wPos_t)(width*mswScale);
+ }
+ style = ((b->option&BO_ICON)? BS_OWNERDRAW : BS_PUSHBUTTON) |
+ WS_CHILD | WS_VISIBLE |
+ mswGetBaseStyle(parent);
+ if ((b->option&BB_DEFAULT) != 0)
+ style |= BS_DEFPUSHBUTTON;
+ b->hWnd = CreateWindow( "BUTTON", labelStr, style, b->x, b->y,
+ /*CW_USEDEFAULT, CW_USEDEFAULT,*/ width, h,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(BUTTON)");
+ return b;
+ }
+ /*SetWindowLong( b->hWnd, 0, (long)b );*/
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ b->action = action;
+ mswCallBacks[B_BUTTON] = &buttonCallBacks;
+ mswChainFocus( (wControl_p)b );
+ newButtProc = MakeProcInstance( (XWNDPROC)pushButt, mswHInst );
+ oldButtProc = (XWNDPROC)GetWindowLong( b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newButtProc );
+ if (mswPalette) {
+ hDc = GetDC( b->hWnd );
+ SelectPalette( hDc, mswPalette, 0 );
+ RealizePalette( hDc );
+ ReleaseDC( b->hWnd, hDc );
+ }
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ return b;
+}
diff --git a/app/wlib/mswlib/mswchksm.c b/app/wlib/mswlib/mswchksm.c
new file mode 100644
index 0000000..602c204
--- /dev/null
+++ b/app/wlib/mswlib/mswchksm.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#include "../include/wlib.h"
+#ifdef WINDOWS
+#include <windows.h>
+#include "mswint.h"
+#endif
+
+#define HEWHDROFFSET (0x3C)
+
+static FILE * openfile( const char * fn, const char * mode, long * fileSize )
+{
+ unsigned short PageCnt;
+ long FileSize;
+ FILE *fp;
+ struct stat Stat;
+ fp = fopen( fn, mode );
+ if (fp == NULL) {
+ perror( "fopen" );
+ return NULL;
+ }
+ fread( &PageCnt, sizeof(PageCnt), 1, fp ); /* Read past signature */
+ fread( &PageCnt, sizeof(PageCnt), 1, fp ); /* Read past pagesize */
+ FileSize = PageCnt;
+ fread( &PageCnt, sizeof(PageCnt), 1, fp ); /* Read past pagesize */
+ if ( FileSize == 0L )
+ FileSize = PageCnt * 512L;
+ else
+ FileSize += (PageCnt - 1) * 512L;
+ *fileSize = FileSize;
+ stat( fn, &Stat );
+ *fileSize = (long)Stat.st_size;
+ fprintf( stderr, "size1 = %ld, size2 = %ld\n", FileSize, (long)Stat.st_size );
+ return fp;
+}
+
+
+static unsigned short mswCheck16( FILE * fp, long FileSize, unsigned short * sum16stored )
+{
+ unsigned short int sum16, NxtInt;
+ long x;
+ unsigned char NxtChar;
+ sum16 = 0;
+ fseek(fp, 0, SEEK_SET);
+
+ for (x=0L; x<FileSize/2L; x++) {
+ fread( &NxtInt, sizeof NxtInt, 1, fp );
+ if (x == 9)
+ *sum16stored = NxtInt;
+ else
+ sum16 += NxtInt;
+ }
+ if (FileSize%2) {
+ fread( &NxtChar, sizeof NxtChar, 1, fp );
+ sum16 += (unsigned int)NxtChar;
+ }
+ return sum16;
+}
+
+
+static int mswCheck32( FILE * fp, long FileSize, long * sum32off, unsigned long * sum32computed, unsigned long * sum32stored )
+{
+ unsigned long sum32, NxtLong;
+ long x;
+ long NewHdrOffset;
+ unsigned char NxtByte, y;
+
+ fseek( fp, HEWHDROFFSET, SEEK_SET );
+ fread( &NewHdrOffset, sizeof NewHdrOffset, 1, fp );
+ if (NewHdrOffset == 0) {
+ fprintf( stderr, "NewHdrOffset == 0\n" );
+ return 0;
+ }
+ NewHdrOffset = (NewHdrOffset/4)*4;
+ *sum32off = NewHdrOffset + 8;
+ sum32 = 0L;
+ fseek( fp, 0, SEEK_SET );
+ for (x = ( NewHdrOffset + 8 ) / 4; x; x-- ) {
+ fread( &NxtLong, sizeof NxtLong, 1, fp );
+ sum32 += NxtLong;
+ }
+ fread( sum32stored, sizeof sum32stored, 1, fp );
+
+ for (x=0; x<(FileSize-NewHdrOffset - 12)/4; x++) {
+ fread( &NxtLong, sizeof NxtLong, 1, fp );
+ sum32 += NxtLong;
+ }
+ if ( 0L != (x=FileSize%4L) ) {
+ NxtLong = 0L;
+ for (y=0; y<x; y++ ) {
+ fread( &NxtByte, sizeof NxtByte, 1, fp );
+ NxtLong += (unsigned long)NxtByte << (8*y);
+ }
+ sum32 += NxtLong;
+ }
+ *sum32computed = sum32;
+ return 1;
+}
+
+
+#ifdef WINDOWS
+wBool_t wCheckExecutable( void )
+{
+ char fileName[1024];
+ FILE * fp;
+ long FileSize;
+ GetModuleFileName( mswHInst, fileName, sizeof fileName );
+ fp = openfile( fileName, "rb", &FileSize );
+#ifdef LATER
+ {
+ unsigned long int sum32offset, sum32computed, sum32stored;
+ if ( ! mswCheck32( fp, FileSize, &sum32offset, &sum32computed, &sum32stored ) )
+ return FALSE;
+ return sum32computed == sum32stored;
+ }
+#else
+ {
+ unsigned short int sum16computed, sum16stored;
+ sum16computed = mswCheck16( fp, FileSize, &sum16stored );
+ sum16computed += sum16stored;
+ return sum16computed == 0xFFFF;
+ }
+#endif
+}
+#endif
diff --git a/app/wlib/mswlib/mswchoic.c b/app/wlib/mswlib/mswchoic.c
new file mode 100644
index 0000000..2ac391a
--- /dev/null
+++ b/app/wlib/mswlib/mswchoic.c
@@ -0,0 +1,423 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "i18n.h"
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Choice Boxes
+ *
+ *****************************************************************************
+ */
+
+int CHOICE_HEIGHT=(17);
+int CHOICE_MIN_WIDTH=25;
+
+static XWNDPROC oldChoiceItemProc = NULL;
+static XWNDPROC newChoiceItemProc;
+
+typedef struct {
+ WOBJ_COMMON
+ wChoice_p owner;
+ } wChoiceItem_t, * wChoiceItem_p;
+
+struct wChoice_t {
+ WOBJ_COMMON
+ const char * * labels;
+ wChoiceItem_p *buttList;
+ long *valueP;
+ long oldVal;
+ wChoiceCallBack_p action;
+ HWND hBorder;
+ };
+
+static FARPROC oldChoiceProc;
+
+void wRadioSetValue(
+ wChoice_p bc,
+ long val )
+{
+ const char ** labels;
+ long cnt;
+ wChoiceItem_p * butts;
+
+ butts = (wChoiceItem_p*)bc->buttList;
+ for (labels = bc->labels, cnt=0; *labels; labels++, cnt++, butts++ )
+ SendMessage( (*butts)->hWnd, BM_SETCHECK,
+ (val==cnt)?1:0, 0L );
+ bc->oldVal = val;
+ if (bc->valueP)
+ *bc->valueP = val;
+}
+
+long wRadioGetValue(
+ wChoice_p bc )
+{
+ return bc->oldVal;
+}
+
+
+
+void wToggleSetValue(
+ wChoice_p bc,
+ long val )
+{
+ const char ** labels;
+ long cnt;
+ wChoiceItem_p * butts;
+
+ butts = (wChoiceItem_p*)bc->buttList;
+ for (labels = bc->labels, cnt=0; *labels; labels++, cnt++, butts++ )
+ SendMessage( (*butts)->hWnd, BM_SETCHECK,
+ (val & (1L<<cnt)) != 0, 0L );
+ bc->oldVal = val;
+ if (bc->valueP)
+ *bc->valueP = val;
+}
+
+
+long wToggleGetValue(
+ wChoice_p bc )
+{
+ return bc->oldVal;
+}
+
+
+static void choiceSetBusy(
+ wControl_p b,
+ BOOL_T busy)
+{
+ wChoiceItem_p * butts;
+ wChoice_p bc = (wChoice_p)b;
+
+ for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ )
+ EnableWindow( (*butts)->hWnd, !(BOOL)busy );
+}
+
+static void choiceShow(
+ wControl_p b,
+ BOOL_T show)
+{
+ wChoice_p bc = (wChoice_p)b;
+ wChoiceItem_p * butts;
+
+ if ((bc->option & BC_NOBORDER)==0)
+ ShowWindow( bc->hBorder, show?SW_SHOW:SW_HIDE );
+
+ for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ )
+ ShowWindow( (*butts)->hWnd, show?SW_SHOW:SW_HIDE );
+}
+
+static void choiceSetPos(
+ wControl_p b,
+ wPos_t x,
+ wPos_t y )
+{
+ wChoice_p bc = (wChoice_p)b;
+ wChoiceItem_p * butts;
+ wPos_t dx, dy;
+
+ dx = x - bc->x;
+ dy = y - bc->y;
+ if ((bc->option & BC_NOBORDER)==0)
+ SetWindowPos( bc->hBorder, HWND_TOP, x, y, CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER );
+
+ for (butts = (wChoiceItem_p*)bc->buttList; *butts; butts++ ) {
+ SetWindowPos( (*butts)->hWnd, HWND_TOP,
+ (*butts)->x+=dx, (*butts)->y+=dy,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER );
+ }
+ bc->x = x;
+ bc->y = y;
+}
+
+long FAR PASCAL _export pushChoiceItem(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+ /* Catch <Return> and cause focus to leave control */
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+
+ wControl_p b = mswMapIndex( inx );
+
+ switch (message) {
+ case WM_CHAR:
+ if ( b != NULL) {
+ switch( wParam ) {
+ case 0x0D:
+ case 0x1B:
+ case 0x09:
+ SetFocus( ((wControl_p)(b->parent))->hWnd );
+ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR,
+ wParam, lParam );
+ /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND,
+ inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/
+ return 0L;
+ }
+ }
+ break;
+ }
+ return CallWindowProc( oldChoiceItemProc, hWnd, message, wParam, lParam );
+}
+
+LRESULT choiceItemProc(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wChoiceItem_p me = (wChoiceItem_p)b, *rest;
+ wChoice_p bc;
+ int num;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+ switch (WCMD_PARAM_NOTF) {
+ case BN_CLICKED:
+ bc = me->owner;
+ num = -1;
+ for (rest = (wChoiceItem_p*)bc->buttList; *rest; rest++ ) {
+ switch (bc->type) {
+ case B_TOGGLE:
+ num = rest-(wChoiceItem_p*)bc->buttList;
+ if (*rest == me) {
+ bc->oldVal ^= (1L<<num);
+ }
+ SendMessage( (*rest)->hWnd, BM_SETCHECK,
+ (bc->oldVal & (1L<<num)) != 0, 0L );
+ break;
+
+ case B_RADIO:
+ if (*rest != me) {
+ SendMessage( (*rest)->hWnd, BM_SETCHECK, 0, 0L );
+ } else {
+ bc->oldVal = rest-(wChoiceItem_p*)bc->buttList;
+ SendMessage( (*rest)->hWnd, BM_SETCHECK, 1, 0L );
+ }
+ break;
+ }
+ }
+ if (bc->valueP)
+ *bc->valueP = bc->oldVal;
+ if (bc->action)
+ bc->action( bc->oldVal, bc->data );
+ break;
+
+ }
+ break;
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static callBacks_t choiceCallBacks = {
+ mswRepaintLabel,
+ NULL,
+ NULL,
+ choiceSetBusy,
+ choiceShow,
+ choiceSetPos };
+
+static callBacks_t choiceItemCallBacks = {
+ NULL,
+ NULL,
+ choiceItemProc };
+
+/**
+ * Creates choice buttons. This function is used to create a group of
+ * radio buttons and checkboxes.
+ *
+ * \param type IN type of button
+ * \param parent IN parent window
+ * \param x, y IN position of group
+ * \param helpStr IN index string to find help
+ * \param labelStr IN label for group
+ * \param option IN ?
+ * \param labels IN labels for individual choices
+ * \param valueP OUT pointer for return value
+ * \param action IN ?
+ * \param data IN ?
+ * \return created choice button group
+ */
+
+static wChoice_p choiceCreate(
+ wType_e type,
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ const char **labels,
+ long *valueP,
+ wChoiceCallBack_p action,
+ void *data )
+{
+ wChoice_p b;
+ const char ** lp;
+ int cnt;
+ wChoiceItem_p * butts;
+ int ppx, ppy;
+ int bs;
+ HDC hDc;
+ HWND hButt;
+ int lab_l;
+ DWORD dw;
+ int w, maxW;
+ int pw, ph;
+ int index;
+ char * helpStrCopy;
+ HFONT hFont;
+
+ b = mswAlloc( parent, type, mswStrdup(labelStr), sizeof *b, data, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ b->valueP = valueP;
+ b->action = action;
+ b->labels = labels;
+ b->labelY += 6;
+
+ ppx = b->x;
+ ppy = b->y;
+
+ switch (b->type) {
+ case B_TOGGLE:
+ bs = BS_CHECKBOX;
+ break;
+ case B_RADIO:
+ bs = BS_RADIOBUTTON;
+ break;
+ }
+ for (lp = b->labels,cnt=0; *lp; lp++,cnt++ );
+ butts = (wChoiceItem_p*)malloc( (cnt+1) * sizeof *butts );
+ b->buttList = butts;
+ b->oldVal = (b->valueP?*b->valueP:0);
+ ph = pw = 2;
+ maxW = 0;
+ if (helpStr)
+ helpStrCopy = mswStrdup( helpStr );
+ for (lp = b->labels, cnt=0; *lp; lp++, cnt++, butts++ ) {
+ *butts = (wChoiceItem_p)mswAlloc( parent, B_CHOICEITEM,
+ mswStrdup(_((char *)*lp)), sizeof( wChoiceItem_t ), data, &index );
+ (*butts)->owner = b;
+ (*butts)->hWnd = hButt = CreateWindow( "BUTTON", (*butts)->labelStr,
+ bs | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), b->x+pw, b->y+ph,
+ 80, CHOICE_HEIGHT,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if ( hButt == (HWND)0 ) {
+ mswFail( "choiceCreate button" );
+ return b;
+ }
+ (*butts)->x = b->x+pw;
+ (*butts)->y = b->y+ph;
+ if (b->hWnd == 0)
+ b->hWnd = (*butts)->hWnd;
+ (*butts)->helpStr = helpStrCopy;
+
+ hDc = GetDC( hButt );
+ lab_l = strlen((*butts)->labelStr);
+
+ if (!mswThickFont) {hFont = SelectObject( hDc, mswLabelFont );}
+ dw = GetTextExtent( hDc, (char *)((*butts)->labelStr), lab_l );
+ if (!mswThickFont) {SelectObject( hDc, hFont );}
+
+ w = LOWORD(dw) + CHOICE_MIN_WIDTH;
+
+ if (w > maxW)
+ maxW = w;
+ SetBkMode( hDc, TRANSPARENT );
+ ReleaseDC( hButt, hDc );
+ if (b->option & BC_HORZ) {
+ pw += w;
+ } else {
+ ph += CHOICE_HEIGHT;
+ }
+ if (!SetWindowPos( hButt, HWND_TOP, 0, 0,
+ w, CHOICE_HEIGHT, SWP_NOMOVE|SWP_NOZORDER)) {
+ mswFail("Create CHOICE: SetWindowPos");
+ }
+ mswChainFocus( (wControl_p)*butts );
+ newChoiceItemProc = MakeProcInstance( (XWNDPROC)pushChoiceItem, mswHInst );
+ oldChoiceItemProc = (XWNDPROC)GetWindowLong( (*butts)->hWnd, GWL_WNDPROC );
+ SetWindowLong( (*butts)->hWnd, GWL_WNDPROC, (LONG)newChoiceItemProc );
+ if ( !mswThickFont )
+ SendMessage( (*butts)->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ }
+ *butts = NULL;
+ switch (b->type) {
+ case B_TOGGLE:
+ wToggleSetValue( b, (b->valueP?*b->valueP:0L) );
+ break;
+ case B_RADIO:
+ wRadioSetValue( b, (b->valueP?*b->valueP:0L) );
+ break;
+ }
+ if (b->option & BC_HORZ) {
+ ph = CHOICE_HEIGHT;
+ } else {
+ pw = maxW;
+ }
+ pw += 4; ph += 4;
+ b->w = pw;
+ b->h = ph;
+
+#define FRAME_STYLE SS_ETCHEDFRAME
+
+ if ((b->option & BC_NOBORDER)==0) {
+ b->hBorder = CreateWindow( "STATIC", NULL, WS_CHILD | WS_VISIBLE | FRAME_STYLE,
+ b->x, b->y, pw, ph, ((wControl_p)parent)->hWnd, 0, mswHInst, NULL );
+ }
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ mswCallBacks[ B_CHOICEITEM ] = &choiceItemCallBacks;
+ mswCallBacks[ type ] = &choiceCallBacks;
+ return b;
+}
+
+
+wChoice_p wRadioCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ const char **labels,
+ long *valueP,
+ wChoiceCallBack_p action,
+ void *data )
+{
+ return choiceCreate( B_RADIO, parent, x, y, helpStr, labelStr,
+ option, labels, valueP, action, data );
+}
+
+wChoice_p wToggleCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ const char **labels,
+ long *valueP,
+ wChoiceCallBack_p action,
+ void *data )
+{
+ return choiceCreate( B_TOGGLE, parent, x, y, helpStr, labelStr,
+ option, labels, valueP, action, data );
+}
diff --git a/app/wlib/mswlib/mswcolor.c b/app/wlib/mswlib/mswcolor.c
new file mode 100644
index 0000000..41bf6a9
--- /dev/null
+++ b/app/wlib/mswlib/mswcolor.c
@@ -0,0 +1,362 @@
+/*
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswcolor.c,v 1.2 2007-01-14 08:43:32 m_fischer Exp $
+ */
+
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <windows.h>
+
+#include "mswint.h"
+
+#include "square10.bmp"
+
+/*
+ *****************************************************************************
+ *
+ * Color
+ *
+ *****************************************************************************
+ */
+
+#define NUM_GRAYS (16)
+#define NUM_COLORS (256)
+
+wDrawColor wDrawColorWhite = 0;
+wDrawColor wDrawColorBlack = 1;
+
+#define MAX_COLOR_DISTANCE (3)
+
+static void mswGetCustomColors( void );
+
+
+static struct {
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[NUM_COLORS];
+ } colorPalette = {
+ 0x300,
+ 2,
+ {
+ { 255, 255, 255 }, /* White */
+ { 0, 0, 0 } /* Black */
+ } };
+
+COLORREF mappedColors[NUM_COLORS];
+
+
+static long flipRGB( long rgb )
+{
+ rgb = ((rgb>>16)&0xFF) | (rgb&0x00FF00) | ((rgb&0xFF)<<16);
+ return rgb;
+}
+
+
+static void getpalette( void )
+{
+
+ HDC hdc;
+ int inx, cnt;
+ PALETTEENTRY pe[256];
+ FILE * f;
+ hdc = GetDC(mswHWnd);
+ if (!(GetDeviceCaps( hdc, RASTERCAPS) & RC_PALETTE)) {
+ ReleaseDC( mswHWnd, hdc );
+ return;
+ }
+ cnt = GetDeviceCaps(hdc, SIZEPALETTE);
+ GetSystemPaletteEntries( hdc, 0, cnt, pe );
+ f = fopen( "palette.txt", "w" );
+ for (inx=0;inx<cnt;inx++)
+ fprintf(f, "%d [ %d %d %d %d ]\n", inx, pe[inx].peRed, pe[inx].peGreen, pe[inx].peBlue, pe[inx].peFlags );
+ fclose(f);
+ ReleaseDC( mswHWnd, hdc );
+}
+
+
+static int findColor( int r0, int g0, int b0 )
+{
+ int r1, g1, b1;
+ int d0, d1;
+ int c, cc;
+ PALETTEENTRY *pal;
+
+ pal = colorPalette.palPalEntry;
+ cc = (int)wDrawColorBlack;
+ d0 = 256*3;
+
+ for ( c = 0; c < (int)colorPalette.palNumEntries; c++ ) {
+ r1 = pal[c].peRed;
+ b1 = pal[c].peBlue;
+ g1 = pal[c].peGreen;
+ d1 = abs(r0-r1) + abs(g0-g1) + abs(b0-b1);
+ if (d1 == 0)
+ return c;
+ if (d1 < d0) {
+ d0 = d1;
+ cc = c;
+ }
+ }
+ if ( colorPalette.palNumEntries < 128 ) {
+ pal[colorPalette.palNumEntries].peRed = r0;
+ pal[colorPalette.palNumEntries].peGreen = g0;
+ pal[colorPalette.palNumEntries].peBlue = b0;
+ if ( mswPalette ) {
+ ResizePalette( mswPalette, colorPalette.palNumEntries+1 );
+ SetPaletteEntries( mswPalette, colorPalette.palNumEntries, 1, &pal[colorPalette.palNumEntries] );
+ }
+ return colorPalette.palNumEntries++;
+ }
+ return cc;
+}
+
+
+int mswGetPaletteClock( void )
+{
+ return colorPalette.palNumEntries;
+}
+
+
+void mswInitColorPalette( void )
+{
+ static int initted = FALSE;
+ HDC hDc;
+ int cnt;
+ int rc;
+ static struct {
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[256];
+ } pe;
+
+ if (initted)
+ return;
+
+ initted = TRUE;
+ mswGetCustomColors();
+ mswFontInit();
+ hDc = GetDC(mswHWnd);
+ if (!(GetDeviceCaps( hDc, RASTERCAPS) & RC_PALETTE)) {
+ ReleaseDC( mswHWnd, hDc );
+ return;
+ }
+ cnt = GetDeviceCaps(hDc, SIZEPALETTE);
+ rc = GetSystemPaletteEntries( hDc, 0, cnt, pe.palPalEntry );
+ mswPalette = CreatePalette( (const LOGPALETTE FAR*)&colorPalette );
+ ReleaseDC( mswHWnd, hDc );
+
+}
+
+
+HPALETTE mswCreatePalette( void )
+{
+ return CreatePalette( (const LOGPALETTE FAR*)&colorPalette );
+}
+
+
+int mswGetColorList( RGBQUAD * colors )
+{
+ int i;
+ for (i=0;i<(int)colorPalette.palNumEntries;i++) {
+ colors[i].rgbBlue = colorPalette.palPalEntry[i].peBlue;
+ colors[i].rgbGreen = colorPalette.palPalEntry[i].peGreen;
+ colors[i].rgbRed = colorPalette.palPalEntry[i].peRed;
+ colors[i].rgbReserved = 0;
+ }
+ return NUM_COLORS;
+}
+
+
+COLORREF mswGetColor( wBool_t hasPalette, wDrawColor color )
+{
+ if ( hasPalette )
+ return PALETTEINDEX(color);
+ else
+ return RGB( colorPalette.palPalEntry[color].peRed, colorPalette.palPalEntry[color].peGreen, colorPalette.palPalEntry[color].peBlue );
+}
+
+
+wDrawColor wDrawColorGray(
+ int percent )
+{
+ int n;
+ n = (percent * NUM_GRAYS) / 100;
+ if ( n <= 0 )
+ return wDrawColorBlack;
+ else if ( n > NUM_GRAYS )
+ return wDrawColorWhite;
+ else {
+ n = (n*256)/NUM_GRAYS;
+ return wDrawFindColor( wRGB(n,n,n) );
+ }
+}
+
+wDrawColor wDrawFindColor(
+ long rgb0 )
+{
+ static long saved_rgb = wRGB(255,255,255);
+ static wDrawColor saved_color = 0;
+ int r0, g0, b0;
+
+ if (rgb0 == saved_rgb)
+ return saved_color;
+ r0 = (int)(rgb0>>16)&0xFF;
+ g0 = (int)(rgb0>>8)&0xFF;
+ b0 = (int)(rgb0)&0xFF;
+ saved_rgb = rgb0;
+ return saved_color = findColor( r0, g0, b0 );
+}
+
+
+long wDrawGetRGB(
+ wDrawColor color )
+{
+ long rgb;
+ int r, g, b;
+ r = colorPalette.palPalEntry[color].peRed;
+ g = colorPalette.palPalEntry[color].peGreen;
+ b = colorPalette.palPalEntry[color].peBlue;
+ rgb = wRGB(r,g,b);
+ return rgb;
+}
+
+
+static CHOOSECOLOR chooseColor;
+static COLORREF aclrCust[16];
+
+static void mswGetCustomColors( void )
+{
+ int inx;
+ char colorName[10];
+ long rgb;
+
+ strcpy( colorName, "custom-" );
+ for ( inx=0; inx<16; inx++ ) {
+ sprintf( colorName+7, "%d", inx );
+ wPrefGetInteger( "mswcolor", colorName, &rgb, 0 );
+ aclrCust[inx] = flipRGB(rgb);
+ }
+}
+
+
+void mswPutCustomColors( void )
+{
+ int inx;
+ char colorName[10];
+ long rgb;
+
+ strcpy( colorName, "custom-" );
+ for ( inx=0; inx<16; inx++ ) {
+ rgb = flipRGB(aclrCust[inx]);
+ if ( rgb != 0 ) {
+ sprintf( colorName+7, "%d", inx );
+ wPrefSetInteger( "mswcolor", colorName, rgb );
+ }
+ }
+}
+
+
+wBool_t wColorSelect(
+ const char * title,
+ wDrawColor * color )
+{
+ long rgb;
+
+ memset( &chooseColor, 0, sizeof chooseColor );
+ rgb = flipRGB(wDrawGetRGB(*color));
+ chooseColor.lStructSize = sizeof chooseColor;
+ chooseColor.hwndOwner = mswHWnd;
+ chooseColor.hInstance = NULL;
+ chooseColor.rgbResult = rgb;
+ chooseColor.lpCustColors = aclrCust;
+ chooseColor.Flags = CC_RGBINIT;
+ chooseColor.lCustData = 0L;
+ chooseColor.lpfnHook = NULL;
+ chooseColor.lpTemplateName = (LPSTR)NULL;
+ if ( ChooseColor( &chooseColor ) ) {
+ rgb = flipRGB(chooseColor.rgbResult);
+ *color = wDrawFindColor(rgb);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+typedef struct {
+ wDrawColor * valueP;
+ wColorSelectButtonCallBack_p action;
+ const char * labelStr;
+ void * data;
+ wDrawColor color;
+ wButton_p button;
+ wIcon_p bm;
+ } colorData_t;
+
+
+static void doColorButton(
+ void * data )
+{
+ colorData_t * cd = (colorData_t*)data;
+ wDrawColor newColor;
+
+ newColor = cd->color;
+ if (wColorSelect( cd->labelStr, &newColor )) {
+ cd->color = newColor;
+ wColorSelectButtonSetColor( cd->button, newColor );
+ if (cd->valueP)
+ *cd->valueP = newColor;
+ if (cd->action)
+ cd->action( cd->data, newColor );
+ }
+}
+
+
+wButton_p wColorSelectButtonCreate(
+ wWin_p win,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ wDrawColor * color,
+ wColorSelectButtonCallBack_p action,
+ void * data )
+{
+ wButton_p bb;
+ wIcon_p bm;
+ colorData_t * cd;
+ bm = wIconCreateBitMap( square10_width, square10_height, square10_bits, (color?*color:0) );
+ cd = malloc( sizeof *cd );
+ cd->valueP = color;
+ cd->action = action;
+ cd->data = data;
+ cd->labelStr = labelStr;
+ cd->color = (color?*color:0);
+ cd->bm = bm;
+ bb = wButtonCreate( win, x, y, helpStr, (char*)bm, option|BO_ICON, width, doColorButton, cd );
+ cd->button = bb;
+ if ( labelStr )
+ wControlSetLabel( (wControl_p)bb, labelStr );
+ return bb;
+}
+
+
+void wColorSelectButtonSetColor(
+ wButton_p bb,
+ wDrawColor color )
+{
+ ((colorData_t*)((wControl_p)bb)->data)->color = color;
+ wIconSetColor( ((colorData_t*)((wControl_p)bb)->data)->bm, color );
+ InvalidateRect( ((wControl_p)bb)->hWnd, NULL, TRUE );
+}
+
+
+wDrawColor wColorSelectButtonGetColor(
+ wButton_p bb )
+{
+ return ((colorData_t*)((wControl_p)bb)->data)->color;
+}
diff --git a/app/wlib/mswlib/mswdraw.c b/app/wlib/mswlib/mswdraw.c
new file mode 100644
index 0000000..498b49e
--- /dev/null
+++ b/app/wlib/mswlib/mswdraw.c
@@ -0,0 +1,1783 @@
+/*
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswdraw.c,v 1.6 2009-05-15 18:16:16 m_fischer Exp $
+ */
+
+#define _WIN32_WINNT 0x0500 /* for wheel mouse supposrt */
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <winuser.h>
+
+#ifdef WIN32
+#define wFont_t tagLOGFONTA
+#else
+#define wFont_t tagLOGFONT
+#endif
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Draw
+ *
+ *****************************************************************************
+ */
+
+static wBool_t initted = FALSE;
+
+long wDebugFont;
+
+static FARPROC oldDrawProc;
+
+
+static long tmpOp = 0x990066;
+static long setOp = 0x8800c6;
+static long clrOp = 0xbb0226;
+
+#define CENTERMARK_LENGTH 6
+
+#ifdef SLOW
+static wPos_t XPIX2INCH( wDraw_p d, int ix )
+{
+ return (wPos_t)ix;
+}
+
+static wPos_t YPIX2INCH( wDraw_p d, int iy )
+{
+ wPos_t y;
+ y = (wPos_t)(d->h-2-iy);
+ return y;
+}
+
+static int XINCH2PIX( wDraw_p d, wPos_t xx )
+{
+ int ix;
+ ix = (int)(xx);
+ return ix;
+}
+
+static int YINCH2PIX( wDraw_p d, wPos_t y )
+{
+ int iy;
+ iy = d->h-2 - (int)(y);
+ return iy;
+}
+
+
+static wPos_t XPIXELSTOINCH( wDraw_p d, int ix )
+{
+ return (wPos_t)ix;
+}
+
+
+static wPos_t YPIXELSTOINCH( wDraw_p d, int iy )
+{
+ return (wPos_t)iy;
+}
+#else
+#define XPIX2INCH( d, ix ) \
+ ((wPos_t)ix)
+
+#define YPIX2INCH( d, iy ) \
+ ((wPos_t)(d->h-2-iy))
+
+#define XINCH2PIX( d, xx ) \
+ ((int)(xx))
+
+#define YINCH2PIX( d, y ) \
+ (d->h-2 - (int)(y))
+
+
+#define XPIXELSTOINCH( d, ix ) \
+ ((wPos_t)ix)
+
+
+#define YPIXELSTOINCH( d, iy ) \
+ ((wPos_t)iy)
+
+#endif
+
+/*
+ *****************************************************************************
+ *
+ * Basic Line Draw
+ *
+ *****************************************************************************
+ */
+
+
+
+static long noNegDrawArgs = -1;
+static long noFlatEndCaps = 0;
+
+void wDrawDelayUpdate(
+ wDraw_p d,
+ wBool_t delay )
+{
+}
+
+/**
+ * Sets the proper pen and composition for the next drawing operation
+ *
+ *
+ * \param hDc IN device context
+ * \param d IN ???
+ * \param dw IN line width
+ * \param lt IN line type (dashed, solid, ...)
+ * \param dc IN color
+ * \param dopt IN ????
+ */
+
+static void setDrawMode(
+ HDC hDc,
+ wDraw_p d,
+ wDrawWidth dw,
+ wDrawLineType_e lt,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ int mode;
+ HPEN hOldPen;
+ static wDraw_p d0;
+ static wDrawWidth dw0 = -1;
+ static wDrawLineType_e lt0 = (wDrawLineType_e)-1;
+ static wDrawColor dc0 = -1;
+ static int mode0 = -1;
+ static LOGBRUSH logBrush = { 0, 0, 0 };
+ DWORD penStyle;
+
+ if ( d->hasPalette ) {
+ int winPaletteClock = mswGetPaletteClock();
+ if ( d->paletteClock < winPaletteClock ) {
+ RealizePalette( hDc );
+ d->paletteClock = winPaletteClock;
+ }
+ }
+
+ if (dopt & wDrawOptTemp) {
+ mode = R2_NOTXORPEN;
+ } else {
+ mode = R2_COPYPEN;
+ }
+ SetROP2( hDc, mode );
+ if ( d == d0 && mode == mode0 && dw0 == dw && lt == lt0 && dc == dc0 )
+ return;
+
+ // make sure that the line width is at least 1!
+ if( !dw )
+ dw++;
+
+ d0 = d; mode0 = mode; dw0 = dw; lt0 = lt; dc0 = dc;
+
+ logBrush.lbColor = mswGetColor(d->hasPalette,dc);
+ if ( lt==wDrawLineSolid ) {
+ penStyle = PS_GEOMETRIC | PS_SOLID;
+ if ( noFlatEndCaps == FALSE )
+ penStyle |= PS_ENDCAP_FLAT;
+ d->hPen = ExtCreatePen( penStyle,
+ dw,
+ &logBrush,
+ 0,
+ NULL );
+ /*colorPalette.palPalEntry[dc] );*/
+ } else {
+ d->hPen = CreatePen( PS_DOT, 0, mswGetColor( d->hasPalette, dc ) );
+ }
+ hOldPen = SelectObject( hDc, d->hPen );
+ DeleteObject( hOldPen );
+}
+
+static void setDrawBrush(
+ HDC hDc,
+ wDraw_p d,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ HBRUSH hOldBrush;
+ static wDraw_p d0;
+ static wDrawColor dc0 = -1;
+
+ setDrawMode( hDc, d, 0, wDrawLineSolid, dc, dopt );
+ if ( d == d0 && dc == dc0 )
+ return;
+
+ d0 = d; dc0 = dc;
+
+ d->hBrush = CreateSolidBrush(
+ mswGetColor(d->hasPalette,dc) );
+ hOldBrush = SelectObject( hDc, d->hBrush );
+ DeleteObject( hOldBrush );
+}
+
+
+static void myInvalidateRect(
+ wDraw_p d,
+ RECT * prect )
+{
+ if ( prect->top < 0 ) prect->top = 0;
+ if ( prect->left < 0 ) prect->left = 0;
+ if ( prect->bottom > d->h ) prect->bottom = d->h;
+ if ( prect->right > d->w ) prect->right = d->w;
+ InvalidateRect( d->hWnd, prect, FALSE );
+}
+
+
+static int clip0( POINT * p0, POINT * p1, wDraw_p d )
+{
+ long int x0=p0->x, y0=p0->y, x1=p1->x, y1=p1->y;
+ long int dx, dy;
+ if ( x0<0 && x1<0 ) return 0;
+ if ( y0<0 && y1<0 ) return 0;
+ dx=x1-x0;
+ dy=y1-y0;
+ if ( x0 < 0 ) {
+ y0 -= x0*dy/dx;
+ x0 = 0;
+ }
+ if ( y0 < 0 ) {
+ if ( (x0 -= y0*dx/dy) < 0 ) return 0;
+ y0 = 0;
+ }
+ if ( x1 < 0 ) {
+ y1 -= x1*dy/dx;
+ x1 = 0;
+ }
+ if ( y1 < 0 ) {
+ if ( (x1 -= y1*dx/dy) < 0 ) return 0;
+ y1 = 0;
+ }
+ p0->x = (int)x0;
+ p0->y = (int)y0;
+ p1->x = (int)x1;
+ p1->y = (int)y1;
+ return 1;
+}
+
+
+void wDrawLine(
+ wDraw_p d,
+ wPos_t p0x,
+ wPos_t p0y,
+ wPos_t p1x,
+ wPos_t p1y,
+ wDrawWidth dw,
+ wDrawLineType_e lt,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ POINT p0, p1;
+ RECT rect;
+ setDrawMode( d->hDc, d, dw, lt, dc, dopt );
+ p0.x = XINCH2PIX(d,p0x);
+ p0.y = YINCH2PIX(d,p0y);
+ p1.x = XINCH2PIX(d,p1x);
+ p1.y = YINCH2PIX(d,p1y);
+ if ( noNegDrawArgs>0 && !clip0( &p0, &p1, d ) )
+ return;
+ MoveTo( d->hDc, p0.x, p0.y );
+ LineTo( d->hDc, p1.x, p1.y );
+ if (d->hWnd) {
+ if (dw==0)
+ dw = 1;
+ dw++;
+ if (p0.y<p1.y) {
+ rect.top = p0.y-dw;
+ rect.bottom = p1.y+dw;
+ } else {
+ rect.top = p1.y-dw;
+ rect.bottom = p0.y+dw;
+ }
+ if (p0.x<p1.x) {
+ rect.left = p0.x-dw;
+ rect.right = p1.x+dw;
+ } else {
+ rect.left = p1.x-dw;
+ rect.right = p0.x+dw;
+ }
+ myInvalidateRect( d, &rect );
+ }
+}
+
+static double mswsin( double angle )
+{
+ while (angle < 0.0) angle += 360.0;
+ while (angle >= 360.0) angle -= 360.0;
+ angle *= (M_PI*2.0)/360.0;
+ return sin( angle );
+}
+
+static double mswcos( double angle )
+{
+ while (angle < 0.0) angle += 360.0;
+ while (angle >= 360.0) angle -= 360.0;
+ angle *= (M_PI*2.0)/360.0;
+ return cos( angle );
+}
+
+static double mswasin( double x, double h )
+{
+ double angle;
+ angle = asin( x/h );
+ angle /= (M_PI*2.0)/360.0;
+ return angle;
+}
+
+/**
+ * Draw an arc around a specified center
+ *
+ * \param d IN ?
+ * \param px, py IN center of arc
+ * \param r IN radius
+ * \param a0, a1 IN start and end angle
+ * \param drawCenter draw marking for center
+ * \param dw line width
+ * \param lt line type
+ * \param dc color
+ * \param dopt ?
+ */
+
+
+void wDrawArc(
+ wDraw_p d,
+ wPos_t px,
+ wPos_t py,
+ wPos_t r,
+ double a0,
+ double a1,
+ int drawCenter,
+ wDrawWidth dw,
+ wDrawLineType_e lt,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ int i, cnt;
+ POINT p0, p1, ps, pe, pp0, pp1, pp2, pc;
+ double psx, psy, pex, pey, len, aa;
+ RECT rect;
+ int needMoveTo;
+ wBool_t fakeArc = FALSE;
+
+ len = a1/360.0 * (2 * M_PI) * r;
+ if (len < 3)
+ return;
+
+ p0.x = XINCH2PIX(d,px-r);
+ p0.y = YINCH2PIX(d,py+r)+1;
+ p1.x = XINCH2PIX(d,px+r);
+ p1.y = YINCH2PIX(d,py-r)+1;
+
+ pex = px + r * mswsin(a0);
+ pey = py + r * mswcos(a0);
+ psx = px + r * mswsin(a0+a1);
+ psy = py + r * mswcos(a0+a1);
+
+ /*pointOnCircle( &pe, p, r, a0 );
+ pointOnCircle( &ps, p, r, a0+a1 );*/
+ ps.x = XINCH2PIX(d,(wPos_t)psx);
+ ps.y = YINCH2PIX(d,(wPos_t)psy);
+ pe.x = XINCH2PIX(d,(wPos_t)pex);
+ pe.y = YINCH2PIX(d,(wPos_t)pey);
+
+ setDrawMode( d->hDc, d, dw, lt, dc, dopt );
+
+ if (dw == 0)
+ dw = 1;
+
+ if (r>4096) {
+ /* The book says 32K but experience says otherwise */
+ fakeArc = TRUE;
+ }
+ if ( noNegDrawArgs > 0 ) {
+ if ( p0.x < 0 || p0.y < 0 || p1.x < 0 || p1.y < 0 )
+ fakeArc = TRUE;
+ }
+ if ( fakeArc ) {
+ cnt = (int)a1;
+ if ( cnt <= 0 ) cnt = 1;
+ if ( cnt > 360 ) cnt = 360;
+ aa = a1 / cnt;
+ psx = px + r * mswsin(a0);
+ psy = py + r * mswcos(a0);
+ pp0.x = XINCH2PIX( d, (wPos_t)psx );
+ pp0.y = YINCH2PIX( d, (wPos_t)psy );
+ needMoveTo = TRUE;
+ for ( i=0; i<cnt; i++ ) {
+ a0 += aa;
+ psx = px + r * mswsin(a0);
+ psy = py + r * mswcos(a0);
+ pp2.x = pp1.x = XINCH2PIX( d, (wPos_t)psx );
+ pp2.y = pp1.y = YINCH2PIX( d, (wPos_t)psy );
+ if ( clip0( &pp0, &pp1, d ) ) {
+ if (needMoveTo) {
+ MoveTo( d->hDc, pp0.x, pp0.y );
+ needMoveTo = FALSE;
+ }
+ LineTo( d->hDc, pp1.x, pp1.y );
+ } else {
+ needMoveTo = TRUE;
+ }
+ pp0.x = pp2.x; pp0.y = pp2.y;
+ }
+ } else {
+ if ( a0 == 0.0 && a1 == 360.0 ) {
+ Arc( d->hDc, p0.x, p1.y, p1.x, p0.y, ps.x, p0.y-1, pe.x, p1.y-1 );
+ Arc( d->hDc, p0.x, p1.y, p1.x, p0.y, ps.x, p1.y-1, pe.x, p0.y-1 );
+ } else {
+ Arc( d->hDc, p0.x, p1.y, p1.x, p0.y, ps.x, ps.y, pe.x, pe.y );
+ }
+ }
+
+ // should the center of the arc be drawn?
+ if( drawCenter ) {
+
+ // calculate the center coordinates
+ pc.x = XINCH2PIX( d, px );
+ pc.y = YINCH2PIX( d, py );
+ // now draw the crosshair
+ MoveTo( d->hDc, pc.x - CENTERMARK_LENGTH/2, pc.y );
+ LineTo( d->hDc, pc.x + CENTERMARK_LENGTH/2, pc.y );
+ MoveTo( d->hDc, pc.x, pc.y - CENTERMARK_LENGTH/2 );
+ LineTo( d->hDc, pc.x, pc.y + CENTERMARK_LENGTH/2 );
+
+ // invalidate the area of the crosshair
+ rect.top = pc.y - CENTERMARK_LENGTH / 2 - 1;
+ rect.bottom = pc.y + CENTERMARK_LENGTH / 2 + 1;
+ rect.left = pc.x - CENTERMARK_LENGTH / 2 - 1;
+ rect.right = pc.x + CENTERMARK_LENGTH / 2 + 1;
+ myInvalidateRect( d, &rect );
+ }
+
+ if (d->hWnd) {
+ dw++;
+ a1 += a0;
+ if (a1>360.0)
+ rect.top = p0.y;
+ else
+ rect.top = min(pe.y,ps.y);
+ if (a1>(a0>180?360.0:0.0)+180)
+ rect.bottom = p1.y;
+ else
+ rect.bottom = max(pe.y,ps.y);
+ if (a1>(a0>270?360.0:0.0)+270)
+ rect.left = p0.x;
+ else
+ rect.left = min(pe.x,ps.x);
+ if (a1>(a0>90?360.0:0.0)+90)
+ rect.right = p1.x;
+ else
+ rect.right = max(pe.x,ps.x);
+ rect.top -= dw;
+ rect.bottom += dw;
+ rect.left -= dw;
+ rect.right += dw;
+ myInvalidateRect( d, &rect );
+
+ }
+}
+
+void wDrawPoint(
+ wDraw_p d,
+ wPos_t px,
+ wPos_t py,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ POINT p0;
+ RECT rect;
+
+ p0.x = XINCH2PIX(d,px);
+ p0.y = YINCH2PIX(d,py);
+
+ if ( p0.x < 0 || p0.y < 0 )
+ return;
+ if ( p0.x >= d->w || p0.y >= d->h )
+ return;
+ setDrawMode( d->hDc, d, 0, wDrawLineSolid, dc, dopt );
+
+ SetPixel( d->hDc, p0.x, p0.y, mswGetColor(d->hasPalette,dc) /*colorPalette.palPalEntry[dc]*/ );
+ if (d->hWnd) {
+ rect.top = p0.y-1;
+ rect.bottom = p0.y+1;
+ rect.left = p0.x-1;
+ rect.right = p0.x+1;
+ myInvalidateRect( d, &rect );
+ }
+}
+
+/*
+ *****************************************************************************
+ *
+ * Fonts
+ *
+ *****************************************************************************
+ */
+
+
+static LOGFONT logFont = {
+ /* Initial default values */
+ -24, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Arial" };
+
+static LOGFONT timesFont[2][2] = {
+ { {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Times" },
+ {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 1, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Times" } },
+ { {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_BOLD,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Times" },
+ {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_BOLD,
+ 1, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Times" } } };
+
+static LOGFONT helvFont[2][2] = {
+ { {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Arial" },
+ {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 1, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Arial" } },
+ { {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_BOLD,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Arial" },
+ {
+ /* Initial default values */
+ 0, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_BOLD,
+ 1, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ 0, /* P&F */
+ "Hevletica" } } };
+
+
+void mswFontInit( void )
+{
+ const char * face;
+ long size;
+ face = wPrefGetString( "msw window font", "face" );
+ wPrefGetInteger( "msw window font", "size", &size, -24 );
+ if (face) {
+ strncpy( logFont.lfFaceName, face, LF_FACESIZE );
+ }
+ logFont.lfHeight = (int)size;
+}
+
+
+static CHOOSEFONT chooseFont;
+static wFontSize_t fontSize = 18;
+static double fontFactor = 1.0;
+
+static void doChooseFont( void )
+{
+ int rc;
+ memset( &chooseFont, 0, sizeof chooseFont );
+ chooseFont.lStructSize = sizeof chooseFont;
+ chooseFont.hwndOwner = mswHWnd;
+ chooseFont.lpLogFont = &logFont;
+ chooseFont.Flags = CF_SCREENFONTS|CF_SCALABLEONLY|CF_INITTOLOGFONTSTRUCT;
+ chooseFont.nFontType = SCREEN_FONTTYPE;
+ rc = ChooseFont( &chooseFont );
+ if (rc) {
+ fontSize = (wFontSize_t)(-logFont.lfHeight * 72) / 96.0 / fontFactor;
+ if (fontSize < 1)
+ fontSize = 1;
+ wPrefSetString( "msw window font", "face", logFont.lfFaceName );
+ wPrefSetInteger( "msw window font", "size", logFont.lfHeight );
+ }
+}
+
+static int computeFontSize( wDraw_p d, double siz )
+{
+ int ret;
+ siz = (siz * d->DPI) / 72.0;
+ ret = (int)(siz * fontFactor);
+ if (ret < 1)
+ ret = 1;
+ return -ret;
+}
+
+void wDrawGetTextSize(
+ wPos_t *w,
+ wPos_t *h,
+ wPos_t *d,
+ wDraw_p bd,
+ const char * text,
+ wFont_p fp,
+ double siz )
+{
+ int x, y;
+ HFONT newFont, prevFont;
+ DWORD extent;
+ int oldLfHeight;
+ if (fp == NULL)
+ fp = &logFont;
+ fp->lfEscapement = 0;
+ oldLfHeight = fp->lfHeight;
+ fp->lfHeight = computeFontSize( bd, siz );
+ fp->lfWidth = 0;
+ newFont = CreateFontIndirect( fp );
+ prevFont = SelectObject( bd->hDc, newFont );
+ extent = GetTextExtent( bd->hDc, CAST_AWAY_CONST text, strlen(text) );
+ x = LOWORD(extent);
+ y = HIWORD(extent);
+ *w = XPIXELSTOINCH( bd, x );
+ *h = YPIXELSTOINCH( bd, y );
+ *d = 0;
+ SelectObject( bd->hDc, prevFont );
+ DeleteObject( newFont );
+ fp->lfHeight = oldLfHeight;
+}
+
+void wDrawString(
+ wDraw_p d,
+ wPos_t px,
+ wPos_t py,
+ double angle,
+ const char * text,
+ wFont_p fp,
+ double siz,
+ wDrawColor dc,
+ wDrawOpts dopts )
+{
+ int x, y;
+ HFONT newFont, prevFont;
+ HDC newDc;
+ HBITMAP oldBm, newBm;
+ DWORD extent;
+ int w, h;
+ RECT rect;
+ int oldLfHeight;
+
+ if (fp == NULL)
+ fp = &logFont;
+ oldLfHeight = fp->lfHeight;
+ fp->lfEscapement = (int)(angle*10.0);
+ fp->lfHeight = computeFontSize( d, siz );
+ fp->lfWidth = 0;
+ newFont = CreateFontIndirect( fp );
+ x = XINCH2PIX(d,px) + (int)(mswsin(angle)*fp->lfHeight-0.5);
+ y = YINCH2PIX(d,py) + (int)(mswcos(angle)*fp->lfHeight-0.5);
+ if ( noNegDrawArgs > 0 && ( x < 0 || y < 0 ) )
+ return;
+ if (dopts & wDrawOptTemp) {
+ setDrawMode( d->hDc, d, 0, wDrawLineSolid, dc, dopts );
+ newDc = CreateCompatibleDC( d->hDc );
+ prevFont = SelectObject( newDc, newFont );
+ extent = GetTextExtent( newDc, CAST_AWAY_CONST text, strlen(text) );
+ w = LOWORD(extent);
+ h = HIWORD(extent);
+ if ( h > w ) w = h;
+ newBm = CreateCompatibleBitmap( d->hDc, w*2, w*2 );
+ oldBm = SelectObject( newDc, newBm );
+ rect.top = rect.left = 0;
+ rect.bottom = rect.right = w*2;
+ FillRect( newDc, &rect, GetStockObject(WHITE_BRUSH) );
+ TextOut( newDc, w, w, text, strlen(text) );
+ BitBlt( d->hDc, x-w, y-w, w*2, w*2, newDc, 0, 0, tmpOp );
+ SelectObject( newDc, oldBm );
+ DeleteObject( newBm );
+ SelectObject( newDc, prevFont );
+ DeleteDC( newDc );
+ if (d->hWnd) {
+ rect.top = y-(w+1);
+ rect.bottom = y+(w+1);
+ rect.left = x-(w+1);
+ rect.right = x+(w+1);
+ myInvalidateRect( d, &rect );
+ }
+#ifdef LATER
+ /* KLUDGE: Can't Invert text, so we just draw a bow - a pox on windows*/
+ MoveTo( d->hDc, x, y );
+ LineTo( d->hDc, x+w, y );
+ LineTo( d->hDc, x+w, y+h );
+ LineTo( d->hDc, x, y+h );
+ LineTo( d->hDc, x, y );
+#endif
+ } else {
+ prevFont = SelectObject( d->hDc, newFont );
+ SetBkMode( d->hDc, TRANSPARENT );
+ if (dc != wDrawColorBlack) {
+ COLORREF old;
+ old = SetTextColor( d->hDc, mswGetColor(d->hasPalette,dc)/*colorPalette.palPalEntry[dc]*/ );
+ TextOut( d->hDc, x, y, text, strlen(text) );
+ SetTextColor( d->hDc, old );
+ } else
+ TextOut( d->hDc, x, y, text, strlen(text) );
+ extent = GetTextExtent( d->hDc, CAST_AWAY_CONST text, strlen(text) );
+ SelectObject( d->hDc, prevFont );
+ w = LOWORD(extent);
+ h = HIWORD(extent);
+ if (d->hWnd) {
+ rect.top = y-(w+h+1);
+ rect.bottom = y+(w+h+1);
+ rect.left = x-(w+h+1);
+ rect.right = x+(w+h+1);
+ myInvalidateRect( d, &rect );
+ }
+ }
+ DeleteObject( newFont );
+ fp->lfHeight = oldLfHeight;
+}
+
+static const char * wCurFont( void )
+{
+ return logFont.lfFaceName;
+}
+
+void wInitializeFonts()
+{
+}
+
+wFont_p wStandardFont( int family, wBool_t bold, wBool_t italic )
+{
+ if (family == F_TIMES)
+ return &timesFont[bold][italic];
+ else if (family == F_HELV)
+ return &helvFont[bold][italic];
+ else
+ return NULL;
+}
+
+void wSelectFont( const char * title )
+{
+ doChooseFont();
+}
+
+
+wFontSize_t wSelectedFontSize( void )
+{
+ return fontSize;
+}
+
+void wSetSelectedFontSize(int size)
+{
+ fontSize = (wFontSize_t)size;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Misc
+ *
+ *****************************************************************************
+ */
+
+
+
+void wDrawFilledRectangle(
+ wDraw_p d,
+ wPos_t px,
+ wPos_t py,
+ wPos_t sx,
+ wPos_t sy,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ RECT rect;
+ if (d == NULL)
+ return;
+ setDrawBrush( d->hDc, d, color, opts );
+ rect.left = XINCH2PIX(d,px);
+ rect.right = XINCH2PIX(d,px+sx);
+ rect.top = YINCH2PIX(d,py+sy);
+ rect.bottom = YINCH2PIX(d,py);
+ if ( rect.right < 0 ||
+ rect.bottom < 0 )
+ return;
+ if ( rect.left < 0 )
+ rect.left = 0;
+ if ( rect.top < 0 )
+ rect.top = 0;
+ if ( rect.left > d->w ||
+ rect.top > d->h )
+ return;
+ if ( rect.right > d->w )
+ rect.right = d->w;
+ if ( rect.bottom > d->h )
+ rect.bottom = d->h;
+ Rectangle( d->hDc, rect.left, rect.top, rect.right, rect.bottom );
+ if (d->hWnd) {
+ rect.top--;
+ rect.left--;
+ rect.bottom++;
+ rect.right++;
+ myInvalidateRect( d, &rect );
+ }
+}
+
+#ifdef DRAWFILLPOLYLOG
+static FILE * logF;
+#endif
+static int wFillPointsMax = 0;
+static POINT * wFillPoints;
+
+static void addPoint(
+ int * pk,
+ POINT * pp,
+ RECT * pr )
+{
+#ifdef DRAWFILLPOLYLOG
+fprintf( logF, " q[%d] = {%d,%d}\n", *pk, pp->x, pp->y );
+#endif
+ if ( *pk > 0 &&
+ wFillPoints[(*pk)-1].x == pp->x && wFillPoints[(*pk)-1].y == pp->y )
+ return;
+ wFillPoints[ (*pk)++ ] = *pp;
+ if (pp->x<pr->left)
+ pr->left = pp->x;
+ if (pp->x>pr->right)
+ pr->right = pp->x;
+ if (pp->y<pr->top)
+ pr->top = pp->y;
+ if (pp->y>pr->bottom)
+ pr->bottom = pp->y;
+}
+
+void wDrawFilledPolygon(
+ wDraw_p d,
+ wPos_t p[][2],
+ int cnt,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ RECT rect;
+ int i, k;
+ POINT p0, p1, q0, q1;
+ static POINT zero = { 0, 0 };
+ wBool_t p1Clipped;
+
+ if (d == NULL)
+ return;
+ if (cnt*2 > wFillPointsMax) {
+ wFillPoints = realloc( wFillPoints, cnt * 2 * sizeof *(POINT*)NULL );
+ wFillPointsMax = cnt*2;
+ }
+ setDrawBrush( d->hDc, d, color, opts );
+ p1.x = rect.left = rect.right = XINCH2PIX(d,p[cnt-1][0]-1);
+ p1.y = rect.top = rect.bottom = YINCH2PIX(d,p[cnt-1][1]+1);
+#ifdef DRAWFILLPOLYLOG
+logF = fopen( "log.txt", "a" );
+fprintf( logF, "\np[%d] = {%d,%d}\n", cnt-1, p1.x, p1.y );
+#endif
+ p1Clipped = FALSE;
+ for ( i=k=0; i<cnt; i++ ) {
+ p0 = p1;
+ p1.x = XINCH2PIX(d,p[i][0]-1);
+ p1.y = YINCH2PIX(d,p[i][1]+1);
+#ifdef DRAWFILLPOLYLOG
+fprintf( logF, "p[%d] = {%d,%d}\n", i, p1.x, p1.y );
+#endif
+ q0 = p0;
+ q1 = p1;
+ if ( clip0( &q0, &q1, NULL ) ) {
+#ifdef DRAWFILLPOLYLOG
+fprintf( logF, " clip( {%d,%d} {%d,%d} ) = {%d,%d} {%d,%d}\n", p0.x, p0.y, p1.x, p1.y, q0.x, q0.y, q1.x, q1.y );
+#endif
+ if ( q0.x != p0.x || q0.y != p0.y ) {
+ if ( k > 0 && ( q0.x > q0.y ) != ( wFillPoints[k-1].x > wFillPoints[k-1].y ) )
+ addPoint( &k, &zero, &rect );
+ addPoint( &k, &q0, &rect );
+ }
+ addPoint( &k, &q1, &rect );
+ p1Clipped = ( q1.x != p1.x || q1.y != p1.y );
+ }
+ }
+ if ( p1Clipped &&
+ ( wFillPoints[k-1].x > wFillPoints[k-1].y ) != ( wFillPoints[0].x > wFillPoints[0].y ) )
+ addPoint( &k, &zero, &rect );
+#ifdef DRAWFILLPOLYLOG
+fflush( logF );
+fclose( logF );
+#endif
+ if ( k <= 2 )
+ return;
+ Polygon( d->hDc, wFillPoints, k );
+ if (d->hWnd) {
+ rect.top--;
+ rect.left--;
+ rect.bottom++;
+ rect.right++;
+ myInvalidateRect( d, &rect );
+ }
+}
+
+#define MAX_FILLCIRCLE_POINTS (30)
+void wDrawFilledCircle(
+ wDraw_p d,
+ wPos_t x,
+ wPos_t y,
+ wPos_t r,
+ wDrawColor color,
+ wDrawOpts opts )
+{
+ POINT p0, p1;
+ RECT rect;
+ static wPos_t circlePts[MAX_FILLCIRCLE_POINTS][2];
+ int inx, cnt;
+ double dang;
+
+ p0.x = XINCH2PIX(d,x-r);
+ p0.y = YINCH2PIX(d,y+r)+1;
+ p1.x = XINCH2PIX(d,x+r);
+ p1.y = YINCH2PIX(d,y-r)+1;
+
+ setDrawBrush( d->hDc, d, color, opts );
+ if ( noNegDrawArgs > 0 && ( p0.x < 0 || p0.y < 0 ) ) {
+ if ( r > MAX_FILLCIRCLE_POINTS )
+ cnt = MAX_FILLCIRCLE_POINTS;
+ else if ( r > 8 )
+ cnt = r;
+ else
+ cnt = 8;
+ dang = 360.0/cnt;
+ for ( inx=0; inx<cnt; inx++ ) {
+ circlePts[inx][0] = x + (int)(r * mswcos( inx*dang ) + 0.5 );
+ circlePts[inx][1] = y + (int)(r * mswsin( inx*dang ) + 0.5 );
+ }
+ wDrawFilledPolygon( d, circlePts, cnt, color, opts );
+ } else {
+ Ellipse( d->hDc, p0.x, p0.y, p1.x, p1.y );
+ if (d->hWnd) {
+ rect.top = p0.y;
+ rect.bottom = p1.y;
+ rect.left = p0.x;
+ rect.right = p1.x;
+ myInvalidateRect( d, &rect );
+ }
+ }
+}
+
+/*
+ *****************************************************************************
+ *
+ * Misc
+ *
+ *****************************************************************************
+ */
+
+
+void wDrawSaveImage(
+ wDraw_p bd )
+{
+ if ( bd->hBmBackup ) {
+ SelectObject( bd->hDcBackup, bd->hBmBackupOld );
+ DeleteObject( bd->hBmBackup );
+ bd->hBmBackup = (HBITMAP)0;
+ }
+ if ( bd->hDcBackup == (HDC)0 )
+ bd->hDcBackup = CreateCompatibleDC( bd->hDc );
+ bd->hBmBackup = CreateCompatibleBitmap( bd->hDc, bd->w, bd->h );
+ bd->hBmBackupOld = SelectObject( bd->hDcBackup, bd->hBmBackup );
+ BitBlt( bd->hDcBackup, 0, 0, bd->w, bd->h, bd->hDc, 0, 0, SRCCOPY );
+}
+
+void wDrawRestoreImage(
+ wDraw_p bd )
+{
+ if ( bd->hBmBackup == (HBITMAP)0 ) {
+ mswFail( "wDrawRestoreImage: hBmBackup == 0" );
+ return;
+ }
+ BitBlt( bd->hDc, 0, 0, bd->w, bd->h, bd->hDcBackup, 0, 0, SRCCOPY );
+ InvalidateRect( bd->hWnd, NULL, FALSE );
+}
+
+
+void wDrawClear( wDraw_p d )
+{
+ RECT rect;
+ SetROP2( d->hDc, R2_WHITE );
+ Rectangle( d->hDc, 0, 0, d->w, d->h );
+ if (d->hWnd) {
+ rect.top = 0;
+ rect.bottom = d->h;
+ rect.left = 0;
+ rect.right = d->w;
+ InvalidateRect( d->hWnd, &rect, FALSE );
+ }
+}
+
+
+void wDrawSetSize(
+ wDraw_p d,
+ wPos_t width,
+ wPos_t height )
+{
+ d->w = width;
+ d->h = height;
+ if (!SetWindowPos( d->hWnd, HWND_TOP, 0, 0,
+ d->w, d->h, SWP_NOMOVE|SWP_NOZORDER)) {
+ mswFail("wDrawSetSize: SetWindowPos");
+ }
+ /*wRedraw( d );*/
+}
+
+
+void wDrawGetSize(
+ wDraw_p d,
+ wPos_t * width,
+ wPos_t * height )
+{
+ *width = d->w-2;
+ *height = d->h-2;
+}
+
+
+void * wDrawGetContext( wDraw_p d )
+{
+ return d->data;
+}
+
+
+double wDrawGetDPI( wDraw_p d )
+{
+ return d->DPI;
+}
+
+double wDrawGetMaxRadius( wDraw_p d )
+{
+ return 4096.0;
+}
+
+void wDrawClip(
+ wDraw_p d,
+ wPos_t x,
+ wPos_t y,
+ wPos_t w,
+ wPos_t h )
+{
+ int ix0, iy0, ix1, iy1;
+ HRGN hRgnClip;
+ ix0 = XINCH2PIX(d,x);
+ iy0 = YINCH2PIX(d,y);
+ ix1 = XINCH2PIX(d,x+w);
+ iy1 = YINCH2PIX(d,y+h);
+ /* Note: Ydim is upside down so iy1<iy0 */
+ hRgnClip = CreateRectRgn( ix0, iy1, ix1, iy0 );
+ SelectClipRgn( d->hDc, hRgnClip );
+ DeleteObject( hRgnClip );
+}
+
+
+void wRedraw( wDraw_p d )
+{
+ wDrawClear( d );
+ if (d->drawRepaint)
+ d->drawRepaint( d, d->data, 0, 0 );
+}
+
+/*
+ *****************************************************************************
+ *
+ * BitMap
+ *
+ *****************************************************************************
+ */
+
+struct wDrawBitMap_t {
+ wDrawBitMap_p next;
+ wPos_t x;
+ wPos_t y;
+ wPos_t w;
+ wPos_t h;
+ char * bmx;
+ wDrawColor color;
+ HBITMAP bm;
+ };
+wDrawBitMap_p bmRoot = NULL;
+
+
+void wDrawBitMap(
+ wDraw_p d,
+ wDrawBitMap_p bm,
+ wPos_t px,
+ wPos_t py,
+ wDrawColor dc,
+ wDrawOpts dopt )
+{
+ HDC bmDc, hDc;
+ HBITMAP oldBm;
+ DWORD mode;
+ int x0, y0;
+ RECT rect;
+
+ x0 = XINCH2PIX(d,px-bm->x);
+ y0 = YINCH2PIX(d,py-bm->y+bm->h);
+#ifdef LATER
+ if ( noNegDrawArgs > 0 && ( x0 < 0 || y0 < 0 ) )
+ return;
+#endif
+ if (dopt & wDrawOptTemp) {
+ mode = tmpOp;
+ } else if (dc == wDrawColorWhite) {
+ mode = clrOp;
+ dc = wDrawColorBlack;
+ } else {
+ mode = setOp;
+ }
+
+ if ( bm->color != dc ) {
+ if ( bm->bm )
+ DeleteObject( bm->bm );
+ bm->bm = mswCreateBitMap( mswGetColor(d->hasPalette,dc) /*colorPalette.palPalEntry[dc]*/, RGB( 255, 255, 255 ),
+ RGB( 255, 255, 255 ), bm->w, bm->h, bm->bmx );
+ bm->color = dc;
+ }
+ if ( (dopt & wDrawOptNoClip) != 0 &&
+ ( px < 0 || px >= d->w || py < 0 || py >= d->h ) ) {
+ x0 += d->x;
+ y0 += d->y;
+ hDc = GetDC( ((wControl_p)(d->parent))->hWnd );
+ bmDc = CreateCompatibleDC( hDc );
+ oldBm = SelectObject( bmDc, bm->bm );
+ BitBlt( hDc, x0, y0, bm->w, bm->h, bmDc, 0, 0, tmpOp );
+ SelectObject( bmDc, oldBm );
+ DeleteDC( bmDc );
+ ReleaseDC( ((wControl_p)(d->parent))->hWnd, hDc );
+ return;
+ }
+
+ bmDc = CreateCompatibleDC( d->hDc );
+ setDrawMode( d->hDc, d, 0, wDrawLineSolid, dc, dopt );
+ oldBm = SelectObject( bmDc, bm->bm );
+ BitBlt( d->hDc, x0, y0, bm->w, bm->h, bmDc, 0, 0, mode );
+ SelectObject( bmDc, oldBm );
+ DeleteDC( bmDc );
+ if (d->hWnd) {
+ rect.top = y0-1;
+ rect.bottom = rect.top+bm->h+1;
+ rect.left = x0-1;
+ rect.right = rect.left+bm->w+1;
+ myInvalidateRect( d, &rect );
+ }
+}
+
+
+wDrawBitMap_p wDrawBitMapCreate(
+ wDraw_p d,
+ int w,
+ int h,
+ int x,
+ int y,
+ const char * bits )
+{
+ wDrawBitMap_p bm;
+ int bmSize = ((w+7)/8) * h;
+ bm = (wDrawBitMap_p)malloc( sizeof *bm );
+ if (bmRoot == NULL) {
+ bmRoot = bm;
+ bm->next = NULL;
+ } else {
+ bm->next = bmRoot;
+ bmRoot = bm;
+ }
+ bm->x = x;
+ bm->y = y;
+ bm->w = w;
+ bm->h = h;
+ bm->bmx = malloc( bmSize );
+ bm->bm = (HBITMAP)0;
+ bm->color = -1;
+ memcpy( bm->bmx, bits, bmSize );
+ /*bm->bm = mswCreateBitMap( GetSysColor(COLOR_BTNTEXT), RGB( 255, 255, 255 ), w, h, bits );*/
+ return bm;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Create
+ *
+ *****************************************************************************
+ */
+
+int doSetFocus = 1;
+
+long FAR PASCAL XEXPORT mswDrawPush(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+ wDraw_p b;
+ short int ix, iy;
+ wPos_t x, y;
+ HDC hDc;
+ PAINTSTRUCT ps;
+ wAction_t action;
+ RECT rect;
+ HWND activeWnd;
+ HWND focusWnd;
+ wAccelKey_e extChar;
+
+ switch( message ) {
+ case WM_CREATE:
+ b = (wDraw_p)mswMapIndex( inx );
+ hDc = GetDC(hWnd);
+ if ( b->option & BD_DIRECT ) {
+ b->hDc = hDc;
+ b->hBm = 0;
+ b->hBmOld = 0;
+ } else {
+ b->hDc = CreateCompatibleDC( hDc );
+ b->hBm = CreateCompatibleBitmap( hDc, b->w, b->h );
+ b->hBmOld = SelectObject( b->hDc, b->hBm );
+ }
+ if (mswPalette) {
+ SelectPalette( b->hDc, mswPalette, 0 );
+ RealizePalette( b->hDc );
+ }
+ b->wFactor = (double)GetDeviceCaps( b->hDc, LOGPIXELSX );
+ b->hFactor = (double)GetDeviceCaps( b->hDc, LOGPIXELSY );
+ b->DPI = 96.0; /*min( b->wFactor, b->hFactor );*/
+ b->hWnd = hWnd;
+ SetROP2( b->hDc, R2_WHITE );
+ Rectangle( b->hDc, 0, 0, b->w, b->h );
+ if ( (b->option & BD_DIRECT) == 0 ) {
+ SetROP2( hDc, R2_WHITE );
+ Rectangle( hDc, 0, 0, b->w, b->h );
+ ReleaseDC( hWnd, hDc );
+ }
+ break;
+ case WM_SIZE:
+ b = (wDraw_p)mswMapIndex( inx );
+ ix = LOWORD( lParam );
+ iy = HIWORD( lParam );
+ b->w = ix+2;
+ b->h = iy+2;
+ if (b->hWnd) {
+ if ( b->option & BD_DIRECT ) {
+ } else {
+ hDc = GetDC( b->hWnd );
+ b->hBm = CreateCompatibleBitmap( hDc, b->w, b->h );
+ DeleteObject(SelectObject( b->hDc, b->hBm ));
+ ReleaseDC( b->hWnd, hDc );
+ SetROP2( b->hDc, R2_WHITE );
+ Rectangle( b->hDc, 0, 0, b->w, b->h );
+ }
+ }
+ /*if (b->drawResize)
+ b->drawResize( b, b->size );*/
+ if (b->drawRepaint)
+ b->drawRepaint( b, b->data, 0, 0 );
+ return 0;
+ case WM_MOUSEMOVE:
+ activeWnd = GetActiveWindow();
+ focusWnd = GetFocus();
+ if (focusWnd != hWnd) {
+ b = (wDraw_p)mswMapIndex( inx );
+ if (!b)
+ break;
+ if ( !((wControl_p)b->parent) )
+ break;
+ if ( ((wControl_p)b->parent)->hWnd != activeWnd )
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ if (message == WM_LBUTTONDOWN)
+ action = wActionLDown;
+ else if (message == WM_RBUTTONDOWN)
+ action = wActionRDown;
+ else if (message == WM_LBUTTONUP)
+ action = wActionLUp;
+ else if (message == WM_RBUTTONUP)
+ action = wActionRUp;
+ else {
+ if ( (wParam & MK_LBUTTON) != 0)
+ action = wActionLDrag;
+ else if ( (wParam & MK_RBUTTON) != 0)
+ action = wActionRDrag;
+ else
+ action = wActionMove;
+ }
+ b = (wDraw_p)mswMapIndex( inx );
+ if (!b)
+ break;
+ if (doSetFocus && message != WM_MOUSEMOVE)
+ SetFocus( ((wControl_p)b->parent)->hWnd );
+ if ( (b->option&BD_NOCAPTURE) == 0 ) {
+ if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN)
+ SetCapture( b->hWnd );
+ else if (message == WM_LBUTTONUP || message == WM_RBUTTONUP)
+ ReleaseCapture();
+ }
+ ix = LOWORD( lParam );
+ iy = HIWORD( lParam );
+ x = XPIX2INCH( b, ix );
+ y = YPIX2INCH( b, iy );
+ if (b->action)
+ b->action( b, b->data, action, x, y );
+ if (b->hWnd)
+ UpdateWindow(b->hWnd);
+ return 0;
+ case WM_CHAR:
+ b = (wDraw_p)mswMapIndex( inx );
+ extChar = wAccelKey_None;
+ if (lParam & 0x01000000L)
+ switch( wParam ) {
+ case VK_DELETE: extChar = wAccelKey_Del; break;
+ case VK_INSERT: extChar = wAccelKey_Ins; break;
+ case VK_HOME: extChar = wAccelKey_Home; break;
+ case VK_END: extChar = wAccelKey_End; break;
+ case VK_PRIOR: extChar = wAccelKey_Pgup; break;
+ case VK_NEXT: extChar = wAccelKey_Pgdn; break;
+ case VK_UP: extChar = wAccelKey_Up; break;
+ case VK_DOWN: extChar = wAccelKey_Down; break;
+ case VK_RIGHT: extChar = wAccelKey_Right; break;
+ case VK_LEFT: extChar = wAccelKey_Left; break;
+ case VK_BACK: extChar = wAccelKey_Back; break;
+ /*case VK_F1: extChar = wAccelKey_F1; break;*/
+ case VK_F2: extChar = wAccelKey_F2; break;
+ case VK_F3: extChar = wAccelKey_F3; break;
+ case VK_F4: extChar = wAccelKey_F4; break;
+ case VK_F5: extChar = wAccelKey_F5; break;
+ case VK_F6: extChar = wAccelKey_F6; break;
+ case VK_F7: extChar = wAccelKey_F7; break;
+ case VK_F8: extChar = wAccelKey_F8; break;
+ case VK_F9: extChar = wAccelKey_F9; break;
+ case VK_F10: extChar = wAccelKey_F10; break;
+ case VK_F11: extChar = wAccelKey_F11; break;
+ case VK_F12: extChar = wAccelKey_F12; break;
+ }
+ if (b && b->action) {
+ if (extChar != wAccelKey_None)
+ b->action( b, b->data, wActionExtKey + ( (int)extChar << 8 ), 0, 0 );
+ else
+ b->action( b, b->data, wActionText + ( wParam << 8 ), 0, 0 );
+ }
+ return 0;
+
+ case WM_PAINT:
+ b = (wDraw_p)mswMapIndex( inx );
+ if (b && b->type == B_DRAW) {
+ if (GetUpdateRect( b->hWnd, &rect, FALSE )) {
+ hDc = BeginPaint( hWnd, &ps );
+ if ( b->hasPalette ) {
+ int winPaletteClock = mswGetPaletteClock();
+ if ( b->paletteClock < winPaletteClock ) {
+ RealizePalette( hDc );
+ b->paletteClock = winPaletteClock;
+ }
+ }
+ BitBlt( hDc, rect.left, rect.top,
+ rect.right-rect.left, rect.bottom-rect.top,
+ b->hDc, rect.left, rect.top,
+ SRCCOPY );
+ EndPaint( hWnd, &ps );
+ }
+ }
+ break;
+ case WM_DESTROY:
+ b = (wDraw_p)mswMapIndex( inx );
+ if (b && b->type == B_DRAW) {
+ if (b->hDc) {
+ DeleteDC( b->hDc );
+ b->hDc = (HDC)0;
+ }
+ if (b->hDcBackup) {
+ DeleteDC( b->hDcBackup );
+ b->hDcBackup = (HDC)0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static LRESULT drawMsgProc( wDraw_p b, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ wAction_t action;
+
+ switch( message ) {
+ case WM_MOUSEWHEEL:
+ /* handle mouse wheel events */
+ /* fwKeys = GET_KEYSTATE_WPARAM(wParam); modifier keys are currently ignored */
+ if ( GET_WHEEL_DELTA_WPARAM(wParam) > 0 ) {
+ action = wActionWheelUp;
+ } else {
+ action = wActionWheelDown;
+ }
+ if (b->action)
+ b->action( b, b->data, action, 0, 0 );
+ return 0;
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static void drawDoneProc( wControl_p b )
+{
+ wDraw_p d = (wDraw_p)b;
+ if (d->hBm) {
+ SelectObject( d->hDc, d->hBmOld );
+ DeleteObject( d->hBm );
+ d->hBm = (HBITMAP)0;
+ }
+ if (d->hPen) {
+ SelectObject( d->hDc, GetStockObject( BLACK_PEN ) );
+ DeleteObject( d->hPen );
+ d->hPen = (HPEN)0;
+ }
+ if (d->hBrush) {
+ SelectObject( d->hDc, GetStockObject( BLACK_BRUSH) );
+ DeleteObject( d->hBrush );
+ d->hBrush = (HBRUSH)0;
+ }
+ if (d->hDc) {
+ DeleteDC( d->hDc );
+ d->hDc = (HDC)0;
+ }
+ if ( d->hDcBackup ) {
+ DeleteDC( d->hDcBackup );
+ d->hDcBackup = (HDC)0;
+ }
+ while (bmRoot) {
+ if (bmRoot->bm)
+ DeleteObject( bmRoot->bm );
+ bmRoot = bmRoot->next;
+ }
+}
+
+
+static callBacks_t drawCallBacks = {
+ NULL,
+ drawDoneProc,
+ (messageCallback_p)drawMsgProc };
+
+wDraw_p drawList = NULL;
+
+
+void mswRedrawAll( void )
+{
+ wDraw_p p;
+ for ( p=drawList; p; p=p->drawNext ) {
+ if (p->drawRepaint)
+ p->drawRepaint( p, p->data, 0, 0 );
+ }
+}
+
+
+void mswRepaintAll( void )
+{
+ wDraw_p b;
+ HDC hDc;
+ RECT rect;
+ PAINTSTRUCT ps;
+
+ for ( b=drawList; b; b=b->drawNext ) {
+ if (GetUpdateRect( b->hWnd, &rect, FALSE )) {
+ hDc = BeginPaint( b->hWnd, &ps );
+ BitBlt( hDc, rect.left, rect.top,
+ rect.right-rect.left, rect.bottom-rect.top,
+ b->hDc, rect.left, rect.top,
+ SRCCOPY );
+ EndPaint( b->hWnd, &ps );
+ }
+ }
+}
+
+
+wDraw_p wDrawCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ long option,
+ wPos_t w,
+ wPos_t h,
+ void * data,
+ wDrawRedrawCallBack_p redrawProc,
+ wDrawActionCallBack_p action )
+{
+ wDraw_p d;
+ RECT rect;
+ int index;
+ HDC hDc;
+
+ if ( noNegDrawArgs < 0 ) {
+ wPrefGetInteger( "msw tweak", "NoNegDrawArgs", &noNegDrawArgs, 0 );
+ wPrefGetInteger( "msw tweak", "NoFlatEndCaps", &noFlatEndCaps, 0 );
+ }
+
+ d = mswAlloc( parent, B_DRAW, NULL, sizeof *d, data, &index );
+ mswComputePos( (wControl_p)d, x, y );
+ d->w = w;
+ d->h = h;
+ d->drawRepaint = NULL;
+ d->action = action;
+ d->option = option;
+
+ d->hWnd = CreateWindow( mswDrawWindowClassName, NULL,
+ WS_CHILDWINDOW|WS_VISIBLE|WS_BORDER,
+ d->x, d->y, w, h,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+
+ if (d->hWnd == (HWND)0) {
+ mswFail( "CreateWindow(DRAW)" );
+ return d;
+ }
+
+ GetWindowRect( d->hWnd, &rect );
+
+ d->w = rect.right - rect.left;
+ d->h = rect.bottom - rect.top;
+ d->drawRepaint = redrawProc;
+ /*if (d->drawRepaint)
+ d->drawRepaint( d, d->data, 0.0, 0.0 );*/
+
+ mswAddButton( (wControl_p)d, FALSE, helpStr );
+ mswCallBacks[B_DRAW] = &drawCallBacks;
+ d->drawNext = drawList;
+ drawList = d;
+ if (mswPalette) {
+ hDc = GetDC( d->hWnd );
+ d->hasPalette = TRUE;
+ SelectPalette( hDc, mswPalette, 0 );
+ ReleaseDC( d->hWnd, hDc );
+ }
+ return d;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Bitmaps
+ *
+ *****************************************************************************
+ */
+
+wDraw_p wBitMapCreate( wPos_t w, wPos_t h, int planes )
+{
+ wDraw_p d;
+ HDC hDc;
+
+ d = (wDraw_p)calloc(1,sizeof *d);
+ d->type = B_DRAW;
+ d->shown = TRUE;
+ d->x = 0;
+ d->y = 0;
+ d->w = w;
+ d->h = h;
+ d->drawRepaint = NULL;
+ d->action = NULL;
+ d->option = 0;
+
+ hDc = GetDC(mswHWnd);
+ d->hDc = CreateCompatibleDC( hDc );
+ if ( d->hDc == (HDC)0 ) {
+ wNoticeEx( NT_ERROR, "CreateBitMap: CreateDC fails", "Ok", NULL );
+ return FALSE;
+ }
+ d->hBm = CreateCompatibleBitmap( hDc, d->w, d->h );
+ if ( d->hBm == (HBITMAP)0 ) {
+ wNoticeEx( NT_ERROR, "CreateBitMap: CreateBM fails", "Ok", NULL );
+ return FALSE;
+ }
+ d->hasPalette = (GetDeviceCaps(hDc,RASTERCAPS ) & RC_PALETTE) != 0;
+ ReleaseDC( mswHWnd, hDc );
+ d->hBmOld = SelectObject( d->hDc, d->hBm );
+ if (mswPalette) {
+ SelectPalette( d->hDc, mswPalette, 0 );
+ RealizePalette( d->hDc );
+ }
+ d->wFactor = (double)GetDeviceCaps( d->hDc, LOGPIXELSX );
+ d->hFactor = (double)GetDeviceCaps( d->hDc, LOGPIXELSY );
+ d->DPI = 96.0; /*min( d->wFactor, d->hFactor );*/
+ d->hWnd = 0;
+ SetROP2( d->hDc, R2_WHITE );
+ Rectangle( d->hDc, 0, 0, d->w, d->h );
+ return d;
+}
+
+wBool_t wBitMapDelete( wDraw_p d )
+{
+ if (d->hPen) {
+ SelectObject( d->hDc, GetStockObject( BLACK_PEN ) );
+ DeleteObject( d->hPen );
+ d->hPen = (HPEN)0;
+ }
+ if (d->hBm) {
+ SelectObject( d->hDc, d->hBmOld );
+ DeleteObject( d->hBm );
+ d->hBm = (HBITMAP)0;
+ }
+ if (d->hDc) {
+ DeleteDC( d->hDc );
+ d->hDc = (HDC)0;
+ }
+ free(d);
+ return TRUE;
+}
+
+wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName )
+{
+ char *pixels;
+ int j, ww, chunk;
+ FILE * f;
+ BITMAPFILEHEADER bmfh;
+ struct {
+ BITMAPINFOHEADER bmih;
+ RGBQUAD colors[256];
+ } bmi;
+ int rc;
+
+ if ( d->hBm == 0)
+ return FALSE;
+ f = wFileOpen( fileName, "wb" );
+ if (!f) {
+ wNoticeEx( NT_ERROR, fileName, "Ok", NULL );
+ return FALSE;
+ }
+ ww = ((d->w +3) / 4) * 4;
+ bmfh.bfType = 'B'+('M'<<8);
+ bmfh.bfSize = (long)(sizeof bmfh) + (long)(sizeof bmi.bmih) + (long)(sizeof bmi.colors) + (long)ww * (long)(d->h);
+ bmfh.bfReserved1 = 0;
+ bmfh.bfReserved2 = 0;
+ bmfh.bfOffBits = sizeof bmfh + sizeof bmi.bmih + sizeof bmi.colors;
+ fwrite( &bmfh, 1, sizeof bmfh, f );
+ bmi.bmih.biSize = sizeof bmi.bmih;
+ bmi.bmih.biWidth = d->w;
+ bmi.bmih.biHeight = d->h;
+ bmi.bmih.biPlanes = 1;
+ bmi.bmih.biBitCount = 8;
+ bmi.bmih.biCompression = BI_RGB;
+ bmi.bmih.biSizeImage = 0;
+ bmi.bmih.biXPelsPerMeter = 75*(10000/254);
+ bmi.bmih.biYPelsPerMeter = 75*(10000/254);
+ bmi.bmih.biClrUsed = bmi.bmih.biClrImportant = mswGetColorList( bmi.colors );
+ SelectObject( d->hDc, d->hBmOld );
+ rc = GetDIBits( d->hDc, d->hBm, 0, 1, NULL, (BITMAPINFO*)&bmi, DIB_RGB_COLORS );
+ if ( rc == 0 ) {
+ wNoticeEx( NT_ERROR, "WriteBitMap: Can't get bitmapinfo from Bitmap", "Ok", NULL );
+ return FALSE;
+ }
+ bmi.bmih.biClrUsed = 256;
+ fwrite( &bmi.bmih, 1, sizeof bmi.bmih, f );
+ fwrite( bmi.colors, 1, sizeof bmi.colors, f );
+ chunk = 32000/ww;
+ pixels = (char*)malloc( ww*chunk );
+ if ( pixels == NULL ) {
+ wNoticeEx( NT_ERROR, "WriteBitMap: no memory", "OK", NULL );
+ return FALSE;
+ }
+ for (j=0;j<d->h;j+=chunk) {
+ if (j+chunk>d->h)
+ chunk = d->h-j;
+ rc = GetDIBits( d->hDc, d->hBm, j, chunk, pixels, (BITMAPINFO*)&bmi, DIB_RGB_COLORS );
+ if ( rc == 0 )
+ if ( rc == 0 ) {
+ wNoticeEx( NT_ERROR, "WriteBitMap: Can't get bits from Bitmap", "Ok", NULL );
+ return FALSE;
+ }
+ rc = fwrite( pixels, 1, ww*chunk, f );
+ if (rc != ww*chunk) {
+ wNoticeEx( NT_ERROR, "WriteBitMap: Bad fwrite", "Ok", NULL);
+ }
+ }
+ free( pixels );
+ SelectObject( d->hDc, d->hBm );
+ fclose( f );
+ return TRUE;
+}
+
diff --git a/app/wlib/mswlib/mswedit.c b/app/wlib/mswlib/mswedit.c
new file mode 100644
index 0000000..5bb26ec
--- /dev/null
+++ b/app/wlib/mswlib/mswedit.c
@@ -0,0 +1,726 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+
+
+struct wString_t {
+ WOBJ_COMMON
+ char * valueP;
+ wIndex_t valueL;
+ wStringCallBack_p action;
+ };
+
+struct wInteger_t {
+ WOBJ_COMMON
+ long low, high;
+ long * valueP;
+ long oldValue;
+ wIntegerCallBack_p action;
+ };
+
+struct wFloat_t {
+ WOBJ_COMMON
+ double low, high;
+ double * valueP;
+ double oldValue;
+ wFloatCallBack_p action;
+ };
+
+
+static XWNDPROC oldEditProc = NULL;
+static XWNDPROC newEditProc;
+static void triggerString( wControl_p b );
+#ifdef LATER
+static void triggerInteger( wControl_p b );
+static void triggerFloat( wControl_p b );
+#endif
+
+
+long FAR PASCAL _export pushEdit(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+ /* Catch <Return> and cause focus to leave control */
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+ wControl_p b = mswMapIndex( inx );
+
+ switch (message) {
+ case WM_CHAR:
+ if ( b != NULL) {
+ switch( wParam ) {
+ case 0x0D:
+ case 0x1B:
+ case 0x09:
+ SetFocus( ((wControl_p)(b->parent))->hWnd );
+ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR,
+ wParam, lParam );
+ /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND,
+ inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/
+ return 0L;
+ }
+ }
+ break;
+
+ case WM_KEYUP:
+ if ( b != NULL)
+ switch (b->type) {
+ case B_STRING:
+ if (((wString_p)b)->action)
+ mswSetTrigger( (wControl_p)b, triggerString );
+ break;
+#ifdef LATER
+ case B_INTEGER:
+ if (((wInteger_p)b)->action)
+ mswSetTrigger( (wControl_p)b, triggerInteger );
+ break;
+ case B_FLOAT:
+ if (((wFloat_p)b)->action)
+ mswSetTrigger( (wControl_p)b, triggerFloat );
+ break;
+#endif
+ }
+ break;
+
+ }
+ return CallWindowProc( oldEditProc, hWnd, message, wParam, lParam );
+}
+
+/*
+ *****************************************************************************
+ *
+ * String Boxes
+ *
+ *****************************************************************************
+ */
+
+
+void wStringSetValue(
+ wString_p b,
+ const char * arg )
+{
+ WORD len = strlen( arg );
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)arg );
+#ifdef WIN32
+ SendMessage( b->hWnd, EM_SETSEL, len, len );
+ SendMessage( b->hWnd, EM_SCROLLCARET, 0, 0L );
+#else
+ SendMessage( b->hWnd, EM_SETSEL, 0, MAKELPARAM(len,len) );
+#endif
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+}
+
+
+void wStringSetWidth(
+ wString_p b,
+ wPos_t w )
+{
+ int rc;
+ b->w = w;
+ rc = SetWindowPos( b->hWnd, HWND_TOP, 0, 0,
+ b->w, b->h, SWP_NOMOVE|SWP_NOZORDER );
+}
+
+
+const char * wStringGetValue(
+ wString_p b )
+{
+ static char buff[256];
+ SendMessage( b->hWnd, WM_GETTEXT, sizeof buff, (DWORD)buff );
+ return buff;
+}
+
+
+static void triggerString(
+ wControl_p b )
+{
+ wString_p bs = (wString_p)b;
+ int cnt;
+
+ if (bs->action) {
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bs->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (bs->valueP)
+ strcpy( bs->valueP, mswTmpBuff );
+ bs->action( mswTmpBuff, bs->data );
+ mswSetTrigger( NULL, NULL );
+ }
+}
+
+
+LRESULT stringProc(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wString_p bs = (wString_p)b;
+ int cnt;
+ int modified;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+ switch (WCMD_PARAM_NOTF) {
+ case EN_KILLFOCUS:
+ modified = (int)SendMessage( bs->hWnd, (UINT)EM_GETMODIFY, 0, 0L );
+ if (!modified)
+ break;
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bs->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (bs->valueP)
+ strncpy( bs->valueP, mswTmpBuff, bs->valueL );
+ if (bs->action) {
+ bs->action( mswTmpBuff, bs->data );
+ mswSetTrigger( NULL, NULL );
+ }
+ break;
+ SendMessage( bs->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L );
+ }
+ break;
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static callBacks_t stringCallBacks = {
+ mswRepaintLabel,
+ NULL,
+ stringProc };
+
+
+wString_p wStringCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ POS_T width,
+ char *valueP,
+ wIndex_t valueL,
+ wStringCallBack_p action,
+ void *data )
+{
+ wString_p b;
+ RECT rect;
+ int index;
+ DWORD style = 0;
+
+ b = (wString_p)mswAlloc( parent, B_STRING, mswStrdup(labelStr), sizeof *b, data, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ b->valueP = valueP;
+ b->valueL = valueL;
+ b->labelY += 2;
+ b->action = action;
+ if (option & BO_READONLY)
+ style |= ES_READONLY;
+
+#ifdef WIN32
+ b->hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT", NULL,
+ ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style,
+ b->x, b->y,
+ width, mswEditHeight,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+#else
+ b->hWnd = CreateWindow( "EDIT", NULL,
+ ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style,
+ b->x, b->y,
+ width, mswEditHeight,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+#endif
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(STRING)");
+ return b;
+ }
+
+#ifdef CONTROL3D
+ Ctl3dSubclassCtl( b->hWnd);
+#endif
+
+ newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst );
+ oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc );
+
+ if (b->valueP) {
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)b->valueP );
+ }
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ mswCallBacks[B_STRING] = &stringCallBacks;
+ mswChainFocus( (wControl_p)b );
+ return b;
+}
+#ifdef LATER
+
+/*
+ *****************************************************************************
+ *
+ * Integer Value Boxes
+ *
+ *****************************************************************************
+ */
+
+
+#define MININT ((long)0x80000000)
+#define MAXINT ((long)0x7FFFFFFF)
+
+
+void wIntegerSetValue(
+ wInteger_p b,
+ long arg )
+{
+ b->oldValue = arg;
+ wsprintf( mswTmpBuff, "%ld", arg );
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff );
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+}
+
+
+long wIntegerGetValue(
+ wInteger_p b )
+{
+ return b->oldValue;
+}
+
+
+static void triggerInteger(
+ wControl_p b )
+{
+ wInteger_p bi = (wInteger_p)b;
+ int cnt;
+ long value;
+ char * cp;
+
+ if (bi->action) {
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bi->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (strcmp( mswTmpBuff, "-" )==0 )
+ return;
+ value = strtol( mswTmpBuff, &cp, 10 );
+ if (*cp != '\0' || value < bi->low || value > bi->high )
+ return;
+ if (bi->oldValue == value)
+ return;
+ if (bi->valueP)
+ *bi->valueP = value;
+ bi->oldValue = value;
+ bi->action( value, bi->data );
+ }
+}
+
+
+LRESULT integerProc(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wInteger_p bi = (wInteger_p)b;
+ int inx;
+ int cnt;
+ long value;
+ char * cp;
+ wBool_t ok;
+ int modified;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+ switch (WCMD_PARAM_NOTF) {
+ case EN_KILLFOCUS:
+ ok = TRUE;
+ modified = (int)SendMessage( bi->hWnd, (UINT)EM_GETMODIFY, 0, 0L );
+ if (!modified)
+ break;
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bi->hWnd, (UINT)EM_GETLINE, 0, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (strcmp( mswTmpBuff, "-" )==0 && 0 >= bi->low && 0 <= bi->high ) {
+ value = 0;
+ } else {
+ value = strtol( mswTmpBuff, &cp, 10 );
+ if (*cp != '\0' || value < bi->low || value > bi->high ) {
+ inx = GetWindowWord( bi->hWnd, GWW_ID );
+ if (wWinIsVisible(bi->parent)) {
+ PostMessage( ((wControl_p)(bi->parent))->hWnd,
+ WM_NOTVALID, inx, 0L );
+ return TRUE;
+ } else {
+ if (value < bi->low)
+ value = bi->low;
+ else
+ value = bi->high;
+ sprintf( mswTmpBuff, "%ld", value );
+ SendMessage( bi->hWnd, (UINT)WM_SETTEXT, 0,
+ (DWORD)(LPSTR)mswTmpBuff );
+ }
+ }
+ }
+ bi->oldValue = value;
+ if (bi->valueP)
+ *bi->valueP = value;
+ if (bi->action) {
+ bi->action( value, bi->data );
+ mswSetTrigger( NULL, NULL );
+ }
+ SendMessage( bi->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L );
+ }
+ break;
+
+ case WM_NOTVALID:
+ wsprintf( mswTmpBuff, "Please enter a value between %ld and %ld",
+ bi->low, bi->high );
+ if (bi->low > MININT && bi->high < MAXINT)
+ sprintf( mswTmpBuff,
+ "Please enter an integer value between %ld and %ld",
+ bi->low, bi->high );
+ else if (bi->low > MININT)
+ sprintf( mswTmpBuff,
+ "Please enter an integer value greater or equal to %ld",
+ bi->low );
+ else if (bi->high < MAXINT)
+ sprintf( mswTmpBuff,
+ "Please enter an integer value less or equal to %ld",
+ bi->high );
+ else
+ strcpy( mswTmpBuff, "Please enter an integer value" );
+ MessageBox( bi->hWnd, mswTmpBuff, "Invalid entry", MB_OK );
+ SetFocus( bi->hWnd );
+#ifdef WIN32
+ SendMessage( bi->hWnd, EM_SETSEL, 0, 0x7fff );
+ SendMessage( bi->hWnd, EM_SCROLLCARET, 0, 0L );
+#else
+ SendMessage( bi->hWnd, EM_SETSEL, 0, MAKELONG(0,0x7fff) );
+#endif
+ return TRUE;
+
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static callBacks_t integerCallBacks = {
+ mswRepaintLabel,
+ NULL,
+ integerProc };
+
+
+wInteger_p wIntegerCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ POS_T width,
+ long low,
+ long high,
+ long *valueP,
+ wIntegerCallBack_p action,
+ void *data )
+{
+ wInteger_p b;
+ RECT rect;
+ int index;
+ DWORD style = 0;
+
+ b = mswAlloc( parent, B_INTEGER, mswStrdup(labelStr), sizeof *b, data, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ b->low = low;
+ b->high = high;
+ b->valueP = valueP;
+ b->labelY += 2;
+ b->action = action;
+ if (option & BO_READONLY)
+ style |= ES_READONLY;
+
+ b->hWnd = CreateWindow( "EDIT", NULL,
+ ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style,
+ b->x, b->y,
+ width, mswEditHeight,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(INTEGER)");
+ return b;
+ }
+
+#ifdef CONTROL3D
+ Ctl3dSubclassCtl( b->hWnd);
+#endif
+
+ newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst );
+ oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc );
+
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ if (b->valueP) {
+ wsprintf( mswTmpBuff, "%ld", *b->valueP );
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff );
+ b->oldValue = *b->valueP;
+ } else
+ b->oldValue = 0;
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ mswCallBacks[ B_INTEGER ] = &integerCallBacks;
+ mswChainFocus( (wControl_p)b );
+ return b;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Floating Point Value Boxes
+ *
+ *****************************************************************************
+ */
+
+
+#define MINFLT (-1000000)
+#define MAXFLT (1000000)
+
+
+
+void wFloatSetValue(
+ wFloat_p b,
+ double arg )
+{
+ b->oldValue = arg;
+ sprintf( mswTmpBuff, "%0.3f", arg );
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff );
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+}
+
+
+double wFloatGetValue(
+ wFloat_p b )
+{
+ return b->oldValue;
+}
+
+
+static void triggerFloat(
+ wControl_p b )
+{
+ wFloat_p bf = (wFloat_p)b;
+ int cnt;
+ double value;
+ char * cp;
+
+ if (bf->action) {
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bf->hWnd, (UINT)EM_GETLINE, 0,
+ (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (strcmp( mswTmpBuff, "-" )==0)
+ return;
+ value = strtod( mswTmpBuff, &cp );
+ if (*cp != '\0' || value < bf->low || value > bf->high )
+ return;
+ if (bf->oldValue == value)
+ return;
+ bf->oldValue = value;
+ if (bf->valueP)
+ *bf->valueP = value;
+ bf->action( wFloatGetValue(bf), bf->data );
+ }
+}
+
+
+LRESULT floatProc(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wFloat_p bf = (wFloat_p)b;
+ int inx;
+ int cnt;
+ double value;
+ char * cp;
+ wBool_t ok;
+ int modified;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+ switch (HIWORD(lParam)) {
+ case EN_KILLFOCUS:
+ ok = TRUE;
+ modified = (int)SendMessage( bf->hWnd, (UINT)EM_GETMODIFY, 0, 0L );
+ if (!modified)
+ break;
+ *(WPARAM*)&mswTmpBuff[0] = 78;
+ cnt = (int)SendMessage( bf->hWnd, (UINT)EM_GETLINE, 0,
+ (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (strcmp( mswTmpBuff, "-" )==0 && 0 >= bf->low && 0 <= bf->high ) {
+ value = 0;
+ } else {
+ value = strtod( mswTmpBuff, &cp );
+ if (*cp != '\0' || value < bf->low || value > bf->high ) {
+ inx = GetWindowWord( bf->hWnd, GWW_ID );
+ if (wWinIsVisible(bf->parent)) {
+ PostMessage( ((wControl_p)(bf->parent))->hWnd,
+ WM_NOTVALID, inx, 0L );
+ return TRUE;
+ } else {
+ if (value < bf->low)
+ value = bf->low;
+ else
+ value = bf->high;
+ sprintf( mswTmpBuff, "%0.3f", value );
+ SendMessage( bf->hWnd, (UINT)WM_SETTEXT, 0,
+ (DWORD)(LPSTR)mswTmpBuff );
+ }
+ }
+ }
+ bf->oldValue = value;
+ if (bf->valueP)
+ *bf->valueP = value;
+ if (bf->action) {
+ bf->action( value, bf->data );
+ mswSetTrigger( NULL, NULL );
+ }
+ SendMessage( bf->hWnd, (UINT)EM_SETMODIFY, FALSE, 0L );
+ }
+ break;
+
+ case WM_NOTVALID:
+ if (bf->low > MINFLT && bf->high < MAXFLT)
+ sprintf( mswTmpBuff,
+ "Please enter an float value between %0.3f and %0.3f",
+ bf->low, bf->high );
+ else if (bf->low > MINFLT)
+ sprintf( mswTmpBuff,
+ "Please enter an float value greater or equal to %0.3f",
+ bf->low );
+ else if (bf->high < MAXFLT)
+ sprintf( mswTmpBuff,
+ "Please enter an float value less or equal to %0.3f",
+ bf->high );
+ else
+ strcpy( mswTmpBuff, "Please enter an float value" );
+ MessageBox( bf->hWnd, mswTmpBuff, "Invalid entry", MB_OK );
+ SetFocus( bf->hWnd );
+#ifdef WIN32
+ SendMessage( bi->hWnd, EM_SETSEL, 0, 0x7fff );
+ SendMessage( bi->hWnd, EM_SCROLLCARET, 0, 0L );
+#else
+ SendMessage( bi->hWnd, EM_SETSEL, 0, MAKELONG(0,0x7fff) );
+#endif
+ return TRUE;
+
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+static callBacks_t floatCallBacks = {
+ mswRepaintLabel,
+ NULL,
+ floatProc };
+
+
+wFloat_p wFloatCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ POS_T width,
+ double low,
+ double high,
+ double *valueP,
+ wFloatCallBack_p action,
+ void *data )
+{
+ wFloat_p b;
+ RECT rect;
+ int index;
+ DWORD style = 0;
+
+ b = mswAlloc( parent, B_FLOAT, mswStrdup(labelStr), sizeof *b, data, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ b->low = low;
+ b->high = high;
+ b->valueP = valueP;
+ b->labelY += 2;
+ b->action = action;
+ if (option & BO_READONLY)
+ style |= ES_READONLY;
+
+ b->hWnd = CreateWindow( "EDIT", NULL,
+ ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | style,
+ b->x, b->y,
+ width, mswEditHeight,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(FLOAT)");
+ return b;
+ }
+
+#ifdef CONTROL3D
+ Ctl3dSubclassCtl( b->hWnd);
+#endif
+
+ newEditProc = MakeProcInstance( (XWNDPROC)pushEdit, mswHInst );
+ oldEditProc = (XWNDPROC)GetWindowLong(b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newEditProc );
+
+ if (b->valueP) {
+ b->oldValue = *b->valueP;
+ } else
+ b->oldValue = 0.0;
+ if (b->valueP)
+ sprintf( mswTmpBuff, "%0.3f", *b->valueP );
+ else
+ strcpy( mswTmpBuff, "0.000" );
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)mswTmpBuff );
+ SendMessage( b->hWnd, EM_SETMODIFY, FALSE, 0L );
+
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ mswCallBacks[ B_FLOAT ] = &floatCallBacks;
+ mswChainFocus( (wControl_p)b );
+ return b;
+}
+#endif
diff --git a/app/wlib/mswlib/mswint.h b/app/wlib/mswlib/mswint.h
new file mode 100644
index 0000000..2311415
--- /dev/null
+++ b/app/wlib/mswlib/mswint.h
@@ -0,0 +1,193 @@
+#include "wlib.h"
+#include "mswlib.h"
+#include "dynarr.h"
+#ifndef WIN32
+/*#define CONTROL3D*/
+#endif
+#include "stdio.h"
+
+#ifdef CONTROL3D
+#include "ctl3d.h"
+#endif
+
+#ifdef WIN32
+#ifdef FAR
+#undef FAR
+#endif
+#define FAR
+#define _export
+#define MoveTo(HDC,X,Y) MoveToEx(HDC,X,Y,NULL)
+#define READ (0)
+#define WRITE (1)
+#define XEXPORT
+#define XWNDPROC WNDPROC
+#define WCMD_PARAM_HWND lParam
+#define WCMD_PARAM_NOTF HIWORD(wParam)
+#define WCMD_PARAM_ID LOWORD(wParam)
+#define WSCROLL_PARAM_CODE LOWORD(wParam)
+#define WSCROLL_PARAM_NPOS HIWORD(wParam)
+#define WSCROLL_PARAM_HWND lParam
+#else
+#define XEXPORT _export
+#define XWNDPROC FARPROC
+#define WCMD_PARAM_HWND LOWORD(lParam)
+#define WCMD_PARAM_NOTF HIWORD(lParam)
+#define WCMD_PARAM_ID wParam
+#define WSCROLL_PARAM_CODE wParam
+#define WSCROLL_PARAM_NPOS LOWORD(lParam)
+#define WSCROLL_PARAM_HWND HIWORD(lParam)
+#endif
+
+#define CAST_AWAY_CONST (char *)
+
+#define BOOL_T wBool_t
+#define POS_T wPos_t
+#define INDEX_T wIndex_t
+#define INTEGER_T wInteger_t
+
+typedef enum {
+ W_MAIN, W_POPUP,
+ B_BUTTON, B_STRING, B_INTEGER, B_FLOAT,
+ B_LIST, B_DROPLIST, B_COMBOLIST,
+ B_RADIO, B_TOGGLE,
+ B_DRAW, B_TEXT, B_MESSAGE, B_LINES,
+ B_MENUITEM, B_CHOICEITEM, B_BOX,
+ B_BITMAP } wType_e;
+
+typedef void (*repaintProcCallback_p)( HWND, wControl_p );
+typedef void (*doneProcCallback_p)( wControl_p b );
+typedef LRESULT (*messageCallback_p)( wControl_p, HWND, UINT, WPARAM, LPARAM );
+typedef void (*setTriggerCallback_p)( wControl_p b );
+typedef void (*setBusyCallback_p)( wControl_p, BOOL_T );
+typedef void (*showCallback_p)( wControl_p, BOOL_T );
+typedef void (*setPosCallback_p)( wControl_p, wPos_t, wPos_t );
+
+typedef struct {
+ repaintProcCallback_p repaintProc;
+ doneProcCallback_p doneProc;
+ messageCallback_p messageProc;
+ setBusyCallback_p setBusyProc;
+ showCallback_p showProc;
+ setPosCallback_p setPosProc;
+ } callBacks_t;
+
+#define CALLBACK_CNT (B_BOX+1)
+extern callBacks_t *mswCallBacks[CALLBACK_CNT];
+
+
+#define WOBJ_COMMON \
+ wType_e type; \
+ wControl_p next; \
+ wControl_p synonym; \
+ wWin_p parent; \
+ POS_T x, y; \
+ POS_T w, h; \
+ long option; \
+ POS_T labelX, labelY; \
+ const char * labelStr; \
+ const char * helpStr; \
+ const char * tipStr; \
+ HWND hWnd; \
+ void * data;\
+ wControl_p focusChainNext; \
+ wBool_t shown;
+
+struct wControl_t {
+ WOBJ_COMMON
+ };
+
+typedef struct {
+ unsigned key;
+ wDrawColor color;
+ } wIconColorMap_t;
+#define mswIcon_bitmap (1)
+#define mswIcon_pixmap (2)
+
+struct wIcon_t {
+ int type;
+ wPos_t w; /**< width */
+ wPos_t h; /**< height */
+ wDrawColor color;
+ int colorcnt; /**< number of colors */
+ RGBQUAD *colormap;
+ char *pixels; /**< pointer to pixel information */
+ int transparent; /**< index of transparent color */
+ };
+
+struct wDraw_t {
+ WOBJ_COMMON
+ HDC hDc;
+ double wFactor;
+ double hFactor;
+ double DPI;
+ wDrawRedrawCallBack_p drawRepaint;
+ wDrawActionCallBack_p action;
+ HBITMAP hBm;
+ HPEN hPen;
+ HBRUSH hBrush;
+ wDraw_p drawNext;
+ HBITMAP hBmOld;
+ wBool_t hasPalette;
+ int paletteClock;
+ HBITMAP hBmBackup;
+ HDC hDcBackup;
+ HBITMAP hBmBackupOld;
+ };
+
+extern HINSTANCE mswHInst;
+extern char mswTmpBuff[1024];
+extern HWND mswHWnd;
+extern const char *mswDrawWindowClassName;
+char *mswProfileFile;
+extern int mswEditHeight;
+extern int mswAllowBalloonHelp;
+extern HFONT mswOldTextFont;
+extern HFONT mswLabelFont;
+extern wDrawColor wDrawColorWhite;
+extern wDrawColor wDrawColorBlack;
+extern long mswThickFont;
+extern double mswScale;
+
+DWORD mswGetBaseStyle( wWin_p );
+char * mswStrdup( const char * );
+HBITMAP mswCreateBitMap( COLORREF, COLORREF, COLORREF, int, int, const char * );
+void mswFail( const char * );
+void mswResize( wWin_p );
+wControl_p mswMapIndex( INDEX_T );
+void mswButtPush( wControl_p );
+void * mswAlloc( wWin_p, wType_e, const char *, int, void *, int * );
+void mswComputePos( wControl_p, wPos_t, wPos_t );
+void mswAddButton( wControl_p, BOOL_T, const char * );
+void mswRepaintLabel( HWND, wControl_p );
+int mswRegister( wControl_p );
+void mswUnregister( int );
+void mswChainFocus( wControl_p );
+void mswSetFocus( wControl_p );
+void mswSetTrigger( wControl_p, setTriggerCallback_p );
+void mswMenuPush( wControl_p );
+void mswCreateCheckBitmaps( void );
+long FAR PASCAL XEXPORT mswDrawPush( HWND, UINT, UINT, LONG );
+#ifdef WIN32
+DWORD GetTextExtent( HDC, CHAR *, UINT );
+#endif
+void mswRedrawAll( void );
+void mswRepaintAll( void );
+HDC mswGetPrinterDC( void );
+int mswMenuAccelerator( wWin_p, long );
+void mswMenuMove( wMenu_p, wPos_t, wPos_t );
+void mswRegisterBitMap( HBITMAP );
+void mswFontInit( void );
+void mswInitColorPalette( void );
+void mswPutCustomColors( void );
+COLORREF mswGetColor( wBool_t, wDrawColor );
+int mswGetColorList( RGBQUAD * );
+int mswGetPaletteClock( void );
+HPALETTE mswPalette;
+HPALETTE mswCreatePalette( void );
+
+/* mswbitmaps.c */
+void deleteBitmaps( void );
+void mswDrawIcon( HDC, int, int, wIcon_p, int, COLORREF, COLORREF );
+
+/* gwin32.c*/
+char *g_win32_getlocale (void); \ No newline at end of file
diff --git a/app/wlib/mswlib/mswlines.c b/app/wlib/mswlib/mswlines.c
new file mode 100644
index 0000000..be1330d
--- /dev/null
+++ b/app/wlib/mswlib/mswlines.c
@@ -0,0 +1,98 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Lines
+ *
+ *****************************************************************************
+ */
+
+struct wLine_t {
+ WOBJ_COMMON
+ int count;
+ wLines_t * lines;
+ };
+
+static void repaintLines( HWND hWnd, wControl_p b )
+{
+ int lastWidth;
+ HDC hDc;
+ wLine_p bl = (wLine_p)(b);
+ wLines_p lp;
+ HPEN oldPen, newPen;
+
+ lastWidth = -1;
+ hDc = GetDC( hWnd );
+ for (lp=bl->lines; lp<&bl->lines[bl->count]; lp++) {
+ if (lastWidth != lp->width) {
+ lastWidth = lp->width;
+ newPen = CreatePen( PS_SOLID, lastWidth, RGB(0,0,0) );
+ oldPen = SelectObject( hDc, newPen );
+ DeleteObject( oldPen );
+ }
+ MoveTo( hDc, lp->x0, lp->y0 );
+ LineTo( hDc, lp->x1, lp->y1 );
+ }
+ ReleaseDC( hWnd, hDc );
+}
+
+
+static callBacks_t linesCallBacks = {
+ repaintLines,
+ NULL,
+ NULL };
+
+
+wLine_p wLineCreate(
+ wWin_p parent,
+ const char * labelStr,
+ int count,
+ wLines_t * lines )
+{
+ wLine_p b;
+ wLines_p lp;
+ POS_T minX, maxX, minY, maxY;
+ int index;
+
+ if (count <= 0)
+ return NULL;
+ b = (wLine_p)mswAlloc( parent, B_LINES, labelStr, sizeof *b, NULL, &index );
+ b->count = count;
+ b->lines = lines;
+
+ lp = lines;
+ minX = maxX = lp->x0;
+ minY = maxY = lp->y0;
+ for (lp=lines; lp<&b->lines[count]; lp++) {
+ if (minX > lp->x0)
+ minX = lp->x0;
+ if (maxX < lp->x0)
+ maxX = lp->x0;
+ if (minY > lp->y0)
+ minY = lp->y0;
+ if (maxY < lp->y0)
+ maxY = lp->y0;
+ if (minX > lp->x1)
+ minX = lp->x1;
+ if (maxX < lp->x1)
+ maxX = lp->x1;
+ if (minY > lp->y1)
+ minY = lp->y1;
+ if (maxY < lp->y1)
+ maxY = lp->y1;
+ }
+ b->x = minX;
+ b->y = minY;
+ b->w = maxX-minX;
+ b->h = maxY-minY;
+ mswAddButton( (wControl_p)b, FALSE, NULL );
+ mswCallBacks[B_LINES] = &linesCallBacks;
+ return b;
+}
diff --git a/app/wlib/mswlib/mswlist.c b/app/wlib/mswlib/mswlist.c
new file mode 100644
index 0000000..968624a
--- /dev/null
+++ b/app/wlib/mswlib/mswlist.c
@@ -0,0 +1,1173 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * List Boxes
+ *
+ *****************************************************************************
+ */
+
+static XWNDPROC oldListProc = NULL;
+static XWNDPROC newListProc;
+static XWNDPROC oldComboProc = NULL;
+static XWNDPROC newComboProc;
+
+struct wList_t {
+ WOBJ_COMMON
+ int count;
+ int last;
+ long * valueP;
+ wListCallBack_p action;
+ wBool_t editable;
+ int colCnt;
+ wPos_t * colWidths;
+ wBool_t * colRightJust;
+ const char * * colTitles;
+ wPos_t maxWidth;
+ wPos_t scrollPos;
+ HWND hScrollWnd;
+ wPos_t scrollH;
+ wPos_t dragPos;
+ int dragCol;
+ wPos_t dragColWidth;
+ };
+
+
+typedef struct {
+ void * itemContext;
+ wIcon_p bm;
+ wBool_t selected;
+ } listData;
+
+static int LIST_HEIGHT = 19;
+static int listTitleHeight = 16;
+
+
+void wListClear(
+ wList_p b )
+{
+ UINT msg;
+ if (b->type==B_LIST)
+ msg = LB_RESETCONTENT;
+ else
+ msg = CB_RESETCONTENT;
+ SendMessage( b->hWnd, msg, 0, 0 );
+ b->last = -1;
+ b->count = 0;
+}
+
+
+
+void wListSetSize( wList_p bl, wPos_t w, wPos_t h )
+{
+ int rc;
+ RECT rect;
+ wPos_t y;
+
+ bl->w = w;
+ bl->h = h;
+ y = bl->y;
+ if ( bl->hScrollWnd && bl->maxWidth > bl->w )
+ h -= bl->scrollH;
+ if ( bl->colTitles ) {
+ h -= listTitleHeight;
+ y += listTitleHeight;
+ }
+ rc = SetWindowPos( bl->hWnd, HWND_TOP, 0, 0,
+ w, h, SWP_NOMOVE|SWP_NOZORDER);
+ if ( bl->hScrollWnd ) {
+ if ( bl->maxWidth > bl->w ) {
+ GetClientRect( bl->hWnd, &rect );
+ rc = SetWindowPos( bl->hScrollWnd, HWND_TOP, bl->x, y+rect.bottom+2,
+ bl->w, bl->scrollH, SWP_NOZORDER);
+ ShowWindow( bl->hScrollWnd, SW_SHOW );
+ } else {
+ ShowWindow( bl->hScrollWnd, SW_HIDE );
+ }
+ }
+
+}
+
+
+void wListSetIndex(
+ wList_p bl,
+ int index )
+{
+ listData * ldp;
+
+ wListGetCount(bl);
+ if ( index >= bl->count )
+ index = bl->count-1;
+ if ( bl->last == index && index == -1 )
+ return;
+ if ( bl->type==B_LIST && (bl->option&BL_MANY) != 0 ) {
+ if ( bl->last != -1 )
+ SendMessage( bl->hWnd, LB_SETSEL, 0, MAKELPARAM(bl->last,0) );
+ if ( index >= 0 )
+ SendMessage( bl->hWnd, LB_SETSEL, 1, MAKELPARAM(index, 0) );
+ } else {
+ SendMessage( bl->hWnd,
+ bl->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL, index, 0 );
+ }
+ if ( bl->last >= 0 ) {
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ bl->last, 0L );
+ if ( ldp && ldp!=(void*)LB_ERR )
+ ldp->selected = FALSE;
+ }
+ if ( index >= 0 ) {
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ index, 0L );
+ if ( ldp && ldp!=(void*)LB_ERR )
+ ldp->selected = TRUE;
+ }
+ /*if (b->option&BL_ICON)*/
+ InvalidateRect( bl->hWnd, NULL, FALSE );
+ bl->last = index;
+}
+
+
+wIndex_t wListGetIndex(
+ wList_p b )
+{
+ return b->last;
+}
+
+
+void wListSetActive(
+ wList_p b,
+ int inx,
+ wBool_t active )
+{
+}
+
+
+void wListSetEditable(
+ wList_p b,
+ wBool_t editable )
+{
+ b->editable = editable;
+}
+
+
+void wListSetValue(
+ wList_p bl,
+ const char * val )
+{
+ if ( bl->type == B_DROPLIST ) {
+ SendMessage( bl->hWnd, WM_SETTEXT, 0, (DWORD)(LPSTR)val );
+ bl->last = -1;
+ }
+}
+
+
+wIndex_t wListFindValue(
+ wList_p bl,
+ const char * val )
+{
+ wIndex_t inx;
+ WORD cnt;
+ wListGetCount(bl);
+ for ( inx = 0; inx < bl->count ; inx++ ) {
+ cnt = (int)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETTEXT:CB_GETLBTEXT), inx,
+ (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if ( strcmp( val, mswTmpBuff ) == 0 )
+ return inx;
+ }
+ return -1;
+}
+
+
+wIndex_t wListGetValues(
+ wList_p bl,
+ char * s,
+ int siz,
+ void * * listContextRef,
+ void * * itemContextRef )
+{
+ WORD cnt;
+ WORD msg;
+ WORD inx = bl->last;
+ listData *ldp = NULL;
+ if ( bl->type==B_DROPLIST && bl->last < 0 ) {
+ msg = WM_GETTEXT;
+ inx = sizeof mswTmpBuff;
+ } else {
+ if ( bl->last < 0 )
+ goto EMPTY;
+ if ( bl->type==B_LIST ) {
+ msg = LB_GETTEXT;
+ } else {
+ msg = CB_GETLBTEXT;
+ }
+ }
+ cnt = (int)SendMessage( bl->hWnd, msg, inx, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (s)
+ strncpy( s, mswTmpBuff, siz );
+ if (bl->last >= 0) {
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ bl->last, 0L );
+ if ( ldp==(listData*)LB_ERR )
+ ldp = NULL;
+ } else {
+ ldp = NULL;
+ }
+EMPTY:
+ if (itemContextRef)
+ *itemContextRef = (ldp?ldp->itemContext:NULL);
+ if (listContextRef)
+ *listContextRef = bl->data;
+ return bl->last;
+}
+
+wBool_t wListSetValues(
+ wList_p b,
+ wIndex_t inx,
+ const char * labelStr,
+ wIcon_p bm,
+ void * itemData )
+{
+ listData * ldp;
+ WORD curSel;
+ ldp = (listData*)malloc( sizeof *ldp );
+ ldp->itemContext = itemData;
+ ldp->bm = bm;
+ ldp->selected = FALSE;
+ if ( (b->option&BL_MANY) == 0 )
+ curSel = (WORD)SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_GETCURSEL:CB_GETCURSEL,
+ (WPARAM)0,
+ (DWORD)0L );
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_DELETESTRING:CB_DELETESTRING,
+ (WPARAM)inx,
+ (DWORD)0L );
+ inx = (wIndex_t)SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_INSERTSTRING:CB_INSERTSTRING,
+ (WPARAM)inx,
+ (DWORD)(LPSTR)labelStr );
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA,
+ (WPARAM)inx,
+ (DWORD)ldp );
+ if ( (b->option&BL_MANY) == 0 && curSel == (WORD)inx)
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL,
+ (WPARAM)inx,
+ (DWORD)0L );
+ /*if (b->option&BL_ICON)*/
+ InvalidateRect( b->hWnd, NULL, FALSE );
+ return TRUE;
+}
+
+
+void wListDelete(
+ wList_p b,
+ wIndex_t inx )
+{
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_DELETESTRING:CB_DELETESTRING,
+ (WPARAM)inx,
+ (DWORD)0L );
+}
+
+
+wIndex_t wListGetCount(
+ wList_p bl )
+{
+ bl->count = (int)SendMessage( bl->hWnd, (UINT)bl->type==B_LIST?LB_GETCOUNT:CB_GETCOUNT, 0, 0L );
+ return bl->count;
+}
+
+
+void * wListGetItemContext(
+ wList_p bl,
+ wIndex_t inx )
+{
+ listData * ldp;
+ wListGetCount(bl);
+ if ( inx < 0 || inx >= bl->count ) return NULL;
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ inx, 0L );
+ return ((ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL);
+}
+
+
+wBool_t wListGetItemSelected(
+ wList_p bl,
+ wIndex_t inx )
+{
+ listData * ldp;
+ wListGetCount(bl);
+ if ( inx < 0 || inx >= bl->count ) return FALSE;
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ inx, 0L );
+ return ((ldp&&ldp!=(void*)LB_ERR)?ldp->selected:FALSE);
+}
+
+
+wIndex_t wListGetSelectedCount(
+ wList_p bl )
+{
+ wIndex_t selcnt, inx;
+ wListGetCount(bl);
+ for ( selcnt=inx=0; inx<bl->count; inx++ )
+ if ( wListGetItemSelected( bl, inx ) )
+ selcnt++;
+ return selcnt;
+}
+
+
+wIndex_t wListAddValue(
+ wList_p b,
+ const char * value,
+ wIcon_p bm,
+ void * itemContext )
+{
+ int nindex;
+ listData * ldp;
+ ldp = (listData*)malloc( sizeof *ldp );
+ ldp->itemContext = itemContext;
+ ldp->bm = bm;
+ ldp->selected = FALSE;
+ if ( value == NULL )
+ value = "";
+ b->count++;
+ nindex = (int)SendMessage(
+ b->hWnd,
+ (UINT)b->type==B_LIST?LB_ADDSTRING:CB_ADDSTRING,
+ (WPARAM)0,
+ (DWORD)value );
+ if (nindex == 0) {
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_SETCURSEL:CB_SETCURSEL,
+ (WPARAM)nindex,
+ (DWORD)0 );
+ b->last = 0;
+ }
+ SendMessage( b->hWnd,
+ (UINT)b->type==B_LIST?LB_SETITEMDATA:CB_SETITEMDATA,
+ (WPARAM)nindex,
+ (DWORD)ldp );
+ return nindex;
+}
+
+
+int wListGetColumnWidths(
+ wList_p bl,
+ int colCnt,
+ wPos_t * colWidths )
+{
+ wIndex_t inx;
+
+ if ( bl->type != B_LIST )
+ return 0;
+ if ( bl->colWidths == NULL )
+ return 0;
+ for ( inx=0; inx<colCnt; inx++ ) {
+ if ( inx < bl->colCnt )
+ colWidths[inx] = bl->colWidths[inx];
+ else
+ colWidths[inx] = 0;
+ }
+ return bl->colCnt;
+}
+
+
+static void listSetBusy(
+ wControl_p b,
+ BOOL_T busy)
+{
+ wList_p bl = (wList_p)b;
+
+ EnableWindow( bl->hWnd, !(BOOL)busy );
+ if ( bl->hScrollWnd )
+ EnableWindow( bl->hScrollWnd, !(BOOL)busy );
+}
+
+static void listShow(
+ wControl_p b,
+ BOOL_T show)
+{
+ wList_p bl = (wList_p)b;
+
+ ShowWindow( bl->hWnd, show?SW_SHOW:SW_HIDE );
+ if ( bl->hScrollWnd && bl->maxWidth > bl->w )
+ ShowWindow( bl->hScrollWnd, show?SW_SHOW:SW_HIDE );
+#ifdef SHOW_DOES_SETFOCUS
+ if ( show && (bl->option&BO_READONLY)==0 )
+ hWnd = SetFocus( bl->hWnd );
+#endif
+}
+
+static void listSetPos(
+ wControl_p b,
+ wPos_t x,
+ wPos_t y )
+{
+ wList_p bl = (wList_p)b;
+ wPos_t x1, y1;
+ RECT rect;
+
+ bl->x = x1 = x;
+ bl->y = y1 = y;
+ if ( bl->colTitles )
+ y1 += listTitleHeight;
+ if (!SetWindowPos( b->hWnd, HWND_TOP, x1, y1,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER))
+ mswFail("listSetPos");
+ if ( bl->hScrollWnd && bl->maxWidth > bl->w ) {
+ GetClientRect( bl->hWnd, &rect );
+ if (!SetWindowPos( bl->hScrollWnd, HWND_TOP, x1, y1+rect.bottom+2,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER))
+ mswFail("listSetPos2");
+ }
+}
+
+
+static void listRepaintLabel(
+ HWND hWnd,
+ wControl_p b )
+{
+ wList_p bl = (wList_p)b;
+ HDC hDc;
+ RECT rc;
+ HFONT hFont;
+ HPEN hPen0, hPen1, hPen2, hPen3;
+ HBRUSH hBrush;
+ const char * * title;
+ int inx;
+ int start;
+ wPos_t colWidth;
+
+ mswRepaintLabel( hWnd, b );
+ if ( bl->colTitles == NULL )
+ return;
+ hDc = GetDC( hWnd );
+ start = bl->x-bl->scrollPos+2;
+ rc.top = bl->y;
+ rc.bottom = bl->y+listTitleHeight;
+ rc.left = bl->x-1;
+ rc.right = bl->x+bl->w;
+ hBrush = CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) );
+ FillRect( hDc, &rc, hBrush );
+ SetBkColor( hDc, GetSysColor( COLOR_BTNFACE ) );
+
+ hFont = SelectObject( hDc, mswLabelFont );
+ hPen1 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNTEXT ) );
+ hPen2 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNHIGHLIGHT ) );
+ hPen3 = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_BTNSHADOW ) );
+ hPen0 = SelectObject( hDc, hPen1 );
+ MoveTo( hDc, rc.left, rc.top );
+ LineTo( hDc, rc.right, rc.top );
+ LineTo( hDc, rc.right, rc.bottom );
+ LineTo( hDc, rc.left, rc.bottom );
+ LineTo( hDc, rc.left, rc.top );
+ SelectObject( hDc, hPen2 );
+ MoveTo( hDc, rc.left+1, rc.bottom-1 );
+ LineTo( hDc, rc.left+1, rc.top+1 );
+ LineTo( hDc, rc.right-1, rc.top+1 );
+ SelectObject( hDc, hPen3 );
+ MoveTo( hDc, rc.left+2, rc.bottom-1 );
+ LineTo( hDc, rc.right-1, rc.bottom-1 );
+ LineTo( hDc, rc.right-1, rc.top+1 );
+ rc.top += 2;
+ rc.bottom -= 1;
+ for ( inx=0,title=bl->colTitles; inx<bl->colCnt&&*title&&start<bl->x+bl->w; inx++ ) {
+ colWidth = bl->colWidths[inx];
+ if ( start+colWidth >= 3 ) {
+ rc.left = start;
+ if ( rc.left < bl->x+2 )
+ rc.left = bl->x+2;
+ rc.right = start+colWidth;
+ if ( rc.right > bl->x+bl->w-1 )
+ rc.right = bl->x+bl->w-1;
+ ExtTextOut( hDc, start+1, rc.top+0,
+ ETO_CLIPPED|ETO_OPAQUE, &rc,
+ *title, strlen(*title), NULL );
+ if ( start-bl->x >= 3 ) {
+ SelectObject( hDc, hPen1 );
+ MoveTo( hDc, start-1, rc.top-1 );
+ LineTo( hDc, start-1, rc.bottom+3 );
+ SelectObject( hDc, hPen2 );
+ MoveTo( hDc, start, rc.top );
+ LineTo( hDc, start, rc.bottom+1 );
+ SelectObject( hDc, hPen3 );
+ MoveTo( hDc, start-2, rc.top );
+ LineTo( hDc, start-2, rc.bottom+1 );
+ }
+ }
+ title++;
+ start += colWidth;
+ }
+ SelectObject( hDc, hPen0 );
+ SelectObject( hDc, hFont );
+ DeleteObject( hBrush );
+ DeleteObject( hPen1 );
+ DeleteObject( hPen2 );
+ DeleteObject( hPen3 );
+}
+
+
+#ifdef LATER
+static void listHandleSelectionState( LPDRAWITEMSTRUCT lpdis, LPRECT rc )
+{
+ int oldROP;
+ oldROP = SetROP2( lpdis->hDC, R2_NOT );
+ Rectangle( lpdis->hDC, rc->left, rc->top, rc->right, rc->bottom );
+ SetROP2( lpdis->hDC, oldROP );
+ /*InvertRect( lpdis->hDC, rc );*/
+}
+#endif
+
+static void listHandleFocusState( LPDRAWITEMSTRUCT lpdis, LPRECT rc )
+{
+ DrawFocusRect( lpdis->hDC, rc );
+}
+
+
+LRESULT listProc(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wList_p bl = (wList_p)b;
+ int cnt, inx, selected;
+ long len;
+ listData * ldp;
+ HDC hDc;
+ LPMEASUREITEMSTRUCT lpmis;
+ TEXTMETRIC tm;
+ LPDRAWITEMSTRUCT lpdis;
+ RECT rc, rc1;
+ char * cp0, * cp1;
+ wPos_t colWidth, x;
+ int nPos;
+ HFONT hFont;
+ HPEN hPen;
+ HBRUSH hBrush;
+ WPARAM notification;
+ COLORREF col;
+
+ if (bl) switch( message ) {
+
+ case WM_COMMAND:
+ notification = WCMD_PARAM_NOTF;
+ switch (bl->type) {
+ case B_LIST:
+ switch (notification) {
+ case LBN_SELCHANGE:
+ case LBN_DBLCLK:
+ if ( (bl->option&BL_DBLCLICK)!=0 ?
+ notification!=LBN_DBLCLK :
+ notification==LBN_DBLCLK )
+ break;
+ if ( (bl->option&BL_MANY) ) {
+ wListGetCount(bl);
+ for ( inx=0; inx<bl->count; inx++ ) {
+ ldp = (listData*)SendMessage( bl->hWnd, LB_GETITEMDATA, inx, 0L );
+ if ( ldp != NULL && ldp != (void*)LB_ERR ) {
+ selected = ((long)SendMessage( bl->hWnd, LB_GETSEL, inx, 0L ) != 0L );
+ if ( selected != ldp->selected ) {
+ ldp->selected = selected;
+ if ( selected ) {
+ bl->last = inx;
+ cnt = (int)SendMessage( bl->hWnd, LB_GETTEXT, bl->last, (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ } else {
+ mswTmpBuff[0] = '\0';
+ }
+ if ( bl->action )
+ bl->action( inx, mswTmpBuff, selected?1:2, bl->data, ldp->itemContext );
+ if ( selected && bl->valueP )
+ *bl->valueP = bl->last;
+ }
+ }
+ }
+ } else {
+ bl->last = (int)SendMessage( bl->hWnd, LB_GETCURSEL, 0, 0L );
+ cnt = (int)SendMessage( bl->hWnd, LB_GETTEXT, bl->last,
+ (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if (bl->action) {
+ ldp = (listData*)SendMessage( bl->hWnd, LB_GETITEMDATA,
+ bl->last, 0L );
+ bl->action( bl->last, mswTmpBuff, 1, bl->data,
+ ((bl->last>=0&&ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL) );
+ }
+ if (bl->valueP) {
+ *bl->valueP = bl->last;
+ }
+ }
+ break;
+
+ case LBN_KILLFOCUS:
+ if ( ( bl->option&BL_MANY ) == 0 &&
+ bl->last != (int)SendMessage( bl->hWnd, LB_GETCURSEL, 0, 0L ) )
+ (void)SendMessage( bl->hWnd, LB_SETCURSEL, bl->last, 0L );
+ break;
+ }
+ break;
+
+ case B_DROPLIST:
+ case B_COMBOLIST:
+ switch (notification) {
+ case CBN_SELCHANGE:
+ case CBN_DBLCLK:
+ if ( (bl->type == B_DROPLIST) ||
+ ( (bl->option&BL_DBLCLICK)!=0 ?
+ notification!=CBN_DBLCLK :
+ notification==CBN_DBLCLK) )
+ break;
+
+ case CBN_CLOSEUP:
+ bl->last = (int)SendMessage( bl->hWnd, CB_GETCURSEL, 0, 0L );
+ if (bl->last < 0)
+ break;
+ if (bl->action) {
+ cnt = (int)SendMessage( bl->hWnd, CB_GETLBTEXT, bl->last,
+ (DWORD)(LPSTR)mswTmpBuff );
+ ldp = (listData*)SendMessage( bl->hWnd, CB_GETITEMDATA,
+ bl->last, 0L );
+ mswTmpBuff[cnt] = '\0';
+ bl->action( bl->last, mswTmpBuff, 1, bl->data,
+ ((bl->last>=0&&ldp&&ldp!=(void*)LB_ERR)?ldp->itemContext:NULL) );
+ }
+ if (bl->valueP) {
+ *bl->valueP = bl->last;
+ }
+ mswAllowBalloonHelp = TRUE;
+ /*SendMessage( bl->bWnd, CB_SETCURSEL, bl->last, 0L );*/
+ break;
+
+ case CBN_KILLFOCUS:
+ inx = (int)SendMessage( bl->hWnd, CB_GETCURSEL, 0, 0L );
+ if ( bl->last != inx )
+ (void)SendMessage( bl->hWnd, CB_SETCURSEL, bl->last, 0L );
+ break;
+
+ case CBN_DROPDOWN:
+ mswAllowBalloonHelp = FALSE;
+ break;
+
+ case CBN_EDITCHANGE:
+ bl->last = -1;
+ if (bl->action) {
+ cnt = (int)SendMessage( bl->hWnd, WM_GETTEXT, sizeof mswTmpBuff,
+ (DWORD)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ bl->action( -1, mswTmpBuff, 1, bl->data, NULL );
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ lpmis = (LPMEASUREITEMSTRUCT)lParam;
+ hDc = GetDC( hWnd );
+ if ( bl->type == B_LIST )
+ hFont = SelectObject( hDc, mswLabelFont );
+ GetTextMetrics( hDc, &tm );
+ lpmis->itemHeight = tm.tmHeight;
+ if ( bl->type == B_LIST )
+ SelectObject( hDc, hFont );
+ ReleaseDC( hWnd, hDc );
+ break;
+
+ case WM_DRAWITEM:
+ lpdis = (LPDRAWITEMSTRUCT)lParam;
+ if (lpdis->itemID == -1) {
+ listHandleFocusState(lpdis, &lpdis->rcItem);
+ return TRUE;
+ }
+ ldp = (listData*)SendMessage( bl->hWnd,
+ (bl->type==B_LIST?LB_GETITEMDATA:CB_GETITEMDATA),
+ lpdis->itemID, 0L );
+ rc = lpdis->rcItem;
+ if (lpdis->itemAction & (ODA_DRAWENTIRE|ODA_SELECT|ODA_FOCUS)) {
+ if( bl->type == B_LIST )
+ hFont = SelectObject( lpdis->hDC, mswLabelFont );
+ cnt = (int)SendMessage( lpdis->hwndItem,
+ (bl->type==B_LIST?LB_GETTEXT:CB_GETLBTEXT),
+ lpdis->itemID, (LONG)(LPSTR)mswTmpBuff );
+ mswTmpBuff[cnt] = '\0';
+ if ( lpdis->itemState & ODS_SELECTED ) {
+ SetTextColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
+ SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
+ } else {
+ SetTextColor( lpdis->hDC, GetSysColor( COLOR_WINDOWTEXT ) );
+ SetBkColor( lpdis->hDC, GetSysColor( COLOR_WINDOW ) );
+ }
+ rc1 = rc;
+ rc1.left -= bl->scrollPos;
+ for ( inx=0,cp0=mswTmpBuff; inx<bl->colCnt&&cp0&&rc1.left<rc.right; inx++ ) {
+ if ( inx>=bl->colCnt-1 || (cp1=strchr(cp0,'\t')) == NULL ) {
+ len = strlen( cp0 );
+ cp1=cp0 + len; // JBB, to avoid an MSC error below where cp1 has not been defined.
+ } else {
+ len = cp1-cp0;
+ cp1 ++;
+ }
+ if ( bl->colWidths ) {
+ colWidth = bl->colWidths[inx];
+ } else {
+ colWidth = rc.right;
+ }
+ if ( inx == 0 && ldp && ldp!=(void*)LB_ERR && ldp->bm ) {
+ if (mswPalette) {
+ SelectPalette( lpdis->hDC, mswPalette, 0 );
+ cnt = RealizePalette( lpdis->hDC );
+ }
+ hPen = SelectObject( lpdis->hDC, CreatePen( PS_SOLID, 0, GetSysColor( COLOR_WINDOW ) ) );
+ hBrush = SelectObject( lpdis->hDC, CreateSolidBrush( GetSysColor( COLOR_WINDOW ) ) );
+ Rectangle( lpdis->hDC, rc1.left, rc1.top, rc1.right, rc1.bottom );
+ DeleteObject( SelectObject( lpdis->hDC, hPen ) );
+ DeleteObject( SelectObject( lpdis->hDC, hBrush ) );
+
+ col = RGB( (ldp->bm->colormap[ 1 ]).rgbRed,
+ (ldp->bm->colormap[ 1 ]).rgbGreen,
+ (ldp->bm->colormap[ 1 ]).rgbBlue );
+ mswDrawIcon( lpdis->hDC, rc1.left+2, rc.top+0, ldp->bm, 0, col, col);
+
+ rc1.left += ldp->bm->w+6;
+ colWidth -= ldp->bm->w+6;
+ }
+ if ( inx>=bl->colCnt-1 || (rc1.right = rc1.left + colWidth) > rc.right )
+ rc1.right = rc.right;
+ if ( rc1.right > 0 && rc1.left+3 < rc.right ) {
+ ExtTextOut( lpdis->hDC, rc1.left+3, rc1.top+1,
+ ETO_CLIPPED | ETO_OPAQUE, &rc1,
+ (LPSTR)cp0, (int)len, NULL );
+ }
+ rc1.left = rc1.right;
+ cp0 = cp1;
+ }
+ if ( lpdis->itemState & ODS_SELECTED ) {
+ SetTextColor( lpdis->hDC, GetSysColor( COLOR_WINDOWTEXT ) );
+ SetBkColor( lpdis->hDC, GetSysColor( COLOR_WINDOW ) );
+ }
+ if (lpdis->itemState & ODS_FOCUS) {
+ DrawFocusRect( lpdis->hDC, &rc );
+ }
+ if ( bl->type == B_LIST)
+ SelectObject( lpdis->hDC, hFont );
+ return TRUE;
+ }
+
+ break;
+
+ case WM_HSCROLL:
+ len = ((long)bl->maxWidth)-((long)bl->w);
+ if ( len <= 0 )
+ return 0;
+ switch ( WSCROLL_PARAM_CODE ) {
+ case SB_LEFT:
+ if ( bl->scrollPos == 0 )
+ return 0;
+ bl->scrollPos = 0;
+ break;
+ case SB_LINELEFT:
+ case SB_PAGELEFT:
+ if ( bl->scrollPos == 0 )
+ return 0;
+ for ( inx=colWidth=0; inx<bl->colCnt; inx++ ) {
+ if ( colWidth+bl->colWidths[inx] >= bl->scrollPos ) {
+ bl->scrollPos = colWidth;
+ break;
+ }
+ colWidth += bl->colWidths[inx];
+ }
+ break;
+ case SB_LINERIGHT:
+ case SB_PAGERIGHT:
+ if ( bl->scrollPos >= len )
+ return 0;
+ for ( inx=colWidth=0; inx<bl->colCnt; inx++ ) {
+ if ( colWidth >= bl->scrollPos ) {
+ bl->scrollPos = colWidth+bl->colWidths[inx];
+ break;
+ }
+ colWidth += bl->colWidths[inx];
+ }
+ break;
+ case SB_RIGHT:
+ if ( bl->scrollPos >= len )
+ return 0;
+ bl->scrollPos = (int)len;
+ break;
+ case SB_THUMBTRACK:
+ return 0;
+ case SB_THUMBPOSITION:
+ nPos = (int)WSCROLL_PARAM_NPOS;
+ bl->scrollPos = (int)(len*nPos/100);
+ break;
+ case SB_ENDSCROLL:
+ return 0;
+ }
+ if ( bl->scrollPos > len ) bl->scrollPos = (int)len;
+ if ( bl->scrollPos < 0 ) bl->scrollPos = 0;
+ nPos = (int)(((long)bl->scrollPos)*100L/len+0.5);
+ SetScrollPos( bl->hScrollWnd, SB_CTL, nPos, TRUE );
+ InvalidateRect( bl->hWnd, NULL, FALSE );
+ listRepaintLabel( ((wControl_p)(bl->parent))->hWnd, (wControl_p)bl );
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ if ( bl->type != B_LIST )
+ break;
+ if ( bl->colCnt <= 1 )
+ break;
+ x = bl->dragPos = LOWORD(lParam)+bl->scrollPos-4;
+ bl->dragCol = -1;
+ for ( inx=0; inx<bl->colCnt; inx++ ) {
+ x -= bl->colWidths[inx];
+ if ( x < -5 ) break;
+ if ( x <= 0 ) { bl->dragCol = inx; break; }
+ if ( x > bl->colWidths[inx+1] ) continue;
+ if ( x <= 10 ) { bl->dragCol = inx; break; }
+ }
+ if ( bl->dragCol >= 0 )
+ bl->dragColWidth = bl->colWidths[inx];
+ return 0L;
+
+#ifdef LATER
+ case WM_MOUSEMOVE:
+ if ( (wParam&MK_LBUTTON) == 0 )
+ break;
+ if ( bl->type != B_LIST )
+ break;
+ if ( bl->colCnt <= 1 )
+ break;
+ x = LOWORD(lParam)+bl->scrolPos;
+ for ( inx=0; inx<bl->colCnt; inx++ ) {
+ x -= bl->colWidths[inx];
+ if ( x <= 0 )
+ break;
+ }
+ return 0L;
+#endif
+
+ case WM_MOUSEMOVE:
+ if ( (wParam&MK_LBUTTON) == 0 )
+ break;
+ case WM_LBUTTONUP:
+ if ( bl->type != B_LIST )
+ break;
+ if ( bl->colCnt <= 1 )
+ break;
+ if ( bl->dragCol < 0 )
+ break;
+ x = LOWORD(lParam)+bl->scrollPos-4-bl->dragPos; /* WIN32??? */
+ bl->colWidths[bl->dragCol] = bl->dragColWidth+x;
+ if ( bl->colWidths[bl->dragCol] < 0 )
+ bl->colWidths[bl->dragCol] = 0;
+ for ( bl->maxWidth=inx=0; inx<bl->colCnt; inx++ )
+ bl->maxWidth += bl->colWidths[inx];
+ if ( bl->maxWidth <= bl->w ) {
+ x = bl->w - bl->maxWidth;
+ bl->colWidths[bl->colCnt-1] += x;
+ bl->maxWidth = bl->w;
+ bl->scrollPos = 0;
+ } else {
+ if ( bl->scrollPos+bl->w > bl->maxWidth ) {
+ bl->scrollPos = bl->maxWidth - bl->w;
+ }
+ }
+ InvalidateRect( bl->hWnd, NULL, FALSE );
+ listRepaintLabel( ((wControl_p)(bl->parent))->hWnd, (wControl_p)bl );
+ return 0L;
+
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+long FAR PASCAL _export pushList(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+ /* Catch <Return> and cause focus to leave control */
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+ wControl_p b = mswMapIndex( inx );
+
+ switch (message) {
+ case WM_CHAR:
+ if ( b != NULL) {
+ switch( WCMD_PARAM_ID ) {
+ case 0x0D:
+ case 0x1B:
+ case 0x09:
+ SetFocus( ((wControl_p)(b->parent))->hWnd );
+ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR,
+ wParam, lParam );
+ /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND,
+ inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/
+ return 0L;
+ }
+ }
+ break;
+ }
+ return CallWindowProc( oldListProc, hWnd, message, wParam, lParam );
+}
+
+long FAR PASCAL _export pushCombo(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam )
+{
+ /* Catch <Return> and cause focus to leave control */
+#ifdef WIN32
+ long inx = GetWindowLong( hWnd, GWL_ID );
+#else
+ short inx = GetWindowWord( hWnd, GWW_ID );
+#endif
+ wControl_p b = mswMapIndex( inx );
+
+ switch (message) {
+ case WM_CHAR:
+ if ( b != NULL) {
+ switch( WCMD_PARAM_ID ) {
+ case 0x0D:
+ case 0x1B:
+ case 0x09:
+ SetFocus( ((wControl_p)(b->parent))->hWnd );
+ SendMessage( ((wControl_p)(b->parent))->hWnd, WM_CHAR,
+ wParam, lParam );
+ /*SendMessage( ((wControl_p)(b->parent))->hWnd, WM_COMMAND,
+ inx, MAKELONG( hWnd, EN_KILLFOCUS ) );*/
+ return 0L;
+ }
+ }
+ break;
+ }
+ return CallWindowProc( oldComboProc, hWnd, message, wParam, lParam );
+}
+
+static callBacks_t listCallBacks = {
+ listRepaintLabel,
+ NULL,
+ listProc,
+ listSetBusy,
+ listShow,
+ listSetPos };
+
+
+static wList_p listCreate(
+ int typ,
+ const char *className,
+ long style,
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ POS_T width,
+ long *valueP,
+ wListCallBack_p action,
+ void *data,
+ wBool_t addFocus,
+ int *indexR )
+{
+ wList_p b;
+ RECT rect;
+ int index;
+
+ b = (wList_p)mswAlloc( parent, typ, mswStrdup(labelStr), sizeof *b, data, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ b->count = 0;
+ b->last = -1;
+ b->valueP = valueP;
+ b->labelY += 4;
+ b->action = action;
+ b->maxWidth = 0;
+ b->scrollPos = 0;
+ b->scrollH = 0;
+ b->dragPos = 0;
+ b->dragCol = -1;
+
+ b->hWnd = CreateWindow( className, NULL,
+ style | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), b->x, b->y,
+ width, LIST_HEIGHT*(int)number,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(LIST)");
+ return b;
+ }
+
+#ifdef CONTROL3D
+ Ctl3dSubclassCtl( b->hWnd );
+#endif
+
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+ b->colCnt = 1;
+ b->colWidths = NULL;
+ b->colTitles = NULL;
+
+ mswAddButton( (wControl_p)b, TRUE, helpStr );
+ mswCallBacks[typ] = &listCallBacks;
+ if (addFocus) {
+ mswChainFocus( (wControl_p)b );
+ if (b->type == B_LIST) {
+ newListProc = MakeProcInstance( (XWNDPROC)pushList, mswHInst );
+ oldListProc = (XWNDPROC)GetWindowLong( b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newListProc );
+ } else {
+ newComboProc = MakeProcInstance( (XWNDPROC)pushCombo, mswHInst );
+ oldComboProc = (XWNDPROC)GetWindowLong( b->hWnd, GWL_WNDPROC );
+ SetWindowLong( b->hWnd, GWL_WNDPROC, (LONG)newComboProc );
+ }
+ }
+ if ( indexR )
+ *indexR = index;
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ return b;
+}
+
+
+wList_p wListCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ POS_T width,
+ int colCnt,
+ wPos_t * colWidths,
+ wBool_t * colRightJust,
+ const char * * colTitles,
+ long *valueP,
+ wListCallBack_p action,
+ void *data )
+{
+ long bs;
+ wList_p bl;
+ static int dbu = 0;
+ RECT rect;
+ int index;
+ int i;
+
+ bs = LBS_NOTIFY | WS_VSCROLL | WS_BORDER | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS;
+ if (option & BL_MANY)
+ bs |= LBS_MULTIPLESEL|LBS_EXTENDEDSEL;
+ if (option & BL_SORT)
+ bs |= LBS_SORT;
+ if ( colCnt > 1 )
+ bs |= WS_HSCROLL;
+ if ( colTitles ) {
+ y += listTitleHeight;
+ number -= 1;
+ }
+ bl = listCreate( B_LIST, "LISTBOX", bs, parent, x, y, helpStr,
+ labelStr, option, number, width, valueP, action, data, TRUE, &index );
+ if ( colTitles ) {
+ bl->y -= listTitleHeight;
+ bl->h += listTitleHeight;
+ }
+ if ( colCnt > 1 ) {
+ bl->colCnt = colCnt;
+ bl->colWidths = (int*)malloc( colCnt * sizeof *bl->colWidths );
+ bl->colRightJust = (wBool_t*)malloc( colCnt * sizeof *bl->colRightJust );
+ bl->colTitles = colTitles;
+ bl->maxWidth = 0;
+ memcpy( bl->colWidths, colWidths, colCnt * sizeof *bl->colWidths );
+ for ( i=0; i<colCnt; i++ ) {
+ bl->colWidths[i] = colWidths[i];
+ bl->maxWidth += bl->colWidths[i];
+ }
+ bl->hScrollWnd = CreateWindow( "ScrollBar", NULL,
+ SBS_HORZ | SBS_BOTTOMALIGN | WS_CHILD | WS_VISIBLE | mswGetBaseStyle(parent), bl->x, bl->y,
+ width, CW_USEDEFAULT,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (bl->hScrollWnd == NULL)
+ mswFail("CreateWindow(LISTSCROLL)");
+ SetScrollRange( bl->hScrollWnd, SB_CTL, 0, 100, TRUE );
+ GetWindowRect( bl->hScrollWnd, &rect );
+ bl->scrollH = rect.bottom - rect.top+2;
+ }
+ return bl;
+}
+
+
+wList_p wDropListCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ POS_T width,
+ long *valueP,
+ wListCallBack_p action,
+ void *data )
+{
+ long bs;
+
+ if ( (option&BL_EDITABLE) != 0 )
+ bs = CBS_DROPDOWN;
+ else
+ bs = CBS_DROPDOWNLIST;
+ bs |= WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
+ if (option & BL_SORT)
+ bs |= CBS_SORT;
+ return listCreate( B_DROPLIST, "COMBOBOX", bs, parent, x, y, helpStr,
+ labelStr, option, number, width, valueP, action, data, TRUE, NULL );
+}
+
+wList_p wComboListCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ POS_T width,
+ long *valueP,
+ wListCallBack_p action,
+ void *data )
+{
+ long bs;
+
+ bs = CBS_SIMPLE | WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
+ if (option & BL_SORT)
+ bs |= CBS_SORT;
+ return listCreate( B_COMBOLIST, "COMBOBOX", bs, parent, x, y, helpStr,
+ labelStr, option, number, width, valueP, action, data, FALSE, NULL );
+}
diff --git a/app/wlib/mswlib/mswmenu.c b/app/wlib/mswlib/mswmenu.c
new file mode 100644
index 0000000..15053a2
--- /dev/null
+++ b/app/wlib/mswlib/mswmenu.c
@@ -0,0 +1,1062 @@
+#define OEMRESOURCE
+
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <ctype.h>
+#include <assert.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Menus
+ *
+ *****************************************************************************
+ */
+
+typedef enum { M_MENU, M_SEPARATOR, M_PUSH, M_LIST, M_LISTITEM, M_TOGGLE, M_RADIO } mtype_e;
+typedef enum { MM_BUTT, MM_MENU, MM_BAR, MM_POPUP } mmtype_e;
+
+typedef struct wMenuItem_t * wMenuItem_p;
+
+struct radioButtonGroup {
+ int firstButton; /* id of first button in group */
+ int lastButton; /* id of last button in group */
+};
+
+/* NOTE: first field must be the same as WOBJ_COMMON */
+#define MOBJ_COMMON \
+ WOBJ_COMMON \
+ int index; \
+ mtype_e mtype; \
+ wMenu_p parentMenu; \
+ wMenuItem_p mnext;
+
+struct wMenuItem_t {
+ MOBJ_COMMON
+ };
+
+struct wMenu_t {
+ MOBJ_COMMON
+ mmtype_e mmtype;
+ wMenuItem_p first, last;
+ struct radioButtonGroup *radioGroup;
+ HMENU menu;
+ wButton_p button;
+ wMenuTraceCallBack_p traceFunc;
+ void * traceData;
+ };
+
+struct wMenuPush_t {
+ MOBJ_COMMON
+ wMenu_p mparent;
+ wMenuCallBack_p action;
+ long acclKey;
+ wBool_t enabled;
+ };
+
+struct wMenuRadio_t {
+ MOBJ_COMMON
+ wMenu_p mparent;
+ wMenuCallBack_p action;
+ long acclKey;
+ wBool_t enabled;
+ };
+struct wMenuToggle_t {
+ MOBJ_COMMON
+ wMenu_p mparent;
+ wMenuToggleCallBack_p action;
+ long acclKey;
+ wBool_t enabled;
+ };
+
+typedef struct wMenuListItem_t * wMenuListItem_p;
+struct wMenuList_t {
+ MOBJ_COMMON
+ wMenuListItem_p left, right;
+ wMenu_p mlparent;
+ int max;
+ int count;
+ wMenuListCallBack_p action;
+ };
+
+struct wMenuListItem_t {
+ MOBJ_COMMON
+ wMenuListItem_p left, right;
+ wMenuListCallBack_p action;
+ };
+
+#define UNCHECK (0)
+#define CHECK (1)
+#define RADIOCHECK (2)
+#define RADIOUNCHECK (3)
+
+static HBITMAP checked;
+static HBITMAP unchecked;
+static HBITMAP checkedRadio;
+static HBITMAP uncheckedRadio;
+
+
+/*
+ *****************************************************************************
+ *
+ * Internal Functions
+ *
+ *****************************************************************************
+ */
+
+char * mswStrdup( const char * str )
+{
+ char * ret;
+ if (str) {
+ ret = (char*)malloc( strlen(str)+1 );
+ strcpy( ret, str );
+ } else
+ ret = NULL;
+ return ret;
+}
+
+static LRESULT menuPush(
+ wControl_p b,
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ wMenuItem_p m = (wMenuItem_p)b;
+ wBool_t set;
+
+ mswAllowBalloonHelp = TRUE;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+
+ switch (m->mtype) {
+ default:
+ mswFail( "pushMenu" );
+ break;
+ case M_PUSH:
+ if (((wMenuPush_p)m)->action)
+ ((wMenuPush_p)m)->action(((wMenuPush_p)m)->data);
+ break;
+ case M_TOGGLE:
+ set = wMenuToggleGet((wMenuToggle_p)m);
+ set = !set;
+ wMenuToggleSet((wMenuToggle_p)m,set);
+ if (((wMenuToggle_p)m)->action)
+ ((wMenuToggle_p)m)->action(set, ((wMenuPush_p)m)->data);
+ break;
+ case M_LISTITEM:
+ if (((wMenuListItem_p)m)->action)
+ ((wMenuListItem_p)m)->action(0, "", ((wMenuListItem_p)m)->data);
+ break;
+ case M_RADIO:
+ if (((wMenuRadio_p)m)->action)
+ ((wMenuRadio_p)m)->action(((wMenuRadio_p)m)->data);
+ break;
+ }
+ return 0L;
+ }
+ if ( (m->parentMenu)->traceFunc ) {
+ (m->parentMenu)->traceFunc( m->parentMenu, m->labelStr, ((wMenu_p)m->parentMenu)->traceData );
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+static void menuDone( wControl_p b )
+{
+ wMenuItem_p m = (wMenuItem_p)b;
+ switch ( m->mtype ) {
+ case M_MENU:
+ if ( ((wMenu_p)m)->mmtype == MM_BUTT ||
+ ((wMenu_p)m)->mmtype == MM_POPUP )
+ DestroyMenu( ((wMenu_p)m)->menu );
+ break;
+ }
+}
+
+static callBacks_t menuItemCallBacks = {
+ NULL,
+ menuDone,
+ menuPush };
+
+
+static wMenuItem_p createMenuItem(
+ wMenu_p m,
+ mtype_e mtype,
+ const char * helpStr,
+ const char * labelStr,
+ int size )
+{
+ wMenuItem_p mi;
+
+ mi = (wMenuItem_p)calloc( 1, size );
+ mi->type = B_MENUITEM;
+ /*mi->messageProc = menuPush;*/
+ mi->index = mswRegister( (wControl_p)mi );
+ mi->mtype = mtype;
+ if (m) {
+ if (m->last != NULL) {
+ m->last->mnext = mi;
+ } else {
+ m->first = m->last = mi;
+ }
+ m->last = mi;
+ }
+ mi->mnext = NULL;
+ mi->labelStr = mswStrdup( labelStr );
+// if (helpStr != NULL) {
+// char *string;
+// string = malloc( strlen(helpStr) + 1 );
+// strcpy( string, helpStr );
+// /*xv_set(mi->menu_item, XV_HELP_DATA, string, 0 );*/
+// }
+ mswCallBacks[B_MENUITEM] = &menuItemCallBacks;
+ return mi;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Accelerators
+ *
+ *****************************************************************************
+ */
+
+
+typedef struct {
+ long acclKey;
+ wMenuPush_p mp;
+ wAccelKeyCallBack_p action;
+ wAccelKey_e key;
+ void * data;
+ } acclTable_t, *acclTable_p;
+dynArr_t acclTable_da;
+#define acclTable(N) DYNARR_N( acclTable_t, acclTable_da, N )
+
+
+int mswMenuAccelerator(
+ wWin_p win,
+ long acclKey )
+{
+ acclTable_p at;
+ if ( ((wControl_p)win)->type != W_MAIN &&
+ ((wControl_p)win)->type != W_POPUP )
+ return 0;
+ for ( at = &acclTable(0); at<&acclTable(acclTable_da.cnt); at++ ) {
+ if (at->acclKey == acclKey) {
+ if (at->mp) {
+ if (at->mp->enabled && at->mp->action)
+ at->mp->action(at->mp->data);
+ return 1;
+ } else if (at->action) {
+ at->action( at->key, at->data );
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+static long acclKeyMap[] = {
+ 0, /* wAccelKey_None, */
+ VK_DELETE, /* wAccelKey_Del, */
+ VK_INSERT, /* wAccelKey_Ins, */
+ VK_HOME, /* wAccelKey_Home, */
+ VK_END, /* wAccelKey_End, */
+ VK_PRIOR, /* wAccelKey_Pgup, */
+ VK_NEXT, /* wAccelKey_Pgdn, */
+ VK_UP, /* wAccelKey_Up, */
+ VK_DOWN, /* wAccelKey_Down, */
+ VK_RIGHT, /* wAccelKey_Right, */
+ VK_LEFT, /* wAccelKey_Left, */
+ VK_BACK, /* wAccelKey_Back, */
+ VK_F1, /* wAccelKey_F1, */
+ VK_F2, /* wAccelKey_F2, */
+ VK_F3, /* wAccelKey_F3, */
+ VK_F4, /* wAccelKey_F4, */
+ VK_F5, /* wAccelKey_F5, */
+ VK_F6, /* wAccelKey_F6, */
+ VK_F7, /* wAccelKey_F7, */
+ VK_F8, /* wAccelKey_F8, */
+ VK_F9, /* wAccelKey_F9, */
+ VK_F10, /* wAccelKey_F10, */
+ VK_F11, /* wAccelKey_F11, */
+ VK_F12 /* wAccelKey_F12, */
+ };
+
+
+void wAttachAccelKey(
+ wAccelKey_e key,
+ int modifier,
+ wAccelKeyCallBack_p action,
+ void * data )
+{
+ acclTable_t * ad;
+ if ( key < 1 || key > wAccelKey_F12 ) {
+ mswFail( "wAttachAccelKey: key out of range" );
+ return;
+ }
+ DYNARR_APPEND( acclTable_t, acclTable_da, 10 );
+ ad = &acclTable(acclTable_da.cnt-1);
+ ad->acclKey = acclKeyMap[key] | (modifier<<8);
+ ad->key = key;
+ ad->action = action;
+ ad->data = data;
+ ad->mp = NULL;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Menu Item Create
+ *
+ *****************************************************************************
+ */
+
+HBITMAP GetMyCheckBitmaps(UINT fuCheck)
+{
+ COLORREF crBackground; /* background color */
+ HBRUSH hbrBackground; /* background brush */
+ HBRUSH hbrTargetOld; /* original background brush */
+ HDC hdcSource; /* source device context */
+ HDC hdcTarget; /* target device context */
+ HBITMAP hbmpCheckboxes; /* handle to check-box bitmap */
+ BITMAP bmCheckbox; /* structure for bitmap data */
+ HBITMAP hbmpSourceOld; /* handle to original source bitmap */
+ HBITMAP hbmpTargetOld; /* handle to original target bitmap */
+ HBITMAP hbmpCheck; /* handle to check-mark bitmap */
+ RECT rc; /* rectangle for check-box bitmap */
+ WORD wBitmapX; /* width of check-mark bitmap */
+ WORD wBitmapY; /* height of check-mark bitmap */
+
+ /* Get the menu background color and create a solid brush
+ with that color. */
+
+ crBackground = GetSysColor(COLOR_MENU);
+ hbrBackground = CreateSolidBrush(crBackground);
+
+ /* Create memory device contexts for the source and
+ destination bitmaps. */
+
+ hdcSource = CreateCompatibleDC((HDC) NULL);
+ hdcTarget = CreateCompatibleDC(hdcSource);
+
+ /* Get the size of the system default check-mark bitmap and
+ create a compatible bitmap of the same size. */
+
+ wBitmapX = GetSystemMetrics(SM_CXMENUCHECK);
+ wBitmapY = GetSystemMetrics(SM_CYMENUCHECK);
+
+ hbmpCheck = CreateCompatibleBitmap(hdcSource, wBitmapX,
+ wBitmapY);
+
+ /* Select the background brush and bitmap into the target DC. */
+
+ hbrTargetOld = SelectObject(hdcTarget, hbrBackground);
+ hbmpTargetOld = SelectObject(hdcTarget, hbmpCheck);
+
+ /* Use the selected brush to initialize the background color
+ of the bitmap in the target device context. */
+
+ PatBlt(hdcTarget, 0, 0, wBitmapX, wBitmapY, PATCOPY);
+
+ /* Load the predefined check box bitmaps and select it
+ into the source DC. */
+
+ hbmpCheckboxes = LoadBitmap((HINSTANCE) NULL,
+ (LPTSTR) OBM_CHECKBOXES);
+
+ hbmpSourceOld = SelectObject(hdcSource, hbmpCheckboxes);
+
+ /* Fill a BITMAP structure with information about the
+ check box bitmaps, and then find the upper-left corner of
+ the unchecked check box or the checked check box. */
+
+ GetObject(hbmpCheckboxes, sizeof(BITMAP), &bmCheckbox);
+
+ switch( fuCheck ) {
+
+ case UNCHECK:
+ rc.left = 0;
+ rc.right = (bmCheckbox.bmWidth / 4);
+ rc.top = 0;
+ rc.bottom = (bmCheckbox.bmHeight / 3);
+ break;
+ case CHECK:
+ rc.left = (bmCheckbox.bmWidth / 4);
+ rc.right = (bmCheckbox.bmWidth / 4) * 2;
+ rc.top = 0;
+ rc.bottom = (bmCheckbox.bmHeight / 3);
+ break;
+ case RADIOCHECK:
+ rc.left = (bmCheckbox.bmWidth / 4);
+ rc.right = (bmCheckbox.bmWidth / 4) * 2;
+ rc.top = (bmCheckbox.bmHeight / 3) + 1;
+ rc.bottom = (bmCheckbox.bmHeight / 3) * 2;
+ break;
+ case RADIOUNCHECK:
+ rc.top = (bmCheckbox.bmHeight / 3) + 1;
+ rc.bottom = (bmCheckbox.bmHeight / 3) * 2;
+ rc.left = 0;
+ rc.right = (bmCheckbox.bmWidth / 4);
+
+ break;
+ }
+
+ /* Copy the appropriate bitmap into the target DC. If the
+ check-box bitmap is larger than the default check-mark
+ bitmap, use StretchBlt to make it fit; otherwise, just
+ copy it. */
+
+ if (((rc.right - rc.left) > (int) wBitmapX) ||
+ ((rc.bottom - rc.top) > (int) wBitmapY))
+ {
+ StretchBlt(hdcTarget, 0, 0, wBitmapX, wBitmapY,
+ hdcSource, rc.left, rc.top, rc.right - rc.left,
+ rc.bottom - rc.top, SRCCOPY);
+ }
+
+ else
+ {
+ BitBlt(hdcTarget, 0, 0, rc.right - rc.left,
+ rc.bottom - rc.top,
+ hdcSource, rc.left, rc.top, SRCCOPY);
+ }
+
+ /* Select the old source and destination bitmaps into the
+ source and destination DCs, and then delete the DCs and
+ the background brush. */
+
+ SelectObject(hdcSource, hbmpSourceOld);
+ SelectObject(hdcTarget, hbrTargetOld);
+ hbmpCheck = SelectObject(hdcTarget, hbmpTargetOld);
+
+ DeleteObject(hbrBackground);
+ DeleteObject(hdcSource);
+ DeleteObject(hdcTarget);
+
+ /* Return a handle to the new check-mark bitmap. */
+
+ return hbmpCheck;
+}
+
+void mswCreateCheckBitmaps()
+{
+ checked = GetMyCheckBitmaps( CHECK );
+ unchecked = GetMyCheckBitmaps( UNCHECK );
+ checkedRadio = GetMyCheckBitmaps( RADIOCHECK );
+ uncheckedRadio = GetMyCheckBitmaps( RADIOUNCHECK );
+
+}
+
+wMenuRadio_p wMenuRadioCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wMenuCallBack_p action,
+ void *data )
+{
+ wMenuRadio_p mi;
+ int rc;
+ char label[80];
+ char *cp;
+ char ac;
+ UINT vk;
+ long modifier;
+
+ mi = (wMenuRadio_p)createMenuItem( m, M_RADIO, helpStr, labelStr, sizeof *mi );
+ mi->action = action;
+ mi->data = data;
+ mi->mparent = m;
+ mi->acclKey = acclKey;
+ mi->enabled = TRUE;
+ strcpy( label, mi->labelStr );
+ modifier = 0;
+ if ( acclKey != 0 ) {
+ DYNARR_APPEND( acclTable_t, acclTable_da, 10 );
+ cp = label + strlen( label );
+ *cp++ = '\t';
+ if (acclKey & WCTL ) {
+ strcpy( cp, "Ctrl+" );
+ cp += 5;
+ modifier |= WKEY_CTRL;
+ }
+ if (acclKey & WALT ) {
+ strcpy( cp, "Alt+" );
+ cp += 4;
+ modifier |= WKEY_ALT;
+ }
+ if (acclKey & WSHIFT ) {
+ strcpy( cp, "Shift+" );
+ cp += 6;
+ modifier |= WKEY_SHIFT;
+ }
+ *cp++ = toupper( (char)(acclKey & 0xFF) );
+ *cp++ = '\0';
+ ac = (char)(acclKey & 0xFF);
+ if (isalpha(ac)) {
+ ac = tolower( ac );
+ }
+ vk = VkKeyScan( ac );
+ if ( vk & 0xFF00 )
+ modifier |= WKEY_SHIFT;
+ acclTable(acclTable_da.cnt-1).acclKey = (modifier<<8) | (vk&0x00FF);
+ acclTable(acclTable_da.cnt-1).mp = (wMenuPush_p)mi;
+ }
+ rc = AppendMenu( m->menu, MF_STRING, mi->index, label );
+
+ /* add the correct bitmaps for radio buttons */
+
+ rc = SetMenuItemBitmaps(m->menu, mi->index, FALSE, uncheckedRadio, checkedRadio );
+
+ if( m->radioGroup == NULL ) {
+ m->radioGroup = malloc( sizeof( struct radioButtonGroup ));
+ assert( m->radioGroup );
+ m->radioGroup->firstButton = mi->index;
+ } else {
+ m->radioGroup->lastButton = mi->index;
+ }
+
+ return mi;
+}
+
+void wMenuRadioSetActive(wMenuRadio_p mi )
+{
+ BOOL rc;
+
+ rc = CheckMenuRadioItem( mi->mparent->menu,
+ mi->mparent->radioGroup->firstButton,
+ mi->mparent->radioGroup->lastButton,
+ mi->index,
+ MF_BYCOMMAND );
+}
+
+
+wMenuPush_p wMenuPushCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wMenuCallBack_p action,
+ void *data )
+{
+ wMenuPush_p mi;
+ int rc;
+ char label[80];
+ char *cp;
+ char ac;
+ UINT vk;
+ long modifier;
+
+ mi = (wMenuPush_p)createMenuItem( m, M_PUSH, helpStr, labelStr, sizeof *mi );
+ mi->action = action;
+ mi->data = data;
+ mi->mparent = m;
+ mi->acclKey = acclKey;
+ mi->enabled = TRUE;
+ strcpy( label, mi->labelStr );
+ modifier = 0;
+ if ( acclKey != 0 ) {
+ DYNARR_APPEND( acclTable_t, acclTable_da, 10 );
+ cp = label + strlen( label );
+ *cp++ = '\t';
+ if (acclKey & WCTL ) {
+ strcpy( cp, "Ctrl+" );
+ cp += 5;
+ modifier |= WKEY_CTRL;
+ }
+ if (acclKey & WALT ) {
+ strcpy( cp, "Alt+" );
+ cp += 4;
+ modifier |= WKEY_ALT;
+ }
+ if (acclKey & WSHIFT ) {
+ strcpy( cp, "Shift+" );
+ cp += 6;
+ modifier |= WKEY_SHIFT;
+ }
+ *cp++ = toupper( (char)(acclKey & 0xFF) );
+ *cp++ = '\0';
+ ac = (char)(acclKey & 0xFF);
+ if (isalpha(ac)) {
+ ac = tolower( ac );
+ }
+ vk = VkKeyScan( ac );
+ if ( vk & 0xFF00 )
+ modifier |= WKEY_SHIFT;
+ acclTable(acclTable_da.cnt-1).acclKey = (modifier<<8) | (vk&0x00FF);
+ acclTable(acclTable_da.cnt-1).mp = mi;
+ }
+ rc = AppendMenu( m->menu, MF_STRING, mi->index, label );
+ return mi;
+}
+
+
+void wMenuPushEnable(
+ wMenuPush_p mi,
+ BOOL_T enable )
+{
+ EnableMenuItem( mi->mparent->menu, mi->index,
+ MF_BYCOMMAND|(enable?MF_ENABLED:(MF_DISABLED|MF_GRAYED)) );
+ mi->enabled = enable;
+}
+
+
+wMenu_p wMenuMenuCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr )
+{
+ wMenu_p mm;
+ int rc;
+
+ mm = (wMenu_p)createMenuItem( NULL, M_MENU, NULL, labelStr, sizeof *mm );
+ mm->menu = CreatePopupMenu();
+ mm->mmtype = MM_MENU;
+ /*mm->parent = (wControl_p)m;*/
+ mm->first = mm->last = NULL;
+
+ rc = AppendMenu( m->menu, MF_STRING|MF_ENABLED|MF_POPUP, (UINT)mm->menu, mm->labelStr );
+
+ return mm;
+}
+
+void wMenuSeparatorCreate(
+ wMenu_p m )
+{
+ int rc;
+ createMenuItem( m, M_SEPARATOR, NULL, NULL, sizeof *(wMenuItem_p)NULL );
+ rc = AppendMenu( m->menu, MF_SEPARATOR, (UINT)0, NULL );
+}
+
+/*
+ *****************************************************************************
+ *
+ * Menu List
+ *
+ *****************************************************************************
+ */
+
+
+static void appendItem(
+ wMenuListItem_p ml,
+ wMenuListItem_p mi )
+{
+ mi->right = ml->right;
+ ml->right->left = mi;
+ mi->left = ml;
+ ml->right = mi;
+}
+
+
+static void removeItem(
+ wMenuListItem_p mi )
+{
+ mi->left->right = mi->right;
+ mi->right->left = mi->left;
+ mi->right = mi->left = mi;
+}
+
+
+wMenuList_p wMenuListCreate(
+ wMenu_p m,
+ const char * helpStr,
+ int max,
+ wMenuListCallBack_p action )
+{
+ wMenuList_p mi;
+ mi = (wMenuList_p)createMenuItem( m, M_LIST, helpStr, NULL, sizeof *mi );
+ mi->count = 0;
+ mi->max = max;
+ mi->mlparent = m;
+ mi->action = action;
+ mi->right = mi->left = (wMenuListItem_p)mi;
+ return mi;
+}
+
+
+int getMlistOrigin( wMenu_p m, wMenuList_p ml )
+{
+ wMenuItem_p mi;
+ int count;
+ count = 0;
+ for ( mi = m->first; mi != NULL; mi = mi->mnext ) {
+ switch( mi->mtype ) {
+ case M_SEPARATOR:
+ case M_PUSH:
+ case M_MENU:
+ count++;
+ break;
+ case M_LIST:
+ if (mi == (wMenuItem_p)ml)
+ return count;
+ count += ((wMenuList_p)mi)->count;
+ break;
+ default:
+ mswFail( "getMlistOrigin" );
+ }
+ }
+ return count;
+}
+
+
+void wMenuListAdd(
+ wMenuList_p ml,
+ int index,
+ const char * labelStr,
+ void * data )
+{
+ int origin;
+ wMenuListItem_p wl_p;
+ wMenuListItem_p mi;
+ int count;
+ int rc;
+
+ origin = getMlistOrigin(ml->mlparent, ml);
+ for ( count=0,wl_p=ml->right; wl_p!=(wMenuListItem_p)ml; count++,wl_p=wl_p->right ) {
+ if (wl_p->labelStr != NULL && strcmp( labelStr, wl_p->labelStr ) == 0) {
+ /* move item */
+ if (count != index) {
+ RemoveMenu( ml->mlparent->menu, origin+count, MF_BYPOSITION );
+ removeItem( wl_p );
+ goto add;
+ }
+ ((wMenuListItem_p)wl_p)->data = data;
+ return;
+ }
+ }
+ if (ml->max > 0 && ml->count >= ml->max) {
+ RemoveMenu( ml->mlparent->menu, origin+ml->count-1, MF_BYPOSITION );
+ wl_p = ml->left;
+ removeItem( ml->left );
+add:
+ ml->count--;
+ if (wl_p->labelStr )
+ free( CAST_AWAY_CONST wl_p->labelStr );
+ wl_p->labelStr = mswStrdup( labelStr );
+ } else {
+ wl_p = (wMenuListItem_p)createMenuItem( NULL, M_LISTITEM, NULL,
+ labelStr, sizeof *wl_p );
+ }
+ ((wMenuListItem_p)wl_p)->data = data;
+ ((wMenuListItem_p)wl_p)->action = ml->action;
+ if (index < 0 || index > ml->count)
+ index = ml->count;
+ for ( mi=(wMenuListItem_p)ml,count=0; count<index; mi=mi->right,count++);
+ rc = InsertMenu( ml->mlparent->menu, origin+index,
+ MF_BYPOSITION|MF_STRING, wl_p->index, wl_p->labelStr );
+ appendItem( mi, wl_p );
+ ml->count++;
+}
+
+
+void wMenuListDelete(
+ wMenuList_p ml,
+ const char * labelStr )
+{
+ int origin, count;
+ wMenuListItem_p wl_p;
+
+ origin = getMlistOrigin(ml->mlparent, ml);
+ for ( count=0,wl_p=ml->right; wl_p!=(wMenuListItem_p)ml; count++,wl_p=wl_p->right ) {
+ if (wl_p->labelStr != NULL && strcmp( labelStr, wl_p->labelStr ) == 0) {
+ /* delete item */
+ mswUnregister( wl_p->index );
+ RemoveMenu( ml->mlparent->menu, origin+count, MF_BYPOSITION );
+ removeItem( wl_p );
+ ml->count--;
+ free( wl_p );
+ return;
+ }
+ }
+}
+
+
+const char * wMenuListGet(
+ wMenuList_p ml,
+ int index,
+ void ** data )
+{
+ int origin, count;
+ wMenuListItem_p wl_p;
+
+ if (index >= ml->count)
+ return NULL;
+ origin = getMlistOrigin(ml->mlparent, ml);
+ for ( count=0,wl_p=ml->right; wl_p&&count<index; count++,wl_p=wl_p->right );
+ if (wl_p==NULL)
+ return NULL;
+ if ( data )
+ *data = wl_p->data;
+ return wl_p->labelStr;
+}
+
+
+void wMenuListClear(
+ wMenuList_p ml )
+{
+ int origin, count;
+ wMenuListItem_p wl_p, wl_q;
+
+ origin = getMlistOrigin(ml->mlparent, ml);
+ for ( count=0,wl_p=ml->right; count<ml->count; count++,wl_p=wl_q ) {
+ /* delete item */
+ mswUnregister( wl_p->index );
+ RemoveMenu( ml->mlparent->menu, origin, MF_BYPOSITION );
+ wl_q = wl_p->right;
+ free( wl_p );
+ }
+ ml->count = 0;
+ ml->right = ml->left = (wMenuListItem_p)ml;
+}
+
+
+
+wMenuToggle_p wMenuToggleCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wBool_t set,
+ wMenuToggleCallBack_p action,
+ void * data )
+{
+ wMenuToggle_p mt;
+ int rc;
+
+ mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof *mt );
+ /*setAcclKey( m->parent, m->menu, mt->menu_item, acclKey );*/
+ mt->action = action;
+ mt->data = data;
+ mt->mparent = m;
+ mt->enabled = TRUE;
+ mt->parentMenu = m;
+ rc = AppendMenu( m->menu, MF_STRING, mt->index, labelStr );
+ wMenuToggleSet( mt, set );
+ return mt;
+}
+
+
+wBool_t wMenuToggleGet(
+ wMenuToggle_p mt )
+{
+ return (GetMenuState( mt->mparent->menu, mt->index, MF_BYCOMMAND ) & MF_CHECKED) != 0;
+}
+
+
+wBool_t wMenuToggleSet(
+ wMenuToggle_p mt,
+ wBool_t set )
+{
+ wBool_t rc;
+ CheckMenuItem( mt->mparent->menu, mt->index, MF_BYCOMMAND|(set?MF_CHECKED:MF_UNCHECKED) );
+ rc = (GetMenuState( mt->mparent->menu, mt->index, MF_BYCOMMAND ) & MF_CHECKED) != 0;
+ return rc;
+}
+
+void wMenuToggleEnable(
+ wMenuToggle_p mt,
+ wBool_t enable )
+{
+ EnableMenuItem( mt->mparent->menu, mt->index,
+ MF_BYCOMMAND|(enable?MF_ENABLED:(MF_DISABLED|MF_GRAYED)) );
+ mt->enabled = enable;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Menu Create
+ *
+ *****************************************************************************
+ */
+
+
+void mswMenuMove(
+ wMenu_p m,
+ wPos_t x,
+ wPos_t y )
+{
+ wControl_p b;
+ b = (wControl_p)m->parent;
+ if (b && b->hWnd)
+ if (!SetWindowPos( b->hWnd, HWND_TOP, x, y,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER))
+ mswFail("mswMenuMove");
+}
+
+
+static void pushMenuButt(
+ void * data )
+{
+ wMenu_p m = (wMenu_p)data;
+ RECT rect;
+ mswAllowBalloonHelp = FALSE;
+ GetWindowRect( m->hWnd, &rect );
+ TrackPopupMenu( m->menu, TPM_LEFTALIGN, rect.left, rect.bottom,
+ 0, ((wControl_p)(m->parent))->hWnd, NULL );
+}
+
+
+wMenu_p wMenuCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option )
+{
+ wMenu_p m;
+ wControl_p b;
+ long buttOption = 0;
+ const char * label = labelStr;
+
+ if (option & BM_ICON) {
+ buttOption = BO_ICON;
+ label = "ICON";
+ }
+ m = (wMenu_p)createMenuItem( NULL, M_MENU, helpStr, label, sizeof *m );
+ m->button = wButtonCreate( parent, x, y, helpStr, labelStr,
+ buttOption, 0, pushMenuButt, (void*)m );
+ b = (wControl_p)m->button;
+ m->parent = b->parent;
+ m->x = b->x;
+ m->y = b->y;
+ m->w = b->w;
+ m->h = b->h;
+ m->hWnd = b->hWnd;
+ m->helpStr = b->helpStr;
+
+ m->menu = CreatePopupMenu();
+ m->mmtype = MM_BUTT;
+ m->first = m->last = NULL;
+
+ return m;
+}
+
+
+wMenu_p wMenuBarAdd(
+ wWin_p w,
+ const char * helpStr,
+ const char * labelStr )
+{
+ HMENU menu;
+ wMenu_p m;
+ int rc;
+
+ menu = GetMenu( ((wControl_p)w)->hWnd );
+ if (menu == (HMENU)0) {
+ menu = CreateMenu();
+ SetMenu( ((wControl_p)w)->hWnd, menu );
+ }
+
+ m = (wMenu_p)createMenuItem( NULL, M_MENU, helpStr, labelStr, sizeof *m );
+ m->menu = CreateMenu();
+ m->parent = w;
+ m->mmtype = MM_BAR;
+ m->first = m->last = NULL;
+
+ rc = AppendMenu( menu, MF_STRING|MF_POPUP|MF_ENABLED, (UINT)m->menu, labelStr );
+
+ DrawMenuBar( ((wControl_p)w)->hWnd );
+ return m;
+}
+
+
+
+wMenu_p wMenuPopupCreate(
+ wWin_p w,
+ const char * labelStr )
+{
+ wMenu_p m;
+ long buttOption = 0;
+ const char * label = labelStr;
+
+ m = (wMenu_p)createMenuItem( NULL, M_MENU, NULL, label, sizeof *m );
+ m->button = NULL;
+ m->parent = w;
+ m->x = 0;
+ m->y = 0;
+ m->w = 0;
+ m->h = 0;
+ m->hWnd = ((wControl_p)w)->hWnd;
+ m->helpStr = NULL;
+
+ m->menu = CreatePopupMenu();
+ m->mmtype = MM_POPUP;
+ m->first = m->last = NULL;
+
+ return m;
+}
+
+
+void wMenuPopupShow( wMenu_p mp )
+{
+ POINT pt;
+ GetCursorPos( &pt );
+ TrackPopupMenu( mp->menu, TPM_LEFTALIGN, pt.x, pt.y, 0, mp->hWnd, NULL );
+}
+
+/*-----------------------------------------------------------------*/
+
+void wMenuSetTraceCallBack(
+ wMenu_p m,
+ wMenuTraceCallBack_p func,
+ void * data )
+{
+ m->traceFunc = func;
+ m->traceData = data;
+}
+
+wBool_t wMenuAction(
+ wMenu_p m,
+ const char * label )
+{
+ wMenuItem_p mi;
+ wMenuToggle_p mt;
+ wBool_t set;
+ for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->mnext ) {
+ if ( mi->labelStr != NULL && strcmp( mi->labelStr, label ) == 0 ) {
+ switch( mi->mtype ) {
+ case M_SEPARATOR:
+ break;
+ case M_PUSH:
+ if ( ((wMenuPush_p)mi)->enabled == FALSE )
+ wBeep();
+ else
+ ((wMenuPush_p)mi)->action( ((wMenuPush_p)mi)->data );
+ break;
+ case M_TOGGLE:
+ mt = (wMenuToggle_p)mi;
+ if ( mt->enabled == FALSE ) {
+ wBeep();
+ } else {
+ set = wMenuToggleGet( mt );
+ wMenuToggleSet( mt, !set );
+ mt->action( set, mt->data );
+ }
+ break;
+ case M_MENU:
+ break;
+ case M_LIST:
+ break;
+ default:
+ fprintf(stderr, "Oops: wMenuAction\n");
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/app/wlib/mswlib/mswmisc.c b/app/wlib/mswlib/mswmisc.c
new file mode 100644
index 0000000..fc1dbe6
--- /dev/null
+++ b/app/wlib/mswlib/mswmisc.c
@@ -0,0 +1,2778 @@
+/** \file mswmisc.c
+ * Basic windows functions and main entry point for application.
+ *
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/mswlib/mswmisc.c,v 1.28 2010-04-28 04:04:38 dspagnol Exp $
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis, 2009 Martin Fischer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <stdio.h>
+#include <assert.h>
+#include <htmlhelp.h>
+#include "mswint.h"
+#include "i18n.h"
+
+#if _MSC_VER > 1300
+ #define stricmp _stricmp
+ #define strnicmp _strnicmp
+ #define strdup _strdup
+#endif
+
+#define OFN_LONGFILENAMES 0x00200000L
+
+char * mswStrdup( const char * );
+
+#define PAUSE_TIMER (901)
+#define ALARM_TIMER (902)
+#define BALLOONHELP_TIMER (903)
+#define TRIGGER_TIMER (904)
+
+#define WANT_LITTLE_LABEL_FONT
+
+#ifndef WANT_LITTLE_LABEL_FONT
+#define LABELFONTDECL
+#define LABELFONTSELECT
+#define LABELFONTRESET
+#else
+#define LABELFONTDECL HFONT hFont;
+#define LABELFONTRESET if (!mswThickFont) {SelectObject( hDc, hFont );}
+#define LABELFONTSELECT if (!mswThickFont) {hFont = SelectObject( hDc, mswLabelFont );}
+#endif
+
+/*
+ * EXPORTED VARIABLES
+ */
+
+long debugWindow = 0;
+HINSTANCE mswHInst;
+HWND mswHWnd = (HWND)0;
+
+const char *mswDrawWindowClassName = "DRAWWINDOW";
+char mswTmpBuff[1024];
+int mswEditHeight;
+int mswAllowBalloonHelp = TRUE;
+int mswGroupStyle;
+HFONT mswOldTextFont;
+HFONT mswLabelFont;
+long mswThickFont = 1;
+double mswScale = 1.0;
+
+callBacks_t *mswCallBacks[CALLBACK_CNT];
+
+void closeBalloonHelp( void );
+static wControl_p getControlFromCursor( HWND, wWin_p * );
+/*
+ * LOCAL VARIABLES
+ */
+
+struct wWin_t {
+ WOBJ_COMMON
+ wPos_t lastX, lastY;
+ wPos_t padX, padY;
+ wControl_p first, last;
+ wWinCallBack_p winProc;
+ BOOL_T busy;
+#ifdef OWNERICON
+ HBITMAP wicon_bm;
+ wPos_t wicon_w, wicon_h;
+#endif
+ DWORD baseStyle;
+ wControl_p focusChainFirst;
+ wControl_p focusChainLast;
+ char * nameStr;
+ wBool_t centerWin;
+ DWORD style;
+ int isBusy;
+ int pendingShow;
+ int modalLevel;
+ };
+
+static needToDoPendingShow = FALSE;
+
+/* System metrics: */
+static int mTitleH;
+static int mFixBorderW;
+static int mFixBorderH;
+static int mResizeBorderW;
+static int mResizeBorderH;
+static int mMenuH;
+static int screenWidth = 0, screenHeight = 0;
+
+wWin_p mswWin = NULL;
+wWin_p winFirst, winLast;
+
+static long count51 = 0;
+
+static UINT alarmTimer;
+static UINT pauseTimer;
+static UINT balloonHelpTimer = (UINT)0;
+static UINT triggerTimer;
+
+static UINT balloonHelpTimeOut = 500;
+static wControl_p balloonHelpButton = NULL;
+static enum { balloonHelpIdle , balloonHelpWait, balloonHelpShow } balloonHelpState = balloonHelpIdle;
+static HWND balloonHelpHWnd = (HWND)0;
+static int balloonHelpFontSize = 8;
+static char balloonHelpFaceName[] = "MS Sans Serif";
+static HFONT balloonHelpOldFont;
+static HFONT balloonHelpNewFont;
+static int balloonHelpEnable = TRUE;
+static wControl_p balloonControlButton = NULL;
+
+static BOOL_T helpInitted = FALSE;
+static DWORD dwCookie;
+
+#define CONTROL_BASE (1)
+typedef struct {
+ wControl_p b;
+ } controlMap_t;
+dynArr_t controlMap_da;
+#define controlMap(N) DYNARR_N(controlMap_t,controlMap_da,N)
+
+
+static char * appName;
+static char * helpFile;
+char *mswProfileFile;
+
+static wBalloonHelp_t * balloonHelpStrings;
+
+static wCursor_t curCursor = wCursorNormal;
+
+#ifdef HELPSTR
+static FILE * helpStrF;
+#endif
+static int inMainWndProc = FALSE;
+
+int newHelp = 1;
+
+static wBool_t mswWinBlockEnabled = TRUE;
+
+static FILE * dumpControlsF;
+static int dumpControls;
+
+extern char *userLocale;
+
+
+/*
+ *****************************************************************************
+ *
+ * Internal Utility functions
+ *
+ *****************************************************************************
+ */
+
+
+DWORD GetTextExtent(
+ HDC hDc,
+ CHAR * str,
+ UINT len )
+{
+ SIZE size;
+ GetTextExtentPoint( hDc, str, len, &size );
+ return size.cx + (size.cy<<16);
+}
+
+
+static char * controlNames[] = {
+ "MAIN", "POPUP",
+ "BUTTON", "STRING", "INTEGER", "FLOAT",
+ "LIST", "DROPLIST", "COMBOLIST",
+ "RADIO", "TOGGLE",
+ "DRAW", "TEXT", "MESSAGE", "LINES",
+ "MENUITEM", "CHOICEITEM", "BOX" };
+
+static void doDumpControls(void)
+{
+ wControl_p b;
+ int inx;
+ if ( !dumpControls )
+ return;
+ if ( !dumpControlsF ) {
+ dumpControlsF = fopen( "controls.lst", "w" );
+ if ( !dumpControlsF )
+ abort();
+ }
+ for ( inx=0; inx<controlMap_da.cnt-1; inx++ ) {
+ b = controlMap(inx).b;
+ if ( b ) {
+ fprintf( dumpControlsF, "[%0.3d] [%x] %s %s %s\n", inx,
+ b->hWnd,
+ (b->type>=0&&b->type<=B_BOX?controlNames[b->type]:"NOTYPE"),
+ (b->labelStr?b->labelStr:"<NULL>"),
+ (b->helpStr?b->helpStr:"<NULL>") );
+ } else {
+ fprintf( dumpControlsF, "[%0.3d] <NULL>\n", inx );
+ }
+ }
+ fflush( dumpControlsF );
+ fclose( dumpControlsF );
+ dumpControls = 0;
+}
+
+void mswFail( const char * where )
+{
+ sprintf( mswTmpBuff, "%s\n# Controls %d", where, controlMap_da.cnt );
+ MessageBox( NULL, mswTmpBuff, "FAIL", MB_TASKMODAL|MB_OK );
+ doDumpControls();
+}
+/*
+static UINT curSysRes = 100;
+static UINT curGdiRes = 100;
+static UINT curUsrRes = 100;
+static UINT curMinRes = 100;
+*/
+
+wControl_p mswMapIndex( INDEX_T inx )
+{
+ if (inx < CONTROL_BASE || inx > controlMap_da.cnt) {
+ mswFail("mswMapIndex- bad index");
+ exit(1);
+ }
+ return controlMap(inx-CONTROL_BASE).b;
+}
+
+
+void mswRepaintLabel( HWND hWnd, wControl_p b )
+{
+ HDC hDc;
+ HBRUSH oldBrush, newBrush;
+ RECT rect;
+ DWORD dw;
+ LABELFONTDECL
+
+
+ if (b->labelStr) {
+ hDc = GetDC( hWnd );
+ LABELFONTSELECT
+ newBrush = CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) );
+ oldBrush = SelectObject( hDc, newBrush );
+ dw = GetTextExtent( hDc, CAST_AWAY_CONST b->labelStr, strlen(b->labelStr) );
+ rect.left = b->labelX;
+ rect.top = b->labelY;
+ rect.right = b->labelX + LOWORD(dw);
+ rect.bottom = b->labelY + HIWORD(dw);
+ FillRect( hDc, &rect, newBrush );
+ DeleteObject( SelectObject( hDc, oldBrush ) );
+ /*SetBkMode( hDc, OPAQUE );*/
+ SetBkColor( hDc, GetSysColor( COLOR_BTNFACE ) );
+ if (!TextOut( hDc, b->labelX, b->labelY, b->labelStr, strlen(b->labelStr) ) )
+ mswFail( "Repainting text label" );
+ LABELFONTRESET
+ ReleaseDC( hWnd, hDc );
+ }
+}
+
+
+
+int mswRegister(
+ wControl_p w )
+{
+ int index;
+ DYNARR_APPEND( controlMap_t, controlMap_da, 25 );
+ index = controlMap_da.cnt-1+CONTROL_BASE;
+ controlMap(controlMap_da.cnt-1).b = (wControl_p)w;
+ return index;
+}
+
+
+void mswUnregister(
+ int index )
+{
+ if (index < 0 || index > controlMap_da.cnt) {
+ mswFail("mswMapIndex- bad index");
+ exit(1);
+ }
+ controlMap(index-CONTROL_BASE).b = NULL;
+}
+
+void * mswAlloc(
+ wWin_p parent,
+ wType_e type,
+ const char * labelStr,
+ int size,
+ void * data,
+ int * index )
+{
+ wControl_p w = (wControl_p)calloc( 1, size );
+
+ if (w == NULL)
+ abort();
+ *index = mswRegister( w );
+ w->type = type;
+ w->next = NULL;
+ w->parent = parent;
+ w->x = 0;
+ w->y = 0;
+ w->w = 0;
+ w->h = 0;
+ w->option = 0;
+ w->labelX = w->labelY = 0;
+ w->labelStr = labelStr;
+ w->helpStr = NULL;
+ w->hWnd = (HWND)0;
+ w->data = data;
+ w->focusChainNext = NULL;
+ w->shown = TRUE;
+ return w;
+}
+
+
+void mswComputePos(
+ wControl_p b,
+ wPos_t origX,
+ wPos_t origY )
+{
+ wWin_p w = b->parent;
+
+ if (origX >= 0)
+ b->x = origX;
+ else
+ b->x = w->lastX + (-origX) - 1;
+ if (origY >= 0)
+ b->y = origY;
+ else
+ b->y = w->lastY + (-origY) - 1;
+
+ b->labelX = b->x;
+ b->labelY = b->y+2;
+
+ if (b->labelStr) {
+ int lab_l;
+ HDC hDc;
+ DWORD dw;
+ LABELFONTDECL
+
+ hDc = GetDC( w->hWnd );
+ LABELFONTSELECT
+ lab_l = strlen(b->labelStr);
+ dw = GetTextExtent( hDc, CAST_AWAY_CONST b->labelStr, lab_l );
+ b->labelX -= LOWORD(dw) + 5;
+ LABELFONTRESET
+ ReleaseDC( w->hWnd, hDc );
+ }
+}
+
+void mswAddButton(
+ wControl_p b,
+ BOOL_T paintLabel,
+ const char * helpStr )
+{
+ wWin_p w = b->parent;
+ BOOL_T resize = FALSE;
+ RECT rect;
+
+ if (w->first == NULL) {
+ w->first = b;
+ } else {
+ w->last->next = b;
+ }
+ w->last = b;
+ b->next = NULL;
+ b->parent = w;
+ w->lastX = b->x + b->w;
+ w->lastY = b->y + b->h;
+ if ((w->option&F_AUTOSIZE)!=0 && w->lastX > w->w) {
+ w->w = w->lastX;
+ resize = TRUE;
+ }
+ if ((w->option&F_AUTOSIZE)!=0 && w->lastY > w->h) {
+ w->h = w->lastY;
+ resize = TRUE;
+ }
+
+ if (resize) {
+ w->busy = TRUE;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = w->w+w->padX;
+ rect.bottom = w->h+w->padY;
+ AdjustWindowRect( &rect, w->style, (w->option&F_MENUBAR)?1:0 );
+ rect.bottom += mFixBorderH;
+ if (!SetWindowPos( w->hWnd, HWND_TOP, CW_USEDEFAULT, CW_USEDEFAULT,
+ rect.right-rect.left, rect.bottom-rect.top,
+ SWP_NOMOVE))
+ mswFail("SetWindowPos");
+ w->busy = FALSE;
+ }
+
+ if (paintLabel)
+ mswRepaintLabel( w->hWnd, (wControl_p)b );
+
+ if (helpStr == NULL)
+ return;
+ b->helpStr = mswStrdup( helpStr );
+
+#ifdef HELPSTR
+ if (helpStrF)
+ fprintf( helpStrF, "HELPSTR - %s\n", helpStr?helpStr:"<>" );
+#endif
+}
+
+
+void mswResize(
+ wWin_p w )
+{
+ wControl_p b;
+ RECT rect;
+
+ w->lastX = 0;
+ w->lastY = 0;
+ for (b=w->first; b; b=b->next) {
+ if (w->lastX < (b->x + b->w))
+ w->lastX = b->x + b->w;
+ if (w->lastY < (b->y + b->h))
+ w->lastY = b->y + b->h;
+ }
+
+ if (w->option&F_AUTOSIZE) {
+ w->w = w->lastX;
+ w->h = w->lastY;
+ w->busy = TRUE;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = w->w + w->padX;
+ rect.bottom = w->h + w->padY;
+ AdjustWindowRect( &rect, w->style, (w->option&F_MENUBAR)?1:0 );
+ rect.bottom += mFixBorderH;
+ if (!SetWindowPos( w->hWnd, HWND_TOP, CW_USEDEFAULT, CW_USEDEFAULT,
+ rect.right-rect.left, rect.bottom-rect.top,
+ SWP_NOMOVE|SWP_NOZORDER))
+ mswFail("SetWindowPos");
+ w->busy = FALSE;
+ }
+}
+
+
+
+void mswChainFocus(
+ wControl_p b )
+{
+ wWin_p w;
+ w = b->parent;
+ if (w->option&F_NOTAB)
+ return;
+ if (b->option&BO_NOTAB)
+ return;
+ if (w->focusChainFirst == NULL) {
+ w->focusChainFirst = w->focusChainLast = w->focusChainNext = b;
+ b->focusChainNext = b;
+ } else {
+ w->focusChainLast->focusChainNext = b;
+ w->focusChainLast = b;
+ b->focusChainNext = w->focusChainFirst;
+ }
+}
+
+void mswSetFocus(
+ wControl_p b )
+{
+ if (b && b->type != B_MENUITEM && b->focusChainNext)
+ b->parent->focusChainNext = b;
+}
+
+/*
+ ******************************************************************************
+ *
+ * Main and Popup Windows
+ *
+ ******************************************************************************
+ */
+
+static void getSavedSizeAndPos(
+ long option,
+ const char * nameStr,
+ wPos_t *rw,
+ wPos_t *rh,
+ wPos_t *rx,
+ wPos_t *ry,
+ int *showCmd )
+{
+ int x, y, w, h;
+ const char *cp;
+ char *cq;
+ int state;
+
+ *showCmd = SW_SHOWNORMAL;
+
+ if ( (option&F_RECALLPOS) && nameStr ) {
+ if ( (option & F_RESIZE) &&
+ (cp = wPrefGetString( "msw window size", nameStr)) &&
+ (state = (int)strtol( cp, &cq, 10 ), cp != cq) &&
+ (cp = cq, w = (wPos_t)strtod( cp, &cq ), cp != cq ) &&
+ (cp = cq, h = (int)strtod( cp, &cq ), cp != cq)
+ ) {
+ if (state == 1)
+ *showCmd = SW_SHOWMINIMIZED;
+ else if (state == 2)
+ *showCmd = SW_SHOWMAXIMIZED;
+ if (w < 10)
+ w = 10;
+ if (h < 10)
+ h = 10;
+ if (w > screenWidth)
+ w = screenWidth;
+ if (h > screenHeight)
+ h = screenHeight;
+ *rw = w;
+ *rh = h;
+ }
+
+ if ((cp = wPrefGetString( "msw window pos", nameStr)) &&
+ (x = (wPos_t)strtod( cp, &cq ), cp != cq) &&
+ (cp = cq, y = (wPos_t)strtod( cp, &cq ), cp != cq)
+ ) {
+ if (y < 0)
+ y = 0;
+ if (x < 0)
+ x = 0;
+ if ( y > screenHeight-40 )
+ y = screenHeight-40;
+ if ( x > screenWidth-40 )
+ x = screenWidth-40;
+ *rx = x;
+ *ry = y;
+ }
+ }
+}
+
+
+static wWin_p winCommonCreate(
+ HWND hWnd,
+ int typ,
+ long option,
+ const char * className,
+ long style,
+ const char * labelStr,
+ wWinCallBack_p winProc,
+ wPos_t w,
+ wPos_t h,
+ void * data,
+ const char * nameStr,
+ int * showCmd )
+{
+ wWin_p win;
+ int index;
+ wPos_t ww, hh, xx, yy;
+ RECT rect;
+
+ win = (wWin_p)mswAlloc( NULL, typ, mswStrdup(labelStr), sizeof *win, data, &index );
+ win->option = option;
+ win->first = win->last = NULL;
+ win->lastX = 0;
+ win->lastY = 0;
+ win->winProc = winProc;
+ win->centerWin = TRUE;
+ win->modalLevel = 0;
+#ifdef OWNERICON
+ win->wicon_bm = (HBITMAP)0;
+#endif
+ win->busy = TRUE;
+ ww = hh = xx = yy = CW_USEDEFAULT;
+ getSavedSizeAndPos( option, nameStr, &ww, &hh, &xx, &yy, showCmd );
+ if (xx != CW_USEDEFAULT)
+ win->centerWin = FALSE;
+ if (option & F_RESIZE) {
+ style |= WS_THICKFRAME;
+ if ( ww != CW_USEDEFAULT ) {
+ w = ww;
+ h = hh;
+ option &= ~F_AUTOSIZE;
+ win->option = option;
+ }
+ }
+
+ if ( option & F_AUTOSIZE ) {
+ win->padX = w;
+ win->padY = h;
+ } else {
+ win->padX = 0;
+ win->padY = 0;
+ win->w = w;
+ win->h = h;
+ }
+ win->style = style;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = win->w + win->padX;
+ rect.bottom = win->h + win->padY;
+ AdjustWindowRect( &rect, win->style, (win->option&F_MENUBAR)?1:0 );
+ rect.bottom += mFixBorderH;
+ win->hWnd = CreateWindow( className, labelStr, style,
+ xx, yy,
+ rect.right-rect.left, rect.bottom-rect.top,
+ hWnd, NULL,
+ mswHInst, NULL );
+ if (win->hWnd == (HWND)0) {
+ mswFail( "CreateWindow(POPUP)" );
+ } else {
+ SetWindowWord( win->hWnd, 0, (WORD)index );
+ }
+ win->baseStyle = WS_GROUP;
+ win->focusChainFirst = win->focusChainLast = win->focusChainNext = NULL;
+ if (winFirst == NULL) {
+ winFirst = winLast = win;
+ } else {
+ winLast->next = (wControl_p)win;
+ winLast = win;
+ }
+#ifdef HELPSTR
+ if (helpStrF)
+ fprintf( helpStrF, "WINDOW - %s\n", labelStr );
+#endif
+ win->nameStr = mswStrdup( nameStr );
+ if (typ == W_MAIN)
+ mswInitColorPalette();
+#ifdef LATER
+ hDc = GetDC( win->hWnd );
+ oldHPal = SelectPalette( hDc, mswPalette, 0 );
+ ReleaseDC( win->hWnd, hDc );
+#endif
+ return win;
+}
+
+void wInitAppName(char *_appName)
+{
+ appName = (char *)malloc( strlen(_appName) + 1 );
+ strcpy(appName, _appName);
+}
+
+
+/**
+ * Initialize the application's main window. This function does the necessary initialization
+ * of the application including creation of the main window.
+ *
+ * \param name IN internal name of the application. Used for filenames etc.
+ * \param x IN size
+ * \param y IN size
+ * \param helpStr IN ??
+ * \param labelStr IN window title
+ * \param nameStr IN ??
+ * \param option IN options for window creation
+ * \param winProc IN pointer to main window procedure
+ * \param data IN ??
+ * \return window handle or NULL on error
+ */
+
+wWin_p wWinMainCreate(
+ const char * name,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ const char * nameStr,
+ long option,
+ wWinCallBack_p winProc,
+ void * data )
+{
+ wWin_p w;
+ RECT rect;
+ const char * appDir;
+ const char * libDir;
+ int showCmd;
+ int error;
+ HDC hDc;
+ TEXTMETRIC tm;
+ char *pos;
+ char * configName;
+
+ /* check for configuration name */
+ if( pos = strchr( name, ';' )) {
+ /* if found, split application name and configuration name */
+ configName = (char *)malloc( strlen( name ) + 1 );
+ strcpy( configName, pos + 1 );
+ } else {
+ /* if not found, application name and configuration name are same */
+ configName = (char*)malloc( strlen(name)+1 );
+ strcpy( configName, name );
+ }
+
+ appDir = wGetAppWorkDir();
+ if ( appDir == NULL ) {
+ free( configName );
+ return NULL;
+ }
+ mswProfileFile = (char*)malloc( strlen(appDir)+1+strlen(configName)+1+3+1 );
+ wsprintf( mswProfileFile, "%s\\%s.ini", appDir, configName );
+ free( configName );
+
+ error = WritePrivateProfileString( "mswtest", "test", "ok", mswProfileFile );
+ if ( error <= 0 ) {
+ sprintf( mswTmpBuff, "Can not write to %s.\nPlease make sure the directory exists and is writable", mswProfileFile );
+ wNoticeEx( NT_ERROR, mswTmpBuff, "Ok", NULL );
+ return NULL;
+ }
+ libDir = wGetAppLibDir();
+ /* length of path + \ + length of filename + . + length of extension + \0 */
+ helpFile = (char*)malloc( strlen(libDir) + 1 + strlen(appName) + 1 + 3 + 1 );
+ wsprintf( helpFile, "%s\\%s.chm", libDir, appName );
+
+ wPrefGetInteger( "msw tweak", "ThickFont", &mswThickFont, 0 );
+
+ showCmd = SW_SHOW;
+ w = winCommonCreate( NULL, W_MAIN, option|F_RESIZE, "MswMainWindow",
+ WS_OVERLAPPEDWINDOW, labelStr, winProc, x, y, data,
+ nameStr, &showCmd );
+ mswHWnd = w->hWnd;
+ if ( !mswThickFont ) {
+ DWORD dw;
+ SendMessage( w->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ hDc = GetDC( w->hWnd );
+ GetTextMetrics( hDc, &tm );
+ mswEditHeight = tm.tmHeight+2;
+ dw = GetTextExtent( hDc, "AXqypj", 6 );
+ mswEditHeight = HIWORD(dw)+2;
+ ReleaseDC( w->hWnd, hDc );
+ }
+ ShowWindow( w->hWnd, showCmd );
+ UpdateWindow( w->hWnd );
+ GetWindowRect( w->hWnd, &rect );
+ GetClientRect( w->hWnd, &rect );
+ w->busy = FALSE;
+
+
+ return w;
+}
+
+wWin_p wWinPopupCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ const char * nameStr,
+ long option,
+ wWinCallBack_p winProc,
+ void * data )
+{
+ wWin_p w;
+ DWORD style;
+ HMENU sysMenu;
+ int showCmd;
+ static DWORD overlapped = WS_OVERLAPPED;
+ static DWORD popup = WS_POPUP;
+
+ style = popup;
+ style |= WS_BORDER | WS_CAPTION | WS_SYSMENU;
+ w = winCommonCreate( parent?parent->hWnd:mswHWnd, W_POPUP, option,
+ "MswPopUpWindow",
+ style, labelStr, winProc, x, y, data, nameStr, &showCmd );
+
+ w->helpStr = mswStrdup( helpStr );
+
+ sysMenu = GetSystemMenu( w->hWnd, FALSE );
+ if (sysMenu) {
+ DeleteMenu( sysMenu, SC_RESTORE, MF_BYCOMMAND );
+ /*DeleteMenu( sysMenu, SC_MOVE, MF_BYCOMMAND );*/
+ /*DeleteMenu( sysMenu, SC_SIZE, MF_BYCOMMAND );*/
+ DeleteMenu( sysMenu, SC_MINIMIZE, MF_BYCOMMAND );
+ DeleteMenu( sysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
+ DeleteMenu( sysMenu, SC_TASKLIST, MF_BYCOMMAND );
+ DeleteMenu( sysMenu, 4, MF_BYPOSITION );
+ }
+ w->busy = FALSE;
+ return w;
+}
+
+void wWinSetBigIcon(
+ wWin_p win,
+ wIcon_p bm )
+{
+#ifdef OWNERICON
+ win->wicon_w = bm->w;
+ win->wicon_h = bm->h;
+ win->wicon_bm = mswCreateBitMap(
+ GetSysColor(COLOR_BTNTEXT), RGB( 255, 255, 255 ), RGB( 255, 255, 255 ),
+ bm->w, bm->h, bm->bits );
+#endif
+}
+
+
+void wWinSetSmallIcon(
+ wWin_p win,
+ wIcon_p bm )
+{
+#ifdef OWNERICON
+ win->wicon_w = bm->w;
+ win->wicon_h = bm->h;
+ win->wicon_bm = mswCreateBitMap(
+ GetSysColor(COLOR_BTNTEXT), RGB( 255, 255, 255 ), RGB( 255, 255, 255 ),
+ bm->w, bm->h, bm->bits );
+#endif
+}
+
+
+void wWinTop(
+ wWin_p win )
+{
+ /*BringWindowToTop( win->hWnd );*/
+ SetWindowPos( win->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
+ SetFocus( win->hWnd );
+}
+
+
+DWORD mswGetBaseStyle( wWin_p win )
+{
+ DWORD style;
+ style = win->baseStyle;
+ win->baseStyle = 0;
+ return style;
+}
+
+
+static wAccelKey_e translateExtKey( UINT wParam )
+{
+ wAccelKey_e extChar;
+ extChar = wAccelKey_None;
+ switch( wParam ) {
+ case VK_DELETE: extChar = wAccelKey_Del; break;
+ case VK_INSERT: extChar = wAccelKey_Ins; break;
+ case VK_HOME: extChar = wAccelKey_Home; break;
+ case VK_END: extChar = wAccelKey_End; break;
+ case VK_PRIOR: extChar = wAccelKey_Pgup; break;
+ case VK_NEXT: extChar = wAccelKey_Pgdn; break;
+ case VK_UP: extChar = wAccelKey_Up; break;
+ case VK_DOWN: extChar = wAccelKey_Down; break;
+ case VK_RIGHT: extChar = wAccelKey_Right; break;
+ case VK_LEFT: extChar = wAccelKey_Left; break;
+ case VK_BACK: extChar = wAccelKey_Back; break;
+ /*case VK_F1: extChar = wAccelKey_F1; break;*/
+ case VK_F2: extChar = wAccelKey_F2; break;
+ case VK_F3: extChar = wAccelKey_F3; break;
+ case VK_F4: extChar = wAccelKey_F4; break;
+ case VK_F5: extChar = wAccelKey_F5; break;
+ case VK_F6: extChar = wAccelKey_F6; break;
+ case VK_F7: extChar = wAccelKey_F7; break;
+ case VK_F8: extChar = wAccelKey_F8; break;
+ case VK_F9: extChar = wAccelKey_F9; break;
+ case VK_F10: extChar = wAccelKey_F10; break;
+ case VK_F11: extChar = wAccelKey_F11; break;
+ case VK_F12: extChar = wAccelKey_F12; break;
+ }
+ return extChar;
+}
+
+
+long notModKey;
+int mswTranslateAccelerator(
+ HWND hWnd,
+ LPMSG pMsg )
+{
+ long acclKey;
+ long state;
+ wWin_p win;
+ wControl_p b;
+
+ if ( pMsg->message != WM_KEYDOWN )
+ return FALSE;
+ acclKey = pMsg->wParam;
+ b = getControlFromCursor( pMsg->hwnd, &win );
+ if ( win == NULL )
+ return 0;
+ if ( b != NULL ) {
+ switch (b->type) {
+ case B_STRING:
+ case B_INTEGER:
+ case B_FLOAT:
+ case B_LIST:
+ case B_DROPLIST:
+ case B_COMBOLIST:
+ case B_TEXT:
+ return 0;
+ }
+ }
+ if ( acclKey == (long)VK_F1 ) {
+ closeBalloonHelp();
+ if (!b && win) {
+ wHelp( win->helpStr );
+ } else {
+ if (b->helpStr)
+ wHelp( b->helpStr );
+ else if (b->parent)
+ wHelp( b->parent->nameStr );
+ }
+ return 1;
+ }
+ /*acclKey = translateExtKey( (WORD)acclKey );*/
+ state = 0;
+ if ( GetKeyState(VK_CONTROL) & 0x1000 )
+ state |= WKEY_CTRL;
+ if ( GetKeyState(VK_MENU) & 0x1000 )
+ state |= WKEY_ALT;
+ if ( GetKeyState(VK_SHIFT) & 0x1000 )
+ state |= WKEY_SHIFT;
+ state <<= 8;
+ acclKey |= state;
+ if (pMsg->wParam > 0x12)
+ notModKey = TRUE;
+ return mswMenuAccelerator( win, acclKey );
+}
+
+/*
+ ******************************************************************************
+ *
+ * Window Utilities
+ *
+ ******************************************************************************
+ */
+
+
+
+void wGetDisplaySize( POS_T * width, POS_T * height )
+{
+ *width = screenWidth;
+ *height = screenHeight;
+}
+
+
+void wWinGetSize( wWin_p w, POS_T * width, POS_T * height )
+{
+ RECT rect;
+ GetWindowRect( w->hWnd, &rect );
+ GetClientRect( w->hWnd, &rect );
+ w->w = rect.right - rect.left;
+ w->h = rect.bottom - rect.top;
+ *width = w->w;
+ *height = w->h;
+}
+
+
+void wWinSetSize( wWin_p w, POS_T width, POS_T height )
+{
+ RECT rect;
+ w->w = width;
+ w->h = height;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = w->w /*+w->padX*/;
+ rect.bottom = w->h /*+w->padY*/;
+ AdjustWindowRect( &rect, w->style, (w->option&F_MENUBAR)?1:0 );
+ rect.bottom += mFixBorderH;
+ if (!SetWindowPos( w->hWnd, HWND_TOP, CW_USEDEFAULT, CW_USEDEFAULT,
+ rect.right-rect.left, rect.bottom-rect.top,
+ SWP_NOMOVE|SWP_NOZORDER))
+ mswFail("wWinSetSize");
+ InvalidateRect( w->hWnd, NULL, TRUE );
+}
+
+
+static int blocking;
+static void blockingLoop( void )
+{
+ MSG msg;
+ int myBlocking=blocking;
+ while (blocking>=myBlocking && GetMessage( &msg, NULL, 0, 0 )) {
+ if (
+#ifdef DOTRANSACCEL
+ (!TranslateAccelerator( mswWin->hWnd, hMswAccel, &msg )) &&
+#endif
+ (!mswTranslateAccelerator( mswWin->hWnd, &msg )) ) {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+}
+
+
+static void savePos( wWin_p win )
+{
+ char posStr[20];
+ WINDOWPLACEMENT windowPlace;
+ wPos_t w, h;
+ RECT rect;
+
+ if ( win->nameStr &&
+ IsWindowVisible( win->hWnd) /*&& !IsIconic( win->hWnd )*/ ) {
+ windowPlace.length = sizeof windowPlace;
+ GetWindowPlacement( win->hWnd, &windowPlace );
+ if (win->option&F_RECALLPOS) {
+ wsprintf( posStr, "%d %d",
+ windowPlace.rcNormalPosition.left,
+ windowPlace.rcNormalPosition.top );
+ wPrefSetString( "msw window pos", win->nameStr, posStr );
+ if (win->option&F_RESIZE) {
+ GetClientRect( win->hWnd, &rect );
+ w = rect.right - rect.left;
+ h = rect.bottom - rect.top;
+ w = windowPlace.rcNormalPosition.right - windowPlace.rcNormalPosition.left;
+ h = windowPlace.rcNormalPosition.bottom - windowPlace.rcNormalPosition.top;
+ w -= mResizeBorderW*2;
+ h -= mResizeBorderH*2 + mTitleH;
+ if (win->option&F_MENUBAR)
+ h -= mMenuH;
+ wsprintf( posStr, "%d %d %d",
+ ( windowPlace.showCmd == SW_SHOWMINIMIZED ? 1 :
+ (windowPlace.showCmd == SW_SHOWMAXIMIZED ? 2 : 0 ) ),
+ w, h );
+ wPrefSetString( "msw window size", win->nameStr, posStr );
+ }
+ }
+ }
+}
+
+
+void wWinShow(
+ wWin_p win,
+ BOOL_T show )
+{
+ wPos_t x, y;
+ wWin_p win1;
+
+ win->busy = TRUE;
+ if (show) {
+ if (win->centerWin) {
+ x = (screenWidth-win->w)/2;
+ y = (screenHeight-win->h)/2;
+ if (x<0)
+ y = 0;
+ if (x<0)
+ y = 0;
+ if (!SetWindowPos( win->hWnd, HWND_TOP, x, y,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER))
+ mswFail( "wWinShow:SetWindowPos()" );
+ }
+ win->centerWin = FALSE;
+ win->shown = TRUE;
+ if (mswHWnd == (HWND)0 || !IsIconic(mswHWnd) ) {
+ ShowWindow( win->hWnd, SW_SHOW );
+ if (win->focusChainFirst) {
+ SetFocus( win->focusChainFirst->hWnd );
+ }
+ win->pendingShow = FALSE;
+ if ( mswWinBlockEnabled && (win->option & F_BLOCK) ) {
+ blocking++;
+ inMainWndProc = FALSE;
+ for ( win1 = winFirst; win1; win1=(wWin_p)win1->next ) {
+ if ( win1->shown && win1 != win ) {
+ if (win1->modalLevel == 0 )
+ EnableWindow( win1->hWnd, FALSE );
+ win1->modalLevel++;
+ }
+ }
+ win->busy = FALSE;
+ blockingLoop();
+ }
+ } else {
+ win->pendingShow = TRUE;
+ needToDoPendingShow = TRUE;
+ }
+ } else {
+ savePos( win );
+ ShowWindow( win->hWnd, SW_HIDE );
+ /*SetWindowPos( win->hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW );*/
+ if ( mswWinBlockEnabled && (win->option & F_BLOCK) ) {
+ blocking--;
+ for ( win1 = winFirst; win1; win1=(wWin_p)win1->next ) {
+ if ( win1->shown && win1 != win ) {
+ if ( win1->modalLevel > 0 )
+ win1->modalLevel--;
+ if (win1->modalLevel == 0 )
+ EnableWindow( win1->hWnd, TRUE );
+ }
+ }
+ }
+ savePos( win );
+ win->pendingShow = FALSE;
+ win->shown = FALSE;
+ }
+ win->busy = FALSE;
+}
+
+
+void wWinBlockEnable(
+ wBool_t enabled )
+{
+ mswWinBlockEnabled = enabled;
+}
+
+
+wBool_t wWinIsVisible(
+ wWin_p w )
+{
+ return IsWindowVisible(w->hWnd);
+}
+
+
+void wWinSetTitle(
+ wWin_p w,
+ const char * title )
+{
+ SetWindowText( w->hWnd, title );
+}
+
+
+void wWinSetBusy(
+ wWin_p w,
+ BOOL_T busy )
+{
+ HMENU menuH;
+ UINT uEnable;
+ int cnt, inx;
+ wControl_p b;
+
+ w->isBusy = busy;
+ menuH = GetMenu( w->hWnd );
+ if (menuH) {
+ uEnable = MF_BYPOSITION|(busy?MF_DISABLED:MF_ENABLED);
+ cnt = GetMenuItemCount(menuH);
+ for (inx=0; inx<cnt; inx++)
+ EnableMenuItem( menuH, inx, uEnable );
+ }
+ for (b=w->first; b; b=b->next) {
+ if ( (b->option&BO_DISABLED)==0) {
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->setBusyProc) {
+ mswCallBacks[b->type]->setBusyProc( b, busy );
+ } else {
+ if (b->hWnd)
+ EnableWindow( b->hWnd, (BOOL)!busy );
+ }
+ }
+ }
+}
+
+
+const char * wWinGetTitle(
+ wWin_p w )
+{
+ return w->labelStr;
+}
+
+
+void wWinClear(
+ wWin_p win,
+ wPos_t x,
+ wPos_t y,
+ wPos_t width,
+ wPos_t height )
+{
+}
+
+void wSetCursor(
+ wCursor_t cursor )
+{
+ switch ( cursor ) {
+ case wCursorNormal:
+ case wCursorQuestion:
+ default:
+ SetCursor( LoadCursor( NULL, IDC_ARROW ) );
+ break;
+ case wCursorWait:
+ SetCursor( LoadCursor( NULL, IDC_WAIT ) );
+ break;
+ case wCursorCross:
+ SetCursor( LoadCursor( NULL, IDC_CROSS ) );
+ break;
+ case wCursorIBeam:
+ SetCursor( LoadCursor( NULL, IDC_IBEAM ) );
+ break;
+ }
+ curCursor = cursor;
+}
+
+void wWinDoCancel( wWin_p win )
+{
+ wControl_p b;
+ for (b=win->first; b; b=b->next) {
+ if ((b->type == B_BUTTON) && (b->option & BB_CANCEL) ) {
+ mswButtPush( b );
+ }
+ }
+}
+
+unsigned long wGetTimer( void )
+{
+ return (unsigned long)GetTickCount();
+}
+
+
+/*
+ ******************************************************************************
+ *
+ * Control Utilities
+ *
+ ******************************************************************************
+ */
+
+
+
+void wControlSetHelp(
+ wControl_p b,
+ const char * help )
+{
+ if (b->helpStr)
+ free(CAST_AWAY_CONST b->helpStr);
+ if (help)
+ b->helpStr = mswStrdup( help );
+ else
+ b->helpStr = NULL;
+}
+
+
+/**
+ * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by
+ * calling wControlLinkedActive for one member of the list
+ *
+ * \param IN first control
+ * \param IN second control
+ * \return none
+ */
+
+void wControlLinkedSet( wControl_p b1, wControl_p b2 )
+{
+ b2->synonym = b1->synonym;
+ if( b2->synonym == NULL )
+ b2->synonym = b1;
+
+ b1->synonym = b2;
+}
+
+/**
+ * Activate/deactivate a group of synonymous controls.
+ *
+ * \param IN control
+ * \param IN state
+ * \return none
+ */
+
+void wControlLinkedActive( wControl_p b, int active )
+{
+ wControl_p savePtr = b;
+
+ if( savePtr->type == B_MENUITEM )
+ wMenuPushEnable( (wMenuPush_p)savePtr, active );
+ else
+ wControlActive( savePtr, active );
+
+ savePtr = savePtr->synonym;
+
+ while( savePtr && savePtr != b ) {
+
+ if( savePtr->type == B_MENUITEM )
+ wMenuPushEnable( (wMenuPush_p)savePtr, active );
+ else
+ wControlActive( savePtr, active );
+
+ savePtr = savePtr->synonym;
+ }
+}
+
+void wControlShow( wControl_p b, BOOL_T show )
+{
+ RECT rc;
+ if (show) {
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->repaintProc)
+ mswCallBacks[b->type]->repaintProc( b->parent->hWnd, b );
+ } else {
+ if( b->labelStr ) {
+ rc.left = b->labelX;
+ rc.right = b->x;
+ rc.top = b->labelY;
+ rc.bottom = b->labelY+b->h;
+ InvalidateRect( ((wControl_p)b->parent)->hWnd, &rc, TRUE );
+ }
+ }
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->showProc) {
+ mswCallBacks[b->type]->showProc( b, show );
+ } else {
+ ShowWindow( b->hWnd, show?SW_SHOW:SW_HIDE );
+#ifdef SHOW_DOES_SETFOCUS
+ if (show && (b->option&BO_READONLY)==0 && b->hWnd != GetFocus() ) {
+ hWnd = SetFocus( b->hWnd );
+ }
+#endif
+ }
+ b->shown = show;
+}
+
+
+void wControlSetFocus(
+ wControl_p b )
+{
+ if ( b->hWnd )
+ SetFocus( b->hWnd );
+}
+
+
+void wControlActive(
+ wControl_p b,
+ int active )
+{
+ if (active)
+ b->option &= ~BO_DISABLED;
+ else
+ b->option |= BO_DISABLED;
+ if (b->parent->isBusy)
+ return;
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->setBusyProc) {
+ mswCallBacks[b->type]->setBusyProc( b, !active );
+ } else {
+ EnableWindow( b->hWnd, (BOOL)active );
+ InvalidateRect( b->hWnd, NULL, TRUE );
+ }
+}
+
+
+const char * wControlGetHelp( wControl_p b )
+{
+ return b->helpStr;
+}
+
+
+wPos_t wLabelWidth( const char * labelStr )
+{
+ int lab_l;
+ HDC hDc;
+ DWORD dw;
+ LABELFONTDECL
+
+ hDc = GetDC( mswHWnd );
+ lab_l = strlen(labelStr);
+ LABELFONTSELECT
+ dw = GetTextExtent( hDc, CAST_AWAY_CONST labelStr, lab_l );
+ LABELFONTRESET
+ ReleaseDC( mswHWnd, hDc );
+ return LOWORD(dw) + 5;
+}
+
+
+wPos_t wControlGetWidth(
+ wControl_p b) /* Control */
+{
+ return b->w;
+}
+
+
+wPos_t wControlGetHeight(
+ wControl_p b) /* Control */
+{
+ return b->h;
+}
+
+
+wPos_t wControlGetPosX(
+ wControl_p b) /* Control */
+{
+ return b->x;
+}
+
+
+wPos_t wControlGetPosY(
+ wControl_p b) /* Control */
+{
+ return b->y;
+}
+
+
+void wControlSetPos(
+ wControl_p b,
+ wPos_t x,
+ wPos_t y )
+{
+ b->labelX = x;
+ b->labelY = y+2;
+
+ if (b->labelStr) {
+ int lab_l;
+ HDC hDc;
+ DWORD dw;
+ LABELFONTDECL
+
+ hDc = GetDC( b->parent->hWnd );
+ LABELFONTSELECT
+ lab_l = strlen(b->labelStr);
+ dw = GetTextExtent( hDc, CAST_AWAY_CONST b->labelStr, lab_l );
+ b->labelX -= LOWORD(dw) + 5;
+ LABELFONTRESET
+ ReleaseDC( b->parent->hWnd, hDc );
+ }
+
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->setPosProc) {
+ mswCallBacks[b->type]->setPosProc( b, x, y );
+ } else {
+ b->x = x;
+ b->y = y;
+ if (b->hWnd)
+ if (!SetWindowPos( b->hWnd, HWND_TOP, x, y,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ SWP_NOSIZE|SWP_NOZORDER))
+ mswFail("wControlSetPos");
+ }
+}
+
+
+void wControlSetLabel(
+ wControl_p b,
+ const char * labelStr )
+{
+ if ( b->type == B_RADIO || b->type == B_TOGGLE ) {
+ ;
+ } else {
+ int lab_l;
+ HDC hDc;
+ DWORD dw;
+ LABELFONTDECL
+
+ hDc = GetDC( b->parent->hWnd );
+ lab_l = strlen(labelStr);
+ LABELFONTSELECT
+ dw = GetTextExtent( hDc, CAST_AWAY_CONST labelStr, lab_l );
+ LABELFONTRESET
+ b->labelX = b->x - LOWORD(dw) - 5;
+ ReleaseDC( b->parent->hWnd, hDc );
+ b->labelStr = mswStrdup( labelStr );
+ if (b->type == B_BUTTON)
+ SetWindowText( b->hWnd, labelStr );
+ }
+}
+
+
+void wControlSetContext(
+ wControl_p b,
+ void * context )
+{
+ b->data = context;
+}
+
+static int controlHiliteWidth = 5;
+static int controlHiliteWidth2 = 3;
+void wControlHilite(
+ wControl_p b,
+ wBool_t hilite )
+{
+ HDC hDc;
+ HPEN oldPen, newPen;
+ int oldMode;
+
+ if ( b == NULL ) return;
+ if ( !IsWindowVisible(b->parent->hWnd) ) return;
+ if ( !IsWindowVisible(b->hWnd) ) return;
+ hDc = GetDC( b->parent->hWnd );
+ newPen = CreatePen( PS_SOLID, controlHiliteWidth, RGB(0,0,0) );
+ oldPen = SelectObject( hDc, newPen );
+ oldMode = SetROP2( hDc, R2_NOTXORPEN );
+ MoveTo( hDc, b->x-controlHiliteWidth2, b->y-controlHiliteWidth2 );
+ LineTo( hDc, b->x+b->w+controlHiliteWidth2, b->y-controlHiliteWidth2 );
+ LineTo( hDc, b->x+b->w+controlHiliteWidth2, b->y+b->h+controlHiliteWidth2 );
+ LineTo( hDc, b->x-controlHiliteWidth2, b->y+b->h+controlHiliteWidth2 );
+ LineTo( hDc, b->x-controlHiliteWidth2, b->y-controlHiliteWidth2 );
+ SetROP2( hDc, oldMode );
+ SelectObject( hDc, oldPen );
+ DeleteObject( newPen );
+ ReleaseDC( b->parent->hWnd, hDc );
+}
+
+/*
+ *****************************************************************************
+ *
+ * Exported Utility Functions
+ *
+ *****************************************************************************
+ */
+
+
+void wMessage(
+ wWin_p w,
+ const char * msg,
+ int beep )
+{
+ HDC hDc;
+ int oldRop;
+ POS_T h;
+ RECT rect;
+ LABELFONTDECL
+
+ if (beep)
+ MessageBeep(0);
+ GetClientRect( w->hWnd, &rect );
+ hDc = GetDC( w->hWnd );
+ oldRop = SetROP2( hDc, R2_WHITE );
+ h = w->h+2;
+ Rectangle( hDc, 0, h, w->w, h );
+ SetROP2( hDc, oldRop );
+ LABELFONTSELECT
+ TextOut( hDc, 0, h, msg, strlen(msg) );
+ LABELFONTRESET
+ ReleaseDC( w->hWnd, hDc );
+}
+
+
+void wExit( int rc )
+{
+ INDEX_T inx;
+ wControl_p b;
+
+ mswPutCustomColors();
+ wPrefFlush();
+ for ( inx=controlMap_da.cnt-1; inx>=0; inx-- ) {
+ b = controlMap(inx).b;
+ if (b != NULL) {
+ if (b->type == W_MAIN || b->type == W_POPUP) {
+ wWin_p w = (wWin_p)b;
+ savePos( w );
+ if (w->winProc != NULL)
+ w->winProc( w, wQuit_e, w->data );
+ }
+ }
+ }
+ for ( inx=controlMap_da.cnt-1; inx>=0; inx-- ) {
+ b = controlMap(inx).b;
+ if (b != NULL) {
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->doneProc != NULL)
+ mswCallBacks[b->type]->doneProc( b );
+ }
+ controlMap(inx).b = NULL;
+ }
+ deleteBitmaps();
+ if (mswOldTextFont != (HFONT)0)
+ DeleteObject( mswOldTextFont );
+ if (helpInitted) {
+ WinHelp(mswHWnd, helpFile, HELP_QUIT, 0L );
+ helpInitted = FALSE;
+ }
+ if (balloonHelpHWnd) {
+ HDC hDc;
+ hDc = GetDC( balloonHelpHWnd );
+ SelectObject( hDc, balloonHelpOldFont );
+ DeleteObject( balloonHelpNewFont );
+ ReleaseDC( balloonHelpHWnd, hDc );
+ }
+#ifdef HELPSTR
+ fclose( helpStrF );
+#endif
+ DestroyWindow( mswHWnd );
+ if (mswPalette) {
+ DeleteObject( mswPalette );
+ /*DeleteObject( mswPrintPalette );*/
+ }
+}
+
+
+void wFlush(
+ void )
+{
+ wWin_p win;
+
+ inMainWndProc = FALSE;
+ mswRepaintAll();
+ for (win=winFirst; win; win=(wWin_p)win->next)
+ UpdateWindow( win->hWnd );
+}
+
+void wUpdate(
+ wWin_p win )
+{
+ UpdateWindow( win->hWnd );
+}
+
+static wBool_t paused;
+static wAlarmCallBack_p alarmFunc;
+static setTriggerCallback_p triggerFunc;
+static wControl_p triggerControl;
+
+/**
+ * Wait until the pause timer expires. During that time, the message loop is
+ * handled and queued messages are processed
+ */
+
+static void pausedLoop( void )
+{
+ MSG msg;
+ while (paused && GetMessage( &msg, NULL, 0, 0 )) {
+ if ( (mswWin) && (!mswTranslateAccelerator( mswWin->hWnd, &msg )) ) {
+ TranslateMessage( &msg );
+ }
+ DispatchMessage( &msg );
+ }
+}
+
+/**
+ * Timer callback function for the pause timer. The only purpose of this
+ * timer proc is to clear the waiting flag and kill the timer itself.
+ */
+void CALLBACK TimerProc( HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
+{
+ if (idEvent == PAUSE_TIMER) {
+ paused = FALSE;
+ KillTimer( hWnd, PAUSE_TIMER );
+ }
+}
+
+/**
+ * Pause the application for a specified time.
+ */
+
+void wPause( long msec )
+{
+ paused = TRUE;
+ if (msec > 65000L)
+ msec = 65000L;
+ pauseTimer = SetTimer( mswHWnd, PAUSE_TIMER, (UINT)msec, TimerProc );
+ if (pauseTimer == 0)
+ mswFail("wPause: No timers");
+ else
+ pausedLoop();
+}
+
+
+void wAlarm(
+ long msec,
+ wAlarmCallBack_p func )
+{
+ alarmFunc = func;
+ if (msec > 65000L)
+ msec = 65000L;
+ alarmTimer = SetTimer( mswHWnd, ALARM_TIMER, (UINT)msec, NULL );
+ if (alarmTimer == 0)
+ mswFail("wAlarm: No timers");
+}
+
+
+void mswSetTrigger(
+ wControl_p control,
+ setTriggerCallback_p func )
+{
+ UINT msec = (UINT)500;
+ triggerControl = control;
+ triggerFunc = func;
+ if (func == NULL && triggerTimer != 0) {
+ KillTimer( mswHWnd, triggerTimer );
+ triggerTimer = 0;
+ return;
+ }
+ if (msec > 65000L)
+ msec = 65000L;
+ triggerTimer = SetTimer( mswHWnd, TRIGGER_TIMER, (UINT)msec, NULL );
+ if (triggerTimer == 0)
+ mswFail("wAlarm: No timers");
+}
+
+
+void wBeep( void )
+{
+ MessageBeep( MB_OK );
+}
+
+/**
+ * Show a notification window with a yes/no reply and an icon.
+ *
+ * \param type IN type of message: Information, Warning, Error
+ * \param msg IN message to display
+ * \param yes IN text for accept button
+ * \param no IN text for cancel button
+ * \return True when accept was selected, false otherwise
+ */
+
+int wNoticeEx(
+ int type,
+ const char * msg,
+ const char * yes,
+ const char * no )
+{
+ int res;
+ UINT flag;
+ char *headline;
+
+ switch( type ) {
+ case NT_INFORMATION:
+ flag = MB_ICONINFORMATION;
+ headline = _("Information");
+ break;
+ case NT_WARNING:
+ flag = MB_ICONWARNING;
+ headline = _("Warning");
+ break;
+ case NT_ERROR:
+ flag = MB_ICONERROR;
+ headline = _("Error");
+ break;
+ }
+ res = MessageBox( mswHWnd, msg, headline, flag | MB_TASKMODAL|((no==NULL)?MB_OK:MB_YESNO) );
+ return res == IDOK || res == IDYES;
+}
+
+int wNotice(
+ const char * msg,
+ const char * yes,
+ const char * no )
+{
+ int res;
+ res = MessageBox( mswHWnd, msg, "Notice", MB_TASKMODAL|((no==NULL)?MB_OK:MB_YESNO) );
+ return res == IDOK || res == IDYES;
+}
+
+/**
+ * Show a notification window with three choices and an icon.
+ *
+ * \param msg IN message to display
+ * \param yes IN text for yes button
+ * \param no IN text for no button
+ * \param cancel IN text for cancel button
+ * \return 1 for yes, -1 for no, 0 for cancel
+ */
+
+
+int wNotice3(
+ const char * msg,
+ const char * yes,
+ const char * no,
+ const char * cancel )
+{
+ int res;
+ res = MessageBox( mswHWnd, msg, _("Warning"), MB_ICONWARNING | MB_TASKMODAL|MB_YESNOCANCEL );
+ if ( res == IDOK || res == IDYES )
+ return 1;
+ else if ( res == IDNO )
+ return -1;
+ else
+ return 0;
+}
+
+
+void wHelp(
+ const char * topic )
+{
+ char *pszHelpTopic;
+ HWND hwndHelp;
+
+ if (!helpInitted) {
+ HtmlHelp( NULL, NULL, HH_INITIALIZE, (DWORD)&dwCookie) ;
+ helpInitted = TRUE;
+ }
+/* "c:\\help.chm::/intro.htm>mainwin", */
+ /* attention: always adapt constant value (10) to needed number of formatting characters */
+ pszHelpTopic = malloc( strlen( helpFile ) + strlen( topic ) + 10 );
+ assert( pszHelpTopic != NULL );
+
+ sprintf( pszHelpTopic, "/%s.html", topic );
+ hwndHelp = HtmlHelp(mswHWnd, helpFile, HH_DISPLAY_TOPIC, (DWORD_PTR)pszHelpTopic);
+ if( !hwndHelp )
+ wNoticeEx( NT_ERROR, pszHelpTopic, "Ok", NULL );
+
+ free( pszHelpTopic );
+}
+
+
+void doHelpMenu( void * context )
+{
+ HH_FTS_QUERY ftsQuery;
+
+ if( !helpInitted ) {
+ HtmlHelp( NULL, NULL, HH_INITIALIZE, (DWORD)&dwCookie) ;
+ helpInitted = TRUE;
+ }
+
+ switch ((int)(long)context) {
+ case 1: /* Contents */
+ HtmlHelp( mswHWnd, helpFile, HH_DISPLAY_TOC, (DWORD_PTR)NULL );
+ break;
+ case 2: /* Search */
+ ftsQuery.cbStruct = sizeof( ftsQuery );
+ ftsQuery.fExecute = FALSE;
+ ftsQuery.fStemmedSearch = FALSE;
+ ftsQuery.fTitleOnly = FALSE;
+ ftsQuery.pszSearchQuery = NULL;
+ ftsQuery.pszWindow = NULL;
+
+ HtmlHelp( mswHWnd, helpFile, HH_DISPLAY_SEARCH,(DWORD)&ftsQuery );
+ break;
+ default:
+ return;
+ }
+ helpInitted = TRUE;
+}
+
+void wMenuAddHelp(
+ wMenu_p m )
+{
+ wMenuPushCreate( m, NULL, "&Contents", 0, doHelpMenu, (void*)1 );
+ wMenuPushCreate( m, NULL, "&Search for Help on...", 0, doHelpMenu, (void*)2 );
+}
+
+
+void wSetBalloonHelp( wBalloonHelp_t * bh )
+{
+ balloonHelpStrings = bh;
+}
+
+
+void wEnableBalloonHelp( int enable )
+{
+ balloonHelpEnable = enable;
+}
+
+
+void wBalloonHelpUpdate ( void )
+{
+}
+
+
+void wControlSetBalloonText( wControl_p b, const char * text )
+{
+ b->tipStr = mswStrdup( text );
+}
+
+
+void startBalloonHelp( void )
+{
+ HDC hDc;
+ DWORD extent;
+ int w, h;
+ RECT rect;
+ POINT pt;
+ wBalloonHelp_t * bh;
+ const char * hs;
+ HFONT hFont;
+
+ if (!balloonHelpStrings)
+ return;
+ if (!balloonHelpEnable)
+ return;
+ if (balloonHelpHWnd) {
+ if ( balloonHelpButton->tipStr ) {
+ hs = balloonHelpButton->tipStr;
+ } else {
+ hs = balloonHelpButton->helpStr;
+ if (!hs)
+ return;
+ for ( bh = balloonHelpStrings; bh->name && strcmp(bh->name,hs) != 0; bh++ );
+ if (!bh->name || !bh->value)
+ return;
+ balloonHelpButton->tipStr = hs = bh->value;
+ }
+if (newHelp) {
+ wControlSetBalloon( balloonHelpButton, 0, 0, hs );
+} else {
+ hDc = GetDC( balloonHelpHWnd );
+ hFont = SelectObject( hDc, mswLabelFont );
+ extent = GetTextExtent( hDc, CAST_AWAY_CONST hs, strlen(hs) );
+ w = LOWORD( extent );
+ h = HIWORD( extent );
+ pt.x = 0;
+ if ( balloonHelpButton->type == B_RADIO ||
+ balloonHelpButton->type == B_TOGGLE ) {
+ pt.y = balloonHelpButton->h;
+ } else {
+ GetClientRect( balloonHelpButton->hWnd, &rect );
+ pt.y = rect.bottom;
+ }
+ ClientToScreen( balloonHelpButton->hWnd, &pt );
+ if (pt.x + w+2 > screenWidth)
+ pt.x = screenWidth-(w+2);
+ if (pt.x < 0)
+ pt.x = 0;
+ SetWindowPos( balloonHelpHWnd, HWND_TOPMOST, pt.x, pt.y, w+6, h+4,
+ SWP_SHOWWINDOW|SWP_NOACTIVATE );
+ SetBkColor( hDc, GetSysColor( COLOR_INFOBK ));
+ TextOut( hDc, 2, 1, hs, strlen(hs) );
+ SelectObject( hDc, hFont );
+ ReleaseDC( balloonHelpHWnd, hDc );
+}
+ }
+}
+
+void closeBalloonHelp( void )
+{
+ if (balloonHelpTimer) {
+ KillTimer( mswHWnd, balloonHelpTimer );
+ balloonHelpTimer = 0;
+ }
+ if (balloonHelpState == balloonHelpShow)
+ if (balloonHelpHWnd)
+ ShowWindow( balloonHelpHWnd, SW_HIDE );
+ balloonHelpState = balloonHelpIdle;
+}
+
+
+void wControlSetBalloon( wControl_p b, wPos_t dx, wPos_t dy, const char * msg )
+{
+ HDC hDc;
+ DWORD extent;
+ int w, h;
+ RECT rect;
+ POINT pt;
+ HFONT hFont;
+
+ if ( msg ) {
+ hDc = GetDC( balloonHelpHWnd );
+ hFont = SelectObject( hDc, mswLabelFont );
+ extent = GetTextExtent( hDc, CAST_AWAY_CONST msg, strlen(msg) );
+ w = LOWORD( extent );
+ h = HIWORD( extent );
+ if ( b->type == B_RADIO ||
+ b->type == B_TOGGLE ) {
+ pt.y = b->h;
+ } else {
+ GetClientRect( b->hWnd, &rect );
+ pt.y = rect.bottom;
+ }
+ pt.x = dx;
+ pt.y -= dy;
+ ClientToScreen( b->hWnd, &pt );
+ if (pt.x + w+2 > screenWidth)
+ pt.x = screenWidth-(w+2);
+ if (pt.x < 0)
+ pt.x = 0;
+ SetWindowPos( balloonHelpHWnd, HWND_TOPMOST, pt.x, pt.y, w+6, h+4,
+ SWP_SHOWWINDOW|SWP_NOACTIVATE );
+ SetBkColor( hDc, GetSysColor( COLOR_INFOBK ) );
+ TextOut( hDc, 2, 1, msg, strlen(msg) );
+ SelectObject( hDc, hFont );
+ ReleaseDC( balloonHelpHWnd, hDc );
+
+ balloonHelpState = balloonHelpShow;
+ balloonControlButton = b;
+ } else {
+ closeBalloonHelp();
+ }
+}
+
+
+int wGetKeyState( void )
+{
+ int rc, keyState;
+ rc = 0;
+ keyState = GetAsyncKeyState( VK_SHIFT );
+ if (keyState & 0x8000)
+ rc |= WKEY_SHIFT;
+ keyState = GetAsyncKeyState( VK_CONTROL );
+ if (keyState & 0x8000)
+ rc |= WKEY_CTRL;
+ keyState = GetAsyncKeyState( VK_MENU );
+ if (keyState & 0x8000)
+ rc |= WKEY_ALT;
+ return rc;
+}
+
+
+/*
+ ******************************************************************************
+ *
+ * File Selection
+ *
+ ******************************************************************************
+ */
+
+FILE * wFileOpen(
+ const char * fileName,
+ const char * mode )
+{
+ return fopen( fileName, mode );
+}
+
+
+struct wFilSel_t {
+ wWin_p parent;
+ wFilSelMode_e mode;
+ int option;
+ const char * title;
+ char * extList;
+ wFilSelCallBack_p action;
+ void * data;
+ };
+
+static char selFileName[1024];
+static char selFileTitle[1024];
+static char sysDirName[1024];
+
+int wFilSelect(
+ struct wFilSel_t * fs,
+ const char * dirName )
+{
+ int rc;
+ OPENFILENAME ofn;
+ char * fileName;
+ const char * ext;
+ char defExt[4];
+ int i;
+
+ if (dirName == NULL ||
+ dirName[0] == '\0' ||
+ strcmp(dirName, ".") == 0 ) {
+ GetSystemDirectory( CAST_AWAY_CONST (dirName = sysDirName), sizeof sysDirName );
+ }
+ memset( &ofn, 0, sizeof ofn );
+ ofn.lStructSize = sizeof ofn;
+ ofn.hwndOwner = mswHWnd;
+ ofn.lpstrFilter = fs->extList;
+ ofn.nFilterIndex = 0;
+ selFileName[0] = '\0';
+ ofn.lpstrFile = selFileName;
+ ofn.nMaxFile = sizeof selFileName;
+ selFileTitle[0] = '\0';
+ ofn.lpstrFileTitle = selFileTitle;
+ ofn.nMaxFileTitle = sizeof selFileTitle;
+ ofn.lpstrInitialDir = dirName;
+ ofn.lpstrTitle = fs->title;
+ ext = fs->extList + strlen(fs->extList)+1;
+ if (*ext++ == '*' && *ext++ == '.') {
+ for ( i=0; i<3 && ext[i] && ext[i]!=';'; i++ )
+ defExt[i] = ext[i];
+ defExt[i] = '\0';
+ } else {
+ defExt[0] = '\0';
+ }
+ ofn.lpstrDefExt = defExt;
+ ofn.Flags |= OFN_LONGFILENAMES;
+ if (fs->mode == FS_LOAD) {
+ ofn.Flags |= OFN_FILEMUSTEXIST;
+ rc = GetOpenFileName( &ofn );
+ } else if (fs->mode == FS_SAVE) {
+ ofn.Flags |= OFN_OVERWRITEPROMPT;
+ rc = GetSaveFileName( &ofn );
+ } else if (fs->mode == FS_UPDATE) {
+ rc = GetSaveFileName( &ofn );
+ } else
+ return FALSE;
+ if (!rc)
+ return FALSE;
+ fileName = strrchr( selFileName, '\\' );
+ if (fileName == NULL) {
+ mswFail( "wFilSelect: cant extract fileName" );
+ return FALSE;
+ }
+ fs->action( selFileName, fileName+1, fs->data );
+ return TRUE;
+}
+
+
+struct wFilSel_t * wFilSelCreate(
+ wWin_p parent,
+ wFilSelMode_e mode,
+ int option,
+ const char * title,
+ const char * extList,
+ wFilSelCallBack_p action,
+ void * data )
+{
+ char * cp;
+ struct wFilSel_t * ret;
+ int len;
+ ret = (struct wFilSel_t*)malloc(sizeof *ret);
+ ret->parent = parent;
+ ret->mode = mode;
+ ret->option = option;
+ ret->title = mswStrdup(title);
+ len = strlen(extList);
+ ret->extList = (char*)malloc(len+2);
+ strcpy(ret->extList,extList);
+ for ( cp=ret->extList; *cp; cp++ ) {
+ if (*cp == '|')
+ *cp = '\0';
+ }
+ *++cp = '\0';
+ ret->action = action;
+ ret->data = data;
+ return ret;
+}
+
+
+const char * wMemStats( void )
+{
+ int rc;
+ static char msg[80];
+ long usedSize = 0;
+ long usedCnt = 0;
+ long freeSize = 0;
+ long freeCnt = 0;
+ _HEAPINFO heapinfo;
+ heapinfo._pentry = NULL;
+
+ while ( (rc=_heapwalk( &heapinfo )) == _HEAPOK ) {
+ switch (heapinfo._useflag) {
+ case _FREEENTRY:
+ freeSize += (long)heapinfo._size;
+ freeCnt++;
+ break;
+ case _USEDENTRY:
+ usedSize += (long)heapinfo._size;
+ usedCnt++;
+ break;
+ }
+ }
+
+ sprintf( msg, "Used: %ld(%ld), Free %ld(%ld)%s",
+ usedSize, usedCnt, freeSize, freeCnt,
+ (rc==_HEAPOK)?"":
+ (rc==_HEAPEMPTY)?"":
+ (rc==_HEAPBADBEGIN)?", BADBEGIN":
+ (rc==_HEAPEND)?"":
+ (rc==_HEAPBADPTR)?", BADPTR":
+ ", Unknown Heap Status" );
+ return msg;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Main
+ *
+ *****************************************************************************
+ */
+
+static wControl_p getControlFromCursor( HWND hWnd, wWin_p * winR )
+{
+ POINT pt;
+ wWin_p w;
+ wControl_p b;
+ wIndex_t inx;
+ HWND hTopWnd;
+
+ if (winR)
+ *winR = NULL;
+ GetCursorPos( &pt );
+ hTopWnd = GetActiveWindow();
+ inx = GetWindowWord( hWnd, 0 );
+ if ( inx < CONTROL_BASE || inx > controlMap_da.cnt ) {
+ /* Unknown control */
+ /*MessageBeep( MB_ICONEXCLAMATION );*/
+ return NULL;
+ }
+ w=(wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ return NULL;
+ if (w->type != W_MAIN && w->type != W_POPUP)
+ return NULL;
+ if ( winR )
+ *winR = w;
+ ScreenToClient( hWnd, &pt );
+ for (b = w->first; b; b=b->next) {
+ if (b->type == B_BOX || b->type == B_LINES)
+ continue;
+ if (b->hWnd == NULL)
+ continue;
+ if (IsWindowVisible( b->hWnd ) == FALSE)
+ continue;
+ if (pt.x > b->x && pt.x < b->x+b->w &&
+ pt.y > b->y && pt.y < b->y+b->h )
+ return b;
+ }
+ return b;
+}
+
+/**
+ * Window function for the main window and all popup windows.
+ *
+ */
+
+LRESULT
+FAR
+PASCAL
+MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ int inx;
+ wWin_p w;
+ wControl_p b, oldW;
+ int child = ((GetWindowLong( hWnd, GWL_STYLE) & WS_CHILD) != 0);
+ POS_T newW, newH;
+ RECT rect;
+ PAINTSTRUCT ps;
+ HWND hWnd2;
+ LRESULT ret;
+ HDC hDc;
+ wAccelKey_e extChar;
+
+ switch (message) {
+
+ case WM_MOUSEWHEEL:
+ inx = GetWindowWord( hWnd, 0 );
+ b = getControlFromCursor( hWnd, NULL );
+ if( b && b->type == B_DRAW )
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->messageProc)
+ return mswCallBacks[b->type]->messageProc( (wControl_p)b, hWnd,
+ message, wParam, lParam );
+ return( 0 );
+ case WM_DRAWITEM:
+ case WM_COMMAND:
+ case WM_MEASUREITEM:
+ case WM_NOTVALID:
+ if (WCMD_PARAM_ID == IDM_DOHELP) {
+ b = getControlFromCursor( hWnd, NULL );
+ closeBalloonHelp();
+ if (!b)
+ return 0L;
+ if (b->helpStr)
+ wHelp( b->helpStr );
+ return 0L;
+ }
+ closeBalloonHelp();
+ if (WCMD_PARAM_ID < CONTROL_BASE || WCMD_PARAM_ID > (WPARAM)controlMap_da.cnt)
+ break;
+ b = controlMap(WCMD_PARAM_ID-CONTROL_BASE).b;
+ if (!b)
+ break;
+ if( b->type == B_BITMAP ) {
+ // draw the bitmap
+ mswDrawIcon(((LPDRAWITEMSTRUCT)lParam)->hDC, 0, 0, (wIcon_p)(b->data), FALSE, (COLORREF)0, (COLORREF)0 );
+ return( TRUE );
+ } else {
+ mswSetFocus( b );
+ ret = 0L;
+ if (!inMainWndProc) {
+ inMainWndProc = TRUE;
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->messageProc) {
+ ret = mswCallBacks[b->type]->messageProc( b, hWnd, message, wParam, lParam );
+ }
+ inMainWndProc = FALSE;
+ }
+ return ret;
+ }
+ case WM_PAINT:
+ inx = GetWindowWord( hWnd, 0 );
+ if (inx >= CONTROL_BASE && inx <= controlMap_da.cnt &&
+ (w = (wWin_p)controlMap(inx-CONTROL_BASE).b) &&
+ (w->type == W_MAIN || w->type == W_POPUP) &&
+ (!IsIconic(mswHWnd)) &&
+ (GetUpdateRect( hWnd, &rect, FALSE ) ) ) {
+ BeginPaint( hWnd, &ps );
+ for (b=w->first; b; b=b->next ) {
+ if (b->shown &&
+ mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->repaintProc)
+ mswCallBacks[b->type]->repaintProc( hWnd, b );
+ }
+ EndPaint( hWnd, &ps );
+ return 1L;
+ }
+ break;
+
+ case WM_SIZE:
+ inx = GetWindowWord( hWnd, 0 );
+ if (inx < CONTROL_BASE || inx > controlMap_da.cnt)
+ break;
+ w = (wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ break;
+ if (w->type != W_MAIN && w->type != W_POPUP)
+ break;
+ if (w->busy)
+ break;
+ switch( wParam ) {
+ case SIZE_MAXIMIZED:
+ case SIZE_MINIMIZED:
+ case SIZE_RESTORED:
+ newW = LOWORD( lParam ); /* WIN32?? */
+ newH = HIWORD( lParam ); /* WIN32?? */
+ if (newW <= 0 || newH <= 0)
+ break;
+ if (newW == w->w && newH == w->h)
+ break;
+ GetWindowRect( w->hWnd, &rect );
+ GetClientRect( w->hWnd, &rect );
+ InvalidateRect( w->hWnd, NULL, TRUE );
+ w->w = newW;
+ w->h = newH;
+ if (w->winProc)
+ w->winProc( w, wResize_e, w->data );
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case WM_CHAR:
+ case WM_KEYUP:
+ inx = GetWindowWord( hWnd, 0 );
+ if ( inx < CONTROL_BASE || inx > controlMap_da.cnt )
+ break;
+ w = (wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ break;
+ if (w->type != W_MAIN && w->type != W_POPUP) {
+ if (mswCallBacks[w->type] != NULL &&
+ mswCallBacks[w->type]->messageProc)
+ return mswCallBacks[w->type]->messageProc( (wControl_p)w, hWnd,
+ message, wParam, lParam );
+ break;
+ }
+ extChar = translateExtKey( WCMD_PARAM_ID );
+ if (message == WM_KEYUP ) {
+ if (extChar == wAccelKey_None)
+ break;
+ if (extChar == wAccelKey_Back)
+ break;
+ }
+ b = getControlFromCursor( hWnd, NULL );
+ closeBalloonHelp();
+ if (b && b->type == B_DRAW) {
+ return SendMessage( b->hWnd, WM_CHAR, wParam, lParam );
+ }
+ switch (WCMD_PARAM_ID) {
+ case 0x0D:
+ /* CR - push default button */
+ for (b=w->first; b; b=b->next) {
+ if (b->type == B_BUTTON && (b->option & BB_DEFAULT) != 0) {
+ inMainWndProc = TRUE;
+ if (mswCallBacks[B_BUTTON] != NULL &&
+ mswCallBacks[B_BUTTON]->messageProc) {
+ ret = mswCallBacks[B_BUTTON]->messageProc( b, b->hWnd,
+ WM_COMMAND, wParam, lParam );
+ }
+ inMainWndProc = FALSE;
+ break;
+ }
+ }
+ return 0L;
+ case 0x1B:
+ /* ESC - push cancel button */
+ for (b=w->first; b; b=b->next) {
+ if (b->type == B_BUTTON && (b->option & BB_CANCEL) != 0) {
+ inMainWndProc = TRUE;
+ if (mswCallBacks[B_BUTTON] != NULL &&
+ mswCallBacks[B_BUTTON]->messageProc) {
+ ret = mswCallBacks[B_BUTTON]->messageProc( b, b->hWnd,
+ WM_COMMAND, wParam, lParam );
+ }
+ inMainWndProc = FALSE;
+ break;
+ }
+ }
+ mswSetTrigger( (wControl_p)TRIGGER_TIMER, NULL );
+ return 0L;
+ case 0x20:
+ /* SPC - push current button with focus */
+ if ( (b=w->focusChainNext) != NULL ) {
+ switch (b->type) {
+ case B_BUTTON:
+ case B_CHOICEITEM:
+ inMainWndProc = TRUE;
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->messageProc) {
+ ret = mswCallBacks[b->type]->messageProc( b, b->hWnd,
+ WM_COMMAND, MAKELPARAM( LOWORD(wParam), BN_CLICKED), (LPARAM)(b->hWnd) );
+ }
+ inMainWndProc = FALSE;
+ break;
+ }
+ }
+ return 0L;
+ case 0x09:
+ /* TAB - jump to next control */
+ if ( w->focusChainNext ) {
+ for ( b = w->focusChainNext->focusChainNext;
+ b!=w->focusChainNext;
+ b=b->focusChainNext ) {
+ if( IsWindowVisible(b->hWnd) && IsWindowEnabled(b->hWnd))
+ break;
+ }
+ oldW = w->focusChainNext;
+ w->focusChainNext = b;
+ if (!inMainWndProc) {
+ inMainWndProc = TRUE;
+ SetFocus( b->hWnd );
+/* if( b->type == B_BUTTON)
+ InvalidateRect( b->hWnd, NULL, TRUE ); */
+ if( oldW->type == B_BUTTON)
+ InvalidateRect( oldW->hWnd, NULL, TRUE );
+
+ inMainWndProc = FALSE;
+ }
+ }
+ return 0L;
+ }
+ /* Not a Draw control */
+ MessageBeep( MB_ICONHAND );
+ return 0L;
+ break;
+
+ case WM_ENABLE:
+ if (wParam == 1) { /* WIN32??? */
+ hWnd2 = SetFocus( hWnd );
+ }
+ break;
+
+ case WM_F1DOWN:
+ if ((hWnd2 = GetActiveWindow()) == hWnd ||
+ (inx=GetWindowWord(hWnd2,0)) < CONTROL_BASE || inx > controlMap_da.cnt )
+ return DefWindowProc( hWnd, message, wParam, lParam );
+ b=controlMap(inx-CONTROL_BASE).b;
+ if (!b)
+ break;
+ closeBalloonHelp();
+ wHelp( b->helpStr );
+ return 0L;
+
+ case WM_SETCURSOR:
+ /*if (any buttons down)
+ break;*/
+ wSetCursor( curCursor );
+ if (!mswAllowBalloonHelp)
+ break;
+ if (IsIconic(mswHWnd))
+ break;
+ b = getControlFromCursor(hWnd, NULL);
+ if ( b == balloonControlButton )
+ break;
+ if ( /*(!IsWindowEnabled(hWnd))*/ GetActiveWindow() != hWnd ||
+ (!b) || b->type == B_DRAW || b->helpStr == NULL ) {
+ closeBalloonHelp();
+ break;
+ }
+ if ( b != balloonHelpButton )
+ closeBalloonHelp();
+ if (balloonHelpState != balloonHelpIdle) {
+ break;
+ }
+ balloonHelpTimer = SetTimer( mswHWnd, BALLOONHELP_TIMER,
+ balloonHelpTimeOut, NULL );
+ if (balloonHelpTimer == (UINT)0)
+ break;
+ balloonHelpState = balloonHelpWait;
+ balloonHelpButton = b;
+ break;
+
+ case WM_SYSCOMMAND:
+ inx = GetWindowWord( hWnd, 0 );
+ if (inx < CONTROL_BASE || inx > controlMap_da.cnt)
+ break;
+ w = (wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ break;
+ if (w->type != W_POPUP)
+ break;
+ if (w->busy)
+ break;
+ if ( (wParam&0xFFF0) != SC_CLOSE )
+ break;
+ if (w->winProc)
+ w->winProc( w, wClose_e, w->data );
+ wWinShow( w, FALSE );
+ return 0L;
+
+
+
+ case WM_CLOSE:
+ inx = GetWindowWord( hWnd, 0 );
+ if (inx < CONTROL_BASE || inx > controlMap_da.cnt)
+ break;
+ w = (wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ break;
+ if (w->type == W_MAIN) {
+ /* It's the big one! */
+ /* call main window procedure for processing of shutdown */
+ if( w->winProc )
+ (w->winProc( w, wClose_e, NULL ));
+ return 0L;
+ }
+
+ case WM_DESTROY:
+ if ( hWnd == mswHWnd ) {
+ PostQuitMessage(0L);
+ return 0L;
+ }
+ break;
+
+ case WM_TIMER:
+ if (wParam == ALARM_TIMER) {
+ KillTimer( mswHWnd, alarmTimer );
+ alarmFunc();
+ } else if (wParam == TRIGGER_TIMER) {
+ KillTimer( mswHWnd, triggerTimer );
+ triggerTimer = 0;
+ if (triggerFunc)
+ triggerFunc( triggerControl );
+ } else if (wParam == BALLOONHELP_TIMER) {
+ KillTimer( hWnd, balloonHelpTimer );
+ balloonHelpTimer = (UINT)0;
+ startBalloonHelp();
+ }
+ return 0L;
+
+ case WM_MENUSELECT:
+ mswAllowBalloonHelp = TRUE;
+ closeBalloonHelp();
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ if (hWnd == mswHWnd && !IsIconic(hWnd) && needToDoPendingShow) {
+ for (w=winFirst; w; w=(wWin_p)w->next) {
+ if (w->hWnd != mswHWnd &&
+ w->pendingShow )
+ ShowWindow( w->hWnd, SW_SHOW );
+ w->pendingShow = FALSE;
+ }
+ needToDoPendingShow = FALSE;
+ }
+ break;
+
+ case 51:
+ count51++;
+ /*return NULL;*/
+
+#ifdef LATER
+ case WM_SETFOCUS:
+ hDc = GetDC( hWnd );
+ rc = RealizePalette( hDc );
+ ReleaseDC( hWnd, hDc );
+ inx = GetWindowWord( hWnd, 0 );
+ if ( inx < CONTROL_BASE || inx > controlMap_da.cnt )
+ break;
+ w = (wWin_p)controlMap(inx-CONTROL_BASE).b;
+ if (!w)
+ break;
+ if (w->type != W_MAIN && w->type != W_POPUP)
+ break;
+ for (b=w->first; b; b=b->next) {
+ if (b->hWnd && (b->type == B_BUTTON || b->type==B_DRAW)) {
+ hDc = GetDC( b->hWnd );
+ rc = RealizePalette( hDc );
+ ReleaseDC( b->hWnd, hDc );
+ }
+ }
+ break;
+#endif
+
+ case WM_PALETTECHANGED:
+ if (wParam == (WPARAM)hWnd)
+ return 0L;
+
+ case WM_QUERYNEWPALETTE:
+ if (mswPalette) {
+ hDc = GetDC( hWnd );
+ SelectPalette( hDc, mswPalette, 0 );
+ inx = RealizePalette( hDc );
+ ReleaseDC( hWnd, hDc );
+ if (inx>0)
+ InvalidateRect( hWnd, NULL, TRUE );
+ return inx;
+ }
+
+ case WM_ACTIVATE:
+ if ( LOWORD(wParam) == WA_INACTIVE )
+ closeBalloonHelp();
+ break;
+
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ b = getControlFromCursor( hWnd, NULL );
+ if (!b)
+ break;
+ /*mswSetFocus( b );*/
+ ret = 0L;
+ if (!inMainWndProc) {
+ inMainWndProc = TRUE;
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->messageProc) {
+ ret = mswCallBacks[b->type]->messageProc( b, hWnd, message, wParam, lParam );
+ }
+ inMainWndProc = FALSE;
+ }
+ return ret;
+
+ case WM_LBUTTONDOWN:
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONUP:
+ b = getControlFromCursor( hWnd, NULL );
+ if (!b)
+ break;
+ /*mswSetFocus( b );*/
+ ret = 0L;
+ if (!inMainWndProc) {
+ inMainWndProc = TRUE;
+ if (mswCallBacks[b->type] != NULL &&
+ mswCallBacks[b->type]->messageProc) {
+ ret = mswCallBacks[b->type]->messageProc( b, hWnd, message, wParam, lParam );
+ }
+ inMainWndProc = FALSE;
+ }
+ return ret;
+
+ default:
+ ;
+ }
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+/*
+ *****************************************************************************
+ *
+ * INIT
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Register window classes used by the application. These are the main window,
+ * the popup windows, the tooltip window and the drawing area.
+ *
+ * \param hinstCurrent IN application instance
+ * \return FALSE in case of error, else TRUE
+ */
+
+static BOOL InitApplication( HINSTANCE hinstCurrent )
+{
+ WNDCLASS wc;
+
+ wc.style = 0L;
+ wc.lpfnWndProc = MainWndProc;
+
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4;
+ wc.hInstance = hinstCurrent;
+ wc.hIcon = LoadIcon( hinstCurrent, "MSWAPPICON" );
+ wc.hCursor = NULL;
+ wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "MswMainWindow";
+ if (!RegisterClass(&wc)) {
+ mswFail("RegisterClass(MainWindow)");
+ return FALSE;
+ }
+
+ wc.style = CS_SAVEBITS;
+ wc.lpfnWndProc = MainWndProc;
+
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 8;
+ wc.hInstance = hinstCurrent;
+ wc.hIcon = LoadIcon( NULL, "wAppIcon" );
+ wc.hCursor = NULL;
+ wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
+ wc.lpszMenuName = "GenericMenu";
+ wc.lpszClassName = "MswPopUpWindow";
+ if (!RegisterClass(&wc)) {
+ mswFail("RegisterClass(PopUpWindow)");
+ return FALSE;
+ }
+
+ wc.style = CS_SAVEBITS;
+ wc.lpfnWndProc = DefWindowProc;
+
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4;
+ wc.hInstance = hinstCurrent;
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = CreateSolidBrush( GetSysColor( COLOR_INFOBK ) );
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "MswBalloonHelp";
+ if (!RegisterClass(&wc)) {
+ mswFail("RegisterClass(BalloonHelp)");
+ return FALSE;
+ }
+
+ wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = mswDrawPush;
+ wc.lpszClassName = mswDrawWindowClassName;
+ wc.cbWndExtra = 4;
+ if (!RegisterClass(&wc)) {
+ mswFail("RegisterClass(drawClass)");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Standard entry point for the app. Nothing special,
+ * create some window classes, initialize some global
+ * variables with system information, call the application main
+ * and finally process the message queue.
+ */
+
+int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow )
+{
+ MSG msg;
+ HDC hDc;
+ char **argv;
+ int argc;
+ TEXTMETRIC tm;
+ DWORD dw;
+
+ if (!hinstPrevious)
+ if (!InitApplication(hinstCurrent))
+ return FALSE;
+
+ mswHInst = hinstCurrent;
+
+ mTitleH = GetSystemMetrics( SM_CYCAPTION ) - 1;
+ mFixBorderW = GetSystemMetrics( SM_CXBORDER );
+ mFixBorderH = GetSystemMetrics( SM_CYBORDER );
+ mResizeBorderW = GetSystemMetrics( SM_CXFRAME );
+ mResizeBorderH = GetSystemMetrics( SM_CYFRAME );
+ mMenuH = GetSystemMetrics( SM_CYMENU ) + 1;
+ screenWidth = GetSystemMetrics( SM_CXSCREEN );
+ screenHeight = GetSystemMetrics( SM_CYSCREEN );
+ mswLabelFont = GetStockObject( DEFAULT_GUI_FONT );
+
+ hDc = GetDC( 0 );
+ mswScale = GetDeviceCaps( hDc, LOGPIXELSX ) / 96.0;
+ if ( mswScale < 1.0 )
+ mswScale = 1.0;
+ GetTextMetrics( hDc, &tm );
+ mswEditHeight = tm.tmHeight + 8;
+ dw = GetTextExtent( hDc, "AXqypj", 6 );
+ mswEditHeight = HIWORD(dw)+2;
+ ReleaseDC( 0, hDc );
+
+ mswCreateCheckBitmaps();
+
+ /*
+ get the command line parameters in standard C style and pass them to the main function. The
+ globals are predefined by Visual C
+ */
+ argc = __argc;
+ argv = __argv;
+
+ mswWin = wMain( argc, (char**)argv );
+ if (mswWin == NULL)
+ return 0;
+
+ balloonHelpHWnd = CreateWindow( "MswBalloonHelp", "BalloonHelp",
+ WS_POPUP|WS_BORDER,
+ 0, 0, 80, 40, mswHWnd, NULL, mswHInst, NULL );
+ if (balloonHelpHWnd == (HWND)0) {
+ mswFail( "CreateWindow(BALLOONHELP)" );
+ } else {
+ hDc = GetDC( balloonHelpHWnd );
+ /* We need to remember this because the hDc gets changed somehow,
+ /* and we when we select the oldFont back in we don't get newFont */
+ balloonHelpNewFont = CreateFont( - balloonHelpFontSize, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, balloonHelpFaceName );
+ balloonHelpOldFont = SelectObject( hDc, balloonHelpNewFont );
+ ReleaseDC( balloonHelpHWnd, hDc );
+ }
+
+ SetCursor( LoadCursor( NULL, IDC_ARROW ) );
+ while (GetMessage( &msg, NULL, 0, 0 )) {
+ if (!mswTranslateAccelerator( mswWin->hWnd, &msg )) {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+
+ if( helpInitted == TRUE )
+ HtmlHelp( NULL, NULL, HH_UNINITIALIZE, (DWORD)dwCookie);
+
+ return msg.wParam;
+}
diff --git a/app/wlib/mswlib/mswmsg.c b/app/wlib/mswlib/mswmsg.c
new file mode 100644
index 0000000..b128534
--- /dev/null
+++ b/app/wlib/mswlib/mswmsg.c
@@ -0,0 +1,212 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Message Boxes
+ *
+ *****************************************************************************
+ */
+
+/**
+ * factors by which fonts are resized if nonstandard text height is used
+ */
+
+#define SCALE_LARGE 1.6
+#define SCALE_SMALL 0.8
+
+#ifdef CONTROL3D
+static int messageHeight = 18;
+#endif
+
+struct wMessage_t {
+ WOBJ_COMMON
+ long flags;
+ const char * message;
+ };
+
+#ifndef CONTROL3D
+static void repaintMessage(
+ HWND hWnd,
+ wControl_p b )
+{
+ wMessage_p bm = (wMessage_p)b;
+ HDC hDc;
+ RECT rect;
+ HFONT hFont;
+ LOGFONT msgFont;
+ double scale = 1.0;
+
+ hDc = GetDC( hWnd );
+
+ if ( !mswThickFont )
+ hFont = SelectObject( hDc, mswLabelFont );
+
+ switch( wMessageSetFont( ((wMessage_p)b)->flags ))
+ {
+ case BM_LARGE:
+ scale = SCALE_LARGE;
+ break;
+ case BM_SMALL:
+ scale = SCALE_SMALL;
+ break;
+ }
+
+ /* is a non-standard text height required? */
+ if( scale != 1.0 )
+ {
+ /* if yes, get information about the standard font used */
+ GetObject( GetStockObject( DEFAULT_GUI_FONT ), sizeof( LOGFONT ), &msgFont );
+
+ /* change the height */
+ msgFont.lfHeight = (long)((double)msgFont.lfHeight * scale);
+
+ /* create and activate the new font */
+ hFont = SelectObject( hDc, CreateFontIndirect( &msgFont ) );
+ } else {
+ if ( !mswThickFont )
+ hFont = SelectObject( hDc, mswLabelFont );
+ }
+
+ rect.bottom = (long)(bm->y+( bm->h ));
+ rect.right = (long)(bm->x+( scale * bm->w ));
+ rect.top = bm->y;
+ rect.left = bm->x;
+
+ SetBkColor( hDc, GetSysColor( COLOR_BTNFACE ) );
+ ExtTextOut( hDc, bm->x, bm->y, ETO_CLIPPED|ETO_OPAQUE, &rect, bm->message, strlen( bm->message ), NULL );
+
+ if( scale != 1.0 )
+ /* in case we did create a new font earlier, delete it now */
+ DeleteObject( SelectObject( hDc, GetStockObject( DEFAULT_GUI_FONT )));
+ else
+ if ( !mswThickFont )
+ SelectObject( hDc, hFont );
+
+ ReleaseDC( hWnd, hDc );
+}
+#endif
+
+void wMessageSetValue(
+ wMessage_p b,
+ const char * arg )
+{
+ if (b->message)
+ free( CAST_AWAY_CONST b->message );
+ if (arg)
+ b->message = mswStrdup( arg );
+ else
+ b->message = NULL;
+#ifdef CONTROL3D
+ SetWindowText( b->hWnd, arg );
+#else
+ repaintMessage( ((wControl_p)(b->parent))->hWnd, (wControl_p)b );
+#endif
+}
+
+void wMessageSetWidth(
+ wMessage_p b,
+ wPos_t width )
+{
+ b->w = width;
+#ifdef CONTROL3D
+ SetWindowPos( b->hWnd, HWND_TOP, CW_USEDEFAULT, CW_USEDEFAULT,
+ width, messageHeight, SWP_NOMOVE );
+#endif
+}
+
+
+wPos_t wMessageGetHeight( long flags )
+{
+#ifdef CONTROL3D
+ return messageHeight;
+#else
+ double scale = 1.0;
+
+ if( flags & BM_LARGE )
+ scale = SCALE_LARGE;
+ if( flags & BM_SMALL )
+ scale = SCALE_SMALL;
+
+ return((wPos_t)((mswEditHeight - 4) * scale ));
+#endif
+}
+
+static void mswMessageSetBusy(
+ wControl_p b,
+ BOOL_T busy )
+{
+}
+
+
+#ifndef CONTROL3D
+static callBacks_t messageCallBacks = {
+ repaintMessage,
+ NULL,
+ NULL,
+ mswMessageSetBusy };
+#endif
+
+
+wMessage_p wMessageCreateEx(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ POS_T width,
+ const char *message,
+ long flags )
+{
+ wMessage_p b;
+ int index;
+
+#ifdef CONTROL3D
+ RECT rect;
+#endif
+
+ b = (wMessage_p)mswAlloc( parent, B_MESSAGE, NULL, sizeof *b, NULL, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option |= BO_READONLY;
+ b->message = mswStrdup( message );
+ b->flags = flags;
+
+#ifdef CONTROL3D
+ if ( width <= 0 && strlen(b->message) > 0 ) {
+ width = wLabelWidth( b->message );
+ }
+
+ b->hWnd = CreateWindow( "STATIC", NULL,
+ SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE,
+ b->x, b->y,
+ width, messageHeight,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(MESSAGE)");
+ return b;
+ }
+
+ if ( !mswThickFont )
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ SetWindowText( b->hWnd, message );
+
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+#else
+ b->w = width;
+ b->h = wMessageGetHeight( flags ) + 1;
+
+ repaintMessage( ((wControl_p)parent)->hWnd, (wControl_p)b );
+#endif
+ mswAddButton( (wControl_p)b, FALSE, helpStr );
+#ifndef CONTROL3D
+ mswCallBacks[B_MESSAGE] = &messageCallBacks;
+#endif
+ return b;
+}
diff --git a/app/wlib/mswlib/mswpref.c b/app/wlib/mswlib/mswpref.c
new file mode 100644
index 0000000..90cf8fc
--- /dev/null
+++ b/app/wlib/mswlib/mswpref.c
@@ -0,0 +1,274 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <stdio.h>
+#include "mswint.h"
+#include <shlobj.h>
+#include <Shlwapi.h>
+
+#if _MSC_VER >=1400
+ #define stricmp _stricmp
+#endif
+
+char * mswStrdup( const char * );
+static char appLibDirName[MAX_PATH];
+static char appWorkDirName[MAX_PATH];
+
+/**
+ * Get the location of the shared files (parameters, help file, etc. ): This location is
+ * derived from the modulename, ie. the directory where the exe is installed.
+ * For an instalaltion directory of somedir/bin/xtrkcad.exe the library directory is
+ * somedir/share/xtrkcad/
+ */
+
+const char * wGetAppLibDir( void )
+{
+ char *cp;
+ char module_name[MAX_PATH];
+
+ if (appLibDirName[0] != '\0') {
+ return appLibDirName;
+ }
+
+ GetModuleFileName( mswHInst, module_name, sizeof module_name );
+ cp = strrchr( module_name, '\\' );
+ if (cp)
+ *cp = '\0';
+
+#ifdef XTRKCAD_CMAKE_BUILD
+ strcpy(appLibDirName, module_name);
+ strcat(appLibDirName, "\\..\\share\\xtrkcad");
+ _fullpath( appLibDirName, appLibDirName, MAX_PATH );
+ return appLibDirName;
+#endif
+
+ strcpy(appLibDirName, module_name);
+ return appLibDirName;
+}
+
+
+/**
+ * Gets the working directory for the application. At least the INI file is stored here.
+ * The working directory can be specified manually by creating a file called xtrkcad0.ini
+ * in the application lib dir (the directory where the .EXE is located).
+ *
+ * [workdir]
+ * path=somepath
+ *
+ * when somepath is set to the keyword "installdir", the install directory for the EXE is
+ * used.
+ *
+ * If no xtrkcad0.ini could be found, the user settings directory (appdata) is used.
+ *
+ */
+const char * wGetAppWorkDir( void )
+{
+ char *cp;
+ int rc;
+ if ( appWorkDirName[0] != 0 ) {
+ return appWorkDirName;
+ }
+ wGetAppLibDir();
+ sprintf( mswTmpBuff, "%s\\xtrkcad0.ini", appLibDirName );
+ rc = GetPrivateProfileString( "workdir", "path", "", appWorkDirName, sizeof appWorkDirName, mswTmpBuff );
+ if ( rc!=0 ) {
+ if ( stricmp( appWorkDirName, "installdir" ) == 0 ) {
+ strcpy( appWorkDirName, appLibDirName );
+ } else {
+ cp = &appWorkDirName[strlen(appWorkDirName)-1];
+ while (cp>appWorkDirName && *cp == '\\') *cp-- = 0;
+ }
+ return appWorkDirName;
+ }
+
+ if (SHGetSpecialFolderPath( NULL, mswTmpBuff, CSIDL_APPDATA, 0 ) == 0 ) {
+ wNoticeEx( NT_ERROR, "Cannot get user's profile directory", "Exit", NULL );
+ wExit(0);
+ } else {
+ sprintf( appWorkDirName, "%s\\%s", mswTmpBuff, "XTrackCad" );
+ if( !PathIsDirectory( appWorkDirName )) {
+ if( !CreateDirectory( appWorkDirName, NULL )) {
+ wNoticeEx( NT_ERROR, "Cannot create user's profile directory", "Exit", NULL );
+ wExit(0);
+ }
+ }
+ }
+
+ return appWorkDirName;
+}
+
+/** Get the user's home directory. The environment variable HOME is
+ * assumed to contain the proper directory.
+ *
+ * \return pointer to the user's home directory
+ */
+
+const char *wGetUserHomeDir( void )
+{
+ if (SHGetSpecialFolderPath( NULL, mswTmpBuff, CSIDL_PERSONAL, 0 ) == 0 ) {
+ wNoticeEx( NT_ERROR, "Cannot get user's home directory", "Exit", NULL );
+ wExit(0);
+ return( NULL );
+ } else {
+ return( mswTmpBuff );
+ }
+}
+
+typedef struct {
+ char * section;
+ char * name;
+ BOOL_T present;
+ BOOL_T dirty;
+ char * val;
+ } prefs_t;
+dynArr_t prefs_da;
+#define prefs(N) DYNARR_N(prefs_t,prefs_da,N)
+
+void wPrefSetString( const char * section, const char * name, const char * sval )
+{
+ prefs_t * p;
+
+ for (p=&prefs(0); p<&prefs(prefs_da.cnt); p++) {
+ if ( strcmp( p->section, section ) == 0 && strcmp( p->name, name ) == 0 ) {
+ if (p->val)
+ free(p->val);
+ p->dirty = TRUE;
+ p->val = mswStrdup( sval );
+ return;
+ }
+ }
+ DYNARR_APPEND( prefs_t, prefs_da, 10 );
+ p = &prefs(prefs_da.cnt-1);
+ p->name = mswStrdup(name);
+ p->section = mswStrdup(section);
+ p->dirty = TRUE;
+ p->val = mswStrdup(sval);
+}
+
+
+const char * wPrefGetString( const char * section, const char * name )
+{
+ prefs_t * p;
+ int rc;
+
+ for (p=&prefs(0); p<&prefs(prefs_da.cnt); p++) {
+ if ( strcmp( p->section, section ) == 0 && strcmp( p->name, name ) == 0 ) {
+ return p->val;
+ }
+ }
+ rc = GetPrivateProfileString( section, name, "", mswTmpBuff, sizeof mswTmpBuff, mswProfileFile );
+ if (rc==0)
+ return NULL;
+ DYNARR_APPEND( prefs_t, prefs_da, 10 );
+ p = &prefs(prefs_da.cnt-1);
+ p->name = mswStrdup(name);
+ p->section = mswStrdup(section);
+ p->dirty = FALSE;
+ p->val = mswStrdup(mswTmpBuff);
+ return p->val;
+}
+
+
+void wPrefSetInteger( const char * section, const char * name, long lval )
+{
+ char tmp[20];
+
+ sprintf( tmp, "%ld", lval );
+ wPrefSetString( section, name, tmp );
+}
+
+
+wBool_t wPrefGetInteger(
+ const char * section,
+ const char * name,
+ long *res,
+ long def )
+{
+ const char * cp;
+ char * cp1;
+
+ cp = wPrefGetString( section, name );
+ if (cp == NULL) {
+ *res = def;
+ return FALSE;
+ }
+ *res = strtol(cp,&cp1,0);
+ if (cp==cp1) {
+ *res = def;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void wPrefSetFloat(
+ const char * section, /* Section */
+ const char * name, /* Name */
+ double lval ) /* Value */
+/*
+*/
+{
+ char tmp[20];
+
+ sprintf(tmp, "%0.6f", lval );
+ wPrefSetString( section, name, tmp );
+}
+
+
+wBool_t wPrefGetFloat(
+ const char * section, /* Section */
+ const char * name, /* Name */
+ double * res, /* Address of result */
+ double def ) /* Default value */
+/*
+*/
+{
+ const char * cp;
+ char * cp1;
+
+ cp = wPrefGetString( section, name );
+ if (cp == NULL) {
+ *res = def;
+ return FALSE;
+ }
+ *res = strtod(cp, &cp1);
+ if (cp == cp1) {
+ *res = def;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void wPrefFlush( void )
+{
+ prefs_t * p;
+
+ for (p=&prefs(0); p<&prefs(prefs_da.cnt); p++) {
+ if ( p->dirty )
+ WritePrivateProfileString( p->section, p->name, p->val, mswProfileFile );
+ }
+ WritePrivateProfileString( NULL, NULL, NULL, mswProfileFile );
+}
+
+
+void wPrefReset(
+ void )
+/*
+*/
+{
+ prefs_t * p;
+
+ for (p=&prefs(0); p<&prefs(prefs_da.cnt); p++) {
+ if (p->section)
+ free( p->section );
+ if (p->name)
+ free( p->name );
+ if (p->val)
+ free( p->val );
+ }
+ prefs_da.cnt = 0;
+}
diff --git a/app/wlib/mswlib/mswprint.c b/app/wlib/mswlib/mswprint.c
new file mode 100644
index 0000000..91f05ea
--- /dev/null
+++ b/app/wlib/mswlib/mswprint.c
@@ -0,0 +1,387 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#ifndef WIN32
+#include <print.h>
+#endif
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * PRINT
+ *
+ *****************************************************************************
+ */
+
+
+struct wDraw_t print_d;
+
+#ifdef WIN32
+struct tagPDA printDlg;
+#else
+struct tagPD printDlg;
+#endif
+static int printStatus = FALSE;
+static DOCINFO docInfo;
+static double pageSizeW = 8.5, pageSizeH = 11.0;
+static double physSizeW = 8.5, physSizeH = 11.0;
+static int pageCount = -1;
+
+static HPALETTE newPrintPalette;
+static HPALETTE oldPrintPalette;
+
+
+void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h )
+{
+ wDrawClip( &print_d, x, y, w, h );
+}
+
+
+void getPageDim( HDC hDc )
+{
+ int rc;
+ POINT dims;
+ POINT offs;
+ int res_w, res_h, size_w, size_h;
+ rc = Escape( hDc, GETPHYSPAGESIZE, 0, NULL, (LPPOINT)&dims );
+ if (rc <0) {
+ mswFail( "GETPHYPAGESIZE" );
+ }
+ rc = Escape( hDc, GETPRINTINGOFFSET, 0, NULL, (LPPOINT)&offs );
+ if (rc <0) {
+ mswFail( "GETPRINTINGOFFSET" );
+ }
+ print_d.wFactor = (double)GetDeviceCaps( hDc, LOGPIXELSX );
+ print_d.hFactor = (double)GetDeviceCaps( hDc, LOGPIXELSY );
+ if (print_d.wFactor <= 0 || print_d.hFactor <= 0) {
+ mswFail( "getPageDim: LOGPIXELS... <= 0" );
+ abort();
+ }
+ print_d.DPI = min( print_d.wFactor, print_d.hFactor );
+ size_w = GetDeviceCaps( hDc, HORZSIZE );
+ size_h = GetDeviceCaps( hDc, VERTSIZE );
+ print_d.w = res_w = GetDeviceCaps( hDc, HORZRES );
+ print_d.h = res_h = GetDeviceCaps( hDc, VERTRES );
+ pageSizeW = ((double)res_w)/print_d.wFactor;
+ pageSizeH = ((double)res_h)/print_d.hFactor;
+ physSizeW = ((double)dims.x)/print_d.wFactor;
+ physSizeH = ((double)dims.y)/print_d.hFactor;
+}
+
+static wBool_t printInit( void )
+{
+ static int initted = FALSE;
+ static int printerOk = FALSE;
+ if (initted) {
+ if (!printerOk) {
+ mswFail( "No Printers are defined" );
+ }
+ return printerOk;
+ }
+ initted = TRUE;
+ printDlg.lStructSize = sizeof printDlg;
+ printDlg.hwndOwner = NULL;
+ printDlg.Flags = PD_RETURNDC|PD_RETURNDEFAULT;
+ if (PrintDlg(&printDlg) != 0 && printDlg.hDC) {
+ getPageDim( printDlg.hDC );
+ DeleteDC( printDlg.hDC );
+ }
+#ifdef LATER
+ DEVMODE * printMode;
+ HDC hDc;
+ char ptrInfo[80];
+ char ptrDrvrDvr[80];
+ char *temp;
+ char *ptrDevice;
+ char *ptrDrvr;
+ char *ptrPort;
+ int size;
+ int rc;
+ FARPROC extDeviceMode;
+ FARPROC deviceMode;
+ HINSTANCE hDriver;
+
+ GetProfileString("windows", "device", "", ptrInfo, sizeof ptrInfo );
+ if (ptrInfo[0] == 0) {
+ mswFail( "No Printers are defined" );
+ return FALSE;
+ }
+ temp = ptrDevice = ptrInfo;
+ ptrDrvr = ptrPort = NULL;
+ while (*temp) {
+ if (*temp == ',') {
+ *temp++ = 0;
+ while( *temp == ' ' )
+ temp++;
+ if (!ptrDrvr)
+ ptrDrvr = temp;
+ else {
+ ptrPort = temp;
+ break;
+ }
+ }
+ else
+ temp = AnsiNext(temp);
+ }
+ strcpy( ptrDrvrDvr, ptrDrvr );
+ strcat( ptrDrvrDvr, ".drv" );
+ if ((long)(hDriver = LoadLibrary( ptrDrvrDvr )) <= 32) {
+ mswFail( "printInit: LoadLibrary" );
+ return FALSE;
+ }
+ if (( extDeviceMode = GetProcAddress( hDriver, "ExtDeviceMode" )) != NULL) {
+ size = extDeviceMode( mswHWnd, (HANDLE)hDriver, (LPDEVMODE)NULL, (LPSTR)ptrDevice, (LPSTR)ptrPort, (LPDEVMODE)NULL, (LPSTR)NULL, 0 );
+ printMode = (DEVMODE*)malloc( size );
+ rc = extDeviceMode( mswHWnd, (HANDLE)hDriver, (LPDEVMODE)printMode, (LPSTR)ptrDevice, (LPSTR)ptrPort, (LPDEVMODE)NULL, (LPSTR)NULL, DM_OUT_BUFFER );
+#ifdef LATER
+ if (rc != IDOK && rc != IDCANCEL) {
+ mswFail( "printInit: extDeviceMode" );
+ return FALSE;
+ }
+#endif
+ } else if (( deviceMode = GetProcAddress( hDriver, "DeviceMode" )) != NULL) {
+ rc = deviceMode( mswHWnd, (HANDLE)hDriver, (LPSTR)ptrDevice, (LPSTR)ptrPort );
+#ifdef LATER
+ if (rc != IDOK && rc != IDCANCEL) {
+ mswFail( "printInit: deviceMode" );
+ return FALSE;
+ }
+#endif
+ }
+
+ hDc = CreateDC( (LPSTR)ptrDrvr, (LPSTR)ptrDevice, (LPSTR)ptrPort, NULL );
+ if (hDc == NULL) {
+ mswFail("printInit: createDC" );
+ abort();
+ }
+ getPageDim( hDc );
+ DeleteDC( hDc );
+
+ FreeLibrary( hDriver );
+#endif
+ printerOk = TRUE;
+ return TRUE;
+}
+
+
+wBool_t wPrintInit( void )
+{
+ if (!printInit()) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void wPrintSetup( wPrintSetupCallBack_p callback )
+{
+ if (!printInit()) {
+ return;
+ }
+ /*memset( &printDlg, 0, sizeof printDlg );*/
+ printDlg.lStructSize = sizeof printDlg;
+ printDlg.hwndOwner = NULL;
+ printDlg.Flags = PD_RETURNDC|PD_PRINTSETUP;
+ if (PrintDlg(&printDlg) != 0 && printDlg.hDC) {
+ getPageDim( printDlg.hDC );
+ }
+ if ( callback ) {
+ callback( TRUE );
+ }
+}
+
+
+void wPrintGetPageSize( double *w, double *h )
+{
+ printInit();
+ *w = pageSizeW;
+ *h = pageSizeH;
+}
+
+
+void wPrintGetPhysSize( double *w, double *h )
+{
+ printInit();
+ *w = physSizeW;
+ *h = physSizeH;
+}
+
+
+HDC mswGetPrinterDC( void )
+{
+ if (!printInit()) {
+ return (HDC)0;
+ }
+ /*memset( &printDlg, 0, sizeof printDlg );*/
+ printDlg.lStructSize = sizeof printDlg;
+ printDlg.hwndOwner = NULL;
+ printDlg.Flags = PD_RETURNDC|PD_NOPAGENUMS|PD_NOSELECTION;
+ if (PrintDlg(&printDlg) != 0)
+ return printDlg.hDC;
+ else
+ return (HDC)0;
+}
+
+
+static wBool_t printAbort = FALSE;
+HWND hAbortDlgWnd;
+FARPROC lpAbortDlg, lpAbortProc;
+static int pageNumber;
+
+int FAR PASCAL mswAbortDlg( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (msg == WM_COMMAND) {
+ if (WCMD_PARAM_ID == IDCANCEL) {
+ printAbort = TRUE;
+ EndDialog( hWnd, wParam );
+ return TRUE;
+ }
+ } else if (msg == WM_INITDIALOG) {
+ SetFocus( GetDlgItem( hWnd, IDCANCEL ) );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+int FAR PASCAL _export mswAbortProc( HDC hdcPrinter, int Code )
+{
+ MSG msg;
+ while (PeekMessage((LPMSG)&msg, (HWND)0, 0, 0, PM_REMOVE)) {
+ if (!IsDialogMessage(hAbortDlgWnd, (LPMSG)&msg) ) {
+ TranslateMessage( (LPMSG)&msg );
+ DispatchMessage( (LPMSG)&msg );
+ }
+ }
+ return !printAbort;
+}
+
+
+wBool_t wPrintDocStart( const char * title, int fpageCount, int * copiesP )
+{
+ printStatus = FALSE;
+ pageCount = fpageCount;
+ pageNumber = 0;
+ print_d.hDc = mswGetPrinterDC();
+ if (print_d.hDc == (HDC)0) {
+ return FALSE;
+ }
+ printStatus = TRUE;
+ docInfo.cbSize = sizeof docInfo;
+ docInfo.lpszDocName = title;
+ docInfo.lpszOutput = NULL;
+ lpAbortDlg = MakeProcInstance( (FARPROC)mswAbortDlg, mswHInst );
+ lpAbortProc = MakeProcInstance( (FARPROC)mswAbortProc, mswHInst );
+ SetAbortProc( print_d.hDc, (ABORTPROC)lpAbortProc );
+ if (StartDoc( print_d.hDc, &docInfo ) < 0) {
+ MessageBox( mswHWnd, "Unable to start print job",
+ NULL, MB_OK|MB_ICONHAND );
+ FreeProcInstance( lpAbortDlg );
+ FreeProcInstance( lpAbortProc );
+ DeleteDC( print_d.hDc );
+ return FALSE;
+ }
+ printAbort = FALSE;
+ hAbortDlgWnd = CreateDialog( mswHInst, "MswAbortDlg", mswHWnd,
+ (DLGPROC)lpAbortDlg );
+ /*SetDlgItemText( hAbortDlgWnd, IDM_PRINTAPP, title );*/
+ SetWindowText( hAbortDlgWnd, title );
+ ShowWindow( hAbortDlgWnd, SW_NORMAL );
+ UpdateWindow( hAbortDlgWnd );
+ EnableWindow( mswHWnd, FALSE );
+ if (copiesP)
+ *copiesP = printDlg.nCopies;
+ if (printDlg.nCopies>1)
+ pageCount *= printDlg.nCopies;
+ if ( (GetDeviceCaps( printDlg.hDC, RASTERCAPS ) & RC_PALETTE) ) {
+ newPrintPalette = mswCreatePalette();
+ oldPrintPalette = SelectPalette( printDlg.hDC, newPrintPalette, 0 );
+ RealizePalette( printDlg.hDC );
+ }
+ return TRUE;
+}
+
+wDraw_p wPrintPageStart( void )
+{
+ char pageL[80];
+ if (!printStatus)
+ return NULL;
+ pageNumber++;
+ if (pageCount > 0)
+ wsprintf( pageL, "Page %d of %d", pageNumber, pageCount );
+ else
+ wsprintf( pageL, "Page %d", pageNumber );
+ SetDlgItemText( hAbortDlgWnd, IDM_PRINTPAGE, pageL );
+ StartPage( printDlg.hDC );
+#ifdef LATER
+ if (mswPrintPalette) {
+ SelectPalette( printDlg.hDC, mswPrintPalette, 0 );
+ RealizePalette( printDlg.hDC );
+ }
+#endif
+ getPageDim( printDlg.hDC );
+ SelectClipRgn( print_d.hDc, NULL );
+ return &print_d;
+}
+
+wBool_t wPrintPageEnd( wDraw_p d )
+{
+ return EndPage( printDlg.hDC ) >= 0;
+}
+
+wBool_t wPrintQuit( void )
+{
+ MSG msg;
+ while (PeekMessage((LPMSG)&msg, (HWND)0, 0, 0, PM_REMOVE)) {
+ if (!IsDialogMessage(hAbortDlgWnd, (LPMSG)&msg) ) {
+ TranslateMessage( (LPMSG)&msg );
+ DispatchMessage( (LPMSG)&msg );
+ }
+ }
+ return printAbort;
+}
+
+void wPrintDocEnd( void )
+{
+ if (!printStatus)
+ return;
+ EndDoc( printDlg.hDC );
+ if ( newPrintPalette ) {
+ SelectPalette( printDlg.hDC, oldPrintPalette, 0 );
+ DeleteObject( newPrintPalette );
+ newPrintPalette = (HPALETTE)0;
+ }
+
+ EnableWindow( mswHWnd, TRUE );
+ DestroyWindow( hAbortDlgWnd );
+ FreeProcInstance( lpAbortDlg );
+ FreeProcInstance( lpAbortProc );
+ DeleteDC( printDlg.hDC );
+ printStatus = FALSE;
+}
+
+wBool_t wPrintFontAlias( const char * font, const char * alias )
+{
+ return TRUE;
+}
+
+wBool_t wPrintNewPrinter( const char * printer )
+{
+ return TRUE;
+}
+
+wBool_t wPrintNewMargin( const char * name, double t, double b, double l, double r )
+{
+ return TRUE;
+}
+
+void wPrintSetCallBacks(
+ wAddPrinterCallBack_p newPrinter,
+ wAddMarginCallBack_p newMargin,
+ wAddFontAliasCallBack_p newFontAlias )
+{
+}
diff --git a/app/wlib/mswlib/mswsplash.c b/app/wlib/mswlib/mswsplash.c
new file mode 100644
index 0000000..bddd081
--- /dev/null
+++ b/app/wlib/mswlib/mswsplash.c
@@ -0,0 +1,266 @@
+/**
+ * Splash window for Windows
+ * $header$
+ */
+
+ /* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2007 Martin Fischer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <ctype.h>
+#include <assert.h>
+#include "mswint.h"
+
+extern HINSTANCE mswHInst;
+extern HWND mswHWnd;
+
+static HWND hSplash;
+
+#define IDAPPNAME 150
+#define IDMESSAGE 200
+#define IDBITMAP 250
+
+static LPWORD lpwAlign( LPWORD lpIn )
+{
+ ULONG ul;
+
+ ul = (ULONG) lpIn;
+ ul +=3;
+ ul >>=2;
+ ul <<=2;
+ return (LPWORD) ul;
+}
+
+/**
+ * Draw the logo bitmap. Thanks to Charles Petzold.
+ */
+
+BOOL
+PaintBitmap( HWND hWnd, HBITMAP hBmp )
+{
+ HDC hdc, hdcMem;
+ RECT rect;
+
+ UpdateWindow( hWnd );
+
+ /* get device context for destination window ( the dialog control ) */
+ hdc = GetDC( hWnd );
+ GetClientRect( hWnd, &rect );
+
+ /* create a memory dc holding the bitmap */
+ hdcMem = CreateCompatibleDC( hdc );
+ SelectObject( hdcMem, hBmp );
+
+ /*
+ show it in the uppler left corner
+ the window is created with the size of the bitmap, so there is no need
+ for any special transformation
+ */
+
+ BitBlt( hdc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
+ hdcMem, 0, 0, SRCCOPY );
+
+ /* release the DCs that are not needed any more */
+ DeleteDC( hdcMem );
+ ReleaseDC( hWnd, hdc );
+
+ return( 0 );
+}
+
+/**
+ * This is the dialog procedure for the splash window. Main activity is to
+ * catch the WM_PAINT message and draw the logo bitmap into that area.
+ */
+
+BOOL CALLBACK
+SplashDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ static HWND hWndBmp;
+ static HBITMAP hBmp;
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+ /* bitmap handle is passed at dialog creation */
+ hBmp = (HBITMAP)lParam;
+
+ hWndBmp = GetDlgItem( hDlg, IDBITMAP );
+ return TRUE;
+ case WM_PAINT:
+ /* paint the logo bitmap */
+ PaintBitmap( hWndBmp, hBmp );
+ break;
+ case WM_DESTROY:
+ /* destroy the bitmap */
+ DeleteObject( hBmp );
+ break;
+ }
+ return FALSE;
+}
+
+/**
+ * Show the splash screen. For display of the splash screen, a dialog template is
+ * created in memory. This template has three static elements:
+ * - the logo
+ * - the application name
+ * - the progress message
+ *
+ * return TRUE if successful, FALSE otherwise.
+ *
+ */
+
+int
+wCreateSplash( char *appname, char *appver )
+{
+ HGLOBAL hgbl;
+ LPDLGTEMPLATE lpdt;
+ LPWORD lpw;
+ LPDLGITEMTEMPLATE lpdit;
+ int cxDlgUnit, cyDlgUnit;
+ int cx, cy;
+ char *pszBuf;
+ HBITMAP hBmp;
+ BITMAP bmp;
+ char logoPath[MAX_PATH];
+
+ /* find the size of a dialog unit */
+ cxDlgUnit = LOWORD(GetDialogBaseUnits());
+ cyDlgUnit = HIWORD(GetDialogBaseUnits());
+
+ /* load the logo bitmap */
+ sprintf( logoPath, "%s\\logo.bmp", wGetAppLibDir());
+ hBmp = LoadImage( mswHInst, logoPath, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE );
+ if( !hBmp )
+ return( 0 );
+
+ /* get info about the loaded logo file */
+ GetObject( hBmp, sizeof(BITMAP), (LPVOID)&bmp );
+
+ /* calculate the size of dialog box */
+ cx = (bmp.bmWidth * 4) / cxDlgUnit; /* start with the size of the bitmap */
+ cy = (bmp.bmHeight * 8) / cyDlgUnit + 20; /* 20 is enough for two lines of text and some room */
+
+ /* allocate memory block for dialog template */
+ hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
+ if (!hgbl)
+ return -1;
+ lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
+
+ /* Define a dialog box. */
+ lpdt->style = WS_POPUP | WS_BORDER | WS_VISIBLE | DS_MODALFRAME | DS_CENTER;
+ lpdt->cdit = 3; // number of controls
+ lpdt->x = 0; lpdt->y = 0;
+ lpdt->cx = cx; lpdt->cy = cy;
+
+ lpw = (LPWORD) (lpdt + 1);
+ *lpw++ = 0; /* no menu */
+ *lpw++ = 0; /* predefined dialog box class (by default) */
+ *lpw++ = 0;
+
+ /* add the static control for the logo bitmap */
+ lpdit = (LPDLGITEMTEMPLATE)lpwAlign(lpw);
+ lpdit->x = 0; lpdit->y = 0;
+ lpdit->cx = (SHORT)((bmp.bmWidth * 4) / cxDlgUnit);
+ lpdit->cy = (SHORT)((bmp.bmHeight * 8) / cyDlgUnit);
+
+ lpdit->id = IDBITMAP;
+ lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0082; /* static class */
+
+ lpw += 1+MultiByteToWideChar (CP_ACP, 0, "Logo should be here...", -1, (LPWSTR)lpw, 50);
+
+ /* add the static control for the program title */
+ lpdit = (LPDLGITEMTEMPLATE)lpwAlign(lpw);
+
+ lpdit->x = 2; lpdit->y = (short)( 1 + (bmp.bmHeight * 8) / cyDlgUnit );
+ lpdit->cx = cx - 2; lpdit->cy = cyDlgUnit;
+ lpdit->id = IDAPPNAME;
+ lpdit->style = WS_CHILD | WS_VISIBLE | SS_CENTER;
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0082; /* static class */
+
+ /* create the title string */
+ pszBuf = malloc( strlen( appname ) + strlen( appver ) + 2 );
+ if( !pszBuf )
+ return( 0 );
+ sprintf( pszBuf, "%s %s", appname, appver );
+
+ lpw += 1+MultiByteToWideChar (CP_ACP, 0, pszBuf, -1, (LPWSTR)lpw, 50);
+
+ /* add the static control for the loading message */
+ lpdit = (LPDLGITEMTEMPLATE)lpwAlign(lpw);
+ lpdit->x = 2; lpdit->y = (short)(bmp.bmHeight * 8) / cyDlgUnit + 10;
+ lpdit->cx = cx - 2; lpdit->cy = cyDlgUnit;
+ lpdit->id = IDMESSAGE;
+ lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0082; /* static class */
+
+ lpw += 1+MultiByteToWideChar (CP_ACP, 0, "Starting Application...", -1, (LPWSTR)lpw, 50);
+
+ /* create the dialog */
+ GlobalUnlock(hgbl);
+ hSplash = CreateDialogIndirectParam( mswHInst, (LPDLGTEMPLATE) hgbl,
+ mswHWnd, (DLGPROC)SplashDlgProc, (LPARAM)hBmp );
+ GetLastError();
+
+ /* free allocated memory */
+ GlobalFree(hgbl);
+ free( pszBuf );
+
+ /* that's it */
+ return 1;
+}
+
+
+/**
+ * Update the progress message inside the splash window
+ * msg text message to display
+ * return nonzero if ok
+ */
+
+int
+wSetSplashInfo( char *msg )
+{
+ if( msg ) {
+ SetWindowText( GetDlgItem( hSplash, IDMESSAGE ), msg );
+ wFlush();
+ return TRUE;
+ }
+ wFlush();
+ return FALSE;
+}
+
+/**
+ * Remove the splash window from the screen.
+ */
+
+void
+wDestroySplash(void)
+{
+ DestroyWindow( hSplash );
+ return;
+} \ No newline at end of file
diff --git a/app/wlib/mswlib/mswtext.c b/app/wlib/mswlib/mswtext.c
new file mode 100644
index 0000000..95f6268
--- /dev/null
+++ b/app/wlib/mswlib/mswtext.c
@@ -0,0 +1,383 @@
+#include <windows.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <commdlg.h>
+#include <math.h>
+#include <stdio.h>
+#include "mswint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Multi-line Text Boxes
+ *
+ *****************************************************************************
+ */
+
+static LOGFONT fixedFont = {
+ /* Initial default values */
+ -18, 0, /* H, W */
+ 0, /* A */
+ 0,
+ FW_REGULAR,
+ 0, 0, 0,/* I, U, SO */
+ ANSI_CHARSET,
+ 0, /* OP */
+ 0, /* CP */
+ 0, /* Q */
+ FIXED_PITCH|FF_MODERN, /* P&F */
+ "Courier" };
+static HFONT fixedTextFont, prevTextFont;
+
+struct wText_t {
+ WOBJ_COMMON
+ HANDLE hText;
+ };
+
+BOOL_T textPrintAbort = FALSE;
+
+
+void wTextClear(
+ wText_p b )
+{
+ long rc;
+ rc = SendMessage( b->hWnd, EM_SETREADONLY, 0, 0L );
+#ifdef WIN32
+ rc = SendMessage( b->hWnd, EM_SETSEL, 0, -1 );
+#else
+ rc = SendMessage( b->hWnd, EM_SETSEL, 1, MAKELONG( 0, -1 ) );
+#endif
+ rc = SendMessage( b->hWnd, WM_CLEAR, 0, 0L );
+ if ( b->option&BO_READONLY )
+ rc = SendMessage( b->hWnd, EM_SETREADONLY, 1, 0L );
+}
+
+
+void wTextAppend(
+ wText_p b,
+ const char * text )
+{
+ HANDLE hMem;
+ char * pMem, *cp;
+ int len, textSize;
+ long rc;
+ long lc;
+ len = strlen(text);
+ if (len <= 0)
+ return;
+ for (cp= CAST_AWAY_CONST text; *cp; cp++) {
+ if ( *cp == '\n' )
+ len++;
+ }
+ hMem = GlobalAlloc( GHND, (DWORD)len+10+1 );
+ pMem = (char*)GlobalLock( hMem );
+ for (cp=pMem; *text; cp++,text++) {
+ if (*text == '\n') {
+ *cp++ = '\r';
+ *cp = '\n';
+ } else
+ *cp = *text;
+ }
+ textSize = LocalSize( b->hText );
+ if ((long)textSize+(long)len > 10000L) {
+ if (len < 1024)
+ len = 1024;
+#ifdef WIN32
+ rc = SendMessage( b->hWnd, EM_SETSEL, 0, len );
+#else
+ rc = SendMessage( b->hWnd, EM_SETSEL, 0, MAKELONG( 0, len ) );
+#endif
+ rc = SendMessage( b->hWnd, WM_CLEAR, 0, 0L );
+#ifdef WIN32
+ rc = SendMessage( b->hWnd, EM_SCROLLCARET, 0, 0 );
+#else
+ rc = SendMessage( b->hWnd, EM_SETSEL, 0, MAKELONG( 32767, 32767 ) );
+#endif
+ }
+ lc = SendMessage( b->hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L );
+ if ( lc < 0 )
+ lc = 0;
+ GlobalUnlock( hMem );
+ rc = OpenClipboard( b->hWnd );
+ rc = EmptyClipboard();
+ rc = (long)SetClipboardData( CF_TEXT, hMem );
+ rc = CloseClipboard();
+ rc = SendMessage( b->hWnd, EM_SETREADONLY, 0, 0L );
+ rc = SendMessage( b->hWnd, WM_PASTE, 0, 0L );
+ lc -= SendMessage( b->hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L );
+#ifdef LATER
+ if ( lc < 0 )
+ SendMessage( b->hWnd, EM_LINESCROLL, 0, MAKELPARAM((WPARAM)lc,0) );
+#endif
+ lc = GetWindowTextLength( b->hWnd );
+ if ( b->option&BO_READONLY )
+ rc = SendMessage( b->hWnd, EM_SETREADONLY, 1, 0L );
+}
+
+
+BOOL_T wTextSave(
+ wText_p b,
+ const char * fileName )
+{
+ FILE * f;
+ int lc, l, len;
+ char line[255];
+
+ f = wFileOpen( fileName, "w" );
+ if (f == NULL) {
+ MessageBox( ((wControl_p)(b->parent))->hWnd, "TextSave", "", MB_OK|MB_ICONHAND );
+ return FALSE;
+ }
+
+ lc = (int)SendMessage( b->hWnd, EM_GETLINECOUNT, 0, 0L );
+
+ for ( l=0; l<lc; l++ ) {
+ *(WORD*)line = sizeof(line)-1;
+ len = (int)SendMessage( b->hWnd, EM_GETLINE, l, (DWORD)(LPSTR)line );
+ line[len] = '\0';
+ fprintf( f, "%s\n", line );
+ }
+ fclose( f );
+ return TRUE;
+}
+
+
+BOOL_T wTextPrint(
+ wText_p b )
+{
+ int lc, l, len;
+ char line[255];
+ HDC hDc;
+ int lineSpace;
+ int linesPerPage;
+ int currentLine;
+ int IOStatus;
+ TEXTMETRIC textMetric;
+ DOCINFO docInfo;
+
+ hDc = mswGetPrinterDC();
+ if (hDc == (HDC)0) {
+ MessageBox( ((wControl_p)(b->parent))->hWnd, "Print", "Cannot print", MB_OK|MB_ICONHAND );
+ return FALSE;
+ }
+ docInfo.cbSize = sizeof(DOCINFO);
+ docInfo.lpszDocName = "XTrkcad Log";
+ docInfo.lpszOutput = (LPSTR)NULL;
+ if (StartDoc(hDc, &docInfo) < 0) {
+ MessageBox( ((wControl_p)(b->parent))->hWnd, "Unable to start print job", NULL, MB_OK|MB_ICONHAND );
+ DeleteDC( hDc );
+ return FALSE;
+ }
+ StartPage( hDc );
+ GetTextMetrics( hDc, &textMetric );
+ lineSpace = textMetric.tmHeight + textMetric.tmExternalLeading;
+ linesPerPage = GetDeviceCaps( hDc, VERTRES ) / lineSpace;
+ currentLine = 1;
+
+ lc = (int)SendMessage( b->hWnd, EM_GETLINECOUNT, 0, 0L );
+
+ IOStatus = 0;
+ for ( l=0; l<lc; l++ ) {
+ *(WORD*)line = sizeof(line)-1;
+ len = (int)SendMessage( b->hWnd, EM_GETLINE, l, (DWORD)(LPSTR)line );
+ TextOut( hDc, 0, currentLine*lineSpace, line, len );
+ if (++currentLine > linesPerPage) {
+ EndPage( hDc );
+ currentLine = 1;
+ IOStatus = EndPage(hDc);
+ if (IOStatus < 0 || textPrintAbort )
+ break;
+ StartPage( hDc );
+ }
+ }
+ if (IOStatus >= 0 && !textPrintAbort ) {
+ EndPage( hDc );
+ EndDoc( hDc );
+ }
+ DeleteDC( hDc );
+ return TRUE;
+}
+
+
+wBool_t wTextGetModified(
+ wText_p b )
+{
+ int rc;
+ rc = (int)SendMessage( b->hWnd, EM_GETMODIFY, 0, 0L );
+ return (wBool_t)rc;
+}
+
+int wTextGetSize(
+ wText_p b )
+{
+ int lc, l, li, len=0;
+ lc = (int)SendMessage( b->hWnd, EM_GETLINECOUNT, 0, 0L );
+ for ( l=0; l<lc ; l++ ) {
+ li = (int)SendMessage( b->hWnd, EM_LINEINDEX, l, 0L );
+ len += (int)SendMessage( b->hWnd, EM_LINELENGTH, l, 0L ) + 1;
+ }
+ if ( len == 1 )
+ len = 0;
+ return len;
+}
+
+void wTextGetText(
+ wText_p b,
+ char * t,
+ int s )
+{
+ int lc, l, len;
+ s--;
+ lc = (int)SendMessage( b->hWnd, EM_GETLINECOUNT, 0, 0L );
+ for ( l=0; l<lc && s>=0; l++ ) {
+ *(WORD*)t = s;
+ len = (int)SendMessage( b->hWnd, EM_GETLINE, l, (DWORD)(LPSTR)t );
+ t += len;
+ *t++ = '\n';
+ s -= len+1;
+ }
+ *t++ = '\0';
+}
+
+
+void wTextSetReadonly(
+ wText_p b,
+ wBool_t ro )
+{
+ if (ro)
+ b->option |= BO_READONLY;
+ else
+ b->option &= ~BO_READONLY;
+ SendMessage( b->hWnd, EM_SETREADONLY, ro, 0L );
+}
+
+
+void wTextSetSize(
+ wText_p bt,
+ wPos_t width,
+ wPos_t height )
+{
+ bt->w = width;
+ bt->h = height;
+ if (!SetWindowPos( bt->hWnd, HWND_TOP, 0, 0,
+ bt->w, bt->h, SWP_NOMOVE|SWP_NOZORDER)) {
+ mswFail("wTextSetSize: SetWindowPos");
+ }
+}
+
+
+void wTextComputeSize(
+ wText_p bt,
+ int rows,
+ int lines,
+ wPos_t * w,
+ wPos_t * h )
+{
+ static wPos_t scrollV_w = -1;
+ static wPos_t scrollH_h = -1;
+ HDC hDc;
+ TEXTMETRIC metrics;
+
+ if (scrollV_w < 0)
+ scrollV_w = GetSystemMetrics( SM_CXVSCROLL );
+ if (scrollH_h < 0)
+ scrollH_h = GetSystemMetrics( SM_CYHSCROLL );
+ hDc = GetDC( bt->hWnd );
+ GetTextMetrics( hDc, &metrics );
+ *w = rows * metrics.tmAveCharWidth + scrollV_w;
+ *h = lines * (metrics.tmHeight + metrics.tmExternalLeading);
+ ReleaseDC( bt->hWnd, hDc );
+ if (bt->option&BT_HSCROLL)
+ *h += scrollH_h;
+}
+
+
+void wTextSetPosition(
+ wText_p bt,
+ int pos )
+{
+ long rc;
+ rc = SendMessage( bt->hWnd, EM_LINESCROLL, 0, MAKELONG( -65535, 0 ) );
+}
+
+static void textDoneProc( wControl_p b )
+{
+ wText_p t = (wText_p)b;
+ HDC hDc;
+ hDc = GetDC( t->hWnd );
+ SelectObject( hDc, mswOldTextFont );
+ ReleaseDC( t->hWnd, hDc );
+}
+
+static callBacks_t textCallBacks = {
+ mswRepaintLabel,
+ textDoneProc,
+ NULL };
+
+wText_p wTextCreate(
+ wWin_p parent,
+ POS_T x,
+ POS_T y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ POS_T width,
+ POS_T height )
+{
+ wText_p b;
+ DWORD style;
+ RECT rect;
+ int index;
+
+ b = mswAlloc( parent, B_TEXT, labelStr, sizeof *b, NULL, &index );
+ mswComputePos( (wControl_p)b, x, y );
+ b->option = option;
+ style = ES_MULTILINE | ES_LEFT | ES_AUTOVSCROLL | ES_WANTRETURN |
+ WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL;
+#ifdef BT_HSCROLL
+ if (option & BT_HSCROLL)
+ style |= WS_HSCROLL | ES_AUTOHSCROLL;
+#endif
+/* if (option & BO_READONLY)
+ style |= ES_READONLY;*/
+
+ b->hWnd = CreateWindow( "EDIT", NULL,
+ style, b->x, b->y,
+ width, height,
+ ((wControl_p)parent)->hWnd, (HMENU)index, mswHInst, NULL );
+ if (b->hWnd == NULL) {
+ mswFail("CreateWindow(TEXT)");
+ return b;
+ }
+#ifdef CONTROL3D
+ Ctl3dSubclassCtl( b->hWnd );
+#endif
+
+ if (option & BT_FIXEDFONT) {
+ if (fixedTextFont == (HFONT)0)
+ fixedTextFont = CreateFontIndirect( &fixedFont );
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)fixedTextFont, (LPARAM)MAKELONG( 1, 0 ) );
+ } else if ( !mswThickFont ) {
+ SendMessage( b->hWnd, WM_SETFONT, (WPARAM)mswLabelFont, 0L );
+ }
+
+ b->hText = (HANDLE)SendMessage( b->hWnd, EM_GETHANDLE, 0, 0L );
+
+ if (option & BT_CHARUNITS) {
+ wPos_t w, h;
+ wTextComputeSize( b, width, height, &w, &h );
+ if (!SetWindowPos( b->hWnd, HWND_TOP, 0, 0,
+ w, h, SWP_NOMOVE|SWP_NOZORDER)) {
+ mswFail("wTextCreate: SetWindowPos");
+ }
+ }
+
+ GetWindowRect( b->hWnd, &rect );
+ b->w = rect.right - rect.left;
+ b->h = rect.bottom - rect.top;
+
+ mswAddButton( (wControl_p)b, FALSE, helpStr );
+ mswCallBacks[B_TEXT] = &textCallBacks;
+ return b;
+}
diff --git a/app/wlib/mswlib/simple-gettext.c b/app/wlib/mswlib/simple-gettext.c
new file mode 100644
index 0000000..295d515
--- /dev/null
+++ b/app/wlib/mswlib/simple-gettext.c
@@ -0,0 +1,522 @@
+/* simple-gettext.c - a simplified version of gettext.
+ * Copyright (C) 1995, 1996, 1997, 1999,
+ * 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of XTrackCAD.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* This is a simplified version of gettext written by Ulrich Drepper.
+ * It is used for the Win32 version of GnuPG beucase all the overhead
+ * of gettext is not needed and we have to do some special Win32 stuff.
+ * I decided that this is far easier than to tweak gettext for the special
+ * cases (I tried it but it is a lot of code). wk 15.09.99
+ */
+
+/*
+ * Based on the simple-gettext from GnuPG a version appropriate for the
+ * needs of XTrackCAD was derived. This is a workaround for any compiler
+ * specifics or runtime library dependencies. mf 26.07.09
+ */
+
+#ifdef USE_SIMPLE_GETTEXT
+#if !defined (_WIN32) && !defined (__CYGWIN32__)
+#error This file can only be used under Windows or Cygwin32
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <windows.h>
+
+#include "mswint.h"
+
+#if _MSC_VER > 1300
+ #define stricmp _stricmp
+ #define strnicmp _strnicmp
+ #define strdup _strdup
+ #define fileno _fileno
+#endif
+
+typedef unsigned long u32;
+
+/* The magic number of the GNU message catalog format. */
+#define MAGIC 0x950412de
+#define MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format. */
+#define MO_REVISION_NUMBER 0
+
+
+/* Header for binary .mo file format. */
+struct mo_file_header
+{
+ /* The magic number. */
+ u32 magic;
+ /* The revision number of the file format. */
+ u32 revision;
+ /* The number of strings pairs. */
+ u32 nstrings;
+ /* Offset of table with start offsets of original strings. */
+ u32 orig_tab_offset;
+ /* Offset of table with start offsets of translation strings. */
+ u32 trans_tab_offset;
+ /* Size of hashing table. */
+ u32 hash_tab_size;
+ /* Offset of first hashing entry. */
+ u32 hash_tab_offset;
+};
+
+struct string_desc
+{
+ /* Length of addressed string. */
+ u32 length;
+ /* Offset of string in file. */
+ u32 offset;
+};
+
+
+struct overflow_space_s
+{
+ struct overflow_space_s *next;
+ u32 idx;
+ char d[1];
+};
+
+struct loaded_domain
+{
+ char *data;
+ int must_swap;
+ u32 nstrings;
+ char *mapped; /* 0 = not yet mapped, 1 = mapped,
+ 2 = mapped to
+ overflow space */
+ struct overflow_space_s *overflow_space;
+ struct string_desc *orig_tab;
+ struct string_desc *trans_tab;
+ u32 hash_size;
+ u32 *hash_tab;
+};
+
+static struct loaded_domain *the_domain;
+
+/**
+ * Translate the input string from UTF8 to Windows codepage.
+ *
+ * \param str IN string in UTF-8 format to translate.
+ * \param len IN number of chars to translate
+ * \param dummy IN ?
+ * \return pointer to translated string. Free after usage
+ */
+char *
+utf8_to_native( char *str, unsigned int len, int dummy )
+{
+ /* maximum output length is size of string * 2 */
+ int buflen = (len + 1) * 2;
+ char *buf = malloc( buflen );
+ int wcharLen;
+ /* maximum result size is size of UTF-8 string */
+ char *resBuffer = malloc( len + 1 );
+
+ if( !resBuffer ) {
+ resBuffer = "ERROR in UTF-8 MALLOC";
+ } else {
+ /* as Windows has no way fo a direct translation fom UTF-8 to */
+ /* the system codepage, we need to take two steps */
+
+ /* 1. convert from UTF-8 to UTF-16 */
+ wcharLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)str, -1, (LPWSTR)buf, buflen / 2 );
+
+ /* 2. convert from UTF-8 to system codepage */
+ WideCharToMultiByte(CP_ACP, 0, (LPWSTR)buf, wcharLen, resBuffer, len + 1, NULL, NULL );
+
+ free( buf );
+ }
+ return( resBuffer );
+}
+
+
+static u32
+do_swap_u32( u32 i )
+{
+ return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+
+#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
+
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+/* The so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+
+static unsigned long
+hash_string( const char *str_param )
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned long int) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
+
+
+static struct loaded_domain *
+load_domain( const char *filename )
+{
+ FILE *fp;
+ size_t size;
+ struct stat st;
+ struct mo_file_header *data = NULL;
+ struct loaded_domain *domain = NULL;
+ size_t to_read;
+ char *read_ptr;
+
+ fp = fopen( filename, "rb" );
+ if( !fp )
+ return NULL; /* can't open the file */
+ /* we must know about the size of the file */
+ if( fstat( fileno(fp ), &st )
+ || (size = (size_t)st.st_size) != st.st_size
+ || size < sizeof (struct mo_file_header) ) {
+ fclose( fp );
+ return NULL;
+ }
+
+ data = malloc( size );
+ if( !data ) {
+ fclose( fp );
+ return NULL; /* out of memory */
+ }
+
+ to_read = size;
+ read_ptr = (char *) data;
+ do {
+ unsigned long int nb = fread( read_ptr, 1, to_read, fp );
+ if( nb < to_read ) {
+ fclose (fp);
+ free(data);
+ return NULL; /* read error */
+ }
+ read_ptr += nb;
+ to_read -= nb;
+ } while( to_read > 0 );
+ fclose (fp);
+
+ /* Using the magic number we can test whether it really is a message
+ * catalog file. */
+ if( data->magic != MAGIC && data->magic != MAGIC_SWAPPED ) {
+ /* The magic number is wrong: not a message catalog file. */
+ free( data );
+ return NULL;
+ }
+
+ domain = calloc( 1, sizeof *domain );
+ if( !domain ) {
+ free( data );
+ return NULL;
+ }
+ domain->data = (char *) data;
+ domain->must_swap = data->magic != MAGIC;
+
+ /* Fill in the information about the available tables. */
+ switch( SWAPIT(domain->must_swap, data->revision) ) {
+ case 0:
+ domain->nstrings = SWAPIT(domain->must_swap, data->nstrings);
+ domain->orig_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset));
+ domain->trans_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset));
+ domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size);
+ domain->hash_tab = (u32 *)
+ ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset));
+ break;
+
+ default: /* This is an invalid revision. */
+ free( data );
+ free( domain );
+ return NULL;
+ }
+
+ /* Allocate an array to keep track of code page mappings. */
+ domain->mapped = calloc( 1, domain->nstrings );
+ if( !domain->mapped ) {
+ free( data );
+ free( domain );
+ return NULL;
+ }
+
+ return domain;
+}
+
+
+/**
+ * Set the file used for translations. Pass a NULL to disable
+ * translation. A new filename may be set at anytime. WARNING:
+ * After changing the filename you should not access any data
+ * retrieved by gettext().
+ */
+int
+set_gettext_file ( const char *filename, const char *regkey )
+{
+ struct loaded_domain *domain = NULL;
+
+ if( filename && *filename ) {
+ if( filename[0] == '/'
+ || ( isalpha(filename[0])
+ && filename[1] == ':'
+ && (filename[2] == '/' || filename[2] == '\\') )
+ ) {
+ /* absolute path - use it as is */
+ domain = load_domain( filename );
+ }
+ if (!domain)
+ return -1;
+ }
+
+ if( the_domain ) {
+ struct overflow_space_s *os, *os2;
+ free( the_domain->data );
+ free( the_domain->mapped );
+ for (os=the_domain->overflow_space; os; os = os2) {
+ os2 = os->next;
+ free (os);
+ }
+ free( the_domain );
+ the_domain = NULL;
+ }
+ the_domain = domain;
+ return 0;
+}
+
+/**
+ * Return the required string from the message table. Before returning the result,
+ * codepage translation from UTF8 to current codepage is performed.
+ */
+
+static const char*
+get_string( struct loaded_domain *domain, u32 idx )
+{
+ struct overflow_space_s *os;
+ char *p;
+
+ p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
+ if (!domain->mapped[idx])
+ {
+ size_t plen, buflen;
+ char *buf;
+
+ domain->mapped[idx] = 1;
+
+ plen = strlen (p);
+ buf = utf8_to_native (p, plen, -1);
+ buflen = strlen (buf);
+ if (buflen <= plen){
+ strcpy (p, buf);
+ free( buf );
+ } else {
+ /* There is not enough space for the translation - store it
+ in the overflow_space else and mark that in the mapped
+ array. Because we expect that this won't happen too
+ often, we use a simple linked list. */
+ os = malloc (sizeof *os + buflen);
+ if (os)
+ {
+ os->idx = idx;
+ strcpy (os->d, buf);
+ os->next = domain->overflow_space;
+ domain->overflow_space = os;
+ p = os->d;
+ }
+ else
+ p = "ERROR in GETTEXT MALLOC";
+ free (buf);
+ }
+ }
+ else if (domain->mapped[idx] == 2)
+ { /* We need to get the string from the overflow_space. */
+ for (os=domain->overflow_space; os; os = os->next)
+ if (os->idx == idx)
+ return (const char*)os->d;
+ p = "ERROR in GETTEXT\n";
+ }
+ return (const char*)p;
+}
+
+/**
+ * This is the translation function itself.
+ */
+
+char *
+gettext( char *msgid )
+{
+ struct loaded_domain *domain;
+ size_t act = 0;
+ size_t top, bottom;
+
+ if( !(domain = the_domain) )
+ goto not_found;
+
+ /* Locate the MSGID and its translation. */
+ if( domain->hash_size > 2 && domain->hash_tab ) {
+ /* Use the hashing table. */
+ u32 len = strlen (msgid);
+ u32 hash_val = hash_string (msgid);
+ u32 idx = hash_val % domain->hash_size;
+ u32 incr = 1 + (hash_val % (domain->hash_size - 2));
+ u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
+
+ if ( !nstr ) /* Hash table entry is empty. */
+ goto not_found;
+
+ if( SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp( msgid,
+ domain->data + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].offset)) )
+ return (char *)get_string( domain, nstr - 1 );
+
+ for(;;) {
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+
+ nstr = SWAPIT(domain->must_swap, domain->hash_tab[idx]);
+ if( !nstr )
+ goto not_found; /* Hash table entry is empty. */
+
+ if ( SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp (msgid,
+ domain->data + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].offset)))
+ return (char *)get_string( domain, nstr-1 );
+ }
+ /* NOTREACHED */
+ }
+
+ /* Now we try the default method: binary search in the sorted
+ array of messages. */
+ bottom = 0;
+ top = domain->nstrings;
+ while( bottom < top ) {
+ int cmp_val;
+
+ act = (bottom + top) / 2;
+ cmp_val = strcmp(msgid, domain->data
+ + SWAPIT(domain->must_swap,
+ domain->orig_tab[act].offset));
+ if (cmp_val < 0)
+ top = act;
+ else if (cmp_val > 0)
+ bottom = act + 1;
+ else
+ return (char *)get_string( domain, act );
+ }
+
+ not_found:
+ return msgid;
+}
+
+/**
+ * This is the main initialization function for simple gettext. The message file is
+ * opened and read into memory. The function must be called once before translating
+ * a string.
+ *
+ * The message files are expected to be in a directory named in the UNIXish form en_US
+ * in the path passed to this function. The filename is expected to be domainname.mo
+ *
+ * \param domainname IN domain
+ * \param dirname IN directory for the message files
+ * \return always NULL
+ */
+
+char *
+bindtextdomain( char *domainname, char *dirname )
+{
+ char *loc;
+ char *dir;
+
+ /* get thread's locale in UNIXish style eg. en_US */
+ loc = g_win32_getlocale();
+
+ /* make sure that path does not end with trailing slash */
+ if( dirname[ strlen(dirname) ] == '/' )
+ dirname[ strlen(dirname) ] = '\0';
+
+ /* allocate buffer for filename, 20 bytes should be enough for extension etc. */
+ dir = malloc( strlen( domainname ) + strlen( dirname ) + strlen( loc ) + 20 );
+
+ if( dir ) {
+ /* create the full filename */
+ sprintf( dir, "%s/%s/LC_MESSAGES/%s.mo", dirname, loc, domainname );
+ /* load the file */
+ set_gettext_file( dir, NULL );
+ free( dir );
+ }
+
+ free( loc );
+ return( NULL );
+}
+
+/**
+ * This is a dummy function to maintain source code compatibility
+ * with other implementations of gettext.
+ * For this implementation, UTF-8 input encoding is assumed
+ *
+ * \param domainname IN domain
+ * \param codeset In codeset
+ * \return always NULL
+ */
+
+char *
+bind_textdomain_codeset(char *domainname, char *codeset )
+{
+ return( NULL );
+}
+
+/**
+ * This is a dummy function to maintain source code compatibility
+ * with other implementations of gettext.
+ *
+ * \param domainname IN domain
+ * \return always NULL
+ */
+
+char *
+textdomain( char *domainname )
+{
+ return( NULL );
+}
+#endif /* USE_SIMPLE_GETTEXT */
diff --git a/app/wlib/mswlib/square10.bmp b/app/wlib/mswlib/square10.bmp
new file mode 100644
index 0000000..c45fb75
--- /dev/null
+++ b/app/wlib/mswlib/square10.bmp
@@ -0,0 +1,6 @@
+#define square10_width 14
+#define square10_height 14
+static unsigned char square10_bits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff};