OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/MW_0_8_9PRE7/mw/src/mwin/winlib
    from Rev 674 to Rev 1765
    Reverse comparison

Rev 674 → Rev 1765

/caret.c
0,0 → 1,184
/*
* Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Caret control for Microwindows win32 api.
*
* TODO: add SetSysTimer for blinking
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#ifndef __ECOS
#include <malloc.h>
#endif
#include "windows.h"
#include "device.h"
 
#define DEF_BLINK_TIME 500 /* default blink time in ms*/
 
typedef struct {
HWND hwnd; /* != NULL if caret is created*/
int x;
int y;
int nWidth;
int nHeight;
BOOL fShown; /* caret is currently visible*/
int nShowCount; /* <= 0 for hidden caret*/
UINT nBlinkTime;
} CARETINFO;
 
/* local data*/
static CARETINFO sysCaret; /* the system caret*/
 
/* local procs*/
static void MwShowCaret(void);
static void MwHideCaret(void);
static void MwUpdateCaret(void);
 
BOOL WINAPI
CreateCaret(HWND hwnd, HBITMAP hBitmap, int nWidth, int nHeight)
{
 
DestroyCaret(); /* destroy old caret if any*/
 
if (nWidth <= 0)
nWidth = 1;
if (nHeight <= 0)
nHeight = 1;
 
sysCaret.hwnd = hwnd;
sysCaret.x = 0;
sysCaret.y = 0;
sysCaret.nWidth = nWidth;
sysCaret.nHeight = nHeight;
sysCaret.fShown = FALSE;
sysCaret.nShowCount = 0;
sysCaret.nBlinkTime = DEF_BLINK_TIME;
return TRUE;
}
 
BOOL WINAPI
DestroyCaret(VOID)
{
if (sysCaret.fShown)
MwHideCaret();
sysCaret.hwnd = NULL;
sysCaret.fShown = FALSE;
return TRUE;
}
 
BOOL WINAPI
HideCaret(HWND hwnd)
{
if (hwnd == NULL)
hwnd = sysCaret.hwnd;
if (hwnd == NULL || hwnd != sysCaret.hwnd)
return FALSE;
 
/* hide caret if this call made it invisible*/
if (--sysCaret.nShowCount == 0) {
MwHideCaret();
return TRUE;
}
return FALSE;
}
 
BOOL WINAPI
ShowCaret(HWND hwnd)
{
if (hwnd == NULL)
hwnd = sysCaret.hwnd;
if (hwnd == NULL || hwnd != sysCaret.hwnd || sysCaret.nShowCount < 0)
return FALSE;
 
if (++sysCaret.nShowCount > 1)
return TRUE;
 
/* show caret, this call made it visible*/
MwShowCaret();
return TRUE;
}
 
BOOL WINAPI
SetCaretPos(int nX, int nY)
{
if (sysCaret.fShown && (sysCaret.x != nX || sysCaret.y != nY)) {
MwUpdateCaret(); /* toggle off*/
sysCaret.x = nX;
sysCaret.y = nY;
MwUpdateCaret(); /* toggle on in new location*/
return TRUE;
}
sysCaret.x = nX;
sysCaret.y = nY;
return TRUE;
}
 
BOOL WINAPI
GetCaretPos(LPPOINT lpPoint)
{
lpPoint->x = sysCaret.x;
lpPoint->y = sysCaret.y;
return TRUE;
}
 
UINT WINAPI
GetCaretBlinkTime(VOID)
{
return sysCaret.nBlinkTime;
}
 
BOOL WINAPI
SetCaretBlinkTime(UINT uMSeconds)
{
sysCaret.nBlinkTime = uMSeconds;
/* SetSysTimer */
return TRUE;
}
 
static void
MwShowCaret(void)
{
if (sysCaret.fShown)
return;
MwUpdateCaret();
sysCaret.fShown = TRUE;
}
 
static void
MwHideCaret(void)
{
if (!sysCaret.fShown)
return;
MwUpdateCaret();
sysCaret.fShown = FALSE;
}
 
/* Draw the caret using XOR. Same routine is used to show and hide caret.*/
static void
MwUpdateCaret(void)
{
int oldmode;
HDC hdc;
HPEN hpen;
HBRUSH hbr;
 
oldmode = GdSetMode(MWMODE_XOR);
hdc = GetDC(sysCaret.hwnd);
hpen = SelectObject(hdc, GetStockObject(WHITE_PEN));
 
/* it seems there's some problems with Rectangle with nWidth == 1*/
if (sysCaret.nWidth == 1) {
MoveToEx(hdc, sysCaret.x, sysCaret.y, NULL);
LineTo(hdc, sysCaret.x, sysCaret.y+sysCaret.nHeight);
} else {
hbr = SelectObject(hdc, GetStockObject(WHITE_BRUSH));
Rectangle(hdc, sysCaret.x, sysCaret.y,
sysCaret.x+sysCaret.nWidth,
sysCaret.y+sysCaret.nHeight);
SelectObject(hdc, hbr);
}
SelectObject(hdc, hpen);
ReleaseDC(sysCaret.hwnd, hdc);
GdSetMode(oldmode);
}
/medit.c
0,0 → 1,1744
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Multi Line Edit Control for Microwindows win32 api.
*/
 
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library 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
*/
 
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
 
/* Note:
** Although there was a version by Zhao Jianghua, this version of
** EDIT control is written by Wei Yongming from scratch.
**
** Create date: 1999/8/26
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/08/30 gv port to microwin ported
**
**
** TODO:
** * Selection.
** * Undo.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#define MWINCLUDECOLORS
#include "windows.h" /* windef.h, winuser.h */
#include "wintools.h"
#include "device.h" /* GdGetTextSize */
 
#define USE_BIG5
 
#define WIDTH_MEDIT_BORDER 2
#define MARGIN_MEDIT_LEFT 1
#define MARGIN_MEDIT_TOP 1
#define MARGIN_MEDIT_RIGHT 2
#define MARGIN_MEDIT_BOTTOM 1
 
#define LEN_MLEDIT_BUFFER 3000
#define LEN_MLEDIT_UNDOBUFFER 1024
 
#define EST_FOCUSED 0x00000001L
#define EST_MODIFY 0x00000002L
#define EST_READONLY 0x00000004L
#define EST_REPLACE 0x00000008L
 
#define MEDIT_OP_NONE 0x00
#define MEDIT_OP_DELETE 0x01
#define MEDIT_OP_INSERT 0x02
#define MEDIT_OP_REPLACE 0x03
 
typedef struct tagLINEDATA {
 
int dataEnd;
 
 
char buffer[LEN_MLEDIT_BUFFER+1];
}LINEDATA;
typedef LINEDATA* PLINEDATA;
 
#define ATTENG 0 /* english */
#define ATTCHL 1 /* chinese left(1st) byte */
#define ATTCHR 2 /* chinese right(2nd) byte */
static char attr[LEN_MLEDIT_BUFFER];
 
typedef struct tagMLEDITDATA {
 
 
int editPos; /* current edit position */
int caretPos; /* caret offset in box */
int editLine; /* current eidt line */
 
int StartlineDisp; /* start line displayed */
int EndlineDisp; /* end line displayed */
 
 
 
int selStartPos; /* selection start position */
int selStartLine; /* selection start line */
int selEndPos; /* selection end position */
int selEndLine; /* selection end line */
int passwdChar; /* password character */
int leftMargin; /* left margin */
int topMargin; /* top margin */
int rightMargin; /* right margin */
int bottomMargin; /* bottom margin */
int hardLimit; /* hard limit */
 
int lastOp; /* last operation */
int lastPos; /* last operation position */
int lastLine; /* last operation line */
int affectedLen; /* affected len of last operation */
int undoBufferLen; /* undo buffer len */
char undoBuffer [LEN_MLEDIT_UNDOBUFFER];
/* Undo buffer; */
PLINEDATA head; /* buffer */
 
}MLEDITDATA;
typedef MLEDITDATA* PMLEDITDATA;
 
BOOL RegisterMLEditControl (void);
 
int MLEditCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
 
#define PIXEL_invalid (-1)
extern HWND sg_hCaretWnd;
extern HWND rootwp;
 
static int GetSysCharHeight (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
 
return xh;
#else
return 12;
#endif
}
 
static int GetSysCharWidth (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
 
return xw;
#else
return 6;
#endif
}
 
static int GetSysCCharWidth (HWND hwnd)
{
return (2*GetSysCharWidth(hwnd));
}
char* GetWindowCaption (HWND hWnd)
{
return hWnd->szTitle;
}
 
DWORD GetWindowAdditionalData (HWND hWnd)
{
return hWnd->userdata;
}
 
DWORD SetWindowAdditionalData (HWND hWnd, DWORD newData)
{
DWORD oldOne = 0L;
 
oldOne = hWnd->userdata;
hWnd->userdata = newData;
return oldOne;
}
 
DWORD GetWindowAdditionalData2 (HWND hWnd)
{
return hWnd->userdata2;
}
 
DWORD SetWindowAdditionalData2 (HWND hWnd, DWORD newData)
{
DWORD oldOne = 0L;
 
oldOne = hWnd->userdata2;
hWnd->userdata2 = newData;
return oldOne;
}
 
DWORD GetWindowStyle (HWND hWnd)
{
return hWnd->style;
}
 
BOOL ExcludeWindowStyle (HWND hWnd, DWORD dwStyle)
{
if (hWnd == rootwp/*HWND_DESKTOP*/)
return FALSE;
 
hWnd->style &= ~dwStyle;
return TRUE;
}
 
BOOL IncludeWindowStyle (HWND hWnd, DWORD dwStyle)
{
 
if (hWnd == rootwp/*HWND_DESKTOP*/)
return FALSE;
 
hWnd->style |= dwStyle;
return TRUE;
}
 
int WINAPI MwRegisterMEditControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)MLEditCtrlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "MEDIT";
 
return RegisterClass(&wc);
}
 
static inline int edtGetOutWidth (HWND hWnd)
{
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
RECT rc;
GetClientRect(hWnd,&rc);
return rc.right - rc.left
- pMLEditData->leftMargin
- pMLEditData->rightMargin;
}
 
static int edtGetStartDispPosAtEnd (HWND hWnd,
PLINEDATA pLineData)
{
int nOutWidth = edtGetOutWidth (hWnd);
int endPos = pLineData->dataEnd;
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
int newStartPos = pMLEditData->dispPos;
const char* buffer = pLineData->buffer;
 
if(endPos < newStartPos)
return 0;
while (TRUE)
{
if ((endPos - newStartPos) * GetSysCharWidth (hWnd) < nOutWidth)
break;
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [newStartPos] > 0xA0)
{
newStartPos ++;
if (newStartPos < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [newStartPos] > 0xA0)
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [newStartPos] >= 0x40 && (BYTE)buffer[newStartPos] <= 0x7e) ||
((BYTE)buffer [newStartPos] >= 0xa1 && (BYTE)buffer[newStartPos] <= 0xfe))
#endif
newStartPos ++;
}
}
else
newStartPos ++;
}
return newStartPos;
}
 
static int edtGetDispLen (HWND hWnd,PLINEDATA pLineData)
{
int i, n = 0;
int nOutWidth = edtGetOutWidth (hWnd);
int nTextWidth = 0;
PMLEDITDATA pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
const char* buffer = pLineData->buffer;
if(buffer[0]==0||pLineData->dataEnd<pMLEditData->dispPos)
return 0;
for (i = pMLEditData->dispPos; i < pLineData->dataEnd; i++)
{
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [i] > 0xA0)
{
i++;
if (i < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (hWnd);
n += 2;
}
else
i--;
}
else
{
nTextWidth += GetSysCharWidth (hWnd);
n++;
}
}
else
{
nTextWidth += GetSysCharWidth (hWnd);
n++;
}
 
if (nTextWidth > nOutWidth)
break;
}
 
return n;
}
 
static int edtGetOffset (HWND hwnd,const MLEDITDATA* pMLEditData, PLINEDATA pLineData, int x)
{
int i;
int newOff = 0;
int nTextWidth = 0;
const char* buffer = pLineData->buffer;
 
if(pLineData->dataEnd<pMLEditData->dispPos)
return pLineData->dataEnd;
 
x -= pMLEditData->leftMargin;
for (i = pMLEditData->dispPos; i < pLineData->dataEnd; i++) {
if ((nTextWidth + (GetSysCharWidth(hwnd) >> 1)) >= x)
break;
 
/* 1st:gb:a1-f7,big5:a1-f9 */
if ((BYTE)buffer [i] > 0xA0)
{
i++;
 
if (nTextWidth + GetSysCCharWidth(hwnd)/2 >= x)
break;
 
if (i < pLineData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (hwnd);
newOff += 2;
}
else
i --;
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
}
return newOff;
}
 
static int edtGetLineNO (HWND hwnd,const MLEDITDATA* pMLEditData, int x)
{
int nline = 0;
if(x>=0)
{
nline = x / GetSysCharHeight(hwnd);
if (nline <= pMLEditData->linesDisp)
return nline;
}
return -1;
}
 
static BOOL edtIsACCharAtPosition (const char* string, int len, int pos)
{
if (pos > (len - 2))
return FALSE;
 
/* 1st:gb:a1-f7,big5:a1-f9 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#ifndef USE_BIG5
if ((BYTE)string [pos] > 0xA0 && (BYTE)string [pos + 1] > 0xA0)
return TRUE;
#else
if ((BYTE)string [pos] > 0xA0)
{
if ( ((BYTE)string [pos + 1] >= 0x40 && (BYTE)string [pos + 1] <= 0x7e) ||
((BYTE)string [pos + 1] >= 0xa1 && (BYTE)string [pos + 1] <= 0xfe)) {
/*fprintf(stderr,"true\n");
fflush(stderr);*/
return TRUE;
}
}
#endif
 
return FALSE;
}
 
static void str2attr(const char* str,int len)
{
int i=0;
do
{
if (edtIsACCharAtPosition(str,len,i))
{
attr[i]=ATTCHL;
attr[i+1]=ATTCHR;
i+=2;
}
else
{
attr[i]=ATTENG;
i++;
}
}while(i<len);
}
 
static BOOL edtIsACCharBeforePosition (const char* string,int len, int pos)
{
if (pos < 2)
return FALSE;
 
/* 1st:gb:a1-f7,big5:a1-f9 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#ifndef USE_BIG5
/* FIXME #ifdef GB2312?*/
if ((BYTE)string [pos - 2] > 0xA0 && (BYTE)string [pos - 1] > 0xA0)
return TRUE;
#else
#if 0
if ((BYTE)string [pos - 2] > 0xA0)
{
if ( ((BYTE)string [pos - 1] >= 0x40 && (BYTE)string[pos - 1] <= 0x7e) ||
((BYTE)string [pos - 1] >= 0xa1 && (BYTE)string[pos - 1] <= 0xfe))
return TRUE;
}
#else
str2attr(string,len);
if (attr[pos-1]==ATTENG) return FALSE;
else return TRUE;
#endif
#endif
 
return FALSE;
}
 
 
static BOOL edtIsACCharFromBegin(const char* string,int len,int pos)
{
int i;
if(pos == 0)
return TRUE;
if(len == 0)
return FALSE;
for(i=0;i<len;)
{
if( edtIsACCharAtPosition(string,len,i) )
i += 2;
else
i++;
if(i==pos)
return TRUE;
}
return FALSE;
}
 
int GetRETURNPos(char *str)
{
int i;
for(i=0;i<strlen(str);i++)
{
if(str[i]==10)
return i;
}
return -1;
}
 
void MLEditInitBuffer (PMLEDITDATA pMLEditData,char *spcaption)
{
char *caption=spcaption;
int off1;
int lineNO=0;
PLINEDATA pLineData;
if (!(pMLEditData->head = malloc (sizeof (LINEDATA)))) {
fprintf (stderr, "EDITLINE: malloc error!\n");
return ;
}
pMLEditData->head->previous = NULL;
pLineData=pMLEditData->head;
while ( (off1 = GetRETURNPos(caption)) != -1)
{
off1 = min(off1, LEN_MLEDIT_BUFFER);
memcpy(pLineData->buffer,caption,off1);
pLineData->buffer[off1] = '\0';
caption+=min(off1,LEN_MLEDIT_BUFFER)+1;
pLineData->lineNO = lineNO;
pMLEditData->dispPos = 0;
pLineData->dataEnd = strlen(pLineData->buffer);
pLineData->next = malloc (sizeof (LINEDATA));
pLineData->next->previous = pLineData;
pLineData = pLineData->next;
lineNO++;
}
off1 = min(strlen(caption),LEN_MLEDIT_BUFFER);
memcpy(pLineData->buffer,caption,off1);
pLineData->buffer[off1] = '\0';
pLineData->lineNO = lineNO++;
pMLEditData->dispPos = 0;
pLineData->dataEnd = strlen(pLineData->buffer);
pLineData->next = NULL;
pMLEditData->lines = lineNO ;
}
 
PLINEDATA GetLineData(PMLEDITDATA pMLEditData,int lineNO)
{
PLINEDATA pLineData=pMLEditData->head;
while(pLineData)
{
if(pLineData->lineNO==lineNO)
return pLineData;
pLineData = pLineData->next;
}
return NULL;
}
 
int MLEditCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
DWORD dwStyle;
DWORD dw;
HDC hdc;
PLINEDATA pLineData;
RECT clientRect;
PMLEDITDATA pMLEditData;
dwStyle = GetWindowStyle(hWnd);
 
switch (message)
{
case WM_CREATE:
{
if (!(pMLEditData = malloc (sizeof (MLEDITDATA)))) {
fprintf (stderr, "EDIT: malloc error!\n");
return -1;
}
 
pMLEditData->totalLen = LEN_MLEDIT_BUFFER;
pMLEditData->editPos = 0;
pMLEditData->editLine = 0;
pMLEditData->caretPos = 0;
 
MLEditInitBuffer(pMLEditData,GetWindowCaption(hWnd));
 
GetClientRect(hWnd,&clientRect);
pMLEditData->MaxlinesDisp = (clientRect.bottom-clientRect.top)/GetSysCharHeight(hWnd);
pMLEditData->linesDisp = min(pMLEditData->MaxlinesDisp,pMLEditData->lines);
pMLEditData->StartlineDisp = 0;
pMLEditData->EndlineDisp = pMLEditData->StartlineDisp + pMLEditData->linesDisp - 1;
 
pMLEditData->selStartPos = 0;
pMLEditData->selEndPos = 0;
pMLEditData->passwdChar = '*';
pMLEditData->leftMargin = MARGIN_MEDIT_LEFT;
pMLEditData->topMargin = MARGIN_MEDIT_TOP;
pMLEditData->rightMargin = MARGIN_MEDIT_RIGHT;
pMLEditData->bottomMargin = MARGIN_MEDIT_BOTTOM;
 
pMLEditData->hardLimit = -1;
/* undo information */
pMLEditData->lastOp = MEDIT_OP_NONE;
pMLEditData->lastPos = 0;
pMLEditData->affectedLen = 0;
pMLEditData->undoBufferLen = LEN_MLEDIT_UNDOBUFFER;
pMLEditData->undoBuffer [0] = '\0';
SetWindowAdditionalData2(hWnd,(DWORD)pMLEditData);
SetWindowAdditionalData(hWnd,(DWORD)0);
break;
}
case WM_DESTROY:
{
PLINEDATA temp;
pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
DestroyCaret ();
pLineData = pMLEditData->head;
while(pLineData)
{
/*printf("delete lineNO = %d,buffer=%s\n",pLineData->lineNO,pLineData->buffer);*/
temp = pLineData->next;
free(pLineData);
pLineData = temp;
}
free(pMLEditData);
}
break;
case WM_SETFONT:
break;
case WM_GETFONT:
break;
 
#if 0 /* fix: no WM_SETCURSOR */
case WM_SETCURSOR:
if (dwStyle & WS_DISABLED) {
SetCursor (GetSystemCursor (IDC_ARROW));
return 0;
}
break;
 
case WM_SIZECHANGED:
{
}
return 0;
#endif
case WM_KILLFOCUS:
{
dw= GetWindowAdditionalData(hWnd);
dw&= ~EST_FOCUSED;
SetWindowAdditionalData(hWnd,dw);
 
HideCaret (hWnd);
DestroyCaret ();
 
SendMessage (GetParent (hWnd),
WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_KILLFOCUS),
(LPARAM)hWnd);
}
break;
case WM_SETFOCUS:
{
dw= GetWindowAdditionalData(hWnd);
if (dw & EST_FOCUSED)
return 0;
dw |= EST_FOCUSED;
SetWindowAdditionalData(hWnd,dw);
 
pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
 
/* only implemented for ES_LEFT align format. */
 
CreateCaret (hWnd, NULL, 1, /*GetSysCharWidth(hWnd)+1,*/
hWnd->clirect.bottom-hWnd->clirect.top-2);
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin, pMLEditData->topMargin);
ShowCaret(hWnd);
 
SendMessage (GetParent (hWnd),
WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_SETFOCUS),
(LPARAM) hWnd);
}
break;
case WM_ENABLE:
if ( (!(dwStyle & WS_DISABLED) && !wParam)
|| ((dwStyle & WS_DISABLED) && wParam) ) {
if (wParam)
ExcludeWindowStyle(hWnd,WS_DISABLED);
else
IncludeWindowStyle(hWnd,WS_DISABLED);
 
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
 
case WM_NCPAINT:
{
RECT rc;
#if 0
if (wParam)
hdc = (HDC)wParam;
else
hdc = GetDC (hWnd);
#if 0 /* fix: no ClipRectIntersect() */
if (lParam)
ClipRectIntersect (hdc, (RECT*)lParam);
#endif
#else
hdc = wParam? (HDC)wParam: GetWindowDC (hWnd);
GetWindowRect(hWnd, &rc);
#endif
if (dwStyle & WS_BORDER)
{
#if 0
RECT rc;
GetWindowRect(hWnd,&rc);
Draw3DDownFrame (hdc, 0, 0,
rc.right - rc.left - 1,
rc.bottom - rc.top - 1,
PIXEL_invalid);
#else
Draw3dInset(hdc, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top);
#endif
}
if (!wParam) {
ReleaseDC(hWnd,hdc);
}
}
return 0;
 
case WM_PAINT:
{
int dispLen,i;
char* dispBuffer;
RECT rect,rc;
PAINTSTRUCT ps;
HGDIOBJ oldfont=NULL;
hdc = BeginPaint (hWnd,&ps);
GetClientRect (hWnd, &rect);
if (dwStyle & WS_DISABLED)
{
rc.left=0; rc.top=0; rc.bottom=rect.bottom; rc.right=rect.right;
FillRect(hdc,&rc,GetStockObject(LTGRAY_BRUSH));
SetBkColor (hdc, LTGRAY/*PIXEL_lightgray*/);
}
else {
rc.left=0; rc.top=0; rc.bottom=rect.bottom; rc.right=rect.right;
FillRect(hdc,&rc,GetStockObject(WHITE_BRUSH));
SetBkColor (hdc, WHITE/*PIXEL_lightwhite*/);
}
 
SetTextColor (hdc, BLACK/*PIXEL_black*/);
 
pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
for(i = pMLEditData->StartlineDisp; i <= pMLEditData->EndlineDisp; i++)
{
pLineData= GetLineData(pMLEditData,i);
dispLen = edtGetDispLen (hWnd,pLineData);
if (dispLen == 0 && pMLEditData->EndlineDisp >= pMLEditData->lines) {
continue;
}
 
#ifdef _DEBUG
if (pMLEditData->dispPos > pLineData->dataEnd)
fprintf (stderr, "ASSERT failure: %s.\n", "Edit Paint");
#endif
dispBuffer = alloca (LEN_MLEDIT_BUFFER+1);
 
if (dwStyle & ES_PASSWORD)
memset (dispBuffer, '*', pLineData->dataEnd);
memcpy (dispBuffer,
pLineData->buffer, /* +pMLEditData->dispPos, */
pLineData->dataEnd); /* - pMLEditData->dispPos); */
dispBuffer[pLineData->dataEnd] = '\0';
 
/* only implemented ES_LEFT align format for single line edit. */
rect.left = pMLEditData->leftMargin;
rect.top = pMLEditData->topMargin ;
rect.right = pMLEditData->rightMargin;
rect.bottom = pMLEditData->bottomMargin;
#if 0
printf("lineNO=%d,lines=%d,editLine=%d\n",pLineData->lineNO,pMLEditData->lines,
pMLEditData->editLine);
printf("--dispBuffer=%s--\n",dispBuffer);
ClipRectIntersect (hdc, &rect); /* fix: no ClipRectIntersect() */
#endif
 
#ifdef USE_BIG5
oldfont=SelectObject(hdc,CreateFont(12,
0,0,0,0,0,0,0,0,0,0,0,
FF_DONTCARE|DEFAULT_PITCH,
"HZXFONT"));
#endif
TextOut (hdc,
pMLEditData->leftMargin - pMLEditData->dispPos * GetSysCharWidth(hWnd) ,
GetSysCharHeight(hWnd)*(pLineData->lineNO - pMLEditData->StartlineDisp)
+ pMLEditData->topMargin,
dispBuffer,-1);
}
#ifdef USE_BIG5
DeleteObject(SelectObject(hdc,oldfont));
#endif
EndPaint (hWnd, &ps);
}
break;
 
case WM_KEYDOWN:
{
BOOL bChange = FALSE;
int i;
int deleted;
PLINEDATA temp = NULL;
char * tempP = NULL;
 
pMLEditData =(PMLEDITDATA) GetWindowAdditionalData2(hWnd);
switch (LOWORD (wParam))
{
case VK_RETURN: /* SCANCODE_ENTER: */
{
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
if (pMLEditData->editPos < pLineData->dataEnd)
tempP = pLineData->buffer + pMLEditData->editPos;
temp = pLineData->next;
pLineData->next = malloc( sizeof(LINEDATA) );
pLineData->next->previous = pLineData;
pLineData->next->next = temp;
if(temp)
{
temp->previous = pLineData->next;
}
temp = pLineData->next;
temp->lineNO = pMLEditData->editLine + 1;
if(tempP)
{
memcpy(temp->buffer,tempP,strlen(tempP));
temp->dataEnd = strlen(tempP);
}
else
temp->dataEnd = 0;
temp->buffer[temp->dataEnd] = '\0';
pLineData->dataEnd = pMLEditData->editPos;
pLineData->buffer[pLineData->dataEnd]='\0';
temp = temp->next;
while (temp)
{
temp->lineNO++;
temp = temp->next;
}
pMLEditData->editPos = 0;
pMLEditData->caretPos= 0;
pMLEditData->dispPos = 0;
if(pMLEditData->linesDisp < pMLEditData->MaxlinesDisp)
{
pMLEditData->EndlineDisp++;
pMLEditData->linesDisp++;
}
else if(pMLEditData->editLine == pMLEditData->EndlineDisp)
{
pMLEditData->StartlineDisp++;
pMLEditData->EndlineDisp++;
}
pMLEditData->editLine++;
pMLEditData->lines++;
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+pMLEditData->topMargin);
InvalidateRect (hWnd, NULL, FALSE);
return 0;
}
case VK_HOME: /* SCANCODE_HOME: */
{
PLINEDATA temp;
if (pMLEditData->editPos == 0)
return 0;
 
pMLEditData->editPos = 0;
pMLEditData->caretPos = 0;
 
SetCaretPos (pMLEditData->leftMargin,
(pMLEditData->editLine-pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+pMLEditData->topMargin);
temp = GetLineData(pMLEditData,pMLEditData->editLine);
if (pMLEditData->dispPos != 0)
{
pMLEditData->dispPos = 0;
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
}
case VK_END: /* SCANCODE_END: */
{
int newStartPos;
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
if (pMLEditData->editPos == pLineData->dataEnd)
return 0;
newStartPos = edtGetStartDispPosAtEnd (hWnd, pLineData);
pMLEditData->editPos = pLineData->dataEnd;
pMLEditData->caretPos = pMLEditData->editPos - newStartPos;
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine-pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
 
if (pMLEditData->dispPos != newStartPos)
InvalidateRect (hWnd, NULL, FALSE);
pMLEditData->dispPos = newStartPos;
}
return 0;
 
case VK_LEFT: /* SCANCODE_CURSORBLOCKLEFT: */
{
BOOL bScroll = FALSE;
int scrollStep,newStartPos;
PLINEDATA temp;
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
if (pMLEditData->editPos == 0 )
{
temp = pLineData->previous;
if(temp && pMLEditData->editLine > pMLEditData->StartlineDisp)
{
pMLEditData->editLine --;
pMLEditData->editPos = temp->dataEnd;
newStartPos = edtGetStartDispPosAtEnd (hWnd, temp);
pMLEditData->caretPos = pMLEditData->editPos - newStartPos;
if (pMLEditData->dispPos != newStartPos)
{
pMLEditData->dispPos = newStartPos;
bScroll = TRUE;
}
}
else
return 0;
}
else
{ if (edtIsACCharBeforePosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
scrollStep = 2;
pMLEditData->editPos -= 2;
}
else {
scrollStep = 1;
pMLEditData->editPos --;
}
 
pMLEditData->caretPos -= scrollStep;
if (pMLEditData->caretPos == 0
&& pMLEditData->editPos != 0) {
 
bScroll = TRUE;
 
if (edtIsACCharBeforePosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
pMLEditData->dispPos -= 2;
pMLEditData->caretPos = 2;
}
else {
pMLEditData->dispPos--;
pMLEditData->caretPos = 1;
}
}
else if (pMLEditData->caretPos < 0) {
pMLEditData->dispPos = 0;
pMLEditData->caretPos = 0;
}
}
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
 
if (bScroll)
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
case VK_RIGHT: /* SCANCODE_CURSORBLOCKRIGHT: */
{
BOOL bScroll = FALSE;
int scrollStep, moveStep;
PLINEDATA temp;
 
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
if (pMLEditData->editPos == pLineData->dataEnd)
{
temp = pLineData->next;
if(temp)
{
pMLEditData->editLine++;
pMLEditData->editPos = 0;
pMLEditData->caretPos = 0;
if(pMLEditData->dispPos !=0)
{
pMLEditData->dispPos = 0;
bScroll = TRUE;
}
}
else
return 0;
}
else
{
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->dispPos)) {
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
scrollStep = 2;
moveStep = 2;
pMLEditData->editPos += 2;
}
else {
scrollStep = 2;
moveStep = 1;
pMLEditData->editPos ++;
}
}
else {
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->dispPos + 1))
scrollStep = 3;
else
scrollStep = 2;
moveStep = 2;
pMLEditData->editPos += 2;
}
else {
scrollStep = 1;
moveStep = 1;
pMLEditData->editPos ++;
}
}
 
pMLEditData->caretPos += moveStep;
if (pMLEditData->caretPos * GetSysCharWidth (hWnd)
> edtGetOutWidth (hWnd)) {
bScroll = TRUE;
pMLEditData->dispPos += scrollStep;
pMLEditData->caretPos =
pMLEditData->editPos - pMLEditData->dispPos;
}
}
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight (hWnd)
+ pMLEditData->topMargin);
 
if (bScroll)
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
case VK_UP: /* SCANCODE_CURSORBLOCKUP: */
{
BOOL bScroll = FALSE;
int newStartPos;
PLINEDATA temp;
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
temp = pLineData->previous;
if(pMLEditData->editLine == 0)
return 0;
else if (pMLEditData->editLine == pMLEditData->StartlineDisp)
{
bScroll = TRUE;
pMLEditData->StartlineDisp--;
pMLEditData->EndlineDisp--;
}
pMLEditData->editLine--;
 
if( pMLEditData->editPos >= temp->dataEnd )
{
pMLEditData->editPos = temp->dataEnd;
pMLEditData->dispPos = 0;
newStartPos = edtGetStartDispPosAtEnd (hWnd, temp);
pMLEditData->dispPos = newStartPos;
pMLEditData->caretPos = pMLEditData->editPos - newStartPos;
bScroll = TRUE;
}
else
{
newStartPos = edtGetOffset(hWnd, pMLEditData,temp,
pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin);
if(!edtIsACCharFromBegin(temp->buffer,temp->dataEnd,
pMLEditData->dispPos))
{
bScroll = TRUE;
pMLEditData->dispPos--;
newStartPos = edtGetOffset(hWnd, pMLEditData,temp,
pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin+GetSysCharWidth(hWnd)/2);
}
pMLEditData->editPos = newStartPos + pMLEditData->dispPos;
pMLEditData->caretPos = newStartPos;
}
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
if(bScroll)
InvalidateRect(hWnd,NULL,FALSE);
}
break;
case VK_DOWN: /* SCANCODE_CURSORBLOCKDOWN: */
{
BOOL bScroll = FALSE;
int newStartPos;
PLINEDATA temp;
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
temp = pLineData->next;
if(pMLEditData->editLine == pMLEditData->lines-1)
return 0;
else if (pMLEditData->editLine == pMLEditData->EndlineDisp)
{
bScroll = TRUE;
pMLEditData->StartlineDisp++;
pMLEditData->EndlineDisp++;
}
pMLEditData->editLine++;
 
if( pMLEditData->editPos >= temp->dataEnd )
{
pMLEditData->editPos = temp->dataEnd;
pMLEditData->dispPos = 0;
newStartPos = edtGetStartDispPosAtEnd (hWnd, temp);
pMLEditData->dispPos = newStartPos;
pMLEditData->caretPos = pMLEditData->editPos - newStartPos;
bScroll = TRUE;
}
else
{
newStartPos = edtGetOffset(hWnd, pMLEditData,temp,
pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin);
if(!edtIsACCharFromBegin(temp->buffer,temp->dataEnd,
pMLEditData->dispPos))
{
bScroll = TRUE;
pMLEditData->dispPos--;
newStartPos = edtGetOffset(hWnd, pMLEditData,temp,
pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin+GetSysCharWidth(hWnd)/2);
}
pMLEditData->editPos = newStartPos + pMLEditData->dispPos;
pMLEditData->caretPos = newStartPos;
}
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
if(bScroll)
InvalidateRect(hWnd,NULL,FALSE);
}
break;
case VK_INSERT: /* SCANCODE_INSERT: */
dw = GetWindowAdditionalData(hWnd);
dw ^= EST_REPLACE;
SetWindowAdditionalData(hWnd,dw);
break;
 
case VK_DELETE: /* SCANCODE_REMOVE: */
{
PLINEDATA temp;
int leftLen;
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
if ((GetWindowAdditionalData(hWnd) & EST_READONLY) ){
#if 0 /* fix: no ping() */
ping ();
#endif
return 0;
}
temp = pLineData->next;
if (pLineData->dataEnd == pMLEditData->editPos && temp)
{
if(pLineData->dataEnd + temp->dataEnd <= LEN_MLEDIT_BUFFER)
{
memcpy(pLineData->buffer+pLineData->dataEnd,temp->buffer,temp->dataEnd);
pLineData->dataEnd += temp->dataEnd;
pLineData->buffer[pLineData->dataEnd] = '\0';
if(temp->next)
{
pLineData->next = temp->next;
temp->next->previous = pLineData;
}
else
pLineData->next = NULL;
free(temp);
temp = pLineData->next;
while (temp)
{
temp->lineNO--;
temp = temp->next;
}
if(pMLEditData->lines <= pMLEditData->MaxlinesDisp)
{
pMLEditData->EndlineDisp--;
pMLEditData->linesDisp--;
}
if(pMLEditData->EndlineDisp >= pMLEditData->lines-1)
{
pMLEditData->EndlineDisp--;
if(pMLEditData->StartlineDisp !=0)
pMLEditData->StartlineDisp--;
else
pMLEditData->linesDisp--;
}
pMLEditData->lines--;
}
else if (temp->dataEnd > 0)
{
leftLen = LEN_MLEDIT_BUFFER - pLineData->dataEnd;
memcpy(pLineData->buffer+pLineData->dataEnd,temp->buffer,leftLen);
pLineData->dataEnd +=leftLen;
pLineData->buffer[pLineData->dataEnd] = '\0';
memcpy(temp->buffer,temp->buffer+leftLen,temp->dataEnd-leftLen);
temp->dataEnd -=leftLen;
temp->buffer[temp->dataEnd] = '\0';
}
}
else if (pMLEditData->editPos != pLineData->dataEnd)
{
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos))
deleted = 2;
else
deleted = 1;
for (i = pMLEditData->editPos;
i < pLineData->dataEnd - deleted;
i++)
pLineData->buffer [i]
= pLineData->buffer [i + deleted];
 
pLineData->dataEnd -= deleted;
pLineData->buffer[pLineData->dataEnd] = '\0';
}
bChange = TRUE;
InvalidateRect (hWnd, NULL,FALSE);
}
break;
 
case VK_BACK: /* SCANCODE_BACKSPACE: */
{
PLINEDATA temp;
int leftLen,tempEnd;
if ((GetWindowAdditionalData(hWnd) & EST_READONLY) ){
#if 0 /* fix: no Ping() */
Ping ();
#endif
return 0;
}
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
temp = pLineData->previous;
if (pMLEditData->editPos == 0 && temp)
{
tempEnd = temp->dataEnd;
if(pLineData->dataEnd + temp->dataEnd <= LEN_MLEDIT_BUFFER)
{
memcpy(temp->buffer+temp->dataEnd,pLineData->buffer,pLineData->dataEnd);
temp->dataEnd +=pLineData->dataEnd;
temp->buffer[temp->dataEnd] = '\0';
if(pLineData->next)
{
temp->next = pLineData->next;
pLineData->next->previous = temp;
}
else
temp->next = NULL;
free(pLineData);
pLineData = temp;
temp = temp->next;
while(temp)
{
temp->lineNO--;
temp = temp->next;
}
if(pMLEditData->StartlineDisp == pMLEditData->editLine
&& pMLEditData->StartlineDisp != 0)
{
pMLEditData->StartlineDisp--;
if(pMLEditData->EndlineDisp == pMLEditData->lines)
pMLEditData->EndlineDisp--;
}
if(pMLEditData->lines <= pMLEditData->MaxlinesDisp)
{
pMLEditData->linesDisp--;
pMLEditData->EndlineDisp--;
}
pMLEditData->lines--;
}
else if (pLineData->dataEnd > 0)
{
leftLen = LEN_MLEDIT_BUFFER - temp->dataEnd;
memcpy(temp->buffer+temp->dataEnd,pLineData->buffer,leftLen);
temp->dataEnd +=leftLen;
temp->buffer[temp->dataEnd] = '\0';
memcpy(pLineData->buffer,pLineData->buffer+leftLen,pLineData->dataEnd-leftLen);
pLineData->dataEnd -=leftLen;
pLineData->buffer[pLineData->dataEnd] = '\0';
}
pMLEditData->editLine--;
pMLEditData->editPos = tempEnd;
pMLEditData->dispPos = tempEnd;
 
if (pMLEditData->caretPos == 0
&& pMLEditData->editPos != 0) {
if (edtIsACCharBeforePosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
pMLEditData->dispPos -= 2;
pMLEditData->caretPos = 2;
}
else {
pMLEditData->dispPos--;
pMLEditData->caretPos = 1;
}
}
else if (pMLEditData->caretPos < 0) {
pMLEditData->dispPos = 0;
pMLEditData->caretPos = 0;
}
}
else if (pMLEditData->editPos != 0 )
{
if (edtIsACCharBeforePosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos))
deleted = 2;
else
deleted = 1;
for (i = pMLEditData->editPos;
i < pLineData->dataEnd;
i++)
pLineData->buffer [i - deleted]
= pLineData->buffer [i];
 
pLineData->dataEnd -= deleted;
pMLEditData->editPos -= deleted;
pMLEditData->caretPos -= deleted;
if (pMLEditData->caretPos == 0
&& pMLEditData->editPos != 0) {
if (edtIsACCharBeforePosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
pMLEditData->dispPos -= 2;
pMLEditData->caretPos = 2;
}
else {
pMLEditData->dispPos --;
pMLEditData->caretPos = 1;
}
}
}
bChange = TRUE;
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
InvalidateRect (hWnd, NULL, FALSE);
}
break;
 
default:
break;
}
if (bChange)
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_CHANGE),
(LPARAM) hWnd);
return 0;
}
 
case WM_CHAR:
{
char charBuffer [2];
int i, chars, scrollStep, inserting;
UINT format;
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
 
pLineData = GetLineData(pMLEditData,pMLEditData->editLine);
 
if (dwStyle & ES_READONLY) {
#if 0 /* fix: no Ping() */
Ping ();
#endif
return 0;
}
if (HIBYTE (wParam)) {
charBuffer [0] = LOBYTE (wParam);
charBuffer [1] = HIBYTE (wParam);
chars = 2;
}
else {
charBuffer [0] = LOBYTE (wParam);
chars = 1;
}
if (chars == 1) {
switch (charBuffer [0])
{
case 0x00: /* NULL */
case 0x07: /* BEL */
case 0x08: /* BS */
case 0x09: /* HT */
case 0x0A: /* LF */
case 0x0B: /* VT */
case 0x0C: /* FF */
case 0x0D: /* CR */
case 0x1B: /* Escape */
return 0;
}
}
if (GetWindowAdditionalData(hWnd) & EST_REPLACE) {
if (pLineData->dataEnd == pMLEditData->editPos)
inserting = chars;
else if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->editPos)) {
if (chars == 2)
inserting = 0;
else
inserting = -1;
}
else {
if (chars == 2)
inserting = 1;
else
inserting = 0;
}
}
else
inserting = chars;
 
/* check space */
if (pLineData->dataEnd + inserting > pMLEditData->totalLen) {
#if 0 /* fix no ping */
Ping ();
#endif
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_MAXTEXT),
(LPARAM) hWnd);
return 0;
}
else if ((pMLEditData->hardLimit >= 0)
&& ((pLineData->dataEnd + inserting)
> pMLEditData->hardLimit)) {
#if 0 /* fix no ping */
Ping ();
#endif
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_MAXTEXT),
(LPARAM) hWnd);
return 0;
}
if (inserting == -1) {
for (i = pMLEditData->editPos; i < pLineData->dataEnd-1; i++)
pLineData->buffer [i] = pLineData->buffer [i + 1];
}
else if (inserting > 0) {
for (i = pLineData->dataEnd + inserting - 1;
i > pMLEditData->editPos + inserting - 1;
i--)
pLineData->buffer [i]
= pLineData->buffer [i - inserting];
}
for (i = 0; i < chars; i++)
pLineData->buffer [pMLEditData->editPos + i]
= charBuffer [i];
pMLEditData->editPos += chars;
pMLEditData->caretPos += chars;
pLineData->dataEnd += inserting;
pLineData->buffer[pLineData->dataEnd] = '\0';
if (pMLEditData->caretPos * GetSysCharWidth (hWnd)
> edtGetOutWidth (hWnd))
{
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->dispPos))
scrollStep = 2;
else {
if (chars == 2) {
if (edtIsACCharAtPosition (pLineData->buffer,
pLineData->dataEnd,
pMLEditData->dispPos + 1))
scrollStep = 3;
else
scrollStep = 2;
}
else
scrollStep = 1;
}
pMLEditData->dispPos += scrollStep;
 
pMLEditData->caretPos =
pMLEditData->editPos - pMLEditData->dispPos;
 
}
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
InvalidateRect (hWnd, NULL,FALSE);
format = DT_NOPREFIX;
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (GetDlgCtrlID(hWnd), EN_CHANGE),
(LPARAM) hWnd);
}
return 0;
 
case WM_GETTEXTLENGTH:
{
PLINEDATA temp;
int lineNO = (int)wParam;
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
temp = pMLEditData->head;
while(temp)
{
if (temp->lineNO == lineNO)
return temp->dataEnd;
temp = temp->next;
}
return -1;
}
case WM_GETTEXT:
{
PLINEDATA temp;
int len,total = 0,lineNO;
char * buffer = (char*)lParam;
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
len = (int)wParam;
lineNO = (int)wParam;
temp = pMLEditData->head;
while (temp && total + temp->dataEnd < len)
{
memcpy(buffer+total,temp->buffer,temp->dataEnd);
total += temp->dataEnd;
temp = temp->next;
}
}
return 0;
/* can i add it to message define ? */
#if 0
case WM_GETLINETEXT:
{
PLINEDATA temp;
char* buffer = (char*)lParam;
int lineNO,len;
 
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
lineNO = (int)wParam;
temp = GetLineData(pMLEditData,lineNO);
if(temp)
{
len = min ((int)wParam, temp->dataEnd);
memcpy (buffer, temp->buffer,len);
buffer [len] = '\0';
return 0;
}
return -1;
}
break;
case WM_SETTEXT:
{
MLEditInitBuffer(pMLEditData,(char *)lParam);
}
return 0;
#endif
/* can i add it to message defined? */
#if 0
case WM_SETLINETEXT:
{
int len,lineNO;
PLINEDATA temp;
 
if (dwStyle & ES_READONLY)
return 0;
 
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
len = strlen ((char*)lParam);
lineNO = (int)wParam;
temp = pMLEditData->head;
len = min (len, pMLEditData->totalLen);
if (pMLEditData->hardLimit >= 0)
len = min (len, pMLEditData->hardLimit);
while (temp)
{
if(temp->lineNO == lineNO)
{
temp->dataEnd = len;
memcpy (temp->buffer, (char*)lParam, len);
}
temp = temp->next;
}
pMLEditData->editPos = 0;
pMLEditData->caretPos = 0;
pMLEditData->dispPos = 0;
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
#endif
case WM_LBUTTONDBLCLK:
break;
case WM_LBUTTONDOWN:
{
int newOff,lineNO;
PLINEDATA temp;
BOOL bScroll = FALSE;
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
lineNO = edtGetLineNO (hWnd,pMLEditData, HIWORD (lParam));
if ( lineNO < 0 )
return 0;
lineNO += pMLEditData->StartlineDisp;
if (lineNO <= pMLEditData->EndlineDisp && lineNO <= pMLEditData->lines-1 )
{
temp = GetLineData(pMLEditData,lineNO);
newOff = edtGetOffset (hWnd,pMLEditData,temp, LOWORD (lParam));
if(!edtIsACCharFromBegin(temp->buffer,temp->dataEnd,pMLEditData->dispPos))
{
bScroll = TRUE;
pMLEditData->dispPos--;
newOff = edtGetOffset (hWnd,pMLEditData,temp, LOWORD(lParam)+GetSysCharWidth(hWnd)/2);
}
if (newOff != pMLEditData->caretPos || lineNO != pMLEditData->editLine) {
pMLEditData->editLine = temp->lineNO;
pMLEditData->editPos = newOff +pMLEditData->dispPos;
pMLEditData->caretPos = newOff;
SetCaretPos (pMLEditData->caretPos * GetSysCharWidth (hWnd)
+ pMLEditData->leftMargin,
(pMLEditData->editLine - pMLEditData->StartlineDisp) * GetSysCharHeight(hWnd)
+ pMLEditData->topMargin);
}
if(bScroll)
InvalidateRect(hWnd,NULL,FALSE);
}
}
break;
 
case WM_LBUTTONUP:
break;
case WM_MOUSEMOVE:
break;
case WM_GETDLGCODE:
return DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS;
case EM_SETREADONLY:
if (wParam)
IncludeWindowStyle(hWnd,ES_READONLY);
else
ExcludeWindowStyle(hWnd,ES_READONLY);
return 0;
case EM_SETPASSWORDCHAR:
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
 
if (pMLEditData->passwdChar != (int)wParam) {
if (dwStyle & ES_PASSWORD) {
pMLEditData->passwdChar = (int)wParam;
InvalidateRect (hWnd, NULL, TRUE);
}
}
return 0;
case EM_GETPASSWORDCHAR:
{
int* passwdchar;
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
passwdchar = (int*) lParam;
 
*passwdchar = pMLEditData->passwdChar;
}
return 0;
case EM_LIMITTEXT:
{
int newLimit = (int)wParam;
if (newLimit >= 0) {
pMLEditData = (PMLEDITDATA)GetWindowAdditionalData2(hWnd);
if (pMLEditData->totalLen < newLimit)
pMLEditData->hardLimit = -1;
else
pMLEditData->hardLimit = newLimit;
}
}
return 0;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
break;
}
 
return 0; /* !DefaultControlProc (hWnd, message, wParam, lParam); */
}
 
/insetr.c
0,0 → 1,14
#include "windows.h"
#include "wintools.h"
/*
* WIN Draw Library
*/
 
void WINAPI
InsetR(LPRECT lprc,int h,int v)
{
lprc->top += v;
lprc->left += h;
lprc->right -= 2*h-1;
lprc->bottom -= 2*v-1;
}
/fastfill.c
0,0 → 1,19
#include "windows.h"
#include "wintools.h"
/*
* WIN Draw Library
* Fast fill rectangle
*/
 
/*
* fast fill background (works with non-dithered colors only)
*/
void WINAPI
FastFillRect(HDC hdc,LPRECT lprect,COLORREF cr)
{
COLORREF crOld;
 
crOld = SetBkColor( hdc, cr);
ExtTextOut( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED, lprect, NULL, 0, NULL);
SetBkColor( hdc, crOld);
}
/combobox.c
0,0 → 1,1785
/*--------------------------------------------------------------------------
** ComboBox.c Twin From: Twin/controls
**
**
**------------------------- < License Information > ------------------------
**
** This file was originally a part of Willows TWIN. Willows
** TWIN was released under a Library GPL (LGPL). This permits
** redistribution of this source code, provided that the full
** TWIN license is in effect, and provided that all modifications
** to this source code are made publicly available.
** Please refer to Willows software (www.willows.com) or
** LICENSE for full information.
**
** Under Twine, this file is also protected by an LGPL. Please
** see LICENSE for full details on this license.
**
**
** Copyright 1997 Willows Software, Inc.
**------------------------ < File Content Description > --------------------
**
** Module: controls/ComboBox.c
**
** Description:
**
**
** Functions defined:
**
**------------------------- < Revision Information > -----------------------
**
** Full Revision history at bottom of file
**
**--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "windows.h"
#include "windowsx.h"
 
#define WinMalloc(n) malloc((n))
#define WinFree(p) free(p)
 
#define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
#define GET_WM_COMMAND_MPS(id, hwnd, cmd) \
(WPARAM)MAKELONG(id, cmd), (LONG)(hwnd)
#define LOSHORT(x) (short int)LOWORD(x)
#define Edit_SetSel(hwndCtl, ichStart, ichEnd) ((void)SendMessage((hwndCtl), EM_SETSEL, (ichStart), (ichEnd)))
 
 
typedef struct {
HFONT hFont; /* hFont used */
HWND hWndParent; /* parent window */
UINT nID; /* control ID */
WORD wStateFlags; /* combobox state flags */
UINT wStyle; /* this is a copy of LOWORD(style) */
BOOL bExtended; /* extended UI flag */
BOOL bRedraw; /* MiD - redraw flag, draw only if it's 1 */
HWND EditControl; /* edit/static control hWnd */
HWND ListBoxControl; /* listbox control hWnd */
RECT ButtonRect; /* local button rect (client) */
RECT ListBoxRect; /* listbox rect (screen) */
UINT uHeight; /* height of the normal state */
WNDPROC lpfnOldStatic; /* previous static wndproc */
UINT nListItems; /* ecw */
} COMBOBOX;
 
#define CWD_LPCBDATA 0
#define CBC_EDITID 1
 
#define CSF_CAPTUREACTIVE 0x0001
#define CSF_LOCALBUTTONDOWN 0x0002
#define CSF_BUTTONDOWN 0x0004
#define CSF_LBOXBUTTONDOWN 0x0008
#define CSF_FOCUS 0x0010 /* MiD */
#define CSF_HASDROPPED 0x0020 /* weav */
 
#define SET_STATE(lp, wMask) (lp->wStateFlags |= (wMask))
#define CLEAR_STATE(lp, wMask) (lp->wStateFlags &= ~(wMask))
#define IS_SET(lp, wMask) (lp->wStateFlags & (wMask))
 
#define BOWNERDRAW(l) ((l)->wStyle & (CBS_OWNERDRAWFIXED|CBS_OWNERDRAWVARIABLE))
 
/**********************************************
Styles:
 
CBS_AUTOHSCROLL passed to the edit control
CBS_DISABLENOSCROLL passed to the listbox control
CBS_DROPDOWN
CBS_DROPDOWNLIST
CBS_HASSTRINGS passed to the listbox control
CBS_NOINTEGRALHEIGHT passed to the listbox control
CBS_OEMCONVERT passed to the edit control
CBS_OWNERDRAWFIXED passed to the listbox control
CBS_OWNERDRAWVARIABLE passed to the listbox control
CBS_SIMPLE TODO
CBS_SORT passed to the listbox control
 
WS_VSCROLL passed to the listbox control
 
*********************************************/
 
/**********************************************
CBN_xxx messages to be added
 
from mouse tracking...
CBN_SELENDCANCEL TODO
CBN_SELENDOK TODO
 
*********************************************/
 
/* imported stuff */
#if 1
void
Draw3DButtonRect(HDC hDC, HPEN hPenHigh, HPEN hPenShadow,
RECT rc, BOOL fClicked)
{
HPEN hPenOld;
POINT lpt[6];
 
POINT p3[3];
int shrink=1;
 
hPenOld = SelectObject(hDC, hPenShadow);
if (fClicked) {
lpt[0].x = lpt[1].x = rc.left;
lpt[1].y = lpt[2].y = rc.top;
lpt[2].x = rc.right-1;
lpt[0].y = rc.bottom-1;
Polyline(hDC,lpt,3);
}
else {
lpt[0].x = lpt[1].x = rc.right-1;
lpt[0].y = rc.top;
lpt[1].y = lpt[2].y = rc.bottom-1;
lpt[2].x = rc.left;
lpt[3].x = rc.left+1;
lpt[3].y = lpt[4].y = rc.bottom-2;
lpt[4].x = lpt[5].x = rc.right-2;
lpt[5].y = rc.top+1;
Polyline(hDC,lpt,6);
 
SelectObject(hDC, hPenHigh);
lpt[0].x = rc.right-1;
lpt[0].y = lpt[1].y = rc.top;
lpt[1].x = lpt[2].x = rc.left;
lpt[2].y = rc.bottom-1;
lpt[3].x = lpt[4].x = rc.left+1;
lpt[3].y = rc.bottom-2;
lpt[4].y = lpt[5].y = rc.top+1;
lpt[5].x = rc.right-2;
Polyline(hDC,lpt,6);
}
 
SelectObject(hDC,GetStockObject(BLACK_BRUSH));
/* down */
p3[0].x= rc.left + ((rc.right-rc.left)/2) - 1;
p3[0].y= rc.bottom - 4 - shrink;
p3[1].x= rc.left + 2 + shrink - 1;
p3[1].y= rc.bottom-(rc.bottom-rc.top) + 2 + shrink;
p3[2].x= rc.left + ((rc.right-rc.left)-4) - shrink;
p3[2].y= rc.bottom-(rc.bottom-rc.top) + 2 + shrink;
Polygon(hDC,p3,3);
 
SelectObject(hDC,hPenOld);
}
#endif
 
#if 0 /* jmt: fix: no COMBOLBOX */
extern LRESULT DefLISTBOXProc(HWND, UINT, WPARAM, LPARAM);
extern LRESULT ListboxCtrlProc(HWND, UINT, WPARAM, LPARAM);
#endif
 
#if 0
static HPEN GetSysColorPen(int color)
{
return NULL;
}
static HBRUSH GetSysColorBrush(int color)
{
return NULL;
}
#endif
 
typedef HWND HWND32;
 
#if 0 /* jmt: fix: no ownerdraw */
typedef HANDLE HCLASS32;
static HCLASS32 FindClass(LPCSTR str, HINSTANCE hInstance)
{
return NULL;
}
#endif
 
#if 0 /* jmt: fix: no scrollbar */
static HWND TWIN_ConvertToSysScroll(HWND hwnd, BOOL status, LPPOINT pp)
{
return NULL;
}
#endif
extern HWND listwp;
static HWND WindowFromPoint(POINT pt)
{
HWND wp,wp1;
int dx,dy,dx1,dy1;
#if 0
return NULL; /* fix!! */
#else
wp1=NULL;
switch(sizeof(dx))
{
case 4:
dx=0x7fffffff;
dy=0x7fffffff;
break;
case 2:
dx=0x7fff;
dy=0x7fff;
break;
}
for(wp=listwp; wp; wp=wp->next)
{
if (wp->winrect.left <= pt.x && pt.x <= wp->winrect.right)
{
dx1=(wp->winrect.right-pt.x);
if (dx1<dx)
{
wp1=wp;
dx=dx1;
}
dx1=(pt.x-wp->winrect.left);
if (dx1<dx)
{
wp1=wp;
dx=dx1;
}
}
if (wp->winrect.top <= pt.y && pt.y <= wp->winrect.bottom)
{
dy1=(wp->winrect.bottom-pt.y);
if (dy1<dy)
{
wp1=wp;
dy=dy1;
}
dy1=(pt.y-wp->winrect.top);
if (dy1<dy)
{
wp1=wp;
dy=dy1;
}
}
}
#endif
return wp1;
}
 
/* internal stuff */
static void CBoxDrawButton(HWND,UINT,COMBOBOX *);
static void CBoxSendMouseToLBox(COMBOBOX *, UINT, WPARAM, POINT);
static void CBoxCapture(HWND, WORD);
static void CBoxDrawEdit(COMBOBOX *, HWND, UINT);
static void CBoxDrawStatic(COMBOBOX *, HWND, UINT); /* MiD */
 
/* handle specific CB messages */
static LRESULT DefCBProc(HWND , UINT , WPARAM , LPARAM );
 
#if 0 /* jmt: fix: no ownerdraw */
static WNDPROC lpComboBinToNat = 0;
#endif
 
static LRESULT CALLBACK
DefComboboxProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
int WINAPI MwRegisterComboboxControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)DefComboboxProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "COMBOBOX";
 
return RegisterClass(&wc);
}
 
static LRESULT CALLBACK
DefComboboxProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hDC;
TEXTMETRIC tm;
#if 0 /* jmt: fix: no ownerdraw */
MEASUREITEMSTRUCT mis;
#endif
COMBOBOX *lp = (COMBOBOX *)NULL;
LRESULT rc;
HINSTANCE hInst;
POINT cp,cpScreen,pp;
UINT uiKey;
LPCREATESTRUCT lpcs;
#if 1 /* jmt: fix: no WM_WINDOWPOSCHANGING */
LPWINDOWPOS lpwp;
#endif
#if 0 /* jmt: fix: no ownerdraw */
HCLASS32 hComboClass32;
LPMEASUREITEMSTRUCT lpmis;
LPDRAWITEMSTRUCT lpdis;
LPDELETEITEMSTRUCT lpdlis;
#endif
DWORD dwStyle,dwExStyle;
WORD wEditWidth = 0,wEditHeight;
WORD wCBN;
#if 0 /* jmt: fix: no WM_SETFONT/WM_GETFONT */
RECT rcClient;
#endif
 
rc = CB_OKAY;
if ((uMsg != WM_CREATE/*WM_NCCREATE*/) && /*(uMsg != WM_CONVERT) &&*/
!(lp = (COMBOBOX *)hWnd->userdata/*GetWindowLong(hWnd,CWD_LPCBDATA)*/))
return rc;
 
switch(uMsg) {
#if 0
case WM_SIZE:
case WM_ENABLE:
case WM_LBUTTONDBLCLK:
case WM_COMPAREITEM:
case WM_CUT:
case WM_CLEAR:
#endif
 
case WM_SETFOCUS:
SET_STATE(lp, CSF_FOCUS);
if ((lp->wStyle & 0x0F) == CBS_DROPDOWNLIST)
{
uiKey = (UINT)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0L);
CBoxDrawStatic(lp, hWnd, uiKey);
}
if (lp->EditControl)
{
SetFocus(lp->EditControl);
}
break;
case WM_KILLFOCUS:
CLEAR_STATE(lp, CSF_FOCUS);
if ((lp->wStyle & 0x0F) == CBS_DROPDOWNLIST)
{
uiKey = (UINT)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0L);
CBoxDrawStatic(lp, hWnd, uiKey);
}
/*
** Hide listbox when loosing focus to window other than
** our own listbox... When wParam == 0 we "loose" the focus
** to the scrollbar in a listbox!
*/
if ((lp->wStyle & 0x0F) != CBS_SIMPLE && wParam != (WPARAM)lp->ListBoxControl && wParam != 0)
SendMessage(hWnd, CB_SHOWDROPDOWN, 0, 0L);
fprintf(stderr," 385: WM_KILLFOCUS\n");
break;
 
#if 0 /* jmt: fix: no WM_KEYDOWN */
case WM_KEYDOWN: /* MiD 08/14/95 */
/*
** We have to process this message in order to show
** current selection in a static control for certain
** keys. This doesn't affect combobox with an edit
** control, since the edit traps all key messages.
*/
{
int nCur = SendMessage(lp->ListBoxControl, LB_GETCURSEL,0, 0L);
int nPrevCur = nCur;
int nCount = SendMessage(lp->ListBoxControl, LB_GETCOUNT, 0, 0L);
 
if (nCount == 0)
break;
 
switch(wParam)
{
case VK_HOME:
nCur = 0;
break;
 
case VK_END:
nCur = nCount - 1;
break;
 
case VK_UP:
nCur--;
break;
 
case VK_DOWN:
nCur++;
break;
 
default:
return 0L;
}
 
if (nCur >= nCount)
nCur = nCount - 1;
if (nCur < 0)
nCur = 0;
 
SendMessage(lp->ListBoxControl, LB_SETCURSEL, nCur, 0L);
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID, hWnd, CBN_SELCHANGE));
if (nCur != nPrevCur)
/* ecw */ SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID, hWnd, CBN_SELENDOK));
InvalidateRect(hWnd, NULL, 1);
break;
}
#endif /* WM_KEYDOWN */
 
case WM_CHAR:
{
int nNewCur;
int nOldCur;
 
if (lp->EditControl)
{
SendMessage(lp->EditControl, uMsg, wParam, lParam);
}
else {
nOldCur = SendMessage(lp->ListBoxControl, LB_GETCURSEL,0, 0L);
SendMessage(lp->ListBoxControl, uMsg, wParam, lParam);
nNewCur = SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0L);
if (nNewCur != nOldCur)
{
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID, hWnd, CBN_SELCHANGE));
InvalidateRect(hWnd, NULL, 1);
}
}
break;
}
 
#if 0 /* jmt: fix: no WM_SETREDRAW */
case WM_SETREDRAW:
lp->bRedraw = wParam;
if (lp->EditControl)
SendMessage(lp->EditControl, WM_SETREDRAW, wParam, lParam);
if (lp->ListBoxControl)
SendMessage(lp->ListBoxControl, WM_SETREDRAW, wParam, lParam);
break;
#endif
case WM_CREATE: /*WM_NCCREATE:*/
lp = (COMBOBOX *)WinMalloc(sizeof(COMBOBOX));
memset((LPSTR)lp,'\0',sizeof(COMBOBOX));
 
/* save ptr to internal structure */
hWnd->userdata=(DWORD)lp; /* -SetWindowLong(hWnd, CWD_LPCBDATA, (LONG) lp); */
 
/* this is for CreateWindow calls */
hInst = NULL; /* -GetWindowInstance(hWnd); */
 
/* fill in the internal structure */
lpcs = (LPCREATESTRUCT)lParam;
lp->bRedraw = 1;
lp->wStateFlags = 0;
lp->wStyle = (UINT)LOWORD(lpcs->style);
if (!BOWNERDRAW(lp))
lp->wStyle |= CBS_HASSTRINGS;
lp->bExtended = TRUE;
lp->hFont = 0;
lp->hWndParent = lpcs->hwndParent;
lp->nID = (UINT)lpcs->hMenu;
 
#if 0 /* jmt: fix: no ownerdraw */
/* calc the height of the edit/static control */
if (0) /* (BOWNERDRAW(lp)) */
{
mis.CtlType = ODT_COMBOBOX;
mis.CtlID = (UINT)lpcs->hMenu;
mis.itemID = (UINT)-1;
mis.itemData = 0L;
SendMessage(lpcs->hwndParent, WM_MEASUREITEM, (WPARAM)lpcs->hMenu, (LPARAM)&mis);
/*** wEditHeight = (WORD)mis.itemHeight + 2; ***/
}
#endif /* ownerdraw */
 
/* get system font dimensions */
hDC = GetDC((HWND)0);
GetTextMetrics(hDC,&tm);
ReleaseDC((HWND)0,hDC);
 
/* allow different fonts to fit, don't hard code */
/* otherwise big fonts won't fit. */
/*****wEditHeight = ((tm.tmHeight - tm.tmInternalLeading)*7)/4;*****/
wEditHeight = tm.tmHeight + tm.tmInternalLeading * 3;
 
lp->uHeight = (UINT)wEditHeight;
 
if ((lp->wStyle & 0x0F) != CBS_SIMPLE)
{
lp->ButtonRect.top = 0;
lp->ButtonRect.left = lpcs->cx - 1 - GetSystemMetrics(SM_CXVSCROLL);
lp->ButtonRect.right = lpcs->cx;
lp->ButtonRect.bottom = wEditHeight;
/* for CBS_DROPDOWN/DROPDOWNLIST resize the window */
SetWindowPos(hWnd, 0,
0, 0, lpcs->cx, (int)wEditHeight,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW);
}
else SetRectEmpty(&lp->ButtonRect);
 
if ((lp->wStyle & 0xf) != CBS_DROPDOWNLIST)
{ /* EDIT field - calc edit control style */
dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER;
if (lp->wStyle & CBS_AUTOHSCROLL)
dwStyle |= ES_AUTOHSCROLL;
if (lp->wStyle & CBS_OEMCONVERT)
dwStyle |= ES_OEMCONVERT;
 
if ((lp->wStyle & 0x0F) == CBS_SIMPLE)
{
fprintf(stderr," 528: wEditWidth = lpcs->cx=%d\n",lpcs->cx);
wEditWidth = lpcs->cx;
}
else /* ?if ((lp->wStyle & 0xf) == CBS_DROPDOWN) */
{
fprintf(stderr," 533: wEditWidth = lp->ButtonRect.left - 5=%d;\n",lp->ButtonRect.left - 5);
wEditWidth = lp->ButtonRect.left - 5;
}
/* create edit control */
lp->EditControl = CreateWindow("EDIT", NULL, dwStyle,
0, 0, wEditWidth, wEditHeight,
hWnd, (HMENU)CBC_EDITID,
hInst,(LPVOID)NULL);
}
else /* CBS_DROPDOWN -- static instead of edit */
lp->EditControl = 0;
/* listbox style */
/* jmt: fix: no WS_EX_SAVEBITS, WS_EX_NOCAPTURE, WS_EX_POPUPMENU */
dwExStyle = 0L; /* WS_EX_SAVEBITS | WS_EX_NOCAPTURE | WS_EX_POPUPMENU; */
dwStyle = WS_BORDER | LBS_NOTIFY ; /* | LBS_COMBOLBOX; */
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
dwStyle |= WS_VISIBLE | WS_CHILD;
else
dwStyle |= WS_POPUP;
#if 0
if (lp->wStyle & CBS_DISABLENOSCROLL)
dwStyle |= LBS_DISABLENOSCROLL;
#endif
if (lp->wStyle & CBS_HASSTRINGS)
dwStyle |= LBS_HASSTRINGS;
if (lp->wStyle & CBS_NOINTEGRALHEIGHT)
dwStyle |= LBS_NOINTEGRALHEIGHT;
if (lp->wStyle & CBS_OWNERDRAWFIXED)
dwStyle |= LBS_OWNERDRAWFIXED;
if (lp->wStyle & CBS_OWNERDRAWVARIABLE)
dwStyle |= LBS_OWNERDRAWVARIABLE;
if (lp->wStyle & CBS_SORT)
dwStyle |= LBS_SORT;
if (lpcs->style & WS_VSCROLL)
dwStyle |= WS_VSCROLL;
 
/* calc listbox dimensions and position */
if ((lp->wStyle & 0xf) == CBS_SIMPLE) {
lp->ListBoxRect.left = 5;
lp->ListBoxRect.top = wEditHeight - 1;
lp->ListBoxRect.right = lpcs->cx;
lp->ListBoxRect.bottom = lpcs->cy - 2;
} else {
lp->ListBoxRect.left = lpcs->x;
lp->ListBoxRect.right = lp->ListBoxRect.left + lpcs->cx - 1;
lp->ListBoxRect.top = lpcs->y + wEditHeight - 1;
lp->ListBoxRect.bottom = lp->ListBoxRect.top + lpcs->cy + 1;
if ((lp->wStyle & 0x0F) == CBS_DROPDOWN) {
lp->ListBoxRect.left += 5;
}
}
#ifdef LATER
cp.x = ((lp->wStyle & 0xf) == CBS_DROPDOWNLIST)?0:5;
cp.y = wEditHeight - 1;
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
ClientToScreen(hWnd,&cp);
lp->ListBoxRect.left = cp.x;
lp->ListBoxRect.top = cp.y;
lp->ListBoxRect.right = cp.x + lpcs->cx;
if ((lp->wStyle & 0xf) != CBS_DROPDOWNLIST)
lp->ListBoxRect.right -= 5;
lp->ListBoxRect.bottom = lp->ListBoxRect.top + lpcs->cy -
wEditHeight + 1;
#endif
 
lp->ListBoxControl = CreateWindowEx(dwExStyle,"LISTBOX",/*"COMBOLBOX",*/
NULL, dwStyle,
lp->ListBoxRect.left, lp->ListBoxRect.top,
lp->ListBoxRect.right - lp->ListBoxRect.left,
lp->ListBoxRect.bottom - lp->ListBoxRect.top,
hWnd, 0,
hInst,(LPVOID)NULL);
#if MWCLIENT
#if 0
GrLowerWindow(lp->ListBoxControl->wid);
#endif
MwLowerWindow(lp->ListBoxControl);
#endif
#ifdef LATER
/* Microsoft Word 6.0 wants to see COMBOLBOX on top */
/* of Z-order... */
if (dwStyle & WS_POPUP)
{
SetWindowPos(lp->ListBoxControl, HWND_TOP,
0, 0, 0, 0,
SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
}
#endif
 
#if 0 /* jmt: fix: no HWND32(LPWININFO) */
/* physically expand client window,
if there is a scroll style
*/
if (lpcs->style & WS_VSCROLL)
{
HWND32 hWnd32 = GETHWND32(hWnd);
 
SetRectEmpty(&hWnd32->rcNC);
 
hWnd32->wWidth = (WORD) hWnd32->rWnd.right-hWnd32->rWnd.left;
hWnd32->wHeight = (WORD)hWnd32->rWnd.bottom-hWnd32->rWnd.top;
RELEASEWININFO(hWnd32);
}
#endif
/*
** Finally turn off border drawing and WM_?SCROLL styles to prevent creation
** of system scrollbars.
*/
dwStyle = GetWindowLong(hWnd, GWL_STYLE);
dwStyle &= ~(WS_VSCROLL | WS_HSCROLL | WS_BORDER | WS_DLGFRAME | WS_THICKFRAME);
SetWindowLong(hWnd, GWL_STYLE, dwStyle);
lp->nListItems = 0;
return TRUE;
 
case WM_DESTROY: /*WM_NCDESTROY:*/
if (IsWindow(lp->ListBoxControl))
DestroyWindow(lp->ListBoxControl);
if (IsWindow(lp->EditControl))
DestroyWindow(lp->EditControl);
WinFree((LPSTR)lp);
return 0L;
 
case WM_GETDLGCODE:
return (LRESULT)(DLGC_WANTCHARS|DLGC_WANTARROWS);
 
/* jmt: twine->mwin bug fixed: */
case WM_NCLBUTTONDOWN: /* jmt: a must */
#if 0 /* twine->mw buggy */
case WM_LBUTTONDOWN:
#endif
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
break;
 
cp.x = (int)(short)LOWORD(lParam);
cp.y = (int)(short)HIWORD(lParam);
#if 1 /* WM_NCLBUTTONDOWM: */
ScreenToClient(hWnd, &cp); /* jmt: a must */
#endif
if (!IS_SET(lp, CSF_CAPTUREACTIVE)) /* no listbox yet */
{
/* click on a button or anywhere if it's dropdown combo */
if (PtInRect(&lp->ButtonRect, cp) ||
(lp->wStyle & 0x0F) == CBS_DROPDOWNLIST)
{
if (PtInRect(&lp->ButtonRect, cp))
CBoxDrawButton(hWnd, 1, lp);
 
cp.x = ((lp->wStyle & 0xf) != CBS_DROPDOWNLIST) ? 5 : 0;
cp.y = lp->uHeight - 1;
 
ClientToScreen(hWnd, &cp);
 
fprintf(stderr," (1)lp->ListBoxRect:(%d,%d,%d,%d)\n",
lp->ListBoxRect.left,
lp->ListBoxRect.top,
lp->ListBoxRect.right,
lp->ListBoxRect.bottom);
 
OffsetRect(&lp->ListBoxRect, cp.x - lp->ListBoxRect.left, cp.y - lp->ListBoxRect.top);
 
fprintf(stderr," (2)lp->ListBoxRect:(%d,%d,%d,%d)\n",
lp->ListBoxRect.left,
lp->ListBoxRect.top,
lp->ListBoxRect.right,
lp->ListBoxRect.bottom);
 
SetWindowPos(lp->ListBoxControl, HWND_TOP, /*0,*/
cp.x, cp.y, 0, 0,
SWP_NOSIZE | /*SWP_NOZORDER |*/ SWP_NOACTIVATE);
 
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_DROPDOWN));
/* ECW added following conditional... 4/4/96 */
/* JMT following conditional is a must for microwindows 8/14/2k */
if (1) /* -(!IS_SET(lp, CSF_HASDROPPED)) jmt: a must */
{
/* ??first time it drops down, size it to hold all items?? */
 
int nitems = SendMessage(lp->ListBoxControl,LB_GETCOUNT,0,0L);
#if 0
/* resize if too small, in this case, also do too long */
if (lp->ListBoxRect.bottom - lp->ListBoxRect.top <
((lp->uHeight-2) * nitems))
{
#endif
nitems = (nitems > 12 ? 12 : nitems); /* a dozen, max */
 
#if 0 /* twine->mw buggy? */
lp->ListBoxRect.bottom =
lp->ListBoxRect.top + ((lp->uHeight-2) * nitems);
#endif
fprintf(stderr," (2.5)lp->ListBoxRect:(%d,%d,%d,%d)\n",
lp->ListBoxRect.left,
lp->ListBoxRect.top,
lp->ListBoxRect.right,
lp->ListBoxRect.bottom);
 
/* jmt: twine->mwin bug fixed: */
fprintf(stderr," 706: fixed: SetWindowPos(lp->ListBoxControl,,%d,%d,...)\n",cp.x,cp.y);
#if 0 /* twine->mwin bug */
SetWindowPos(lp->ListBoxControl,HWND_TOP,0,0,
lp->ListBoxRect.right - lp->ListBoxRect.left,
lp->ListBoxRect.bottom - lp->ListBoxRect.top,
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
#else /* jmt: twine->mwin bug fixed: */
SetWindowPos(lp->ListBoxControl,HWND_TOP,cp.x,cp.y,
lp->ListBoxRect.right - lp->ListBoxRect.left,
lp->ListBoxRect.bottom - lp->ListBoxRect.top,
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
#endif
 
#if 0
}
#endif
SET_STATE(lp, CSF_HASDROPPED);
}
/* End of addition */
ShowWindow(lp->ListBoxControl, SW_SHOW);
#if 0 /* orig(twine) */
SetFocus(lp->ListBoxControl);
#else /* jmt: mwclient */
SetForegroundWindow(lp->ListBoxControl);
#endif
CBoxCapture(hWnd, 1);
SET_STATE(lp, CSF_CAPTUREACTIVE);
SET_STATE(lp, CSF_BUTTONDOWN);
}
}
else
{ /* there is a listbox visible */
HWND hwndNewFocus = 0;
cpScreen = cp;
 
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
{
ClientToScreen(hWnd, &cpScreen);
hwndNewFocus = WindowFromPoint(cpScreen);
}
 
fprintf(stderr," (3)lp->ListBoxRect:(%d,%d,%d,%d)\n",
lp->ListBoxRect.left,
lp->ListBoxRect.top,
lp->ListBoxRect.right,
lp->ListBoxRect.bottom);
 
if (PtInRect(&lp->ListBoxRect, cpScreen))
{
CBoxSendMouseToLBox(lp, WM_LBUTTONDOWN, wParam, cpScreen);
}
else
{
if (PtInRect(&lp->ButtonRect, cp))
CBoxDrawButton(hWnd, 0, lp);
if ((lp->wStyle & 0x0F) == CBS_DROPDOWN && hwndNewFocus == lp->EditControl)
/* don't close listbox */;
else {
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_CLOSEUP));
 
fprintf(stderr," 802: (hide) SetWindowPos(lp->ListBoxControl, , 0, 0, 0, 0,..)\n");
 
SetWindowPos(lp->ListBoxControl, 0,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW);
#if MWCLIENT
MwLowerWindow(lp->ListBoxControl);
#endif
CBoxCapture(hWnd, 0);
CLEAR_STATE(lp, CSF_BUTTONDOWN);
}
CLEAR_STATE(lp, CSF_CAPTUREACTIVE);
 
if (hwndNewFocus && hwndNewFocus != hWnd)
{
ScreenToClient(hwndNewFocus, &cpScreen);
SetFocus(hwndNewFocus);
 
SendMessage(hwndNewFocus, WM_LBUTTONDOWN, wParam, MAKELONG(cpScreen.x, cpScreen.y));
}
} /* !(PtInRect(&lp->ListBoxRect, cpScreen)) */
}
break;
 
/* jmt: twine->mwin bug fixed: */
case WM_NCMOUSEMOVE:
#if 0 /* jmt: twine->mw buggy */
case WM_MOUSEMOVE:
#endif
if (!IS_SET(lp,CSF_BUTTONDOWN) && ((lp->wStyle & 0xf) == CBS_SIMPLE))
break;
 
cp.x = (int)(short)LOWORD(lParam);
cp.y = (int)(short)HIWORD(lParam);
#if 1 /* WM_NCMOUSEMOVE: */
ScreenToClient(hWnd, &cp); /* jmt: a must */
#endif
 
if (IS_SET(lp, CSF_CAPTUREACTIVE))
{
if (PtInRect(&lp->ButtonRect,cp))
{
if (!IS_SET(lp, CSF_LOCALBUTTONDOWN))
CBoxDrawButton(hWnd, 1, lp);
break;
}
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
ClientToScreen(hWnd,&cp);
if (PtInRect(&lp->ListBoxRect,cp))
{
CBoxSendMouseToLBox(lp,WM_MOUSEMOVE,wParam,cp);
}
if (IS_SET(lp,CSF_LOCALBUTTONDOWN) && ((lp->wStyle & 0xf) != CBS_SIMPLE))
CBoxDrawButton(hWnd,0,lp);
}
break;
 
/* jmt: twine->mwin bug fixed: */
case WM_NCLBUTTONUP:
#if 0 /* twine->mw buggy */
case WM_LBUTTONUP:
#endif
if (!IS_SET(lp, CSF_CAPTUREACTIVE))
break;
 
cp.x = (int)(short)LOWORD(lParam);
cp.y = (int)(short)HIWORD(lParam);
#if 1 /* WM_NCLBUTTONUP */
ScreenToClient(hWnd, &cp); /* jmt: a must */
#endif
 
CLEAR_STATE(lp,CSF_BUTTONDOWN);
 
if (PtInRect(&lp->ButtonRect, cp))
/*(lp->wStyle & 0x0F) == CBS_DROPDOWNLIST)*/
{
if (PtInRect(&lp->ButtonRect, cp))
CBoxDrawButton(hWnd, 0, lp);
if (IS_SET(lp, CSF_LBOXBUTTONDOWN))
{
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
ClientToScreen(hWnd, &cp);
CBoxSendMouseToLBox(lp, WM_LBUTTONUP, wParam, cp);
CLEAR_STATE(lp,CSF_LBOXBUTTONDOWN);
}
break;
}
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
ClientToScreen(hWnd, &cp);
 
if (PtInRect(&lp->ListBoxRect, cp))
{
uiKey = (UINT)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0);
if (uiKey != (UINT)LB_ERR)
{
if (lp->EditControl)
{
SetFocus(lp->EditControl);
 
CBoxDrawEdit(lp, hWnd, uiKey);
}
else {
SetFocus(hWnd);
 
CBoxDrawStatic(lp, hWnd, uiKey);
}
/* LATER check the WS_EX_NOPARENTNOTIFY bit in ext style.*/
/* ecw */ SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_SELENDOK));
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_CLOSEUP));
 
fprintf(stderr," 844: (hide) SetWindowPos(lp->ListBoxControl, , 0, 0, 0, 0,..)\n");
 
SetWindowPos(lp->ListBoxControl, 0,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW);
 
CBoxCapture(hWnd, 0);
CLEAR_STATE(lp,CSF_CAPTUREACTIVE);
} /* uiKey ok */
CBoxSendMouseToLBox(lp, WM_LBUTTONUP, wParam, cp);
CLEAR_STATE(lp,CSF_LBOXBUTTONDOWN);
#if MWCLIENT
#if 0
GrLowerWindow(lp->ListBoxControl->wid);
#endif
MwLowerWindow(lp->ListBoxControl);
#endif
}
else /* clicked somewhere outside button or listbox -
** the listbox should stay intact... MiD
*/
if (IS_SET(lp, CSF_LBOXBUTTONDOWN))
{
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
ClientToScreen(hWnd, &cp);
CBoxSendMouseToLBox(lp, WM_LBUTTONUP, wParam, cp);
CLEAR_STATE(lp,CSF_LBOXBUTTONDOWN);
}
break;
 
case WM_ERASEBKGND:
return 1L;
 
case WM_PAINT:
BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
 
if (!IsWindowVisible(hWnd) || !lp->bRedraw)
return 0L;
 
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
CBoxDrawButton(hWnd, IS_SET(lp,CSF_LOCALBUTTONDOWN), lp);
uiKey = (UINT)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0);
if (lp->EditControl)
CBoxDrawEdit(lp, hWnd, uiKey);
else CBoxDrawStatic(lp, hWnd, uiKey);
return 0L;
case WM_COMMAND:
if (GET_WM_COMMAND_ID(wParam,lParam) == CBC_EDITID) {
/* edit/static control notifications */
switch((short)GET_WM_COMMAND_CMD(wParam,lParam)) {
case EN_SETFOCUS:
#ifdef LATER
wCBN = CBN_SETFOCUS;
#else
wCBN = 0;
#endif
break;
case EN_KILLFOCUS:
wCBN = CBN_KILLFOCUS;
break;
case EN_CHANGE:
{
int index = 0;
char sz[128];
/*
** Advance listbox
** selection until there is string match. One first mismatch
** listbox advances to its first item.
*/
SendMessage(lp->EditControl, WM_GETTEXT, sizeof(sz)-1, (LPARAM)sz);
if (/*l*/strlen(sz) > 0/*L*/)
index = (int)SendMessage(lp->ListBoxControl, LB_FINDSTRING, -1, (LPARAM)sz);
if (index == LB_ERR)
index = 0;
SendMessage(lp->ListBoxControl, LB_SETTOPINDEX, index, 0L);
wCBN = CBN_EDITCHANGE;
break;
}
case EN_UPDATE:
wCBN = CBN_EDITUPDATE;
break;
case EN_ERRSPACE:
wCBN = CBN_ERRSPACE;
break;
default:
wCBN = 0;
break;
}
if (wCBN)
return SendMessage(lp->hWndParent,WM_COMMAND,
GET_WM_COMMAND_MPS(lp->nID,hWnd,wCBN));
else
return rc;
}
if (GET_WM_COMMAND_ID(wParam,lParam) == 0) {
/* listbox notifications */
switch ((short)GET_WM_COMMAND_CMD(wParam,lParam)) {
case LBN_ERRSPACE:
wCBN = CBN_ERRSPACE;
break;
case LBN_SELCHANGE:
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
{
uiKey = (UINT)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0);
if (uiKey != (UINT)LB_ERR)
if (lp->EditControl)
{
CBoxDrawEdit(lp, hWnd, uiKey);
}
}
wCBN = CBN_SELCHANGE;
break;
case LBN_DBLCLK:
wCBN = CBN_DBLCLK;
break;
case LBN_SELCANCEL: /* TODO */
wCBN = 0;
break;
case LBN_SETFOCUS:
wCBN = CBN_SETFOCUS;
break;
case LBN_KILLFOCUS:
wCBN = CBN_KILLFOCUS;
break;
default:
wCBN = 0;
break;
}
if (wCBN)
return SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,wCBN));
else
return rc;
}
break;
 
case WM_GETTEXT:
if ( lp->EditControl )
return SendMessage(lp->EditControl,uMsg,wParam,lParam);
else if ( lp->ListBoxControl ) {
WPARAM sel, len;
 
sel = (WPARAM)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0);
if ( sel != (WPARAM)LB_ERR ) {
len = (WPARAM)SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, 0, 0);
if ( len <= wParam )
return SendMessage(lp->ListBoxControl, LB_GETTEXT, sel, lParam);
}
}
return CB_ERR;
 
case WM_GETTEXTLENGTH:
if ( lp->EditControl )
return SendMessage(lp->EditControl,uMsg,wParam,lParam);
else if ( lp->ListBoxControl ) {
WPARAM sel;
 
sel = (WPARAM)SendMessage(lp->ListBoxControl, LB_GETCURSEL, 0, 0);
if ( sel != (WPARAM)LB_ERR )
return SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, sel, 0);
}
return CB_ERR;
 
case WM_SETTEXT:
if ( lp->EditControl )
return SendMessage(lp->EditControl,uMsg,wParam,lParam);
return CB_ERR;
 
#if 0 /* jmt: fix: no WM_SETFONT/WM_GETFONT */
case WM_SETFONT:
lp->hFont = (HFONT)wParam;
 
hDC = GetDC(hWnd);
SelectObject(hDC,lp->hFont);
GetTextMetrics(hDC,&tm);
ReleaseDC(hWnd,hDC);
wEditHeight = tm.tmHeight + 3 * tm.tmInternalLeading;
 
if (wEditHeight == lp->uHeight)
return 0L;
 
lp->uHeight = (UINT)wEditHeight;
lp->ButtonRect.bottom = wEditHeight;
/*
** The following SetWindowPos causes WM_WINDOWPOSCHANGING message
** where child windows are resized and/or moved.
*/
ShowWindow(hWnd, SW_HIDE);
GetClientRect(hWnd,&rcClient);
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
SetWindowPos(hWnd, 0,
0, 0, rcClient.right, (int)wEditHeight,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW);
else SetWindowPos(hWnd, 0,
0, 0, rcClient.right, (int)wEditHeight + lp->ListBoxRect.bottom - lp->ListBoxRect.top + 1,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW);
ShowWindow(hWnd, SW_SHOWNA);
 
if (lp->EditControl)
SendMessage(lp->EditControl, WM_SETFONT, wParam,lParam);
SendMessage(lp->ListBoxControl, WM_SETFONT, wParam,lParam);
 
if(LOWORD(lParam))
RedrawWindow(hWnd,(const RECT *)0,(HRGN)0,
RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
return (LRESULT)0;
 
case WM_GETFONT:
return lp->hFont;
#endif /* WM_SETFONT/WM_GETFONT */
 
case WM_MOVE: /*WM_WINDOWPOSCHANGING:*/
#if 0
lpwp = (LPWINDOWPOS)lParam;
#else
pp.x=LOWORD(lParam);
pp.y=HIWORD(lParam);
#endif
if (1)/*(lpwp)*/ {
if (1)/*(!(lpwp->flags & SWP_NOSIZE))*/ {
lp->ButtonRect.right = (hWnd->winrect.right-hWnd->winrect.left); /* lpwp->cx; */
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
lp->ButtonRect.left = lp->ButtonRect.right;
else lp->ButtonRect.left = (hWnd->winrect.right-hWnd->winrect.left)/*lpwp->cx*/ - 1 -
GetSystemMetrics(SM_CXVSCROLL);
 
if (lp->EditControl)
{
wEditWidth = lp->ButtonRect.left + 1;
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
wEditWidth --;
if ((lp->wStyle & 0xf) == CBS_DROPDOWN)
wEditWidth -= 5;
SetWindowPos(lp->EditControl,(HWND)0,
0,0,
wEditWidth, lp->uHeight,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
}
if (lp->ListBoxControl)
{
if ((lp->wStyle & 0x0F) == CBS_SIMPLE)
{
lp->ListBoxRect.left = 5;
lp->ListBoxRect.top = lp->uHeight - 1;
lp->ListBoxRect.right = (hWnd->winrect.right-hWnd->winrect.left); /* lpwp->cx; */
lp->ListBoxRect.bottom = (hWnd->winrect.bottom-hWnd->winrect.top)/*lpwp->cy*/ - 2;
}
else {
POINT cp;
cp.x = 0;
cp.y = lp->uHeight - 1;
ClientToScreen(hWnd, &cp);
OffsetRect(&lp->ListBoxRect, cp.x - lp->ListBoxRect.left, cp.y - lp->ListBoxRect.top);
 
lp->ListBoxRect.right = lp->ListBoxRect.left + (hWnd->winrect.right-hWnd->winrect.left)/*lpwp->cx*/;
if ((lp->wStyle & 0xf) != CBS_DROPDOWNLIST)
lp->ListBoxRect.right -= 5;
}
 
SetWindowPos(lp->ListBoxControl,(HWND)0,
lp->ListBoxRect.left, lp->ListBoxRect.top,
lp->ListBoxRect.right - lp->ListBoxRect.left,
lp->ListBoxRect.bottom - lp->ListBoxRect.top,
SWP_NOACTIVATE|SWP_NOZORDER);
}
#if 0 /* jmt: fix: no WM_WINDOWPOSCHANGING */
/* the height of the normal state stays the same */
if ((lp->wStyle & 0xf) != CBS_SIMPLE)
lpwp->cy = (int)lp->uHeight;
#endif
}
}
return (LRESULT)0;
 
case WM_WINDOWPOSCHANGED:
DefWindowProc(hWnd,uMsg,wParam,lParam);
lpwp = (LPWINDOWPOS)lParam;
if (lpwp) {
if (!(lpwp->flags & SWP_NOSIZE)) /* TODO */
#if 0
RedrawWindow(hWnd,(const RECT *)0,(HRGN)0,
RDW_INVALIDATE|RDW_ERASE);
#else
InvalidateRect(hWnd,NULL,TRUE);
#endif
}
return (LRESULT)0;
 
#if 0 /* jmt: fix: no ownerdraw */
/*********************************************/
/* ownerdraw stuff */
/*********************************************/
case WM_DRAWITEM:
lpdis = (LPDRAWITEMSTRUCT)lParam;
lpdis->CtlType = ODT_COMBOBOX;
lpdis->CtlID = lp->nID;
lpdis->hwndItem = hWnd;
return SendMessage(lp->hWndParent,WM_DRAWITEM,
(WPARAM)lp->nID,lParam);
 
case WM_MEASUREITEM:
lpmis = (LPMEASUREITEMSTRUCT)lParam;
lpmis->CtlType = ODT_COMBOBOX;
lpmis->CtlID = lp->nID;
return SendMessage(lp->hWndParent,WM_MEASUREITEM,
(WPARAM)lp->nID,lParam);
 
case WM_DELETEITEM:
lpdlis = (LPDELETEITEMSTRUCT)lParam;
lpdlis->CtlType = ODT_COMBOBOX;
lpdlis->CtlID = lp->nID;
lpdlis->hwndItem = hWnd;
return SendMessage(lp->hWndParent,WM_DELETEITEM,
(WPARAM)lp->nID,lParam);
 
case WM_CONVERT:
if (!lpComboBinToNat) {
hComboClass32 = FindClass("COMBOBOX",0);
lpComboBinToNat = (WNDPROC)GetClassHandleLong(
hComboClass32,GCL_BINTONAT);
}
if (lpComboBinToNat)
return lpComboBinToNat(hWnd, uMsg, wParam, lParam);
else
return (LRESULT)0;
#endif /* ownerdraw */
 
default:
return DefCBProc( hWnd, uMsg, wParam, lParam);
}
return rc;
}
 
/************************************************************************
**
************************************************************************/
static LRESULT DefCBProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int len,index;
COMBOBOX *lp;
char *selection;
int rc;
POINT cp;
 
lp = (COMBOBOX *) hWnd->userdata/*GetWindowLong(hWnd,CWD_LPCBDATA)*/;
switch(uMsg) {
/*********************************************/
/* messages specific to the list box control */
/*********************************************/
case CB_ADDSTRING:
lp->nListItems++; /* shd. test for successful return */
return SendMessage(lp->ListBoxControl,LB_ADDSTRING,
wParam,lParam);
case CB_DELETESTRING:
if (lp->nListItems)
lp->nListItems--;
return SendMessage(lp->ListBoxControl,LB_DELETESTRING,
wParam,lParam);
case CB_DIR:
return SendMessage(lp->ListBoxControl,LB_DIR,
wParam,lParam);
case CB_FINDSTRING:
return SendMessage(lp->ListBoxControl,LB_FINDSTRING,
wParam,lParam);
case CB_FINDSTRINGEXACT:
return SendMessage(lp->ListBoxControl,LB_FINDSTRINGEXACT,
wParam,lParam);
case CB_GETCOUNT:
return SendMessage(lp->ListBoxControl,LB_GETCOUNT,
wParam,lParam);
case CB_GETCURSEL:
return SendMessage(lp->ListBoxControl,LB_GETCURSEL,
wParam,lParam);
case CB_GETITEMDATA:
return SendMessage(lp->ListBoxControl,LB_GETITEMDATA,
wParam,lParam);
case CB_GETITEMHEIGHT:
return SendMessage(lp->ListBoxControl,LB_GETITEMHEIGHT,
wParam,lParam);
case CB_GETLBTEXT:
return SendMessage(lp->ListBoxControl,LB_GETTEXT,
wParam,lParam);
case CB_GETLBTEXTLEN:
return SendMessage(lp->ListBoxControl,LB_GETTEXTLEN,
wParam,lParam);
case CB_INSERTSTRING:
return SendMessage(lp->ListBoxControl,LB_INSERTSTRING,
wParam,lParam);
case CB_SETITEMDATA:
return SendMessage(lp->ListBoxControl,LB_SETITEMDATA,
wParam,lParam);
/*********************************************/
/* messages specific to the edit control */
/*********************************************/
case CB_GETEDITSEL:
return SendMessage(lp->EditControl,EM_GETSEL,0,0);
case CB_LIMITTEXT:
return SendMessage(lp->EditControl,EM_LIMITTEXT,
wParam,lParam);
 
case CB_SETEDITSEL:
return SendMessage(lp->EditControl,EM_SETSEL,
wParam,lParam);
 
/*********************************************/
/* messages handled by the combobox */
/*********************************************/
case CB_GETDROPPEDCONTROLRECT:
CopyRect((LPRECT)lParam,&lp->ListBoxRect);
break;
case CB_GETDROPPEDSTATE:
return IS_SET(lp,CSF_CAPTUREACTIVE);
 
case CB_GETEXTENDEDUI:
return (LRESULT)lp->bExtended;
 
case CB_RESETCONTENT:
SendMessage(lp->ListBoxControl,LB_RESETCONTENT,0,0);
if (lp->EditControl)
SendMessage(lp->EditControl,WM_SETTEXT,0,(LPARAM)(LPSTR)"");
break;
 
case CB_SELECTSTRING:
index = (int)SendMessage(lp->ListBoxControl, LB_SELECTSTRING, wParam, lParam);
if (index == LB_ERR)
return CB_ERR;
 
len = (int)SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, index, 0);
if (len <= 0)
return CB_ERR;
 
selection = (LPSTR)WinMalloc((UINT)len+1);
rc = (int)SendMessage(lp->ListBoxControl, LB_GETTEXT, (WPARAM)index, (LPARAM)selection);
if (lp->EditControl)
rc = (int)SendMessage(lp->EditControl, WM_SETTEXT, 0, (LPARAM)selection);
else CBoxDrawStatic(lp, hWnd, index);
WinFree(selection);
break;
case CB_SETCURSEL:
rc = (int)SendMessage(lp->ListBoxControl, LB_SETCURSEL, wParam, lParam);
if (rc == LB_ERR)
return CB_ERR;
len = (int)SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, wParam, 0);
if (len <= 0)
return CB_ERR;
 
selection = (LPSTR)WinMalloc((UINT)len+1);
rc = (int)SendMessage(lp->ListBoxControl, LB_GETTEXT, wParam, (LPARAM)selection);
if (lp->EditControl)
rc = (int)SendMessage(lp->EditControl, WM_SETTEXT, 0, (LPARAM)selection);
else CBoxDrawStatic(lp, hWnd, wParam);
WinFree(selection);
return (LRESULT)wParam;
 
case CB_SETEXTENDEDUI:
lp->bExtended = (BOOL)wParam;
break;
 
case CB_SETITEMHEIGHT: /* TODO */
break;
 
case CB_SHOWDROPDOWN:
if ((lp->wStyle & 0xf) == CBS_SIMPLE)
return 1L;
if (wParam)
{
if (IS_SET(lp,CSF_CAPTUREACTIVE))
return 1L;
 
cp.x = ((lp->wStyle & 0xf) != CBS_DROPDOWNLIST) ? 5 : 0;
cp.y = lp->uHeight -1;
 
ClientToScreen(hWnd, &cp);
OffsetRect(&lp->ListBoxRect, cp.x - lp->ListBoxRect.left, cp.y - lp->ListBoxRect.top);
 
SetWindowPos(lp->ListBoxControl, 0,
cp.x, cp.y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
 
SendMessage(lp->hWndParent,WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_DROPDOWN));
 
fprintf(stderr," 1330: SetWindowPos(lp->ListBoxControl, , 0, 0, 0, 0,..)\n");
 
SetWindowPos(lp->ListBoxControl, HWND_TOP,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
CBoxCapture(hWnd, 1);
SET_STATE(lp,CSF_CAPTUREACTIVE);
}
else
{
if (!IS_SET(lp,CSF_CAPTUREACTIVE))
return 1L;
 
SendMessage(lp->hWndParent, WM_COMMAND, GET_WM_COMMAND_MPS(lp->nID,hWnd,CBN_CLOSEUP));
/* test: */
fprintf(stderr," 1343: (hide) SetWindowPos(lp->ListBoxControl, , 0, 0, 0, 0,..)\n");
 
SetWindowPos(lp->ListBoxControl, 0,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW);
 
CBoxCapture(hWnd, 0);
CLEAR_STATE(lp, CSF_CAPTUREACTIVE);
}
return 1L;
 
/*********************************************/
/* messages handled by the defwindowproc.... */
/*********************************************/
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam);
}
return CB_OKAY;
}
 
 
static void
CBoxDrawButton(HWND hWnd,UINT wState,COMBOBOX *lp)
{
HDC hDC;
int x,y;
int dx,dy;
#if 0 /* jmt: fix: no LoadBitmap() */
int cx,cy;
static int nWidth,nHeight;
BITMAP bmpCombo;
static HBITMAP hbmpCombo = 0;
HBITMAP hbmpOld = 0;
HDC hdcSrc;
COLORREF rgbText, rgbBk;
#endif
HBRUSH hBrush;
HPEN hPenHigh,hPenShadow;
RECT rc;
 
hDC = GetDC(hWnd);
 
CopyRect(&rc,&lp->ButtonRect);
x = rc.left;
y = rc.top;
dx = rc.right;
dy = rc.bottom;
 
hPenHigh = GetStockObject(WHITE_PEN);
#if 0
hPenShadow = GetSysColorPen(COLOR_BTNSHADOW);
#else
hPenShadow = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW));
#endif
#if 0
hBrush = GetSysColorBrush(COLOR_BTNFACE);
#else
hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
#endif
FillRect(hDC, &rc, hBrush);
#if 0
hBrush = GetStockObject(BLACK_BRUSH);
FillRect/*FrameRect*/(hDC, &lp->ButtonRect, hBrush);
#else
SelectObject(hDC,GetStockObject(BLACK_PEN));
Rectangle(hDC,lp->ButtonRect.left,lp->ButtonRect.top,lp->ButtonRect.right,lp->ButtonRect.bottom);
#endif
rc.left += 1; rc.right -= 1;
rc.top += 1; rc.bottom -= 1;
 
Draw3DButtonRect(hDC,hPenHigh,hPenShadow,rc,wState);
 
#if 0 /* jmt: fix: no LoadBitmap(),GetObject() */
if (hbmpCombo == 0)
{
hbmpCombo = LoadBitmap(0,(LPSTR)OBM_COMBO);
GetObject(hbmpCombo, sizeof(BITMAP), (LPVOID)&bmpCombo);
nWidth = bmpCombo.bmWidth;
nHeight = bmpCombo.bmHeight;
}
/*
** MiD 08/15/95 changed to mono bitmap as it is in Windows. Convert
** it to colors on the fly
*/
hdcSrc = CreateCompatibleDC(hDC);
hbmpOld = SelectObject(hdcSrc, hbmpCombo);
/*
** Source hdc ok. Prepare the target hdc, then BitBlt to it.
*/
rgbText = SetTextColor(hDC,GetSysColor(COLOR_BTNTEXT));
rgbBk = SetBkColor(hDC,GetSysColor(COLOR_BTNFACE));
 
cx = (dx - x - nWidth)/2;
cy = (dy - y - nHeight)/2;
if (wState)
{ cx++; cy++; }
BitBlt(hDC, x+cx, y+cy, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
 
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBk);
SelectObject(hdcSrc,hbmpOld);
DeleteDC(hdcSrc);
#endif /* BitBlt Bitmap */
#if 1
DeleteObject(hBrush);
DeleteObject(hPenShadow);
#endif
ReleaseDC(hWnd,hDC);
 
if (wState)
SET_STATE(lp,CSF_LOCALBUTTONDOWN);
else
CLEAR_STATE(lp,CSF_LOCALBUTTONDOWN);
}
 
#if 0 /* jmt: fix: no COMBOLBOX */
/************************************************************************
**
************************************************************************/
LRESULT DefCOMBOLBOXProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
#if 0
return DefLISTBOXProc(hWnd, msg, wParam,lParam);
#endif
return ListboxCtrlProc(hWnd, msg, wParam,lParam);
}
#endif
 
/************************************************************************
**
************************************************************************/
static void CBoxSendMouseToLBox(COMBOBOX *lp, UINT uiMsg, WPARAM wParam, POINT ptScreen)
{
POINT pt;
int nNCHit;
#if 0 /* jmt: fix: no scrollbar */
HWND hWndScroll;
#endif
pt = ptScreen;
ScreenToClient(lp->ListBoxControl,&pt);
 
nNCHit = LOSHORT(SendMessage(lp->ListBoxControl, WM_NCHITTEST, 0, MAKELPARAM(ptScreen.x,ptScreen.y)));
 
switch (nNCHit)
{
case HTCLIENT:
if (uiMsg == WM_MOUSEMOVE && !IS_SET(lp,CSF_LBOXBUTTONDOWN))
{
SendMessage(lp->ListBoxControl, WM_LBUTTONDOWN, 0, MAKELONG((WORD)pt.x,(WORD)pt.y));
 
SET_STATE(lp, CSF_BUTTONDOWN | CSF_LBOXBUTTONDOWN);
}
SendMessage(lp->ListBoxControl, uiMsg, wParam, MAKELONG((WORD)pt.x,(WORD)pt.y));
break;
 
#if 0 /* jmt: fix: no scrollbar */
case HTVSCROLL:
if (0 != (hWndScroll = TWIN_ConvertToSysScroll(lp->ListBoxControl, TRUE /* vertical */, &pt)))
SendMessage(hWndScroll, uiMsg, wParam, MAKELONG((WORD)pt.x,(WORD)pt.y));
break;
#endif
default:
break;
}
}
 
/************************************************************************
**
************************************************************************/
static void CBoxCapture(HWND hWnd, WORD wFunc)
{
static HWND hWndCapture = (HWND)0;
 
if (wFunc)
{
hWndCapture = SetCapture(hWnd);
 
SetFocus(hWnd);
}
else {
if (!hWndCapture)
ReleaseCapture();
else {
#ifdef LATER
SetCapture(hWndCapture);
#else
ReleaseCapture();
#endif
hWndCapture = (HWND)0;
}
}
}
 
/************************************************************************
**
************************************************************************/
static void CBoxDrawEdit(COMBOBOX *lp, HWND hWnd, UINT uiKey)
{
int nLen;
LPVOID lpData;
#if 0 /* jmt: fix: no ownerdraw */
HRGN hRgn;
DRAWITEMSTRUCT dis;
#endif
/*
if (uiKey == (UINT)LB_ERR)
return;
 
if (!BOWNERDRAW(lp))
*/
if (lp->wStyle & CBS_HASSTRINGS)
{
if (uiKey == (UINT)LB_ERR)
return;
nLen = (int)SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, uiKey, 0L);
if (nLen <= 0)
return;
lpData = (LPVOID)WinMalloc(nLen+1);
SendMessage(lp->ListBoxControl, LB_GETTEXT, uiKey, (LPARAM)lpData);
SendMessage(lp->EditControl, WM_SETTEXT, strlen(lpData), (LPARAM)lpData);
Edit_SetSel(lp->EditControl, 0, -1);
WinFree((LPSTR)lpData);
}
#if 0 /* jmt: fix: no ownerdraw */
else {
dis.CtlType = ODT_COMBOBOX;
dis.CtlID = (UINT)lp->nID;
dis.itemID = -1; /* used to be uiKey */
dis.itemAction = ODA_DRAWENTIRE;
dis.itemState = ODS_FOCUS;
dis.hwndItem = hWnd;
dis.itemData = 0;
GetClientRect(lp->EditControl,&dis.rcItem);
dis.rcItem.left += 3;
dis.rcItem.right -= 3;
dis.rcItem.top += 2;
dis.rcItem.bottom -= 2;
 
dis.hDC = GetDC(lp->EditControl);
hRgn = CreateRectRgnIndirect(&dis.rcItem);
SelectClipRgn(dis.hDC,hRgn);
SelectObject(dis.hDC, lp->hFont);
SendMessage(lp->hWndParent, WM_DRAWITEM, (WPARAM)(UINT)lp->nID, (LPARAM)&dis);
ReleaseDC(lp->EditControl,dis.hDC);
DeleteObject(hRgn);
}
#endif /* ownerdraw */
}
 
/************************************************************************
**
************************************************************************/
static void CBoxDrawStatic(COMBOBOX *lp, HWND hWnd, UINT uiKey)
{
int nLen;
HDC hdc;
LPVOID lpData;
RECT rcClient;
HFONT hfonOld = 0;
#if 0 /* jmt: fix: no ownerdraw */
HRGN hRgn;
DRAWITEMSTRUCT dis;
#endif
HBRUSH hbrStatic, hbrOld;
/* Draw rectangle regardless of ownerdraw style...
*/
hdc = GetDC(hWnd);
rcClient.left = 0;
rcClient.top = 0;
rcClient.right = lp->ButtonRect.left+1;
rcClient.bottom = lp->uHeight;
hbrStatic = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
hbrOld = SelectObject(hdc, hbrStatic);
SelectObject(hdc, GetStockObject(BLACK_PEN));/* ??? COLOR_WINDOWFRAME */
Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
SelectObject(hdc, hbrOld);
DeleteObject(hbrStatic);
ReleaseDC(hWnd, hdc);
 
if (uiKey == (UINT)LB_ERR)
return;
 
/* jmt: no ownerdraw */
if (1) /* (!BOWNERDRAW(lp)) */
{
/* if necessary, draw text */
hdc = GetDC(hWnd);
nLen = (int)SendMessage(lp->ListBoxControl, LB_GETTEXTLEN, (WPARAM)uiKey, 0L);
if (nLen > 0)
{
lpData = (LPVOID)WinMalloc(nLen+1);
SendMessage(lp->ListBoxControl, LB_GETTEXT, uiKey, (LPARAM)lpData);
SetBkMode(hdc, TRANSPARENT);
if (!IS_SET(lp, CSF_FOCUS))
{
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
rcClient.left += 2;
}
else {
InflateRect(&rcClient, -2, -2);
hbrStatic = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
hbrOld = SelectObject(hdc, hbrStatic);
FillRect(hdc, &rcClient, hbrStatic);
#if 0 /* jmt: fix: no DrawFocusRect() */
DrawFocusRect(hdc, &rcClient);
#endif
SelectObject(hdc, hbrOld);
DeleteObject(hbrStatic);
SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
if (lp->hFont)
hfonOld = SelectObject(hdc, lp->hFont);
DrawText(hdc, (LPSTR)lpData, nLen, &rcClient, DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
if (lp->hFont)
SelectObject(hdc, hfonOld);
WinFree((LPVOID)lpData);
}
ReleaseDC(hWnd, hdc);
}
#if 0 /* jmt: fix: no ownerdraw */
else { /* fill OWNERDRAWSTRUCT and send WM_DRAWITEM message */
dis.CtlType = ODT_COMBOBOX;
dis.CtlID = (UINT)lp->nID;
dis.itemID = uiKey;
dis.itemAction = ODA_DRAWENTIRE;
dis.itemState = ODS_FOCUS;
dis.hwndItem = hWnd;
dis.itemData = SendMessage(lp->ListBoxControl, LB_GETITEMDATA, uiKey, 0L);
GetClientRect(hWnd, &dis.rcItem);
dis.rcItem.left += 3;
dis.rcItem.right = lp->ButtonRect.left - 2; /* do not touch button */
dis.rcItem.top += 2;
dis.rcItem.bottom -= 2;
 
dis.hDC = GetDC(hWnd);
hRgn = CreateRectRgnIndirect(&dis.rcItem);
SelectClipRgn(dis.hDC, hRgn);
SelectObject(dis.hDC, lp->hFont);
SendMessage(lp->hWndParent, WM_DRAWITEM, (WPARAM)(UINT)lp->nID, (LPARAM)&dis);
ReleaseDC(hWnd, dis.hDC);
DeleteObject(hRgn);
}
#endif /* ownerdraw */
}
 
 
/*------------------------- < Full Revision History > ----------------------
** Revision 1.2 2001/11/06 23:35:46 greg
**
** Revision 1.1.1.1 2001/06/21 06:32:42 greg
** Microwindows pre8 with patches
**
** Revision 1.1.1.1 2001/06/05 03:44:01 root
** First import of 5/5/2001 Microwindows to CVS
**
** Revision 1.8 2000/08/14 jmt
** ported to microwin(non-client/server mode)
**
** Revision 1.7 2000/06/28 jmt
** porting to microwin
**
** Revision 1.6 2000/01/21 02:48:47 robf
** remove dead code
**
** Revision 1.5 1999/11/29 05:07:54 robf
** removed extraneous call CreateCompatibleDC
**
** Revision 1.4 1999/07/08 18:52:50 mwalsh
** Updated Comments
**
**-------------------------------------------------------------------------*/
 
/ptinsid.c
0,0 → 1,18
#include "windows.h"
#include "wintools.h"
 
BOOL WINAPI
PtInsideWindow(HWND hwnd,UINT x,UINT y)
{
/* Determine whether or not the position ( x, y) is contained */
/* within the control's client rectangle. */
 
RECT clientRect;
POINT buttonPoint;
 
buttonPoint.x = x;
buttonPoint.y = y;
 
GetClientRect( hwnd, &clientRect);
return PtInRect( &clientRect, buttonPoint);
}
/button.c
0,0 → 1,898
#include "windows.h"
#include "windowsx.h"
#include "wintools.h"
/*
* WINCTL Custom Control Library
* Push button Custom Control
* This control implements a custom pushbutton control.
*
* 4/8/98 g haerr original version from control palette v2.00, Blaise Computing
*/
 
#define GET_PBSTATE(h) (GetWindowWord(h, 0))
#define GET_PBCAPTURE(h) (GetWindowWord(h, 2))
#define GET_PBWASINSIDE(h) (GetWindowWord(h, 4))
#define GET_PBDELETEFONT(h) (GetWindowWord(h, 6))
#define GET_PBFONT(h) (GetWindowWord(h, 8))
 
#define SET_PBSTATE(h,x) (SetWindowWord(h, 0, x))
#define SET_PBCAPTURE(h,x) (SetWindowWord(h, 2, x))
#define SET_PBWASINSIDE(h,x) (SetWindowWord(h, 4, x))
#define SET_PBDELETEFONT(h,x) (SetWindowWord(h, 6, x))
#define SET_PBFONT(h,x) (SetWindowWord(h, 8, x))
 
#define PARENT(hwnd) ((HWND)GetWindowLong(hwnd,GWL_HWNDPARENT))
 
/* Internal state variable bit positions */
#define PUSH_UP 0x0000
#define PUSH_DOWN 0x0001 /* Button is down */
#define PUSH_FOCUS 0x0002 /* Button is focused */
#define PUSH_DISABLED 0x0004 /* Button is disabled */
#define PUSH_DEFAULT 0x0008 /* Button is currently a default */
#define PUSH_CHECKED 0x0010
 
/* Push Button states */
#define PBS_UP 0x0000 /* Normal button state. */
#define PBS_FOCUSDOWN 0x0001 /* Button pressed. */
#define PBS_FOCUSUP 0x0002 /* Focused state. */
#define PBS_DISABLED 0x0004 /* Disabled state. */
#define PBS_DEFAULT 0x0008 /* Default state. */
#define PBS_CHECKED 0x0010 /* checked state. */
 
#define WM_PAINT_SPECIAL WM_PAINT
#define HANDLE_WM_PAINT_SPECIAL(hwnd, wParam, lParam, fn) \
((fn)((hwnd),(HDC)(wParam)), 0L)
 
/* BOOL Cls_OnGetState( HWND hwnd); */
#define HANDLE_BM_GETSTATE(hwnd, wParam, lParam, fn) ((fn)(hwnd))
#define FORWARD_BM_GETSTATE(hwnd) \
(LONG)(fn)((hwnd), BM_GETSTATE, (WPARAM)0, (LPARAM)0)
 
/* void Cls_OnSetState( HWND hwnd, WORD wState); */
#define HANDLE_BM_SETSTATE( hwnd, wParam, lParam, fn) \
((fn)((hwnd), (WORD)wParam), 0)
#define FORWARD_BM_SETSTATE( hwnd, wState) \
(fn)((hwnd), BM_SETSTATE, (WPARAM)wState, (LPARAM)0)
 
/* void Cls_OnSetStyle( HWND hwnd, WORD style, BOOL bRedraw); */
#define HANDLE_BM_SETSTYLE( hwnd, wParam, lParam, fn) \
((fn)((hwnd), (WORD)wParam, (BOOL)LOWORD(lParam)), 0)
#define FORWARD_BM_SETSTYLE( hwnd, style, bRedraw, fn) \
(fn)((hwnd), BM_SETSTYLE, (WPARAM)style, MAKELPARAM(bRedraw, 0))
 
/* entry points*/
void WINAPI CheckRadioButton(HWND hDlg, int nIDFirst,int nIDLast,
int nIDCheckButton);
 
/* local procs*/
static void WINAPI cenButton_FnEnd( HWND, WORD);
static WORD WINAPI cenButton_FnStart( HWND);
static BOOL WINAPI cenButton_OnCreate( HWND, LPCREATESTRUCT);
/*static void WINAPI cenButton_OnDestroy( HWND);*/
/*static void WINAPI cenButton_OnEnable( HWND, BOOL);*/
static BOOL WINAPI cenButton_OnEraseBkgnd( HWND, HDC);
/*static UINT WINAPI cenButton_OnGetDlgCode( HWND, LPMSG);*/
static LONG WINAPI cenButton_OnGetState( HWND);
/*static void WINAPI cenButton_OnKey( HWND, UINT, BOOL, int, UINT);*/
static void WINAPI cenButton_OnKillFocus( HWND, HWND);
static void WINAPI cenButton_OnLButtonDown( HWND, BOOL, UINT, UINT, UINT);
static void WINAPI cenButton_OnLButtonUp( HWND, UINT, UINT, UINT);
static void WINAPI cenButton_OnMouseMove( HWND, UINT, UINT, UINT);
static void WINAPI cenButton_OnPaint( HWND, HDC);
static void WINAPI DrawPushButton(HWND hwnd,HDC hDCwParam,UINT wEnumState,
DWORD dwStyle);
static void WINAPI DrawGroupBox(HWND hwnd,HDC hDCwParam, DWORD dwStyle);
static void WINAPI cenButton_OnSetFocus( HWND, HWND);
static void WINAPI cenButton_OnSetStyle( HWND, WORD, BOOL);
static void WINAPI cenButton_OnSetState( HWND, WORD);
static void WINAPI cenButton_SetState( HWND, WORD, BOOL);
static void WINAPI cenButton_OnSetText( HWND, LPCSTR);
 
static void WINAPI
cenButton_FnEnd(
HWND hwnd,
WORD wState)
{
if( wState != GET_PBSTATE( hwnd)) {
if( IsWindowVisible( hwnd))
UpdateWindow( hwnd);
}
}
 
static WORD WINAPI
cenButton_FnStart(
HWND hwnd)
{
return GET_PBSTATE( hwnd);
}
 
static BOOL WINAPI
cenButton_OnCreate(
HWND hwnd,
LPCREATESTRUCT lpCreate)
{
/* Set initial states */
/*SET_PBDELETEFONT( hwnd, FALSE);*/
/*SET_PBFONT( hwnd, NULL);*/
SET_PBSTATE( hwnd, PUSH_UP );
SET_PBCAPTURE( hwnd, FALSE );
SET_PBWASINSIDE( hwnd, FALSE );
 
if ((lpCreate->style & 0x0f) == BS_DEFPUSHBUTTON)
cenButton_SetState( hwnd, PUSH_DEFAULT, TRUE );
 
if (lpCreate->style & WS_DISABLED)
cenButton_SetState( hwnd, PUSH_DISABLED, TRUE );
 
return( TRUE);
}
 
#if 0
static void WINAPI
cenButton_OnDestroy(
HWND hwnd)
{
if( GET_PBDELETEFONT( hwnd)) {
DeleteObject( GET_PBFONT( hwnd));
SET_PBDELETEFONT( hwnd, FALSE);
}
}
 
static void WINAPI
cenButton_OnEnable(
HWND hwnd,
BOOL bEnable)
{
WORD wState;
 
wState = cenButton_FnStart( hwnd);
cenButton_SetState( hwnd, PUSH_DISABLED, !bEnable);
cenButton_FnEnd( hwnd, wState);
}
#endif
 
static BOOL WINAPI
cenButton_OnEraseBkgnd(
HWND hwnd,
HDC hdc)
{
/* Background is erased at WM_PAINT time, so return TRUE*/
return TRUE;
}
 
#if 0
static UINT WINAPI
cenButton_OnGetDlgCode(
HWND hwnd,
LPMSG lpMsg)
{
/* WM_GETDLGCODE is sent by the dialog manager to find */
/* what type/style of control is responding and/or to */
/* determine what keystrokes the control wants to process */
/* itself. In this case, the pushbutton identifies itself */
/* and also indicates whether it is currently the default */
/* pushbutton. */
 
/*return( DLGC_BUTTON | ((GET_PBSTATE( hwnd) & PUSH_DEFAULT) ?
DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON));*/
return( DLGC_BUTTON);
}
#endif
 
static LONG WINAPI
cenButton_OnGetState(
HWND hwnd)
{
/* BM_GETSTATE is sent to enquire about the state of the */
/* control. It returns TRUE if the button is in the down */
/* state. */
 
return( ( GET_PBSTATE( hwnd) & PUSH_DOWN) == PUSH_DOWN);
}
 
#if 0
static void WINAPI
cenButton_OnKey(
HWND hwnd,
UINT vk,
BOOL bDown,
int cRepeat,
UINT flag)
{
WORD wState;
 
wState = cenButton_FnStart( hwnd);
if (bDown) {
/* WM_KEYDOWN is sent when a non-system key is pressed. */
/* If a spacebar is detected and the previous key state */
/* was up, then the control should switch to the down */
/* state. */
 
if ( (vk == ' ') && !(HIBYTE(flag) & 0x40) )
cenButton_SetState( hwnd, PUSH_DOWN, TRUE );
}
else {
/* WM_KEYUP is sent when a non-system key is released. */
/* If a space bar is detected, change to the up state. If */
/* the control is the focused control, send the BN_CLICKED */
/* notification message. */
 
if ( vk == ' ' )
{ cenButton_SetState( hwnd, PUSH_DOWN, FALSE );
 
if (GET_PBSTATE( hwnd) & PUSH_FOCUS) {
FORWARD_WM_COMMAND( PARENT( hwnd), GetDlgCtrlID( hwnd),
hwnd, BN_CLICKED, SendMessage);
if(!IsWindow(hwnd))
return;
}
}
}
cenButton_FnEnd( hwnd, wState);
}
#endif
 
static void WINAPI
cenButton_OnKillFocus(
HWND hwnd,
HWND hwndNewFocus)
{
WORD wState;
 
wState = cenButton_FnStart( hwnd);
cenButton_SetState( hwnd, PUSH_FOCUS, FALSE );
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnLButtonDown(
HWND hwnd,
BOOL bDblClick,
UINT x,
UINT y,
UINT keyState)
{
WORD wState;
 
wState = cenButton_FnStart( hwnd);
/* capture the mouse*/
SetCapture( hwnd );
/* set focus to ourself*/
SetFocus( hwnd );
SET_PBCAPTURE( hwnd, TRUE );
SET_PBWASINSIDE( hwnd, TRUE );
/* set down state*/
cenButton_SetState( hwnd, PUSH_DOWN, TRUE );
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnLButtonUp(
HWND hwnd,
UINT x,
UINT y,
UINT keys)
{
WORD wState;
DWORD dwStyle;
dwStyle = GetWindowLong(hwnd, GWL_STYLE);
wState = cenButton_FnStart( hwnd);
 
/* only draw up state if we captured mouse*/
if(GetCapture() == hwnd)
cenButton_SetState( hwnd, PUSH_DOWN, FALSE );
/* release mouse capture*/
ReleaseCapture();
 
/* if cursor is inside control, send clicked notification to parent*/
if (GET_PBWASINSIDE( hwnd)) {
switch((int)(dwStyle & 0x0f)) {
case BS_AUTOCHECKBOX:
SendMessage(hwnd,BM_SETCHECK,(wState & PBS_CHECKED)?0:1,0L);
break;
case BS_AUTORADIOBUTTON:
CheckRadioButton(PARENT(hwnd),0,0xffff,hwnd->id);
break;
}
FORWARD_WM_COMMAND( PARENT( hwnd), GetDlgCtrlID( hwnd), hwnd,
BN_CLICKED, SendMessage);
if(!IsWindow(hwnd))
return;
}
 
SET_PBCAPTURE( hwnd, FALSE );
SET_PBWASINSIDE( hwnd, FALSE );
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnMouseMove(
HWND hwnd,
UINT x,
UINT y,
UINT keys)
{
/* WM_MOUSEMOVE is sent at every discernable mouse */
/* movement. It is necessary to detect this because if */
/* the mouse has been captured (because of a button down */
/* message), the location of the cursor needs to be */
/* tracked. If it moves out of the confines of the */
/* control, the control should change to the focus/up */
/* state (and retain capture.) If the cursor then moves */
/* back into the control, change back to the down state. */
 
WORD wState;
DWORD dwStyle;
 
wState = cenButton_FnStart( hwnd);
dwStyle = GetWindowLong(hwnd, GWL_STYLE);
if( GET_PBCAPTURE( hwnd)) {
if( !PtInsideWindow( hwnd, x, y) ) {
if( GET_PBWASINSIDE( hwnd)) {
cenButton_SetState( hwnd, PUSH_DOWN, FALSE);
SET_PBWASINSIDE( hwnd, FALSE );
}
} else {
if( !GET_PBWASINSIDE( hwnd) ) {
cenButton_SetState( hwnd, PUSH_DOWN, TRUE );
SET_PBWASINSIDE( hwnd, TRUE );
}
}
}
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnPaint(
HWND hwnd,
HDC hDCwParam)
{
UINT wEnumState;
DWORD dwStyle;
 
if( GET_PBSTATE( hwnd) & PUSH_DISABLED)
wEnumState = PBS_DISABLED;
else if( GET_PBSTATE( hwnd) & PUSH_DOWN)
wEnumState = PBS_FOCUSDOWN;
else if( GET_PBSTATE( hwnd) & PUSH_CHECKED)
wEnumState = PBS_CHECKED;
else
{
if( GET_PBSTATE( hwnd) & PUSH_FOCUS)
wEnumState = PBS_FOCUSUP;
else
wEnumState = PBS_UP;
if( GET_PBSTATE( hwnd) & PUSH_DEFAULT)
wEnumState |= PBS_DEFAULT;
}
 
/* common draw code for button and checkbox*/
dwStyle = GetWindowLong(hwnd, GWL_STYLE);
switch((int)(dwStyle & 0x0f)) {
case BS_GROUPBOX:
DrawGroupBox( hwnd, hDCwParam, dwStyle);
break;
default:
DrawPushButton( hwnd, hDCwParam, wEnumState, dwStyle);
}
}
 
static void WINAPI
DrawPushButton(HWND hwnd,HDC hDCwParam,UINT wEnumState,DWORD dwStyle)
{
HDC hdc;
HBRUSH hNewBrush;
RECT rect;
RECT rectClient;
RECT rectSave;
RECT rc;
int iFaceOffset = 0;
INT uiHeight;
INT uiWidth;
COLORREF crOld;
COLORREF crBkOld;
int oldBkMode;
HFONT hNewFont;
HFONT hOldFont;
HPEN hOldPen;
COLORREF hOldColor;
PAINTSTRUCT ps;
char buf[256];
#define uiWidthFrame 0
#define uiWidthShadow 2
 
hdc = BeginPaint(hwnd, &ps);
if(!hdc)
goto Return;
 
GetWindowText(hwnd, buf, sizeof(buf));
GetClientRect( hwnd, &rectClient );
uiWidth = rectClient.right - rectClient.left;
uiHeight = rectClient.bottom - rectClient.top;
 
hNewBrush = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
crOld = SetTextColor( hdc, GetSysColor( COLOR_BTNTEXT));
crBkOld = SetBkColor( hdc, GetSysColor( COLOR_BTNFACE));
 
rc = rectClient;
switch((int)(dwStyle & 0x0f)) {
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON:
if( wEnumState & PBS_FOCUSDOWN) {
Draw3dBox(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_WINDOWFRAME), GetSysColor(COLOR_WINDOWFRAME));
InsetR(&rc, 1, 1);
Draw3dBox(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_BTNSHADOW), GetSysColor(COLOR_BTNSHADOW));
InsetR(&rc, 1, 1);
FastFillRect(hdc, &rc, GetSysColor(COLOR_BTNFACE));
iFaceOffset = 1;
} else {
if(wEnumState & PBS_DEFAULT) {
Draw3dBox(hdc, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_WINDOWFRAME),
GetSysColor(COLOR_WINDOWFRAME));
InsetR(&rc, 1, 1);
}
Draw3dBox(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_BTNHIGHLIGHT),GetSysColor(COLOR_WINDOWFRAME));
InsetR(&rc, 1, 1);
Draw3dBox(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_BTNSHADOW));
InsetR(&rc, 1, 1);
FastFillRect(hdc, &rc, GetSysColor(COLOR_BTNFACE));
iFaceOffset = 0;
}
break;
 
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
FastFillRect(hdc, &rc, GetSysColor(COLOR_BTNFACE));
/*rc.left += 2;*/
/*rc.top += 2;*/
rc.right = rc.left + 12;
rc.bottom = rc.top + 12;
/*Draw3dBox(hdc, rc.left, rc.top, 8, 8,
GetSysColor(COLOR_BTNSHADOW), GetSysColor(COLOR_3DLIGHT));*/
Draw3dInset(hdc, rc.left, rc.top, 12, 12);
InsetR(&rc, 2, 2);
FastFillRect(hdc, &rc, GetSysColor(COLOR_BTNHIGHLIGHT));
iFaceOffset = 1;
if(wEnumState & PBS_CHECKED) {
MoveToEx(hdc, rc.left, rc.top,NULL);
LineTo(hdc, rc.right, rc.bottom);
MoveToEx(hdc, rc.left, rc.bottom,NULL);
LineTo(hdc, rc.right, rc.top);
}
break;
 
case BS_AUTORADIOBUTTON:
case BS_RADIOBUTTON:
FastFillRect(hdc, &rc, GetSysColor(COLOR_BTNFACE));
rc.left = 0;
rc.top += 1;
rc.right = rc.left + 10;
rc.bottom = rc.top + 10;
 
SelectObject(hdc, GetStockObject(NULL_BRUSH));
hOldPen = SelectObject(hdc, CreatePen(PS_SOLID, 1,
GetSysColor(COLOR_BTNSHADOW)));
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
Ellipse(hdc,rc.left,rc.top, rc.right,rc.bottom);
InsetR(&rc, 1, 1);
 
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
DeleteObject(SelectObject(hdc,
CreatePen(PS_SOLID, 1,GetSysColor(COLOR_WINDOWFRAME))));
Ellipse(hdc,rc.left,rc.top, rc.right,rc.bottom);
DeleteObject(SelectObject(hdc, hOldPen));
 
iFaceOffset = 0;
if(wEnumState & PBS_CHECKED)
Ellipse(hdc, rc.left+2, rc.top+2, rc.right-2,
rc.bottom-2);
break;
}
 
/*
* draw text
*/
if(buf[ 0]) {
hNewFont = GetStockObject( DEFAULT_GUI_FONT);
hOldFont = SelectObject( hdc, hNewFont);
 
/* calculate text bounding rect*/
rect.left = 0;
rect.top = 0;
DrawText( hdc, buf, -1, &rect, DT_CALCRECT | DT_LEFT |
DT_SINGLELINE | DT_TOP);
rectSave = rect;
 
/*
* calculate text draw location
*/
switch((int)(dwStyle & (BS_LEFT|BS_CENTER|BS_RIGHT))) {
case BS_CENTER:
default:
rect.left = (uiWidth - (rect.right - rect.left)) / 2
+ iFaceOffset;
break;
case BS_LEFT:
rect.left = uiWidthFrame + uiWidthShadow + 2
+ iFaceOffset;
break;
case BS_RIGHT:
rect.left = (rect.right - rect.left) + uiWidthFrame
+ uiWidthShadow + 4 + iFaceOffset;
break;
}
 
switch((int)(dwStyle & 0x0f)) {
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
case BS_AUTORADIOBUTTON:
case BS_RADIOBUTTON:
rect.left = 12;
break;
}
 
rect.right += rect.left - rectSave.left;
 
switch((int)(dwStyle & (BS_TOP|BS_VCENTER|BS_BOTTOM))) {
case BS_VCENTER:
default:
rect.top = (uiHeight - (rect.bottom - rect.top)) / 2
+ iFaceOffset;
break;
case BS_TOP:
rect.top = 2 + uiWidthFrame + uiWidthShadow
+ iFaceOffset;
break;
case BS_BOTTOM:
rect.top = uiHeight - uiWidthFrame - uiWidthShadow -
(rect.bottom - rect.top) - 1 + iFaceOffset;
break;
}
switch((int)(dwStyle & 0x0f)) {
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
case BS_AUTORADIOBUTTON:
case BS_RADIOBUTTON:
rect.top = 0;
break;
}
rect.bottom += rect.top - rectSave.top;
 
oldBkMode = SetBkMode( hdc, TRANSPARENT);
if(wEnumState & PBS_DISABLED)
hOldColor = SetTextColor( hdc,
GetSysColor( COLOR_GRAYTEXT));
else
hOldColor = SetTextColor( hdc,
GetSysColor( COLOR_BTNTEXT));
 
DrawText( hdc, buf, -1, &rect,DT_LEFT | DT_SINGLELINE | DT_TOP);
 
SetBkMode( hdc, oldBkMode);
SetTextColor( hdc, hOldColor);
SelectObject( hdc, hOldFont);
}
 
#if 0
if( (!(wEnumState&PBS_CHECKED) && (wEnumState&PBS_FOCUSDOWN)) ||
(wEnumState & PBS_FOCUSUP)) {
rect = rectClient;
uiWidth = uiWidthFrame + uiWidthShadow + 2;
rect.left += uiWidth;
rect.top += uiWidth;
rect.right -= uiWidth;
rect.bottom -= uiWidth;
if((dwStyle & (BS_FLAT|BS_NOFOCUSRECT)) == 0)
DrawFocusRect( hdc, &rect);
}
#endif
 
SetTextColor( hdc, crOld);
SetBkColor( hdc, crBkOld);
 
Return:
EndPaint(hwnd, &ps);
}
 
static void WINAPI
cenButton_OnSetFocus(
HWND hwnd,
HWND hwndOldFocus)
{
/* WM_SETFOCUS is sent when the user clicks on the control */
/* or when the dialog manager determines that a keystroke */
/* should cause the control to be focused. This affects */
/* the appearance of the control so the state is saved for */
/* future drawing. */
 
WORD wState;
 
wState = cenButton_FnStart( hwnd);
/*if(!IsWindowEnabled(hwnd))
cenButton_SetState( hwnd, PUSH_FOCUS, TRUE );*/
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnSetStyle(
HWND hwnd,
WORD style,
BOOL bRedraw)
{
WORD wState;
 
wState = cenButton_FnStart( hwnd);
cenButton_SetState( hwnd, PUSH_DEFAULT,
(style & 0x0f) == BS_DEFPUSHBUTTON);
cenButton_FnEnd( hwnd, wState);
}
 
static void WINAPI
cenButton_OnSetState(
HWND hwnd,
WORD wState)
{
WORD wStateOld;
 
wStateOld = cenButton_FnStart( hwnd);
cenButton_SetState( hwnd, PUSH_DOWN, (wState ? TRUE : FALSE ) );
cenButton_FnEnd( hwnd, wStateOld);
}
 
static void WINAPI
cenButton_SetState(
HWND hwnd,
WORD wState,
BOOL bEnable )
{
/* Turn on/off state bits according to the bEnable flag. If the */
/* new state is different, invalidate the client window so that */
/* the proper bitmap is displayed. */
 
WORD wNewState;
WORD wOldState;
RECT rectClient;
 
wOldState = GET_PBSTATE( hwnd);
wNewState = (bEnable ? (wOldState | wState) : (wOldState & ~wState));
 
if (wOldState != wNewState)
{ SET_PBSTATE( hwnd, wNewState );
GetClientRect(hwnd, &rectClient);
InvalidateRect(hwnd, &rectClient, FALSE);
}
}
 
#if 0
static void WINAPI
cenButton_OnSetFont(
HWND hwnd,
HFONT hFont,
BOOL bRedraw)
{
BOOL bDeleteFont = FALSE;
HFONT hFontNew = 0;
LOGFONT logFont;
 
/* create a thin font*/
if( GetObject( hFont, sizeof( logFont), &logFont) != 0) {
if( logFont.lfWeight != FW_NORMAL) {
logFont.lfWeight = FW_NORMAL;
if( ( hFontNew = CreateFontIndirect( &logFont)) != 0) {
hFont = hFontNew;
bDeleteFont = TRUE;
}
}
}
 
if( GET_PBDELETEFONT( hwnd))
DeleteObject( GET_PBFONT( hwnd));
 
SET_PBDELETEFONT( hwnd, bDeleteFont);
SET_PBFONT( hwnd, hFont);
 
FORWARD_WM_SETFONT( hwnd, hFont, bRedraw, DefWindowProc);
}
#endif
 
static void WINAPI
cenButton_OnSetText(
HWND hwnd,
LPCSTR lpszText)
{
/* WM_SETTEXT is sent to change the text of the button */
/* control. In this case we allow the default window proc */
/* to handle the message first. But this only affects the */
/* internal Windows data structure of the control, it does */
/* not display the change. To do this we invalidate and */
/* update the client area of the control which displays */
/* the new text. */
 
FORWARD_WM_SETTEXT( hwnd, lpszText, DefWindowProc);
InvalidateRect( hwnd, NULL, FALSE);
UpdateWindow( hwnd);
}
 
LRESULT CALLBACK
cenButtonWndFn(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
/* This is the window proc for the pushbutton control. Most of */
/* the drawing is accomplished in the DrawPushButton() function. */
/* The code below is mainly concerned with the keyboard and mouse */
/* events that the control detects. */
 
switch( message) {
HANDLE_MSG( hwnd, WM_CREATE, cenButton_OnCreate);
/*HANDLE_MSG( hwnd, WM_ENABLE, cenButton_OnEnable);*/
HANDLE_MSG( hwnd, WM_SETFOCUS, cenButton_OnSetFocus);
HANDLE_MSG( hwnd, WM_KILLFOCUS, cenButton_OnKillFocus);
HANDLE_MSG( hwnd, WM_LBUTTONDOWN, cenButton_OnLButtonDown);
HANDLE_MSG( hwnd, WM_LBUTTONDBLCLK, cenButton_OnLButtonDown);
HANDLE_MSG( hwnd, WM_LBUTTONUP, cenButton_OnLButtonUp);
HANDLE_MSG( hwnd, WM_MOUSEMOVE, cenButton_OnMouseMove);
/*HANDLE_MSG( hwnd, WM_KEYDOWN, cenButton_OnKey);*/
/*HANDLE_MSG( hwnd, WM_KEYUP, cenButton_OnKey);*/
HANDLE_MSG( hwnd, WM_ERASEBKGND, cenButton_OnEraseBkgnd);
HANDLE_MSG( hwnd, WM_PAINT_SPECIAL, cenButton_OnPaint);
/*HANDLE_MSG( hwnd, WM_GETDLGCODE, cenButton_OnGetDlgCode);*/
HANDLE_MSG( hwnd, BM_SETSTYLE, cenButton_OnSetStyle);
HANDLE_MSG( hwnd, BM_GETSTATE, cenButton_OnGetState);
HANDLE_MSG( hwnd, BM_SETSTATE, cenButton_OnSetState);
/*HANDLE_MSG( hwnd, WM_DESTROY, cenButton_OnDestroy);*/
/*HANDLE_MSG( hwnd, WM_SETFONT, cenButton_OnSetFont);*/
HANDLE_MSG( hwnd, WM_SETTEXT, cenButton_OnSetText);
 
case BM_GETCHECK:
#if 0
return cenButton_OnGetState(hwnd);
#else
return( ( GET_PBSTATE(hwnd) & PUSH_CHECKED) == PUSH_CHECKED);
#endif
 
case BM_SETCHECK:
#if 0
cenButton_OnSetState(hwnd, (WORD)wParam);
#else
{
WORD wStateOld;
 
wStateOld = cenButton_FnStart( hwnd);
cenButton_SetState( hwnd, PUSH_CHECKED,
((WORD)wParam ? TRUE : FALSE) );
cenButton_FnEnd( hwnd, wStateOld);
}
#endif
return 0;
}
 
return DefWindowProc( hwnd, message, wParam, lParam);
}
 
/* backwards compatibility*/
int WINAPI
MwButtonRegister(HINSTANCE hInstance)
{
return MwRegisterButtonControl(hInstance);
}
 
int WINAPI
MwRegisterButtonControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)cenButtonWndFn;
wc.cbClsExtra = 0;
wc.cbWndExtra = 10;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "BUTTON";
 
return RegisterClass(&wc);
}
 
static void WINAPI
DrawGroupBox(HWND hwnd,HDC hDCwParam,DWORD dwStyle)
{
HDC hdc;
HFONT hFont;
RECT rcClient;
RECT rcText;
RECT rc;
PAINTSTRUCT ps;
char buf[256];
HPEN hPenTop, hPenBottom, holdPen;
COLORREF crTop,crBottom;
 
 
hdc = BeginPaint(hwnd, &ps);
if(!hdc)
goto Return;
 
GetWindowText(hwnd, buf, sizeof(buf));
GetClientRect( hwnd, &rcClient );
 
hFont = GetStockObject( DEFAULT_GUI_FONT);
if (hFont)
hFont = SelectObject(hdc,hFont);
 
rc.left = 0;
rc.top = 0;
DrawText( hdc, buf, -1, &rc, DT_CALCRECT);
 
if(buf[ 0]) {
SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
SetBkMode(hdc,TRANSPARENT);
SetRect(&rcText,8,2,rc.right+8,rc.bottom+2);
DrawText(hdc,buf,-1,&rcText,DT_CENTER);
}
 
crTop=GetSysColor(COLOR_BTNHIGHLIGHT);
crBottom=GetSysColor(COLOR_BTNSHADOW);
 
hPenTop = CreatePen( PS_SOLID, 1, crTop);
hPenBottom = CreatePen( PS_SOLID, 1, crBottom);
holdPen = SelectObject( hdc, hPenTop);
 
MoveToEx(hdc,0,rc.bottom/2,NULL);
 
if(buf[ 0]) {
LineTo(hdc,5,rc.bottom/2);
MoveToEx(hdc,rc.right+11,rc.bottom/2,NULL);
LineTo(hdc,rcClient.right-1,rc.bottom/2);
}
else
LineTo(hdc,rcClient.right-1,rc.bottom/2);
 
LineTo(hdc,rcClient.right-1,rcClient.bottom-1);
 
SelectObject( hdc, hPenBottom);
LineTo(hdc,rcClient.left,rcClient.bottom-1);
LineTo(hdc,rcClient.left,rc.bottom/2);
 
SelectObject( hdc, holdPen);
DeleteObject( hPenTop);
DeleteObject( hPenBottom);
 
if (hFont)
SelectObject(hdc,hFont);
 
Return:
EndPaint(hwnd, &ps);
}
 
/* temporarily here, should move to winuser.c*/
void WINAPI
CheckRadioButton(HWND hDlg, int nIDFirst,int nIDLast,int nIDCheckButton)
{
HWND hWndCheck,hWndTemp;
DWORD dwStyle;
 
if (!(hWndCheck = GetDlgItem(hDlg,nIDCheckButton)))
return;
 
for(hWndTemp=hDlg->children; hWndTemp; hWndTemp=hWndTemp->siblings) {
if(hWndCheck == hWndTemp) continue;
dwStyle = GetWindowLong(hWndTemp,GWL_STYLE);
if ((hWndTemp->id >= (WORD)nIDFirst) &&
(hWndTemp->id <= (WORD)nIDLast) &&
((LOWORD(dwStyle) == BS_RADIOBUTTON) ||
(LOWORD(dwStyle) == BS_AUTORADIOBUTTON)))
SendMessage(hWndTemp,BM_SETCHECK,FALSE,0);
}
SendMessage(hWndCheck,BM_SETCHECK,TRUE,0);
}
/mwuser.c
0,0 → 1,7
#include "windows.h"
 
int
MwUserInit(int ac,char **av)
{
return 0;
}
/listbox.c
0,0 → 1,1688
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Listbox for Microwindows win32 api.
*/
 
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library 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
*/
 
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
 
/* Note:
** Although there was a version by Zhao Jianghua, this version of
** LISTBOX control is written by Wei Yongming from scratch.
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** Wei Yongming 1999/10/18 Tsinghua Item Additional Data Finished
** Wei Yongming 1999/10/31 Tsinghua Space bar for checkmark Finished
** Wei Yongming 1999/10/31 Tsinghua Character match item Finished
** Wei Yongming 1999/11/07 Tsinghua Character match item Bug fixing
** WEI Yongming 2000/01/20 Tsinghua Thumb dragging Finished
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/05/26 gv port to microwin ported
** Greg Haerr 2000/06/15 Utah 3d look, bug fixes Finished
** Kevin Tseng 2000/06/22 gv port to mw-nanox ported
** Kevin Tseng 2000/06/22 gv fixed bug if no item Finished
** Kevin Tseng 2000/08/08 gv enable scrollbar(V) porting
** Kevin Tseng 2000/08/10 gv enable scrollbar(V) ported
** Kevin Tseng 2000/08/10 gv WM_CHAR, WM_KEYDOWN ported
**
** TODO:
** 1. Multiple columns support.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "windows.h"
#include "wintools.h" /* Draw3dBox */
#include "device.h" /* GdGetTextSize */
 
#define FixStrAlloc(n) malloc((n)+1)
#define FreeFixStr(p) free(p)
 
#define LBIF_NORMAL 0x0000L
#define LBIF_SELECTED 0x0001L
#define LBIF_CHECKED 0x0010L
#define LBIF_PARTCHECKED 0x0020L
#define LBIF_CHECKMARKMASK 0x00F0L
 
#define CMFLAG_BLANK 0
#define CMFLAG_CHECKED 1
#define CMFLAG_PARTCHECKED 2
typedef struct _LISTBOXITEMINFO {
int insPos; /* insert position */
char* string; /* item string */
int cmFlag; /* check mark flag */
HICON hIcon; /* handle of icon */
} LISTBOXITEMINFO, *PLISTBOXITEMINFO;
 
typedef struct _LISTBOXITEM {
char* key; /* item sort key */
DWORD dwFlags; /* item flags */
DWORD dwData; /* item data */
DWORD dwAddData; /* item additional data */
struct _LISTBOXITEM* next; /* next item */
} LISTBOXITEM, *PLISTBOXITEM;
 
#define DEF_LB_BUFFER_LEN 5
 
#define LBF_FOCUS 0x0001
#define LBF_NOTHINGSELECTED 0x0002
 
typedef struct _LISTBOXDATA {
DWORD dwFlags; /* listbox flags */
 
int itemCount; /* items count */
int itemTop; /* start display item */
int itemVisibles; /* number of visible items */
 
int itemHilighted; /* current hilighted item */
int itemHeight; /* item height */
 
LISTBOXITEM* head; /* items linked list head */
 
int buffLen; /* buffer length */
LISTBOXITEM* buffStart; /* buffer start */
LISTBOXITEM* buffEnd; /* buffer end */
LISTBOXITEM* freeList; /* free list in buffer */
} LISTBOXDATA, *PLISTBOXDATA;
 
void ListboxControlCleanup ();
static LRESULT CALLBACK
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
#define ITEM_BOTTOM(x) (x->itemTop + x->itemVisibles - 1)
 
#define LST_WIDTH_CHECKMARK 11
#define LST_HEIGHT_CHECKMARK 11
#define LST_INTER_BMPTEXT 2
 
int WINAPI MwRegisterListboxControl(HINSTANCE hInstance)
{
WNDCLASS wc;
#if 0
static BITMAP sg_bmpCheckMark;
if (!LoadSystemBitmap (&sg_bmpCheckMark, "checkmark")) {
fprintf (stderr, "Load ListBox Check Mark Bitmap failure!\n");
return FALSE;
}
#endif
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)ListboxCtrlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "LISTBOX";
 
return RegisterClass(&wc);
}
 
void ListboxControlCleanup ()
{
#if 0
UnloadBitmap (&sg_bmpCheckMark);
#endif
}
 
static LRESULT NotifyParent (HWND hwnd, int id, int code)
{
return SendMessage (GetParent (hwnd), WM_COMMAND,
(WPARAM) MAKELONG (id, code), (LPARAM)hwnd);
}
 
static BOOL lstInitListBoxData (HWND hwnd,LISTBOXDATA* pData, int len)
{
int i, xw, xh, xb;
PLISTBOXITEM plbi;
HDC hdc;
memset (pData, 0, sizeof (LISTBOXDATA));
#if 0
pData->itemHeight = GetSysCharHeight ();
#else
hdc=GetDC(hwnd);
#if MWCLIENT /* nanox client */
GrSetGCFont(hdc->gc,hdc->font->fontid);
GrGetGCTextSize(hdc->gc,"X",1,
MWTF_ASCII,&xw,&xh,&xb);
#else
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1,
&xw,&xh,&xb,MWTF_ASCII);
#endif
ReleaseDC(hwnd,hdc);
pData->itemHeight=xh + 1;
#endif
pData->itemHilighted = 0;
pData->dwFlags = LBF_NOTHINGSELECTED;
 
/* init item buffer. */
if (!(pData->buffStart = malloc (len * sizeof (LISTBOXITEM))))
return FALSE;
 
pData->buffLen = len;
pData->buffEnd = pData->buffStart + len;
pData->freeList = pData->buffStart;
 
plbi = pData->freeList;
for (i = 0; i < len - 1; i++) {
plbi->next = plbi + 1;
plbi ++;
}
plbi->next = NULL;
 
return TRUE;
}
 
static void lstListBoxCleanUp (LISTBOXDATA* pData)
{
PLISTBOXITEM plbi;
PLISTBOXITEM next;
 
plbi = pData->head;
while (plbi) {
FreeFixStr (plbi->key);
next = plbi->next;
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
 
plbi = next;
}
free (pData->buffStart);
}
 
static void lstResetListBoxContent (PLISTBOXDATA pData)
{
int i;
PLISTBOXITEM plbi, next;
 
pData->itemCount = 0;
pData->itemTop = 0;
pData->itemHilighted = 0;
#if 0
pData->itemVisibles = 0;
#endif
 
plbi = pData->head;
while (plbi) {
FreeFixStr (plbi->key);
next = plbi->next;
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
 
plbi = next;
}
 
pData->head = NULL;
pData->freeList = pData->buffStart;
 
plbi = pData->freeList;
for (i = 0; i < pData->buffLen - 1; i++) {
plbi->next = plbi + 1;
plbi ++;
}
plbi->next = NULL;
}
 
static PLISTBOXITEM lstAllocItem (PLISTBOXDATA pData)
{
PLISTBOXITEM plbi;
 
if (pData->freeList) {
plbi = pData->freeList;
pData->freeList = plbi->next;
}
else
plbi = (PLISTBOXITEM) malloc (sizeof (LISTBOXITEM));
return plbi;
}
 
static void lstFreeItem (PLISTBOXDATA pData, PLISTBOXITEM plbi)
{
if (plbi < pData->buffStart || plbi > pData->buffEnd)
free (plbi);
else {
plbi->next = pData->freeList;
pData->freeList = plbi;
}
}
 
static int lstAddNewItem (DWORD dwStyle,
PLISTBOXDATA pData, PLISTBOXITEM newItem, int pos)
{
PLISTBOXITEM plbi;
PLISTBOXITEM insPosItem = NULL;
int insPos = 0;
 
newItem->next = NULL;
if (!pData->head)
insPosItem = NULL;
else if (dwStyle & LBS_SORT) {
plbi = pData->head;
 
if (strcmp (newItem->key, plbi->key) < 0) {
insPosItem = NULL;
insPos = 0;
}
else {
while (plbi->next) {
if (strcmp (newItem->key, plbi->next->key) <= 0)
break;
plbi = plbi->next;
insPos ++;
}
insPosItem = plbi;
}
}
else {
plbi = pData->head;
 
if (pos < 0) {
while (plbi->next) {
plbi = plbi->next;
insPos ++;
}
insPosItem = plbi;
}
else if (pos > 0) {
int index = 0;
 
while (plbi->next) {
if (pos == index)
break;
plbi = plbi->next;
index ++;
insPos ++;
}
insPosItem = plbi;
}
}
 
if (insPosItem) {
plbi = insPosItem->next;
insPosItem->next = newItem;
newItem->next = plbi;
 
insPos ++;
}
else {
plbi = pData->head;
pData->head = newItem;
newItem->next = plbi;
}
 
pData->itemCount ++;
return insPos;
}
 
static PLISTBOXITEM lstRemoveItem (PLISTBOXDATA pData, int* pos)
{
int index = 0;
PLISTBOXITEM plbi, prev;
 
if (!pData->head)
return NULL;
 
if (*pos < 0) {
prev = pData->head;
plbi = pData->head;
while (plbi->next) {
prev = plbi;
plbi = plbi->next;
index ++;
}
 
if (plbi == pData->head) {
pData->head = pData->head->next;
*pos = 0;
return plbi;
}
else {
prev->next = plbi->next;
*pos = index;
return plbi;
}
}
else if (*pos == 0) {
plbi = pData->head;
pData->head = plbi->next;
return plbi;
}
else {
index = 0;
prev = pData->head;
plbi = pData->head;
while (plbi->next) {
if (*pos == index)
break;
 
prev = plbi;
plbi = plbi->next;
index ++;
}
 
if (plbi == pData->head) {
pData->head = pData->head->next;
*pos = 0;
return plbi;
}
else {
prev->next = plbi->next;
*pos = index;
return plbi;
}
}
 
return NULL;
}
 
static void lstGetItemsRect (PLISTBOXDATA pData, int start, int end, RECT* prc)
{
if (start < 0)
start = 0;
 
prc->top = (start - pData->itemTop)*pData->itemHeight;
 
if (end >= 0)
prc->bottom = (end - pData->itemTop + 1)*pData->itemHeight;
 
}
 
static void lstInvalidateItem (HWND hwnd, PLISTBOXDATA pData, int pos,BOOL fEBk)
{
RECT rcInv;
if (pos < pData->itemTop || pos > (pData->itemTop + pData->itemVisibles))
return;
GetClientRect (hwnd, &rcInv);
rcInv.top = (pos - pData->itemTop)*pData->itemHeight;
rcInv.bottom = rcInv.top + pData->itemHeight;
 
InvalidateRect (hwnd, &rcInv, fEBk);
}
 
static BOOL lstInvalidateUnderItem (HWND hwnd, PLISTBOXDATA pData, int pos)
{
RECT rcInv;
if (pos > (pData->itemTop + pData->itemVisibles))
return FALSE;
 
if (pos <= pData->itemTop) {
InvalidateRect (hwnd, NULL, TRUE);
return TRUE;
}
GetClientRect (hwnd, &rcInv);
 
lstGetItemsRect (pData, pos, -1, &rcInv);
 
if (rcInv.top < rcInv.bottom)
InvalidateRect (hwnd, &rcInv, TRUE);
 
return TRUE;
}
 
static PLISTBOXITEM lstGetItem (PLISTBOXDATA pData, int pos)
{
int i;
PLISTBOXITEM plbi;
 
plbi = pData->head;
for (i=0; i < pos && plbi; i++)
plbi = plbi->next;
 
return plbi;
}
 
static int lstFindItem (PLISTBOXDATA pData, int start, char* key, BOOL bExact)
{
PLISTBOXITEM plbi;
int keylen = strlen (key);
if (start >= (pData->itemCount - 1))
start = 0;
 
plbi = lstGetItem (pData, start);
 
while (plbi)
{
if (bExact && (keylen != strlen (plbi->key))) {
plbi = plbi->next;
start ++;
continue;
}
 
if (strncasecmp (key, plbi->key, keylen) == 0)
return start;
plbi = plbi->next;
start ++;
}
 
return LB_ERR;
}
 
static void lstOnDrawSListBoxItems (HDC hdc, DWORD dwStyle,
PLISTBOXDATA pData, int width)
{
PLISTBOXITEM plbi;
int i;
int x = 0, y = 0;
int offset;
RECT rc;
COLORREF bk;
 
plbi = lstGetItem (pData, pData->itemTop);
for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) {
 
if (plbi->dwFlags & LBIF_SELECTED) {
SetBkColor (hdc, bk = BLUE);
SetTextColor (hdc, WHITE);
}
else {
SetBkColor (hdc, bk = WHITE);
SetTextColor (hdc, BLACK);
}
rc.left = 0;
rc.top = y;
rc.right = width;
rc.bottom = y + pData->itemHeight;
FastFillRect(hdc, &rc, bk);
 
if (dwStyle & LBS_CHECKBOX) {
x = LST_INTER_BMPTEXT;
if (plbi->dwFlags & LBIF_CHECKED)
offset = 0;
else if (plbi->dwFlags & LBIF_PARTCHECKED)
offset = LST_WIDTH_CHECKMARK << 1;
else
offset = LST_WIDTH_CHECKMARK;
#if 0 /* fix: no bitmap */
FillBoxWithBitmapPart (hdc,
x, y + ((pData->itemHeight - LST_HEIGHT_CHECKMARK)>>1),
LST_WIDTH_CHECKMARK, LST_HEIGHT_CHECKMARK,
0, 0,
&sg_bmpCheckMark,
offset, 0);
#endif
x += LST_WIDTH_CHECKMARK + LST_INTER_BMPTEXT;
}
#if 0 /* fix: no icon */
if (dwStyle & LBS_USEICON && plbi->dwData) {
DrawIcon (hdc,
x, y, pData->itemHeight, pData->itemHeight,
(HICON) plbi->dwData);
x += pData->itemHeight + LST_INTER_BMPTEXT;
}
#endif
 
/* jmt: should be SYSTEM_FIXED_FONT because of minigui's GetSysCharXXX() */
#if 0
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
#endif
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
TextOut (hdc, x+2, y, plbi->key,-1);
 
y += pData->itemHeight;
plbi = plbi->next;
}
}
 
static int lstSelectItem (DWORD dwStyle, PLISTBOXDATA pData, int newSel)
{
PLISTBOXITEM plbi, newItem;
int index;
newItem = lstGetItem (pData, newSel);
#if 1 /* jmt: fixed if no item added */
if (!newItem) return -1;
#endif
#ifdef _DEBUG
if (!newItem)
fprintf (stderr, "ASSERT failed: return value of lstGetItem"
" in lstSelectItem.\n");
#endif
 
if (dwStyle & LBS_MULTIPLESEL) {
newItem->dwFlags ^= LBIF_SELECTED;
return newSel;
}
 
index = 0;
plbi = pData->head;
while (plbi) {
if (plbi->dwFlags & LBIF_SELECTED) {
if (index != newSel) {
plbi->dwFlags &= ~LBIF_SELECTED;
newItem->dwFlags |= LBIF_SELECTED;
return index;
}
break;
}
 
plbi = plbi->next;
index ++;
}
 
newItem->dwFlags |= LBIF_SELECTED;
return -1;
}
 
static void lstDrawFocusRect (HDC hdc, PLISTBOXDATA pData, RECT* rc)
{
HGDIOBJ oldbrush,oldpen;
 
if (pData->itemHilighted < pData->itemTop
|| pData->itemHilighted > (pData->itemTop + pData->itemVisibles))
return;
 
if (pData->dwFlags & LBF_FOCUS) {
lstGetItemsRect (pData, pData->itemHilighted, pData->itemHilighted, rc);
#if 0
InflateRect (rc, -1, -1);
 
FocusRect (hdc, rc->left - 1, rc->top, rc->right, rc->bottom);
#else
oldbrush=SelectObject(hdc, GetStockObject(NULL_BRUSH));
oldpen=SelectObject(hdc, CreatePen(PS_SOLID, 1,
GetSysColor(COLOR_BTNHIGHLIGHT)));
#if 0
GdSetMode(MWMODE_XOR);
#endif
Rectangle (hdc, rc->left, rc->top, rc->right, rc->bottom);
#if 0
GdSetMode(MWMODE_SET);
#endif
SelectObject(hdc,oldbrush);
DeleteObject(SelectObject(hdc,oldpen));
#endif
}
}
 
static void lstCalcParams (const RECT* rcClient, PLISTBOXDATA pData)
{
#define RECTHP(prc) (prc->bottom - prc->top)
pData->itemVisibles = (RECTHP (rcClient)) / pData->itemHeight;
 
#if 1 /* test calculation of itemVisibles */
if( ((RECTHP (rcClient)) % pData->itemHeight) )
pData->itemVisibles++;
#endif
}
 
extern BOOL SetScrollPos (HWND hWnd, int iSBar, int iNewPos);
extern BOOL EnableScrollBar (HWND hWnd, int iSBar, BOOL bEnable);
 
static void lstSetVScrollInfo (HWND hwnd, PLISTBOXDATA pData, BOOL fRedraw)
{
SCROLLINFO si;
 
if (pData->itemVisibles >= pData->itemCount)
{
SetScrollPos (hwnd, SB_VERT, 0);
EnableScrollBar (hwnd, SB_VERT, FALSE);
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = pData->itemCount - 1;
si.nMin = 0;
si.nPage = min (pData->itemVisibles, (pData->itemCount - pData->itemTop));
si.nPos = pData->itemTop;
 
SetScrollInfo (hwnd, SB_VERT, &si, fRedraw);
EnableScrollBar (hwnd, SB_VERT, TRUE);
}
 
LRESULT CALLBACK
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HWND pCtrl;
PLISTBOXDATA pData;
DWORD dwStyle;
pCtrl = hwnd;
dwStyle = pCtrl->style;
 
switch (message)
{
case WM_CREATE:
pData = (LISTBOXDATA*) malloc (sizeof(LISTBOXDATA));
if (pData == NULL)
return -1;
 
pCtrl->userdata = (DWORD)pData;
if (!lstInitListBoxData (hwnd, pData, DEF_LB_BUFFER_LEN)) {
free (pData);
return -1;
}
break;
 
case WM_SIZE:
{
RECT rc;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
GetClientRect(hwnd, &rc);
lstCalcParams (&rc, pData);
}
break;
 
case WM_DESTROY:
pData = (PLISTBOXDATA)pCtrl->userdata;
lstListBoxCleanUp (pData);
free (pData);
break;
 
case LB_RESETCONTENT:
pData = (PLISTBOXDATA)pCtrl->userdata;
lstResetListBoxContent (pData);
InvalidateRect (hwnd, NULL, TRUE);
break;
case LB_ADDSTRING:
case LB_INSERTSTRING:
{
char* string = NULL;
PLISTBOXITEMINFO plbii = NULL;
PLISTBOXITEM newItem;
int pos;
if (dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON) {
plbii = (PLISTBOXITEMINFO)lParam;
if (!plbii)
return LB_ERR;
 
string = plbii->string;
}
else {
string = (char*)lParam;
if (string == NULL || string [0] == '\0')
return LB_ERR;
}
 
pData = (PLISTBOXDATA)pCtrl->userdata;
newItem = lstAllocItem (pData);
if (!newItem) {
NotifyParent (hwnd, pCtrl->id, LBN_ERRSPACE);
return LB_ERRSPACE;
}
 
newItem->key = FixStrAlloc (strlen (string));
strcpy (newItem->key, string);
newItem->dwFlags = LBIF_NORMAL;
if (plbii) {
switch (plbii->cmFlag) {
case CMFLAG_CHECKED:
newItem->dwFlags |= LBIF_CHECKED;
break;
case CMFLAG_PARTCHECKED:
newItem->dwFlags |= LBIF_PARTCHECKED;
break;
}
if (dwStyle & LBS_USEICON)
newItem->dwData = (DWORD)plbii->hIcon;
else
newItem->dwData = 0L;
}
newItem->dwAddData = 0L;
 
if (message == LB_ADDSTRING)
pos = lstAddNewItem (dwStyle, pData, newItem, -1);
else
pos = lstAddNewItem (dwStyle, pData, newItem, (int)wParam);
 
lstInvalidateUnderItem (hwnd, pData, pos);
 
lstSetVScrollInfo (hwnd, pData, TRUE);
 
return pos;
}
break;
case LB_DELETESTRING:
{
PLISTBOXITEM removed;
int delete;
 
delete = (int)wParam;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
removed = lstRemoveItem (pData, &delete);
if (removed) {
FreeFixStr (removed->key);
lstFreeItem (pData, removed);
pData->itemCount --;
 
if (pData->itemTop != 0
&& pData->itemCount <= pData->itemVisibles) {
pData->itemTop = 0;
InvalidateRect (hwnd, NULL, TRUE);
}
else {
lstInvalidateUnderItem (hwnd, pData, delete);
if (delete <= pData->itemTop) {
pData->itemTop --;
if (pData->itemTop < 0)
pData->itemTop = 0;
}
}
 
if (pData->itemHilighted >= pData->itemCount) {
pData->itemHilighted = pData->itemCount - 1;
if (pData->itemHilighted < 0)
pData->itemHilighted = 0;
}
 
if (pData->itemHilighted < pData->itemTop)
pData->itemHilighted = pData->itemTop;
if (pData->itemHilighted > ITEM_BOTTOM (pData))
pData->itemHilighted = ITEM_BOTTOM (pData);
lstSetVScrollInfo (hwnd, pData, TRUE);
}
}
break;
 
case LB_FINDSTRING:
if( *(char*)lParam == '\0' )
return LB_ERR;
pData = (PLISTBOXDATA)pCtrl->userdata;
return lstFindItem(pData, (int)wParam, (char*)lParam, FALSE);
 
case LB_FINDSTRINGEXACT:
if( *(char*)lParam == '\0' )
return LB_ERR;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
return lstFindItem(pData, (int)wParam, (char*)lParam, TRUE);
case LB_SETTOPINDEX:
{
int newTop = (int) wParam;
pData = (PLISTBOXDATA)pCtrl->userdata;
 
if (newTop <0)
newTop = 0;
else if (newTop > pData->itemCount - pData->itemVisibles)
newTop = pData->itemCount - pData->itemVisibles;
if (pData->itemTop != newTop) {
pData->itemTop = newTop;
 
if (pData->itemHilighted < pData->itemTop)
pData->itemHilighted = pData->itemTop;
if (pData->itemHilighted > ITEM_BOTTOM (pData))
pData->itemHilighted = ITEM_BOTTOM (pData);
 
lstSetVScrollInfo (hwnd, pData, TRUE);
 
InvalidateRect (hwnd, NULL, TRUE);
}
}
break;
case LB_SETCURSEL:
case LB_SETCARETINDEX:
{
int new = (int)wParam;
int old, newTop;
pData = (PLISTBOXDATA)pCtrl->userdata;
if (new < 0 || new > pData->itemCount - 1)
return LB_ERR;
 
old = pData->itemHilighted;
if (new >= 0 && new != old) {
if (pData->itemCount - new >= pData->itemVisibles)
newTop = new;
else
newTop = max (pData->itemCount - pData->itemVisibles, 0);
 
pData->itemTop = newTop;
pData->itemHilighted = new;
lstSetVScrollInfo (hwnd, pData, TRUE);
}
 
if (!(dwStyle & LBS_MULTIPLESEL))
lstSelectItem (dwStyle, pData, new);
InvalidateRect (hwnd, NULL, TRUE);
 
return old;
}
break;
case LB_GETCOUNT:
pData = (PLISTBOXDATA)pCtrl->userdata;
return pData->itemCount;
break;
case LB_GETCURSEL:
{
PLISTBOXITEM plbi;
int index = 0;
pData = (PLISTBOXDATA)pCtrl->userdata;
if (dwStyle & LBS_MULTIPLESEL)
return pData->itemHilighted;
 
plbi = pData->head;
while (plbi) {
if (plbi->dwFlags & LBIF_SELECTED)
return index;
 
index ++;
plbi = plbi->next;
}
return LB_ERR;
}
break;
case LB_GETSELCOUNT:
{
int nSel;
PLISTBOXITEM plbi;
pData = (PLISTBOXDATA)pCtrl->userdata;
 
nSel = 0;
plbi = pData->head;
while (plbi) {
if (plbi->dwFlags & LBIF_SELECTED)
nSel ++;
plbi = plbi->next;
}
return nSel;
}
break;
case LB_GETTOPINDEX:
pData = (PLISTBOXDATA)pCtrl->userdata;
return pData->itemTop;
break;
case LB_GETCARETINDEX:
pData = (PLISTBOXDATA)pCtrl->userdata;
return pData->itemHilighted;
break;
 
case LB_GETTEXTLEN:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = lstGetItem (pData, (int)wParam);
if (plbi)
return strlen (plbi->key);
else
return LB_ERR;
}
break;
case LB_GETTEXT:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = lstGetItem (pData, (int)wParam);
if (plbi)
strcpy ((char*)lParam, plbi->key);
else
return LB_ERR;
}
break;
 
case LB_SETTEXT:
{
PLISTBOXITEM plbi;
char* newStr;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = lstGetItem (pData, (int)wParam);
if (plbi) {
newStr = FixStrAlloc (strlen ((char*)lParam));
if (newStr) {
FreeFixStr (plbi->key);
plbi->key = newStr;
strcpy (plbi->key, (char*)lParam);
lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
}
else
return LB_ERR;
}
else
return LB_ERR;
}
break;
case LB_GETITEMDATA:
{
PLISTBOXITEM plbi;
PLISTBOXITEMINFO plbii;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
if (!(dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) {
return plbi->dwData;
}
plbii = (PLISTBOXITEMINFO)lParam;
if (!plbii)
return LB_ERR;
 
if (plbi->dwFlags & LBIF_CHECKED)
plbii->cmFlag = CMFLAG_CHECKED;
else if (plbi->dwFlags & LBIF_PARTCHECKED)
plbii->cmFlag = CMFLAG_PARTCHECKED;
else
plbii->cmFlag = CMFLAG_BLANK;
plbii->hIcon = (HICON)plbi->dwData;
 
return LB_OKAY;
}
break;
case LB_SETITEMDATA:
{
PLISTBOXITEM plbi;
PLISTBOXITEMINFO plbii;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
if (!(dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) {
plbi->dwData = (DWORD)lParam;
return LB_OKAY;
}
 
plbii = (PLISTBOXITEMINFO)lParam;
if (!plbii)
return LB_ERR;
 
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
switch (plbii->cmFlag) {
case CMFLAG_CHECKED:
plbi->dwFlags |= LBIF_CHECKED;
break;
case CMFLAG_PARTCHECKED:
plbi->dwFlags |= LBIF_PARTCHECKED;
break;
}
if (dwStyle & LBS_USEICON)
plbi->dwData = (DWORD)plbii->hIcon;
else
plbi->dwData = 0;
lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
 
return LB_OKAY;
}
break;
case LB_GETITEMADDDATA:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
return plbi->dwAddData;
}
break;
case LB_SETITEMADDDATA:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
plbi->dwAddData = (DWORD)lParam;
 
return LB_OKAY;
}
break;
case LB_GETCHECKMARK:
{
PLISTBOXITEM plbi;
 
if (!(dwStyle & LBS_CHECKBOX))
return LB_ERR;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
if (plbi->dwFlags & LBIF_CHECKED)
return CMFLAG_CHECKED;
 
if (plbi->dwFlags & LBIF_PARTCHECKED)
return CMFLAG_PARTCHECKED;
 
return CMFLAG_BLANK;
}
break;
 
case LB_SETCHECKMARK:
{
PLISTBOXITEM plbi;
 
if (!(dwStyle & LBS_CHECKBOX))
return LB_ERR;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (!(plbi = lstGetItem (pData, (int)wParam)))
return LB_ERR;
 
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
switch (lParam) {
case CMFLAG_CHECKED:
plbi->dwFlags |= LBIF_CHECKED;
break;
case CMFLAG_PARTCHECKED:
plbi->dwFlags |= LBIF_PARTCHECKED;
break;
}
lstInvalidateItem (hwnd, pData, (int)wParam, TRUE);
 
return LB_OKAY;
}
break;
 
case LB_GETSELITEMS:
{
int nItem;
int nSel = 0;
int index = 0;
int* pInt;
PLISTBOXITEM plbi;
 
nItem = (int)wParam;
pInt = (int*)lParam;
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = pData->head;
while (plbi) {
 
if (plbi->dwFlags & LBIF_SELECTED) {
if (pInt) {
if (nSel < nItem)
*(pInt + nSel) = index;
else
return nItem;
}
nSel ++;
}
plbi = plbi->next;
index ++;
}
return nSel;
}
break;
case LB_GETSEL:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = lstGetItem (pData, (int)wParam);
if (plbi)
return plbi->dwFlags & LBIF_SELECTED;
else
return LB_ERR;
}
break;
 
case LB_SETSEL:
{
PLISTBOXITEM plbi;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
plbi = lstGetItem (pData, (int)lParam);
if (plbi) {
pData->dwFlags &= ~LBF_NOTHINGSELECTED;
if (wParam == -1)
plbi->dwFlags ^= LBIF_SELECTED;
else if (wParam == 0)
plbi->dwFlags &= ~LBIF_SELECTED;
else
plbi->dwFlags |= LBIF_SELECTED;
 
lstInvalidateItem (hwnd, pData, (int)lParam, FALSE);
}
else
return LB_ERR;
}
break;
case LB_GETITEMHEIGHT:
pData = (PLISTBOXDATA)pCtrl->userdata;
return pData->itemHeight;
break;
case LB_SETITEMHEIGHT:
pData = (PLISTBOXDATA)pCtrl->userdata;
if (pData->itemHeight != LOWORD (lParam)) {
RECT rcClient;
pData->itemHeight = LOWORD (lParam);
GetClientRect (hwnd, &rcClient);
lstCalcParams (&rcClient, pData);
lstSetVScrollInfo (hwnd, pData, TRUE);
InvalidateRect (hwnd, NULL, TRUE);
}
break;
 
case WM_SETFOCUS:
{
pData = (PLISTBOXDATA)pCtrl->userdata;
 
if (pData->dwFlags & LBF_FOCUS)
break;
pData->dwFlags |= LBF_FOCUS;
InvalidateRect(hwnd, NULL, TRUE);
 
NotifyParent (hwnd, pCtrl->id, LBN_SETFOCUS);
}
break;
case WM_KILLFOCUS:
{
pData = (PLISTBOXDATA)pCtrl->userdata;
 
pData->dwFlags &= ~LBF_FOCUS;
InvalidateRect(hwnd, NULL, TRUE);
 
NotifyParent (hwnd, pCtrl->id, LBN_KILLFOCUS);
}
break;
 
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTCHARS;
 
case WM_GETTEXTLENGTH:
case WM_GETTEXT:
case WM_SETTEXT:
return -1;
#if 0
case WM_SETFONT:
break;
case WM_GETFONT:
break;
#endif
case WM_NCCALCSIZE:
{
LPNCCALCSIZE_PARAMS lpnc;
 
/* calculate client rect from passed window rect in rgrc[0]*/
lpnc = (LPNCCALCSIZE_PARAMS)lParam;
if(GetWindowLong(hwnd, GWL_STYLE) & WS_BORDER)
InflateRect(&lpnc->rgrc[0], -2, -2);
}
break;
 
case WM_NCPAINT:
{
RECT rc;
 
hdc = wParam? (HDC)wParam: GetWindowDC (hwnd);
GetWindowRect(hwnd, &rc);
 
if (dwStyle & WS_BORDER)
Draw3dInset(hdc, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top);
 
if (!wParam)
ReleaseDC (hwnd, hdc);
}
break;
 
case WM_PAINT:
{
RECT rc;
PAINTSTRUCT ps;
hdc = BeginPaint (hwnd,&ps);
pData = (PLISTBOXDATA)pCtrl->userdata;
 
/*
* If this is the first paint and there's nothing
* selected, then auto select the topmost displayed item.
*/
if (pData->dwFlags & LBF_NOTHINGSELECTED) {
lstSelectItem (hwnd->style, pData, pData->itemTop);
pData->dwFlags &= ~LBF_NOTHINGSELECTED;
}
GetClientRect (hwnd, &rc);
lstOnDrawSListBoxItems (hdc, dwStyle, pData, rc.right-rc.left);
lstDrawFocusRect (hdc, pData, &rc);
 
EndPaint (hwnd, &ps);
}
break;
case WM_LBUTTONDBLCLK:
if (dwStyle & LBS_NOTIFY)
NotifyParent (hwnd, pCtrl->id, LBN_DBLCLK);
break;
case WM_LBUTTONDOWN:
{
int oldSel, mouseX, mouseY, hit;
RECT rcInv;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
if (pData->itemCount == 0)
break;
 
mouseX = LOWORD (lParam);
mouseY = HIWORD (lParam);
hit = mouseY / pData->itemHeight;
hit += pData->itemTop;
if (hit >= pData->itemCount)
break;
 
GetClientRect (hwnd, &rcInv);
oldSel = lstSelectItem (dwStyle, pData, hit);
if ((dwStyle & LBS_NOTIFY) && (oldSel != hit))
NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
if (oldSel >= 0) {
if (oldSel >= pData->itemTop
&& (oldSel <= pData->itemTop + pData->itemVisibles)) {
lstGetItemsRect (pData, oldSel, oldSel, &rcInv);
InvalidateRect (hwnd, &rcInv, TRUE);
}
}
 
lstGetItemsRect (pData, hit, hit, &rcInv);
InvalidateRect (hwnd, &rcInv, TRUE);
 
if (pData->itemHilighted != hit)
{
hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
 
lstDrawFocusRect (hdc, pData, &rcInv);
ReleaseDC (hwnd,hdc);
}
pData->itemHilighted = hit;
 
if (dwStyle & LBS_CHECKBOX) {
if (mouseX > 0 && mouseX < LST_WIDTH_CHECKMARK) {
NotifyParent (hwnd, pCtrl->id, LBN_CLICKCHECKMARK);
if (dwStyle & LBS_AUTOCHECK) {
PLISTBOXITEM plbi;
 
plbi = lstGetItem (pData, hit);
 
switch (plbi->dwFlags & LBIF_CHECKMARKMASK) {
case LBIF_CHECKED:
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
break;
default:
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
plbi->dwFlags |= LBIF_CHECKED;
break;
}
lstInvalidateItem (hwnd, pData, hit, TRUE);
}
}
}
lstSetVScrollInfo (hwnd, pData, TRUE);
}
break;
case WM_LBUTTONUP:
break;
case WM_MOUSEMOVE:
break;
 
case WM_KEYDOWN:
{
int oldSel, newSel, newTop;
RECT rcInv;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
newTop = pData->itemTop;
newSel = pData->itemHilighted;
switch (LOWORD (wParam))
{
case VK_HOME: /* SCANCODE_HOME: */
newSel = 0;
newTop = 0;
break;
case VK_END: /* SCANCODE_END: */
newSel = pData->itemCount - 1;
if (pData->itemCount > pData->itemVisibles)
newTop = pData->itemCount - pData->itemVisibles;
else
newTop = 0;
break;
case VK_DOWN: /* SCANCODE_CURSORBLOCKDOWN: */
newSel ++;
if (newSel >= pData->itemCount)
return 0;
if (newSel > ITEM_BOTTOM (pData))
newTop ++;
break;
case VK_UP: /* SCANCODE_CURSORBLOCKUP: */
newSel --;
if (newSel < 0)
return 0;
if (newSel < pData->itemTop)
newTop --;
break;
case VK_NEXT: /* SCANCODE_PAGEDOWN: */
newSel += pData->itemVisibles;
if (newSel >= pData->itemCount)
newSel = pData->itemCount - 1;
if (pData->itemCount - newSel >= pData->itemVisibles)
newTop = newSel;
else
newTop = max (pData->itemCount-pData->itemVisibles, 0);
break;
 
case VK_PRIOR: /* SCANCODE_PAGEUP: */
newSel -= pData->itemVisibles;
if (newSel < 0)
newSel = 0;
newTop -= pData->itemVisibles;
if (newTop < 0)
newTop = 0;
break;
default:
return 0;
}
 
GetClientRect (hwnd, &rcInv);
if (pData->itemHilighted != newSel) {
if (pData->itemTop != newTop) {
pData->itemTop = newTop;
pData->itemHilighted = newSel;
if (!(dwStyle & LBS_MULTIPLESEL)) {
oldSel = lstSelectItem (dwStyle, pData, newSel);
if ((dwStyle & LBS_NOTIFY) && (oldSel != newSel))
NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
}
InvalidateRect (hwnd, NULL, TRUE);
}
else {
if (!(dwStyle & LBS_MULTIPLESEL)) {
oldSel = lstSelectItem (dwStyle, pData, newSel);
if ((dwStyle & LBS_NOTIFY) && (oldSel != newSel))
NotifyParent (hwnd, pCtrl->id, LBN_SELCHANGE);
if (oldSel >= 0) {
if (oldSel >= pData->itemTop
&& oldSel <= (ITEM_BOTTOM (pData) + 1)) {
lstGetItemsRect (pData, oldSel, oldSel, &rcInv);
InvalidateRect (hwnd, &rcInv, TRUE);
}
}
if (newSel < newTop) {
pData->itemHilighted = newSel;
break;
}
lstGetItemsRect (pData, pData->itemHilighted,
pData->itemHilighted, &rcInv);
 
hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
 
lstDrawFocusRect (hdc, pData, &rcInv);
ReleaseDC (hwnd,hdc);
pData->itemHilighted = newSel;
lstGetItemsRect (pData, newSel, newSel, &rcInv);
InvalidateRect (hwnd, &rcInv, TRUE);
}
else
{
hdc = GetDC(hwnd); /* hdc = GetClientDC (hwnd); */
 
lstDrawFocusRect (hdc, pData, &rcInv);
pData->itemHilighted = newSel;
GetClientRect (hwnd, &rcInv);
lstDrawFocusRect (hdc, pData, &rcInv);
ReleaseDC (hwnd,hdc);
}
}
lstSetVScrollInfo (hwnd, pData, TRUE);
}
}
break;
 
case WM_CHAR:
{
char head [2];
int index;
int newTop;
head [0] = (char) (wParam);
head [1] = '\0';
 
pData = (PLISTBOXDATA)pCtrl->userdata;
 
if (head[0] == ' ') {
if (dwStyle & LBS_MULTIPLESEL) {
RECT rcInv;
GetClientRect (hwnd, &rcInv);
lstSelectItem (dwStyle, pData, pData->itemHilighted);
lstGetItemsRect (pData,
pData->itemHilighted,
pData->itemHilighted,
&rcInv);
InvalidateRect (hwnd, &rcInv, TRUE);
}
else if (dwStyle & LBS_CHECKBOX) {
NotifyParent (hwnd, pCtrl->id, LBN_CLICKCHECKMARK);
if (dwStyle & LBS_AUTOCHECK) {
PLISTBOXITEM plbi;
 
plbi = lstGetItem (pData, pData->itemHilighted);
 
switch (plbi->dwFlags & LBIF_CHECKMARKMASK) {
case LBIF_CHECKED:
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
break;
default:
plbi->dwFlags &= ~LBIF_CHECKMARKMASK;
plbi->dwFlags |= LBIF_CHECKED;
break;
}
lstInvalidateItem (hwnd, pData,
pData->itemHilighted, TRUE);
}
}
break;
}
 
index = lstFindItem (pData, pData->itemHilighted + 1, head, FALSE);
if (index < 0) {
index = lstFindItem (pData, 0, head, FALSE);
}
 
if (index >= 0) {
if (pData->itemCount - index >= pData->itemVisibles)
newTop = index;
else
newTop = max (pData->itemCount - pData->itemVisibles, 0);
 
pData->itemTop = newTop;
pData->itemHilighted = index;
if (!(dwStyle & LBS_MULTIPLESEL))
lstSelectItem (dwStyle, pData, index);
InvalidateRect (hwnd, NULL, TRUE);
 
lstSetVScrollInfo (hwnd, pData, TRUE);
}
}
break;
case WM_VSCROLL:
{
int newTop;
int scrollHeight = 0;
 
pData = (PLISTBOXDATA)pCtrl->userdata;
newTop = pData->itemTop;
switch(wParam)
{
case SB_LINEDOWN:
 
#if 0 /* test itemVisibles */
printf("itemVisibles:%d\n",pData->itemVisibles);
printf("SB_LINEDOWN:(%d:%d)\n",
ITEM_BOTTOM (pData),(pData->itemCount - 1 ));
#endif
if (ITEM_BOTTOM (pData) < (pData->itemCount - 1 ))
{
newTop ++;
scrollHeight = -pData->itemHeight; /* for ScrollWindow() */
}
break;
case SB_LINEUP:
if (pData->itemTop > 0)
{
newTop --;
scrollHeight = pData->itemHeight;
}
break;
case SB_PAGEDOWN:
if ((pData->itemTop + (pData->itemVisibles << 1)) <=
pData->itemCount)
newTop += pData->itemVisibles;
else
newTop = pData->itemCount - pData->itemVisibles;
 
if (newTop < 0)
return 0;
 
scrollHeight = -(newTop - pData->itemTop)
*pData->itemHeight;
break;
 
case SB_PAGEUP:
if (pData->itemTop >= pData->itemVisibles)
newTop -= pData->itemVisibles;
else
newTop = 0;
 
scrollHeight = (pData->itemTop - newTop)*pData->itemHeight;
break;
 
case SB_THUMBTRACK:
newTop = (int)lParam;
scrollHeight = (pData->itemTop - newTop)*pData->itemHeight;
break;
}
if (scrollHeight)
{
pData->itemTop = newTop;
#if 0 /* !!: fix: no scroll */
ScrollWindow (hwnd, 0, scrollHeight, NULL, NULL);
#endif
SendMessage (hwnd, WM_PAINT, 0, 0);
 
lstSetVScrollInfo (hwnd, pData, TRUE);
 
return 0;
}
}
break;
 
case WM_HSCROLL:
pData = (PLISTBOXDATA)pCtrl->userdata;
switch (wParam)
{
case SB_LINERIGHT:
break;
case SB_LINELEFT:
break;
case SB_PAGELEFT:
break;
case SB_PAGERIGHT:
break;
}
break;
 
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
/draw3d.c
0,0 → 1,144
#include "windows.h"
#include "wintools.h"
/*
* WIN Draw Library
* Draw3dShadow - draws a shadow with bottom-left and top-right missing
* Draw3dBox - draws a complete shadow
* Draw3dInset - draw a 2 line 3d inset
* Draw3dOutset - draw a 2 line 3d outset
*/
 
/*
* Draw3dShadow
* NOINDENT_BLACK T=white, B=black
* NOINDENT_GRAY T=white, B=dkgray
* INDENT_BLACK T=black, B=white
* INDENT_GRAY T=dkgray, B=white
*
* TTTTTTTTTTTTTT
* T B
* T B
* BBBBBBBBBBBBBB
*/
void WINAPI
Draw3dShadow(HDC hDC,int x,int y,int w,int h,COLORREF crTop,COLORREF crBottom)
{
HPEN hPenTop, hPenBottom, holdPen;
 
hPenTop = CreatePen( PS_SOLID, 1, crTop);
hPenBottom = CreatePen( PS_SOLID, 1, crBottom);
holdPen = SelectObject( hDC, hPenTop);
MoveToEx( hDC, x, y+h-2, NULL);
LineTo( hDC, x, y); /* left side*/
LineTo( hDC, x+w-1, y); /* top side*/
 
SelectObject( hDC, hPenBottom);
MoveToEx( hDC, x+w-1, y+1, NULL);
LineTo( hDC, x+w-1, y+h-1); /* right side*/
LineTo( hDC, x, y+h-1); /* bottom side*/
 
SelectObject( hDC, holdPen);
DeleteObject( hPenTop);
DeleteObject( hPenBottom);
}
 
/*
* Draw3dBox
*
* TTTTTTTTTTTTTTB
* T B
* T B
* BBBBBBBBBBBBBBB
*/
void WINAPI
Draw3dBox(HDC hDC,int x,int y,int w,int h,COLORREF crTop,COLORREF crBottom)
{
HPEN hPenTop, hPenBottom, holdPen;
 
hPenTop = CreatePen( PS_SOLID, 1, crTop);
hPenBottom = CreatePen( PS_SOLID, 1, crBottom);
holdPen = SelectObject( hDC, hPenTop);
MoveToEx( hDC, x, y+h-2, NULL);
LineTo( hDC, x, y); /* left side*/
MoveToEx( hDC, x, y, NULL);
LineTo( hDC, x+w-1, y); /* top side*/
 
SelectObject( hDC, hPenBottom);
MoveToEx( hDC, x+w-1, y, NULL);
LineTo( hDC, x+w-1, y+h-1); /* right side*/
LineTo( hDC, x-1, y+h-1); /* bottom side*/
 
SelectObject( hDC, holdPen);
DeleteObject( hPenTop);
DeleteObject( hPenBottom);
}
 
/*
* Draw 2 line deep 3d inset
*/
void WINAPI
Draw3dInset(HDC hDC,int x,int y,int w,int h)
{
Draw3dBox(hDC, x, y, w, h,
GetSysColor(COLOR_BTNSHADOW), GetSysColor(COLOR_BTNHIGHLIGHT));
++x; ++y; w -= 2; h -= 2;
Draw3dBox(hDC, x, y, w, h,
GetSysColor(COLOR_WINDOWFRAME), GetSysColor(COLOR_3DLIGHT));
}
 
/*
* Draw 2 line deep 3d outset
*/
void WINAPI
Draw3dOutset(HDC hDC,int x,int y,int w,int h)
{
Draw3dBox(hDC, x, y, w, h,
GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_WINDOWFRAME));
++x; ++y; w -= 2; h -= 2;
Draw3dBox(hDC, x, y, w, h,
GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_BTNSHADOW));
}
 
/*
* Draw 1 line pushed down rectangle
*/
void WINAPI
Draw3dPushDown(HDC hDC, int x, int y, int w, int h)
{
Draw3dBox(hDC, x, y, w, h, GetSysColor(COLOR_BTNSHADOW),
GetSysColor(COLOR_BTNSHADOW));
}
 
/*
* Draw either 3d up or down depending on state
*/
void WINAPI
Draw3dUpDownState(HDC hDC, int x, int y, int w, int h, BOOL fDown)
{
if (fDown)
Draw3dPushDown(hDC, x, y, w, h);
else Draw3dOutset(hDC, x, y, w, h);
}
 
void WINAPI
Draw3dUpFrame(HDC hDC, int l, int t, int r, int b)
{
RECT rc;
HBRUSH hbr;
 
SetRect(&rc, l, t, r, b);
Draw3dBox(hDC, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_3DLIGHT),
GetSysColor(COLOR_WINDOWFRAME));
InflateRect(&rc, -1, -1);
Draw3dBox(hDC, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top,
GetSysColor(COLOR_BTNHIGHLIGHT),
GetSysColor(COLOR_BTNSHADOW));
InflateRect(&rc, -1, -1);
 
hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
FillRect(hDC, &rc, hbr);
DeleteObject(hbr);
}
/edit.c
0,0 → 1,1172
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Edit control for Microwindows win32 api.
*/
 
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library 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
*/
 
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
 
/* Note:
** Although there was a version by Zhao Jianghua, this version of
** EDIT control is written by Wei Yongming from scratch.
**
** Create date: 1999/8/26
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/05/30 gv port to microwin ported
** Greg Haerr 2000/06/16 Utah 3d look, bug fixes Finished
** Kevin Tseng 2000/06/22 gv port to mw-nanox ported
**
** TODO:
** * Selection.
** * Undo.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "windows.h" /* windef.h, winuser.h */
#include "wintools.h"
#include "device.h" /* GdGetTextSize */
 
#define USE_BIG5
 
#if 0
#define DEFAULT_FONT DEFAULT_GUI_FONT
#endif
#define DEFAULT_FONT SYSTEM_FIXED_FONT
 
#define WIDTH_EDIT_BORDER 2
#define MARGIN_EDIT_LEFT 1
#define MARGIN_EDIT_TOP 1
#define MARGIN_EDIT_RIGHT 2
#define MARGIN_EDIT_BOTTOM 1
 
#define LEN_SLEDIT_BUFFER 3000
#define LEN_SLEDIT_UNDOBUFFER 1024
 
#define EST_FOCUSED 0x00000001L
#define EST_MODIFY 0x00000002L
#define EST_READONLY 0x00000004L
#define EST_REPLACE 0x00000008L
 
#define EDIT_OP_NONE 0x00
#define EDIT_OP_DELETE 0x01
#define EDIT_OP_INSERT 0x02
#define EDIT_OP_REPLACE 0x03
 
typedef struct tagSLEDITDATA {
HFONT hFont; /* hFont used */
int bufferLen; /* length of buffer */
 
int dataEnd; /* data end position */
int editPos; /* current edit position */
int caretOff; /* caret offset in box */
int startPos; /* start display position */
int selStart; /* selection start position */
int selEnd; /* selection end position */
int passwdChar; /* password character */
int leftMargin; /* left margin */
int topMargin; /* top margin */
int rightMargin; /* right margin */
int bottomMargin; /* bottom margin */
int hardLimit; /* hard limit */
 
int lastOp; /* last operation */
int lastPos; /* last operation position */
int affectedLen; /* affected len of last operation */
int undoBufferLen; /* undo buffer len */
char undoBuffer [LEN_SLEDIT_UNDOBUFFER]; /* Undo buffer; */
char buffer [LEN_SLEDIT_BUFFER]; /* buffer */
} SLEDITDATA, *PSLEDITDATA;
 
static LRESULT CALLBACK
SLEditCtrlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
static int GetSysCharHeight (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
 
return xh;
#else
return 12;
#endif
}
 
static int GetSysCharWidth (HWND hwnd)
{
#ifndef USE_BIG5
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(DEFAULT_FONT));
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
ReleaseDC(hwnd,hdc);
 
return xw;
#else
return 6;
#endif
}
 
static int GetSysCCharWidth (HWND hwnd)
{
return (2*GetSysCharWidth(hwnd));
}
 
int WINAPI MwRegisterEditControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)SLEditCtrlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "EDIT";
 
return RegisterClass(&wc);
}
 
static int edtGetOutWidth (const HWND pCtrl)
{
return pCtrl->clirect.right - pCtrl->clirect.left
- ((PSLEDITDATA)(pCtrl->userdata2))->leftMargin
- ((PSLEDITDATA)(pCtrl->userdata2))->rightMargin;
}
 
static int edtGetStartDispPosAtEnd (const HWND pCtrl, PSLEDITDATA pSLEditData)
{
int nOutWidth = edtGetOutWidth (pCtrl);
int endPos = pSLEditData->dataEnd;
int newStartPos = pSLEditData->startPos;
const char* buffer = pSLEditData->buffer;
 
while (TRUE) {
if ((endPos - newStartPos) * GetSysCharWidth (pCtrl) < nOutWidth)
break;
/* FIXME: #ifdef GB2312?*/
if ((BYTE)buffer [newStartPos] > 0xA0) /* 1st:gb:a1-f7,big5:a1-f9 */
{
newStartPos ++;
if (newStartPos < pSLEditData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [newStartPos] > 0xA0)
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [newStartPos] >= 0x40 && (BYTE)buffer[newStartPos] <= 0x7e) ||
((BYTE)buffer [newStartPos] >= 0xa1 && (BYTE)buffer[newStartPos] <= 0xfe))
#endif
newStartPos ++;
}
}
else
newStartPos ++;
}
 
return newStartPos;
}
 
static int edtGetDispLen (const HWND pCtrl)
{
int i, n = 0;
int nOutWidth = edtGetOutWidth (pCtrl);
int nTextWidth = 0;
PSLEDITDATA pSLEditData = (PSLEDITDATA)(pCtrl->userdata2);
const char* buffer = pSLEditData->buffer;
 
for (i = pSLEditData->startPos; i < pSLEditData->dataEnd; i++) {
/* FIXME #ifdef GB2312?*/
if ((BYTE)buffer [i] > 0xA0) /* st:gb:a1-f7,big5:a1-f9 */
{
i++;
if (i < pSLEditData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (pCtrl);
n += 2;
}
else
i--;
}
else
{
nTextWidth += GetSysCharWidth (pCtrl);
n++;
}
}
else
{
nTextWidth += GetSysCharWidth (pCtrl);
n++;
}
 
if (nTextWidth > nOutWidth)
break;
}
 
return n;
}
 
static int edtGetOffset (HWND hwnd,const SLEDITDATA* pSLEditData, int x)
{
int i;
int newOff = 0;
int nTextWidth = 0;
const char* buffer = pSLEditData->buffer;
 
x -= pSLEditData->leftMargin;
for (i = pSLEditData->startPos; i < pSLEditData->dataEnd; i++) {
if ((nTextWidth + (GetSysCharWidth(hwnd) >> 1)) >= x)
break;
 
/* FIXME #ifdef GB2312?*/
if ((BYTE)buffer [i] > 0xA0) /* 1st:gb:a1-f7,big5:a1-f9 */
{
i++;
if (i < pSLEditData->dataEnd)
{
#ifndef USE_BIG5
if ((BYTE)buffer [i] > 0xA0) /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#else /* 2nd:gb:a1-fe,big5:40-7e,a1-fe */
if ( ((BYTE)buffer [i] >= 0x40 && (BYTE)buffer[i] <= 0x7e) ||
((BYTE)buffer [i] >= 0xa1 && (BYTE)buffer[i] <= 0xfe))
#endif
{
nTextWidth += GetSysCCharWidth (hwnd);
newOff += 2;
}
else
i --;
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
}
else
{
nTextWidth += GetSysCharWidth (hwnd);
newOff ++;
}
 
}
 
return newOff;
}
 
static BOOL edtIsACCharBeforePosition (const char* string, int pos)
{
if (pos < 2)
return FALSE;
 
/* 1st:gb:a1-f7,big5:a1-f9 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#ifndef USE_BIG5
/* FIXME #ifdef GB2312?*/
if ((BYTE)string [pos - 2] > 0xA0 && (BYTE)string [pos - 1] > 0xA0)
return TRUE;
#else
if ((BYTE)string [pos - 2] > 0xA0)
{
if ( ((BYTE)string [pos - 1] >= 0x40 && (BYTE)string[pos - 1] <= 0x7e) ||
((BYTE)string [pos - 1] >= 0xa1 && (BYTE)string[pos - 1] <= 0xfe))
return TRUE;
}
#endif
 
return FALSE;
}
 
static BOOL edtIsACCharAtPosition (const char* string, int len, int pos)
{
if (pos > (len - 2))
return FALSE;
 
/* 1st:gb:a1-f7,big5:a1-f9 2nd:gb:a1-fe,big5:40-7e,a1-fe */
#ifndef USE_BIG5
if ((BYTE)string [pos] > 0xA0 && (BYTE)string [pos + 1] > 0xA0)
return TRUE;
#else
if ((BYTE)string [pos] > 0xA0)
{
if ( ((BYTE)string [pos + 1] >= 0x40 && (BYTE)string [pos + 1] <= 0x7e) ||
((BYTE)string [pos + 1] >= 0xa1 && (BYTE)string [pos + 1] <= 0xfe)) {
/*fprintf(stderr,"true\n");
fflush(stderr);*/
return TRUE;
}
}
#endif
 
return FALSE;
}
 
LRESULT CALLBACK
SLEditCtrlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND pCtrl;
DWORD dwStyle;
HDC hdc;
PSLEDITDATA pSLEditData;
RECT rc;
 
pCtrl = hWnd;
dwStyle = pCtrl->style;
 
switch (message)
{
case WM_CREATE:
if (!(pSLEditData = malloc (sizeof (SLEDITDATA)))) {
fprintf (stderr, "EDIT: malloc error!\n");
return -1;
}
 
pSLEditData->hFont = GetStockObject(DEFAULT_FONT);
 
pSLEditData->bufferLen = LEN_SLEDIT_BUFFER;
pSLEditData->editPos = 0;
pSLEditData->caretOff = 0;
pSLEditData->startPos = 0;
pSLEditData->selStart = 0;
pSLEditData->selEnd = 0;
pSLEditData->passwdChar = '*';
pSLEditData->leftMargin = MARGIN_EDIT_LEFT;
pSLEditData->topMargin = MARGIN_EDIT_TOP;
pSLEditData->rightMargin = MARGIN_EDIT_RIGHT;
pSLEditData->bottomMargin = MARGIN_EDIT_BOTTOM;
 
pSLEditData->hardLimit = -1;
/* undo information */
pSLEditData->lastOp = EDIT_OP_NONE;
pSLEditData->lastPos = 0;
pSLEditData->affectedLen = 0;
pSLEditData->undoBufferLen = LEN_SLEDIT_UNDOBUFFER;
pSLEditData->undoBuffer [0] = '\0';
 
pSLEditData->dataEnd = strlen (pCtrl->szTitle);
memcpy (pSLEditData->buffer, pCtrl->szTitle,
min (LEN_SLEDIT_BUFFER, pSLEditData->dataEnd));
 
pCtrl->userdata2 = (DWORD) pSLEditData;
 
pCtrl->userdata = 0;
break;
 
case WM_DESTROY:
DestroyCaret ();
 
free ((void*)pCtrl->userdata2);
break;
#if 0
case WM_CHANGESIZE:
{
pCtrl->cl = pCtrl->left + WIDTH_EDIT_BORDER;
pCtrl->ct = pCtrl->top + WIDTH_EDIT_BORDER;
pCtrl->cr = pCtrl->right - WIDTH_EDIT_BORDER;
pCtrl->cb = pCtrl->bottom - WIDTH_EDIT_BORDER;
}
break;
#endif
 
#if 1 /* jmt: for edit: chinese support */
case WM_SETFONT:
{
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
pSLEditData->hFont = (HFONT)wParam;
 
ShowWindow(hWnd, SW_HIDE);
ShowWindow(hWnd, SW_SHOWNA);
 
if(LOWORD(lParam))
InvalidateRect(hWnd,NULL,TRUE);
}
return (LRESULT)0;
case WM_GETFONT:
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
return (LRESULT)pSLEditData->hFont;
#endif
 
#if 0
case WM_SETCURSOR:
if (dwStyle & WS_DISABLED)
{
SetCursor (GetSystemCursor (IDC_ARROW));
return 0;
}
break;
#endif
case WM_KILLFOCUS:
pCtrl->userdata &= ~EST_FOCUSED;
 
HideCaret (hWnd);
DestroyCaret ();
 
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_KILLFOCUS), (LPARAM)hWnd);
break;
case WM_SETFOCUS:
if (pCtrl->userdata & EST_FOCUSED)
return 0;
pCtrl->userdata |= EST_FOCUSED;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
/* only implemented for ES_LEFT align format. */
 
CreateCaret (hWnd, NULL, 1 /*+ GetSysCharWidth(hWnd)*/,
hWnd->clirect.bottom-hWnd->clirect.top-2);
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
ShowCaret (hWnd);
 
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_SETFOCUS), (LPARAM) hWnd);
break;
case WM_ENABLE:
if ( (!(dwStyle & WS_DISABLED) && !wParam)
|| ((dwStyle & WS_DISABLED) && wParam) ) {
if (wParam)
pCtrl->style &= ~WS_DISABLED;
else
pCtrl->style |= WS_DISABLED;
 
InvalidateRect (hWnd, NULL, FALSE);
}
break;
 
case WM_NCCALCSIZE:
{
LPNCCALCSIZE_PARAMS lpnc;
 
/* calculate client rect from passed window rect in rgrc[0]*/
lpnc = (LPNCCALCSIZE_PARAMS)lParam;
if(GetWindowLong(hWnd, GWL_STYLE) & WS_BORDER)
InflateRect(&lpnc->rgrc[0], -2, -2);
}
break;
 
case WM_NCPAINT:
hdc = wParam? (HDC)wParam: GetWindowDC (hWnd);
GetWindowRect(hWnd, &rc);
 
if (dwStyle & WS_BORDER)
Draw3dInset(hdc, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top);
 
if (!wParam)
ReleaseDC (hWnd, hdc);
break;
 
case WM_PAINT:
{
int dispLen;
char* dispBuffer;
RECT rect,rc;
PAINTSTRUCT ps;
 
HGDIOBJ oldfont;
oldfont=NULL;
 
hdc = BeginPaint (hWnd,&ps);
GetClientRect (hWnd, &rect);
if (dwStyle & WS_DISABLED)
{
#if 0
SetBrushColor (hdc, LTGRAY/*COLOR_lightgray*/);
FillBox (hdc, 0, 0, rect.right, rect.bottom);
#else
rc.left=0; rc.top=0; rc.bottom=rect.bottom; rc.right=rect.right;
FillRect(hdc,&rc,GetStockObject(LTGRAY_BRUSH));
#endif
SetBkColor (hdc, LTGRAY/*COLOR_lightgray*/);
}
else
{
#if 0
SetBrushColor (hdc, WHITE/*COLOR_lightwhite*/);
FillBox (hdc, 0, 0, rect.right, rect.bottom);
#else
rc.left=0; rc.top=0; rc.bottom=rect.bottom; rc.right=rect.right;
FillRect(hdc,&rc,GetStockObject(WHITE_BRUSH));
#endif
SetBkColor (hdc, WHITE/*COLOR_lightwhite*/);
}
 
SetTextColor (hdc, BLACK/*COLOR_black*/);
dispLen = edtGetDispLen (pCtrl);
if (dispLen == 0)
{
EndPaint (hWnd, &ps);
break;
}
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
 
#ifdef _DEBUG
if (pSLEditData->startPos > pSLEditData->dataEnd)
fprintf (stderr, "ASSERT failure: %s.\n", "Edit Paint");
#endif
dispBuffer = ALLOCA(dispLen + 1);
 
if (dwStyle & ES_PASSWORD)
memset (dispBuffer, '*', dispLen);
else
memcpy (dispBuffer,
pSLEditData->buffer + pSLEditData->startPos,
dispLen);
 
dispBuffer [dispLen] = '\0';
 
/* only implemented ES_LEFT align format for single line edit. */
rect.left += pSLEditData->leftMargin;
rect.top += pSLEditData->topMargin;
rect.right -= pSLEditData->rightMargin;
rect.bottom -= pSLEditData->bottomMargin;
 
#if 0 /* FIXME no ClipRectIntersect() */
#if 0
ClipRectIntersect (hdc, &rect);
#else
GdSetClipRects(hdc->psd,1,&rect); /*??==ClipRectIntersect??*/
#endif
#endif
 
#ifdef USE_BIG5
oldfont=SelectObject(hdc,CreateFont(12,
0,0,0,0,0,0,0,0,0,0,0,
FF_DONTCARE|DEFAULT_PITCH,
"HZXFONT"));
#else
SelectObject(hdc, pSLEditData->hFont);
#endif
TextOut (hdc, pSLEditData->leftMargin, pSLEditData->topMargin,
dispBuffer,-1);
 
#ifdef USE_BIG5
DeleteObject(SelectObject(hdc,oldfont));
#endif
EndPaint (hWnd, &ps);
 
FREEA(dispBuffer);
}
break;
#if 1 /* jmt+ */
case WM_KEYDOWN:
{
BOOL bChange = FALSE;
int i;
RECT InvRect;
int deleted;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
switch ((int)(wParam)) /* (LOWORD (wParam)) */
{
#if 0
case SCANCODE_ENTER:
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_ENTER), (LPARAM) hWnd);
return 0;
 
case SCANCODE_HOME:
if (pSLEditData->editPos == 0)
return 0;
 
pSLEditData->editPos = 0;
pSLEditData->caretOff = 0;
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
if (pSLEditData->startPos != 0)
InvalidateRect (hWnd, NULL, FALSE);
pSLEditData->startPos = 0;
return 0;
case SCANCODE_END:
{
int newStartPos;
if (pSLEditData->editPos == pSLEditData->dataEnd)
return 0;
 
newStartPos = edtGetStartDispPosAtEnd (pCtrl, pSLEditData);
pSLEditData->editPos = pSLEditData->dataEnd;
pSLEditData->caretOff = pSLEditData->editPos - newStartPos;
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
if (pSLEditData->startPos != newStartPos)
InvalidateRect (hWnd, NULL, FALSE);
pSLEditData->startPos = newStartPos;
}
return 0;
#endif
 
case VK_LEFT: /* SCANCODE_CURSORBLOCKLEFT: */
{
BOOL bScroll = FALSE;
int scrollStep;
if (pSLEditData->editPos == 0)
return 0;
 
if (edtIsACCharBeforePosition (pSLEditData->buffer,
pSLEditData->editPos))
{
scrollStep = 2;
pSLEditData->editPos -= 2;
}
else {
scrollStep = 1;
pSLEditData->editPos --;
}
 
pSLEditData->caretOff -= scrollStep;
if (pSLEditData->caretOff == 0
&& pSLEditData->editPos != 0)
{
bScroll = TRUE;
 
if (edtIsACCharBeforePosition (pSLEditData->buffer,
pSLEditData->editPos))
{
pSLEditData->startPos -= 2;
pSLEditData->caretOff = 2;
}
else
{
pSLEditData->startPos --;
pSLEditData->caretOff = 1;
}
}
else if (pSLEditData->caretOff < 0)
{
pSLEditData->startPos = 0;
pSLEditData->caretOff = 0;
}
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
if (bScroll)
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
case VK_RIGHT: /* SCANCODE_CURSORBLOCKRIGHT: */
{
BOOL bScroll = FALSE;
int scrollStep, moveStep;
 
if (pSLEditData->editPos == pSLEditData->dataEnd)
return 0;
 
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->startPos))
{
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->editPos))
{
scrollStep = 2;
moveStep = 2;
pSLEditData->editPos += 2;
}
else
{
scrollStep = 2;
moveStep = 1;
pSLEditData->editPos ++;
}
}
else
{
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->editPos))
{
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->startPos + 1))
scrollStep = 3;
else
scrollStep = 2;
 
moveStep = 2;
pSLEditData->editPos += 2;
}
else
{
scrollStep = 1;
moveStep = 1;
pSLEditData->editPos ++;
}
}
 
pSLEditData->caretOff += moveStep;
if (pSLEditData->caretOff * GetSysCharWidth (hWnd)
> edtGetOutWidth (pCtrl))
{
bScroll = TRUE;
pSLEditData->startPos += scrollStep;
 
pSLEditData->caretOff =
pSLEditData->editPos - pSLEditData->startPos;
}
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
if (bScroll)
InvalidateRect (hWnd, NULL, FALSE);
}
return 0;
#if 0
case SCANCODE_INSERT:
pCtrl->userdata ^= EST_REPLACE;
break;
#endif
case VK_DELETE: /* SCANCODE_REMOVE: */
if ((pCtrl->userdata & EST_READONLY)
|| (pSLEditData->editPos == pSLEditData->dataEnd)){
#if 0 /* fix: no ping() */
Ping ();
#endif
return 0;
}
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd, pSLEditData->editPos))
deleted = 2;
else
deleted = 1;
for (i = pSLEditData->editPos;
i < pSLEditData->dataEnd - deleted; i++)
pSLEditData->buffer [i]
= pSLEditData->buffer [i + deleted];
 
pSLEditData->dataEnd -= deleted;
bChange = TRUE;
InvRect.left = pSLEditData->leftMargin
+ pSLEditData->caretOff * GetSysCharWidth (hWnd);
InvRect.top = pSLEditData->topMargin;
InvRect.right = pCtrl->clirect.right - pCtrl->clirect.left;
InvRect.bottom = pCtrl->clirect.bottom - pCtrl->clirect.top;
 
InvalidateRect (hWnd, &InvRect, FALSE);
break;
 
case VK_BACK: /* SCANCODE_BACKSPACE: */
if ((pCtrl->userdata & EST_READONLY)
|| (pSLEditData->editPos == 0)) {
#if 0 /* fix: no ping */
Ping ();
#endif
return 0;
}
 
if (edtIsACCharBeforePosition (pSLEditData->buffer,
pSLEditData->editPos))
deleted = 2;
else
deleted = 1;
for (i = pSLEditData->editPos;
i < pSLEditData->dataEnd;
i++)
pSLEditData->buffer [i - deleted]
= pSLEditData->buffer [i];
 
pSLEditData->dataEnd -= deleted;
pSLEditData->editPos -= deleted;
bChange = TRUE;
pSLEditData->caretOff -= deleted;
if (pSLEditData->caretOff == 0
&& pSLEditData->editPos != 0) {
if (edtIsACCharBeforePosition (pSLEditData->buffer,
pSLEditData->editPos)) {
pSLEditData->startPos -= 2;
pSLEditData->caretOff = 2;
}
else {
pSLEditData->startPos --;
pSLEditData->caretOff = 1;
}
InvRect.left = pSLEditData->leftMargin;
InvRect.top = pSLEditData->topMargin;
InvRect.right = pCtrl->clirect.right -
pCtrl->clirect.left;
InvRect.bottom = pCtrl->clirect.bottom -
pCtrl->clirect.top;
}
else {
InvRect.left = pSLEditData->leftMargin
+ pSLEditData->caretOff * GetSysCharWidth (hWnd);
InvRect.top = pSLEditData->topMargin;
InvRect.right = pCtrl->clirect.right -
pCtrl->clirect.left;
InvRect.bottom = pCtrl->clirect.bottom -
pCtrl->clirect.top;
}
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
InvalidateRect (hWnd, &InvRect, FALSE);
break;
 
default:
break;
}
if (bChange)
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_CHANGE), (LPARAM) hWnd);
}
break;
#endif
case WM_CHAR:
{
char charBuffer [2];
int i, chars, scrollStep, inserting;
RECT InvRect;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
 
if (dwStyle & ES_READONLY) {
 
#if 0 /* fix: no ping() */
Ping();
#endif
return 0;
}
if (HIBYTE (wParam)) {
charBuffer [0] = LOBYTE (wParam);
charBuffer [1] = HIBYTE (wParam);
chars = 2;
}
else {
charBuffer [0] = LOBYTE (wParam);
chars = 1;
}
if (chars == 1) {
switch (charBuffer [0])
{
case 0x00: /* NULL */
case 0x07: /* BEL */
case 0x08: /* BS */
case 0x09: /* HT */
case 0x0A: /* LF */
case 0x0B: /* VT */
case 0x0C: /* FF */
case 0x0D: /* CR */
case 0x1B: /* Escape */
return 0;
}
}
 
if (pCtrl->userdata & EST_REPLACE) {
if (pSLEditData->dataEnd == pSLEditData->editPos)
inserting = chars;
else if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->editPos)) {
if (chars == 2)
inserting = 0;
else
inserting = -1;
}
else {
if (chars == 2)
inserting = 1;
else
inserting = 0;
}
}
else
inserting = chars;
 
/* check space */
if (pSLEditData->dataEnd + inserting > pSLEditData->bufferLen) {
 
#if 0 /* fix: no ping() */
Ping ();
#endif
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_MAXTEXT), (LPARAM) hWnd);
return 0;
}
else if ((pSLEditData->hardLimit >= 0)
&& ((pSLEditData->dataEnd + inserting)
> pSLEditData->hardLimit)) {
#if 0 /* fix: no ping() */
Ping ();
#endif
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_MAXTEXT), (LPARAM) hWnd);
return 0;
}
 
if (inserting == -1) {
for (i = pSLEditData->editPos; i < pSLEditData->dataEnd-1; i++)
pSLEditData->buffer [i] = pSLEditData->buffer [i + 1];
}
else if (inserting > 0) {
for (i = pSLEditData->dataEnd + inserting - 1;
i > pSLEditData->editPos + inserting - 1;
i--)
pSLEditData->buffer [i]
= pSLEditData->buffer [i - inserting];
}
 
for (i = 0; i < chars; i++)
pSLEditData->buffer [pSLEditData->editPos + i]
= charBuffer [i];
pSLEditData->editPos += chars;
pSLEditData->caretOff += chars;
pSLEditData->dataEnd += inserting;
 
if (pSLEditData->caretOff * GetSysCharWidth (hWnd)
> edtGetOutWidth (pCtrl))
{
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->startPos))
scrollStep = 2;
else {
if (chars == 2) {
if (edtIsACCharAtPosition (pSLEditData->buffer,
pSLEditData->dataEnd,
pSLEditData->startPos + 1))
scrollStep = 3;
else
scrollStep = 2;
}
else
scrollStep = 1;
}
pSLEditData->startPos += scrollStep;
 
pSLEditData->caretOff =
pSLEditData->editPos - pSLEditData->startPos;
 
InvRect.left = pSLEditData->leftMargin;
InvRect.top = pSLEditData->topMargin;
InvRect.right = pCtrl->clirect.right - pCtrl->clirect.left;
InvRect.bottom = pCtrl->clirect.bottom - pCtrl->clirect.top;
}
else {
InvRect.left = pSLEditData->leftMargin
+ (pSLEditData->caretOff - chars)
* GetSysCharWidth (hWnd);
InvRect.top = pSLEditData->topMargin;
InvRect.right = pCtrl->clirect.right - pCtrl->clirect.left;
InvRect.bottom = pCtrl->clirect.bottom - pCtrl->clirect.top;
}
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
InvalidateRect (hWnd, &InvRect, FALSE);
 
SendMessage (GetParent (hWnd), WM_COMMAND,
(WPARAM) MAKELONG (pCtrl->id, EN_CHANGE), (LPARAM) hWnd);
}
break;
 
case WM_GETTEXTLENGTH:
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
return pSLEditData->dataEnd;
case WM_GETTEXT:
{
char* buffer = (char*)lParam;
int len;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
 
len = min ((int)wParam, pSLEditData->dataEnd);
 
memcpy (buffer, pSLEditData->buffer, len);
buffer [len] = '\0';
 
return len;
}
break;
 
case WM_SETTEXT:
{
int len;
 
if (dwStyle & ES_READONLY)
return 0;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
 
len = strlen ((char*)lParam);
len = min (len, pSLEditData->bufferLen);
if (pSLEditData->hardLimit >= 0)
len = min (len, pSLEditData->hardLimit);
pSLEditData->dataEnd = len;
memcpy (pSLEditData->buffer, (char*)lParam, len);
 
pSLEditData->editPos = 0;
pSLEditData->caretOff = 0;
pSLEditData->startPos = 0;
InvalidateRect (hWnd, NULL, FALSE);
}
break;
 
case WM_LBUTTONDBLCLK:
break;
case WM_LBUTTONDOWN:
{
int newOff;
 
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
newOff = edtGetOffset (hWnd,pSLEditData, LOWORD (lParam));
if (newOff != pSLEditData->caretOff)
{
pSLEditData->editPos += newOff - pSLEditData->caretOff;
pSLEditData->caretOff = newOff;
 
SetCaretPos (pSLEditData->caretOff * GetSysCharWidth (hWnd)
+ pSLEditData->leftMargin, pSLEditData->topMargin);
}
}
break;
 
case WM_LBUTTONUP:
break;
case WM_MOUSEMOVE:
break;
 
case WM_GETDLGCODE:
return DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS;
 
case EM_SETREADONLY:
if (wParam)
pCtrl->style/*dwStyle*/ |= ES_READONLY;
else
pCtrl->style/*dwStyle*/ &= ~ES_READONLY;
return 0;
case EM_SETPASSWORDCHAR:
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
 
if (pSLEditData->passwdChar != (int)wParam) {
if (dwStyle & ES_PASSWORD) {
pSLEditData->passwdChar = (int)wParam;
InvalidateRect (hWnd, NULL, TRUE);
}
}
return 0;
case EM_GETPASSWORDCHAR:
{
int* passwdchar;
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
passwdchar = (int*) lParam;
 
*passwdchar = pSLEditData->passwdChar;
}
return 0;
case EM_LIMITTEXT:
{
int newLimit = (int)wParam;
if (newLimit >= 0) {
pSLEditData = (PSLEDITDATA) (pCtrl->userdata2);
if (pSLEditData->bufferLen < newLimit)
pSLEditData->hardLimit = -1;
else
pSLEditData->hardLimit = newLimit;
}
}
return 0;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
break;
}
return 0;
}
/static.c
0,0 → 1,369
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Static control for Microwindows win32 api.
*/
 
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library 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
*/
 
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
 
/* Create date: 1999/5/22
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** WEI Yongming 1999/8/21 Tsinghua Rearrangment Finished
** WEI Yongming 1999/10/27 Tsinghua SETTEXT bug Finished
** WEI Yongming 1999/10/27 Tsinghua SETTEXT bug Finished
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/06/26 gv port to microwin ported
** Greg Haerr 2000/07/05 Utah bug fixes Finished
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "windows.h" /* windef.h, winuser.h */
#include "wintools.h"
#include "device.h" /* GdGetTextSize */
 
/* jmt: should be SYSTEM_FIXED_FONT because of minigui's GetSysCharXXX() */
#define FONT_NAME SYSTEM_FIXED_FONT /* was DEFAULT_GUI_FONT*/
 
static LRESULT CALLBACK
StaticControlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
int WINAPI MwRegisterStaticControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)StaticControlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "STATIC";
 
return RegisterClass(&wc);
}
 
#if 1
#define RECTW(rc) (rc.right-rc.left)
#define RECTH(rc) (rc.bottom-rc.top)
 
static DWORD GetWindowStyle (HWND hwnd)
{
return hwnd->style;
}
 
static COLORREF GetWindowBkColor (HWND hwnd)
{
MWBRUSHOBJ *hbr;
hbr=(MWBRUSHOBJ *)hwnd->pClass->hbrBackground;
return hbr->color;
}
 
static char *GetWindowCaption (HWND hwnd)
{
return hwnd->szTitle;
}
 
static void SetWindowCaption (HWND hwnd,char *caption)
{
if (strlen(caption)<=63) /* mw: szTitle[64] */
strcpy(hwnd->szTitle,caption);
else
{
strncpy(hwnd->szTitle,caption,63);
hwnd->szTitle[63]='\0';
}
}
 
static int GetSysCharHeight (HWND hwnd)
{
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
 
SelectObject(hdc, GetStockObject(FONT_NAME));
 
#if MWCLIENT /* nanox client */
GrGetGCTextSize(hdc->gc, "X", 1, MWTF_ASCII, &xw, &xh, &xb);
#else
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
#endif
ReleaseDC(hwnd,hdc);
 
return xh;
}
 
static int GetSysCharWidth (HWND hwnd)
{
HDC hdc;
int xw, xh, xb;
 
hdc = GetDC(hwnd);
 
SelectObject(hdc, GetStockObject(FONT_NAME));
 
#if MWCLIENT /* nanox client */
GrGetGCTextSize(hdc->gc, "X", 1, MWTF_ASCII, &xw, &xh, &xb);
#else
GdGetTextSize(hdc->font->pfont,"X",1, &xw,&xh,&xb,MWTF_ASCII);
#endif
ReleaseDC(hwnd,hdc);
 
return xw;
}
#endif
 
static LRESULT CALLBACK
StaticControlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
HDC hdc;
char* spCaption;
HWND pCtrl;
UINT uFormat;
DWORD dwStyle;
pCtrl = hwnd;
switch (message) {
case WM_CREATE:
return 0;
case WM_DESTROY:
break;
 
case STM_GETIMAGE:
return (int)(pCtrl->userdata);
case STM_SETIMAGE:
{
int pOldValue;
pOldValue = (int)(pCtrl->userdata);
pCtrl->userdata = (DWORD)wParam;
InvalidateRect (hwnd, NULL, FALSE);
return pOldValue;
}
case WM_GETDLGCODE:
return DLGC_STATIC;
 
 
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
HBRUSH hbr;
 
hdc = BeginPaint (hwnd,&ps);
 
GetClientRect (hwnd, &rcClient);
 
FastFillRect(hdc, &rcClient, GetSysColor(COLOR_BTNFACE));
 
dwStyle = GetWindowStyle (hwnd);
 
switch (dwStyle & SS_TYPEMASK)
{
case SS_GRAYRECT:
#if 0
SetBrushColor (hdc, LTGRAY);
FillBox(hdc, 0, 0, RECTW(rcClient), RECTH(rcClient));
#else
rc.left=0; rc.top=0; rc.bottom=RECTH(rcClient); rc.right=RECTW(rcClient);
FillRect(hdc,&rc,GetStockObject(LTGRAY_BRUSH));
#endif
break;
case SS_GRAYFRAME:
#if 0
Draw3DDownFrame (hdc,
0, 0, rcClient.right, rcClient.bottom,
DKGRAY);
#else
Draw3dInset(hdc, 0, 0,
rcClient.right, rcClient.bottom);
#endif
break;
case SS_BITMAP:
#if 0 /* jmt: fix: no FillBoxWithBitmap() */
FillBoxWithBitmap(hdc, 0, 0, 0, 0,
(PBITMAP)(pCtrl->userdata));
#endif
break;
case SS_ICON:
#if 0 /* jmt: fix: no DrawIcon */
hIcon = (HICON)(pCtrl->userdata);
DrawIcon (hdc, 0, 0, 0, 0, hIcon);
#endif
break;
case SS_SIMPLE:
#if 0
SetBrushColor (hdc, GetWindowBkColor (hwnd));
FillBox (hdc, 0, 0, rcClient.right, rcClient.bottom);
#else
hbr=CreateSolidBrush(GetWindowBkColor(hwnd));
rc.left=0; rc.top=0; rc.bottom=rcClient.bottom; rc.right=rcClient.right;
FillRect(hdc,&rc,hbr);
DeleteObject(hbr);
#endif
if (dwStyle & WS_DISABLED)
SetTextColor (hdc, DKGRAY);
else
SetTextColor (hdc, BLACK);
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
spCaption = GetWindowCaption (hwnd);
if (spCaption)
{
SelectObject(hdc, GetStockObject(FONT_NAME));
TextOut (hdc, 0, 0, spCaption, -1);
}
break;
 
case SS_LEFT:
case SS_CENTER:
case SS_RIGHT:
case SS_LEFTNOWORDWRAP:
uFormat = DT_TOP;
if ( (dwStyle & SS_TYPEMASK) == SS_LEFT)
uFormat |= DT_LEFT | DT_WORDBREAK;
else if ( (dwStyle & SS_TYPEMASK) == SS_CENTER)
uFormat |= DT_CENTER | DT_WORDBREAK;
else if ( (dwStyle & SS_TYPEMASK) == SS_RIGHT)
uFormat |= DT_RIGHT | DT_WORDBREAK;
else if ( (dwStyle & SS_TYPEMASK) == SS_LEFTNOWORDWRAP)
uFormat |= DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS;
if (dwStyle & WS_DISABLED)
SetTextColor (hdc, DKGRAY);
else
SetTextColor (hdc, BLACK);
 
#if 0
SetBkColor (hdc, GetWindowBkColor (hwnd));
#endif
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
spCaption = GetWindowCaption (hwnd);
if (dwStyle & SS_NOPREFIX)
uFormat |= DT_NOPREFIX;
if (spCaption)
{
SelectObject(hdc, GetStockObject(FONT_NAME));
DrawText (hdc, spCaption, -1, &rcClient, uFormat);
}
break;
 
case SS_GROUPBOX:
#if 0
Draw3DBorder (hdc, rcClient.left,
rcClient.top + (GetSysCharHeight(hwnd) >> 1),
rcClient.right, rcClient.bottom);
#else
Draw3dInset(hdc, rcClient.left,
rcClient.top+(GetSysCharHeight(hwnd) >> 1),
rcClient.right-rcClient.left,
rcClient.bottom-rcClient.top);
#endif
if (dwStyle & WS_DISABLED)
SetTextColor (hdc, DKGRAY);
else
SetTextColor (hdc, BLACK);
 
#if 0
SetBkColor(hdc, GetWindowBkColor (GetParent (hwnd)));
#endif
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
spCaption = GetWindowCaption (hwnd);
if (spCaption)
{
SelectObject(hdc, GetStockObject(FONT_NAME));
TextOut (hdc, GetSysCharWidth (hwnd), 2, spCaption, -1);
}
break;
}
EndPaint (hwnd, &ps);
}
break;
 
#if 0 /* jmt: SS_NOTIFY isn't standard in win32 */
case WM_LBUTTONDBLCLK:
if (GetWindowStyle (hwnd) & SS_NOTIFY)
SendMessage (GetParent(hwnd), WM_COMMAND,
(WPARAM)MAKELONG(pCtrl->id, STN_DBLCLK),
(LPARAM)hwnd);
break;
#endif
case WM_LBUTTONDOWN:
break;
 
case WM_NCLBUTTONDBLCLK:
break;
 
case WM_NCLBUTTONDOWN:
break;
 
case WM_NCHITTEST:
dwStyle = GetWindowStyle (hwnd);
if ((dwStyle & SS_TYPEMASK) == SS_GROUPBOX)
return HTTRANSPARENT;
 
#if 0 /* jmt: SS_NOTIFY isn't standard in win32 */
if (GetWindowStyle (hwnd) & SS_NOTIFY)
return HTCLIENT;
else
#endif
return HTNOWHERE;
break;
 
 
#if 0 /* jmt: fix: no WM_GETFONT/WM_SETFONT */
case WM_GETFONT:
break;
case WM_SETFONT:
break;
#endif
case WM_SETTEXT:
SetWindowCaption (hwnd, (char*)lParam);
InvalidateRect (hwnd, NULL, TRUE);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
/scrlbar.c
0,0 → 1,1140
/*
* Copyright (c) 2000 Greg Haerr <greg@censoft.com>
* Portions Copyright (c) 1999, 2000, Wei Yongming.
* jmt: scrollbar thumb ported
*
* Microwindows win32 Scrollbars control
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS /* jmt: for color macros */
#include "windows.h"
#include "wintern.h"
#include "wintools.h"
 
/* scrollbar status/positions*/
#define SBS_UNKNOWN 0x0000
#define SBS_LEFTARROW 0x0001
#define SBS_RIGHTARROW 0x0002
#define SBS_LEFTSPACE 0x0004
#define SBS_RIGHTSPACE 0x0008
#define SBS_HORZTHUMB 0x0010
#define SBS_UPARROW 0x0020
#define SBS_DOWNARROW 0x0040
#define SBS_UPSPACE 0x0080
#define SBS_DOWNSPACE 0x0100
#define SBS_VERTTHUMB 0x0200
#define SBS_MASK 0x03ff
#define SBS_DISABLED 0x4000
#define SBS_HIDE 0x8000
 
 
#define MWM_DEFBARLEN 18
#define MWM_MINBARLEN 8
 
static LRESULT CALLBACK
ScrollbarControlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 
int WINAPI MwRegisterScrollbarControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)ScrollbarControlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "SCROLLBAR";
 
return RegisterClass(&wc);
}
 
static DWORD GetWindowStyle (HWND hwnd)
{
return hwnd->style;
}
 
static int
wndGetBorder(HWND hwnd)
{
if (hwnd->style & WS_BORDER) {
if ((hwnd->style & WS_CAPTION) == WS_CAPTION)
return mwSYSMETRICS_CXFRAME;
return mwSYSMETRICS_CXBORDER;
}
return 0;
}
 
static BOOL
wndGetVScrollBarRect (HWND hwnd, RECT* rcVBar)
{
int cx,cy; RECT rc;
MWSCROLLBARINFO* pData;
pData = (MWSCROLLBARINFO *)hwnd->userdata;
rc = hwnd->winrect;
cx=rc.right-rc.left;
cy=rc.bottom-rc.top;
 
rcVBar->left = hwnd->winrect.right - cx
- wndGetBorder (hwnd);
rcVBar->right = hwnd->winrect.right - wndGetBorder (hwnd);
rcVBar->top = hwnd->winrect.top;
rcVBar->bottom = hwnd->winrect.bottom - wndGetBorder (hwnd);
 
return TRUE;
}
 
static BOOL
wndGetHScrollBarRect (HWND hwnd, RECT* rcHBar)
{
int cx,cy; RECT rc;
MWSCROLLBARINFO* pData;
pData = (MWSCROLLBARINFO *)hwnd->userdata;
rc = hwnd->winrect;
cx=rc.right-rc.left;
cy=rc.bottom-rc.top;
 
rcHBar->top = hwnd->winrect.bottom - cy
- wndGetBorder (hwnd);
rcHBar->bottom = hwnd->winrect.bottom - wndGetBorder (hwnd);
rcHBar->left = hwnd->winrect.left;
rcHBar->right = hwnd->winrect.right - wndGetBorder (hwnd);
 
return TRUE;
}
 
void
MwPaintScrollbars(HWND hwnd, HDC hdc, DWORD style)
{
BOOL vertbar = (style==SBS_VERT);
BOOL horzbar = (style==SBS_HORZ);
BOOL fGotDC = FALSE;
RECT rc,rc2;
 
POINT p3[3];
int shrink=2;
 
int start = 0;
RECT rcHBar, rcVBar;
 
int cx,cy;
MWSCROLLBARINFO* pData;
pData = (MWSCROLLBARINFO *)hwnd->userdata;
rc = hwnd->winrect;
cx=rc.right-rc.left;
cy=rc.bottom-rc.top;
 
if (!hdc && (horzbar || vertbar)) {
hdc = GetWindowDC(hwnd);
fGotDC = TRUE;
}
 
if (vertbar) {
 
#if 1
/* bkgnd */
rc2.left=rc.left; rc2.right=rc2.left+ cx;
rc2.top=rc.top;
rc2.bottom=rc2.top+ cx;
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE+1));
rc2.top=rc.bottom- cx;
rc2.bottom=rc2.top+ cx;
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE+1));
#endif
/* up */
Draw3dUpDownState(hdc, rc.left, rc.top,
cx, cx,
pData->status & SBS_UPARROW);
/* down */
Draw3dUpDownState(hdc, rc.left,rc.bottom-cx,
cx, cx,
pData->status & SBS_DOWNARROW);
/* jmt: draw arrows */
SelectObject(hdc,GetStockObject(BLACK_BRUSH));
/* up */
p3[0].x= rc.left + (cx/2) - 1;
p3[0].y= rc.top + 2 + shrink;
p3[1].x= rc.left + 2 + shrink - 1;
p3[1].y= rc.top + (cx-4) - shrink;
p3[2].x= rc.left + (cx-4) - shrink;
p3[2].y= rc.top + (cx-4) - shrink;
Polygon(hdc,p3,3);
/* down */
p3[0].x= rc.left + (cx/2) - 1;
p3[0].y= rc.bottom - 4 - shrink;
p3[1].x= rc.left + 2 + shrink - 1;
p3[1].y= rc.bottom-cx + 2 + shrink;
p3[2].x= rc.left + (cx-4) - shrink;
p3[2].y= rc.bottom-cx + 2 + shrink;
Polygon(hdc,p3,3);
 
/* draw moving bar */
 
wndGetVScrollBarRect (hwnd, &rcVBar);
rcVBar.left -- ;
/*rcVBar.right -- ;*/
 
start = rcVBar.top + cx + pData->barStart;
if (start + pData->barLen > rcVBar.bottom)
start = rcVBar.bottom - pData->barLen;
if (pData->barLen == 0)
pData->barLen=rc.bottom-rc.top-(cx*2);
 
/* bkgnd */
rc2.left=rc.left; rc2.right=rc.right/*-1*/;
rc2.top=rc.top+cx;
rc2.bottom=start;
if (rc2.bottom>rc2.top)
FillRect(hdc, &rc2, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
 
rc2.top=start+pData->barLen;
rc2.bottom=rc.bottom-cx;
if (rc2.bottom>rc2.top)
FillRect(hdc, &rc2, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
 
Draw3dUpFrame (hdc, rcVBar.left, start, rcVBar.right,
start + pData->barLen);
/*printf("barv:(l,t,r,b):(%d,%d,%d,%d)\n",
rcVBar.left, start, rcVBar.right,
start + pData->barLen);*/
 
}
if (horzbar) {
#if 1
/* bkgnd */
rc2.top=rc.top; rc2.bottom=rc2.top+ cy;
rc2.left=rc.left;
rc2.right=rc2.left+ cy;
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE+1));
rc2.left=rc.right- cy;
rc2.right=rc2.left+ cy;
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE+1));
#endif
/* left */
Draw3dUpDownState(hdc, rc.left, rc.top,
cy, cy,
pData->status & SBS_LEFTARROW);
/* right */
Draw3dUpDownState(hdc, rc.right-cy, rc.top,
cy, cy,
pData->status & SBS_RIGHTARROW);
/* jmt: draw arrows */
SelectObject(hdc,GetStockObject(BLACK_BRUSH));
/* left */
p3[0].x= rc.left + 2 + shrink;
p3[0].y= rc.top + (cy/2) ;
p3[1].x= rc.left + (cy-4) - shrink ;
p3[1].y= rc.top + 2 + shrink;
p3[2].x= rc.left + (cy-4) - shrink;
p3[2].y= rc.bottom - 4 - shrink + 1;
Polygon(hdc,p3,3);
/* right */
p3[0].x= rc.right - 4 - shrink;
p3[0].y= rc.top + (cy/2) ;
p3[1].x= rc.right-cy + 2 + shrink ;
p3[1].y= rc.top + 2 + shrink;
p3[2].x= rc.right-cy + 2 + shrink;
p3[2].y= rc.bottom - 4 - shrink + 1;
Polygon(hdc,p3,3);
 
/* draw moving bar. */
 
wndGetHScrollBarRect (hwnd, &rcHBar);
rcHBar.top -- ;
/*rcHBar.bottom -- ;*/
 
start = rcHBar.left + cy + pData->barStart;
 
if (start + pData->barLen > rcHBar.right)
start = rcHBar.right - pData->barLen;
 
if (pData->barLen == 0)
pData->barLen=rc.right-rc.left-(cy*2);
 
/* bkgnd */
rc2.top=rc.top; rc2.bottom=rc.bottom/*-1*/;
rc2.left=rc.left+cy;
rc2.right=start;
if (rc2.right>rc2.left)
FillRect(hdc, &rc2, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
 
rc2.left=start+pData->barLen;
rc2.right=rc.right-cy;
if (rc2.right>rc2.left)
FillRect(hdc, &rc2, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
 
Draw3dUpFrame (hdc, start, rcHBar.top, start + pData->barLen,
rcHBar.bottom);
/*printf("barh:(l,t,r,b):(%d,%d,%d,%d)\n",
start, rcHBar.top, start + pData->barLen,
rcHBar.bottom);*/
}
 
if (fGotDC)
ReleaseDC(hwnd, hdc);
}
 
/* handle a non-client message for a scrollbar*/
void
MwHandleMessageScrollbar(HWND hwnd, WPARAM hitcode, LPARAM lParam, UINT msg, DWORD style)
{
int pos = SBS_UNKNOWN;
BOOL vertbar = (style==SBS_VERT);
BOOL horzbar = (style==SBS_HORZ);
int * pStat;
POINT pt;
RECT rc;
 
static BOOL bDraw;
 
static int downPos = SBS_UNKNOWN;
static int sbCode;
int newThumbPos;
 
int itemMoveable,itemCount,itemVisible,moveRange; /* jmt:2k0819 */
int moveTop,moveBottom,moveLeft,moveRight; /* jmt:2k0819 */
 
int cx,cy;
MWSCROLLBARINFO* pData;
pData = (MWSCROLLBARINFO *)hwnd->userdata;
rc = hwnd->winrect;
cx=rc.right-rc.left;
cy=rc.bottom-rc.top;
 
POINTSTOPOINT(pt, lParam);
for (;;) { /* use for() to allow break statement*/
if (vertbar)
{
pStat = &pData->status;
rc = hwnd->winrect;
rc.bottom = rc.top + cx;
if (PtInRect(&rc, pt))
{
pos = SBS_UPARROW;
break;
}
rc.bottom = hwnd->winrect.bottom;
rc.top = rc.bottom - cx;
if (PtInRect(&rc, pt))
{
pos = SBS_DOWNARROW;
break;
}
pos = SBS_VERTTHUMB;
} else if (horzbar)
{
pStat = &pData->status;
rc = hwnd->winrect;
rc.right = rc.left + cy;
if (PtInRect(&rc, pt)) {
pos = SBS_LEFTARROW;
break;
}
rc.right = hwnd->winrect.right;
rc.left = rc.right - cy;
if (PtInRect(&rc, pt)) {
pos = SBS_RIGHTARROW;
break;
}
pos = SBS_HORZTHUMB;
} else
return;
break;
}
 
if (pos == SBS_UNKNOWN)
return;
 
*pStat &= ~SBS_MASK; /* remove stray mouse states*/
 
if (msg == WM_NCLBUTTONDOWN || msg == WM_NCLBUTTONDBLCLK)
*pStat |= pos;
else *pStat &= ~pos;
 
if (msg == WM_NCLBUTTONDOWN || msg == WM_NCLBUTTONDBLCLK)
bDraw=TRUE;
 
if (bDraw)
MwPaintScrollbars(hwnd, NULL,style);
 
if (pos == SBS_UPARROW || pos == SBS_LEFTARROW) /* jmt:2k0820 */
{
if (pData->curPos != pData->minPos)
sbCode = SB_LINEUP;
}
else if (pos == SBS_DOWNARROW || pos == SBS_RIGHTARROW) /* jmt:2k0820 */
{
if (pData->curPos != pData->maxPos)
sbCode = SB_LINEDOWN;
}
else if (pos == SBS_VERTTHUMB || pos == SBS_HORZTHUMB)
{
sbCode = SB_THUMBTRACK;
}
 
switch(msg)
{
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
downPos = pos;
break;
 
case WM_NCMOUSEMOVE:
if (vertbar)
{
if (sbCode == SB_THUMBTRACK && downPos == SBS_VERTTHUMB)
{
/* jmt(2k0819): new algorithm for SB_THUMBTRACK */
 
rc = hwnd->winrect;
moveTop = rc.top + cx;
moveBottom = hwnd->winrect.bottom - cx;
moveRange = moveBottom - moveTop;
 
itemCount = pData->maxPos - pData->minPos + 1;
itemVisible = pData->pageStep;
itemMoveable = itemCount - itemVisible + 1;
 
newThumbPos = ((pt.y - moveTop) * itemMoveable) / moveRange;
printf("((%d-%d)*%d)/%d=%d\n",
pt.y,moveTop,itemMoveable,moveRange,newThumbPos);
 
if ( newThumbPos >= pData->minPos &&
newThumbPos <= pData->maxPos)
{
SendMessage (hwnd,
WM_VSCROLL, SB_THUMBTRACK, newThumbPos);
 
SendMessage (GetParent(hwnd),
WM_VSCROLL, SB_THUMBTRACK, newThumbPos);
}
break;
}
}
if (horzbar)
{
if (sbCode == SB_THUMBTRACK && downPos == SBS_HORZTHUMB)
{
/* jmt(2k0819): new algorithm for SB_THUMBTRACK */
 
rc = hwnd->winrect;
moveLeft = rc.left + cy;
moveRight = hwnd->winrect.right - cy;
moveRange = moveRight - moveLeft;
 
itemCount = pData->maxPos - pData->minPos + 1;
itemVisible = pData->pageStep;
itemMoveable = itemCount - itemVisible + 1;
 
newThumbPos = ((pt.x - moveLeft) * itemMoveable) / moveRange;
printf("((%d-%d)*%d)/%d=%d\n",
pt.y,moveLeft,itemMoveable,moveRange,newThumbPos);
if ( newThumbPos >= pData->minPos &&
newThumbPos <= pData->maxPos)
{
SendMessage (hwnd,
WM_HSCROLL, SB_THUMBTRACK, newThumbPos);
 
SendMessage (GetParent(hwnd),
WM_HSCROLL, SB_THUMBTRACK, newThumbPos);
}
break;
}
}
break;
 
case WM_NCLBUTTONUP:
bDraw=FALSE;
downPos = SBS_UNKNOWN;
 
if (sbCode==SB_THUMBTRACK)
{
if (vertbar)
{
/* jmt(2k0819): new algorithm for SB_THUMBTRACK */
 
rc = hwnd->winrect;
moveTop = rc.top + cx;
moveBottom = hwnd->winrect.bottom - cx;
moveRange = moveBottom - moveTop;
 
itemCount = pData->maxPos - pData->minPos + 1;
itemVisible = pData->pageStep;
itemMoveable = itemCount - itemVisible + 1;
 
newThumbPos = ((pt.y - moveTop) * itemMoveable) / moveRange;
printf("((%d-%d)*%d)/%d=%d\n",
pt.y,moveTop,itemMoveable,moveRange,newThumbPos);
 
if ( newThumbPos >= pData->minPos &&
newThumbPos <= pData->maxPos)
{
SendMessage (hwnd,
WM_VSCROLL, SB_THUMBTRACK, newThumbPos);
 
SendMessage (GetParent(hwnd),
WM_VSCROLL, SB_THUMBTRACK, newThumbPos);
}
break; /* case */
}
if (horzbar)
{
/* jmt(2k0819): new algorithm for SB_THUMBTRACK */
 
rc = hwnd->winrect;
moveLeft = rc.left + cy;
moveRight = hwnd->winrect.right - cy;
moveRange = moveRight - moveLeft;
 
itemCount = pData->maxPos - pData->minPos + 1;
itemVisible = pData->pageStep;
itemMoveable = itemCount - itemVisible + 1;
 
newThumbPos = ((pt.x - moveLeft) * itemMoveable) / moveRange;
printf("((%d-%d)*%d)/%d=%d\n",
pt.y,moveLeft,itemMoveable,moveRange,newThumbPos);
if ( newThumbPos >= pData->minPos &&
newThumbPos <= pData->maxPos)
{
SendMessage (hwnd,
WM_HSCROLL, SB_THUMBTRACK, newThumbPos);
 
SendMessage (GetParent(hwnd),
WM_HSCROLL, SB_THUMBTRACK, newThumbPos);
}
break; /* case */
}
}
else
{
if (vertbar)
{
SendMessage (hwnd, WM_VSCROLL, sbCode, 0);
SendMessage (GetParent(hwnd), WM_VSCROLL, sbCode, 0);
}
if (horzbar)
{
SendMessage (hwnd, WM_HSCROLL, sbCode, 0);
SendMessage (GetParent(hwnd), WM_HSCROLL, sbCode, 0);
}
}
break;
}
}
 
 
static BOOL
PtInRect2(const RECT *lprc, int x, int y)
{
POINT p;
 
p.x = x;
p.y = y;
return PtInRect(lprc, p);
}
 
static void
wndScrollBarPos (HWND hwnd, BOOL bIsHBar, RECT* rcBar) /* jmt: 2k0820 */
{
UINT moveRange;
PMWSCROLLBARINFO pSBar;
int cx,cy;
RECT rc;
rc = hwnd->winrect;
cx=rc.right-rc.left;
cy=rc.bottom-rc.top;
pSBar = (MWSCROLLBARINFO *)hwnd->userdata;
 
if (pSBar->minPos == pSBar->maxPos) {
pSBar->status |= SBS_HIDE;
return;
}
 
if (bIsHBar)
moveRange = (rcBar->right - rcBar->left) - (cy << 1);
else
moveRange = (rcBar->bottom - rcBar->top) - (cx << 1);
 
 
if (pSBar->pageStep == 0)
{
pSBar->barLen = MWM_DEFBARLEN;
 
if (pSBar->barLen > moveRange)
pSBar->barLen = MWM_MINBARLEN;
}
else
{
pSBar->barLen = moveRange * pSBar->pageStep /
(pSBar->maxPos - pSBar->minPos + 1);
if (pSBar->barLen < MWM_MINBARLEN)
pSBar->barLen = MWM_MINBARLEN;
}
 
pSBar->barStart = moveRange * (pSBar->curPos - pSBar->minPos) /
(pSBar->maxPos - pSBar->minPos + 1);
 
 
if (pSBar->barStart + pSBar->barLen > moveRange)
pSBar->barStart = moveRange - pSBar->barLen;
 
 
if (pSBar->barStart < 0)
pSBar->barStart = 0;
}
 
static PMWSCROLLBARINFO wndGetScrollBar (HWND pWin) /* jmt: 2k0820 */
{
MWSCROLLBARINFO* pData;
pData = (MWSCROLLBARINFO *)pWin->userdata;
 
if (!strcmp(pWin->pClass->lpszClassName,"SCROLLBAR"))
return pData;
else
return NULL;
}
 
BOOL EnableScrollBarEx (HWND hWnd, int iSBar, BOOL bEnable) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
BOOL bPrevState;
RECT rcBar;
DWORD dwStyle; /* jmt:2k0820 */
 
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
bPrevState = !(pSBar->status & SBS_DISABLED);
 
if (bEnable && !bPrevState)
pSBar->status &= ~SBS_DISABLED;
else if (!bEnable && bPrevState)
pSBar->status |= SBS_DISABLED;
else
return FALSE;
 
dwStyle = (GetWindowStyle (hWnd) & SBS_TYPEMASK); /* jmt: 2k0820 */
 
if (dwStyle == SBS_VERT)
{
wndGetVScrollBarRect (pWin, &rcBar);
rcBar.left --;
rcBar.right --;
}
else
{
wndGetHScrollBarRect (pWin, &rcBar);
rcBar.top --;
rcBar.bottom --;
}
#if 0
SendMessage (hWnd, WM_NCPAINT, 0, (LPARAM)(&rcBar));
#else
MwPaintScrollbars(hWnd,NULL,dwStyle); /* a must */
#endif
 
return TRUE;
}
 
BOOL GetScrollPosEx (HWND hWnd, int iSBar, int* pPos) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
*pPos = pSBar->curPos;
return TRUE;
}
 
BOOL GetScrollRangeEx (HWND hWnd, int iSBar, int* pMinPos, int* pMaxPos) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
*pMinPos = pSBar->minPos;
*pMaxPos = pSBar->maxPos;
return TRUE;
}
 
BOOL SetScrollPosEx (HWND hWnd, int iSBar, int iNewPos) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
RECT rcBar;
DWORD dwStyle; /* jmt:2k0820 */
 
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
if (iNewPos < pSBar->minPos)
pSBar->curPos = pSBar->minPos;
else
pSBar->curPos = iNewPos;
 
{
int max = pSBar->maxPos;
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
 
if (pSBar->curPos > max)
pSBar->curPos = max;
}
dwStyle = (GetWindowStyle (hWnd) & SBS_TYPEMASK); /* jmt: 2k0820 */
 
if (dwStyle == SBS_VERT)
{
wndGetVScrollBarRect (pWin, &rcBar);
rcBar.left --;
rcBar.right --;
}
else
{
wndGetHScrollBarRect (pWin, &rcBar);
rcBar.top --;
rcBar.bottom --;
}
 
wndScrollBarPos (pWin, dwStyle == SBS_HORZ, &rcBar);
 
#if 0
SendMessage (hWnd, WM_NCPAINT, 0, (LPARAM)(&rcBar));
#else
MwPaintScrollbars(hWnd,NULL,dwStyle); /* a must */
#endif
return TRUE;
}
 
BOOL SetScrollRangeEx (HWND hWnd, int iSBar, int iMinPos, int iMaxPos) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
RECT rcBar;
DWORD dwStyle; /* jmt:2k0820 */
 
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
pSBar->minPos = (iMinPos < iMaxPos)?iMinPos:iMaxPos;
pSBar->maxPos = (iMinPos > iMaxPos)?iMinPos:iMaxPos;
/* validate parameters. */
if (pSBar->curPos < pSBar->minPos)
pSBar->curPos = pSBar->minPos;
 
if (pSBar->pageStep <= 0)
pSBar->pageStep = 0;
else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))
pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;
{
int max = pSBar->maxPos;
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
 
if (pSBar->curPos > max)
pSBar->curPos = max;
}
 
dwStyle = (GetWindowStyle (hWnd) & SBS_TYPEMASK); /* jmt: 2k0820 */
 
if (dwStyle == SBS_VERT)
{
wndGetVScrollBarRect (pWin, &rcBar);
rcBar.left --;
rcBar.right --;
}
else
{
wndGetHScrollBarRect (pWin, &rcBar);
rcBar.top --;
rcBar.bottom --;
}
wndScrollBarPos (pWin, dwStyle == SBS_HORZ, &rcBar);
 
#if 0
SendMessage (hWnd, WM_NCPAINT, 0, (LPARAM)(&rcBar));
#else
MwPaintScrollbars(hWnd,NULL,dwStyle); /* a must */
#endif
 
return TRUE;
}
 
BOOL SetScrollInfoEx (HWND hWnd, int iSBar,
LPCSCROLLINFO lpsi, BOOL fRedraw) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
RECT rcBar;
DWORD dwStyle; /* jmt:2k0820 */
 
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
if( lpsi->fMask & SIF_RANGE )
{
pSBar->minPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMin:lpsi->nMax;
pSBar->maxPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMax:lpsi->nMin;
}
if( lpsi->fMask & SIF_POS )
pSBar->curPos = lpsi->nPos;
if( lpsi->fMask & SIF_PAGE )
pSBar->pageStep = lpsi->nPage;
 
/* validate parameters. */
if (pSBar->curPos < pSBar->minPos)
pSBar->curPos = pSBar->minPos;
 
if (pSBar->pageStep <= 0)
pSBar->pageStep = 0;
else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))
pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;
{
int max = pSBar->maxPos;
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
 
if (pSBar->curPos > max)
pSBar->curPos = max;
}
 
dwStyle = (GetWindowStyle (hWnd) & SBS_TYPEMASK); /* jmt: 2k0820 */
 
if(fRedraw)
{
if (dwStyle == SBS_VERT)
{
wndGetVScrollBarRect (pWin, &rcBar);
rcBar.left --;
rcBar.right --;
}
else
{
wndGetHScrollBarRect (pWin, &rcBar);
rcBar.top --;
rcBar.bottom --;
}
wndScrollBarPos (pWin, dwStyle == SBS_HORZ, &rcBar);
 
#if 0
SendMessage (hWnd, WM_NCPAINT, 0, (LPARAM)(&rcBar));
#else
MwPaintScrollbars(hWnd,NULL,dwStyle); /* a must */
#endif
}
return TRUE;
}
 
BOOL GetScrollInfoEx(HWND hWnd, int iSBar, LPSCROLLINFO lpsi) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
if( lpsi->fMask & SIF_RANGE )
{
lpsi->nMin = pSBar->minPos;
lpsi->nMax = pSBar->maxPos;
}
if( lpsi->fMask & SIF_POS )
{
lpsi->nPos = pSBar->curPos;
}
if( lpsi->fMask & SIF_PAGE )
lpsi->nPage = pSBar->pageStep;
return TRUE;
}
 
BOOL ShowScrollBarEx (HWND hWnd, int iSBar, BOOL bShow) /* jmt: iSBar not used */
{
PMWSCROLLBARINFO pSBar;
HWND pWin;
BOOL bPrevState;
RECT rcBar;
DWORD dwStyle; /* jmt:2k0820 */
 
pWin = (HWND)hWnd;
if ( !(pSBar = wndGetScrollBar (pWin)) )
return FALSE;
 
bPrevState = !(pSBar->status & SBS_HIDE);
 
if (bShow && !bPrevState)
pSBar->status &= ~SBS_HIDE;
else if (!bShow && bPrevState)
pSBar->status |= SBS_HIDE;
else
return FALSE;
 
#if 0 /* fix: no WM_CHANGESIZE */
SendMessage (hWnd, WM_CHANGESIZE, 0, 0);
#endif
 
dwStyle = (GetWindowStyle (hWnd) & SBS_TYPEMASK); /* jmt: 2k0820 */
 
if (dwStyle == SBS_VERT)
wndGetVScrollBarRect (pWin, &rcBar);
else
wndGetHScrollBarRect (pWin, &rcBar);
 
{
RECT rcWin, rcClient;
memcpy (&rcWin, &pWin->winrect.left, sizeof (RECT));
rcClient.left = 0;
rcClient.top = 0;
rcClient.right = pWin->clirect.right - pWin->clirect.left;
rcClient.bottom = pWin->clirect.bottom - pWin->clirect.top;
#if 0 /* fix: no WM_SIZECHANGED */
SendMessage (hWnd, WM_SIZECHANGED,
(WPARAM)&rcWin, (LPARAM)&rcClient);
#endif
}
if (bShow) {
SendMessage (hWnd, WM_NCPAINT, 0, 0);
}
else {
rcBar.left -= pWin->clirect.left;
rcBar.top -= pWin->clirect.top;
rcBar.right -= pWin->clirect.left;
rcBar.bottom -= pWin->clirect.top;
SendMessage (hWnd, WM_NCPAINT, 0, 0);
InvalidateRect (hWnd, &rcBar, TRUE);
}
 
return TRUE;
}
 
static void sbSetScrollInfo (HWND hwnd, PMWSCROLLBARINFO pData, BOOL fRedraw) /* jmt:2k0820 */
{
SCROLLINFO si;
 
int itemCount,itemVisibles;
 
itemCount = pData->maxPos - pData->minPos + 1;
itemVisibles = pData->pageStep;
 
if (itemVisibles >= itemCount)
{
SetScrollPosEx (hwnd, 0, 0); /* jmt: arg2 not used */
EnableScrollBarEx (hwnd, 0, FALSE); /* jmt: arg2 not used */
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = itemCount - 1;
si.nMin = 0;
 
si.nPage = itemVisibles; /* jmt(2k0819): new algorithm for SB_THUMBTRACK */
 
si.nPos = pData->curPos;
 
SetScrollInfoEx (hwnd, 0, &si, fRedraw); /* jmt: arg2 not used */
EnableScrollBarEx (hwnd, 0, TRUE); /* jmt: arg2 not used */
}
 
static LRESULT CALLBACK
ScrollbarControlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* jmt:2k0820 */
{
DWORD dwStyle;
MWSCROLLBARINFO* pData;
 
int moveRange;
RECT rcBar;
 
dwStyle = (GetWindowStyle (hwnd) & SBS_TYPEMASK);
switch (message)
{
case WM_CREATE:
if (!(pData = malloc (sizeof (MWSCROLLBARINFO))))
{
fprintf(stderr, "Create scroll bar control failure!\n");
return -1;
}
 
pData->minPos=0; /* min value of scroll range.*/
/* max value of scroll range.*/
pData->maxPos=0;
if (dwStyle==SBS_VERT)
moveRange=((hwnd->winrect.bottom-hwnd->winrect.top)
-((hwnd->winrect.right-hwnd->winrect.left)<<1));
else
moveRange=((hwnd->winrect.right-hwnd->winrect.left)
-((hwnd->winrect.bottom-hwnd->winrect.top)<<1));
if (moveRange > MWM_MINBARLEN)
{
 
 
pData->maxPos=moveRange / MWM_MINBARLEN;
if( (moveRange % MWM_MINBARLEN) )
pData->maxPos++;
}
printf("maxPos=%d\n",pData->maxPos);
 
pData->curPos=0; /* current scroll pos.*/
 
/* steps per page.*/
pData->pageStep=1;
if ( (pData->maxPos - 2) > 1)
pData->pageStep = pData->maxPos - 2;
printf("pageStep=%d\n",pData->pageStep);
 
pData->barStart=0; /* start pixel of bar.*/
pData->barLen=MWM_MINBARLEN; /* length of bar.*/
pData->status=SBS_UNKNOWN; /* status of scroll bar.*/
#if 0 /* jmt: must handle WM_MOVE */
pData->rc=hwnd->winrect; /* screen coordinates position*/
#endif
hwnd->userdata = (DWORD)pData;
 
if (dwStyle == SBS_VERT)
{
wndGetVScrollBarRect (hwnd, &rcBar);
rcBar.left --;
rcBar.right --;
}
else
{
wndGetHScrollBarRect (hwnd, &rcBar);
rcBar.top --;
rcBar.bottom --;
}
/* adjust pData->barLen */
wndScrollBarPos (hwnd, dwStyle == SBS_HORZ, &rcBar);
 
break;
case WM_DESTROY:
free ((void *)(hwnd->userdata));
break;
 
case WM_PAINT:
MwPaintScrollbars(hwnd,NULL,dwStyle);
break;
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONUP:
MwHandleMessageScrollbar(hwnd, wParam, lParam, message, dwStyle);
break;
 
case WM_HSCROLL:
case WM_VSCROLL:
{
int newTop,itemCount,itemVisibles;
 
pData = (MWSCROLLBARINFO *)hwnd->userdata;
newTop = pData->curPos;
itemCount = pData->maxPos - pData->minPos + 1;
itemVisibles = pData->pageStep;
 
switch(wParam)
{
case SB_LINEDOWN:
#define ITEM_BOTTOM(x) (x->curPos + itemVisibles - 1)
if (ITEM_BOTTOM (pData) < (itemCount - 1 ))
{
newTop ++;
}
break;
case SB_LINEUP:
if (pData->curPos > 0)
{
newTop --;
}
break;
case SB_PAGEDOWN:
if ((pData->curPos + (itemVisibles << 1)) <=
itemCount)
newTop += itemVisibles;
else
newTop = itemCount - itemVisibles;
 
if (newTop < 0)
return 0;
 
break;
 
case SB_PAGEUP:
if (pData->curPos >= itemVisibles)
newTop -= itemVisibles;
else
newTop = 0;
 
break;
 
case SB_THUMBTRACK:
newTop = (int)lParam;
break;
}
pData->curPos = newTop;
 
SendMessage (hwnd, WM_PAINT, 0, 0);
 
sbSetScrollInfo (hwnd, pData, TRUE);
 
return 0;
}
break;
 
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
 
/graph3d.c
0,0 → 1,540
/*
* Copyright (c) 1999 Greg Haerr <greg@censoft.com>
*
* 3D Graphics Library for Micro-Windows
*/
#define MWINCLUDECOLORS
#include "windows.h"
#include "device.h"
#include "graph3d.h"
#define USEBLIT 1 /* =1 to use memDC's*/
 
static int nxpix;
static int nypix;
static vec1 xscale;
static vec1 yscale;
static vec3 eye;
static vec3 direct;
static double Q[5][5];
static HDC hdc;
static HDC hdcMem;
static HBITMAP hbmp, hbmpOrg;
 
/* setup eye, direction, calc observation matrix Q*/
void
look3(vec1 x, vec1 y, vec1 z)
{
eye.x = x;
eye.y = y;
eye.z = z;
direct.x = -eye.x;
direct.y = -eye.y;
direct.z = -eye.z;
findQ();
}
 
void
init3(HDC hDC, HWND memhwnd)
{
HBRUSH hbr;
 
hdc = hDC;
if(hdc) {
nxpix = hdc->hwnd->clirect.right - hdc->hwnd->clirect.left;
nypix = hdc->hwnd->clirect.bottom - hdc->hwnd->clirect.top;
xscale = (vec1)(nxpix-1) / nxpix * nxpix/2;
yscale = (vec1)(nypix-1) / nypix * nypix/2;
 
if(memhwnd) {
hdcMem = CreateCompatibleDC(NULL);
if(hdcMem) {
hbmp = CreateCompatibleBitmap(hdcMem,
nxpix, nypix);
hbmpOrg = SelectObject(hdcMem, hbmp);
hdc = hdcMem;
}
hbr = (HBRUSH)GetClassLong(memhwnd, GCL_HBRBACKGROUND);
FillRect(hdc, NULL, hbr);
}
/* create pen for setcolor3() color override*/
SelectObject(hdc, CreatePen(PS_SOLID, 1, BLACK));
}
}
 
void
paint3(HDC hDC)
{
if(hdcMem) {
BitBlt(hDC, 0, 0, nxpix, nypix, hdcMem, 0, 0, SRCCOPY);
DeleteObject(SelectObject(hdcMem, hbmpOrg));
DeleteDC(hdcMem);
}
hdcMem = NULL;
}
 
int
fx(vec1 x)
{
return (int)(x * xscale + nxpix*0.5 - 0.5);
}
 
int
fy(vec1 y)
{
return (int)(y * yscale + nypix*0.5 - 0.5);
}
 
void
moveto3(vec2 pt)
{
MoveToEx(hdc, fx(pt.x), fy(pt.y), NULL);
}
 
void
setcolor3(MWCOLORVAL c)
{
if(hdc)
hdc->pen->color = c;
}
 
void
lineto3(vec2 pt)
{
LineTo(hdc, fx(pt.x), fy(pt.y));
}
 
void
polyfill(int n, vec2 points[])
{
int i;
int xoff, yoff;
MWPOINT pv[MAXPOLY];
 
if(!hdc)
return;
 
/* calc window offset*/
xoff = hdc->hwnd->clirect.left;
yoff = hdc->hwnd->clirect.top;
 
/* only plot non-trivial polygons*/
if(n > 2) {
for(i=0; i<n; ++i) {
pv[i].x = fx(points[i].x) + xoff;
pv[i].y = fy(points[i].y) + yoff;
/* fix: floating round error, y intercept difference
* with GdLine
*/
/*pv[i].x = fx(points[i].x + xoff);*/
/*pv[i].y = fy(points[i].y + yoff);*/
}
GdSetForeground(GdFindColor(hdc->pen->color));
GdFillPoly(hdc->psd, n, pv);
}
}
 
void
square(void)
{
vec2 pt0, pt1, pt2, pt3;
 
pt0.x = -1; pt0.y = 1;
pt1.x = -1; pt1.y = -1;
pt2.x = 1; pt2.y = -1;
pt3.x = 1; pt3.y = 1;
moveto3(pt0);
lineto3(pt1);
lineto3(pt2);
lineto3(pt3);
lineto3(pt0);
}
 
void
circle3(vec1 r)
{
vec1 theta = 0;
vec1 thinc = 2*pi/100;
int i;
vec2 pt;
 
pt.x = r;
pt.y = 0.0;
moveto3(pt);
 
for(i=0; i<100; ++i) {
theta = theta + thinc;
pt.x = r*cos(theta);
pt.y = r*sin(theta);
lineto3(pt);
}
}
 
void
daisy(vec1 r,int points)
{
int i, j;
vec1 theta = 0;
vec1 thinc;
vec2 pt[100];
 
/* calculate n points on a circle*/
thinc = 2*pi/points;
for(i=0; i<points; ++i) {
pt[i].x = r*cos(theta);
pt[i].y = r*sin(theta);
theta += thinc;
}
 
/* join point i to point j for all 0 <= i < j < n */
for(i=0; i<points-1; ++i) {
for(j=i+1; j<points; ++j) {
moveto3(pt[i]);
lineto3(pt[j]);
}
}
}
 
void
rose(vec1 r,int levels,int points)
{
int i, j, m, n;
vec1 r1, theta, thinc;
vec2 inner[100];
vec2 outer[100];
vec2 triangle[3];
 
m = levels;
n = points;
thinc = 2*pi/n;
 
/* initial inner circle*/
for(i=0; i<n; ++i) {
inner[i].x = 0.0;
inner[i].y = 0.0;
}
 
/* loop thru m levels*/
for(j=1; j<=m; ++j) {
theta = -j*pi/n;
r1 = r * (vec1)j/m;
 
/* calc n points on outer circle*/
for(i=0; i<n; ++i) {
theta += thinc;
outer[i].x = r1*cos(theta);
outer[i].y = r1*sin(theta);
}
 
/* construct/draw triangles with vertices on
* inner and outer circles
*/
for(i=0; i<n; ++i) {
triangle[0] = outer[i];
triangle[1] = outer[(i+1) % n];
triangle[2] = inner[i];
 
/* fill triangle in red*/
setcolor3(RED);
polyfill(3, triangle);
 
#if 1
/* outline triangle in white*/
setcolor3(WHITE);
moveto3(triangle[0]);
lineto3(triangle[1]);
lineto3(triangle[2]);
lineto3(triangle[0]);
#endif
}
 
/* copy points on outer circle to inner arrays*/
for(i=0; i<n; ++i)
inner[i] = outer[i];
}
}
 
/* draw a triangle with cordners v0, v1, v2*/
void
triangle(vec2 v0, vec2 v1, vec2 v2)
{
vec2 poly[3];
 
poly[0] = v0;
poly[1] = v1;
poly[2] = v2;
 
setcolor3(GREEN);
polyfill(3, poly);
setcolor3(BLACK);
moveto3(poly[2]);
lineto3(poly[0]);
lineto3(poly[1]);
lineto3(poly[2]);
}
 
/* draw a quadrilateral with corners v0, v1, v2, v3*/
void
quadrilateral(vec2 v0, vec2 v1, vec2 v2, vec2 v3)
{
vec2 poly[4];
 
poly[0] = v0;
poly[1] = v1;
poly[2] = v2;
poly[3] = v3;
setcolor3(GREEN);
polyfill(4, poly);
setcolor3(BLACK);
moveto3(poly[3]);
lineto3(poly[0]);
lineto3(poly[1]);
lineto3(poly[2]);
lineto3(poly[3]);
}
 
/* find intersection of lines v0 to v1 and v2 to v3*/
static int
patch(vec2 v0, vec2 v1, vec2 v2, vec2 v3)
{
vec1 denom;
vec1 mu;
vec2 v4;
 
denom = (v1.x-v0.x)*(v3.y-v2.y) - (v1.y-v0.y)*(v3.x-v2.x);
if(fabs(denom) > epsilon) {
mu = ((v2.x-v0.x)*(v3.y-v2.y) - (v2.y-v0.y)*(v3.x-v2.x))/denom;
 
/* if intersection between lines v0 to v1 and v2 to v3,
* call it v4 and form triangles v0,v2,v4 and v1,v3,v4
*/
if(mu >= 0 && mu <= 1) {
v4.x = (1-mu)*v0.x + mu*v1.x;
v4.y = (1-mu)*v0.y + mu*v1.y;
triangle(v0, v2, v4);
triangle(v1, v3, v4);
return 0;
}
}
 
/* else find intersection of lines v0 to v2 and v1 to v3*/
denom = (v2.x-v0.x)*(v3.y-v1.y) - (v2.y-v0.y)*(v3.x-v1.x);
if(fabs(denom) > epsilon) {
mu = ((v1.x-v0.x)*(v3.y-v1.y) - (v1.y-v0.y)*(v3.x-v1.x))/denom;
 
/* if intersection between v0 and v1, call it v4
* and form triangles v0,v1,v4 and v2,v3,v4
*/
if(mu >= 0 && mu <= 1) {
v4.x = (1-mu)*v0.x + mu*v2.x;
v4.y = (1-mu)*v0.y + mu*v2.y;
triangle(v0, v1, v4);
triangle(v2, v3, v4);
return 0;
}
}
 
/* there are no proper intersections so form quadrilateral v0,v1,v3,v2*/
quadrilateral(v0, v1, v3, v2);
return 1;
}
 
/* plotted function*/
static vec1
plotfn(vec1 x, vec1 z)
{
vec1 t;
 
/* y = 4sin(sqrt(x*x+z*z))/sqrt(x*x+z*z) */
t = sqrt(x*x + z*z);
if(fabs(t) < epsilon)
return 4.0;
return 4.0 * sin(t) / t;
}
 
/* draw mathematical function plotfn*/
void
drawgrid(vec1 xmin, vec1 xmax, int nx, vec1 zmin, vec1 zmax, int nz)
{
int i, j;
vec1 xi, xstep, yij;
vec1 zj, zstep;
vec2 v[2][100];
double S[5][5];
 
/* scale it down*/
scale3(1.0/(xmax-xmin)*2, 1.0/(xmax-xmin)*2, 1.0/(zmax-zmin), S);
mult3(Q, S, Q);
 
/* grid from xmin to xmax in nx steps and zmin to xmax in nz steps*/
xstep = (xmax-xmin)/nx;
zstep = (zmax-zmin)/nz;
xi = xmin;
zj = zmin;
 
/* calc grid points on first fixed-z line, fine the y-height
* and transfrorm the points (xi,yij,zj) into observed
* position. Observed first set stored in v[0,1..nx]
*/
for(i=0; i<=nx; ++i) {
yij = plotfn(xi, zj);
v[0][i].x = Q[1][1]*xi + Q[1][2]*yij + Q[1][3]*zj;
v[0][i].y = Q[2][1]*xi + Q[2][2]*yij + Q[2][3]*zj;
xi += xstep;
}
 
/* run thru consecutive fixed-z lines (the second set)*/
for(j=0; j<nz; ++j) {
xi = xmin;
zj += zstep;
 
/* calc grid points on this second set, find the
* y-height and transform the points (xi,yij,zj)
* into observed position. Observed second set
* stored in v[1,0..nx]
*/
for(i=0; i<=nx; ++i) {
yij = plotfn(xi, zj);
v[1][i].x = Q[1][1]*xi + Q[1][2]*yij + Q[1][3]*zj;
v[1][i].y = Q[2][1]*xi + Q[2][2]*yij + Q[2][3]*zj;
xi += xstep;
}
 
/* run thru the nx patches formed by these two sets*/
for(i=0; i<nx; ++i)
patch(v[0][i], v[0][i+1], v[1][i], v[1][i+1]);
 
/* copy second set into first set*/
for(i=0; i<=nx; ++i)
v[0][i] = v[1][i];
}
}
 
/* returns the angle whose tangent is y/x.
* all anomalies such as x=0 are also checked
*/
vec1
angle(vec1 x, vec1 y)
{
if(fabs(x) < epsilon)
if(fabs(y) < epsilon)
return 0.0;
else
if(y > 0.0)
return pi*0.5;
else return pi*1.5;
else
if(x < 0.0)
return atan(y/x) + pi;
else return atan(y/x);
}
 
/* calc 3d scaling matrix A giving scaling vector sx,sy,sz.
* one unit on the x axis becomes sx units, one unit on y, sy,
* and one unit on the z axis becomes sz units
*/
void
scale3(vec1 sx, vec1 sy, vec1 sz, double A[][5])
{
int i, j;
 
for(i=1; i<5; ++i)
for(j=1; j<5; ++j)
A[i][j] = 0.0;
A[1][1] = sx;
A[2][2] = sy;
A[3][3] = sz;
A[4][4] = 1.0;
}
 
/* calc 3d axes translation matrix A
* origin translated by vectdor tx,ty,tz
*/
void
tran3(vec1 tx, vec1 ty, vec1 tz, double A[][5])
{
int i, j;
 
for(i=1; i<5; ++i) {
for(j=1; j<5; ++j)
A[i][j] = 0.0;
A[i][i] = 1.0;
}
A[1][4] = -tx;
A[2][4] = -ty;
A[3][4] = -tz;
}
 
/* calc 3d axes rotation matrix A. The axes are
* rotated anti-clockwise through an angle theta radians
* about an axis specified by m: m=1 means x, m=2 y, m=3 z axis
*/
void
rot3(int m, vec1 theta, double A[][5])
{
int i, j, m1, m2;
vec1 c, s;
 
for(i=1; i<5; ++i)
for(j=1; j<5; ++j)
A[i][j] = 0.0;
A[m][m] = 1.0;
A[4][4] = 1.0;
m1 = (m % 3) + 1;
m2 = (m1 % 3) + 1;
c = cos(theta);
s = sin(theta);
A[m1][m1] = c;
A[m2][m2] = c;
A[m1][m2] = s;
A[m2][m1] = s;
}
 
/* calc the matrix product C of two matrices A and B*/
void
mult3(double A[][5], double B[][5], double C[][5])
{
int i, j, k;
vec1 ab;
 
for(i=1; i<5; ++i)
for(j=1; j<5; ++j) {
ab = 0;
for(k=1; k<5; ++k)
ab += A[i][k] * B[k][j];
C[i][j] = ab;
}
}
 
/* calc observation matrix Q for given observer*/
void
findQ(void)
{
vec1 alpha, beta, gamma, v, w;
double E[5][5];
double F[5][5];
double G[5][5];
double H[5][5];
double U[5][5];
 
/* calc translation matrix F*/
tran3(eye.x, eye.y, eye.z, F);
 
/* calc rotation matrix G*/
alpha = angle(-direct.x, -direct.y);
rot3(3, alpha, G);
 
/* calc rotation matrix H*/
v = sqrt(direct.x*direct.x + direct.y*direct.y);
beta = angle(-direct.z, v);
rot3(2, beta, H);
 
/* calc rotation matrix U*/
w = sqrt(v*v + direct.z*direct.z);
gamma = angle(-direct.x*w, direct.y*direct.z);
rot3(3, -gamma, U);
 
/* combine the transformations to find Q*/
mult3(G, F, Q);
mult3(H, Q, E);
mult3(U, E, Q);
}
/progbar.c
0,0 → 1,363
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 Greg Haerr <greg@censoft.com>
*
* Progress bar for Microwindows win32 api.
*/
 
/*
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library 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
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library 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
*/
 
/*
** Alternatively, the contents of this file may be used under the terms
** of the Mozilla Public License (the "MPL License") in which case the
** provisions of the MPL License are applicable instead of those above.
*/
 
/* Copyright (C) 1999, 2000, Wei Yongming.
**
** Note:
** Originally by Zhao Jianghua.
**
** Create date: 1999/8/29
**
** Modify records:
**
** Who When Where For What Status
**-----------------------------------------------------------------------------
** WEI Yongming 1999/10/27 Tsinghua unsigned int Finished
** WEI Yongming 1999/10/27 Tsinghua FPException fixing Finished
** WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished
** Kevin Tseng 2000/05/24 gv port to microwin ported
** Greg Haerr 2000/06/15 Utah removed floats Finished
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "windows.h" /* windef.h, winuser.h */
#include "wintools.h" /* Draw3dBox */
#include "device.h" /* GdGetTextSize */
 
#define TEST 1 /* =1 for testing*/
 
#define WIDTH_PBAR_BORDER 2
 
typedef struct _PROGRESSDATA {
unsigned int nMin;
unsigned int nMax;
unsigned int nPos;
unsigned int nStepInc;
} PROGRESSDATA, *PPROGRESSDATA;
 
static LRESULT CALLBACK
ProgressBarCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
int WINAPI MwRegisterProgressBarControl(HINSTANCE hInstance)
{
WNDCLASS wc;
 
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
wc.lpfnWndProc = (WNDPROC)ProgressBarCtrlProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/
wc.hbrBackground= GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= "PROGBAR";
 
return RegisterClass(&wc);
}
 
static void
FillBox(HDC hdc, int x, int y, int w, int h, COLORREF cr)
{
RECT rc;
 
if (w <= 0)
return;
SetRect(&rc, x, y, x+w, y+h);
FastFillRect(hdc, &rc, cr);
}
 
static int
GetSysCharWidth(HDC hdc)
{
int cw, ch, cb;
 
GdGetTextSize(hdc->font->pfont,"X",1, &cw,&ch,&cb,MWTF_ASCII);
return cw;
}
 
static int
GetSysCharHeight(HDC hdc)
{
int cw, ch, cb;
 
GdGetTextSize(hdc->font->pfont,"X",1, &cw,&ch,&cb,MWTF_ASCII);
return ch;
}
 
void pbarOnDraw (HWND hwnd, HDC hdc, PROGRESSDATA* pData, BOOL fVertical,
BOOL fErase)
{
int x, y, w, h;
unsigned int nAllPart;
unsigned int nNowPart;
int whOne, nRem;
int ix, iy;
int i;
int step;
COLORREF cr;
RECT rcClient;
char szText[8];
if (!hdc || (pData->nMax == pData->nMin))
return;
if ((pData->nMax - pData->nMin) > 5)
step = 5;
else
step = 1;
 
GetClientRect (hwnd, &rcClient);
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
 
x = rcClient.left + WIDTH_PBAR_BORDER;
y = rcClient.top + WIDTH_PBAR_BORDER;
w = (rcClient.right - rcClient.left) - (WIDTH_PBAR_BORDER << 1);
h = (rcClient.bottom - rcClient.top) - (WIDTH_PBAR_BORDER << 1);
 
nAllPart = (pData->nMax - pData->nMin) / step;
nNowPart = (pData->nPos - pData->nMin) / step;
if (fVertical) {
whOne = h / nAllPart;
nRem = h % nAllPart;
} else {
whOne = w / nAllPart;
nRem = w % nAllPart;
}
if (fErase)
FillBox (hdc, x, y, w, h, GetSysColor(COLOR_BTNSHADOW));
 
if(whOne >= 4) {
if (fVertical) {
for (i = 0, iy = y + h - 1; i < nNowPart; ++i) {
#if 0
if ((iy - whOne) < y)
whOne = iy - y;
#endif
 
FillBox (hdc, x, iy - whOne, w, whOne - 1, BLUE);
 
iy -= whOne + 1;
#if 0
if(nRem > 0) {
iy --;
nRem --;
}
#endif
}
}
else {
for (i = 0, ix = x + 1; i < nNowPart; ++i) {
#if 0
if ((ix + whOne) > (x + w))
whOne = x + w - ix;
#endif
FillBox (hdc, ix, y, whOne - 1, h, BLUE);
ix += whOne + 1;
#if 0
if(nRem > 0) {
ix ++;
nRem --;
}
#endif
}
}
}
else {
/* no vertical support */
int d = nNowPart*100/nAllPart;
int maxw = GetSysCharWidth (hdc) << 2;
int charh = GetSysCharHeight (hdc);
 
if (d > 50)
cr = BLUE;
else
cr = GetSysColor(COLOR_BTNSHADOW);
FillBox (hdc, x + ((w - maxw)>>1), y + ((h - charh) > 1), maxw,
charh - 1, cr);
FillBox (hdc, x, y, (int)((long)w*d/100L), h, BLUE);
SetTextColor (hdc, WHITE);
SetBkMode (hdc, TRANSPARENT);
sprintf (szText, "%d%%", d);
TextOut (hdc, x + ((w - GetSysCharWidth (hdc) * strlen (szText) )>>1),
y + ((h - GetSysCharHeight(hdc) )>>1),
szText, strlen(szText));
}
}
 
static void pbarNormalizeParams (const HWND pCtrl,
PROGRESSDATA* pData, BOOL fNotify)
{
if (pData->nPos > pData->nMax) {
if (fNotify)
SendMessage (GetParent ((HWND)pCtrl), WM_COMMAND,
(WPARAM)MAKELONG (pCtrl->id, PBN_REACHMAX), (LPARAM)pCtrl);
pData->nPos = pData->nMax;
}
 
if (pData->nPos < pData->nMin) {
if (fNotify)
SendMessage (GetParent ((HWND)pCtrl), WM_COMMAND,
(WPARAM)MAKELONG (pCtrl->id, PBN_REACHMIN), (LPARAM)pCtrl);
pData->nPos = pData->nMin;
}
}
 
static LRESULT CALLBACK
ProgressBarCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HWND pCtrl;
PROGRESSDATA* pData;
BOOL fErase;
RECT rc;
PAINTSTRUCT ps;
int pos;
pCtrl = hwnd;
switch (message)
{
case WM_CREATE:
if (!(pData = malloc (sizeof (PROGRESSDATA)))) {
fprintf(stderr, "Create progress bar control failure!\n");
return -1;
}
#if TEST
pData->nMax = 1000;
pData->nMin = 0;
pData->nPos = 500;
pData->nStepInc = 100;
#else
pData->nMax = 100;
pData->nMin = 0;
pData->nPos = 0;
pData->nStepInc = 10;
#endif
 
pCtrl->userdata = (DWORD)pData;
break;
case WM_DESTROY:
free ((void *)(pCtrl->userdata));
break;
 
case WM_GETDLGCODE:
return DLGC_STATIC;
 
case WM_NCPAINT:
if(GetWindowLong(hwnd, GWL_STYLE) & WS_BORDER) {
GetWindowRect(hwnd, &rc);
hdc = GetWindowDC(hwnd);
Draw3dBox(hdc, rc.left, rc.top, rc.right-rc.left,
rc.bottom-rc.top, GetSysColor(COLOR_BTNSHADOW),
GetSysColor(COLOR_BTNHIGHLIGHT));
}
break;
 
case WM_PAINT:
hdc = BeginPaint (hwnd,&ps);
pbarOnDraw (hwnd, hdc, (PROGRESSDATA *)pCtrl->userdata,
hwnd->style & PBS_VERTICAL, TRUE);
EndPaint (hwnd, &ps);
break;
 
case PBM_SETRANGE:
pData = (PROGRESSDATA *)pCtrl->userdata;
pData->nMin = min (wParam, lParam);
pData->nMax = max (wParam, lParam);
if (pData->nPos > pData->nMax)
pData->nPos = pData->nMax;
if (pData->nPos < pData->nMin)
pData->nPos = pData->nMin;
break;
case PBM_SETSTEP:
pData = (PROGRESSDATA *)pCtrl->userdata;
pData->nStepInc = wParam;
break;
case PBM_SETPOS:
pData = (PROGRESSDATA *)pCtrl->userdata;
if (pData->nPos == wParam)
break;
 
fErase = (wParam < pData->nPos);
pData->nPos = wParam;
pbarNormalizeParams (pCtrl, pData, hwnd->style & PBS_NOTIFY);
InvalidateRect(hwnd, NULL, fErase);
break;
case PBM_DELTAPOS:
pData = (PROGRESSDATA *)pCtrl->userdata;
 
if (wParam == 0)
break;
fErase = (wParam < 0);
pData->nPos += wParam;
pbarNormalizeParams (pCtrl, pData, hwnd->style & PBS_NOTIFY);
InvalidateRect(hwnd, NULL, fErase);
break;
case PBM_STEPIT:
pData = (PROGRESSDATA *)pCtrl->userdata;
if (pData->nStepInc == 0)
break;
 
fErase = (pData->nStepInc < 0);
pData->nPos += pData->nStepInc;
pbarNormalizeParams (pCtrl, pData, hwnd->style & PBS_NOTIFY);
InvalidateRect(hwnd, NULL, fErase);
break;
#if TEST
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
pData = (PROGRESSDATA *)pCtrl->userdata;
pos = pData->nPos;
pos += pData->nStepInc;
if (pos > pData->nMax)
pos = pData->nMin;
SendMessage(hwnd, PBM_SETPOS, pos, 0L);
break;
#endif
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
/Makefile
0,0 → 1,50
##############################################################################
# Microwindows template Makefile
# Copyright (c) 2000 Martin Jolicoeur, Greg Haerr
##############################################################################
 
ifndef TOP
TOP = ../..
CONFIG = $(TOP)/config
endif
 
include $(CONFIG)
 
######################## Additional Flags section ############################
 
# Directories list for header files
INCLUDEDIRS +=
# Defines for preprocessor
DEFINES +=
 
# Compilation flags for C files OTHER than include directories
CFLAGS +=
# Preprocessor flags OTHER than defines
CPPFLAGS +=
# Linking flags
LDFLAGS +=
 
############################# targets section ################################
 
ifeq ($(MICROWIN), Y)
 
# If you want to create a library with the objects files, define the name here
LIBNAME = libmwinlib.a
LIBNAMESO = libmwinlib.so
 
# List of objects to compile
OBJS = draw3d.o ptinsid.o insetr.o fastfill.o graph3d.o mwuser.o
 
ifneq ($(ARCH), ELKS)
OBJS += button.o edit.o listbox.o progbar.o static.o combobox.o caret.o \
scrlbar.o medit.o
endif
 
endif
 
######################### Makefile.rules section #############################
 
include $(TOP)/Makefile.rules
 
######################## Tools targets section ###############################
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.