MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static INT aiPuzzle[NUMROWS][NUMCOLS], iBlankRow, iBlankCol, cxSquare, cySquare ; CHAR szNum[10] ; HPS hps ; HWND hwndFrame ; INT iRow, iCol, iMouseRow, iMouseCol, i ; POINTL ptl ; RECTL rcl, rclInvalid, rclIntersect ; SIZEL sizl ; switch (msg) { case WM_CREATE: // Calculate square size in pixels hps = WinGetPS (hwnd) ; sizl.cx = sizl.cy = 0 ; GpiSetPS (hps, &sizl, PU_LOENGLISH) ; ptl.x = SQUARESIZE ; ptl.y = SQUARESIZE ; GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, &ptl) ; WinReleasePS (hps) ; cxSquare = ptl.x ; cySquare = ptl.y ; // Calculate client window size and position rcl.xLeft = (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - NUMCOLS * cxSquare) / 2 ; rcl.yBottom = (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - NUMROWS * cySquare) / 2 ; rcl.xRight = rcl.xLeft + NUMCOLS * cxSquare ; rcl.yTop = rcl.yBottom + NUMROWS * cySquare ; // Set frame window position and size hwndFrame = WinQueryWindow (hwnd, QW_PARENT) ; WinCalcFrameRect (hwndFrame, &rcl, FALSE) ; WinSetWindowPos (hwndFrame, NULLHANDLE, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ACTIVATE) ; // Initialize the aiPuzzle array WinSendMsg (hwnd, WM_COMMAND, MPFROMSHORT (IDM_NORMAL), NULL) ; return 0 ; case WM_PAINT: hps = WinBeginPaint (hwnd, NULLHANDLE, &rclInvalid) ; // Draw the squares for (iRow = NUMROWS - 1 ; iRow >= 0 ; iRow--) for (iCol = 0 ; iCol < NUMCOLS ; iCol++) { rcl.xLeft = cxSquare * iCol ; rcl.yBottom = cySquare * iRow ; rcl.xRight = rcl.xLeft + cxSquare ; rcl.yTop = rcl.yBottom + cySquare ; if (!WinIntersectRect (0, &rclIntersect, &rcl, &rclInvalid)) continue ; if (iRow == iBlankRow && iCol == iBlankCol) WinFillRect (hps, &rcl, CLR_BLACK) ; else { WinDrawBorder (hps, &rcl, 5, 5, CLR_PALEGRAY, CLR_DARKGRAY, DB_STANDARD | DB_INTERIOR) ; WinDrawBorder (hps, &rcl, 2, 2, CLR_BLACK, 0L, DB_STANDARD) ; sprintf (szNum, "%d", aiPuzzle[iRow][iCol]) ; WinDrawText (hps, -1, szNum, &rcl, CLR_WHITE, CLR_DARKGRAY, DT_CENTER | DT_VCENTER) ; } } WinEndPaint (hps) ; return 0 ; case WM_BUTTON1DOWN: iMouseCol = MOUSEMSG(&msg)->x / cxSquare ; iMouseRow = MOUSEMSG(&msg)->y / cySquare ; // Check if mouse was in valid area if ( iMouseRow < 0 || iMouseCol < 0 || iMouseRow >= NUMROWS || iMouseCol >= NUMCOLS || (iMouseRow != iBlankRow && iMouseCol != iBlankCol) || (iMouseRow == iBlankRow && iMouseCol == iBlankCol)) break ; // Move a row right or left if (iMouseRow == iBlankRow) { if (iMouseCol < iBlankCol) for (iCol = iBlankCol ; iCol > iMouseCol ; iCol--) aiPuzzle[iBlankRow][iCol] = aiPuzzle[iBlankRow][iCol - 1] ; else for (iCol = iBlankCol ; iCol < iMouseCol ; iCol++) aiPuzzle[iBlankRow][iCol] = aiPuzzle[iBlankRow][iCol + 1] ; } // Move a column up or down else { if (iMouseRow < iBlankRow) for (iRow = iBlankRow ; iRow > iMouseRow ; iRow--) aiPuzzle[iRow][iBlankCol] = aiPuzzle[iRow - 1][iBlankCol] ; else for (iRow = iBlankRow ; iRow < iMouseRow ; iRow++) aiPuzzle[iRow][iBlankCol] = aiPuzzle[iRow + 1][iBlankCol] ; } // Calculate invalid rectangle rcl.xLeft = cxSquare * min (iMouseCol, iBlankCol) ; rcl.yBottom = cySquare * min (iMouseRow, iBlankRow) ; rcl.xRight = cxSquare * (max (iMouseCol, iBlankCol) + 1) ; rcl.yTop = cySquare * (max (iMouseRow, iBlankRow) + 1) ; // Set new array and blank values iBlankRow = iMouseRow ; iBlankCol = iMouseCol ; aiPuzzle[iBlankRow][iBlankCol] = 0 ; // Invalidate rectangle WinInvalidateRect (hwnd, &rcl, FALSE) ; break ; case WM_CHAR: if (!(CHARMSG(&msg)->fs & KC_VIRTUALKEY) || CHARMSG(&msg)->fs & KC_KEYUP) return 0 ; // Mimic a WM_BUTTON1DOWN message iMouseCol = iBlankCol ; iMouseRow = iBlankRow ; switch (CHARMSG(&msg)->vkey) { case VK_LEFT: iMouseCol++ ; break ; case VK_RIGHT: iMouseCol-- ; break ; case VK_UP: iMouseRow-- ; break ; case VK_DOWN: iMouseRow++ ; break ; default: return 0 ; } WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (iMouseCol * cxSquare, iMouseRow * cySquare), NULL) ; return 0 ; case WM_COMMAND: switch (COMMANDMSG(&msg)->cmd) { // Initialize aiPuzzle array case IDM_NORMAL: case IDM_INVERT: for (iRow = 0 ; iRow < NUMROWS ; iRow++) for (iCol = 0 ; iCol < NUMCOLS ; iCol++) aiPuzzle[iRow][iCol] = iCol + 1 + NUMCOLS * (NUMROWS - iRow - 1) ; if (COMMANDMSG(&msg)->cmd == IDM_INVERT) { aiPuzzle[0][NUMCOLS-2] = NUMCOLS * NUMROWS - 2 ; aiPuzzle[0][NUMCOLS-3] = NUMCOLS * NUMROWS - 1 ; } aiPuzzle[iBlankRow = 0][iBlankCol = NUMCOLS - 1] = 0 ; WinInvalidateRect (hwnd, NULL, FALSE) ; return 0 ; // Randomly scramble the squares case IDM_SCRAMBLE: WinSetPointer (HWND_DESKTOP, WinQuerySysPointer ( HWND_DESKTOP, SPTR_WAIT, FALSE)) ; srand ((int) WinGetCurrentTime (0)) ; for (i = 0 ; i < SCRAMBLEREP ; i++) { WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (rand() % NUMCOLS * cxSquare, iBlankRow * cySquare), NULL) ; WinUpdateWindow (hwnd) ; WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (iBlankCol * cxSquare, rand() % NUMROWS * cySquare), NULL) ; WinUpdateWindow (hwnd) ; } WinSetPointer (HWND_DESKTOP, WinQuerySysPointer ( HWND_DESKTOP, SPTR_ARROW, FALSE)); return 0 ; } break ; } return WinDefWindowProc (hwnd, msg, mp1, mp2) ; }
/*---------------------------------------------------------------------------*/ void paintText( HPS hps,WINDOWINFO *pwi,POBJECT pObj,RECTL *prcl, int iMode ) { int iBreakCount, iSurplus ; PCHAR pStart, pEnd ; PCHAR pText; POINTL ptlStart, aptlTextBox [TXTBOX_COUNT] ; blocktext *pT; RECTL rclColumn; SIZEF sizfx; FIXED fxBreakExtra; int iLineBreak; int iLen; iSurplus = 0; pT = (blocktext *)pObj; if (iMode != MODE_PREPPRINTING) { if (pwi->usdrawlayer != pT->bt.usLayer) return; } /* ** Just in case the text starts with a linebreak... */ memset ((void *)aptlTextBox,0,( sizeof(POINTL) * TXTBOX_COUNT)); /* ** Get column rectangle of first column.. */ getColumnOutline(pT,&rclColumn,pwi,0,(BOOL)(iMode == MODE_PREPPRINTING)); pText = (PCHAR)pT->pszText; ptlStart.y = rclColumn.yTop ; if (!pText) return; if (prcl) { RECTL rclDest; /* ** prcl is only true for screen operations! ** For this moment we only check on the first column ** TODO !!! All columns */ if (!WinIntersectRect(hab,&rclDest,prcl,&rclColumn)) return; } if (iMode == MODE_PREPPRINTING) { sizfx.cx = pT->sizfx.fcx * pwi->usWidth; sizfx.cy = pT->sizfx.fcy * pwi->usHeight; } else { sizfx.cx = pT->sizfx.fcx * pwi->usFormWidth; sizfx.cy = pT->sizfx.fcy * pwi->usFormHeight; } setFont(pwi,&pT->fattrs,sizfx); if (iMode == MODE_PREPPRINTING) GpiQueryWidthTable(pwi->hps,0,MAX_NRWIDTH,pObj->lWidth); if (paintColumn(hps,pwi,pObj,rclColumn,iMode)) { rclColumn.xLeft += 20; rclColumn.yBottom += 20; rclColumn.xRight -= 20; rclColumn.yTop -= 20; } if (iMode != MODE_OUTLINE) GpiSetColor(hps,pT->bt.fColor); if (pwi->bPrinter) { /* ** Set the text on paper and get out!! */ PrintBlockText(pObj,pwi); return; } do // until end of text { iBreakCount = 0; fxBreakExtra = 0; iLineBreak = 0; while (*pText == ' ') // Skip over leading blanks pText++ ; pStart = pText ; do // until line is known { iLineBreak = 0; while (*pText == ' ') // Skip over leading blanks pText++ ; // Find next break point while (*pText != '\x00' && *pText != ' ' && *pText != '\r' && *pText != '\n') pText++ ; if (*pText == '\r'|| *pText == '\n') { pText++; iLineBreak = 1; if (*pText == '\n' || *pText == '\r') { pText++; iLineBreak = 2; } } /* ** A line with only a cariage return linefeed? */ if ( ((pText - pStart) - iLineBreak) <= 0) { pEnd = pText ; break; } // Determine text width GpiQueryTextBox (hps, (pText - pStart) - iLineBreak, pStart, TXTBOX_COUNT, aptlTextBox) ; // Normal case: text less wide than column if (aptlTextBox[TXTBOX_CONCAT].x < (rclColumn.xRight - rclColumn.xLeft)) { iBreakCount++ ; pEnd = pText; } // Text wider than window with only one word else if (iBreakCount == 0) { pEnd = pText ; break ; } // Text wider than window, so fix up and get out else { iBreakCount-- ; pText = pEnd ; /* ** Although we could have found a line break the ** text did not fit the line at all. So... */ iLineBreak = 0; break ; } } while (*pText != '\x00' && !iLineBreak) ; // Get the final text box iLen = (int)(pEnd - pStart); if (iLen - iLineBreak > 0) GpiQueryTextBox (hps, (pEnd - pStart)-iLineBreak, pStart, TXTBOX_COUNT, aptlTextBox) ; // Drop down by maximum ascender ptlStart.y -= aptlTextBox[TXTBOX_TOPLEFT].y ; // Find surplus space in text line iSurplus = rclColumn.xRight - rclColumn.xLeft - aptlTextBox[TXTBOX_CONCAT].x ; // Adjust starting position and // space and character spacing switch (pT->nAlign) { case ALIGN_LEFT: ptlStart.x = rclColumn.xLeft ; break ; case ALIGN_RIGHT: ptlStart.x = rclColumn.xLeft + iSurplus ; break ; case ALIGN_CENTER: ptlStart.x = rclColumn.xLeft + iSurplus / 2 ; break ; case ALIGN_JUST: ptlStart.x = rclColumn.xLeft ; if (*pText == '\x00') break ; if (iBreakCount > 0) { fxBreakExtra = 65536 * iSurplus / iBreakCount; GpiSetCharBreakExtra (hps,fxBreakExtra); } else if (pEnd - pStart - 1 > 0) { fxBreakExtra = 65536 * iSurplus / (pEnd - pStart - 1 - iLineBreak); GpiSetCharExtra (hps,fxBreakExtra); } break ; } // Drop down by maximum descender if (pT->nSpace != SPACE_NONE) ptlStart.y += aptlTextBox[TXTBOX_BOTTOMLEFT].y ; // Display the string & return to normal if ((pEnd - pStart)) GpiCharStringAt (hps, &ptlStart, (pEnd - pStart ) - iLineBreak, pStart) ; if (iMode == MODE_PREPPRINTING) { bTextMakePrintBlock(pObj, pwi, fxBreakExtra, iBreakCount, ptlStart, (LONG)((pEnd - pStart) -iLineBreak), pStart); } GpiSetCharExtra (hps, 0) ; GpiSetCharBreakExtra (hps, 0) ; // Do additional line-spacing switch (pT->nSpace) { case SPACE_HALF: ptlStart.y -= (aptlTextBox[TXTBOX_TOPLEFT].y - aptlTextBox[TXTBOX_BOTTOMLEFT].y) / 2 ; break ; case SPACE_DOUBLE: ptlStart.y -= aptlTextBox[TXTBOX_TOPLEFT].y - aptlTextBox[TXTBOX_BOTTOMLEFT].y ; break ; } } while (*pText != '\x00' && ptlStart.y > rclColumn.yBottom) ; }
static void draw_stuff( HWND hwnd ) { HPS win_dc; RECTL paint; RECTL intersect; #ifdef DRAW_ALL_AT_ONCE int old_top; int width, height; SIZEL sizl = { 0, 0 }; BITMAPINFOHEADER2 bmih; LONG formats[24]; POINTL pts[3]; LONG old_cursor; LONG hour_glass_cur; RECTL interior; DEVOPENSTRUC dop = { 0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L }; #endif win_dc = WinBeginPaint( hwnd, 0, &paint ); GpiCreateLogColorTable( win_dc, 0L, LCOLF_RGB, 0L, 0L, NULL ); #ifdef DRAW_ALL_AT_ONCE old_top = paint.yBottom; paint.yBottom = Draw_area.yTop; #endif WinFillRect( win_dc, &paint, SYSCLR_WINDOW ); #ifdef DRAW_ALL_AT_ONCE paint.yBottom = old_top; #endif if( WinIntersectRect( Main_hab, &intersect, &paint, &Draw_area ) ) { #ifdef DRAW_ALL_AT_ONCE width = Draw_area.xRight - Draw_area.xLeft; height = Draw_area.yTop - Draw_area.yBottom; interior.xLeft = 0; interior.yBottom = 0; interior.xRight = width; interior.yTop = height; if( Draw_bitmap == NULLHANDLE ) { Hdc = DevOpenDC( Main_hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE ); Mem_dc = GpiCreatePS( Main_hab, Hdc, &sizl, PU_PELS | GPIA_ASSOC ); memset( &bmih, 0, sizeof( BITMAPINFOHEADER2 ) ); GpiQueryDeviceBitmapFormats( Mem_dc, 24L, formats ); bmih.cbFix = sizeof( BITMAPINFOHEADER2 ); bmih.cx = width; bmih.cy = height; bmih.cPlanes = (USHORT) formats[0]; bmih.cBitCount = (USHORT) formats[1]; Draw_bitmap = GpiCreateBitmap( Mem_dc, &bmih, 0L, NULL, NULL ); Old_bitmap = GpiSetBitmap( Mem_dc, Draw_bitmap ); GpiCreateLogColorTable( Mem_dc, 0, LCOLF_RGB, 0, 0, NULL ); WinFillRect( Mem_dc, &interior, SYSCLR_WINDOW ); hour_glass_cur = WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE ); old_cursor = WinQueryPointer( HWND_DESKTOP ); WinSetPointer( HWND_DESKTOP, hour_glass_cur ); hThree_d = three_d_begin( Mem_dc, &interior ); draw_room(); three_d_draw( hThree_d ); three_d_end( hThree_d ); WinSetPointer( HWND_DESKTOP, old_cursor ); } pts[0].x = Draw_area.xLeft; pts[0].y = Draw_area.yBottom; pts[1].x = Draw_area.xLeft + width; pts[1].y = Draw_area.yBottom + height; pts[2].x = 0; pts[2].y = 0; GpiBitBlt( win_dc, Mem_dc, 3, pts, ROP_SRCCOPY, BBO_IGNORE ); #else hThree_d = three_d_begin( win_dc, &Draw_area ); draw_room(); three_d_draw( hThree_d ); three_d_end( hThree_d ); #endif } WinEndPaint( win_dc ); }