1 #include "Fb.h"
2
3 #ifdef GUI_FB
4
5 NAMESPACE_UPP
6
7 #define LLOG(x) //DLOG(x)
8 #define LDUMP(x) //DDUMP(x)
9 #define LDUMPC(x) //DDUMPC(x)
10
11 ImageBuffer Ctrl::framebuffer;
12 Vector<Rect> Ctrl::invalid;
13 Vector<Rect> Ctrl::update;
14
15 Ptr<Ctrl> Ctrl::desktop;
16 Vector<Ctrl *> Ctrl::topctrl;
17
18 Point Ctrl::fbCursorPos = Null;
19 Image Ctrl::fbCursorImage;
20 Point Ctrl::fbCursorBakPos = Null;
21 Image Ctrl::fbCursorBak;
22 Rect Ctrl::fbCaretRect;
23 Image Ctrl::fbCaretBak;
24 int Ctrl::fbCaretTm;
25 int Ctrl::renderingMode = MODE_ANTIALIASED;
26 bool Ctrl::fbEndSession;
27 bool Ctrl::FullWindowDrag;
28 int Ctrl::PaintLock;
29
SetDesktop(Ctrl & q)30 void Ctrl::SetDesktop(Ctrl& q)
31 {
32 desktop = &q;
33 desktop->SetRect(framebuffer.GetSize());
34 desktop->SetOpen(true);
35 desktop->NewTop();
36 invalid.Add(framebuffer.GetSize());
37 }
38
SetRenderingMode(int mode)39 void Ctrl::SetRenderingMode(int mode)
40 {
41 renderingMode = mode;
42 invalid.Add(framebuffer.GetSize());
43 }
44
InitFB()45 void Ctrl::InitFB()
46 {
47 Ctrl::GlobalBackBuffer();
48 Ctrl::InitTimer();
49 framebuffer.Create(1, 1);
50
51 #ifdef PLATFORM_POSIX
52 SetStdFont(ScreenSans(12)); //FIXME general handling
53 #endif
54 ChStdSkin();
55
56 static StaticRect x;
57 x.Color(Cyan());
58 SetDesktop(x);
59 }
60
EndSession()61 void Ctrl::EndSession()
62 {
63 GuiLock __;
64 LLOG("Ctrl::EndSession");
65 fbEndSession = true;
66 EndSessionLoopNo = EventLoopNo;
67 }
68
ExitFB()69 void Ctrl::ExitFB()
70 {
71 TopWindow::ShutdownWindows();
72 Ctrl::CloseTopCtrls();
73 if(fbEndSession)
74 FBQuitSession();
75 }
76
SetFramebufferSize(Size sz)77 void Ctrl::SetFramebufferSize(Size sz)
78 {
79 framebuffer.Create(sz);
80 if(desktop)
81 desktop->SetRect(sz);
82 invalid.Add(sz);
83 SyncTopWindows();
84 }
85
FindTopCtrl() const86 int Ctrl::FindTopCtrl() const
87 {
88 for(int i = 0; i < topctrl.GetCount(); i++)
89 if(this == topctrl[i])
90 return i;
91 return -1;
92 }
93
IsAlphaSupported()94 bool Ctrl::IsAlphaSupported()
95 {
96 return false;
97 }
98
IsCompositedGui()99 bool Ctrl::IsCompositedGui()
100 {
101 return false;
102 }
103
GetTopCtrls()104 Vector<Ctrl *> Ctrl::GetTopCtrls()
105 {
106 Vector<Ctrl *> ctrl;
107 if(desktop)
108 ctrl.Add(desktop);
109 for(int i = 0; i < topctrl.GetCount(); i++)
110 if(!dynamic_cast<TopWindowFrame *>(topctrl[i]))
111 ctrl.Add(topctrl[i]);
112 return ctrl;
113 }
114
GetOwner()115 Ctrl *Ctrl::GetOwner()
116 {
117 GuiLock __;
118 int q = FindTopCtrl();
119 if(q > 0 && topctrl[q]->top) {
120 Ctrl *x = topctrl[q]->top->owner_window;
121 LDUMP(Upp::Name(x));
122 return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x;
123 }
124 return NULL;
125 }
126
GetActiveCtrl()127 Ctrl *Ctrl::GetActiveCtrl()
128 {
129 GuiLock __;
130 return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
131 }
132
133 // Vector<Callback> Ctrl::hotkey;
134
RegisterSystemHotKey(dword key,Callback cb)135 int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
136 {
137 /* ASSERT(key >= K_DELTA);
138 int q = hotkey.GetCount();
139 for(int i = 0; i < hotkey.GetCount(); i++)
140 if(!hotkey[i]) {
141 q = i;
142 break;
143 }
144 hotkey.At(q) = cb;
145 dword mod = 0;
146 if(key & K_ALT)
147 mod |= MOD_ALT;
148 if(key & K_SHIFT)
149 mod |= MOD_SHIFT;
150 if(key & K_CTRL)
151 mod |= MOD_CONTROL;
152
153 return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
154 return -1;
155 }
156
UnregisterSystemHotKey(int id)157 void Ctrl::UnregisterSystemHotKey(int id)
158 {
159 /* if(id >= 0 && id < hotkey.GetCount()) {
160 UnregisterHotKey(NULL, id);
161 hotkey[id].Clear();
162 }*/
163 }
164
IsWaitingEvent()165 bool Ctrl::IsWaitingEvent()
166 {
167 return FBIsWaitingEvent();
168 }
169
AddUpdate(const Rect & rect)170 void Ctrl::AddUpdate(const Rect& rect)
171 {
172 LLOG("@AddUpdate " << rect);
173 AddRefreshRect(update, rect);
174 }
175
AddInvalid(const Rect & rect)176 void Ctrl::AddInvalid(const Rect& rect)
177 {
178 LLOG("@AddInvalid " << rect);
179 AddRefreshRect(invalid, rect);
180 }
181
SyncTopWindows()182 void Ctrl::SyncTopWindows()
183 {
184 for(int i = 0; i < topctrl.GetCount(); i++) {
185 TopWindow *w = dynamic_cast<TopWindow *>(topctrl[i]);
186 if(w)
187 w->SyncRect();
188 }
189 }
190
ProcessEvent(bool * quit)191 bool Ctrl::ProcessEvent(bool *quit)
192 {
193 LLOG("@ ProcessEvent");
194 ASSERT(IsMainThread());
195 if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle())
196 ReleaseCtrlCapture();
197 if(FBProcessEvent(quit)) {
198 LLOG("FBProcesEvent returned true");
199 SyncTopWindows();
200 DefferedFocusSync();
201 SyncCaret();
202 return true;
203 }
204 return false;
205 }
206
GetClipBound(const Vector<Rect> & inv,const Rect & r)207 Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
208 {
209 Rect ri = Null;
210 for(int j = 0; j < inv.GetCount(); j++) {
211 Rect rr = inv[j] & r;
212 if(!rr.IsEmpty())
213 ri = IsNull(ri) ? rr : rr | ri;
214 }
215 return ri;
216 }
217
218
ViewDraw(Ctrl * ctrl)219 ViewDraw::ViewDraw(Ctrl *ctrl)
220 {
221 if(Ctrl::invalid.GetCount())
222 Ctrl::DoPaint();
223 Ctrl::invalid.Clear();
224 Ctrl::RemoveCursor();
225 Ctrl::RemoveCaret();
226 Rect r = ctrl->GetScreenView();
227 Ctrl::invalid.Add(r);
228 Ctrl::AddUpdate(r);
229 for(int i = max(ctrl->GetTopCtrl()->FindTopCtrl() + 1, 0); i < Ctrl::topctrl.GetCount(); i++) {
230 Rect rr = Ctrl::topctrl[i]->GetScreenRect();
231 ExcludeClip(rr);
232 Subtract(Ctrl::invalid, rr);
233 }
234 Offset(r.TopLeft());
235 }
236
~ViewDraw()237 ViewDraw::~ViewDraw()
238 {
239 FBInitUpdate();
240 Ctrl::DoUpdate();
241 FBFlush();
242 // Ctrl::invalid.Clear();
243 }
244
DoUpdate()245 void Ctrl::DoUpdate()
246 {
247 LLOG("DoUpdate");
248 invalid.Clear();
249 CursorSync();
250 LDUMPC(update);
251 #if 0
252 FBUpdate(framebuffer.GetSize());
253 #else
254 for(int i = 0; i < update.GetCount(); i++) {
255 LDUMP(update[i]);
256 FBUpdate(update[i]);
257 }
258 #endif
259 update.Clear();
260 // Sleep(1000);
261 }
262
GetPaintRects()263 Vector<Rect> Ctrl::GetPaintRects()
264 {
265 Vector<Rect> r;
266 int q = FindTopCtrl();
267 r.Add(GetScreenRect());
268 for(int i = max(FindTopCtrl() + 1, 0); i < topctrl.GetCount(); i++)
269 Subtract(r, topctrl[i]->GetScreenRect());
270 return r;
271 }
272
273
DDRect(RGBA * t,int dir,const byte * pattern,int pos,int count)274 void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count)
275 {
276 while(count-- > 0) {
277 byte p = pattern[7 & pos++];
278 t->r ^= p;
279 t->g ^= p;
280 t->b ^= p;
281 t += dir;
282 }
283 }
284
DrawLine(const Vector<Rect> & clip,int x,int y,int cx,int cy,bool horz,const byte * pattern,int animation)285 void Ctrl::DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz, const byte *pattern, int animation)
286 {
287 if(cx <= 0 || cy <= 0)
288 return;
289 Vector<Rect> rr = Intersection(clip, RectC(x, y, cx, cy));
290 for(int i = 0; i < rr.GetCount(); i++) {
291 Rect r = rr[i];
292 AddUpdate(r);
293 if(horz)
294 for(int y = r.top; y < r.bottom; y++)
295 DDRect(framebuffer[y] + r.left, 1, pattern, r.left + animation, r.GetWidth());
296 else
297 for(int x = r.left; x < r.right; x++)
298 DDRect(framebuffer[r.top] + x, framebuffer.GetWidth(), pattern, r.top + animation, r.GetHeight());
299 }
300 }
301
DragRectDraw0(const Vector<Rect> & clip,const Rect & rect,int n,const byte * pattern,int animation)302 void Ctrl::DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n, const byte *pattern, int animation)
303 {
304 int hn = min(rect.GetHeight(), n);
305 int vn = min(rect.GetWidth(), n);
306 DrawLine(clip, rect.left, rect.top, rect.GetWidth(), hn, true, pattern, animation);
307 DrawLine(clip, rect.left, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
308 DrawLine(clip, rect.right - vn, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
309 DrawLine(clip, rect.left + vn, rect.bottom - hn, rect.GetWidth() - 2 * vn, hn, true, pattern, animation);
310 }
311
DragRectDraw(const Rect & rect1,const Rect & rect2,const Rect & clip,int n,Color color,int type,int animation)312 void Ctrl::DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
313 Color color, int type, int animation)
314 {
315 static byte solid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
316 static byte normal[] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 };
317 static byte dashed[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
318 Point p = GetScreenView().TopLeft();
319 Vector<Rect> pr;
320 if(type & DRAWDRAGRECT_SCREEN) {
321 pr.Add(Rect(framebuffer.GetSize()));
322 type &= ~DRAWDRAGRECT_SCREEN;
323 p = Point(0, 0);
324 }
325 else
326 pr = Intersection(GetPaintRects(), clip.Offseted(p));
327 const byte *pattern = type == DRAWDRAGRECT_DASHED ? dashed :
328 type == DRAWDRAGRECT_NORMAL ? normal : solid;
329 RemoveCursor();
330 RemoveCaret();
331 DragRectDraw0(pr, rect1.Offseted(p), n, pattern, animation);
332 DragRectDraw0(pr, rect2.Offseted(p), n, pattern, animation);
333 }
334
DoPaint()335 void Ctrl::DoPaint()
336 {
337 LLOG("@ DoPaint");
338 if(!PaintLock) {
339 bool scroll = false;
340 if(desktop)
341 desktop->SyncScroll();
342 for(int i = 0; i < topctrl.GetCount(); i++)
343 topctrl[i]->SyncScroll();
344 if((invalid.GetCount() || scroll) && desktop) {
345 RemoveCursor();
346 RemoveCaret();
347 for(int phase = 0; phase < 2; phase++) {
348 LLOG("DoPaint invalid phase " << phase);
349 LDUMPC(invalid);
350 SystemDraw painter;
351 painter.Begin();
352 for(int i = 0; i < invalid.GetCount(); i++) {
353 painter.RectPath(invalid[i]);
354 AddUpdate(invalid[i]);
355 }
356 painter.Painter::Clip();
357 for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
358 Rect r = topctrl[i]->GetRect();
359 Rect ri = GetClipBound(invalid, r);
360 if(!IsNull(ri)) {
361 painter.Clipoff(r);
362 topctrl[i]->UpdateArea(painter, ri - r.TopLeft());
363 painter.End();
364 Subtract(invalid, r);
365 painter.ExcludeClip(r);
366 }
367 }
368 Rect ri = GetClipBound(invalid, framebuffer.GetSize());
369 if(!IsNull(ri))
370 desktop->UpdateArea(painter, ri);
371 }
372 }
373 }
374 DoUpdate();
375 }
376
WndUpdate0r(const Rect & r)377 void Ctrl::WndUpdate0r(const Rect& r)
378 {
379 GuiLock __;
380 Rect rr = r + GetRect().TopLeft();
381 bool dummy;
382 Vector<Rect> h;
383 h <<= invalid;
384 invalid = Intersect(invalid, rr, dummy);
385 FBInitUpdate();
386 DoPaint();
387 invalid <<= h;
388 Subtract(invalid, rr);
389 FBFlush();
390 }
391
ProcessEvents(bool * quit)392 bool Ctrl::ProcessEvents(bool *quit)
393 {
394 //LOGBLOCK("@ ProcessEvents");
395 // MemoryCheckDebug();
396 if(!ProcessEvent(quit))
397 return false;
398 while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop()));
399 TimeStop tm;
400 TimerProc(GetTickCount());
401 LLOG("TimerProc elapsed: " << tm);
402 SweepMkImageCache();
403 FBInitUpdate();
404 DoPaint();
405 FBFlush();
406 return true;
407 }
408
EventLoop0(Ctrl * ctrl)409 void Ctrl::EventLoop0(Ctrl *ctrl)
410 {
411 GuiLock __;
412 ASSERT(IsMainThread());
413 ASSERT(LoopLevel == 0 || ctrl);
414 LoopLevel++;
415 LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
416 Ptr<Ctrl> ploop;
417 if(ctrl) {
418 ploop = LoopCtrl;
419 LoopCtrl = ctrl;
420 ctrl->inloop = true;
421 }
422
423 bool quit = false;
424 int64 loopno = ++EventLoopNo;
425 ProcessEvents(&quit);
426 while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount()))
427 {
428 // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep");
429 SyncCaret();
430 GuiSleep(20);
431 // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents");
432 ProcessEvents(&quit);
433 // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents");
434 LDUMP(loopno);
435 LDUMP(fbEndSessionLoop);
436 }
437
438 if(ctrl)
439 LoopCtrl = ploop;
440 LoopLevel--;
441 LLOG(LOG_END << "Leaving event loop ");
442 }
443
GuiSleep0(int ms)444 void Ctrl::GuiSleep0(int ms)
445 {
446 GuiLock __;
447 ASSERT(IsMainThread());
448 LLOG("GuiSleep");
449 int level = LeaveGuiMutexAll();
450 FBSleep(ms);
451 EnterGuiMutex(level);
452 }
453
GetWndScreenRect() const454 Rect Ctrl::GetWndScreenRect() const
455 {
456 GuiLock __;
457 return GetRect();
458 }
459
WndShow0(bool b)460 void Ctrl::WndShow0(bool b)
461 {
462 GuiLock __;
463 }
464
WndUpdate0()465 void Ctrl::WndUpdate0()
466 {
467 GuiLock __;
468 }
469
IsWndOpen() const470 bool Ctrl::IsWndOpen() const {
471 GuiLock __;
472 return FindTopCtrl() >= 0 || this == desktop;
473 }
474
SetAlpha(byte alpha)475 void Ctrl::SetAlpha(byte alpha)
476 {
477 GuiLock __;
478 }
479
GetWorkArea() const480 Rect Ctrl::GetWorkArea() const
481 {
482 GuiLock __;
483 return framebuffer.GetSize();
484 }
485
GetWorkArea(Array<Rect> & rc)486 void Ctrl::GetWorkArea(Array<Rect>& rc)
487 {
488 GuiLock __;
489 Array<Rect> r;
490 r.Add(framebuffer.GetSize());
491 }
492
GetVirtualWorkArea()493 Rect Ctrl::GetVirtualWorkArea()
494 {
495 return framebuffer.GetSize();
496 }
497
GetWorkArea(Point pt)498 Rect Ctrl::GetWorkArea(Point pt)
499 {
500 return framebuffer.GetSize();
501 }
502
GetVirtualScreenArea()503 Rect Ctrl::GetVirtualScreenArea()
504 {
505 GuiLock __;
506 return framebuffer.GetSize();
507 }
508
GetPrimaryWorkArea()509 Rect Ctrl::GetPrimaryWorkArea()
510 {
511 Rect r;
512 return framebuffer.GetSize();
513 }
514
GetPrimaryScreenArea()515 Rect Ctrl::GetPrimaryScreenArea()
516 {
517 return framebuffer.GetSize();
518 }
519
GetKbdDelay()520 int Ctrl::GetKbdDelay()
521 {
522 GuiLock __;
523 return 500;
524 }
525
GetKbdSpeed()526 int Ctrl::GetKbdSpeed()
527 {
528 GuiLock __;
529 return 1000 / 32;
530 }
531
DestroyWnd()532 void Ctrl::DestroyWnd()
533 {
534 for(int i = 0; i < topctrl.GetCount(); i++)
535 if(topctrl[i]->top && topctrl[i]->top->owner_window == this)
536 topctrl[i]->WndDestroy0();
537 int q = FindTopCtrl();
538 if(q >= 0) {
539 AddInvalid(GetRect());
540 topctrl.Remove(q);
541 }
542 if(top) {
543 delete top;
544 top = NULL;
545 }
546 isopen = false;
547 TopWindow *win = dynamic_cast<TopWindow *>(this);
548 if(win)
549 win->DestroyFrame();
550 }
551
WndDestroy0()552 void Ctrl::WndDestroy0()
553 {
554 DestroyWnd();
555 if(topctrl.GetCount())
556 topctrl.Top()->ActivateWnd();
557 }
558
PutForeground()559 void Ctrl::PutForeground()
560 {
561 int q = FindTopCtrl();
562 if(q >= 0) {
563 AddInvalid(GetRect());
564 topctrl.Remove(q);
565 topctrl.Add(this);
566 }
567 Vector< Ptr<Ctrl> > fw;
568 for(int i = 0; i < topctrl.GetCount(); i++)
569 if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this)
570 fw.Add(topctrl[i]);
571 for(int i = 0; i < fw.GetCount(); i++)
572 if(fw[i])
573 fw[i]->PutForeground();
574 }
575
SetWndForeground0()576 void Ctrl::SetWndForeground0()
577 {
578 GuiLock __;
579 ASSERT(IsOpen());
580 if(IsWndForeground())
581 return;
582 Ctrl *to = this;
583 while(to->top && to->top->owner_window)
584 to = to->top->owner_window;
585 to->PutForeground();
586 if(this != focusCtrl)
587 ActivateWnd();
588 }
589
IsWndForeground() const590 bool Ctrl::IsWndForeground() const
591 {
592 GuiLock __;
593 bool b = false;
594 for(int i = 0; i < topctrl.GetCount(); i++) {
595 const TopWindow *tw = dynamic_cast<const TopWindow *>(topctrl[i]);
596 if(tw)
597 b = tw == this;
598 }
599 return b;
600 }
601
WndEnable0(bool * b)602 void Ctrl::WndEnable0(bool *b)
603 {
604 GuiLock __;
605 *b = true;
606 }
607
SetWndFocus0(bool * b)608 void Ctrl::SetWndFocus0(bool *b)
609 {
610 GuiLock __;
611 *b = true;
612 }
613
HasWndFocus() const614 bool Ctrl::HasWndFocus() const
615 {
616 GuiLock __;
617 return focusCtrl && focusCtrl->GetTopCtrl() == this;
618 }
619
SetWndCapture()620 bool Ctrl::SetWndCapture()
621 {
622 GuiLock __;
623 ASSERT(IsMainThread());
624 return true;
625 }
626
ReleaseWndCapture()627 bool Ctrl::ReleaseWndCapture()
628 {
629 GuiLock __;
630 ASSERT(IsMainThread());
631 return true;
632 }
633
HasWndCapture() const634 bool Ctrl::HasWndCapture() const
635 {
636 GuiLock __;
637 return captureCtrl && captureCtrl->GetTopCtrl() == this;
638 }
639
WndInvalidateRect(const Rect & r)640 void Ctrl::WndInvalidateRect(const Rect& r)
641 {
642 GuiLock __;
643 int q = FindTopCtrl();
644 if(q >= 0)
645 AddInvalid(r + topctrl[q]->GetRect().TopLeft());
646 else
647 AddInvalid(r);
648 }
649
WndSetPos0(const Rect & rect)650 void Ctrl::WndSetPos0(const Rect& rect)
651 {
652 GuiLock __;
653 TopWindow *w = dynamic_cast<TopWindow *>(this);
654 if(w)
655 w->SyncFrameRect(rect);
656 invalid.Add(GetRect());
657 SetWndRect(rect);
658 invalid.Add(rect);
659 }
660
WndScrollView0(const Rect & r,int dx,int dy)661 void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
662 {
663 GuiLock __;
664 if(dx == 0 && dy == 0)
665 return;
666 if(dx && dy) {
667 Refresh(r);
668 return;
669 }
670 RemoveCursor();
671 RemoveCaret();
672 Rect sr = r.Offseted(GetScreenRect().TopLeft());
673 Vector<Rect> pr = Intersection(GetPaintRects(), sr);
674 for(int i = 0; i < pr.GetCount(); i++) {
675 Rect r = pr[i];
676 if(dx) {
677 int n = r.GetWidth() - abs(dx);
678 if(n > 0) {
679 int to = r.left + dx * (dx > 0);
680 int from = r.left - dx * (dx < 0);
681 for(int y = r.top; y < r.bottom; y++)
682 memmove(framebuffer[y] + to, framebuffer[y] + from, n * sizeof(RGBA));
683 }
684 n = min(abs(dx), r.GetWidth());
685 Refresh(dx < 0 ? r.left : r.right - n, r.top, n, r.GetHeight());
686 }
687 else {
688 int n = r.GetHeight() - abs(dy);
689 for(int y = 0; y < n; y++)
690 memmove(framebuffer[dy < 0 ? r.top + y : r.bottom - 1 - y] + r.left,
691 framebuffer[dy < 0 ? r.top + y - dy : r.bottom - 1 - y - dy] + r.left,
692 r.GetWidth() * sizeof(RGBA));
693 n = min(abs(dy), r.GetHeight());
694 Refresh(r.left, dy < 0 ? r.bottom - n : r.top, r.GetWidth(), n);
695 }
696 }
697
698 Vector<Rect> ur;
699 for(int i = 0; i < invalid.GetCount(); i++)
700 if(invalid[i].Intersects(sr))
701 ur.Add(invalid[i]);
702 for(int i = 0; i < ur.GetCount(); i++)
703 AddInvalid(ur[i].Offseted(dx, dy));
704 }
705
PopUp(Ctrl * owner,bool savebits,bool activate,bool dropshadow,bool topmost)706 void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
707 {
708 ASSERT(!IsChild() && !IsOpen() && FindTopCtrl() < 0);
709 NewTop();
710 if(owner) {
711 Ctrl *owner_window = owner->GetTopWindow();
712 if(!owner_window)
713 owner_window = owner->GetTopCtrl();
714 ASSERT(owner_window->IsOpen());
715 if(owner_window != desktop) {
716 owner_window->SetForeground();
717 top->owner_window = owner_window;
718 }
719 }
720 topctrl.Add(this);
721 popup = isopen = true;
722 RefreshLayoutDeep();
723 if(activate) SetFocusWnd();
724 AddInvalid(GetRect());
725 }
726
GetDefaultWindowRect()727 Rect Ctrl::GetDefaultWindowRect() {
728 GuiLock __;
729 static int ii = 0;
730 Size sz = framebuffer.GetSize();
731 Rect rect = framebuffer.GetSize();
732 rect.Deflate(sz / 10);
733 rect.Offset(Size(GetStdFontCy(), 2 * GetStdFontCy()) * (++ii % 8));
734 return rect;
735 }
736
SplitCmdLine__(const char * cmd)737 Vector<WString> SplitCmdLine__(const char *cmd)
738 {
739 Vector<WString> out;
740 while(*cmd)
741 if((byte)*cmd <= ' ')
742 cmd++;
743 else if(*cmd == '\"') {
744 WString quoted;
745 while(*++cmd && (*cmd != '\"' || *++cmd == '\"'))
746 quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString());
747 out.Add(quoted);
748 }
749 else {
750 const char *begin = cmd;
751 while((byte)*cmd > ' ')
752 cmd++;
753 out.Add(String(begin, cmd).ToWString());
754 }
755 return out;
756 }
757
758 END_UPP_NAMESPACE
759
760 #endif
761