- XMLChildrenFilter iterator
[reactos.git] / reactos / subsys / system / explorer / utility / utility.h
1 /*
2 * Copyright 2003, 2004 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 #ifndef _MSC_VER
44 #include <objbase.h>
45 #endif
46 #include <oleauto.h> // for VARIANT
47
48 #include <malloc.h> // for alloca()
49 #include <assert.h>
50 #include <stdlib.h> // for _MAX_DIR, ...
51 #include <stdio.h> // for sprintf()
52 #include <time.h>
53
54 #ifndef _MAX_PATH
55 #define _MAX_DRIVE 3
56 #define _MAX_FNAME 256
57 #define _MAX_DIR _MAX_FNAME
58 #define _MAX_EXT _MAX_FNAME
59 #define _MAX_PATH 260
60 #endif
61
62
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66
67
68 #define for if (0) {} else for
69
70 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
71
72
73 #define BUFFER_LEN 2048
74
75
76 extern void _log_(LPCTSTR txt);
77
78 #define LOG(txt) _log_(txt)
79
80
81 #ifdef _MSC_VER
82 #define LONGLONGARG TEXT("I64")
83 #else
84 #define LONGLONGARG TEXT("L")
85 #endif
86
87
88 #ifndef _tcsrchr
89 #ifdef UNICODE
90 #define _tcsrchr wcsrchr
91 #else
92 #define _tcsrchr strrchr
93 #endif
94 #endif
95
96 #ifndef _stprintf
97 #ifdef UNICODE
98 #define _stprintf wcsprintf
99 #else
100 #define _stprintf sprintf
101 #endif
102 #endif
103
104 #define U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL)
105 #define U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL)
106 #define A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l)
107 #define A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l)
108
109
110 #ifdef __WINE__
111 #ifdef UNICODE
112 extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
113 #else
114 extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
115 #endif
116 #define _tcsnicmp strncasecmp
117 #define _tcsicoll strcasecmp
118 #endif
119
120 #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
121 #define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
122 #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
123 #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
124 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
125 #endif
126
127
128 #define SetDlgCtrlID(hwnd, id) SetWindowLong(hwnd, GWL_ID, id)
129 #define SetWindowStyle(hwnd, val) (DWORD)SetWindowLong(hwnd, GWL_STYLE, val)
130 #define SetWindowExStyle(h, val) (DWORD)SetWindowLong(hwnd, GWL_EXSTYLE, val)
131 #define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
132
133
134 // center window in respect to its parent window
135 extern void CenterWindow(HWND hwnd);
136
137 // move window into visibility
138 extern void MoveVisible(HWND hwnd);
139
140 // display error message
141 extern void display_error(HWND hwnd, DWORD error);
142
143 // convert time_t to WIN32 FILETIME
144 extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
145
146 // search for windows of a specific classname
147 extern int find_window_class(LPCTSTR classname);
148
149 // create a directory with all missing parent directories
150 BOOL RecursiveCreateDirectory(LPCTSTR path_in);
151
152
153 #ifdef __cplusplus
154 } // extern "C"
155 #endif
156
157
158 #ifdef __cplusplus
159
160 #ifdef _MSC_VER
161 #pragma warning(disable: 4786) // disable warnings about too long debug information symbols
162 #endif
163
164 // STL headers for strings and streams
165 #include <string>
166 #include <iostream>
167 using namespace std;
168
169 // containers
170 #include <map>
171 #include <set>
172 #include <list>
173 #include <vector>
174
175
176 #if _MSC_VER>=1300 // VS.Net
177 #define _NO_COMUTIL //@@
178 #endif
179
180 #if defined(_MSC_VER) && !defined(_NO_COMUTIL)
181
182 // COM utility headers
183 #include <comdef.h>
184 using namespace _com_util;
185
186 #endif // _MSC_VER && !_NO_COMUTIL
187
188
189 // launch a program or document file
190 extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow, LPCTSTR parameters=NULL);
191 #ifdef UNICODE
192 extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow, LPCSTR parameters=NULL);
193 #else
194 #define launch_fileA launch_file
195 #endif
196
197 // call an DLL export like rundll32
198 extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
199
200 // launch control panel applet
201 extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet);
202
203
204 /// initialization of windows common controls
205 struct CommonControlInit
206 {
207 CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
208 {
209 INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
210
211 InitCommonControlsEx(&icc);
212 }
213 };
214
215
216 /// wait cursor
217
218 struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
219 {
220 WaitCursor()
221 {
222 _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
223 }
224
225 ~WaitCursor()
226 {
227 SetCursor(_old_cursor);
228 }
229
230 protected:
231 HCURSOR _old_cursor;
232 };
233
234
235 /// base of all structures storing a window handle
236 struct WindowHandle
237 {
238 WindowHandle(HWND hwnd=0)
239 : _hwnd(hwnd) {}
240
241 operator HWND() const {return _hwnd;}
242 HWND* operator&() {return &_hwnd;}
243
244 protected:
245 HWND _hwnd;
246 };
247
248
249 /// locally hide a window
250 struct HiddenWindow : public WindowHandle
251 {
252 HiddenWindow(HWND hwnd)
253 : WindowHandle(hwnd)
254 {
255 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
256 }
257
258 ~HiddenWindow()
259 {
260 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
261 }
262 };
263
264
265 /// critical section wrapper
266
267 struct CritSect : public CRITICAL_SECTION
268 {
269 CritSect()
270 {
271 InitializeCriticalSection(this);
272 }
273
274 ~CritSect()
275 {
276 DeleteCriticalSection(this);
277 }
278 };
279
280
281 /// Lock protects a code section utilizing a critical section
282
283 struct Lock
284 {
285 Lock(CritSect& crit_sect)
286 : _crit_sect(crit_sect)
287 {
288 EnterCriticalSection(&crit_sect);
289 }
290
291 ~Lock()
292 {
293 LeaveCriticalSection(&_crit_sect);
294 }
295
296 protected:
297 CritSect& _crit_sect;
298 };
299
300
301 /// Thread base class
302
303 struct Thread
304 {
305 Thread()
306 : _alive(false)
307 {
308 _hThread = INVALID_HANDLE_VALUE;
309 }
310
311 virtual ~Thread()
312 {
313 Stop();
314
315 CloseHandle(_hThread);
316 }
317
318 void Start()
319 {
320 if (!_alive) {
321 _alive = true;
322 _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
323 }
324 }
325
326 void Stop()
327 {
328 if (_alive) {
329 {
330 Lock lock(_crit_sect);
331 _alive = false;
332 }
333
334 // wait for finishing
335 WaitForSingleObject(_hThread, INFINITE);
336 }
337 }
338
339 virtual int Run() = 0;
340
341 bool is_alive() const {return _alive;}
342
343 CritSect _crit_sect;
344
345 protected:
346 static DWORD WINAPI ThreadProc(void* para);
347
348 HANDLE _hThread;
349 bool _alive;
350 };
351
352
353 // window utilities
354
355 /// ClientRect retreives the client area rectangle of a window.
356 struct ClientRect : public RECT
357 {
358 ClientRect(HWND hwnd)
359 {
360 GetClientRect(hwnd, this);
361 }
362
363 operator LPRECT() {return this;}
364
365 POINT& pos() {return *(LPPOINT)this;}
366 };
367
368 /// ClientRect retreives the window rectangle of a window.
369 struct WindowRect : public RECT
370 {
371 WindowRect(HWND hwnd)
372 {
373 GetWindowRect(hwnd, this);
374 }
375
376 operator LPRECT() {return this;}
377
378 POINT& pos() {return *(LPPOINT)this;}
379 };
380
381 /// PointL encapsulates the POINT structure into a C++ object.
382 struct Point : public POINT
383 {
384 Point(LONG x_, LONG y_)
385 {
386 x = x_;
387 y = y_;
388 }
389
390 // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
391 Point(LPARAM lparam)
392 {
393 x = GET_X_LPARAM(lparam);
394 y = GET_Y_LPARAM(lparam);
395 }
396
397 operator LPPOINT() {return this;}
398 };
399
400
401 /// transform coordinates in a RECT from client to screen coordiantes
402 inline void ClientToScreen(HWND hwnd, RECT* prect)
403 {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
404
405 /// transform coordinates in a RECT from screen to client coordiantes
406 inline void ScreenToClient(HWND hwnd, RECT* prect)
407 {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
408
409
410 /// structure containing information about full screen display of the frame window
411 struct FullScreenParameters
412 {
413 FullScreenParameters()
414 : _mode(FALSE)
415 {
416 }
417
418 BOOL _mode;
419 RECT _orgPos;
420 BOOL _wasZoomed;
421 };
422
423
424 // drawing utilities
425
426 /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
427 struct PaintCanvas : public PAINTSTRUCT
428 {
429 PaintCanvas(HWND hwnd)
430 : _hwnd(hwnd)
431 {
432 BeginPaint(hwnd, this);
433 }
434
435 ~PaintCanvas()
436 {
437 EndPaint(_hwnd, this);
438 }
439
440 operator HDC() const {return hdc;}
441
442 protected:
443 HWND _hwnd;
444 };
445
446 /// Canvas is a encapsulation of device contexts.
447 struct Canvas
448 {
449 Canvas(HDC hdc) : _hdc(hdc) {}
450
451 operator HDC() {return _hdc;}
452
453 protected:
454 HDC _hdc;
455 };
456
457 /// WindowCanvas is a encapsulation of client area device contexts.
458 struct WindowCanvas : public Canvas
459 {
460 WindowCanvas(HWND hwnd)
461 : Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
462
463 ~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
464
465 protected:
466 HWND _hwnd;
467 };
468
469
470 // double buffering classes
471
472 /// Memory Canvas creates and destroys memory devoce contexts.
473 struct MemCanvas : public Canvas
474 {
475 MemCanvas(HDC hdc=0)
476 : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
477
478 ~MemCanvas() {DeleteDC(_hdc);}
479 };
480
481 /// SelectedBitmap is used to localy select bitmaps into device contexts.
482 struct SelectedBitmap
483 {
484 SelectedBitmap(HDC hdc, HBITMAP hbmp)
485 : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
486
487 ~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
488
489 protected:
490 HDC _hdc;
491 HBITMAP _old_hbmp;
492 };
493
494 /// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
495 struct BufferCanvas : public MemCanvas
496 {
497 BufferCanvas(HDC hdc, int x, int y, int w, int h)
498 : MemCanvas(hdc), _hdctarg(hdc),
499 _x(x), _y(y), _w(w), _h(h),
500 _bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
501
502 BufferCanvas(HDC hdc, const RECT& rect)
503 : MemCanvas(hdc), _hdctarg(hdc),
504 _x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
505 _bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
506
507 protected:
508 HDC _hdctarg;
509 int _x, _y, _w, _h;
510 SelectedBitmap _bmp;
511 };
512
513 /// BufferedCanvas enables double buffering for a device context.
514 struct BufferedCanvas : public BufferCanvas
515 {
516 BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
517 : BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
518
519 BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
520 : BufferCanvas(hdc, rect), _mode(mode) {}
521
522 ~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
523
524 DWORD _mode;
525 };
526
527 /// BufferedPaintCanvas extends PaintCanvas for double buffering.
528 struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
529 {
530 BufferedPaintCanvas(HWND hwnd)
531 : PaintCanvas(hwnd),
532 BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
533 {
534 }
535
536 operator HDC() {return BufferedCanvas::_hdc;}
537 };
538
539
540 /// TextColor locally selects a text color for drawing.
541 struct TextColor
542 {
543 TextColor(HDC hdc, COLORREF color)
544 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
545
546 ~TextColor() {SetTextColor(_hdc, _old_color);}
547
548 protected:
549 HDC _hdc;
550 COLORREF _old_color;
551 };
552
553 /// BkMode locally sets the background mode for drawing.
554 struct BkMode
555 {
556 BkMode(HDC hdc, int bkmode)
557 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
558
559 ~BkMode() {SetBkMode(_hdc, _old_bkmode);}
560
561 protected:
562 HDC _hdc;
563 COLORREF _old_bkmode;
564 };
565
566 /// FontSelection locally selects a font for drawing.
567 struct FontSelection
568 {
569 FontSelection(HDC hdc, HFONT hFont)
570 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
571
572 ~FontSelection() {SelectFont(_hdc, _old_hFont);}
573
574 protected:
575 HDC _hdc;
576 HFONT _old_hFont;
577 };
578
579 /// BitmapSelection locally selects a bitmap into a device context.
580 struct BitmapSelection
581 {
582 BitmapSelection(HDC hdc, HBITMAP hBmp)
583 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
584
585 ~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
586
587 protected:
588 HDC _hdc;
589 HBITMAP _old_hBmp;
590 };
591
592 /// BrushSelection locally selects a brush into a device context.
593 struct BrushSelection
594 {
595 BrushSelection(HDC hdc, HBRUSH hBrush)
596 : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {}
597
598 ~BrushSelection() {SelectBrush(_hdc, _old_hBrush);}
599
600 protected:
601 HDC _hdc;
602 HBRUSH _old_hBrush;
603 };
604
605
606 /// Popup Menus
607 struct PopupMenu
608 {
609 PopupMenu()
610 : _hmenu(CreatePopupMenu())
611 {
612 }
613
614 PopupMenu(UINT nid);
615
616 operator HMENU() {return _hmenu;}
617
618 void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING)
619 {
620 AppendMenu(_hmenu, flags, id, str);
621 }
622
623 int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) {
624 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm);
625 }
626
627 int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
628 POINT pt; POINTSTOPOINT(pt, pos);
629 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
630 }
631
632 int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
633 POINT pt; POINTSTOPOINT(pt, pos);
634 ClientToScreen(hwnd, &pt);
635 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
636 }
637
638 int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) {
639 POINT pt; GetCursorPos(&pt);
640 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
641 }
642
643 int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) {
644 return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL);
645 }
646
647 protected:
648 HMENU _hmenu;
649 };
650
651
652 struct Variant : public VARIANT
653 {
654 Variant() {VariantInit(this);}
655 Variant(const VARIANT& var);
656 Variant(const VARIANT* var);
657 ~Variant();
658
659 operator long() const;
660 operator bool() const;
661 operator VARIANT_BOOL() const;
662 operator IDispatch*() const;
663 };
664
665
666 struct BStr
667 {
668 BStr()
669 {
670 _p = NULL;
671 }
672
673 BStr(const BSTR s)
674 {
675 _p = SysAllocString(s);
676 }
677
678 BStr(LPCSTR s)
679 {
680 WCHAR b[BUFFER_LEN];
681
682 if (s)
683 _p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);
684 else
685 _p = NULL;
686 }
687
688 BStr(LPCWSTR s)
689 {
690 _p = SysAllocString(s);
691 }
692
693 BStr(const VARIANT& var)
694 : _p(NULL)
695 {
696 assign(var);
697 }
698
699 ~BStr()
700 {
701 SysFreeString(_p);
702 }
703
704 void assign(BSTR s);
705 void assign(const VARIANT& var);
706
707 operator BSTR() const
708 {
709 return _p? _p: (BSTR)L"";
710 }
711
712 int length() const
713 {
714 return _p? wcslen(_p): 0;
715 }
716
717 protected:
718 BSTR _p;
719 };
720
721
722 /// string class for TCHAR strings
723 struct String
724 #ifdef UNICODE
725 : public wstring
726 #else
727 : public string
728 #endif
729 {
730 #ifdef UNICODE
731 typedef wstring super;
732 #else
733 typedef string super;
734 #endif
735
736 String() {}
737 String(LPCTSTR s) {if (s) super::assign(s);}
738 String(LPCTSTR s, int l) : super(s, l) {}
739 String(const super& other) : super(other) {}
740 String(const String& other) : super(other) {}
741
742 #ifdef UNICODE
743 String(LPCSTR s) {assign(s);}
744 String(LPCSTR s, int l) {assign(s, l);}
745 String(const string& other) {assign(other.c_str());}
746 String& operator=(LPCSTR s) {assign(s); return *this;}
747 void assign(LPCSTR s) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);} else erase();}
748 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();}
749 void assign(const BStr& s) {int l = s.length(); super::assign(s, l);}
750 #else
751 String(LPCWSTR s) {assign(s);}
752 String(LPCWSTR s, int l) {assign(s, l);}
753 String(const wstring& other) {assign(other.c_str());}
754 String& operator=(LPCWSTR s) {assign(s); return *this;}
755 void assign(LPCWSTR s) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, -1, b, BUFFER_LEN, 0, 0)-1);} else erase();}
756 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();}
757 void assign(const BStr& s) {int l = s.length(); if (l) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
758 #endif
759 String(const BStr& s) {assign(s);}
760 String& operator=(const BStr& s) {assign(s); return *this;}
761
762 String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
763 String& operator=(const super& s) {super::assign(s); return *this;}
764 void assign(LPCTSTR s) {super::assign(s);}
765 void assign(LPCTSTR s, int l) {super::assign(s, l);}
766
767 operator LPCTSTR() const {return c_str();}
768
769 #ifdef UNICODE
770 operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);}
771 #else
772 operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);}
773 #endif
774
775 String& printf(LPCTSTR fmt, ...)
776 {
777 va_list l;
778 TCHAR b[BUFFER_LEN];
779
780 va_start(l, fmt);
781 super::assign(b, _vstprintf(b, fmt, l));
782 va_end(l);
783
784 return *this;
785 }
786
787 String& vprintf(LPCTSTR fmt, va_list l)
788 {
789 TCHAR b[BUFFER_LEN];
790
791 super::assign(b, _vstprintf(b, fmt, l));
792
793 return *this;
794 }
795
796 String& appendf(LPCTSTR fmt, ...)
797 {
798 va_list l;
799 TCHAR b[BUFFER_LEN];
800
801 va_start(l, fmt);
802 super::append(b, _vstprintf(b, fmt, l));
803 va_end(l);
804
805 return *this;
806 }
807
808 String& vappendf(LPCTSTR fmt, va_list l)
809 {
810 TCHAR b[BUFFER_LEN];
811
812 super::append(b, _vstprintf(b, fmt, l));
813
814 return *this;
815 }
816 };
817
818 #define _STRING_DEFINED
819
820
821 struct FmtString : public String
822 {
823 FmtString(LPCTSTR fmt, ...)
824 {
825 va_list l;
826
827 va_start(l, fmt);
828 vprintf(fmt, l);
829 va_end(l);
830 }
831 };
832
833
834 #ifdef UNICODE
835
836 struct ANS
837 {
838 ANS(LPCWSTR s)
839 {
840 int l = wcslen(s) + 1;
841 _str = (LPSTR) malloc(2*l);
842
843 if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
844 *_str = '\0';
845 }
846
847 ~ANS()
848 {
849 free(_str);
850 }
851
852 operator LPCSTR() {return _str;}
853
854 protected:
855 LPSTR _str;
856 };
857
858 #define UNC(x) ((LPCWSTR)(x))
859
860 #else
861
862 #define ANS(x) ((LPCSTR)(x))
863
864 struct UNC
865 {
866 UNC(LPCSTR s)
867 {
868 int l = strlen(s) + 1;
869 _str = (LPWSTR) malloc(2*l);
870
871 if (MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
872 *_str = '\0';
873 }
874
875 ~UNC()
876 {
877 free(_str);
878 }
879
880 operator LPCWSTR() {return _str;}
881
882 protected:
883 LPWSTR _str;
884 };
885
886 #endif
887
888
889 /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
890 template<typename FCT> struct DynamicFct
891 {
892 DynamicFct(LPCTSTR moduleName, UINT ordinal)
893 {
894 HMODULE hModule = GetModuleHandle(moduleName);
895
896 _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
897 }
898
899 DynamicFct(LPCTSTR moduleName, LPCSTR name)
900 {
901 HMODULE hModule = GetModuleHandle(moduleName);
902
903 _fct = (FCT) GetProcAddress(hModule, name);
904 }
905
906 FCT operator*() const {return _fct;}
907 operator bool() const {return _fct? true: false;}
908
909 protected:
910 FCT _fct;
911 };
912
913
914 /// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
915 template<typename FCT> struct DynamicLoadLibFct
916 {
917 DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
918 {
919 _hModule = LoadLibrary(moduleName);
920
921 _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
922 }
923
924 DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
925 {
926 _hModule = LoadLibrary(moduleName);
927
928 _fct = (FCT) GetProcAddress(_hModule, name);
929 }
930
931 ~DynamicLoadLibFct()
932 {
933 FreeLibrary(_hModule);
934 }
935
936 FCT operator*() const {return _fct;}
937 operator bool() const {return _fct? true: false;}
938
939 protected:
940 HMODULE _hModule;
941 FCT _fct;
942 };
943
944
945 struct Context
946 {
947 Context(const char* ctx)
948 : _ctx(ctx)
949 {
950 _last = s_current;
951 s_current = this;
952 }
953
954 Context(const char* ctx, LPCSTR obj)
955 : _ctx(ctx),
956 _obj(obj)
957 {
958 _last = s_current;
959 s_current = this;
960 }
961
962 Context(const char* ctx, LPCWSTR obj)
963 : _ctx(ctx),
964 _obj(obj)
965 {
966 _last = s_current;
967 s_current = this;
968 }
969
970 Context(const Context& other)
971 : _ctx(other._ctx),
972 _obj(other._obj)
973 {
974 _last = NULL;
975 }
976
977 ~Context()
978 {
979 if (_last) {
980 s_current = _last;
981 _last = NULL;
982 }
983 }
984
985 String toString() const;
986 String getStackTrace() const;
987
988 const char* _ctx;
989 String _obj;
990
991 static Context& current() {return *s_current;}
992
993 protected:
994 Context* _last;
995
996 static Context* s_current; ///@todo use TLS
997 static Context s_main;
998 };
999
1000 #define CONTEXT_OBJ __ctx__._obj
1001 #define CONTEXT(c) Context __ctx__(c)
1002 #define CURRENT_CONTEXT Context::current()
1003 #define OBJ_CONTEXT(c, o) Context __ctx__(c, o);
1004
1005
1006 #endif // __cplusplus