--- /dev/null
+<directory name="solitaire">
+ <xi:include href="solitaire/solitaire.xml" />
+</directory>
+
+<directory name="winemine">
+ <xi:include href="winemine/winemine.xml" />
+</directory>
--- /dev/null
+Solitaire for ReactOS\r
+\r
+/*****************************************\r
+A complete working example of the CardLib \r
+card-game library.\r
+\r
+Freeware\r
+Copyright J Brown 2001\r
+\r
+Updates at http://www.catch22.net\r
+\r
+******************************************/\r
+\r
+The author has given permission to use these sources\r
+under Public Domain. Do what thou will but please give\r
+credit where credit is due.\r
+\r
+If you wish to use cardlib to write another card game\r
+for ReactOS please make cardlib a static lib.\r
+\r
+-sedwards\r
+\r
--- /dev/null
+//
+// CardLib - Card class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+
+#ifndef _CARD_INCLUDED
+#define _CARD_INCLUDED
+
+enum eSuit { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 };
+enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7,
+ Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 };
+
+inline int MAKE_CARD(int Value, int Suit)
+{
+ if(Value < 1) Value = 1;
+ if(Value == 14) Value = 1;
+ if(Value > 13) Value = 13;
+
+ if(Suit < 0) Suit = 0;
+ if(Suit > 3) Suit = 3;
+
+ return ((Value - 1) * 4 + Suit);
+}
+
+class Card
+{
+ friend class CardStack;
+
+public:
+
+ Card()
+ {
+ nValue = 0; //ace of spades by default
+ fFaceUp = true;
+ }
+
+ Card(int value, int suit) //specify a face value [1-13] and suit [0-3]
+ {
+ nValue = MAKE_CARD(value, suit);
+ fFaceUp = true;
+ }
+
+ Card(int index) //specify a 0-51 index
+ {
+ if(index < 0) index = 0;
+ if(index > 51) index = 51;
+
+ nValue = index;
+ fFaceUp = true;
+ }
+
+ int Suit() const
+ {
+ return (nValue % 4);
+ }
+
+ int LoVal() const
+ {
+ return (nValue / 4) + 1;
+ }
+
+ int HiVal() const
+ {
+ return ((nValue < 4) ? 14 : (nValue / 4) + 1);
+ }
+
+ int Idx() const //unique value (0-51 etc)
+ {
+ return nValue;
+ }
+
+ bool FaceUp() const
+ {
+ return fFaceUp;
+ }
+
+ bool FaceDown() const
+ {
+ return !fFaceUp;
+ }
+
+ void SetFaceUp(bool fTrue)
+ {
+ fFaceUp = fTrue;
+ }
+
+ bool IsBlack() const
+ {
+ return Suit() == 0 || Suit() == 3;
+ }
+
+ bool IsRed() const
+ {
+ return !IsBlack();
+ }
+
+private:
+
+ int nValue;
+ bool fFaceUp;
+};
+
+#endif
--- /dev/null
+//
+// CardLib - Card bitmap support
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include "globals.h"
+#include "cardcolor.h"
+
+#ifndef __REACTOS__
+#pragma comment( lib, "..\\CardLib\\cards16.lib" )
+
+extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR );
+extern "C" void WINAPI FreeLibrary16( HINSTANCE );
+#endif
+
+#define NUMCARDBITMAPS (52+16)
+
+void PaintRect(HDC hdc, RECT *rect, COLORREF col);
+
+void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight)
+{
+ HBITMAP hBitmap;
+ HDC hdcCard = NULL;
+ HANDLE hOld;
+ int i, xpos;
+ int width, height;
+ BITMAP bmp;
+
+ for(i = 0; i < NUMCARDBITMAPS; i++)
+ {
+ //convert into the range used by the cdt_xxx functions
+ int val;
+
+ if(i < 52) val = (i % 4) * 13 + (i/4);
+ else val = i;
+
+ hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1));
+ GetObject(hBitmap, sizeof(bmp), &bmp);
+
+ width = bmp.bmWidth;
+ height = bmp.bmHeight;
+
+ if(i == 0) //if first time through, create BIG bitmap..
+ {
+ HDC hdc = GetDC(0);
+ __hdcCardBitmaps = CreateCompatibleDC(hdc);
+ __hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height);
+ SelectObject(__hdcCardBitmaps, __hbmCardBitmaps);
+
+ hdcCard = CreateCompatibleDC(0);
+
+ ReleaseDC(0, hdc);
+ }
+
+ hOld = SelectObject(hdcCard, hBitmap);
+ BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY);
+ SelectObject(hdcCard, hOld);
+
+ //Now draw a black border around each card...
+ xpos = i*width;
+ MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0);
+ LineTo(__hdcCardBitmaps, xpos+width - 3, 0);
+ LineTo(__hdcCardBitmaps, xpos+width - 1, 2);
+ LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3); //vertical
+ LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1);
+ LineTo(__hdcCardBitmaps, xpos+2, height - 1);
+ LineTo(__hdcCardBitmaps, xpos+0, height - 3);
+ LineTo(__hdcCardBitmaps, xpos+0, 2);
+ LineTo(__hdcCardBitmaps, xpos+2, 0);
+
+ DeleteObject(hBitmap);
+ }
+
+ DeleteDC(hdcCard);
+
+ *pwidth = width;
+ *pheight = height;
+
+}
+
+void LoadCardBitmaps(void)
+{
+ HINSTANCE hCardDll;
+
+
+ //If Windows NT/2000/XP
+ if(GetVersion() < 0x80000000)
+ {
+ hCardDll = LoadLibrary("cards.dll");
+
+ if(hCardDll == 0)
+ {
+ MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);
+ PostQuitMessage(0);
+ return;
+ }
+
+ LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);
+
+ FreeLibrary(hCardDll);
+ }
+#ifndef __REACTOS__
+ //Else, Win9X
+ else
+ {
+ hCardDll = LoadLibrary16("cards.dll");
+
+ if(hCardDll == 0)
+ {
+ MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);
+ PostQuitMessage(0);
+ return;
+ }
+
+ LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);
+
+ FreeLibrary16(hCardDll);
+ }
+#endif
+}
+
+void FreeCardBitmaps()
+{
+ DeleteObject (__hbmCardBitmaps);
+ DeleteDC (__hdcCardBitmaps);
+}
+//
+// Paint a checkered rectangle, with each alternate
+// pixel being assigned a different colour
+//
+static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
+{
+ static WORD wCheckPat[8] =
+ {
+ 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
+ };
+
+ HBITMAP hbmp;
+ HBRUSH hbr, hbrold;
+ COLORREF fgold, bgold;
+
+ hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
+ hbr = CreatePatternBrush(hbmp);
+
+ //UnrealizeObject(hbr);
+
+ SetBrushOrgEx(hdc, rect->left, rect->top, 0);
+
+ hbrold = (HBRUSH)SelectObject(hdc, hbr);
+
+ fgold = SetTextColor(hdc, fg);
+ bgold = SetBkColor(hdc, bg);
+
+ PatBlt(hdc, rect->left, rect->top,
+ rect->right - rect->left,
+ rect->bottom - rect->top,
+ PATCOPY);
+
+ SetBkColor(hdc, bgold);
+ SetTextColor(hdc, fgold);
+
+ SelectObject(hdc, hbrold);
+ DeleteObject(hbr);
+ DeleteObject(hbmp);
+}
+
+void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2)
+{
+ if(bg) *bg = crBase;
+ if(fg) *fg = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140);
+ if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4);
+ if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2);
+}
+
+HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height)
+{
+ HANDLE hold, hpold;
+ HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height);
+
+ HPEN hpfg, hpbg, hpsh, hpsh2;
+
+ RECT rect;
+ COLORREF fg, bg, shadow, shadow2;
+
+ GetSinkCols(col, &fg, &bg, &shadow, &shadow2);
+
+ hold = SelectObject(hdc, hbm);
+
+ //fill with a solid base colour
+ SetRect(&rect, 0,0,width,height);
+ PaintRect(hdc, &rect, MAKE_PALETTERGB(bg));
+
+ //draw the outline
+ hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg));
+ hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg));
+ hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow));
+ hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2));
+
+ hpold = SelectObject(hdc, hpsh);
+ MoveToEx(hdc, 2, 0, NULL);
+ LineTo (hdc, width-3,0);
+ LineTo (hdc, width-1, 2);
+
+ SelectObject(hdc, hpold);
+ hpold = SelectObject(hdc, hpsh2);
+ LineTo (hdc, width-1, height-3); //vertical
+ LineTo (hdc, width-3, height-1);
+ LineTo (hdc, 2, height-1);
+ LineTo (hdc, 0, height-3);
+ SelectObject(hdc, hpold);
+ hpold = SelectObject(hdc, hpsh);
+
+ //MoveToEx( hdc, 0, height-3,0);
+ LineTo (hdc, 0, 2);
+ LineTo (hdc, 2, 0);
+
+ SelectObject(hdc, hpold);
+
+ //draw the highlight (vertical)
+ hpold = SelectObject(hdc, hpfg);
+ MoveToEx(hdc, width - 2, 3, NULL);
+ LineTo (hdc, width - 2, height - 2);
+
+ //(horz)
+ MoveToEx(hdc, width - 3, height-2, NULL);
+ LineTo (hdc, 3, height-2);
+ SelectObject(hdc, hpold);
+
+ //draw the background
+ InflateRect(&rect, -2, -2);
+ DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg));
+
+ //overwrite the top-left background pixel
+ SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg));
+
+ DeleteObject(hpsh);
+ DeleteObject(hpsh2);
+ DeleteObject(hpfg);
+ DeleteObject(hpbg);
+
+
+ return hbm;
+}
+
+
+
+void CopyColor(PALETTEENTRY *pe, COLORREF col)
+{
+ pe->peBlue = GetBValue(col);
+ pe->peGreen = GetGValue(col);
+ pe->peRed = GetRValue(col);
+ pe->peFlags = 0;
+}
+
+HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours)
+{
+ LOGPALETTE *lp;
+ HPALETTE hPalette;
+
+ // Allocate memory for the logical palette
+ lp = (LOGPALETTE *)HeapAlloc(
+ GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours);
+
+ lp->palNumEntries = nNumColours;
+ lp->palVersion = 0x300;
+
+ //copy the colours into the logical palette format
+ for(int i = 0; i < nNumColours; i++)
+ {
+ CopyColor(&lp->palPalEntry[i], cols[i]);
+ }
+
+ // create palette!
+ hPalette = CreatePalette(lp);
+
+ HeapFree(GetProcessHeap(), 0, lp);
+
+ return hPalette;
+}
--- /dev/null
+//
+// CardLib - CardButton class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include <tchar.h>
+
+#include "cardlib.h"
+#include "cardwindow.h"
+#include "cardbutton.h"
+#include "cardcolor.h"
+
+HPALETTE UseNicePalette(HDC, HPALETTE);
+void RestorePalette(HDC, HPALETTE);
+
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
+
+CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,
+ int x, int y, int width, int height)
+
+ : parentWnd(parent), id(Id), uStyle(Style), fVisible(visible), ButtonCallback(0)
+{
+ crText = RGB(255,255,255);
+ crBack = RGB(0, 128, 0);
+
+ xadjust = 0;
+ yadjust = 0;
+ xjustify = 0;
+ yjustify = 0;
+
+ fMouseDown = false;
+ fButtonDown = false;
+
+ hIcon = 0;
+
+ SetText(szText);
+ Move(x, y, width, height);
+
+ mxlock = CreateMutex(0, FALSE, 0);
+
+ hFont = 0;
+}
+
+CardButton::~CardButton()
+{
+ CloseHandle(mxlock);
+}
+
+void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)
+{
+ RECT fill;
+
+ HANDLE hOld;
+
+ HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));
+ HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));
+ HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);
+
+ int x = rect->left;
+ int y = rect->top;
+ int width = rect->right-rect->left - 1;
+ int height = rect->bottom-rect->top - 1;
+
+ SetRect(&fill, x+1, y+1, x+width-1, y+height-1);
+
+ int one = 1;
+
+ if(!fNormal)
+ {
+ x += width;
+ y += height;
+ width = -width;
+ height = -height;
+ one = -1;
+ OffsetRect(&fill, 1, 1);
+ }
+
+ if(fNormal)
+ hOld = SelectObject(hdc, hhi);
+ else
+ hOld = SelectObject(hdc, hhi);
+
+ MoveToEx(hdc, x, y+height, 0);
+ LineTo(hdc, x, y);
+ LineTo(hdc, x+width, y);
+ SelectObject(hdc, hOld);
+
+ hOld = SelectObject(hdc, hbl);
+ LineTo(hdc, x+width, y+height);
+ LineTo(hdc, x-one, y+height);
+ SelectObject(hdc, hOld);
+
+ hOld = SelectObject(hdc, hsh);
+ MoveToEx(hdc, x+one, y+height-one, 0);
+ LineTo(hdc, x+width-one, y+height-one);
+ LineTo(hdc, x+width-one, y);
+ SelectObject(hdc, hOld);
+
+ PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));
+
+ DeleteObject(hhi);
+ DeleteObject(hsh);
+}
+
+void CardButton::Clip(HDC hdc)
+{
+ if(fVisible == false) return;
+
+ ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
+}
+
+void CardButton::Draw(HDC hdc, bool fNormal)
+{
+ SIZE textsize;
+ int x, y; //text x, y
+ int ix, iy; //icon x, y
+ int iconwidth = 0;
+
+ RECT cliprect;
+
+ if(fVisible == 0) return;
+
+ if(hFont == 0)
+ SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ else
+ SelectObject(hdc, hFont);
+
+ GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);
+
+ if(hIcon)
+ {
+ x = rect.left + 32 + 8;
+ }
+ else
+ {
+ if(uStyle & CB_ALIGN_LEFT)
+ {
+ x = rect.left + iconwidth;
+ }
+ else if(uStyle & CB_ALIGN_RIGHT)
+ {
+ x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);
+ }
+ else //centered
+ {
+ x = rect.right - rect.left - iconwidth;
+ x = (x - textsize.cx) / 2;
+ x += rect.left + iconwidth;
+ }
+ }
+
+ y = rect.bottom - rect.top;
+ y = (y - textsize.cy) / 2;
+ y += rect.top;
+
+ //calc icon position..
+ ix = rect.left + 4;
+ iy = rect.top + (rect.bottom-rect.top-32) / 2;
+
+ //if button is pressed, then shift text
+ if(fNormal == false && (uStyle & CB_PUSHBUTTON))
+ {
+ x += 1;
+ y += 1;
+ ix += 1;
+ iy += 1;
+ }
+
+ SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);
+ ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);
+
+ //
+ // Calc icon pos
+ //
+
+ if(hIcon)
+ {
+ ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);
+ }
+
+ if(uStyle & CB_PUSHBUTTON)
+ {
+ DrawRect(hdc, &rect, fNormal);
+
+ SetBkColor(hdc, MAKE_PALETTERGB(crBack));
+ SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
+
+ SelectClipRgn(hdc, 0);
+
+ ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);
+ }
+ else
+ {
+ SetBkColor(hdc, MAKE_PALETTERGB(crBack));
+ SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
+
+ SelectClipRgn(hdc, 0);
+
+ ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
+ }
+
+ if(hIcon)
+ {
+ HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));
+ DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);
+ DeleteObject(hbr);
+ }
+
+}
+
+void CardButton::AdjustPosition(int winwidth, int winheight)
+{
+ int width = rect.right-rect.left;
+ int height = rect.bottom-rect.top;
+
+ width = width & ~0x1;
+
+ switch(xjustify)
+ {
+ case CS_XJUST_NONE:
+ break;
+
+ case CS_XJUST_CENTER: //centered
+ rect.left = (winwidth - (width)) / 2;
+ rect.left += xadjust;
+ rect.right = rect.left+width;
+ break;
+
+ case CS_XJUST_RIGHT: //right-aligned
+ rect.left = winwidth - width;
+ rect.left += xadjust;
+ rect.right = rect.left+width;
+ break;
+ }
+
+ switch(yjustify)
+ {
+ case CS_YJUST_NONE:
+ break;
+
+ case CS_YJUST_CENTER: //centered
+ rect.top = (winheight - (height)) / 2;
+ rect.top += yadjust;
+ rect.bottom = rect.top+height;
+ break;
+
+ case CS_YJUST_BOTTOM: //right-aligned
+ rect.top = winheight - height;
+ rect.top += yadjust;
+ rect.bottom = rect.top+height;
+ break;
+ }
+
+}
+
+int CardButton::OnLButtonDown(HWND hwnd, int x, int y)
+{
+ if((uStyle & CB_PUSHBUTTON) == 0)
+ return 0;
+
+ //make sure that the user is allowed to do something
+ if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
+ {
+ return 0;
+ }
+ else
+ {
+ ReleaseMutex(mxlock);
+ }
+
+ fMouseDown = true;
+ fButtonDown = true;
+
+ Redraw();
+
+ SetCapture(hwnd);
+
+ return 1;
+}
+
+int CardButton::OnMouseMove(HWND hwnd, int x, int y)
+{
+ if(fMouseDown)
+ {
+ bool fOldButtonDown = fButtonDown;
+
+ POINT pt;
+
+ pt.x = x;
+ pt.y = y;
+
+ if(PtInRect(&rect, pt))
+ fButtonDown = true;
+ else
+ fButtonDown = false;
+
+ if(fButtonDown != fOldButtonDown)
+ Redraw();
+ }
+
+ return 0;
+}
+
+int CardButton::OnLButtonUp(HWND hwnd, int x, int y)
+{
+ if(fMouseDown)
+ {
+ fMouseDown = false;
+ fButtonDown = false;
+
+ if(uStyle & CB_PUSHBUTTON)
+ {
+ Redraw();
+ ReleaseCapture();
+ }
+
+ //if have clicked the button
+ if(parentWnd.CardButtonFromPoint(x, y) == this)
+ {
+ if(ButtonCallback)
+ {
+ ButtonCallback(*this);
+ }
+ else
+ {
+ HWND hwnd = (HWND)parentWnd;
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#define _countof(array) (sizeof(array)/sizeof(array[0]))
+
+CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)
+{
+ CardButton *cb;
+
+ if(nNumButtons == MAXBUTTONS)
+ return 0;
+
+ cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);
+ Buttons[nNumButtons++] = cb;
+
+ if(uStyle & CB_PUSHBUTTON)
+ {
+ cb->SetBackColor(CardButton::GetFace(crBackgnd));
+ //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));
+ cb->SetForeColor(RGB(255,255,255));
+ }
+ else
+ {
+ cb->SetBackColor(crBackgnd);
+ cb->SetForeColor(RGB(255,255,255));
+ }
+
+ return cb;
+}
+
+void CardButton::SetText(TCHAR *lpszFormat, ...)
+{
+ int count;
+
+ va_list args;
+ va_start(args, lpszFormat);
+
+ count = wvsprintf(szText, lpszFormat, args);
+ va_end(args);
+}
+
+int CardButton::Id()
+{
+ return id;
+}
+
+void CardButton::Show(bool fShow)
+{
+ fVisible = fShow;
+}
+
+void CardButton::Move(int x, int y, int width, int height)
+{
+ SetRect(&rect, x, y, x+width, y+height);
+}
+
+void CardButton::Redraw()
+{
+ HDC hdc = GetDC((HWND)parentWnd);
+
+ HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);
+
+ Draw(hdc, !fButtonDown);
+
+ RestorePalette(hdc, hOldPal);
+
+ ReleaseDC((HWND)parentWnd, hdc);
+}
+
+void CardButton::SetForeColor(COLORREF cr)
+{
+ crText = cr;
+}
+
+void CardButton::SetBackColor(COLORREF cr)
+{
+ crBack = cr;
+
+ crHighlight = GetHighlight(cr);
+ crShadow = GetShadow(cr);
+
+ //crHighlight = ScaleLumRGB(cr, +0.25);
+ //crShadow = ScaleLumRGB(cr, -0.25);
+}
+
+// Static member
+COLORREF CardButton::GetHighlight(COLORREF crBase)
+{
+ return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);
+}
+
+// Static member
+COLORREF CardButton::GetShadow(COLORREF crBase)
+{
+ return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25);
+}
+
+COLORREF CardButton::GetFace(COLORREF crBase)
+{
+ return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);
+}
+
+void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
+{
+ xadjust = xAdjust;
+ yadjust = yAdjust;
+ xjustify = xJustify;
+ yjustify = yJustify;
+}
+
+void CardButton::SetIcon(HICON hicon, bool fRedraw)
+{
+ hIcon = hicon;
+
+ if(fRedraw)
+ Redraw();
+}
+
+void CardButton::SetFont(HFONT font)
+{
+ //don't delete the existing font..
+ hFont = font;
+}
+
+void CardButton::SetButtonProc(pButtonProc proc)
+{
+ ButtonCallback = proc;
+}
+
+bool CardButton::Lock()
+{
+ DWORD dw = WaitForSingleObject(mxlock, 0);
+
+ if(dw == WAIT_OBJECT_0)
+ return true;
+ else
+ return false;
+}
+
+bool CardButton::UnLock()
+{
+ if(ReleaseMutex(mxlock))
+ return true;
+ else
+ return false;
+}
+
+void CardButton::SetStyle(UINT style)
+{
+ uStyle = style;
+}
+
+UINT CardButton::GetStyle()
+{
+ return uStyle;
+}
--- /dev/null
+#ifndef CARDBUTTON_INCLUDED
+#define CARDBUTTON_INCLUDED
+
+#define MAXBUTTONTEXT 64
+
+#include "cardlib.h"
+
+class CardButton
+{
+ friend class CardWindow;
+
+ //
+ // Constructor is PRIVATE - only a
+ // CardWindow can create buttons!
+ //
+ CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible,
+ int x, int y, int width, int height);
+
+ ~CardButton();
+
+public:
+
+ void SetStyle(UINT uStyle);
+ UINT GetStyle();
+
+ void SetText(TCHAR *fmt, ...);
+ void SetFont(HFONT font);
+
+ void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);
+
+ void SetForeColor(COLORREF cr);
+ void SetBackColor(COLORREF cr);
+
+ void Move(int x, int y, int width, int height);
+ void Show(bool fShow);
+ void Redraw();
+ int Id();
+
+ void SetIcon(HICON hicon, bool fRedraw);
+
+ void SetButtonProc(pButtonProc proc);
+
+ CardWindow &GetCardWindow() { return parentWnd; }
+
+ bool Lock();
+ bool UnLock();
+
+ static COLORREF GetHighlight(COLORREF crBase);
+ static COLORREF GetShadow(COLORREF crBase);
+ static COLORREF GetFace(COLORREF crBase);
+
+private:
+
+ //
+ // Private member functions
+ //
+ void AdjustPosition(int winwidth, int winheight);
+
+ void DrawRect(HDC hdc, RECT *rect, bool fNormal);
+ void Draw(HDC hdc, bool fNormal);
+ void Clip(HDC hdc);
+
+ int OnLButtonDown(HWND hwnd, int x, int y);
+ int OnMouseMove(HWND hwnd, int x, int y);
+ int OnLButtonUp(HWND hwnd, int x, int y);
+
+ //
+ // Private members
+ //
+ CardWindow &parentWnd;
+
+ RECT rect;
+ int id;
+ UINT uStyle;
+ bool fVisible;
+
+ int xadjust;
+ int xjustify;
+ int yadjust;
+ int yjustify;
+
+ HICON hIcon;
+ HFONT hFont;
+
+ TCHAR szText[MAXBUTTONTEXT];
+
+ COLORREF crBack;
+ COLORREF crText;
+ COLORREF crHighlight;
+ COLORREF crShadow;
+ COLORREF crShadow2;
+
+ bool fMouseDown;
+ bool fButtonDown;
+
+ HANDLE mxlock;
+
+ pButtonProc ButtonCallback;
+};
+
+#endif
--- /dev/null
+//
+// Colour support
+//
+#include <windows.h>
+
+#define MakeRGB RGB
+
+#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )
+#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )
+
+inline double fMax(double a, double b)
+{
+ return a < b ? b : a;
+}
+
+inline double fMin(double a, double b)
+{
+ return a < b ? a : b;
+}
+/******************************************************************************
+ FUNCTION: RGBtoHLS
+ PURPOSE: Convert from RGB to HLS
+ IN: RGB color (0xBBGGRR)
+ OUT: Hue, Saturation, Luminance from 0 to 1
+ COPYRIGHT:1995-1997 Robert Mashlan
+ Modified for LabWindows/CVI, 1999 Guillaume Dargaud
+******************************************************************************/
+void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S )
+{
+ double delta;
+ double r = (double)((rgb )&0xFF)/255;
+ double g = (double)((rgb>> 8)&0xFF)/255;
+ double b = (double)((rgb>>16)&0xFF)/255;
+ double cmax = MAX3(r,g,b);
+ double cmin = MIN3(r,g,b);
+ *L=(cmax+cmin)/2.0;
+
+ if(cmax == cmin)
+ {
+ *S = *H = 0; // it's really undefined
+ }
+ else
+ {
+ if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin);
+ else *S = (cmax-cmin)/(2.0-cmax-cmin);
+
+ delta = cmax - cmin;
+
+ if(r == cmax)
+ {
+ *H = (g - b) / delta;
+ }
+ else
+ {
+ if(g == cmax) *H = 2.0 + (b-r) / delta;
+ else *H = 4.0 + (r-g) / delta;
+ }
+ *H /= 6.0;
+ if (*H < 0.0) *H += 1;
+ }
+}
+
+/******************************************************************************
+ FUNCTION: HueToRGB
+ PURPOSE: Convert a hue (color) to RGB
+ COPYRIGHT:1995-1997 Robert Mashlan
+ Modified for LabWindows/CVI, 1999 Guillaume Dargaud
+******************************************************************************/
+double HueToRGB(const double m1, const double m2, double h )
+{
+ if (h<0) h+=1.0;
+ if (h>1) h-=1.0;
+ if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);
+ if (2.0*h < 1 ) return m2;
+ if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
+ return m1;
+}
+
+
+/******************************************************************************
+ FUNCTION: HLStoRGB
+ PURPOSE: Convert from HSL to RGB
+ IN: Hue, Saturation, Luminance from 0 to 1
+ RETURN: RGB color (0xBBGGRR)
+ COPYRIGHT:1995-1997 Robert Mashlan
+ Modified for LabWindows/CVI, 1999 Guillaume Dargaud
+******************************************************************************/
+
+COLORREF HLStoRGB(const double H, const double L, const double S )
+{
+ double r,g,b;
+ double m1, m2;
+
+ if(S == 0)
+ {
+ r = g = b = L;
+ }
+ else
+ {
+ if (L <= 0.5)
+ m2 = L * (1.0 + S);
+ else
+ m2 = L + S - L * S;
+
+ m1 = 2.0 * L - m2;
+
+ r = HueToRGB(m1,m2,H+1.0/3.0);
+ g = HueToRGB(m1,m2,H);
+ b = HueToRGB(m1,m2,H-1.0/3.0);
+ }
+
+ return RGB(r*255, g*255, b*255);
+}
+
+
+
+/******************************************************************************
+ FUNCTION: ColorScaleHSL
+ PURPOSE: Returns the HSL linear interpolated color between 2 colors
+ (more natural looking than RGB interpolation)
+ For instance if the luminance is the same in Col1 and Col2,
+ then the luminance of the result will be the same
+ If Ratio=0, you get Col1,
+ If Ratio=1, you get Col2
+ IN: Col1: low color in hex 0xBBGGRR format
+ Col2: high color in hex 0xBBGGRR format
+ Ratio: 0 for low color, 1 for high color, or in between
+ EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F
+******************************************************************************/
+COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio)
+{
+ static double H1, H2, S1, S2, L1, L2;
+
+ if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
+ else if (Ratio>=1) return Col2;
+
+ RGBtoHLS( Col1, &H1, &L1, &S1);
+ RGBtoHLS( Col2, &H2, &L2, &S2);
+ return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );
+}
+
+
+/******************************************************************************
+ FUNCTION: ColorScaleRGB
+ PURPOSE: Returns the RGB linear interpolated color between 2 colors
+ If Ratio=0, you get Col1,
+ If Ratio=1, you get Col2
+ IN: Col1: low color in hex 0xBBGGRR format
+ Col2: high color in hex 0xBBGGRR format
+ Ratio: 0 for low color, 1 for high color, or in between
+ EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080
+******************************************************************************/
+COLORREF ColorScaleRGB( const COLORREF Col1,
+ const COLORREF Col2,
+ const double Ratio) {
+ int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;
+ int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;
+
+ if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
+ else if (Ratio>=1) return Col2;
+
+/* return RGB(
+ (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
+ (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
+ (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
+ );*/
+
+ /*double r = Ratio;
+ if(Col2 == 0)
+ r = 1-Ratio;
+ else
+ r = 1+Ratio;
+ R1 = (int)(double(R1) * r + 0.5);
+ G1 = (int)(double(G1) * r + 0.5);
+ B1 = (int)(double(B1) * r + 0.5);
+ return RGB(R1,G1,B1);*/
+
+ return RGB(
+ (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
+ (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
+ (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
+ );
+}
+
+
+
+COLORREF ColorDarker(COLORREF col, double ratio)
+{
+ return ColorScaleHSL(col, RGB(0,0,0), ratio);
+}
+
+COLORREF ColorLighter(COLORREF col, double ratio)
+{
+ return ColorScaleHSL(col, RGB(255,255,255), ratio);
+}
+
+//
+// Experimental!!!
+//
+#if 0
+
+typedef enum { Red, Green, Blue };
+
+void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)
+{
+ double mn, mx;
+ int major;
+
+ BYTE red, green, blue;
+
+ red = GetRValue(rgb);
+ green = GetGValue(rgb);
+ blue = GetBValue(rgb);
+
+ if(red < green)
+ {
+ mn = red; mx = green; major = Green;
+ }
+ else
+ {
+ mn = green; mx = red; major = Red;
+ }
+
+ if(blue < mn)
+ {
+ mn = blue;
+ }
+ else if(blue > mx)
+ {
+ mx = blue; major = Blue;
+ }
+
+ if(mn == mx)
+ {
+ *Lum = mn / 255;
+ *Sat = 0;
+ *Hue = 0;
+ }
+ else
+ {
+ *Lum = (mx + mn) / 510;
+
+ if(*Lum <= 0.5)
+ *Sat = (mx-mn) / (mn+mx);
+ else
+ *Sat = (mx-mn) / (510-mn-mx);
+
+ switch(major)
+ {
+ case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;
+ break;
+
+ case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;
+ break;
+
+ case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;
+ break;
+
+ }
+
+ if(*Hue > 360.0)
+ *Hue -= 360.0;
+ }
+}
+
+static BYTE Value(double m1, double m2, double hue)
+{
+
+ if(hue > 360) hue -= 360;
+ else if(hue < 0) hue += 360;
+
+ if(hue < 60)
+ m1 = m1 + (m2 - m1) * hue / 60;
+ else if(hue < 180)
+ m1 = m2;
+ else if(hue < 240)
+ m1 = m1 + (m2 - m1) * (240 - hue) / 60;
+
+ return (BYTE)(m1 * 255);
+}
+
+COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)
+{
+ BYTE red, green, blue;
+
+ if(Sat == 0)
+ {
+ red = green = blue = (BYTE)(Lum * 255);
+ }
+ else
+ {
+ double m1, m2;
+
+ if(Lum <= 0.5)
+ m2 = Lum + Lum * Sat;
+ else
+ m2 = Lum + Sat - Lum * Sat;
+
+ m1 = 2 * Lum - m2;
+
+ red = Value(m1, m2, Hue + 120);
+ green = Value(m1, m2, Hue);
+ blue = Value(m1, m2, Hue - 120);
+ }
+
+ return RGB(red, green, blue);
+}
+
+COLORREF ScaleLumRGB(COLORREF col1, double ratio)
+{
+ double H1, L1, S1;
+
+ RGBtoHLS(col1, &H1, &L1, &S1);
+
+ L1 += L1 * ratio;
+
+ return HLStoRGB(H1, L1, S1);
+}
+
+COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio)
+{
+ static double H1, H2, S1, S2, L1, L2;
+
+ if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1
+ else if(Ratio >= 1) return Col2;
+
+ RGBtoHLS( Col1, &H1, &L1, &S1);
+ RGBtoHLS( Col2, &H2, &L2, &S2);
+
+ return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);
+}
+
+COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)
+{
+ return ColorScaleHSL(Col1, Col2, Ratio);
+}
+#endif
--- /dev/null
+
+COLORREF ColorScaleRGB( const COLORREF Col1,
+ const COLORREF Col2,
+ const double Ratio);
+
+COLORREF ColorScaleHSL( const COLORREF Col1,
+ const COLORREF Col2,
+ const double Ratio);
+
+
+COLORREF ColorDarker(COLORREF col, double ratio);
+COLORREF ColorLighter(COLORREF col, double ratio);
+
+COLORREF ScaleLumRGB(COLORREF col1, double ratio);
+
+#define MAKE_PALETTERGB(colref) (0x02000000 | colref)
--- /dev/null
+//
+// CardCount is a helper library for CardStacks.
+//
+// When you initialize a CardCount object with a
+// cardstack, it keeps track of the number of cards
+// the stack contains.
+//
+// e.g. CardCount count(cardstack);
+//
+// Then you can do:
+//
+// int num_fives = count[5]
+//
+// count.Add(cardstack2); - combine with another stack
+//
+// int num_aces = count[1] - aces low
+// int num_aces = count[14] - aces high
+//
+// count.Clear();
+//
+#include "cardcount.h"
+
+CardCount::CardCount()
+{
+ Clear();
+}
+
+CardCount::CardCount(const CardStack &cs)
+{
+ Init(cs);
+}
+
+void CardCount::Clear()
+{
+ for(int i = 0; i < 13; i++)
+ count[i] = 0;
+}
+
+void CardCount::Add(const CardStack &cs)
+{
+ for(int i = 0; i < cs.NumCards(); i++)
+ {
+ Card card = cs[i];
+
+ int val = card.LoVal();
+ count[val - 1]++;
+ }
+}
+
+void CardCount::Sub(const CardStack &cs)
+{
+ for(int i = 0; i < cs.NumCards(); i++)
+ {
+ Card card = cs[i];
+ int val = card.LoVal();
+
+ if(count[val - 1] > 0)
+ count[val - 1]--;
+ }
+}
+
+void CardCount::Init(const CardStack &cs)
+{
+ Clear();
+ Add(cs);
+}
+
+int CardCount::operator [] (size_t index) const
+{
+ if(index < 1) return 0;
+ else if(index > 14) return 0; //if out of range
+ else if(index == 14) index = 1; //if a "ace-high"
+
+ return count[index - 1];
+}
+
+//
+// Decrement specified item by one
+//
+void CardCount::Dec(size_t index)
+{
+ if(index < 1) return;
+ else if(index > 14) return; //if out of range
+ else if(index == 14) index = 1; //if a "ace-high"
+
+ index -= 1;
+
+ if(count[index] > 0)
+ count[index]--;
+}
--- /dev/null
+#ifndef _CARDCOUNT_INCLUDED
+#define _CARDCOUNT_INCLUDED
+
+#include <windows.h>
+
+#include "cardstack.h"
+
+class CardCount
+{
+public:
+ CardCount();
+ CardCount(const CardStack &cs);
+
+ void Init(const CardStack &cs);
+ void Clear();
+ void Add(const CardStack &cs);
+ void Sub(const CardStack &cs);
+
+ void Dec(size_t index);
+
+ int operator[] (size_t index) const;
+
+ CardCount &operator = (const CardStack &cs);
+ CardCount &operator += (const CardStack &cs);
+
+private:
+ int count[13]; //13 different card values
+ //(ace,2,3,4,5,6,7,8,9,10,J,Q,K)
+};
+
+#endif
--- /dev/null
+//
+// CardLib - not much of interest in here
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include "cardlib.h"
+#include "globals.h"
+
+void LoadCardBitmaps(void);
+
+//static bool __CARDLIB_ACES_HIGH = false;
+extern double __CARDZOOMSPEED;
+
+//
+// Global variables!
+//
+HDC __hdcCardBitmaps;
+HBITMAP __hbmCardBitmaps;
+
+HDC __hdcPlaceHolder;
+HBITMAP __hbmPlaceHolder;
+HPALETTE __holdplacepal;
+
+int __cardwidth;
+int __cardheight;
+
+HPALETTE __hPalette;
+
+
+//
+// Cardlib global functions!
+//
+void CardLib_SetZoomSpeed(int speed)
+{
+ __CARDZOOMSPEED = (double)speed;
+}
+
+/*
+
+ It's dangerous to use these operators, because of all
+ the implicit conversions that could take place, which
+ would have unpredicted side-effects.
+
+ e.g. Card card(Hearts, 4);
+ if(card == 4) - how does 4 get converted??
+ It uses the Card(int uval) constructor,
+ which results in a 2 of clubs...
+ not what was expected
+*/
+/*
+void CardLib_SetAcesHigh(bool fHigh);
+bool operator != (const Card &lhs, const Card &rhs);
+bool operator == (const Card &lhs, const Card &rhs);
+bool operator < (const Card &lhs, const Card &rhs);
+bool operator <= (const Card &lhs, const Card &rhs);
+bool operator > (const Card &lhs, const Card &rhs);
+bool operator >= (const Card &lhs, const Card &rhs);
+*/
+
+/*
+void CardLib_SetAcesHigh(bool fHigh)
+{
+ __CARDLIB_ACES_HIGH = fHigh;
+}
+
+bool operator == (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() == rhs.HiVal();
+ else
+ return lhs.LoVal() == rhs.LoVal();
+}
+
+bool operator != (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() != rhs.HiVal();
+ else
+ return lhs.LoVal() != rhs.LoVal();
+}
+
+bool operator > (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() > rhs.HiVal();
+ else
+ return lhs.LoVal() > rhs.LoVal();
+}
+
+bool operator >= (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() >= rhs.HiVal();
+ else
+ return lhs.LoVal() >= rhs.LoVal();
+}
+
+bool operator < (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() < rhs.HiVal();
+ else
+ return lhs.LoVal() < rhs.LoVal();
+}
+
+bool operator <= (const Card &lhs, const Card &rhs)
+{
+ if(__CARDLIB_ACES_HIGH)
+ return lhs.HiVal() <= rhs.HiVal();
+ else
+ return lhs.LoVal() <= rhs.LoVal();
+}
+*/
+
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour)
+{
+ COLORREF oldcr = SetBkColor(hdc, colour);
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0);
+ SetBkColor(hdc, oldcr);
+}
--- /dev/null
+#ifndef CARDLIB_INCLUDED
+#define CARDLIB_INCLUDED
+
+#define CARDLIBPROC __stdcall
+
+void CardBlt(HDC hdc, int x, int y, int nCardNum);
+void CardLib_SetZoomSpeed(int);
+
+#define CS_EI_NONE 0
+#define CS_EI_SUNK 1
+
+#define CS_DEFXOFF 12 //x-offset
+#define CS_DEFYOFF 18 //y-offset
+#define CS_NO3D 1 //default 3d counts (recommened)
+#define CS_DEF3D 10 //(best for decks)
+
+//#define CS_EI_CIRC 2
+//#define CS_EI_X 3
+
+#define CS_DRAG_NONE 0
+#define CS_DRAG_TOP 1
+#define CS_DRAG_ALL 2
+#define CS_DRAG_CALLBACK 3
+
+#define CS_DROP_NONE 0
+#define CS_DROP_ALL 1
+#define CS_DROP_CALLBACK 2
+
+#define CS_XJUST_NONE 0
+#define CS_XJUST_RIGHT 1
+#define CS_XJUST_CENTER 2
+
+#define CS_YJUST_NONE 0
+#define CS_YJUST_BOTTOM 1
+#define CS_YJUST_CENTER 2
+
+#define CB_STATIC 0 //static text label
+#define CB_PUSHBUTTON 1 //normal button
+#define CB_ALIGN_CENTER 0 //centered is default
+#define CB_ALIGN_LEFT 2
+#define CB_ALIGN_RIGHT 4
+
+#define CS_FACE_UP 0 //all cards face-up
+#define CS_FACE_DOWN 1 //all cards face-down
+#define CS_FACE_DOWNUP 2 //bottom X cards down, top-most face-up
+#define CS_FACE_UPDOWN 3 //bottom X cards up, top-most face-down
+#define CS_FACE_ANY 4 //cards can be any orientation
+
+#define CS_DROPZONE_NODROP -1
+
+//
+// Define the standard card-back indices
+//
+#define ecbCROSSHATCH 53
+#define ecbWEAVE1 54
+#define ecbWEAVE2 55
+#define ecbROBOT 56
+#define ecbFLOWERS 57
+#define ecbVINE1 58
+#define ecbVINE2 59
+#define ecbFISH1 60
+#define ecbFISH2 61
+#define ecbSHELLS 62
+#define ecbCASTLE 63
+#define ecbISLAND 64
+#define ecbCARDHAND 65
+#define ecbUNUSED 66
+#define ecbTHE_X 67
+#define ecbTHE_O 68
+
+
+class CardRegion;
+class CardButton;
+class CardStack;
+class CardWindow;
+
+typedef bool (CARDLIBPROC *pCanDragProc) (CardRegion &stackobj, int iNumDragging);
+typedef bool (CARDLIBPROC *pCanDropProc) (CardRegion &stackobj, const CardStack &cards);
+typedef void (CARDLIBPROC *pClickProc) (CardRegion &stackobj, int iNumCards);
+typedef void (CARDLIBPROC *pAddProc) (CardRegion &stackobj, const CardStack &cards);
+typedef void (CARDLIBPROC *pRemoveProc) (CardRegion &stackobj, int iNumRemoved);
+
+typedef void (CARDLIBPROC *pResizeWndProc) (int width, int height);
+typedef int (CARDLIBPROC *pDropZoneProc) (int dzid, const CardStack &cards);
+
+typedef void (CARDLIBPROC *pButtonProc) (CardButton &pButton);
+
+
+#include "card.h"
+#include "cardbutton.h"
+#include "cardstack.h"
+#include "cardregion.h"
+#include "cardcount.h"
+#include "cardwindow.h"
+
+#ifdef _DEBUG
+typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj);
+void CardLib_SetStackClickProc(pDebugClickProc proc);
+#endif
+
+
+#endif
--- /dev/null
+//
+// CardLib - CardRegion class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+
+#include "cardlib.h"
+#include "cardregion.h"
+#include "cardwindow.h"
+#include "cardcolor.h"
+
+HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height);
+
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
+
+CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset)
+: id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible)
+{
+ width = __cardwidth;
+ height = __cardheight;
+
+ crBackgnd = RGB(0, 64, 100);
+
+ uFaceDirType = CS_FACE_UP;
+ nFaceDirOption = 0;
+ uEmptyImage = CS_EI_SUNK;
+
+ fVisible = visible;
+
+ nThreedCount = 1;
+ nBackCardIdx = 53;
+
+ Update(); //Update this stack's size+card count
+
+ hdcBackGnd = 0;
+ hbmBackGnd = 0;
+ hdcDragCard = 0;
+ hbmDragCard = 0;
+
+ nDragCardWidth = 0;
+ nDragCardHeight = 0;
+
+ CanDragCallback = 0;
+ CanDropCallback = 0;
+ AddCallback = 0;
+ RemoveCallback = 0;
+ ClickCallback = 0;
+ DblClickCallback = 0;
+
+ uDragRule = CS_DRAG_ALL;
+ uDropRule = CS_DROP_ALL;
+
+ xjustify = yjustify = xadjust = yadjust = 0;
+
+ nFlashCount = 0;
+ fFlashVisible = false;
+ uFlashTimer = (UINT)-1;
+
+ fMouseDragging = false;
+
+ mxlock = CreateMutex(0, FALSE, 0);
+}
+
+CardRegion::~CardRegion()
+{
+ CloseHandle(mxlock);
+}
+
+void CardRegion::SetBackColor(COLORREF cr)
+{
+ crBackgnd = cr;
+}
+
+int CardRegion::CalcApparentCards(int realnum)
+{
+ return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount;
+}
+
+void CardRegion::CalcApparentCards()
+{
+ nNumApparentCards = CalcApparentCards(cardstack.NumCards());
+}
+
+
+void CardRegion::UpdateSize(void)
+{
+ if(cardstack.NumCards() > 0)
+ {
+ if(xoffset > 0)
+ width = (nNumApparentCards - 1) * xoffset + __cardwidth;
+ else
+ width = (nNumApparentCards - 1) * -xoffset + __cardwidth;
+
+ if(yoffset > 0)
+ height = (nNumApparentCards - 1) * yoffset + __cardheight;
+ else
+ height = (nNumApparentCards - 1) * -yoffset + __cardheight;
+ }
+ else
+ {
+ width = __cardwidth;
+ height = __cardheight;
+ }
+}
+
+CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset)
+{
+ CardRegion *cr;
+
+ if(nNumCardRegions == MAXCARDSTACKS)
+ return FALSE;
+
+ cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset);
+ cr->SetBackColor(crBackgnd);
+ cr->SetBackCardIdx(nBackCardIdx);
+
+ Regions[nNumCardRegions++] = cr;
+
+ return cr;
+}
+
+int CardRegion::GetOverlapRatio(int x, int y, int w, int h)
+{
+ RECT me, him;
+ RECT inter;
+ SetRect(&him, x, y, x+w, y+h);
+ SetRect(&me, xpos, ypos, xpos+width, ypos+height);
+
+ //see if the specified rectangle overlaps us
+ if(IntersectRect(&inter, &me, &him))
+ {
+ int wi = inter.right - inter.left;
+ int hi = inter.bottom - inter.top;
+
+ int overlap = wi * hi;
+ int total = width * height;
+
+ int percent = (overlap << 16) / total;
+ return (percent * 100) >> 16;
+ }
+ //do not overlap
+ else
+ {
+ return 0;
+ }
+}
+
+bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc)
+{
+ switch(uDragType)
+ {
+ case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP:
+ uDragRule = uDragType;
+ return true;
+
+ case CS_DRAG_CALLBACK:
+ uDragRule = uDragType;
+ CanDragCallback = proc;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc)
+{
+ switch(uDropType)
+ {
+ case CS_DROP_NONE: case CS_DROP_ALL:
+ uDropRule = uDropType;
+ return true;
+
+ case CS_DROP_CALLBACK:
+ uDropRule = uDropType;
+ CanDropCallback = proc;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void CardRegion::SetClickProc(pClickProc proc)
+{
+ ClickCallback = proc;
+}
+
+void CardRegion::SetDblClickProc(pClickProc proc)
+{
+ DblClickCallback = proc;
+}
+
+void CardRegion::SetAddCardProc(pAddProc proc)
+{
+ AddCallback = proc;
+}
+
+void CardRegion::SetRemoveCardProc(pRemoveProc proc)
+{
+ RemoveCallback = proc;
+}
+
+void CardRegion::Update()
+{
+ CalcApparentCards();
+ UpdateSize();
+ UpdateFaceDir(cardstack);
+}
+
+
+bool CardRegion::SetThreedCount(int count)
+{
+ if(count < 1)
+ {
+ return false;
+ }
+ else
+ {
+ nThreedCount = count;
+ return true;
+ }
+}
+
+void CardRegion::SetOffsets(int x, int y)
+{
+ xoffset = x;
+ yoffset = y;
+}
+
+void CardRegion::SetPos(int x, int y)
+{
+ xpos = x;
+ ypos = y;
+}
+
+void CardRegion::Show(bool fShow)
+{
+ fVisible = fShow;
+}
+
+bool CardRegion::IsVisible()
+{
+ return fVisible;
+}
+
+void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
+{
+ xjustify = xJustify;
+ yjustify = yJustify;
+ xadjust = xAdjust;
+ yadjust = yAdjust;
+}
+
+void CardRegion::SetFaceDirection(UINT uDirType, int nOption)
+{
+ switch(uDirType)
+ {
+ case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP:
+ case CS_FACE_UPDOWN: case CS_FACE_ANY:
+ uFaceDirType = uDirType;
+ nFaceDirOption = nOption;
+
+ UpdateFaceDir(cardstack);
+
+ break;
+ }
+}
+
+UINT CardRegion::GetFaceDirection(int *pnOption)
+{
+ if(pnOption)
+ *pnOption = nFaceDirOption;
+
+ return uFaceDirType;
+}
+
+void CardRegion::AdjustPosition(int winwidth, int winheight)
+{
+ Update(); //Update this stack's card count + size
+
+ switch(xjustify)
+ {
+ default: case CS_XJUST_NONE: break;
+
+ case CS_XJUST_CENTER: //centered
+ xpos = (winwidth - (width & ~0x1)) / 2;
+ xpos += xadjust;
+
+ if(xoffset < 0) xpos += (width - __cardwidth);
+
+ break;
+
+ case CS_XJUST_RIGHT: //right-aligned
+ xpos = winwidth - __cardwidth;//width - 20;
+ xpos += xadjust;
+ break;
+ }
+
+ switch(yjustify)
+ {
+ default: case CS_YJUST_NONE: break;
+
+ case CS_YJUST_CENTER: //centered
+ ypos = (winheight - height) / 2;
+ ypos += yadjust;
+ if(yoffset < 0) ypos += (height - __cardheight);
+ break;
+
+ case CS_YJUST_BOTTOM: //bottom-aligned
+ ypos = winheight - __cardheight;//height - 20;
+ ypos += yadjust;
+ break;
+ }
+
+}
+
+
+void CardRegion::Flash(int count, int milliseconds)
+{
+ if(count <= 0) return;
+
+ nFlashCount = count;
+ fFlashVisible = false;
+ uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0);
+
+ parentWnd.Redraw();
+}
+
+void CardRegion::StopFlash()
+{
+ if(uFlashTimer != (UINT)-1)
+ {
+ KillTimer((HWND)parentWnd, uFlashTimer);
+ nFlashCount = 0;
+ uFlashTimer = (UINT)-1;
+ fFlashVisible = true;
+ }
+}
+
+void CardRegion::DoFlash()
+{
+ if(uFlashTimer != (UINT)-1)
+ {
+ fFlashVisible = !fFlashVisible;
+
+ if(--nFlashCount == 0)
+ {
+ KillTimer((HWND)parentWnd, uFlashTimer);
+ uFlashTimer = (UINT)-1;
+ fFlashVisible = true;
+ }
+
+ parentWnd.Redraw();
+ }
+}
+
+int CardRegion::Id()
+{
+ return id;
+}
+
+void CardRegion::SetEmptyImage(UINT uImage)
+{
+ switch(uImage)
+ {
+ case CS_EI_NONE: case CS_EI_SUNK:
+ uEmptyImage = uImage;
+ break;
+
+ default:
+ uEmptyImage = CS_EI_NONE;
+ break;
+ }
+
+}
+
+void CardRegion::SetBackCardIdx(UINT uBackIdx)
+{
+ if(uBackIdx >= 52 && uBackIdx <= 68)
+ nBackCardIdx = uBackIdx;
+}
+
+void CardRegion::SetCardStack(const CardStack &cs)
+{
+ //make a complete copy of the specified stack..
+ cardstack = cs;
+
+ // Update the face-direction and stack-size
+ Update();
+}
+
+const CardStack & CardRegion::GetCardStack()
+{
+ //return reference to our internal stack
+ return cardstack;
+}
+
+//
+// Update specified card-stack using THIS stack's
+// face direction rules!
+//
+void CardRegion::UpdateFaceDir(CardStack &cards)
+{
+ int i, n, num;
+
+ num = cards.NumCards();
+
+ //Now apply the face direction rules..
+ switch(uFaceDirType)
+ {
+ case CS_FACE_UP:
+
+ for(i = 0; i < num; i++)
+ {
+ cards[i].SetFaceUp(true);
+ }
+
+ break;
+
+ case CS_FACE_DOWN:
+
+ for(i = 0; i < num; i++)
+ {
+ cards[i].SetFaceUp(false);
+ }
+
+ break;
+
+ case CS_FACE_DOWNUP:
+
+ num = cardstack.NumCards();
+ n = min(nFaceDirOption, num);
+
+ //bottom n cards..
+ for(i = 0; i < n; i++)
+ {
+ cards[num - i - 1].SetFaceUp(false);
+ }
+
+ for(i = n; i < num; i++)
+ {
+ cards[num - i - 1].SetFaceUp(true);
+ }
+
+ break;
+
+ case CS_FACE_UPDOWN:
+
+ num = cardstack.NumCards();
+ n = min(nFaceDirOption, num);
+
+ for(i = 0; i < n; i++)
+ {
+ cards[num - i - 1].SetFaceUp(true);
+ }
+
+ for(i = n; i < num; i++)
+ {
+ cards[num - i - 1].SetFaceUp(false);
+ }
+
+ break;
+
+ case CS_FACE_ANY: //cards can be any orientation
+ default:
+ break;
+ }
+}
+
+bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate)
+{
+ HDC hdc;
+
+ int x, y;
+
+ if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; }
+
+ if(nNumCards < 0 || nNumCards > cardstack.NumCards())
+ return false;
+
+ x = xpos + xoffset * (nNumApparentCards - nNumCards);
+ y = ypos + yoffset * (nNumApparentCards - nNumCards);
+
+ oldx = x;
+ oldy = y;
+
+ dragstack = cardstack.Pop(nNumCards);
+
+ //Alter the drag-stack so that it's cards are the same way up
+ //as the destination. Use the destination's drag-rules
+ //instead of this ones!!
+ CardStack temp;
+ temp.Push(pDestStack->GetCardStack());
+ temp.Push(dragstack);
+
+ pDestStack->UpdateFaceDir(temp);
+
+ dragstack = temp.Pop(nNumCards);
+
+ if(fAnimate)
+ {
+ iNumDragCards = nNumCards;
+ PrepareDragBitmaps(nNumCards);
+ }
+
+ Update(); //Update this stack's size+card count
+
+ if(fAnimate)
+ {
+ hdc = GetDC((HWND)parentWnd);
+
+ ZoomCard(hdc, x, y, pDestStack);
+
+ ReleaseDC((HWND)parentWnd, hdc);
+ ReleaseDragBitmaps();
+ }
+
+ // Get a copy of the cardstack
+ CardStack cs = pDestStack->GetCardStack();
+ cs.Push(dragstack);
+
+ pDestStack->SetCardStack(cs);
+
+ //cs = pDestStack->GetCardStack();
+ //pDestStack->Update();
+ //pDestStack->UpdateFaceDir(cs);
+
+ RedrawIfNotDim(pDestStack, false);
+
+ //forcedfacedir = -1;
+ return true;
+}
+
+//
+// Simple wrappers
+//
+int CardRegion::NumCards() const
+{
+ if(fMouseDragging)
+ return cardstack.NumCards() + dragstack.NumCards();
+ else
+ return cardstack.NumCards();
+}
+
+bool CardRegion::Lock()
+{
+ DWORD dw = WaitForSingleObject(mxlock, 0);
+
+ if(dw == WAIT_OBJECT_0)
+ {
+ //TRACE("LockStack succeeded\n");
+ return true;
+ }
+ else
+ {
+ //TRACE("LockStack failed\n");
+ return false;
+ }
+ return false;
+}
+
+bool CardRegion::UnLock()
+{
+ if(ReleaseMutex(mxlock))
+ {
+ //TRACE("Unlocking stack\n");
+ return true;
+ }
+ else
+ {
+ //TRACE("Unlocking stack failed\n");
+ return false;
+ }
+}
+
+bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num)
+{
+ //search the stack for the specified card value...
+ while(num--)
+ {
+ for(int i = 0; i < cardstack.NumCards(); i++)
+ {
+ if(cardstack[i].HiVal() == value)
+ {
+ //swap the card with one at top pos...
+ Card card = cardstack.RemoveCard(i);
+ cardstack.Push(card);
+
+ Redraw();
+
+ MoveCard(pDestStack, 1, true);
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+//
+// Redraw the current stack if it has a different
+// layout than the comparison stack.
+//
+void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw)
+{
+ //
+ //
+ //
+ if( pCompare->xoffset != xoffset ||
+ pCompare->yoffset != yoffset ||
+ pCompare->nThreedCount != nThreedCount ||
+ pCompare->uFaceDirType != uFaceDirType ||
+ pCompare->uFaceDirType != CS_FACE_ANY
+ )
+ {
+ if(fFullRedraw)
+ parentWnd.Redraw();
+ else
+ pCompare->Redraw();
+ }
+
+}
+
+//
+// SimulateDrag mimicks the complete drag+drop process.
+// It basically just a MoveCard(..), but it calls the
+// event callbacks as well.
+//
+bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate)
+{
+ if(pDestStack == 0)
+ return false;
+
+ if(CanDragCards(iNumDragCards) != false)
+ {
+ //make a list of the cards that would be in the drag list
+ CardStack tempstack = cardstack.Top(iNumDragCards);
+
+ if(pDestStack->CanDropCards(tempstack))
+ {
+ MoveCard(pDestStack, iNumDragCards, fAnimate);
+
+ if(RemoveCallback)
+ RemoveCallback(*this, iNumDragCards);
+
+ if(pDestStack->AddCallback)
+ pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);
+
+ RedrawIfNotDim(pDestStack, true);
+ }
+
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef CARDREGION_INCLUDED
+#define CARDREGION_INCLUDED
+
+#include "globals.h"
+#include "cardstack.h"
+#include "cardlib.h"
+
+class CardWindow;
+
+//
+// This class defines a physical card-stack,
+// which draws the cards, supports
+//
+
+class CardRegion
+{
+ friend class CardWindow;
+ friend class CardStack;
+
+ //
+ // Constructor is PRIVATE - only
+ // a CardWindow can create cardstacks!
+ //
+ CardRegion(CardWindow &parent, int id, bool fVisible,
+ int x, int y, int xOffset, int yOffset);
+
+ ~CardRegion();
+
+public:
+
+ void SetBackColor(COLORREF cr);
+
+ void SetCardStack(const CardStack &cs);
+ const CardStack & GetCardStack();
+
+ //
+ // Event-callback support
+ //
+ bool SetDragRule(UINT uDragType, pCanDragProc proc = 0);
+ bool SetDropRule(UINT uDropType, pCanDropProc proc = 0);
+
+ void SetClickProc (pClickProc proc);
+ void SetDblClickProc (pClickProc proc);
+
+ void SetAddCardProc (pAddProc proc);
+ void SetRemoveCardProc (pRemoveProc proc);
+
+ //
+ // Physical attribute support
+ //
+ bool SetThreedCount (int count);
+ void SetOffsets (int x, int y);
+ void SetPos (int x, int y);
+ void Show (bool fShow);
+ bool IsVisible ();
+
+ void SetEmptyImage (UINT uImage);
+ void SetBackCardIdx (UINT uBackIdx);
+ void SetPlacement (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);
+
+ void Update();
+ void Redraw();
+
+ void SetFaceDirection(UINT uDirType, int nOption);
+ UINT GetFaceDirection(int *pnOption);
+
+ void Flash(int count, int timeout);
+ void StopFlash();
+
+ int Id();
+
+ CardWindow &GetCardWindow() { return parentWnd; }
+
+ bool PlayCard(CardRegion *pDestStack, int value, int num);
+ bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate);
+ bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate);
+
+ bool Lock();
+ bool UnLock();
+
+ //
+ // Common wrappers for the CardStack object
+ //
+ int NumCards() const;
+ void NewDeck() { cardstack.NewDeck(); }
+ void Shuffle() { cardstack.Shuffle(); }
+ void Clear() { cardstack.Clear(); }
+
+ void Reverse() { cardstack.Reverse(); }
+
+ void Push(const Card card) { cardstack.Push(card); }
+ void Push(const CardStack &cs) { cardstack.Push(cs); }
+
+ Card Pop() { return cardstack.Pop(); }
+ CardStack Pop(int items) { return cardstack.Pop(items); }
+
+ Card Top() { return cardstack.Top(); }
+ CardStack Top(int items) { return cardstack.Top(items); }
+
+
+private:
+
+ void DoFlash();
+ void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw);
+
+ void UpdateFaceDir(CardStack &cards);
+ void Clip(HDC hdc);
+ void Render(HDC hdc);
+ int GetOverlapRatio(int x, int y, int width, int height);
+
+ void MoveDragCardTo(HDC hdc, int x, int y);
+ void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest);
+
+ void RenderBottomMost(HDC hdc, int minustopmost = 0);
+ void PrepareDragBitmaps(int numtodrag);
+ void PrepareDragBitmapsThreed(int numtodrag);
+ void ReleaseDragBitmaps(void);
+
+ bool CanDragCards(int iNumCards);
+ bool CanDropCards(CardStack &cards);
+
+ void CalcApparentCards();
+ int CalcApparentCards(int realnum);
+
+ void UpdateSize();
+ void AdjustPosition(int winwidth, int winheight);
+
+ bool IsPointInStack(int x, int y);
+
+ int GetNumDragCards(int x, int y);
+ bool OnLButtonDown(int x, int y);
+ bool OnLButtonDblClk(int x, int y);
+ bool OnMouseMove(int x, int y);
+ bool OnLButtonUp(int x, int y);
+
+
+ //
+ // Private data members
+ //
+
+ int id;
+
+ CardWindow &parentWnd;
+
+ CardStack cardstack; //cards in this stack
+ CardStack dragstack; //cards which we might be dragging
+
+ bool fMouseDragging;
+
+ int xpos; //coordinates of stack
+ int ypos;
+
+ int xoffset; //direction that cards take
+ int yoffset;
+
+ int width; //stack-size of all cards
+ int height;
+
+ //
+ // justify / placement vars
+ int xjustify;
+ int yjustify;
+ int xadjust;
+ int yadjust;
+
+ //
+ // Used for mouse-dragging / moving cards
+ //
+ int iNumDragCards;
+ int mousexoffset;
+ int mouseyoffset;
+ int oldx;
+ int oldy;
+
+ int nDragCardWidth;
+ int nDragCardHeight;
+
+ HDC hdcBackGnd;
+ HBITMAP hbmBackGnd;
+ HDC hdcDragCard;
+ HBITMAP hbmDragCard;
+
+ int nNumApparentCards;
+ int nThreedCount;
+ bool fVisible;
+
+ int nFlashCount;
+ bool fFlashVisible;
+ UINT uFlashTimer;
+
+ COLORREF crBackgnd;
+
+ UINT uEmptyImage;
+ UINT uFaceDirType;
+ int nFaceDirOption;
+ int nBackCardIdx;
+
+ UINT uDragRule;
+ UINT uDropRule;
+
+ //
+ // Stack callback support
+ //
+ pCanDragProc CanDragCallback;
+ pCanDropProc CanDropCallback;
+ pClickProc ClickCallback;
+ pClickProc DblClickCallback;
+ pAddProc AddCallback;
+ pRemoveProc RemoveCallback;
+
+ //locking mechanism to prevent user dragging etc
+ HANDLE mxlock;
+};
+
+#endif
+
--- /dev/null
+//
+// CardLib - CardRegion drawing support
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include "cardlib.h"
+#include "cardregion.h"
+#include "cardcolor.h"
+
+HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette);
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
+void CardBlt(HDC hdc, int x, int y, int nCardNum);
+void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
+
+//
+// Draw specified card at position x, y
+// xoff - source offset from left of card
+// yoff - source offset from top of card
+// width - width to draw
+// height - height to draw
+//
+void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height)
+{
+ int sx = nCardNum * __cardwidth;
+ int sy = 0;
+ int width = __cardwidth;
+ int height = __cardheight;
+
+ //draw main center band
+ BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY);
+
+ //draw the two bits to the left
+ BitBlt(hdc, x, y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY);
+ BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY);
+
+ //draw the two bits to the right
+ BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY);
+ BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY);
+}
+
+//
+// Draw a shape this this:
+//
+// ++++++++++++
+// ++++++++++++++
+// ++ ++
+//
+void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips)
+{
+ int sx = nCardNum * __cardwidth;
+ int sy = 0;
+ int one = 1;
+ int two = 2;
+ BOOL tips = fDrawTips ? FALSE : TRUE;
+
+ if(height == 0) return;
+
+ if(height < 0)
+ {
+ sy = sy + __cardheight;
+ y -= height;
+ one = -one;
+ two = -two;
+ }
+
+ // draw the main vertical band
+ //
+ BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY);
+
+ //if(height <= 1) return;
+
+ // draw the "lips" at the left and right
+ BitBlt(hdc, x+1, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1, sy+one, SRCCOPY);
+ BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY);
+
+ //if(height <= 2) return;
+
+ // draw the outer-most lips
+ BitBlt(hdc, x, y+two, 1, height-two*tips, __hdcCardBitmaps, sx, sy+two, SRCCOPY);
+ BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY);
+}
+
+//
+// Draw a shape like this:
+//
+// +++
+// +++
+// +++
+// +++
+// +++
+// +++
+// +++
+// +++
+// +++
+// +++
+//
+//
+void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips)
+{
+ int sx = nCardNum * __cardwidth;
+ int sy = 0;
+ int one = 1;
+ int two = 2;
+ BOOL tips = fDrawTips ? FALSE : TRUE;
+
+ if(width == 0) return;
+
+
+ if(width < 0)
+ {
+ sx = sx + __cardwidth;
+ x -= width;
+ one = -1;
+ two = -2;
+ }
+
+ // draw the main vertical band
+ //
+ BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY);
+
+ //if(width <= 1) return;
+
+ // draw the "lips" at the top and bottom
+ BitBlt(hdc, x+one, y+1, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1, SRCCOPY);
+ BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY);
+
+ //if(width <= 2) return;
+
+ // draw the outer-most lips
+ BitBlt(hdc, x+two, y, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy, SRCCOPY);
+ BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY);
+}
+
+//
+// xdir - <0 or >0
+// ydir - <0 or >0
+//
+void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir)
+{
+ int sx = cardval * __cardwidth;
+ int sy = 0;
+
+ HDC hdcSource = __hdcCardBitmaps;
+
+ if(xdir < 0)
+ {
+ x += __cardwidth + xdir - 1;
+ sx += __cardwidth + xdir - 1;
+ }
+ else
+ {
+ x += xdir;
+ sx += xdir;
+ }
+
+ if(ydir < 0)
+ {
+ y += __cardheight + ydir - 1;
+ sy += __cardheight + ydir - 1;
+ }
+ else
+ {
+ y += ydir;
+ sy += ydir;
+ }
+
+ //convert x,y directions to -1, +1
+ xdir = xdir < 0 ? -1 : 1;
+ ydir = ydir < 0 ? -1 : 1;
+
+ SetPixel(hdc, x+xdir, y , GetPixel(hdcSource, sx+xdir, sy));
+ SetPixel(hdc, x, y, GetPixel(hdcSource, sx, sy));
+ SetPixel(hdc, x, y+ydir, GetPixel(hdcSource, sx, sy+ydir));
+
+}
+
+//
+// Draw a card (i.e. miss out the corners)
+//
+void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height)
+{
+ //draw main center band
+ BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY);
+
+ //draw the two bits to the left
+ BitBlt(hdc, x, y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY);
+ BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY);
+
+ //draw the two bits to the right
+ BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY);
+ BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY);
+}
+
+//
+// Clip a card SHAPE - basically any rectangle
+// with rounded corners
+//
+int ClipCard(HDC hdc, int x, int y, int width, int height)
+{
+ ExcludeClipRect(hdc, x+2, y, x+2+width-4, y+ height);
+ ExcludeClipRect(hdc, x, y+2, x+1, y+2+height-4);
+ ExcludeClipRect(hdc, x+1, y+1, x+2, y+1+height-2);
+ ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2);
+ ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4);
+ return 0;
+}
+
+void CardRegion::Clip(HDC hdc)
+{
+ int numtoclip;
+
+ if(fVisible == false)
+ return;
+
+ Update(); //Update this stack's size+card count
+ numtoclip = nNumApparentCards;
+
+ //if we are making this stack flash on/off, then only
+ //clip the stack for drawing if the flash is in its ON state
+ if(nFlashCount != 0)
+ {
+ if(fFlashVisible == FALSE)
+ numtoclip = 0;
+ }
+
+ //if offset along a diagonal
+ if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0)
+ {
+ for(int j = 0; j < numtoclip; j ++)
+ {
+ ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight);
+ }
+ }
+ //otherwise if just offset along a horizontal/vertical axis
+ else
+ {
+ if(yoffset < 0 && numtoclip > 0)
+ {
+ ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height);
+ }
+ else if(xoffset < 0 && numtoclip > 0)
+ {
+ ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height);
+ }
+ else
+ {
+ ClipCard(hdc, xpos, ypos, width, height);
+ }
+ }
+
+}
+
+void CardRegion::Render(HDC hdc)
+{
+ int cardnum = 0;
+ int numtodraw;
+ BOOL fDrawTips;
+
+ Update(); //Update this stack's card count + size
+
+ numtodraw = nNumApparentCards;
+
+ if(nFlashCount != 0)
+ {
+ if(fFlashVisible == false)
+ numtodraw = 0;
+ }
+
+ if(fVisible == 0) return;
+
+ cardnum = cardstack.NumCards() - numtodraw;
+ int counter;
+
+ for(counter = 0; counter < numtodraw; counter++)
+ {
+ int cardval;
+
+ int x = xoffset * counter + xpos;
+ int y = yoffset * counter + ypos;
+
+ //if about to draw last card, then actually draw the top card
+ if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1;
+
+ Card card = cardstack.cardlist[cardnum];
+ cardval = card.Idx();
+
+ if(card.FaceDown())
+ cardval = nBackCardIdx; //card-back
+
+ //only draw the visible part of the card
+ if(counter < numtodraw - 1)
+ {
+ if(yoffset != 0 && xoffset != 0)
+ fDrawTips = FALSE;
+ else
+ fDrawTips = TRUE;
+
+ if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1)
+ fDrawTips = TRUE;
+
+ //draw horizontal strips
+ if(yoffset > 0)
+ {
+ DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips);
+ }
+ else if(yoffset < 0)
+ {
+ DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips);
+ }
+
+ //draw some vertical bars
+ if(xoffset > 0)
+ {
+ DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips);
+ }
+ else if(xoffset < 0)
+ {
+ DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips);
+ }
+
+ if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE)
+ {
+ //if we didn't draw any tips, then this is a 2-dim stack
+ //(i.e, it goes at a diagonal).
+ //in this case, we need to fill in the small triangle in
+ //each corner!
+ DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset);
+ }
+ }
+ //if the top card, draw the whole thing
+ else
+ {
+ CardBlt(hdc, x, y, cardval);
+ }
+
+ cardnum ++;
+
+ } //end of index
+
+ if(counter == 0) //if the cardstack is empty, then draw it that way
+ {
+ int x = xpos;
+ int y = ypos;
+
+ switch(uEmptyImage)
+ {
+ default: case CS_EI_NONE:
+ //this wipes the RECT variable, so watch out!
+ //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);
+ //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
+ parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y);
+ break;
+
+ case CS_EI_SUNK: //case CS_EI_CIRC: case CS_EI_X:
+ DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight);
+ break;
+ }
+
+ }
+
+ return;
+}
+
+int calc_offset(int offset, int numcards, int numtodrag, int realvisible)
+{
+ if(offset >= 0)
+ return -offset * numcards;
+ else
+ return -offset * (numtodrag) +
+ -offset * (realvisible - 1);
+}
+
+void CardRegion::PrepareDragBitmaps(int numtodrag)
+{
+ RECT rect;
+ HDC hdc;
+ int icard;
+ int numcards = cardstack.NumCards();
+ int xoff, yoff;
+
+ if(nThreedCount > 1)
+ {
+ PrepareDragBitmapsThreed(numtodrag);
+ return;
+ }
+
+ //work out how big the bitmaps need to be
+ nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;
+ nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;
+
+ //Create bitmap for the back-buffer
+ hdc = GetDC(NULL);
+ hdcBackGnd = CreateCompatibleDC(hdc);
+ hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
+ SelectObject(hdcBackGnd, hbmBackGnd);
+
+ //Create bitmap for the drag-image
+ hdcDragCard = CreateCompatibleDC(hdc);
+ hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
+ SelectObject(hdcDragCard, hbmDragCard);
+ ReleaseDC(NULL, hdc);
+
+ UseNicePalette(hdcBackGnd, __hPalette);
+ UseNicePalette(hdcDragCard, __hPalette);
+
+ int realvisible = numcards / nThreedCount;
+
+ //if(numcards > 0 && realvisible == 0) realvisible = 1;
+ int iwhichcard = numcards - 1;
+ if(nThreedCount == 1) iwhichcard = 0;
+
+ //grab the first bit of background so we can prep the back buffer; do this by
+ //rendering the card stack (minus the card we are dragging) to the temporary
+ //background buffer, so it appears if we have lifted the card from the stack
+ //PaintRect(hdcBackGnd, &rect, crBackgnd);
+ SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
+
+ xoff = calc_offset(xoffset, numcards, numtodrag, realvisible);
+ yoff = calc_offset(yoffset, numcards, numtodrag, realvisible);
+
+ parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff, ypos - yoff);
+
+ //
+ // Render the cardstack into the back-buffer. The stack
+ // has already had the dragcards removed, so just draw
+ // what is left
+ //
+ for(icard = 0; icard < realvisible; icard++)
+ {
+ Card card = cardstack.cardlist[iwhichcard];
+ int nCardVal;
+
+ nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
+
+ xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
+ yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
+
+ CardBlt(hdcBackGnd, xoff, yoff, nCardVal);
+ iwhichcard++;
+ }
+
+ //
+ // If there are no cards under this one, just draw the place holder
+ //
+ if(numcards == 0)
+ {
+ int xoff = 0, yoff = 0;
+
+ if(xoffset < 0) xoff = nDragCardWidth - __cardwidth;
+ if(yoffset < 0) yoff = nDragCardHeight - __cardheight;
+
+ switch(uEmptyImage)
+ {
+ case CS_EI_NONE:
+ //No need to draw anything: We already cleared the
+ //back-buffer before the main loop..
+
+ //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);
+ //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));
+ //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);
+ break;
+
+ case CS_EI_SUNK:
+ DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight);
+ break;
+ }
+ }
+
+ //
+ // now render the drag-cards into the dragcard image
+ //
+ PaintRect(hdcDragCard, &rect, crBackgnd);
+
+ for(icard = 0; icard < numtodrag; icard++)
+ {
+ int nCardVal;
+
+ if(xoffset >= 0) xoff = xoffset * icard;
+ else xoff = -xoffset * (numtodrag - icard - 1);
+
+ if(yoffset >= 0) yoff = yoffset * icard;
+ else yoff = -yoffset * (numtodrag - icard - 1);
+
+ Card card = dragstack.cardlist[icard];
+
+ nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
+
+ CardBlt(hdcDragCard, xoff, yoff, nCardVal);
+ }
+}
+
+void CardRegion::PrepareDragBitmapsThreed(int numtodrag)
+{
+ RECT rect;
+ HDC hdc;
+ int icard;
+ int numunder = 0;
+ int iwhichcard;
+
+ int numcards = cardstack.NumCards();
+
+ //work out how big the bitmaps need to be
+ nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;
+ nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;
+
+ //Create bitmap for the back-buffer
+ hdc = GetDC(NULL);
+ hdcBackGnd = CreateCompatibleDC(hdc);
+ hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
+ SelectObject(hdcBackGnd, hbmBackGnd);
+
+ //create bitmap for the drag-image
+ hdcDragCard = CreateCompatibleDC(hdc);
+ hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
+ SelectObject(hdcDragCard, hbmDragCard);
+ ReleaseDC(NULL, hdc);
+
+ UseNicePalette(hdcBackGnd, __hPalette);
+ UseNicePalette(hdcDragCard, __hPalette);
+
+ //grab the first bit of background so we can prep the back buffer; do this by
+ //rendering the card stack (minus the card we are dragging) to the temporary
+ //background buffer, so it appears if we have lifted the card from the stack
+ //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
+ //--PaintRect(hdcBackGnd, &rect, crBackgnd);
+
+ int threedadjust = numcards % nThreedCount == 0;
+
+ numunder = CalcApparentCards(numcards);
+ iwhichcard = (numcards+numtodrag) - numunder - 1;
+ if(nThreedCount == 1) iwhichcard = 0;
+
+ int xoff = calc_offset(xoffset, numunder, numtodrag, numunder);
+ int yoff = calc_offset(yoffset, numunder, numtodrag, numunder);
+
+ parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff);
+
+ //
+ // Render the cardstack into the back-buffer. The stack
+ // has already had the dragcards removed, so just draw
+ // what is left
+ //
+ for(icard = 0; icard < numunder; icard++)
+ {
+ Card card = cardstack.cardlist[iwhichcard];
+ int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
+
+ CardBlt(hdcBackGnd,
+ xoffset * icard - xoffset*(numunder-numtodrag+threedadjust),
+ yoffset * icard - yoffset*(numunder-numtodrag+threedadjust),
+ nCardVal);
+
+ iwhichcard++;
+ }
+
+ //
+ // If there are no cards under this one, just draw the place holder
+ //
+ if(numcards == 0)
+ {
+ switch(uEmptyImage)
+ {
+ case CS_EI_NONE:
+ //no need! we've already cleared the whole
+ //back-buffer before the main loop!
+ //SetRect(&rect, 0, 0, __cardwidth, __cardheight);
+ //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));
+ break;
+
+ case CS_EI_SUNK:
+ DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight);
+ break;
+
+ }
+ }
+
+ //
+ // now render the drag-cards into the dragcard image
+ //
+ PaintRect(hdcDragCard, &rect, crBackgnd);
+
+ for(icard = 0; icard < numtodrag; icard++)
+ {
+ Card card = dragstack.cardlist[icard];
+ int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
+
+ CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal);
+ }
+}
+
+void CardRegion::ReleaseDragBitmaps(void)
+{
+ //SelectObject(hdcBackGnd, hOld1);
+ DeleteObject(hbmBackGnd);
+ DeleteDC(hdcBackGnd);
+
+ //SelectObject(hdcDragCard, hOld2);
+ DeleteObject(hbmDragCard);
+ DeleteDC(hdcDragCard);
+}
+
+
+void CardRegion::Redraw()
+{
+ HDC hdc = GetDC((HWND)parentWnd);
+
+ Update();
+ Render(hdc);
+
+ ReleaseDC((HWND)parentWnd, hdc);
+}
--- /dev/null
+//
+// CardLib - CardRegion mouse-related stuff
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "cardlib.h"
+#include "cardwindow.h"
+#include "cardregion.h"
+
+#if 1
+#define TRACE(s)
+#else
+#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
+#endif
+
+double __CARDZOOMSPEED = 32;
+
+int ClipCard(HDC hdc, int x, int y, int width, int height);
+void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
+
+#ifdef _DEBUG
+
+static pDebugClickProc DebugStackClickProc = 0;
+
+void CardLib_SetStackClickProc(pDebugClickProc proc)
+{
+ DebugStackClickProc = proc;
+}
+
+#endif
+
+CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)
+{
+ int maxoverlap = 0;
+ int maxoverlapidx = -1;
+
+ //find the stack which is most covered by the dropped
+ //cards. Only include those which allow drops.
+ //
+ for(int i = 0; i < nNumCardRegions; i++)
+ {
+ int percent = Regions[i]->GetOverlapRatio(x, y, w, h);
+
+ //if this stack has the biggest coverage yet
+ if(percent > maxoverlap && Regions[i]->IsVisible())
+ {
+ maxoverlap = percent;
+ maxoverlapidx = i;
+ }
+ }
+
+ //if we found a stack to drop onto
+ if(maxoverlapidx != -1)
+ {
+ return Regions[maxoverlapidx];
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool CardRegion::IsPointInStack(int x, int y)
+{
+ int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;
+ int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;
+
+ if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)
+ return true;
+ else
+ return false;
+}
+
+int CardRegion::GetNumDragCards(int x, int y)
+{
+ int cardindex = 0; //index from stack start
+ int maxidx;
+
+ //make x,y relative to the stack's upper left corner
+ x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);
+ y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);
+
+ //if stack is empty, cannot drag any cards from it
+ if(cardstack.NumCards() <= 0)
+ return 0;
+
+ //see which card in the stack has been clicked on
+ //top-bottom ordering
+ if(yoffset > 0)
+ {
+ if(y < height - __cardheight)
+ cardindex = y / yoffset;
+ else
+ cardindex = cardstack.NumCards() - 1;
+ }
+ else if(yoffset < 0)
+ {
+ if(y < __cardheight)
+ cardindex = cardstack.NumCards() - 1;
+ else
+ cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;
+ }
+ else //yoffset == 0
+ {
+ cardindex = cardstack.NumCards() - 1;
+ }
+
+ maxidx = cardindex;
+
+ //if left-right
+ if(xoffset > 0)
+ {
+ if(x < width - __cardwidth)
+ cardindex = x / xoffset;
+ else
+ cardindex = cardstack.NumCards() - 1;
+ }
+ else if(xoffset < 0)
+ {
+ if(x < __cardwidth)
+ cardindex = cardstack.NumCards() - 1;
+ else
+ cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;
+ }
+ else
+ {
+ cardindex = cardstack.NumCards() - 1;
+ }
+
+ if(cardindex > maxidx) cardindex = maxidx;
+
+ if(cardindex > cardstack.NumCards())
+ cardindex = 1;
+
+ //if are trying to drag too many cards at once
+ return cardstack.NumCards() - cardindex;
+}
+
+bool CardRegion::CanDragCards(int iNumCards)
+{
+ if(iNumCards <= 0) return false;
+ if(nThreedCount > 1 && iNumCards > 1) return false;
+
+ if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
+ {
+// TRACE("Failed to gain access to card stack\n");
+ return false;
+ }
+
+ ReleaseMutex(mxlock);
+
+ switch(uDragRule)
+ {
+ case CS_DRAG_ALL:
+ return true;
+
+ case CS_DRAG_TOP:
+
+ if(iNumCards == 1)
+ return true;
+ else
+ return false;
+
+ case CS_DRAG_NONE:
+ return false;
+
+ case CS_DRAG_CALLBACK:
+
+ if(CanDragCallback)
+ {
+ return CanDragCallback(*this, iNumCards);
+ }
+ else
+ {
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+bool CardRegion::CanDropCards(CardStack &cards)
+{
+ if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
+ {
+ return false;
+ }
+
+ ReleaseMutex(mxlock);
+
+ switch(uDropRule)
+ {
+ case CS_DROP_ALL:
+ return true;
+
+ case CS_DROP_NONE:
+ return false;
+
+ case CS_DROP_CALLBACK:
+
+ if(CanDropCallback)
+ {
+ return CanDropCallback(*this, cards);
+ }
+ else
+ {
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+bool CardRegion::OnLButtonDblClk(int x, int y)
+{
+ iNumDragCards = GetNumDragCards(x, y);
+
+ if(DblClickCallback)
+ DblClickCallback(*this, iNumDragCards);
+
+ return true;
+}
+
+bool CardRegion::OnLButtonDown(int x, int y)
+{
+ iNumDragCards = GetNumDragCards(x, y);
+
+#ifdef _DEBUG
+ if(DebugStackClickProc)
+ {
+ if(!DebugStackClickProc(*this))
+ return false;
+ }
+#endif
+
+ if(ClickCallback)
+ ClickCallback(*this, iNumDragCards);
+
+ if(CanDragCards(iNumDragCards) != false)
+ {
+
+ //offset of the mouse cursor relative to the top-left corner
+ //of the cards that are being dragged
+ mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);
+ mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);
+
+ if(xoffset < 0)
+ mousexoffset += -xoffset * (iNumDragCards - 1);
+
+ if(yoffset < 0)
+ mouseyoffset += -yoffset * (iNumDragCards - 1);
+
+ //remove the cards from the source stack
+ dragstack = cardstack.Pop(iNumDragCards);
+
+ //prepare the back buffer, and the drag image
+ PrepareDragBitmaps(iNumDragCards);
+
+ oldx = x - mousexoffset;
+ oldy = y - mouseyoffset;
+
+ Update(); //Update this stack's card count + size
+
+ SetCapture((HWND)parentWnd);
+
+ //set AFTER settings the dragstack...
+ fMouseDragging = true;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CardRegion::OnLButtonUp(int x, int y)
+{
+ CardRegion *pDestStack = 0;
+ HDC hdc;
+ int dropstackid = CS_DROPZONE_NODROP;
+
+ RECT dragrect;
+ DropZone *dropzone;
+
+ fMouseDragging = false;
+
+ //first of all, see if any drop zones have been registered
+ SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);
+
+ dropzone = parentWnd.GetDropZoneFromRect(&dragrect);
+
+ if(dropzone)
+ {
+ dropstackid = dropzone->DropCards(dragstack);
+
+ if(dropstackid != CS_DROPZONE_NODROP)
+ pDestStack = parentWnd.CardRegionFromId(dropstackid);
+ else
+ pDestStack = 0;
+ }
+ else
+ {
+ pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);
+ }
+
+ // If have found a stack to drop onto
+ //
+ TRACE ( "can I drop card?\n" );
+ if(pDestStack && pDestStack->CanDropCards(dragstack))
+ {
+ TRACE ( "yes, dropping card\n" );
+ hdc = GetDC((HWND)parentWnd);
+ // UseNicePalette(hdc);
+ ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack);
+ ReleaseDC((HWND)parentWnd, hdc);
+
+ //
+ //add the cards to the destination stack
+ //
+ CardStack temp = pDestStack->GetCardStack();
+ temp.Push(dragstack);
+
+ pDestStack->SetCardStack(temp);
+// pDestStack->Update(); //Update this stack's card count + size
+// pDestStack->UpdateFaceDir(temp);
+
+ // Call the remove callback on THIS stack, if one is specified
+ //
+ if(RemoveCallback)
+ RemoveCallback(*this, iNumDragCards);
+
+ // Call the add callback, if one is specified
+ //
+ if(pDestStack->AddCallback)
+ pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);
+
+ RedrawIfNotDim(pDestStack, true);
+ TRACE ( "done dropping card\n" );
+ }
+
+ //
+ // Otherwise, let the cards snap back onto this stack
+ //
+ else
+ {
+ TRACE ( "no, putting card back\n" );
+ hdc = GetDC((HWND)parentWnd);
+ TRACE ( "calling ZoomCard()\n" );
+ ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);
+ TRACE ( "cardstack += dragstack\n" );
+ cardstack += dragstack;
+ TRACE ( "calling ReleaseDC()\n" );
+ ReleaseDC((HWND)parentWnd, hdc);
+
+ TRACE ( "calling Update()\n" );
+ Update(); //Update this stack's card count + size
+ TRACE ( "done putting card back\n" );
+ }
+
+ ReleaseDragBitmaps();
+ ReleaseCapture();
+
+ TRACE ( "OnLButtonUp() done\n" );
+ return true;
+}
+
+bool CardRegion::OnMouseMove(int x, int y)
+{
+ HDC hdc;
+
+ hdc = GetDC((HWND)parentWnd);
+
+ x -= mousexoffset;
+ y -= mouseyoffset;
+
+ MoveDragCardTo(hdc, x, y);
+
+ //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
+ //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);
+
+ ReleaseDC((HWND)parentWnd, hdc);
+
+ oldx = x;
+ oldy = y;
+
+ return true;
+}
+
+//
+// There is a bug in BitBlt when the source x,y
+// become < 0. So this wrapper function simply adjusts
+// the coords so that we never try to blt in from this range
+//
+BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)
+{
+ if(srcx < 0)
+ {
+ x = 0 - srcx;
+ width = width + srcx;
+ srcx = 0;
+ }
+
+ if(srcy < 0)
+ {
+ y = 0 - srcy;
+ height = height + srcy;
+ srcy = 0;
+ }
+
+ return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);
+}
+
+void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)
+{
+ RECT inter, rect1, rect2;
+
+ //mask off the new position of the drag-card, so
+ //that it will not be painted over
+ ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);
+
+ //restore the area covered by the card at its previous position
+ BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
+
+ //remove clipping so we can draw the card at its new place
+ SelectClipRgn(hdc, NULL);
+
+ //if the card's old and new positions overlap, then we
+ //need some funky code to update the "saved background" image,
+ SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);
+ SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight);
+
+ if(IntersectRect(&inter, &rect1, &rect2))
+ {
+ int interwidth = inter.right-inter.left;
+ int interheight = inter.bottom-inter.top;
+ int destx, desty, srcx, srcy;
+
+ if(rect2.left > rect1.left)
+ {
+ destx = 0; srcx = nDragCardWidth - interwidth;
+ }
+ else
+ {
+ destx = nDragCardWidth - interwidth; srcx = 0;
+ }
+
+ if(rect2.top > rect1.top)
+ {
+ desty = 0; srcy = nDragCardHeight - interheight;
+ }
+ else
+ {
+ desty = nDragCardHeight - interheight; srcy = 0;
+ }
+
+ //shift the bit we didn't use for the restore (due to the clipping)
+ //into the opposite corner
+ BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);
+
+ ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);
+
+ //this bit requires us to clip the BitBlt (from screen to background)
+ //as BitBlt is a bit buggy it seems
+ ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
+ SelectClipRgn(hdcBackGnd, NULL);
+ }
+ else
+ {
+ BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
+ }
+
+ //finally draw the card to the screen
+ DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);
+}
+
+
+//extern "C" int _fltused(void) { return 0; }
+//extern "C" int _ftol(void) { return 0; }
+
+//
+// Better do this in fixed-point, to stop
+// VC from linking in floatingpoint-long conversions
+//
+//#define FIXED_PREC_MOVE
+#ifdef FIXED_PREC_MOVE
+#define PRECISION 12
+void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)
+{
+ long dx, dy, x , y;
+
+
+ int apparentcards;
+ x = xpos << PRECISION; y = ypos << PRECISION;
+
+ oldx = (int)xpos;
+ oldy = (int)ypos;
+
+ apparentcards=dest->numcards/dest->threedcount;
+
+ int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards);
+ int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);
+
+ //normalise the motion vector
+ dx = (idestx<<PRECISION) - x;
+ dy = (idesty<<PRECISION) - y;
+ long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);
+
+ dx *= recip * 16;//CARDZOOMSPEED;
+ dy *= recip * 16;//CARDZOOMSPEED;
+
+ //if(dx < 0) dxinc = 1.001; else
+
+ for(;;)
+ {
+ int ix, iy;
+ x += dx;
+ y += dy;
+
+ ix = (int)x>>PRECISION;
+ iy = (int)y>>PRECISION;
+ if(dx < 0 && ix < idestx) ix = idestx;
+ else if(dx > 0 && ix > idestx) ix = idestx;
+
+ if(dy < 0 && iy < idesty) iy = idesty;
+ else if(dy > 0 && iy > idesty) iy = idesty;
+
+ MoveDragCardTo(hdc, ix, iy);
+
+ if(ix == idestx && iy == idesty)
+ break;
+
+ oldx = (int)x >> PRECISION;
+ oldy = (int)y >> PRECISION;
+
+ //dx *= 1.2;
+ //dy *= 1.2;
+
+ Sleep(10);
+ }
+}
+#else
+void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)
+{
+ TRACE ( "ENTER ZoomCard()\n" );
+ double dx, dy, x ,y;
+ int apparentcards;
+ x = (double)xpos; y = (double)ypos;
+
+ oldx = (int)x;
+ oldy = (int)y;
+
+ apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;
+
+ int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);
+ int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);
+
+ if(pDestStack->yoffset < 0)
+ idesty += pDestStack->yoffset * (iNumDragCards-1);
+
+ if(pDestStack->xoffset < 0)
+ idestx += pDestStack->xoffset * (iNumDragCards-1);
+
+ //normalise the motion vector
+ dx = idestx - x;
+ dy = idesty - y;
+ if ( fabs(dx) + fabs(dy) < 0.001f )
+ {
+ MoveDragCardTo(hdc, idestx, idesty);
+ return;
+ }
+ double recip = 1.0 / sqrt(dx*dx + dy*dy);
+ dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;
+
+ //if(dx < 0) dxinc = 1.001; else
+
+ for(;;)
+ {
+ bool attarget = true;
+ int ix, iy;
+ x += dx;
+ y += dy;
+
+ ix = (int)x;
+ iy = (int)y;
+
+ if(dx < 0.0 && ix < idestx) ix = idestx;
+ else if(dx > 0.0 && ix > idestx) ix = idestx;
+ else attarget = false;
+
+ if(dy < 0.0 && iy < idesty) iy = idesty;
+ else if(dy > 0.0 && iy > idesty) iy = idesty;
+ else attarget = false;
+
+ //if the target stack wants the drag cards drawn differently
+ //to how they are, then redraw the drag card image just before
+ //the cards land
+ /*if(attarget == true)
+ {
+ for(int i = 0; i < iNumDragCards; i++)
+ {
+ int xdraw = pDestStack->xoffset*i;
+ int ydraw = pDestStack->yoffset*i;
+
+ if(pDestStack->yoffset < 0)
+ ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);
+ if(pDestStack->xoffset < 0)
+ xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);
+
+ if(pDestStack->facedirection == CS_FACEUP &&
+ pDestStack->numcards+i >= dest->numfacedown)
+ {
+ //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);
+ }
+ else
+ {
+ //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);
+ }
+ }
+ }*/
+
+ MoveDragCardTo(hdc, ix, iy);
+
+ if(attarget || ix == idestx && iy == idesty)
+ break;
+
+ oldx = (int)x;
+ oldy = (int)y;
+
+ //dx *= 1.2;
+ //dy *= 1.2;
+
+ Sleep(10);
+ }
+ TRACE ( "EXIT ZoomCard()\n" );
+}
+#endif
--- /dev/null
+//
+// CardLib - CardStack class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include <stdlib.h>
+
+#include "cardstack.h"
+
+Card &CardStack::operator[] (size_t index)
+{
+ if(index >= (size_t)nNumCards) index = nNumCards - 1;
+ return cardlist[nNumCards - index - 1];
+}
+
+const Card &CardStack::operator[] (size_t index) const
+{
+ if(index >= (size_t)nNumCards) index = nNumCards - 1;
+ return cardlist[nNumCards - index - 1];
+}
+
+// Subscripting operator for a constant sequence
+//
+/*Card CardStack::operator[] (size_t index) const
+{
+ return cardlist[index];
+}*/
+
+//
+// Subscripting operator for a non-const sequence
+//
+/*CardStack::ref CardStack::operator[] (size_t index)
+{
+ return ref(this, index);
+}*/
+
+void CardStack::Clear()
+{
+ nNumCards = 0;
+}
+
+void CardStack::NewDeck()
+{
+ nNumCards = 52;
+
+ for(int i = 0; i < 52; i++)
+ cardlist[i].nValue = i;
+}
+
+void CardStack::Shuffle()
+{
+ int src, dest;
+ Card temp;
+
+ //shuffle 8 times..
+ for(int i = 0; i < 8; i++)
+ for(dest = nNumCards - 1; dest > 0; dest--)
+ {
+ //want to do this:
+ // bad: src = rand() % (dest + 1)
+ // good: src = rand() / (RAND_MAX / (dest+1) + 1)
+
+ //positions from 0 to dest
+ src = rand() / (RAND_MAX / (dest+1) + 1);
+
+ //swap the cards
+ temp = cardlist[src];
+ cardlist[src] = cardlist[dest];
+ cardlist[dest] = temp;
+ }
+}
+
+void CardStack::Reverse()
+{
+ for(int i = 0; i < nNumCards / 2; i++)
+ {
+ Card temp = cardlist[i];
+ cardlist[i] = cardlist[nNumCards - i - 1];
+ cardlist[nNumCards - i - 1] = temp;
+ }
+}
+
+void CardStack::Push(const Card card)
+{
+ if(nNumCards < MAX_CARDSTACK_SIZE)
+ cardlist[nNumCards++] = card;
+}
+
+void CardStack::Push(const CardStack &cardstack)
+{
+ if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE)
+ {
+ int num = cardstack.NumCards();
+
+ for(int i = 0; i < num; i++)
+ cardlist[nNumCards++] = cardstack.cardlist[i];
+ }
+}
+
+CardStack& CardStack::operator += (Card card)
+{
+ Push(card);
+ return *this;
+}
+
+CardStack& CardStack::operator += (CardStack &cs)
+{
+ Push(cs);
+ return *this;
+}
+
+CardStack CardStack::operator + (Card card)
+{
+ CardStack poo = *this;
+ poo.Push(card);
+ return poo;
+}
+
+CardStack CardStack::operator + (CardStack &cs)
+{
+ CardStack poo = *this;
+ poo.Push(cs);
+ return poo;
+}
+
+
+Card CardStack::Pop()
+{
+ if(nNumCards > 0)
+ return cardlist[--nNumCards];
+ else
+ return 0;
+}
+
+CardStack CardStack::Pop(int items)
+{
+ if(items <= nNumCards && nNumCards > 0)
+ {
+ CardStack cs(*this, nNumCards - items);
+
+ nNumCards -= items;
+
+ return cs;
+ }
+ else
+ {
+ return CardStack();
+ }
+}
+
+Card CardStack::Top()
+{
+ if(nNumCards > 0)
+ return cardlist[nNumCards - 1];
+ else
+ return 0;
+}
+
+CardStack CardStack::Top(int items)
+{
+ if(items <= nNumCards && nNumCards > 0)
+ {
+ return CardStack (*this, nNumCards - items);
+ }
+ else
+ {
+ return CardStack();
+ }
+
+}
+
+Card CardStack::RemoveCard(size_t index)
+{
+ if(nNumCards == 0 || index >= (size_t)nNumCards)
+ return 0;
+
+ //put index into reverse range..
+ index = nNumCards - index - 1;
+
+ Card temp = cardlist[index];
+
+ nNumCards--;
+
+ for(size_t i = index; i < (size_t)nNumCards; i++)
+ {
+ cardlist[i] = cardlist[i+1];
+ }
+
+ return temp;
+}
+
+void CardStack::InsertCard(size_t index, Card card)
+{
+ if(nNumCards == MAX_CARDSTACK_SIZE)
+ return;
+
+ if(index > (size_t)nNumCards)
+ return;
+
+ if((size_t)nNumCards == index)
+ {
+ cardlist[nNumCards] = card;
+ nNumCards++;
+ return;
+ }
+
+ //put index into reverse range..
+ index = nNumCards - index - 1;
+
+ nNumCards++;
+
+ //make room for the card
+ for(size_t i = nNumCards; i > index; i--)
+ {
+ cardlist[i] = cardlist[i - 1];
+ }
+
+ cardlist[index] = card;
+}
+
+
+void CardStack::Print()
+{
+// for(int i = 0; i < nNumCards; i++)
+// cout << cardlist[i].HiVal() << " ";
+}
+
+CardStack::CardStack(CardStack ©this, size_t fromindex)
+{
+ nNumCards = copythis.nNumCards - fromindex;
+
+ for(int i = 0; i < nNumCards; i++)
+ cardlist[i] = copythis.cardlist[fromindex + i];
+}
+
--- /dev/null
+#ifndef CARDSTACK_INCLUDED
+#define CARDSTACK_INCLUDED
+
+#include "card.h"
+
+#define MAX_CARDSTACK_SIZE 128
+
+class CardStack
+{
+ friend class CardRegion;
+
+public:
+ CardStack() : nNumCards(0) { }
+
+ void NewDeck();
+ int NumCards() const { return nNumCards; }
+ void Shuffle();
+ void Clear();
+ void Reverse();
+
+ void Push(const Card card);
+ void Push(const CardStack &cardstack);
+
+ Card Pop();
+ CardStack Pop(int items);
+
+ Card Top();
+ CardStack Top(int items);
+
+ void Print();
+
+ Card RemoveCard(size_t index);
+ void InsertCard(size_t index, Card card);
+
+ //subscript capability!!
+ Card & operator[] (size_t index);
+ const Card & operator[] (size_t index) const;
+
+ CardStack &operator += (Card card);
+ CardStack &operator += (CardStack &cs);
+
+ CardStack operator + (Card card);
+ CardStack operator + (CardStack &cs);
+
+private:
+
+ CardStack(CardStack ©this, size_t fromindex);
+
+ Card cardlist[MAX_CARDSTACK_SIZE];
+ int nNumCards;
+};
+
+#endif
--- /dev/null
+//
+// CardLib - CardWindow class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include <tchar.h>
+
+#include "globals.h"
+#include "cardlib.h"
+#include "cardbutton.h"
+#include "cardregion.h"
+#include "cardwindow.h"
+#include "cardcolor.h"
+
+extern HPALETTE __holdplacepal;
+
+HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette)
+{
+ HPALETTE hOld;
+
+ hOld = SelectPalette(hdc, hPalette, FALSE);
+ RealizePalette(hdc);
+
+ return hOld;
+}
+
+void RestorePalette(HDC hdc, HPALETTE hOldPal)
+{
+ SelectPalette(hdc, hOldPal, TRUE);
+}
+
+HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours);
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
+HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height);
+void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2);
+
+void LoadCardBitmaps();
+void FreeCardBitmaps();
+
+static TCHAR szCardName[] = _T("CardWnd32");
+static bool fRegistered = false;
+static LONG uCardBitmapRef = 0;
+
+
+void RegisterCardWindow()
+{
+ WNDCLASSEX wc;
+
+ //Window class for the main application parent window
+ wc.cbSize = sizeof(wc);
+ wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
+ wc.lpfnWndProc = CardWindow::CardWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(CardWindow *);
+ wc.hInstance = GetModuleHandle(0);
+ wc.hIcon = 0;
+ wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = szCardName;
+ wc.hIconSm = 0;
+
+ RegisterClassEx(&wc);
+}
+
+CardWindow::CardWindow() : m_hWnd(0)
+{
+ HDC hdc = GetDC(0);
+
+ nNumButtons = 0;
+ nNumCardRegions = 0;
+ nNumDropZones = 0;
+ nBackCardIdx = 53;
+
+ ResizeWndCallback = 0;
+ hbmBackImage = 0;
+ hdcBackImage = 0;
+
+ srand((unsigned)GetTickCount());
+
+ //All colours (buttons, highlights, decks)
+ //are calculated off this single base colour
+ crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100);
+
+ // If uCardBitmapRef was previously zero, then
+ // load the card bitmaps
+ if(1 == InterlockedIncrement(&uCardBitmapRef))
+ {
+ LoadCardBitmaps();
+
+ __hPalette = CreateCardPalette();
+
+ __hdcPlaceHolder = CreateCompatibleDC(hdc);
+
+ __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);
+
+ __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
+
+ }
+
+ ReleaseDC(0, hdc);
+
+ //register the window class if necessary
+ if(!fRegistered)
+ {
+ fRegistered = true;
+ RegisterCardWindow();
+ }
+
+}
+
+BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height)
+{
+ if(m_hWnd)
+ return FALSE;
+
+ //Create the window associated with this object
+ m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0,
+ WS_CHILD | WS_VISIBLE,
+ 0,0,100,100,
+ hwndParent, 0, GetModuleHandle(0), this);
+
+ return TRUE;
+}
+
+BOOL CardWindow::Destroy()
+{
+ DestroyWindow(m_hWnd);
+ m_hWnd = 0;
+
+ return TRUE;
+}
+
+CardWindow::~CardWindow()
+{
+ if(m_hWnd)
+ DestroyWindow(m_hWnd);
+
+ DeleteAll();
+
+ if(0 == InterlockedDecrement(&uCardBitmapRef))
+ {
+ FreeCardBitmaps();
+
+ DeleteObject(__hbmPlaceHolder);
+ DeleteDC (__hdcPlaceHolder);
+
+ RestorePalette(__hdcPlaceHolder, __holdplacepal);
+
+ if(__hPalette)
+ DeleteObject(__hPalette);
+ }
+}
+
+bool CardWindow::DeleteAll()
+{
+ int i;
+
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ delete Regions[i];
+ }
+
+ for(i = 0; i < nNumButtons; i++)
+ {
+ delete Buttons[i];
+ }
+
+ for(i = 0; i < nNumDropZones; i++)
+ {
+ delete dropzone[i];
+ }
+
+ nNumCardRegions = nNumButtons = nNumDropZones = 0;
+
+ return true;
+}
+
+void CardWindow::SetBackColor(COLORREF cr)
+{
+ crBackgnd = cr;
+ int i;
+
+ //
+ // Create the exact palette we need to render the buttons/stacks
+ //
+ RestorePalette(__hdcPlaceHolder, __holdplacepal);
+
+ if(__hPalette)
+ DeleteObject(__hPalette);
+
+ __hPalette = CreateCardPalette();
+
+ //
+ // re-create the place-holder!
+ HDC hdc = GetDC(m_hWnd);
+
+ DeleteObject(__hbmPlaceHolder);
+
+ __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);
+
+ __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
+ //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);
+
+ //reset all buttons to same colour
+ for(i = 0; i < nNumButtons; i++)
+ {
+ if(Buttons[i]->GetStyle() & CB_PUSHBUTTON)
+ {
+ Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1));
+ }
+ else
+ {
+ Buttons[i]->SetBackColor(crBackgnd);
+ }
+ }
+
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->SetBackColor(crBackgnd);
+ }
+
+
+ ReleaseDC(m_hWnd, hdc);
+}
+
+COLORREF CardWindow::GetBackColor()
+{
+ return crBackgnd;
+}
+
+CardButton* CardWindow::CardButtonFromPoint(int x, int y)
+{
+ CardButton *bptr = 0;
+
+ POINT pt;
+ pt.x = x;
+ pt.y = y;
+
+ //Search BACKWARDS...to reflect the implicit Z-order that
+ //the button creation provided
+ for(int i = nNumButtons - 1; i >= 0; i--)
+ {
+ bptr = Buttons[i];
+ if(PtInRect(&bptr->rect, pt) && bptr->fVisible)
+ return bptr;
+ }
+
+ return 0;
+}
+
+CardRegion* CardWindow::CardRegionFromPoint(int x, int y)
+{
+ POINT pt;
+ pt.x = x;
+ pt.y = y;
+
+ //Search BACKWARDS...to reflect the implicit Z-order that
+ //the stack creation provided
+ for(int i = nNumCardRegions - 1; i >= 0; i--)
+ {
+ if(Regions[i]->IsPointInStack(x, y))
+ return Regions[i];
+ }
+
+ return 0;
+}
+
+//
+// Forward all window messages onto the appropriate
+// class instance
+//
+LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0);
+ return cw->WndProc(hwnd, iMsg, wParam, lParam);
+}
+
+void CardWindow::Paint(HDC hdc)
+{
+ int i;
+ RECT rect;
+ HPALETTE hOldPal;
+
+ hOldPal = UseNicePalette(hdc, __hPalette);
+
+ //
+ // Clip the card stacks so that they won't
+ // get painted over
+ //
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->Clip(hdc);
+ }
+
+ //
+ // Clip the buttons
+ //
+ for(i = 0; i < nNumButtons; i++)
+ {
+ Buttons[i]->Clip(hdc);
+ }
+
+
+ // Now paint the whole screen with background colour,
+ //
+ GetClientRect(m_hWnd, &rect);
+
+ //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
+ PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0);
+ SelectClipRgn(hdc, NULL);
+
+ // Don't let cards draw over buttons, so clip buttons again
+ //
+ for(i = 0; i < nNumButtons; i++)
+ {
+ Buttons[i]->Clip(hdc);
+ }
+
+ // Paint each card stack in turn
+ //
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->Render(hdc);
+ }
+
+ // Paint each button now
+ //
+ SelectClipRgn(hdc, NULL);
+
+ for(i = 0; i < nNumButtons; i++)
+ {
+ Buttons[i]->Redraw();
+ }
+
+ RestorePalette(hdc, hOldPal);
+}
+
+
+
+
+LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+
+ CREATESTRUCT *cs;
+
+ static CardButton *buttonptr = 0;
+ static CardRegion *stackptr = 0;
+
+ int x, y, i;
+
+ switch(iMsg)
+ {
+ case WM_NCCREATE:
+
+ // When we created this window, we passed in the
+ // pointer to the class object (CardWindow *) in the
+ // call to CreateWindow.
+ cs = (CREATESTRUCT *)lParam;
+
+ //
+ // associate this class with the window
+ //
+ SetWindowLong(hwnd, 0, (LONG)cs->lpCreateParams);
+
+ return 1;
+
+ case WM_NCDESTROY:
+ // Don't delete anything here..
+ break;
+
+ case WM_SIZE:
+ nWidth = LOWORD(lParam);
+ nHeight = HIWORD(lParam);
+
+ //
+ // reposition all the stacks and buttons
+ // in case any of them are centered, right-justified etc
+ //
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->AdjustPosition(nWidth, nHeight);
+ }
+
+ for(i = 0; i < nNumButtons; i++)
+ {
+ Buttons[i]->AdjustPosition(nWidth, nHeight);
+ }
+
+ //
+ // Call the user-defined resize proc AFTER all the stacks
+ // have been positioned
+ //
+ if(ResizeWndCallback)
+ ResizeWndCallback(nWidth, nHeight);
+
+ return 0;
+
+ case WM_PAINT:
+
+ hdc = BeginPaint(hwnd, &ps);
+
+ Paint(hdc);
+
+ EndPaint(hwnd, &ps);
+ return 0;
+
+ case WM_TIMER:
+
+ //find the timer object in the registered funcs
+ /*if(wParam >= 0x10000)
+ {
+ for(i = 0; i < nRegFuncs; i++)
+ {
+ if(RegFuncs[i].id == wParam)
+ {
+ KillTimer(hwnd, wParam);
+
+ //call the registered function!!
+ RegFuncs[i].func(RegFuncs[i].dwParam);
+
+ RegFuncs[i] = RegFuncs[nRegFuncs-1];
+ nRegFuncs--;
+ }
+ }
+ }
+ else*/
+ {
+ //find the cardstack
+ CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam);
+ stackobj->DoFlash();
+ }
+
+ return 0;
+
+ case WM_LBUTTONDBLCLK:
+
+ x = (short)LOWORD(lParam);
+ y = (short)HIWORD(lParam);
+
+ if((buttonptr = CardButtonFromPoint(x, y)) != 0)
+ {
+ buttonptr->OnLButtonDown(hwnd, x, y);
+ return 0;
+ }
+
+ if((stackptr = CardRegionFromPoint(x, y)) != 0)
+ {
+ stackptr->OnLButtonDblClk(x, y);
+ stackptr = 0;
+ }
+
+ return 0;
+
+ case WM_LBUTTONDOWN:
+
+ x = (short)LOWORD(lParam);
+ y = (short)HIWORD(lParam);
+
+ //if clicked on a button
+ if((buttonptr = CardButtonFromPoint(x, y)) != 0)
+ {
+ if(buttonptr->OnLButtonDown(hwnd, x, y) == 0)
+ buttonptr = 0;
+
+ return 0;
+ }
+
+ if((stackptr = CardRegionFromPoint(x, y)) != 0)
+ {
+ if(!stackptr->OnLButtonDown(x, y))
+ stackptr = 0;
+ }
+
+ return 0;
+
+ case WM_LBUTTONUP:
+
+ x = (short)LOWORD(lParam);
+ y = (short)HIWORD(lParam);
+
+ //
+ // if we were clicking a button
+ //
+ if(buttonptr != 0)
+ {
+ buttonptr->OnLButtonUp(hwnd, x, y);
+ buttonptr = 0;
+ return 0;
+ }
+
+ if(stackptr != 0)
+ {
+ stackptr->OnLButtonUp(x, y);
+ stackptr = 0;
+ return 0;
+ }
+
+ return 0;
+
+ case WM_MOUSEMOVE:
+
+ x = (short)LOWORD(lParam);
+ y = (short)HIWORD(lParam);
+
+ // if we were clicking a button
+ if(buttonptr != 0)
+ {
+ buttonptr->OnMouseMove(hwnd, x, y);
+ return 0;
+ }
+
+ if(stackptr != 0)
+ {
+ return stackptr->OnMouseMove(x, y);
+ }
+
+ return 0;
+
+ }
+
+ return DefWindowProc (hwnd, iMsg, wParam, lParam);
+}
+
+
+CardRegion* CardWindow::CardRegionFromId(int id)
+{
+ for(int i = 0; i < nNumCardRegions; i++)
+ {
+ if(Regions[i]->id == id)
+ return Regions[i];
+ }
+
+ return 0;
+}
+
+CardButton* CardWindow::CardButtonFromId(int id)
+{
+ for(int i = 0; i < nNumButtons; i++)
+ {
+ if(Buttons[i]->id == id)
+ return Buttons[i];
+ }
+
+ return 0;
+}
+
+void CardWindow::Redraw()
+{
+ InvalidateRect(m_hWnd, 0, 0);
+ UpdateWindow(m_hWnd);
+}
+
+bool CardWindow::DeleteButton(CardButton *pButton)
+{
+ for(int i = 0; i < nNumButtons; i++)
+ {
+ if(Buttons[i] == pButton)
+ {
+ CardButton *cb = Buttons[i];
+
+ //shift any after this one backwards
+ for(int j = i; j < nNumButtons - 1; j++)
+ {
+ Buttons[j] = Buttons[j + 1];
+ }
+
+ delete cb;
+ nNumButtons--;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CardWindow::DeleteRegion(CardRegion *pRegion)
+{
+ for(int i = 0; i < nNumCardRegions; i++)
+ {
+ if(Regions[i] == pRegion)
+ {
+ CardRegion *cr = Regions[i];
+
+ //shift any after this one backwards
+ for(int j = i; j < nNumCardRegions - 1; j++)
+ {
+ Regions[j] = Regions[j + 1];
+ }
+
+ delete cr;
+ nNumCardRegions--;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CardWindow::EmptyStacks(void)
+{
+ for(int i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->Clear();
+ Regions[i]->Update();
+ }
+
+ Redraw();
+}
+
+bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX)
+{
+ int numvisiblestacks = 0;
+ int curx = nStartX;
+ int startindex = -1;
+ int i;
+
+ //find the stack which starts with our ID
+ for(i = 0; i < nNumCardRegions; i++)
+ {
+ if(Regions[i]->Id() == nIdFrom)
+ {
+ startindex = i;
+ break;
+ }
+ }
+
+ //if didn't find, return
+ if(i == nNumCardRegions) return false;
+
+ //count the stacks that are visible
+ for(i = startindex; i < startindex + nNumStacks; i++)
+ {
+ if(Regions[i]->IsVisible())
+ numvisiblestacks++;
+ }
+
+ if(xJustify == CS_XJUST_CENTER)
+ {
+ //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;
+ int viswidth;
+ viswidth = numvisiblestacks * __cardwidth;
+ viswidth += xSpacing * (numvisiblestacks - 1);
+ curx = -(viswidth - __cardwidth) / 2;
+
+ for(i = startindex; i < startindex + nNumStacks; i++)
+ {
+ if(Regions[i]->IsVisible())
+ {
+ Regions[i]->xadjust = curx;
+ Regions[i]->xjustify = CS_XJUST_CENTER;
+ curx += Regions[i]->width + xSpacing;
+ }
+
+ }
+ }
+
+ if(xJustify == CS_XJUST_RIGHT)
+ {
+ nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing);
+ }
+
+ if(xJustify == CS_XJUST_NONE)
+ {
+ for(i = startindex; i < startindex + nNumStacks; i++)
+ {
+ if(Regions[i]->IsVisible())
+ {
+ Regions[i]->xpos = curx;
+ curx += Regions[i]->width + xSpacing;
+ Regions[i]->UpdateSize();
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+void CardWindow::Update()
+{
+ for(int i = 0; i < nNumCardRegions; i++)
+ {
+ Regions[i]->AdjustPosition(nWidth, nHeight);
+ }
+}
+
+
+void CardWindow::SetResizeProc(pResizeWndProc proc)
+{
+ ResizeWndCallback = proc;
+}
+
+
+HPALETTE CardWindow::CreateCardPalette()
+{
+ COLORREF cols[10];
+ int nNumCols;
+
+
+ //include button text colours
+ cols[0] = RGB(0, 0, 0);
+ cols[1] = RGB(255, 255, 255);
+
+ //include the base background colour
+ cols[1] = crBackgnd;
+
+ //include the standard button colours...
+ cols[3] = CardButton::GetHighlight(crBackgnd);
+ cols[4] = CardButton::GetShadow(crBackgnd);
+ cols[5] = CardButton::GetFace(crBackgnd);
+
+ //include the sunken image bitmap colours...
+ GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]);
+
+ nNumCols = 10;
+
+ return MakePaletteFromCols(cols, nNumCols);
+}
+
+void CardWindow::SetBackCardIdx(UINT uBackIdx)
+{
+ if(uBackIdx >= 52 && uBackIdx <= 68)
+ nBackCardIdx = uBackIdx;
+
+ for(int i = 0; i < nNumCardRegions; i++)
+ Regions[i]->SetBackCardIdx(uBackIdx);
+
+}
+
+void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy)
+{
+ RECT rect;
+
+ //if just a solid background colour
+ if(hbmBackImage == 0)
+ {
+ SetRect(&rect, dx, dy, dx+width, dy+height);
+
+ /*if(GetVersion() < 0x80000000)
+ {
+ PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
+ }
+ else*/
+ {
+ HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd));
+ FillRect(hdc, &rect, hbr);
+ DeleteObject(hbr);
+ }
+ }
+ //otherwise, paint using the bitmap
+ else
+ {
+ // Draw whatever part of background we can
+ BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY);
+
+ // Now we need to paint any area outside the bitmap,
+ // just in case the bitmap is too small to fill whole window
+ if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight)
+ {
+ // Find out size of bitmap
+ BITMAP bm;
+ GetObject(hbmBackImage, sizeof(bm), &bm);
+
+ HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height);
+ HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
+ HRGN hr3 = CreateRectRgn(0,0, 1, 1);
+ HRGN hr4 = CreateRectRgn(0,0, 1, 1);
+
+ CombineRgn(hr3, hr1, hr2, RGN_DIFF);
+
+ GetClipRgn(hdc, hr4);
+
+ CombineRgn(hr3, hr4, hr3, RGN_AND);
+ SelectClipRgn(hdc, hr3);
+
+ // Fill remaining space not filled with bitmap
+ HBRUSH hbr = CreateSolidBrush(crBackgnd);
+ FillRgn(hdc, hr3, hbr);
+ DeleteObject(hbr);
+
+ // Clean up
+ SelectClipRgn(hdc, hr4);
+
+ DeleteObject(hr1);
+ DeleteObject(hr2);
+ DeleteObject(hr3);
+ DeleteObject(hr4);
+ }
+ }
+}
+
+void CardWindow::SetBackImage(HBITMAP hBitmap)
+{
+ //delete current image?? NO!
+ if(hdcBackImage == 0)
+ {
+ hdcBackImage = CreateCompatibleDC(0);
+ }
+
+ hbmBackImage = hBitmap;
+
+ if(hBitmap)
+ SelectObject(hdcBackImage, hBitmap);
+}
--- /dev/null
+#ifndef CARDBOARD_INCLUDED
+#define CARDBOARD_INCLUDED
+
+#define MAXBUTTONS 32
+#define MAXCARDSTACKS 32
+#define MAXDROPZONES 8
+
+#include "dropzone.h"
+#include "cardlib.h"
+
+class CardRegion;
+class CardButton;
+
+LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+class CardWindow
+{
+ friend class CardRegion;
+ friend class CardButton;
+
+ friend void RegisterCardWindow();
+
+public:
+
+ CardWindow();
+ ~CardWindow();
+
+ //
+ // Basic windowing support
+ //
+ BOOL Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height);
+ BOOL Destroy();
+
+ operator HWND() { return m_hWnd; }
+
+ CardButton *CreateButton (int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height);
+ CardRegion *CreateRegion (int id, bool fVisible, int x, int y, int xoffset, int yoffset);
+
+ CardButton *CardButtonFromId(int id);
+ CardRegion *CardRegionFromId(int id);
+
+ bool DeleteButton(CardButton *pButton);
+ bool DeleteRegion(CardRegion *pRegion);
+ bool DeleteAll();
+
+ void SetBackColor(COLORREF cr);
+ COLORREF GetBackColor();
+ void SetBackCardIdx(UINT uBackIdx);
+ void SetBackImage(HBITMAP hBitmap);
+
+ void EmptyStacks(void);
+ void Redraw(void);
+ void Update(void);
+
+ bool DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX);
+ void SetResizeProc(pResizeWndProc proc);
+ int GetWidth() { return nWidth; }
+ int GetHeight() { return nHeight; }
+
+ //
+ // Dropzone support
+ //
+ bool RegisterDropZone(int id, RECT *rect, pDropZoneProc proc);
+ bool DeleteDropZone(int id);
+
+private:
+
+ int GetNumDropZones() { return nNumDropZones; }
+ DropZone* GetDropZoneFromRect(RECT *rect);
+
+ //
+ // Window procedure - don't call
+ //
+ LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+ //
+ // Private functions
+ //
+ void Paint(HDC hdc);
+ void PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy);
+
+ HPALETTE CreateCardPalette();
+
+ CardButton *CardButtonFromPoint(int x, int y);
+ CardRegion *CardRegionFromPoint(int x, int y);
+ CardRegion *GetBestStack(int x, int y, int w, int h);
+
+ //
+ // Private members
+ //
+
+ HWND m_hWnd; //window handle!
+ int nWidth, nHeight;
+
+ UINT nBackCardIdx; //all stacks share this card index by default
+
+ HBITMAP hbmBackImage;
+ HDC hdcBackImage;
+
+
+ CardButton * Buttons[MAXBUTTONS];
+ int nNumButtons;
+
+ CardRegion * Regions[MAXCARDSTACKS];
+ int nNumCardRegions;
+
+ DropZone * dropzone[MAXDROPZONES];
+ int nNumDropZones;
+
+ COLORREF crBackgnd;
+
+ pResizeWndProc ResizeWndCallback;
+
+
+};
+
+
+#endif
--- /dev/null
+//
+// CardLib - DropZone class
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+
+#include "cardlib.h"
+#include "cardwindow.h"
+#include "dropzone.h"
+
+bool CardWindow::RegisterDropZone(int id, RECT *rect, pDropZoneProc proc)
+{
+ if(nNumDropZones == MAXDROPZONES)
+ return false;
+
+ DropZone *dz = new DropZone(id, rect, proc);
+
+ dropzone[nNumDropZones++] = dz;
+
+ return false;
+}
+
+DropZone *CardWindow::GetDropZoneFromRect(RECT *rect)
+{
+ for(int i = 0; i < nNumDropZones; i++)
+ {
+ RECT inter;
+ RECT zone;
+
+ //if any part of the drag rectangle falls within a drop zone,
+ //let that take priority over any other card stack.
+ dropzone[i]->GetZone(&zone);
+
+ if(IntersectRect(&inter, rect, &zone))
+ {
+ //see if the callback wants us to drop a card on
+ //a particular stack
+ return dropzone[i];
+ }
+ }
+
+ return 0;
+}
+
+bool CardWindow::DeleteDropZone(int id)
+{
+ for(int i = 0; i < nNumDropZones; i++)
+ {
+ if(dropzone[i]->id == id)
+ {
+ DropZone *dz = dropzone[i];
+
+ //shift any after this one backwards
+ for(int j = i; j < nNumDropZones - 1; j++)
+ {
+ dropzone[j] = dropzone[j + 1];
+ }
+
+ delete dz;
+ nNumDropZones--;
+ return true;
+ }
+ }
+
+ return false;
+}
+
--- /dev/null
+#ifndef DROPZONE_INCLUDED
+#define DROPZONE_INCLUDED
+
+//
+// define a drop-zone, which can be used to over-ride
+// drop-behaviour for any card stacks which fall under it
+//
+
+class CardStack;
+
+class DropZone
+{
+ friend class CardWindow;
+
+ DropZone(int Id, RECT *rect, pDropZoneProc proc) :
+ id(Id), DropZoneCallback(proc) { CopyRect(&zone, rect); }
+
+public:
+
+ void SetZone(RECT *rect) { CopyRect(&zone, rect); }
+ void GetZone(RECT *rect) { CopyRect(rect, &zone); }
+ void SetCallback(pDropZoneProc callback) { DropZoneCallback = callback; }
+
+ int DropCards(CardStack &cardstack)
+ {
+ if(DropZoneCallback)
+ return DropZoneCallback(id, cardstack);
+ else
+ return -1;
+ }
+
+private:
+
+ int id;
+ RECT zone;
+ pDropZoneProc DropZoneCallback;
+};
+
+#endif
--- /dev/null
+#ifndef GLOBALS_INCLUDED
+#define GLOBALS_INCLUDED
+
+extern int __cardwidth;
+extern int __cardheight;
+
+extern HDC __hdcCardBitmaps;
+extern HBITMAP __hbmCardBitmaps;
+
+extern HDC __hdcPlaceHolder;
+extern HBITMAP __hbmPlaceHolder;
+
+extern HPALETTE __hPalette;
+
+#endif
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Solitaire.rc
+//
+#define IDD_DIALOG1 101
+#define IDR_MENU1 102
+#define IDR_ACCELERATOR1 103
+#define IDI_ICON1 104
+#define IDM_GAME_NEW 40001
+#define IDM_GAME_DECK 40002
+#define IDM_GAME_OPTIONS 40003
+#define IDM_GAME_EXIT 40004
+#define IDM_HELP_CONTENTS 40005
+#define IDM_HELP_ABOUT 40006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40007
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
--- /dev/null
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+/* winemaker: #include "afxres.h" */
+/* winemaker:warning: 'afxres.h' is an MFC specific header. Replacing it with 'winres.h' */
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+ POPUP "&Game"
+ BEGIN
+ MENUITEM "&Deal\tF2", IDM_GAME_NEW
+ MENUITEM SEPARATOR
+ MENUITEM "De&ck...", IDM_GAME_DECK
+ MENUITEM "&Options...", IDM_GAME_OPTIONS
+ MENUITEM SEPARATOR
+ MENUITEM "&Exit", IDM_GAME_EXIT
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Contents\tF1", IDM_HELP_CONTENTS
+ MENUITEM "&About", IDM_HELP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT
+ VK_F2, IDM_GAME_NEW, VIRTKEY, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON DISCARDABLE "icon1.ico"
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+#include <windows.h>
+#include <commctrl.h>
+#include <tchar.h>
+#include "resource.h"
+#include "cardlib/cardlib.h"
+
+#include "solitaire.h"
+
+const int yBorder = 20;
+const int xBorder = 20;
+const int yRowStacks = yBorder + 128;
+
+CardRegion *pDeck;
+CardRegion *pPile;
+CardRegion *pSuitStack[4];
+CardRegion *pRowStack[NUM_ROW_STACKS];
+
+extern CardStack activepile;
+
+HBITMAP hbmBitmap;
+HDC hdcBitmap;
+
+void CreateSol()
+{
+ int i;
+
+// hbmBitmap = (HBITMAP)LoadImage(0,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
+// SolWnd.SetBackImage(hbmBitmap);
+
+ activepile.Clear();
+
+
+ pDeck = SolWnd.CreateRegion(DECK_ID, true, xBorder, yBorder, 2, 1);
+ pDeck->SetEmptyImage(CS_EI_SUNK);
+ pDeck->SetThreedCount(6);
+ pDeck->SetDragRule(CS_DRAG_NONE, 0);
+ pDeck->SetDropRule(CS_DROP_NONE, 0);
+ pDeck->SetClickProc(DeckClickProc);
+ pDeck->SetDblClickProc(DeckClickProc);
+ pDeck->SetFaceDirection(CS_FACE_DOWN, 0);
+
+ pPile = SolWnd.CreateRegion(PILE_ID, true, 110, yBorder, CS_DEFXOFF, 1);
+ pPile->SetEmptyImage(CS_EI_NONE);
+ pPile->SetDragRule(CS_DRAG_TOP, 0);
+ pPile->SetDropRule(CS_DROP_NONE, 0);
+ pPile->SetDblClickProc(PileDblClickProc);
+ pPile->SetRemoveCardProc(PileRemoveProc);
+
+ //
+ // Create the suit stacks
+ //
+ for(i = 0; i < 4; i++)
+ {
+ pSuitStack[i] = SolWnd.CreateRegion(SUIT_ID+i, true, 0, yBorder, 0, 0);
+ pSuitStack[i]->SetEmptyImage(CS_EI_SUNK);
+ //pSuitStack[i]->SetPlacement(CS_XJUST_RIGHT, 0, -i * (__cardwidth + 4) - xBorder, 0);
+ pSuitStack[i]->SetPlacement(CS_XJUST_CENTER, 0, i * (__cardwidth + 10) , 0);
+
+ pSuitStack[i]->SetDropRule(CS_DROP_CALLBACK, SuitStackDropProc);
+ pSuitStack[i]->SetDragRule(CS_DRAG_TOP);
+
+ pSuitStack[i]->SetAddCardProc(SuitStackAddProc);
+ }
+
+ //
+ // Create the row stacks
+ //
+ for(i = 0; i < NUM_ROW_STACKS; i++)
+ {
+ pRowStack[i] = SolWnd.CreateRegion(ROW_ID+i, true, 0, yRowStacks, 0, 14);
+ pRowStack[i]->SetEmptyImage(CS_EI_SUNK);
+ pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);
+
+ pRowStack[i]->SetPlacement(CS_XJUST_CENTER, 0,
+ (i - NUM_ROW_STACKS/2) * (__cardwidth + 10), 0);
+
+ pRowStack[i]->SetEmptyImage(CS_EI_NONE);
+
+ pRowStack[i]->SetDragRule(CS_DRAG_CALLBACK, RowStackDragProc);
+ pRowStack[i]->SetDropRule(CS_DROP_CALLBACK, RowStackDropProc);
+ pRowStack[i]->SetClickProc(RowStackClickProc);
+ pRowStack[i]->SetDblClickProc(RowStackDblClickProc);
+ }
+}
--- /dev/null
+#include <windows.h>
+#include <commctrl.h>
+#include <tchar.h>
+#include <stdio.h>
+#include "resource.h"
+#include "cardlib/cardlib.h"
+//#include "../catch22lib/trace.h"
+#include "solitaire.h"
+
+#if 1
+#define TRACE(s)
+#else
+#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
+#endif
+
+CardStack activepile;
+bool fGameStarted = false;
+
+void NewGame(void)
+{
+ TRACE("ENTER NewGame()\n");
+ int i, j;
+
+ SolWnd.EmptyStacks();
+
+ //create a new card-stack
+ CardStack deck;
+ deck.NewDeck();
+ deck.Shuffle();
+ activepile.Clear();
+
+ //deal to each row stack..
+ for(i = 0; i < NUM_ROW_STACKS; i++)
+ {
+ CardStack temp;
+ temp.Clear();
+
+ pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);
+
+ for(j = 0; j <= i; j++)
+ {
+ temp.Push(deck.Pop());
+ }
+
+ pRowStack[i]->SetCardStack(temp);
+ }
+
+ //put the other cards onto the deck
+ pDeck->SetCardStack(deck);
+ pDeck->Update();
+
+ SolWnd.Redraw();
+
+ fGameStarted = false;
+ TRACE("EXIT NewGame()\n");
+}
+
+//
+// Now follow the stack callback functions. This is where we
+// provide the game functionality and rules
+//
+
+//
+// Can only drag face-up cards
+//
+bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)
+{
+ TRACE("ENTER RowStackDragProc()\n");
+ int numfacedown;
+ int numcards;
+
+ stackobj.GetFaceDirection(&numfacedown);
+
+ numcards = stackobj.NumCards();
+
+ TRACE("EXIT RowStackDragProc()\n");
+ if(iNumDragCards <= numcards-numfacedown)
+ return true;
+ else
+ return false;
+
+}
+
+//
+// Row a row-stack, we can only drop cards
+// that are lower / different colour
+//
+bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
+{
+ TRACE("ENTER RowStackDropProc()\n");
+ Card dragcard = dragcards[dragcards.NumCards() - 1];
+
+ //if we are empty, can only drop a stack with a King at bottom
+ if(stackobj.NumCards() == 0)
+ {
+ if(dragcard.LoVal() != 13)
+ {
+ TRACE("EXIT RowStackDropProc(false)\n");
+ return false;
+ }
+ }
+ else
+ {
+ const CardStack &mystack = stackobj.GetCardStack();
+
+ //can only drop if card is 1 less
+ if(mystack[0].LoVal() != dragcard.LoVal() + 1)
+ {
+ TRACE("EXIT RowStackDropProc(false)\n");
+ return false;
+ }
+
+ //can only drop if card is different colour
+ if( mystack[0].IsBlack() && !dragcard.IsRed() ||
+ !mystack[0].IsBlack() && dragcard.IsRed() )
+ {
+ TRACE("EXIT RowStackDropProc(false)\n");
+ return false;
+ }
+ }
+
+ TRACE("EXIT RowStackDropProc(true)\n");
+ return true;
+}
+
+//
+// Can only drop a card onto a suit-stack if the
+// card is 1 higher, and is the same suit
+//
+bool CanDrop(CardRegion &stackobj, Card card)
+{
+ TRACE("ENTER CanDrop()\n");
+ int topval;
+
+ const CardStack &cardstack = stackobj.GetCardStack();
+
+ if(cardstack.NumCards() > 0)
+ {
+ if(card.Suit() != cardstack[0].Suit())
+ {
+ TRACE("EXIT CanDrop()\n");
+ return false;
+ }
+
+ topval = cardstack[0].LoVal();
+ }
+ else
+ {
+ topval = 0;
+ }
+
+ //make sure 1 higher
+ if(card.LoVal() != (topval + 1))
+ {
+ TRACE("EXIT CanDrop()\n");
+ return false;
+ }
+
+ TRACE("EXIT CanDrop()\n");
+ return true;
+}
+
+//
+// Can only drop a card onto suit stack if it is same suit, and 1 higher
+//
+bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
+{
+ TRACE("ENTER SuitStackDropProc()\n");
+ //only drop 1 card at a time
+ if(dragcards.NumCards() != 1)
+ {
+ TRACE("EXIT SuitStackDropProc()\n");
+ return false;
+ }
+
+ bool b = CanDrop(stackobj, dragcards[0]);
+ TRACE("EXIT SuitStackDropProc()\n");
+ return b;
+}
+
+//
+// Single-click on one of the row-stacks
+// Turn the top-card over if they are all face-down
+//
+void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked)
+{
+ TRACE("ENTER RowStackClickProc()\n");
+ int numfacedown;
+
+ stackobj.GetFaceDirection(&numfacedown);
+
+ //if all face-down, then make top card face-up
+ if(stackobj.NumCards() == numfacedown)
+ {
+ if(numfacedown > 0) numfacedown--;
+ stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown);
+ stackobj.Redraw();
+ }
+ TRACE("EXIT RowStackClickProc()\n");
+}
+
+//
+// Find the suit-stack that can accept the specified card
+//
+CardRegion *FindSuitStackFromCard(Card card)
+{
+ TRACE("ENTER FindSuitStackFromCard()\n");
+ for(int i = 0; i < 4; i++)
+ {
+ if(CanDrop(*pSuitStack[i], card))
+ {
+ TRACE("EXIT FindSuitStackFromCard()\n");
+ return pSuitStack[i];
+ }
+ }
+
+ TRACE("EXIT FindSuitStackFromCard()\n");
+ return 0;
+}
+
+//
+// What happens when we add a card to one of the suit stacks?
+// Well, nothing (it is already added), but we need to
+// check all four stacks (not just this one) to see if
+// the game has finished.
+//
+void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)
+{
+ TRACE("ENTER SuitStackAddProc()\n");
+ bool fGameOver = true;
+
+ for(int i = 0; i < 4; i++)
+ {
+ if(pSuitStack[i]->NumCards() != 13)
+ {
+ fGameOver = false;
+ break;
+ }
+ }
+
+ if(fGameOver)
+ {
+ MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION);
+
+ for(int i = 0; i < 4; i++)
+ {
+ pSuitStack[i]->Flash(11, 100);
+ }
+ }
+ TRACE("EXIT SuitStackAddProc()\n");
+}
+
+//
+// Double-click on one of the row stacks
+// The aim is to find a suit-stack to move the
+// double-clicked card to.
+//
+void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked)
+{
+ TRACE("ENTER RowStackDblClickProc()\n");
+ //can only move 1 card at a time
+ if(iNumClicked != 1)
+ {
+ TRACE("EXIT RowStackDblClickProc()\n");
+ return;
+ }
+
+ //find a suit-stack to move the card to...
+ const CardStack &cardstack = stackobj.GetCardStack();
+ CardRegion *pDest = FindSuitStackFromCard(cardstack[0]);
+
+ if(pDest != 0)
+ {
+ //stackobj.MoveCards(pDest, 1, true);
+ //use the SimulateDrag funcion, because we get the
+ //AddProc callbacks called for us on the destination stacks...
+ stackobj.SimulateDrag(pDest, 1, true);
+ }
+ TRACE("EXIT RowStackDblClickProc()\n");
+}
+
+//
+// Face-up pile double-click
+//
+void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)
+{
+ TRACE("ENTER PileDblClickProc()\n");
+ RowStackDblClickProc(stackobj, iNumClicked);
+ TRACE("EXIT PileDblClickProc()\n");
+}
+
+//
+// What happens when a card is removed from face-up pile?
+//
+void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)
+{
+ TRACE("ENTER PileRemoveProc()\n");
+ //modify our "virtual" pile by removing the same card
+ //that was removed from the physical card stack
+ activepile.Pop(iItems);
+
+ //if there is just 1 card left, then modify the
+ //stack to contain ALL the face-up cards..the effect
+ //will be, the next time a card is dragged, all the
+ //previous card-triplets will be available underneath
+ if(stackobj.NumCards() == 1)
+ {
+ stackobj.SetOffsets(0,0);
+ stackobj.SetCardStack(activepile);
+ }
+ TRACE("EXIT PileRemoveProc()\n");
+}
+
+//
+// Double-click on the deck
+// Move 3 cards to the face-up pile
+//
+void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)
+{
+ TRACE("ENTER DeckClickProc()\n");
+ CardStack cardstack = stackobj.GetCardStack();
+ CardStack pile = pPile->GetCardStack();
+
+ fGameStarted = true;
+
+ //reset the face-up pile to represent 3 cards
+ pPile->SetOffsets(CS_DEFXOFF, 1);
+
+ if(cardstack.NumCards() == 0)
+ {
+ pile.Clear();
+
+ activepile.Reverse();
+ cardstack.Push(activepile);
+ activepile.Clear();
+ }
+ else
+ {
+ int numcards = min(3, cardstack.NumCards());
+
+ //make a "visible" copy of these cards
+ CardStack temp;
+ temp = cardstack.Pop(numcards);
+ temp.Reverse();
+
+ pile.Clear();
+ pile.Push(temp);
+
+ //remove the top 3 from deck
+ activepile.Push(temp);
+ }
+
+ activepile.Print();
+
+ pDeck->SetCardStack(cardstack);
+ pPile->SetCardStack(pile);
+
+ SolWnd.Redraw();
+ TRACE("EXIT DeckClickProc()\n");
+}
--- /dev/null
+#include <windows.h>
+#include <commctrl.h>
+#include <tchar.h>
+#include "resource.h"
+#include "cardlib/cardlib.h"
+
+#include "solitaire.h"
+
+TCHAR szHelpPath[MAX_PATH];
+
+DWORD dwAppStartTime;
+HWND hwndMain;
+HWND hwndStatus;
+HINSTANCE hInstance;
+
+TCHAR szAppName[] = _T("Solitaire");
+
+CardWindow SolWnd;
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+void MakePath(TCHAR *szDest, UINT nDestLen, TCHAR *szExt)
+{
+ TCHAR *ptr;
+
+ ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1;
+ while(*ptr-- != '.');
+ lstrcpy(ptr + 1, szExt);
+}
+
+int main ( int argc, char** argv )
+{
+ return WinMain ( NULL, NULL, NULL, SW_SHOW );
+}
+
+//
+// Main entry point
+//
+int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
+{
+ HWND hwnd;
+ MSG msg;
+ WNDCLASSEX wndclass;
+ INITCOMMONCONTROLSEX ice;
+ HACCEL hAccelTable;
+
+ hInstance = hInst;
+
+ //Window class for the main application parent window
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)NULL;
+ wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
+ wndclass.lpszClassName = szAppName;
+ wndclass.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0);
+
+ RegisterClassEx(&wndclass);
+
+ ice.dwSize = sizeof(ice);
+ ice.dwICC = ICC_BAR_CLASSES;
+ InitCommonControlsEx(&ice);
+
+ srand((unsigned)GetTickCount());//timeGetTime());
+
+// InitCardLib();
+
+// LoadSettings();
+
+ //Construct the path to our help file
+ MakePath(szHelpPath, MAX_PATH, _T(".hlp"));
+
+ hwnd = CreateWindow(szAppName, // window class name
+ szAppName, // window caption
+ WS_OVERLAPPEDWINDOW
+ ,//|WS_CLIPCHILDREN, // window style
+ CW_USEDEFAULT, // initial x position
+ CW_USEDEFAULT, // initial y position
+ CW_USEDEFAULT, // initial x size
+ CW_USEDEFAULT, // initial y size
+ NULL, // parent window handle
+ NULL, // use window class menu
+ hInst, // program instance handle
+ NULL); // creation parameters
+
+ hwndMain = hwnd;
+
+ ShowWindow(hwnd, iCmdShow);
+ UpdateWindow(hwnd);
+
+ hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
+
+ while(GetMessage(&msg, NULL,0,0))
+ {
+ if(!TranslateAccelerator(hwnd, hAccelTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+// SaveSettings();
+
+ return msg.wParam;
+}
+
+
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ static int nWidth, nHeight;
+ int nStatusHeight = 0;//20;
+ int parts[] = { 100, -1 };
+ UINT ret;
+
+ MINMAXINFO *mmi;
+
+ switch(iMsg)
+ {
+ case WM_CREATE:
+ hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "Ready", hwnd, 0);
+
+ //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0);
+
+ SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
+ SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"");
+
+ ShowWindow(hwndStatus, SW_HIDE);
+
+ SolWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0);
+
+ CreateSol();
+
+ NewGame();
+
+ dwAppStartTime = GetTickCount();
+
+ return 0;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SIZE:
+ nWidth = LOWORD(lParam);
+ nHeight = HIWORD(lParam);
+
+ MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE);
+ //MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE);
+ //parts[0] = nWidth - 256;
+ //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
+
+ return 0;
+
+ case WM_GETMINMAXINFO:
+ mmi = (MINMAXINFO *)lParam;
+ mmi->ptMinTrackSize.x = 600;
+ mmi->ptMinTrackSize.y = 400;
+
+ return 0;
+
+ case WM_COMMAND:
+
+ switch(LOWORD(wParam))
+ {
+ case IDM_GAME_NEW:
+ //simulate a button click on the new button..
+ NewGame();
+ return 0;
+
+ case IDM_GAME_DECK:
+ //ShowDeckOptionsDlg(hwnd);
+ return 0;
+
+ case IDM_GAME_OPTIONS:
+ //ShowGameOptionsDlg(hwnd);
+ return 0;
+
+ case IDM_HELP_CONTENTS:
+
+ WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
+
+ return 0;
+
+ case IDM_HELP_ABOUT:
+ MessageBox(hwnd, _T("Solitare by J Brown\r\n\r\nCardLib version 1.0."), szAppName, MB_OK|MB_ICONINFORMATION);
+
+ return 0;
+
+ case IDM_GAME_EXIT:
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return 0;
+ }
+
+ return 0;
+
+ case WM_CLOSE:
+
+ ret = IDOK;
+
+ if(fGameStarted)
+ {
+ ret = MessageBox(hwnd, _T("Quit the current game?"), szAppName, MB_OKCANCEL|MB_ICONQUESTION);
+ }
+
+ if(ret == IDOK)
+ {
+ WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
+ DestroyWindow(hwnd);
+ }
+
+ return 0;
+ }
+
+ return DefWindowProc (hwnd, iMsg, wParam, lParam);
+}
+
--- /dev/null
+#ifndef SOLITAIRE_INCLUDED
+#define SOLITAIRE_INCLUDED
+
+extern CardWindow SolWnd;
+extern TCHAR szAppName[];
+extern bool fGameStarted;
+
+void CreateSol();
+void NewGame(void);
+
+#define NUM_ROW_STACKS 7
+#define DECK_ID 1
+#define PILE_ID 2
+#define SUIT_ID 4
+#define ROW_ID 10
+
+extern CardRegion *pDeck;
+extern CardRegion *pPile;
+extern CardRegion *pSuitStack[];
+extern CardRegion *pRowStack[];
+
+
+bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumCards);
+bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards);
+
+bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards);
+void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added);
+
+void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked);
+void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked);
+
+void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked);
+void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked);
+
+void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iRemoved);
+
+#endif
--- /dev/null
+<module name="sol" type="win32gui" installbase="system32" installname="solitaire.exe" allowwarnings="true">
+ <include base="sol">.</include>
+ <include base="sol">cardlib</include>
+ <linkerflag>-lstdc++</linkerflag>
+ <define name="__USE_W32API" />
+ <define name="_WIN32_IE">0x0501</define>
+ <define name="_WIN32_WINNT">0x0501</define>
+ <define name="__REACTOS__" />
+
+ <library>kernel32</library>
+ <library>user32</library>
+ <library>gdi32</library>
+ <library>cards</library>
+ <library>comctl32</library>
+
+ <file>solcreate.cpp</file>
+ <file>solgame.cpp</file>
+ <file>solitaire.cpp</file>
+ <directory name="cardlib">
+ <file>cardbitmaps.cpp</file>
+ <file>cardbutton.cpp</file>
+ <file>cardcolor.cpp</file>
+ <file>cardcount.cpp</file>
+ <file>cardlib.cpp</file>
+ <file>cardregion.cpp</file>
+ <file>cardrgndraw.cpp</file>
+ <file>cardrgnmouse.cpp</file>
+ <file>cardstack.cpp</file>
+ <file>cardwindow.cpp</file>
+ <file>dropzone.cpp</file>
+ </directory>
+ <file>sol.rc</file>
+</module>
--- /dev/null
+#include "resource.h"\r
+\r
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL\r
+\r
+STRINGTABLE {\r
+ IDS_APPNAME, "WineMine"\r
+\r
+}\r
+\r
+MENU_WINEMINE MENU DISCARDABLE\r
+{\r
+ POPUP "&Optionen" {\r
+ MENUITEM "&Neu", IDM_NEW\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Mark Question", IDM_MARKQ\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Anfänger", IDM_BEGINNER\r
+ MENUITEM "&Fortgeschrittene", IDM_ADVANCED\r
+ MENUITEM "&Experten", IDM_EXPERT\r
+ MENUITEM "&Benutzerdefiniert", IDM_CUSTOM\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "Beenden", IDM_EXIT\r
+ }\r
+ POPUP "&Info" {\r
+ MENUITEM "&Bestzeiten", IDM_TIMES\r
+ MENUITEM "&Ãœber", IDM_ABOUT\r
+ }\r
+}\r
+\r
+DLG_TIMES DIALOG DISCARDABLE 0, 0, 160, 80\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Bestzeiten"\r
+{\r
+ GROUPBOX "Bestzeiten", IDIGNORE, 10, 10, 140, 45\r
+ LTEXT "Anfänger", IDIGNORE, 20, 20, 40, 8\r
+ LTEXT "Fortgeschrittene", IDIGNORE, 20, 30, 40, 8\r
+ LTEXT "Experten", IDIGNORE, 20, 40, 40, 8\r
+ LTEXT "999", IDC_TIME1, 70, 20, 15, 8\r
+ LTEXT "999", IDC_TIME2, 70, 30, 15, 8\r
+ LTEXT "999", IDC_TIME3, 70, 40, 15, 8\r
+ LTEXT "", IDC_NAME1, 90, 20, 55, 8\r
+ LTEXT "", IDC_NAME2, 90, 30, 55, 8\r
+ LTEXT "", IDC_NAME3, 90, 40, 55, 8\r
+ DEFPUSHBUTTON "OK", IDOK, 55, 60, 50, 15\r
+}\r
+\r
+DLG_CONGRATS DIALOG DISCARDABLE 0, 0, 160, 60\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Glückwunsch!"\r
+{\r
+ LTEXT "Bitte geben Sie ihren Namen ein", IDIGNORE, 10, 10, 150, 10\r
+ EDITTEXT IDC_EDITNAME, 25, 20, 110, 12\r
+ DEFPUSHBUTTON "Ok", IDOK, 60, 40, 40, 15\r
+}\r
+\r
+DLG_CUSTOM DIALOG DISCARDABLE 0, 0, 100, 100\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Benutzerdefiniertes Spiel"\r
+{\r
+ LTEXT "Zeilen", IDIGNORE, 5, 5, 30, 10\r
+ LTEXT "Spalten", IDIGNORE, 5, 35, 30, 10\r
+ LTEXT "Minen", IDIGNORE, 5, 65, 30, 10\r
+ EDITTEXT IDC_EDITROWS, 5, 15, 20, 12, ES_NUMBER\r
+ EDITTEXT IDC_EDITCOLS, 5, 45, 20, 12, ES_NUMBER\r
+ EDITTEXT IDC_EDITMINES, 5, 75, 20, 12, ES_NUMBER\r
+ DEFPUSHBUTTON "Ok", IDOK, 40, 30, 50, 15\r
+ PUSHBUTTON "Abbrechen", IDCANCEL, 40, 50, 50, 15\r
+}\r
+\r
+DLG_ABOUT DIALOG DISCARDABLE 0, 0, 145, 80\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "About"\r
+{\r
+ LTEXT "Winemine", IDIGNORE, 10, 10, 35, 10\r
+ LTEXT "Copyright 2000, Joshua Thielen", IDIGNORE, 35, 25, 100, 10\r
+ LTEXT "unter der Wine Lizenz", IDIGNORE, 35, 35, 100, 10\r
+ ICON "WINEMINE", IDIGNORE, 10, 25, 20, 20\r
+ DEFPUSHBUTTON "Ok", IDOK, 50, 60, 55, 15\r
+}\r
--- /dev/null
+#include "resource.h"\r
+\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+\r
+STRINGTABLE {\r
+ IDS_APPNAME, "WineMine"\r
+\r
+}\r
+\r
+MENU_WINEMINE MENU DISCARDABLE\r
+{\r
+ POPUP "&Options" {\r
+ MENUITEM "&New", IDM_NEW\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Mark Question", IDM_MARKQ\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Beginner", IDM_BEGINNER\r
+ MENUITEM "&Advanced", IDM_ADVANCED\r
+ MENUITEM "&Expert", IDM_EXPERT\r
+ MENUITEM "&Custom", IDM_CUSTOM\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "E&xit", IDM_EXIT\r
+ }\r
+ POPUP "&Info" {\r
+ MENUITEM "&Fastest Times", IDM_TIMES\r
+ MENUITEM "&About", IDM_ABOUT\r
+ }\r
+}\r
+\r
+DLG_TIMES DIALOG DISCARDABLE 0, 0, 160, 80\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Fastest Times"\r
+{\r
+ GROUPBOX "Fastest Times", IDIGNORE, 10, 10, 140, 45\r
+ LTEXT "Beginner", IDIGNORE, 20, 20, 40, 8\r
+ LTEXT "Advanced", IDIGNORE, 20, 30, 40, 8\r
+ LTEXT "Expert", IDIGNORE, 20, 40, 40, 8\r
+ LTEXT "999", IDC_TIME1, 70, 20, 15, 8\r
+ LTEXT "999", IDC_TIME2, 70, 30, 15, 8\r
+ LTEXT "999", IDC_TIME3, 70, 40, 15, 8\r
+ LTEXT "", IDC_NAME1, 90, 20, 55, 8\r
+ LTEXT "", IDC_NAME2, 90, 30, 55, 8\r
+ LTEXT "", IDC_NAME3, 90, 40, 55, 8\r
+ DEFPUSHBUTTON "OK", IDOK, 55, 60, 50, 15\r
+}\r
+\r
+DLG_CONGRATS DIALOG DISCARDABLE 0, 0, 160, 60\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Congratulations!"\r
+{\r
+ LTEXT "Please enter your name", IDIGNORE, 10, 10, 150, 10\r
+ EDITTEXT IDC_EDITNAME, 25, 20, 110, 12\r
+ DEFPUSHBUTTON "Ok", IDOK, 60, 40, 40, 15\r
+}\r
+\r
+DLG_CUSTOM DIALOG DISCARDABLE 0, 0, 100, 100\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "Custom Game"\r
+{\r
+ LTEXT "Rows", IDIGNORE, 5, 5, 30, 10\r
+ LTEXT "Cols", IDIGNORE, 5, 35, 30, 10\r
+ LTEXT "Mines", IDIGNORE, 5, 65, 30, 10\r
+ EDITTEXT IDC_EDITROWS, 5, 15, 20, 12, ES_NUMBER\r
+ EDITTEXT IDC_EDITCOLS, 5, 45, 20, 12, ES_NUMBER\r
+ EDITTEXT IDC_EDITMINES, 5, 75, 20, 12, ES_NUMBER\r
+ DEFPUSHBUTTON "Ok", IDOK, 40, 30, 50, 15\r
+ PUSHBUTTON "Cancel", IDCANCEL, 40, 50, 50, 15\r
+}\r
+\r
+DLG_ABOUT DIALOG DISCARDABLE 0, 0, 145, 80\r
+STYLE DS_MODALFRAME | DS_3DLOOK |\r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP\r
+CAPTION "About"\r
+{\r
+ LTEXT "Winemine", IDIGNORE, 10, 10, 35, 10\r
+ LTEXT "Copyright 2000, Joshua Thielen", IDIGNORE, 35, 25, 100, 10\r
+ LTEXT "under the Wine license", IDIGNORE, 35, 35, 100, 10\r
+ ICON "WINEMINE", IDIGNORE, 10, 25, 20, 20\r
+ DEFPUSHBUTTON "Ok", IDOK, 50, 60, 55, 15\r
+}\r
--- /dev/null
+WineMine README
+
+WineMine, copyright March 2000, Joshua Thielen
+WineMine is to be distributed under the Wine License
+See the Wine License for further information.
+
+
+This is minesweeper for wine...
+Enjoy. I wrote it because it rhymes ;).
+
+KNOWN BUGS:
+ Chokes on fastest times names greater than 16 characters long, must have
+ something to do with GetDlgItemText.
+
+ No help file.
+
+ Starting a new game causes the window to drop one pixel (Peter Hunnisett)
+ I don't know if it's a window manager problem (KDE)
+
+UNKNOWN BUGS:
+ ???
--- /dev/null
+/*
+ * WineMine (dialog.c)
+ *
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <windows.h>
+#include "main.h"
+#include "dialog.h"
+#include "resource.h"
+
+BOOL CALLBACK CustomDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ BOOL IsRet;
+ static BOARD *p_board;
+
+ switch( uMsg ) {
+ case WM_INITDIALOG:
+ p_board = (BOARD*) lParam;
+ SetDlgItemInt( hDlg, IDC_EDITROWS, p_board->rows, FALSE );
+ SetDlgItemInt( hDlg, IDC_EDITCOLS, p_board->cols, FALSE );
+ SetDlgItemInt( hDlg, IDC_EDITMINES, p_board->mines, FALSE );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam ) ) {
+ case IDOK:
+ p_board->rows = GetDlgItemInt( hDlg, IDC_EDITROWS, &IsRet, FALSE );
+ p_board->cols = GetDlgItemInt( hDlg, IDC_EDITCOLS, &IsRet, FALSE );
+ p_board->mines = GetDlgItemInt( hDlg, IDC_EDITMINES, &IsRet, FALSE );
+ CheckLevel( p_board );
+ EndDialog( hDlg, 0 );
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK CongratsDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ static BOARD *p_board;
+
+ switch( uMsg ) {
+ case WM_INITDIALOG:
+ p_board = (BOARD*) lParam;
+ SetDlgItemText( hDlg, IDC_EDITNAME,
+ p_board->best_name[p_board->difficulty] );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam ) ) {
+ case IDOK:
+ GetDlgItemText( hDlg, IDC_EDITNAME,
+ p_board->best_name[p_board->difficulty],
+ sizeof( p_board->best_name[p_board->difficulty] ) );
+ EndDialog( hDlg, 0 );
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK TimesDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ static BOARD *p_board;
+ unsigned i;
+
+ switch( uMsg ) {
+ case WM_INITDIALOG:
+ p_board = (BOARD*) lParam;
+
+ /* set best names */
+ for( i = 0; i < 3; i++ )
+ SetDlgItemText( hDlg, (IDC_NAME1) + i, p_board->best_name[i] );
+
+ /* set best times */
+ for( i = 0; i < 3; i++ )
+ SetDlgItemInt( hDlg, (IDC_TIME1) + i, p_board->best_time[i], FALSE );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam ) ) {
+ case IDOK:
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch( uMsg ) {
+ case WM_INITDIALOG:
+ return TRUE;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam ) ) {
+ case IDOK:
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
--- /dev/null
+/*
+ * WineMine (dialog.h)
+ *
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+BOOL CALLBACK CustomDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK CongratsDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK TimesDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
--- /dev/null
+/*
+ * WineMine (main.c)
+ *
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <windows.h>
+#include "main.h"
+#include "dialog.h"
+#include "resource.h"
+
+/* Work around a Wine bug which defines handles as UINT rather than LPVOID */
+#ifdef WINE_STRICT
+#define NULL_HANDLE NULL
+#else
+#define NULL_HANDLE 0
+#endif
+
+#ifdef DUMB_DEBUG
+#include <stdio.h>
+#define DEBUG(x) fprintf(stderr,x)
+#else
+#define DEBUG(x)
+#endif
+
+
+int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow )
+{
+ MSG msg;
+ WNDCLASS wc;
+ HWND hWnd;
+ HACCEL haccel;
+ char appname[9];
+
+ LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
+
+ wc.style = 0;
+ wc.lpfnWndProc = MainProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInst;
+ wc.hIcon = LoadIcon( hInst, appname );
+ wc.hCursor = LoadCursor( NULL_HANDLE, (LPCTSTR)IDI_APPLICATION );
+ wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
+ wc.lpszMenuName = "MENU_WINEMINE";
+ wc.lpszClassName = appname;
+
+ if (!RegisterClass(&wc)) exit(1);
+ hWnd = CreateWindow( appname, appname,
+ WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL_HANDLE, NULL_HANDLE, hInst, NULL );
+
+ if (!hWnd) exit(1);
+
+ ShowWindow( hWnd, cmdshow );
+ UpdateWindow( hWnd );
+
+ haccel = LoadAccelerators( hInst, appname );
+ SetTimer( hWnd, ID_TIMER, 1000, NULL );
+
+ while( GetMessage(&msg, NULL_HANDLE, 0, 0) ) {
+ if (!TranslateAccelerator( hWnd, haccel, &msg ))
+ TranslateMessage( &msg );
+
+ DispatchMessage( &msg );
+ }
+ return msg.wParam;
+}
+
+
+LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+ HMENU hMenu;
+ static BOARD board;
+
+ switch( msg ) {
+ case WM_CREATE:
+ board.hInst = ((LPCREATESTRUCT) lParam)->hInstance;
+ board.hWnd = hWnd;
+ InitBoard( &board );
+ CreateBoard( &board );
+ return 0;
+
+ case WM_PAINT:
+ {
+ HDC hMemDC;
+
+ DEBUG("WM_PAINT\n");
+ hdc = BeginPaint( hWnd, &ps );
+ hMemDC = CreateCompatibleDC( hdc );
+
+ DrawBoard( hdc, hMemDC, &ps, &board );
+
+ DeleteDC( hMemDC );
+ EndPaint( hWnd, &ps );
+
+ return 0;
+ }
+
+ case WM_MOVE:
+ DEBUG("WM_MOVE\n");
+ board.pos.x = (unsigned) LOWORD(lParam);
+ board.pos.y = (unsigned) HIWORD(lParam);
+ return 0;
+
+ case WM_DESTROY:
+ SaveBoard( &board );
+ DestroyBoard( &board );
+ PostQuitMessage( 0 );
+ return 0;
+
+ case WM_TIMER:
+ if( board.status == PLAYING ) {
+ board.time++;
+ RedrawWindow( hWnd, &board.timer_rect, NULL_HANDLE,
+ RDW_INVALIDATE | RDW_UPDATENOW );
+ }
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ DEBUG("WM_LBUTTONDOWN\n");
+ if( wParam & MK_RBUTTON )
+ msg = WM_MBUTTONDOWN;
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ SetCapture( hWnd );
+ return 0;
+
+ case WM_LBUTTONUP:
+ DEBUG("WM_LBUTTONUP\n");
+ if( wParam & MK_RBUTTON )
+ msg = WM_MBUTTONUP;
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ ReleaseCapture();
+ return 0;
+
+ case WM_RBUTTONDOWN:
+ DEBUG("WM_RBUTTONDOWN\n");
+ if( wParam & MK_LBUTTON ) {
+ board.press.x = 0;
+ board.press.y = 0;
+ msg = WM_MBUTTONDOWN;
+ }
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ return 0;
+
+ case WM_RBUTTONUP:
+ DEBUG("WM_RBUTTONUP\n");
+ if( wParam & MK_LBUTTON )
+ msg = WM_MBUTTONUP;
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ return 0;
+
+ case WM_MBUTTONDOWN:
+ DEBUG("WM_MBUTTONDOWN\n");
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ return 0;
+
+ case WM_MBUTTONUP:
+ DEBUG("WM_MBUTTONUP\n");
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+ return 0;
+
+ case WM_MOUSEMOVE:
+ {
+ if( (wParam & MK_LBUTTON) && (wParam & MK_RBUTTON) ) {
+ msg = WM_MBUTTONDOWN;
+ }
+ else if( wParam & MK_LBUTTON ) {
+ msg = WM_LBUTTONDOWN;
+ }
+ else {
+ return 0;
+ }
+
+ TestBoard( hWnd, &board, LOWORD(lParam), HIWORD(lParam), msg );
+
+ return 0;
+ }
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDM_NEW:
+ CreateBoard( &board );
+ return 0;
+
+ case IDM_MARKQ:
+ hMenu = GetMenu( hWnd );
+ board.IsMarkQ = !board.IsMarkQ;
+ if( board.IsMarkQ )
+ CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
+ else
+ CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
+ return 0;
+
+ case IDM_BEGINNER:
+ SetDifficulty( &board, BEGINNER );
+ CreateBoard( &board );
+ return 0;
+
+ case IDM_ADVANCED:
+ SetDifficulty( &board, ADVANCED );
+ CreateBoard( &board );
+ return 0;
+
+ case IDM_EXPERT:
+ SetDifficulty( &board, EXPERT );
+ CreateBoard( &board );
+ return 0;
+
+ case IDM_CUSTOM:
+ SetDifficulty( &board, CUSTOM );
+ CreateBoard( &board );
+ return 0;
+
+ case IDM_EXIT:
+ SendMessage( hWnd, WM_CLOSE, 0, 0);
+ return 0;
+
+ case IDM_TIMES:
+ DialogBoxParam( board.hInst, "DLG_TIMES", hWnd,
+ TimesDlgProc, (LPARAM) &board);
+ return 0;
+
+ case IDM_ABOUT:
+ DialogBox( board.hInst, "DLG_ABOUT", hWnd, AboutDlgProc );
+ return 0;
+ default:
+ DEBUG("Unknown WM_COMMAND command message received\n");
+ break;
+ }
+ }
+ return( DefWindowProc( hWnd, msg, wParam, lParam ));
+}
+
+void InitBoard( BOARD *p_board )
+{
+ HMENU hMenu;
+
+ p_board->hMinesBMP = LoadBitmap( p_board->hInst, (LPCSTR) IDB_MINES);
+ p_board->hFacesBMP = LoadBitmap( p_board->hInst, (LPCSTR) IDB_FACES);
+ p_board->hLedsBMP = LoadBitmap( p_board->hInst, (LPCSTR) IDB_LEDS);
+
+ LoadBoard( p_board );
+
+ if( p_board->pos.x < (unsigned) GetSystemMetrics( SM_CXFIXEDFRAME ))
+ p_board->pos.x = GetSystemMetrics( SM_CXFIXEDFRAME );
+
+ if( p_board->pos.x > (unsigned) (GetSystemMetrics( SM_CXSCREEN )
+ - GetSystemMetrics( SM_CXFIXEDFRAME ))) {
+ p_board->pos.x = GetSystemMetrics( SM_CXSCREEN )
+ - GetSystemMetrics( SM_CXFIXEDFRAME );
+ }
+
+ if( p_board->pos.y < (unsigned) (GetSystemMetrics( SM_CYMENU )
+ + GetSystemMetrics( SM_CYCAPTION )
+ + GetSystemMetrics( SM_CYFIXEDFRAME ))) {
+ p_board->pos.y = GetSystemMetrics( SM_CYMENU ) +
+ GetSystemMetrics( SM_CYCAPTION ) +
+ GetSystemMetrics( SM_CYFIXEDFRAME );
+ }
+
+ if( p_board->pos.y > (unsigned) (GetSystemMetrics( SM_CYSCREEN )
+ - GetSystemMetrics( SM_CYFIXEDFRAME ))) {
+ p_board->pos.y = GetSystemMetrics( SM_CYSCREEN )
+ - GetSystemMetrics( SM_CYFIXEDFRAME );
+ }
+
+ hMenu = GetMenu( p_board->hWnd );
+ CheckMenuItem( hMenu, IDM_BEGINNER + (unsigned) p_board->difficulty,
+ MF_CHECKED );
+ if( p_board->IsMarkQ )
+ CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
+ else
+ CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
+ CheckLevel( p_board );
+}
+
+void LoadBoard( BOARD *p_board )
+{
+ DWORD size;
+ DWORD type;
+ HKEY hkey;
+ char data[16];
+ char key_name[8];
+ unsigned i;
+
+
+ RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\Wine\\WineMine",
+ 0, KEY_QUERY_VALUE, &hkey );
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Xpos", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS ) {
+ p_board->pos.x = atoi( data );
+ }
+ else
+ p_board->pos.x = GetSystemMetrics( SM_CXFIXEDFRAME );
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Ypos", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->pos.y = atoi( data );
+ else
+ p_board->pos.y = GetSystemMetrics( SM_CYMENU )
+ + GetSystemMetrics( SM_CYCAPTION )
+ + GetSystemMetrics( SM_CYFIXEDFRAME );
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Rows", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->rows = atoi( data );
+ else
+ p_board->rows = BEGINNER_ROWS;
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Cols", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->cols = atoi( data );
+ else
+ p_board->cols = BEGINNER_COLS;
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Mines", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->mines = atoi( data );
+ else
+ p_board->rows = BEGINNER_ROWS;
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "Difficulty", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->difficulty = (DIFFICULTY) atoi( data );
+ else
+ p_board->difficulty = BEGINNER;
+
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, "MarkQ", NULL, (LPDWORD) &type,
+ (LPBYTE) data, (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->IsMarkQ = atoi( data );
+ else
+ p_board->IsMarkQ = TRUE;
+
+ for( i = 0; i < 3; i++ ) {
+ wsprintf( key_name, "Name%d", i );
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
+ (LPBYTE) data,
+ (LPDWORD) &size ) == ERROR_SUCCESS )
+ strncpy( p_board->best_name[i], data, sizeof( data ) );
+ else
+ wsprintf( p_board->best_name[i], "Nobody");
+ }
+
+ for( i = 0; i < 3; i++ ) {
+ wsprintf( key_name, "Time%d", i );
+ size = sizeof( data );
+ if( RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
+ (LPBYTE) data,
+ (LPDWORD) &size ) == ERROR_SUCCESS )
+ p_board->best_time[i] = atoi( data );
+ else
+ p_board->best_time[i] = 999;
+ }
+ RegCloseKey( hkey );
+}
+
+void SaveBoard( BOARD *p_board )
+{
+ DWORD disp;
+ HKEY hkey;
+ unsigned i;
+ char data[16];
+ char key_name[8];
+
+ if( RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ "Software\\Wine\\WineMine", 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
+ &hkey, &disp ) != ERROR_SUCCESS)
+ return;
+
+ wsprintf( data, "%d", p_board->pos.x );
+ RegSetValueEx( hkey, "Xpos", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", p_board->pos.x );
+ RegSetValueEx( hkey, "Ypos", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", (int) p_board->difficulty );
+ RegSetValueEx( hkey, "Difficulty", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", p_board->rows );
+ RegSetValueEx( hkey, "Rows", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", p_board->cols );
+ RegSetValueEx( hkey, "Cols", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", p_board->mines );
+ RegSetValueEx( hkey, "Mines", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ wsprintf( data, "%d", (int) p_board->IsMarkQ );
+ RegSetValueEx( hkey, "MarkQ", 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+
+ for( i = 0; i < 3; i++ ) {
+ wsprintf( key_name, "Name%u", i );
+ strncpy( data, p_board->best_name[i], sizeof( data ) );
+ RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+ }
+
+ for( i = 0; i < 3; i++ ) {
+ wsprintf( key_name, "Time%u", i );
+ wsprintf( data, "%d", p_board->best_time[i] );
+ RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
+ }
+ RegCloseKey( hkey );
+}
+
+void DestroyBoard( BOARD *p_board )
+{
+ DeleteObject( p_board->hFacesBMP );
+ DeleteObject( p_board->hLedsBMP );
+ DeleteObject( p_board->hMinesBMP );
+}
+
+void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty )
+{
+ HMENU hMenu = GetMenu( p_board->hWnd );
+
+ CheckMenuItem( hMenu, IDM_BEGINNER + p_board->difficulty, MF_UNCHECKED );
+ p_board->difficulty = difficulty;
+ CheckMenuItem( hMenu, IDM_BEGINNER + difficulty, MF_CHECKED );
+
+ switch( difficulty ) {
+ case BEGINNER:
+ p_board->cols = BEGINNER_COLS;
+ p_board->rows = BEGINNER_ROWS;
+ p_board->mines = BEGINNER_MINES;
+ break;
+
+ case ADVANCED:
+ p_board->cols = ADVANCED_COLS;
+ p_board->rows = ADVANCED_ROWS;
+ p_board->mines = ADVANCED_MINES;
+ break;
+
+ case EXPERT:
+ p_board->cols = EXPERT_COLS;
+ p_board->rows = EXPERT_ROWS;
+ p_board->mines = EXPERT_MINES;
+ break;
+
+ case CUSTOM:
+ DialogBoxParam( p_board->hInst, "DLG_CUSTOM", p_board->hWnd,
+ CustomDlgProc, (LPARAM) p_board);
+ break;
+ }
+}
+
+void CreateBoard( BOARD *p_board )
+{
+ int left, top, bottom, right, wnd_x, wnd_y, wnd_width, wnd_height;
+
+ p_board->mb = MB_NONE;
+ p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines;
+ p_board->num_flags = 0;
+
+ CreateBoxes( p_board );
+
+ p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2;
+
+ p_board->height = p_board->rows * MINE_HEIGHT + LED_HEIGHT
+ + BOARD_HMARGIN * 3;
+
+ wnd_x = p_board->pos.x - GetSystemMetrics( SM_CXFIXEDFRAME );
+ wnd_y = p_board->pos.y - GetSystemMetrics( SM_CYMENU )
+ - GetSystemMetrics( SM_CYCAPTION )
+ - GetSystemMetrics( SM_CYFIXEDFRAME );
+ wnd_width = p_board->width
+ + GetSystemMetrics( SM_CXFIXEDFRAME ) * 2;
+ wnd_height = p_board->height
+ + GetSystemMetrics( SM_CYMENU )
+ + GetSystemMetrics( SM_CYCAPTION )
+ + GetSystemMetrics( SM_CYFIXEDFRAME ) * 2;
+
+ /* setting the mines rectangle boundary */
+ left = BOARD_WMARGIN;
+ top = BOARD_HMARGIN * 2 + LED_HEIGHT;
+ right = left + p_board->cols * MINE_WIDTH;
+ bottom = top + p_board->rows * MINE_HEIGHT;
+ SetRect( &p_board->mines_rect, left, top, right, bottom );
+
+ /* setting the face rectangle boundary */
+ left = p_board->width / 2 - FACE_WIDTH / 2;
+ top = BOARD_HMARGIN;
+ right = left + FACE_WIDTH;
+ bottom = top + FACE_HEIGHT;
+ SetRect( &p_board->face_rect, left, top, right, bottom );
+
+ /* setting the timer rectangle boundary */
+ left = BOARD_WMARGIN;
+ top = BOARD_HMARGIN;
+ right = left + LED_WIDTH * 3;
+ bottom = top + LED_HEIGHT;
+ SetRect( &p_board->timer_rect, left, top, right, bottom );
+
+ /* setting the counter rectangle boundary */
+ left = p_board->width - BOARD_WMARGIN - LED_WIDTH * 3;
+ top = BOARD_HMARGIN;
+ right = p_board->width - BOARD_WMARGIN;
+ bottom = top + LED_HEIGHT;
+ SetRect( &p_board->counter_rect, left, top, right, bottom );
+
+ p_board->status = WAITING;
+ p_board->face_bmp = SMILE_BMP;
+ p_board->time = 0;
+
+ MoveWindow( p_board->hWnd, wnd_x, wnd_y, wnd_width, wnd_height, TRUE );
+ RedrawWindow( p_board->hWnd, NULL, NULL_HANDLE,
+ RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE );
+}
+
+
+void CheckLevel( BOARD *p_board )
+{
+ if( p_board->rows < BEGINNER_ROWS )
+ p_board->rows = BEGINNER_ROWS;
+
+ if( p_board->rows > MAX_ROWS )
+ p_board->rows = MAX_ROWS;
+
+ if( p_board->cols < BEGINNER_COLS )
+ p_board->cols = BEGINNER_COLS;
+
+ if( p_board->cols > MAX_COLS )
+ p_board->cols = MAX_COLS;
+
+ if( p_board->mines < BEGINNER_MINES )
+ p_board->mines = BEGINNER_MINES;
+
+ if( p_board->mines > p_board->cols * p_board->rows - 1 )
+ p_board->mines = p_board->cols * p_board->rows - 1;
+}
+
+
+void CreateBoxes( BOARD *p_board )
+{
+ int i, j;
+ unsigned col, row;
+
+ srand( (unsigned) time( NULL ) );
+
+ /* Create the boxes...
+ * We actually create them with an empty border,
+ * so special care doesn't have to be taken on the edges
+ */
+
+ for( col = 0; col <= p_board->cols + 1; col++ )
+ for( row = 0; row <= p_board->rows + 1; row++ ) {
+ p_board->box[col][row].IsPressed = FALSE;
+ p_board->box[col][row].IsMine = FALSE;
+ p_board->box[col][row].FlagType = NORMAL;
+ p_board->box[col][row].NumMines = 0;
+ }
+
+ /* create mines */
+ i = 0;
+ while( (unsigned) i < p_board->mines ) {
+ col = (int) (p_board->cols * (float) rand() / RAND_MAX + 1);
+ row = (int) (p_board->rows * (float) rand() / RAND_MAX + 1);
+
+ if( !p_board->box[col][row].IsMine ) {
+ i++;
+ p_board->box[col][row].IsMine = TRUE;
+ }
+ }
+
+ /*
+ * Now we label the remaining boxes with the
+ * number of mines surrounding them.
+ */
+
+ for( col = 1; col < p_board->cols + 1; col++ )
+ for( row = 1; row < p_board->rows + 1; row++ ) {
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ if( p_board->box[col + i][row + j].IsMine ) {
+ p_board->box[col][row].NumMines++ ;
+ }
+ }
+ }
+}
+
+void DrawMines ( HDC hdc, HDC hMemDC, BOARD *p_board )
+{
+ HGDIOBJ hOldObj;
+ unsigned col, row;
+ hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
+
+ for( row = 1; row <= p_board->rows; row++ ) {
+ for( col = 1; col <= p_board->cols; col++ ) {
+ DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
+ }
+ }
+ SelectObject( hMemDC, hOldObj );
+}
+
+void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed )
+{
+ MINEBMP_OFFSET offset = BOX_BMP;
+
+ if( col == 0 || col > p_board->cols || row == 0 || row > p_board->rows )
+ return;
+
+ if( p_board->status == GAMEOVER ) {
+ if( p_board->box[col][row].IsMine ) {
+ switch( p_board->box[col][row].FlagType ) {
+ case FLAG:
+ offset = FLAG_BMP;
+ break;
+ case COMPLETE:
+ offset = EXPLODE_BMP;
+ break;
+ case NORMAL:
+ offset = MINE_BMP;
+ }
+ } else {
+ switch( p_board->box[col][row].FlagType ) {
+ case QUESTION:
+ offset = QUESTION_BMP;
+ break;
+ case FLAG:
+ offset = WRONG_BMP;
+ break;
+ case NORMAL:
+ offset = BOX_BMP;
+ break;
+ case COMPLETE:
+ /* Do nothing */
+ break;
+ default:
+ DEBUG("Unknown FlagType during game over in DrawMine\n");
+ break;
+ }
+ }
+ } else { /* WAITING or PLAYING */
+ switch( p_board->box[col][row].FlagType ) {
+ case QUESTION:
+ if( !IsPressed )
+ offset = QUESTION_BMP;
+ else
+ offset = QPRESS_BMP;
+ break;
+ case FLAG:
+ offset = FLAG_BMP;
+ break;
+ case NORMAL:
+ if( !IsPressed )
+ offset = BOX_BMP;
+ else
+ offset = MPRESS_BMP;
+ break;
+ case COMPLETE:
+ /* Do nothing */
+ break;
+ default:
+ DEBUG("Unknown FlagType while playing in DrawMine\n");
+ break;
+ }
+ }
+
+ if( p_board->box[col][row].FlagType == COMPLETE
+ && !p_board->box[col][row].IsMine )
+ offset = (MINEBMP_OFFSET) p_board->box[col][row].NumMines;
+
+ BitBlt( hdc,
+ (col - 1) * MINE_WIDTH + p_board->mines_rect.left,
+ (row - 1) * MINE_HEIGHT + p_board->mines_rect.top,
+ MINE_WIDTH, MINE_HEIGHT,
+ hMemDC, 0, offset * MINE_HEIGHT, SRCCOPY );
+}
+
+void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y )
+{
+ HGDIOBJ hOldObj;
+ unsigned led[3], i;
+ int count;
+
+ count = number;
+ if( count < 1000 ) {
+ if( count >= 0 ) {
+ led[0] = count / 100 ;
+ count -= led[0] * 100;
+ }
+ else {
+ led[0] = 10; /* negative sign */
+ count = -count;
+ }
+ led[1] = count / 10;
+ count -= led[1] * 10;
+ led[2] = count;
+ }
+ else {
+ for( i = 0; i < 3; i++ )
+ led[i] = 10;
+ }
+
+ /* use unlit led if not playing */
+ if( p_board->status == WAITING )
+ for( i = 0; i < 3; i++ )
+ led[i] = 11;
+
+ hOldObj = SelectObject (hMemDC, p_board->hLedsBMP);
+
+ for( i = 0; i < 3; i++ ) {
+ BitBlt( hdc,
+ i * LED_WIDTH + x,
+ y,
+ LED_WIDTH,
+ LED_HEIGHT,
+ hMemDC,
+ 0,
+ led[i] * LED_HEIGHT,
+ SRCCOPY);
+ }
+
+ SelectObject( hMemDC, hOldObj );
+}
+
+
+void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board )
+{
+ HGDIOBJ hOldObj;
+
+ hOldObj = SelectObject (hMemDC, p_board->hFacesBMP);
+
+ BitBlt( hdc,
+ p_board->face_rect.left,
+ p_board->face_rect.top,
+ FACE_WIDTH,
+ FACE_HEIGHT,
+ hMemDC, 0, p_board->face_bmp * FACE_HEIGHT, SRCCOPY);
+
+ SelectObject( hMemDC, hOldObj );
+}
+
+
+void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board )
+{
+ RECT tmp_rect;
+
+ if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->counter_rect ) )
+ DrawLeds( hdc, hMemDC, p_board, p_board->mines - p_board->num_flags,
+ p_board->counter_rect.left,
+ p_board->counter_rect.top );
+
+ if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->timer_rect ) )
+ DrawLeds( hdc, hMemDC, p_board, p_board->time,
+ p_board->timer_rect.left,
+ p_board->timer_rect.top );
+
+ if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->face_rect ) )
+ DrawFace( hdc, hMemDC, p_board );
+
+ if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->mines_rect ) )
+ DrawMines( hdc, hMemDC, p_board );
+}
+
+
+void TestBoard( HWND hWnd, BOARD *p_board, unsigned x, unsigned y, int msg )
+{
+ POINT pt;
+
+ pt.x = x;
+ pt.y = y;
+
+ if( PtInRect( &p_board->mines_rect, pt ) && p_board->status != GAMEOVER
+ && p_board->status != WON )
+ TestMines( p_board, pt, msg );
+ else {
+ UnpressBoxes( p_board,
+ p_board->press.x,
+ p_board->press.y );
+ p_board->press.x = 0;
+ p_board->press.y = 0;
+ }
+
+ if( p_board->boxes_left == 0 ) {
+ p_board->status = WON;
+
+ if( p_board->difficulty != CUSTOM &&
+ p_board->time < p_board->best_time[p_board->difficulty] ) {
+ p_board->best_time[p_board->difficulty] = p_board->time;
+
+ DialogBoxParam( p_board->hInst, "DLG_CONGRATS", hWnd,
+ CongratsDlgProc, (LPARAM) p_board);
+
+ DialogBoxParam( p_board->hInst, "DLG_TIMES", hWnd,
+ TimesDlgProc, (LPARAM) p_board);
+ }
+ }
+ TestFace( p_board, pt, msg );
+}
+
+void TestMines( BOARD *p_board, POINT pt, int msg )
+{
+ BOOL draw = TRUE;
+ unsigned col, row;
+
+ col = (pt.x - p_board->mines_rect.left) / MINE_WIDTH + 1;
+ row = (pt.y - p_board->mines_rect.top ) / MINE_HEIGHT + 1;
+
+ switch ( msg ) {
+ case WM_LBUTTONDOWN:
+ if( p_board->press.x != col || p_board->press.y != row ) {
+ UnpressBox( p_board,
+ p_board->press.x, p_board->press.y );
+ p_board->press.x = col;
+ p_board->press.y = row;
+ PressBox( p_board, col, row );
+ }
+ draw = FALSE;
+ break;
+
+ case WM_LBUTTONUP:
+ if( p_board->press.x != col || p_board->press.y != row )
+ UnpressBox( p_board,
+ p_board->press.x, p_board->press.y );
+ p_board->press.x = 0;
+ p_board->press.y = 0;
+ if( p_board->box[col][row].FlagType != FLAG )
+ p_board->status = PLAYING;
+ CompleteBox( p_board, col, row );
+ break;
+
+ case WM_MBUTTONDOWN:
+ PressBoxes( p_board, col, row );
+ draw = FALSE;
+ break;
+
+ case WM_MBUTTONUP:
+ if( p_board->press.x != col || p_board->press.y != row )
+ UnpressBoxes( p_board,
+ p_board->press.x, p_board->press.y );
+ p_board->press.x = 0;
+ p_board->press.y = 0;
+ CompleteBoxes( p_board, col, row );
+ break;
+
+ case WM_RBUTTONDOWN:
+ AddFlag( p_board, col, row );
+ p_board->status = PLAYING;
+ break;
+ default:
+ DEBUG("Unknown message type received in TestMines\n");
+ break;
+ }
+
+ if( draw )
+ {
+ RedrawWindow( p_board->hWnd, NULL, NULL_HANDLE,
+ RDW_INVALIDATE | RDW_UPDATENOW );
+ }
+}
+
+
+void TestFace( BOARD *p_board, POINT pt, int msg )
+{
+ if( p_board->status == PLAYING || p_board->status == WAITING ) {
+ if( msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN )
+ p_board->face_bmp = OOH_BMP;
+ else p_board->face_bmp = SMILE_BMP;
+ }
+ else if( p_board->status == GAMEOVER )
+ p_board->face_bmp = DEAD_BMP;
+ else if( p_board->status == WON )
+ p_board->face_bmp = COOL_BMP;
+
+ if( PtInRect( &p_board->face_rect, pt ) ) {
+ if( msg == WM_LBUTTONDOWN )
+ p_board->face_bmp = SPRESS_BMP;
+
+ if( msg == WM_LBUTTONUP )
+ CreateBoard( p_board );
+ }
+
+ RedrawWindow( p_board->hWnd, &p_board->face_rect, NULL_HANDLE,
+ RDW_INVALIDATE | RDW_UPDATENOW );
+}
+
+
+void CompleteBox( BOARD *p_board, unsigned col, unsigned row )
+{
+ int i, j;
+
+ if( p_board->box[col][row].FlagType != COMPLETE &&
+ p_board->box[col][row].FlagType != FLAG &&
+ col > 0 && col < p_board->cols + 1 &&
+ row > 0 && row < p_board->rows + 1 ) {
+ p_board->box[col][row].FlagType = COMPLETE;
+
+ if( p_board->box[col][row].IsMine ) {
+ p_board->face_bmp = DEAD_BMP;
+ p_board->status = GAMEOVER;
+ }
+ else if( p_board->status != GAMEOVER )
+ p_board->boxes_left--;
+
+ if( p_board->box[col][row].NumMines == 0 )
+ {
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ )
+ CompleteBox( p_board, col + i, row + j );
+ }
+ }
+}
+
+
+void CompleteBoxes( BOARD *p_board, unsigned col, unsigned row )
+{
+ unsigned numFlags = 0;
+ int i, j;
+
+ if( p_board->box[col][row].FlagType == COMPLETE ) {
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ if( p_board->box[col+i][row+j].FlagType == FLAG )
+ numFlags++;
+ }
+
+ if( numFlags == p_board->box[col][row].NumMines ) {
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ if( p_board->box[col+i][row+j].FlagType != FLAG )
+ CompleteBox( p_board, col+i, row+j );
+ }
+ }
+ }
+}
+
+
+void AddFlag( BOARD *p_board, unsigned col, unsigned row )
+{
+ if( p_board->box[col][row].FlagType != COMPLETE ) {
+ switch( p_board->box[col][row].FlagType ) {
+ case FLAG:
+ if( p_board->IsMarkQ )
+ p_board->box[col][row].FlagType = QUESTION;
+ else
+ p_board->box[col][row].FlagType = NORMAL;
+ p_board->num_flags--;
+ break;
+
+ case QUESTION:
+ p_board->box[col][row].FlagType = NORMAL;
+ break;
+
+ default:
+ p_board->box[col][row].FlagType = FLAG;
+ p_board->num_flags++;
+ }
+ }
+}
+
+
+void PressBox( BOARD *p_board, unsigned col, unsigned row )
+{
+ HDC hdc;
+ HGDIOBJ hOldObj;
+ HDC hMemDC;
+
+ hdc = GetDC( p_board->hWnd );
+ hMemDC = CreateCompatibleDC( hdc );
+ hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
+
+ DrawMine( hdc, hMemDC, p_board, col, row, TRUE );
+
+ SelectObject( hMemDC, hOldObj );
+ DeleteDC( hMemDC );
+ ReleaseDC( p_board->hWnd, hdc );
+}
+
+
+void PressBoxes( BOARD *p_board, unsigned col, unsigned row )
+{
+ int i, j;
+
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ p_board->box[col + i][row + j].IsPressed = TRUE;
+ PressBox( p_board, col + i, row + j );
+ }
+
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ if( !p_board->box[p_board->press.x + i][p_board->press.y + j].IsPressed )
+ UnpressBox( p_board, p_board->press.x + i, p_board->press.y + j );
+ }
+
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ p_board->box[col + i][row + j].IsPressed = FALSE;
+ PressBox( p_board, col + i, row + j );
+ }
+
+ p_board->press.x = col;
+ p_board->press.y = row;
+}
+
+
+void UnpressBox( BOARD *p_board, unsigned col, unsigned row )
+{
+ HDC hdc;
+ HGDIOBJ hOldObj;
+ HDC hMemDC;
+
+ hdc = GetDC( p_board->hWnd );
+ hMemDC = CreateCompatibleDC( hdc );
+ hOldObj = SelectObject( hMemDC, p_board->hMinesBMP );
+
+ DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
+
+ SelectObject( hMemDC, hOldObj );
+ DeleteDC( hMemDC );
+ ReleaseDC( p_board->hWnd, hdc );
+}
+
+
+void UnpressBoxes( BOARD *p_board, unsigned col, unsigned row )
+{
+ int i, j;
+
+ for( i = -1; i <= 1; i++ )
+ for( j = -1; j <= 1; j++ ) {
+ UnpressBox( p_board, col + i, row + j );
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <windows.h>
+
+#define BEGINNER_MINES 10
+#define BEGINNER_COLS 8
+#define BEGINNER_ROWS 8
+
+#define ADVANCED_MINES 40
+#define ADVANCED_COLS 16
+#define ADVANCED_ROWS 16
+
+#define EXPERT_MINES 99
+#define EXPERT_COLS 30
+#define EXPERT_ROWS 16
+
+#define MAX_COLS 30
+#define MAX_ROWS 24
+
+#define BOTTOM_MARGIN 20
+#define BOARD_WMARGIN 5
+#define BOARD_HMARGIN 5
+
+/* mine defines */
+#define MINE_WIDTH 16
+#define MINE_HEIGHT 16
+#define LED_WIDTH 12
+#define LED_HEIGHT 23
+#define FACE_WIDTH 24
+#define FACE_HEIGHT 24
+
+typedef enum { SPRESS_BMP, COOL_BMP, DEAD_BMP, OOH_BMP, SMILE_BMP } FACE_BMP;
+
+typedef enum { WAITING, PLAYING, GAMEOVER, WON } GAME_STATUS;
+
+typedef enum {
+ MPRESS_BMP, ONE_BMP, TWO_BMP, THREE_BMP, FOUR_BMP, FIVE_BMP, SIX_BMP,
+ SEVEN_BMP, EIGHT_BMP, BOX_BMP, FLAG_BMP, QUESTION_BMP, EXPLODE_BMP,
+ WRONG_BMP, MINE_BMP, QPRESS_BMP
+} MINEBMP_OFFSET;
+
+typedef enum { BEGINNER, ADVANCED, EXPERT, CUSTOM } DIFFICULTY;
+
+typedef struct tagBOARD
+{
+ BOOL IsMarkQ;
+ HDC hdc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ HBITMAP hMinesBMP;
+ HBITMAP hFacesBMP;
+ HBITMAP hLedsBMP;
+ RECT mines_rect;
+ RECT face_rect;
+ RECT timer_rect;
+ RECT counter_rect;
+
+ unsigned width;
+ unsigned height;
+ POINT pos;
+
+ unsigned time;
+ unsigned num_flags;
+ unsigned boxes_left;
+ unsigned num_mines;
+
+ /* difficulty info */
+ unsigned rows;
+ unsigned cols;
+ unsigned mines;
+ char best_name [3][16];
+ unsigned best_time [3];
+ DIFFICULTY difficulty;
+
+ POINT press;
+
+ /* defines for mb */
+ #define MB_NONE 0
+ #define MB_LEFTDOWN 1
+ #define MB_LEFTUP 2
+ #define MB_RIGHTDOWN 3
+ #define MB_RIGHTUP 4
+ #define MB_BOTHDOWN 5
+ #define MB_BOTHUP 6
+ unsigned mb;
+
+ FACE_BMP face_bmp;
+ GAME_STATUS status;
+ struct BOX_STRUCT
+ {
+ unsigned IsMine : 1;
+ unsigned IsPressed : 1;
+ unsigned FlagType : 2;
+ unsigned NumMines : 4;
+ } box [MAX_COLS + 2] [MAX_ROWS + 2];
+
+ /* defines for FlagType */
+ #define NORMAL 0
+ #define QUESTION 1
+ #define FLAG 2
+ #define COMPLETE 3
+
+} BOARD;
+
+void ExitApp( int error );
+
+void InitBoard( BOARD *p_board );
+
+void LoadBoard( BOARD *p_board );
+
+void SaveBoard( BOARD *p_board );
+
+void DestroyBoard( BOARD *p_board );
+
+void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty );
+
+void CheckLevel( BOARD *p_board );
+
+void CreateBoard( BOARD *p_board );
+
+void CreateBoxes( BOARD *p_board );
+
+void TestBoard( HWND hWnd, BOARD *p_board, unsigned x, unsigned y, int msg );
+
+void TestMines( BOARD *p_board, POINT pt, int msg );
+
+void TestFace( BOARD *p_board, POINT pt, int msg );
+
+void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board );
+
+void DrawMines( HDC hdc, HDC hMemDC, BOARD *p_board );
+
+void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed );
+
+void AddFlag( BOARD *p_board, unsigned col, unsigned row );
+
+void CompleteBox( BOARD *p_board, unsigned col, unsigned row );
+
+void CompleteBoxes( BOARD *p_board, unsigned col, unsigned row );
+
+void PressBox( BOARD *p_board, unsigned col, unsigned row );
+
+void PressBoxes( BOARD *p_board, unsigned col, unsigned row );
+
+void UnpressBox( BOARD *p_board, unsigned col, unsigned row );
+
+void UnpressBoxes( BOARD *p_board, unsigned col, unsigned row );
+
+void UpdateTimer( BOARD *p_board );
+
+void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y);
+
+void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board );
+
+LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK CustomDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK CongratsDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK TimesDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+BOOL CALLBACK AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+/* end of header */
--- /dev/null
+/*
+ * WineMine (resource.h)
+ *
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#define ID_TIMER 1000
+
+/* menu defines */
+#define IDM_NEW 1001
+#define IDM_EXIT 1002
+#define IDM_TIMES 1003
+#define IDM_ABOUT 1004
+#define IDM_BEGINNER 1005
+#define IDM_ADVANCED 1006
+#define IDM_EXPERT 1007
+#define IDM_CUSTOM 1008
+#define IDM_MARKQ 1009
+
+#define IDC_TIME1 1011
+#define IDC_TIME2 1012
+#define IDC_TIME3 1013
+#define IDC_NAME1 1014
+#define IDC_NAME2 1015
+#define IDC_NAME3 1016
+
+#define IDC_EDITNAME 1021
+
+#define IDC_EDITCOLS 1031
+#define IDC_EDITROWS 1032
+#define IDC_EDITMINES 1033
+
+#define IDS_APPNAME 1101
+
+#define IDI_WINEMINE 1201
+
+#define IDB_FACES 1301
+#define IDB_LEDS 1302
+#define IDB_MINES 1303
--- /dev/null
+/*
+ * WineMine (rsrc.rc)
+ *
+ * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <windows.h>
+#include "resource.h"
+
+#include "En.rc"
+#include "De.rc"
+
+IDI_WINEMINE ICON MOVEABLE "rc/winemine.ico"
+
+IDB_FACES BITMAP MOVEABLE "rc/faces.bmp"
+
+IDB_LEDS BITMAP MOVEABLE "rc/leds.bmp"
+
+IDB_MINES BITMAP MOVEABLE "rc/mines.bmp"
+
--- /dev/null
+<module name="winemine" type="win32gui" installbase="system32" installname="winemine.exe">
+ <include base="winemine">.</include>
+ <define name="__USE_W32API" />
+ <define name="_WIN32_IE">0x0501</define>
+ <define name="_WIN32_WINNT">0x0501</define>
+ <library>kernel32</library>
+ <library>gdi32</library>
+ <file>main.c</file>
+ <file>dialog.c</file>
+ <file>winemine.rc</file>
+</module>