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