Index: src/apps/pairs/Pairs.cpp
===================================================================
--- src/apps/pairs/Pairs.cpp	(revision 35982)
+++ src/apps/pairs/Pairs.cpp	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. 
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -16,8 +17,9 @@
 
 
 Pairs::Pairs()
-	: BApplication(kSignature),
-	  fWindow(NULL)
+	: 
+	BApplication(kSignature),
+	fWindow(NULL)
 {
 	be_locale->GetAppCatalog(&fCatalog);
 }
Index: src/apps/pairs/PairsView.h
===================================================================
--- src/apps/pairs/PairsView.h	(revision 35982)
+++ src/apps/pairs/PairsView.h	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -15,14 +16,19 @@
 class PairsView : public BView {
 public:
 								PairsView(BRect frame, const char* name,
+									int width, int height, 
 									uint32 resizingMode);
 
 	virtual						~PairsView();
 	virtual	void				AttachedToWindow();
 	virtual	void				Draw(BRect updateRect);
 	virtual	void				CreateGameBoard();
+	
+			int 				fWidth;
+			int					fHeight;
+			int					fNumOfCards;
 
-			TopButton*			fDeckCard[16];
+			BList				fDeckCard;
 			int					GetIconFromPos(int pos);
 
 private:
@@ -32,10 +38,10 @@
 			bool				_HasBitmap(BList& bitmaps, BBitmap* bitmap);
 
 			BMessage*			fButtonMessage;
-			BBitmap*			fCard[8];
-			int					fRandPos[16];
-			int					fPosX[16];
-			int					fPosY[16];
+			BList				fCardBitmaps;
+			int*				fRandPos;
+			int*				fPosX;
+			int*				fPosY;
 };
 
 
Index: src/apps/pairs/PairsTopButton.h
===================================================================
--- src/apps/pairs/PairsTopButton.h	(revision 35982)
+++ src/apps/pairs/PairsTopButton.h	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
Index: src/apps/pairs/Pairs.h
===================================================================
--- src/apps/pairs/Pairs.h	(revision 35982)
+++ src/apps/pairs/Pairs.h	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
Index: src/apps/pairs/PairsGlobal.h
===================================================================
--- src/apps/pairs/PairsGlobal.h	(revision 35982)
+++ src/apps/pairs/PairsGlobal.h	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -12,6 +13,7 @@
 const uint32 kMsgCardButton = 'card';
 const uint32 kMsgPairComparing = 'pcom';
 const int kBitmapSize = 64;
+const int kSpaceSize = 10;
 
 
 #endif // PAIRS_GLOBAL_H
Index: src/apps/pairs/PairsWindow.cpp
===================================================================
--- src/apps/pairs/PairsWindow.cpp	(revision 35982)
+++ src/apps/pairs/PairsWindow.cpp	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -12,6 +13,9 @@
 #include <Button.h>
 #include <Catalog.h>
 #include <Locale.h>
+#include <Menu.h>
+#include <MenuBar.h>
+#include <MenuItem.h>
 #include <MessageRunner.h>
 #include <String.h>
 #include <TextView.h>
@@ -25,24 +29,27 @@
 #undef TR_CONTEXT
 #define TR_CONTEXT "PairsWindow"
 
+const uint32 MENU_NEW					= 'MGnw';
+const uint32 MENU_SIZE					= 'MGsz';
+const uint32 MENU_QUIT					= 'MGqu';
+
 PairsWindow::PairsWindow()
-	: BWindow(BRect(100, 100, 405, 405), "Pairs", B_TITLED_WINDOW,
+	: BWindow(BRect(100, 100, 405, 423), "Pairs", B_TITLED_WINDOW,
 		B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
 			| B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
-	  fPairComparing(NULL),
-	  fIsFirstClick(true),
-	  fIsPairsActive(true),
-	  fPairCard(0),
-	  fPairCardTmp(0),
-	  fButtonTmp(0),
-	  fButton(0),
-	  fButtonClicks(0),
-	  fFinishPairs(0)
+	fPairComparing(NULL),
+	fIsFirstClick(true),
+	fIsPairsActive(true),
+	fPairCard(0),
+	fPairCardTmp(0),
+	fButtonTmp(0),
+	fButton(0),
+	fButtonClicks(0),
+	fFinishPairs(0)
 {
-	fPairsView = new PairsView(Bounds().InsetByCopy(0, 0).OffsetToSelf(0, 0),
-		"PairsView", B_FOLLOW_NONE);
-	fPairsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
-	AddChild(fPairsView);
+	_MakeMenuBar();	
+		
+	_MakeGameView(4, 4);	
 
 	CenterOnScreen();
 }
@@ -55,9 +62,102 @@
 
 
 void
+PairsWindow::_MakeMenuBar()
+{
+	fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar");
+	AddChild(fMenuBar);
+	
+	BMenu* menu = new BMenu(TR("Game"));
+	fMenuBar->AddItem(menu);
+	
+	BMenuItem* menuItem;
+	menu->AddItem(menuItem = new BMenuItem(TR("New"),
+		new BMessage(MENU_NEW), 'N'));
+	
+	menu->AddSeparatorItem();
+	
+	BMenu* sizeMenu = new BMenu(TR("Size"));
+	sizeMenu->SetRadioMode(true);
+	
+	BMessage* sizeMessage = new BMessage(MENU_SIZE);
+	sizeMessage->AddInt32("width",4);
+	sizeMessage->AddInt32("height",4);
+	sizeMenu->AddItem(menuItem = new BMenuItem(TR("Beginner (4x4)"),
+		sizeMessage));
+	menuItem->SetMarked(true);
+	
+	sizeMessage = new BMessage(MENU_SIZE);
+	sizeMessage->AddInt32("width",6);
+	sizeMessage->AddInt32("height",6);
+	sizeMenu->AddItem(menuItem = new BMenuItem(TR("Intermediate (6x6)"),
+		sizeMessage));
+		
+	sizeMessage = new BMessage(MENU_SIZE);
+	sizeMessage->AddInt32("width",8);
+	sizeMessage->AddInt32("height",8);
+	sizeMenu->AddItem(menuItem = new BMenuItem(TR("Expert (8x8)"),
+		sizeMessage));
+	
+	menu->AddItem(sizeMenu);
+	
+	menu->AddSeparatorItem();
+	
+	menu->AddItem(menuItem = new BMenuItem(TR("Quit"),
+		new BMessage(MENU_QUIT), 'Q'));
+}
+
+
+void
+PairsWindow::_MakeGameView(int width, int height)
+{
+	BRect viewBounds = Bounds();
+	viewBounds.top = fMenuBar->Bounds().Height() + 1;
+		
+	fPairsView = new PairsView(viewBounds, "PairsView", width, height, 
+		B_FOLLOW_NONE);
+	fPairsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+	AddChild(fPairsView);
+}
+
+
+void
+PairsWindow::NewGame()
+{
+	fButtonClicks = 0;
+	fFinishPairs = 0;
+	fPairsView->CreateGameBoard();
+}
+
+
+void
+PairsWindow::SetGameSize(int width, int height) {
+	ResizeTo((kBitmapSize + kSpaceSize) * width + kSpaceSize,
+		(kBitmapSize + kSpaceSize) * height + kSpaceSize 
+		+ fMenuBar->Bounds().Height());
+	RemoveChild(fPairsView);
+	delete fPairsView;
+	_MakeGameView(width, height);
+	NewGame();
+}
+
+
+void
 PairsWindow::MessageReceived(BMessage* message)
-{
+{	
 	switch (message->what) {
+		case MENU_NEW:			
+			NewGame();
+			break;
+		case MENU_SIZE:
+			int32 width;
+			int32 height;
+			message->FindInt32("width", &width);
+			message->FindInt32("height", &height);
+			SetGameSize(width, height);	
+			break;
+		case MENU_QUIT:
+			be_app->PostMessage(B_QUIT_REQUESTED);
+			break;
 		case kMsgCardButton:
 			if (fIsPairsActive) {
 				fButtonClicks++;
@@ -66,17 +166,17 @@
 				if (message->FindInt32("ButtonNum", &num) < B_OK)
 					break;
 
-				// look what Icon is behind a button
-				for (int h = 0; h < 16; h++) {
+				// look what Icon is behind a button				
+				for (int h = 0; h < fPairsView->fNumOfCards; h++) {
 					if (fPairsView->GetIconFromPos(h) == num) {
-						fPairCard = (h % 8);
+						fPairCard = (h % fPairsView->fNumOfCards / 2);
 						fButton = fPairsView->GetIconFromPos(h);
 						break;
 					}
 				}
 
 				// gameplay
-				fPairsView->fDeckCard[fButton]->Hide();
+				((TopButton*)fPairsView->fDeckCard.ItemAt(fButton))->Hide();
 
 				if (fIsFirstClick) {
 					fPairCardTmp = fPairCard;
@@ -104,13 +204,13 @@
 
 				if (fPairCard == fPairCardTmp) {
 					fFinishPairs++;
-				} else {
-					fPairsView->fDeckCard[fButton]->Show();
-					fPairsView->fDeckCard[fButtonTmp]->Show();
+				} else {					
+					((TopButton*)fPairsView->fDeckCard.ItemAt(fButton))->Show();
+					((TopButton*)fPairsView->fDeckCard.ItemAt(fButtonTmp))->Show();
 				}
 
 				// game end and results
-				if (fFinishPairs == 8) {
+				if (fFinishPairs == fPairsView->fNumOfCards / 2) {
 					BString strAbout;
 					strAbout
 						<< "Pairs\n"
@@ -136,9 +236,7 @@
 
 					if (alert->Go() == 0) {
 						// New game
-						fButtonClicks = 0;
-						fFinishPairs = 0;
-						fPairsView->CreateGameBoard();
+						NewGame();						
 					} else {
 						// Quit game
 						be_app->PostMessage(B_QUIT_REQUESTED);
Index: src/apps/pairs/PairsView.cpp
===================================================================
--- src/apps/pairs/PairsView.cpp	(revision 35982)
+++ src/apps/pairs/PairsView.cpp	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -26,15 +27,18 @@
 #include "PairsGlobal.h"
 #include "PairsTopButton.h"
 
-// TODO: support custom board sizes
-
-PairsView::PairsView(BRect frame, const char* name, uint32 resizingMode)
-	: BView(frame, name, resizingMode, B_WILL_DRAW)
+PairsView::PairsView(BRect frame, const char* name,
+						int width, int height,
+						uint32 resizingMode)
+	: 
+	BView(frame, name, resizingMode, B_WILL_DRAW),
+	fWidth(width),
+	fHeight(height),
+	fNumOfCards(width * height),
+	fRandPos(new int[fNumOfCards]),
+	fPosX(new int[fNumOfCards]),
+	fPosY(new int[fNumOfCards])
 {
-	// init bitmap pointers
-	for (int i = 0; i < 8; i++)
-		fCard[i] = NULL;
-
 	CreateGameBoard();
 	_SetPairsBoard();
 }
@@ -55,11 +59,15 @@
 
 PairsView::~PairsView()
 {
-	for (int i = 0; i < 8; i++)
-		delete fCard[i];
+	for (int i = 0; i < fCardBitmaps.CountItems(); i++)
+		delete ((BBitmap*)fCardBitmaps.ItemAt(i));
 
-	for (int i = 0; i < 16; i++)
-		delete fDeckCard[i];
+	for (int i = 0; i < fDeckCard.CountItems(); i++)
+		delete ((TopButton*)fDeckCard.ItemAt(i));
+		
+		delete fRandPos;
+		delete fPosX;
+		delete fPosY;
 }
 
 
@@ -91,10 +99,10 @@
 	// TODO: maybe read the icons only once at startup
 
 	// clean out any previous icons
-	for (int i = 0; i < 8; i++) {
-		delete fCard[i];
-		fCard[i] = NULL;
+	for (int i = 0; i < fCardBitmaps.CountItems(); i++) {
+		delete ((BBitmap*)fCardBitmaps.ItemAt(i));
 	}
+	fCardBitmaps.MakeEmpty();
 
 	BDirectory appsDirectory;
 	BDirectory prefsDirectory;
@@ -152,16 +160,20 @@
 	// pick eight random bitmaps from the ones we got in the list
 	srand((unsigned)time(0));
 
-	for (int i = 0; i < 8; i++) {
+	for (int i = 0; i < fNumOfCards / 2; i++) {
 		int32 index = rand() % bitmaps.CountItems();
-		fCard[i] = (BBitmap*)bitmaps.RemoveItem(index);
-		if (fCard[i] == NULL) {
-			BAlert* alert = new BAlert("fatal", "Pairs did not find enough "
-				"vector icons in the system, it needs at least eight.",
+		BBitmap* bitmap = ((BBitmap*)bitmaps.RemoveItem(index));		
+		if (bitmap == NULL) {
+			BString strErr;
+			strErr
+				<< "Pairs did not find enough vector icons in the system; it "
+				<< "needs at least " << fNumOfCards / 2;
+			BAlert* alert = new BAlert("fatal", strErr,
 				"OK", NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
 			alert->Go();
 			exit(1);
 		}
+		fCardBitmaps.AddItem(bitmap);
 	}
 
 	// delete the remaining bitmaps from the list
@@ -173,15 +185,16 @@
 void
 PairsView::_SetPairsBoard()
 {
-	for (int i = 0; i < 16; i++) {
+	for (int i = 0; i < fNumOfCards; i++) {
 		fButtonMessage = new BMessage(kMsgCardButton);
 		fButtonMessage->AddInt32("ButtonNum", i);
 
-		int x =  i % 4 * (kBitmapSize + 10) + 10;
-		int y =  i / 4 * (kBitmapSize + 10) + 10;
-
-		fDeckCard[i] = new TopButton(x, y, fButtonMessage);
-		AddChild(fDeckCard[i]);
+		int x =  i % fWidth * (kBitmapSize + kSpaceSize) + kSpaceSize;
+		int y =  i / fHeight * (kBitmapSize + kSpaceSize) + kSpaceSize;
+		
+		TopButton* button = new TopButton(x, y, fButtonMessage);
+		fDeckCard.AddItem(button);		
+		AddChild(button);
 	}
 }
 
@@ -191,25 +204,29 @@
 {
 	_ReadRandomIcons();
 
-	srand((unsigned)time(0));
+	srand((unsigned)time(0));	
 
-	int positions[16];
-	for (int i = 0; i < 16; i++)
+	int* positions = new int[fNumOfCards];
+	for (int i = 0; i < fNumOfCards; i++)
 		positions[i] = i;
 
-	for (int i = 16; i >= 1; i--) {
+	for (int i = fNumOfCards; i >= 1; i--) {
 		int index = rand() % i;
 
-		fRandPos[16-i] = positions[index];
+		fRandPos[fNumOfCards - i] = positions[index];
 
 		for (int j = index; j < i - 1; j++)
 			positions[j] = positions[j + 1];
 	}
 
-	for (int i = 0; i < 16; i++) {
-		fPosX[i] = (fRandPos[i]) % 4 * (kBitmapSize + 10) + 10;
-		fPosY[i] = (fRandPos[i]) / 4 * (kBitmapSize + 10) + 10;
+	for (int i = 0; i < fNumOfCards; i++) {
+		fPosX[i] = (fRandPos[i]) % fWidth * (kBitmapSize + kSpaceSize) 
+			+ kSpaceSize;
+		fPosY[i] = (fRandPos[i]) / fHeight * (kBitmapSize + kSpaceSize) 
+			+ kSpaceSize;
 	}
+	
+	delete [] positions;
 }
 
 
@@ -219,8 +236,10 @@
 	SetDrawingMode(B_OP_ALPHA);
 
 	// draw rand pair 1 & 2
-	for (int i = 0; i < 16; i++)
-		DrawBitmap(fCard[i % 8], BPoint(fPosX[i], fPosY[i]));
+	for (int i = 0; i < fNumOfCards; i++) {
+		BBitmap* bitmap = ((BBitmap*)fCardBitmaps.ItemAt(i % fNumOfCards / 2));
+		DrawBitmap(bitmap, BPoint(fPosX[i], fPosY[i]));
+	}
 }
 
 
Index: src/apps/pairs/PairsWindow.h
===================================================================
--- src/apps/pairs/PairsWindow.h	(revision 35982)
+++ src/apps/pairs/PairsWindow.h	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
@@ -18,10 +19,17 @@
 		virtual					~PairsWindow();
 
 		virtual	void			MessageReceived(BMessage* message);
+		
+		void					NewGame();
+		void					SetGameSize(int width, int height);
 
 private:
+				void			_MakeGameView(int width, int height);
+				void			_MakeMenuBar();
+
 				BView*			fBackgroundView;
 				PairsView*		fPairsView;
+				BMenuBar*		fMenuBar;
 				BMessageRunner*	fPairComparing;
 				bool			fIsFirstClick;
 				bool			fIsPairsActive;
Index: src/apps/pairs/PairsTopButton.cpp
===================================================================
--- src/apps/pairs/PairsTopButton.cpp	(revision 35982)
+++ src/apps/pairs/PairsTopButton.cpp	(working copy)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved.
+ * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. 
+ * All rights reserved.
  * Distributed under the terms of the MIT License.
  */
  
