home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol04 / 01b / macsl / mpmcreat.c < prev    next >
C/C++ Source or Header  |  1988-10-03  |  13KB  |  439 lines

  1. /*-----------------------------------------------------------------*/
  2. /* MpmCreate.c                                                     */
  3. /* Window creation functions                                       */
  4. /*-----------------------------------------------------------------*/
  5.  
  6. #include "MacPM.h"
  7.  
  8. /*-----------------------------------------------------------------*/
  9.  
  10. HMYCLASS    _hFirstClass = NULL;
  11.  
  12. Rect    _rectAdjPlainDBox    = {  1, 1, -1, -1 };  /* wrong... */
  13. Rect    _rectAdjDocumentProc = { 19, 1, -2, -2 };
  14. Rect    _rectAdjDBoxProc     = {  5, 5, -5, -5 };  /* check this */
  15. Rect    _rectAdjAltDBoxProc  = {  1, 1, -3, -3 };  /* this too! */
  16.  
  17. /*-----------------------------------------------------------------*/
  18.  
  19. LOCAL HMYCLASS  MpmFindClass( PSZ pszName, USHORT usHash );
  20. LOCAL VOID      MpmFixName( PSZ* ppszName, PSZ pszBuf,
  21.                             PUSHORT pusHash );
  22.  
  23. /*-----------------------------------------------------------------*/
  24. /* Create a window.                                                */
  25. /*-----------------------------------------------------------------*/
  26.  
  27. HWND APIENTRY
  28. WinCreateWindow( hwndParent, pszClass,  pszName, flStyle,
  29.                  x, y, cx, cy, hwndOwner, hwndPrevSibling, id,
  30.                  pCtlData, pPresParams )
  31.     HWND        hwndParent, hwndOwner, hwndPrevSibling;
  32.     PSZ         pszClass, pszName;
  33.     ULONG       flStyle;
  34.     SHORT       x, y, cx, cy;
  35.     USHORT      id;
  36.     PVOID       pCtlData, pPresParams;
  37. {
  38.     HWND        hwnd, hwndNextSibling, hwndMac;
  39.     PMYWND      pwnd;
  40.     HMYCLASS    hClass;
  41.     PMYCLASS    pClass;
  42.     USHORT      usLen;
  43.     SHORT       sProcID;
  44.     Rect        rect, rectAdj;
  45.     WindowPeek  pwin, pwinBehind;
  46.     CHAR        szTitle[256];
  47.     BOOL        fGoAway, fFrameWindow;
  48.     UCHAR       ucKind;
  49.     USHORT      usHash;
  50.     CHAR        szClassBuf[10];
  51.     ULONG       flFrameFlags;
  52.  
  53.     /* Figure out which WK_ code to use */
  54.  
  55.     if( pszClass == WC_DESKTOP )
  56.       ucKind = WK_DESKTOP;
  57.     else
  58.     {
  59.       if( ! hwndParent  ||  hwndParent == HWND_DESKTOP )
  60.         hwndParent = _hwndDesktop;
  61.       if( hwndParent == _hwndDesktop )
  62.         ucKind = WK_MAIN;
  63.       else
  64.         ucKind = WK_CHILD;
  65.     }
  66.  
  67.     /* Fix up WC_ names, calculate hash, and find window class */
  68.  
  69.     MpmFixName( &pszClass, szClassBuf, &usHash );
  70.  
  71.     hClass = MpmFindClass( pszClass, usHash );
  72.     if( ! hClass )
  73.       return NULL;
  74.  
  75.     /* Grab frame flags if it's the window frame class */
  76.  
  77.     fFrameWindow = MpmIsFrameClass( pszClass );
  78.     flFrameFlags =
  79.       ( fFrameWindow && pCtlData ? *(PULONG)pCtlData : 0 );
  80.  
  81.     /* Allocate window structure */
  82.  
  83.     usLen = sizeof(MYWND) + (**hClass).class.cbWindowData;
  84.     hwnd = (HWND)MpmNewHandleZ( usLen );
  85.     if( ! hwnd )
  86.       return NULL;
  87.  
  88.     /* Handle WK_ specific stuff */
  89.  
  90.     switch( ucKind )
  91.     {
  92.       /* Desktop window: just set window position */
  93.  
  94.       case WK_DESKTOP:
  95.         SetRect( &rect, 0, 0, cx, cy );
  96.         SetRect( &rectAdj, 0, 0, 0, 0 );
  97.         break;
  98.  
  99.       /* Main Mac window: figure out which style of Mac window
  100.          to use and create it */
  101.  
  102.       case WK_MAIN:
  103.         fGoAway = FALSE;
  104.         if( ! ( flStyle & FS_BORDER )  &&
  105.             ! ( flFrameFlags & FCF_DOCBITS ) )
  106.         {
  107.           sProcID = plainDBox;  /* shouldn't have border! */
  108.           rectAdj = _rectAdjPlainDBox;
  109.         }
  110.         else if( flFrameFlags & FCF_DOCBITS )
  111.         {
  112.           sProcID = documentProc;
  113.           rectAdj = _rectAdjDocumentProc;
  114.           if( flFrameFlags & FCF_MAXBUTTON )
  115.             sProcID += 8;
  116.           if( flFrameFlags & FCF_SYSMENU )
  117.             fGoAway = TRUE;
  118.         }
  119.         else if( flStyle & FS_DLGBORDER )
  120.         {
  121.           sProcID = dBoxProc;
  122.           rectAdj = _rectAdjDBoxProc;
  123.         }
  124.         else
  125.         {
  126.           sProcID = altDBoxProc;
  127.           rectAdj = _rectAdjAltDBoxProc;
  128.         }
  129.  
  130.         rect.left   = rectAdj.left   + x;
  131.         rect.right  = rectAdj.right  + x + cx;
  132.         rect.top    = rectAdj.top    + rect.bottom - cy;
  133.         rect.bottom = rectAdj.bottom + screenBits.bounds.bottom - y;
  134.     
  135.         /* Should check rect for out of screen boundaries! */
  136.     
  137.         strncpy( szTitle, pszName, 255 );
  138.         szTitle[255] = '\0';
  139.     
  140.         if( hwndPrevSibling == HWND_TOP )
  141.           pwinBehind = (WindowPeek)(-1);
  142.         else if( hwndPrevSibling == HWND_BOTTOM )
  143.           pwinBehind = (WindowPeek)NULL;
  144.         else if( ISMAINWINDOW(hwndPrevSibling) )
  145.           pwinBehind = PWINOFHWND(hwndPrevSibling);
  146.         else
  147.           ERROR( "WinCreateWindow: Invalid hwndPrevSibling" );
  148.     
  149.         pwin = 
  150.           (WindowPeek)NewWindow( NULL, &rect, CtoPstr(szTitle),
  151.                                  FALSE, sProcID, pwinBehind,
  152.                                  fGoAway, (LONG)hwnd );
  153.         if( ! pwin )
  154.         {
  155.           DisposHandle( (Handle)hwnd );
  156.           return NULL;
  157.         }
  158.         PWINOFHWND(hwnd) = pwin;
  159.  
  160.         break;
  161.  
  162.       /* Child window: set up all the "kin" windows */
  163.  
  164.       case WK_CHILD:
  165.         if( hwndPrevSibling == HWND_TOP )
  166.         {
  167.           MYWNDOF(hwnd).hwndNextSibling = hwndNextSibling =
  168.             MYWNDOF(hwndParent).hwndTopChild;
  169.           MYWNDOF(hwndNextSibling).hwndPrevSibling = hwnd;
  170.           MYWNDOF(hwndParent).hwndTopChild = hwnd;
  171.         }
  172.         else if( hwndPrevSibling == HWND_BOTTOM )
  173.         {
  174.           MYWNDOF(hwnd).hwndPrevSibling = hwndPrevSibling =
  175.             MYWNDOF(hwndParent).hwndBottomChild;
  176.           MYWNDOF(hwndPrevSibling).hwndNextSibling = hwnd;
  177.           MYWNDOF(hwndParent).hwndBottomChild = hwnd;
  178.         }
  179.         else
  180.         {
  181.           if( ! MpmValidateWindow(hwndPrevSibling) )
  182.             return NULL;
  183.           if( MYWNDOF(hwndPrevSibling).hwndParent != hwndParent )
  184.             return NULL;
  185.           MYWNDOF(hwnd).hwndNextSibling = hwndNextSibling =
  186.             MYWNDOF(hwndPrevSibling).hwndNextSibling;
  187.           MYWNDOF(hwnd).hwndPrevSibling = hwndPrevSibling;
  188.           MYWNDOF(hwndPrevSibling).hwndNextSibling = hwnd;
  189.           if( hwndNextSibling )
  190.             MYWNDOF(hwndNextSibling).hwndPrevSibling = hwnd;
  191.           else
  192.             MYWNDOF(hwndParent).hwndBottomChild = hwnd;
  193.         }
  194.         if( ! MYWNDOF(hwndParent).hwndTopChild )
  195.           MYWNDOF(hwndParent).hwndTopChild = hwnd;
  196.         if( ! MYWNDOF(hwndParent).hwndBottomChild )
  197.           MYWNDOF(hwndParent).hwndBottomChild = hwnd;
  198.         for( hwndMac = hwndParent;
  199.              ISCHILDWINDOW(hwndMac);
  200.              hwndMac = MYWNDOF(hwndMac).hwndParent );
  201.         PWINOFHWND(hwnd) = PWINOFHWND(hwndMac);
  202.         rectAdj = MYWNDOF(hwndMac).rectAdj;
  203.         break;
  204.     }
  205.  
  206.     /* Fill in the window structure fields */
  207.  
  208.     pClass = *hClass;
  209.     pwnd = PMYWNDOF(hwnd);
  210.  
  211.     pwnd->signature = WND_SIGNATURE;
  212.     pwnd->ucKind = ucKind;
  213.     pwnd->pfnwp = pClass->class.pfnWindowProc;
  214.     pwnd->hclass = hClass;
  215.     pwnd->flStyle =
  216.       ( flStyle & ~WS_VISIBLE ) |
  217.       ( pClass->class.flClassStyle & CLASSWINDOWBITS );
  218.     pwnd->hwndOwner = hwndOwner;
  219.     pwnd->hwndParent = hwndParent;
  220.     pwnd->id = id;
  221.     pwnd->rectAdj = rectAdj;
  222.     pwnd->flFrameFlags = flFrameFlags;
  223.  
  224.     /* Now the window is here for real, so send the WM_CREATE */
  225.  
  226.     if( WinSendMsg( hwnd, WM_CREATE,
  227.                     MPFROMP(pCtlData), MPFROMP(&hwndParent) ) )
  228.     {
  229.       WinDestroyWindow( hwnd );
  230.       return NULL;
  231.     }
  232.  
  233.     /* Send the WM_ADJUSTWINDOWPOS if it's not the desktop window
  234.        and it has a nonzero size */
  235.  
  236.     if( cx  &&  cy  &&  ucKind != WK_DESKTOP )
  237.       WinSetWindowPos( hwnd, NULL, x, y, cx, cy, SWP_MOVE | SWP_SIZE );
  238.  
  239.     /* Make the window visible if it's supposed to be visible */
  240.  
  241.     if( flStyle & WS_VISIBLE )
  242.       WinShowWindow( hwnd, TRUE );
  243.  
  244.     return hwnd;
  245. }
  246.  
  247. /*-----------------------------------------------------------------*/
  248. /* Destroy a window.                                               */
  249. /*-----------------------------------------------------------------*/
  250.  
  251. BOOL APIENTRY WinDestroyWindow( hwnd )
  252.     HWND        hwnd;
  253. {
  254.     HWND        hwndChild, hwndNextSibling, hwndPrevSibling;
  255.     PMYWND      pwnd, pwndParent;
  256.  
  257.     if( ! MpmValidateWindow(hwnd) )
  258.       return FALSE;
  259.  
  260.     /* Hide the window if it's visible */
  261.  
  262.     if( MYWNDOF(hwnd).flStyle & WS_VISIBLE )
  263.       WinShowWindow( hwnd, FALSE );
  264.  
  265.     /* Destroy all children */
  266.  
  267.     while( hwndChild = MYWNDOF(hwnd).hwndTopChild )
  268.       WinDestroyWindow( hwndChild );
  269.  
  270.     /* Let the window know it's being destroyed */
  271.  
  272.     WinSendMsg( hwnd, WM_DESTROY, 0L, 0L );
  273.  
  274.     /* For top level windows, destroy the Mac window; for
  275.        child windows, clean up the "kin" pointers */
  276.  
  277.     if( ISMAINWINDOW(hwnd) )
  278.     {
  279.       DisposeWindow( PWINOFHWND(hwnd) );
  280.     }
  281.     else if( ISCHILDWINDOW(hwnd) )
  282.     {
  283.       pwnd            = PMYWNDOF( hwnd );
  284.       pwndParent      = PMYWNDOF( pwnd->hwndParent );
  285.       hwndNextSibling = pwnd->hwndNextSibling;
  286.       hwndPrevSibling = pwnd->hwndPrevSibling;
  287.  
  288.       if( pwndParent->hwndTopChild == hwnd )
  289.         pwndParent->hwndTopChild = hwndNextSibling;
  290.  
  291.       if( pwndParent->hwndBottomChild == hwnd )
  292.         pwndParent->hwndBottomChild = hwndPrevSibling;
  293.  
  294.       if( hwndNextSibling )
  295.         MYWNDOF(hwndNextSibling).hwndPrevSibling = hwndPrevSibling;
  296.  
  297.       if( hwndPrevSibling )
  298.         MYWNDOF(hwndPrevSibling).hwndNextSibling = hwndNextSibling;
  299.     }
  300.     else
  301.       ERROR( "WinDestroyWindow: Cannot destroy desktop window." );
  302.  
  303.     /* All done, free up the window structure */
  304.  
  305.     DisposHandle( (Handle)hwnd );
  306.  
  307.     return TRUE;
  308. }
  309.  
  310. /*-----------------------------------------------------------------*/
  311. /* Get the window class information for a class name               */
  312. /*-----------------------------------------------------------------*/
  313.  
  314. BOOL APIENTRY WinQueryClassInfo( hab, pszClassName, pClassInfo )
  315.     HAB         hab;
  316.     PSZ         pszClassName;
  317.     PCLASSINFO  pClassInfo;
  318. {
  319.     HMYCLASS    hClass;
  320.     CHAR        szClassBuf[10];
  321.     USHORT      usHash;
  322.  
  323.     /* Fix up WC_ names and calculate hash */
  324.  
  325.     MpmFixName( &pszClassName, szClassBuf, &usHash );
  326.  
  327.     /* Find the class info and copy it back */
  328.  
  329.     hClass = MpmFindClass( pszClassName, usHash );
  330.     if( ! hClass )
  331.       return FALSE;
  332.  
  333.     *pClassInfo = (**hClass).class;
  334.  
  335.     return TRUE;
  336. }
  337.  
  338. /*-----------------------------------------------------------------*/
  339. /* Register a window class.                                        */
  340. /*-----------------------------------------------------------------*/
  341.  
  342. BOOL APIENTRY
  343. WinRegisterClass( hab, pszClassName, pfnwp,
  344.                     flStyle, cbWindowData )
  345.     HAB         hab;
  346.     PSZ         pszClassName;
  347.     PFNWP       pfnwp;
  348.     ULONG       flStyle;
  349.     USHORT      cbWindowData;
  350. {
  351.     HMYCLASS    hClass;
  352.     PMYCLASS    pClass;
  353.     CHAR        szClassBuf[10];
  354.     USHORT      usHash;
  355.  
  356.     /* Fix up WC_ names and calculate hash */
  357.  
  358.     MpmFixName( &pszClassName, szClassBuf, &usHash );
  359.  
  360.     /* Make sure the class doesn't already exist */
  361.  
  362.     if( MpmFindClass( pszClassName, usHash ) )
  363.       return FALSE;
  364.  
  365.     /* Allocate the class structure and fill it in */
  366.  
  367.     hClass =
  368.       (HMYCLASS)MpmNewHandleZ( sizeof(MYCLASS) +
  369.                                strlen(pszClassName) );
  370.     if( ! hClass )
  371.       return FALSE;
  372.  
  373.     pClass = *hClass;
  374.     
  375.     pClass->usHash = usHash;
  376.     pClass->class.flClassStyle = flStyle;
  377.     pClass->class.pfnWindowProc = pfnwp;
  378.     pClass->class.cbWindowData = cbWindowData;
  379.     strcpy( pClass->szName, pszClassName );
  380.  
  381.     /* Link the class into the class chain */
  382.  
  383.     pClass->hNextClass = _hFirstClass;
  384.     _hFirstClass = hClass;
  385.  
  386.     return TRUE;
  387. }
  388.  
  389. /*-----------------------------------------------------------------*/
  390. /* Find the MYCLASS structure for a class name                     */
  391. /*-----------------------------------------------------------------*/
  392.  
  393. LOCAL HMYCLASS MpmFindClass( pszClassName, usHash )
  394.     PSZ         pszClassName;
  395.     USHORT      usHash;
  396. {
  397.     HMYCLASS    hClass;
  398.  
  399.     for( hClass = _hFirstClass;
  400.          hClass;
  401.          hClass = (**hClass).hNextClass )
  402.       if( usHash == (**hClass).usHash  &&
  403.           strcmp( pszClassName, (**hClass).szName ) == 0 )
  404.         return hClass;
  405.  
  406.     return NULL;
  407. }
  408.  
  409. /*-----------------------------------------------------------------*/
  410. /* Fix up the special WC_ class "names" and calculate the hash     */
  411. /* value for a class name.                                         */
  412. /*-----------------------------------------------------------------*/
  413.  
  414. LOCAL VOID MpmFixName( ppszName, pszBuf, pusHash )
  415.     PSZ*        ppszName;
  416.     PSZ         pszBuf;
  417.     PUSHORT     pusHash;
  418. {
  419.     PSZ         pszName;
  420.     USHORT      usHash;
  421.  
  422.     pszName = *ppszName;
  423.  
  424.     if( HIUSHORT(pszName) == 0xFFFF )
  425.     {
  426.       sprintf( pszBuf, "#%u", LOUSHORT(pszName) );
  427.       pszName = pszBuf;
  428.     }
  429.  
  430.     *ppszName = pszName;
  431.  
  432.     for( usHash = 0;  *pszName;  pszName++ )
  433.       usHash = (usHash << 1) ^ *pszName;
  434.  
  435.     *pusHash = usHash;
  436. }
  437.  
  438. /*-----------------------------------------------------------------*/
  439.