home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************\
- * ARRANGE.c - This file contains code to do window arrangment.
- *
- * Created by Microsoft Corporation, 1989
- \***************************************************************************/
-
- #define INCL_WINSYS
- #define INCL_WINCOMMON
- #define INCL_WINMESSAGEMGR
- #define INCL_WINPOINTERS
- #define INCL_WININPUT
- #define INCL_WINMENUS
- #define INCL_WINFRAMEMGR
- #define INCL_WINWINDOWMGR
- #define INCL_WINRECTANGLES
- #define INCL_WINHEAP
- #include <os2.h>
- #include "app.h"
- #include "appdata.h"
- #include "mdi.h"
- #include "mdidata.h"
-
-
- #define MINMAXFIX /* add hack to keep the min/max icons in sync with reality */
-
- /* internal function prototypes */
- BOOL SetTilePositions(PRECTL prc, SHORT cWnd, PSWP aswp);
- SHORT CeilSquareRoot(USHORT us);
- BOOL SetCascadePositions(PRECTL prc, SHORT cWnd, PSWP aswp);
- BOOL SetCascadeParams(PRECTL prc, SHORT *pxEdge, SHORT *pyEdge,
- SHORT *pxDelta, SHORT *pyDelta, SHORT *cMaxWnd);
- BOOL GetArrangeSwp(USHORT *, SWP *, USHORT *, SWP *);
- BOOL GetArrangeRectangle(PRECTL, BOOL);
- BOOL ArrangeIconPositions(USHORT, PSWP);
-
- /* internal constants */
- #define CASC_EDGE_NUM 2
- #define CASC_EDGE_DENOM 3
-
- /* local constants */
- #define ICON_PARK_NUM 5
- #define ICON_PARK_DENOM 3
- #define CLASS_NAME_LENGTH 8
-
- /***************************************************************************\
- * ArrangeWindowPositions
- *
- * This function sets positions for arranging windows nicely in a rectangle.
- * The hwnd field of each SWP structure should be set by the user, either
- * before or after calling this function. The function sets all other
- * fields. The SWP array can then be passed to WinSetMultWindowPos() to do
- * the physical arrangement. There are two arrangement styles available,
- * AWP_TILED and AWP_CASCADED.
- *
- * AWP_TILED:
- *
- * The tiles are generated by rows, top left (first) to bottom right (last).
- * Each row has the same number of tiles. The number of tiles in each
- * column will differ by at most one, with each column containing one fewer
- * tile to the left of the other columns.
- *
- * AWP_CASCADED:
- *
- * The windows are generated bottom right (first) to top left (last).
- *
- * Parameters:
- * prc: rectangle to contain the tiled windows
- * cWnd: number of windows to tile
- * aswp: array of SWP structures, one for each tile window
- * fStyle: the style to arrange the windows
- \***************************************************************************/
-
- BOOL ArrangeWindowPositions(PRECTL prc, SHORT cWnd, PSWP aswp, USHORT fStyle)
- {
- /* check validity of input rectangle */
- if ((prc->xRight - prc->xLeft < 1) || (prc->yTop - prc->yBottom < 1)) {
- return FALSE;
- }
-
- /* set window positions */
- switch (fStyle) {
- case AWP_TILED:
- return SetTilePositions(prc, cWnd, aswp);
- case AWP_CASCADED:
- return SetCascadePositions(prc, cWnd, aswp);
- default:
- return FALSE;
- }
- }
-
-
- /***************************************************************************\
- * SetTilePositions
- *
- * This function sets positions for tiling windows in a rectangle.
- *
- * NOTE:
- * There are a few subtleties to this code:
- *
- * The algorithm lays tiles in a modified NxN grid. It can be shown
- * that any positive number of tiles can be laid out in such a grid of
- * N columns so that each column has at least N-2 tiles and no column
- * has more than one tile more than any other. Proof left to the
- * interested reader.
- *
- * The tiles coordinates are not generated by stepping over a fixed
- * interval since this will not usually fill the rectangle completely.
- * Thus the offset at each step is calculated from the previous tile
- * to the correct fractional position within the whole rectangle.
- *
- * Since the last "row" of tiles may not have any members in the beginning
- * columns, these tiles are addressed differently in the SWP array to
- * account for the "missing" tiles.
- *
- * Parameters:
- * prc: rectangle to contain the tiled windows
- * cWnd: number of windows to tile the rectangle with
- * aswp: array of SWP structures, one for each tile window
- \***************************************************************************/
-
- BOOL SetTilePositions(PRECTL prc, SHORT cWnd, PSWP aswp)
- {
- register SHORT usRoot;
- register SHORT cExtras;
- SHORT iChange;
- SHORT cDiff;
- SHORT x, y, cx, cy;
- SHORT iRow, iCol;
-
- /* get grid dimensions */
- usRoot = CeilSquareRoot(cWnd);
- cExtras = usRoot * usRoot - cWnd;
-
- /* find column where number of rows increases and find initial
- difference of rows versus columns */
- if (cExtras >= usRoot) {
- iChange = cExtras - usRoot;
- cDiff = 2;
- } else {
- iChange = cExtras;
- cDiff = 1;
- }
-
- /* assign x coordinates */
- x = (SHORT)prc->xLeft;
- cx = 0;
- for (iCol = 0; iCol < usRoot; iCol++) {
- x += cx - cxBorder;
- cx = ((SHORT)prc->xLeft) +
- (((SHORT)(prc->xRight - prc->xLeft)) * (iCol + 1)) / usRoot -
- x + cxBorder;
- for (iRow = 0; iRow < usRoot - cDiff; iRow++) {
- aswp[iRow * usRoot + iCol].x = x;
- aswp[iRow * usRoot + iCol].cx = cx;
- aswp[iRow * usRoot + iCol].fs = SWP_SIZE | SWP_MOVE;
- }
- /* assign "extra" row */
- if (iCol >= iChange) {
- aswp[iRow * usRoot + iCol - iChange].x = x;
- aswp[iRow * usRoot + iCol - iChange].cx = cx;
- aswp[iRow * usRoot + iCol - iChange].fs = SWP_SIZE | SWP_MOVE;
- }
- }
-
- /* assign y coordinates, columns without extra row */
- y = (SHORT)prc->yBottom;
- cy = 0;
- for (iRow = usRoot - cDiff - 1; iRow >= 0; iRow--) {
- y += cy - cyBorder;
- cy = ((SHORT)prc->yBottom) +
- (((SHORT)(prc->yTop - prc->yBottom)) * (usRoot - cDiff - iRow)) /
- (usRoot - cDiff) - y + cyBorder;
- for (iCol = 0; iCol < iChange; iCol++) {
- aswp[iRow * usRoot + iCol].y = y;
- aswp[iRow * usRoot + iCol].cy = cy;
- }
- }
-
- /* assign y coordinates, columns with extra row */
- /* do last row first (different offsets) */
- y = (SHORT)prc->yBottom - cyBorder;
- cy = ((SHORT)(prc->yTop - prc->yBottom)) / (usRoot - cDiff + 1) +
- 2 * cyBorder;
- for (iCol = iChange; iCol < usRoot; iCol++) {
- aswp[usRoot * (usRoot - cDiff) + iCol - iChange].y = y;
- aswp[usRoot * (usRoot - cDiff) + iCol - iChange].cy = cy;
- }
- for (iRow = usRoot - cDiff - 1; iRow >= 0; iRow--) {
- y += cy - cyBorder;
- cy = ((SHORT)(prc->yBottom)) +
- (((SHORT)(prc->yTop - prc->yBottom)) * (usRoot - cDiff - iRow + 1))
- / (usRoot - cDiff + 1) - y + cyBorder;
- for (iCol = iChange; iCol < usRoot; iCol++) {
- aswp[iRow * usRoot + iCol].y = y;
- aswp[iRow * usRoot + iCol].cy = cy;
- }
- }
-
- return TRUE;
- }
-
-
- /***************************************************************************\
- * CeilSquareRoot
- *
- * This function returns the smallest integer greater or equal to the square
- * root of an unsigned 16 bit integer.
- *
- * Parameter:
- * us: value to take the root of
- \***************************************************************************/
-
- SHORT CeilSquareRoot(register USHORT us)
- {
- register SHORT i;
-
- /* prevent overflow of large numbers */
- if (us > 0xFE * 0xFE)
- return 0xFF;
-
- /* iterate up past root */
- for (i = 0; i*i < (SHORT) us; i++)
- ;
- return i;
- }
-
-
- /***************************************************************************\
- * SetCascadePositions
- *
- * This function sets positions for cascading windows in a rectangle.
- *
- * Parameters:
- * prc: rectangle to contain the cascaded windows
- * cWnd: number of windows to cascade
- * aswp: array of SWP structures, one for each cascaded window
- \***************************************************************************/
-
- BOOL SetCascadePositions(PRECTL prc, SHORT cWnd, PSWP aswp)
- {
- SHORT xEdge, yEdge;
- SHORT xDelta, yDelta;
- SHORT cMaxWnd;
- register SHORT x, y;
- SHORT i, j;
- RECTL rc;
-
- /* set cascade parameters */
- rc.xLeft = prc->xLeft - cxBorder;
- rc.xRight = prc->xRight + cyBorder;
- rc.yBottom = prc->yBottom - cyBorder;
- rc.yTop = prc->yTop + cyBorder;
- if (!SetCascadeParams((PRECTL)&rc, &xEdge, &yEdge, &xDelta, &yDelta,
- &cMaxWnd)) {
- return FALSE;
- }
-
- if (cWnd <= cMaxWnd) {
- /* only one run needed; move to top left corner */
- x = (SHORT)rc. xLeft;
- y = (SHORT)rc. yTop - yEdge;
- for (i = cWnd - 1; i >= 0; i--) {
- aswp[i].x = x;
- aswp[i].y = y;
- aswp[i].cx = xEdge;
- aswp[i].cy = yEdge;
- aswp[i].fs = SWP_SIZE | SWP_MOVE;
- x += xDelta;
- y -= yDelta;
- }
-
- } else {
-
- /* multiple runs necessary; start at bottom right, iterate up to
- top left */
-
- i = 0;
-
- while (i < cWnd) {
-
- /* even run */
- x = ((SHORT)rc. xLeft) + (cMaxWnd-1) * xDelta;
- y = ((SHORT)rc. yTop) - yEdge - (cMaxWnd-1) * yDelta;
- for (j = 0; j < cMaxWnd; j++) {
- aswp[i].x = x;
- aswp[i].y = y;
- aswp[i].cx = xEdge;
- aswp[i].cy = yEdge;
- aswp[i].fs = SWP_SIZE | SWP_MOVE;
- x -= xDelta;
- y += yDelta;
- if (++i >= cWnd)
- break;
- }
-
- if (i >= cWnd)
- break;
-
- /* odd run, offset by half delta y, one and one half delta x */
- x = ((SHORT)rc. xLeft) + (cMaxWnd-1) * xDelta + xDelta/2;
- y = ((SHORT)rc. yTop) - yEdge - (cMaxWnd-1) * yDelta + yDelta/2;
- for (j = 0; j < cMaxWnd - 1; j++) {
- aswp[i].x = x;
- aswp[i].y = y;
- aswp[i].cx = xEdge;
- aswp[i].cy = yEdge;
- aswp[i].fs = SWP_SIZE | SWP_MOVE;
- x -= xDelta;
- y += yDelta;
- if (++i >= cWnd)
- break;
- }
- }
- }
-
- return TRUE;
- }
-
-
- /***************************************************************************\
- * SetCascadeParams
- *
- * This function sets parameters for cascading windows. The window edges
- * are based on a fraction CASC_EDGE_NUM/CASC_EDGE_DENOM of the rectangle.
- * The x delta is four system font characters across, the y delta is two
- * system lines high.
- *
- * Parameters:
- * prc: rectangle to contain the windows
- * pxEdge: width of the cascaded windows
- * pyEdge: height of the cascaded windows
- * pxDelta: x cascade offset
- * pyDelta: y cascade offset
- * pcMaxWnd: maximum number of windows in a cascade
- \***************************************************************************/
-
- BOOL SetCascadeParams(PRECTL prc, SHORT *pxEdge, SHORT *pyEdge, SHORT *pxDelta,
- SHORT *pyDelta, SHORT *pcMaxWnd)
- {
- register SHORT xEdge, yEdge;
- SHORT xDelta, yDelta;
- SHORT cMaxWnd;
-
- /* get x and y deltas from system values */
- xDelta = LOUSHORT(WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER)) +
- LOUSHORT(WinQuerySysValue(HWND_DESKTOP, SV_CXMINMAXBUTTON)) / 2 + 2;
- yDelta = LOUSHORT(WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER)) +
- LOUSHORT(WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR))
- - cyBorder;
-
- /* get initial cut at yEdge using fraction */
- yEdge = (((SHORT)(prc->yTop - prc->yBottom)) * CASC_EDGE_NUM) /
- CASC_EDGE_DENOM;
-
- /* determine maximum number of deltas used per run */
- cMaxWnd = (((SHORT)(prc->yTop - prc->yBottom)) - yEdge) / yDelta;
-
- /* set x and y edges so full cascade will fill rectangle completely */
- xEdge = ((SHORT)(prc->xRight - prc->xLeft)) - xDelta/2 - cMaxWnd * xDelta;
- yEdge = ((SHORT)(prc->yTop - prc->yBottom)) - cMaxWnd * yDelta;
-
- /* check that values are reasonable */
- if (cMaxWnd < 1 || xEdge < 1 || yEdge < 1) {
- return FALSE;
- }
-
- *pxEdge = xEdge;
- *pyEdge = yEdge;
- *pxDelta = xDelta;
- *pyDelta = yDelta;
- /* return cMaxWnd as the maximum number of windows in a cascade */
- *pcMaxWnd = cMaxWnd + 1;
-
- return TRUE;
- }
-
-
- /***************************************************************************\
- * ArrangeWindows
- *
- * This function arranges application document windows.
- *
- * Returns:
- * TRUE if successful
- * FALSE otherwise
- \***************************************************************************/
-
- BOOL ArrangeWindows(USHORT fStyle)
- {
- USHORT cswpWnd, cswpIcon;
- RECTL rcl;
- register BOOL fReturn = FALSE;
- SWP NEAR *npswpWnd;
- SWP NEAR *npswpIcon;
-
- npswpWnd = (SWP NEAR *) WinAllocMem(hHeap, sizeof(SWP) * cDocs);
- npswpIcon = (SWP NEAR *) WinAllocMem(hHeap, sizeof(SWP) * cDocs);
-
- GetArrangeSwp(&cswpWnd, npswpWnd, &cswpIcon, npswpIcon);
-
- GetArrangeRectangle((PRECTL)&rcl, (BOOL)cswpIcon);
-
- /* set window positions */
- if (!ArrangeWindowPositions((PRECTL)&rcl, cswpWnd, (PSWP)npswpWnd, fStyle) ||
- !ArrangeIconPositions(cswpIcon, (PSWP)npswpIcon)) {
- goto ARRANGE_CLEANUP;
- }
-
- #if 1
- /* rearrange the windows */
- WinSetMultWindowPos(NULL, (PSWP)npswpWnd, cswpWnd);
- WinSetMultWindowPos(NULL, (PSWP)npswpIcon, cswpIcon);
- #endif
- fReturn = TRUE;
-
- ARRANGE_CLEANUP:
- WinFreeMem(hHeap, (NPBYTE)npswpWnd, sizeof(SWP) * cDocs);
- WinFreeMem(hHeap, (NPBYTE)npswpIcon, sizeof(SWP) * cDocs);
-
- return fReturn;
- }
-
- /***************************************************************************\
- * GetArrangeHandles
- *
- * This function generates the handles of all windows to be arranged and
- * creates an array of SWP structures containing those handles. Minimized
- * and non-minimized windows are separated. Non-frame, invisible and
- * non-sizeable windows are ignored.
- *
- * Parameter:
- * npcswpWnd: number of nonminimized windows found
- * npswpWnd: array of SWP structures for nonminimized windows
- * npcswpIcon: number of minimized windows found
- * npswpIcon: array of SWP structures for minimized windows
- *
- * Returns:
- * TRUE if successful
- * FALSE otherwise
- \***************************************************************************/
-
- BOOL GetArrangeSwp(USHORT *npcswpWnd, SWP *npswpWnd, USHORT *npcswpIcon,
- SWP *npswpIcon)
- {
- register USHORT cWnd, cIcon;
- ULONG ulStyle;
- HWND hwnd;
- register NPDOC npdoc;
-
- cWnd = 0;
- cIcon = 0;
-
- /* enumerate windows and selectively add them to the arrange lists */
- for (hwnd = WinQueryWindow(hwndMDI, QW_TOP, FALSE);
- hwnd;
- hwnd = WinQueryWindow(hwnd, QW_NEXT, FALSE)) {
-
- /* make sure the window is visible and owned by the app client window */
- ulStyle = WinQueryWindowULong(hwnd, QWL_STYLE);
- if (WinQueryWindow(hwnd, QW_OWNER, FALSE) ||
- !(ulStyle & WS_VISIBLE)) {
- continue;
- }
-
- if (ulStyle & WS_MINIMIZED) {
- npswpIcon->hwnd = hwnd;
- npswpIcon++;
- cIcon++;
- } else {
- /* restore maximized windows */
- if (ulStyle & WS_MAXIMIZED) {
-
- #ifdef MINMAXFIX
- /* Bring the min/max buttons back to life for a moment so
- they stay in sync when the window is restored. Then put
- them back to the object window 07-Sep-1989 johnba
- */
-
- npdoc = NPDOCFROMCLIENT(WinWindowFromID(hwnd,FID_CLIENT));
- WinSetParent(npdoc->hwndMinmax, hwnd, FALSE);
- #endif
- WinSetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_RESTORE );
- #ifdef MINMAXFIX
-
-
- if (hwndActiveDoc != hwnd) {
- WinSetParent(npdoc->hwndMinmax, HWND_OBJECT, FALSE);
- WinSendMsg(hwnd, WM_UPDATEFRAME, 0L, 0L);
- }
- #endif
- }
- npswpWnd->hwnd = hwnd;
- npswpWnd++;
- cWnd++;
- }
- }
-
- *npcswpWnd = cWnd;
- *npcswpIcon = cIcon;
- return TRUE;
- }
-
-
- /***************************************************************************\
- * GetArrangeRectangle
- *
- * This function determines the area in which task windows are arranged.
- *
- * Parameter:
- * prc: the generated area rectangle
- * fIconPark: specifies if room should be made for icon parking lot
- *
- * Returns:
- * TRUE if successful
- * FALSE otherwise
- \***************************************************************************/
-
- BOOL GetArrangeRectangle(PRECTL prc, BOOL fIconPark)
- {
- register USHORT yIcon;
- register SHORT cxBorderInset;
-
- /* get dimensions of desktop window */
- WinQueryWindowRect(hwndMDI, prc);
-
- cxBorderInset = (SHORT)(WinQuerySysValue(HWND_DESKTOP, SV_CXBYTEALIGN) -
- WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER));
- WinInflateRect(NULL, prc, -cxBorderInset, -cxBorderInset *
- (cyBorder / cxBorder));
-
- if (fIconPark) {
- /* make room for single row of icon carpark */
- yIcon = LOUSHORT(WinQuerySysValue(HWND_DESKTOP, SV_CYICON));
- prc->yBottom += (yIcon * ICON_PARK_NUM) / ICON_PARK_DENOM;
- }
-
- return TRUE;
- }
-
- /***************************************************************************\
- * ArrangeIconPositions
- *
- * This function sets positions for minimized windows.
- *
- * Parameters:
- * cIcon: number of icons to position
- * aswp: array of SetWindowPos structures for those icons
- *
- * Returns:
- * TRUE if successful
- * FALSE otherwise
- \***************************************************************************/
-
- BOOL ArrangeIconPositions(USHORT cIcon, PSWP aswpIcon)
- {
- register USHORT i;
-
- for (i = 0; i < cIcon; i++) {
- aswpIcon[i].x = 0;
- aswpIcon[i].y = 0;
- aswpIcon[i].fs = SWP_MOVE;
- }
-
- return TRUE;
- }
-