Initial git commit -- Transition from CodeGuard repository
[sdk] / ecere / src / gui / Window.ec
1 namespace gui;
2
3 import "Display"
4
5 import "Anchor"
6 import "Key"
7 import "GuiApplication"
8 import "Interface"
9 import "Skin"
10 import "Timer"
11 import "Cursor"
12 import "ClipBoard"
13
14 import "Button"
15 import "ListBox"
16 import "DropBox"
17 import "Label"
18 import "Picture"
19 import "ScrollBar"
20 import "Button"
21 import "Menu"
22 import "StatusBar"
23 import "ProgressBar"
24 import "EditBox"
25 import "DataBox"
26
27 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
28 import "Desktop3D"
29 #endif
30
31 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
32 import "FormDesigner"
33 #endif
34
35 import "FileDialog"
36 import "MessageBox"
37 import "WindowList"
38
39 default extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
40
41 public enum DialogResult { cancel, yes, no, ok };
42
43 public class MouseButtons
44 {
45 public:
46    bool left:1, right:1, middle:1;
47 };
48
49 public struct SizeAnchor
50 {
51    Size size;
52    bool isClientW, isClientH;
53 };
54
55 #include <stdarg.h>
56
57 #define SNAPDOWN(x, d) \
58       if(Abs(x) % (d)) \
59       { \
60          if(x < 0) x -= ((d) - Abs(x) % (d)); else x -= x % (d); \
61       }
62
63 #define SNAPUP(x, d) \
64       if(Abs(x) % (d)) \
65       { \
66          if(x > 0) x += ((d) - Abs(x) % (d)); else x += x % (d); \
67       }
68
69 /*static */define MAX_DIRTY_BACK = 10;
70
71 /////////////////////////////////////////////////////////////////////////////
72 ////////// EXTENT MANIPULATION //////////////////////////////////////////////
73 /////////////////////////////////////////////////////////////////////////////
74
75 #define ACCESS_ITEM(l, id) \
76    id
77
78 #define FASTLIST_LOOP(l, v)      \
79    for(v = (BoxItem)l.first; v; v = (BoxItem)v.next)
80
81 #define FASTLIST_LOOPN(l, v, n) \
82    for(v = (BoxItem)l.first, n = (BoxItem)(v ? v.next : null); v; v = (BoxItem)next, n = (BoxItem)(v ? v.next : null))
83
84 /*
85 #define ACCESS_ITEM(l, id) \
86       ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
87
88 #define FASTLIST_LOOP(l, v)      \
89    for(v = (void *)ACCESS_ITEM((l), (l).first); v; v = (void *)ACCESS_ITEM((l), v.next))
90
91 #define FASTLIST_LOOPN(l, v, n) \
92    for( v = (void *)ACCESS_ITEM((l), (l).first), \
93         n = v ? ((void *)ACCESS_ITEM((l), v.next)): null; \
94         v; v = n, n = n ? (void *)ACCESS_ITEM((l), n.next) : null)
95
96
97 private class FastItem : struct
98 {
99    int prev, next;
100 };
101
102 private struct FastList
103 {
104    FastItem items;
105    int first, last;
106    int free;
107    int count, size, itemSize;
108
109    void Clear(void)
110    {
111       count = 0;
112       size = 0;
113       items = null;
114       first = last = free = -1;
115       itemSize = 0;
116    }
117
118    void Empty(void)
119    {
120       FastItem item, next;
121       Free();
122       // FASTLIST_LOOPN(this, item, next) { Delete(item); };
123    }
124
125    FastItem Add(uint itemSize)
126    {
127       FastItem item;
128       if(free == -1 || !size)
129       {
130          int c;
131          int newSize;
132                
133          if(size)
134          {
135             newSize = (size + (size >> 1));
136             items = (FastItem)renew items byte[newSize * itemSize];
137          }
138          else
139          {
140             newSize = 4;
141             this.itemSize = itemSize;
142             items = (FastItem)new byte[newSize * itemSize];
143          }
144
145          for(c = size; c<newSize-1; c++)
146          {
147             ACCESS_ITEM(this, c).prev = -1;
148             ACCESS_ITEM(this, c).next = c+1;
149          }
150          ACCESS_ITEM(this, c).prev = -1;
151          ACCESS_ITEM(this, c).next = -1;
152          free = size;
153          size = newSize;
154       }
155       item = ACCESS_ITEM(this, free);
156       item.prev = last;
157       if(item.prev != -1)
158          ACCESS_ITEM(this, item.prev).next = free;
159       if(first == -1)
160          first = free;
161       last = free;
162       free = item.next;
163       item.next = -1;
164       count++;
165       return item;
166    }
167
168    void Delete(FastItem item)
169    {
170       if(item.prev != -1)
171          ACCESS_ITEM(this, item.prev).next = item.next;
172       if(item.next != -1)
173          ACCESS_ITEM(this, item.next).prev = item.prev;
174
175       if(ACCESS_ITEM(this, first) == item)
176          first = item.next;
177       if(ACCESS_ITEM(this, last) == item)
178          last = item.prev;
179       count--;
180
181       item.next = free;
182       free = ((byte *)item - (byte *)items) / itemSize;
183    }
184
185    void Free(void)
186    {
187       delete items;
188       size = 0;
189       count = 0;
190       free = first = last = -1;
191    }
192 };
193 */
194 private class BoxItem : Item //FastItem
195 {
196    Box box;
197 };
198
199 public /*private */struct Extent : OldList //FastList
200 {
201    void Empty()
202    {
203       Free(null);
204    }
205
206    void AddBox(Box box)
207    {
208       //BoxItem extentBox = (BoxItem)Add(sizeof(class BoxItem));
209       Add(BoxItem { box = box });
210    }
211
212    void Copy(Extent source)
213    {
214       BoxItem extentBox;
215
216       // Clear();
217       Empty();
218       FASTLIST_LOOP(source, extentBox)
219          AddBox(extentBox.box);
220    }
221
222    void IntersectBox(Box box)
223    {
224       // Clip all boxes of extent against inside of the new box
225       BoxItem extentBox, next;
226
227       FASTLIST_LOOPN(this, extentBox, next)
228       {
229          if(box.left > extentBox.box.left) extentBox.box.left = box.left;
230          if(box.top > extentBox.box.top) extentBox.box.top = box.top;
231          if(box.right < extentBox.box.right) extentBox.box.right = box.right;
232          if(box.bottom < extentBox.box.bottom) extentBox.box.bottom = box.bottom;
233          if(extentBox.box.right < extentBox.box.left || extentBox.box.bottom < extentBox.box.top)
234             Delete(extentBox);
235       }
236    }
237
238    void ExcludeBox(Box box, Extent temp)
239    {
240       BoxItem extentBox;
241
242       temp.Copy(this);
243       Empty();
244       
245       FASTLIST_LOOP(temp, extentBox)
246       {
247          if(extentBox.box.left < box.right && extentBox.box.right > box.left && 
248             extentBox.box.top < box.bottom && extentBox.box.bottom > box.top)
249          {
250             // Top box
251             if(extentBox.box.top < box.top && extentBox.box.bottom >= box.top)
252             {
253                Box newBox
254                {
255                   extentBox.box.left, extentBox.box.top, 
256                   extentBox.box.right, Min(extentBox.box.bottom, box.top -1)
257                };
258                AddBox(newBox);
259             }
260
261             // Bottom box
262             if(extentBox.box.bottom > box.bottom && extentBox.box.top <= box.bottom)
263             {
264                Box newBox
265                {
266                   extentBox.box.left, Max(extentBox.box.top,box.bottom +1),
267                   extentBox.box.right, extentBox.box.bottom
268                };
269                AddBox(newBox);
270             }
271
272             // Middle boxes
273             if(extentBox.box.bottom >= box.top && extentBox.box.top <= box.bottom)
274             {
275                // Left box
276                if(extentBox.box.left < box.left && extentBox.box.right >= box.left)
277                {
278                   Box newBox
279                   {
280                      extentBox.box.left, Max(extentBox.box.top, box.top),
281                      Min(extentBox.box.right, box.left-1), Min(extentBox.box.bottom, box.bottom)
282                   };
283                   AddBox(newBox);
284                }
285
286                // Right box
287                if(extentBox.box.right > box.right && extentBox.box.left <= box.right)
288                {
289                   Box newBox
290                   {
291                      Max(extentBox.box.left, box.right+1), Max(extentBox.box.top, box.top),
292                      extentBox.box.right, Min(extentBox.box.bottom, box.bottom)
293                   };
294                   AddBox(newBox);
295                }
296             }
297          }
298          else
299          {
300             AddBox(extentBox.box);
301          }
302       }
303       temp.Empty();
304    }
305
306    void UnionBox(Box box, Extent temp)
307    {
308       BoxItem extentBox, next;
309
310       // First pass: check if this box is not already covered by one of the extent's box
311       FASTLIST_LOOP(this, extentBox)
312       {
313          if(extentBox.box.left <= box.left && extentBox.box.right >= box.right && 
314             extentBox.box.top <= box.top && extentBox.box.bottom >= box.bottom)
315          {
316             // No change
317             return;
318          }
319       }
320         
321       // Second pass: only keep boxes not completely covered in the new box
322       FASTLIST_LOOPN(this, extentBox, next)
323       {
324          if(extentBox.box.left >= box.left && extentBox.box.right <= box.right &&
325             extentBox.box.top >= box.top && extentBox.box.bottom <= box.bottom)
326             Delete(extentBox);
327       }
328
329       // Add the exclusion to the extent
330       ExcludeBox(box, temp);
331
332       // Add the new box
333       if(box.bottom >= box.top && box.right >= box.left)
334       {
335          // Optimization: if the resulting boxes touch, add them smarter
336          FASTLIST_LOOP(this, extentBox)
337          {
338             if(box.top == extentBox.box.top && box.bottom == extentBox.box.bottom)
339             {
340                if(Abs(box.right - extentBox.box.left) <= 1)
341                {
342                   extentBox.box.left = box.left;
343                   break;
344                }
345                else if(Abs(box.left - extentBox.box.right) <= 1)
346                {
347                   extentBox.box.right = box.right;
348                   break;
349                }
350             }
351             else if(box.left == extentBox.box.left && box.right == extentBox.box.right)
352             {
353                if(Abs(box.bottom - extentBox.box.top) <= 1)
354                {
355                   extentBox.box.top = box.top;
356                   break;
357                }
358                else if(Abs(box.top - extentBox.box.bottom) <= 1)
359                {
360                   extentBox.box.bottom = box.bottom;
361                   break;
362                }
363             }
364          }
365          
366          // Else, add it
367          if(!extentBox)
368             AddBox(box);
369       }
370    }
371
372    void Union(Extent b, Extent temp)
373    {
374       BoxItem extentBox;
375
376       FASTLIST_LOOP(b, extentBox)
377          UnionBox(extentBox.box, temp);
378    }
379
380    void Intersection(Extent b, Extent temp, Extent temp2, Extent temp3)
381    {
382       BoxItem extentBox;
383       temp.Copy(this);
384
385       Empty();
386
387       FASTLIST_LOOP(b, extentBox)
388       {
389          temp2.Copy(temp);
390          temp2.IntersectBox(extentBox.box);
391          Union(temp2, temp3);
392          temp2.Empty();
393       }
394       temp.Empty();
395    }
396
397    void Exclusion(Extent b, Extent temp)
398    {
399       BoxItem extentBox;   
400       FASTLIST_LOOP(b, extentBox)
401          ExcludeBox(extentBox.box, temp);
402    }
403
404    void Offset(int x, int y)
405    {
406       BoxItem extentBox;
407       FASTLIST_LOOP(this, extentBox)
408       {
409          extentBox.box.left += x;
410          extentBox.box.top += y;
411          extentBox.box.right += x;
412          extentBox.box.bottom += y;
413       }
414    }
415 };
416
417 private define MINIMIZED_WIDTH = 160;
418 private define CASCADE_SPACE = 16;
419
420 // namespace Windows;
421
422 private class ScrollFlags
423 {
424    bool snapX:1, snapY:1, dontHide:1;   
425 };
426
427 public class BorderBits { public: bool contour:1, fixed:1, sizable:1, deep:1, bevel:1; };
428
429 class WindowBits : BorderBits
430 {
431    BorderBits borderBits:5:0;
432    bool hidden:1, isActiveClient:1, hasHorzScroll:1, hasVertScroll:1, stayOnTop:1, modal:1, unused1:1, isDefault:1, inactive:1, isRemote:1, drawBehind:1;
433    bool interim:1, tabCycle:1, noCycle:1, dontScrollHorz:1, dontScrollVert:1, hasMaximize:1, hasMinimize:1, hasClose:1;
434    bool embedded:1, unused2:1, hasMenuBar:1, isDocument:1, showInTaskBar:1, hasStatusBar:1, nonClient:1, clickThrough:1;
435 };
436
437 public enum BorderStyle : BorderBits
438 {
439    none,
440    contour      = BorderBits { contour = true },
441    fixed        = BorderBits { fixed = true } | contour,
442    sizable      = BorderBits { sizable = true } | fixed,
443    deep         = BorderBits { deep = true },
444    bevel        = BorderBits { bevel = true },
445    sizableDeep  = sizable|deep,
446    sizableBevel = sizable|bevel,
447    fixedDeep    = fixed|deep,
448    fixedBevel   = fixed|bevel,
449    deepContour  = deep|contour
450 };
451
452 public enum CreationActivationOption
453 {
454    activate, flash, doNothing
455 };
456
457 public enum WindowState { normal, minimized, maximized };
458
459 private class ResPtr : struct
460 {
461    ResPtr prev, next;
462    Resource resource;
463    void * loaded;
464 };
465
466 private class HotKeySlot : struct
467 {
468    HotKeySlot prev, next;
469    Window window;
470    Key key;
471 };
472
473 public class Window
474 {
475 private:
476    class_data char * icon;
477    class_no_expansion
478    class_default_property text;
479    // class_initialize GuiApplication::Initialize;
480    class_designer FormDesigner;
481    class_property char * icon
482    {
483       set { class_data(icon) = value; }
484       get { return class_data(icon); }
485    }
486
487    Window()
488    {
489       if(guiApp) guiApp.Initialize(true);
490
491       if(guiApp && guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
492       {
493          if(_vTbl == ((subclass(Window))_class).pureVTbl)
494          {
495             _vTbl = _class._vTbl;
496          }
497          else if(_vTbl != _class._vTbl)
498          {
499             int m;
500             for(m = 0; m < _class.vTblSize; m++)
501             {
502                if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
503                   _vTbl[m] = _class._vTbl[m];
504             }
505          }
506       }
507       
508       //tempExtents[0] = { /*first = -1, last = -1, free = -1*/ };
509       //tempExtents[1] = { /*first = -1, last = -1, free = -1*/ };
510       //tempExtents[2] = { /*first = -1, last = -1, free = -1*/ };
511       //tempExtents[3] = { /*first = -1, last = -1, free = -1*/ };
512
513       setVisible = true;
514
515       // caption = CopyString(class.name);
516
517       children.offset = (byte*)&prev - (byte*)this;
518       childrenOrder.circ = true;
519       childrenCycle.circ = true;
520
521       maxSize = Size { MAXINT, MAXINT };
522       background = white;
523       foreground = black;
524       
525       //style.isActiveClient = true;
526       mergeMenus = true;
527       autoCreate = true;
528       modifyVirtArea = true;
529       manageDisplay = true;
530
531       // scrollFlags = ScrollFlags { snapX = true, snapY = true };
532       sbStep.x = sbStep.y = 8;
533
534       if(guiApp)  // dynamic_cast<GuiApplication>(thisModule)
535       {
536          cursor = guiApp.GetCursor(arrow);
537          property::parent = guiApp.desktop;
538       }
539    }
540
541    ~Window()
542    {
543       Window child;
544       OldLink slave;
545       ResPtr ptr;
546
547       if(parent)
548          stopwatching(parent, font);
549
550       if(!destroyed)
551       { 
552          // Prevent destructor from being called again...
553          incref this;
554          incref this;
555          DestroyEx(0);
556       }
557
558       /////////////////////////////////
559       if(master)
560       {
561          OldLink slave = master.slaves.FindLink(this);
562          master.slaves.Delete(slave);
563          master = null;
564       }
565
566       if(parent)
567       {
568          if(cycle)
569             parent.childrenCycle.Remove(cycle);
570          if(order)
571             parent.childrenOrder.Remove(order);
572          parent.children.Remove(this);
573          parent = null;
574       }
575       delete cycle;
576       delete order;
577       /////////////////////////////////
578
579       while(ptr = resources.first)
580       {
581          delete ptr.resource;
582          resources.Delete(ptr);
583       }
584
585       usedFont = null;
586       delete setFont;
587       delete systemFont;
588
589       for(child = children.first; child; child = child.next)
590       {
591          // child.stopwatching(this, font);
592          if(child.parent)
593             eInstance_StopWatching(this, __ecereProp___ecereNameSpace__ecere__gui__Window_font, child);
594          // Don't want property here
595          *&child.parent = null;
596       }
597
598       while(slave = slaves.first)
599       {
600          // Don't want property here
601          *&((Window)slave.data).master = null;
602          slaves.Delete(slave);
603       }
604
605       // Because we do a decref in DestroyEx...
606       if(!destroyed)
607       {
608          incref this;
609          incref this;
610          DestroyEx(0);
611       }
612
613       // Why was this commented?
614       //if(this != guiApp.desktop)
615       {
616          delete caption;
617          delete fileName;
618       }
619
620       delete menu;
621       delete statusBar;
622
623       OnDestroyed();
624       delete mutex;
625       delete icon;
626
627       if(((subclass(Window))_class).pureVTbl)
628       {
629          if(_vTbl == _class._vTbl)
630          {
631             _vTbl = ((subclass(Window))_class).pureVTbl;
632          }
633          else
634          {
635             int m;
636             for(m = 0; m < _class.vTblSize; m++)
637             {
638                if(_vTbl[m] == _class._vTbl[m])
639                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
640             }
641          }
642       }
643       if(_vTbl == ((subclass(Window))_class).pureVTbl || _vTbl == _class._vTbl)
644          _vTbl = null;
645
646       dirtyArea.Free(null);
647       renderArea.Free(null);
648       overRenderArea.Free(null);
649       clipExtent.Free(null);
650       scrollExtent.Free(null);
651       dirtyBack.Free(null);
652
653       if(tempExtents)
654       {
655          tempExtents[0].Free(null);
656          tempExtents[1].Free(null);
657          tempExtents[2].Free(null);
658          tempExtents[3].Free(null);
659          delete tempExtents;
660       }
661    }
662
663 //#if !defined(ECERE_VANILLA)
664    char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
665    {
666       if(this == activeDesigner)
667          return "(Desktop)";
668       else 
669       {
670          char * name = property::name;
671          return name ? name : "";
672       }
673    }
674 //#endif
675
676 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
677    bool OnGetDataFromString(char * string)
678    {
679       FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
680       if(string[0])
681       {
682          if(!strcmp(string, "this") || !strcmp(string, designer.form.name))
683             this = designer.form;
684          else if(!strcmpi(string, "(Desktop)"))
685             this = activeDesigner;
686          else
687             return activeDesigner.FindObject(&this, string);
688       }
689       return true;
690    }
691 #endif
692
693    // --- Window updates system ---
694
695    // Setup a bitmap for Redrawing on client area of Window
696    Surface Redraw(Box box)
697    {
698       Surface surface = null;
699       Box mox = box;
700       Box clientArea = this.clientArea;
701
702       SetBox(clientArea);
703
704       mox.left   -= clientStart.x;
705       mox.top    -= clientStart.y;
706       mox.right  -= clientStart.x;
707       mox.bottom -= clientStart.y;
708       
709       mox.Clip(clientArea);
710       // mox.ClipOffset(against, scrolledPos.x, scrolledPos.y);
711
712       if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && mox.right >= mox.left && mox.bottom >= mox.top)
713       {
714          int x = absPosition.x + clientStart.x;
715          int y = absPosition.y + clientStart.y;
716          if(!guiApp.fullScreenMode || is3D)
717          {
718             x -= rootWindow.absPosition.x;
719             y -= rootWindow.absPosition.y;
720
721             if(rootWindow.is3D)
722             {
723                x += rootWindow.parent.clientStart.x;
724                y += rootWindow.parent.clientStart.y;
725                /*
726                mox.left += rootWindow.parent.clientStart.x;
727                mox.top += rootWindow.parent.clientStart.y;
728                mox.right += rootWindow.parent.clientStart.x;
729                mox.bottom += rootWindow.parent.clientStart.y;
730                */
731             }
732          }
733          surface = display.GetSurface(x, y, mox);
734          /*if(surface)
735          {
736             surface.width = clientSize.w;
737             surface.height = clientSize.h;
738          }*/
739       }
740       return surface;
741    }
742
743    // Setup a bitmap for Redrawing on full Window
744    Surface RedrawFull(Box box)
745    {
746       Surface surface = null;
747       Box mox;
748       if(box != null)
749          box.Clip(this.box);
750       else
751          box = &this.box;
752       mox = box;
753
754       if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && box.right >= box.left && box.bottom >= box.top)
755       {
756          int x = absPosition.x;
757          int y = absPosition.y;
758          if(!guiApp.fullScreenMode || is3D)
759          {
760             x -= rootWindow.absPosition.x;
761             y -= rootWindow.absPosition.y; 
762
763             if(rootWindow.is3D)
764             {
765                x += rootWindow.parent.clientStart.x;
766                y += rootWindow.parent.clientStart.y;
767                /*
768                mox.left += rootWindow.parent.clientStart.x;
769                mox.top += rootWindow.parent.clientStart.y;
770                mox.right += rootWindow.parent.clientStart.x;
771                mox.bottom += rootWindow.parent.clientStart.y;
772                */
773             }
774          }
775          surface = display.GetSurface(x, y, mox);
776          /*if(surface)
777          {
778             surface.width = size.w;
779             surface.height = size.h;
780          }*/
781       }
782       return surface;
783    }
784
785    void FigureCaption(char * caption)
786    {
787       caption[0] = '\0';
788       if(this.caption)
789          strcpy(caption, this.caption);
790       if(style.isDocument || fileName)
791       {
792          if(caption[0]) strcat(caption, " - ");
793          if(fileName)
794             strcat(caption, fileName);
795          else
796          {
797             char title[256];
798             sprintf(title, "Untitled %d", documentID);
799             strcat(caption, title);
800          }
801          if(modifiedDocument)
802             strcat(caption, " *");
803       }
804       if(activeClient && menuBar && 
805          activeClient.state == maximized)
806       {
807          if(activeClient.caption)
808          {
809             if(caption[0]) strcat(caption, " - ");
810             strcat(caption, activeClient.caption);
811          }
812          if(activeClient.style.isDocument || activeClient.fileName)
813          {
814             if(caption[0]) strcat(caption, " - ");
815             strcat(caption, "[");
816             if(activeClient.fileName)
817                strcat(caption, activeClient.fileName);
818             else
819             {
820                char title[256];
821                sprintf(title, "Untitled %d", activeClient.documentID);
822                strcat(caption, title);
823             }
824             if(activeClient.modifiedDocument)
825                strcat(caption, " *");
826             strcat(caption, "]");
827          }
828       }
829    }
830
831    // Code for returning dirty from ScrollDisplay:
832       /*
833       for(d = 0; d<scrollExtent.count; d++)
834       {
835          Box * box = &scrollExtent.boxes[d];
836          if(scroll.x < 0)
837          {
838             Box update
839             {
840                box.left, box.top,
841                Min(box.right, box.left-scroll.x),box.bottom
842             };
843             dirtyArea.UnionBox(update);
844          }
845          else if(scroll.x)
846          {
847             Box update
848             {
849                Max(box.left, box.right-scroll.x), box.top,
850                box.right, box.bottom
851             };
852             dirtyArea.UnionBox(update);
853          }
854
855          if(scroll.y < 0)
856          {
857             Box update
858             {
859                box.left, box.top,
860                box.right, Min(box.bottom, box.top-scroll.y),
861             };
862             dirtyArea.UnionBox(update);
863          }
864          else if(scroll.y)
865          {
866             Box update
867             {
868                box.left, Max(box.top, box.bottom-scroll.y),
869                box.right, box.bottom
870             };
871             dirtyArea.UnionBox(update);
872          }
873       }
874       */
875
876    void UpdateDecorations(void)
877    {
878       // TODO: *** TEMPORARY HACK ***
879       /*
880       if(parent)
881          parent.Update(null);
882       */
883
884       // Top
885       Update({ -clientStart.x, -clientStart.y, -clientStart.x + size.w-1, 0 });
886       // Bottom
887       Update({ -clientStart.x, clientSize.h, -clientStart.x + size.w-1, -clientStart.y + size.h-1 });
888       // Left
889       Update({ -clientStart.x,0, -1, clientSize.h-1 });
890       // Right
891       Update({ clientSize.w, 0, -clientStart.x + size.w-1, clientSize.h-1 });
892    }
893
894    // Returns w & h for Position
895    void ComputeAnchors(Anchor anchor, SizeAnchor sizeAnchor, int *ox, int *oy, int *ow, int *oh)
896    {
897       Window parent = this.parent ? this.parent : guiApp.desktop;
898       int vpw = parent ? parent.clientSize.w : 0;
899       int vph = parent ? parent.clientSize.h : 0;
900       int pw = parent ? parent.clientSize.w : 0;
901       int ph = parent ? parent.clientSize.h : 0;
902       int w = sizeAnchor.size.w, h = sizeAnchor.size.h;
903       int x = anchor.left.distance, y = anchor.top.distance;
904       float ex, ey;
905       MinMaxValue ew = 0, eh = 0;
906       int numCascade;
907       float cascadeW, cascadeH;
908       int numTiling;
909       int tilingW, tilingH, tilingSplit, tilingLastH;
910       int addX = 0, addY = 0;
911
912       if(parent && rootWindow == this && guiApp && guiApp.interfaceDriver)
913       {
914          Window masterWindow = this;
915          Box box { addX, addY, addX + vpw - 1, addY + vph - 1 };
916          if(!visible)
917          {
918             if(master == guiApp.desktop)
919                masterWindow = guiApp.desktop.activeChild;
920             else
921                masterWindow = master.rootWindow;
922             if(!masterWindow) masterWindow = this;
923          }
924          guiApp.interfaceDriver.GetScreenArea(masterWindow, box);
925          if((anchor.left.type == offset && anchor.right.type == offset) || anchor.left.type == none)
926          {
927             addX = box.left;
928             pw = vpw = box.right - box.left + 1;
929          }
930          if((anchor.top.type == offset && anchor.bottom.type == offset) || anchor.top.type == none)
931          {
932             addY = box.top;
933             ph = vph = box.bottom - box.top + 1;
934          }
935       }
936       
937       if(!parent)
938       {
939          *ow = w;
940          *oh = h;
941
942          *ox = x;
943          *oy = y;
944          return;
945       }
946
947       if(style.nonClient)
948       {
949          vpw = pw = parent.size.w;
950          vph = ph = parent.size.h;
951       }
952       else if(!style.fixed /*|| style.isDocument*/)
953       {
954          if(!style.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
955          if(!style.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
956       }
957 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
958       if(is3D)
959       {
960          Desktop3D_FixSize(&pw, &ph);
961          Desktop3D_FixSize(&vpw, &vph);
962       }
963 #endif
964       if(pw < skinMinSize.w) pw = skinMinSize.w;
965       if(ph < skinMinSize.h) ph = skinMinSize.h;
966       if(vpw < skinMinSize.w) vpw = skinMinSize.w;
967       if(vph < skinMinSize.h) vph = skinMinSize.h;
968
969       // TODO: Must fix what we're snapping
970       if(guiApp.textMode)
971       {
972          if(anchor.left.type)
973          {
974             SNAPUP(x, textCellW);
975          }
976          else if(anchor.right.type)
977          {
978             SNAPDOWN(x, textCellW);
979          }
980
981          if(anchor.top.type)
982          {
983             SNAPUP(y, textCellH);   
984          }
985          else if(anchor.bottom.type)
986          {
987             SNAPDOWN(y, textCellH);
988          }
989       }
990
991       GetDecorationsSize(&ew, &eh);
992
993       if(anchor.left.type >= cascade && (state == normal /*|| state == Hidden*/))
994       {
995          if(parent.sbv && !parent.sbv.style.hidden) 
996             pw += guiApp.currentSkin.VerticalSBW();
997          if(parent.sbh && !parent.sbh.style.hidden)
998             ph += guiApp.currentSkin.HorizontalSBH();
999
1000          if(anchor.left.type == cascade)
1001          {
1002             w = (int)(pw * 0.80);
1003             h = (int)(ph * 0.80);
1004          }
1005          else if(anchor.left.type >= vTiled)
1006          {
1007             int leftOver;
1008             int x2, y2;
1009
1010             numTiling = parent.numPositions - parent.numIcons;
1011             if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1012             if(anchor.left.type == vTiled)
1013             {
1014                tilingH = (int)sqrt(numTiling);
1015                tilingW = numTiling / tilingH;
1016             }
1017             else
1018             {
1019                tilingW = (int)sqrt(numTiling);
1020                tilingH = numTiling / tilingW;
1021             }
1022
1023             leftOver = numTiling - tilingH * tilingW;
1024             if(leftOver)
1025             {
1026                tilingSplit = (tilingW - leftOver) * tilingH;
1027                tilingLastH = tilingH+1;
1028             }
1029             else
1030                tilingSplit = numTiling;
1031
1032             if(positionID >= tilingSplit)
1033             {
1034                x = pw * (tilingSplit / tilingH + (positionID - tilingSplit) / tilingLastH)/tilingW;
1035                y = ph * ((positionID - tilingSplit) % tilingLastH) / tilingLastH;
1036                x2 = pw * (tilingSplit/tilingH + (positionID - tilingSplit) / tilingLastH + 1)/tilingW;
1037                y2 = ph * (((positionID - tilingSplit) % tilingLastH) + 1) / tilingLastH;
1038             }
1039             else
1040             {
1041                x = pw * (positionID / tilingH) / tilingW;
1042                y = ph * (positionID % tilingH) / tilingH;
1043                x2 = pw * (positionID / tilingH + 1) / tilingW;
1044                y2 = ph * ((positionID % tilingH) + 1) / tilingH;
1045             }
1046             if(guiApp.textMode)
1047             {
1048                SNAPDOWN(x, textCellW);
1049                SNAPDOWN(y, textCellH);
1050                SNAPDOWN(x2, textCellW);
1051                SNAPDOWN(y2, textCellH);
1052             }
1053             w = x2 - x;
1054             h = y2 - y;
1055          }
1056       }
1057       else
1058       {
1059          if(sizeAnchor.isClientW) w += ew;
1060          if(sizeAnchor.isClientH) h += eh;
1061          
1062          if(anchor.left.type == offset)
1063             x = anchor.left.distance;
1064          else if(anchor.left.type == relative)
1065             x = (anchor.left.percent < 0) ? ((int)(vpw * anchor.left.percent - 0.5)) : (int)(vpw * anchor.left.percent + 0.5);
1066          else if(anchor.right.type == relative)
1067             // ex = (anchor.right.percent < 0) ? ((int)(vpw * anchor.right.percent + 0)) : ((int)(vpw * anchor.right.percent + 0));
1068             ex = (anchor.right.percent < 0) ? ((int)(vpw * (1.0-anchor.right.percent) + 0)) : ((int)(vpw * (1.0-anchor.right.percent) + 0));
1069          else if(anchor.right.type == offset)
1070             ex = vpw - anchor.right.distance;
1071
1072          if(anchor.top.type == offset)
1073             y = anchor.top.distance;
1074          else if(anchor.top.type == relative)
1075             y = (anchor.top.percent < 0) ? ((int)(vph * anchor.top.percent - 0.5)) : ((int)(vph * anchor.top.percent + 0.5));
1076          else if(anchor.bottom.type == relative)
1077             //ey = (anchor.bottom.percent < 0) ? ((int)(vph * anchor.bottom.percent + 0)) : ((int)(vph * anchor.bottom.percent + 0));
1078             ey = (anchor.bottom.percent < 0) ? ((int)(vph * (1.0-anchor.bottom.percent) + 0)) : ((int)(vph * (1.0-anchor.bottom.percent) + 0));
1079          else if(anchor.bottom.type == offset)
1080             ey = vph - anchor.bottom.distance;
1081
1082          if(anchor.left.type && anchor.right.type)
1083          {
1084             switch(anchor.right.type)
1085             {
1086                case relative: 
1087                   ex = pw * (1.0f-anchor.right.percent); 
1088                   w = Max((int)(ex + 0.5) - x, 0);
1089                   break;
1090                case offset:
1091                   ex = vpw - anchor.right.distance;
1092                   w = Max((int)(ex + 0.5) - x, 0);
1093                   break;
1094             }
1095          }
1096          if(anchor.top.type && anchor.bottom.type)
1097          {
1098             switch(anchor.bottom.type)
1099             {
1100                case relative:
1101                   ey = ph * (1.0f-anchor.bottom.percent);
1102                   h = Max((int)(ey + 0.5) - y, 0);
1103                   break;
1104                case offset:
1105                   ey = vph - anchor.bottom.distance;
1106                   h = Max((int)(ey + 0.5) - y, 0);
1107                   break;
1108             }
1109          }
1110       }
1111
1112       w -= ew;
1113       h -= eh; 
1114
1115       if(state == normal /*|| state == Hidden*/)
1116       {
1117          bool addSbV = false, addSbH = false;
1118
1119          if(sizeAnchor.isClientW || (anchor.left.type && anchor.right.type))  w = Max(w, 1); else w = Max(w, 0);
1120          if(sizeAnchor.isClientH || (anchor.top.type && anchor.bottom.type))  h = Max(h, 1); else h = Max(h, 0);
1121
1122          w = Max(w, minSize.w);
1123          h = Max(h, minSize.h);
1124          w = Min(w, maxSize.w);
1125          h = Min(h, maxSize.h);
1126
1127          if((sizeAnchor.isClientW || !w || (anchor.left.type && anchor.right.type)) && reqScrollArea.h > h /*&& w*/ && sbv) 
1128          {
1129             if(w) w -= guiApp.currentSkin.VerticalSBW();
1130             addSbV = true;
1131          }
1132          if((sizeAnchor.isClientH || !h ||  (anchor.top.type && anchor.bottom.type)) && reqScrollArea.w > w /*&& h*/ && sbh) 
1133          {
1134             if(h) h -= guiApp.currentSkin.HorizontalSBH();
1135             addSbH = true;
1136          }
1137
1138          if(!OnResizing(&w, &h))
1139          {
1140             w = clientSize.w;
1141             h = clientSize.h;
1142          }
1143
1144          if((addSbV)) // || reqScrollArea.h > h) && sbv) 
1145             w += guiApp.currentSkin.VerticalSBW();
1146          if((addSbH)) // || reqScrollArea.w > w) && sbh)
1147             h += guiApp.currentSkin.HorizontalSBH();
1148
1149          w = Max(w, skinMinSize.w);
1150          h = Max(h, skinMinSize.h);
1151       }
1152       else
1153       {
1154          w = Max(w, 0);
1155          h = Max(h, 0);
1156       }
1157
1158       w += ew;
1159       h += eh; 
1160
1161       if(guiApp.textMode)
1162       {
1163          SNAPDOWN(w, textCellW);
1164          SNAPDOWN(h, textCellH);
1165       }
1166
1167       if(anchor.left.type == cascade && (state == normal /*|| state == Hidden*/))
1168       {
1169          if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1170
1171          numCascade = Min(
1172             (pw - w) / CASCADE_SPACE, 
1173             (ph - h) / CASCADE_SPACE);
1174          
1175          if(guiApp.textMode)
1176          {
1177                int cascW, cascH;
1178                numCascade++;
1179                cascW = (pw - w) / (numCascade-1);
1180                cascH = (ph - h) / (numCascade-1);
1181                SNAPDOWN(cascW, textCellW);
1182                SNAPDOWN(cascH, textCellH);
1183                cascadeW = (float)cascW;
1184                cascadeH = (float)cascH;
1185          }
1186          else
1187          {
1188             numCascade = Max(numCascade, 2);
1189             cascadeW = (float)(pw - w) / (numCascade-1);
1190             cascadeH = (float)(ph - h) / (numCascade-1);
1191          }
1192
1193          x = (int)((positionID % numCascade) * cascadeW);
1194          y = (int)((positionID % numCascade) * cascadeH);
1195       }
1196       else if(anchor.left.type < vTiled)
1197       {
1198          if(!anchor.left.type || anchor.horz.type == middleRelative)
1199          {
1200             if(!anchor.right.type)
1201             {
1202                if(anchor.horz.type == middleRelative)
1203                   x = (int)(vpw * (0.5 + anchor.horz.percent) - w / 2);
1204                else
1205                   x = vpw / 2 + anchor.horz.distance - w / 2;
1206             }
1207             else
1208                x = (int)(ex - w);
1209          }
1210
1211          // case A_EDGE: x = x - w; break;
1212
1213          if(!anchor.top.type || anchor.vert.type == middleRelative)
1214          {
1215             if(!anchor.bottom.type)
1216             {
1217                if(anchor.vert.type == middleRelative)
1218                   y = (int)(vph * (0.5 + anchor.vert.percent) - h / 2);
1219                else
1220                   y = vph / 2 + anchor.vert.distance - h / 2;      
1221             }
1222             else
1223                y = (int)(ey - h);
1224          }
1225
1226          // case A_EDGE: y = y - h; break;
1227       }
1228
1229       if((state == normal /*|| state == Hidden*/) && !OnMoving(&x, &y, w, h))
1230       {
1231          x = position.x;
1232          y = position.y;
1233       }
1234
1235       if(guiApp.textMode)
1236       {
1237          SNAPDOWN(x, textCellW);
1238          SNAPDOWN(y, textCellH);
1239       }
1240
1241       x += addX;
1242       y += addY;
1243
1244       *ow = w;
1245       *oh = h;
1246
1247       *ox = x;
1248       *oy = y;
1249
1250       if(anchored && style.fixed && style.isActiveClient)
1251          anchored = false;
1252    }
1253
1254    // --- Carets ---
1255    void UpdateCaret(bool forceUpdate, bool erase)
1256    {
1257       static Window lastWindow = null;
1258       static int caretX, caretY, caretSize;
1259
1260       if(guiApp && guiApp.caretOwner == this)
1261       {
1262          int x = caretPos.x - scroll.x;
1263          int y = caretPos.y - scroll.y;
1264
1265          if((erase || this.caretSize) &&
1266             x >= clientArea.left && x <= clientArea.right && 
1267             y >= clientArea.top  && y <= clientArea.bottom)
1268          {
1269             if(!erase)
1270             {
1271                guiApp.interfaceDriver.SetCaret(
1272                   x + absPosition.x + clientStart.x, 
1273                   y + absPosition.y + clientStart.y, this.caretSize);
1274                guiApp.caretEnabled = true;
1275             }
1276             if(erase || lastWindow != this || caretX != x || caretY != y || caretSize != this.caretSize || forceUpdate)
1277             {
1278                Box updateBox;
1279
1280                if(lastWindow != this)
1281                {
1282                   updateBox.left = x + 1;
1283                   updateBox.top = y;
1284                   updateBox.right = x + 2;
1285                   updateBox.bottom = y + this.caretSize - 1;
1286                }
1287                else
1288                {
1289                   updateBox.left = Min(x + 1, caretX + 1);
1290                   updateBox.top = Min(y, caretY);
1291                   updateBox.right = Max(x + 2, caretX + 2);
1292                   updateBox.bottom = Max(y + this.caretSize - 1, caretY + caretSize - 1);
1293                }
1294
1295                guiApp.caretOwner.Update(updateBox);
1296
1297                if(!erase)
1298                {
1299                   lastWindow = this;
1300                   caretX = x;
1301                   caretY = y;
1302                   caretSize = this.caretSize;
1303                }
1304             }
1305          }
1306          else
1307          {
1308             guiApp.interfaceDriver.SetCaret(0,0,0);
1309             guiApp.caretEnabled = false;
1310             lastWindow = null;
1311          }
1312       }
1313    }
1314
1315    void SetPosition(int x, int y, int w, int h, bool modifyArea, bool modifyThisArea, bool modifyClientArea)
1316    {
1317       Window child;
1318
1319       // Set position
1320       scrolledPos.x = position.x = x;
1321       scrolledPos.y = position.y = y;
1322
1323       clientSize.w = size.w = w;
1324       clientSize.h = size.h = h;
1325
1326       if(parent && !style.nonClient)
1327       {
1328          //if(!style.fixed || style.isDocument)
1329          {
1330             if(!style.dontScrollHorz) scrolledPos.x -= parent.scroll.x;
1331             if(!style.dontScrollVert) scrolledPos.y -= parent.scroll.y;
1332          }
1333       }
1334
1335       clientStart.x = clientStart.y = 0;
1336
1337       SetWindowArea(&clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1338
1339       //if(!activeClient || activeClient.state != maximized)
1340       if(!noAutoScrollArea)
1341       {
1342          // Check if scroll area must be modified
1343          if(guiApp && !guiApp.modeSwitching && (sbv || sbh))
1344          {
1345             bool foundChild = false;
1346             int w = 0, h = 0;
1347             int cw = clientSize.w;// + ((!sbv || sbv.range > 1) ? guiApp.currentSkin.VerticalSBW() : 0);
1348             int ch = clientSize.h;// + ((!sbh || sbh.rangw > 1) ? guiApp.currentSkin.HorizontalSBH() : 0);
1349             for(child = children.first; child; child = child.next)
1350             {
1351                if(child.modifyVirtArea && !child.style.hidden && child.created && /*!child.anchored &&*/
1352                   !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1353                {
1354                   if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == offset)
1355                      w = Max(w, child.position.x + child.size.w);
1356                   else if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == none)
1357                      w = Max(w, Max(child.position.x, 0) + child.size.w);
1358                   if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == offset)
1359                      h = Max(h, child.position.y + child.size.h);
1360                   else if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == none)
1361                      h = Max(h, Max(child.position.y, 0) + child.size.h);
1362
1363                   foundChild = true;
1364                }
1365             }
1366             if(foundChild && (w > cw || h > ch))
1367             {
1368                //if((w > reqScrollArea.w) || (h > reqScrollArea.w))
1369                {
1370                   int stepX = sbStep.x, stepY = sbStep.y;
1371                   // Needed to make snapped down position match the skin's check of client area 
1372                   // against realvirtual
1373                   if(guiApp.textMode)
1374                   {
1375                      SNAPDOWN(stepX, textCellW);
1376                      SNAPDOWN(stepY, textCellH);
1377                      stepX = Max(stepX, textCellW);
1378                      stepY = Max(stepY, textCellH);
1379                   }
1380                   if(scrollFlags.snapX)
1381                      SNAPUP(w, stepX);
1382                   if(scrollFlags.snapY)
1383                      SNAPUP(h, stepY);
1384
1385                   reqScrollArea.w = w;
1386                   reqScrollArea.h = h;
1387                }
1388             }
1389             else if(reqScrollArea.w || reqScrollArea.h)
1390             {
1391                reqScrollArea.w = 0;
1392                reqScrollArea.h = 0;
1393                SetScrollPosition(0,0);
1394             }
1395          }
1396       }
1397
1398       // Automatic MDI Client Scrolling Area Adjustment
1399       if(parent && !parent.noAutoScrollArea)
1400       {
1401          if(modifyArea && modifyVirtArea /*&& !anchored*/ && (parent.sbv || parent.sbh) && 
1402             !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient)
1403          {
1404             Window parent = this.parent;
1405             int w = parent.reqScrollArea.w;
1406             int h = parent.reqScrollArea.h;
1407
1408             if(stateAnchor.right.type == none && stateAnchor.left.type == offset)
1409                w = Max(w, position.x + size.w);
1410             else if(stateAnchor.right.type == none && stateAnchor.left.type == none)
1411                w = Max(w, Max(position.x, 0) + size.w);
1412             if(stateAnchor.bottom.type == none && stateAnchor.top.type == offset)
1413                h = Max(h, position.y + size.h);
1414             else if(stateAnchor.bottom.type == none && stateAnchor.top.type == none)
1415                h = Max(h, Max(position.y, 0) + size.h);
1416
1417             if((w > parent.clientSize.w && w > parent.reqScrollArea.w) || 
1418                (h > parent.clientSize.h && h > parent.reqScrollArea.h))
1419             {
1420                /*bool resize = false;
1421                int stepX = parent.sbStep.x, stepY = parent.sbStep.y;
1422                // Needed to make snapped down position match the skin's check of client area 
1423                // against realvirtual
1424                if(guiApp.textMode)
1425                {
1426                   SNAPDOWN(stepX, textCellW);
1427                   SNAPDOWN(stepY, textCellH);
1428                   stepX = Max(stepX, textCellW);
1429                   stepY = Max(stepY, textCellH);
1430                }
1431                if(parent.scrollFlags.snapX)
1432                   SNAPUP(w, stepX);
1433                if(parent.scrollFlags.snapY)
1434                   SNAPUP(h, stepY);
1435                if(parent.reqScrollArea.w != w || parent.reqScrollArea.h != h)
1436                {
1437                   parent.reqScrollArea.w = w;
1438                   parent.reqScrollArea.h = h;*/
1439
1440                  // parent.UpdateScrollBars(true, true);
1441                   parent.Position(parent.position.x, parent.position.y, parent.size.w, parent.size.h, 
1442                      false, true, true, true, false, false);
1443                   return;
1444                //}
1445             }
1446             else 
1447                GetRidOfVirtualArea();
1448          }
1449       }
1450       if(modifyThisArea)
1451          UpdateScrollBars(modifyThisArea, false);
1452       else if(guiApp.currentSkin)
1453       {
1454          SetWindowArea(
1455             &clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1456
1457          if(sbv && (scrollFlags.dontHide || sbv.range > 1))
1458             clientSize.w -= guiApp.currentSkin.VerticalSBW();
1459          if(sbh && (scrollFlags.dontHide || sbh.range > 1))
1460             clientSize.h -= guiApp.currentSkin.HorizontalSBH();
1461       }
1462
1463       scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1464       scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1465
1466       absPosition = scrolledPos;
1467       if(guiApp && guiApp.driver != null && guiApp.interfaceDriver)
1468          guiApp.interfaceDriver.OffsetWindow(this, &absPosition.x, &absPosition.y);
1469
1470       if(this != guiApp.desktop && parent)
1471       {
1472          absPosition.x += parent.absPosition.x;
1473          absPosition.y += parent.absPosition.y;
1474          if(!style.nonClient && this != guiApp.desktop)
1475          {
1476             absPosition.x += parent.clientStart.x;
1477             absPosition.y += parent.clientStart.y;
1478          }
1479       }
1480
1481       box = Box { 0, 0, size.w - 1, size.h - 1 };
1482       SetBox(box);
1483
1484       if(against)
1485       {
1486          // Clip against parent's client area
1487          box.ClipOffset(against, scrolledPos.x, scrolledPos.y);
1488       }
1489       // Compute client area in this window coordinate system
1490       clientArea.left = 0;
1491       clientArea.top = 0;
1492       clientArea.right = clientSize.w - 1;
1493       clientArea.bottom = clientSize.h - 1;
1494
1495       // Clip against parent's client area
1496       if(against)
1497          clientArea.ClipOffset(against, scrolledPos.x + clientStart.x, scrolledPos.y + clientStart.y);
1498
1499       if(is3D)
1500       {
1501          //absPosition.x -= parent.clientStart.x;
1502          //absPosition.y -= parent.clientStart.y;
1503       }
1504
1505       // Adjust all children
1506       for(child = children.first; child; child = child.next)
1507          child.SetPosition(child.position.x, child.position.y, child.size.w, child.size.h, false, true, true);
1508
1509       UpdateCaret(false, false);
1510    }
1511
1512    void GetRidOfVirtualArea(void)
1513    {
1514       if(parent && !parent.destroyed && style.fixed &&
1515          !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient &&
1516          parent.reqScrollArea.w && parent.reqScrollArea.h)
1517       {
1518          if(!parent.noAutoScrollArea)
1519          {
1520             Window child;
1521             bool found = false;
1522             for(child = children.first; child; child = child.next)
1523             {
1524                if(child.modifyVirtArea && !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1525                {
1526                   if(child.position.x + child.size.w > parent.clientSize.w + ((!parent.sbv || parent.sbv.style.hidden) ? 0 : guiApp.currentSkin.VerticalSBW()) ||
1527                      child.position.y + child.size.h > parent.clientSize.h + ((!parent.sbh || parent.sbh.style.hidden) ? 0 : guiApp.currentSkin.HorizontalSBH()))
1528                   {
1529                      found = true;
1530                      break;
1531                   }
1532                }
1533             }
1534             //if(!found)
1535             {
1536                Window parent = this.parent;
1537                parent.Position(
1538                   parent.position.x, parent.position.y, parent.size.w, parent.size.h, 
1539                   false, true, true, true, false, false);
1540                /*
1541                parent.SetScrollArea(0,0,true);
1542                parent.SetScrollPosition(0,0);
1543                */
1544             }
1545          }
1546       }
1547    }
1548    public void ExternalPosition(int x, int y, int w, int h)
1549    {
1550       Position(x, y, w, h, false, true, true, true, false, false);
1551    }
1552
1553    // (w, h): Full window size
1554    bool Position(int x, int y, int w, int h, bool force, bool processAnchors, bool modifyArea, bool updateScrollBars, bool thisOnly, bool changeRootWindow)
1555    {
1556       bool result = false;
1557       int oldCW = clientSize.w, oldCH = clientSize.h;
1558       bool clientResized, windowResized, windowMoved;
1559       Window child;
1560       bool realResized = size.w != w || size.h != h;
1561
1562       // TOCHECK: This wasn't in ecere.dll
1563       //if(!parent) return true;
1564       if(destroyed) return false;
1565
1566       windowMoved = position.x != x || position.y != y || force;
1567
1568       // windowResized = realResized || force;
1569       windowResized = size.w != w || size.h != h || force;
1570      
1571       if(rootWindow != this && display && !display.flags.flipping && scrolledPos.x != MININT)
1572       {
1573          if(style.nonClient)
1574          {
1575             Box box
1576             { 
1577                scrolledPos.x - parent.clientStart.x + this.box.left, scrolledPos.y - parent.clientStart.y + this.box.top, 
1578                scrolledPos.x - parent.clientStart.x + this.box.right,
1579                scrolledPos.y - parent.clientStart.y + this.box.bottom 
1580             };
1581             parent.Update(box);
1582          }
1583          else
1584          {
1585             Box box { scrolledPos.x + this.box.left, scrolledPos.y + this.box.top, scrolledPos.x + this.box.right, scrolledPos.y + this.box.bottom};
1586             parent.Update(box);
1587          }
1588       }
1589
1590       SetPosition(x, y, w, h, true, modifyArea, updateScrollBars);
1591
1592       clientResized = oldCW != clientSize.w || oldCH != clientSize.h || force;
1593
1594       if(display && rootWindow != this)
1595          Update(null);
1596
1597       if(guiApp && guiApp.windowMoving)
1598       {
1599          if(guiApp.windowMoving.style.nonClient)
1600             guiApp.windowMoving.parent.SetMouseRangeToWindow();
1601          else
1602             guiApp.windowMoving.parent.SetMouseRangeToClient();
1603       }
1604
1605       if(!positioned)
1606       {
1607          positioned = true;
1608          if(clientResized)
1609          {
1610             if(!thisOnly)
1611             {
1612                UpdateNonClient();
1613
1614                // Process Anchored Children
1615                if(processAnchors)
1616                {
1617                   int x,y,w,h;
1618                   for(child = children.first; child; child = child.next)
1619                   {
1620                      if(child.created && 
1621                      ((child.stateAnchor.left.type != offset ||
1622                        child.stateAnchor.top.type != offset ||
1623                        child.stateAnchor.right.type != none ||
1624                        child.stateAnchor.bottom.type != none) ||
1625                         child.state == maximized || child.state == minimized))
1626                      {
1627                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor,
1628                            &x, &y, &w, &h);
1629                         // child.Position(x, y, w, h, false, true, true, true, false);
1630                         // This must be true cuz otherwise we're gonna miss everything since we SetPosition recursively already
1631                         child.Position(x, y, w, h, true, true, true, true, false, true /*false*/);
1632                      }
1633                   }
1634                }
1635             }
1636
1637             // Is this gonna cause other problems? Commented out for the FileDialog end bevel bug
1638             //if(updateScrollBars)
1639             if(created)
1640                OnResize(clientSize.w, clientSize.h);
1641          }
1642          if((clientResized || windowMoved) && created)
1643             OnPosition(position.x, position.y, clientSize.w, clientSize.h);
1644    /*
1645          if(guiApp.interimWindow && guiApp.interimWindow.master.rootWindow == this)
1646          {
1647             Window master = guiApp.interimWindow.master;
1648             master.OnPosition(master.position.x, master.position.y, master.clientSize.w, master.clientSize.h);
1649          }
1650    */
1651          if(rootWindow == this && !is3D)
1652          {
1653             /*if(style.interim)
1654             {
1655                x -= guiApp.desktop.absPosition.x;
1656                y -= guiApp.desktop.absPosition.y;
1657             }*/
1658             //guiApp.Log("Position %s\n", caption);
1659             if(windowResized || windowMoved)
1660                if(display && !display.flags.memBackBuffer && changeRootWindow)
1661                   guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
1662
1663             if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
1664                for(child = parent.children.first; child && child != this; child = child.next)
1665                   if(child.rootWindow)
1666                      guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
1667
1668             if(display)
1669             {
1670                if(windowMoved || windowResized)
1671                {
1672                   display.Lock(true /*false*/);
1673                }
1674                if(windowMoved)
1675                   display.Position(absPosition.x, absPosition.y);
1676                if(windowResized)
1677                {
1678                   // result = realResized ? display.Resize(size.w, size.h) : true;
1679                   result = manageDisplay ? display.Resize(size.w, size.h) : true;
1680                   resized = true;
1681                   Update(null);
1682                }
1683                else if(clientResized)
1684                   Update(clientArea);
1685                // --- Major Slow Down / Fix OpenGL Resizing Main Window Lag
1686                
1687                /*
1688                if(!guiApp.fullScreenMode && !guiApp.modeSwitching && this == rootWindow)
1689                   UpdateDisplay();
1690                */
1691                
1692                if(windowMoved || windowResized)
1693                {
1694                   display.Unlock();
1695                }
1696             }
1697             if(guiApp.driver && changeRootWindow)
1698             {
1699                if(windowResized || windowMoved)
1700                   if(!display || display.flags.memBackBuffer)
1701                      guiApp.interfaceDriver.PositionRootWindow(this, 
1702                         x, y, w, h, windowMoved, windowResized);
1703                guiApp.interfaceDriver.UpdateRootWindow(this);
1704             }
1705             for(child = children.first; child; child = child.next)
1706             {
1707                if(child.is3D && child.created)
1708                {
1709                   // Copy Display Content
1710                   child.display.displaySystem = display.displaySystem;
1711                   child.display.window = display.window;
1712                   child.display.current = display.current;
1713                   child.display.width = display.width;
1714                   child.display.height = display.height;
1715                   child.display.driverData = display.driverData;
1716                   child.display.mutex = null;
1717                }
1718             }
1719          }
1720          else
1721             result = true;
1722          positioned = false;
1723       }
1724       return result;
1725    }
1726
1727    void UpdateScrollBars(bool flag, bool fullThing)
1728    {
1729       int rvw, rvh;
1730       bool resizeH = false, resizeV = false;
1731       bool scrolled = false;
1732       rvw = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.w;
1733       rvh = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.h;
1734
1735       if(destroyed) return;
1736       if(guiApp.currentSkin)
1737       {
1738          MinMaxValue cw = 0, ch = 0;
1739          bool sbvVisible, sbhVisible;
1740          int rangeH, rangeV;
1741          int positionH, positionV;
1742
1743          // First get client area with no respect to scroll bars
1744
1745          if(flag)
1746          {
1747             SetWindowArea(
1748                &clientStart.x, &clientStart.y, &size.w, &size.h, &cw, &ch);
1749
1750             if(scrollFlags.dontHide)
1751             {
1752                if(sbv)
1753                   cw -= guiApp.currentSkin.VerticalSBW();
1754                if(sbh)
1755                   ch -= guiApp.currentSkin.HorizontalSBH();
1756
1757                // Update the scrollbar visibility
1758                if(sbh)
1759                {
1760                   sbh.seen = cw;
1761                   sbh.total = rvw;
1762                   rangeH = sbh.range;
1763                   sbh.disabled = rangeH <= 1;
1764                   if(sbh.style.hidden)
1765                   {
1766                      resizeH = true;
1767                   }
1768                }
1769                if(sbv)
1770                {
1771                   sbv.seen = ch;
1772                   sbv.total = rvh;
1773                   rangeV = sbv.range;
1774                   sbv.disabled = rangeV <= 1;
1775                   if(sbv.style.hidden)
1776                   {
1777                      resizeV = true;
1778                   }
1779                }
1780             }
1781             else
1782             {
1783                // Then start off with horizontal scrollbar range
1784                if(sbh)
1785                {
1786                   positionH = sbh.thumbPosition;
1787                   sbh.seen = cw;
1788                   sbh.total = rvw;
1789                   rangeH = sbh.range;
1790                   if(rangeH > 1)
1791                      ch -= guiApp.currentSkin.HorizontalSBH();
1792                }
1793
1794                // Do the same for vertical scrollbar
1795                if(sbv)
1796                {
1797                   positionV = sbv.thumbPosition;
1798                   sbv.seen = ch;
1799                   sbv.total = rvh;
1800                   rangeV = sbv.range;
1801                   if(rangeV > 1)
1802                   {
1803                      cw -= guiApp.currentSkin.VerticalSBW();
1804                      // Maybe we need to set the range on the horizontal scrollbar again
1805                      if(sbh)
1806                      {
1807                         sbh.seen = cw;
1808                         sbh.total = rvw;
1809                         sbh.Action(setRange, positionH, 0);
1810                         if(rangeH <= 1 && sbh.range > 1)
1811                         {
1812                            ch -= guiApp.currentSkin.HorizontalSBH();
1813                            sbv.seen = ch;
1814                            sbv.total = rvh;
1815                            rangeV = sbv.range;
1816                            sbv.Action(setRange, positionV, 0);
1817                         }
1818                         rangeH = sbh.range;
1819                      }
1820                   }
1821                }
1822
1823                // Update the scrollbar visibility
1824                if(!scrollFlags.dontHide)
1825                {
1826                   if(sbh && ((rangeH <= 1 && !sbh.style.hidden) || (rangeH > 1 && sbh.style.hidden)))
1827                   {
1828                      resizeH = true;
1829                   }
1830                   if(sbv && ((rangeV <= 1 && !sbv.style.hidden) || (rangeV > 1 && sbv.style.hidden)))
1831                   {
1832                      resizeV = true;
1833                   }
1834                }
1835             }
1836
1837             if(guiApp.currentSkin)
1838             {
1839                clientSize.w = cw;
1840                clientSize.h = ch;
1841             }
1842
1843             if(resizeH)
1844                sbhVisible = sbh.style.hidden ? true : false;
1845             if(resizeV)
1846                sbvVisible = sbv.style.hidden ? true : false;
1847
1848             // Do our resize here
1849             if(flag && (resizeH || resizeV) && fullThing)
1850             {
1851                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, false);
1852                
1853                if(!positioned)
1854                {
1855                   positioned = true;
1856                   OnResize(clientSize.w, clientSize.h);
1857                   positioned = false;
1858                }
1859             }
1860       
1861             if(resizeH && sbh)
1862                sbh.visible = sbhVisible;
1863             if(resizeV && sbv)
1864                sbv.visible = sbvVisible;
1865          }
1866          scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1867          scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1868
1869          if(sbh)
1870             sbh.pageStep = clientSize.w;
1871          if(sbv)
1872             sbv.pageStep = clientSize.h;
1873
1874          // Notify doesn't handle setRange anymore... process it here
1875          if(sbh)
1876          {
1877             int positionH = sbh.thumbPosition;
1878             if(scroll.x != positionH)
1879             {
1880                OnHScroll(setRange, positionH, 0);
1881                scrolled = true;
1882             }
1883             if(guiApp.textMode)
1884                SNAPDOWN(positionH, textCellW);
1885             scroll.x = positionH;
1886          }
1887          else
1888          {
1889             int x = scroll.x;
1890             int range;
1891             int seen = clientSize.w, total = reqScrollArea.w;
1892             seen = Max(1,seen);
1893
1894             if(scrollFlags.snapX)
1895                SNAPDOWN(seen, sbStep.x);
1896
1897             if(!total) total = seen;
1898             range = total - seen + 1;
1899
1900             range = Max(range, 1);
1901             if(x < 0) x = 0;
1902             if(x >= range) x = range - 1;
1903
1904             if(scrollFlags.snapX)
1905                SNAPUP(x, sbStep.x);
1906
1907             if(scroll.x != x)
1908             {
1909                OnHScroll(setRange, x, 0);
1910             }
1911
1912             if(guiApp.textMode)
1913             {
1914                SNAPDOWN(x, textCellW);
1915             }
1916             scroll.x = x;
1917          }
1918          if(sbv)
1919          {
1920             int positionV = sbv.thumbPosition;
1921             if(scroll.y != positionV)
1922             {
1923                OnVScroll(setRange, positionV, 0);
1924                scrolled = true;
1925             }
1926             if(guiApp.textMode)
1927                SNAPDOWN(positionV, textCellH);
1928             scroll.y = positionV;
1929          }
1930          else
1931          {
1932             int y = scroll.y;
1933             int range;
1934             int seen = clientSize.h, total = reqScrollArea.h;
1935             seen = Max(1,seen);
1936
1937             if(scrollFlags.snapY)
1938                SNAPDOWN(seen, sbStep.y);
1939
1940             if(!total) total = seen;
1941             range = total - seen + 1;
1942             range = Max(range, 1);
1943             if(y < 0) y = 0;
1944             if(y >= range) y = range - 1;
1945
1946             if(scrollFlags.snapY)
1947                SNAPUP(y, sbStep.y);
1948
1949             if(scroll.y != y)
1950             {
1951                OnVScroll(setRange, y, 0);
1952             }
1953
1954             if(guiApp.textMode)
1955             {
1956                SNAPDOWN(y, textCellH);
1957             }
1958             scroll.y = y;
1959          }
1960
1961          /*
1962          if(scrolled || (resizeH || resizeV))   // This ensures children anchored to bottom/right gets repositioned correctly
1963          {
1964             Window child;
1965             for(child = children.first; child; child = child.next)
1966             {
1967                if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
1968                {
1969                   int x,y,w,h;
1970                   child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
1971                   child.Position(x, y, w, h, false, true, false, true, false, false);
1972                }
1973             }
1974          }
1975          */
1976       }
1977
1978       // Process Scrollbars
1979
1980       if(sbh) // && !sbh.style.hidden
1981       {
1982          sbh.Move(clientStart.x, clientStart.y + clientSize.h, clientSize.w,0);
1983          // Need to set the range again (should improve...) since the scrollbars didn't have
1984          // the right size when UpdateScrollArea set the range on it
1985          if(flag)
1986          {
1987             sbh.seen = clientSize.w;
1988             sbh.total = rvw;
1989          }
1990       }
1991       if(sbv) // && !sbv.state.hidden
1992       {
1993          sbv.Move(clientStart.x + clientSize.w, clientStart.y, 0, clientSize.h);
1994          // Need to set the range again (should improve...) since the scrollbars didn't have
1995          // the right size when UpdateScrollArea set the range on it
1996          if(flag)
1997          {
1998             sbv.seen = clientSize.h;
1999             sbv.total = rvh;
2000          }
2001       }
2002
2003       // TESTING THIS LOWER
2004       if(scrolled || (resizeH || resizeV))   // This ensures children anchored to bottom/right gets repositioned correctly
2005       {
2006          Window child;
2007          for(child = children.first; child; child = child.next)
2008          {
2009             if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2010             {
2011                int x,y,w,h;
2012                child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2013                child.Position(x, y, w, h, false, true, false, true, false, false);
2014             }
2015          }
2016       }
2017    }
2018
2019    bool MaximizeButtonClicked(Button button, int x, int y, Modifiers mods)
2020    {
2021       SetState(maximized, false, mods);
2022       return false;
2023    }
2024
2025    bool RestoreButtonClicked(Button button, int x, int y, Modifiers mods)
2026    {
2027       SetState(normal, false, mods);
2028       return false;
2029    }
2030
2031    bool MinimizeButtonClicked(Button button, int x, int y, Modifiers mods)
2032    {
2033       SetState(minimized, false, mods);
2034       parent.CycleChildren(false, true, false, true);
2035       return false;
2036    }
2037
2038    void ScrollBarNotification(ScrollBar control, ScrollBarAction action, int position, Key keyFlags)
2039    {
2040       Window child;
2041       // Scroll bar notifications
2042       if(action != setRange)
2043       {
2044          bool changed = false;
2045
2046          if(control == sbh)
2047          {
2048             if(scroll.x != position)
2049             {
2050                OnHScroll(action, position, keyFlags);
2051                changed = true;
2052             }
2053             if(guiApp.textMode)
2054             {
2055                SNAPDOWN(position, textCellW);
2056             }
2057             scroll.x = position;
2058          }
2059          else
2060          {
2061             if(scroll.y != position)
2062             {
2063                OnVScroll(action, position, keyFlags);
2064                changed = true;
2065             }
2066             if(guiApp.textMode)
2067             {
2068                SNAPDOWN(position, textCellH);
2069             }
2070             scroll.y = position;
2071          }
2072          if(changed)
2073          {
2074             bool childMove = false;
2075             for(child = children.first; child; child = child.next)
2076             {
2077                if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2078                {
2079                   int x,y,w,h;
2080                   child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2081                   child.Position(x, y, w, h, false, true, false, true, false, false);
2082                   childMove = true;
2083                }
2084             }
2085             // Testing this patch out to solve MDI workspace redraw bugs
2086             // We were already supposed to be updating parent's affected area in Position() but it doesn't seem to be working
2087             // Scroll offsets to blame?
2088             if(childMove)
2089                Update(null);
2090          }
2091          UpdateCaret(false, false);
2092       }
2093       else
2094       {
2095          // Testing this patch out to solve MDI workspace redraw bugs
2096          for(child = children.first; child; child = child.next)
2097          {
2098             if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2099             {
2100                Update(null);
2101                break;
2102             }
2103          }         
2104       }
2105    }
2106
2107    void CreateSystemChildren(void)
2108    {
2109       Window parent = this;
2110       bool scrollBarChanged = false;
2111       bool hasClose = false, hasMaxMin = false;
2112       Point scroll = this.scroll;
2113
2114       if(state == maximized && this.parent.menuBar)
2115       {
2116          if(this.parent.activeClient == this)
2117             parent = this.parent.menuBar;
2118          else
2119             parent = null;
2120       }
2121
2122       if(parent)
2123       {
2124          if(style.hasClose) hasClose = true;
2125          if(style.hasMaximize || style.hasMinimize)
2126          {
2127             hasClose = true;
2128             hasMaxMin = true;
2129          }
2130       }
2131
2132       if(sysButtons[2] && (!hasClose || sysButtons[2].parent != parent))
2133       {
2134          sysButtons[2].Destroy(0);
2135          sysButtons[2] = null;
2136       }
2137       if(sysButtons[1] && (!hasMaxMin || sysButtons[1].parent != parent))
2138       {
2139          sysButtons[1].Destroy(0);
2140          sysButtons[1] = null;
2141       }
2142       if(sysButtons[0] && (!hasMaxMin || sysButtons[0].parent != parent))
2143       {
2144          sysButtons[0].Destroy(0);
2145          sysButtons[0] = null;
2146       }
2147       //return;
2148       if(hasClose && parent)
2149       {
2150          if(!sysButtons[2])
2151          {
2152             sysButtons[2] = 
2153                Button
2154                {
2155                   parent, master = this,
2156                   inactive = true, nonClient = true, visible = false;
2157
2158                   bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2159                   {
2160                      Destroy(0);
2161                      return true;
2162                   }
2163                };
2164             if(this.parent == guiApp.desktop)
2165                sysButtons[2].hotKey = altF4;
2166             else if(style.isActiveClient)
2167                sysButtons[2].hotKey = ctrlF4;
2168             sysButtons[2].Create();
2169          }
2170          
2171          sysButtons[2].symbol = 'X';
2172          sysButtons[2].disabled = !style.hasClose;
2173       }
2174
2175       if(hasMaxMin && parent)
2176       {
2177          SkinBitmap skin;
2178          unichar symbol;
2179          bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2180          if(state == maximized) 
2181          {
2182             skin = restore;
2183             method = RestoreButtonClicked;
2184             symbol = '\x12';
2185          }
2186          else
2187          {
2188             skin = maximize;
2189             method = MaximizeButtonClicked;
2190             symbol = '\x18';
2191          }
2192          if(!sysButtons[1])
2193          {
2194             sysButtons[1] =
2195                Button
2196                {
2197                   parent, master = this,
2198                   hotKey = altEnter, inactive = true, nonClient = true, visible = false
2199                };
2200             sysButtons[1].Create();
2201          }
2202          sysButtons[1].NotifyClicked = method;
2203
2204          sysButtons[1].symbol = symbol;
2205          sysButtons[1].disabled = !style.hasMaximize;
2206       }
2207
2208       if(hasMaxMin && parent)
2209       {
2210          SkinBitmap skin;
2211          unichar symbol;
2212          bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2213          if (state == minimized) 
2214          {
2215             skin = restore;
2216             method = RestoreButtonClicked;
2217             symbol = '\x12';
2218          }
2219          else
2220          {
2221             skin = minimize;
2222             method = MinimizeButtonClicked;
2223             symbol = '\x19';
2224          }
2225          if(!sysButtons[0])
2226          {
2227             sysButtons[0] =
2228                Button
2229                {
2230                   parent, master = this,
2231                   hotKey = altM, inactive = true, nonClient = true, visible = false
2232                };
2233             sysButtons[0].Create();
2234          }
2235          sysButtons[0].NotifyClicked = method;
2236
2237          sysButtons[0].symbol = symbol;
2238          sysButtons[0].disabled = !style.hasMinimize;
2239       }
2240
2241       // Create the scrollbars
2242       if(style.hasHorzScroll && !sbh)
2243       {
2244          sbh =
2245             ScrollBar
2246             {
2247                this,
2248                direction = horizontal,
2249                windowOwned = true,
2250                inactive = true,
2251                nonClient = true,
2252                snap = scrollFlags.snapX,
2253                NotifyScrolling = ScrollBarNotification
2254             };
2255          sbh.Create();
2256          scrollBarChanged = true;
2257       }
2258       else if(sbh && !style.hasHorzScroll)
2259       {
2260          sbh.Destroy(0);
2261          sbh = null;
2262       }
2263
2264       if(style.hasVertScroll && !sbv)
2265       {
2266          sbv =
2267             ScrollBar
2268             {
2269                this,
2270                direction = vertical,
2271                windowOwned = true,
2272                inactive = true,
2273                nonClient = true,
2274                snap = scrollFlags.snapY,
2275                NotifyScrolling = ScrollBarNotification
2276             };
2277          sbv.Create();
2278          scrollBarChanged = true;
2279       }
2280       else if(sbv && !style.hasVertScroll)
2281       {
2282          sbv.Destroy(0);
2283          sbv = null;
2284       }
2285       if(scrollBarChanged)
2286       {
2287          SetScrollLineStep(sbStep.x, sbStep.y);   
2288          UpdateScrollBars(true, true);
2289       }   
2290       UpdateNonClient();
2291
2292       if(scrollBarChanged)
2293       {
2294          if(sbh) sbh.thumbPosition = scroll.x;
2295          if(sbv) sbv.thumbPosition = scroll.y;
2296       }
2297    }
2298
2299    void UpdateCaption(void)
2300    {
2301       if(rootWindow == this)
2302       {
2303          char caption[2048];
2304          FigureCaption(caption);
2305          guiApp.interfaceDriver.SetRootWindowCaption(this, caption);
2306       }
2307       UpdateDecorations();
2308       if(parent)
2309       {
2310          if(parent.rootWindow == parent && parent.activeClient == this) // Added this last check
2311          {
2312             char caption[2048];
2313             parent.FigureCaption(caption);
2314             guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
2315          }
2316          parent.UpdateDecorations();
2317       }
2318    }
2319
2320    void UpdateActiveDocument(Window previous)
2321    {
2322       Window activeClient = this.activeClient;
2323       Window activeChild = this.activeChild;
2324       if(menuBar)
2325       {
2326          UpdateCaption();
2327          if(!destroyed)
2328          {
2329             if(activeClient)
2330                activeClient.CreateSystemChildren();
2331             if(previous)
2332                previous.CreateSystemChildren();
2333          }
2334       }
2335       if(menu)
2336       {
2337          MenuItem item;
2338          bool disabled;
2339
2340          if(menu)
2341             menu.Clean(this);
2342
2343          if(activeClient && activeClient.menu && activeClient.state != minimized)
2344          {
2345             if(mergeMenus)
2346             {
2347                //activeClient.menu.Clean(activeClient);
2348                menu.Merge(activeClient.menu, true, activeClient);
2349             }
2350          }
2351          
2352          if(activeChild && activeChild != activeClient && activeChild.menu && activeChild.state != minimized)
2353          {
2354             if(mergeMenus)
2355                menu.Merge(activeChild.menu, true, activeChild);
2356          }
2357          
2358          // Build window list
2359          if(activeClient)
2360          {
2361             Menu windowMenu = menu.FindMenu("Window");
2362             if(windowMenu)
2363             {
2364                OldLink cycle;
2365                int id;
2366                for(id = 0, cycle = activeClient.cycle; cycle && id<10;)
2367                {
2368                   MenuItem item;
2369                   Window document = cycle.data;
2370                   if(!document.style.nonClient && document.style.isActiveClient)
2371                   {
2372                      char name[2048], caption[2048];
2373                      document.FigureCaption(caption);
2374                      sprintf(name, "%d %s", id+1, caption);
2375                      windowMenu.AddDynamic(MenuItem 
2376                         { 
2377                            copyText = true, text = name, hotKey = Key { k1 + id }, id = id++, 
2378                            NotifySelect = MenuWindowSelectWindow 
2379                         }, this, false);
2380                   }
2381                   cycle = cycle.next;
2382                   if(activeClient.cycle == cycle) break;
2383                }
2384             }
2385          }
2386          
2387          if((!previous && activeClient) || !activeClient)
2388          {
2389             if(!activeClient)
2390                disabled = true;
2391             else
2392                disabled = false;
2393             item = menu.FindItem(MenuWindowCloseAll, 0);
2394             if(item) item.disabled = false;
2395             item = menu.FindItem(MenuWindowNext, 0);
2396             if(item) item.disabled = false;
2397             item = menu.FindItem(MenuWindowPrevious, 0);
2398             if(item) item.disabled = false;
2399             item = menu.FindItem(MenuWindowCascade, 0);
2400             if(item) item.disabled = false;
2401             item = menu.FindItem(MenuWindowTileHorz, 0);
2402             if(item) item.disabled = false;
2403             item = menu.FindItem(MenuWindowTileVert, 0);
2404             if(item) item.disabled = false;
2405             item = menu.FindItem(MenuWindowArrangeIcons, 0);
2406             if(item) item.disabled = false;
2407             item = menu.FindItem(MenuWindowWindows, 0);
2408             if(item) item.disabled = false;
2409          }      
2410
2411          item = menu.FindItem(MenuFileClose, 0);
2412          if(item) item.disabled = !activeClient || !activeClient.style.hasClose;
2413          item = menu.FindItem(MenuFileSaveAll, 0);
2414          if(item) item.disabled = numDocuments < 1;
2415       }
2416       // This is called again for a child window change, with same active client
2417       OnActivateClient(activeClient, previous);
2418    }
2419
2420    void _ShowDecorations(Box box, bool post)
2421    {
2422       if(nativeDecorations) return;
2423       if(visible && this != guiApp.desktop)
2424       {
2425          Surface surface = RedrawFull(box);
2426          if(surface)
2427          {
2428             char caption[2048];
2429             FigureCaption(caption);
2430             
2431             if(post)
2432                ShowDecorations(captionFont.font,
2433                   surface,
2434                   caption,
2435                   active, //parent.activeClient == this
2436                   guiApp.windowMoving == this);
2437             else
2438                PreShowDecorations(captionFont.font,
2439                   surface,
2440                   caption,
2441                   active, //parent.activeClient == this
2442                   guiApp.windowMoving == this);
2443                
2444             delete surface;
2445          }
2446       }
2447    }
2448
2449    void UpdateExtent(Box refresh)
2450    {
2451       Surface surface = null;
2452
2453       if(!manageDisplay) { OnRedraw(null);return; }
2454       _ShowDecorations(refresh, false);
2455
2456       surface = Redraw(refresh);               
2457       // Opaque background: just fill before EW_REDRAW (clear?)
2458       if(surface) 
2459       {
2460          surface.SetBackground(background);
2461          surface.SetForeground(foreground);
2462          surface.DrawingChar(' ');
2463          if(this == rootWindow)
2464          {
2465             if(style.drawBehind || background.a)
2466                surface.Clear(colorBuffer);
2467          }
2468          else if(background.a)
2469          {
2470 #ifdef _DEBUG
2471             /*
2472             background.color = { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2473             surface.SetForeground((background.color.r > 128 || background.color.g > 128) ? black : white);
2474             */
2475 #endif
2476             if(display.flags.alpha && background.a < 255 && background)
2477             {
2478                surface.Area(0,0,clientSize.w, clientSize.h);
2479                /*if(style.clearDepthBuffer)
2480                   surface.Clear(depthBuffer);*/
2481             }
2482             else if(/*style.clearDepthBuffer || */background.a)
2483             {
2484                // surface.Clear((style.clearDepthBuffer ? depthBuffer : 0) | (background.a ? colorBuffer : 0));
2485                surface.Clear(colorBuffer);
2486             }
2487          }
2488
2489          // Default Settings
2490          surface.TextFont(usedFont.font);
2491          surface.TextOpacity(false);
2492
2493          OnRedraw(surface);
2494
2495          // Draw the caret ...
2496          if(!disabled && this == guiApp.caretOwner && guiApp.caretEnabled /*&& !guiApp.interimWindow*/ && !guiApp.currentSkin.textMode)
2497          {
2498             // surface.SetBackground(0xFFFFFF - background.color);
2499             surface.SetBackground(~background.color);
2500             surface.Area(
2501                caretPos.x - scroll.x + 1, caretPos.y - scroll.y,
2502                caretPos.x - scroll.x + 2, caretPos.y - scroll.y + caretSize - 1);
2503          }
2504          delete surface;
2505       }
2506    }
2507
2508    void DrawOverChildren(Box refresh)
2509    {
2510       Surface surface = Redraw(refresh);               
2511       if(surface) 
2512       {
2513          // Default Settings
2514          surface.DrawingChar(' ');
2515          surface.SetBackground(background);
2516          surface.SetForeground(foreground);
2517
2518          surface.TextFont(usedFont.font);
2519          surface.TextOpacity(false);
2520
2521          OnDrawOverChildren(surface);
2522
2523          delete surface;
2524
2525       }
2526       _ShowDecorations(refresh, true);
2527    }
2528
2529    void ComputeClipExtents(void)
2530    {
2531       Window child;
2532       Extent clipExtent { /*first = -1, last = -1, free = -1*/ };
2533
2534       clipExtent.Copy(this.clipExtent);
2535       
2536       for(child = children.last; child; child = child.prev)
2537       {
2538          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2539          {
2540             bool opaque = child.IsOpaque(); // TODO: acess background directly 
2541             int dx = child.absPosition.x - absPosition.x, dy = child.absPosition.y - absPosition.y;
2542
2543             child.clipExtent.Copy(clipExtent);
2544             child.clipExtent.Offset(-dx, -dy);
2545             child.clipExtent.IntersectBox(child.box);
2546
2547             child.ComputeClipExtents();
2548
2549             if(opaque && !child.style.nonClient)
2550             {
2551                // Adjust the box for the parent:
2552                Box box { child.box.left + dx, child.box.top + dy, child.box.right + dx, child.box.bottom + dy };
2553                clipExtent.ExcludeBox(box, rootWindow.tempExtents[0]);
2554             }
2555             
2556          }
2557       }
2558       // ??? Only do this for overlapped window or if parent has with clip children flag
2559
2560       // Do this if window has clip children flag on (default false?)
2561       // this.clipExtent = clipExtent;
2562
2563       clipExtent.Free(null);
2564    }
2565
2566    void ComputeRenderAreaNonOpaque(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2567    {
2568       bool opaque = IsOpaque();
2569       Window child;
2570       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y; 
2571
2572       for(child = children.last; child; child = child.prev)
2573       {
2574          ColorAlpha background = *(ColorAlpha *)&child.background;
2575          bool opaque = child.IsOpaque();
2576          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2577          {
2578             if(!opaque)
2579             {
2580                int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y; 
2581                // Adjust renderArea to the root window level
2582                Extent * renderArea = &rootWindow.tempExtents[1];
2583                /*
2584                Extent childRenderArea;
2585                
2586                if(backBufferUpdate != null)
2587                {
2588                   childRenderArea.Copy(backBufferUpdate);
2589                   childRenderArea.Offset(-offsetX, -offsetY);
2590                }
2591                else
2592                   childRenderArea.Copy(child.dirtyArea);
2593
2594                // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2595                renderArea.Copy(dirtyExtent);
2596                renderArea.Offset(-offsetX, -offsetY);
2597                childRenderArea.Union(renderArea);
2598                renderArea.Free();
2599
2600                // Intersect with the clip extent
2601                childRenderArea.Intersection(child.clipExtent);
2602                */
2603
2604                renderArea->Copy(child.dirtyArea /*childRenderArea*/);
2605                renderArea->Offset(offsetX, offsetY);
2606                dirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2607                // overDirtyExtent.Union(renderArea);
2608                renderArea->Empty();
2609                // childRenderArea.Free();
2610
2611                //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2612             }
2613          }
2614       }
2615
2616       for(child = children.last; child; child = child.prev)
2617       {
2618          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2619          {
2620             child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2621          }
2622       }
2623    }
2624
2625    void ComputeRenderArea(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2626    {
2627       bool opaque = IsOpaque();
2628       Extent * dirtyExtentWindow = &rootWindow.tempExtents[1];
2629       Window child;
2630       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y; 
2631
2632 #if 0
2633       for(child = children.last; child; child = child.prev)
2634       {
2635          //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2636          /*
2637          ColorAlpha background = *(ColorAlpha *)&child.background;
2638          bool opaque = child.IsOpaque();
2639          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2640          {
2641             if(!opaque)
2642             {
2643                int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y; 
2644                // Adjust renderArea to the root window level
2645                Extent renderArea;
2646                renderArea.Copy(child.dirtyArea);
2647                renderArea.Offset(offsetX, offsetY);
2648                dirtyExtent.Union(renderArea);
2649                overDirtyExtent.Union(renderArea);
2650                renderArea.Free();
2651             }
2652          }*/
2653       }
2654 #endif
2655       for(child = children.last; child; child = child.prev)
2656       {
2657          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2658          {
2659             child.ComputeRenderArea(dirtyExtent, overDirtyExtent, backBufferUpdate);
2660          }
2661       }
2662
2663       if(backBufferUpdate != null)
2664       {
2665          renderArea.Copy(backBufferUpdate);
2666          renderArea.Offset(-offsetX, -offsetY);
2667          
2668          overRenderArea.Copy(backBufferUpdate);
2669          overRenderArea.Offset(-offsetX, -offsetY);
2670          
2671          
2672       }
2673       else
2674       {
2675          renderArea.Copy(dirtyArea);
2676          
2677          overRenderArea.Copy(dirtyArea);
2678       }
2679
2680       // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2681       dirtyExtentWindow->Copy(dirtyExtent);
2682       dirtyExtentWindow->Offset(-offsetX, -offsetY);
2683       renderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2684       dirtyExtentWindow->Empty();
2685
2686       // Intersect with the clip extent
2687       renderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2688
2689       /*
2690       if(renderArea.count > 10)
2691       {
2692          BoxItem extentBox;
2693          printf("\nToo many extents (%d):\n", renderArea.count);
2694
2695          //extent.UnionBox({ 112, 6, 304, 7 }, rootWindow.tempExtents[0]);
2696          //extent.UnionBox({ 112, 8, 304, 17 }, rootWindow.tempExtents[0]);
2697          //printf("Test\n");
2698
2699          {
2700             int c;
2701             for(c = 0; c<10; c++)
2702             {
2703                Extent extent { };
2704                FASTLIST_LOOP(renderArea, extentBox)
2705                {
2706                   extent.UnionBox(extentBox.box, rootWindow.tempExtents[0]);
2707                }
2708                renderArea.Copy(extent);
2709
2710                FASTLIST_LOOP(renderArea, extentBox)
2711                {
2712       #ifdef _DEBUG
2713                   printf("(%d, %d) - (%d, %d)\n", 
2714                      extentBox.box.left, extentBox.box.top, 
2715                      extentBox.box.right, extentBox.box.bottom);
2716       #endif
2717                }
2718
2719                printf("\nNow %d\n", renderArea.count);
2720             }
2721          }
2722       }
2723       */
2724       
2725       // WHY WAS THIS COMMENTED ??
2726
2727       // Add extent forced by DrawOverChildren to the dirty area, adjusting dirty extent to the window
2728       dirtyExtentWindow->Copy(overDirtyExtent);
2729       dirtyExtentWindow->Offset(-offsetX, -offsetY);
2730       overRenderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2731       dirtyExtentWindow->Empty();
2732
2733       // Intersect with the clip extent
2734       overRenderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2735       
2736
2737       if(opaque)
2738       {
2739          // Scrolling
2740          if(scrollExtent.count)
2741          {
2742             // Subtract render extent from scrolling extent
2743             scrollExtent.Exclusion(renderArea, rootWindow.tempExtents[0]);
2744
2745             if(backBufferUpdate == null)
2746             {
2747                Extent * dirty = &rootWindow.tempExtents[3];
2748                BoxItem scrollBox;
2749
2750                // Intersect scrolling extent with clip extent
2751                scrollExtent.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2752
2753                // offset this scroll to be at the root window level
2754                scrollExtent.Offset(offsetX, offsetY);
2755                // Add area that was scrolled to the dirty extents of the back buffer
2756                rootWindow.dirtyBack.Union(scrollExtent, rootWindow.tempExtents[0]);
2757
2758                dirty->Empty();
2759
2760                // Will need scrolledArea.x & scrolledArea.y to support multiple scrolls
2761                FASTLIST_LOOP(scrollExtent, scrollBox)
2762                   display.Scroll(scrollBox.box, scrolledArea.x, scrolledArea.y, dirty);
2763
2764                scrolledArea.x = 0;
2765                scrolledArea.y = 0;
2766
2767                scrollExtent.Empty();
2768
2769                // Add the exposed extent to the window render area
2770                dirty->Offset(-offsetX, -offsetY);
2771                renderArea.Union(dirty, rootWindow.tempExtents[0]);
2772                dirty->Empty();
2773             }
2774          }
2775
2776          // Subtract the window's box from the transparency forced extent
2777          dirtyExtent.ExcludeBox({box.left + offsetX, box.top + offsetY, box.right + offsetX, box.bottom + offsetY }, rootWindow.tempExtents[0]);
2778       }
2779       /*else
2780       {
2781          Extent renderArea;
2782
2783          renderArea.Copy(this.renderArea);
2784          renderArea.Offset(offsetX, offsetY);
2785          dirtyExtent.Union(renderArea);
2786          renderArea.Free();
2787       }*/
2788       
2789       
2790       {
2791          Extent renderArea { };
2792          
2793          renderArea.Copy(overRenderArea);
2794          renderArea.Offset(offsetX, offsetY);
2795          overDirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2796          renderArea.Empty();
2797       }
2798       
2799
2800       if(backBufferUpdate != null)
2801       {
2802          // Remove render area from dirty area
2803          dirtyArea.Exclusion(renderArea, rootWindow.tempExtents[0]);
2804
2805          dirtyArea.Exclusion(overRenderArea, rootWindow.tempExtents[0]);
2806       }
2807       else
2808          dirtyArea.Empty();
2809
2810       clipExtent.Empty();
2811    /*
2812       // Remove the window render area from the dirty extents of the back buffer
2813       rootWindow.dirtyBack.Exclusion(renderArea);
2814    */
2815    }
2816
2817    void Render(Extent updateExtent)
2818    {
2819       BoxItem extentBox;
2820       Window child;
2821       Window rootWindow = this.rootWindow;
2822       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2823
2824       if(rootWindow.fullRender)
2825       {
2826          UpdateExtent(box);
2827          dirtyArea.Empty();
2828       }
2829       else
2830       {
2831 #ifdef _DEBUG
2832          /*
2833          background = Color { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2834          foreground = (background.color.r > 128 || background.color.g > 128) ? black : white;
2835          */
2836 #endif
2837             
2838 #ifdef _DEBUG
2839          /*if(renderArea.count)
2840             printf("\n\nRendering %s (%x):\n------------------------------------------\n", _class.name, this);*/
2841 #endif
2842             
2843          FASTLIST_LOOP(renderArea, extentBox)
2844          {
2845             Box box = extentBox.box;
2846
2847 #ifdef _DEBUG
2848                /*printf("(%d, %d) - (%d, %d)\n", 
2849                   extentBox.box.left, extentBox.box.top, 
2850                   extentBox.box.right, extentBox.box.bottom);*/
2851 #endif
2852                
2853             UpdateExtent(box);
2854
2855             box.left += offsetX;
2856             box.top += offsetY;
2857             box.right += offsetX;
2858             box.bottom += offsetY;
2859
2860             if(updateExtent != null)
2861                updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2862          }
2863       }
2864
2865       for(child = children.first; child; child = child.next)
2866          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && !child.nonClient)
2867             child.Render(updateExtent);
2868
2869       if(rootWindow.fullRender)
2870          DrawOverChildren(box);
2871       else
2872       {
2873          // TO DO: There's an issue about draw over children...
2874          // TO DO: Don't wanna go through this if method isn't used
2875          FASTLIST_LOOP(/*renderArea */overRenderArea, extentBox)
2876          {
2877             Box box = extentBox.box;
2878
2879             DrawOverChildren(box);
2880
2881             box.left += offsetX;
2882             box.top += offsetY;
2883             box.right += offsetX;
2884             box.bottom += offsetY;
2885
2886             if(updateExtent != null)
2887                updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2888          }
2889       }
2890       for(child = children.first; child; child = child.next)
2891          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && child.nonClient)
2892             child.Render(updateExtent);
2893
2894       renderArea.Empty();
2895       overRenderArea.Empty();
2896    }
2897
2898    public void UpdateDisplay(void)
2899    {
2900       if(!manageDisplay) { OnRedraw(null);return; }
2901       if(rootWindow && this != rootWindow) 
2902          rootWindow.UpdateDisplay();
2903       else if(display)
2904       {
2905          Extent dirtyExtent { /*first = -1, last = -1, free = -1*/ };  // Extent that needs to be forced due to transparency
2906          Extent overExtent { /*first = -1, last = -1, free = -1*/ };  // Extent that forced for DrawOverChildren
2907          BoxItem extentBox;
2908
2909          dirtyExtent.Clear();
2910          overExtent.Clear();
2911
2912          clipExtent.AddBox(box);
2913
2914          display.StartUpdate();
2915
2916          if(!rootWindow.fullRender)
2917          {
2918             ComputeClipExtents();
2919             ComputeRenderAreaNonOpaque(dirtyExtent, overExtent, null);
2920             ComputeRenderArea(dirtyExtent, overExtent, null);
2921          }
2922          else
2923             clipExtent.Free(null);                     
2924
2925          dirtyExtent.Free(null);
2926          overExtent.Free(null);
2927
2928          if(display.flags.flipping)
2929          {
2930             Render(null);
2931             display.Update(null);
2932          }
2933          else
2934          {
2935             Extent updateExtent { /*first = -1, last = -1, free = -1*/ }; // Extent that needs to be updated
2936             updateExtent.Clear();
2937
2938             Render(updateExtent);
2939             if(fullRender)
2940                updateExtent.UnionBox(this.box, tempExtents[0]);
2941             
2942 #ifdef _DEBUG
2943             //printf("\n\nUpdate:\n------------------------------------------\n");
2944 #endif
2945             
2946             FASTLIST_LOOP(updateExtent, extentBox)
2947             {
2948 #ifdef _DEBUG
2949                /*printf("Updating (%d, %d) - (%d, %d)\n", 
2950                   extentBox.box.left, extentBox.box.top, 
2951                   extentBox.box.right, extentBox.box.bottom);*/
2952 #endif
2953                
2954                display.Update(extentBox.box);
2955                
2956             }
2957             updateExtent.Free(null);
2958          }
2959
2960          display.EndUpdate();
2961          dirtyBack.Empty();
2962
2963          dirty = false;
2964          resized = false;
2965       }
2966    }
2967
2968    void UpdateBackDisplay(Box box)
2969    {
2970       if(display)
2971       {
2972          Extent dirtyExtent;
2973          Extent overExtent;
2974          Extent intersection { /*first = -1, last = -1, free = -1*/ };
2975
2976          //printf("UpdateBackDisplay going through!\n");
2977          display.StartUpdate();
2978
2979          if(resized)
2980          {
2981             intersection.Copy(dirtyBack);
2982             intersection.IntersectBox(box);
2983          
2984             dirtyExtent.Clear();
2985             overExtent.Clear();
2986
2987             clipExtent.AddBox(box);
2988          
2989             if(!rootWindow.fullRender)
2990             {
2991                ComputeClipExtents();
2992                ComputeRenderArea(dirtyExtent, overExtent, intersection);
2993             }
2994             else
2995                clipExtent.Free(null);
2996
2997             intersection.Free(null);
2998             dirtyExtent.Free(null);
2999             overExtent.Free(null);
3000
3001             Render(null);
3002          }
3003
3004          if(display.flags.flipping)
3005             display.Update(null);
3006          else
3007          {
3008             rootWindow.display.Update(box);
3009          }
3010
3011          display.EndUpdate();
3012
3013          if(resized)
3014          {
3015             dirtyBack.ExcludeBox(box, rootWindow.tempExtents[0]);
3016             if(dirtyBack.count > MAX_DIRTY_BACK)
3017             {
3018                BoxItem extentBox, next;
3019                BoxItem first = (BoxItem)ACCESS_ITEM(dirtyBack, dirtyBack.first);
3020                FASTLIST_LOOPN(dirtyBack, extentBox, next)
3021                {
3022                   if(extentBox != first)
3023                   {
3024                      if(extentBox.box.left < first.box.left)
3025                         first.box.left = extentBox.box.left;
3026                      if(extentBox.box.top < first.box.top)
3027                         first.box.top = extentBox.box.top;
3028                      if(extentBox.box.right > first.box.right)
3029                         first.box.right = extentBox.box.right;
3030                      if(extentBox.box.bottom > first.box.bottom)
3031                         first.box.bottom = extentBox.box.bottom;
3032                      dirtyBack.Delete(extentBox);
3033                   }
3034                }
3035             }
3036             resized = false;
3037          }
3038       }
3039    }
3040
3041    // --- Window positioning ---
3042    // --- Window identification ---
3043
3044    // Returns window at position "Position"
3045    Window GetAtPosition(int x, int y, bool clickThru, bool acceptDisabled, Window last)
3046    {
3047       Window child, result = null;
3048       Box box = this.box;
3049       box.left += absPosition.x;
3050       box.right += absPosition.x;
3051       box.top += absPosition.y;
3052       box.bottom += absPosition.y;
3053
3054       if(!destroyed && visible && (acceptDisabled || !disabled))
3055       {
3056          int lx = x - absPosition.x;
3057          int ly = y - absPosition.y;
3058          if(IsInside(lx, ly))
3059          // if(box.IsPointInside(Point{x, y}))
3060          {
3061             if(!clickThru || !style.clickThrough) result = (this == last) ? null : this;
3062             // If the window is disabled, stop looking in children (for acceptDisabled mode)
3063             if(!disabled)
3064             {
3065                for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3066                {
3067                   if(child != statusBar && child.rootWindow == rootWindow)
3068                   {
3069                      Window childResult = child.GetAtPosition(x, y, clickThru, acceptDisabled, last);
3070                      if(childResult) 
3071                         return childResult;
3072                   }
3073                }
3074                if(clickThru)
3075                {
3076                   for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3077                   {
3078                      if(child != statusBar && child.rootWindow == rootWindow)
3079                      {
3080                         Window childResult = child.GetAtPosition(x, y, false, acceptDisabled, last);
3081                         if(childResult)
3082                            return childResult;
3083                      }
3084                   }
3085                }
3086             }
3087          }
3088       }
3089       return result;
3090    }
3091
3092    Window FindModal(void)
3093    {
3094       Window modalWindow = this, check;
3095       Window check2 = null;
3096       for(check = this; check.master; check = check.master)
3097       {
3098          if(check.master.modalSlave && check.master.modalSlave.created && check != check.master.modalSlave)
3099          {
3100             modalWindow = check.master.modalSlave;
3101             check = modalWindow;
3102          }
3103          // TESTING THIS FOR DROPBOX...
3104          if(!rootWindow || !rootWindow.style.interim)
3105          {
3106             for(check2 = check; check2.activeChild; check2 = check2.activeChild)
3107             {
3108                if(check2.modalSlave && check2.modalSlave.created)
3109                {
3110                   modalWindow = check2.modalSlave;
3111                   break;
3112                }
3113             }
3114          }
3115       }
3116
3117       /*
3118       if(modalWindow == this)
3119       {
3120          for(check = this; check.activeChild; check = check.activeChild)
3121          {
3122             if(check.modalSlave)
3123             {
3124                modalWindow = check.modalSlave;
3125                break;
3126             }
3127          }
3128       }
3129       */
3130       for(; modalWindow.modalSlave && modalWindow.modalSlave.created; modalWindow = modalWindow.modalSlave);
3131       return (modalWindow == this || this == guiApp.interimWindow || IsDescendantOf(modalWindow)) ? null : modalWindow;
3132    }
3133
3134    void StopMoving(void)
3135    {
3136       if(this == guiApp.windowMoving)
3137       {
3138          guiApp.windowMoving = null;
3139          UpdateDecorations();
3140          SetMouseRange(null);
3141          if(rootWindow)
3142          {
3143             if(rootWindow.active)
3144                guiApp.interfaceDriver.StopMoving(rootWindow);
3145          }
3146          ReleaseCapture();
3147          guiApp.resizeX = guiApp.resizeY = guiApp.resizeEndX = guiApp.resizeEndY = false;
3148          guiApp.windowIsResizing = false;
3149       }
3150    }
3151
3152    void SelectMouseCursor(void)
3153    {
3154       int x,y;
3155       Window mouseWindow;
3156       Window modalWindow;
3157       Window cursorWindow = null;
3158       bool rx, ry, rex, rey;
3159
3160       guiApp.desktop.GetMousePosition(&x, &y);
3161       mouseWindow = rootWindow ? rootWindow.GetAtPosition(x,y, true, false, null) : null;
3162
3163       if((guiApp.windowMoving && !guiApp.windowIsResizing) || guiApp.windowScrolling)
3164          guiApp.SetCurrentCursor(guiApp.systemCursors[moving]);
3165       else if(mouseWindow)
3166       {
3167          modalWindow = mouseWindow.FindModal();
3168          x -= mouseWindow.absPosition.x;
3169          y -= mouseWindow.absPosition.y;
3170          if(guiApp.windowIsResizing)
3171          {
3172             rex = guiApp.resizeEndX;
3173             rey = guiApp.resizeEndY;
3174             rx = guiApp.resizeX;
3175             ry = guiApp.resizeY;
3176             if((rex && rey) || (rx && ry))
3177                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3178             else if((rex && ry) || (rx && rey))
3179                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3180             else if((ry || rey) && (!rx && !rex))
3181                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3182             else if((rx || rex) && (!ry && !rey))
3183                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3184          }
3185          else if(!modalWindow && !guiApp.windowCaptured &&
3186             mouseWindow.IsMouseResizing(x, y, mouseWindow.size.w, mouseWindow.size.h,
3187                &rx, &ry, &rex, &rey))
3188          {
3189             if((rex && rey) || (rx && ry))
3190                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3191             else if((rex && ry) || (rx && rey))
3192                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3193             else if((ry || rey) && (!rx && !rex))
3194                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3195             else if((rx || rex) && (!ry && !rey))
3196                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3197          }
3198          else if(!guiApp.windowCaptured && !modalWindow && !guiApp.interimWindow)
3199          {
3200             if(!mouseWindow.clientArea.IsPointInside({x - mouseWindow.clientStart.x, y - mouseWindow.clientStart.y}))
3201                cursorWindow = mouseWindow.parent;
3202             else
3203                cursorWindow = mouseWindow;
3204          }
3205          else if(!guiApp.interimWindow)
3206             cursorWindow = guiApp.windowCaptured;
3207          if(cursorWindow)
3208          {
3209             for(; !cursorWindow.cursor && !cursorWindow.style.nonClient; cursorWindow = cursorWindow.parent);
3210             guiApp.SetCurrentCursor(cursorWindow.cursor ? cursorWindow.cursor : guiApp.systemCursors[arrow]);
3211          }
3212          else if(modalWindow)
3213          {
3214             guiApp.SetCurrentCursor(guiApp.systemCursors[arrow]);
3215          }
3216          else if(guiApp.interimWindow)
3217          {
3218             if(guiApp.interimWindow.cursor)
3219                guiApp.SetCurrentCursor(guiApp.interimWindow.cursor);
3220             else
3221                guiApp.SetCurrentCursor(mouseWindow.cursor ? mouseWindow.cursor : guiApp.systemCursors[arrow]);
3222          }
3223       }
3224    }
3225
3226    // --- State based input ---
3227    bool AcquireInputEx(bool state)
3228    {
3229       bool result;
3230       if(state) 
3231       {
3232          guiApp.interfaceDriver.GetMousePosition(&guiApp.acquiredMouseX, &guiApp.acquiredMouseY);
3233          guiApp.interfaceDriver.SetMousePosition(clientSize.w/2 + absPosition.x, clientSize.h/2 + absPosition.y);
3234       }
3235       result = guiApp.interfaceDriver.AcquireInput(rootWindow, state);
3236       if(result)
3237          guiApp.acquiredWindow = state ? this : null;
3238       if(state && result)
3239       {
3240          SetMouseRangeToClient();
3241          guiApp.interfaceDriver.SetMouseCursor((SystemCursor)-1);
3242       }
3243       else
3244       {
3245          FreeMouseRange();
3246          SelectMouseCursor();
3247       }
3248       if(!state) guiApp.interfaceDriver.SetMousePosition(guiApp.acquiredMouseX, guiApp.acquiredMouseY);
3249       return result;
3250    }
3251
3252    // --- Window activation ---
3253    bool PropagateActive(bool active, Window previous, bool * goOnWithActivation, bool direct)
3254    {
3255       bool result = true;
3256       if(!parent || !parent.style.inactive)
3257       {
3258          Window parent = this.parent;
3259
3260          /*
3261          if(rootWindow == this)
3262             Log(active ? "active\n" : "inactive\n");
3263          */
3264
3265          // Testing this here...
3266          if(!parent || parent == guiApp.desktop || parent.active)
3267          {
3268             this.active = active;
3269          }
3270
3271          // TESTING THIS HERE
3272          UpdateDecorations();
3273          if(result = OnActivate(active, previous, goOnWithActivation, direct) && *goOnWithActivation && master)
3274             result = NotifyActivate(master, this, active, previous);
3275          else
3276          {
3277             this.active = !active;
3278          }
3279
3280          if(result)
3281          {
3282             if(!parent || parent == guiApp.desktop || parent.active)
3283             {
3284                this.active = active;
3285                if(acquiredInput)
3286                   AcquireInputEx(active);
3287                if(active)
3288                {
3289                   if(caretSize)
3290                   {
3291                      if(guiApp.caretOwner)
3292                      {
3293                         Box extent 
3294                         {
3295                            guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 1, 
3296                            guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + 1,
3297                            guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 2, 
3298                            guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + guiApp.caretOwner.caretSize - 1
3299                         };
3300                         guiApp.caretOwner.Update(extent);
3301                      }
3302
3303                      if(visible || !guiApp.caretOwner)
3304                         guiApp.caretOwner = this;
3305                      UpdateCaret(false, false);
3306                   }
3307                }
3308             }
3309             else
3310             {
3311                this.active = false;
3312                if(acquiredInput)
3313                   AcquireInputEx(active);
3314             }
3315             if(!active && guiApp.caretOwner == this)
3316             {
3317                UpdateCaret(false, true);
3318                guiApp.caretOwner = null;
3319                guiApp.interfaceDriver.SetCaret(0,0,0);
3320                guiApp.caretEnabled = false;
3321             }
3322
3323             if(!style.interim)
3324             {
3325                if(!active && parent && parent.activeChild && parent.activeChild != this)
3326                   if(!parent.activeChild.PropagateActive(false, previous, goOnWithActivation, true) || !*goOnWithActivation)
3327                   {
3328                      return false;
3329                   }
3330             }
3331
3332             if(!active && menuBar)
3333             {
3334                bool goOn;
3335                menuBar.OnActivate(false, null, &goOn, true);
3336                menuBar.NotifyActivate(menuBar.master, menuBar, false, null);
3337             }
3338
3339             if(activeChild)
3340                if(!activeChild.PropagateActive(active, previous, goOnWithActivation, false) || !*goOnWithActivation)
3341                {
3342                   return false;
3343                }
3344          }
3345       }
3346       return result;
3347    }
3348
3349    void ConsequentialMouseMove(bool kbMoving)
3350    {
3351       if(rootWindow)
3352       {
3353          if(kbMoving || !guiApp.windowMoving)
3354          {
3355             Modifiers mods {};
3356             int x,y;
3357             if(rootWindow == guiApp.desktop || rootWindow.parent == guiApp.desktop)
3358             {
3359                guiApp.interfaceDriver.GetMousePosition(&x, &y);
3360
3361                if(guiApp.windowMoving || rootWindow.GetAtPosition(x, y, true, false, null))
3362                   rootWindow.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &mods, true, false);
3363             }
3364          }
3365       }
3366    }
3367
3368    bool IsDescendantOf(Window ancestor)
3369    {
3370       Window window;
3371       for(window = this; window && window != ancestor; window = window.parent);
3372       return window == ancestor;
3373    }
3374
3375    bool IsSlaveOf(Window master)
3376    {
3377       Window window;
3378       for(window = this; window && window != master; window = window.master);
3379       return window == master;
3380    }
3381
3382    bool ActivateEx(bool active, bool activateParent, bool moveInactive, bool activateRoot, Window external, Window externalSwap)
3383    {
3384       bool result = true;
3385
3386       if(this && !destroyed /*&& state != Hidden*/)
3387       {
3388          Window swap = externalSwap;
3389
3390          incref this;
3391
3392          if(parent)
3393          {
3394             if(!active)
3395                StopMoving();
3396             if(activateParent && 
3397                (parent.activeChild != this || 
3398                (guiApp.interimWindow && !IsDescendantOf(guiApp.interimWindow))) &&
3399                active && style.modal && 
3400                parent != master && master)
3401                master.ActivateEx(true, true, false, activateRoot, external, externalSwap);
3402
3403             if(active)
3404             {
3405                if(parent)
3406                {
3407                   bool real = parent.activeChild != this;
3408
3409                   // TEST THIS: New activateParent check here!!! CAUSED MENUS NOT GOING AWAY
3410                   if(/*activateParent && */guiApp.interimWindow && 
3411                      !IsDescendantOf(guiApp.interimWindow) && 
3412                      !IsSlaveOf(guiApp.interimWindow))
3413                   {
3414                      Window interimWindow = guiApp.interimWindow;
3415                      while(interimWindow && interimWindow != this)
3416                      {
3417                         Window master = interimWindow.master;
3418                         bool goOn = true;
3419                         guiApp.interimWindow = null;
3420                         if(guiApp.caretOwner)
3421                            guiApp.caretOwner.UpdateCaret(false, false);
3422
3423                         incref interimWindow;
3424                         if(!interimWindow.PropagateActive(false, this, &goOn, true))
3425                         {
3426                            result = false;
3427                            real = false;
3428                         }
3429                         delete interimWindow;
3430                         interimWindow = (master && master.style.interim) ? master : null;
3431                      }
3432                   }
3433                   if(style.interim)
3434                   {
3435                      guiApp.interimWindow = this;
3436                      /*guiApp.interfaceDriver.SetCaret(0,0,0);
3437                      guiApp.caretEnabled = false;*/
3438                      UpdateCaret(false, true);
3439                   }
3440
3441                   if(real)
3442                   {
3443                      bool acquireInput = false;
3444                      bool maximize =
3445                         parent.activeChild &&
3446                         parent.activeChild.state == maximized &&
3447                         parent != guiApp.desktop;
3448
3449                      if(!style.inactive) // (!style.isRemote || parent.active || parent.style.hidden))
3450                      {
3451                         if(!style.interim)
3452                         {
3453                            if(!swap && parent)
3454                               swap = parent.activeChild;
3455                            if(swap && swap.destroyed) swap = null;
3456                            if(swap && swap != this)
3457                            {
3458                               bool goOn = true;
3459                               if(!swap.PropagateActive(false, this, &goOn, true))
3460                                  swap = parent.activeChild;
3461                               if(!goOn)
3462                               {
3463                                  delete this;
3464                                  return false;
3465                               }
3466                            }
3467                            else
3468                               swap = null;
3469                         }
3470
3471                         if(!parent || parent.activeChild != this || style.interim)
3472                         {
3473                            bool goOn = true;
3474                            result = PropagateActive(true, swap, &goOn, true);
3475                            if(!result && !goOn) 
3476                            {
3477                               delete this;
3478                               return false;
3479                            }
3480                            acquireInput = true;
3481                         }
3482                      }
3483
3484                      if(style.hasMaximize && parent != guiApp.desktop)
3485                      {
3486                         if(maximize)
3487                            SetState(maximized, false, 0);
3488                         else if(state != maximized)
3489                         {
3490                            Window child;
3491                            for(child = parent.children.first; child; child = child.next)
3492                            {
3493                               if(this != child && child.state == maximized)
3494                                  child.SetState(normal, false, 0);
3495                            }
3496                         }
3497                      }
3498                   }
3499                   if(result)
3500                   {
3501                      if(!style.inactive && !style.interim /*&& (!style.isRemote || parent.active || parent.style.hidden)*/)
3502                      {
3503                         Window previous = parent.activeClient;
3504                         parent.activeChild = this;
3505                         if(!style.nonClient /*&& style.isActiveClient*/)
3506                         {
3507                            if(style.isActiveClient && !style.hidden)
3508                               parent.activeClient = this;
3509                            parent.UpdateActiveDocument(previous);
3510                         }
3511                      }
3512                   }
3513
3514                   //if(!style.isRemote)
3515                   {
3516                      if(rootWindow != this)
3517                      {
3518                         if(activateParent && !parent.active /*parent != parent.parent.activeChild*/)
3519                            parent.ActivateEx(true, true, moveInactive, activateRoot, external, externalSwap);
3520                      }
3521                      else if(!guiApp.fullScreenMode)
3522                      {
3523                         Window modalRoot = FindModal();
3524                         if(!modalRoot) modalRoot = this;
3525                         if(!modalRoot.isForegroundWindow)
3526                         {
3527                            modalRoot.isForegroundWindow = true;
3528                            // To check : Why is parent null?
3529                            if(activateRoot && modalRoot.parent && !modalRoot.parent.display && external != modalRoot)
3530                            {
3531                               guiApp.interfaceDriver.ActivateRootWindow(modalRoot);
3532                            }
3533                            modalRoot.isForegroundWindow = false;
3534                         }
3535                      }
3536                   }
3537                
3538                   if(result && real && (!style.inactive || moveInactive) && parent)
3539                   {
3540                      Window last = parent.children.last;
3541
3542                      if(!style.stayOnTop)
3543                         for(; last && last.style.stayOnTop; last = last.prev);
3544                      
3545                      parent.children.Move(this, last);
3546
3547                      // Definitely don't want that:   why not?
3548                      Update(null);
3549
3550                      if(order)
3551                         parent.childrenOrder.Move(order, parent.childrenOrder.last);
3552                   }
3553                }
3554             }
3555             else 
3556             {
3557                if(!parent || style.interim || (parent.activeChild == this && !style.inactive))
3558                {
3559                   bool goOn = true;
3560                   if(!style.interim)
3561                   {
3562                      if(parent)
3563                      {
3564                         parent.activeChild = null;
3565                         if(!style.nonClient /*&& style.isActiveClient*/)
3566                         {
3567                            Window previous = parent.activeClient;
3568                            if(style.isActiveClient)
3569                               parent.activeClient = null;
3570                            parent.UpdateActiveDocument(previous);
3571                         }
3572                      }
3573                   }
3574                   if(this == guiApp.interimWindow)
3575                   {
3576                      guiApp.interimWindow = null;
3577                      if(guiApp.caretOwner)
3578                         guiApp.caretOwner.UpdateCaret(false, false);
3579                   }
3580                   if(!PropagateActive(false, externalSwap, &goOn, true) || !goOn)
3581                   {
3582                      delete this;
3583                      return false;
3584                   }
3585                }
3586             }
3587             if(!active || !swap)
3588                UpdateDecorations();
3589             if(swap)
3590                swap.UpdateDecorations();
3591
3592             if(active && rootWindow != this)
3593                ConsequentialMouseMove(false);
3594          }
3595          delete this;
3596       }
3597       return true;
3598    }
3599
3600    // --- Input Messages ---
3601    void ::UpdateMouseMove(int mouseX, int mouseY, bool consequential)
3602    {
3603       static bool reEntrancy = false;
3604       if(reEntrancy) return;
3605
3606       reEntrancy = true;
3607
3608       guiApp.cursorUpdate = true;
3609       if(guiApp.windowScrolling && !consequential)
3610       {
3611          guiApp.windowScrolling.SetScrollPosition(
3612             (guiApp.windowScrolling.sbh) ? 
3613                (guiApp.windowScrollingBefore.x - mouseX + guiApp.windowScrollingStart.x) : 0,
3614             (guiApp.windowScrolling.sbv) ? 
3615                (guiApp.windowScrollingBefore.y - mouseY + guiApp.windowScrollingStart.y) : 0);
3616       }
3617       if(guiApp.windowMoving)
3618       {
3619          if(mouseX != guiApp.movingLast.x || mouseY != guiApp.movingLast.y)
3620          {
3621             Window window = guiApp.windowMoving;
3622             int rx, ry;
3623             int w = window.size.w;
3624             int h = window.size.h;
3625             int aw, ah;
3626             MinMaxValue ew, eh;
3627             int x, y;
3628
3629             rx = mouseX - guiApp.windowMovingStart.x;
3630             ry = mouseY - guiApp.windowMovingStart.y;
3631
3632             // Size
3633             window.GetDecorationsSize(&ew, &eh);
3634
3635             if(guiApp.windowIsResizing)
3636             {
3637                x = window.scrolledPos.x;
3638                y = window.scrolledPos.y;
3639
3640                if(guiApp.resizeX)
3641                {
3642                   aw = Max(guiApp.windowResizingBefore.w - rx,window.skinMinSize.w);
3643                   rx = guiApp.windowResizingBefore.w - aw;
3644                   rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3645                   w = guiApp.windowResizingBefore.w - rx;
3646                }
3647                if(guiApp.resizeY)
3648                {
3649                   ah = Max(guiApp.windowResizingBefore.h - ry,window.skinMinSize.h);
3650                   ry = guiApp.windowResizingBefore.h - ah;
3651                   ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3652                   ry = Max(ry, -guiApp.windowMovingBefore.y);
3653                   h = guiApp.windowResizingBefore.h - ry;
3654                }
3655                if(guiApp.resizeEndX)
3656                {
3657                   w = guiApp.windowResizingBefore.w + rx;
3658                   w = Max(w,1-x);
3659                }
3660                if(guiApp.resizeEndY) h = guiApp.windowResizingBefore.h + ry;
3661
3662                w -= ew;
3663                h -= eh;
3664
3665                w = Max(w, 1);
3666                h = Max(h, 1);
3667
3668                w = Max(w, window.minSize.w);
3669                h = Max(h, window.minSize.h);
3670                w = Min(w, window.maxSize.w);
3671                h = Min(h, window.maxSize.h);
3672
3673                if(!window.OnResizing(&w, &h))
3674                {
3675                   w = window.clientSize.w;
3676                   h = window.clientSize.h;
3677                }
3678
3679                w = Max(w, window.skinMinSize.w);
3680                h = Max(h, window.skinMinSize.h);
3681
3682                w += ew;
3683                h += eh;
3684
3685                if(guiApp.textMode)
3686                {
3687                   SNAPDOWN(w, textCellW);
3688                   SNAPDOWN(h, textCellH);
3689                }
3690
3691                if(guiApp.resizeX)
3692                {
3693                   aw = Max(w,window.skinMinSize.w);
3694                   rx = guiApp.windowResizingBefore.w - aw;
3695                   rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3696                   w = guiApp.windowResizingBefore.w - rx;
3697                }
3698                if(guiApp.resizeY)
3699                {
3700                   ah = Max(h,window.skinMinSize.h);
3701                   ry = guiApp.windowResizingBefore.h - ah;
3702                   ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3703                   ry = Max(ry, -guiApp.windowMovingBefore.y);
3704                   h = guiApp.windowResizingBefore.h - ry;
3705                }
3706             }
3707          
3708             // Position
3709             if(!guiApp.windowIsResizing || guiApp.resizeX)
3710                x = guiApp.windowMovingBefore.x + rx;
3711             if(!guiApp.windowIsResizing || guiApp.resizeY)
3712                y = guiApp.windowMovingBefore.y + ry;
3713
3714             if(!guiApp.windowIsResizing)
3715             {
3716                // Limit
3717                if(window.parent == guiApp.desktop && guiApp.virtualScreen.w)
3718                {
3719                   x = Min(x, (guiApp.virtualScreen.w + guiApp.virtualScreenPos.x) -1);
3720                   y = Min(y, (guiApp.virtualScreen.h + guiApp.virtualScreenPos.y) -1);
3721                   x = Max(x,-(w-1) + guiApp.virtualScreenPos.x);
3722                   y = Max(y,-(h-1) + guiApp.virtualScreenPos.y);
3723                }
3724                else
3725                {
3726                   x = Min(x, (window.parent.reqScrollArea.w ? window.parent.reqScrollArea.w : window.parent.clientSize.w) -1);
3727                   y = Min(y, (window.parent.reqScrollArea.h ? window.parent.reqScrollArea.h : window.parent.clientSize.h) -1);
3728                   x = Max(x,-(w-1));
3729                   y = Max(y,-(h-1));
3730                }
3731             }
3732
3733             if(!guiApp.windowIsResizing || (guiApp.resizeX || guiApp.resizeY))
3734             {
3735                if(!window.OnMoving(&x, &y, w, h))
3736                {
3737                   x = window.scrolledPos.x;
3738                   y = window.scrolledPos.y;
3739                }
3740             }
3741
3742             if(guiApp.textMode)
3743             {
3744                SNAPDOWN(x, textCellW);
3745                SNAPDOWN(y, textCellH);
3746             }
3747
3748             if(!window.style.nonClient)
3749             {
3750                if(!window.style.fixed /*|| window.style.isDocument*/)
3751                {
3752                   if(!window.style.dontScrollHorz)
3753                      x += window.parent.scroll.x;
3754                   if(!window.style.dontScrollVert)
3755                      y += window.parent.scroll.y;
3756                }
3757             }
3758
3759             // Break the anchors for moveable/resizable windows
3760             // Will probably cause problem with IDE windows... Will probably need a way to specify if anchors should break
3761             if(window.style.fixed) 
3762             {
3763                if(window.state == normal)
3764                {
3765                   window.normalAnchor = Anchor { left = x, top = y };
3766                   window.normalSizeAnchor = SizeAnchor { { w, h } };
3767                   window.anchored = false;
3768                }
3769             }
3770
3771             window.stateAnchor = Anchor { left = x, top = y };
3772             window.stateSizeAnchor = SizeAnchor { { w, h } };
3773
3774             window.Position(x, y, w, h, false, true, guiApp.windowIsResizing, guiApp.windowIsResizing, false, true);
3775             // TOCHECK: Investigate why the following only redraws the scrollbars
3776             //window.Position(x, y, w, h, false, true, true, true, false, true);
3777
3778             guiApp.movingLast.x = mouseX;
3779             guiApp.movingLast.y = mouseY;
3780          }
3781       }
3782       reEntrancy = false;
3783    }
3784
3785    public bool MouseMessage(uint method, int x, int y, Modifiers * mods, bool consequential, bool activate)
3786    {
3787       bool result = true;
3788       bool wasMoving = guiApp.windowMoving ? true : false;
3789       bool wasScrolling = guiApp.windowScrolling ? true : false;
3790       Window w = null;
3791       while(result && w != this)
3792       {
3793          Window msgWindow = GetAtPosition(x,y, false, true, w);
3794          Window trueWindow = GetAtPosition(x,y, false, false, w);
3795          bool windowDragged = false;
3796          Window window;
3797          delete w;
3798          w = msgWindow;
3799          if(w) incref w;
3800          window = (w && !w.disabled) ? w : null;
3801          
3802          if(trueWindow) incref trueWindow;
3803
3804          if(consequential) mods->isSideEffect = true;
3805
3806          UpdateMouseMove(x, y, consequential);
3807
3808          if(guiApp.windowCaptured && (guiApp.windowCaptured.rootWindow == this))
3809          {
3810             if(!guiApp.windowCaptured.isEnabled)
3811                guiApp.windowCaptured.ReleaseCapture();
3812             else
3813                window = guiApp.windowCaptured;
3814          }
3815
3816          if(trueWindow && activate &&
3817             (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3818              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3819              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3820              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3821          {
3822             Window modalWindow = trueWindow.FindModal();
3823             
3824             if(mods->alt && !mods->ctrl && !mods->shift)
3825             {
3826                Window moved = trueWindow;
3827                for(moved = trueWindow; moved; moved = moved.parent)
3828                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized)) 
3829                      break;
3830                if(moved) 
3831                {
3832                   window = moved;
3833                   windowDragged = true;
3834
3835                   // Cancel the ALT menu toggling...
3836                   window.rootWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
3837                }
3838             }
3839          }
3840
3841          if(window && activate &&
3842             (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3843              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3844              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3845              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3846          {
3847             Window modalWindow = window.FindModal();
3848
3849             /*if(mods->alt && !mods->shift && !mods->ctrl)
3850             {
3851                Window moved = window;
3852                for(moved = window; moved; moved = moved.parent)
3853                   if(method == OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized)) 
3854                      break;
3855                if(moved) 
3856                {
3857                   window = moved;
3858                   windowDragged = true;
3859
3860                   // Cancel the ALT menu toggling...
3861                   window.rootWindow.KeyMessage(OnKeyDown, 0, 0);
3862                }
3863             }*/
3864
3865             if(!windowDragged)
3866             {
3867                Window activateWindow = modalWindow ? modalWindow : window;
3868                if(activateWindow && !activateWindow.isRemote)
3869                {
3870                   bool doActivation = true;
3871                   //bool needToDoActivation = false;
3872                   Window check = activateWindow;
3873
3874                   for(check = activateWindow; check && check != guiApp.desktop; check = check.parent)
3875                   {
3876                      if(!check.style.inactive)
3877                      {
3878                         //needToDoActivation = true;
3879                         if(check.active)
3880                            doActivation = false;
3881                         break;
3882                      }
3883                   }
3884                   /*
3885                   if(!needToDoActivation)
3886                      doActivation = false;
3887                   */
3888
3889                   if((doActivation && (activateWindow.parent != guiApp.desktop || guiApp.fullScreen)) || 
3890                      (guiApp.interimWindow && !window.IsDescendantOf(guiApp.interimWindow)))
3891                   {
3892                      //if(activate)
3893                      {
3894                         incref activateWindow;
3895                         if(!activateWindow.ActivateEx(true, true, false, true, null, null))
3896                         {
3897                            delete activateWindow;
3898                            delete trueWindow;
3899                            return false;
3900                         }
3901                         if(activateWindow._refCount == 1)
3902                         {
3903                            delete activateWindow;
3904                            delete trueWindow;
3905                            return false;
3906                         }
3907                         delete activateWindow;
3908                      }
3909                      mods->isActivate = true;
3910                   }
3911                }
3912             }
3913             if(!modalWindow && window && !window.destroyed)
3914             {
3915                if(!guiApp.windowCaptured || windowDragged)
3916                {
3917                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown)
3918                   {
3919                      bool moving = ((window.state != maximized &&
3920                            window.IsMouseMoving(
3921                         x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
3922                         || (guiApp.windowMoving && !guiApp.windowIsResizing);
3923
3924                      if(!moving && window.IsMouseResizing(
3925                         x - window.absPosition.x,
3926                         y - window.absPosition.y,
3927                         window.size.w, window.size.h,
3928                         &guiApp.resizeX, &guiApp.resizeY, &guiApp.resizeEndX, &guiApp.resizeEndY))
3929                      {
3930                         guiApp.windowIsResizing = true;
3931                         guiApp.windowResizingBefore.w = window.size.w;
3932                         guiApp.windowResizingBefore.h = window.size.h;
3933                      }
3934                      if(guiApp.windowIsResizing || windowDragged || moving)
3935                      {
3936                         window.Capture();
3937                         guiApp.windowMoving = window;
3938                         guiApp.windowMovingStart.x = guiApp.movingLast.x = x;
3939                         guiApp.windowMovingStart.y = guiApp.movingLast.y = y;
3940                         guiApp.windowMovingBefore.x = window.position.x;//s;
3941                         guiApp.windowMovingBefore.y = window.position.y;//s;
3942                         if(guiApp.windowMoving == guiApp.windowMoving.rootWindow)
3943                            guiApp.interfaceDriver.StartMoving(guiApp.windowMoving.rootWindow, 0,0,false);
3944                      }
3945                   }
3946                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown)
3947                   {
3948                      if(window.style.fixed &&
3949                         (windowDragged || 
3950                         window.IsMouseMoving(
3951                            x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
3952                      {
3953                         window.ShowSysMenu(x, y);
3954                         result = false;
3955                      }
3956                   }
3957                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown)
3958                   {
3959                      if(window.sbv || window.sbh)
3960                      {
3961                         window.Capture();
3962                         guiApp.windowScrolling = window;
3963                         guiApp.windowScrollingStart.x = x;
3964                         guiApp.windowScrollingStart.y = y;
3965                         guiApp.windowScrollingBefore.x = window.scroll.x;
3966                         guiApp.windowScrollingBefore.y = window.scroll.y;
3967                      }
3968                   }
3969                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick)
3970                   {
3971                      if(window.style.hasMaximize && 
3972                         window.IsMouseMoving( 
3973                            x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h))
3974                      {
3975                         window.SetState(
3976                            (window.state == maximized) ? normal : maximized, false, *mods);
3977                         result = false;
3978                      }
3979                   }
3980                }
3981             }
3982             else
3983                window = null;
3984             if(guiApp.windowMoving) 
3985             {
3986                if(guiApp.windowMoving.parent)
3987                {
3988                   if(guiApp.windowMoving.style.nonClient)
3989                      guiApp.windowMoving.parent.SetMouseRangeToWindow();
3990                   else
3991                      guiApp.windowMoving.parent.SetMouseRangeToClient();
3992                }
3993                else
3994                   FreeMouseRange();
3995                window.UpdateDecorations();
3996             }
3997          }
3998          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp)
3999          {
4000             // Log("\n*** LEFT BUTTON UP ***\n");
4001             if(guiApp.windowMoving)
4002                guiApp.windowMoving.StopMoving();
4003          }
4004          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp)
4005          {
4006             if(guiApp.windowScrolling)
4007             {
4008                Window windowScrolling = guiApp.windowScrolling;
4009                guiApp.windowScrolling = null;
4010                windowScrolling.ReleaseCapture();
4011             }
4012          }
4013
4014          if(!result || (window && window.destroyed)) window = null;
4015
4016          if(window && window.FindModal())
4017             window = null;
4018
4019          if(trueWindow && trueWindow.FindModal())
4020             delete trueWindow;
4021          
4022          /*if(trueWindow)
4023             incref trueWindow;
4024          */
4025
4026          /*
4027          msgWindow = GetAtPosition(x,y, true, false);
4028          if(msgWindow)
4029             msgWindow.SelectMouseCursor();
4030          */
4031
4032          if(guiApp.windowCaptured || trueWindow)
4033          {
4034             Window prevWindow = guiApp.prevWindow;
4035             if(guiApp.prevWindow && trueWindow != guiApp.prevWindow)
4036             {
4037                guiApp.prevWindow.mouseInside = false;
4038                guiApp.prevWindow = null;
4039
4040                // Eventually fix this not to include captured?
4041                if(!prevWindow.OnMouseLeave(*mods))
4042                   result = false;
4043             }
4044             if(result && trueWindow && !trueWindow.destroyed/* && trueWindow == window*/)
4045             {
4046                Box box = trueWindow.box;
4047                box.left += trueWindow.absPosition.x;
4048                box.right += trueWindow.absPosition.x;
4049                box.top += trueWindow.absPosition.y;
4050                box.bottom += trueWindow.absPosition.y;
4051
4052                if(box.IsPointInside({x, y}) && trueWindow != /*guiApp.*/prevWindow /*!trueWindow.mouseInside*/)
4053                {
4054                   int overX = x - (trueWindow.absPosition.x + trueWindow.clientStart.x);
4055                   int overY = y - (trueWindow.absPosition.y + trueWindow.clientStart.y);
4056
4057                   overX = Max(Min(overX, 32767),-32768);
4058                   overY = Max(Min(overY, 32767),-32768);
4059
4060                   trueWindow.mouseInside = true;
4061                   if(!trueWindow.OnMouseOver(overX, overY, *mods))
4062                      result = false;
4063                }
4064             }
4065             if(trueWindow && trueWindow._refCount > 1 && !trueWindow.destroyed)
4066                guiApp.prevWindow = trueWindow;
4067             else
4068                guiApp.prevWindow = null;
4069          }
4070          SelectMouseCursor();
4071
4072          if(window && !guiApp.windowMoving && !wasMoving && !wasScrolling)
4073          {
4074             int clientX = x - (window.absPosition.x + window.clientStart.x);
4075             int clientY = y - (window.absPosition.y + window.clientStart.y);
4076
4077             bool (* MouseMethod)(Window instance, int x, int y, Modifiers mods);
4078
4079             clientX = Max(Min(clientX, 32767),-32768);
4080             clientY = Max(Min(clientY, 32767),-32768);
4081
4082             MouseMethod = (void *)window._vTbl[method];
4083
4084             if(MouseMethod /*&& !consequential*/ && !window.disabled)
4085             {
4086                incref window;
4087                if(!MouseMethod(window, clientX, clientY, *mods))
4088                   result = false;
4089                delete window;
4090             }
4091          }
4092          delete trueWindow;
4093          /*
4094          if(result && w && w.clickThrough && w.parent)
4095             w = w.parent;
4096          else
4097             break;
4098          */
4099          if(!result || !w || !w.clickThrough)
4100             break;
4101       }
4102       delete w;
4103       return result;
4104    }
4105
4106    // --- Mouse cursor management ---
4107
4108    bool KeyMessage(uint method, Key key, unichar character)
4109    {
4110       bool status = true;
4111       if(!parent)
4112       {
4113          if(guiApp.interimWindow)
4114             this = guiApp.interimWindow;
4115       }
4116 #ifdef _DEBUG
4117       if((SmartKey)key != alt && (SmartKey)key != Key::control && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && parent && this != parent.menuBar)
4118          Print("");
4119 #endif
4120
4121       if(!style.inactive || rootWindow != this)
4122       {
4123          bool (*KeyMethod)(Window window, Key key, unichar ch) = (void *)_vTbl[method];
4124          Window modalWindow = FindModal();
4125          Window interimMaster = master ? master.rootWindow : null;
4126
4127          incref this;
4128
4129          if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4130             status = OnSysKeyDown(key, character);
4131          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4132             status = OnSysKeyHit(key, character);
4133          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4134             status = OnSysKeyUp(key, character);
4135          if(!status)
4136          {
4137             delete this;
4138             return true;
4139          }
4140
4141          // Process Key Message for Internal UI Keyboard actions
4142          if(status && !destroyed && menuBar && state != minimized)
4143          {
4144             // Disable the ALT
4145             if((SmartKey)key != alt) 
4146                menuBar.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
4147             if(menuBar.focus)
4148             {
4149                SmartKey sk = (SmartKey) key;
4150                if((character && !key.alt && !key.ctrl) || sk == left || sk == right || sk == up || sk == down || sk == home || sk == end || sk == escape || sk == alt)
4151                {
4152                   status = menuBar.KeyMessage(method, key, character);
4153                   status = false;
4154                }
4155                else
4156                {
4157                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4158                      menuBar.OnKeyHit(escape, 0);
4159                }
4160                if(!menuBar.focus && guiApp.caretOwner)
4161                   guiApp.caretOwner.UpdateCaret(true, false);
4162             }
4163          }
4164          if(!destroyed && status)
4165          {
4166             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4167             {
4168                switch(key)
4169                {
4170                   case left: case up: case right: case down:
4171                      if(guiApp.windowMoving == this)
4172                      {
4173                         int step = 1; //8;
4174                         int w = guiApp.windowMoving.size.w;
4175                         int h = guiApp.windowMoving.size.h;
4176                         int x = guiApp.windowMoving.scrolledPos.x;
4177                         int y = guiApp.windowMoving.scrolledPos.y;
4178
4179                         if(guiApp.textMode)
4180                         {
4181                            if(key == down || key == up)
4182                               step = Max(step, textCellH);
4183                            else
4184                               step = Max(step, textCellW);
4185                         }
4186
4187                         if(guiApp.windowIsResizing)
4188                         {
4189                            switch(key)
4190                            {
4191                               case left: w-=step; break;
4192                               case right: w+=step; break;
4193                               case up: h-=step;   break;
4194                               case down: h+=step; break;
4195                            }
4196                         }
4197                         else
4198                         {
4199                            switch(key)
4200                            {
4201                               case left: x-=step; break;
4202                               case right: x+=step; break;
4203                               case up: y-=step;   break;
4204                               case down: y+=step; break;
4205                            }
4206                         }
4207
4208                         if(guiApp.resizeX) x += w - guiApp.windowMoving.size.w;
4209                         if(guiApp.resizeY) y += h - guiApp.windowMoving.size.h;
4210
4211                         if(!guiApp.windowIsResizing || guiApp.resizeX)
4212                            x = (x - guiApp.windowMovingBefore.x) + guiApp.windowMovingStart.x;
4213                         else
4214                            x = (w - guiApp.windowResizingBefore.w) + guiApp.windowMovingStart.x;
4215
4216                         if(!guiApp.windowIsResizing || guiApp.resizeY)
4217                            y = (y - guiApp.windowMovingBefore.y) + guiApp.windowMovingStart.y;
4218                         else                           
4219                            y = (h - guiApp.windowResizingBefore.h) + guiApp.windowMovingStart.y;
4220
4221                         guiApp.interfaceDriver.SetMousePosition(x, y);
4222                         ConsequentialMouseMove(true);
4223
4224                         status = false;
4225                      }
4226                      break;
4227                   case escape:
4228                   case enter:
4229                   case keyPadEnter:
4230                      if(guiApp.windowMoving && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4231                      {
4232                         guiApp.windowMoving.StopMoving();
4233                         ConsequentialMouseMove(false);
4234                   
4235                         status = false;
4236                      }
4237                      break;
4238                   case altSpace:
4239                      if(style.fixed)
4240                      {
4241                         ShowSysMenu(absPosition.x, absPosition.y);
4242                         status = false;
4243                      }
4244                      break;
4245                }
4246             }
4247          }
4248
4249          if(!destroyed && status && state != minimized)
4250          {
4251             // Process all the way down the children
4252             if(activeChild && !activeChild.disabled)
4253             {
4254                status = activeChild.KeyMessage(method, key, character);
4255             }
4256             if(status && activeClient && activeChild != activeClient && !activeClient.disabled && (key.alt || key.ctrl) &&
4257                key.code != left && key.code != right && key.code != up && key.code != down)
4258             {
4259                status = activeClient.KeyMessage(method, key, character);
4260             }
4261
4262             // Default Control
4263             if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4264             {
4265                if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && !defaultControl.disabled && state != minimized)
4266                   // && defaultControl != activeChild)
4267                {
4268                   delete previousActive;
4269                   previousActive = activeChild;
4270                   if(previousActive) incref previousActive;
4271
4272                   ConsequentialMouseMove(false);
4273                   if((defaultControl.active ||
4274                      defaultControl.ActivateEx(true, true, false, true, null, null)) && !defaultControl.disabled)
4275                      defaultControl.KeyMessage(method, defaultKey, character);
4276                   status = false;                       
4277                }
4278             }
4279          }
4280
4281          if(!destroyed && status && (!modalWindow || this == guiApp.desktop))
4282          {
4283             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4284             {
4285                switch(key)
4286                {
4287                   case altMinus:
4288                      if(style.fixed)
4289                      {
4290                         ShowSysMenu(absPosition.x, absPosition.y);
4291                         status = false;
4292                      }
4293                      break;
4294                   //case f5:
4295                   /*
4296                   case shiftF5:
4297                      if(this != guiApp.desktop)
4298                      {
4299                         if(!guiApp.windowMoving && !guiApp.windowCaptured)
4300                         {
4301                            if(state != maximized && (key.shift ? style.sizeable : style.fixed))
4302                            {
4303                               MenuMoveOrSize(key.shift, true);
4304                               status = false;
4305                            }
4306                         }
4307                         else if(guiApp.windowMoving)
4308                         {
4309                            guiApp.windowMoving.StopMoving();
4310                            ConsequentialMouseMove(false);
4311                            status = false;
4312                         }
4313                      }
4314                      break;
4315                   */
4316                }
4317             }
4318             if(!destroyed && status && state != minimized)
4319             {
4320                if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4321                {
4322                   switch(key)
4323                   {
4324                      case tab: case shiftTab:
4325                      {
4326                         Window cycleParent = this;
4327                         if(this == guiApp.interimWindow && !master.style.interim && !cycleParent.style.tabCycle)
4328                            cycleParent = master.parent;
4329                         
4330                         if(!guiApp.windowCaptured && cycleParent.style.tabCycle)
4331                         {
4332                            if(cycleParent.CycleChildren(!key.shift, false, false, true))
4333                            {
4334                               Window child = cycleParent.activeChild;
4335
4336                               // Scroll the window to include the active control
4337                               /*
4338                               if(cycleParent.sbh && !child.style.dontScrollHorz)
4339                               {
4340                                  if(child.scrolledPos.x < 0)
4341                                     cycleParent.sbh.Action(Position, 
4342                                        cycleParent.scroll.x + child.scrolledPos.x, 0);
4343                                  else if(child.scrolledPos.x + child.size.w > cycleParent.clientSize.w)
4344                                     cycleParent.sbh.Action(Position,
4345                                        cycleParent.scroll.x + child.scrolledPos.x + child.size.w - cycleParent.clientSize.w, 0);
4346                               }
4347                               if(cycleParent.sbv && !child.style.dontScrollVert)
4348                               {
4349                                  if(child.scrolledPos.y < 0)
4350                                     cycleParent.sbv.Action(Position, 
4351                                        cycleParent.scroll.y + child.scrolledPos.y, 0);
4352                                  else if(child.scrolledPos.y + child.size.w > window.clientSize.h)
4353                                     cycleParent.sbv.Action(Position,
4354                                        cycleParent.scroll.y + child.scrolledPos.y+child.size.h - cycleParent.clientSize.h, 0);
4355                               }
4356                               */
4357                               cycleParent.ConsequentialMouseMove(false);
4358                               status = false;
4359                            }
4360                         }
4361                         break;
4362                      }
4363                      case f6: case shiftF6:
4364                         if(!guiApp.windowMoving /*!guiApp.windowCaptured*/)
4365                         {
4366                            // NOT NEEDED... guiApp.windowMoving.ReleaseCapture();
4367                            if(parent == guiApp.desktop)
4368                               if(guiApp.desktop.CycleChildren(key.shift, true, false, true))
4369                               {
4370                                  status = false;
4371                                  break;
4372                               }
4373                            if(style.tabCycle ||
4374                               CycleChildren(key.shift, true, false, true))
4375                            {
4376                               delete this;
4377                               return true;
4378                            }
4379                         }
4380                         break;
4381                      /*
4382                      // mIRC Style Window Shortcuts
4383                      case alt1: case alt2: case alt3: case alt4: case alt5:
4384                      case alt6: case alt7: case alt8: case alt9: case alt0:
4385                      {
4386                         if(numPositions)
4387                         {
4388                            Window document;
4389                            for(document = children.first; document; document = document.next)
4390                            {
4391                               if(document.style.isDocument && document.documentID - 1 == key.code - k1)
4392                               {
4393                                  if(document == activeChild)
4394                                  {
4395                                     if(document.state == minimized)
4396                                        document.SetState(normal, false, key);
4397                                     else
4398                                     {
4399                                        document.SetState(minimized, false, key);
4400                                        CycleChildren(false, true, false);
4401                                     }
4402                                  }
4403                                  else
4404                                  {
4405                                     if(activeChild.state == maximized && document.style.hasMaximize)
4406                                        document.SetState(maximized, false, key);
4407                                     else if(document.state == minimized)
4408                                        document.SetState(normal, false, key);
4409                                     document.Activate();
4410                                  }
4411                                  status = false;
4412                                  break;
4413                               }
4414                            }
4415                         }
4416                         break;            
4417                      }
4418                      */
4419                   }
4420                }
4421             }
4422          }
4423
4424          if(!destroyed && status)
4425          {
4426             if(state == minimized)
4427             {
4428                delete this;
4429                return true;
4430             }
4431             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4432             {
4433                if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && previousActive)
4434                {
4435                   if(defaultControl.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, character))
4436                      previousActive.ActivateEx(true, false, false, true, null, null);
4437                   delete previousActive;
4438                   status = false;
4439                }
4440             }
4441          }
4442
4443          if(!destroyed && status)
4444          {
4445             status = ProcessHotKeys(method, key, character);
4446          }
4447          if(!destroyed && status && !modalWindow && state != minimized)
4448          {
4449             if(KeyMethod)
4450                status = KeyMethod(this, key, character);
4451             if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4452                status = OnKeyHit(key, character);
4453             if(!destroyed && status && (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit))
4454             {
4455                bool result = false;
4456                switch(key)
4457                {
4458                   case ctrlUp: case ctrlDown:
4459                      if(sbv && !guiApp.windowScrolling)
4460                         result = sbv.Action((key == ctrlUp) ? up : down, 0, key);
4461                      break;
4462                   case wheelUp: case wheelDown:
4463                      if(sbv && !guiApp.windowScrolling)
4464                      {
4465                         result = sbv.Action((key == wheelUp) ? wheelUp : wheelDown, 0, key);
4466                         // Do we want to do a consequential move regardless of result in this case?
4467                         ConsequentialMouseMove(false);
4468                      }
4469                      break;
4470                   case ctrlPageUp: case ctrlPageDown:
4471                      if(sbh && !guiApp.windowScrolling)
4472                         result = sbh.Action((key == ctrlPageUp) ? up : down, 0, key);
4473                      break;
4474                }
4475                if(result)
4476                {
4477                   ConsequentialMouseMove(false);
4478                   status = false;
4479                }
4480             }
4481          }
4482          if(status && !destroyed && menuBar && state != minimized)
4483             status = menuBar.KeyMessage(method, key, character);
4484
4485          if(style.interim && /*destroyed && */status && interimMaster)
4486          {
4487             // Testing this... for Ctrl-O to open dialog when autocompletion listbox is popped...
4488             status = interimMaster.KeyMessage(method, key, character);
4489          }
4490          delete this;
4491       }
4492       return status;
4493    }
4494
4495    bool ProcessHotKeys(uint method, Key key, unichar character)
4496    {
4497       bool status = true;
4498       HotKeySlot hotKey;
4499
4500       for(hotKey = hotKeys.first; hotKey; hotKey = hotKey.next)
4501          if((hotKey.key == key || (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp && hotKey.key.code == key.code)) &&
4502             !hotKey.window.disabled && !hotKey.window.style.hidden && (hotKey.window.style.nonClient || state != minimized))
4503          {
4504             Window hotKeyWindow = hotKey.window;
4505             Window prevActiveWindow = activeChild;
4506
4507             if(prevActiveWindow) incref prevActiveWindow;
4508             incref hotKeyWindow;
4509             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient)
4510                if(!hotKeyWindow.ActivateEx(true, true, false, true, null, null))
4511                {
4512                   status = false;
4513                   delete hotKeyWindow;
4514                   delete prevActiveWindow;
4515                   break;
4516                }
4517
4518             if(hotKeyWindow.style.nonClient && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4519                method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
4520             if(!hotKeyWindow.KeyMessage(method, Key::hotKey, character))
4521             {
4522                // *********   WORKING ON THIS   ***********
4523                if(prevActiveWindow && !guiApp.interimWindow)
4524                   prevActiveWindow.ActivateEx(true, false, false, false, null, null);
4525                status = false;
4526             }
4527             else if(hotKeyWindow.style.inactive)
4528                status = hotKeyWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, Key::hotKey, character);
4529
4530             delete prevActiveWindow;
4531             delete hotKeyWindow;
4532             // For Key Ups, don't set status to false... (e.g.: Releasing Enter vs AltEnter hot key)
4533             if(method != __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4534                status = false;
4535             break;
4536          }
4537       if(status && tabCycle)
4538       {
4539          Window child;
4540          for(child = children.first; child; child = child.next)
4541          {
4542             if(child.tabCycle && !child.ProcessHotKeys(method, key, character))
4543             {
4544                status = false;
4545                break;
4546             }
4547          }
4548       }
4549       return status;
4550    }
4551
4552
4553    // --- Windows and graphics initialization / termination ---
4554    bool SetupRoot(void)
4555    {
4556       Window child;
4557
4558       // Setup relationship with outside world (bb root || !bb)
4559       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || this == guiApp.desktop || 
4560          (displayDriver && displayDriver != parent.displayDriver))
4561       {
4562          rootWindow = this;
4563          if(!tempExtents)
4564             tempExtents = new0 Extent[4];
4565          against = null;
4566       }
4567       else
4568       {
4569          /*if(guiApp.fullScreenMode)
4570             rootWindow = guiApp.desktop;
4571          else*/
4572          //rootWindow = parent.created ? parent.rootWindow : null;
4573          rootWindow = parent.rootWindow;
4574
4575          if(style.nonClient)
4576             against = &parent.box;
4577          else
4578             against = &parent.clientArea;
4579       }
4580
4581       for(child = children.first; child; child = child.next)
4582          child.SetupRoot();
4583
4584       return (rootWindow && (rootWindow == this || rootWindow.created)) ? true : false;
4585    }
4586
4587    bool Setup(bool positionChildren)
4588    {
4589       bool result = false;
4590       Window child;
4591
4592       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (displayDriver && displayDriver != parent.displayDriver))))
4593       {
4594          subclass(DisplayDriver) dDriver = dispDriver ? dispDriver : GetDisplayDriver(guiApp.defaultDisplayDriver);
4595          DisplaySystem displaySystem = dDriver ? dDriver.displaySystem : null;
4596
4597          windowHandle = dDriver.printer ? null : guiApp.interfaceDriver.CreateRootWindow(this);
4598
4599          // This was here, is it really needed?
4600          //guiApp.interfaceDriver.ActivateRootWindow(this);
4601
4602          if(!displaySystem)
4603          {
4604             displaySystem = DisplaySystem {};
4605             if(!displaySystem.Create(dDriver.name, guiApp.fullScreenMode ? windowHandle : windowHandle /*null*/, guiApp.fullScreenMode))
4606             {
4607                delete displaySystem;
4608             }
4609          }
4610          if(displaySystem)
4611          {
4612             display = Display { alphaBlend = alphaBlend, useSharedMemory = useSharedMemory, windowDriverData = windowData };
4613             if(display.Create(displaySystem, windowHandle))
4614                result = true;
4615             else
4616             {
4617                delete display;
4618             }
4619          }
4620          guiApp.interfaceDriver.SetIcon(this, icon);
4621       }
4622       else if(this != guiApp.desktop)
4623       {
4624          display = rootWindow ? rootWindow.display : null;
4625          result = true;
4626       }
4627       else
4628          result = true;
4629
4630       if(guiApp.acquiredWindow && rootWindow == guiApp.acquiredWindow.rootWindow)
4631          guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, true);
4632
4633       for(child = children.first; child; child = child.next)
4634       {
4635          if(child.created && !child.Setup(false))
4636             result = false; 
4637       }
4638       return result;
4639    }
4640
4641    bool SetupDisplay(void)
4642    {
4643 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
4644       if(is3D) return Window3D_SetupDisplay(this); else 
4645 #endif   
4646       if(SetupRoot())
4647          return Setup(true);
4648       return false;
4649    }
4650
4651    class_data void ** pureVTbl;
4652
4653    bool LoadGraphics(bool creation, bool resetAnchors)
4654    {
4655       bool result = false;
4656       bool success = false;
4657       Window child;
4658
4659       /*
4660       if(!rootWindow.created)
4661          printf("");
4662       */
4663       
4664       if(((subclass(Window))_class).pureVTbl)
4665       {
4666          if(_vTbl == _class._vTbl)
4667          {
4668             _vTbl = ((subclass(Window))_class).pureVTbl;
4669          }
4670          else
4671          {
4672             int m;
4673             for(m = 0; m < _class.vTblSize; m++)
4674             {
4675                if(_vTbl[m] == _class._vTbl[m])
4676                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
4677             }
4678          }
4679       }
4680       if(guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
4681       {
4682          if(_vTbl == ((subclass(Window))_class).pureVTbl)
4683          {
4684             _vTbl = _class._vTbl;
4685          }
4686          else
4687          {
4688             int m;
4689             for(m = 0; m < _class.vTblSize; m++)
4690             {
4691                if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
4692                   _vTbl[m] = _class._vTbl[m];
4693             }
4694          }
4695       }
4696       
4697       if(guiApp.fullScreenMode || this != guiApp.desktop)
4698       {
4699          SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
4700          if(display)
4701          {
4702             ResPtr ptr;
4703             success = true;
4704
4705             display.Lock(false);
4706             if(rootWindow == this)
4707             {
4708                // Set Color Palette
4709                display.SetPalette(palette, true);
4710
4711                // Load Cursors
4712                /*
4713                if(guiApp.fullScreenMode && this == guiApp.desktop)
4714                {
4715                   int c;
4716                   Cursor cursor;
4717
4718                   for(c=0; c<SystemCursor::enumSize; c++)
4719                      if(!guiApp.systemCursors[c].bitmap)
4720                      {
4721                         guiApp.systemCursors[c].bitmapName = guiApp.currentSkin.CursorsBitmaps(c,
4722                            &guiApp.systemCursors[c].hotSpotX,&guiApp.systemCursors[c].hotSpotY, &guiApp.systemCursors[c].paletteShades);
4723                         if(guiApp.systemCursors[c].bitmapName)
4724                         {
4725                            guiApp.systemCursors[c].bitmap = eBitmap_LoadT(guiApp.systemCursors[c].bitmapName, null,
4726                               guiApp.systemCursors[c].paletteShades ? null : guiApp.desktop.display.displaySystem);
4727                            if(guiApp.systemCursors[c].bitmap)
4728                               guiApp.systemCursors[c].bitmap.paletteShades = guiApp.systemCursors[c].paletteShades;
4729                            else
4730                               success = false;
4731                         }
4732                      }
4733                   for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
4734                   {
4735                      cursor.bitmap = eBitmap_LoadT(cursor.bitmapName, null, 
4736                         cursor.paletteShades ? null : guiApp.desktop.display.displaySystem);
4737                      if(cursor.bitmap)
4738                         cursor.bitmap.paletteShades = cursor.paletteShades;
4739                      else
4740                         success = false;
4741                   }
4742                   guiApp.cursorUpdate = true;
4743
4744                   display.Unlock();
4745                   ConsequentialMouseMove(false);
4746                   display.Lock(true);
4747                }
4748                */
4749             }
4750
4751             // Load Window Graphic Resources
4752             
4753             /*
4754             if(usedFont == setFont || usedFont == window.systemFont)
4755                RemoveResource(usedFont);
4756             */
4757             if(setFont)
4758                RemoveResource(setFont); // TESTING setFont instead of usedFont);
4759
4760             if(systemFont)
4761                RemoveResource(systemFont);
4762             
4763             if(captionFont)
4764                RemoveResource(captionFont);
4765
4766             for(ptr = resources.first; ptr; ptr = ptr.next)
4767             {
4768                ptr.loaded = display.displaySystem.LoadResource(ptr.resource);
4769             }
4770             if(setFont)
4771                AddResource(setFont);
4772             if(systemFont)
4773                AddResource(systemFont);
4774
4775             usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
4776
4777             firewatchers font;
4778
4779             /*
4780             if(!setFont)
4781             {
4782                //if(master && master.font)
4783                if(parent && parent.font)
4784                {
4785                   font = FontResource
4786                   {
4787                      faceName = parent.font.faceName,
4788                      size = parent.font.size,
4789                      bold = parent.font.bold,
4790                      italic = parent.font.italic,
4791                      underline = parent.font.underline
4792                   };
4793                   //font = parent.font;
4794                   watch(parent) { font { } };
4795                }
4796                else
4797                   font = guiApp.currentSkin.SystemFont();
4798                AddResource(font);
4799
4800                firewatchers font;
4801             }
4802             */
4803
4804             captionFont = guiApp.currentSkin.CaptionFont();
4805             AddResource(captionFont);
4806
4807             if(OnLoadGraphics())
4808             {
4809                int x,y,w,h;
4810
4811                display.Unlock();
4812
4813                //SetScrollLineStep(sbStep.x, sbStep.y);
4814                
4815                if(this != guiApp.desktop)
4816                {
4817                   if(resetAnchors)
4818                   {
4819                      normalAnchor = anchor;
4820                      normalSizeAnchor = sizeAnchor;
4821                   }
4822
4823                   // Break the anchors for moveable/resizable windows
4824                   /*
4825                   if(style.fixed && style.isDocument)
4826                   {
4827                      ComputeAnchors(ax, ay, aw, ah, &x, &y, &w, &h);
4828                      ax = x;
4829                      ay = y;
4830                      aw = w;
4831                      ah = h;
4832                      anchored = false;
4833                   }
4834                   */
4835                   switch(state)
4836                   {
4837                      case maximized:
4838                      
4839                         stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
4840                         stateSizeAnchor = SizeAnchor {};
4841                         break;
4842                      
4843                      case minimized:
4844                      {
4845                         int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
4846
4847                         stateAnchor = 
4848                            Anchor 
4849                            {
4850                               left = (iconID % maxIcons) * MINIMIZED_WIDTH,
4851                               bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24)
4852                            };
4853                         
4854                         stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
4855                         break;
4856                      }
4857                      case normal:
4858                         stateAnchor = normalAnchor;
4859                         stateSizeAnchor = normalSizeAnchor;
4860                         break;
4861                   }
4862                   position = Point { };
4863                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
4864
4865                }
4866                else
4867                {
4868                   x = scrolledPos.x;
4869                   y = scrolledPos.y;
4870                   w = size.w;
4871                   h = size.h;
4872                }
4873
4874                if(Position(x, y, w, h, true, false, true, true, true, true))
4875                {
4876                   if((this != guiApp.desktop || guiApp.fullScreenMode) && rootWindow == this)
4877                   {
4878                      if(!style.hidden)
4879                         guiApp.interfaceDriver.SetRootWindowState(this, normal, true);
4880                   }
4881
4882                   Update(null);
4883
4884                   result = true;
4885                }
4886             }
4887             else
4888             {
4889                result = false;
4890                display.Unlock();
4891             }
4892          }
4893       }
4894       else
4895       {
4896          success = result = true;
4897       }
4898
4899       if(!creation && result)
4900       {
4901          // Load menu bar first because sys buttons are on it...
4902          if(menuBar)
4903          {
4904             if(!menuBar.LoadGraphics(false, resetAnchors))
4905             {
4906                result = false;
4907                success = false;
4908             }
4909          }
4910          for(child = children.first; child; child = child.next)
4911          {
4912             if(child.created && child != menuBar && !child.LoadGraphics(false, resetAnchors))
4913             {
4914                result = false;
4915                success = false;
4916             }
4917          }
4918          if(!creation)
4919             CreateSystemChildren();
4920
4921          OnApplyGraphics();
4922       }
4923       if(this == guiApp.desktop && !guiApp.fullScreenMode)
4924       {
4925          if(activeChild)
4926             guiApp.interfaceDriver.ActivateRootWindow(activeChild);
4927       }
4928       /*
4929       TODO:
4930       if(!success)
4931          //guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, caption);
4932          guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, class.name);
4933       */
4934       return result;
4935    }
4936
4937    void UnloadGraphics(bool destroyWindows)
4938    {
4939       Window child;
4940
4941       // Free children's graphics
4942       for(child = children.first; child; child = child.next)
4943          child.UnloadGraphics(destroyWindows);
4944
4945       if(display)
4946          display.Lock(false);
4947
4948       // Free cursors
4949       if(guiApp.fullScreenMode && this == guiApp.desktop)
4950       {
4951          Cursor cursor;
4952          SystemCursor c;
4953
4954          for(c=0; c<SystemCursor::enumSize; c++)
4955             if(guiApp.systemCursors[c].bitmap)
4956                delete guiApp.systemCursors[c].bitmap;
4957
4958          for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
4959             delete cursor.bitmap;
4960
4961          guiApp.cursorBackground.Free();
4962       }
4963
4964       if(display && display.displaySystem)
4965       {
4966          ResPtr ptr;
4967
4968          for(ptr = resources.first; ptr; ptr = ptr.next)
4969          {
4970             if(ptr.loaded)
4971             {
4972                display.displaySystem.UnloadResource(ptr.resource, ptr.loaded);
4973                ptr.loaded = null;
4974             }
4975          }
4976
4977          // Free window graphics
4978          OnUnloadGraphics();
4979
4980          // Free skin graphics
4981          if(rootWindow == this)
4982          {
4983             DisplaySystem displaySystem = display.displaySystem;
4984             if(is3D)
4985             {
4986                display.driverData = null;
4987                display.displaySystem = null;
4988             }
4989             display.Unlock();
4990             delete display;
4991             if(displaySystem && !displaySystem.numDisplays && !is3D)
4992                delete displaySystem;
4993          }
4994          else
4995          {
4996             display.Unlock();
4997             display = null;
4998          }
4999       }
5000
5001       if(guiApp.acquiredWindow && this == guiApp.acquiredWindow.rootWindow)
5002          guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, false);
5003
5004       if(this == guiApp.desktop || parent == guiApp.desktop)
5005       {
5006          if((guiApp.fullScreenMode || this != guiApp.desktop) && rootWindow == this && windowHandle && destroyWindows)
5007             guiApp.interfaceDriver.DestroyRootWindow(this);
5008       }
5009    }
5010
5011    // --- Window Hiding ---
5012
5013    void SetVisibility(bool state)
5014    {
5015       bool visible = (style.hidden || !created) ? false : state;
5016       if(visible != this.visible)
5017       {
5018          Window child;
5019
5020          this.visible = visible;
5021          for(child = children.first; child; child = child.next)
5022             child.SetVisibility(visible);
5023          Update(null);
5024          ConsequentialMouseMove(false);
5025       }
5026    }
5027
5028    // --- Windows and graphics initialization / termination ---
5029
5030    bool DisplayModeChanged(void)
5031    {
5032       bool result = false;
5033       if(!guiApp.fullScreenMode && !guiApp.modeSwitching/* && guiApp.desktop.active*/)
5034       {
5035          guiApp.modeSwitching = true;
5036          UnloadGraphics(false);
5037          if(SetupDisplay())
5038             if(LoadGraphics(false, false))
5039                result = true;
5040          guiApp.modeSwitching = false;
5041       }
5042       return result;
5043    }
5044
5045    // --- Window updates system ---
5046
5047    void UpdateDirty(Box updateBox)
5048    {
5049       if(!manageDisplay) { OnRedraw(null);return; }
5050       if(visible)
5051       {
5052          if(display && (!guiApp.fullScreenMode || guiApp.desktop.active) && !guiApp.modeSwitching)
5053          {
5054             display.Lock(true);
5055             if(display.flags.flipping)
5056             {
5057                Update(null);
5058                rootWindow.UpdateDisplay();
5059             }
5060             else
5061                UpdateBackDisplay(updateBox);
5062
5063             if(guiApp.fullScreenMode)
5064             {
5065                guiApp.cursorUpdate = true;
5066                guiApp.PreserveAndDrawCursor();
5067             }
5068             if(guiApp.fullScreenMode)
5069                guiApp.RestoreCursorBackground();
5070             display.Unlock();
5071          }
5072       }
5073    }
5074
5075    // This function is strictly called as a result of system window activation
5076    bool ExternalActivate(bool active, bool activateRoot, Window window, Window swap)
5077    {
5078       bool result = true;
5079       Window interimMaster = null;
5080       Window interimWindow = guiApp.interimWindow;
5081       if(interimWindow && interimWindow.master)
5082          interimMaster = interimWindow.master.rootWindow;
5083
5084       if(active && state == minimized)
5085          // SetState(normal, false, 0);
5086          SetState(lastState, false, 0);
5087
5088       if(interimMaster && swap == interimMaster && interimMaster.IsSlaveOf(window))
5089          return false;
5090
5091       incref this;
5092       /* WTH is this doing here?
5093       while(swap && swap.activeChild)
5094       {
5095          swap = swap.activeChild;         
5096       }
5097       */
5098       // TESTING THIS BEFORE...
5099       if(interimWindow && this == interimMaster)
5100       {
5101          if(active)
5102          {
5103             // Window interimSwap = this;
5104             Window menuBar = this.menuBar;
5105             if(menuBar && interimWindow.master == menuBar)
5106             {
5107                /*
5108                while(interimSwap && interimSwap.activeChild)
5109                   interimSwap = interimSwap.activeChild;
5110
5111                result = interimWindow.ActivateEx(false, false, false, activateRoot, null,
5112                (menuBar && interimWindow.master == menuBar) ? menuBar : interimSwap);
5113                */
5114                result = /*interimWindow.*/ActivateEx(false, false, false, activateRoot, null, menuBar);
5115                //result = ActivateEx(true, true, false, activateRoot, window, null);
5116             }
5117          }
5118       }
5119       else
5120          // Testing & FindModal() here: broke reactivating when a modal dialog is up (didn't root activate dialog)
5121          result = ActivateEx(active, active, false, activateRoot /*&& FindModal()*/, window, swap);
5122
5123       if(interimWindow == this && interimMaster && !active)
5124       {
5125          while(interimMaster && interimMaster.interim && interimMaster.master)
5126          {
5127             // printf("Going up one master %s\n", interimMaster._class.name);
5128             interimMaster = interimMaster.master.rootWindow;
5129          }
5130          // printf("Unactivating interim master %s (%x)\n", interimMaster._class.name, interimMaster);
5131          interimMaster.ActivateEx(active, active, false, activateRoot, window, swap);
5132       }
5133       delete this;
5134       return result;
5135    }
5136
5137    bool DestroyEx(int returnCode)
5138    {
5139       OldLink slave;
5140       Timer timer, nextTimer;
5141       Window child;
5142       OldLink prevOrder = null;
5143       Window client = null;
5144
5145       if(parent) stopwatching(parent, font); 
5146
5147       // if(window.modalSlave) return false;
5148       if(destroyed || !created)
5149       {
5150          if(master)
5151          {
5152             /*
5153             if(destroyed)
5154             {
5155                OldLink slave = master.slaves.FindVoid(this);
5156                master.slaves.Delete(slave);
5157             }
5158             */
5159             // TOFIX IMMEDIATELY: COMMENTED THIS OUT... causes problem second time creating file dialog
5160             //master = null;
5161          }
5162          return true;
5163       }
5164
5165       this.returnCode = (DialogResult)returnCode;
5166
5167       AcquireInput(false);
5168
5169       destroyed = true;
5170       if(hotKey)
5171       {
5172          parent.hotKeys.Delete(hotKey);
5173          hotKey = null;
5174       }
5175
5176       if(guiApp.prevWindow == this)
5177       {
5178          guiApp.prevWindow = null;
5179          OnMouseLeave(0);
5180       }
5181       if(guiApp.caretOwner == this) 
5182       {
5183          guiApp.interfaceDriver.SetCaret(0,0,0);
5184          UpdateCaret(false, true);
5185          guiApp.caretEnabled = false;
5186       }
5187
5188       /*
5189       if(cycle)
5190          parent.childrenCycle.Remove(cycle);
5191       */
5192       if(order)
5193       {
5194          OldLink tmpPrev = order.prev;
5195          if(tmpPrev && !(((Window)tmpPrev.data).style.hidden) && !(((Window)tmpPrev.data).destroyed) && (((Window)tmpPrev.data).created))
5196             prevOrder = tmpPrev;
5197          for(;;)
5198          {
5199             client = tmpPrev ? tmpPrev.data : null;
5200             if(client == this) { client = null; break; }
5201             if(client && (client.style.hidden || client.destroyed || !client.created))
5202                tmpPrev = client.order.prev;
5203             else
5204             {
5205                if(client)
5206                   prevOrder = tmpPrev;
5207                break;
5208             }
5209          }
5210
5211          // If this window can be an active client, make sure the next window we activate can also be one
5212          if(!style.nonClient && style.isActiveClient)
5213          {
5214             tmpPrev = prevOrder;
5215             for(;;)
5216             {
5217                client = tmpPrev ? tmpPrev.data : null;
5218                if(client == this) { client = null; break; }
5219                if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
5220                   tmpPrev = client.order.prev;
5221                else 
5222                {
5223                   if(client)
5224                      prevOrder = tmpPrev;
5225                   break;
5226                }
5227             }
5228             if(client && client.style.hidden) client = null;
5229          }
5230          // parent.childrenOrder.Remove(order);
5231       }
5232
5233       // TESTING THIS HERE!
5234       created = false;
5235       visible = false;
5236
5237       // If no display, don't bother deactivating stuff (causes unneeded problems when trying
5238       // to create a window inside a rootwindow that's being destroyed)
5239       // DISABLED THIS BECAUSE OF CREATING WINDOW IN DESKTOP IN WINDOWED MODE
5240
5241       if(parent && !parent.destroyed /*&&
5242          rootWindow && rootWindow.display && !rootWindow.destroyed*/)
5243       {
5244          if(parent.defaultControl == this)
5245             parent.defaultControl = null;
5246          if((parent.activeChild == this /*|| parent.activeClient == this */|| guiApp.interimWindow == this))
5247          {
5248             if(order && prevOrder && prevOrder.data != this && active)
5249             {
5250                //((Window)prevOrder.data).ActivateEx(true, false, false, false /*true*/, null);
5251
5252                ((Window)prevOrder.data).ActivateEx(true, false, false, (rootWindow == this) ? true : false, null, null);
5253                if(parent.activeClient == this)
5254                {
5255                   parent.activeClient = null;
5256                   parent.UpdateActiveDocument(null);
5257                }
5258             }
5259             else 
5260             {
5261                if(guiApp.interimWindow == this)
5262                {
5263                   bool goOn = true;
5264                   PropagateActive(false, null, &goOn, true);
5265                }
5266                else
5267                {
5268                   //if(window.parent.activeChild == window)
5269                      parent.activeChild = null;
5270                   if(!style.nonClient /*&& style.isActiveClient*/)
5271                   {
5272                      Window previous = parent.activeClient;
5273                      if(style.isActiveClient)
5274                         parent.activeClient = null;
5275                      parent.UpdateActiveDocument(previous);
5276                   }
5277                }
5278             }
5279          }
5280          else if(parent.activeClient == this)
5281          {
5282             parent.activeClient = client;
5283             parent.UpdateActiveDocument(this);
5284
5285          }
5286       }
5287       if(guiApp.interimWindow == this)
5288       {
5289          guiApp.interimWindow = null;
5290          if(guiApp.caretOwner)
5291          {
5292             Window desktop = guiApp.desktop;
5293             if(desktop.activeChild && desktop.activeChild.menuBar && !desktop.activeChild.menuBar.focus)
5294                guiApp.caretOwner.UpdateCaret(false, false);
5295          }
5296       }
5297
5298       active = false;
5299       if(style.modal && master && master.modalSlave == this)
5300          master.modalSlave = null;
5301
5302       if(parent)
5303       {
5304          if(!guiApp.caretOwner && parent.caretSize)
5305          {
5306             guiApp.caretOwner = parent;
5307             parent.UpdateCaret(false, false);
5308             parent.Update(null);
5309          }
5310
5311          if(style.isActiveClient && visible)
5312          {
5313             if(state == minimized) parent.numIcons--;
5314             parent.numPositions--;
5315          }
5316          // Why was this commented out?
5317          GetRidOfVirtualArea();
5318       }
5319       /*
5320       delete cycle;
5321       delete order;
5322       */
5323       dirtyArea.Free(null);
5324       dirtyBack.Free(null);
5325       scrollExtent.Free(null);
5326
5327       /* ATTEMPTING TO MOVE THAT ABOVE
5328       created = false;
5329       visible = false;
5330       */
5331
5332       /*
5333       OnDestroy();
5334       {
5335          //Window next;
5336          //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5337          for(;(child = window.children.first);)
5338          {
5339             for(; child && (child.destroyed || !child.created); child = child.next);
5340             if(child)
5341                child.DestroyEx(0);
5342             else
5343                break;
5344          }
5345       }
5346       */
5347
5348       UnloadGraphics(true);
5349
5350       if(previousActive)
5351          delete previousActive;
5352
5353       menuBar = null;
5354       // statusBar = null;
5355       sbv = sbh = null;
5356
5357       if(master && !master.destroyed)
5358       {
5359          //master.NotifyDestroyed(this, this.returnCode);
5360          NotifyDestroyed(master, this, this.returnCode);
5361       }
5362
5363       for(timer = guiApp.windowTimers.first; timer; timer = nextTimer)
5364       {
5365          nextTimer = timer.next;
5366          if(timer.window == this)
5367          {
5368             // WHY WERE WE SETTING THIS TO NULL? NO MORE WINDOW WHEN RECREATING...
5369             // timer.window = null;
5370             timer.Stop();
5371             //delete timer;
5372          }
5373       }
5374
5375       if(this == guiApp.windowMoving)
5376          StopMoving();
5377
5378       if(guiApp.windowCaptured == this)
5379          ReleaseCapture();
5380          //guiApp.windowCaptured = null;
5381
5382       if(rootWindow != this && rootWindow)
5383          rootWindow.ConsequentialMouseMove(false);
5384
5385       rootWindow = null;
5386
5387       OnDestroy();
5388
5389       {
5390          //Window next;
5391          //for(child = children.first; next = child ? child.next : null, child; child = next)
5392          for(;(child = children.first); )
5393          {
5394             for(; child && (child.destroyed || !child.created); child = child.next);
5395             if(child)
5396                child.DestroyEx(0);
5397             else
5398                break;
5399          }
5400       }
5401
5402       // master = null;
5403
5404       /* // MOVED THIS UP...
5405       {
5406          //Window next;
5407          //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5408          for(;(child = window.children.first); )
5409          {
5410             for(; child && (child.destroyed || !child.created); child = child.next);
5411             if(child)
5412                child.DestroyEx(0);
5413             else
5414                break;
5415          }
5416       }
5417       */
5418
5419       while((slave = slaves.first))
5420       {
5421          for(; slave && (((Window)slave.data).destroyed || !((Window)slave.data).created); slave = slave.next);
5422          if(slave)
5423             ((Window)slave.data).DestroyEx(0);
5424          else
5425             break;
5426       }
5427
5428       if(guiApp.caretOwner == this)
5429          guiApp.caretOwner = null;
5430
5431       sysButtons[0] = null;
5432       sysButtons[1] = null;
5433       sysButtons[2] = null;
5434       activeChild = null;
5435
5436       if(rootWindow != this)
5437       {
5438          Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
5439          if(style.nonClient)
5440          {
5441             box.left   -= parent.clientStart.x;
5442             box.top    -= parent.clientStart.y;
5443             box.right  -= parent.clientStart.x;
5444             box.bottom -= parent.clientStart.y;
5445          }
5446          if(parent) parent.Update(box);
5447       }
5448       /*
5449       if(master)
5450       {
5451          OldLink slave = master.slaves.FindVoid(this);
5452          master.slaves.Delete(slave);
5453          master = null;
5454       }
5455
5456       if(parent)
5457       {
5458          parent.children.Remove(this);
5459          parent = null;
5460       }
5461       */
5462
5463       //autoCreate = false;
5464       //created = false;
5465
5466       // SHOULD THIS BE HERE? FIXED CRASH WITH GOTO DIALOG
5467       if(((subclass(Window))_class).pureVTbl)
5468       {
5469          if(_vTbl == _class._vTbl)
5470          {
5471             _vTbl = ((subclass(Window))_class).pureVTbl;
5472          }
5473          else
5474          {
5475             int m;
5476             for(m = 0; m < _class.vTblSize; m++)
5477             {
5478                if(_vTbl[m] == _class._vTbl[m])
5479                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
5480             }
5481          }
5482       }
5483
5484       delete this;
5485       return true;
5486    }
5487
5488    void SetStateEx(WindowState newState, bool activate)
5489    {
5490       int x,y,w,h;
5491       WindowState prevState = state;
5492
5493       state = newState;
5494       if(prevState != newState)
5495          lastState = prevState;
5496       if(style.isActiveClient && !style.hidden && prevState == minimized)
5497          parent.numIcons--;
5498
5499       // This block used to be at the end of the function... moved it for flicker problem in X
5500       // ------------------------------------------------------
5501       switch(state)
5502       {
5503          case normal:
5504             stateAnchor = normalAnchor;
5505             stateSizeAnchor = normalSizeAnchor;
5506             break;
5507          case maximized:
5508             stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
5509             stateSizeAnchor = SizeAnchor {};
5510             break;
5511          case minimized:
5512          {
5513             int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
5514             Window child;
5515             int size = 256;
5516             byte * idBuffer = new0 byte[size];
5517             int c;
5518             for(child = parent.children.first; child; child = child.next)
5519             {
5520                if(child != this && child.state == minimized)
5521                {
5522                   if(child.iconID > size - 2)
5523                   {
5524                      idBuffer = renew0 idBuffer byte[size*2];
5525                      memset(idBuffer + size, 0, size);
5526                      size *= 2;
5527                   }
5528                   idBuffer[child.iconID] = (byte)bool::true;
5529                }
5530             }
5531             for(c = 0; c<size; c++)
5532                if(!idBuffer[c])
5533                   break;
5534             iconID = c;
5535             delete idBuffer;
5536             if(style.isActiveClient && !style.hidden)
5537                parent.numIcons++;
5538
5539             stateAnchor = Anchor { left = (iconID % maxIcons) * MINIMIZED_WIDTH, bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24) };
5540             stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
5541             break;
5542          }
5543       }
5544
5545       // TOCHECK: Why was this here?
5546       //position.x = (tx > 0) ? tx & 0xFFFFF : tx;
5547       //position.y = (ty > 0) ? ty & 0xFFFFF : ty;
5548
5549       ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5550
5551       Position(x, y, w, h, true, true, true, true, false, true);
5552
5553       if(!style.inactive && !style.interim && this == parent.activeClient)
5554          parent.UpdateActiveDocument(null);
5555
5556       CreateSystemChildren();
5557       // ------------------------------------------------------
5558    }
5559
5560    int GetPositionID(Window forChild)
5561    {
5562       Window child;
5563       int size = 256;
5564       byte * idBuffer = new0 byte[size];
5565       int c;
5566
5567       for(child = children.first; child; child = child.next)
5568       {
5569          if(child.style.isActiveClient && !child.style.hidden && child != forChild)
5570          {
5571             if(child.positionID > size - 2)
5572             {
5573                idBuffer = renew0 idBuffer byte[size*2];
5574                memset(idBuffer + size, 0, size);
5575                size *= 2;
5576             }
5577             idBuffer[child.positionID] = (byte)bool::true;
5578          }
5579       }
5580       for(c = 0; c<size; c++)
5581          if(!idBuffer[c])
5582             break;
5583       delete idBuffer;
5584       return c;
5585    }
5586
5587    // --- Window related graphics ---
5588
5589    void SetPalette(ColorAlpha * newPalette, bool colorMatch)
5590    {
5591       palette = newPalette;
5592       if(rootWindow.display)
5593          rootWindow.display.SetPalette(palette, colorMatch);
5594    }
5595
5596    public bool AcquireInput(bool acquired)
5597    {
5598       bool result = true;
5599       if(acquiredInput != acquired)
5600       {
5601          if(active || (!visible && creationActivation == activate))
5602             result = AcquireInputEx(acquired);
5603          /*if(!result)
5604          {
5605             Print("");
5606          }*/
5607          acquiredInput = acquired ? result : !result;
5608       }
5609       return result;
5610    }
5611
5612    void ListChildren(ListBox listBox)
5613    {
5614       Window child;
5615       char caption[2048];
5616       for(child = children.first; child; child = child.next)
5617       {
5618          if(child.cycle && !child.style.nonClient && child.style.isActiveClient)
5619          {
5620             DataRow row = listBox.AddRow();
5621             row.tag = (int)child;
5622             child.FigureCaption(caption);
5623             row.SetData(null, caption);
5624          }
5625       }
5626    }
5627
5628    void UpdateVisual(Box extent)
5629    {
5630       if(guiApp.driver != null)
5631       {
5632          if(guiApp.fullScreenMode && guiApp.desktop.display)
5633          {
5634             guiApp.desktop.mutex.Wait();
5635             guiApp.desktop.display.Lock(true);
5636          
5637             Update(extent);
5638             if(guiApp.desktop.active)
5639             {
5640                if(guiApp.desktop.dirty || guiApp.cursorUpdate)
5641                {
5642                   if(guiApp.desktop.display.flags.flipping)
5643                      guiApp.desktop.Update(null);
5644                   guiApp.desktop.UpdateDisplay();
5645                   guiApp.cursorUpdate = true;
5646                }
5647                if(guiApp.cursorUpdate || guiApp.desktop.dirty)
5648                {
5649                   guiApp.PreserveAndDrawCursor();
5650                   // guiApp.desktop.display.ShowScreen();
5651                   guiApp.cursorUpdate = false;
5652                   guiApp.desktop.dirty = false;
5653                   guiApp.RestoreCursorBackground();
5654                }
5655             }
5656          
5657             guiApp.desktop.display.Unlock();
5658             guiApp.desktop.mutex.Release();
5659          }
5660          else
5661          {
5662             Window rootWindow = this.rootWindow;
5663             rootWindow.mutex.Wait();
5664             display.Lock(true);
5665          
5666             Update(extent);
5667             if(guiApp.waiting)
5668                guiApp.SignalEvent();
5669             else
5670             {
5671                guiApp.waitMutex.Wait();
5672                guiApp.interfaceDriver.Lock(rootWindow);
5673                if(!rootWindow.style.hidden && rootWindow.dirty)
5674                {
5675                   if(rootWindow.display)
5676                   {
5677                      rootWindow.UpdateDisplay();
5678                      //rootWindow.display.ShowScreen(null);
5679                   }
5680                   rootWindow.dirty = false;
5681                }
5682                guiApp.interfaceDriver.Unlock(rootWindow);
5683                guiApp.waitMutex.Release();
5684             }
5685             display.Unlock();
5686             rootWindow.mutex.Release();
5687          }
5688       }
5689    }
5690
5691    void UnlockDisplay(void)
5692    {
5693       guiApp.interfaceDriver.Unlock(rootWindow);
5694    }
5695
5696    void LockDisplay(void)
5697    {
5698       guiApp.interfaceDriver.Lock(rootWindow);
5699    }
5700
5701    Surface GetSurface(Box box)
5702    {
5703       return Redraw((box == null) ? this.box : box);
5704    }
5705
5706    void SetMousePosition(int x, int y)
5707    {
5708       guiApp.interfaceDriver.SetMousePosition(x + absPosition.x + clientStart.x, y + absPosition.y + clientStart.y);
5709    }
5710
5711    /*
5712    void IntegrationActivate(bool active)
5713    {
5714       if(!guiApp.modeSwitching && !guiApp.fullScreenMode)
5715       {
5716          isForegroundWindow = true;
5717          ActivateEx(active, active, false, false, null, null);
5718          isForegroundWindow = false;
5719       }  
5720    }
5721    */
5722
5723    Window QueryCapture(void)
5724    {
5725       return guiApp.windowCaptured;
5726    }
5727
5728    int GetDocumentID(void)
5729    {
5730       Window child;
5731       int size = 256;
5732       byte * idBuffer = new0 byte[size];
5733       int c;
5734
5735       for(child = children.first; child; child = child.next)
5736       {
5737          if(child.style.isDocument)
5738          {
5739             if(child.documentID-1 > size - 2)
5740             {
5741                idBuffer = renew0 idBuffer byte[size*2];
5742                memset(idBuffer + size, 0, size);
5743                size *= 2;
5744             }
5745             idBuffer[child.documentID-1] = 1;
5746          }
5747       }
5748       for(c = 0; c<size; c++)
5749          if(!idBuffer[c])
5750             break;
5751       numDocuments++;
5752       delete idBuffer;
5753       return c + 1;
5754    }
5755
5756    void SetInitSize(Size size)
5757    {
5758       int x, y, w, h;
5759       sizeAnchor.size = size;
5760       normalSizeAnchor = sizeAnchor;
5761
5762       // Break the anchors for moveable/resizable windows
5763       if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
5764       {
5765          stateAnchor = normalAnchor;
5766          stateSizeAnchor = normalSizeAnchor;
5767
5768          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5769          Position(x,y, w, h, true, true, true, true, false, true);
5770       }
5771    }
5772
5773    void MenuMoveOrSize(bool resize, bool setCursorPosition)
5774    {
5775       if(this != guiApp.desktop && state != maximized && (resize ? (state != minimized && style.sizable) : (style.fixed || moveable)))
5776       {
5777          guiApp.windowIsResizing = resize;
5778          guiApp.windowMoving = this;
5779          guiApp.windowMovingStart = guiApp.movingLast = absPosition;
5780          if(guiApp.windowIsResizing)
5781          {
5782             guiApp.windowMovingStart.x += size.w - 1;
5783             guiApp.windowMovingStart.y += size.h - 1;
5784          }
5785          guiApp.windowMovingBefore = scrolledPos;
5786          guiApp.windowResizingBefore = size;
5787          guiApp.windowMoving.UpdateDecorations();
5788          if(guiApp.windowIsResizing) 
5789             guiApp.resizeEndX = guiApp.resizeEndY = true;
5790
5791          if(setCursorPosition)
5792             guiApp.interfaceDriver.SetMousePosition(guiApp.windowMovingStart.x, guiApp.windowMovingStart.y);
5793          else
5794          {
5795             int x, y;
5796             guiApp.interfaceDriver.GetMousePosition(&x, &y);
5797             guiApp.windowMovingStart.x += x - absPosition.x;
5798             guiApp.windowMovingStart.y += y - absPosition.y;
5799          } 
5800
5801          if(guiApp.windowMoving)
5802          {
5803             if(guiApp.windowMoving.style.nonClient)
5804                guiApp.windowMoving.parent.SetMouseRangeToWindow();
5805             else
5806                guiApp.windowMoving.parent.SetMouseRangeToClient();
5807          }
5808
5809          Capture();
5810
5811          if(this == rootWindow)
5812             guiApp.interfaceDriver.StartMoving(rootWindow, guiApp.windowMovingStart.x, guiApp.windowMovingStart.y, true);
5813       }
5814    }
5815
5816 public:
5817    // normal Methods
5818    bool Create()
5819    {
5820       bool result = false;
5821
5822       if(created)
5823          result = true;
5824       else if(guiApp && guiApp.driver != null)
5825       {
5826          void * systemParent = null;
5827          OldLink slaveHolder;
5828          Window last;
5829          bool visible = !style.hidden;
5830
5831          if(style.embedded) 
5832          {
5833             systemParent = parent;
5834             parent = guiApp.desktop;
5835          }
5836          last = parent ? parent.children.last : null;
5837
5838          if((parent && parent != guiApp.desktop && !parent.created) ||
5839             (master && master != guiApp.desktop && !master.created))
5840             return false;
5841
5842          if(!parent)
5843             property::parent = guiApp.desktop;
5844          if(!master) master = parent;
5845
5846          if(style.modal && master.modalSlave)
5847             return false;
5848
5849          if(parent)
5850             parent.children.Remove(this);
5851          if(master)
5852          {
5853             for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
5854                if(slaveHolder.data == this)
5855                {
5856                   master.slaves.Delete(slaveHolder);
5857                   break;
5858                }
5859          }
5860
5861          if(parent == guiApp.desktop && !mutex)
5862             mutex = Mutex {};
5863
5864          if(style.isDocument)
5865          {
5866             if(parent)
5867                parent.numDocuments--;
5868             documentID = parent.GetDocumentID();
5869          }
5870
5871          if(!style.stayOnTop)
5872             for(; last && last.style.stayOnTop; last = last.prev);
5873
5874          parent.children.Insert((last == this) ? null : last, this);
5875          //parent.children.Add(this);
5876
5877          if(!dispDriver)
5878             dispDriver = parent.dispDriver;
5879          destroyed = false;
5880          if(style.modal)
5881             master.modalSlave = this;
5882
5883          box = Box { MAXINT, MAXINT, MININT, MININT }; //-MAXINT, -MAXINT };
5884
5885          incref this;
5886          incref this;
5887
5888          master.slaves.Add(slaveHolder = OldLink { data = this });
5889          if(slaveHolder)
5890          {
5891             if(setHotKey)
5892             {
5893                parent.hotKeys.Add(hotKey = HotKeySlot { key = setHotKey, window = this });
5894             }
5895             if(style.isDefault && !parent.defaultControl)
5896                parent.defaultControl = this;
5897
5898             stateAnchor = normalAnchor = anchor;
5899             stateSizeAnchor = normalSizeAnchor = sizeAnchor;
5900
5901             // TOCHECK: Why is this here?
5902             //position.x = (ax > 0) ? ax & 0xFFFFF : ax;
5903             //position.y = (ay > 0) ? ay & 0xFFFFF : ay;
5904
5905             this.visible = false;
5906             style.hidden = true;
5907     
5908             //created = true;
5909             // autoCreate = true;
5910             wasCreated = true;
5911             if(SetupDisplay())
5912             {
5913                created = true;
5914                if(OnCreate())
5915                {
5916                   /*
5917                   if(parent == guiApp.desktop)
5918                      Log("LoadGraphics %s\n", caption);
5919                   */
5920                   if(LoadGraphics(true, false))
5921                   {
5922                      if(!setFont)
5923                      {
5924                         watch(parent)
5925                         {
5926                            font
5927                            {
5928                               usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
5929                               firewatchers font;
5930                               Update(null);
5931                            }
5932                         };
5933                      }
5934
5935                      if(style.hasMenuBar /*&& menu*/)
5936                      {
5937                         menuBar = 
5938                            PopupMenu
5939                            {
5940                               this,
5941                               menu = menu, isMenuBar = true, anchor = Anchor { top = 23, left = 1, right = 1 },
5942                               interim = false, inactive = true, nonClient = true, size.h = 24
5943                            };
5944                         menuBar.Create();
5945                      }
5946
5947                      if(statusBar)
5948                         statusBar.Create();
5949                      
5950                      // Create the system buttons
5951                      CreateSystemChildren();
5952
5953                      UpdateActiveDocument(null);
5954
5955                      if(style.isDocument)
5956                      {
5957                         if(menu)
5958                         {
5959                            MenuItem item = menu.FindItem(MenuFileSave, 0);
5960                            if(item) item.disabled = !modifiedDocument && fileName;
5961                         }
5962                      }
5963
5964                      /*
5965                      if(parent == guiApp.desktop)
5966                         Log("Preemptive SetState %s\n", caption);
5967                      */
5968
5969                      // Preemptive Set State to ensure proper anchoring
5970                      SetStateEx(state, false);
5971                      /*
5972                      style.hidden = true;
5973                      visible = false;
5974                      */
5975
5976                      {
5977                         Window child, next;
5978                         for(child = children.first; child; child = next)
5979                         {
5980                            next = child.next;
5981                            if(!child.created && (child.autoCreate || child.wasCreated))
5982                               child.Create();
5983                         }
5984                      }
5985
5986                      {
5987                         OldLink link, next;
5988                         for(link = slaves.first; link; link = next)
5989                         {
5990                            Window slave = link.data;
5991                            next = link.next;
5992                            if(!slave.created && (slave.autoCreate || slave.wasCreated))
5993                               slave.Create();
5994                         }
5995                      }
5996
5997                      if(OnPostCreate())
5998                         OnApplyGraphics();
5999
6000                      /*
6001                      if(parent == guiApp.desktop)
6002                         Log("Real SetState %s\n", caption);
6003                      */
6004
6005                      if(isActiveClient && visible)
6006                      {
6007                         parent.numPositions--;
6008                         if(state == minimized) parent.numIcons--;
6009                      }
6010
6011                      // Real set state & activate for proper display & activation
6012                      property::visible = visible;
6013                      //  SetState(state & 0x00000003, true, 0);
6014
6015                      if(visible)
6016                      {
6017                         UpdateCaption();
6018                         /*if(rootWindow == this)
6019                            guiApp.interfaceDriver.ActivateRootWindow(this);
6020                         else*/
6021                         if(creationActivation == activate)
6022                            ActivateEx(true, false, true, true, null, null);
6023                         else if(creationActivation == flash)
6024                            Flash();
6025                      }
6026
6027                      if(!destroyed)
6028                         rootWindow.ConsequentialMouseMove(false);
6029
6030                      result = true;
6031                   }
6032                }
6033             }
6034          }
6035          /*
6036          if(!result)
6037          {
6038             Destroy(0);
6039             guiApp.LogErrorCode(IERR_WINDOW_CREATION_FAILED, caption);
6040          }
6041          */
6042
6043          if(!result)
6044          {
6045             // Testing this here... Otherwise a failed LoadGraphics stalls the application
6046             created = false;
6047             //style.hidden = true; // !visible;
6048             style.hidden = !visible;
6049             if(master.modalSlave == this)
6050                master.modalSlave = null;
6051          }
6052          delete this;
6053       }
6054       return result;
6055    }
6056
6057    void WriteCaption(Surface surface, int x, int y)
6058    {
6059       if(caption)
6060          Interface::WriteKeyedTextDisabled(surface, x,y, caption, hotKey ? hotKey.key : 0, !isEnabled);
6061    }
6062
6063    void Update(Box region)
6064    {
6065       if(this)
6066       {
6067          Window rootWindow;
6068
6069          rootWindow = this.rootWindow;
6070
6071          // rootWindow.mutex.Wait();
6072          if(!destroyed && visible && display)
6073          {
6074             Window child;
6075             Box realBox;
6076             
6077             // Testing this to avoid repetitve full update to take time...
6078             if(dirtyArea.count == 1)
6079             {
6080                BoxItem item = (BoxItem)ACCESS_ITEM(dirtyArea, dirtyArea.first);
6081                if(item.box.left <= box.left &&
6082                   item.box.top <= box.top &&
6083                   item.box.right >= box.right &&
6084                   item.box.bottom >= box.bottom)
6085                {
6086                   rootWindow.dirty = true;
6087                   return;
6088                }
6089             }
6090
6091             if(display.flags.flipping && !rootWindow.dirty)
6092             {
6093                if(this == rootWindow)
6094                   region = null;
6095                else
6096                {
6097                   rootWindow.Update(null);
6098                   return;
6099                }
6100             }
6101             
6102             rootWindow.dirty = true;
6103
6104             if(region != null)
6105             {
6106                realBox = region;
6107                realBox.left += clientStart.x;
6108                realBox.top += clientStart.y;
6109                realBox.right += clientStart.x;
6110                realBox.bottom += clientStart.y;
6111                realBox.Clip(box);
6112             }
6113             else
6114                realBox = box;
6115
6116             if(realBox.right >= realBox.left && 
6117                realBox.bottom >= realBox.top)
6118             {
6119                // if(!rootWindow.fullRender)
6120                   dirtyArea.UnionBox(realBox, rootWindow.tempExtents[0]);
6121
6122                for(child = children.first; child; child = child.next)
6123                {
6124                   if(!child.is3D)
6125                   {
6126                      Box box = realBox;
6127                      box.left -= child.absPosition.x - absPosition.x;
6128                      box.top -= child.absPosition.y - absPosition.y;
6129                      box.right -= child.absPosition.x - absPosition.x;
6130                      box.bottom -= child.absPosition.y - absPosition.y;
6131                      if(box.right >= child.box.left && box.left <= child.box.right &&
6132                         box.bottom >= child.box.top && box.top <= child.box.bottom)
6133                      {
6134                         box.left -= child.clientStart.x;
6135                         box.top -= child.clientStart.y;
6136                         box.right -= child.clientStart.x;
6137                         box.bottom -= child.clientStart.y;
6138                         child.Update(box);
6139                      }
6140                   }
6141                }
6142
6143                realBox.left += absPosition.x - rootWindow.absPosition.x;
6144                realBox.top += absPosition.y - rootWindow.absPosition.y;
6145                realBox.right += absPosition.x - rootWindow.absPosition.x;
6146                realBox.bottom += absPosition.y - rootWindow.absPosition.y;
6147                rootWindow.dirtyBack.UnionBox(realBox, rootWindow.tempExtents[0]);
6148             }
6149          }
6150          else if(this == guiApp.desktop)
6151          {
6152             Window window;
6153             for(window = children.first; window; window = window.next)
6154             {
6155                if(!window.is3D)
6156                {
6157                   if(region != null)
6158                   {
6159                      Box childBox = region;
6160
6161                      childBox.left    -= window.absPosition.x - guiApp.desktop.absPosition.x;
6162                      childBox.top     -= window.absPosition.y - guiApp.desktop.absPosition.y;
6163                      childBox.right   -= window.absPosition.x - guiApp.desktop.absPosition.x;
6164                      childBox.bottom  -= window.absPosition.y - guiApp.desktop.absPosition.y;
6165        
6166                      window.Update(childBox);
6167                   }
6168                   else
6169                      window.Update(null);
6170                }
6171             }
6172          }
6173
6174          // rootWindow.mutex.Release();
6175       }
6176    }
6177
6178    bool Capture(void)
6179    {
6180       bool result = true;
6181       if(guiApp.windowCaptured != this)
6182       {
6183          if(guiApp.windowCaptured)
6184             result = false;
6185          else
6186          {
6187             //Logf("Captured %s (%s)\n", caption, class.name);
6188             guiApp.interfaceDriver.SetMouseCapture(rootWindow);
6189             guiApp.windowCaptured = this;
6190          }
6191       }
6192       return result;
6193    }
6194
6195    bool Destroy(int code)
6196    {
6197       //if(created)
6198       if(this)
6199       {
6200          if(!CloseConfirmation(false)) return false;
6201          incref this;
6202          if(DestroyEx(code))
6203          {
6204             // TOCHECK: Should autoCreate be set to false here?
6205             autoCreate = false;
6206             wasCreated = false;
6207             // Is this needed here? DestroyEx should decref already...
6208             delete this;
6209             return true;
6210          }
6211          delete this;
6212       }
6213       return false;
6214    }
6215
6216    void Move(int x, int y, int w, int h)
6217    {
6218       normalAnchor = Anchor { left = x, top = y };
6219       normalSizeAnchor = SizeAnchor { size = { w, h } };
6220
6221       if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
6222       {
6223          if(destroyed) return;
6224
6225          stateAnchor = normalAnchor;
6226          stateSizeAnchor = normalSizeAnchor;
6227
6228          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
6229          Position(x,y, w, h, true, true, true, true, false, true);
6230       }
6231    }
6232
6233    DialogResult Modal(void)
6234    {
6235       isModal = true;
6236       if(Create())
6237          return DoModal();
6238
6239       // FIXES MEMORY LEAK IF Create() FAILED
6240       incref this;
6241       delete this;
6242       return 0;
6243    }
6244
6245    void SetScrollArea(int width, int height, bool snapToStep)
6246    {
6247       bool resize = false;
6248       if(snapToStep)
6249       {
6250          int stepX = sbStep.x, stepY = sbStep.y;
6251          // Needed to make snapped down position match the skin's check of client area 
6252          // against realvirtual
6253          if(guiApp.textMode)
6254          {
6255             SNAPDOWN(stepX, textCellW);
6256             SNAPDOWN(stepY, textCellH);
6257             stepX = Max(stepX, textCellW);
6258             stepY = Max(stepY, textCellH);
6259          }
6260          if(scrollFlags.snapX)
6261             SNAPUP(width, stepX);
6262          if(scrollFlags.snapY)
6263             SNAPUP(height, stepY);
6264       }
6265
6266       reqScrollArea.w = width;
6267       reqScrollArea.h = height;
6268       noAutoScrollArea = (width > 0 || height > 0);
6269
6270       UpdateScrollBars(true, true);
6271    }
6272
6273    void SetScrollPosition(int x, int y)
6274    {
6275       if(sbh)
6276          sbh.Action(setPosition, x, 0);
6277       else
6278       {
6279          int range;
6280          int seen = clientSize.w, total = reqScrollArea.w;
6281          seen = Max(1,seen);
6282          if(scrollFlags.snapX)
6283             SNAPDOWN(seen, sbStep.x);
6284
6285          if(!total) total = seen;
6286          range = total - seen + 1;
6287          range = Max(range, 1);
6288          if(x < 0) x = 0;
6289          if(x >= range) x = range - 1;
6290
6291          if(scrollFlags.snapX)
6292             SNAPUP(x, sbStep.x);
6293
6294          if(scroll.x != x)
6295             OnHScroll(setPosition, x, 0);
6296
6297          if(guiApp.textMode)
6298          {
6299             SNAPDOWN(x, textCellW);
6300          }
6301          scroll.x = x;
6302       }
6303
6304       if(sbv)
6305          sbv.Action(setPosition, y, 0);
6306       else
6307       {
6308          int range;
6309          int seen = clientSize.h, total = reqScrollArea.h;
6310          seen = Max(1,seen);
6311
6312          if(scrollFlags.snapY)
6313             SNAPDOWN(seen, sbStep.y);
6314
6315          if(!total) total = seen;
6316          range = total - seen + 1;
6317          range = Max(range, 1);
6318          if(y < 0) y = 0;
6319          if(y >= range) y = range - 1;
6320
6321          if(scrollFlags.snapY)
6322             SNAPUP(y, sbStep.y);
6323
6324          if(scroll.y != y)
6325             OnVScroll(setPosition, y, 0);
6326          if(guiApp.textMode)
6327          {
6328             SNAPDOWN(y, textCellH);
6329          }
6330          scroll.y = y;
6331       }
6332       if(!sbh || !sbv)
6333          UpdateCaret(false, false);
6334    }
6335
6336    void SetScrollLineStep(int stepX, int stepY)
6337    {
6338       sbStep.x = stepX;
6339       sbStep.y = stepY;
6340       if(guiApp.textMode)
6341       {
6342          SNAPDOWN(stepX, textCellW);
6343          SNAPDOWN(stepY, textCellH);
6344          stepX = Max(stepX, textCellW);
6345          stepY = Max(stepY, textCellH);
6346       }
6347       if(sbh)
6348          sbh.lineStep = stepX;
6349       if(sbv)
6350          sbv.lineStep = stepY;
6351    }
6352
6353    void SetState(WindowState newState, bool activate, Modifiers mods)
6354    {
6355       if(created)
6356       {
6357          if(state == newState || OnStateChange(newState, mods))
6358          {
6359             WindowState prevState = state;
6360
6361             StopMoving();
6362
6363             // This used to be at the end of the brackets... moved for X, testing...
6364             // This has the effect of activating the window through the system...
6365             if(rootWindow == this)
6366                guiApp.interfaceDriver.SetRootWindowState(this, newState, !style.hidden);
6367       
6368             SetStateEx(newState, activate);
6369
6370             if(rootWindow == this)
6371             {
6372                int x = position.x, y = position.y;
6373                /*if(style.interim)
6374                {
6375                   x -= guiApp.desktop.absPosition.x;
6376                   y -= guiApp.desktop.absPosition.y;
6377                }*/
6378                guiApp.interfaceDriver.PositionRootWindow(this, x, y, size.w, size.h, true, true);
6379             }
6380
6381             //state = newState;
6382             //state = prevState;
6383
6384             if(state != maximized && style.hasMaximize)
6385             {
6386                Window child;
6387                for(child = parent.children.first; child; child = child.next)
6388                {
6389                   if(child != this && child.state == maximized)
6390                      child.SetStateEx(normal, false);
6391                }
6392             }
6393
6394             if(!style.nonClient && (sbv || sbh) && this != parent.sbv && this != parent.sbh)
6395                parent.UpdateScrollBars(true, true);
6396
6397             /*
6398             // Do we really need this stuff here? 
6399             // Shouldn't the Activate stuff take care of it?              
6400             if(parent.rootWindow == parent && style)
6401             {
6402                char caption[2048];
6403                parent.FigureCaption(caption);
6404                guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
6405                parent.UpdateDecorations();
6406             }         
6407             */
6408
6409             rootWindow.ConsequentialMouseMove(false);
6410          }
6411       }
6412       else
6413          state = newState;
6414    }
6415
6416    BitmapResource GetIcon(SkinBitmap iconID)
6417    {
6418       return guiApp.currentSkin.GetBitmap(iconID);
6419    }
6420
6421    void SetMouseRange(Box range)
6422    {
6423       if(range || guiApp.fullScreenMode)
6424       {
6425          Box clip;
6426          if(range != null)
6427          {
6428             clip.left   = range.left + absPosition.x + clientStart.x;
6429             clip.top    = range.top + absPosition.y + clientStart.y;
6430             clip.right  = range.right + absPosition.x + clientStart.x;
6431             clip.bottom = range.bottom + absPosition.y + clientStart.y;
6432          }
6433          else
6434          {
6435             clip.left   = guiApp.desktop.box.left;
6436             clip.top    = guiApp.desktop.box.top;
6437             clip.right  = guiApp.desktop.box.right;
6438             clip.bottom = guiApp.desktop.box.bottom;
6439          }
6440          guiApp.interfaceDriver.SetMouseRange(rootWindow, clip);
6441       }
6442       else
6443          guiApp.interfaceDriver.SetMouseRange(rootWindow, null);
6444    }
6445
6446    void SetMouseRangeToClient(void)
6447    {
6448       if(guiApp.fullScreenMode || this != guiApp.desktop)
6449       {
6450          Box box {0, 0, clientSize.w - 1, clientSize.h - 1 };
6451          box.Clip(clientArea);
6452          SetMouseRange(box);
6453       }
6454       else
6455          SetMouseRange(null);
6456    }
6457
6458    void SetMouseRangeToWindow(void)
6459    {
6460       Box box { -clientStart.x, -clientStart.y, size.w-1, size.h-1 };
6461       if(this == guiApp.desktop)
6462          SetMouseRangeToClient();
6463       else
6464          SetMouseRange(box);
6465    }
6466
6467    // x, y: Desktop Coordinates
6468    void ShowSysMenu(int x, int y)
6469    {
6470       Menu menu { };
6471       PopupMenu windowMenu { master = this, interim = true, position = { x + 1 - guiApp.desktop.position.x, y + 1 - guiApp.desktop.position.y }, menu = menu };
6472       MenuItem
6473       {
6474          menu, "Restore", r, NotifySelect = MenuWindowRestore, 
6475          disabled = (!style.hasMaximize && !style.hasMinimize) || state == normal, bitmap = guiApp.currentSkin.GetBitmap(restore)
6476       };
6477       MenuItem
6478       {
6479          menu, "Move", m, NotifySelect = MenuWindowMove, 
6480          disabled = !style.fixed || state == maximized
6481       };
6482       MenuItem
6483       {
6484          menu, "Size", s, NotifySelect = MenuWindowSize, 
6485          disabled = !style.sizable || state != normal
6486       };
6487       MenuItem
6488       {
6489          menu, "Minimize", n, NotifySelect = MenuWindowMinimize, 
6490          disabled = !style.hasMinimize || state == minimized, bitmap = guiApp.currentSkin.GetBitmap(minimize)
6491       };
6492       MenuItem
6493       {
6494          menu, "Maximize", KeyCode::x, NotifySelect = MenuWindowMaximize, 
6495          disabled = !style.hasMaximize || state == maximized, bitmap = guiApp.currentSkin.GetBitmap(maximize)
6496       };
6497       MenuItem
6498       {
6499          menu, "Stay On Top", t, NotifySelect = MenuWindowStayOnTop, 
6500          disabled = !style.fixed, checkable = true, checked = style.stayOnTop
6501       };
6502       MenuDivider { menu };
6503       MenuItem
6504       {
6505          menu, "Close", c, (parent == guiApp.desktop) ? altF4 : ( style.isActiveClient ? ctrlF4 : 0), NotifySelect = MenuWindowClose,
6506          bold = true, disabled = !style.hasClose, bitmap = guiApp.currentSkin.GetBitmap(close)
6507       };
6508       windowMenu.Create();
6509    }
6510
6511    void Activate(void)
6512    {
6513       ActivateEx(true, true, true, true, null, null);
6514    }
6515
6516    void MakeActive(void)
6517    {
6518       ActivateEx(true, false, true, false, null, null);
6519    }
6520
6521    void SoftActivate(void)
6522    {
6523       if(guiApp.desktop.active)
6524          Activate();
6525       else if(!active)
6526          Flash();
6527    }
6528
6529    void Deactivate(void)
6530    {
6531       ActivateEx(false, true, true, true, null, null);
6532    }
6533
6534    void Flash(void)
6535    {
6536       guiApp.interfaceDriver.FlashRootWindow(rootWindow);
6537    }
6538
6539    bool CycleChildren(bool backward, bool clientOnly, bool tabCycleOnly, bool cycleParents)
6540    {
6541       bool result = false;
6542       if(activeChild && activeChild.cycle)
6543       {
6544          Window modalWindow, child = activeChild;
6545          if(!clientOnly /*&& parent.tabCycle*/)
6546          {
6547             Window next = child;
6548             while(true)
6549             {
6550                if(next.cycle == (backward ? childrenCycle.first : childrenCycle.last))
6551                {
6552                   if(cycleParents)
6553                   {
6554                      if(parent && parent.CycleChildren(backward, false, true, true))
6555                         return true;
6556                      break;
6557                   }
6558                   else
6559                      return false;
6560                }
6561                if(backward)
6562                   next = next.cycle.prev.data;
6563                else
6564                   next = next.cycle.next.data;
6565                if(!next.disabled && !next.inactive /*isRemote*/ && next.created && !next.nonClient && (!clientOnly || next.style.isActiveClient) && !next.style.hidden && next.FindModal() != activeChild)
6566                   break;
6567             }
6568          }
6569          /*
6570          if(!clientOnly && child.cycle == (backward ? childrenCycle.first : childrenCycle.last) && 
6571             parent.tabCycle && parent.CycleChildren(backward, false, false))
6572             return true;
6573          */
6574
6575          if(tabCycleOnly && !tabCycle) return false;
6576
6577          while(child)
6578          {
6579             while(true)
6580             {
6581                if(backward)
6582                   child = child.cycle.prev.data;
6583                else
6584                   child = child.cycle.next.data;
6585                if(child == child.parent.activeChild)
6586                   return result;
6587                else if(!child.disabled && child.created && (!clientOnly || child.style.isActiveClient) && !child.style.hidden && child.FindModal() != activeChild)
6588                   break;
6589             }
6590             modalWindow = child.FindModal();
6591             if(!modalWindow)
6592             {
6593                // Scroll the window to include the active control
6594                if(sbh && !child.style.dontScrollHorz)
6595                {
6596                   if(child.scrolledPos.x < 0)
6597                      sbh.Action(setPosition, scroll.x + child.scrolledPos.x, 0);
6598                   else if(child.scrolledPos.x + child.size.w > clientSize.w)
6599                      sbh.Action(setPosition, scroll.x + child.scrolledPos.x + child.size.w - clientSize.w, 0);
6600                }
6601                if(sbv && !child.style.dontScrollVert)
6602                {
6603                   if(child.scrolledPos.y < 0)
6604                      sbv.Action(setPosition, scroll.y + child.scrolledPos.y, 0);
6605                   else if(child.scrolledPos.y + child.size.h > clientSize.h)
6606                      sbv.Action(setPosition, scroll.y + child.scrolledPos.y + child.size.h - clientSize.h, 0);
6607                }
6608             }
6609             result = true;
6610             child = modalWindow ? modalWindow : child;
6611             child.ActivateEx(true, true, true, true, null, null);
6612             if(child.tabCycle && child.childrenCycle.first)
6613                child = ((OldLink)(backward ? child.childrenCycle.first : child.childrenCycle.last)).data;
6614             else
6615                break;
6616          }
6617       }
6618       else
6619          return false;
6620
6621       ConsequentialMouseMove(false);
6622       return result;
6623    }
6624
6625    void AddResource(Resource resource)
6626    {
6627       if(resource)
6628       {
6629          ResPtr ptr { resource = resource };
6630          resources.Add(ptr);
6631          incref resource;
6632
6633          // Load Graphics here if window is created already
6634          if(/*created && */display)
6635          {
6636             display.Lock(false);
6637             ptr.loaded = display.displaySystem.LoadResource(resource);
6638             display.Unlock();
6639          }
6640          /*
6641          // Temporary hack to load font right away for listbox in dropbox ...
6642          else if(master && master.display)
6643          {
6644             master.display.Lock(false);
6645             master.display.displaySystem.LoadResource(resource);
6646             master.display.Unlock();
6647          }
6648          */
6649       }
6650    }
6651
6652    void RemoveResource(Resource resource)
6653    {
6654       if(resource)
6655       {
6656          ResPtr ptr;
6657          for(ptr = resources.first; ptr; ptr = ptr.next)
6658          {
6659             if(ptr.resource == resource)
6660                break;
6661          }
6662
6663          if(ptr)
6664          {
6665             // Unload Graphics here if window is created already
6666             if(/*created && */display)
6667             {
6668                if(ptr.loaded)
6669                {
6670                   display.Lock(false);
6671                   display.displaySystem.UnloadResource(resource, ptr.loaded);
6672                   display.Unlock();
6673                   ptr.loaded = null;
6674                }
6675             }
6676             delete resource;
6677             resources.Delete(ptr);
6678          }
6679       }
6680    }
6681
6682    void SetCaret(int x, int y, int size)
6683    {
6684       if(!destroyed)
6685       {
6686          caretPos.x = x;
6687          caretPos.y = y;
6688          caretSize = size;
6689          if(active && !style.interim)
6690          {
6691             if(visible || !guiApp.caretOwner)
6692                guiApp.caretOwner = size ? this : null;
6693             if(size)
6694                UpdateCaret(false, false);
6695             else
6696             {
6697                guiApp.interfaceDriver.SetCaret(0,0,0);
6698                UpdateCaret(false, true);
6699                guiApp.caretEnabled = false;
6700             }
6701          }
6702          else if(style.inactive && active)
6703          {
6704             guiApp.interfaceDriver.SetCaret(0,0,0);
6705             UpdateCaret(false, true);
6706             guiApp.caretEnabled = false;
6707          }
6708       }
6709    }
6710
6711    void Scroll(int x, int y)
6712    {
6713       bool opaque = !style.drawBehind || background.a;
6714       if(opaque && display && display.flags.scrolling)
6715       {
6716          Box box = clientArea;
6717          box.left += clientStart.x;
6718          box.top += clientStart.y;
6719          box.right += clientStart.x;
6720          box.bottom += clientStart.y;
6721
6722          //scrollExtent.Free(null);
6723          scrollExtent.AddBox(box);
6724          scrolledArea.x += x;
6725          scrolledArea.y += y;
6726
6727          //scrollExtent.Free();
6728          //scrollExtent.AddBox(clientArea);
6729          //scrollExtent.Offset(clientStart.x, clientStart.y);
6730          //scrolledArea.x = x;
6731          //scrolledArea.y = y;
6732       }
6733       else
6734          Update(clientArea);
6735
6736       if(rootWindow)
6737          rootWindow.dirty = true;
6738    }
6739
6740    void ReleaseCapture()
6741    {
6742       if(guiApp && guiApp.windowCaptured && guiApp.windowCaptured == this)
6743       {
6744          Window oldCaptured = guiApp.windowCaptured;
6745          guiApp.windowCaptured = null;
6746          guiApp.prevWindow = null;
6747          incref oldCaptured;
6748
6749          //guiApp.Log("Released Capture\n");
6750
6751          guiApp.interfaceDriver.SetMouseCapture(null);
6752
6753          //oldCaptured.OnMouseCaptureLost();
6754
6755          if(oldCaptured)
6756             oldCaptured.ConsequentialMouseMove(false);
6757          delete oldCaptured;
6758       }
6759    }
6760
6761    void SetText(char * format, ...)
6762    {
6763       if(this)
6764       {
6765          delete caption;
6766          if(format)
6767          {
6768             char caption[MAX_F_STRING];
6769             va_list args;
6770             va_start(args, format);
6771             vsprintf(caption, format, args);
6772             va_end(args);
6773
6774             this.caption = new char[strlen(caption)+1];
6775             if(this.caption)
6776                strcpy(this.caption, caption);
6777          }
6778          if(created)
6779             UpdateCaption();
6780
6781          firewatchers text;
6782       }
6783    }
6784
6785    bool Grab(Bitmap bitmap, Box box, bool decorations)
6786    {
6787       bool result = false;
6788       if(display || this == guiApp.desktop)
6789       {
6790          Box clip = {MININT, MININT, MAXINT, MAXINT};
6791
6792          if(box != null)
6793             clip = box;
6794
6795          if(!decorations)
6796             clip.Clip(clientArea);
6797          else
6798             clip.Clip(this.box);
6799
6800          if(rootWindow != this)
6801          {
6802             clip.left   += absPosition.y;
6803             clip.top    += absPosition.y;
6804             clip.right  += absPosition.x;
6805             clip.bottom += absPosition.y;
6806          }
6807
6808          clip.left += decorations ? 0 : clientStart.x;
6809          clip.top += decorations ? 0 : clientStart.y;
6810          clip.right += decorations ? 0 : clientStart.x;
6811          clip.bottom += decorations ? 0 : clientStart.y;
6812
6813          if(display && display.flags.flipping)
6814          {
6815             rootWindow.Update(null);
6816             rootWindow.UpdateDisplay();
6817          }
6818
6819          if(!display)
6820          {
6821             Window window { };
6822             window.Create();
6823             result = window.display.displaySystem.driver.GrabScreen(null, bitmap, clip.left, clip.top, 
6824                clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6825             delete window;
6826          }
6827          else
6828             result = display.Grab(bitmap, clip.left, clip.top, 
6829                clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6830
6831          if(bitmap.pixelFormat != pixelFormat888 && bitmap.pixelFormat != pixelFormat8)
6832          {
6833             if(!bitmap.Convert(null, pixelFormat888, null))
6834                result = false;
6835          }
6836       }
6837       return result;
6838    }
6839
6840    void GetMousePosition(int * x, int * y)
6841    {
6842       int mouseX = 0, mouseY = 0;
6843       if(!guiApp.acquiredWindow && (guiApp.desktop.active || !guiApp.fullScreenMode))
6844       {
6845          if(guiApp.driver)
6846             guiApp.interfaceDriver.GetMousePosition(&mouseX, &mouseY);
6847          if(this != guiApp.desktop)
6848          {
6849             mouseX -= absPosition.x + clientStart.x;
6850             mouseY -= absPosition.y + clientStart.y;
6851          }
6852       }
6853       if(x) *x = mouseX;
6854       if(y) *y = mouseY;
6855    }
6856
6857    DialogResult DoModal()
6858    {
6859       DialogResult returnCode = 0;
6860       int terminated = terminateX;
6861       isModal = true;
6862       incref this;
6863       while(!destroyed && guiApp.driver != null)
6864       {
6865          if(terminateX != terminated)
6866          {
6867             terminated = terminateX;
6868             guiApp.desktop.Destroy(0);
6869             if(guiApp.desktop.created)
6870             {
6871                terminated = 0;
6872                //printf("Resetting terminate X to 0\n");
6873                terminateX = 0;
6874             }
6875             break;
6876          }
6877
6878          guiApp.UpdateDisplay();
6879          if(!guiApp.ProcessInput(false))
6880             guiApp.Wait();
6881       }
6882       returnCode = this.returnCode;
6883       delete this;
6884       return returnCode;
6885    }
6886
6887    void DoModalStart()
6888    {
6889       isModal = true;
6890       incref this;
6891    }
6892
6893    bool DoModalLoop()
6894    {
6895       return !destroyed && guiApp.driver != null && terminateX < 2;
6896    }
6897
6898    DialogResult DoModalEnd()
6899    {
6900       DialogResult returnCode = this.returnCode;
6901       delete this;
6902       return returnCode;
6903    }
6904
6905    // --- Window manipulation ---
6906    /*bool GetDisabled()
6907    {
6908       bool disabled = this.disabled;
6909       Window window;
6910       for(window = this; (window = window.master); )
6911       {
6912          if(window.disabled)
6913          {
6914             disabled = true;
6915             break;
6916          }
6917       }
6918       return disabled;
6919    }*/
6920
6921    // --- Mouse Manipulation ---
6922    void GetNCMousePosition(int * x, int * y)
6923    {
6924       GetMousePosition(x, y);
6925       if(x) *x += clientStart.x;
6926       if(y) *y += clientStart.y;
6927    }
6928
6929    // --- Carets manipulation ---
6930    void GetCaretPosition(Point caretPos)
6931    {
6932       caretPos = this.caretPos;
6933    }
6934
6935    int GetCaretSize(void)
6936    {
6937       return caretSize;
6938    }
6939
6940    bool ButtonCloseDialog(Button button, int x, int y, Modifiers mods)
6941    {
6942       Destroy(button.id);
6943       return true;
6944    }
6945
6946    bool CloseConfirmation(bool parentClosing)
6947    {
6948       bool result = true;
6949       OldLink slave;
6950       Window child;
6951
6952       if(closing)
6953          return false;
6954       if(terminateX > 1)
6955          return true;
6956          
6957       closing = true;
6958
6959       if(!OnClose(parentClosing))
6960          result = false;
6961
6962       // If you want to skip this, simply set modifiedDocument to false in OnClose
6963       if(result && (/*fileName || */style.isDocument) && modifiedDocument)
6964       {
6965          DialogResult dialogRes;
6966          char message[1024];
6967          if(fileName)
6968             sprintf(message, "Save changes to %s?", fileName);
6969          else
6970             sprintf(message, "Save changes to Untitled %d?", documentID);
6971
6972          dialogRes = MessageBox { master = master, type = yesNoCancel, text = parent.caption, contents = message }.Modal();
6973
6974          if(dialogRes == yes)
6975          {
6976             // TOFIX: Precomp error if brackets are taken out
6977             result = (DialogResult)MenuFileSave(null, 0) != cancel;
6978          }
6979          else if(dialogRes == cancel)
6980             result = false;
6981       }
6982
6983       if(result)
6984       {
6985          for(slave = slaves.first; slave; slave = slave.next)
6986             if(!((Window)slave.data).CloseConfirmation(true))
6987             {
6988                // ((Window)slave.data).CloseConfirmation(true);
6989                result = false;
6990                break;
6991             }
6992       }
6993
6994       if(result)
6995       {
6996          for(child = children.first; child; child = child.next)
6997             if(child.master != this && !child.CloseConfirmation(true))
6998             {
6999                result = false;
7000                break;
7001             }
7002       }
7003       closing = false;
7004       return result;
7005    }
7006
7007    // Static methods... move them somewhere else?
7008    void ::RestoreCaret()
7009    {
7010       if(guiApp.caretOwner)
7011          guiApp.caretOwner.UpdateCaret(false, false);
7012    }
7013
7014    void ::FreeMouseRange()
7015    {
7016       guiApp.interfaceDriver.SetMouseRange(null, null);
7017    }
7018
7019    // Menu Methods
7020    bool MenuFileClose(MenuItem selection, Modifiers mods)
7021    {
7022       Window document = activeChild;
7023       if(document)
7024          document.Destroy(0);
7025       return true;
7026    }
7027
7028    bool MenuFileExit(MenuItem selection, Modifiers mods)
7029    {
7030       Destroy(0);
7031       return true;
7032    }
7033
7034    bool MenuFileSave(MenuItem selection, Modifiers mods)
7035    {
7036       if(fileName)
7037       {
7038          fileMonitor.fileName = null;
7039          saving = true;
7040
7041          if(OnSaveFile(fileName))
7042          {
7043             //if(OnFileModified != Window::OnFileModified)
7044             {
7045                saving = false;
7046                fileMonitor.fileName = fileName;
7047             }
7048             return true;
7049          }
7050          else
7051          {
7052             MessageBox dialog { master = master, type = yesNoCancel, text = "Error writing file", contents = "Save as a different file?" };
7053             DialogResult answer = dialog.Modal();
7054             saving = false;
7055             if(answer != yes) return (bool)answer;
7056          }
7057       }
7058       return MenuFileSaveAs(selection, mods);
7059    }
7060
7061    bool MenuFileSaveAs(MenuItem selection, Modifiers mods)
7062    {
7063       DialogResult result = (DialogResult)bool::true;
7064       FileDialog fileDialog = saveDialog;
7065
7066       if(!fileDialog)
7067          fileDialog = FileDialog {};
7068       if(fileDialog)
7069       {
7070          incref fileDialog;
7071          if(fileName)
7072             fileDialog.filePath = fileName;
7073          else
7074          {
7075             char filePath[MAX_FILENAME];
7076             sprintf(filePath, "Untitled %d", documentID);
7077             fileDialog.filePath = filePath;
7078          }
7079          fileMonitor.fileName = null;
7080
7081          fileDialog.type = save;
7082          fileDialog.text = "Save As";
7083
7084          while(true)
7085          {
7086             fileDialog.master = master.parent ? master : this;
7087             if(fileDialog.Modal() == ok)
7088             {
7089                char * filePath = fileDialog.filePath;
7090                saving = true;
7091                if(OnSaveFile(filePath))
7092                {
7093                   saving = false;
7094                   property::fileName = filePath;
7095                   NotifySaved(master, this, filePath);
7096                   break;
7097                }
7098                else
7099                {
7100                   MessageBox dialog { master = master.parent ? master : this, type = yesNoCancel, text = "Error writing file", contents = "Save as a different file?" };
7101                   DialogResult answer = dialog.Modal();
7102                   saving = false;
7103                   if(answer != yes) 
7104                   {
7105                      result = answer;
7106                      break;
7107                   }
7108                }
7109             }
7110             else
7111             {
7112                result = cancel;
7113                break;
7114             }
7115          }
7116          //if(OnFileModified != Window::OnFileModified && fileName)
7117          {
7118             if(fileName)
7119                fileMonitor.fileName = fileName;
7120          }
7121          delete fileDialog;
7122       }
7123       return (bool)result; // Actually returning result from Yes/NoCancel message box
7124    }
7125
7126    bool MenuFileSaveAll(MenuItem selection, Modifiers mods)
7127    {
7128       Window document = activeChild;
7129       Window next;
7130       for(document = children.first; document; document = next)
7131       {
7132          next = document.next;
7133          if(document.style.isDocument || document.fileName)
7134             document.MenuFileSave(selection, mods);
7135       }
7136       return true;
7137    }
7138
7139    bool MenuWindowArrangeIcons(MenuItem selection, Modifiers mods)
7140    {
7141       Window document;
7142
7143       for(document = children.first; document; document = document.next)
7144          //if(document.style.isDocument && document.state == minimized)
7145          if(document.style.isActiveClient && document.state == minimized)
7146             document.SetState(minimized, false, mods);
7147       return true;
7148    }
7149
7150    bool MenuWindowCascade(MenuItem selection, Modifiers mods)
7151    {
7152       Window document = activeChild;
7153       if(document)
7154       {
7155          Window firstDocument = null;
7156          Window child;
7157          OldLink cycle = document.cycle.prev;
7158          int id = 0;
7159          while(true)
7160          {
7161             child = cycle.data;
7162             if(child.style.isActiveClient && !child.style.hidden)
7163             {
7164                Window last;
7165
7166                firstDocument = child;
7167                if(child.state == minimized)
7168                   child.SetState(minimized, false, mods);
7169                else
7170                {
7171                   child.positionID = id++;
7172                   child.SetState(normal, false, mods);
7173                   child.anchor.left.type = cascade;
7174                   {
7175                      int x, y, w, h;
7176                      child.normalSizeAnchor = *&child.sizeAnchor;
7177                      child.normalAnchor = child.anchor;
7178
7179                      // Break the anchors for moveable/resizable windows
7180                      if(child.style.fixed)
7181                      {
7182                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7183
7184                         (*&child.normalAnchor).left = x;
7185                         (*&child.normalAnchor).top = y;
7186                         (*&child.normalAnchor).right.type = none;
7187                         (*&child.normalAnchor).bottom.type = none;
7188
7189                         child.normalSizeAnchor.isClientW = false;
7190                         child.normalSizeAnchor.isClientH = false;
7191                         child.normalSizeAnchor.size.w = w;
7192                         child.normalSizeAnchor.size.h = h;
7193                         child.anchored = false;
7194                      }
7195
7196                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7197                      {
7198                         child.stateAnchor = child.normalAnchor;
7199                         child.stateSizeAnchor = child.normalSizeAnchor;
7200
7201                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7202                         child.Position(x, y, w, h, true, true, true, true, false, false);
7203                      }
7204                   }
7205                }
7206
7207                last = children.last;
7208                if(!child.style.stayOnTop)
7209                   for(; last && last.style.stayOnTop; last = last.prev);
7210                children.Move(child, last);
7211                childrenOrder.Move(child.order, childrenOrder.last);
7212             }
7213             if(cycle == document.cycle) break;
7214             cycle = cycle.prev;
7215          }
7216          if(firstDocument)
7217             firstDocument.Activate();
7218       }
7219       return true;
7220    }
7221
7222    bool MenuWindowClose(MenuItem selection, Modifiers mods)
7223    {
7224       if(style.hasClose)
7225          Destroy(0);
7226       return true;
7227    }
7228
7229    // Close all closes all active clients, not all documents
7230    bool MenuWindowCloseAll(MenuItem selection, Modifiers mods)
7231    {
7232       Window next, document;
7233
7234       for(document = children.first; document; document = next)
7235       {
7236          for(next = document.next; next && !(next.style.isActiveClient; next = next.next);
7237          if(document.style.isActiveClient)
7238             if(!document.Destroy(0) && !document.style.hidden)
7239                return false;
7240       }
7241       return true;
7242    }
7243
7244    bool MenuWindowMaximize(MenuItem selection, Modifiers mods)
7245    {
7246       if(style.hasMaximize && state != maximized)
7247          SetState(maximized, 0, 0);
7248       return true;
7249    }
7250
7251    bool MenuWindowMinimize(MenuItem selection, Modifiers mods)
7252    {
7253       if(style.hasMinimize && state != minimized)
7254       {
7255          SetState(minimized, 0, 0);
7256          parent.CycleChildren(false, true, false, true);
7257       }
7258       return true;
7259    }
7260
7261    bool MenuWindowMove(MenuItem selection, Modifiers mods)
7262    {
7263       MenuMoveOrSize(false, selection ? true : false);
7264       return true;
7265    }
7266
7267    bool MenuWindowNext(MenuItem selection, Modifiers mods)
7268    {
7269       CycleChildren(false, true, false, true);
7270       return true;
7271    }
7272
7273    bool MenuWindowPrevious(MenuItem selection, Modifiers mods)
7274    {
7275       CycleChildren(true, true, false, true);
7276       return true;
7277    }
7278
7279    bool MenuWindowSize(MenuItem selection, Modifiers mods)
7280    {
7281       MenuMoveOrSize(true, true);
7282       return true;
7283    }
7284
7285    bool MenuWindowRestore(MenuItem selection, Modifiers mods)
7286    {
7287       if(state != normal)
7288          SetState(normal, 0, 0);
7289       return true;
7290    }
7291
7292    bool MenuWindowSelectWindow(MenuItem selection, Modifiers mods)
7293    {
7294       Window document;
7295       int id = selection.id;
7296       OldLink cycle = activeClient.cycle;
7297       int c = 0;
7298       //for(c = 0, cycle = activeChild.cycle; c<id; cycle = cycle.next, c++);
7299       while(true)
7300       {
7301          Window sibling = cycle.data;
7302          if(sibling.style.isActiveClient)
7303          {
7304             if(c == id)
7305                break;
7306             c++;
7307          }
7308          cycle = cycle.next;
7309       }
7310       document = cycle.data;
7311       document.Activate();
7312       
7313       //if(activeChild.state == maximized)
7314       //  document.SetState(maximized, false, mods);
7315       //else if(document.state == minimized)
7316       //   document.SetState(normal, false, mods);
7317       return true;
7318    }
7319
7320    bool MenuWindowStayOnTop(MenuItem selection, Modifiers mods)
7321    {
7322       stayOnTop = !style.stayOnTop;
7323       return true;
7324    }
7325
7326    bool MenuWindowTileHorz(MenuItem selection, Modifiers mods)
7327    {
7328       Window document = activeChild;
7329       if(document)
7330       {
7331          Window firstDocument = null;
7332          OldLink cycle = document.cycle;
7333          int id = 0;
7334          while(true)
7335          {
7336             Window child = cycle.data;
7337             if(child.style.isActiveClient && !child.style.hidden)
7338             {
7339                if(!firstDocument) firstDocument = child;
7340                if(child.state == minimized)
7341                   child.SetState(minimized, false, mods);
7342                else
7343                {
7344                   child.positionID = id++;
7345                   child.SetState(normal, false, mods);
7346                   child.ActivateEx(true, false, false, false, null, null);   // To move active clients on top of other windows
7347
7348                   child.anchor.left.type = hTiled;
7349                   {
7350                      int x, y, w, h;
7351                      child.normalSizeAnchor = *&child.sizeAnchor;
7352                      child.normalAnchor = child.anchor;
7353
7354                      // Break the anchors for moveable/resizable windows
7355                      if(child.style.fixed)
7356                      {
7357                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7358
7359                         (*&child.normalAnchor).left = x;
7360                         (*&child.normalAnchor).top = y;
7361                         (*&child.normalAnchor).right.type = none;
7362                         (*&child.normalAnchor).bottom.type = none;
7363                         child.normalSizeAnchor.isClientW = false;
7364                         child.normalSizeAnchor.isClientH = false;
7365                         child.normalSizeAnchor.size.w = w;
7366                         child.normalSizeAnchor.size.h = h;
7367                         child.anchored = false;
7368                      }
7369
7370                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7371                      {
7372                         child.stateAnchor = child.normalAnchor;
7373                         child.stateSizeAnchor = child.normalSizeAnchor;
7374
7375                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7376                         child.Position(x,y, w, h, true, true, true, true, false, true);
7377                      }
7378                   }
7379                }
7380             }
7381             if((cycle = cycle.next) == document.cycle) break;
7382          }
7383          if(firstDocument)
7384             firstDocument.Activate();
7385       }
7386       return true;
7387    }
7388
7389    bool MenuWindowTileVert(MenuItem selection, Modifiers mods)
7390    {
7391       Window document = activeChild;
7392       if(document)
7393       {
7394          Window firstDocument = null;
7395          Window child;
7396          OldLink cycle = document.cycle;
7397          int id = 0;
7398          while(true)
7399          {
7400             child = cycle.data;
7401             //if(child.style.isDocument)
7402             if(child.style.isActiveClient && !child.style.hidden)
7403             {
7404                if(!firstDocument) firstDocument = child;
7405                if(child.state == minimized)
7406                   child.SetState(minimized, false, mods);
7407                else
7408                {
7409                   child.positionID = id++;
7410                   child.SetState(normal, false, mods);
7411                   child.ActivateEx(true, false, false, false, null, null);   // To move active clients on top of other windows
7412
7413                   child.anchor.left.type = vTiled;
7414                   {
7415                      int x, y, w, h;
7416                      child.normalSizeAnchor = *&child.sizeAnchor;
7417                      child.normalAnchor = child.anchor;
7418
7419                      // Break the anchors for moveable/resizable windows
7420                      if(child.style.fixed)
7421                      {
7422                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7423
7424                         (*&child.normalAnchor).left = x;
7425                         (*&child.normalAnchor).top = y;
7426                         (*&child.normalAnchor).right.type = none;
7427                         (*&child.normalAnchor).bottom.type = none;
7428                         child.normalSizeAnchor.isClientW = false;
7429                         child.normalSizeAnchor.isClientH = false;
7430                         child.normalSizeAnchor.size.w = w;
7431                         child.normalSizeAnchor.size.h = h;
7432                         child.anchored = false;
7433                      }
7434
7435                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7436                      {
7437                         child.stateAnchor = child.normalAnchor;
7438                         child.stateSizeAnchor = child.normalSizeAnchor;
7439
7440                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7441                         child.Position(x,y, w, h, true, true, true, true, false, true);
7442                      }
7443                   }
7444                }
7445             }
7446             if((cycle = cycle.next) == document.cycle) break;
7447          }
7448          if(firstDocument)
7449             firstDocument.Activate();
7450       }
7451       return true;
7452    }
7453
7454    bool MenuWindowWindows(MenuItem selection, Modifiers mods)
7455    {
7456       WindowList dialog { master = this };
7457       Window document = (Window)dialog.Modal();
7458       if(document)
7459       {
7460          if(activeChild.state == maximized)
7461             document.SetState(maximized, false, mods);
7462          else if(document.state == minimized)
7463             document.SetState(normal, false, mods);
7464          document.Activate();
7465       }
7466       return true;
7467    }
7468
7469    // Virtual Methods
7470    virtual bool OnCreate(void);
7471    virtual void OnDestroy(void);
7472    virtual void OnDestroyed(void);
7473    virtual bool OnClose(bool parentClosing);
7474    virtual bool OnStateChange(WindowState state, Modifiers mods);
7475    virtual bool OnPostCreate(void);
7476    virtual bool OnMoving(int *x, int *y, int w, int h);
7477    virtual bool OnResizing(int *width, int *height);
7478    virtual void OnResize(int width, int height);
7479    virtual void OnPosition(int x, int y, int width, int height);
7480    virtual bool OnLoadGraphics(void);
7481    virtual void OnApplyGraphics(void);
7482    virtual void OnUnloadGraphics(void);
7483    virtual void OnRedraw(Surface surface);
7484    virtual bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct);
7485    virtual void OnActivateClient(Window client, Window previous);
7486    virtual bool OnKeyDown(Key key, unichar ch);
7487    virtual bool OnKeyUp(Key key, unichar ch);
7488    virtual bool OnKeyHit(Key key, unichar ch);
7489    virtual bool OnSysKeyDown(Key key, unichar ch);
7490    virtual bool OnSysKeyUp(Key key, unichar ch);
7491    virtual bool OnSysKeyHit(Key key, unichar ch);
7492    virtual bool OnMouseOver(int x, int y, Modifiers mods);
7493    virtual bool OnMouseLeave(Modifiers mods);
7494    virtual bool OnMouseMove(int x, int y, Modifiers mods);
7495    virtual bool OnLeftButtonDown(int x, int y, Modifiers mods);
7496    virtual bool OnLeftButtonUp(int x, int y, Modifiers mods);
7497    virtual bool OnLeftDoubleClick(int x, int y, Modifiers mods);
7498    virtual bool OnRightButtonDown(int x, int y, Modifiers mods);
7499    virtual bool OnRightButtonUp(int x, int y, Modifiers mods);
7500    virtual bool OnRightDoubleClick(int x, int y, Modifiers mods);
7501    virtual bool OnMiddleButtonDown(int x, int y, Modifiers mods);
7502    virtual bool OnMiddleButtonUp(int x, int y, Modifiers mods);
7503    virtual bool OnMiddleDoubleClick(int x, int y, Modifiers mods);
7504    virtual void OnMouseCaptureLost(void);
7505    virtual void OnHScroll(ScrollBarAction action, int position, Key key);
7506    virtual void OnVScroll(ScrollBarAction action, int position, Key key);
7507    virtual void OnDrawOverChildren(Surface surface);
7508    virtual bool OnFileModified(FileChange fileChange, char * param);
7509    virtual bool OnSaveFile(char * fileName);
7510
7511    // Skins Virtual Functions
7512    virtual void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h);
7513    virtual void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh);
7514    virtual void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
7515    {
7516       *cw = *w;
7517       *ch = *h;      
7518    }
7519    virtual void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7520    virtual void PreShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7521    virtual bool IsMouseMoving(int x, int y, int w, int h);
7522    virtual bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY);
7523    virtual void UpdateNonClient();
7524    virtual void SetBox(Box box);
7525    virtual bool IsInside(int x, int y)
7526    {
7527       return box.IsPointInside({x, y});
7528    }
7529    virtual bool IsOpaque()
7530    {
7531       return (!style.drawBehind || background.a == 255);
7532    }
7533
7534    // Notifications
7535    virtual bool Window::NotifyActivate(Window window, bool active, Window previous);
7536    virtual void Window::NotifyDestroyed(Window window, DialogResult result);
7537    virtual void Window::NotifySaved(Window window, char * filePath);
7538
7539    // Public Methods
7540
7541    // Properties
7542    property Window parent
7543    {
7544       property_category "Layout"
7545       set
7546       {
7547          if(value || guiApp.desktop)
7548          {
7549             Window last;
7550             Window oldParent = parent;
7551             Anchor anchor = this.anchor;
7552
7553             if(value && value.IsDescendantOf(this)) return;
7554             if(value && value == this)
7555                return;
7556             if(!value) value = guiApp.desktop;
7557
7558             if(value == oldParent) return;
7559
7560             if(!master || (master == this.parent && master == guiApp.desktop))
7561                property::master = value;
7562             
7563             if(parent)
7564             {
7565                parent.children.Remove(this);
7566
7567                parent.Update(
7568                {
7569                   box.left - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7570                   box.top - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y,
7571                   box.right - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7572                   box.bottom - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y
7573                });
7574             }
7575
7576             last = value.children.last;
7577
7578             if(style.isDocument)
7579             {
7580                if(parent)
7581                   parent.numDocuments--;
7582                documentID = value.GetDocumentID();
7583             }
7584
7585             if(style.isActiveClient && !style.hidden)
7586             {
7587                if(parent && parent != guiApp.desktop && !(style.hidden))
7588                {
7589                   if(state == minimized) parent.numIcons--;
7590                   parent.numPositions--;
7591                }
7592             }
7593
7594             if(!style.stayOnTop)
7595                for(; last && last.style.stayOnTop; last = last.prev);
7596
7597             value.children.Insert(last, this);
7598
7599             // *** NEW HERE: ***
7600             if(cycle)
7601                parent.childrenCycle.Delete(cycle);
7602             if(order)
7603                parent.childrenOrder.Delete(order);
7604             cycle = null;
7605             order = null;
7606
7607             //if(created)
7608             {
7609                if(hotKey)
7610                {
7611                   if(parent)
7612                      parent.hotKeys.Remove(hotKey);
7613                   value.hotKeys.Add(hotKey);
7614                   hotKey = null;
7615                }
7616                if(parent && parent.defaultControl == this)
7617                   parent.defaultControl = null;
7618
7619                if(style.isDefault && !value.defaultControl)
7620                   value.defaultControl = this;
7621
7622                if(created)
7623                {
7624                   int x = position.x, y = position.y, w = size.w, h = size.h;
7625                   
7626                   int vpw, vph;
7627
7628                   x += parent.absPosition.x - value.absPosition.x + parent.clientStart.x - value.clientStart.x;
7629                   y += parent.absPosition.y - value.absPosition.y + parent.clientStart.y - value.clientStart.y;
7630                   
7631                   vpw = value.clientSize.w;
7632                   vph = value.clientSize.h;
7633                   if(style.nonClient)
7634                   {
7635                      vpw = value.size.w;
7636                      vph = value.size.h;
7637                   }
7638                   else if(style.fixed)
7639                   {
7640                      if(!style.dontScrollHorz && value.scrollArea.w) vpw = value.scrollArea.w;
7641                      if(!style.dontScrollVert && value.scrollArea.h) vph = value.scrollArea.h;
7642                   }
7643
7644                   anchor = this.anchor;
7645
7646                   if(anchor.left.type == offset)            anchor.left.distance = x;
7647                   else if(anchor.left.type == relative)     anchor.left.percent = (float)x / vpw;
7648                   if(anchor.top.type == offset)             anchor.top.distance = y;
7649                   else if(anchor.top.type == relative)      anchor.top.percent = (float)y / vph;
7650                   if(anchor.right.type == offset)           anchor.right.distance = vpw - (x + w);
7651                   //else if(anchor.right.type == relative)  anchor.right.percent = 1.0-(float) (vpw - (x + w)) / vpw;
7652                   else if(anchor.right.type == relative)    anchor.right.percent = (float) (vpw - (x + w)) / vpw;
7653                   if(anchor.bottom.type == offset)          anchor.bottom.distance = vph - (y + h);
7654                   //else if(anchor.bottom.type == relative) anchor.bottom.percent = 1.0-(float) (vph - (y + h)) / vph;
7655                   else if(anchor.bottom.type == relative)   anchor.bottom.percent = (float) (vph - (y + h)) / vph;
7656
7657                   if(!anchor.left.type && !anchor.right.type)
7658                   {
7659                      anchor.horz.distance = (x + w / 2) - (vpw / 2);
7660                      //anchor.horz.type = anchor.horz.distance ? AnchorValueOffset : 0;
7661                   }
7662                   else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
7663                   if(!anchor.top.type && !anchor.bottom.type)
7664                   {
7665                      anchor.vert.distance = (y + h / 2) - (vph / 2);
7666                      //anchor.vert.type = anchor.vert.distance ? AnchorValueOffset : 0;
7667                   }
7668                   else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
7669                }
7670                parent = value;
7671
7672                // *** NEW HERE ***
7673                if(!style.inactive)
7674                {
7675                   if(!style.noCycle)
7676                      parent.childrenCycle.Insert(
7677                         (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
7678                         cycle = OldLink { data = this });
7679                   parent.childrenOrder.Insert(
7680                      (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last, 
7681                      order = OldLink { data = this });
7682                }
7683
7684                if(!style.hidden && style.isActiveClient)
7685                {
7686                   positionID = parent.GetPositionID(this);
7687                   parent.numPositions++;
7688                   if(state == minimized) parent.numIcons--;
7689                }
7690
7691                // *** FONT INHERITANCE ***
7692                if(!setFont && oldParent) 
7693                   stopwatching(oldParent, font);
7694
7695                if(systemFont)
7696                {
7697                   RemoveResource(systemFont);
7698                   delete systemFont;
7699                }
7700                // TESTING WITH WATCHERS:
7701                usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7702                // usedFont = setFont ? setFont : (systemFont);
7703
7704                if(!usedFont)
7705                {
7706                   if(guiApp.currentSkin)
7707                   {
7708                      systemFont = guiApp.currentSkin.SystemFont();
7709                      incref systemFont;
7710                   }
7711                   usedFont = systemFont;
7712                   AddResource(systemFont);
7713                }
7714
7715                if(!setFont)
7716                   watch(value)
7717                   {
7718                      font
7719                      {
7720                         usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7721                         firewatchers font;
7722                         Update(null);
7723                      }
7724                   };
7725                
7726                firewatchers font;
7727
7728
7729                if(value.rootWindow && value.rootWindow.display && rootWindow)
7730                {
7731                   bool reloadGraphics = (oldParent.rootWindow == oldParent && value.rootWindow) || (!value.rootWindow && rootWindow == this) || 
7732                         (value.rootWindow.display && value.rootWindow.display.displaySystem != rootWindow.display.displaySystem);
7733                   
7734                   if(reloadGraphics)
7735                      UnloadGraphics(false);
7736                   SetupDisplay();
7737                   if(reloadGraphics)
7738                      LoadGraphics(false, false);
7739                      
7740                   /*
7741                   if(value.rootWindow != rootWindow)
7742                      DisplayModeChanged();
7743                   else
7744                   */
7745                }
7746                scrolledPos.x = MININT; // Prevent parent update
7747                property::anchor = anchor;
7748                /*
7749                {
7750                   int x, y, w, h;
7751                   if(guiApp.currentSkin)
7752                      guiApp.currentSkin.SetWindowMinimum(this, &skinMinSize.w, &skinMinSize.h);
7753
7754                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7755                   Position(x, y, w, h, true, true, true, true, false, true);
7756                }
7757                */
7758
7759             }
7760             // else parent = value;
7761          }
7762       }
7763       get { return parent; }
7764    };
7765
7766    property Window master
7767    {
7768       property_category "Behavior"
7769       set
7770       {
7771          //if(this == value) return;
7772          if(value && value.IsSlaveOf(this)) return;
7773
7774          if(master != value)
7775          {
7776             if(master)
7777             {
7778                OldLink slaveHolder;
7779                for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
7780                   if(slaveHolder.data == this)
7781                   {
7782                      master.slaves.Delete(slaveHolder);
7783                      break;
7784                   }
7785             }
7786
7787             if(value)
7788                value.slaves.Add(OldLink { data = this });
7789          }
7790          master = value;
7791       }
7792       get { return master ? master : parent; }
7793    };
7794
7795    property char * text
7796    {
7797       property_category "Appearance"
7798       watchable
7799       set
7800       {
7801          delete caption;
7802          if(value)
7803          {
7804             caption = new char[strlen(value)+1];
7805             if(caption)
7806                strcpy(caption, value);
7807          }
7808          if(created)
7809             UpdateCaption();
7810       }
7811       get { return caption; }
7812    };
7813
7814    property Key hotKey
7815    {
7816       property_category "Behavior"
7817       set
7818       {
7819          setHotKey = value;
7820          if(created)
7821          {
7822             if(value)
7823             {
7824                if(!hotKey)
7825                   parent.hotKeys.Add(hotKey = HotKeySlot { });
7826                if(hotKey)
7827                {
7828                   hotKey.key = value;
7829                   hotKey.window = this;
7830                }
7831             }
7832             else if(hotKey)
7833             {
7834                parent.hotKeys.Delete(hotKey);
7835                hotKey = null;
7836             }
7837          }
7838       }
7839       get { return hotKey ? hotKey.key : 0; }
7840    };
7841
7842    property Color background
7843    {
7844       property_category "Appearance"
7845       set
7846       {
7847          background.color = value;
7848          firewatchers;
7849          if(created)
7850          {
7851             Update(null);
7852             if(this == rootWindow)
7853                guiApp.interfaceDriver.SetRootWindowColor(this);
7854          }
7855       }
7856       get { return background.color; }
7857    };
7858
7859    property Percentage opacity
7860    {
7861       property_category "Appearance"
7862       set
7863       {
7864          background.a = (byte)Min(Max((int)(value * 255), 0), 255);
7865          drawBehind = background.a ? false : true;
7866       }
7867       get { return background.a / 255.0f; }
7868    };
7869
7870    property Color foreground
7871    {
7872       property_category "Appearance"
7873       set
7874       {
7875          foreground = value;
7876          firewatchers;
7877          if(created)
7878             Update(null);
7879       }
7880       get { return foreground; }
7881    };
7882
7883    property BorderStyle borderStyle
7884    {
7885       property_category "Appearance"
7886       set
7887       {
7888          if(!((BorderBits)value).fixed)
7889          {
7890             style.hasClose = false;
7891             style.hasMaximize = false;
7892             style.hasMinimize = false;
7893          }
7894          style.borderBits = value;
7895          if(created)
7896          {
7897             int x, y, w, h;
7898             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
7899
7900             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7901             Position(x, y, w, h, true, true, true, true, false, true);
7902             CreateSystemChildren();
7903          }
7904       }
7905       get { return (BorderStyle)style.borderBits; } 
7906    };
7907
7908    property Size minClientSize
7909    {
7910       property_category "Layout"
7911       set { minSize = value; }
7912       get { value = minSize; }
7913    };
7914
7915    property Size maxClientSize
7916    {
7917       property_category "Layout"
7918       set { maxSize = value; }
7919       get { value = maxSize; }
7920    };
7921
7922    property bool hasMaximize
7923    {
7924       property_category "Window Style"
7925       set
7926       {
7927          style.hasMaximize = value;
7928          if(value) { style.fixed = true; style.contour = true; }
7929          if(created)
7930          {
7931             int x, y, w, h;
7932             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
7933
7934             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7935             Position(x, y, w, h, true, true, true, true, false, true);
7936
7937             CreateSystemChildren();
7938          }
7939       }
7940       get { return style.hasMaximize; }
7941    };
7942
7943    property bool hasMinimize
7944    {
7945       property_category "Window Style"
7946       set
7947       {
7948          style.hasMinimize = value;
7949          if(value) { style.fixed = true; style.contour = true; }
7950          if(created)
7951          {
7952             int x, y, w, h;
7953             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
7954
7955             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7956             Position(x, y, w, h, true, true, true, true, false, true);
7957
7958             CreateSystemChildren();
7959          }
7960       }
7961       get { return style.hasMinimize;  }
7962    };
7963
7964    property bool hasClose
7965    {
7966       property_category "Window Style"
7967       set
7968       {
7969          style.hasClose = value;
7970          if(value) { style.fixed = true; style.contour = true; }
7971          if(created)
7972          {
7973             int x, y, w, h;
7974             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
7975             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7976             Position(x, y, w, h, true, true, true, true, false, true);
7977             CreateSystemChildren();
7978          }
7979       }
7980       get { return style.hasClose; }
7981    };
7982    
7983    property bool nonClient
7984    {
7985       property_category "Layout"
7986       set
7987       {
7988          style.nonClient = value;
7989          if(value)
7990             style.stayOnTop = true;
7991       }
7992       get { return style.nonClient; }
7993    };
7994
7995    property bool inactive
7996    {
7997       property_category "Behavior"
7998       set
7999       {
8000          if(value) 
8001          {
8002             // *** NEW HERE: ***
8003             if(!style.inactive)
8004             {
8005                if(cycle)
8006                   parent.childrenCycle.Delete(cycle);
8007                if(order)
8008                   parent.childrenOrder.Delete(order);
8009                cycle = null;
8010                order = null;
8011             }
8012
8013             if(created)
8014             {
8015                active = false; // true;
8016                if(parent.activeChild == this)
8017                   parent.activeChild = null;
8018                if(parent.activeClient == this)
8019                   parent.activeClient = null;
8020             }
8021          }
8022          else
8023          {
8024             if(style.inactive)
8025             {
8026                if(!style.noCycle)
8027                {
8028                   parent.childrenCycle.Insert(
8029                      (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
8030                      cycle = OldLink { data = this });
8031                }
8032                parent.childrenOrder.Insert(
8033                   (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8034                   order = OldLink { data = this });
8035             }
8036          }
8037          style.inactive = value;
8038       }
8039       get { return style.inactive; }
8040    };
8041
8042    property bool clickThrough
8043    {
8044       property_category "Behavior"
8045       set { style.clickThrough = value; }
8046       get { return style.clickThrough; }
8047    };
8048
8049    property bool isRemote
8050    {
8051       property_category "Behavior"
8052       set { style.isRemote = value; }
8053       get { return style.isRemote; }
8054    };
8055
8056    property bool noCycle
8057    {
8058       property_category "Behavior"
8059       set { style.noCycle = value; }
8060       get { return style.noCycle; }
8061    };
8062
8063    property bool isModal
8064    {
8065       property_category "Behavior"
8066       set { style.modal = value; }
8067       get { return style.modal; }
8068    };
8069
8070    property bool interim
8071    {
8072       property_category "Behavior"
8073       set { style.interim = value; }
8074       get { return style.interim; }
8075    };
8076
8077    property bool tabCycle
8078    {
8079       property_category "Behavior"
8080       set { style.tabCycle = value; }
8081       get { return style.tabCycle; }
8082    };
8083      
8084    property bool isDefault
8085    {
8086       property_category "Behavior"
8087       set
8088       {
8089          if(parent)
8090          {
8091             if(value)
8092             {
8093                Window sibling;
8094                for(sibling = parent.children.first; sibling; sibling = sibling.next)
8095                   if(sibling != this && sibling.style.isDefault)
8096                      sibling.style.isDefault = false;
8097                parent.defaultControl = this;
8098             }
8099             else if(parent.defaultControl == this)
8100                parent.defaultControl = null;
8101
8102             // Update(null);
8103          }
8104          style.isDefault = value;
8105          if(created)
8106             Position(position.x, position.y, size.w, size.h, true, true, true,true,true, true);
8107       }
8108       get { return style.isDefault; }
8109    };
8110
8111    property bool drawBehind
8112    {
8113       property_category "Window Style"
8114       set { style.drawBehind = value; }
8115       get { return style.drawBehind; }
8116    };
8117
8118    property bool hasMenuBar
8119    {
8120       property_category "Window Style"
8121       set
8122       {
8123          if(value) 
8124          {
8125             if(!menu)
8126             {
8127                menu = Menu { };
8128                incref menu;
8129             }
8130             if(created && !menuBar)
8131             {
8132                menuBar =
8133                   PopupMenu 
8134                   {
8135                      this, menu = menu,
8136                      isMenuBar = true,
8137                      anchor = Anchor { top = 23, left = 1, right = 1 },
8138                      size.h = 24,
8139                      inactive = true, nonClient = true                            
8140                   };
8141                menuBar.Create();
8142             }
8143          }
8144          else if(created && menuBar)
8145          {
8146             menuBar.Destroy(0);
8147             menuBar = null;
8148          }
8149          style.hasMenuBar = value;
8150       }
8151       get { return style.hasMenuBar; }
8152    };
8153
8154    property bool hasStatusBar
8155    {
8156       property_category "Window Style"
8157       set
8158       {
8159          if(value)
8160          {
8161             if(!statusBar)
8162             {
8163                statusBar = StatusBar { this };
8164                incref statusBar;
8165                if(created)
8166                   statusBar.Create();
8167             }
8168          }
8169          else if(statusBar)
8170             delete statusBar;
8171          style.hasStatusBar = value;
8172       }
8173       get { return style.hasStatusBar; }
8174    };
8175    property bool stayOnTop
8176    {
8177       property_category "Window Style"
8178       set
8179       {
8180          if(value)
8181          {
8182             if(created && !style.stayOnTop)
8183             {
8184                if(rootWindow == this)
8185                   guiApp.interfaceDriver.OrderRootWindow(this, true);
8186                else if(parent.children.last != this)
8187                {
8188                   parent.children.Move(this, parent.children.last);
8189                   Update(null);
8190                }
8191             }
8192             style.stayOnTop = true;
8193          }
8194          else
8195          {
8196             if(created && style.stayOnTop)
8197             {
8198                if(rootWindow == this)
8199                   guiApp.interfaceDriver.OrderRootWindow(this, false);
8200                else
8201                {
8202                   Window last;
8203                   if(order)
8204                   {
8205                      OldLink order;
8206                      for(order = (this.order == parent.childrenOrder.first) ? null : this.order.prev; 
8207                          order && ((Window)order.data).style.stayOnTop;
8208                          order = (order == parent.childrenOrder.first) ? null : order.prev);
8209                       last = order ? order.data : null;
8210                   }
8211                   else
8212                   {
8213                      for(last = parent.children.last; 
8214                          last && last.style.stayOnTop;
8215                          last = last.prev);
8216                   }
8217
8218                   parent.children.Move(this, last);
8219                   Update(null);
8220                }
8221             }
8222             style.stayOnTop = false;
8223          }
8224       }
8225       get { return style.stayOnTop; }
8226    };
8227
8228    property Menu menu
8229    {
8230       property_category "Window Style"
8231       set
8232       {
8233          delete menu;
8234          if(value)
8235          {
8236             menu = value;
8237             incref menu;
8238          }
8239
8240          if(menuBar && !value)
8241          {
8242             menuBar.Destroy(0);
8243             menuBar = null;
8244          }
8245          if(created)
8246          {
8247             if(!menuBar && style.hasMenuBar && value)
8248             {
8249                menuBar = PopupMenu
8250                          { 
8251                             this, menu = value, isMenuBar = true, 
8252                             anchor = Anchor { left = 1, top = 23, right = 1 }, size.h = 24, 
8253                             inactive = true, nonClient = true
8254                          };
8255                 menuBar.Create();
8256             }
8257             UpdateActiveDocument(null);
8258          }
8259       }
8260       get { return menu; }
8261    };
8262
8263    property FontResource font
8264    {
8265       property_category "Appearance"
8266       watchable
8267       isset { return setFont ? true : false; }
8268       set
8269       {
8270          if(this)
8271          {
8272             if(value && !setFont) { stopwatching(parent, font); }
8273             else if(!value && setFont)
8274             {
8275                watch(parent)
8276                {
8277                   font
8278                   {
8279                      usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
8280                      firewatchers font;
8281                      Update(null);
8282                   }
8283                };
8284             }
8285
8286             if(setFont)
8287             {
8288                RemoveResource(setFont);
8289                delete setFont;
8290             }
8291             if(systemFont)
8292             {
8293                RemoveResource(systemFont);
8294                delete systemFont;
8295             }
8296             setFont = value;
8297             if(setFont)
8298             {
8299                incref setFont;
8300                AddResource(setFont);
8301             }
8302
8303             usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
8304             if(!usedFont)
8305             {
8306                systemFont = guiApp.currentSkin.SystemFont();
8307                incref systemFont;
8308                usedFont = systemFont;
8309                AddResource(systemFont);
8310             }
8311
8312             firewatchers;
8313
8314             Update(null);
8315          }
8316       }
8317       get { return usedFont; }
8318    };
8319
8320    property SizeAnchor sizeAnchor
8321    {
8322       property_category "Layout"
8323       isset
8324       {
8325          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8326                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8327             sizeAnchor.isClientW != sizeAnchor.isClientH;
8328       }
8329       set
8330       {
8331          int x, y, w, h;
8332          sizeAnchor = value;
8333
8334          normalSizeAnchor = sizeAnchor;
8335
8336          if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8337          {
8338             stateAnchor = normalAnchor;
8339             stateSizeAnchor = normalSizeAnchor;
8340
8341             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8342             Position(x,y, w, h, true, true, true, true, false, true);
8343          }
8344       }
8345       get
8346       {
8347          value =
8348          {
8349             { sizeAnchor.isClientW ? clientSize.w : size.w, sizeAnchor.isClientH ? clientSize.h : size.h },
8350             sizeAnchor.isClientW,
8351             sizeAnchor.isClientH
8352          };
8353       }
8354    };
8355
8356    property Size size
8357    {
8358       property_category "Layout"
8359       isset
8360       {
8361          Anchor thisAnchor = anchor;
8362          SizeAnchor thisSizeAnchor = sizeAnchor;
8363          bool leftRight = (anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none);
8364          bool topBottom = (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none);
8365          bool isClient = !sizeAnchor.isClientW && !sizeAnchor.isClientH;
8366          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8367                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8368             !sizeAnchor.isClientW && !sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8369       }
8370       set
8371       {
8372          int x, y, w, h;
8373
8374          sizeAnchor.isClientW = false;
8375          sizeAnchor.isClientH = false;
8376          sizeAnchor.size = value;
8377
8378          normalSizeAnchor = sizeAnchor;
8379
8380          if(state == normal /*|| state == Hidden*/)   // Hidden is new here ...
8381          {
8382             stateAnchor = normalAnchor;
8383             stateSizeAnchor = normalSizeAnchor;
8384
8385             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8386             Position(x, y, w, h, true, true, true, true, false, true);
8387          }
8388       }
8389       get { value = size; }
8390    };
8391
8392    property Size clientSize
8393    {
8394       property_category "Layout"
8395       isset
8396       {
8397          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8398                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8399             sizeAnchor.isClientW && sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8400       }
8401       set
8402       {
8403          int x, y, w, h;
8404          sizeAnchor.isClientW = true;
8405          sizeAnchor.isClientH = true;
8406          sizeAnchor.size = value;
8407
8408          normalSizeAnchor = sizeAnchor;
8409
8410          if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8411          {
8412             stateAnchor = normalAnchor;
8413             stateSizeAnchor = normalSizeAnchor;
8414
8415             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8416             Position(x,y, w, h, true, true, true, true, false, true);
8417          }
8418       }
8419       get { value = clientSize; }
8420    };
8421
8422    property Size initSize { get { value = sizeAnchor.size; } };
8423
8424    property Anchor anchor
8425    {
8426       property_category "Layout"
8427       isset { return (anchor.left.type != offset || anchor.top.type != offset || anchor.right.type || anchor.bottom.type); }
8428
8429       set
8430       {
8431          if(value != null)
8432          {
8433             if(anchor.left.type && anchor.right.type && (!value.left.type || !value.right.type))
8434             {
8435                normalSizeAnchor.isClientW = sizeAnchor.isClientW = false;
8436                normalSizeAnchor.size.w = sizeAnchor.size.w = size.w;
8437             }
8438             if(anchor.top.type && anchor.bottom.type && (!value.top.type || !value.bottom.type))
8439             {
8440                normalSizeAnchor.isClientH = sizeAnchor.isClientH = false;
8441                normalSizeAnchor.size.h = sizeAnchor.size.h = size.h;
8442             }
8443             anchor = value;
8444
8445             if(anchor.right.type && (anchor.horz.type == middleRelative || !anchor.left.type)) 
8446             {
8447                anchor.left.distance = 0;
8448                anchor.horz.type = 0;
8449             }
8450             if(anchor.bottom.type && (anchor.vert.type == middleRelative || !anchor.top.type))
8451             {
8452                anchor.top.distance = 0;
8453                anchor.vert.type = 0;
8454             }
8455
8456             anchored = true;
8457
8458             //if(created)
8459             {
8460                int x, y, w, h;
8461
8462                normalAnchor = anchor;
8463                
8464                // Break the anchors for moveable/resizable windows
8465                /*if(style.fixed ) //&& value.left.type == cascade)
8466                {
8467                   ComputeAnchors(anchor, sizeAnchor, &x, &y, &w, &h);
8468
8469                   this.anchor = normalAnchor = Anchor { left = x, top = y };
8470                   normalSizeAnchor = SizeAnchor { { w, h } };
8471                   anchored = false;
8472                }*/
8473                if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8474                {
8475                   stateAnchor = normalAnchor;
8476                   stateSizeAnchor = normalSizeAnchor;
8477
8478                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8479                   Position(x, y, w, h, true, true, true, true, false, true);
8480                }
8481             }
8482          }
8483          else
8484          {
8485             anchored = false;
8486          }
8487       }
8488       get { value = this ? anchor : Anchor { }; }
8489    };
8490
8491    property Point position
8492    {
8493       property_category "Layout"
8494       set
8495       {
8496          if(value == null) return;
8497
8498          anchor.left = value.x;
8499          anchor.top  = value.y;
8500          anchor.right.type = none;
8501          anchor.bottom.type = none;
8502          //if(created)
8503          {
8504             int x, y, w, h;
8505
8506             normalAnchor = anchor;
8507
8508             // Break the anchors for moveable/resizable windows
8509             /*
8510             if(style.fixed)
8511             {
8512                ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8513
8514                normalAnchor.left = x;
8515                normalAnchor.top = y;
8516                normalAnchor.right.type = none;
8517                normalAnchor.bottom.type = none;
8518                normalSizeAnchor.size.width = w;
8519                normalSizeAnchor.size.height = h;
8520                anchored = false;
8521             }
8522             */
8523             if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8524             {
8525                stateAnchor = normalAnchor;
8526                stateSizeAnchor = normalSizeAnchor;
8527
8528                ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8529                Position(x,y, w, h, true, true, true, true, false, true);
8530             }
8531          }
8532       }
8533       get { value = position; }
8534    };
8535
8536    property bool disabled
8537    {
8538       property_category "Behavior"
8539       set
8540       {
8541          if(this && disabled != value)
8542          {
8543             disabled = value;
8544             if(created)
8545                Update(null);
8546          }
8547       }
8548       get { return (bool)disabled; }
8549    };
8550
8551    property bool isEnabled
8552    {
8553       get
8554       {
8555          Window parent;
8556          for(parent = this; parent; parent = parent.parent)
8557             if(parent.disabled)
8558                return false;
8559          return true;
8560       }
8561    };
8562
8563    property WindowState state
8564    {
8565       property_category "Behavior"
8566       set { SetState(value, false, 0); }
8567       get { return this ? state : 0; }
8568    };
8569
8570    property bool visible
8571    {
8572       property_category "Behavior"
8573       set
8574       {
8575          if(this && !value && !style.hidden && parent)
8576          {
8577             Window client = null;
8578
8579             style.hidden = true;
8580             if(created)
8581             {
8582                OldLink prevOrder = null;
8583
8584                if(rootWindow == this)
8585                   guiApp.interfaceDriver.SetRootWindowState(this, state, false);
8586                else
8587                {
8588                   Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
8589                   if(style.nonClient)
8590                   {
8591                      box.left   -= parent.clientStart.x;
8592                      box.top    -= parent.clientStart.y;
8593                      box.right  -= parent.clientStart.x;
8594                      box.bottom -= parent.clientStart.y;
8595                   }
8596                   parent.Update(box);
8597                }
8598                if(style.modal && master && master.modalSlave == this)
8599                   master.modalSlave = null;
8600
8601                if(style.isActiveClient)
8602                {
8603                   parent.numPositions--;
8604                   if(state == minimized) parent.numIcons--;
8605                }
8606
8607                if(order)
8608                {
8609                   OldLink tmpPrev = order.prev;
8610                   client = tmpPrev ? tmpPrev.data : null;
8611                   if(client && !client.style.hidden && !client.destroyed && client.created)
8612                      prevOrder = tmpPrev;
8613                   for(;;)
8614                   {
8615                      client = tmpPrev ? tmpPrev.data : null;
8616                      if(client == this) { client = null; break; }
8617                      if(client && ((client.style.hidden) || client.destroyed || !client.created))
8618                      {
8619                         tmpPrev = client.order.prev;
8620                      }
8621                      else
8622                      {
8623                         if(client)
8624                            prevOrder = tmpPrev;
8625                         break;
8626                      }
8627                   }
8628
8629                   // If this window can be an active client, make sure the next window we activate can also be one
8630                   if(!style.nonClient && style.isActiveClient)
8631                   {
8632                      tmpPrev = prevOrder;
8633                      for(;;)
8634                      {
8635                         client = tmpPrev ? tmpPrev.data : null;
8636                         if(client == this) { client = null; break; }
8637                         if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
8638                         {
8639                            tmpPrev = client.order.prev;
8640                         }
8641                         else 
8642                         {
8643                            if(client)
8644                               prevOrder = tmpPrev;
8645                            break;
8646                         }
8647                      }
8648                      if(client && client.style.hidden) client = null;
8649                   }
8650                }
8651
8652                if((parent.activeChild == this || guiApp.interimWindow == this) && true /*activate*/)
8653                {
8654                   if(order && prevOrder && prevOrder.data != this)
8655                      ((Window)prevOrder.data).ActivateEx(true, false, false, true, null, null);
8656                   else
8657                      ActivateEx(false, false, false, true, null, null);
8658
8659                   // TESTING THIS HERE FOR HIDING ACTIVE CLIENT
8660                   if(parent.activeClient == this)
8661                   {
8662                      parent.activeClient = null;
8663                      parent.UpdateActiveDocument(null);
8664                   }
8665                }
8666                else if(parent.activeClient == this)
8667                {
8668                   parent.activeClient = client;
8669                   parent.UpdateActiveDocument(this);
8670                }
8671
8672                // *** Not doing this anymore ***
8673               /*
8674                if(cycle)
8675                   parent.childrenCycle.Delete(cycle);
8676                if(order)
8677                   parent.childrenOrder.Delete(order);
8678                cycle = null;
8679                order = null;
8680                */
8681                
8682                SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8683             }
8684
8685             firewatchers;
8686          }
8687          else if(this && value && style.hidden)
8688          {
8689             style.hidden = false;
8690             if(created)
8691             {
8692                SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8693                if(rootWindow == this)
8694                   guiApp.interfaceDriver.SetRootWindowState(this, state, true);
8695
8696                if(style.modal && master)
8697                   master.modalSlave = this;
8698
8699                if(style.isActiveClient)
8700                {
8701                   positionID = parent.GetPositionID(this);
8702                   parent.numPositions++;
8703                   if(state == minimized) parent.numIcons++;
8704                }
8705
8706                // *** NOT DOING THIS ANYMORE ***
8707                /*
8708                if(!(style.inactive))
8709                {
8710                   if(!(style.noCycle))
8711                   {
8712                      cycle = parent.childrenCycle.AddAfter(
8713                         (parent.activeChild && parent.activeChild.cycle) ? 
8714                            parent.activeChild.cycle.prev : null, sizeof(OldLink));
8715                      cycle.data = this;
8716                   }
8717                   order = parent.childrenOrder.AddAfter(
8718                      (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8719                      sizeof(OldLink));
8720                   order.data = this;
8721                }
8722                */
8723      
8724                /*
8725                if(true || !parent.activeChild)
8726                   ActivateEx(true, false, true, true, null, null);
8727                */
8728                if(creationActivation == activate)
8729                   ActivateEx(true, false, true, true, null, null);
8730                else if(creationActivation == flash && !object)
8731                   Flash();               
8732
8733                //SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8734                Update(null);
8735
8736                // rootWindow.
8737                ConsequentialMouseMove(false);
8738             }
8739
8740             firewatchers;
8741          }
8742       }
8743
8744       get { return (style.hidden || !setVisible) ? false : true; }
8745    };
8746     
8747    property bool isDocument
8748    {
8749       property_category "Document"
8750       set { style.isDocument = value; }
8751       get { return style.isDocument; }
8752    };
8753
8754    property bool mergeMenus
8755    {
8756       property_category "Window Style"
8757       set { mergeMenus = value; }
8758       get { return (bool)mergeMenus; }
8759    };
8760
8761    property bool hasHorzScroll
8762    {
8763       property_category "Window Style"
8764       set
8765       {
8766          if(value)
8767          {
8768             if(!style.hasHorzScroll && created)
8769             {
8770                CreateSystemChildren();         
8771                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8772             }
8773          }
8774          else if(style.hasHorzScroll)
8775          {
8776             sbh.Destroy(0);
8777             sbh = null;
8778             Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8779          }
8780          style.hasHorzScroll = value;
8781       }
8782
8783       get { return style.hasHorzScroll; }
8784    };
8785
8786    property bool hasVertScroll
8787    {
8788       property_category "Window Style"
8789       set
8790       {
8791          if(value)
8792          {
8793             if(!style.hasVertScroll && created)
8794             {
8795                style.hasVertScroll = true;
8796                CreateSystemChildren();
8797                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8798             }
8799          }
8800          else if(style.hasVertScroll)
8801          {
8802             sbv.Destroy(0);
8803             sbv = null;
8804             Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8805          }
8806          style.hasVertScroll = value;
8807       }
8808       get { return style.hasVertScroll; }
8809    };
8810
8811    property bool dontHideScroll
8812    {
8813       property_category "Behavior"
8814       set
8815       {
8816          scrollFlags.dontHide = value;
8817          if(value)
8818          {
8819             //UpdateScrollBars(true, true);
8820             Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8821          }
8822          else
8823          {
8824             // UpdateScrollBars(true, true);
8825             Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8826          }
8827       }
8828       get { return scrollFlags.dontHide; }
8829    };
8830
8831    property bool dontScrollVert
8832    {
8833       property_category "Behavior"
8834       set { style.dontScrollVert = value; }
8835       get { return style.dontScrollVert; }
8836    };
8837    property bool dontScrollHorz
8838    {
8839       property_category "Behavior"
8840       set { style.dontScrollHorz = value; }
8841       get { return style.dontScrollHorz; }
8842    };
8843
8844    property bool snapVertScroll
8845    {
8846       property_category "Behavior"
8847       set
8848       {
8849          scrollFlags.snapY = value;
8850          if(sbv) sbv.snap = value;
8851       }
8852       get { return scrollFlags.snapY; }
8853    };
8854    property bool snapHorzScroll
8855    {
8856        property_category "Behavior"
8857       set
8858       {
8859          scrollFlags.snapX = value;
8860          if(sbh) sbh.snap = value;
8861       }
8862       get { return scrollFlags.snapX; }
8863    };
8864
8865    property Point scroll
8866    {
8867       property_category "Behavior"
8868       set
8869       {
8870          // scroll = value;
8871          // TESTING THIS IMPLEMENTATION:
8872          SetScrollPosition(value.x, value.y);
8873       }
8874       get { value = scroll; }
8875    };
8876
8877    property bool modifyVirtualArea
8878    {
8879       property_category "Behavior"
8880       set { modifyVirtArea = value; }
8881       get { return (bool)modifyVirtArea; }
8882    };
8883
8884    property char * fileName
8885    {
8886       property_category "Document"
8887       set
8888       {
8889          if(menu && ((!fileName && value) || (fileName && !value)))
8890          {
8891             MenuItem item = menu.FindItem(MenuFileSave, 0);
8892             if(item) item.disabled = !modifiedDocument && value;
8893          }
8894
8895          delete fileName;
8896
8897          if(value && value[0])
8898             fileName = CopyString(value);
8899
8900          if(parent && this == parent.activeClient)
8901             parent.UpdateActiveDocument(null);
8902          else
8903             UpdateCaption();
8904
8905          // if(style.isDocument)
8906          if(!saving)
8907             fileMonitor.fileName = value;
8908       }
8909       get { return fileName; }
8910    };
8911
8912    property int id
8913    {
8914       property_category "Data"
8915       set { id = value; }
8916       get { return id; }
8917    };
8918
8919    property bool modifiedDocument
8920    {
8921       property_category "Document"
8922       set
8923       {
8924          if(style.isDocument || fileName)
8925          {
8926             if(menu)
8927             {
8928                MenuItem item = menu.FindItem(MenuFileSave, 0);
8929                if(item) item.disabled = !value && fileName;
8930             }
8931          }
8932
8933          if(modifiedDocument != value)
8934          {
8935             modifiedDocument = value;
8936             if(style.isDocument || fileName)
8937                UpdateCaption();
8938          }
8939       }
8940       get { return (bool)modifiedDocument; }
8941    };
8942
8943    property bool showInTaskBar
8944    {
8945       property_category "Window Style"
8946       set { style.showInTaskBar = value; }
8947       get { return (style.showInTaskBar; }
8948    };
8949    property FileDialog saveDialog { set { saveDialog = value; } };
8950    property bool isActiveClient
8951    {
8952       property_category "Behavior"
8953       set { style.isActiveClient = value; }
8954       get { return style.isActiveClient; }
8955    };
8956
8957    property Cursor cursor
8958    {
8959       property_category "Appearance"
8960       set
8961       {
8962          cursor = value;
8963          SelectMouseCursor();
8964       }
8965       get { return cursor; }
8966    };      
8967
8968 //#if !defined(ECERE_VANILLA)
8969    property char * name
8970    {
8971       property_category "Design"
8972       get
8973       {
8974          return (this && object) ? object.name : null;
8975       }
8976       set
8977       {
8978          if(activeDesigner)
8979             activeDesigner.RenameObject(object, value);
8980       }
8981    };
8982 //#endif
8983    property char * displayDriver
8984    {
8985       property_category "Behavior"
8986       set
8987       {
8988          dispDriver = GetDisplayDriver(value);
8989          //DisplayModeChanged();
8990       }
8991       get
8992       {
8993          return dispDriver ? dispDriver.name : null;
8994       }
8995    }
8996
8997    // RUNTIME PROPERTIES
8998    property bool autoCreate { set { autoCreate = value; } get { return (bool)autoCreate; } };
8999    property Size scrollArea
9000    {
9001       property_category "Behavior"
9002       set
9003       {
9004          if(value != null)
9005             SetScrollArea(value.w, value.h, false);
9006          else
9007             SetScrollArea(0,0, true);
9008       }
9009       get { value = scrollArea; }
9010       isset
9011       {
9012          return scrollArea.w > clientSize.w || scrollArea.h > clientSize.h;
9013       }
9014    };
9015    property bool is3D
9016    {
9017       property_category "Layout"
9018       set { if(this) is3D = value; }
9019       get { return (bool)is3D; }
9020    };
9021
9022    // Runtime Only Properties (No Set, can display the displayable ones depending on the type?)
9023                                                                                                             
9024    // Will be merged with font later
9025    property Font fontObject { get { return usedFont ? usedFont.font : null; } };
9026    property Point clientStart { get { value = clientStart; } };
9027    property Point absPosition { get { value = absPosition; } };
9028    property Anchor normalAnchor { get {value = normalAnchor; } };
9029    // property Size normalSizeAnchor { get { value = normalSizeAnchor; } };
9030    property bool active { get { return (bool)active; } };
9031    property bool created { get { return (bool)created; } };
9032    property bool destroyed { get { return (bool)destroyed; } };
9033    property Window firstSlave { get { return slaves.first ? ((OldLink)slaves.first).data : null; } };
9034    property Window firstChild { get { return children.first; } };   
9035    property Window lastChild { get { return children.last; } };   
9036    property Window activeClient { get { return activeClient; } };
9037    property Window activeChild { get { return activeChild; } };
9038    property Display display  { get { return display ? display : ((parent && parent.rootWindow) ? parent.rootWindow.display : null); } };
9039    property DisplaySystem displaySystem { get { return display ? display.displaySystem : null; } };
9040    property ScrollBar horzScroll { get { return sbh; } };
9041    property ScrollBar vertScroll { get { return sbv; } };
9042    property StatusBar statusBar { get { return statusBar; } };
9043    property Window rootWindow { get { return rootWindow; } };   
9044    property bool closing { get { return (bool)closing; } set { closing = value; } };
9045    property int documentID { get { return documentID; } };
9046    property Window previous { get { return prev; } }
9047    property Window next { get { return next; } }
9048    property Window nextSlave { get { OldLink link = master.slaves.FindLink(this); return (link && link.next) ? link.next.data : null; } }
9049    property PopupMenu menuBar { get { return menuBar; } }
9050    property ScrollBar sbv { get { return sbv; } }
9051    property ScrollBar sbh { get { return sbh; } }
9052    property bool fullRender { set { fullRender = value; } get { return (bool)fullRender; } }
9053    property void * systemHandle { get { return windowHandle; } }
9054    property Button minimizeButton { get { return sysButtons[0]; } };
9055    property Button maximizeButton { get { return sysButtons[1]; } };   
9056    property Button closeButton { get { return sysButtons[2]; } };
9057    property BitmapResource icon
9058    {
9059       get { return icon; }
9060       set
9061       {
9062          icon = value;
9063          incref icon;
9064          if(created)
9065             guiApp.interfaceDriver.SetIcon(this, value);
9066       }
9067    };
9068    property bool moveable { get { return (bool)moveable; } set { moveable = value; } };
9069    property bool alphaBlend { get { return (bool)alphaBlend; } set { alphaBlend = value; } };
9070    property bool useSharedMemory { get { return (bool)useSharedMemory; } set { useSharedMemory = value; } };
9071    property CreationActivationOption creationActivation { get { return creationActivation; } set { creationActivation = value; } };
9072    property bool nativeDecorations { get { return (bool)nativeDecorations; } set { nativeDecorations = value; } };
9073    property bool manageDisplay { get { return (bool)manageDisplay; } set { manageDisplay = value; } };
9074    
9075 private:
9076    // Data
9077    //char * yo;
9078    Window prev, next;
9079    WindowBits style;       // Window Style
9080    char * caption;            // Name / Caption
9081    Window parent;    // Parent window
9082    OldList children;          // List of children in Z order
9083    Window activeChild;     // Child window having focus
9084    Window activeClient;
9085    Window previousActive;  // Child active prior to activating the default child
9086    Window master;          // Window owning and receiving notifications concerning this window
9087    OldList slaves;            // List of windows belonging to this window
9088    Display display;        // Display this window is drawn into
9089
9090    Point position;         // Position in parent window client area
9091    Point absPosition;      // Absolute position
9092    Point clientStart;      // Client area position from (0,0) in this window
9093    Size size;              // Size
9094    Size clientSize;        // Client area size
9095    Size scrollArea;        // Virtual Scroll area size
9096    Size reqScrollArea;     // Requested virtual area size
9097    Point scroll;           // Virtual area scrolling position
9098    public ScrollBar sbh, sbv;        // Scrollbar window handles
9099    Cursor cursor;        // Mouse cursor used for this window
9100    WindowState state;
9101    PopupMenu menuBar;
9102    StatusBar statusBar;
9103    Button sysButtons[3];
9104    char * fileName;
9105    Box clientArea;         // Client Area box clipped to parent
9106    Key setHotKey;
9107    HotKeySlot hotKey;        // HotKey for this window
9108    int numDocuments;
9109    int numPositions;
9110    Menu menu;
9111    ScrollFlags scrollFlags;// Window Scrollbar Flags
9112    int id;                 // Control ID
9113    int documentID;
9114    ColorAlpha background;  // Background color used to draw the window area
9115    Color foreground;
9116    subclass(DisplayDriver) dispDriver;   // Display driver name for this window
9117    OldList childrenCycle;     // Cycling order
9118    OldLink cycle;             // Element of parent's cycling order
9119    OldList childrenOrder;     // Circular Z-Order
9120    OldLink order;             // Element of parent's circular Z-Order
9121    Window modalSlave;      // Slave window blocking this window's interaction
9122
9123    Window rootWindow;      // Topmost system managed window
9124    void * windowHandle;    // System window handle
9125
9126    DialogResult returnCode;// Return code for modal windows
9127   
9128    Point sbStep;           // Scrollbar line scrolling steps
9129
9130    Anchor stateAnchor;
9131    SizeAnchor stateSizeAnchor;
9132
9133    Anchor normalAnchor;
9134    SizeAnchor normalSizeAnchor;
9135
9136    Size skinMinSize;       // Minimal window size based on style
9137    Point scrolledPos;      // Scrolled position
9138    Box box;                // Window box clipped to parent
9139    Box * against;          // What to clip the box to
9140
9141    Extent dirtyArea { /*first = -1, last = -1, free = -1*/ };       // Area marked for update by Update
9142    Extent renderArea { /*first = -1, last = -1, free = -1*/ };      // Temporary extent: Area that is going to be rendered
9143    Extent overRenderArea { /*first = -1, last = -1, free = -1*/ };  // Temporary extent: Area that is going to be rendered over children
9144    Extent clipExtent { /*first = -1, last = -1, free = -1*/ };      // Temporary extent against which to clip render area
9145    Extent scrollExtent { /*first = -1, last = -1, free = -1*/ };    // Area to scroll
9146    Point scrolledArea;     // Distance to scroll area by
9147    Extent dirtyBack { /*first = -1, last = -1, free = -1*/ };       // Only used by root window
9148
9149    OldList hotKeys;           // List of the hotkeys of all children
9150    Window defaultControl;  // Default child control
9151    Size minSize;
9152    Size maxSize;
9153
9154    ColorAlpha * palette;   // Color palette used for this window
9155
9156    int caretSize;          // Size of caret, non zero if a caret is present
9157    Point caretPos;         // Caret position
9158
9159    void * systemParent;    // Parent System Window for embedded windows
9160
9161    int iconID;
9162    int numIcons;
9163    int positionID;
9164
9165    Mutex mutex;
9166    WindowState lastState;
9167
9168    FileMonitor fileMonitor
9169    {
9170       this, FileChange { modified = true };
9171
9172       bool OnFileNotify(FileChange action, char * param)
9173       {
9174          incref this;
9175          fileMonitor.StopMonitoring();
9176          if(OnFileModified(action, param))
9177             fileMonitor.StartMonitoring();
9178          delete this;
9179          return true;
9180       }
9181    };
9182    FontResource setFont, systemFont;
9183    FontResource usedFont;
9184    FontResource captionFont;
9185    OldList resources;
9186    FileDialog saveDialog;
9187    Anchor anchor;
9188    SizeAnchor sizeAnchor;
9189
9190    // FormDesigner data
9191    ObjectInfo object;
9192    Window control;
9193    Extent * tempExtents; //[4];
9194    BitmapResource icon;
9195    void * windowData;
9196    CreationActivationOption creationActivation;
9197    struct
9198    {
9199       bool active:1;            // true if window and ancestors are active
9200       bool acquiredInput:1;     // true if the window is processing state based input
9201       bool modifiedDocument:1;
9202       bool disabled:1;          // true if window cannot interact
9203       bool isForegroundWindow:1;// true while a root window is being activated
9204       bool visible:1;           // Visibility flag
9205       bool destroyed:1;         // true if window is being destroyed
9206       bool anchored:1;          // true if this window is repositioned when the parent resizes
9207       bool dirty:1;             // Flag set to true if any descendant must be redrawn
9208       bool mouseInside:1;
9209       bool positioned:1;
9210       bool created:1;
9211       bool is3D:1;
9212       bool mergeMenus:1;
9213       bool modifyVirtArea:1;
9214       bool noAutoScrollArea:1;
9215       bool closing:1;
9216       bool autoCreate:1;
9217       bool setVisible:1;      // FOR FORM DESIGNER
9218       bool wasCreated:1;
9219       bool fullRender:1;
9220       bool moveable:1;
9221       bool alphaBlend:1;
9222       bool composing:1;
9223       bool useSharedMemory:1;
9224       bool resized:1;
9225       bool saving:1;
9226       bool nativeDecorations:1;
9227       bool manageDisplay:1;
9228    }; 
9229
9230    WindowController controller;
9231    public property WindowController controller { get { return controller; } set { delete controller; controller = value; if(controller) incref controller; } }
9232 };
9233
9234 public class CommonControl : Window
9235 {
9236    // creationActivation = doNothing;
9237 };
9238
9239 public class Percentage : float
9240 {
9241    char * OnGetString(char * string, float * fieldData, bool * needClass)
9242    {
9243       int c;
9244       int last = 0;
9245       sprintf(string, "%.2f", this);
9246       c = strlen(string)-1;
9247       for( ; c >= 0; c--)
9248       {
9249          if(string[c] != '0') 
9250             last = Max(last, c);
9251          if(string[c] == '.')
9252          {
9253             if(last == c)
9254                string[c] = 0;
9255             else
9256                string[last+1] = 0;
9257             break;
9258          }
9259       }
9260       return string;
9261    }
9262 };
9263
9264 public void ApplySkin(Class c, char * name, void ** vTbl)
9265 {
9266    char className[1024];
9267    Class sc;
9268    OldLink d;
9269    int m;
9270
9271    subclass(Window) wc = (subclass(Window))c;
9272    subclass(Window) base = (subclass(Window))c.base;
9273
9274    sprintf(className, "%sSkin_%s", name, c.name);
9275    wc.pureVTbl = c._vTbl;
9276    c._vTbl = new void *[c.vTblSize];
9277    memcpy(c._vTbl, wc.pureVTbl, c.vTblSize * sizeof(void *));
9278    sc = eSystem_FindClass(c.module.application, className);
9279    
9280    if(vTbl)
9281    {
9282       for(m = 0; m < c.base.vTblSize; m++)
9283       {
9284          if(c._vTbl[m] == base.pureVTbl[m])
9285             c._vTbl[m] = vTbl[m];
9286       }
9287    }
9288    if(sc)
9289    {
9290       for(m = 0; m < c.vTblSize; m++)
9291       {
9292          if(sc._vTbl[m] != wc.pureVTbl[m])
9293             c._vTbl[m] = sc._vTbl[m];
9294       }
9295    }
9296       
9297    for(d = c.derivatives.first; d; d = d.next)
9298    {
9299       ApplySkin(d.data, name, c._vTbl);
9300    }
9301 }
9302
9303 public void UnapplySkin(Class c)
9304 {
9305    char className[1024];
9306    Class sc;
9307    subclass(Window) wc = (subclass(Window))c;
9308    subclass(Window) base = (subclass(Window))c.base;
9309    OldLink d;
9310
9311    if(wc.pureVTbl && c._vTbl != wc.pureVTbl)
9312    {
9313       delete c._vTbl;
9314       c._vTbl = wc.pureVTbl;
9315       wc.pureVTbl = null;
9316    }
9317
9318    for(d = c.derivatives.first; d; d = d.next)
9319    {
9320       UnapplySkin(d.data);
9321    }
9322 }
9323 /*
9324 void CheckFontIntegrity(Window window)
9325 {
9326    Window c;
9327    if(window)
9328    {
9329       if(window.usedFont && window.usedFont.font == 0xecececec)
9330       {
9331          FontResource uf = window.usedFont;
9332          char * className = window._class.name;
9333          char * text = window.text;
9334          Print("");
9335       }
9336       for(c = window.firstChild; c; c = c.next)
9337          CheckFontIntegrity(c);
9338    }
9339 }*/
9340
9341 public class ControllableWindow : Window
9342 {
9343    /*WindowController controller;
9344    public property WindowController controller { get { return controller; } set { delete controller; controller = value; incref controller; } }
9345    ~ControllableWindow() { delete controller; }*/
9346 }
9347
9348 class WindowControllerInterface : ControllableWindow
9349 {
9350    bool OnKeyDown(Key key, unichar ch)
9351    {
9352       bool result = ((int(*)())(void *)controller.OnKeyDown)((void *)controller.controlled, (void *)controller, key, ch);
9353       if(result)
9354          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown](controller.window, key, ch);
9355       return result;
9356    }
9357
9358    bool OnKeyUp(Key key, unichar ch)
9359    {
9360       bool result = ((int(*)())(void *)controller.OnKeyUp)((void *)controller.controlled, (void *)controller, key, ch);
9361       if(result)
9362          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp](controller.window, key, ch);
9363       return result;
9364    }
9365
9366    bool OnKeyHit(Key key, unichar ch)
9367    {
9368       bool result = ((int(*)())(void *)controller.OnKeyHit)((void *)controller.controlled, (void *)controller, key, ch);
9369       if(result)
9370          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit](controller.window, key, ch);
9371       return result;
9372    }
9373
9374    bool OnMouseMove(int x, int y, Modifiers mods)
9375    {
9376       bool result = ((int(*)())(void *)controller.OnMouseMove)((void *)controller.controlled, (void *)controller, x, y, mods);
9377       if(result)
9378          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove](controller.window, x, y, mods);
9379       return result;
9380    }
9381
9382    bool OnLeftButtonDown(int x, int y, Modifiers mods)
9383    {
9384       bool result = ((int(*)())(void *)controller.OnLeftButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9385       if(result)
9386          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown](controller.window, x, y, mods);
9387       return result;
9388    }
9389
9390    bool OnLeftButtonUp(int x, int y, Modifiers mods)
9391    {
9392       bool result = ((int(*)())(void *)controller.OnLeftButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9393       if(result)
9394          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp](controller.window, x, y, mods);
9395       return result;
9396    }
9397
9398    bool OnLeftDoubleClick(int x, int y, Modifiers mods)
9399    {
9400       bool result = ((int(*)())(void *)controller.OnLeftDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9401       if(result)
9402          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick](controller.window, x, y, mods);
9403       return result;
9404    }
9405
9406    bool OnRightButtonDown(int x, int y, Modifiers mods)
9407    {
9408       bool result = ((int(*)())(void *)controller.OnRightButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9409       if(result)
9410          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown](controller.window, x, y, mods);
9411       return result;
9412    }
9413
9414    bool OnRightButtonUp(int x, int y, Modifiers mods)
9415    {
9416       bool result = ((int(*)())(void *)controller.OnRightButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9417       if(result)
9418          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp](controller.window, x, y, mods);
9419       return result;
9420    }
9421
9422    bool OnRightDoubleClick(int x, int y, Modifiers mods)
9423    {
9424       bool result = ((int(*)())(void *)controller.OnRightDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9425       if(result)
9426          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick](controller.window, x, y, mods);
9427       return result;
9428    }
9429
9430    bool OnMiddleButtonDown(int x, int y, Modifiers mods)
9431    {
9432       bool result = ((int(*)())(void *)controller.OnMiddleButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9433       if(result)
9434          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown](controller.window, x, y, mods);
9435       return result;
9436    }
9437
9438    bool OnMiddleButtonUp(int x, int y, Modifiers mods)
9439    {
9440       bool result = ((int(*)())(void *)controller.OnMiddleButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9441       if(result)
9442          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp](controller.window, x, y, mods);
9443       return result;
9444    }
9445
9446    bool OnMiddleDoubleClick(int x, int y, Modifiers mods)
9447    {
9448       bool result = ((int(*)())(void *)controller.OnMiddleDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9449       if(result)
9450          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick](controller.window, x, y, mods);
9451       return result;
9452    }
9453
9454    void OnResize(int width, int height)
9455    {
9456       ((int(*)())(void *)controller.OnResize)((void *)controller.controlled, (void *)controller, width, height);
9457       controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize](controller.window, width, height);
9458    }
9459
9460    void OnRedraw(Surface surface)
9461    {
9462       ((int(*)())(void *)controller.OnRedraw)((void *)controller.controlled, (void *)controller, surface);
9463       controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw](controller.window, surface);
9464    }
9465
9466    bool OnCreate()
9467    {
9468       bool result = ((int(*)())(void *)controller.OnCreate)((void *)controller.controlled, (void *)controller);
9469       if(result)
9470          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate](controller.window);
9471       return result;
9472    }
9473 }
9474
9475 public class WindowController<class V>
9476 {
9477 public:
9478    property Window window
9479    {
9480       set
9481       {
9482          uint size = class(Window).vTblSize;
9483          if(value)
9484          {
9485             windowVTbl = new void *[size];
9486             memcpy(windowVTbl, value._vTbl, size * sizeof(void *));
9487             if(value._vTbl == value._class._vTbl)
9488             {
9489                value._vTbl = new void *[value._class.vTblSize];
9490                memcpy(value._vTbl + size, value._class._vTbl + size, (value._class.vTblSize - size) * sizeof(void *));
9491             }
9492             {
9493                int c;
9494                for(c = 0; c < size; c++)
9495                {
9496                   void * function = class(WindowControllerInterface)._vTbl[c];
9497                   if(function != DefaultFunction)
9498                      value._vTbl[c] = function;
9499                   else
9500                      value._vTbl[c] = windowVTbl[c];
9501                }
9502             }
9503          }
9504          else
9505             memcpy(value._vTbl, windowVTbl, class(Window).vTblSize * sizeof(void *));
9506          window = value;
9507       }
9508       get { return window; }
9509    }
9510    property V controlled
9511    {
9512       set { controlled = value; }
9513       get { return controlled; }
9514    }
9515    virtual bool V::OnKeyDown(WindowController controller, Key key, unichar ch);
9516    virtual bool V::OnKeyUp(WindowController controller, Key key, unichar ch);
9517    virtual bool V::OnKeyHit(WindowController controller, Key key, unichar ch);
9518    virtual bool V::OnMouseMove(WindowController controller, int x, int y, Modifiers mods);
9519    virtual bool V::OnLeftButtonDown(WindowController controller, int x, int y, Modifiers mods);
9520    virtual bool V::OnLeftButtonUp(WindowController controller, int x, int y, Modifiers mods);
9521    virtual bool V::OnLeftDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9522    virtual bool V::OnRightButtonDown(WindowController controller, int x, int y, Modifiers mods);
9523    virtual bool V::OnRightButtonUp(WindowController controller, int x, int y, Modifiers mods);
9524    virtual bool V::OnRightDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9525    virtual bool V::OnMiddleButtonDown(WindowController controller, int x, int y, Modifiers mods);
9526    virtual bool V::OnMiddleButtonUp(WindowController controller, int x, int y, Modifiers mods);
9527    virtual bool V::OnMiddleDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9528    virtual void V::OnResize(WindowController controller, int width, int height);
9529    virtual void V::OnRedraw(WindowController controller, Surface surface);
9530    virtual bool V::OnCreate(WindowController controller);
9531
9532 private:
9533    int (** windowVTbl)();   
9534    V controlled;
9535    Window window;
9536
9537    ~WindowController()
9538    {
9539       delete windowVTbl;
9540    }
9541 }