imported catch-22 sol clone with authors permission
authorSteven Edwards <winehacker@gmail.com>
Thu, 10 Mar 2005 04:04:27 +0000 (04:04 +0000)
committerSteven Edwards <winehacker@gmail.com>
Thu, 10 Mar 2005 04:04:27 +0000 (04:04 +0000)
svn path=/trunk/; revision=13904

32 files changed:
rosapps/games/solitaire/ReadMe.txt [new file with mode: 0644]
rosapps/games/solitaire/cardlib/card.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardbitmaps.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardbutton.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardbutton.cpp.bak [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardbutton.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardcolor.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardcolor.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardcount.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardcount.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardlib.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardlib.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardregion.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardregion.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardrgndraw.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp.bak [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardstack.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardstack.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardwindow.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/cardwindow.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/dropzone.cpp [new file with mode: 0644]
rosapps/games/solitaire/cardlib/dropzone.h [new file with mode: 0644]
rosapps/games/solitaire/cardlib/globals.h [new file with mode: 0644]
rosapps/games/solitaire/icon1.ico [new file with mode: 0644]
rosapps/games/solitaire/makefile [new file with mode: 0644]
rosapps/games/solitaire/resource.h [new file with mode: 0644]
rosapps/games/solitaire/sol.rc [new file with mode: 0644]
rosapps/games/solitaire/solcreate.cpp [new file with mode: 0644]
rosapps/games/solitaire/solgame.cpp [new file with mode: 0644]
rosapps/games/solitaire/solitaire.cpp [new file with mode: 0644]
rosapps/games/solitaire/solitaire.h [new file with mode: 0644]

diff --git a/rosapps/games/solitaire/ReadMe.txt b/rosapps/games/solitaire/ReadMe.txt
new file mode 100644 (file)
index 0000000..90bd89b
--- /dev/null
@@ -0,0 +1,22 @@
+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
diff --git a/rosapps/games/solitaire/cardlib/card.h b/rosapps/games/solitaire/cardlib/card.h
new file mode 100644 (file)
index 0000000..13dc190
--- /dev/null
@@ -0,0 +1,105 @@
+//\r
+//     CardLib - Card class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+\r
+#ifndef _CARD_INCLUDED\r
+#define _CARD_INCLUDED\r
+\r
+enum eSuit  { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 };\r
+enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, \r
+              Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 };\r
+\r
+inline int MAKE_CARD(int Value, int Suit)\r
+{\r
+       if(Value < 1)   Value = 1;\r
+       if(Value == 14) Value = 1;\r
+       if(Value >  13) Value = 13;\r
+\r
+       if(Suit < 0)    Suit = 0;\r
+       if(Suit > 3)    Suit = 3;\r
+\r
+       return ((Value - 1) * 4 + Suit);\r
+}\r
+\r
+class Card\r
+{\r
+       friend class CardStack;\r
+\r
+public:\r
+\r
+       Card() \r
+       { \r
+               nValue = 0;             //ace of spades by default\r
+               fFaceUp = true; \r
+       }\r
+       \r
+       Card(int value, int suit)       //specify a face value [1-13] and suit [0-3]\r
+       { \r
+               nValue = MAKE_CARD(value, suit);\r
+               fFaceUp = true; \r
+       }\r
+       \r
+       Card(int index)                         //specify a 0-51 index\r
+       { \r
+               if(index < 0)  index = 0;\r
+               if(index > 51) index = 51;\r
+\r
+               nValue = index; \r
+               fFaceUp = true;\r
+       }\r
+       \r
+       int Suit() const\r
+       { \r
+               return (nValue % 4); \r
+       }\r
+\r
+       int LoVal() const\r
+       { \r
+               return (nValue / 4) + 1; \r
+       }\r
+\r
+       int HiVal() const\r
+       { \r
+               return ((nValue < 4) ? 14 : (nValue / 4) + 1); \r
+       }\r
+\r
+       int Idx() const //unique value (0-51 etc)\r
+       {\r
+               return nValue;\r
+       }\r
+\r
+       bool FaceUp() const\r
+       {\r
+               return fFaceUp;\r
+       }\r
+       \r
+       bool FaceDown() const\r
+       {\r
+               return !fFaceUp;\r
+       }\r
+\r
+       void SetFaceUp(bool fTrue)\r
+       {\r
+               fFaceUp = fTrue;\r
+       }\r
+\r
+       bool IsBlack() const\r
+       {\r
+               return Suit() == 0 || Suit() == 3;\r
+       }\r
+\r
+       bool IsRed() const\r
+       {\r
+               return !IsBlack();\r
+       }\r
+\r
+private:\r
+\r
+       int  nValue;\r
+       bool fFaceUp;\r
+};\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardbitmaps.cpp b/rosapps/games/solitaire/cardlib/cardbitmaps.cpp
new file mode 100644 (file)
index 0000000..530f651
--- /dev/null
@@ -0,0 +1,281 @@
+//\r
+//     CardLib - Card bitmap support\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include "globals.h"\r
+#include "cardcolor.h"\r
+\r
+#ifndef __REACTOS__\r
+#pragma comment( lib, "..\\CardLib\\cards16.lib" )\r
+\r
+extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR );\r
+extern "C" void                 WINAPI FreeLibrary16( HINSTANCE );\r
+#endif\r
+\r
+#define NUMCARDBITMAPS (52+16)\r
+\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF col);\r
+\r
+void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight)\r
+{\r
+       HBITMAP   hBitmap;\r
+       HDC               hdcCard;\r
+       HANDLE    hOld;\r
+       int             i, xpos;\r
+       int             width, height;\r
+       BITMAP bmp;\r
+\r
+       for(i = 0; i < NUMCARDBITMAPS; i++)\r
+       {\r
+               //convert into the range used by the cdt_xxx functions\r
+               int val;\r
+               \r
+               if(i < 52) val = (i % 4) * 13 + (i/4);\r
+               else       val = i;\r
+               \r
+               hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1));\r
+               GetObject(hBitmap, sizeof(bmp), &bmp);\r
+               \r
+               width  = bmp.bmWidth;\r
+               height = bmp.bmHeight;\r
+               \r
+               if(i == 0)      //if first time through, create BIG bitmap..\r
+               {\r
+                       HDC hdc = GetDC(0);\r
+                       __hdcCardBitmaps = CreateCompatibleDC(hdc);\r
+                       __hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height);\r
+                       SelectObject(__hdcCardBitmaps, __hbmCardBitmaps);\r
+                       \r
+                       hdcCard = CreateCompatibleDC(0);\r
+                       \r
+                       ReleaseDC(0, hdc);\r
+               }\r
+               \r
+               hOld = SelectObject(hdcCard, hBitmap);\r
+               BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY);\r
+               SelectObject(hdcCard, hOld);\r
+               \r
+               //Now draw a black border around each card...\r
+               xpos = i*width;\r
+               MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0);\r
+               LineTo(__hdcCardBitmaps, xpos+width - 3, 0);\r
+               LineTo(__hdcCardBitmaps, xpos+width - 1, 2);\r
+               LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3);   //vertical\r
+               LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1);\r
+               LineTo(__hdcCardBitmaps, xpos+2, height - 1);\r
+               LineTo(__hdcCardBitmaps, xpos+0, height - 3);\r
+               LineTo(__hdcCardBitmaps, xpos+0, 2);\r
+               LineTo(__hdcCardBitmaps, xpos+2, 0);\r
+               \r
+               DeleteObject(hBitmap);\r
+       }\r
+       \r
+       DeleteDC(hdcCard);\r
+\r
+       *pwidth = width;\r
+       *pheight = height;\r
+                               \r
+}\r
+\r
+void LoadCardBitmaps(void)\r
+{\r
+       HINSTANCE hCardDll;\r
+       \r
+\r
+       //If Windows NT/2000/XP\r
+       if(GetVersion() < 0x80000000)\r
+       {\r
+               hCardDll = LoadLibrary("cards.dll");\r
+\r
+               if(hCardDll == 0)\r
+               {\r
+                       MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);\r
+                       PostQuitMessage(0);\r
+                       return;\r
+               }\r
+               \r
+               LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);\r
+               \r
+               FreeLibrary(hCardDll);\r
+       }\r
+#ifndef __REACTOS__\r
+       //Else, Win9X\r
+       else\r
+       {\r
+               hCardDll = LoadLibrary16("cards.dll");\r
+\r
+               if(hCardDll == 0)\r
+               {\r
+                       MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);\r
+                       PostQuitMessage(0);\r
+                       return;\r
+               }\r
+\r
+               LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);\r
+\r
+               FreeLibrary16(hCardDll);\r
+       }\r
+#endif\r
+}\r
+\r
+void FreeCardBitmaps()\r
+{\r
+       DeleteObject (__hbmCardBitmaps);\r
+       DeleteDC     (__hdcCardBitmaps);\r
+}\r
+//\r
+//     Paint a checkered rectangle, with each alternate\r
+//     pixel being assigned a different colour\r
+//\r
+static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)\r
+{\r
+       static WORD wCheckPat[8] = \r
+       { \r
+               0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 \r
+       };\r
+\r
+       HBITMAP hbmp;\r
+       HBRUSH  hbr, hbrold;\r
+       COLORREF fgold, bgold;\r
+\r
+       hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);\r
+       hbr  = CreatePatternBrush(hbmp);\r
+\r
+       //UnrealizeObject(hbr);\r
+\r
+       SetBrushOrgEx(hdc, rect->left, rect->top, 0);\r
+\r
+       hbrold = (HBRUSH)SelectObject(hdc, hbr);\r
+\r
+       fgold = SetTextColor(hdc, fg);\r
+       bgold = SetBkColor(hdc, bg);\r
+       \r
+       PatBlt(hdc, rect->left, rect->top, \r
+                               rect->right - rect->left, \r
+                               rect->bottom - rect->top, \r
+                               PATCOPY);\r
+       \r
+       SetBkColor(hdc, bgold);\r
+       SetTextColor(hdc, fgold);\r
+       \r
+       SelectObject(hdc, hbrold);\r
+       DeleteObject(hbr);\r
+       DeleteObject(hbmp);\r
+}\r
+\r
+void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2)\r
+{\r
+       if(bg) *bg       = crBase;\r
+       if(fg) *fg   = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140);\r
+       if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4);\r
+       if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2);\r
+}\r
+\r
+HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height)\r
+{\r
+       HANDLE hold, hpold;\r
+       HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height);\r
+\r
+       HPEN hpfg, hpbg, hpsh, hpsh2;\r
+\r
+       RECT rect;\r
+       COLORREF fg, bg, shadow, shadow2;\r
+\r
+       GetSinkCols(col, &fg, &bg, &shadow, &shadow2);\r
+\r
+       hold = SelectObject(hdc, hbm);\r
+\r
+       //fill with a solid base colour\r
+       SetRect(&rect, 0,0,width,height);\r
+       PaintRect(hdc, &rect, MAKE_PALETTERGB(bg));\r
+\r
+       //draw the outline\r
+       hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg));\r
+       hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg));\r
+       hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow));\r
+       hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2));        \r
+\r
+       hpold = SelectObject(hdc, hpsh);\r
+       MoveToEx(hdc, 2, 0, NULL);\r
+       LineTo  (hdc, width-3,0);\r
+       LineTo  (hdc, width-1, 2);\r
+       \r
+       SelectObject(hdc, hpold);\r
+       hpold = SelectObject(hdc, hpsh2);\r
+       LineTo  (hdc, width-1, height-3);       //vertical\r
+       LineTo  (hdc, width-3, height-1);\r
+       LineTo  (hdc, 2, height-1);\r
+       LineTo  (hdc, 0, height-3);\r
+       SelectObject(hdc, hpold);\r
+       hpold = SelectObject(hdc, hpsh);\r
+\r
+       //MoveToEx( hdc, 0, height-3,0);\r
+       LineTo  (hdc, 0, 2);\r
+       LineTo  (hdc, 2, 0);\r
+\r
+       SelectObject(hdc, hpold);\r
+\r
+       //draw the highlight (vertical)\r
+       hpold = SelectObject(hdc, hpfg);\r
+       MoveToEx(hdc, width - 2, 3, NULL);\r
+       LineTo  (hdc, width - 2, height - 2);\r
+       \r
+       //(horz)\r
+       MoveToEx(hdc, width - 3, height-2, NULL);\r
+       LineTo  (hdc, 3, height-2);\r
+       SelectObject(hdc, hpold);\r
+       \r
+       //draw the background\r
+       InflateRect(&rect, -2, -2);\r
+       DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg));\r
+\r
+       //overwrite the top-left background pixel\r
+       SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg));\r
+\r
+       DeleteObject(hpsh);\r
+       DeleteObject(hpsh2);\r
+       DeleteObject(hpfg);\r
+       DeleteObject(hpbg);\r
+\r
+       \r
+       return hbm;\r
+}\r
+\r
+\r
+\r
+void CopyColor(PALETTEENTRY *pe, COLORREF col)\r
+{\r
+       pe->peBlue  = GetBValue(col);\r
+       pe->peGreen = GetGValue(col);\r
+       pe->peRed   = GetRValue(col);\r
+       pe->peFlags = 0;\r
+}\r
+\r
+HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours)\r
+{\r
+       LOGPALETTE      *lp;\r
+       HPALETTE        hPalette;\r
+\r
+       //      Allocate memory for the logical palette\r
+       lp = (LOGPALETTE *)HeapAlloc(\r
+               GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours);\r
+\r
+       lp->palNumEntries = nNumColours;\r
+       lp->palVersion    = 0x300;\r
+\r
+       //copy the colours into the logical palette format\r
+       for(int i = 0; i < nNumColours; i++)\r
+       {\r
+               CopyColor(&lp->palPalEntry[i], cols[i]);\r
+       }\r
+\r
+       // create palette!\r
+       hPalette = CreatePalette(lp);\r
+\r
+       HeapFree(GetProcessHeap(), 0, lp);\r
+\r
+       return hPalette;\r
+}\r
diff --git a/rosapps/games/solitaire/cardlib/cardbutton.cpp b/rosapps/games/solitaire/cardlib/cardbutton.cpp
new file mode 100644 (file)
index 0000000..a0a2b3a
--- /dev/null
@@ -0,0 +1,489 @@
+//\r
+//     CardLib - CardButton class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <tchar.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardwindow.h"\r
+#include "cardbutton.h"\r
+#include "cardcolor.h"\r
+\r
+HPALETTE UseNicePalette(HDC, HPALETTE);\r
+void    RestorePalette(HDC, HPALETTE);\r
+\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
+\r
+CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,\r
+                                               int x, int y, int width, int height)\r
+\r
+ : parentWnd(parent), id(Id), fVisible(visible), uStyle(Style), ButtonCallback(0)\r
+{\r
+       crText = RGB(255,255,255);\r
+       crBack = RGB(0, 128, 0);\r
+       \r
+       xadjust = 0;\r
+       yadjust = 0;\r
+       xjustify = 0;\r
+       yjustify = 0;\r
+\r
+       fMouseDown = false;\r
+       fButtonDown = false;\r
+\r
+       hIcon = 0;\r
+\r
+       SetText(szText);\r
+       Move(x, y, width, height);\r
+\r
+       mxlock = CreateMutex(0, FALSE, 0);\r
+\r
+       hFont = 0;\r
+}\r
+\r
+CardButton::~CardButton()\r
+{\r
+       CloseHandle(mxlock);\r
+}\r
+\r
+void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)\r
+{\r
+       RECT fill;\r
+\r
+       HANDLE hOld;\r
+\r
+       HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));\r
+       HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));\r
+       HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);\r
+       \r
+       int x           = rect->left;\r
+       int y           = rect->top;\r
+       int width       = rect->right-rect->left - 1;\r
+       int height      = rect->bottom-rect->top - 1;\r
+       \r
+       SetRect(&fill, x+1, y+1, x+width-1, y+height-1);\r
+\r
+       int one = 1;\r
+       \r
+       if(!fNormal)\r
+       {\r
+               x += width;\r
+               y += height;\r
+               width = -width;\r
+               height = -height;\r
+               one = -1;\r
+               OffsetRect(&fill, 1, 1);\r
+       }\r
+       \r
+       if(fNormal)\r
+               hOld = SelectObject(hdc, hhi);\r
+       else\r
+               hOld = SelectObject(hdc, hhi);\r
+\r
+       MoveToEx(hdc, x, y+height, 0);\r
+       LineTo(hdc, x, y);\r
+       LineTo(hdc, x+width, y);\r
+       SelectObject(hdc, hOld);\r
+\r
+       hOld = SelectObject(hdc, hbl);\r
+       LineTo(hdc, x+width, y+height);\r
+       LineTo(hdc, x-one, y+height);\r
+       SelectObject(hdc, hOld);\r
+\r
+       hOld = SelectObject(hdc, hsh);\r
+       MoveToEx(hdc, x+one, y+height-one, 0);\r
+       LineTo(hdc, x+width-one, y+height-one);\r
+       LineTo(hdc, x+width-one, y);\r
+       SelectObject(hdc, hOld);\r
+\r
+       PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));\r
+\r
+       DeleteObject(hhi);\r
+       DeleteObject(hsh);\r
+}\r
+\r
+void CardButton::Clip(HDC hdc)\r
+{\r
+       if(fVisible == false) return;\r
+       \r
+       ExcludeClipRect(hdc, rect.left,  rect.top, rect.right, rect.bottom);\r
+}\r
+\r
+void CardButton::Draw(HDC hdc, bool fNormal)\r
+{\r
+       SIZE textsize;\r
+       int x, y;               //text x, y\r
+       int ix, iy;             //icon x, y\r
+       int iconwidth = 0;\r
+\r
+       RECT cliprect;\r
+\r
+       if(fVisible == 0) return;\r
+\r
+       if(hFont == 0)\r
+               SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));    \r
+       else\r
+               SelectObject(hdc, hFont);       \r
+       \r
+       GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);\r
+       \r
+       if(hIcon)\r
+       {\r
+               x = rect.left + 32 + 8;\r
+       }\r
+       else\r
+       {\r
+               if(uStyle & CB_ALIGN_LEFT)\r
+               {\r
+                       x = rect.left + iconwidth;\r
+               }\r
+               else if(uStyle & CB_ALIGN_RIGHT)\r
+               {\r
+                       x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);\r
+               }\r
+               else    //centered\r
+               {\r
+                       x = rect.right - rect.left - iconwidth;\r
+                       x = (x - textsize.cx) / 2;\r
+                       x += rect.left + iconwidth;\r
+               }\r
+       }\r
+       \r
+       y = rect.bottom - rect.top;\r
+       y = (y - textsize.cy) / 2;\r
+       y += rect.top;\r
+       \r
+       //calc icon position..\r
+       ix = rect.left + 4;\r
+       iy = rect.top + (rect.bottom-rect.top-32) / 2;\r
+\r
+       //if button is pressed, then shift text\r
+       if(fNormal == false && (uStyle & CB_PUSHBUTTON))\r
+       {\r
+               x += 1;\r
+               y += 1;\r
+               ix += 1;\r
+               iy += 1;\r
+       }\r
+\r
+       SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);\r
+       ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);\r
+\r
+       //\r
+       //      Calc icon pos\r
+       //\r
+       \r
+       if(hIcon)\r
+       {\r
+               ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);\r
+       }\r
+       \r
+       if(uStyle & CB_PUSHBUTTON)\r
+       {\r
+               DrawRect(hdc, &rect, fNormal);\r
+\r
+               SetBkColor(hdc,   MAKE_PALETTERGB(crBack));\r
+               SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
+               \r
+               SelectClipRgn(hdc, 0);          \r
+\r
+               ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);\r
+       }\r
+       else\r
+       {\r
+               SetBkColor(hdc,   MAKE_PALETTERGB(crBack));\r
+               SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
+\r
+               SelectClipRgn(hdc, 0);\r
+\r
+               ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);\r
+       }\r
+\r
+       if(hIcon)\r
+       {\r
+               HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));\r
+               DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);\r
+               DeleteObject(hbr);\r
+       }\r
+\r
+}\r
+\r
+void CardButton::AdjustPosition(int winwidth, int winheight)\r
+{\r
+       int width = rect.right-rect.left;\r
+       int height = rect.bottom-rect.top;\r
+\r
+       width = width & ~0x1;\r
+\r
+       switch(xjustify)\r
+       {\r
+       case CS_XJUST_NONE:\r
+               break;\r
+\r
+       case CS_XJUST_CENTER:           //centered\r
+               rect.left = (winwidth - (width)) / 2;\r
+               rect.left += xadjust;\r
+               rect.right = rect.left+width;\r
+               break;\r
+\r
+       case CS_XJUST_RIGHT:            //right-aligned\r
+               rect.left = winwidth - width;\r
+               rect.left += xadjust;\r
+               rect.right = rect.left+width;\r
+               break;\r
+       }\r
+\r
+       switch(yjustify)\r
+       {\r
+       case CS_YJUST_NONE:\r
+               break;\r
+\r
+       case CS_YJUST_CENTER:           //centered\r
+               rect.top = (winheight - (height)) / 2;\r
+               rect.top += yadjust;\r
+               rect.bottom = rect.top+height;\r
+               break;\r
+\r
+       case CS_YJUST_BOTTOM:           //right-aligned\r
+               rect.top = winheight - height;\r
+               rect.top += yadjust;\r
+               rect.bottom = rect.top+height;\r
+               break;\r
+       }\r
+\r
+}\r
+\r
+int CardButton::OnLButtonDown(HWND hwnd, int x, int y)\r
+{\r
+       if((uStyle & CB_PUSHBUTTON) == 0) \r
+               return 0;\r
+\r
+       //make sure that the user is allowed to do something\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+               return 0;\r
+       }\r
+       else\r
+       {\r
+               ReleaseMutex(mxlock);\r
+       }\r
+       \r
+       fMouseDown = true;\r
+       fButtonDown = true;\r
+\r
+       Redraw();\r
+\r
+       SetCapture(hwnd);\r
+\r
+       return 1;\r
+}\r
+\r
+int CardButton::OnMouseMove(HWND hwnd, int x, int y)\r
+{\r
+       if(fMouseDown)\r
+       {\r
+               bool fOldButtonDown = fButtonDown;\r
+\r
+               POINT pt;\r
+               \r
+               pt.x = x;\r
+               pt.y = y;\r
+               \r
+               if(PtInRect(&rect, pt))\r
+                       fButtonDown = true;\r
+               else\r
+                       fButtonDown = false;\r
+               \r
+               if(fButtonDown != fOldButtonDown)\r
+                       Redraw();\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+int CardButton::OnLButtonUp(HWND hwnd, int x, int y)\r
+{\r
+       if(fMouseDown)\r
+       {\r
+               fMouseDown = false;\r
+               fButtonDown = false;\r
+               \r
+               if(uStyle & CB_PUSHBUTTON)\r
+               {\r
+                       Redraw();\r
+                       ReleaseCapture();\r
+               }\r
+               \r
+               //if have clicked the button\r
+               if(parentWnd.CardButtonFromPoint(x, y) == this)\r
+               {\r
+                       if(ButtonCallback)\r
+                       {\r
+                               ButtonCallback(*this);  \r
+                       }\r
+                       else\r
+                       {\r
+                               HWND hwnd = (HWND)parentWnd;\r
+                               SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+#define _countof(array) (sizeof(array)/sizeof(array[0]))\r
+\r
+CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)\r
+{\r
+       CardButton *cb;\r
+\r
+       if(nNumButtons == MAXBUTTONS) \r
+               return 0;\r
+\r
+       cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);\r
+       Buttons[nNumButtons++] = cb;\r
+\r
+       if(uStyle & CB_PUSHBUTTON)\r
+       {\r
+               cb->SetBackColor(CardButton::GetFace(crBackgnd));\r
+               //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));\r
+               cb->SetForeColor(RGB(255,255,255));\r
+       }\r
+       else\r
+       {\r
+               cb->SetBackColor(crBackgnd);\r
+               cb->SetForeColor(RGB(255,255,255));\r
+       }\r
+       \r
+       return cb;\r
+}\r
+\r
+void CardButton::SetText(TCHAR *lpszFormat, ...)\r
+{\r
+       int count;\r
+\r
+       va_list args;\r
+       va_start(args, lpszFormat);\r
+\r
+       count = wvsprintf(szText, lpszFormat, args);\r
+       va_end(args);\r
+}\r
+\r
+int CardButton::Id()\r
+{\r
+       return id;\r
+}\r
+\r
+void CardButton::Show(bool fShow)\r
+{\r
+       fVisible = fShow;\r
+}\r
+\r
+void CardButton::Move(int x, int y, int width, int height)\r
+{\r
+       SetRect(&rect, x, y, x+width, y+height);\r
+}\r
+\r
+void CardButton::Redraw()\r
+{\r
+       HDC hdc = GetDC((HWND)parentWnd);\r
+\r
+       HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);\r
+\r
+       Draw(hdc, !fButtonDown);\r
+       \r
+       RestorePalette(hdc, hOldPal);\r
+       \r
+       ReleaseDC((HWND)parentWnd, hdc);\r
+}\r
+\r
+void CardButton::SetForeColor(COLORREF cr)\r
+{\r
+       crText = cr;\r
+}\r
+\r
+void CardButton::SetBackColor(COLORREF cr)\r
+{\r
+       crBack = cr;\r
+\r
+       crHighlight = GetHighlight(cr);\r
+       crShadow    = GetShadow(cr);\r
+       \r
+       //crHighlight = ScaleLumRGB(cr, +0.25);\r
+       //crShadow    = ScaleLumRGB(cr, -0.25);\r
+}\r
+\r
+//     Static member\r
+COLORREF CardButton::GetHighlight(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);\r
+}\r
+\r
+//     Static member\r
+COLORREF CardButton::GetShadow(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(0,  0,  0),   0.25);\r
+}\r
+\r
+COLORREF CardButton::GetFace(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);\r
+}\r
+\r
+void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)\r
+{\r
+       xadjust = xAdjust;\r
+       yadjust = yAdjust;\r
+       xjustify = xJustify;\r
+       yjustify = yJustify;\r
+}\r
+\r
+void CardButton::SetIcon(HICON hicon, bool fRedraw)\r
+{\r
+       hIcon = hicon;\r
+       \r
+       if(fRedraw)\r
+               Redraw();\r
+}\r
+\r
+void CardButton::SetFont(HFONT font)\r
+{\r
+       //don't delete the existing font..\r
+       hFont = font;\r
+}\r
+\r
+void CardButton::SetButtonProc(pButtonProc proc)\r
+{\r
+       ButtonCallback  = proc;\r
+}\r
+\r
+bool CardButton::Lock()\r
+{\r
+       DWORD dw = WaitForSingleObject(mxlock, 0);\r
+\r
+       if(dw == WAIT_OBJECT_0)\r
+               return true; \r
+       else\r
+               return false;\r
+}\r
+\r
+bool CardButton::UnLock()\r
+{\r
+       if(ReleaseMutex(mxlock))\r
+               return true;\r
+       else\r
+               return false;\r
+}\r
+\r
+void CardButton::SetStyle(UINT style)\r
+{\r
+       uStyle = style;\r
+}\r
+\r
+UINT CardButton::GetStyle()\r
+{\r
+       return uStyle;\r
+}\r
diff --git a/rosapps/games/solitaire/cardlib/cardbutton.cpp.bak b/rosapps/games/solitaire/cardlib/cardbutton.cpp.bak
new file mode 100644 (file)
index 0000000..123f254
--- /dev/null
@@ -0,0 +1,489 @@
+//\r
+//     CardLib - CardButton class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <tchar.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardwindow.h"\r
+#include "cardbutton.h"\r
+#include "cardcolor.h"\r
+\r
+HPALETTE UseNicePalette(HDC, HPALETTE);\r
+void    RestorePalette(HDC, HPALETTE);\r
+\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
+\r
+CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,\r
+                                               int x, int y, int width, int height)\r
+\r
+ : parentWnd(parent), id(Id), fVisible(visible), uStyle(Style), ButtonCallback(0)\r
+{\r
+       crText = RGB(255,255,255);\r
+       crBack = RGB(0, 128, 0);\r
+       \r
+       xadjust = 0;\r
+       yadjust = 0;\r
+       xjustify = 0;\r
+       yjustify = 0;\r
+\r
+       fMouseDown = false;\r
+       fButtonDown = false;\r
+\r
+       hIcon = 0;\r
+\r
+       SetText(szText);\r
+       Move(x, y, width, height);\r
+\r
+       mxlock = CreateMutex(0, FALSE, 0);\r
+\r
+       hFont = 0;\r
+}\r
+\r
+CardButton::~CardButton()\r
+{\r
+       CloseHandle(mxlock);\r
+}\r
+\r
+void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)\r
+{\r
+       RECT fill;\r
+\r
+       HANDLE hOld;\r
+\r
+       HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));\r
+       HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));\r
+       HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);\r
+       \r
+       int x           = rect->left;\r
+       int y           = rect->top;\r
+       int width       = rect->right-rect->left - 1;\r
+       int height      = rect->bottom-rect->top - 1;\r
+       \r
+       SetRect(&fill, x+1, y+1, x+width-1, y+height-1);\r
+\r
+       int one = 1;\r
+       \r
+       if(!fNormal)\r
+       {\r
+               x += width;\r
+               y += height;\r
+               width = -width;\r
+               height = -height;\r
+               one = -1;\r
+               OffsetRect(&fill, 1, 1);\r
+       }\r
+       \r
+       if(fNormal)\r
+               hOld = SelectObject(hdc, hhi);\r
+       else\r
+               hOld = SelectObject(hdc, hhi);\r
+\r
+       MoveToEx(hdc, x, y+height, 0);\r
+       LineTo(hdc, x, y);\r
+       LineTo(hdc, x+width, y);\r
+       SelectObject(hdc, hOld);\r
+\r
+       hOld = SelectObject(hdc, hbl);\r
+       LineTo(hdc, x+width, y+height);\r
+       LineTo(hdc, x-one, y+height);\r
+       SelectObject(hdc, hOld);\r
+\r
+       hOld = SelectObject(hdc, hsh);\r
+       MoveToEx(hdc, x+one, y+height-one, 0);\r
+       LineTo(hdc, x+width-one, y+height-one);\r
+       LineTo(hdc, x+width-one, y);\r
+       SelectObject(hdc, hOld);\r
+\r
+       PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));\r
+\r
+       DeleteObject(hhi);\r
+       DeleteObject(hsh);\r
+}\r
+\r
+void CardButton::Clip(HDC hdc)\r
+{\r
+       if(fVisible == false) return;\r
+       \r
+       ExcludeClipRect(hdc, rect.left,  rect.top, rect.right, rect.bottom);\r
+}\r
+\r
+void CardButton::Draw(HDC hdc, bool fNormal)\r
+{\r
+       SIZE textsize;\r
+       int x, y;               //text x, y\r
+       int ix, iy;             //icon x, y\r
+       int iconwidth = 0;\r
+\r
+       RECT cliprect;\r
+\r
+       if(fVisible == 0) return;\r
+\r
+       if(hFont == 0)\r
+               SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));    \r
+       else\r
+               SelectObject(hdc, hFont);       \r
+       \r
+       GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);\r
+       \r
+       if(hIcon)\r
+       {\r
+               x = rect.left + 32 + 8;\r
+       }\r
+       else\r
+       {\r
+               if(uStyle & CB_ALIGN_LEFT)\r
+               {\r
+                       x = rect.left + iconwidth;\r
+               }\r
+               else if(uStyle & CB_ALIGN_RIGHT)\r
+               {\r
+                       x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);\r
+               }\r
+               else    //centered\r
+               {\r
+                       x = rect.right - rect.left - iconwidth;\r
+                       x = (x - textsize.cx) / 2;\r
+                       x += rect.left + iconwidth;\r
+               }\r
+       }\r
+       \r
+       y = rect.bottom - rect.top;\r
+       y = (y - textsize.cy) / 2;\r
+       y += rect.top;\r
+       \r
+       //calc icon position..\r
+       ix = rect.left + 4;\r
+       iy = rect.top + (rect.bottom-rect.top-32) / 2;\r
+\r
+       //if button is pressed, then shift text\r
+       if(fNormal == false && (uStyle & CB_PUSHBUTTON))\r
+       {\r
+               x += 1;\r
+               y += 1;\r
+               ix += 1;\r
+               iy += 1;\r
+       }\r
+\r
+       SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);\r
+       ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);\r
+\r
+       //\r
+       //      Calc icon pos\r
+       //\r
+       \r
+       if(hIcon)\r
+       {\r
+               ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);\r
+       }\r
+       \r
+       if(uStyle & CB_PUSHBUTTON)\r
+       {\r
+               DrawRect(hdc, &rect, fNormal);\r
+\r
+               SetBkColor(hdc,   MAKE_PALETTERGB(crBack));\r
+               SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
+               \r
+               SelectClipRgn(hdc, 0);          \r
+\r
+               ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);\r
+       }\r
+       else\r
+       {\r
+               SetBkColor(hdc,   MAKE_PALETTERGB(crBack));\r
+               SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
+\r
+               SelectClipRgn(hdc, 0);\r
+\r
+               ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);\r
+       }\r
+\r
+       if(hIcon)\r
+       {\r
+               HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));\r
+               DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);\r
+               DeleteObject(hbr);\r
+       }\r
+\r
+}\r
+\r
+void CardButton::AdjustPosition(int winwidth, int winheight)\r
+{\r
+       int width = rect.right-rect.left;\r
+       int height = rect.bottom-rect.top;\r
+\r
+       width = width & ~0x1;\r
+\r
+       switch(xjustify)\r
+       {\r
+       case CS_XJUST_NONE:\r
+               break;\r
+\r
+       case CS_XJUST_CENTER:           //centered\r
+               rect.left = (winwidth - (width)) / 2;\r
+               rect.left += xadjust;\r
+               rect.right = rect.left+width;\r
+               break;\r
+\r
+       case CS_XJUST_RIGHT:            //right-aligned\r
+               rect.left = winwidth - width;\r
+               rect.left += xadjust;\r
+               rect.right = rect.left+width;\r
+               break;\r
+       }\r
+\r
+       switch(yjustify)\r
+       {\r
+       case CS_YJUST_NONE:\r
+               break;\r
+\r
+       case CS_YJUST_CENTER:           //centered\r
+               rect.top = (winheight - (height)) / 2;\r
+               rect.top += yadjust;\r
+               rect.bottom = rect.top+height;\r
+               break;\r
+\r
+       case CS_YJUST_BOTTOM:           //right-aligned\r
+               rect.top = winheight - height;\r
+               rect.top += yadjust;\r
+               rect.bottom = rect.top+height;\r
+               break;\r
+       }\r
+\r
+}\r
+\r
+int CardButton::OnLButtonDown(HWND hwnd, int x, int y)\r
+{\r
+       if((uStyle & CB_PUSHBUTTON) == 0) \r
+               return 0;\r
+\r
+       //make sure that the user is allowed to do something\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+               return 0;\r
+       }\r
+       else\r
+       {\r
+               ReleaseMutex(mxlock);\r
+       }\r
+       \r
+       fMouseDown = true;\r
+       fButtonDown = true;\r
+\r
+       Redraw();\r
+\r
+       SetCapture(hwnd);\r
+\r
+       return 1;\r
+}\r
+\r
+int CardButton::OnMouseMove(HWND hwnd, int x, int y)\r
+{\r
+       if(fMouseDown)\r
+       {\r
+               bool fOldButtonDown = fButtonDown;\r
+\r
+               POINT pt;\r
+               \r
+               pt.x = x;\r
+               pt.y = y;\r
+               \r
+               if(PtInRect(&rect, pt))\r
+                       fButtonDown = true;\r
+               else\r
+                       fButtonDown = false;\r
+               \r
+               if(fButtonDown != fOldButtonDown)\r
+                       Redraw();\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+int CardButton::OnLButtonUp(HWND hwnd, int x, int y)\r
+{\r
+       if(fMouseDown)\r
+       {\r
+               fMouseDown = false;\r
+               fButtonDown = false;\r
+               \r
+               if(uStyle & CB_PUSHBUTTON)\r
+               {\r
+                       Redraw();\r
+                       ReleaseCapture();\r
+               }\r
+               \r
+               //if have clicked the button\r
+               if(parentWnd.CardButtonFromPoint(x, y) == this)\r
+               {\r
+                       if(ButtonCallback)\r
+                       {\r
+                               ButtonCallback(*this);  \r
+                       }\r
+                       else\r
+                       {\r
+                               HWND hwnd = (HWND)parentWnd;\r
+                               SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+#define _countof(array) (sizeof(array)/sizeof(array[0]))\r
+\r
+CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)\r
+{\r
+       CardButton *cb;\r
+\r
+       if(nNumButtons == MAXBUTTONS) \r
+               return 0;\r
+\r
+       cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);\r
+       Buttons[nNumButtons++] = cb;\r
+\r
+       if(uStyle & CB_PUSHBUTTON)\r
+       {\r
+               cb->SetBackColor(CardButton::GetFace(crBackgnd));\r
+               //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));\r
+               cb->SetForeColor(RGB(255,255,255));\r
+       }\r
+       else\r
+       {\r
+               cb->SetBackColor(crBackgnd);\r
+               cb->SetForeColor(RGB(255,255,255));\r
+       }\r
+       \r
+       return cb;\r
+}\r
+\r
+void CardButton::SetText(TCHAR *lpszFormat, ...)\r
+{\r
+       int count;\r
+\r
+       va_list args;\r
+       va_start(args, lpszFormat);\r
+\r
+       count = wvsprintf(szText, lpszFormat, args);\r
+       va_end(args);\r
+}\r
+\r
+int CardButton::Id()\r
+{\r
+       return id;\r
+}\r
+\r
+void CardButton::Show(bool fShow)\r
+{\r
+       fVisible = fShow;\r
+}\r
+\r
+void CardButton::Move(int x, int y, int width, int height)\r
+{\r
+       SetRect(&rect, x, y, x+width, y+height);\r
+}\r
+\r
+void CardButton::Redraw()\r
+{\r
+       HDC hdc = GetDC((HWND)parentWnd);\r
+\r
+       HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);\r
+\r
+       Draw(hdc, !fButtonDown);\r
+       \r
+       RestorePalette(hdc, hOldPal);\r
+       \r
+       ReleaseDC((HWND)parentWnd, hdc);\r
+}\r
+\r
+void CardButton::SetForeColor(COLORREF cr)\r
+{\r
+       crText = cr;\r
+}\r
+\r
+void CardButton::SetBackColor(COLORREF cr)\r
+{\r
+       crBack = cr;\r
+\r
+       crHighlight = GetHighlight(cr);\r
+       crShadow    = GetShadow(cr);\r
+       \r
+       //crHighlight = ScaleLumRGB(cr, +0.25);\r
+       //crShadow    = ScaleLumRGB(cr, -0.25);\r
+}\r
+\r
+//     Static member\r
+COLORREF CardButton::GetHighlight(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);\r
+}\r
+\r
+//     Static member\r
+COLORREF CardButton::GetShadow(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(0,  0,  0),   0.25);\r
+}\r
+\r
+COLORREF CardButton::GetFace(COLORREF crBase)\r
+{\r
+       return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);\r
+}\r
+\r
+void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)\r
+{\r
+       xadjust = xAdjust;\r
+       yadjust = yAdjust;\r
+       xjustify = xJustify;\r
+       yjustify = yJustify;\r
+}\r
+\r
+void CardButton::SetIcon(HICON hicon, bool fRedraw)\r
+{\r
+       hIcon = hicon;\r
+       \r
+       if(fRedraw)\r
+               Redraw();\r
+}\r
+\r
+void CardButton::SetFont(HFONT font)\r
+{\r
+       //don't delete the existing font..\r
+       hFont = font;\r
+}\r
+\r
+void CardButton::SetButtonProc(pButtonProc proc)\r
+{\r
+       ButtonCallback  = proc;\r
+}\r
+\r
+bool CardButton::Lock()\r
+{\r
+       DWORD dw = WaitForSingleObject(mxlock, 0);\r
+\r
+       if(dw == WAIT_OBJECT_0)\r
+               return true; \r
+       else\r
+               return false;\r
+}\r
+\r
+bool CardButton::UnLock()\r
+{\r
+       if(ReleaseMutex(mxlock))\r
+               return true;\r
+       else\r
+               return false;\r
+}\r
+\r
+void CardButton::SetStyle(UINT style)\r
+{\r
+       uStyle = style;\r
+}\r
+\r
+UINT CardButton::GetStyle()\r
+{\r
+       return uStyle;\r
+}
\ No newline at end of file
diff --git a/rosapps/games/solitaire/cardlib/cardbutton.h b/rosapps/games/solitaire/cardlib/cardbutton.h
new file mode 100644 (file)
index 0000000..14be629
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef CARDBUTTON_INCLUDED\r
+#define CARDBUTTON_INCLUDED\r
+\r
+#define MAXBUTTONTEXT 64\r
+\r
+#include "cardlib.h"\r
+\r
+class CardButton\r
+{\r
+       friend class CardWindow;\r
+\r
+       //\r
+       //      Constructor is PRIVATE - only a\r
+       //  CardWindow can create buttons!\r
+       //\r
+       CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible, \r
+               int x, int y, int width, int height);\r
+\r
+       ~CardButton();\r
+\r
+public:\r
+\r
+       void SetStyle(UINT uStyle);\r
+       UINT GetStyle();\r
+\r
+       void SetText(TCHAR *fmt, ...);\r
+       void SetFont(HFONT font);\r
+\r
+       void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);\r
+\r
+       void SetForeColor(COLORREF cr);\r
+       void SetBackColor(COLORREF cr);\r
+\r
+       void Move(int x, int y, int width, int height);\r
+       void Show(bool fShow);\r
+       void Redraw();\r
+       int  Id();\r
+\r
+       void SetIcon(HICON hicon, bool fRedraw);\r
+\r
+       void SetButtonProc(pButtonProc proc);\r
+\r
+       CardWindow &GetCardWindow() { return parentWnd; }\r
+\r
+       bool Lock();\r
+       bool UnLock();\r
+\r
+       static COLORREF GetHighlight(COLORREF crBase);\r
+       static COLORREF GetShadow(COLORREF crBase);\r
+       static COLORREF GetFace(COLORREF crBase);\r
+\r
+private:\r
+\r
+       //\r
+       //      Private member functions\r
+       //\r
+       void AdjustPosition(int winwidth, int winheight);\r
+\r
+       void DrawRect(HDC hdc, RECT *rect, bool fNormal);\r
+       void Draw(HDC hdc, bool fNormal);\r
+       void Clip(HDC hdc);\r
+\r
+       int  OnLButtonDown(HWND hwnd, int x, int y);\r
+       int  OnMouseMove(HWND hwnd, int x, int y);\r
+       int  OnLButtonUp(HWND hwnd, int x, int y);\r
+\r
+       //\r
+       //      Private members\r
+       //\r
+       CardWindow &parentWnd;\r
+\r
+       RECT    rect;\r
+       int             id;\r
+       UINT    uStyle;\r
+       bool    fVisible;\r
+\r
+       int             xadjust;\r
+       int             xjustify;\r
+       int             yadjust;\r
+       int             yjustify;\r
+\r
+       HICON   hIcon;\r
+       HFONT   hFont;\r
+\r
+       TCHAR   szText[MAXBUTTONTEXT];\r
+\r
+       COLORREF crBack;\r
+       COLORREF crText;\r
+       COLORREF crHighlight;\r
+       COLORREF crShadow;\r
+       COLORREF crShadow2;\r
+\r
+       bool    fMouseDown;\r
+       bool    fButtonDown;\r
+\r
+       HANDLE  mxlock;\r
+\r
+       pButtonProc     ButtonCallback;\r
+};\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardcolor.cpp b/rosapps/games/solitaire/cardlib/cardcolor.cpp
new file mode 100644 (file)
index 0000000..f82c9fa
--- /dev/null
@@ -0,0 +1,353 @@
+//\r
+//     Colour support\r
+//\r
+#include <windows.h>\r
+\r
+#define MakeRGB RGB\r
+\r
+#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )\r
+#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )\r
+\r
+inline double fMax(double a, double b)\r
+{\r
+       return a < b ? b : a;\r
+}\r
+\r
+inline double fMin(double a, double b)\r
+{\r
+       return a < b ? a : b;\r
+}\r
+/******************************************************************************\r
+  FUNCTION: RGBtoHLS\r
+  PURPOSE:     Convert from RGB to HLS\r
+  IN: RGB color (0xBBGGRR)\r
+  OUT: Hue, Saturation, Luminance from 0 to 1\r
+  COPYRIGHT:1995-1997 Robert Mashlan\r
+            Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
+******************************************************************************/\r
+void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S ) \r
+{\r
+       double delta;\r
+       double r = (double)((rgb    )&0xFF)/255;\r
+       double g = (double)((rgb>> 8)&0xFF)/255;\r
+       double b = (double)((rgb>>16)&0xFF)/255;\r
+       double cmax = MAX3(r,g,b);\r
+       double cmin = MIN3(r,g,b);\r
+       *L=(cmax+cmin)/2.0;\r
+       \r
+       if(cmax == cmin) \r
+       {\r
+               *S = *H = 0; // it's really undefined\r
+       }\r
+       else \r
+       {\r
+               if(*L < 0.5)    *S = (cmax-cmin)/(cmax+cmin);\r
+               else                    *S = (cmax-cmin)/(2.0-cmax-cmin);\r
+               \r
+               delta = cmax - cmin;\r
+               \r
+               if(r == cmax) \r
+               {\r
+                       *H = (g - b) / delta;\r
+               }\r
+               else\r
+               {\r
+                       if(g == cmax) *H = 2.0 + (b-r) / delta;\r
+                       else          *H = 4.0 + (r-g) / delta;\r
+               }\r
+               *H /= 6.0;\r
+               if (*H < 0.0) *H += 1;\r
+       }\r
+}\r
+\r
+/******************************************************************************\r
+  FUNCTION: HueToRGB\r
+  PURPOSE:     Convert a hue (color) to RGB\r
+  COPYRIGHT:1995-1997 Robert Mashlan\r
+            Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
+******************************************************************************/\r
+double HueToRGB(const double m1, const double m2, double h ) \r
+{\r
+       if (h<0) h+=1.0;\r
+       if (h>1) h-=1.0;\r
+       if (6.0*h < 1  ) return (m1+(m2-m1)*h*6.0);\r
+       if (2.0*h < 1  ) return m2;\r
+       if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);\r
+       return m1;\r
+}\r
+\r
+\r
+/******************************************************************************\r
+  FUNCTION: HLStoRGB\r
+  PURPOSE:     Convert from HSL to RGB\r
+  IN:          Hue, Saturation, Luminance from 0 to 1\r
+  RETURN:      RGB color (0xBBGGRR)\r
+  COPYRIGHT:1995-1997 Robert Mashlan\r
+            Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
+******************************************************************************/\r
+\r
+COLORREF HLStoRGB(const double H, const double L, const double S ) \r
+{\r
+       double r,g,b;\r
+       double m1, m2;\r
+\r
+       if(S == 0) \r
+       {\r
+               r = g = b = L;\r
+       }\r
+       else \r
+       {\r
+               if (L <= 0.5) \r
+                       m2 = L * (1.0 + S);\r
+               else         \r
+                       m2 = L + S - L * S;\r
+\r
+               m1 = 2.0 * L - m2;\r
+\r
+               r = HueToRGB(m1,m2,H+1.0/3.0);\r
+               g = HueToRGB(m1,m2,H);\r
+               b = HueToRGB(m1,m2,H-1.0/3.0);\r
+       }\r
+  \r
+       return RGB(r*255, g*255, b*255);\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+  FUNCTION: ColorScaleHSL\r
+  PURPOSE:     Returns the HSL linear interpolated color between 2 colors\r
+                       (more natural looking than RGB interpolation)\r
+               For instance if the luminance is the same in Col1 and Col2, \r
+                       then the luminance of the result will be the same\r
+               If Ratio=0, you get Col1,\r
+                       If Ratio=1, you get Col2\r
+  IN: Col1: low color in hex 0xBBGGRR format\r
+         Col2: high color in hex 0xBBGGRR format\r
+         Ratio: 0 for low color, 1 for high color, or in between\r
+  EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F\r
+******************************************************************************/\r
+COLORREF ColorScaleHSL(        const COLORREF Col1, const COLORREF Col2, const double Ratio) \r
+{\r
+       static double H1, H2, S1, S2, L1, L2;\r
+       \r
+       if (Ratio<=0) return Col1;      // Ratio parameter must be between 0 and 1\r
+       else if (Ratio>=1) return Col2;\r
+\r
+       RGBtoHLS( Col1, &H1, &L1, &S1);\r
+       RGBtoHLS( Col2, &H2, &L2, &S2);\r
+       return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );\r
+}\r
+\r
+\r
+/******************************************************************************\r
+  FUNCTION: ColorScaleRGB\r
+  PURPOSE:     Returns the RGB linear interpolated color between 2 colors\r
+               If Ratio=0, you get Col1,\r
+                       If Ratio=1, you get Col2\r
+  IN: Col1: low color in hex 0xBBGGRR format\r
+         Col2: high color in hex 0xBBGGRR format\r
+         Ratio: 0 for low color, 1 for high color, or in between\r
+  EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080\r
+******************************************************************************/\r
+COLORREF ColorScaleRGB(        const COLORREF Col1, \r
+                                               const COLORREF Col2, \r
+                                               const double Ratio) {\r
+       int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;\r
+       int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;\r
+\r
+       if (Ratio<=0) return Col1;      // Ratio parameter must be between 0 and 1\r
+       else if (Ratio>=1) return Col2;\r
+\r
+/*     return RGB(\r
+                      (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5),         // rounding\r
+                          (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),\r
+                          (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)\r
+                          );*/\r
+\r
+       /*double r = Ratio;\r
+       if(Col2 == 0)\r
+               r = 1-Ratio;\r
+       else\r
+               r = 1+Ratio;\r
+       R1 = (int)(double(R1) * r + 0.5);\r
+       G1 = (int)(double(G1) * r + 0.5);\r
+       B1 = (int)(double(B1) * r + 0.5);\r
+       return RGB(R1,G1,B1);*/\r
+\r
+       return RGB(\r
+                          (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5),             // rounding\r
+                          (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),\r
+                          (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)\r
+                          );\r
+}\r
+\r
+\r
+\r
+COLORREF ColorDarker(COLORREF col, double ratio)\r
+{\r
+       static double Hue, Lum, Sat;\r
+\r
+       //RGBtoHLS(col, &Hue, &Lum, &Sat);\r
+\r
+       //col = HLStoRGB(Hue, fMax(0.0,Lum-ratio), Sat);\r
+\r
+       return ColorScaleHSL(col, RGB(0,0,0), ratio);\r
+\r
+       //return col;\r
+}\r
+\r
+COLORREF ColorLighter(COLORREF col, double ratio)\r
+{\r
+       static double Hue, Lum, Sat;\r
+\r
+       //RGBtoHLS(col, &Hue, &Lum, &Sat);\r
+\r
+       //col = HLStoRGB(Hue, fMin(1.0,Lum+ratio), Sat);\r
+\r
+       return ColorScaleHSL(col, RGB(255,255,255), ratio);\r
+\r
+       //return col;\r
+}\r
+\r
+//\r
+//     Experimental!!!\r
+//\r
+#if 0\r
+\r
+typedef enum { Red, Green, Blue };\r
+\r
+void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)\r
+{\r
+       double mn, mx;\r
+       int major;\r
+\r
+       BYTE red, green, blue;\r
+\r
+       red    = GetRValue(rgb);\r
+       green  = GetGValue(rgb);\r
+       blue   = GetBValue(rgb);\r
+\r
+       if(red < green)\r
+       {\r
+               mn = red; mx = green; major = Green;\r
+       }\r
+       else\r
+       {\r
+               mn = green; mx = red; major = Red;\r
+       }\r
+\r
+       if(blue < mn)\r
+       {\r
+               mn = blue;\r
+       }\r
+       else if(blue > mx)\r
+       {\r
+               mx = blue; major = Blue;\r
+       }\r
+\r
+       if(mn == mx)\r
+       {\r
+               *Lum = mn / 255;\r
+               *Sat = 0;\r
+               *Hue = 0;\r
+       }\r
+       else\r
+       {\r
+               *Lum = (mx + mn) / 510;\r
+\r
+               if(*Lum <= 0.5)\r
+                       *Sat = (mx-mn) / (mn+mx);\r
+               else\r
+                       *Sat = (mx-mn) / (510-mn-mx);\r
+\r
+               switch(major)\r
+               {\r
+               case Red:   *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;\r
+                                   break;\r
+\r
+               case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;\r
+                               break;\r
+\r
+               case Blue:  *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;\r
+                               break;\r
+\r
+               }\r
+\r
+               if(*Hue > 360.0)\r
+                       *Hue -= 360.0;\r
+       }\r
+}\r
+\r
+static BYTE Value(double m1, double m2, double hue)\r
+{\r
+\r
+       if(hue > 360)           hue -= 360;\r
+       else if(hue < 0)        hue += 360;\r
+\r
+       if(hue < 60)\r
+               m1 = m1 + (m2 - m1) * hue / 60;\r
+       else if(hue < 180)\r
+               m1 = m2;\r
+       else if(hue < 240)\r
+               m1 = m1 + (m2 - m1) * (240 - hue) / 60;\r
+\r
+       return (BYTE)(m1 * 255);\r
+}\r
+\r
+COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)\r
+{\r
+       BYTE red, green, blue;\r
+\r
+       if(Sat == 0)\r
+       {\r
+               red = green = blue = (BYTE)(Lum * 255);         \r
+       }\r
+       else\r
+       {\r
+               double m1, m2;\r
+\r
+               if(Lum <= 0.5)\r
+                       m2 = Lum + Lum * Sat;\r
+               else\r
+                       m2 = Lum + Sat - Lum * Sat;\r
+\r
+               m1 = 2 * Lum - m2;\r
+\r
+               red   = Value(m1, m2, Hue + 120);\r
+               green = Value(m1, m2, Hue);\r
+               blue  = Value(m1, m2, Hue - 120);\r
+       }\r
+\r
+       return RGB(red, green, blue);\r
+}\r
+\r
+COLORREF ScaleLumRGB(COLORREF col1, double ratio)\r
+{\r
+       double H1, L1, S1;\r
+\r
+       RGBtoHLS(col1, &H1, &L1, &S1);\r
+\r
+       L1 += L1 * ratio;\r
+\r
+       return HLStoRGB(H1, L1, S1);\r
+}\r
+\r
+COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio) \r
+{\r
+       static double H1, H2, S1, S2, L1, L2;\r
+       \r
+       if(Ratio <= 0)          return Col1;    // Ratio parameter must be between 0 and 1\r
+       else if(Ratio >= 1)     return Col2;\r
+\r
+       RGBtoHLS( Col1, &H1, &L1, &S1);\r
+       RGBtoHLS( Col2, &H2, &L2, &S2);\r
+\r
+       return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);\r
+}\r
+\r
+COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)\r
+{\r
+       return ColorScaleHSL(Col1, Col2, Ratio);\r
+}\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardcolor.h b/rosapps/games/solitaire/cardlib/cardcolor.h
new file mode 100644 (file)
index 0000000..d97adce
--- /dev/null
@@ -0,0 +1,16 @@
+\r
+COLORREF ColorScaleRGB(        const COLORREF Col1, \r
+                                               const COLORREF Col2, \r
+                                               const double Ratio);\r
+\r
+COLORREF ColorScaleHSL(        const COLORREF Col1, \r
+                                               const COLORREF Col2, \r
+                                               const double Ratio);\r
+\r
+\r
+COLORREF ColorDarker(COLORREF col, double ratio);\r
+COLORREF ColorLighter(COLORREF col, double ratio);\r
+\r
+COLORREF ScaleLumRGB(COLORREF col1, double ratio);\r
+\r
+#define MAKE_PALETTERGB(colref) (0x02000000 | colref)\r
diff --git a/rosapps/games/solitaire/cardlib/cardcount.cpp b/rosapps/games/solitaire/cardlib/cardcount.cpp
new file mode 100644 (file)
index 0000000..e14777a
--- /dev/null
@@ -0,0 +1,90 @@
+//\r
+//     CardCount is a helper library for CardStacks.\r
+//     \r
+//     When you initialize a CardCount object with a \r
+//  cardstack, it keeps track of the number of cards\r
+//     the stack contains.\r
+//\r
+//     e.g. CardCount count(cardstack);\r
+//\r
+//     Then you can do:\r
+//     \r
+//             int num_fives = count[5]\r
+//             \r
+//             count.Add(cardstack2);          - combine with another stack\r
+//\r
+//             int num_aces = count[1]         - aces low\r
+//             int num_aces = count[14]    - aces high\r
+//\r
+//             count.Clear();\r
+//\r
+#include "cardcount.h"\r
+\r
+CardCount::CardCount()\r
+{\r
+       Clear();\r
+}\r
+\r
+CardCount::CardCount(const CardStack &cs)\r
+{\r
+       Init(cs);\r
+}\r
+\r
+void CardCount::Clear()\r
+{\r
+       for(int i = 0; i < 13; i++)\r
+               count[i] = 0;\r
+}\r
+\r
+void CardCount::Add(const CardStack &cs)\r
+{\r
+       for(int i = 0; i < cs.NumCards(); i++)\r
+       {\r
+               Card card = cs[i];\r
+\r
+               int val = card.LoVal();\r
+               count[val - 1]++;\r
+       }\r
+}\r
+\r
+void CardCount::Sub(const CardStack &cs)\r
+{\r
+       for(int i = 0; i < cs.NumCards(); i++)\r
+       {\r
+               Card card = cs[i];\r
+               int val = card.LoVal();\r
+               \r
+               if(count[val - 1] > 0)\r
+                       count[val - 1]--;\r
+       }\r
+}\r
+\r
+void CardCount::Init(const CardStack &cs)\r
+{\r
+       Clear();\r
+       Add(cs);\r
+}\r
+\r
+int CardCount::operator [] (size_t index) const\r
+{\r
+       if(index < 1) return 0;\r
+       else if(index > 14)  return 0;  //if out of range\r
+       else if(index == 14) index = 1; //if a "ace-high"\r
+\r
+       return count[index - 1];\r
+}\r
+\r
+//\r
+//     Decrement specified item by one\r
+//\r
+void CardCount::Dec(size_t index)\r
+{\r
+       if(index < 1) return;\r
+       else if(index > 14)  return;    //if out of range\r
+       else if(index == 14) index = 1; //if a "ace-high"\r
+\r
+       index -= 1;\r
+\r
+       if(count[index] > 0) \r
+               count[index]--;\r
+}
\ No newline at end of file
diff --git a/rosapps/games/solitaire/cardlib/cardcount.h b/rosapps/games/solitaire/cardlib/cardcount.h
new file mode 100644 (file)
index 0000000..f97ba15
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _CARDCOUNT_INCLUDED\r
+#define _CARDCOUNT_INCLUDED\r
+\r
+#include <windows.h>\r
+\r
+#include "cardstack.h"\r
+\r
+class CardCount\r
+{\r
+public:\r
+       CardCount();\r
+       CardCount(const CardStack &cs);\r
+\r
+       void Init(const CardStack &cs);\r
+       void Clear();\r
+       void Add(const CardStack &cs);\r
+       void Sub(const CardStack &cs);\r
+\r
+       void Dec(size_t index);\r
+\r
+       int operator[] (size_t index) const;\r
+\r
+       CardCount &operator =  (const CardStack &cs);\r
+       CardCount &operator += (const CardStack &cs);\r
+\r
+private:\r
+       int count[13];  //13 different card values \r
+                                       //(ace,2,3,4,5,6,7,8,9,10,J,Q,K)\r
+};\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardlib.cpp b/rosapps/games/solitaire/cardlib/cardlib.cpp
new file mode 100644 (file)
index 0000000..07cd4ee
--- /dev/null
@@ -0,0 +1,122 @@
+//\r
+//     CardLib - not much of interest in here\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include "cardlib.h"\r
+#include "globals.h"\r
+\r
+void LoadCardBitmaps(void);\r
+\r
+static bool __CARDLIB_ACES_HIGH = false;\r
+extern double __CARDZOOMSPEED;\r
+\r
+//\r
+//     Global variables!\r
+//\r
+HDC     __hdcCardBitmaps;\r
+HBITMAP __hbmCardBitmaps;\r
+\r
+HDC            __hdcPlaceHolder;\r
+HBITMAP        __hbmPlaceHolder;\r
+HPALETTE __holdplacepal;\r
+\r
+int            __cardwidth;\r
+int            __cardheight;\r
+\r
+HPALETTE __hPalette;\r
+\r
+\r
+//\r
+//     Cardlib global functions!\r
+//\r
+void CardLib_SetZoomSpeed(int speed)\r
+{\r
+       __CARDZOOMSPEED = (double)speed;\r
+}\r
+\r
+/*\r
+\r
+  It's dangerous to use these operators, because of all\r
+  the implicit conversions that could take place, which\r
+  would have unpredicted side-effects.\r
+\r
+  e.g. Card card(Hearts, 4);\r
+       if(card == 4)   - how does 4 get converted??\r
+                             It uses the Card(int uval) constructor,\r
+                                                 which results in a 2 of clubs...\r
+                                                 not what was expected\r
+*/ \r
+/*\r
+void CardLib_SetAcesHigh(bool fHigh);\r
+bool operator != (const Card &lhs, const Card &rhs);\r
+bool operator == (const Card &lhs, const Card &rhs);\r
+bool operator <  (const Card &lhs, const Card &rhs);\r
+bool operator <= (const Card &lhs, const Card &rhs);\r
+bool operator >  (const Card &lhs, const Card &rhs);\r
+bool operator >= (const Card &lhs, const Card &rhs);\r
+*/\r
+\r
+/*\r
+void CardLib_SetAcesHigh(bool fHigh)\r
+{\r
+       __CARDLIB_ACES_HIGH = fHigh;\r
+}\r
+\r
+bool operator == (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() == rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() == rhs.LoVal();\r
+}\r
+\r
+bool operator != (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() != rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() != rhs.LoVal();\r
+}\r
+\r
+bool operator > (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() > rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() > rhs.LoVal();\r
+}\r
+\r
+bool operator >= (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() >= rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() >= rhs.LoVal();\r
+}\r
+\r
+bool operator < (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() < rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() < rhs.LoVal();\r
+}\r
+\r
+bool operator <= (const Card &lhs, const Card &rhs)\r
+{\r
+       if(__CARDLIB_ACES_HIGH)\r
+               return lhs.HiVal() <= rhs.HiVal();\r
+       else\r
+               return lhs.LoVal() <= rhs.LoVal();\r
+}\r
+*/\r
+\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour)\r
+{\r
+    COLORREF oldcr = SetBkColor(hdc, colour);\r
+    ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0);\r
+    SetBkColor(hdc, oldcr);\r
+}\r
diff --git a/rosapps/games/solitaire/cardlib/cardlib.h b/rosapps/games/solitaire/cardlib/cardlib.h
new file mode 100644 (file)
index 0000000..bad3f0c
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef CARDLIB_INCLUDED\r
+#define CARDLIB_INCLUDED\r
+\r
+#define CARDLIBPROC __stdcall\r
+\r
+void CardBlt(HDC hdc, int x, int y, int nCardNum);\r
+void CardLib_SetZoomSpeed(int);\r
+\r
+#define CS_EI_NONE     0\r
+#define CS_EI_SUNK     1\r
+\r
+#define CS_DEFXOFF                     12              //x-offset\r
+#define CS_DEFYOFF                     18              //y-offset\r
+#define CS_NO3D                                1               //default 3d counts (recommened)\r
+#define CS_DEF3D                       10              //(best for decks)\r
+\r
+//#define CS_EI_CIRC   2\r
+//#define CS_EI_X              3\r
+\r
+#define CS_DRAG_NONE           0\r
+#define CS_DRAG_TOP                    1\r
+#define CS_DRAG_ALL                    2\r
+#define CS_DRAG_CALLBACK       3\r
+\r
+#define CS_DROP_NONE           0\r
+#define CS_DROP_ALL                    1\r
+#define        CS_DROP_CALLBACK        2\r
+\r
+#define CS_XJUST_NONE          0\r
+#define CS_XJUST_RIGHT         1\r
+#define CS_XJUST_CENTER                2\r
+\r
+#define CS_YJUST_NONE          0\r
+#define CS_YJUST_BOTTOM                1\r
+#define CS_YJUST_CENTER                2\r
+\r
+#define CB_STATIC                      0               //static text label\r
+#define CB_PUSHBUTTON          1               //normal button\r
+#define CB_ALIGN_CENTER                0               //centered is default\r
+#define CB_ALIGN_LEFT          2\r
+#define CB_ALIGN_RIGHT         4\r
+\r
+#define CS_FACE_UP              0      //all cards face-up\r
+#define CS_FACE_DOWN    1      //all cards face-down\r
+#define CS_FACE_DOWNUP  2      //bottom X cards down, top-most face-up\r
+#define CS_FACE_UPDOWN  3      //bottom X cards up, top-most face-down\r
+#define CS_FACE_ANY             4      //cards can be any orientation\r
+\r
+#define CS_DROPZONE_NODROP     -1\r
+\r
+//\r
+//     Define the standard card-back indices\r
+//\r
+#define ecbCROSSHATCH  53\r
+#define ecbWEAVE1              54\r
+#define ecbWEAVE2              55\r
+#define ecbROBOT               56\r
+#define ecbFLOWERS             57\r
+#define ecbVINE1               58\r
+#define ecbVINE2               59\r
+#define ecbFISH1               60\r
+#define ecbFISH2               61\r
+#define ecbSHELLS              62\r
+#define ecbCASTLE              63\r
+#define ecbISLAND              64\r
+#define ecbCARDHAND            65\r
+#define ecbUNUSED              66\r
+#define ecbTHE_X               67\r
+#define ecbTHE_O               68\r
+\r
+\r
+class CardRegion;\r
+class CardButton;\r
+class CardStack;\r
+\r
+typedef bool (CARDLIBPROC *pCanDragProc)    (CardRegion &stackobj, int iNumDragging);\r
+typedef bool (CARDLIBPROC *pCanDropProc)    (CardRegion &stackobj, const CardStack &cards);\r
+typedef void (CARDLIBPROC *pClickProc)      (CardRegion &stackobj, int iNumCards);\r
+typedef void (CARDLIBPROC *pAddProc)        (CardRegion &stackobj, const CardStack &cards);\r
+typedef void (CARDLIBPROC *pRemoveProc)     (CardRegion &stackobj, int iNumRemoved);\r
+\r
+typedef void (CARDLIBPROC *pResizeWndProc)  (int width, int height);\r
+typedef int  (CARDLIBPROC *pDropZoneProc)   (int dzid, const CardStack &cards);\r
+\r
+typedef void (CARDLIBPROC *pButtonProc)                (CardButton &pButton);\r
+\r
+\r
+#include "card.h"\r
+#include "cardbutton.h"\r
+#include "cardstack.h"\r
+#include "cardregion.h"\r
+#include "cardcount.h"\r
+#include "cardwindow.h"\r
+\r
+#ifdef _DEBUG\r
+typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj);\r
+void CardLib_SetStackClickProc(pDebugClickProc proc);\r
+#endif\r
+\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardregion.cpp b/rosapps/games/solitaire/cardlib/cardregion.cpp
new file mode 100644 (file)
index 0000000..1a7e8ce
--- /dev/null
@@ -0,0 +1,658 @@
+//\r
+//     CardLib - CardRegion class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardregion.h"\r
+#include "cardwindow.h"\r
+#include "cardcolor.h"\r
+\r
+HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height);\r
+\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
+\r
+CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset) \r
+: parentWnd(parent), id(Id), fVisible(visible), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset)\r
+{\r
+       width  = __cardwidth;\r
+       height = __cardheight;\r
+\r
+       crBackgnd  = RGB(0, 64, 100);\r
+\r
+       uFaceDirType   = CS_FACE_UP;\r
+       nFaceDirOption = 0;\r
+       uEmptyImage  = CS_EI_SUNK;\r
+\r
+       fVisible         = visible;\r
+\r
+       nThreedCount = 1;\r
+       nBackCardIdx = 53;\r
+\r
+       Update();                               //Update this stack's size+card count\r
+\r
+       hdcBackGnd = 0;\r
+       hbmBackGnd = 0;\r
+       hdcDragCard = 0;\r
+       hbmDragCard = 0;\r
+\r
+       nDragCardWidth = 0;\r
+       nDragCardHeight = 0;\r
+       \r
+       CanDragCallback  = 0;\r
+       CanDropCallback  = 0;\r
+       AddCallback      = 0;\r
+       RemoveCallback   = 0;\r
+       ClickCallback    = 0;\r
+       DblClickCallback = 0;\r
+\r
+       uDragRule = CS_DRAG_ALL;\r
+       uDropRule = CS_DROP_ALL;\r
+\r
+       xjustify = yjustify = xadjust = yadjust = 0;\r
+\r
+       nFlashCount             = 0;\r
+       fFlashVisible   = false;\r
+       uFlashTimer             = -1;\r
+\r
+       fMouseDragging = false;\r
+\r
+       mxlock = CreateMutex(0, FALSE, 0);\r
+}\r
+\r
+CardRegion::~CardRegion()\r
+{\r
+       CloseHandle(mxlock);\r
+}\r
+\r
+void CardRegion::SetBackColor(COLORREF cr)\r
+{\r
+       crBackgnd = cr;\r
+}\r
+\r
+int CardRegion::CalcApparentCards(int realnum)\r
+{\r
+       return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount;\r
+}\r
+\r
+void CardRegion::CalcApparentCards()\r
+{\r
+       nNumApparentCards = CalcApparentCards(cardstack.NumCards());\r
+}\r
+\r
+\r
+void CardRegion::UpdateSize(void)\r
+{\r
+       if(cardstack.NumCards() > 0)\r
+       {\r
+               if(xoffset > 0)\r
+                       width  = (nNumApparentCards - 1) * xoffset + __cardwidth;\r
+               else\r
+                       width  = (nNumApparentCards - 1) * -xoffset + __cardwidth;\r
+\r
+               if(yoffset > 0)\r
+                       height = (nNumApparentCards - 1) * yoffset + __cardheight;\r
+               else\r
+                       height = (nNumApparentCards - 1) * -yoffset + __cardheight;\r
+       }\r
+       else\r
+       {\r
+               width = __cardwidth;\r
+               height = __cardheight;\r
+       }\r
+}\r
+\r
+CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset)\r
+{\r
+       CardRegion *cr;\r
+\r
+       if(nNumCardRegions == MAXCARDSTACKS)\r
+               return FALSE;\r
+\r
+       cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset);\r
+       cr->SetBackColor(crBackgnd);\r
+       cr->SetBackCardIdx(nBackCardIdx);\r
+\r
+       Regions[nNumCardRegions++] = cr;\r
+       \r
+       return cr;\r
+}\r
+\r
+int CardRegion::GetOverlapRatio(int x, int y, int w, int h)\r
+{\r
+       RECT me, him;\r
+       RECT inter;\r
+       SetRect(&him, x, y, x+w, y+h);\r
+       SetRect(&me,  xpos, ypos, xpos+width, ypos+height);\r
+\r
+       //see if the specified rectangle overlaps us\r
+       if(IntersectRect(&inter, &me, &him))\r
+       {\r
+               int wi = inter.right  - inter.left;\r
+               int hi = inter.bottom - inter.top;\r
+\r
+               int overlap = wi * hi;\r
+               int total   = width * height;\r
+\r
+               int percent = (overlap << 16) / total;\r
+               return (percent * 100) >> 16;\r
+       }\r
+       //do not overlap\r
+       else\r
+       {\r
+               return 0;\r
+       }\r
+}\r
+\r
+bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc)\r
+{ \r
+       switch(uDragType)\r
+       {\r
+       case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP:\r
+               uDragRule = uDragType;\r
+               return true;\r
+\r
+       case CS_DRAG_CALLBACK:\r
+               uDragRule = uDragType;\r
+               CanDragCallback = proc;\r
+               return true;\r
+\r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc)\r
+{ \r
+       switch(uDropType)\r
+       {\r
+       case CS_DROP_NONE: case CS_DROP_ALL: \r
+               uDropRule = uDropType;\r
+               return true;\r
+\r
+       case CS_DROP_CALLBACK:\r
+               uDropRule = uDropType;\r
+               CanDropCallback = proc;\r
+               return true;\r
+\r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+void CardRegion::SetClickProc(pClickProc proc)\r
+{\r
+       ClickCallback = proc;\r
+}\r
+\r
+void CardRegion::SetDblClickProc(pClickProc proc)\r
+{\r
+       DblClickCallback = proc;\r
+}\r
+\r
+void CardRegion::SetAddCardProc(pAddProc proc)\r
+{\r
+       AddCallback = proc;\r
+}\r
+\r
+void CardRegion::SetRemoveCardProc(pRemoveProc proc)\r
+{\r
+       RemoveCallback = proc;\r
+}\r
+\r
+void CardRegion::Update()\r
+{\r
+       CalcApparentCards();\r
+       UpdateSize(); \r
+       UpdateFaceDir(cardstack);\r
+}\r
+\r
+\r
+bool CardRegion::SetThreedCount(int count)\r
+{\r
+       if(count < 1) \r
+       {\r
+               return false;\r
+       }\r
+       else\r
+       {\r
+               nThreedCount = count;\r
+               return true;\r
+       }\r
+}\r
+\r
+void CardRegion::SetOffsets(int x, int y)\r
+{\r
+       xoffset = x;\r
+       yoffset = y;\r
+}\r
+\r
+void CardRegion::SetPos(int x, int y)\r
+{\r
+       xpos = x;\r
+       ypos = y;\r
+}\r
+\r
+void CardRegion::Show(bool fShow)\r
+{\r
+       fVisible = fShow;\r
+}\r
+\r
+bool CardRegion::IsVisible()\r
+{ \r
+       return fVisible;\r
+}\r
+\r
+void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)\r
+{\r
+       xjustify = xJustify;\r
+       yjustify = yJustify;\r
+       xadjust  = xAdjust;\r
+       yadjust  = yAdjust;\r
+}\r
+\r
+void CardRegion::SetFaceDirection(UINT uDirType, int nOption)\r
+{\r
+       switch(uDirType)\r
+       {\r
+       case CS_FACE_UP:     case CS_FACE_DOWN: case CS_FACE_DOWNUP:\r
+       case CS_FACE_UPDOWN: case CS_FACE_ANY:\r
+               uFaceDirType    = uDirType;\r
+               nFaceDirOption  = nOption;\r
+\r
+               UpdateFaceDir(cardstack);\r
+\r
+               break;\r
+       }\r
+}\r
+\r
+UINT CardRegion::GetFaceDirection(int *pnOption)\r
+{\r
+       if(pnOption)\r
+               *pnOption = nFaceDirOption;\r
+\r
+       return uFaceDirType;\r
+}\r
+\r
+void CardRegion::AdjustPosition(int winwidth, int winheight)\r
+{\r
+       Update();                       //Update this stack's card count + size\r
+\r
+       switch(xjustify)\r
+       {\r
+       default: case CS_XJUST_NONE: break;\r
+       \r
+       case CS_XJUST_CENTER:           //centered\r
+               xpos = (winwidth - (width & ~0x1)) / 2;\r
+               xpos += xadjust;\r
+\r
+               if(xoffset < 0) xpos += (width - __cardwidth);\r
+       \r
+               break;\r
+\r
+       case CS_XJUST_RIGHT:            //right-aligned\r
+               xpos = winwidth - __cardwidth;//width - 20;\r
+               xpos += xadjust;\r
+               break;\r
+       }\r
+\r
+       switch(yjustify)\r
+       {\r
+       default: case CS_YJUST_NONE: break;\r
+       \r
+       case CS_YJUST_CENTER:           //centered\r
+               ypos = (winheight - height) / 2;\r
+               ypos += yadjust;\r
+               if(yoffset < 0) ypos += (height - __cardheight);\r
+               break;\r
+\r
+       case CS_YJUST_BOTTOM:           //bottom-aligned\r
+               ypos = winheight - __cardheight;//height - 20;\r
+               ypos += yadjust;\r
+               break;\r
+       }\r
+\r
+}\r
+\r
+\r
+void CardRegion::Flash(int count, int milliseconds)\r
+{\r
+       if(count <= 0) return;\r
+\r
+       nFlashCount             = count;\r
+       fFlashVisible   = false;\r
+       uFlashTimer             = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0);\r
+       \r
+       parentWnd.Redraw();\r
+}\r
+\r
+void CardRegion::StopFlash()\r
+{\r
+       if(uFlashTimer != -1)\r
+       {\r
+               KillTimer((HWND)parentWnd, uFlashTimer);\r
+               nFlashCount             = 0;\r
+               uFlashTimer             = -1;\r
+               fFlashVisible   = true;\r
+       }\r
+}\r
+\r
+void CardRegion::DoFlash()\r
+{\r
+       if(uFlashTimer != -1)\r
+       {\r
+               fFlashVisible = !fFlashVisible;\r
+\r
+               if(--nFlashCount == 0)\r
+               {\r
+                       KillTimer((HWND)parentWnd, uFlashTimer);\r
+                       uFlashTimer = -1;\r
+                       fFlashVisible = true;\r
+               }\r
+       \r
+               parentWnd.Redraw();\r
+       }\r
+}\r
+\r
+int CardRegion::Id()\r
+{\r
+       return id;\r
+}\r
+\r
+void CardRegion::SetEmptyImage(UINT uImage)\r
+{\r
+       switch(uImage)\r
+       {\r
+       case CS_EI_NONE: case CS_EI_SUNK:\r
+               uEmptyImage = uImage;\r
+               break;\r
+\r
+       default:\r
+               uEmptyImage = CS_EI_NONE;\r
+               break;\r
+       }\r
+       \r
+}\r
+\r
+void CardRegion::SetBackCardIdx(UINT uBackIdx)\r
+{\r
+       if(uBackIdx >= 52 && uBackIdx <= 68)\r
+               nBackCardIdx = uBackIdx;\r
+}\r
+\r
+void CardRegion::SetCardStack(const CardStack &cs)\r
+{ \r
+       //make a complete copy of the specified stack..\r
+       cardstack = cs; \r
+\r
+       // Update the face-direction and stack-size\r
+       Update();\r
+}\r
+\r
+const CardStack & CardRegion::GetCardStack()\r
+{ \r
+       //return reference to our internal stack\r
+       return cardstack; \r
+}\r
+\r
+//\r
+//     Update specified card-stack using THIS stack's\r
+//  face direction rules!\r
+//\r
+void CardRegion::UpdateFaceDir(CardStack &cards)\r
+{\r
+       int i, n, num;\r
+\r
+       num = cards.NumCards();\r
+\r
+       //Now apply the face direction rules..\r
+       switch(uFaceDirType)\r
+       {\r
+       case CS_FACE_UP:\r
+\r
+               for(i = 0; i < num; i++)\r
+               {\r
+                       cards[i].SetFaceUp(true);\r
+               }\r
+\r
+               break;\r
+\r
+       case CS_FACE_DOWN:\r
+\r
+               for(i = 0; i < num; i++)\r
+               {\r
+                       cards[i].SetFaceUp(false);\r
+               }\r
+\r
+               break;\r
+\r
+       case CS_FACE_DOWNUP:\r
+\r
+               num = cardstack.NumCards();\r
+               n = min(nFaceDirOption, num);\r
+\r
+               //bottom n cards..\r
+               for(i = 0; i < n; i++)\r
+               {\r
+                       cards[num - i - 1].SetFaceUp(false);\r
+               }\r
+\r
+               for(i = n; i < num; i++)\r
+               {\r
+                       cards[num - i - 1].SetFaceUp(true);\r
+               }\r
+\r
+               break;\r
+\r
+       case CS_FACE_UPDOWN:\r
+\r
+               num = cardstack.NumCards();\r
+               n = min(nFaceDirOption, num);\r
+\r
+               for(i = 0; i < n; i++)\r
+               {\r
+                       cards[num - i - 1].SetFaceUp(true);\r
+               }\r
+\r
+               for(i = n; i < num; i++)\r
+               {\r
+                       cards[num - i - 1].SetFaceUp(false);\r
+               }\r
+\r
+               break;\r
+\r
+       case CS_FACE_ANY:       //cards can be any orientation\r
+       default:\r
+               break;\r
+       }\r
+}\r
+\r
+bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate)\r
+{\r
+       HDC hdc;\r
+\r
+       int x, y;\r
+\r
+       if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; }\r
+\r
+       if(nNumCards < 0 || nNumCards > cardstack.NumCards())\r
+               return false;\r
+\r
+       x = xpos + xoffset * (nNumApparentCards - nNumCards);\r
+       y = ypos + yoffset * (nNumApparentCards - nNumCards);\r
+\r
+       oldx = x;\r
+       oldy = y;\r
+       \r
+       dragstack = cardstack.Pop(nNumCards);\r
+\r
+       //Alter the drag-stack so that it's cards are the same way up\r
+       //as the destination. Use the destination's drag-rules\r
+       //instead of this ones!!\r
+       CardStack temp;\r
+       temp.Push(pDestStack->GetCardStack());\r
+       temp.Push(dragstack);\r
+\r
+       pDestStack->UpdateFaceDir(temp);\r
+\r
+       dragstack = temp.Pop(nNumCards);\r
+\r
+       if(fAnimate)\r
+       {\r
+               iNumDragCards = nNumCards;\r
+               PrepareDragBitmaps(nNumCards);\r
+       }\r
+\r
+       Update();               //Update this stack's size+card count\r
+\r
+       if(fAnimate)\r
+       {\r
+               hdc = GetDC((HWND)parentWnd);\r
+\r
+               ZoomCard(hdc, x, y, pDestStack);\r
+               \r
+               ReleaseDC((HWND)parentWnd, hdc);\r
+               ReleaseDragBitmaps();\r
+       }\r
+\r
+       // Get a copy of the cardstack\r
+       CardStack cs = pDestStack->GetCardStack();\r
+       cs.Push(dragstack);\r
+       \r
+       pDestStack->SetCardStack(cs);\r
+       \r
+       //cs = pDestStack->GetCardStack();\r
+       //pDestStack->Update();\r
+       //pDestStack->UpdateFaceDir(cs);\r
+\r
+       RedrawIfNotDim(pDestStack, false);\r
+\r
+       //forcedfacedir = -1;\r
+       return true;\r
+}\r
+\r
+//\r
+//     Simple wrappers\r
+//\r
+int CardRegion::NumCards() const\r
+{\r
+       if(fMouseDragging)\r
+               return cardstack.NumCards() + dragstack.NumCards();\r
+       else\r
+               return cardstack.NumCards(); \r
+}\r
+\r
+bool CardRegion::Lock()\r
+{\r
+       DWORD dw = WaitForSingleObject(mxlock, 0);\r
+\r
+       if(dw == WAIT_OBJECT_0)\r
+       {\r
+               //TRACE("LockStack succeeded\n");\r
+               return true; \r
+       }\r
+       else\r
+       {\r
+               //TRACE("LockStack failed\n");\r
+               return false;\r
+       }\r
+       return false;\r
+}\r
+\r
+bool CardRegion::UnLock()\r
+{\r
+       if(ReleaseMutex(mxlock))\r
+       {\r
+               //TRACE("Unlocking stack\n");\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               //TRACE("Unlocking stack failed\n");    \r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num)\r
+{\r
+       //search the stack for the specified card value...\r
+       while(num--)\r
+       {\r
+               for(int i = 0; i < cardstack.NumCards(); i++)\r
+               {\r
+                       if(cardstack[i].HiVal() == value)\r
+                       {\r
+                               //swap the card with one at top pos...\r
+                               Card card = cardstack.RemoveCard(i);\r
+                               cardstack.Push(card);\r
+\r
+                               Redraw();\r
+\r
+                               MoveCard(pDestStack, 1, true);\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+//\r
+//     Redraw the current stack if it has a different\r
+//     layout than the comparison stack.\r
+//\r
+void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw)\r
+{\r
+       //\r
+       //\r
+       //\r
+       if( pCompare->xoffset != xoffset || \r
+               pCompare->yoffset != yoffset || \r
+               pCompare->nThreedCount != nThreedCount ||\r
+               pCompare->uFaceDirType != uFaceDirType ||\r
+               pCompare->uFaceDirType != CS_FACE_ANY\r
+               )\r
+       {\r
+               if(fFullRedraw)\r
+                       parentWnd.Redraw();\r
+               else\r
+                       pCompare->Redraw();\r
+       }\r
+       \r
+}\r
+\r
+//\r
+//     SimulateDrag mimicks the complete drag+drop process.\r
+//  It basically just a MoveCard(..), but it calls the\r
+//  event callbacks as well.\r
+//\r
+bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate)\r
+{\r
+       if(pDestStack == 0)\r
+               return false;\r
+\r
+       if(CanDragCards(iNumDragCards) != false)\r
+    {\r
+               //make a list of the cards that would be in the drag list\r
+               CardStack tempstack = cardstack.Top(iNumDragCards);\r
+\r
+               if(pDestStack->CanDropCards(tempstack)) \r
+               {\r
+                       MoveCard(pDestStack, iNumDragCards, fAnimate);          \r
+                               \r
+                       if(RemoveCallback)\r
+                               RemoveCallback(*this, iNumDragCards);\r
+\r
+                       if(pDestStack->AddCallback)\r
+                               pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);\r
+               \r
+                       RedrawIfNotDim(pDestStack, true);\r
+               }       \r
+\r
+       }\r
+\r
+       return true;\r
+}
\ No newline at end of file
diff --git a/rosapps/games/solitaire/cardlib/cardregion.h b/rosapps/games/solitaire/cardlib/cardregion.h
new file mode 100644 (file)
index 0000000..d2806a9
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef CARDREGION_INCLUDED\r
+#define CARDREGION_INCLUDED\r
+\r
+#include "globals.h"\r
+#include "cardstack.h"\r
+#include "cardlib.h"\r
+\r
+class CardWindow;\r
+\r
+//\r
+//     This class defines a physical card-stack,\r
+//     which draws the cards, supports\r
+//\r
+\r
+class CardRegion\r
+{\r
+       friend class CardWindow;\r
+       friend class CardStack;\r
+\r
+       //\r
+       //      Constructor is PRIVATE - only\r
+       //  a CardWindow can create cardstacks!\r
+       //\r
+       CardRegion(CardWindow &parent, int id, bool fVisible, \r
+               int x, int y, int xOffset, int yOffset);\r
+\r
+       ~CardRegion();\r
+\r
+public:\r
+\r
+       void SetBackColor(COLORREF cr);\r
+       \r
+       void              SetCardStack(const CardStack &cs);\r
+       const CardStack & GetCardStack();\r
+\r
+       //\r
+       //      Event-callback support\r
+       //\r
+       bool SetDragRule(UINT uDragType, pCanDragProc proc = 0);\r
+       bool SetDropRule(UINT uDropType, pCanDropProc proc = 0);\r
+       \r
+       void SetClickProc    (pClickProc proc);\r
+       void SetDblClickProc (pClickProc proc);\r
+\r
+       void SetAddCardProc    (pAddProc proc);\r
+       void SetRemoveCardProc (pRemoveProc proc);\r
+\r
+       //\r
+       //      Physical attribute support\r
+       //\r
+       bool SetThreedCount (int count);\r
+       void SetOffsets     (int x, int y);\r
+       void SetPos         (int x, int y);\r
+       void Show           (bool fShow);\r
+       bool IsVisible      ();\r
+\r
+       void SetEmptyImage      (UINT uImage);\r
+       void SetBackCardIdx (UINT uBackIdx);\r
+       void SetPlacement   (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);\r
+\r
+       void Update();\r
+       void Redraw();\r
+\r
+       void SetFaceDirection(UINT uDirType, int nOption);\r
+       UINT GetFaceDirection(int *pnOption);\r
+\r
+       void Flash(int count, int timeout);\r
+       void StopFlash();\r
+\r
+       int  Id();\r
+\r
+       CardWindow &GetCardWindow() { return parentWnd; }\r
+\r
+       bool PlayCard(CardRegion *pDestStack, int value, int num);\r
+       bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate);\r
+       bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate);\r
+\r
+       bool Lock();\r
+       bool UnLock();\r
+\r
+       //\r
+       //      Common wrappers for the CardStack object\r
+       //\r
+       int         NumCards() const;\r
+       void        NewDeck()        { cardstack.NewDeck();  }\r
+       void        Shuffle()        { cardstack.Shuffle();  }\r
+       void        Clear()          { cardstack.Clear();    }\r
+\r
+       void            Reverse()        { cardstack.Reverse();  }\r
+       \r
+       void            Push(const Card card)     { cardstack.Push(card); }\r
+       void            Push(const CardStack &cs) { cardstack.Push(cs);   }\r
+\r
+       Card            Pop()          { return cardstack.Pop();      }\r
+       CardStack       Pop(int items) { return cardstack.Pop(items); }\r
+\r
+       Card            Top()          { return cardstack.Top();      }\r
+       CardStack       Top(int items) { return cardstack.Top(items); }\r
+\r
+\r
+private:\r
+\r
+       void DoFlash();\r
+       void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw);\r
+\r
+       void UpdateFaceDir(CardStack &cards);\r
+       void Clip(HDC hdc);\r
+       void Render(HDC hdc);\r
+       int      GetOverlapRatio(int x, int y, int width, int height);\r
+\r
+       void MoveDragCardTo(HDC hdc, int x, int y);\r
+       void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest);\r
+\r
+       void RenderBottomMost(HDC hdc, int minustopmost = 0);\r
+       void PrepareDragBitmaps(int numtodrag);\r
+       void PrepareDragBitmapsThreed(int numtodrag);\r
+       void ReleaseDragBitmaps(void);\r
+\r
+       bool CanDragCards(int iNumCards);\r
+       bool CanDropCards(CardStack &cards);\r
+       \r
+       void CalcApparentCards();\r
+       int      CalcApparentCards(int realnum);\r
+\r
+       void UpdateSize();\r
+       void AdjustPosition(int winwidth, int winheight);\r
+\r
+       bool IsPointInStack(int x, int y);\r
+\r
+       int       GetNumDragCards(int x, int y);\r
+       bool  OnLButtonDown(int x, int y);\r
+       bool  OnLButtonDblClk(int x, int y);\r
+       bool  OnMouseMove(int x, int y);\r
+       bool  OnLButtonUp(int x, int y);\r
+\r
+       \r
+       //\r
+       //      Private data members\r
+       //\r
+\r
+       int             id;\r
+       \r
+       CardWindow &parentWnd;\r
+       \r
+       CardStack  cardstack;   //cards in this stack\r
+       CardStack  dragstack;   //cards which we might be dragging\r
+\r
+       bool    fMouseDragging;\r
+\r
+       int             xoffset;                //direction that cards take\r
+       int             yoffset;\r
+       \r
+       int             xpos;                   //coordinates of stack\r
+       int             ypos;\r
+\r
+       int             width;                  //stack-size of all cards\r
+       int             height;\r
+\r
+       //\r
+       //      justify / placement vars\r
+       int             xjustify;\r
+       int             yjustify;\r
+       int             xadjust;\r
+       int             yadjust;\r
+\r
+       //\r
+       //      Used for mouse-dragging / moving cards\r
+       //\r
+       int             iNumDragCards;\r
+       int             mousexoffset;   \r
+       int             mouseyoffset;\r
+       int             oldx;\r
+       int             oldy;\r
+       \r
+       int             nDragCardWidth;\r
+       int             nDragCardHeight;\r
+       \r
+       HDC             hdcBackGnd;\r
+       HBITMAP hbmBackGnd;\r
+       HDC             hdcDragCard;\r
+       HBITMAP hbmDragCard;\r
+\r
+       int             nNumApparentCards;\r
+       int             nThreedCount;\r
+       bool    fVisible;\r
+       \r
+       int             nFlashCount;\r
+       bool    fFlashVisible;\r
+       UINT    uFlashTimer;\r
+\r
+       COLORREF crBackgnd;\r
+\r
+       UINT    uEmptyImage;\r
+       UINT    uFaceDirType;\r
+       int             nFaceDirOption;\r
+       int             nBackCardIdx;\r
+\r
+       UINT    uDragRule;\r
+       UINT    uDropRule;\r
+       \r
+       //\r
+       //      Stack callback support\r
+       //      \r
+       pCanDragProc    CanDragCallback;\r
+       pCanDropProc    CanDropCallback;\r
+       pClickProc              ClickCallback;\r
+       pClickProc              DblClickCallback;\r
+       pAddProc                AddCallback;\r
+       pRemoveProc             RemoveCallback;\r
+\r
+       //locking mechanism to prevent user dragging etc\r
+       HANDLE                  mxlock;         \r
+};\r
+\r
+#endif\r
+\r
diff --git a/rosapps/games/solitaire/cardlib/cardrgndraw.cpp b/rosapps/games/solitaire/cardlib/cardrgndraw.cpp
new file mode 100644 (file)
index 0000000..32d8bbf
--- /dev/null
@@ -0,0 +1,613 @@
+//\r
+//     CardLib - CardRegion drawing support\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include "cardlib.h"\r
+#include "cardregion.h"\r
+#include "cardcolor.h"\r
+\r
+HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette);\r
+void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
+void CardBlt(HDC hdc, int x, int y, int nCardNum);\r
+void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);\r
+\r
+//\r
+//     Draw specified card at position x, y\r
+//     xoff   - source offset from left of card\r
+//     yoff   - source offset from top of card\r
+//     width  - width to draw\r
+//     height - height to draw\r
+//\r
+void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height)\r
+{\r
+       int sx = nCardNum * __cardwidth;\r
+       int sy = 0;\r
+       int width  = __cardwidth;\r
+       int height = __cardheight;\r
+\r
+       //draw main center band\r
+       BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY);\r
+\r
+       //draw the two bits to the left\r
+       BitBlt(hdc, x,   y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY);\r
+       BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY);\r
+\r
+       //draw the two bits to the right\r
+       BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY);\r
+       BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY);\r
+}\r
+\r
+//\r
+//     Draw a shape this this:\r
+//\r
+//   ++++++++++++\r
+//  ++++++++++++++\r
+// ++            ++\r
+//\r
+void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips)\r
+{\r
+       int sx  = nCardNum * __cardwidth;\r
+       int sy  = 0;\r
+       int one = 1;\r
+       int two = 2;\r
+       BOOL tips = fDrawTips ? FALSE : TRUE;\r
+\r
+       if(height == 0) return;\r
+\r
+       if(height < 0)\r
+       {\r
+               sy = sy + __cardheight;\r
+               y  -= height;\r
+               one = -one;\r
+               two = -two;\r
+       }\r
+\r
+       // draw the main vertical band\r
+       //\r
+       BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY);\r
+\r
+       //if(height <= 1) return;\r
+\r
+       // draw the "lips" at the left and right\r
+       BitBlt(hdc, x+1,             y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1,             sy+one, SRCCOPY);\r
+       BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY);\r
+\r
+       //if(height <= 2) return;\r
+\r
+       // draw the outer-most lips\r
+       BitBlt(hdc, x,               y+two, 1, height-two*tips, __hdcCardBitmaps, sx,               sy+two, SRCCOPY);\r
+       BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY);   \r
+}\r
+\r
+//\r
+//     Draw a shape like this:\r
+//\r
+//     +++\r
+//       +++\r
+//   +++\r
+//   +++\r
+//   +++\r
+//   +++\r
+//   +++\r
+//   +++\r
+//    +++\r
+//     +++\r
+//\r
+//\r
+void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips)\r
+{\r
+       int sx  = nCardNum * __cardwidth;\r
+       int sy  = 0;\r
+       int one = 1;\r
+       int two = 2;\r
+       BOOL tips = fDrawTips ? FALSE : TRUE;\r
+\r
+       if(width == 0) return;\r
+       \r
+\r
+       if(width < 0)\r
+       {\r
+               sx = sx + __cardwidth;\r
+               x  -= width;\r
+               one = -1;\r
+               two = -2;\r
+       }\r
+\r
+       // draw the main vertical band\r
+       //\r
+       BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY);\r
+\r
+       //if(width <= 1) return;\r
+\r
+       // draw the "lips" at the top and bottom\r
+       BitBlt(hdc, x+one, y+1,              width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1,              SRCCOPY);\r
+       BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY);\r
+\r
+       //if(width <= 2) return;\r
+\r
+       // draw the outer-most lips\r
+       BitBlt(hdc, x+two, y,                width-two*tips, 1, __hdcCardBitmaps, sx+two, sy,                  SRCCOPY);\r
+       BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY);\r
+}\r
+\r
+//\r
+//     xdir -   <0 or >0\r
+//     ydir -   <0 or >0\r
+//\r
+void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir)\r
+{\r
+       int sx = cardval * __cardwidth;\r
+       int sy = 0;\r
+\r
+       HDC hdcSource = __hdcCardBitmaps;\r
+\r
+       if(xdir < 0) \r
+       {\r
+               x  += __cardwidth + xdir - 1;\r
+               sx += __cardwidth + xdir - 1;\r
+       }\r
+       else\r
+       {\r
+               x  += xdir;\r
+               sx += xdir;\r
+       }\r
+\r
+       if(ydir < 0) \r
+       {\r
+               y  += __cardheight + ydir - 1;\r
+               sy += __cardheight + ydir - 1;\r
+       }\r
+       else\r
+       {\r
+               y  += ydir;\r
+               sy += ydir;\r
+       }\r
+\r
+       //convert x,y directions to -1, +1\r
+       xdir = xdir < 0 ? -1 : 1;\r
+       ydir = ydir < 0 ? -1 : 1;\r
+\r
+       SetPixel(hdc, x+xdir, y ,     GetPixel(hdcSource, sx+xdir, sy));\r
+       SetPixel(hdc, x,      y,      GetPixel(hdcSource, sx,      sy));\r
+       SetPixel(hdc, x,      y+ydir, GetPixel(hdcSource, sx,      sy+ydir));\r
+\r
+}\r
+\r
+//\r
+//     Draw a card (i.e. miss out the corners)\r
+//\r
+void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height)\r
+{\r
+       //draw main center band\r
+       BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY);\r
+\r
+       //draw the two bits to the left\r
+       BitBlt(hdc, x,   y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY);\r
+       BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY);\r
+\r
+       //draw the two bits to the right\r
+       BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY);\r
+       BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY);\r
+}\r
+\r
+//\r
+//     Clip a card SHAPE - basically any rectangle\r
+//  with rounded corners\r
+//\r
+int ClipCard(HDC hdc, int x, int y, int width, int height)\r
+{\r
+       ExcludeClipRect(hdc, x+2,               y,       x+2+width-4, y+  height);\r
+       ExcludeClipRect(hdc, x,                 y+2, x+1,                 y+2+height-4);\r
+       ExcludeClipRect(hdc, x+1,               y+1, x+2,                 y+1+height-2);\r
+       ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2);\r
+       ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4);\r
+       return 0;\r
+}\r
+\r
+void CardRegion::Clip(HDC hdc)\r
+{\r
+       int numtoclip;\r
+\r
+       if(fVisible == false) \r
+               return;\r
+\r
+       Update();                               //Update this stack's size+card count\r
+       numtoclip = nNumApparentCards;\r
+\r
+       //if we are making this stack flash on/off, then only \r
+       //clip the stack for drawing if the flash is in its ON state\r
+       if(nFlashCount != 0)\r
+       {\r
+               if(fFlashVisible == FALSE)\r
+                       numtoclip = 0;\r
+       }\r
+\r
+       //if offset along a diagonal\r
+       if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0)\r
+       {\r
+               for(int j = 0; j < numtoclip; j ++)\r
+               {       \r
+                       ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight);\r
+               }       \r
+       }\r
+       //otherwise if just offset along a horizontal/vertical axis\r
+       else\r
+       {\r
+               if(yoffset < 0 && numtoclip > 0)\r
+               {\r
+                       ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height);\r
+               }\r
+               else if(xoffset < 0 && numtoclip > 0)\r
+               {\r
+                       ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height);\r
+               }\r
+               else\r
+               {\r
+                       ClipCard(hdc, xpos, ypos, width, height);\r
+               }\r
+       }\r
+\r
+}\r
+\r
+void CardRegion::Render(HDC hdc)\r
+{\r
+       int cardnum = 0;\r
+       int numtodraw;\r
+       BOOL fDrawTips;\r
+       \r
+       Update();                       //Update this stack's card count + size\r
+\r
+       numtodraw = nNumApparentCards;\r
+\r
+       if(nFlashCount != 0)\r
+       {\r
+               if(fFlashVisible == false)\r
+                       numtodraw = 0;\r
+       }\r
+\r
+       if(fVisible == 0) return;\r
+       \r
+       cardnum = cardstack.NumCards() - numtodraw;\r
+       int counter;\r
+\r
+       for(counter = 0; counter < numtodraw; counter++)\r
+       {\r
+               int cardval;\r
+               \r
+               int x = xoffset * counter + xpos;\r
+               int y = yoffset * counter + ypos;\r
+\r
+               //if about to draw last card, then actually draw the top card\r
+               if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1;\r
+               \r
+               Card card = cardstack.cardlist[cardnum];\r
+               cardval = card.Idx();\r
+               \r
+               if(card.FaceDown())\r
+                       cardval = nBackCardIdx; //card-back\r
+                       \r
+               //only draw the visible part of the card\r
+               if(counter < numtodraw - 1)\r
+               {\r
+                       if(yoffset != 0 && xoffset != 0)\r
+                               fDrawTips = FALSE;\r
+                       else\r
+                               fDrawTips = TRUE;\r
+\r
+                       if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1)\r
+                               fDrawTips = TRUE;\r
+\r
+                       //draw horizontal strips\r
+                       if(yoffset > 0) \r
+                       {\r
+                               DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips);\r
+                       }\r
+                       else if(yoffset < 0)\r
+                       {\r
+                               DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips);\r
+                       }\r
+\r
+                       //draw some vertical bars\r
+                       if(xoffset > 0)\r
+                       {\r
+                               DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips);\r
+                       }\r
+                       else if(xoffset < 0)\r
+                       {\r
+                               DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips);\r
+                       }\r
+\r
+                       if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE)\r
+                       {\r
+                               //if we didn't draw any tips, then this is a 2-dim stack\r
+                               //(i.e, it goes at a diagonal).\r
+                               //in this case, we need to fill in the small triangle in\r
+                               //each corner!\r
+                               DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset);\r
+                       }\r
+               }\r
+               //if the top card, draw the whole thing\r
+               else\r
+               {\r
+                       CardBlt(hdc, x, y, cardval);\r
+               }\r
+\r
+               cardnum ++;\r
+\r
+       } //end of index\r
+       \r
+       if(counter == 0)        //if the cardstack is empty, then draw it that way\r
+       {\r
+               int x = xpos;\r
+               int y = ypos;\r
+               \r
+               switch(uEmptyImage)\r
+               {\r
+               default: case CS_EI_NONE:\r
+                       //this wipes the RECT variable, so watch out!\r
+                       //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);\r
+                       //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));\r
+                       parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y);\r
+                       break;\r
+                       \r
+               case CS_EI_SUNK:        //case CS_EI_CIRC: case CS_EI_X:\r
+                       DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight);\r
+                       break;\r
+               }\r
+               \r
+       }\r
+\r
+       return;\r
+}\r
+\r
+int calc_offset(int offset, int numcards, int numtodrag, int realvisible)\r
+{\r
+       if(offset >= 0)\r
+               return -offset * numcards;\r
+       else\r
+               return -offset * (numtodrag)       + \r
+                          -offset * (realvisible - 1);\r
+}\r
+\r
+void CardRegion::PrepareDragBitmaps(int numtodrag)\r
+{\r
+       RECT rect;\r
+       HDC hdc;\r
+       int icard;\r
+       int numcards = cardstack.NumCards();\r
+       int xoff, yoff;\r
+\r
+       if(nThreedCount > 1)\r
+       {\r
+               PrepareDragBitmapsThreed(numtodrag);\r
+               return;\r
+       }\r
+\r
+       //work out how big the bitmaps need to be\r
+       nDragCardWidth  = (numtodrag - 1) * abs(xoffset) + __cardwidth;\r
+       nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;\r
+\r
+       //Create bitmap for the back-buffer\r
+       hdc = GetDC(NULL);\r
+       hdcBackGnd = CreateCompatibleDC(hdc);\r
+       hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
+       SelectObject(hdcBackGnd, hbmBackGnd);\r
+\r
+       //Create bitmap for the drag-image\r
+       hdcDragCard = CreateCompatibleDC(hdc);\r
+       hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
+       SelectObject(hdcDragCard, hbmDragCard);\r
+       ReleaseDC(NULL, hdc);\r
+\r
+       UseNicePalette(hdcBackGnd,  __hPalette);\r
+       UseNicePalette(hdcDragCard, __hPalette);\r
+\r
+       int realvisible = numcards / nThreedCount;\r
+\r
+       //if(numcards > 0 && realvisible == 0) realvisible = 1;\r
+       int iwhichcard = numcards - 1;\r
+       if(nThreedCount == 1) iwhichcard = 0;\r
+\r
+       //grab the first bit of background so we can prep the back buffer; do this by\r
+       //rendering the card stack (minus the card we are dragging) to the temporary\r
+       //background buffer, so it appears if we have lifted the card from the stack\r
+       //PaintRect(hdcBackGnd, &rect, crBackgnd);\r
+       SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);\r
\r
+       xoff = calc_offset(xoffset, numcards, numtodrag, realvisible);\r
+       yoff = calc_offset(yoffset, numcards, numtodrag, realvisible);\r
+       \r
+       parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff,  ypos - yoff);\r
+\r
+       //\r
+       //      Render the cardstack into the back-buffer. The stack\r
+       //      has already had the dragcards removed, so just draw\r
+       //      what is left\r
+       //\r
+       for(icard = 0; icard < realvisible; icard++)\r
+       {\r
+               Card card = cardstack.cardlist[iwhichcard];\r
+               int nCardVal;\r
+               \r
+               nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
+\r
+               xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);\r
+               yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);\r
+\r
+               CardBlt(hdcBackGnd, xoff, yoff, nCardVal);\r
+               iwhichcard++;\r
+       }\r
+       \r
+       //\r
+       // If there are no cards under this one, just draw the place holder\r
+       //\r
+       if(numcards == 0)   \r
+       {\r
+               int xoff = 0, yoff = 0;\r
+\r
+               if(xoffset < 0) xoff = nDragCardWidth  -  __cardwidth;\r
+               if(yoffset < 0) yoff = nDragCardHeight -  __cardheight;\r
+\r
+               switch(uEmptyImage)\r
+               {\r
+               case CS_EI_NONE:\r
+                       //No need to draw anything: We already cleared the\r
+                       //back-buffer before the main loop..\r
+\r
+                       //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);\r
+                       //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));\r
+                       //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);\r
+                       break;\r
+\r
+               case CS_EI_SUNK:\r
+                       DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       //\r
+       //      now render the drag-cards into the dragcard image\r
+       //\r
+       PaintRect(hdcDragCard, &rect, crBackgnd);\r
+\r
+       for(icard = 0; icard < numtodrag; icard++)\r
+       {\r
+               int nCardVal;\r
+\r
+               if(xoffset >= 0) xoff =  xoffset * icard;\r
+               else                     xoff = -xoffset * (numtodrag - icard - 1);\r
+                       \r
+               if(yoffset >= 0) yoff =  yoffset * icard;\r
+               else             yoff = -yoffset * (numtodrag - icard - 1);\r
+\r
+               Card card = dragstack.cardlist[icard];\r
+               \r
+               nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
+\r
+               CardBlt(hdcDragCard, xoff, yoff, nCardVal);\r
+       }\r
+}\r
+\r
+void CardRegion::PrepareDragBitmapsThreed(int numtodrag)\r
+{\r
+       RECT rect;\r
+       HDC hdc;\r
+       int icard;\r
+       int numunder = 0;\r
+       int iwhichcard;\r
+\r
+       int numcards = cardstack.NumCards();\r
+\r
+       //work out how big the bitmaps need to be\r
+       nDragCardWidth  = (numtodrag - 1) * abs(xoffset) + __cardwidth;\r
+       nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;\r
+\r
+       //Create bitmap for the back-buffer\r
+       hdc = GetDC(NULL);\r
+       hdcBackGnd = CreateCompatibleDC(hdc);\r
+       hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
+       SelectObject(hdcBackGnd, hbmBackGnd);\r
+\r
+       //create bitmap for the drag-image\r
+       hdcDragCard = CreateCompatibleDC(hdc);\r
+       hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
+       SelectObject(hdcDragCard, hbmDragCard);\r
+       ReleaseDC(NULL, hdc);\r
+\r
+       UseNicePalette(hdcBackGnd,  __hPalette);\r
+       UseNicePalette(hdcDragCard, __hPalette);\r
+\r
+       //grab the first bit of background so we can prep the back buffer; do this by\r
+       //rendering the card stack (minus the card we are dragging) to the temporary\r
+       //background buffer, so it appears if we have lifted the card from the stack\r
+       //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);\r
+       //--PaintRect(hdcBackGnd, &rect, crBackgnd);\r
+\r
+       int threedadjust = numcards  % nThreedCount == 0;\r
+       \r
+       numunder = CalcApparentCards(numcards);\r
+       iwhichcard = (numcards+numtodrag) - numunder - 1;\r
+       if(nThreedCount == 1) iwhichcard = 0;\r
+       \r
+       int xoff = calc_offset(xoffset, numunder, numtodrag, numunder);\r
+       int yoff = calc_offset(yoffset, numunder, numtodrag, numunder);\r
+\r
+       parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff);\r
+\r
+       //\r
+       //      Render the cardstack into the back-buffer. The stack\r
+       //      has already had the dragcards removed, so just draw\r
+       //      what is left\r
+       //\r
+       for(icard = 0; icard < numunder; icard++)\r
+       {\r
+               Card card = cardstack.cardlist[iwhichcard];\r
+               int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
+\r
+               CardBlt(hdcBackGnd, \r
+                               xoffset * icard - xoffset*(numunder-numtodrag+threedadjust),\r
+                               yoffset * icard - yoffset*(numunder-numtodrag+threedadjust),\r
+                               nCardVal);\r
+\r
+               iwhichcard++;\r
+       }\r
+       \r
+       //\r
+       // If there are no cards under this one, just draw the place holder\r
+       //\r
+       if(numcards == 0)   \r
+       {\r
+               switch(uEmptyImage)\r
+               {\r
+               case CS_EI_NONE:\r
+                       //no need! we've already cleared the whole\r
+                       //back-buffer before the main loop!\r
+                       //SetRect(&rect, 0, 0, __cardwidth, __cardheight);\r
+                       //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));\r
+                       break;\r
+\r
+               case CS_EI_SUNK:\r
+                       DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight);\r
+                       break;\r
+       \r
+               }\r
+       }\r
+\r
+       //\r
+       //      now render the drag-cards into the dragcard image\r
+       //\r
+       PaintRect(hdcDragCard, &rect, crBackgnd);\r
+       \r
+       for(icard = 0; icard < numtodrag; icard++)\r
+       {\r
+               Card card = dragstack.cardlist[icard];\r
+               int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
+\r
+               CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal);\r
+       }\r
+}\r
+\r
+void CardRegion::ReleaseDragBitmaps(void)\r
+{\r
+       //SelectObject(hdcBackGnd, hOld1);\r
+       DeleteObject(hbmBackGnd);\r
+       DeleteDC(hdcBackGnd);\r
+\r
+       //SelectObject(hdcDragCard, hOld2);\r
+       DeleteObject(hbmDragCard);\r
+       DeleteDC(hdcDragCard);\r
+}\r
+\r
+\r
+void CardRegion::Redraw()\r
+{\r
+       HDC hdc = GetDC((HWND)parentWnd);\r
+\r
+       Update();\r
+       Render(hdc);\r
+\r
+       ReleaseDC((HWND)parentWnd, hdc);\r
+}\r
diff --git a/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp b/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp
new file mode 100644 (file)
index 0000000..a3bf6e7
--- /dev/null
@@ -0,0 +1,618 @@
+//\r
+//     CardLib - CardRegion mouse-related stuff\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <math.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardwindow.h"\r
+#include "cardregion.h"\r
+\r
+double __CARDZOOMSPEED = 32;\r
+\r
+int ClipCard(HDC hdc, int x, int y, int width, int height);\r
+void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);\r
+\r
+#ifdef _DEBUG\r
+\r
+static pDebugClickProc DebugStackClickProc = 0;\r
+\r
+void CardLib_SetStackClickProc(pDebugClickProc proc)\r
+{\r
+       DebugStackClickProc = proc;\r
+}\r
+\r
+#endif\r
+\r
+CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)\r
+{\r
+       int maxoverlap    =  0;\r
+       int maxoverlapidx = -1;\r
+\r
+       //find the stack which is most covered by the dropped\r
+       //cards. Only include those which allow drops.\r
+       //\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               int percent = Regions[i]->GetOverlapRatio(x, y, w, h);\r
+\r
+               //if this stack has the biggest coverage yet\r
+               if(percent > maxoverlap && Regions[i]->IsVisible())\r
+               {\r
+                       maxoverlap = percent;\r
+                       maxoverlapidx = i;\r
+               }\r
+       }\r
+       \r
+       //if we found a stack to drop onto\r
+       if(maxoverlapidx != -1)\r
+       {\r
+               return Regions[maxoverlapidx];\r
+       }\r
+       else\r
+       {\r
+               return 0;\r
+       }\r
+}\r
+\r
+bool CardRegion::IsPointInStack(int x, int y)\r
+{\r
+       int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;\r
+       int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;\r
+       \r
+       if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)\r
+               return true;\r
+       else\r
+               return false;\r
+}\r
+\r
+int CardRegion::GetNumDragCards(int x, int y)\r
+{\r
+       int cardindex = 0;              //index from stack start\r
+       int maxidx;\r
+\r
+       //make x,y relative to the stack's upper left corner\r
+       x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);\r
+       y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);\r
+       \r
+       //if stack is empty, cannot drag any cards from it\r
+       if(cardstack.NumCards() <= 0)\r
+               return 0;\r
+\r
+       //see which card in the stack has been clicked on\r
+       //top-bottom ordering\r
+       if(yoffset > 0)\r
+       {\r
+               if(y < height - __cardheight)\r
+                       cardindex = y / yoffset;\r
+               else\r
+                       cardindex = cardstack.NumCards() - 1;\r
+       }\r
+       else if(yoffset < 0)\r
+       {\r
+               if(y < __cardheight)\r
+                       cardindex = cardstack.NumCards() - 1;\r
+               else\r
+                       cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;\r
+       }\r
+       else    //yoffset == 0\r
+       {\r
+               cardindex = cardstack.NumCards() - 1;\r
+       }\r
+\r
+       maxidx = cardindex;\r
+\r
+       //if left-right\r
+       if(xoffset > 0)\r
+       {\r
+               if(x < width - __cardwidth)\r
+                       cardindex = x / xoffset;\r
+               else\r
+                       cardindex = cardstack.NumCards() - 1;\r
+       }\r
+       else if(xoffset < 0)\r
+       {\r
+               if(x < __cardwidth)\r
+                       cardindex = cardstack.NumCards() - 1;\r
+               else\r
+                       cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;\r
+       }\r
+       else\r
+       {\r
+               cardindex = cardstack.NumCards() - 1;\r
+       }\r
+\r
+       if(cardindex > maxidx) cardindex = maxidx;\r
+\r
+       if(cardindex > cardstack.NumCards())\r
+               cardindex = 1;\r
+\r
+       //if are trying to drag too many cards at once\r
+       return cardstack.NumCards() - cardindex;\r
+}\r
+\r
+bool CardRegion::CanDragCards(int iNumCards)\r
+{\r
+       if(iNumCards <= 0) return false;\r
+       if(nThreedCount > 1 && iNumCards > 1) return false;\r
+\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+//             TRACE("Failed to gain access to card stack\n");\r
+               return false;\r
+       }\r
+\r
+       ReleaseMutex(mxlock);\r
+\r
+       switch(uDragRule)\r
+       {\r
+       case CS_DRAG_ALL:\r
+               return true;\r
+               \r
+       case CS_DRAG_TOP:\r
+\r
+               if(iNumCards == 1)\r
+                       return true;\r
+               else\r
+                       return false;\r
+               \r
+       case CS_DRAG_NONE:\r
+               return false;\r
+               \r
+       case CS_DRAG_CALLBACK:\r
+               \r
+               if(CanDragCallback)\r
+               {\r
+                       return CanDragCallback(*this, iNumCards);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+               \r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::CanDropCards(CardStack &cards)\r
+{\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       ReleaseMutex(mxlock);\r
+\r
+       switch(uDropRule)\r
+       {\r
+       case CS_DROP_ALL:\r
+               return true;\r
+\r
+       case CS_DROP_NONE:\r
+               return false;\r
+\r
+       case CS_DROP_CALLBACK:\r
+               \r
+               if(CanDropCallback)\r
+               {\r
+                       return CanDropCallback(*this, cards);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+\r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::OnLButtonDblClk(int x, int y)\r
+{\r
+       iNumDragCards = GetNumDragCards(x, y); \r
+\r
+       if(DblClickCallback)\r
+               DblClickCallback(*this, iNumDragCards);\r
+\r
+       return true;\r
+}\r
+\r
+bool CardRegion::OnLButtonDown(int x, int y)\r
+{\r
+       iNumDragCards = GetNumDragCards(x, y); \r
+\r
+#ifdef _DEBUG\r
+       if(DebugStackClickProc)\r
+       {\r
+               if(!DebugStackClickProc(*this))\r
+                       return false;\r
+       }\r
+#endif\r
+\r
+       if(ClickCallback)\r
+               ClickCallback(*this, iNumDragCards);\r
+\r
+       if(CanDragCards(iNumDragCards) != false)\r
+    {\r
+\r
+               //offset of the mouse cursor relative to the top-left corner\r
+               //of the cards that are being dragged\r
+               mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);\r
+               mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);\r
+               \r
+               if(xoffset < 0)\r
+                       mousexoffset += -xoffset * (iNumDragCards - 1);\r
+\r
+               if(yoffset < 0)\r
+                       mouseyoffset += -yoffset * (iNumDragCards - 1);\r
+               \r
+               //remove the cards from the source stack\r
+               dragstack = cardstack.Pop(iNumDragCards);\r
+\r
+               //prepare the back buffer, and the drag image\r
+               PrepareDragBitmaps(iNumDragCards);\r
+\r
+               oldx = x - mousexoffset;\r
+               oldy = y - mouseyoffset;\r
+               \r
+               Update();                       //Update this stack's card count + size\r
+\r
+               SetCapture((HWND)parentWnd);\r
+\r
+               //set AFTER settings the dragstack...\r
+               fMouseDragging = true;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CardRegion::OnLButtonUp(int x, int y)\r
+{\r
+       CardRegion *pDestStack = 0;\r
+       HDC hdc;\r
+       int dropstackid = CS_DROPZONE_NODROP;\r
+       \r
+       RECT dragrect;\r
+       DropZone *dropzone;\r
+\r
+       fMouseDragging = false;\r
+\r
+       //first of all, see if any drop zones have been registered\r
+       SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);\r
+\r
+       dropzone = parentWnd.GetDropZoneFromRect(&dragrect);\r
+\r
+       if(dropzone)\r
+       {\r
+               dropstackid = dropzone->DropCards(dragstack);\r
+               \r
+               if(dropstackid != CS_DROPZONE_NODROP)\r
+                       pDestStack = parentWnd.CardRegionFromId(dropstackid);\r
+               else\r
+                       pDestStack = 0;\r
+       }\r
+       else\r
+       {\r
+               pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);\r
+       }\r
+       \r
+       // If have found a stack to drop onto\r
+       //\r
+       if(pDestStack && pDestStack->CanDropCards(dragstack)) \r
+       {\r
+               hdc = GetDC((HWND)parentWnd);\r
+               //                      UseNicePalette(hdc);\r
+               ZoomCard(hdc, x - mousexoffset, y  - mouseyoffset, pDestStack);\r
+               ReleaseDC((HWND)parentWnd, hdc);\r
+               \r
+               //\r
+               //add the cards to the destination stack\r
+               //\r
+               CardStack temp = pDestStack->GetCardStack();\r
+               temp.Push(dragstack);\r
+               \r
+               pDestStack->SetCardStack(temp);\r
+//             pDestStack->Update();           //Update this stack's card count + size\r
+//             pDestStack->UpdateFaceDir(temp);\r
+               \r
+               //      Call the remove callback on THIS stack, if one is specified\r
+               //\r
+               if(RemoveCallback)\r
+                       RemoveCallback(*this, iNumDragCards);\r
+\r
+               //      Call the add callback, if one is specified\r
+               //\r
+               if(pDestStack->AddCallback)\r
+                       pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);\r
+               \r
+               RedrawIfNotDim(pDestStack, true);\r
+       }       \r
+\r
+       //\r
+       //      Otherwise, let the cards snap back onto this stack\r
+       //\r
+       else\r
+       {\r
+               \r
+               hdc = GetDC((HWND)parentWnd);\r
+               ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);\r
+               cardstack += dragstack;\r
+               ReleaseDC((HWND)parentWnd, hdc);\r
+\r
+               Update();               //Update this stack's card count + size\r
+       }\r
+       \r
+       ReleaseDragBitmaps();\r
+       ReleaseCapture();\r
+       \r
+       return true;\r
+}\r
+\r
+bool CardRegion::OnMouseMove(int x, int y)\r
+{\r
+       HDC hdc;\r
+\r
+       hdc = GetDC((HWND)parentWnd);\r
+               \r
+       x -= mousexoffset;\r
+       y -= mouseyoffset;\r
+               \r
+       MoveDragCardTo(hdc, x, y);\r
+\r
+       //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
+       //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);\r
+       \r
+       ReleaseDC((HWND)parentWnd, hdc);\r
+               \r
+       oldx = x;\r
+       oldy = y;\r
+       \r
+       return true;\r
+}\r
+\r
+//\r
+//     There is a bug in BitBlt when the source x,y\r
+//     become < 0. So this wrapper function simply adjusts\r
+//     the coords so that we never try to blt in from this range\r
+//\r
+BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)\r
+{\r
+       if(srcx < 0)\r
+       {\r
+               x = 0 - srcx;\r
+               width = width + srcx;\r
+               srcx = 0;\r
+       }\r
+\r
+       if(srcy < 0)\r
+       {\r
+               y = 0 - srcy;\r
+               height = height + srcy;\r
+               srcy = 0;\r
+       }\r
+\r
+       return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);\r
+}\r
+\r
+void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)\r
+{\r
+       RECT inter, rect1, rect2;\r
+\r
+       //mask off the new position of the drag-card, so\r
+       //that it will not be painted over\r
+       ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);\r
+       \r
+       //restore the area covered by the card at its previous position\r
+       BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
+\r
+       //remove clipping so we can draw the card at its new place\r
+       SelectClipRgn(hdc, NULL);\r
+       \r
+       //if the card's old and new positions overlap, then we\r
+       //need some funky code to update the "saved background" image,\r
+       SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);\r
+       SetRect(&rect2,    x,    y,    x+nDragCardWidth,    y+nDragCardHeight);\r
+       \r
+       if(IntersectRect(&inter, &rect1, &rect2))\r
+       {\r
+               int interwidth = inter.right-inter.left;\r
+               int interheight = inter.bottom-inter.top;\r
+               int destx, desty, srcx, srcy;\r
+               \r
+               if(rect2.left > rect1.left) \r
+               {       \r
+                       destx = 0; srcx = nDragCardWidth - interwidth; \r
+               }\r
+               else\r
+               {\r
+                       destx = nDragCardWidth  - interwidth; srcx = 0;\r
+               }\r
+               \r
+               if(rect2.top  > rect1.top) \r
+               {\r
+                       desty = 0; srcy = nDragCardHeight - interheight;\r
+               }\r
+               else \r
+               {\r
+                       desty = nDragCardHeight - interheight; srcy = 0;\r
+               }\r
+               \r
+               //shift the bit we didn't use for the restore (due to the clipping)\r
+               //into the opposite corner\r
+               BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);\r
+               \r
+               ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);\r
+               \r
+               //this bit requires us to clip the BitBlt (from screen to background)\r
+               //as BitBlt is a bit buggy it seems\r
+               ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
+               SelectClipRgn(hdcBackGnd, NULL);\r
+       }\r
+       else\r
+       {\r
+               BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
+       }\r
+       \r
+       //finally draw the card to the screen\r
+       DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);\r
+}\r
+\r
+\r
+//extern "C" int _fltused(void) { return 0; }\r
+//extern "C" int _ftol(void) { return 0; }\r
+\r
+//\r
+//     Better do this in fixed-point, to stop\r
+//     VC from linking in floatingpoint-long conversions\r
+//\r
+//#define FIXED_PREC_MOVE\r
+#ifdef  FIXED_PREC_MOVE\r
+#define PRECISION 12\r
+void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)\r
+{\r
+       long dx, dy, x , y;\r
+\r
+       \r
+       int apparentcards;\r
+       x = xpos << PRECISION; y = ypos << PRECISION;\r
+\r
+       oldx = (int)xpos;\r
+       oldy = (int)ypos;\r
+\r
+       apparentcards=dest->numcards/dest->threedcount;\r
+\r
+       int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards); \r
+       int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);\r
+\r
+       //normalise the motion vector\r
+       dx = (idestx<<PRECISION) - x;\r
+       dy = (idesty<<PRECISION) - y;\r
+       long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);\r
+\r
+       dx *= recip * 16;//CARDZOOMSPEED; \r
+       dy *= recip * 16;//CARDZOOMSPEED;\r
+\r
+       //if(dx < 0) dxinc = 1.001; else\r
+\r
+       for(;;)\r
+       {\r
+               int ix, iy;\r
+               x += dx;\r
+               y += dy;\r
+\r
+               ix = (int)x>>PRECISION;\r
+               iy = (int)y>>PRECISION;\r
+               if(dx < 0 && ix < idestx) ix = idestx;\r
+               else if(dx > 0 && ix > idestx) ix = idestx;\r
+\r
+               if(dy < 0 && iy < idesty) iy = idesty;\r
+               else if(dy > 0 && iy > idesty) iy = idesty;\r
+\r
+               MoveDragCardTo(hdc, ix, iy);\r
+\r
+               if(ix == idestx && iy == idesty)\r
+                       break;\r
+\r
+               oldx = (int)x >> PRECISION;\r
+               oldy = (int)y >> PRECISION;\r
+\r
+               //dx *= 1.2;\r
+               //dy *= 1.2;\r
+\r
+               Sleep(10);\r
+       }\r
+}\r
+#else\r
+void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)\r
+{\r
+       double dx, dy, x ,y;\r
+       int apparentcards;\r
+       x = (double)xpos; y = (double)ypos;\r
+\r
+       oldx = (int)x;\r
+       oldy = (int)y;\r
+\r
+       apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;\r
+\r
+       int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);\r
+       int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);\r
+\r
+       if(pDestStack->yoffset < 0)\r
+               idesty += pDestStack->yoffset * (iNumDragCards-1);\r
+\r
+       if(pDestStack->xoffset < 0)\r
+               idestx += pDestStack->xoffset * (iNumDragCards-1);\r
+\r
+       //normalise the motion vector\r
+       dx = idestx - x;\r
+       dy = idesty - y;\r
+       double recip = 1.0 / sqrt(dx*dx + dy*dy);\r
+       dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;\r
+\r
+       //if(dx < 0) dxinc = 1.001; else\r
+\r
+       for(;;)\r
+       {\r
+               bool attarget = true;\r
+               int ix, iy;\r
+               x += dx;\r
+               y += dy;\r
+\r
+               ix = (int)x;\r
+               iy = (int)y;\r
+               if(dx < 0.0 && ix < idestx) ix = idestx; \r
+               else if(dx > 0.0 && ix > idestx) ix = idestx;\r
+               else attarget = false;\r
+\r
+               if(dy < 0.0 && iy < idesty) iy = idesty;\r
+               else if(dy > 0.0 && iy > idesty) iy = idesty;\r
+               else attarget = false;\r
+\r
+               //if the target stack wants the drag cards drawn differently\r
+               //to how they are, then redraw the drag card image just before\r
+               //the cards land\r
+               /*if(attarget == true)\r
+               {\r
+                       for(int i = 0; i < iNumDragCards; i++)\r
+                       {\r
+                               int xdraw = pDestStack->xoffset*i;\r
+                               int ydraw = pDestStack->yoffset*i;\r
+\r
+                               if(pDestStack->yoffset < 0)\r
+                                       ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);\r
+                               if(pDestStack->xoffset < 0)\r
+                                       xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);\r
+\r
+                               if(pDestStack->facedirection == CS_FACEUP && \r
+                                       pDestStack->numcards+i >= dest->numfacedown)\r
+                               {\r
+                                       //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);\r
+                               }\r
+                               else\r
+                               {\r
+                                       //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);\r
+                               }\r
+                       }\r
+               }*/\r
+\r
+               MoveDragCardTo(hdc, ix, iy);\r
+\r
+               if(attarget || ix == idestx && iy == idesty)\r
+                       break;\r
+\r
+               oldx = (int)x;\r
+               oldy = (int)y;\r
+\r
+               //dx *= 1.2;\r
+               //dy *= 1.2;\r
+\r
+               Sleep(10);\r
+       }\r
+}\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp.bak b/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp.bak
new file mode 100644 (file)
index 0000000..1a913dc
--- /dev/null
@@ -0,0 +1,618 @@
+//\r
+//     CardLib - CardRegion mouse-related stuff\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <math.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardwindow.h"\r
+#include "cardregion.h"\r
+\r
+double __CARDZOOMSPEED = 32;\r
+\r
+int ClipCard(HDC hdc, int x, int y, int width, int height);\r
+void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);\r
+\r
+#ifdef _DEBUG\r
+\r
+static pDebugClickProc DebugStackClickProc = 0;\r
+\r
+void CardLib_SetStackClickProc(pDebugClickProc proc)\r
+{\r
+       DebugStackClickProc = proc;\r
+}\r
+\r
+#endif\r
+\r
+CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)\r
+{\r
+       int maxoverlap    =  0;\r
+       int maxoverlapidx = -1;\r
+\r
+       //find the stack which is most covered by the dropped\r
+       //cards. Only include those which allow drops.\r
+       //\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               int percent = Regions[i]->GetOverlapRatio(x, y, w, h);\r
+\r
+               //if this stack has the biggest coverage yet\r
+               if(percent > maxoverlap && Regions[i]->IsVisible())\r
+               {\r
+                       maxoverlap = percent;\r
+                       maxoverlapidx = i;\r
+               }\r
+       }\r
+       \r
+       //if we found a stack to drop onto\r
+       if(maxoverlapidx != -1)\r
+       {\r
+               return Regions[maxoverlapidx];\r
+       }\r
+       else\r
+       {\r
+               return 0;\r
+       }\r
+}\r
+\r
+bool CardRegion::IsPointInStack(int x, int y)\r
+{\r
+       int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;\r
+       int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;\r
+       \r
+       if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)\r
+               return true;\r
+       else\r
+               return false;\r
+}\r
+\r
+int CardRegion::GetNumDragCards(int x, int y)\r
+{\r
+       int cardindex = 0;              //index from stack start\r
+       int maxidx;\r
+\r
+       //make x,y relative to the stack's upper left corner\r
+       x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);\r
+       y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);\r
+       \r
+       //if stack is empty, cannot drag any cards from it\r
+       if(cardstack.NumCards() <= 0)\r
+               return 0;\r
+\r
+       //see which card in the stack has been clicked on\r
+       //top-bottom ordering\r
+       if(yoffset > 0)\r
+       {\r
+               if(y < height - __cardheight)\r
+                       cardindex = y / yoffset;\r
+               else\r
+                       cardindex = cardstack.NumCards() - 1;\r
+       }\r
+       else if(yoffset < 0)\r
+       {\r
+               if(y < __cardheight)\r
+                       cardindex = cardstack.NumCards() - 1;\r
+               else\r
+                       cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;\r
+       }\r
+       else    //yoffset == 0\r
+       {\r
+               cardindex = cardstack.NumCards() - 1;\r
+       }\r
+\r
+       maxidx = cardindex;\r
+\r
+       //if left-right\r
+       if(xoffset > 0)\r
+       {\r
+               if(x < width - __cardwidth)\r
+                       cardindex = x / xoffset;\r
+               else\r
+                       cardindex = cardstack.NumCards() - 1;\r
+       }\r
+       else if(xoffset < 0)\r
+       {\r
+               if(x < __cardwidth)\r
+                       cardindex = cardstack.NumCards() - 1;\r
+               else\r
+                       cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;\r
+       }\r
+       else\r
+       {\r
+               cardindex = cardstack.NumCards() - 1;\r
+       }\r
+\r
+       if(cardindex > maxidx) cardindex = maxidx;\r
+\r
+       if(cardindex > cardstack.NumCards())\r
+               cardindex = 1;\r
+\r
+       //if are trying to drag too many cards at once\r
+       return cardstack.NumCards() - cardindex;\r
+}\r
+\r
+bool CardRegion::CanDragCards(int iNumCards)\r
+{\r
+       if(iNumCards <= 0) return false;\r
+       if(nThreedCount > 1 && iNumCards > 1) return false;\r
+\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+//             TRACE("Failed to gain access to card stack\n");\r
+               return false;\r
+       }\r
+\r
+       ReleaseMutex(mxlock);\r
+\r
+       switch(uDragRule)\r
+       {\r
+       case CS_DRAG_ALL:\r
+               return true;\r
+               \r
+       case CS_DRAG_TOP:\r
+\r
+               if(iNumCards == 1)\r
+                       return true;\r
+               else\r
+                       return false;\r
+               \r
+       case CS_DRAG_NONE:\r
+               return false;\r
+               \r
+       case CS_DRAG_CALLBACK:\r
+               \r
+               if(CanDragCallback)\r
+               {\r
+                       return CanDragCallback(*this, iNumCards);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+               \r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::CanDropCards(CardStack &cards)\r
+{\r
+       if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       ReleaseMutex(mxlock);\r
+\r
+       switch(uDropRule)\r
+       {\r
+       case CS_DROP_ALL:\r
+               return true;\r
+\r
+       case CS_DROP_NONE:\r
+               return false;\r
+\r
+       case CS_DROP_CALLBACK:\r
+               \r
+               if(CanDropCallback)\r
+               {\r
+                       return CanDropCallback(*this, cards);\r
+               }\r
+               else\r
+               {\r
+                       return false;\r
+               }\r
+\r
+       default:\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CardRegion::OnLButtonDblClk(int x, int y)\r
+{\r
+       iNumDragCards = GetNumDragCards(x, y); \r
+\r
+       if(DblClickCallback)\r
+               DblClickCallback(*this, iNumDragCards);\r
+\r
+       return true;\r
+}\r
+\r
+bool CardRegion::OnLButtonDown(int x, int y)\r
+{\r
+       iNumDragCards = GetNumDragCards(x, y); \r
+\r
+#ifdef _DEBUG\r
+       if(DebugStackClickProc)\r
+       {\r
+               if(!DebugStackClickProc(*this))\r
+                       return false;\r
+       }\r
+#endif\r
+\r
+       if(ClickCallback)\r
+               ClickCallback(*this, iNumDragCards);\r
+\r
+       if(CanDragCards(iNumDragCards) != false)\r
+    {\r
+\r
+               //offset of the mouse cursor relative to the top-left corner\r
+               //of the cards that are being dragged\r
+               mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);\r
+               mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);\r
+               \r
+               if(xoffset < 0)\r
+                       mousexoffset += -xoffset * (iNumDragCards - 1);\r
+\r
+               if(yoffset < 0)\r
+                       mouseyoffset += -yoffset * (iNumDragCards - 1);\r
+               \r
+               //remove the cards from the source stack\r
+               dragstack = cardstack.Pop(iNumDragCards);\r
+\r
+               //prepare the back buffer, and the drag image\r
+               PrepareDragBitmaps(iNumDragCards);\r
+\r
+               oldx = x - mousexoffset;\r
+               oldy = y - mouseyoffset;\r
+               \r
+               Update();                       //Update this stack's card count + size\r
+\r
+               SetCapture((HWND)parentWnd);\r
+\r
+               //set AFTER settings the dragstack...\r
+               fMouseDragging = true;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CardRegion::OnLButtonUp(int x, int y)\r
+{\r
+       CardRegion *pDestStack = 0;\r
+       HDC hdc;\r
+       int dropstackid = CS_DROPZONE_NODROP;\r
+       \r
+       RECT dragrect;\r
+       DropZone *dropzone;\r
+\r
+       fMouseDragging = false;\r
+\r
+       //first of all, see if any drop zones have been registered\r
+       SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);\r
+\r
+       dropzone = parentWnd.GetDropZoneFromRect(&dragrect);\r
+\r
+       if(dropzone)\r
+       {\r
+               dropstackid = dropzone->DropCards(dragstack);\r
+               \r
+               if(dropstackid != CS_DROPZONE_NODROP)\r
+                       pDestStack = parentWnd.CardRegionFromId(dropstackid);\r
+               else\r
+                       pDestStack = 0;\r
+       }\r
+       else\r
+       {\r
+               pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);\r
+       }\r
+       \r
+       // If have found a stack to drop onto\r
+       //\r
+       if(pDestStack && pDestStack->CanDropCards(dragstack)) \r
+       {\r
+               hdc = GetDC((HWND)parentWnd);\r
+               //                      UseNicePalette(hdc);\r
+               ZoomCard(hdc, x - mousexoffset, y  - mouseyoffset, pDestStack);\r
+               ReleaseDC((HWND)parentWnd, hdc);\r
+               \r
+               //\r
+               //add the cards to the destination stack\r
+               //\r
+               CardStack temp = pDestStack->GetCardStack();\r
+               temp.Push(dragstack);\r
+               \r
+               pDestStack->SetCardStack(temp);\r
+//             pDestStack->Update();           //Update this stack's card count + size\r
+//             pDestStack->UpdateFaceDir(temp);\r
+               \r
+               //      Call the remove callback on THIS stack, if one is specified\r
+               //\r
+               if(RemoveCallback)\r
+                       RemoveCallback(*this, iNumDragCards);\r
+\r
+               //      Call the add callback, if one is specified\r
+               //\r
+               if(pDestStack->AddCallback)\r
+                       pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);\r
+               \r
+               RedrawIfNotDim(pDestStack, true);\r
+       }       \r
+\r
+       //\r
+       //      Otherwise, let the cards snap back onto this stack\r
+       //\r
+       else\r
+       {\r
+               \r
+               hdc = GetDC((HWND)parentWnd);\r
+               ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);\r
+               cardstack += dragstack;\r
+               ReleaseDC((HWND)parentWnd, hdc);\r
+\r
+               Update();               //Update this stack's card count + size\r
+       }\r
+       \r
+       ReleaseDragBitmaps();\r
+       ReleaseCapture();\r
+       \r
+       return true;\r
+}\r
+\r
+bool CardRegion::OnMouseMove(int x, int y)\r
+{\r
+       HDC hdc;\r
+\r
+       hdc = GetDC((HWND)parentWnd);\r
+               \r
+       x -= mousexoffset;\r
+       y -= mouseyoffset;\r
+               \r
+       MoveDragCardTo(hdc, x, y);\r
+\r
+       //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
+       //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);\r
+       \r
+       ReleaseDC((HWND)parentWnd, hdc);\r
+               \r
+       oldx = x;\r
+       oldy = y;\r
+       \r
+       return true;\r
+}\r
+\r
+//\r
+//     There is a bug in BitBlt when the source x,y\r
+//     become < 0. So this wrapper function simply adjusts\r
+//     the coords so that we never try to blt in from this range\r
+//\r
+BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)\r
+{\r
+       if(srcx < 0)\r
+       {\r
+               x = 0 - srcx;\r
+               width = width + srcx;\r
+               srcx = 0;\r
+       }\r
+\r
+       if(srcy < 0)\r
+       {\r
+               y = 0 - srcy;\r
+               height = height + srcy;\r
+               srcy = 0;\r
+       }\r
+\r
+       return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);\r
+}\r
+\r
+void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)\r
+{\r
+       RECT inter, rect1, rect2;\r
+\r
+       //mask off the new position of the drag-card, so\r
+       //that it will not be painted over\r
+       ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);\r
+       \r
+       //restore the area covered by the card at its previous position\r
+       BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
+\r
+       //remove clipping so we can draw the card at its new place\r
+       SelectClipRgn(hdc, NULL);\r
+       \r
+       //if the card's old and new positions overlap, then we\r
+       //need some funky code to update the "saved background" image,\r
+       SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);\r
+       SetRect(&rect2,    x,    y,    x+nDragCardWidth,    y+nDragCardHeight);\r
+       \r
+       if(IntersectRect(&inter, &rect1, &rect2))\r
+       {\r
+               int interwidth = inter.right-inter.left;\r
+               int interheight = inter.bottom-inter.top;\r
+               int destx, desty, srcx, srcy;\r
+               \r
+               if(rect2.left > rect1.left) \r
+               {       \r
+                       destx = 0; srcx = nDragCardWidth - interwidth; \r
+               }\r
+               else\r
+               {\r
+                       destx = nDragCardWidth  - interwidth; srcx = 0;\r
+               }\r
+               \r
+               if(rect2.top  > rect1.top) \r
+               {\r
+                       desty = 0; srcy = nDragCardHeight - interheight;\r
+               }\r
+               else \r
+               {\r
+                       desty = nDragCardHeight - interheight; srcy = 0;\r
+               }\r
+               \r
+               //shift the bit we didn't use for the restore (due to the clipping)\r
+               //into the opposite corner\r
+               BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);\r
+               \r
+               ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);\r
+               \r
+               //this bit requires us to clip the BitBlt (from screen to background)\r
+               //as BitBlt is a bit buggy it seems\r
+               ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
+               SelectClipRgn(hdcBackGnd, NULL);\r
+       }\r
+       else\r
+       {\r
+               BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
+       }\r
+       \r
+       //finally draw the card to the screen\r
+       DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);\r
+}\r
+\r
+\r
+//extern "C" int _fltused(void) { return 0; }\r
+//extern "C" int _ftol(void) { return 0; }\r
+\r
+//\r
+//     Better do this in fixed-point, to stop\r
+//     VC from linking in floatingpoint-long conversions\r
+//\r
+//#define FIXED_PREC_MOVE\r
+#ifdef  FIXED_PREC_MOVE\r
+#define PRECISION 12\r
+void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)\r
+{\r
+       long dx, dy, x , y;\r
+\r
+       \r
+       int apparentcards;\r
+       x = xpos << PRECISION; y = ypos << PRECISION;\r
+\r
+       oldx = (int)xpos;\r
+       oldy = (int)ypos;\r
+\r
+       apparentcards=dest->numcards/dest->threedcount;\r
+\r
+       int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards); \r
+       int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);\r
+\r
+       //normalise the motion vector\r
+       dx = (idestx<<PRECISION) - x;\r
+       dy = (idesty<<PRECISION) - y;\r
+       long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);\r
+\r
+       dx *= recip * 16;//CARDZOOMSPEED; \r
+       dy *= recip * 16;//CARDZOOMSPEED;\r
+\r
+       //if(dx < 0) dxinc = 1.001; else\r
+\r
+       for(;;)\r
+       {\r
+               int ix, iy;\r
+               x += dx;\r
+               y += dy;\r
+\r
+               ix = (int)x>>PRECISION;\r
+               iy = (int)y>>PRECISION;\r
+               if(dx < 0 && ix < idestx) ix = idestx;\r
+               else if(dx > 0 && ix > idestx) ix = idestx;\r
+\r
+               if(dy < 0 && iy < idesty) iy = idesty;\r
+               else if(dy > 0 && iy > idesty) iy = idesty;\r
+\r
+               MoveDragCardTo(hdc, ix, iy);\r
+\r
+               if(ix == idestx && iy == idesty)\r
+                       break;\r
+\r
+               oldx = (int)x >> PRECISION;\r
+               oldy = (int)y >> PRECISION;\r
+\r
+               //dx *= 1.2;\r
+               //dy *= 1.2;\r
+\r
+               Sleep(10);\r
+       }\r
+}\r
+#else\r
+void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)\r
+{\r
+       double dx, dy, x ,y;\r
+       int apparentcards;\r
+       x = (double)xpos; y = (double)ypos;\r
+\r
+       oldx = (int)x;\r
+       oldy = (int)y;\r
+\r
+       apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;\r
+\r
+       int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);\r
+       int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);\r
+\r
+       if(pDestStack->yoffset < 0)\r
+               idesty += pDestStack->yoffset * (iNumDragCards-1);\r
+\r
+       if(pDestStack->xoffset < 0)\r
+               idestx += pDestStack->xoffset * (iNumDragCards-1);\r
+\r
+       //normalise the motion vector\r
+       dx = idestx - x;\r
+       dy = idesty - y;\r
+       double recip = 1.0 / sqrt(dx*dx + dy*dy);\r
+       dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;\r
+\r
+       //if(dx < 0) dxinc = 1.001; else\r
+\r
+       for(;;)\r
+       {\r
+               bool attarget = true;\r
+               int ix, iy;\r
+               x += dx;\r
+               y += dy;\r
+\r
+               ix = (int)x;\r
+               iy = (int)y;\r
+               if(dx < 0.0 && ix < idestx) ix = idestx; \r
+               else if(dx > 0.0 && ix > idestx) ix = idestx;\r
+               else attarget = false;\r
+\r
+               if(dy < 0.0 && iy < idesty) iy = idesty;\r
+               else if(dy > 0.0 && iy > idesty) iy = idesty;\r
+               else attarget = false;\r
+\r
+               //if the target stack wants the drag cards drawn differently\r
+               //to how they are, then redraw the drag card image just before\r
+               //the cards land\r
+               /*if(attarget == true)\r
+               {\r
+                       for(int i = 0; i < iNumDragCards; i++)\r
+                       {\r
+                               int xdraw = pDestStack->xoffset*i;\r
+                               int ydraw = pDestStack->yoffset*i;\r
+\r
+                               if(pDestStack->yoffset < 0)\r
+                                       ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);\r
+                               if(pDestStack->xoffset < 0)\r
+                                       xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);\r
+\r
+                               if(pDestStack->facedirection == CS_FACEUP && \r
+                                       pDestStack->numcards+i >= dest->numfacedown)\r
+                               {\r
+                                       //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);\r
+                               }\r
+                               else\r
+                               {\r
+                                       //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);\r
+                               }\r
+                       }\r
+               }*/\r
+\r
+               MoveDragCardTo(hdc, ix, iy);\r
+\r
+               if(attarget || ix == idestx && iy == idesty)\r
+                       break;\r
+\r
+               oldx = (int)x;\r
+               oldy = (int)y;\r
+\r
+               //dx *= 1.2;\r
+               //dy *= 1.2;\r
+\r
+               Sleep(10);\r
+       }\r
+}\r
+#endif
\ No newline at end of file
diff --git a/rosapps/games/solitaire/cardlib/cardstack.cpp b/rosapps/games/solitaire/cardlib/cardstack.cpp
new file mode 100644 (file)
index 0000000..147c096
--- /dev/null
@@ -0,0 +1,237 @@
+//\r
+//     CardLib - CardStack class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <stdlib.h>\r
+\r
+#include "cardstack.h"\r
+\r
+Card &CardStack::operator[] (size_t index)\r
+{\r
+       if(index >= (size_t)nNumCards) index = nNumCards - 1;\r
+       return cardlist[nNumCards - index - 1];\r
+}\r
+\r
+const Card &CardStack::operator[] (size_t index) const\r
+{\r
+       if(index >= (size_t)nNumCards) index = nNumCards - 1;\r
+       return cardlist[nNumCards - index - 1];\r
+}\r
+\r
+//     Subscripting operator for a constant sequence\r
+//\r
+/*Card CardStack::operator[] (size_t index) const\r
+{\r
+       return cardlist[index];\r
+}*/\r
+\r
+//\r
+//     Subscripting operator for a non-const sequence\r
+//\r
+/*CardStack::ref  CardStack::operator[] (size_t index)\r
+{\r
+       return ref(this, index);\r
+}*/\r
+\r
+void CardStack::Clear()\r
+{\r
+       nNumCards = 0;\r
+}\r
+\r
+void CardStack::NewDeck()\r
+{\r
+       nNumCards = 52;\r
+\r
+       for(int i = 0; i < 52; i++)\r
+               cardlist[i].nValue = i;\r
+}\r
+\r
+void CardStack::Shuffle()\r
+{\r
+       int src, dest;\r
+       Card temp;\r
+\r
+       //shuffle 8 times..\r
+       for(int i = 0; i < 8; i++)\r
+               for(dest = nNumCards - 1; dest > 0; dest--)\r
+               {\r
+                       //want to do this:\r
+                       //  bad:   src = rand() % (dest + 1)\r
+                       //  good:  src = rand() / (RAND_MAX / (dest+1) + 1)\r
+                       \r
+                       //positions from 0 to dest\r
+                       src = rand() / (RAND_MAX / (dest+1) + 1);\r
+                       \r
+                       //swap the cards\r
+                       temp           = cardlist[src];\r
+                       cardlist[src]  = cardlist[dest];\r
+                       cardlist[dest] = temp;\r
+               }\r
+}\r
+\r
+void CardStack::Reverse()\r
+{\r
+       for(int i = 0; i < nNumCards / 2; i++)\r
+       {\r
+               Card temp                   = cardlist[i];\r
+               cardlist[i]                 = cardlist[nNumCards - i - 1];\r
+               cardlist[nNumCards - i - 1] = temp;\r
+       }\r
+}\r
+\r
+void CardStack::Push(const Card card)\r
+{\r
+       if(nNumCards < MAX_CARDSTACK_SIZE)\r
+               cardlist[nNumCards++] = card;\r
+}\r
+\r
+void CardStack::Push(const CardStack &cardstack)\r
+{\r
+       if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE)\r
+       {\r
+               int num = cardstack.NumCards();\r
+               \r
+               for(int i = 0; i < num; i++)\r
+                       cardlist[nNumCards++] = cardstack.cardlist[i];\r
+       }\r
+}\r
+\r
+CardStack& CardStack::operator += (Card card)\r
+{\r
+       Push(card);\r
+       return *this;\r
+}\r
+\r
+CardStack& CardStack::operator += (CardStack &cs)\r
+{\r
+       Push(cs);\r
+       return *this;\r
+}\r
+\r
+CardStack CardStack::operator +  (Card card)\r
+{\r
+       CardStack poo = *this;\r
+       poo.Push(card);\r
+       return poo;\r
+}\r
+\r
+CardStack CardStack::operator + (CardStack &cs)\r
+{\r
+       CardStack poo = *this;\r
+       poo.Push(cs);\r
+       return poo;\r
+}\r
+\r
+\r
+Card CardStack::Pop()\r
+{\r
+       if(nNumCards > 0)\r
+               return cardlist[--nNumCards];\r
+       else\r
+               return 0;\r
+}\r
+\r
+CardStack CardStack::Pop(int items)\r
+{\r
+       if(items <= nNumCards && nNumCards > 0)\r
+       {\r
+               CardStack cs(*this, nNumCards - items);\r
+\r
+               nNumCards -= items;\r
+\r
+               return cs;\r
+       }\r
+       else\r
+       {\r
+               return CardStack();\r
+       }\r
+}\r
+\r
+Card CardStack::Top()\r
+{\r
+       if(nNumCards > 0)\r
+               return cardlist[nNumCards - 1];\r
+       else\r
+               return 0;\r
+}\r
+\r
+CardStack CardStack::Top(int items)\r
+{\r
+       if(items <= nNumCards && nNumCards > 0)\r
+       {\r
+               return CardStack (*this, nNumCards - items);\r
+       }\r
+       else\r
+       {\r
+               return CardStack();\r
+       }\r
+\r
+}\r
+\r
+Card CardStack::RemoveCard(size_t index)\r
+{\r
+       if(nNumCards == 0 || index >= (size_t)nNumCards)\r
+               return 0;\r
+\r
+       //put index into reverse range..\r
+       index = nNumCards - index - 1;\r
+\r
+       Card temp = cardlist[index];\r
+\r
+       nNumCards--;\r
+\r
+       for(size_t i = index; i < (size_t)nNumCards; i++)\r
+       {\r
+               cardlist[i] = cardlist[i+1];\r
+       }\r
+\r
+       return temp;\r
+}\r
+\r
+void CardStack::InsertCard(size_t index, Card card)\r
+{\r
+       if(nNumCards == MAX_CARDSTACK_SIZE)\r
+               return;\r
+\r
+       if(index > (size_t)nNumCards)\r
+               return;\r
+\r
+       if((size_t)nNumCards == index)\r
+       {\r
+               cardlist[nNumCards] = card;\r
+               nNumCards++;\r
+               return;\r
+       }\r
+\r
+       //put index into reverse range..\r
+       index = nNumCards - index - 1;\r
+\r
+       nNumCards++;\r
+\r
+       //make room for the card\r
+       for(size_t i = nNumCards; i > index; i--)\r
+       {\r
+               cardlist[i] = cardlist[i - 1];\r
+       }\r
+\r
+       cardlist[index] = card;\r
+}\r
+\r
+\r
+void CardStack::Print()\r
+{\r
+//     for(int i = 0; i < nNumCards; i++)\r
+//             cout << cardlist[i].HiVal() << " ";\r
+}\r
+\r
+CardStack::CardStack(CardStack &copythis, size_t fromindex)\r
+{\r
+       nNumCards = copythis.nNumCards - fromindex;\r
+\r
+       for(int i = 0; i < nNumCards; i++)\r
+               cardlist[i] = copythis.cardlist[fromindex + i];\r
+}\r
+\r
diff --git a/rosapps/games/solitaire/cardlib/cardstack.h b/rosapps/games/solitaire/cardlib/cardstack.h
new file mode 100644 (file)
index 0000000..eae8736
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef CARDSTACK_INCLUDED\r
+#define CARDSTACK_INCLUDED\r
+\r
+#include "card.h"\r
+\r
+#define MAX_CARDSTACK_SIZE 128\r
+\r
+class CardStack\r
+{\r
+       friend class CardRegion;\r
+\r
+public:\r
+       CardStack() : nNumCards(0) { }\r
+\r
+       void            NewDeck();\r
+       int                     NumCards() const { return nNumCards; }\r
+       void            Shuffle();\r
+       void            Clear();\r
+       void            Reverse();\r
+       \r
+       void            Push(const Card card);\r
+       void            Push(const CardStack &cardstack);\r
+\r
+       Card            Pop();\r
+       CardStack       Pop(int items);\r
+\r
+       Card            Top();\r
+       CardStack       Top(int items);\r
+\r
+       void Print();\r
+\r
+       Card            RemoveCard(size_t index);\r
+       void            InsertCard(size_t index, Card card);\r
+\r
+       //subscript capability!!\r
+             Card & operator[] (size_t index);\r
+       const Card & operator[] (size_t index) const;\r
+\r
+       CardStack &operator += (Card card);\r
+       CardStack &operator += (CardStack &cs);\r
+\r
+       CardStack operator +  (Card card);\r
+       CardStack operator +  (CardStack &cs);\r
+               \r
+private:       \r
+\r
+       CardStack(CardStack &copythis, size_t fromindex);\r
+\r
+       Card cardlist[MAX_CARDSTACK_SIZE];\r
+       int  nNumCards;\r
+};\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/cardwindow.cpp b/rosapps/games/solitaire/cardlib/cardwindow.cpp
new file mode 100644 (file)
index 0000000..748ac71
--- /dev/null
@@ -0,0 +1,812 @@
+//\r
+//     CardLib - CardWindow class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+#include <tchar.h>\r
+\r
+#include "globals.h"\r
+#include "cardlib.h"\r
+#include "cardbutton.h"\r
+#include "cardregion.h"\r
+#include "cardwindow.h"\r
+#include "cardcolor.h"\r
+\r
+extern HPALETTE __holdplacepal;\r
+\r
+HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette)\r
+{\r
+       HPALETTE hOld;\r
+\r
+       hOld = SelectPalette(hdc, hPalette, FALSE);\r
+       RealizePalette(hdc);\r
+\r
+       return hOld;\r
+}\r
+\r
+void RestorePalette(HDC hdc, HPALETTE hOldPal)\r
+{\r
+       SelectPalette(hdc, hOldPal, TRUE);\r
+}\r
+\r
+HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours);\r
+void    PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
+HBITMAP  CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height);\r
+void     GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2);\r
+\r
+void    LoadCardBitmaps();\r
+void    FreeCardBitmaps();\r
+\r
+static TCHAR szCardName[]   = _T("CardWnd32");\r
+static bool  fRegistered    = false;\r
+static LONG  uCardBitmapRef = 0;\r
+\r
+\r
+void RegisterCardWindow()\r
+{\r
+       WNDCLASSEX wc;\r
+\r
+       //Window class for the main application parent window\r
+       wc.cbSize                       = sizeof(wc);\r
+       wc.style                        = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;\r
+       wc.lpfnWndProc          = CardWindow::CardWndProc;\r
+       wc.cbClsExtra           = 0;\r
+       wc.cbWndExtra           = sizeof(CardWindow *);\r
+       wc.hInstance            = GetModuleHandle(0);\r
+       wc.hIcon                        = 0;\r
+       wc.hCursor                      = LoadCursor (NULL, IDC_ARROW);\r
+       wc.hbrBackground        = 0;\r
+       wc.lpszMenuName         = 0;\r
+       wc.lpszClassName        = szCardName;\r
+       wc.hIconSm                      = 0;\r
+\r
+       RegisterClassEx(&wc);\r
+}\r
+\r
+CardWindow::CardWindow() : m_hWnd(0)\r
+{\r
+       HDC hdc = GetDC(0);\r
+\r
+       nNumButtons       = 0;\r
+       nNumCardRegions   = 0;\r
+       nNumDropZones     = 0;\r
+       nBackCardIdx      = 53;\r
+\r
+       ResizeWndCallback = 0;\r
+       hbmBackImage      = 0;\r
+       hdcBackImage      = 0;\r
+\r
+       srand((unsigned)GetTickCount());\r
+\r
+       //All colours (buttons, highlights, decks)\r
+       //are calculated off this single base colour\r
+       crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100);\r
+\r
+       // If uCardBitmapRef was previously zero, then\r
+       // load the card bitmaps\r
+       if(1 == InterlockedIncrement(&uCardBitmapRef))\r
+       {\r
+               LoadCardBitmaps();\r
+\r
+               __hPalette  = CreateCardPalette();\r
+\r
+               __hdcPlaceHolder  = CreateCompatibleDC(hdc);\r
+       \r
+               __holdplacepal  = UseNicePalette(__hdcPlaceHolder, __hPalette);\r
+\r
+               __hbmPlaceHolder  = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);\r
+\r
+       }\r
+\r
+       ReleaseDC(0, hdc);\r
+\r
+       //register the window class if necessary\r
+       if(!fRegistered)\r
+       {\r
+               fRegistered = true;\r
+               RegisterCardWindow();\r
+       }\r
+\r
+}\r
+\r
+BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height)\r
+{\r
+       if(m_hWnd)\r
+               return FALSE;\r
+\r
+       //Create the window associated with this object\r
+       m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0, \r
+               WS_CHILD | WS_VISIBLE,\r
+               0,0,100,100, \r
+               hwndParent, 0, GetModuleHandle(0), this);\r
+\r
+       return TRUE;\r
+}\r
+\r
+BOOL CardWindow::Destroy()\r
+{\r
+       DestroyWindow(m_hWnd);\r
+       m_hWnd = 0;\r
+\r
+       return TRUE;\r
+}\r
+\r
+CardWindow::~CardWindow()\r
+{\r
+       if(m_hWnd)\r
+               DestroyWindow(m_hWnd);\r
+\r
+       DeleteAll();\r
+\r
+       if(0 == InterlockedDecrement(&uCardBitmapRef))\r
+       {\r
+               FreeCardBitmaps();\r
+\r
+               DeleteObject(__hbmPlaceHolder);\r
+               DeleteDC    (__hdcPlaceHolder);\r
+\r
+               RestorePalette(__hdcPlaceHolder, __holdplacepal);\r
+\r
+               if(__hPalette)\r
+                       DeleteObject(__hPalette);\r
+       }\r
+}\r
+\r
+bool CardWindow::DeleteAll()\r
+{\r
+       int i;\r
+\r
+       for(i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               delete Regions[i];\r
+       }\r
+\r
+       for(i = 0; i < nNumButtons; i++)\r
+       {\r
+               delete Buttons[i];\r
+       }\r
+\r
+       for(i = 0; i < nNumDropZones; i++)\r
+       {\r
+               delete dropzone[i];\r
+       }\r
+\r
+       nNumCardRegions = nNumButtons = nNumDropZones = 0;\r
+\r
+       return true;\r
+}\r
+\r
+void CardWindow::SetBackColor(COLORREF cr)\r
+{\r
+       crBackgnd = cr;\r
+       int i;\r
+       \r
+       //\r
+       // Create the exact palette we need to render the buttons/stacks\r
+       //\r
+       RestorePalette(__hdcPlaceHolder, __holdplacepal);\r
+\r
+       if(__hPalette)\r
+               DeleteObject(__hPalette);\r
+\r
+       __hPalette = CreateCardPalette();\r
+\r
+       //\r
+       // re-create the place-holder!\r
+       HDC hdc = GetDC(m_hWnd);\r
+\r
+       DeleteObject(__hbmPlaceHolder);\r
+\r
+       __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);\r
+\r
+       __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);\r
+       //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);\r
+\r
+       //reset all buttons to same colour\r
+       for(i = 0; i < nNumButtons; i++)\r
+       {\r
+               if(Buttons[i]->GetStyle() & CB_PUSHBUTTON)\r
+               {\r
+                       Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1));\r
+               }\r
+               else\r
+               {\r
+                       Buttons[i]->SetBackColor(crBackgnd);\r
+               }\r
+       }\r
+\r
+       for(i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               Regions[i]->SetBackColor(crBackgnd);\r
+       }\r
+\r
+\r
+       ReleaseDC(m_hWnd, hdc);\r
+}\r
+\r
+COLORREF CardWindow::GetBackColor()\r
+{\r
+       return crBackgnd;\r
+}\r
+\r
+CardButton* CardWindow::CardButtonFromPoint(int x, int y)\r
+{\r
+       CardButton *bptr = 0;\r
+\r
+       POINT pt;\r
+       pt.x = x;\r
+       pt.y = y;\r
+\r
+       //Search BACKWARDS...to reflect the implicit Z-order that\r
+       //the button creation provided\r
+       for(int i = nNumButtons - 1; i >= 0; i--)\r
+       {\r
+               bptr = Buttons[i];\r
+               if(PtInRect(&bptr->rect, pt) && bptr->fVisible)\r
+                       return bptr;\r
+       }\r
+\r
+       return 0;       \r
+}\r
+\r
+CardRegion* CardWindow::CardRegionFromPoint(int x, int y)\r
+{\r
+       POINT pt;\r
+       pt.x = x;\r
+       pt.y = y;\r
+\r
+       //Search BACKWARDS...to reflect the implicit Z-order that\r
+       //the stack creation provided\r
+       for(int i = nNumCardRegions - 1; i >= 0; i--)\r
+       {\r
+               if(Regions[i]->IsPointInStack(x, y))\r
+                       return Regions[i];\r
+       }\r
+\r
+       return 0;       \r
+}\r
+\r
+//\r
+//     Forward all window messages onto the appropriate\r
+//  class instance\r
+//\r
+LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
+{\r
+       CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0);\r
+       return cw->WndProc(hwnd, iMsg, wParam, lParam);\r
+}\r
+\r
+void CardWindow::Paint(HDC hdc)\r
+{\r
+       int i;\r
+       RECT rect;\r
+       int xpos = 10;\r
+       HPALETTE hOldPal;\r
+\r
+       hOldPal = UseNicePalette(hdc, __hPalette);\r
+\r
+       //\r
+       //      Clip the card stacks so that they won't\r
+       //      get painted over\r
+       //\r
+       for(i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               Regions[i]->Clip(hdc);\r
+       }\r
+\r
+       //\r
+       //      Clip the buttons \r
+       //\r
+       for(i = 0; i < nNumButtons; i++)\r
+       {\r
+               Buttons[i]->Clip(hdc);\r
+       }\r
+\r
+\r
+       //      Now paint the whole screen with background colour, \r
+       //\r
+       GetClientRect(m_hWnd, &rect);\r
+       \r
+       //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));\r
+       PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0);\r
+       SelectClipRgn(hdc, NULL);\r
+\r
+       //      Don't let cards draw over buttons, so clip buttons again\r
+       //\r
+       for(i = 0; i < nNumButtons; i++)\r
+       {\r
+               Buttons[i]->Clip(hdc);\r
+       }\r
+\r
+       //      Paint each card stack in turn\r
+       //\r
+       for(i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               Regions[i]->Render(hdc);\r
+       }\r
+               \r
+       //      Paint each button now\r
+       //\r
+       SelectClipRgn(hdc, NULL);\r
+\r
+       for(i = 0; i < nNumButtons; i++)\r
+       {\r
+               Buttons[i]->Redraw();\r
+       }\r
+\r
+       RestorePalette(hdc, hOldPal);\r
+}\r
+\r
+\r
+\r
+\r
+LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
+{\r
+       HDC hdc;\r
+       PAINTSTRUCT ps;\r
+\r
+       CREATESTRUCT *cs;\r
+\r
+       static CardButton *buttonptr   = 0;\r
+       static CardRegion *stackptr    = 0;\r
+\r
+       int x, y, i;\r
+\r
+       switch(iMsg)\r
+       {\r
+       case WM_NCCREATE:\r
+\r
+               // When we created this window, we passed in the\r
+               // pointer to the class object (CardWindow *) in the\r
+               // call to CreateWindow.\r
+               cs = (CREATESTRUCT *)lParam;\r
+\r
+               //\r
+               // associate this class with the window\r
+               //\r
+               SetWindowLong(hwnd, 0, (LONG)cs->lpCreateParams);\r
+\r
+               return 1;\r
+\r
+       case WM_NCDESTROY:\r
+               // Don't delete anything here..\r
+               break;\r
+\r
+       case WM_SIZE:\r
+               nWidth = LOWORD(lParam);\r
+               nHeight = HIWORD(lParam);\r
+               \r
+               //\r
+               // reposition all the stacks and buttons\r
+               // in case any of them are centered, right-justified etc\r
+               //\r
+               for(i = 0; i < nNumCardRegions; i++)\r
+               {\r
+                       Regions[i]->AdjustPosition(nWidth, nHeight);\r
+               }\r
+       \r
+               for(i = 0; i < nNumButtons; i++)\r
+               {\r
+                       Buttons[i]->AdjustPosition(nWidth, nHeight);\r
+               }\r
+\r
+               // \r
+               // Call the user-defined resize proc AFTER all the stacks\r
+               // have been positioned\r
+               //\r
+               if(ResizeWndCallback) \r
+                       ResizeWndCallback(nWidth, nHeight);\r
+\r
+               return 0;\r
+\r
+       case WM_PAINT:\r
+\r
+               hdc = BeginPaint(hwnd, &ps);\r
+\r
+               Paint(hdc);\r
+\r
+               EndPaint(hwnd, &ps);\r
+               return 0;\r
+\r
+       case WM_TIMER:\r
+               \r
+               //find the timer object in the registered funcs\r
+               /*if(wParam >= 0x10000)\r
+               {\r
+                       for(i = 0; i < nRegFuncs; i++)\r
+                       {\r
+                               if(RegFuncs[i].id == wParam)\r
+                               {\r
+                                       KillTimer(hwnd, wParam);\r
+       \r
+                                       //call the registered function!!\r
+                                       RegFuncs[i].func(RegFuncs[i].dwParam);\r
+       \r
+                                       RegFuncs[i] = RegFuncs[nRegFuncs-1];\r
+                                       nRegFuncs--;\r
+                               }\r
+                       }\r
+               }\r
+               else*/\r
+               {\r
+                       //find the cardstack\r
+                       CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam);\r
+                       stackobj->DoFlash();\r
+               }\r
+\r
+               return 0;\r
+\r
+       case WM_LBUTTONDBLCLK:\r
+\r
+               x = (short)LOWORD(lParam);\r
+               y = (short)HIWORD(lParam);\r
+\r
+               if((buttonptr = CardButtonFromPoint(x, y)) != 0)\r
+               {\r
+                       buttonptr->OnLButtonDown(hwnd, x, y);\r
+                       return 0;\r
+               }\r
+\r
+               if((stackptr = CardRegionFromPoint(x, y)) != 0)\r
+               {\r
+                       stackptr->OnLButtonDblClk(x, y);\r
+                       stackptr = 0;\r
+               }\r
+\r
+               return 0;\r
+\r
+       case WM_LBUTTONDOWN:\r
+\r
+               x = (short)LOWORD(lParam);\r
+               y = (short)HIWORD(lParam);\r
+\r
+               //if clicked on a button\r
+               if((buttonptr = CardButtonFromPoint(x, y)) != 0)\r
+               {\r
+                       if(buttonptr->OnLButtonDown(hwnd, x, y) == 0)\r
+                               buttonptr = 0;\r
+\r
+                       return 0;\r
+               }\r
+\r
+               if((stackptr = CardRegionFromPoint(x, y)) != 0)\r
+               {\r
+                       if(!stackptr->OnLButtonDown(x, y))\r
+                               stackptr = 0;\r
+               }\r
+               \r
+               return 0;\r
+\r
+       case WM_LBUTTONUP:\r
+               \r
+               x = (short)LOWORD(lParam);\r
+               y = (short)HIWORD(lParam);\r
+\r
+               //\r
+               // if we were clicking a button\r
+               //\r
+               if(buttonptr != 0)\r
+               {\r
+                       buttonptr->OnLButtonUp(hwnd, x, y);\r
+                       buttonptr = 0;\r
+                       return 0;\r
+               }\r
+               \r
+               if(stackptr != 0)\r
+               {\r
+                       stackptr->OnLButtonUp(x, y);\r
+                       stackptr = 0;\r
+                       return 0;\r
+               }\r
+\r
+               return 0;\r
+\r
+       case WM_MOUSEMOVE:\r
+               \r
+               x = (short)LOWORD(lParam);\r
+               y = (short)HIWORD(lParam);\r
+\r
+               // if we were clicking a button\r
+               if(buttonptr != 0)\r
+               {\r
+                       buttonptr->OnMouseMove(hwnd, x, y);\r
+                       return 0;\r
+               }\r
+\r
+               if(stackptr != 0)\r
+               {\r
+                       return stackptr->OnMouseMove(x, y);\r
+               }\r
+               \r
+               return 0;\r
+\r
+       }\r
+\r
+       return DefWindowProc (hwnd, iMsg, wParam, lParam);\r
+}\r
+\r
+\r
+CardRegion* CardWindow::CardRegionFromId(int id)\r
+{\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               if(Regions[i]->id == id)\r
+                       return Regions[i];\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+CardButton* CardWindow::CardButtonFromId(int id)\r
+{\r
+       for(int i = 0; i < nNumButtons; i++)\r
+       {\r
+               if(Buttons[i]->id == id)\r
+                       return Buttons[i];\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+void CardWindow::Redraw()\r
+{\r
+       InvalidateRect(m_hWnd, 0, 0);\r
+       UpdateWindow(m_hWnd);\r
+}\r
+\r
+bool CardWindow::DeleteButton(CardButton *pButton)\r
+{\r
+       for(int i = 0; i < nNumButtons; i++)\r
+       {\r
+               if(Buttons[i] == pButton)\r
+               {\r
+                       CardButton *cb = Buttons[i];\r
+                       \r
+                       //shift any after this one backwards\r
+                       for(int j = i; j < nNumButtons - 1; j++)\r
+                       {\r
+                               Buttons[j] = Buttons[j + 1];\r
+                       }\r
+\r
+                       delete cb;\r
+                       nNumButtons--;\r
+                       \r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CardWindow::DeleteRegion(CardRegion *pRegion)\r
+{\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               if(Regions[i] == pRegion)\r
+               {\r
+                       CardRegion *cr = Regions[i];\r
+                       \r
+                       //shift any after this one backwards\r
+                       for(int j = i; j < nNumCardRegions - 1; j++)\r
+                       {\r
+                               Regions[j] = Regions[j + 1];\r
+                       }\r
+\r
+                       delete cr;\r
+                       nNumCardRegions--;\r
+\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CardWindow::EmptyStacks(void)\r
+{\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               Regions[i]->Clear();\r
+               Regions[i]->Update();\r
+       }\r
+\r
+       Redraw();\r
+}\r
+\r
+bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX)\r
+{\r
+       int numvisiblestacks = 0;\r
+       int curx = nStartX;\r
+       int startindex = -1;\r
+       int i;\r
+\r
+       //find the stack which starts with our ID\r
+       for(i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               if(Regions[i]->Id() == nIdFrom)\r
+               {\r
+                       startindex = i;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       //if didn't find, return\r
+       if(i == nNumCardRegions) return false;\r
+\r
+       //count the stacks that are visible\r
+       for(i = startindex; i < startindex + nNumStacks; i++)\r
+       {\r
+               if(Regions[i]->IsVisible())\r
+                       numvisiblestacks++;\r
+       }\r
+       \r
+       if(xJustify == CS_XJUST_CENTER)\r
+       {\r
+               //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;\r
+               int viswidth;\r
+               viswidth = numvisiblestacks * __cardwidth;\r
+               viswidth += xSpacing * (numvisiblestacks - 1);\r
+               curx = -(viswidth  - __cardwidth) / 2;\r
+\r
+               for(i = startindex; i < startindex + nNumStacks; i++)\r
+               {\r
+                       if(Regions[i]->IsVisible())\r
+                       {\r
+                               Regions[i]->xadjust = curx;\r
+                               Regions[i]->xjustify = CS_XJUST_CENTER;\r
+                               curx += Regions[i]->width + xSpacing;\r
+                       }\r
+                       \r
+               }\r
+       }\r
+\r
+       if(xJustify == CS_XJUST_RIGHT)\r
+       {\r
+               nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing);\r
+       }\r
+       \r
+       if(xJustify == CS_XJUST_NONE)\r
+       {\r
+               for(i = startindex; i < startindex + nNumStacks; i++)\r
+               {\r
+                       if(Regions[i]->IsVisible())\r
+                       {\r
+                               Regions[i]->xpos = curx;\r
+                               curx += Regions[i]->width + xSpacing;\r
+                               Regions[i]->UpdateSize();\r
+                       }\r
+                       \r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+void CardWindow::Update()\r
+{\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+       {\r
+               Regions[i]->AdjustPosition(nWidth, nHeight);\r
+       }\r
+}\r
+\r
+\r
+void CardWindow::SetResizeProc(pResizeWndProc proc)\r
+{\r
+       ResizeWndCallback = proc;\r
+}\r
+\r
+\r
+HPALETTE CardWindow::CreateCardPalette()\r
+{\r
+       COLORREF cols[10];\r
+       int nNumCols;\r
+\r
+\r
+       //include button text colours\r
+       cols[0] = RGB(0, 0, 0);\r
+       cols[1] = RGB(255, 255, 255);\r
+\r
+       //include the base background colour\r
+       cols[1] = crBackgnd;\r
+\r
+       //include the standard button colours...\r
+       cols[3] = CardButton::GetHighlight(crBackgnd);\r
+       cols[4] = CardButton::GetShadow(crBackgnd);\r
+       cols[5] = CardButton::GetFace(crBackgnd);\r
+\r
+       //include the sunken image bitmap colours...\r
+       GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]);\r
+\r
+       nNumCols = 10;\r
+\r
+       return MakePaletteFromCols(cols, nNumCols);\r
+}\r
+\r
+void CardWindow::SetBackCardIdx(UINT uBackIdx)\r
+{\r
+       if(uBackIdx >= 52 && uBackIdx <= 68)\r
+               nBackCardIdx = uBackIdx;\r
+\r
+       for(int i = 0; i < nNumCardRegions; i++)\r
+               Regions[i]->SetBackCardIdx(uBackIdx);\r
+\r
+}\r
+\r
+void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy)\r
+{\r
+       RECT rect;\r
+\r
+       //if just a solid background colour\r
+       if(hbmBackImage == 0)\r
+       {\r
+               SetRect(&rect, dx, dy, dx+width, dy+height);\r
+               \r
+               /*if(GetVersion() < 0x80000000)\r
+               {\r
+                       PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));\r
+               }\r
+               else*/\r
+               {\r
+                       HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd));\r
+                       FillRect(hdc, &rect, hbr);\r
+                       DeleteObject(hbr);\r
+               }\r
+       }\r
+       //otherwise, paint using the bitmap\r
+       else\r
+       {\r
+               // Draw whatever part of background we can \r
+               BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY);\r
+\r
+               // Now we need to paint any area outside the bitmap,\r
+               // just in case the bitmap is too small to fill whole window\r
+               if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight)\r
+               {\r
+                       // Find out size of bitmap\r
+                       BITMAP bm;\r
+                       GetObject(hbmBackImage, sizeof(bm), &bm);\r
+\r
+                       HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height);\r
+                       HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);\r
+                       HRGN hr3 = CreateRectRgn(0,0, 1, 1);\r
+                       HRGN hr4 = CreateRectRgn(0,0, 1, 1);\r
+               \r
+                       CombineRgn(hr3, hr1, hr2, RGN_DIFF);\r
+               \r
+                       GetClipRgn(hdc, hr4);\r
+                       \r
+                       CombineRgn(hr3, hr4, hr3, RGN_AND);\r
+                       SelectClipRgn(hdc, hr3);\r
+               \r
+                       // Fill remaining space not filled with bitmap\r
+                       HBRUSH hbr = CreateSolidBrush(crBackgnd);\r
+                       FillRgn(hdc, hr3, hbr);\r
+                       DeleteObject(hbr);\r
+\r
+                       // Clean up\r
+                       SelectClipRgn(hdc, hr4);\r
+               \r
+                       DeleteObject(hr1);\r
+                       DeleteObject(hr2);\r
+                       DeleteObject(hr3);\r
+                       DeleteObject(hr4);\r
+               }\r
+       }\r
+}\r
+\r
+void CardWindow::SetBackImage(HBITMAP hBitmap)\r
+{\r
+       //delete current image?? NO!\r
+       if(hdcBackImage == 0)\r
+       {\r
+               hdcBackImage = CreateCompatibleDC(0);\r
+       }\r
+\r
+       hbmBackImage = hBitmap;\r
+\r
+       if(hBitmap)\r
+               SelectObject(hdcBackImage, hBitmap);\r
+}\r
diff --git a/rosapps/games/solitaire/cardlib/cardwindow.h b/rosapps/games/solitaire/cardlib/cardwindow.h
new file mode 100644 (file)
index 0000000..bcc2409
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef CARDBOARD_INCLUDED\r
+#define CARDBOARD_INCLUDED\r
+\r
+#define MAXBUTTONS             32\r
+#define MAXCARDSTACKS  32\r
+#define MAXDROPZONES   8\r
+\r
+#include "dropzone.h"\r
+#include "cardlib.h"\r
+\r
+class CardRegion;\r
+class CardButton;\r
+\r
+LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);\r
+\r
+class CardWindow\r
+{\r
+       friend class CardRegion;\r
+       friend class CardButton;\r
+       \r
+       friend void RegisterCardWindow();\r
+\r
+public:\r
+\r
+       CardWindow();\r
+       ~CardWindow();\r
+\r
+       //\r
+       //      Basic windowing support\r
+       //\r
+       BOOL Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height);\r
+       BOOL Destroy();\r
+\r
+       operator HWND() { return m_hWnd; }\r
+\r
+       CardButton *CreateButton (int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height);\r
+       CardRegion *CreateRegion (int id, bool fVisible, int x, int y, int xoffset, int yoffset);\r
+\r
+       CardButton *CardButtonFromId(int id);\r
+       CardRegion *CardRegionFromId(int id);\r
+\r
+       bool DeleteButton(CardButton *pButton);\r
+       bool DeleteRegion(CardRegion *pRegion);\r
+       bool DeleteAll();\r
+\r
+       void     SetBackColor(COLORREF cr);\r
+       COLORREF GetBackColor();\r
+       void     SetBackCardIdx(UINT uBackIdx);\r
+       void     SetBackImage(HBITMAP hBitmap);\r
+\r
+       void EmptyStacks(void);\r
+       void Redraw(void);\r
+       void Update(void);\r
+\r
+       bool DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX);\r
+       void SetResizeProc(pResizeWndProc proc);\r
+       int  GetWidth() { return nWidth; }\r
+       int  GetHeight() { return nHeight; }\r
+       \r
+       //\r
+       //      Dropzone support\r
+       //\r
+       bool      RegisterDropZone(int id, RECT *rect, pDropZoneProc proc);\r
+       bool      DeleteDropZone(int id);\r
+\r
+private:\r
+\r
+       int               GetNumDropZones() { return nNumDropZones; }\r
+       DropZone* GetDropZoneFromRect(RECT *rect);\r
+\r
+       //\r
+       //      Window procedure - don't call\r
+       //\r
+          LRESULT CALLBACK WndProc    (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);\r
+static LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);\r
+\r
+       //\r
+       //      Private functions\r
+       //\r
+       void Paint(HDC hdc);\r
+       void PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy);\r
+\r
+       HPALETTE CreateCardPalette();\r
+\r
+       CardButton *CardButtonFromPoint(int x, int y);\r
+       CardRegion *CardRegionFromPoint(int x, int y);\r
+       CardRegion *GetBestStack(int x, int y, int w, int h);\r
+\r
+       //\r
+       //      Private members\r
+       //\r
+\r
+       HWND m_hWnd;                    //window handle!\r
+       int  nWidth, nHeight;\r
+       \r
+       UINT    nBackCardIdx;   //all stacks share this card index by default\r
+\r
+       HBITMAP hbmBackImage;\r
+       HDC             hdcBackImage;\r
+\r
+\r
+       CardButton  * Buttons[MAXBUTTONS];\r
+       int                       nNumButtons;\r
+\r
+       CardRegion  * Regions[MAXCARDSTACKS];\r
+       int                       nNumCardRegions;\r
+\r
+       DropZone        * dropzone[MAXDROPZONES];\r
+       int                       nNumDropZones;\r
+\r
+       COLORREF  crBackgnd;\r
+\r
+       pResizeWndProc  ResizeWndCallback;\r
+\r
+\r
+};\r
+\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/dropzone.cpp b/rosapps/games/solitaire/cardlib/dropzone.cpp
new file mode 100644 (file)
index 0000000..dfa6dcc
--- /dev/null
@@ -0,0 +1,69 @@
+//\r
+//     CardLib - DropZone class\r
+//\r
+//     Freeware\r
+//     Copyright J Brown 2001\r
+//\r
+#include <windows.h>\r
+\r
+#include "cardlib.h"\r
+#include "cardwindow.h"\r
+#include "dropzone.h"\r
+\r
+bool CardWindow::RegisterDropZone(int id, RECT *rect, pDropZoneProc proc)\r
+{\r
+       if(nNumDropZones == MAXDROPZONES)\r
+               return false;\r
+\r
+       DropZone *dz = new DropZone(id, rect, proc);\r
+       \r
+       dropzone[nNumDropZones++] = dz;\r
+\r
+       return false;\r
+}\r
+\r
+DropZone *CardWindow::GetDropZoneFromRect(RECT *rect)\r
+{\r
+       for(int i = 0; i < nNumDropZones; i++)\r
+       {\r
+               RECT inter;\r
+               RECT zone;\r
+                               \r
+               //if any part of the drag rectangle falls within a drop zone,\r
+               //let that take priority over any other card stack.\r
+               dropzone[i]->GetZone(&zone);\r
+\r
+               if(IntersectRect(&inter, rect, &zone))\r
+               {\r
+                       //see if the callback wants us to drop a card on\r
+                       //a particular stack\r
+                       return dropzone[i];\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+bool CardWindow::DeleteDropZone(int id)\r
+{\r
+       for(int i = 0; i < nNumDropZones; i++)\r
+       {\r
+               if(dropzone[i]->id == id)\r
+               {\r
+                       DropZone *dz = dropzone[i];\r
+                       \r
+                       //shift any after this one backwards\r
+                       for(int j = i; j < nNumDropZones - 1; j++)\r
+                       {\r
+                               dropzone[j] = dropzone[j + 1];\r
+                       }\r
+\r
+                       delete dz;\r
+                       nNumDropZones--;\r
+                       return true;\r
+               }       \r
+       }\r
+\r
+       return false;\r
+}\r
+\r
diff --git a/rosapps/games/solitaire/cardlib/dropzone.h b/rosapps/games/solitaire/cardlib/dropzone.h
new file mode 100644 (file)
index 0000000..2f5d080
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef DROPZONE_INCLUDED\r
+#define DROPZONE_INCLUDED\r
+\r
+//\r
+//     define a drop-zone, which can be used to over-ride\r
+//     drop-behaviour for any card stacks which fall under it\r
+//\r
+\r
+class CardStack;\r
+\r
+class DropZone\r
+{\r
+       friend class CardWindow;\r
+\r
+       DropZone(int Id, RECT *rect, pDropZoneProc proc) : \r
+         id(Id), DropZoneCallback(proc) { CopyRect(&zone, rect); }\r
+\r
+public:\r
+\r
+       void SetZone(RECT *rect) { CopyRect(&zone, rect); }\r
+       void GetZone(RECT *rect) { CopyRect(rect, &zone); }\r
+       void SetCallback(pDropZoneProc callback) { DropZoneCallback = callback; }\r
+\r
+       int  DropCards(CardStack &cardstack) \r
+       {\r
+               if(DropZoneCallback)\r
+                       return DropZoneCallback(id, cardstack);\r
+               else\r
+                       return -1;\r
+       }\r
+\r
+private:\r
+\r
+       int  id;\r
+       RECT zone;\r
+       pDropZoneProc DropZoneCallback;\r
+};\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/cardlib/globals.h b/rosapps/games/solitaire/cardlib/globals.h
new file mode 100644 (file)
index 0000000..e4cdb48
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef GLOBALS_INCLUDED\r
+#define GLOBALS_INCLUDED\r
+\r
+extern int __cardwidth;\r
+extern int __cardheight;\r
+\r
+extern HDC     __hdcCardBitmaps;\r
+extern HBITMAP __hbmCardBitmaps;\r
+\r
+extern HDC             __hdcPlaceHolder;\r
+extern HBITMAP  __hbmPlaceHolder;\r
+\r
+extern HPALETTE __hPalette;\r
+\r
+#endif\r
diff --git a/rosapps/games/solitaire/icon1.ico b/rosapps/games/solitaire/icon1.ico
new file mode 100644 (file)
index 0000000..92bcf50
Binary files /dev/null and b/rosapps/games/solitaire/icon1.ico differ
diff --git a/rosapps/games/solitaire/makefile b/rosapps/games/solitaire/makefile
new file mode 100644 (file)
index 0000000..449a771
--- /dev/null
@@ -0,0 +1,42 @@
+\r
+PATH_TO_TOP = ../../../reactos\r
+\r
+TARGET_TYPE = program\r
+\r
+TARGET_APPTYPE = windows\r
+\r
+TARGET_INSTALLDIR = system32\r
+\r
+TARGET_NAME = sol\r
+\r
+TARGET_SDKLIBS = kernel32.a user32.a gdi32.a cards.a comctl32.a\r
+\r
+TARGET_GCCLIBS = stdc++\r
+\r
+TARGET_OBJECTS = $(SOL_OBJECTS) $(CARDLIB_OBJECTS)\r
+\r
+SOL_OBJECTS = \\r
+       solcreate.o \\r
+       solgame.o \\r
+       solitaire.o\r
+\r
+CARDLIB_OBJECTS = \\r
+       cardlib/cardbitmaps.o \\r
+       cardlib/cardbutton.o \\r
+       cardlib/cardcolor.o \\r
+       cardlib/cardcount.o \\r
+       cardlib/cardlib.o \\r
+       cardlib/cardregion.o \\r
+       cardlib/cardrgndraw.o \\r
+       cardlib/cardrgnmouse.o \\r
+       cardlib/cardstack.o \\r
+       cardlib/cardwindow.o \\r
+       cardlib/dropzone.o\r
+\r
+TARGET_CPPFLAGS = -Icardlib -Wall -D__USE_W32API -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -D__REACTOS__\r
+\r
+include $(PATH_TO_TOP)/rules.mak\r
+\r
+include $(TOOLS_PATH)/helper.mk\r
+\r
+# EOF\r
diff --git a/rosapps/games/solitaire/resource.h b/rosapps/games/solitaire/resource.h
new file mode 100644 (file)
index 0000000..25abe7e
--- /dev/null
@@ -0,0 +1,25 @@
+//{{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
diff --git a/rosapps/games/solitaire/sol.rc b/rosapps/games/solitaire/sol.rc
new file mode 100644 (file)
index 0000000..cfc0760
--- /dev/null
@@ -0,0 +1,144 @@
+//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
+
diff --git a/rosapps/games/solitaire/solcreate.cpp b/rosapps/games/solitaire/solcreate.cpp
new file mode 100644 (file)
index 0000000..9f2facb
--- /dev/null
@@ -0,0 +1,87 @@
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <tchar.h>\r
+#include "resource.h"\r
+#include "cardlib/cardlib.h"\r
+\r
+#include "solitaire.h"\r
+\r
+const int yBorder = 20;\r
+const int xBorder = 20;\r
+const int yRowStacks = yBorder + 128;\r
+\r
+CardRegion *pDeck;\r
+CardRegion *pPile;\r
+CardRegion *pSuitStack[4];\r
+CardRegion *pRowStack[NUM_ROW_STACKS];\r
+\r
+extern CardStack activepile;\r
+\r
+HBITMAP hbmBitmap;\r
+HDC            hdcBitmap;\r
+\r
+void CreateSol()\r
+{\r
+       int i;\r
+\r
+//     hbmBitmap = (HBITMAP)LoadImage(0,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);\r
+//     SolWnd.SetBackImage(hbmBitmap);\r
+\r
+       activepile.Clear();\r
+\r
+\r
+       pDeck = SolWnd.CreateRegion(DECK_ID, true, xBorder, yBorder, 2, 1);\r
+       pDeck->SetEmptyImage(CS_EI_SUNK);\r
+       pDeck->SetThreedCount(6);\r
+       pDeck->SetDragRule(CS_DRAG_NONE, 0);\r
+       pDeck->SetDropRule(CS_DROP_NONE, 0);\r
+       pDeck->SetClickProc(DeckClickProc);\r
+       pDeck->SetDblClickProc(DeckClickProc);\r
+       pDeck->SetFaceDirection(CS_FACE_DOWN, 0);\r
+\r
+       pPile = SolWnd.CreateRegion(PILE_ID, true, 110, yBorder, CS_DEFXOFF, 1);\r
+       pPile->SetEmptyImage(CS_EI_NONE);\r
+       pPile->SetDragRule(CS_DRAG_TOP, 0);\r
+       pPile->SetDropRule(CS_DROP_NONE, 0);\r
+       pPile->SetDblClickProc(PileDblClickProc);\r
+       pPile->SetRemoveCardProc(PileRemoveProc);\r
+\r
+       //\r
+       //      Create the suit stacks\r
+       //\r
+       for(i = 0; i < 4; i++)\r
+       {\r
+               pSuitStack[i] = SolWnd.CreateRegion(SUIT_ID+i, true, 0, yBorder, 0, 0);\r
+               pSuitStack[i]->SetEmptyImage(CS_EI_SUNK);\r
+               //pSuitStack[i]->SetPlacement(CS_XJUST_RIGHT, 0, -i * (__cardwidth + 4) - xBorder, 0);\r
+               pSuitStack[i]->SetPlacement(CS_XJUST_CENTER, 0, i * (__cardwidth + 10) , 0);\r
+\r
+               pSuitStack[i]->SetDropRule(CS_DROP_CALLBACK, SuitStackDropProc);\r
+               pSuitStack[i]->SetDragRule(CS_DRAG_TOP);\r
+\r
+               pSuitStack[i]->SetAddCardProc(SuitStackAddProc);\r
+       }\r
+\r
+       //\r
+       //      Create the row stacks\r
+       //\r
+       for(i = 0; i < NUM_ROW_STACKS; i++)\r
+       {\r
+               pRowStack[i] = SolWnd.CreateRegion(ROW_ID+i, true, 0, yRowStacks, 0, 14);\r
+               pRowStack[i]->SetEmptyImage(CS_EI_SUNK);\r
+               pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);\r
+               \r
+               pRowStack[i]->SetPlacement(CS_XJUST_CENTER, 0, \r
+                       (i - NUM_ROW_STACKS/2) * (__cardwidth + 10),    0);\r
+\r
+               pRowStack[i]->SetEmptyImage(CS_EI_NONE);\r
+\r
+               pRowStack[i]->SetDragRule(CS_DRAG_CALLBACK, RowStackDragProc);\r
+               pRowStack[i]->SetDropRule(CS_DROP_CALLBACK, RowStackDropProc);\r
+               pRowStack[i]->SetClickProc(RowStackClickProc);\r
+               pRowStack[i]->SetDblClickProc(RowStackDblClickProc);\r
+       }\r
+\r
+\r
+\r
+}\r
diff --git a/rosapps/games/solitaire/solgame.cpp b/rosapps/games/solitaire/solgame.cpp
new file mode 100644 (file)
index 0000000..b2ae928
--- /dev/null
@@ -0,0 +1,308 @@
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <tchar.h>\r
+#include "resource.h"\r
+#include "cardlib/cardlib.h"\r
+//#include "../catch22lib/trace.h"\r
+#include "solitaire.h"\r
+\r
+CardStack activepile;\r
+bool fGameStarted = false;\r
+\r
+void NewGame(void)\r
+{\r
+       int i, j;\r
+\r
+       SolWnd.EmptyStacks();\r
+       \r
+       //create a new card-stack\r
+       CardStack deck;\r
+       deck.NewDeck();\r
+       deck.Shuffle();\r
+       activepile.Clear();\r
+\r
+       //deal to each row stack..\r
+       for(i = 0; i < NUM_ROW_STACKS; i++)\r
+       {\r
+               CardStack temp;\r
+               temp.Clear();\r
+\r
+               pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);\r
+\r
+               for(j = 0; j <= i; j++)\r
+               {\r
+                       temp.Push(deck.Pop());\r
+               }\r
+\r
+               pRowStack[i]->SetCardStack(temp);\r
+       }\r
+\r
+       //put the other cards onto the deck\r
+       pDeck->SetCardStack(deck);\r
+       pDeck->Update();\r
+       \r
+       SolWnd.Redraw();\r
+\r
+       fGameStarted = false;\r
+}\r
+\r
+//\r
+//     Now follow the stack callback functions. This is where we\r
+//  provide the game functionality and rules\r
+//\r
+\r
+//\r
+//     Can only drag face-up cards\r
+//\r
+bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)\r
+{\r
+       int numfacedown;\r
+       int numcards;\r
+\r
+       stackobj.GetFaceDirection(&numfacedown);\r
+\r
+       numcards = stackobj.NumCards();\r
+\r
+       if(iNumDragCards <= numcards-numfacedown)\r
+               return true;\r
+       else\r
+               return false;\r
+\r
+}\r
+\r
+//\r
+//     Row a row-stack, we can only drop cards \r
+//     that are lower / different colour\r
+//\r
+bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj,  const CardStack &dragcards)\r
+{\r
+       Card dragcard = dragcards[dragcards.NumCards() - 1];\r
+\r
+       //if we are empty, can only drop a stack with a King at bottom\r
+       if(stackobj.NumCards() == 0)\r
+       {\r
+               if(dragcard.LoVal() != 13)\r
+                       return false;\r
+       }\r
+       else\r
+       {\r
+               const CardStack &mystack = stackobj.GetCardStack();\r
+               \r
+               //can only drop if card is 1 less\r
+               if(mystack[0].LoVal() != dragcard.LoVal() + 1)\r
+                       return false;\r
+\r
+               //can only drop if card is different colour\r
+               if( mystack[0].IsBlack() && !dragcard.IsRed() ||\r
+                  !mystack[0].IsBlack() &&  dragcard.IsRed() )\r
+                       return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+//\r
+//     Can only drop a card onto a suit-stack if the\r
+//  card is 1 higher, and is the same suit\r
+//\r
+bool CanDrop(CardRegion &stackobj, Card card)\r
+{\r
+       int topval;\r
+\r
+       const CardStack &cardstack = stackobj.GetCardStack();\r
+\r
+       if(cardstack.NumCards() > 0)\r
+       {\r
+               if(card.Suit() != cardstack[0].Suit())\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               topval = cardstack[0].LoVal();\r
+       }\r
+       else\r
+       {\r
+               topval = 0;\r
+       }\r
+\r
+       //make sure 1 higher\r
+       if(card.LoVal() != (topval + 1))\r
+               return false;\r
+\r
+       return true;\r
+}\r
+\r
+//\r
+//     Can only drop a card onto suit stack if it is same suit, and 1 higher\r
+//\r
+bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards)\r
+{\r
+       int topval = 0;\r
+\r
+       //only drop 1 card at a time\r
+       if(dragcards.NumCards() != 1)\r
+               return false;\r
+\r
+       return CanDrop(stackobj, dragcards[0]);\r
+}\r
+\r
+//\r
+//     Single-click on one of the row-stacks\r
+//     Turn the top-card over if they are all face-down\r
+//\r
+void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked)\r
+{\r
+       int numfacedown;\r
+       \r
+       stackobj.GetFaceDirection(&numfacedown);\r
+\r
+       //if all face-down, then make top card face-up\r
+       if(stackobj.NumCards() == numfacedown)\r
+       {\r
+               if(numfacedown > 0) numfacedown--;\r
+               stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown);\r
+               stackobj.Redraw();\r
+       }\r
+}\r
+\r
+//\r
+//     Find the suit-stack that can accept the specified card\r
+//\r
+CardRegion *FindSuitStackFromCard(Card card)\r
+{\r
+       for(int i = 0; i < 4; i++)\r
+       {\r
+               if(CanDrop(*pSuitStack[i], card))\r
+                       return pSuitStack[i];\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+//\r
+//     What happens when we add a card to one of the suit stacks?\r
+//  Well, nothing (it is already added), but we need to\r
+//  check all four stacks (not just this one) to see if\r
+//  the game has finished.\r
+//\r
+void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)\r
+{\r
+       bool fGameOver = true;\r
+\r
+       for(int i = 0; i < 4; i++)\r
+       {\r
+               if(pSuitStack[i]->NumCards() != 13)\r
+               {\r
+                       fGameOver = false;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if(fGameOver)\r
+       {\r
+               MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION);\r
+       \r
+               for(int i = 0; i < 4; i++)\r
+               {\r
+                       pSuitStack[i]->Flash(11, 100);\r
+               }\r
+       }\r
+}\r
+\r
+//\r
+//     Double-click on one of the row stacks\r
+//     The aim is to find a suit-stack to move the\r
+//  double-clicked card to.\r
+//\r
+void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked)\r
+{\r
+       //can only move 1 card at a time\r
+       if(iNumClicked != 1)\r
+               return;\r
+\r
+       //find a suit-stack to move the card to...\r
+       const CardStack &cardstack = stackobj.GetCardStack();\r
+       CardRegion *pDest = FindSuitStackFromCard(cardstack[0]);\r
+       \r
+       if(pDest != 0)\r
+       {\r
+               //stackobj.MoveCards(pDest, 1, true);\r
+               //use the SimulateDrag funcion, because we get the\r
+               //AddProc callbacks called for us on the destination stacks...\r
+               stackobj.SimulateDrag(pDest, 1, true);\r
+       }\r
+}\r
+\r
+//\r
+//     Face-up pile double-click\r
+//\r
+void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)\r
+{\r
+       RowStackDblClickProc(stackobj, iNumClicked);\r
+}\r
+\r
+//\r
+//     What happens when a card is removed from face-up pile?\r
+//\r
+void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)\r
+{\r
+       //modify our "virtual" pile by removing the same card\r
+       //that was removed from the physical card stack\r
+       activepile.Pop(iItems);\r
+\r
+       //if there is just 1 card left, then modify the\r
+       //stack to contain ALL the face-up cards..the effect\r
+       //will be, the next time a card is dragged, all the\r
+       //previous card-triplets will be available underneath\r
+       if(stackobj.NumCards() == 1)\r
+       {\r
+               stackobj.SetOffsets(0,0);\r
+               stackobj.SetCardStack(activepile);\r
+       }\r
+}\r
+\r
+//\r
+//     Double-click on the deck\r
+//     Move 3 cards to the face-up pile\r
+//\r
+void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)\r
+{\r
+       CardStack cardstack = stackobj.GetCardStack();\r
+       CardStack pile           = pPile->GetCardStack();\r
+\r
+       fGameStarted = true;\r
+\r
+       //reset the face-up pile to represent 3 cards\r
+       pPile->SetOffsets(CS_DEFXOFF, 1);\r
+\r
+       if(cardstack.NumCards() == 0)\r
+       {\r
+               pile.Clear();\r
+\r
+               activepile.Reverse();\r
+               cardstack.Push(activepile);\r
+               activepile.Clear();\r
+       }\r
+       else\r
+       {\r
+               int numcards = min(3, cardstack.NumCards());\r
+               \r
+               //make a "visible" copy of these cards\r
+               CardStack temp;\r
+               temp = cardstack.Pop(numcards);\r
+               temp.Reverse();\r
+\r
+               pile.Clear();\r
+               pile.Push(temp);\r
+\r
+               //remove the top 3 from deck\r
+               activepile.Push(temp);\r
+       }\r
+\r
+       activepile.Print();\r
+\r
+       pDeck->SetCardStack(cardstack);\r
+       pPile->SetCardStack(pile);\r
+\r
+       SolWnd.Redraw();\r
+}\r
diff --git a/rosapps/games/solitaire/solitaire.cpp b/rosapps/games/solitaire/solitaire.cpp
new file mode 100644 (file)
index 0000000..c8e3e66
--- /dev/null
@@ -0,0 +1,217 @@
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <tchar.h>\r
+#include "resource.h"\r
+#include "cardlib/cardlib.h"\r
+\r
+#include "solitaire.h"\r
+\r
+TCHAR szHelpPath[MAX_PATH];\r
+\r
+DWORD          dwAppStartTime;\r
+HWND           hwndMain;\r
+HWND           hwndStatus;\r
+HINSTANCE      hInstance;\r
+\r
+TCHAR szAppName[] = _T("Solitaire");\r
+\r
+CardWindow SolWnd;\r
+\r
+LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);\r
+\r
+void MakePath(TCHAR *szDest, UINT nDestLen, TCHAR *szExt)\r
+{\r
+       TCHAR *ptr;\r
+       \r
+       ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1;\r
+       while(*ptr-- != '.');\r
+       lstrcpy(ptr + 1, szExt);\r
+}\r
+\r
+//\r
+//     Main entry point\r
+//\r
+int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)\r
+{\r
+       HWND            hwnd;\r
+       MSG                     msg;\r
+       WNDCLASSEX      wndclass;\r
+       INITCOMMONCONTROLSEX ice;\r
+       HACCEL          hAccelTable;                    \r
+\r
+       hInstance = hInst;\r
+\r
+       //Window class for the main application parent window\r
+       wndclass.cbSize                 = sizeof(wndclass);\r
+       wndclass.style                  = 0;//CS_HREDRAW | CS_VREDRAW;\r
+       wndclass.lpfnWndProc    = WndProc;\r
+       wndclass.cbClsExtra             = 0;\r
+       wndclass.cbWndExtra             = 0;\r
+       wndclass.hInstance              = hInst;\r
+       wndclass.hIcon                  = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));\r
+       wndclass.hCursor                = LoadCursor (NULL, IDC_ARROW);\r
+       wndclass.hbrBackground  = (HBRUSH)NULL;\r
+       wndclass.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU1);\r
+       wndclass.lpszClassName  = szAppName;\r
+       wndclass.hIconSm                = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0);\r
+\r
+       RegisterClassEx(&wndclass);\r
+\r
+       ice.dwSize = sizeof(ice);\r
+       ice.dwICC = ICC_BAR_CLASSES;\r
+       InitCommonControlsEx(&ice);\r
+\r
+       srand((unsigned)GetTickCount());//timeGetTime());\r
+\r
+//     InitCardLib();\r
+\r
+//     LoadSettings();\r
+\r
+       //Construct the path to our help file\r
+       MakePath(szHelpPath, MAX_PATH, _T(".hlp"));\r
+       \r
+       hwnd = CreateWindow(szAppName,          // window class name\r
+                               szAppName,                              // window caption\r
+                               WS_OVERLAPPEDWINDOW\r
+                               ,//|WS_CLIPCHILDREN,    // window style\r
+                               CW_USEDEFAULT,                  // initial x position\r
+                               CW_USEDEFAULT,                  // initial y position\r
+                               CW_USEDEFAULT,                  // initial x size\r
+                               CW_USEDEFAULT,                  // initial y size\r
+                               NULL,                                   // parent window handle\r
+                               NULL,                                   // use window class menu\r
+                               hInst,                                  // program instance handle\r
+                               NULL);                                  // creation parameters\r
+\r
+       hwndMain = hwnd;\r
+\r
+       ShowWindow(hwnd, iCmdShow);\r
+       UpdateWindow(hwnd);\r
+\r
+       hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));\r
+\r
+       while(GetMessage(&msg, NULL,0,0))\r
+       {\r
+               if(!TranslateAccelerator(hwnd, hAccelTable, &msg))\r
+               {\r
+                       TranslateMessage(&msg);\r
+                       DispatchMessage(&msg);\r
+               }\r
+       }\r
+\r
+//     SaveSettings();\r
+\r
+       return msg.wParam;\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
+{\r
+       static int nWidth, nHeight;\r
+       int nStatusHeight = 0;//20;\r
+       int parts[] = { 100, -1 };\r
+       UINT ret;\r
+\r
+       MINMAXINFO *mmi;\r
+\r
+       switch(iMsg)\r
+       {\r
+       case WM_CREATE:\r
+               hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "Ready", hwnd, 0);\r
+               \r
+               //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0);\r
+\r
+               SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); \r
+               SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"");\r
+\r
+               ShowWindow(hwndStatus, SW_HIDE);\r
+\r
+               SolWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0);\r
+\r
+               CreateSol();\r
+\r
+               NewGame();\r
+\r
+               dwAppStartTime = GetTickCount();\r
+\r
+               return 0;\r
+\r
+       case WM_DESTROY:\r
+               PostQuitMessage(0);\r
+               return 0;\r
+\r
+       case WM_SIZE:\r
+               nWidth  = LOWORD(lParam);\r
+               nHeight = HIWORD(lParam);\r
+\r
+               MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE);\r
+               //MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE);\r
+               //parts[0] = nWidth - 256;\r
+               //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); \r
+\r
+               return 0;\r
+\r
+       case WM_GETMINMAXINFO:\r
+               mmi = (MINMAXINFO *)lParam;             \r
+               mmi->ptMinTrackSize.x = 600;\r
+               mmi->ptMinTrackSize.y = 400;\r
+\r
+               return 0;\r
+\r
+       case WM_COMMAND:\r
+       \r
+               switch(LOWORD(wParam))\r
+               {\r
+               case IDM_GAME_NEW:\r
+                       //simulate a button click on the new button..\r
+                       NewGame();\r
+                       return 0;\r
+\r
+               case IDM_GAME_DECK:\r
+                       //ShowDeckOptionsDlg(hwnd);\r
+                       return 0;\r
+\r
+               case IDM_GAME_OPTIONS:\r
+                       //ShowGameOptionsDlg(hwnd);\r
+                       return 0;\r
+\r
+               case IDM_HELP_CONTENTS:\r
+\r
+                       WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");\r
+                       \r
+                       return 0;\r
+\r
+               case IDM_HELP_ABOUT:\r
+                       MessageBox(hwnd, _T("Solitare by J Brown\r\n\r\nCardLib version 1.0."), szAppName, MB_OK|MB_ICONINFORMATION);\r
+\r
+                       return 0;\r
+\r
+               case IDM_GAME_EXIT:\r
+                       PostMessage(hwnd, WM_CLOSE, 0, 0);\r
+                       return 0;\r
+               }\r
+\r
+               return 0;\r
+\r
+       case WM_CLOSE:\r
+               \r
+               ret = IDOK;\r
+\r
+               if(fGameStarted)\r
+               {\r
+                       ret = MessageBox(hwnd, _T("Quit the current game?"), szAppName, MB_OKCANCEL|MB_ICONQUESTION);\r
+               }\r
+\r
+               if(ret == IDOK)\r
+               {\r
+                       WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);\r
+                       DestroyWindow(hwnd);\r
+               }\r
+\r
+               return 0;\r
+       }\r
+\r
+       return DefWindowProc (hwnd, iMsg, wParam, lParam);\r
+}\r
+\r
diff --git a/rosapps/games/solitaire/solitaire.h b/rosapps/games/solitaire/solitaire.h
new file mode 100644 (file)
index 0000000..a1b1d38
--- /dev/null
@@ -0,0 +1,37 @@
+#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