summaryrefslogtreecommitdiff
path: root/app/wlib/mswlib/mswmisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/mswlib/mswmisc.c')
-rw-r--r--app/wlib/mswlib/mswmisc.c2778
1 files changed, 2778 insertions, 0 deletions
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;
+}