fixed Context destructor when constructed using the copy constructor
[reactos.git] / reactos / subsys / system / explorer / utility / utility.h
1 /*
2 * Copyright 2003 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // utility.h
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 // standard windows headers
30 #define WIN32_LEAN_AND_MEAN
31 #define WIN32_EXTRA_LEAN
32 #include <windows.h>
33
34 // Unicode support
35 #ifdef UNICODE
36 #define _UNICODE
37 #endif
38 #include <tchar.h>
39
40 #include <windowsx.h> // for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ...
41 #include <commctrl.h>
42
43 #include <malloc.h> // for alloca()
44 #include <assert.h>
45 #include <stdlib.h> // for _MAX_DIR, ...
46 #include <stdio.h> // for sprintf()
47 #include <time.h>
48
49 #ifndef _MAX_PATH
50 #define _MAX_DRIVE 3
51 #define _MAX_FNAME 256
52 #define _MAX_DIR _MAX_FNAME
53 #define _MAX_EXT _MAX_FNAME
54 #define _MAX_PATH 260
55 #endif
56
57
58 #ifdef __cplusplus
59 extern "C" {
60 #endif
61
62
63 #define for if (0) {} else for
64
65
66 #define BUFFER_LEN 1024
67
68
69 extern void _log_(LPCTSTR txt);
70
71 #define LOG(txt) _log_(txt)
72
73
74 #ifdef _MSC_VER
75 #define LONGLONGARG TEXT("I64")
76 #else
77 #define LONGLONGARG TEXT("L")
78 #endif
79
80
81 #ifndef _tcsrchr
82 #ifdef UNICODE
83 #define _tcsrchr wcsrchr
84 #else
85 #define _tcsrchr strrchr
86 #endif
87 #endif
88
89 #ifndef _stprintf
90 #ifdef UNICODE
91 #define _stprintf wcsprintf
92 #else
93 #define _stprintf sprintf
94 #endif
95 #endif
96
97
98 #ifdef __WINE__
99 #ifdef UNICODE
100 extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
101 #else
102 extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
103 #endif
104 #endif
105
106 #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
107 #define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
108 #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
109 #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
110 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
111 #endif
112
113
114 #define SetDlgCtrlID(hwnd, id) SetWindowLong(hwnd, GWL_ID, id)
115 #define SetWindowStyle(hwnd, val) (DWORD)SetWindowLong(hwnd, GWL_STYLE, val)
116 #define SetWindowExStyle(h, val) (DWORD)SetWindowLong(hwnd, GWL_EXSTYLE, val)
117 #define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
118
119
120 // center window in respect to its parent window
121 extern void CenterWindow(HWND hwnd);
122
123 // move window into visibility
124 extern void MoveVisible(HWND hwnd);
125
126 // display error message
127 extern void display_error(HWND hwnd, DWORD error);
128
129 // convert time_t to WIN32 FILETIME
130 extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
131
132 // search for windows of a specific classname
133 extern int find_window_class(LPCTSTR classname);
134
135 // create a bitmap from an icon
136 extern HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd);
137
138 // launch a program or document file
139 extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow);
140 #ifdef UNICODE
141 extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow);
142 #else
143 #define launch_fileA launch_file
144 #endif
145
146 // call an DLL export like rundll32
147 BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
148
149
150 #ifdef __cplusplus
151 } // extern "C"
152 #endif
153
154
155 #ifdef __cplusplus
156
157 #ifdef _MSC_VER
158 #pragma warning(disable: 4786) // disable warnings about too long debug information symbols
159 #endif
160
161 // STL headers for strings and streams
162 #include <string>
163 #include <iostream>
164 using namespace std;
165
166 #if _MSC_VER>=1300 // VS.Net
167 #define _NO_COMUTIL //@@
168 #endif
169
170 #if defined(_MSC_VER) && !defined(_NO_COMUTIL)
171
172 // COM utility headers
173 #include <comdef.h>
174 using namespace _com_util;
175
176 #endif // _MSC_VER && !_NO_COMUTIL
177
178
179 /// initialization of windows common controls
180 struct CommonControlInit
181 {
182 CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
183 {
184 INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
185
186 InitCommonControlsEx(&icc);
187 }
188 };
189
190
191 /// wait cursor
192
193 struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
194 {
195 WaitCursor()
196 {
197 _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
198 }
199
200 ~WaitCursor()
201 {
202 SetCursor(_old_cursor);
203 }
204
205 protected:
206 HCURSOR _old_cursor;
207 };
208
209
210 /// base of all structures storing a window handle
211 struct WindowHandle
212 {
213 WindowHandle(HWND hwnd=0)
214 : _hwnd(hwnd) {}
215
216 operator HWND() const {return _hwnd;}
217 HWND* operator&() {return &_hwnd;}
218
219 protected:
220 HWND _hwnd;
221 };
222
223
224 /// locally hide a window
225 struct HiddenWindow : public WindowHandle
226 {
227 HiddenWindow(HWND hwnd)
228 : WindowHandle(hwnd)
229 {
230 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
231 }
232
233 ~HiddenWindow()
234 {
235 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
236 }
237 };
238
239
240 /// critical section wrapper
241
242 struct CritSect : public CRITICAL_SECTION
243 {
244 CritSect()
245 {
246 InitializeCriticalSection(this);
247 }
248
249 ~CritSect()
250 {
251 DeleteCriticalSection(this);
252 }
253 };
254
255
256 /// Lock protects a code section utilizing a critical section
257
258 struct Lock
259 {
260 Lock(CritSect& crit_sect)
261 : _crit_sect(crit_sect)
262 {
263 EnterCriticalSection(&crit_sect);
264 }
265
266 ~Lock()
267 {
268 LeaveCriticalSection(&_crit_sect);
269 }
270
271 protected:
272 CritSect& _crit_sect;
273 };
274
275
276 /// Thread base class
277
278 struct Thread
279 {
280 Thread()
281 : _alive(false)
282 {
283 _hThread = INVALID_HANDLE_VALUE;
284 }
285
286 virtual ~Thread()
287 {
288 Stop();
289
290 CloseHandle(_hThread);
291 }
292
293 void Start()
294 {
295 if (!_alive) {
296 _alive = true;
297 _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
298 }
299 }
300
301 void Stop()
302 {
303 if (_alive) {
304 {
305 Lock lock(_crit_sect);
306 _alive = false;
307 }
308
309 // wait for finishing
310 WaitForSingleObject(_hThread, INFINITE);
311 }
312 }
313
314 virtual int Run() = 0;
315
316 bool is_alive() const {return _alive;}
317
318 CritSect _crit_sect;
319
320 protected:
321 static DWORD WINAPI ThreadProc(void* para);
322
323 HANDLE _hThread;
324 bool _alive;
325 };
326
327
328 // window utilities
329
330 /// ClientRect retreives the client area rectangle of a window.
331 struct ClientRect : public RECT
332 {
333 ClientRect(HWND hwnd)
334 {
335 GetClientRect(hwnd, this);
336 }
337
338 operator LPRECT() {return this;}
339
340 POINT& pos() {return *(LPPOINT)this;}
341 };
342
343 /// ClientRect retreives the window rectangle of a window.
344 struct WindowRect : public RECT
345 {
346 WindowRect(HWND hwnd)
347 {
348 GetWindowRect(hwnd, this);
349 }
350
351 operator LPRECT() {return this;}
352
353 POINT& pos() {return *(LPPOINT)this;}
354 };
355
356 /// PointL encapsulates the POINT structure into a C++ object.
357 struct Point : public POINT
358 {
359 Point(LONG x_, LONG y_)
360 {
361 x = x_;
362 y = y_;
363 }
364
365 // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
366 Point(LPARAM lparam)
367 {
368 x = GET_X_LPARAM(lparam);
369 y = GET_Y_LPARAM(lparam);
370 }
371
372 operator LPPOINT() {return this;}
373 };
374
375
376 /// transform coordinates in a RECT from client to screen coordiantes
377 inline void ClientToScreen(HWND hwnd, RECT* prect)
378 {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
379
380 /// transform coordinates in a RECT from screen to client coordiantes
381 inline void ScreenToClient(HWND hwnd, RECT* prect)
382 {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
383
384
385 /// structure containing information about full screen display of the frame window
386 struct FullScreenParameters
387 {
388 FullScreenParameters()
389 : _mode(FALSE)
390 {
391 }
392
393 BOOL _mode;
394 RECT _orgPos;
395 BOOL _wasZoomed;
396 };
397
398
399 // drawing utilities
400
401 /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
402 struct PaintCanvas : public PAINTSTRUCT
403 {
404 PaintCanvas(HWND hwnd)
405 : _hwnd(hwnd)
406 {
407 BeginPaint(hwnd, this);
408 }
409
410 ~PaintCanvas()
411 {
412 EndPaint(_hwnd, this);
413 }
414
415 operator HDC() const {return hdc;}
416
417 protected:
418 HWND _hwnd;
419 };
420
421 /// Canvas is a encapsulation of device contexts.
422 struct Canvas
423 {
424 Canvas(HDC hdc) : _hdc(hdc) {}
425
426 operator HDC() {return _hdc;}
427
428 protected:
429 HDC _hdc;
430 };
431
432 /// WindowCanvas is a encapsulation of client area device contexts.
433 struct WindowCanvas : public Canvas
434 {
435 WindowCanvas(HWND hwnd)
436 : Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
437
438 ~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
439
440 protected:
441 HWND _hwnd;
442 };
443
444
445 // double buffering classes
446
447 /// Memory Canvas creates and destroys memory devoce contexts.
448 struct MemCanvas : public Canvas
449 {
450 MemCanvas(HDC hdc=0)
451 : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
452
453 ~MemCanvas() {DeleteDC(_hdc);}
454 };
455
456 /// SelectedBitmap is used to localy select bitmaps into device contexts.
457 struct SelectedBitmap
458 {
459 SelectedBitmap(HDC hdc, HBITMAP hbmp)
460 : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
461
462 ~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
463
464 protected:
465 HDC _hdc;
466 HBITMAP _old_hbmp;
467 };
468
469 /// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
470 struct BufferCanvas : public MemCanvas
471 {
472 BufferCanvas(HDC hdc, int x, int y, int w, int h)
473 : MemCanvas(hdc), _hdctarg(hdc),
474 _x(x), _y(y), _w(w), _h(h),
475 _bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
476
477 BufferCanvas(HDC hdc, const RECT& rect)
478 : MemCanvas(hdc), _hdctarg(hdc),
479 _x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
480 _bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
481
482 protected:
483 HDC _hdctarg;
484 int _x, _y, _w, _h;
485 SelectedBitmap _bmp;
486 };
487
488 /// BufferedCanvas enables double buffering for a device context.
489 struct BufferedCanvas : public BufferCanvas
490 {
491 BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
492 : BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
493
494 BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
495 : BufferCanvas(hdc, rect), _mode(mode) {}
496
497 ~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
498
499 DWORD _mode;
500 };
501
502 /// BufferedPaintCanvas extends PaintCanvas for double buffering.
503 struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
504 {
505 BufferedPaintCanvas(HWND hwnd)
506 : PaintCanvas(hwnd),
507 BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
508 {
509 }
510
511 operator HDC() {return BufferedCanvas::_hdc;}
512 };
513
514
515 /// TextColor locally selects a text color for drawing.
516 struct TextColor
517 {
518 TextColor(HDC hdc, COLORREF color)
519 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
520
521 ~TextColor() {SetTextColor(_hdc, _old_color);}
522
523 protected:
524 HDC _hdc;
525 COLORREF _old_color;
526 };
527
528 /// TextColor locally sets the background mode for drawing.
529 struct BkMode
530 {
531 BkMode(HDC hdc, int bkmode)
532 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
533
534 ~BkMode() {SetBkMode(_hdc, _old_bkmode);}
535
536 protected:
537 HDC _hdc;
538 COLORREF _old_bkmode;
539 };
540
541 /// TextColor locally selects a font for drawing.
542 struct FontSelection
543 {
544 FontSelection(HDC hdc, HFONT hFont)
545 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
546
547 ~FontSelection() {SelectFont(_hdc, _old_hFont);}
548
549 protected:
550 HDC _hdc;
551 HFONT _old_hFont;
552 };
553
554 /// TextColor locally selects a bitmap into a device context.
555 struct BitmapSelection
556 {
557 BitmapSelection(HDC hdc, HBITMAP hBmp)
558 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
559
560 ~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
561
562 protected:
563 HDC _hdc;
564 HBITMAP _old_hBmp;
565 };
566
567
568 /// string class for convenience
569 struct String
570 #ifdef UNICODE
571 : public wstring
572 #else
573 : public string
574 #endif
575 {
576 #ifdef UNICODE
577 typedef wstring super;
578 #else
579 typedef string super;
580 #endif
581
582 String() {}
583 String(LPCTSTR s) {if (s) super::assign(s);}
584 String(LPCTSTR s, int l) : super(s, l) {}
585 String(const super& other) : super(other) {}
586 String(const String& other) : super(other) {}
587
588 #ifdef UNICODE
589 String(LPCSTR s) {assign(s);}
590 String(LPCSTR s, int l) {assign(s, l);}
591 String(const string& other) {assign(other.c_str());}
592 String& operator=(LPCSTR s) {assign(s); return *this;}
593 void assign(LPCSTR s) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN));} else erase();}
594 void assign(LPCSTR s, int l) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, BUFFER_LEN));} else erase();}
595 #else
596 String(LPCWSTR s) {assign(s);}
597 String(LPCWSTR s, int l) {assign(s, l);}
598 String(const wstring& other) {assign(other.c_str());}
599 String& operator=(LPCWSTR s) {assign(s); return *this;}
600 void assign(LPCWSTR s) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, -1, b, BUFFER_LEN, 0, 0));} else erase();}
601 void assign(LPCWSTR s, int l) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
602 #endif
603
604 String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
605 String& operator=(const super& s) {super::assign(s); return *this;}
606
607 operator LPCTSTR() const {return c_str();}
608
609 String& printf(LPCTSTR fmt, ...)
610 {
611 va_list l;
612 TCHAR b[BUFFER_LEN];
613
614 va_start(l, fmt);
615 super::assign(b, _vstprintf(b, fmt, l));
616 va_end(l);
617
618 return *this;
619 }
620
621 String& vprintf(LPCTSTR fmt, va_list l)
622 {
623 TCHAR b[BUFFER_LEN];
624
625 super::assign(b, _vstprintf(b, fmt, l));
626
627 return *this;
628 }
629
630 String& appendf(LPCTSTR fmt, ...)
631 {
632 va_list l;
633 TCHAR b[BUFFER_LEN];
634
635 va_start(l, fmt);
636 super::append(b, _vstprintf(b, fmt, l));
637 va_end(l);
638
639 return *this;
640 }
641
642 String& vappendf(LPCTSTR fmt, va_list l)
643 {
644 TCHAR b[BUFFER_LEN];
645
646 super::append(b, _vstprintf(b, fmt, l));
647
648 return *this;
649 }
650 };
651
652
653 struct FmtString : public String
654 {
655 FmtString(LPCTSTR fmt, ...)
656 {
657 va_list l;
658
659 va_start(l, fmt);
660 vprintf(fmt, l);
661 va_end(l);
662 }
663 };
664
665
666 #ifdef UNICODE
667
668 struct ANS
669 {
670 ANS(LPCWSTR s)
671 {
672 int l = wcslen(s) + 1;
673 _str = (LPSTR) malloc(2*l);
674
675 if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
676 *_str = '\0';
677 }
678
679 ~ANS()
680 {
681 free(_str);
682 }
683
684 operator LPCSTR() {return _str;}
685
686 protected:
687 LPSTR _str;
688 };
689
690 #define UNC(x) ((LPCWSTR)(x))
691
692 #else
693
694 #define ANS(x) ((LPCSTR)(x))
695
696 struct UNC
697 {
698 UNC(LPCSTR s)
699 {
700 int l = strlen(s) + 1;
701 _str = (LPWSTR) malloc(2*l);
702
703 if (MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
704 *_str = '\0';
705 }
706
707 ~UNC()
708 {
709 free(_str);
710 }
711
712 operator LPCWSTR() {return _str;}
713
714 protected:
715 LPWSTR _str;
716 };
717
718 #endif
719
720
721 /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
722 template<typename FCT> struct DynamicFct
723 {
724 DynamicFct(LPCTSTR moduleName, UINT ordinal)
725 {
726 HMODULE hModule = GetModuleHandle(moduleName);
727
728 _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
729 }
730
731 DynamicFct(LPCTSTR moduleName, LPCSTR name)
732 {
733 HMODULE hModule = GetModuleHandle(moduleName);
734
735 _fct = (FCT) GetProcAddress(hModule, name);
736 }
737
738 FCT operator*() const {return _fct;}
739 operator bool() const {return _fct? true: false;}
740
741 protected:
742 FCT _fct;
743 };
744
745
746 /// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
747 template<typename FCT> struct DynamicLoadLibFct
748 {
749 DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
750 {
751 _hModule = LoadLibrary(moduleName);
752
753 _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
754 }
755
756 DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
757 {
758 _hModule = LoadLibrary(moduleName);
759
760 _fct = (FCT) GetProcAddress(_hModule, name);
761 }
762
763 ~DynamicLoadLibFct()
764 {
765 FreeLibrary(_hModule);
766 }
767
768 FCT operator*() const {return _fct;}
769 operator bool() const {return _fct? true: false;}
770
771 protected:
772 HMODULE _hModule;
773 FCT _fct;
774 };
775
776
777 struct Context
778 {
779 Context(const char* ctx)
780 : _ctx(ctx)
781 {
782 _last = s_current;
783 s_current = this;
784 }
785
786 Context(const char* ctx, LPCSTR obj)
787 : _ctx(ctx),
788 _obj(obj)
789 {
790 _last = s_current;
791 s_current = this;
792 }
793
794 Context(const char* ctx, LPCWSTR obj)
795 : _ctx(ctx),
796 _obj(obj)
797 {
798 _last = s_current;
799 s_current = this;
800 }
801
802 Context(const Context& other)
803 : _ctx(other._ctx),
804 _obj(other._obj)
805 {
806 _last = NULL;
807 }
808
809 ~Context()
810 {
811 if (_last) {
812 s_current = _last;
813 _last = NULL;
814 }
815 }
816
817 String toString() const;
818 String getStackTrace() const;
819
820 const char* _ctx;
821 String _obj;
822
823 static Context& current() {return *s_current;}
824
825 protected:
826 Context* _last;
827
828 static Context* s_current; ///@todo use TLS
829 static Context s_main;
830 };
831
832 #define CONTEXT_OBJ __ctx__._obj
833 #define CONTEXT(c) Context __ctx__(c)
834 #define CURRENT_CONTEXT Context::current()
835 #define OBJ_CONTEXT(c, o) Context __ctx__(c, o);
836
837
838 #endif // __cplusplus