Updated copyright notice to 2013
[xboard.git] / winboard / winboard.c
index 88092ac..5249c92 100644 (file)
@@ -5,7 +5,7 @@
  * Massachusetts. \r
  *\r
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
- * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.\r
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
  *\r
  * Enhancements Copyright 2005 Alessandro Scotti\r
  *\r
@@ -164,7 +164,7 @@ BoardSize boardSize;
 Boolean chessProgram;\r
 //static int boardX, boardY;\r
 int  minX, minY; // [HGM] placement: volatile limits on upper-left corner\r
-int squareSize, lineGap, minorSize;\r
+int squareSize, lineGap, minorSize, border;\r
 static int winW, winH;\r
 static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo\r
 static int logoHeight = 0;\r
@@ -296,7 +296,7 @@ int dialogItems[][42] = {
   OPT_ChooseTellColor, OPT_ChooseChallengeColor, OPT_ChooseRequestColor,\r
   OPT_ChooseSeekColor, OPT_ChooseNormalColor, OPT_ChooseBackgroundColor,\r
   OPT_DefaultColors, OPT_DontColorize, IDC_Boxes, GPB_Colors, GPB_Premove,\r
-  GPB_General, GPB_Alarm }, \r
+  GPB_General, GPB_Alarm, OPT_AutoCreate }, \r
 { DLG_BoardOptions, IDOK, IDCANCEL, OPT_SizeTiny, OPT_SizeTeeny, OPT_SizeDinky,\r
   OPT_SizePetite, OPT_SizeSlim, OPT_SizeSmall, OPT_SizeMediocre, OPT_SizeMiddling,\r
   OPT_SizeAverage, OPT_SizeModerate, OPT_SizeMedium, OPT_SizeBulky, OPT_SizeLarge,\r
@@ -1030,6 +1030,7 @@ InitTextures()
   backTextureSquareSize = 0; // kludge to force recalculation of texturemode\r
   \r
   if( appData.liteBackTextureFile && appData.liteBackTextureFile[0] != NULLCHAR && appData.liteBackTextureFile[0] != '*' ) {\r
+      if(liteBackTexture) DeleteObject(liteBackTexture);\r
       liteBackTexture = LoadImage( 0, appData.liteBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
       liteBackTextureMode = appData.liteBackTextureMode;\r
 \r
@@ -1039,6 +1040,7 @@ InitTextures()
   }\r
   \r
   if( appData.darkBackTextureFile && appData.darkBackTextureFile[0] != NULLCHAR && appData.darkBackTextureFile[0] != '*' ) {\r
+      if(darkBackTexture) DeleteObject(darkBackTexture);\r
       darkBackTexture = LoadImage( 0, appData.darkBackTextureFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
       darkBackTextureMode = appData.darkBackTextureMode;\r
 \r
@@ -1277,6 +1279,7 @@ ParseFontName(char *name, MyFontParams *mfp)
     p = q + 1;\r
   } else {\r
     q = mfp->faceName;\r
+\r
     while (*p && !isdigit(*p)) {\r
       *q++ = *p++;\r
       if (q - mfp->faceName >= sizeof(mfp->faceName))\r
@@ -2113,9 +2116,15 @@ void CreatePiecesFromFont()
 HBITMAP\r
 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)\r
 {\r
-  char name[128];\r
+  char name[128], buf[MSG_SIZ];\r
 \r
     snprintf(name, sizeof(name)/sizeof(name[0]), "%s%d%s", piece, squareSize, suffix);\r
+  if(appData.pieceDirectory[0]) {\r
+    HBITMAP res;\r
+    snprintf(buf, MSG_SIZ, "%s\\%s.bmp", appData.pieceDirectory, name);\r
+    res = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+    if(res) return res;\r
+  }\r
   if (gameInfo.event &&\r
       strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&\r
       strcmp(name, "k80s") == 0) {\r
@@ -2275,6 +2284,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   squareSize = sizeInfo[boardSize].squareSize;\r
   lineGap = sizeInfo[boardSize].lineGap;\r
   minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted  */\r
+  border = appData.useBorder && appData.border[0] ? squareSize/2 : 0;\r
 \r
   if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
       lineGap = appData.overrideLineGap;\r
@@ -2299,8 +2309,8 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     DrawMenuBar(hwndMain);\r
   }\r
 \r
-  boardWidth  = BoardWidth(boardSize, BOARD_WIDTH);\r
-  boardHeight = BoardWidth(boardSize, BOARD_HEIGHT);\r
+  boardWidth  = BoardWidth(boardSize, BOARD_WIDTH) + 2*border;\r
+  boardHeight = BoardWidth(boardSize, BOARD_HEIGHT) + 2*border;\r
 \r
   /* Get text area sizes */\r
   hdc = GetDC(hwndMain);\r
@@ -2471,20 +2481,20 @@ InitDrawingSizes(BoardSize boardSize, int flags)
 \r
     /* [HGM] Loop had to be split in part for vert. and hor. lines */\r
     for (i = 0; i < BOARD_HEIGHT + 1; i++) {\r
-      gridEndpoints[i*2].x = boardRect.left + lineGap / 2;\r
+      gridEndpoints[i*2].x = boardRect.left + lineGap / 2 + border;\r
       gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =\r
-       boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));\r
+       boardRect.top + lineGap / 2 + (i * (squareSize + lineGap)) + border;\r
       gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +\r
-        BOARD_WIDTH * (squareSize + lineGap);\r
+        BOARD_WIDTH * (squareSize + lineGap) + border;\r
       gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
     }\r
     for (i = 0; i < BOARD_WIDTH + 1; i++) {\r
-      gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2;\r
+      gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].y = boardRect.top + lineGap / 2 + border;\r
       gridEndpoints[i*2 + BOARD_HEIGHT*2 + 2].x =\r
         gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].x = boardRect.left +\r
-       lineGap / 2 + (i * (squareSize + lineGap));\r
+       lineGap / 2 + (i * (squareSize + lineGap)) + border;\r
       gridEndpoints[i*2 + 1 + BOARD_HEIGHT*2 + 2].y =\r
-        boardRect.top + BOARD_HEIGHT * (squareSize + lineGap);\r
+        boardRect.top + BOARD_HEIGHT * (squareSize + lineGap) + border;\r
       gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
     }\r
   }\r
@@ -2737,11 +2747,11 @@ VOID
 SquareToPos(int row, int column, int * x, int * y)\r
 {\r
   if (flipView) {\r
-    *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);\r
-    *y = boardRect.top + lineGap + row * (squareSize + lineGap);\r
+    *x = boardRect.left + lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap) + border;\r
+    *y = boardRect.top + lineGap + row * (squareSize + lineGap) + border;\r
   } else {\r
-    *x = boardRect.left + lineGap + column * (squareSize + lineGap);\r
-    *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);\r
+    *x = boardRect.left + lineGap + column * (squareSize + lineGap) + border;\r
+    *y = boardRect.top + lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap) + border;\r
   }\r
 }\r
 \r
@@ -2768,15 +2778,23 @@ DrawCoordsOnDC(HDC hdc)
   y = boardRect.top + lineGap;\r
   x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);\r
 \r
+  if(border) {\r
+    SetTextAlign(hdc, TA_RIGHT|TA_TOP);\r
+    x += border - lineGap - 4; y += squareSize - 6;\r
+  } else\r
   SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
   for (i = 0; i < BOARD_HEIGHT; i++) {\r
     str[0] = files[start + i];\r
-    ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);\r
+    ExtTextOut(hdc, x + 2 - (border ? gameInfo.holdingsWidth * (squareSize + lineGap) : 0), y + 1, 0, NULL, str, 1, NULL);\r
     y += squareSize + lineGap;\r
   }\r
 \r
   start = flipView ? 23-(BOARD_RGHT-BOARD_LEFT) : 23;\r
 \r
+  if(border) {\r
+    SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
+    x += -border + 4; y += border - squareSize + 6;\r
+  } else\r
   SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);\r
   for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {\r
     str[0] = ranks[start + i];\r
@@ -2813,14 +2831,14 @@ DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)
   if (lineGap == 0) return;\r
   if (flipView) {\r
     x1 = boardRect.left +\r
-      lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap);\r
+      lineGap/2 + ((BOARD_WIDTH-1)-x) * (squareSize + lineGap) + border;\r
     y1 = boardRect.top +\r
-      lineGap/2 + y * (squareSize + lineGap);\r
+      lineGap/2 + y * (squareSize + lineGap) + border;\r
   } else {\r
     x1 = boardRect.left +\r
-      lineGap/2 + x * (squareSize + lineGap);\r
+      lineGap/2 + x * (squareSize + lineGap) + border;\r
     y1 = boardRect.top +\r
-      lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap);\r
+      lineGap/2 + ((BOARD_HEIGHT-1)-y) * (squareSize + lineGap) + border;\r
   }\r
   hPen = pen ? premovePen : highlightPen;\r
   oldPen = SelectObject(hdc, on ? hPen : gridPen);\r
@@ -2898,7 +2916,9 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
     BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,\r
           sqcolor ? SRCCOPY : NOTSRCCOPY);\r
   } else {\r
+    HBRUSH xBrush = whitePieceBrush;\r
     tmpSize = squareSize;\r
+    if(appData.pieceDirectory[0]) xBrush = GetStockObject(WHITE_BRUSH);\r
     if(minorSize &&\r
         ((piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper) ||\r
          (piece >= (int)BlackNightrider && piece <= BlackGrasshopper))  ) {\r
@@ -2911,7 +2931,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
     if (color || appData.allWhite ) {\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
       if( color )\r
-              oldBrush = SelectObject(hdc, whitePieceBrush);\r
+              oldBrush = SelectObject(hdc, xBrush);\r
       else    oldBrush = SelectObject(hdc, blackPieceBrush);\r
       if(appData.upsideDown && color==flipView)\r
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
@@ -2923,6 +2943,18 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
+    } else if(appData.pieceDirectory[0]) {\r
+      oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
+      oldBrush = SelectObject(hdc, xBrush);\r
+      if(appData.upsideDown && color==flipView)\r
+        StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
+      else\r
+        BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
+      SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
+      if(appData.upsideDown && color==flipView)\r
+        StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
+      else\r
+        BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
     } else {\r
       /* Use square color for details of black pieces */\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
@@ -3310,6 +3342,40 @@ BOOL DrawPositionNeedsFullRepaint()
     return result;\r
 }\r
 \r
+static HBITMAP borderBitmap;\r
+\r
+VOID\r
+DrawBackgroundOnDC(HDC hdc)\r
+{\r
+  \r
+  BITMAP bi;\r
+  HDC tmphdc;\r
+  HBITMAP hbm;\r
+  static char oldBorder[MSG_SIZ];\r
+  int w = 600, h = 600, mode;\r
+\r
+  if(strcmp(appData.border, oldBorder)) { // load new one when old one no longer valid\r
+    strncpy(oldBorder, appData.border, MSG_SIZ-1);\r
+    borderBitmap = LoadImage( 0, appData.border, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );        \r
+  }\r
+  if(borderBitmap == NULL) { // loading failed, use white\r
+    FillRect( hdc, &boardRect, whitePieceBrush );\r
+    return;\r
+  }\r
+  tmphdc = CreateCompatibleDC(hdc);\r
+  hbm = SelectObject(tmphdc, borderBitmap);\r
+  if( GetObject( borderBitmap, sizeof(bi), &bi ) > 0 ) {\r
+            w = bi.bmWidth;\r
+            h = bi.bmHeight;\r
+  }\r
+  mode = SetStretchBltMode(hdc, COLORONCOLOR);\r
+  StretchBlt(hdc, boardRect.left, boardRect.top, boardRect.right - boardRect.left, \r
+                  boardRect.bottom - boardRect.top, tmphdc, 0, 0, w, h, SRCCOPY);\r
+  SetStretchBltMode(hdc, mode);\r
+  SelectObject(tmphdc, hbm);\r
+  DeleteDC(tmphdc);\r
+}\r
+\r
 VOID\r
 DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)\r
 {\r
@@ -3828,6 +3894,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
        Ellipse(hdcmem, x-r, y-r, x+r, y+r);\r
        SelectObject(hdcmem, oldBrush);\r
   } else {\r
+    if(border) DrawBackgroundOnDC(hdcmem);\r
     DrawGridOnDC(hdcmem);\r
     if(nr == 0) { // [HGM] dual: decide which highlights to draw\r
        DrawHighlightsOnDC(hdcmem, &highlightInfo, HIGHLIGHT_PEN);\r
@@ -4081,11 +4148,11 @@ PaintProc(HWND hwnd)
 int EventToSquare(x, limit)\r
      int x, limit;\r
 {\r
-  if (x <= 0)\r
+  if (x <= border)\r
     return -2;\r
-  if (x < lineGap)\r
+  if (x < lineGap + border)\r
     return -1;\r
-  x -= lineGap;\r
+  x -= lineGap + border;\r
   if ((x % (squareSize + lineGap)) >= squareSize)\r
     return -1;\r
   x /= (squareSize + lineGap);\r
@@ -4803,6 +4870,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       }\r
       break;\r
 \r
+    case IDM_CreateBook:\r
+      CreateBookEvent();\r
+      break;\r
+\r
     case IDM_CopyGame:\r
       CopyGameToClipboard();\r
       break;\r
@@ -5141,6 +5212,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       BoardOptionsPopup(hwnd);\r
       break;\r
 \r
+    case IDM_ThemeOptions:\r
+      ThemeOptionsPopup(hwnd);\r
+      break;\r
+\r
     case IDM_EnginePlayOptions:\r
       EnginePlayOptionsPopup(hwnd);\r
       break;\r
@@ -9696,7 +9771,7 @@ CmailSigHandlerCallBack(InputSourceRef isr, VOIDSTAR closure,
 /* see wedittags.c for Edit Tags functions */\r
 \r
 \r
-VOID\r
+int\r
 ICSInitScript()\r
 {\r
   FILE *f;\r
@@ -9708,8 +9783,10 @@ ICSInitScript()
     if (f != NULL) {\r
       ProcessICSInitScript(f);\r
       fclose(f);\r
+      return TRUE;\r
     }\r
   }\r
+  return FALSE;\r
 }\r
 \r
 \r
@@ -9865,11 +9942,11 @@ ScreenSquare(column, row, pt)
      int column; int row; POINT * pt;\r
 {\r
   if (flipView) {\r
-    pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);\r
-    pt->y = lineGap + row * (squareSize + lineGap);\r
+    pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap) + border;\r
+    pt->y = lineGap + row * (squareSize + lineGap) + border;\r
   } else {\r
-    pt->x = lineGap + column * (squareSize + lineGap);\r
-    pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);\r
+    pt->x = lineGap + column * (squareSize + lineGap) + border;\r
+    pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap) + border;\r
   }\r
 }\r
 \r
@@ -9937,3 +10014,24 @@ int flock(int fid, int code)
     }\r
     return 0;\r
 }\r
+\r
+char *\r
+Col2Text (int n)\r
+{\r
+    static int i=0;\r
+    static char col[8][20];\r
+    COLORREF color = *(COLORREF *) colorVariable[n];\r
+    i = i+1 & 7;\r
+    snprintf(col[i], 20, "#%02lx%02lx%02lx", color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
+    return col[i];\r
+}\r
+\r
+void\r
+ActivateTheme (int new)\r
+{   // Redo initialization of features depending on options that can occur in themes\r
+   InitTextures();\r
+   if(new) InitDrawingColors();\r
+   fontBitmapSquareSize = 0; // request creation of new font pieces\r
+   InitDrawingSizes(-2, 0);\r
+   InvalidateRect(hwndMain, NULL, TRUE);\r
+}\r