wm.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:44k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/GUI
  4. *                        Universal graphic software for embedded applications
  5. *
  6. *                       (c) Copyright 2002, Micrium Inc., Weston, FL
  7. *                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
  8. *
  9. *              礐/GUI is protected by international copyright laws. Knowledge of the
  10. *              source code may not be used to write a similar product. This file may
  11. *              only be used in accordance with a license and should not be redistributed
  12. *              in any way. We appreciate your understanding and fairness.
  13. *
  14. ----------------------------------------------------------------------
  15. File        : WM.C
  16. Purpose     : Windows manager core
  17. ----------------------------------------------------------------------
  18. Version-Date---Author-Explanation
  19. ----------------------------------------------------------------------
  20. 3.00a   010621 RS     a) module accelerated by skipping parameter
  21.                          to FindNext_IVR
  22. 3.00    010502 RS     a) WM module split up for library applications
  23.                       b) Module dramatically accelerated (without
  24.                          changes in the routine structure)
  25. 1.18    000909 RS     a) WM_CreateBWin does not activate the
  26.                          new window unless specified via create flags
  27. 1.16a   000724 RS     a) Function WM_EnableMemdevRead added
  28. 1.16    000614 RS     a) Cleanup
  29.                       b) Counter for invalid windows and
  30.                          WM_GetNumInvalidWindows() added
  31. 1.14g   000522 RS     a) WM_ExecAll added
  32. 1.14f   000316 RS     a) Internal Create routine created in order to
  33.                          handle creation of regular windows and
  34.                          objects seperately (and correctly) in all
  35.                          cases (by avoiding casts)
  36. 1.14e   000307 RS     a) WM_MoveTo added
  37. 1.14d   000224 RS     a) WM_CF_ACTIVATE flag now needed in order to
  38.                          automatically activate a created window
  39. 1.14c   000209 RS     a) GUI_Clear eliminated in default callback for
  40.                          default background window
  41. 1.14b   000125 RS     a) Bugfix for bug created in 1.14a
  42. 1.14a   000122 RS     a) WM_CreateObj: Change in order to avoid
  43.                          compiler warning with IARs new frontend
  44. 1.14    999109 RS     a) Bugfix: Deleted window could still receive
  45.                          up to 1 drawing message. Fixed. (->NextDrawWin)
  46.                       b) WM_Obj now uses memory handle
  47.                       c) WM_DefaultProc now handles WM_DELETE
  48.                       d) Drawing area reduction for callbacks
  49.                          to invalide area
  50.                       e) WM_SetCallback added
  51.                       f) Call to WM_Error if insufficient windows have
  52.                          been configured
  53. 1.12h   000107 RS     a) WM_Sendmessage: unused local eliminated
  54.                       b) WMALLOC_Init call eliminated
  55. 1.12g   991230 RS     a) Callback for background window defined
  56. 1.12f   991228 RS     a) Locking macros moved -> WM.H
  57. 1.12e   991208 RS     a) WM_DrawNext now saves the entire context, not
  58.                          just the active window
  59. 1.12d   991204 RS     a) WM_GetBGndWin added
  60. 1.12c   991203 RS     a) WM_Init now creates default window
  61. 1.12b   991126 RS     a) Cleanup in order to avoid compiler warnings
  62. 1.12a   991112 RS     a) Invalidate now also invalidates any
  63.                          transparent window on top of the invalidated
  64.                          area
  65.                       b) Internal changes in order to support
  66.                          dynamic memory (using WM_ALLOC)
  67.                       c) Additional ASSERTs inserted
  68. 1.12    991110 RS     a) Invalidate now also invalidates a window
  69.                          below a transparent window
  70. 1.10c   991018 RS     a) WM_DrawNext:
  71.                          NextDrawWin=WM_HWIN_NULL -> NextDrawWin==WM_HWIN_NULL
  72. 1.10b   991015 RS     a) WM_ValidateBWin corrected (Invalid
  73.                          flag was never reset, leading to superfluos redraws)
  74.                       b) WM_SetDefault(void) implemented
  75. 1.10a   991012 RS     a) Compile warnings eliminated
  76. 1.10    990918 RS     a) Objects for windows manager added:
  77.                          WM_CreateObject, WM_DeleteObject
  78.                       b) "Magic number" -1 eliminated
  79.                       c) static routines put on top of file
  80.                       d) Locking added (WM_LOCK), ensuring thread
  81.                          safety of all routines
  82.                       e) Window marked as valid only if a callback
  83.                          exists, allowing mixed callback/non callback
  84.                          modes for different windows
  85. 1.08.02 990827 RS     a) Optimization bug in WM_SetHasTrans
  86.                          fixed
  87. 1.08.01 990826 RS     a) Transparent windows can no longer obstruct
  88.                       an area of a window below in Z-direction
  89.                       (in FindNext_IVR) for correct handling of
  90.                       transparent windows
  91. 1.08.00 990823 RS     a) WM__GetOrgX -> WM_GetOrgX
  92.                          WM__GetOrgY -> WM_GetOrgY
  93.                       b) Clearing memory in WM_Init
  94. 1.07.01 990730 RS     a) In WM_DrawNext() add. condition added to make
  95.                       sure that loop does not iterate using
  96.                       -1 (end-of-list) as index
  97. 1.07    990720 RS     a) New switch: WM_SUPPORT_OBSTRUCT, def. 1
  98. 1.06    990504 BB     functions WM_GetWinSizeX() and WM_GetWinSizeY()
  99.                       added.
  100. 1.05    990423 RS     a) Prototype for WM_CreateBWin changed,
  101.                       parameter WM_MESSAGE* is no longer const
  102.                       (Causing some other changes reg. const)
  103.                       b) WM_ShowBWin WM_HideBWin tested in simulator
  104. 1.04    990417 RS     a) DrawNext bug fixed: It had passed the
  105.                       entire WIndow-Rectangle instead of just
  106.                       the InvalidRectangle with the WM_PAINT
  107.                       command
  108. 1.03    990401 RS     a) Implemented the following functions
  109.                       WM_SetHasTrans()
  110.                       WM_ClrHasTrans()
  111.                       WM_GetHasTrans()
  112.                       WM_HideBWin()
  113.                       WM_ShowBWin()
  114.                       WM_ValidateBWin()
  115.                       WM_GetActiveBWin()
  116. 1.02    990315 RS     a) Windows stack organisation routines cleaned
  117.                       up, resulting in more efficient code
  118. 1.01    990314 RS     a) Invalidation and IVR calculation optimized
  119.                       b) Windows which are on top of a window causing
  120.                       invalidation are no longer affected
  121. 1.00    990310 RS     Moving and resizing tested in simulation
  122. 0.99    990309 RS     All routines implemented, moving & resizing
  123.                       need to be tested under different circumstances.
  124. 0.50    990308 RS     Core of WM works (Calculation and iteration over
  125.                       IVRs). Side routines like moving windows and the
  126.                       corresponding message handling missing.
  127.                       There is now a clear seperation between the LCD
  128.                       and GL layers and WM.
  129. 0.01    990301 RS     Incomplete version, for BB to check
  130. ----------------------------------------------------------------------
  131. Known problems:
  132. None.
  133. ----------------------------------------------------------------------
  134. Open issues:
  135. None.
  136. ----------------------------------------------------------------------
  137. Todo:
  138. Nothing.
  139. */
  140. #include <stddef.h>           /* needed for definition of NULL */
  141. #include <string.h>           /* required for memset */
  142. #define WM_C
  143. #include "WM_Intern.h"
  144. #if GUI_WINSUPPORT    /* If 0, WM will not generate any code */
  145. /******************************************************************
  146. *
  147. *              Config defaults
  148. *
  149. *******************************************************************
  150. */
  151. /* This is for tests only. It will fill the invalid area of a window.
  152.    Can be used for debugging. */
  153. #ifndef WM_SHOW_INVALID
  154.   #define WM_SHOW_INVALID 0
  155. #endif
  156. /*******************************************************************
  157. *
  158. *                 Macros for internal use
  159. *
  160. ********************************************************************
  161. */
  162. #define ASSIGN_IF_LESS(v0,v1) if (v1<v0) v0=v1
  163. /******************************************************************
  164. *
  165. *              Local typedefs
  166. *
  167. *******************************************************************
  168. */
  169. typedef struct {
  170.   GUI_RECT ClientRect;
  171.   GUI_RECT CurRect;
  172.   int Cnt;
  173.   int EntranceCnt;
  174. } WM_IVR_CONTEXT;
  175. /******************************************************************
  176. *
  177. *              WM_ global data
  178. *
  179. *******************************************************************
  180. */
  181. U8                     WM_IsActive;
  182. U16                    WM__CreateFlags = 0;
  183. WM_DELETE_WINDOW_HOOK* WM__pfDeleteWindowHook;
  184. GUI_COLOR              WM__BkColor = GUI_INVALID_COLOR;
  185. WM_HWIN                WM__hCapture = 0, WM__hWinFocus =0;
  186. char                   WM__CaptureReleaseAuto;
  187. /******************************************************************
  188. *
  189. *              Static data
  190. *
  191. *******************************************************************
  192. */
  193. static WM_HWIN        NextDrawWin;
  194. static U8             IsInCallback;
  195. static WM_IVR_CONTEXT ClipContext;
  196. static char           _IsInited = 0;
  197. /*******************************************************************
  198. *
  199. *       Static routines
  200. *
  201. ********************************************************************
  202. */
  203. /*******************************************************************
  204. *
  205. *       _ClipAtParentBorders
  206.   Iterates over all its ancestors and intersects all rectangles to
  207.   find out which part is actually visible.
  208.   Reduces the rectangle to the visible area.
  209. */
  210. void _ClipAtParentBorders(GUI_RECT* pRect, WM_Obj* pWin) {
  211.   WM_HWIN hWin;
  212.   hWin = pWin->hParent;
  213.   while (hWin) {
  214.     pWin = WM_H2P(hWin);
  215.     GUI__IntersectRect(pRect, &pWin->Rect);
  216.     hWin = pWin->hParent;
  217.   }
  218. }
  219. /*******************************************************************
  220. *
  221. *
  222.   When drawing, we have to start at the bottom window !
  223. */
  224. static void ResetNextDrawWin(void) {
  225.   NextDrawWin = WM_HWIN_NULL;
  226. }
  227. /*******************************************************************
  228. *
  229. *       _AddChild
  230. */
  231. void _AddChild(WM_HWIN hParent, WM_HWIN hChild, int OnTop) {
  232.   WM_Obj* pChild;
  233.   WM_Obj* pParent;
  234.   WM_Obj* pi;
  235.   WM_HWIN hi;
  236.   if (hParent) {
  237.     pParent = WM_H2P(hParent);
  238.     pChild  = WM_H2P(hChild);
  239.     hi = pParent->hFirstChild;
  240.     if (hi == 0) {   /* No child yet ... Makes things easy ! */
  241.       pParent->hFirstChild = hChild;
  242.         return;                         /* Early out ... We are done */
  243.     }
  244.     if (!OnTop) {
  245.       pi = WM_H2P(hi);
  246.       if (pi->Status & WM_SF_STAYONTOP) {
  247.         pChild->hNext = hi;
  248.         pParent->hFirstChild = hChild;
  249.         return;                         /* Early out ... We are done */
  250.       }
  251.     }
  252.     /* put if at the end of the list or after the last non "STAY-ON-TOP" child */
  253.     do {
  254.       WM_Obj* pNext;
  255.       WM_HWIN hNext;
  256.       pi = WM_H2P(hi);
  257.       if ((hNext = pi->hNext) == 0) {
  258.         pi->hNext = hChild;
  259.         break;
  260.       }
  261.       if (!OnTop) {
  262.         pNext = WM_H2P(hNext);
  263.         if (pNext->Status & WM_SF_STAYONTOP) {
  264.           pi->hNext = hChild;
  265.           pChild->hNext = hNext;
  266.           break;
  267.         }
  268.       }
  269.       hi = hNext;
  270.     }  while (1);
  271.   }
  272. }
  273. /*******************************************************************
  274. *
  275. *
  276. */
  277. static void _DeleteAllChildren(WM_HWIN hChild) {
  278.   while (hChild) {
  279.     WM_Obj* pChild = WM_H2P(hChild);
  280.     WM_HWIN hNext = pChild->hNext;
  281.     WM_DeleteWindow(hChild);
  282.     hChild = hNext;
  283.   }
  284. }
  285. /*******************************************************************
  286. *
  287. *
  288. */
  289. static void _DeleteInSiblingList(WM_HWIN hWin) {
  290.   WM_Obj* pWin;
  291.   WM_Obj* pParent;
  292.   WM_Obj* pi;
  293.   WM_HWIN hParent;
  294.   WM_HWIN hi;
  295.   pWin = WM_H2P(hWin);
  296.   if (pWin->hParent) {
  297.     hParent = pWin->hParent;
  298.     pParent = WM_H2P(hParent);
  299.     hi = pParent->hFirstChild;
  300.     if (hi == hWin) {
  301.       pi = WM_H2P(hi);
  302.       pParent->hFirstChild = pi->hNext;
  303.     } else {
  304.       while (hi) {
  305.         pi = WM_H2P(hi);
  306.         if (pi->hNext == hWin) {
  307.           pi->hNext = pWin->hNext;
  308.           return;
  309.         }
  310.         hi = pi->hNext;
  311.       }
  312.     }
  313.   }
  314. }
  315. /*********************************************************************
  316. *
  317. *             Module internal routines
  318. *
  319. **********************************************************************
  320. */
  321. void WM__Client2Screen(const WM_Obj* pWin, GUI_RECT *pRect) {
  322.   GUI_MoveRect(pRect, pWin->Rect.x0, pWin->Rect.y0);
  323. }
  324. int WM__IsWindow(WM_HWIN hWin) {
  325.   WM_HWIN iWin;
  326.   int r = 0;
  327.   for (iWin = WM__FirstWin; iWin; iWin = WM_H2P(iWin)->hNextLin) {
  328.     if (iWin == hWin) {
  329.       r = 1;
  330.       break;
  331.     }
  332.   }
  333.   return r;
  334. }
  335. /*******************************************************************
  336. *
  337. *
  338. */
  339. void WM__RemoveFromLinList(WM_HWIN hWin) {
  340.   WM_Obj* piWin;
  341.   WM_HWIN hiWin, hNext;
  342.   for (hiWin = WM__FirstWin; hiWin; ) {
  343.     piWin = WM_H2P(hiWin);
  344.     hNext = piWin->hNextLin;
  345.     if (hNext == hWin) {
  346.       piWin->hNextLin = WM_H2P(hWin)->hNextLin;
  347.       break;
  348.     }
  349.     hiWin = hNext;
  350.   }
  351. }
  352. /*******************************************************************
  353. *
  354. *
  355. */
  356. void _AddToLinList(WM_HWIN hNew) {
  357.   WM_Obj* pFirst;
  358.   WM_Obj* pNew;
  359.   if (WM__FirstWin) {
  360.     pFirst = WM_H2P(WM__FirstWin);
  361.     pNew   = WM_H2P(hNew);
  362.     pNew->hNextLin = pFirst->hNextLin;
  363.     pFirst->hNextLin = hNew;
  364.   } else {
  365.     WM__FirstWin = hNew;
  366.   }
  367. }
  368. /*********************************************************************
  369.    Check if the rectangle has some content (is non-zero)
  370.    Returns 0 if the Rectangle has no content, else 1.
  371. */
  372. int WM__RectIsNZ(const GUI_RECT* pr) {
  373.   if (pr->x0 > pr->x1)
  374.     return 0;
  375.   if (pr->y0 > pr->y1)
  376.     return 0;
  377.   return 1;
  378. }
  379. /*
  380.   ********************************************************************
  381.   *                                                                  *
  382.   *                    Sending messages                              *
  383.   *                                                                  *
  384.   ********************************************************************
  385. */
  386. void WM_SendMessage(WM_HWIN hWin, WM_MESSAGE* pMsg) {
  387.   WM_Obj* pWin;
  388.   WM_LOCK();
  389.   if (hWin) {
  390.     pWin = WM_H2P(hWin);
  391.   /* Do some checking to avoid program crashes due to user
  392.      programming errors */
  393.     #if GUI_DEBUG_LEVEL > 0
  394.       if (!pWin->Status)
  395.         goto Done;
  396.     #endif
  397.     if (pWin->cb != NULL) {
  398.       pMsg->hWin = hWin;
  399.       IsInCallback = 1;
  400.       (*pWin->cb)(pMsg);
  401.       IsInCallback = 0;
  402.     }
  403.   }
  404.   #if GUI_DEBUG_LEVEL > 0
  405. Done:
  406.   #endif
  407.   WM_UNLOCK();
  408. }
  409. /*******************************************************************
  410. *
  411. *
  412. */
  413. void WM__SendMsgNoData(WM_HWIN hWin, U8 MsgId) {
  414.   WM_MESSAGE Msg;
  415.   Msg.hWin  = hWin;
  416.   Msg.MsgId = MsgId;
  417.   WM_SendMessage(hWin, &Msg);
  418. }
  419. /* Get client rectangle in windows coordinates. This means that the
  420.   upper left corner is always at (0,0). */
  421. void WM__GetClientRectWin(WM_Obj* pWin, GUI_RECT* pRect) {
  422.   pRect->x0 = pRect->y0 = 0;
  423.   pRect->x1 = pWin->Rect.x1 - pWin->Rect.x0;
  424.   pRect->y1 = pWin->Rect.y1 - pWin->Rect.y0;
  425. }
  426. static void WM__GetInvalidRectAbs(WM_Obj* pWin, GUI_RECT* pRect) {
  427.   *pRect = pWin->InvalidRect;
  428.   GUI_MoveRect (pRect, pWin->Rect.x0, pWin->Rect.y0);
  429. }
  430. /*
  431.           *****************************************************************
  432.           *                                                               *
  433.           *              Invalidation functions                           *
  434.           *                                                               *
  435.           *****************************************************************
  436. */
  437. /* Invalidate, using window coordinates */
  438. static void WM_InvalidateBWin1(WM_HWIN hWin, const GUI_RECT*pRect) {
  439.   GUI_RECT r;
  440.   WM_Obj* pWin = WM_H2P(hWin);
  441.   WM__GetClientRectWin(pWin, &r);
  442.   if (pRect)
  443.     GUI__IntersectRect(&r, pRect);
  444.   if (WM__RectIsNZ(&r)) {
  445.     if (pWin->Status & WM_SF_INVALID) {
  446.       GUI_MergeRect(&pWin->InvalidRect, &pWin->InvalidRect, &r);
  447.     } else {
  448.       pWin->InvalidRect = r;
  449.       pWin->Status |= WM_SF_INVALID;
  450.       WM__NumInvalidWindows++;
  451.       /* Debug code: shows invalid areas */
  452.       #if (WM_SHOW_INVALID)
  453.       {
  454.         GUI_CONTEXT Context = GUI_Context;
  455.         WM_SelectWindow(hWin);
  456.         GUI_SetBkColor(GUI_GREEN);
  457.         GUI_ClearRect(r.x0, r.y0, r.x1, r.y1);
  458.         GUI_Context = Context;
  459.       }
  460.       #endif
  461.     }
  462.   }
  463. }
  464. /* Invalidate, using desktop coordinates (only this window,
  465.    not the ones below !!!)
  466. */
  467. static void WM_InvalidateBWin1Abs(WM_HWIN hWin, const GUI_RECT*pRect) {
  468.   GUI_RECT r = *pRect;
  469.   WM_LOCK();
  470.   GUI_MoveRect(&r, -WM_H2P(hWin)->Rect.x0, -WM_H2P(hWin)->Rect.y0);
  471.   WM_InvalidateBWin1(hWin, &r);
  472.   WM_UNLOCK();
  473. }
  474. /*
  475.   Invalidate a certain section of the display. One main reason for this is
  476.   that a window has been moved or destroyed.
  477.   The following windows are affected:
  478.   * windows below the window creating the invalidation.
  479.   * transparent windows located above
  480.   The coordinates given are absolute coordinates (desktop coordinates)
  481. */
  482. void WM__InvalidateAreaBelow(const GUI_RECT* pRect, WM_HWIN StopWin) {
  483.   WM_HWIN   iWin, iNext;
  484.   /* Iterate over windows below StopWin */
  485.   for (iWin = WM__FirstWin; iWin!=StopWin; iWin = iNext) {
  486.     GUI_RECT r = *pRect;
  487.     WM_Obj* pWin = WM_H2P(iWin);
  488.     iNext = pWin->hNextLin;
  489.     if (GUI__IntersectRects(&r, &r, &pWin->Rect)) {
  490.       WM_InvalidateBWin1Abs (iWin, &r);
  491.     }
  492.   };
  493. }
  494. /*
  495.   Invalidate any transparent window above the given area
  496. */
  497. void WM__InvalidateTransAreaAbove(const GUI_RECT* pRect, WM_HWIN StopWin) {
  498.   GUI_USE_PARA(pRect);
  499.   GUI_USE_PARA(StopWin);
  500. #if 0
  501.   WM_HWIN   iWin;
  502.   /* Iterate over windows below StopWin */
  503.   for (iWin = StopWin; iWin!=WM_HWIN_NULL; iWin = WM_H2P(iWin)->Next) {
  504.     WM_Obj *pWin = WM_H2P(iWin);
  505.     if (pWin->Status & WM_SF_HASTRANS) {
  506.       GUI_RECT r = *pRect;
  507.       if (GUI__IntersectRects(&r, &r, &WM_H2P(iWin)->Rect)) {
  508.         WM_InvalidateBWin1Abs (iWin, &r);
  509.       }
  510.     }
  511.   }
  512. #endif
  513. }
  514. /*
  515.           *****************************************************************
  516.           *                                                               *
  517.           *              Invalidation functions                           *
  518.           *                                                               *
  519.           *****************************************************************
  520. */
  521. /* Invalidate a section of the window. The optional rectangle
  522.    contains client coordinates, which are independent of the
  523.    position of the window on the logical desktop area.
  524. */
  525. void WM_InvalidateRect(WM_HWIN hWin, const GUI_RECT*pRect) {
  526.   GUI_RECT r;
  527.   WM_Obj* pWin;
  528.   WM_LOCK();
  529.   pWin = WM_H2P(hWin);
  530.   WM__GetClientRectWin(pWin, &r);
  531.   if (pRect) {
  532.     GUI__IntersectRect(&r, pRect);
  533.   }
  534.   WM_InvalidateBWin1(hWin, &r);
  535. /* Convert into absolute coordinates ... */
  536.   GUI_MoveRect (&r, pWin->Rect.x0, pWin->Rect.y0);
  537. /* Make sure windows below are invalidated if this one is transparent */
  538.   if (pWin->Status & WM_SF_HASTRANS) {
  539.     ResetNextDrawWin();
  540.     WM__InvalidateAreaBelow(&r, hWin);
  541.   }
  542. /* Invalidate the transparent ones above */
  543.   WM__InvalidateTransAreaAbove(&r,hWin);
  544.   WM_UNLOCK();
  545. }
  546. void WM_InvalidateWindow(WM_HWIN hWin) {
  547.   WM_InvalidateRect(hWin, NULL);
  548. }
  549. /* Invalidate, using desktop coordinates */
  550. void WM_InvalidateBWinAbs(WM_HWIN hWin, const GUI_RECT*pRect) {
  551.   GUI_RECT r = *pRect;
  552.   WM_LOCK();
  553.   GUI_MoveRect(&r, -WM_H2P(hWin)->Rect.x0, -WM_H2P(hWin)->Rect.y0);
  554.   WM_InvalidateRect(hWin, &r);
  555.   WM_UNLOCK();
  556. }
  557. /*
  558.   Invalidate a certain section of the display. One main reason for this is
  559.   that the top window has been moved or destroyed.
  560.   The coordinates given are absolute coordinates (desktop coordinates)
  561. */
  562. void WM_InvalidateArea(GUI_RECT* pRect) {
  563.   WM_HWIN   iWin;
  564.   WM_LOCK();
  565.   /* Iterate over all windows */
  566.   for (iWin=WM__FirstWin; iWin !=0; ) {
  567.     WM_Obj* pWin = WM_H2P(iWin);
  568.     GUI_RECT r = *pRect;
  569.     GUI__IntersectRect(&r, &pWin->Rect);
  570.     /* Calculate which area is actually visible by subtracting the
  571.        windows which are on top of this one */
  572.     WM_InvalidateBWinAbs (iWin, &r);
  573.     iWin = pWin->hNextLin;
  574.   }
  575.   WM_UNLOCK();
  576. }
  577. /*
  578.   ********************************************************************
  579.   *                                                                  *
  580.   *              manage windows stack                                *
  581.   *                                                                  *
  582.   ********************************************************************
  583. */
  584. /* Return index (handle) of the window which is bottom of stack.
  585.    Note that in the current implementation, this is always
  586.    window 0.
  587. */
  588. WM_HWIN WM_GetDesktopWindow(void) {
  589.   return WM__FirstWin;
  590. }
  591. /*
  592.   ********************************************************************
  593.   *
  594.   *              Create window (as child)
  595.   *
  596.   ********************************************************************
  597. */
  598. WM_HWIN WM_CreateWindowAsChild(
  599.                     int x0, int y0, int width, int height
  600.                    ,WM_HWIN hWinParent
  601.                    ,U16 Style
  602.                    ,WM_CALLBACK* cb
  603.                    ,int NumExtraBytes)
  604. {
  605.   WM_Obj* pWin;
  606.   WM_HWIN hWin;
  607.   WM_LOCK();
  608.   Style |= WM__CreateFlags;
  609.   /* Get Parent info */
  610.   if (!hWinParent) {
  611.     if (WM__NumWindows) {
  612.       hWinParent = WM_HBKWIN;
  613.     }
  614.   }
  615.   if (hWinParent) {
  616.     GUI_RECT Rect;
  617.     WM_MESSAGE Msg;
  618.     Msg.MsgId = WM_GETCLIENTRECT_ABS;
  619.     Msg.Data.p = &Rect;
  620.     WM_SendMessage(hWinParent, &Msg);
  621.     x0 += Rect.x0;
  622.     y0 += Rect.y0;
  623.     if (width==0)
  624.       width = Rect.x1-Rect.x0+1;
  625.     if (height==0)
  626.       height = Rect.y1-Rect.y0+1;
  627.   }
  628.   if ((hWin = (WM_HWIN) WM_ALLOC(NumExtraBytes+sizeof(WM_Obj))) == 0) {
  629.     GUI_DEBUG_ERROROUT("WM_CreateWindow: No memory to create window");
  630.   } else {
  631.     WM__NumWindows++;
  632.     pWin = WM_H2P(hWin);
  633.     memset (pWin,   0, sizeof(WM_Obj));        /* erase this data structure
  634.            The explicit zero-init is no longer needed since the entire data structure
  635.            is already zeroed. The advantage is that it reduces program size.
  636.            */
  637.     pWin->Rect.x0 = x0;
  638.     pWin->Rect.y0 = y0;
  639.     pWin->Rect.x1 = x0+width-1;
  640.     pWin->Rect.y1 = y0+height-1;
  641.     pWin->Status = WM_SF_INUSE;     /* Mark window as in use */
  642.     pWin->cb = cb;
  643.     /* Add to linked lists */
  644.     pWin->hParent = hWinParent;
  645.     _AddChild(hWinParent, hWin, Style & WM_CF_STAYONTOP);
  646.     _AddToLinList(hWin);
  647.   /* Put Window on top (or bottom) of windows stack */
  648.     if (Style & WM_CF_ACTIVATE /*| (cb==NULL)*/) {
  649.       WM_SelectWindow(hWin);  /* This is not needed
  650.                                  if callbacks are being used, but it
  651.                                  does not cost a lot and makes life
  652.                                  easier ... */
  653.     }
  654.   /* Mark client area as invalid */
  655.     WM__SendMsgNoData(hWin, WM_CREATE);
  656.   /* Handle the Style flags, one at a time */
  657.     if (Style & WM_CF_SHOW) {
  658.       WM_ShowWindow(hWin);
  659.     }
  660.   /* Hide if parent is not visible */
  661.     if (hWinParent) {
  662.       WM_Obj* pWinParent = WM_H2P(hWinParent);
  663.       if (!(pWinParent->Status & WM_SF_ISVIS)) {
  664.         WM_HideWindow(hWin);
  665.       }
  666.     }
  667.     /* Copy the flags which can simply be accepted */
  668.     pWin->Status |= (Style & (WM_SF_MEMDEV|WM_SF_STAYONTOP|WM_SF_HASTRANS));
  669.   }
  670.   WM_UNLOCK();
  671.   return hWin;
  672. }
  673. WM_HWIN WM_CreateWindow(int x0, int y0, int width, int height, U16 Style, WM_CALLBACK* cb, int NumExtraBytes) {
  674.   return WM_CreateWindowAsChild(x0,y0,width,height, 0 /* No parent */,  Style, cb, NumExtraBytes);
  675. }
  676. /****************************************************************
  677. *
  678. *          Delete window
  679. *
  680. *****************************************************************
  681. */
  682. void WM_DeleteWindow (WM_HWIN Win) {
  683.   WM_Obj* pWin;
  684.   if (!Win)
  685.     return;
  686.   WM_LOCK();
  687.   if (WM__IsWindow(Win)) {
  688.     pWin = WM_H2P(Win);
  689.     ResetNextDrawWin();              /* Make sure the window will no longer receive drawing messages */
  690.   /* Make sure that focus is set to an existing window */
  691.     if (WM__hWinFocus == Win) {
  692.       WM__hWinFocus = 0;
  693.     }
  694.     if (Win == WM__hCapture) {
  695.       WM__hCapture = 0;
  696.     }
  697.   /* Delete all children */
  698.     _DeleteAllChildren(pWin->hFirstChild);
  699.     _DeleteInSiblingList(Win);
  700.   /* Send WM_DELETE message to window in order to inform window itself */
  701.     WM__SendMsgNoData(Win, WM_DELETE);     /* tell window about it */
  702.     /* Inform other modules if necessary */
  703.     if (WM__pfDeleteWindowHook) {
  704.       (*WM__pfDeleteWindowHook)(Win);
  705.     }
  706.   /* Remove window from window stack */
  707.     if (pWin->Status & WM_SF_INVALID) {
  708.       WM__NumInvalidWindows--;
  709.     }
  710.     WM__RemoveFromLinList(Win);
  711.   /* Clear area used by this window */
  712.     WM_InvalidateArea(&pWin->Rect);
  713.   /* Free window memory */
  714.     WM__NumWindows--;
  715.     WM_FREE(Win);
  716.   /* Select a valid window */
  717.     WM_SelectWindow(WM__FirstWin);
  718.   } else {
  719.     GUI_DEBUG_WARN("WM_DeleteWindow: Invalid handle");
  720.   }
  721.   WM_UNLOCK();
  722. }
  723. void WM__SetMaxClipRect(const WM_Obj* pWin) {
  724.   WM_LOCK();
  725.   LCD_SetClipRectEx(&pWin->Rect);
  726.   WM_UNLOCK();
  727. }
  728. /****************************************************************
  729. *
  730. *              WM_SelectWindow
  731. *
  732. *****************************************************************
  733. Sets the active Window. The active Window is the one that is used for all
  734. drawing (and text) operations.
  735. */
  736. WM_HWIN WM_SelectWindow(WM_HWIN  hWin) {
  737.   WM_HWIN hWinPrev;
  738.   WM_LOCK();
  739.   hWinPrev = GUI_Context.hAWin;
  740.   if (hWin == 0) {
  741.     hWin = WM__FirstWin;
  742.   }
  743.   if (!(WM_H2P(hWin)->Status & WM_SF_INUSE)) {
  744.     GUI_DEBUG_ERROROUT1("Selecting invalid window", hWin);
  745.     hWin=0;
  746.   }
  747.   /* Select new window */
  748.   GUI_Context.hAWin = hWin;
  749.   WM__SetMaxClipRect(WM_H2P(hWin));
  750.   WM_UNLOCK();
  751.   return hWinPrev;
  752. }
  753. WM_HWIN WM_GetActiveWindow(void) {
  754.   return GUI_Context.hAWin;
  755. }
  756. /*
  757.   ********************************************************************
  758.   *                                                                  *
  759.   *                 Show / hide window                               *
  760.   *                                                                  *
  761.   ********************************************************************
  762. */
  763. void WM_ShowWindow   (WM_HWIN hWin) {
  764.   WM_Obj *pWin;
  765.   WM_LOCK();
  766.   pWin = WM_H2P(hWin);  
  767.   /* First check if this is necessary at all */
  768.   if ((pWin->Status&WM_SF_ISVIS)) {
  769.     WM_UNLOCK();
  770.     return;
  771.   }
  772.   /* Set Visibility flag */
  773.   pWin->Status |= WM_SF_ISVIS;
  774.   /* Mark content as invalid */
  775.   WM_InvalidateWindow(hWin);
  776.   WM_UNLOCK();
  777. }
  778. /*
  779.           *****************************************************************
  780.           *                                                               *
  781.           *                    GetOrg                                     *
  782.           *                                                               *
  783.           *****************************************************************
  784. These routines return the offset of the client area in absolute coordinates.
  785. They are used to convert window coordinates into absolute coordinates and are
  786. used in the clipping libraries (CL_).
  787. */
  788. int WM__GetOrgX(void) {
  789.   return WM_H2P(GUI_Context.hAWin)->Rect.x0;
  790. }
  791. int WM__GetOrgY(void) {
  792.   return WM_H2P(GUI_Context.hAWin)->Rect.y0;
  793. }
  794. /*********************************************************************
  795. *
  796. *           IVR calculation
  797. IVRs are invalid rectangles. When redrawing, only the portion of the
  798. window which is
  799.   a) within the window-rectangle
  800.   b) not covered by an other window
  801.   c) marked as invalid
  802.   is actually redrawn. Unfortunately, this section is not always
  803.   rectangular. If the window is partially covered by an other window,
  804.   it consists of the sum of multiple rectangles. In all drawing
  805.   operations, we have to iterate over every one of these rectangles in
  806.   order to make sure the window is drawn completly.
  807. Function works as follows:
  808.   STEP 1: - Set upper left coordinates to next pixel. If end of line (right border), goto next line -> (r.x0, r.y0)
  809.   STEP 2: - Check if we are done, return if we are.
  810.   STEP 3: - If we are at the left border, find max. heigtht (r.y1) by iterating over windows above
  811.   STEP 4: - Find x0 for the given y0, y1 by iterating over windows above
  812.   STEP 5: - If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
  813.   STEP 6: - Find r.x1. We have to Iterate over all windows which are above
  814. */
  815. #if WM_SUPPORT_OBSTRUCT
  816. static int FindNext_IVR(void) {
  817.   int hParent;
  818.   int iWin;
  819.   GUI_RECT r;
  820.   U8 Status;
  821.   WM_Obj* pWin;
  822.   WM_Obj* pAWin;
  823.   WM_Obj* pParent;
  824.   r = ClipContext.CurRect;  /* temps  so we do not have to work with pointers too much */
  825.   /*
  826.      STEP 1:
  827.        Set the next position which could be part of the next IVR
  828.        This will be the first unhandle pixel in reading order, i.e. next one to the right
  829.        or next one down if we are at the right border.
  830.   */
  831.   if (ClipContext.Cnt == 0) {       /* First IVR starts in upper left */
  832.     r.x0 = ClipContext.ClientRect.x0;
  833.     r.y0 = ClipContext.ClientRect.y0;
  834.   } else {
  835.     r.x0 = ClipContext.CurRect.x1+1;
  836.     r.y0 = ClipContext.CurRect.y0;
  837.     if (r.x0 > ClipContext.ClientRect.x1) {
  838. NextStripe:  /* go down to next stripe */
  839.       r.x0 = ClipContext.ClientRect.x0;
  840.       r.y0 = ClipContext.CurRect.y1+1;
  841.     }
  842.   }
  843.   /*
  844.      STEP 2:
  845.        Check if we are done completely.
  846.   */
  847.   if (r.y0 >ClipContext.ClientRect.y1)
  848.     return 0;
  849.   /* STEP 3:
  850.        Find out the max. height (r.y1) if we are at the left border.
  851.        Since we are using the same height for all IVRs at the same y0,
  852.        we do this only for the leftmost one.
  853.   */
  854.   pAWin = WM_H2P(GUI_Context.hAWin);
  855.   if (r.x0 == ClipContext.ClientRect.x0) {
  856.     r.y1 = ClipContext.ClientRect.y1;
  857.     r.x1 = ClipContext.ClientRect.x1;
  858.     /* Iterate over all windows which are above */
  859.     /* Check all siblings above (Iterate over Parents and top siblings (hNext) */
  860.     for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
  861.       pParent = WM_H2P(hParent);
  862.       for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) { 
  863.         Status = (pWin = WM_H2P(iWin))->Status;
  864.         /* Check if this window affects us at all */    
  865.         if ((Status & WM_SF_ISVIS)  && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
  866.           if (pWin->Rect.y0 > r.y0) {
  867.             ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1);      /* Check upper border of window */
  868.           } else {
  869.             ASSIGN_IF_LESS(r.y1, pWin->Rect.y1);        /* Check lower border of window */
  870.           }
  871.         }
  872.       }
  873.     }
  874.     /* Check all children */
  875.     for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) { 
  876.       Status = (pWin = WM_H2P(iWin))->Status;
  877.       /* Check if this window affects us at all */    
  878.       if ((Status & WM_SF_ISVIS)  && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
  879.         if (pWin->Rect.y0 > r.y0) {
  880.           ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1);      /* Check upper border of window */
  881.         } else {
  882.           ASSIGN_IF_LESS(r.y1, pWin->Rect.y1);        /* Check lower border of window */
  883.         }
  884.       }
  885.     }
  886.   }
  887.   /* 
  888.     STEP 4
  889.       Find out x0 for the given y0, y1 by iterating over windows above.
  890.       if we find one that intersects, adjust x0 to the right.
  891.   */
  892. Find_x0:
  893.   r.x1 = r.x0;
  894.   /* Iterate over all windows which are above */
  895.   /* Check all siblings above */
  896.     for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
  897.     pParent = WM_H2P(hParent);
  898.     for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) { 
  899.       Status = (pWin = WM_H2P(iWin))->Status;
  900.       if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     /* Check if this window affects us at all */
  901.         r.x0 = pWin->Rect.x1+1;
  902.         goto Find_x0;
  903.       }
  904.     }
  905.   }
  906.   /* Check all children */
  907.   for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) { 
  908.     Status = (pWin = WM_H2P(iWin))->Status;
  909.     if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     /* Check if this window affects us at all */
  910.       r.x0 = pWin->Rect.x1+1;
  911.       goto Find_x0;
  912.     }
  913.   }
  914.   /* 
  915.    STEP 5:
  916.      If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
  917.      Find out x1 for the given x0, y0, y1
  918.   */
  919.   r.x1 = ClipContext.ClientRect.x1;
  920.   if (r.x1 < r.x0) {/* horizontal border reached ? */
  921.     ClipContext.CurRect = r;
  922.     goto NextStripe;
  923.   }    
  924.   /* 
  925.    STEP 6:
  926.      Find r.x1. We have to Iterate over all windows which are above
  927.   */
  928.   /* Check all siblings above (Iterate over Parents and top siblings (hNext) */
  929.   for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
  930.     pParent = WM_H2P(hParent);
  931.     for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) { 
  932.       Status = (pWin = WM_H2P(iWin))->Status;
  933.       if (    (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     /* Check if this window affects us at all */
  934.         r.x1 = pWin->Rect.x0-1;    
  935.       }
  936.     }
  937.   }
  938.   /* Check all children */
  939.   for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) { 
  940.     Status = (pWin = WM_H2P(iWin))->Status;
  941.     if (    (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     /* Check if this window affects us at all */
  942.       r.x1 = pWin->Rect.x0-1;    
  943.     }
  944.   }
  945.   /* We are done. Return the rectangle we found in the ClipContext. */
  946.   if (ClipContext.Cnt >200) {
  947.     return 0;  /* error !!! This should not happen !*/
  948.   }
  949.   ClipContext.CurRect = r;
  950.   return 1;  /* IVR is valid ! */
  951. }
  952. #else
  953. static int FindNext_IVR(void) {
  954.   if (ClipContext.Cnt ==0) {
  955.     ClipContext.CurRect = GUI_Context.pAWin->Rect;
  956.     return 1;  /* IVR is valid ! */
  957.   }
  958.   return 0;  /* Nothing left to draw */
  959. }
  960. #endif
  961. /*********************************************************************
  962. *
  963. *              Get next IVR
  964.   Sets the next clipping rectangle. If a valid one has
  965.   been found (and set), 1 is returned in order to indicate
  966.   that the drawing operation needs to be executed.
  967.   Returning 0 signals that we have iterated over all
  968.   rectangles.
  969.   Returns: 0 if no valid rectangle is found
  970.            1 if rectangle has been found
  971. */
  972. int  WM__GetNextIVR   (void) {
  973.   #if GUI_SUPPORT_CURSOR
  974.     static char _CursorHidden;
  975.   #endif
  976.   /* If WM is not active, we have no rectangles to return */
  977.   if (WM_IsActive==0)
  978.     return 0;
  979.   if (ClipContext.EntranceCnt > 1) {
  980.     ClipContext.EntranceCnt--;
  981.     return 0;
  982.   }
  983.   #if GUI_SUPPORT_CURSOR
  984.     if (_CursorHidden) {
  985.       _CursorHidden = 0;
  986.       (*GUI_CURSOR_pfTempUnhide) ( &ClipContext.CurRect);
  987.     }
  988.   #endif
  989.   ++ClipContext.Cnt;
  990.   /* Find next rectangle and use it as ClipRect */
  991.   if (!FindNext_IVR()) {
  992.     ClipContext.EntranceCnt--;  /* This search is over ! */
  993.     return 0;        /* Could not find an other one ! */
  994.   }
  995.   /* Hide cursor if necessary */
  996.   LCD_SetClipRectEx(&ClipContext.CurRect);
  997.   #if GUI_SUPPORT_CURSOR
  998.     if (GUI_CURSOR_pfTempHide) {
  999.       _CursorHidden = 1;
  1000.       (*GUI_CURSOR_pfTempHide) ( &ClipContext.CurRect);
  1001.     }
  1002.   #endif
  1003.   return 1;
  1004. }
  1005. /*********************************************************************
  1006. *
  1007. *              Init IVR  search
  1008.   This routine is called from the clipping level
  1009.   (the WM_ITERATE_START macro) when starting an iteration over the
  1010.   visible rectangles.
  1011.   Return value:
  1012.     0 : There is no valid rectangle (nothing to do ...)
  1013.     1 : There is a valid rectangle
  1014. */
  1015. int WM__InitIVRSearch(const GUI_RECT* pMaxRect) {
  1016.   GUI_RECT r;
  1017.   WM_Obj* pAWin;
  1018.    /* If WM is not active -> nothing to do, leave cliprect alone */
  1019.   if (WM_IsActive==0)
  1020.     return 1;            
  1021.   /* If we entered multiple times, leave Cliprect alone */
  1022.   if (++ClipContext.EntranceCnt > 1)
  1023.     return 1;
  1024.   pAWin = WM_H2P(GUI_Context.hAWin);
  1025.   ClipContext.Cnt        = -1;
  1026.  /* When using callback mechanism, it is legal to reduce drawing
  1027.     area to the invalid area ! */
  1028.   if (IsInCallback) {
  1029.     WM__GetInvalidRectAbs(pAWin, &r);
  1030.   } else {  /* Not using callback mechanism, therefor allow entire rectangle */
  1031.     if (pAWin->Status & WM_SF_ISVIS) {
  1032.       r = pAWin->Rect;
  1033.     } else {
  1034.       --ClipContext.EntranceCnt;
  1035.       return 0;  /* window is not even visible ! */
  1036.     }
  1037.   }
  1038.   /* If the drawing routine has specified a rectangle, use it to reduce the rectangle */
  1039.   if (pMaxRect) {
  1040.     GUI__IntersectRect(&r, pMaxRect);
  1041.   }
  1042.   /* If user has reduced the cliprect size, reduce the rectangle */
  1043.   if (GUI_Context.WM__pUserClipRect) {
  1044.     GUI_RECT rUser = *(GUI_Context.WM__pUserClipRect);
  1045.     WM__Client2Screen(pAWin, &rUser);
  1046.     GUI__IntersectRect(&r, &rUser);
  1047.   }
  1048.   /* Iterate over all ancestors and clip at their borders */
  1049.   _ClipAtParentBorders(&r, pAWin);
  1050.   /* Store the rectangle and find the first rectangle of the area */
  1051.   ClipContext.ClientRect = r;
  1052.   return WM__GetNextIVR();
  1053. }
  1054. /*
  1055.           ********************************************
  1056.           *                                          *
  1057.           *       Set default                        *
  1058.           *                                          *
  1059.           ********************************************
  1060.   This routine sets the defaults for WM and the layers below.
  1061.   It is used before a drawing routine is called in order to
  1062.   make sure that defaults are set (in case the default settings
  1063.   had been altered before by the application)
  1064. */
  1065. void WM_SetDefault(void) {
  1066.   GL_SetDefault();
  1067.   GUI_Context.WM__pUserClipRect = NULL;   /* No add. clipping */
  1068. }
  1069. /*
  1070.   ********************************************
  1071.   *
  1072.   *        Callback for Paint message
  1073.   *
  1074.   ********************************************
  1075.   This callback is used by the window manger in conjunction with banding
  1076.   memory devices. A pointer to this routine is given to the banding memory device.
  1077.   This callback in turn will send the paint message to the window.
  1078. */
  1079. #if GUI_SUPPORT_MEMDEV
  1080. static void cbPaint(void* pMsg) {
  1081.   WM_SendMessage(((WM_MESSAGE*)pMsg)->hWin, (WM_MESSAGE*) pMsg);
  1082. }
  1083. #endif
  1084. /*
  1085.           ********************************************
  1086.           *                                          *
  1087.           *       Draw next window                   *
  1088.           *                                          *
  1089.           ********************************************
  1090. */
  1091. static void _DrawNext(void) {
  1092.   int UpdateRem = 1;
  1093.   WM_HWIN iWin = (NextDrawWin == WM_HWIN_NULL) ? WM__FirstWin : NextDrawWin;
  1094.   GUI_CONTEXT ContextOld;
  1095.   GUI_SaveContext(&ContextOld);
  1096.   /* Make sure the next window to redraw is valid */
  1097.   for (; (iWin!=WM_HWIN_NULL) && UpdateRem; ) {
  1098.     WM_Obj* pWin = WM_H2P(iWin);
  1099.     if (pWin->Status & WM_SF_INVALID) {
  1100.       U8 Status = (pWin->Status &=  ~WM_SF_INVALID); /* Clear invalid flag */
  1101.       WM__NumInvalidWindows--;
  1102.       /* Send WM_PAINT if window is visible and a callback is defined */
  1103.       if ((pWin->cb != NULL)  && (Status & WM_SF_ISVIS)) {
  1104.         WM_MESSAGE Msg;
  1105.         Msg.hWin   = iWin;
  1106.         Msg.MsgId  = WM_PAINT;
  1107.         Msg.Data.p = (GUI_RECT*)&pWin->InvalidRect;
  1108.         WM_SelectWindow(iWin);
  1109.         WM_SetDefault();
  1110.         #if GUI_SUPPORT_MEMDEV
  1111.           if (Status & WM_SF_MEMDEV) {
  1112.             GUI_RECT r = pWin->InvalidRect;
  1113.             GUI_MoveRect (&r, pWin->Rect.x0, pWin->Rect.y0);
  1114.             GUI_MEMDEV_Draw(&r, cbPaint, &Msg, 0, (Status & WM_SF_HASTRANS) ? GUI_MEMDEV_HASTRANS : 0);
  1115.           } else
  1116.         #endif
  1117.         WM_SendMessage(iWin, &Msg);
  1118.         UpdateRem--;  /* Only the given number of windows at a time ... */
  1119.       }
  1120.     }
  1121.     iWin = pWin->hNextLin;
  1122.   }  
  1123.   NextDrawWin = iWin;   /* Remember the window */
  1124.   GUI_RestoreContext(&ContextOld);
  1125. }
  1126. /*
  1127.           *****************************************************************
  1128.           *                                                               *
  1129.           *                 Idle loop                                     *
  1130.           *                                                               *
  1131.           *****************************************************************
  1132. */
  1133. int WM_Exec1(void) 
  1134. {
  1135. #if 0
  1136.   if (WM_pfHandleHID) 
  1137.   {
  1138.     if (WM_pfHandleHID())
  1139.       return 1;               /* We have done something ... */
  1140.   }
  1141.   if (GUI_PollKeyMsg()) 
  1142.   {
  1143.     return 1;               /* We have done something ... */
  1144.   }
  1145.  #endif
  1146.   if (WM_IsActive && WM__NumInvalidWindows) 
  1147.   {
  1148.     WM_LOCK();
  1149.     _DrawNext();
  1150.     WM_UNLOCK();
  1151.     return 1;               /* We have done something ... */
  1152.   }
  1153.   return 0;                  /* There was nothing to do ... */
  1154. }
  1155. int WM_Exec(void) 
  1156. {
  1157.   int r = 0;
  1158.   while (WM_Exec1()) 
  1159.   {
  1160.     r = 1;                  /* We have done something */
  1161.   }
  1162.   return r;
  1163. }
  1164. /****************************************************************
  1165. *                                                               *
  1166. *              Callback for background window                   *
  1167. *                                                               *
  1168. *****************************************************************
  1169. */
  1170. static WM_RESULT cbBackWin( WM_MESSAGE* pMsg) {
  1171.   WM_KEY_INFO* pKeyInfo;
  1172.   switch (pMsg->MsgId) {
  1173.   case WM_KEY:
  1174.     pKeyInfo = (WM_KEY_INFO*)pMsg->Data.p;
  1175.     if (pKeyInfo->PressedCnt == 0) {
  1176.       GUI_StoreKey(pKeyInfo->Key);
  1177.     }
  1178.     break;
  1179.   case WM_PAINT:
  1180.     if (WM__BkColor != GUI_INVALID_COLOR) {
  1181.       GUI_SetBkColor(WM__BkColor);
  1182.       GUI_Clear();
  1183.     }
  1184.   default:
  1185.     WM_DefaultProc(pMsg);
  1186.   }
  1187. }
  1188. /****************************************************************
  1189. *
  1190. *                    WM_Activate  / WM_Deactivate
  1191. *
  1192. *****************************************************************
  1193. */
  1194. void WM_Activate(void) {
  1195.   WM_IsActive = 1;       /* Running */
  1196. }
  1197. void WM_Deactivate(void) {
  1198.   WM_IsActive = 0;       /* No clipping performed by WM */
  1199.   WM__SetMaxClipRect(WM_H2P(WM_HBKWIN));
  1200. }
  1201. /*
  1202.           *****************************************************************
  1203.           *                                                               *
  1204.           *              WM_Init                                         *
  1205.           *                                                               *
  1206.           *****************************************************************
  1207. */
  1208. void WM_Init(void) {
  1209. if (!_IsInited) {
  1210.   WM_HWIN hWin;
  1211.   NextDrawWin = WM__FirstWin = WM_HWIN_NULL;
  1212.   GUI_Context.WM__pUserClipRect = NULL;
  1213.   WM__NumWindows = WM__NumInvalidWindows =0;
  1214.   /* Make sure we have at least one window. This greatly simplifies the
  1215.   drawing routines as they do not have to check if the window is valid.
  1216.   */
  1217.   hWin = WM_CreateWindow(0, 0, GUI_XMAX, GUI_YMAX, WM_CF_SHOW, cbBackWin, 0);
  1218.   WM_SelectWindow(hWin);
  1219.   WM_Activate();
  1220.     _IsInited =1;
  1221. }
  1222. }
  1223. /*
  1224.           ******************************************************
  1225.           *                                                    *
  1226.           *              Default procedure                     *
  1227.           *                                                    *
  1228.           ******************************************************
  1229. */
  1230. WM_RESULT WM_DefaultProc(WM_MESSAGE* pMsg) {
  1231.   WM_HWIN hWin = pMsg->hWin;
  1232.   void *p = pMsg->Data.p;
  1233.   WM_Obj* pWin = WM_H2P(hWin);
  1234.   /* Exec message */
  1235.   switch (pMsg->MsgId) {
  1236.   case WM_GETORG:
  1237.     ((GUI_POINT*)p)->x = pWin->Rect.x0;
  1238.     ((GUI_POINT*)p)->y = pWin->Rect.y0;
  1239.     break;
  1240.   case WM_GETCLIENTRECT:     /* return client window in window coordinates */
  1241.     WM__GetClientRectWin(pWin, (GUI_RECT*)p);
  1242.     break;
  1243.   case WM_GETCLIENTRECT_ABS:      /* return client window in absolute (screen) coordinates */
  1244.     WM__GetClientRectWin(pWin, (GUI_RECT*)p);
  1245.     GUI_MoveRect((GUI_RECT*)p, pWin->Rect.x0, pWin->Rect.y0);
  1246.     break;
  1247.   case WM_GET_CLIENT_WINDOW:      /* return handle to client window. For most windows, there is no seperate client window, so it is the same handle */
  1248.     pMsg->Data.v = hWin;
  1249.     return;                       /* Message handled */
  1250.   case WM_KEY:
  1251.     WM_SendToParent(hWin, pMsg);
  1252.     return;                       /* Message handled */
  1253.    case WM_GET_BKCOLOR:
  1254.     pMsg->Data.Color = GUI_INVALID_COLOR;
  1255.     return;                       /* Message handled */
  1256.   }
  1257.   /* Message not handled. If it queries something, we return 0 to be on the safe side. */
  1258.   pMsg->Data.v = 0;
  1259.   pMsg->Data.p = 0;
  1260. }
  1261. #else
  1262. void WM(void) {} /* avoid empty object files */
  1263. #endif /* WM_MAX_WINDOW */