diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-12-28 16:52:56 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-12-28 16:52:56 +0100 | 
| commit | 7b358424ebad9349421acd533c2fa1cbf6cf3e3e (patch) | |
| tree | 686678532eefed525c242fd214d0cfb2914726c5 /app/wlib/mswlib | |
Initial import of xtrkcad version 1:4.0.2-2
Diffstat (limited to 'app/wlib/mswlib')
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 ×Font[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}; | 
