Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1068 lines
30 KiB

  1. /*
  2. * Private headers
  3. */
  4. #ifndef STRICT
  5. #define STRICT
  6. #endif
  7. #ifndef WIN32_LEAN_AND_MEAN /* build.exe will define it for us on NT */
  8. #define WIN32_LEAN_AND_MEAN
  9. #endif
  10. #undef WINVER /* build process defines this */
  11. #define WINVER 0x0400 /* Windows 95 compatible */
  12. #define _WIN32_WINDOWS 0x0400 /* Windows 95 compatible */
  13. #include <windows.h> /* Everybody's favourite */
  14. #include <commctrl.h>
  15. #ifndef RC_INVOKED
  16. #include <windowsx.h> /* Message crackers */
  17. #include <shlwapi.h>
  18. #include <shellapi.h>
  19. #endif
  20. /*****************************************************************************
  21. *
  22. * Resources
  23. *
  24. *****************************************************************************/
  25. /*
  26. * Icons
  27. */
  28. #define IDI_SDV 0x0001
  29. /*
  30. * Bitmaps
  31. */
  32. #define IDB_PLUS 0x0001
  33. #define IDB_IMAGES 0x0002
  34. /*
  35. * Strings
  36. */
  37. #define IDS_TITLE 0x0001
  38. #define IDS_IE4 0x0002
  39. #define IDS_SD_EXEC_ERR 0x0003
  40. #define IDS_DEFAULT_BUGPAGE 0x0004
  41. #define IDS_VIEWBUG_FORMAT 0x0005
  42. #define IDS_VIEWBUG_NONE 0x0006
  43. #define IDS_COL_REV 0x0100
  44. #define IDS_COL_CHANGE 0x0101
  45. #define IDS_COL_OP 0x0102
  46. #define IDS_COL_DATE 0x0103
  47. #define IDS_COL_DEV 0x0104
  48. #define IDS_COL_CHURN 0x0105
  49. #define IDS_COL_COMMENT 0x0106
  50. /*
  51. * Menus
  52. */
  53. #define IDM_CHANGES 1
  54. #define IDM_CHANGES_POPUP 2
  55. #define IDM_DESCRIBE 3
  56. #define IDM_DESCRIBE_POPUP 4
  57. #define IDM_FILELOG 5
  58. #define IDM_FILELOG_POPUP 6
  59. #define IDM_OPENED 7
  60. #define IDM_OPENED_POPUP 8
  61. #define IDM_EXIT 100
  62. #define IDM_EXITALL 101
  63. #define IDM_COPY 102
  64. #define IDM_COPYALL 103
  65. #define IDM_VIEWDESC 104
  66. #define IDM_VIEWFILEDIFF 105
  67. #define IDM_VIEWWINDIFF 106
  68. #define IDM_VIEWBUG 107
  69. #define IDM_VIEWFILELOG 108
  70. #define IDM_HELP 200
  71. /*
  72. * Accelerators
  73. */
  74. #define IDA_CHANGES 1
  75. #define IDA_DESCRIBE 2
  76. #define IDA_FILELOG 3
  77. #define IDA_OPENED 4
  78. /*****************************************************************************
  79. *
  80. * Assorted goo
  81. *
  82. *****************************************************************************/
  83. #ifndef RC_INVOKED
  84. extern HINSTANCE g_hinst;
  85. extern HCURSOR g_hcurWait;
  86. extern HCURSOR g_hcurArrow;
  87. extern HCURSOR g_hcurAppStarting;
  88. extern LONG g_lThreads;
  89. extern TCHAR g_szTitle[MAX_PATH];
  90. extern UINT g_wShowWindow;
  91. DWORD EndThreadTask(DWORD dwExitCode);
  92. #ifndef ARRAYSIZE
  93. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  94. #endif
  95. #ifndef NO_VTABLE
  96. #define NO_VTABLE __declspec(novtable)
  97. #endif
  98. /*
  99. * Because C++ syntax is so ugly.
  100. */
  101. #define SAFECAST(T, p) static_cast<T>(p)
  102. #define RECAST(T, p) reinterpret_cast<T>(p)
  103. #define CCAST(T, p) const_cast<T>(p)
  104. /*****************************************************************************
  105. *
  106. * Utility goo
  107. *
  108. *****************************************************************************/
  109. class String;
  110. int ListView_GetCurSel(HWND hwnd);
  111. void ListView_SetCurSel(HWND hwnd, int iIndex);
  112. int ListView_GetSubItemText(HWND hwnd, int iItem, int iSubItem, LPTSTR pszBuf, int cch);
  113. #undef ListView_GetItemText
  114. #define ListView_GetItemText(hwnd, iItem, pszBuf, cch) \
  115. ListView_GetSubItemText(hwnd, iItem, 0, pszBuf, cch)
  116. void ChangeTabsToSpaces(LPTSTR psz);
  117. void PremungeFilespec(LPTSTR psz);
  118. void PostmungeFilespec(LPTSTR psz);
  119. BOOL ContainsWildcards(LPCTSTR psz);
  120. enum MAPTOX {
  121. MAPTOX_DEPOT, // //depot/path
  122. MAPTOX_CLIENT, // //CLIENT/path
  123. MAPTOX_LOCAL, // C:\src\path
  124. };
  125. BOOL MapToXPath(LPCTSTR pszSD, String& strOut, MAPTOX X);
  126. inline BOOL MapToFullDepotPath(LPCTSTR pszSD, String& strOut)
  127. { return MapToXPath(pszSD, strOut, MAPTOX_DEPOT); }
  128. inline BOOL MapToClientPath(LPCTSTR pszSD, String& strOut)
  129. { return MapToXPath(pszSD, strOut, MAPTOX_CLIENT); }
  130. BOOL MapToLocalPath(LPCTSTR pszSD, String& strOut);
  131. void Help(HWND hwnd, LPCTSTR pszAnchor);
  132. BOOL SpawnProcess(LPTSTR pszCommand);
  133. void WindiffChangelist(int iChange);
  134. void WindiffOneChange(LPTSTR pszPath);
  135. int ParseBugNumber(LPCTSTR psz);
  136. int ParseBugNumberFromSubItem(HWND hwnd, int iItem, int iSubItem);
  137. void AdjustBugMenu(HMENU hmenu, int iBug, BOOL fContextMenu);
  138. void OpenBugWindow(HWND hwnd, int iBug);
  139. void JiggleMouse();
  140. HMENU LoadPopupMenu(LPCTSTR pszMenu);
  141. void MakeMenuPretty(HMENU hmenu);
  142. void EnableDisableOrRemoveMenuItem(HMENU hmenu, UINT id, BOOL fEnable, BOOL fDelete);
  143. void SetClipboardText(HWND hwnd, LPCTSTR psz);
  144. // SCHAR is the opposite of TCHAR
  145. #ifdef UNICODE
  146. typedef CHAR SCHAR;
  147. #else
  148. typedef WCHAR SCHAR;
  149. #endif
  150. typedef SCHAR *LPSSTR;
  151. typedef const SCHAR *LPCSSTR;
  152. /*****************************************************************************
  153. *
  154. * Change types
  155. *
  156. *****************************************************************************/
  157. enum {
  158. OP_UNKNOWN,
  159. OP_EDIT,
  160. OP_DELETE,
  161. OP_ADD,
  162. OP_INTEGRATE,
  163. OP_MERGE,
  164. OP_BRANCH,
  165. OP_COPY,
  166. OP_IGNORED,
  167. OP_MAX,
  168. };
  169. extern struct LogEntryImageMap {
  170. LPCTSTR _pszOp;
  171. int _iImage;
  172. } c_rgleim[];
  173. int ParseOp(LPCTSTR psz);
  174. /*****************************************************************************
  175. *
  176. * Assertion goo
  177. *
  178. *****************************************************************************/
  179. #ifdef DEBUG
  180. void AssertFailed(char *psz, char *pszFile, int iLine);
  181. #define ASSERT(f) ((f) || (AssertFailed(#f, __FILE__, __LINE__), 0))
  182. #else
  183. #define ASSERT sizeof
  184. #endif
  185. #define COMPILETIME_ASSERT(f) switch (0) case 0: case f:
  186. /*****************************************************************************
  187. *
  188. * Downlevel OS support (is this still needed?)
  189. *
  190. *****************************************************************************/
  191. #undef SUPPORT_DOWNLEVEL
  192. #ifdef SUPPORT_DOWNLEVEL
  193. typedef BOOL (WINAPI *QUEUEUSERWORKITEM)(LPTHREAD_START_ROUTINE, LPVOID, ULONG);
  194. typedef BOOL (WINAPI *ALLOWSETFOREGROUNDWINDOW)(DWORD);
  195. extern QUEUEUSERWORKITEM _QueueUserWorkItem;
  196. extern ALLOWSETFOREGROUNDWINDOW _AllowSetForegroundWindow;
  197. #else
  198. #define _QueueUserWorkItem QueueUserWorkItem
  199. #define _AllowSetForegroundWindow AllowSetForegroundWindow
  200. #endif
  201. /*****************************************************************************
  202. *
  203. * Ctype
  204. *
  205. *****************************************************************************/
  206. #define C_NONE 0x00
  207. #define C_SPACE 0x01
  208. #define C_DIGIT 0x02
  209. #define C_ALPHA 0x04
  210. #define C_DASH 0x08
  211. #define C_BRNCH 0x10
  212. #define B_DEFAULT C_NONE // Characters above 128 are this
  213. extern const BYTE c_rgbCtype[128];
  214. inline BOOL _InOrder(UINT tch1, UINT tch2, UINT tch3)
  215. {
  216. return tch2 - tch1 <= tch3 - tch1;
  217. }
  218. inline BOOL _Ctype(TCHAR tch, BYTE fl)
  219. {
  220. UINT ui = (UINT)tch;
  221. BYTE b;
  222. if (ui < ARRAYSIZE(c_rgbCtype)) {
  223. b = c_rgbCtype[ui];
  224. } else {
  225. b = B_DEFAULT;
  226. }
  227. return b & fl;
  228. }
  229. inline BOOL IsSpace(TCHAR tch)
  230. {
  231. return _Ctype(tch, C_SPACE);
  232. }
  233. inline BOOL IsDigit(TCHAR tch)
  234. {
  235. return _Ctype(tch, C_DIGIT);
  236. }
  237. inline BOOL IsNZDigit(TCHAR tch)
  238. {
  239. return _InOrder(TEXT('1'), tch, TEXT('9'));
  240. }
  241. inline BOOL IsAlpha(TCHAR tch)
  242. {
  243. return _Ctype(tch, C_ALPHA);
  244. }
  245. inline BOOL IsAlias(TCHAR tch)
  246. {
  247. return _Ctype(tch, C_DASH | C_DIGIT | C_ALPHA);
  248. }
  249. inline BOOL IsBranch(TCHAR tch)
  250. {
  251. return _Ctype(tch, C_DASH | C_DIGIT | C_ALPHA | C_BRNCH);
  252. }
  253. inline BOOL _IsPrint(TCHAR tch)
  254. {
  255. return _InOrder(TEXT(' '), tch, TEXT('~'));
  256. }
  257. #define _IsWord(ch) ((UINT)(ch) > TEXT(' '))
  258. /*****************************************************************************
  259. *
  260. * Commands
  261. *
  262. *****************************************************************************/
  263. extern DWORD CALLBACK CChanges_ThreadProc(LPVOID lpParameter);
  264. extern DWORD CALLBACK CDescribe_ThreadProc(LPVOID lpParameter);
  265. extern DWORD CALLBACK CFileLog_ThreadProc(LPVOID lpParameter);
  266. extern DWORD CALLBACK CFileOut_ThreadProc(LPVOID lpParameter);
  267. extern DWORD CALLBACK COpened_ThreadProc(LPVOID lpParameter);
  268. BOOL LaunchThreadTask(LPTHREAD_START_ROUTINE pfn, LPCTSTR pszArgs);
  269. /*****************************************************************************
  270. *
  271. * String, _String, OutputStringBuffer
  272. *
  273. * An extremely lame low-performance string class
  274. * Be careful what you do with it since you can't do much.
  275. *
  276. * _String is the base class that does the heavy lifting and shunts long
  277. * strings into the heap.
  278. *
  279. * String collects strings into a private buffer (which can overflow into
  280. * the heap).
  281. *
  282. * OutputStringBuffer collects strings into the buffer provided
  283. * (which can overflow into the heap). On destruction, copies the result
  284. * if necessary back to the buffer provided.
  285. *
  286. *****************************************************************************/
  287. class _String
  288. {
  289. public:
  290. explicit _String(LPTSTR pszBufOrig, UINT cchBufOrig);
  291. ~_String();
  292. void Reset();
  293. operator LPTSTR() const { return _pszBuf; }
  294. LPTSTR Buffer() const { return _pszBuf; }
  295. int BufferLength() const { return _cchBuf; }
  296. _String& operator<<(LPCTSTR psz) { Append(psz); return *this; }
  297. _String& operator<<(const _String& str) { Append(str); return *this; }
  298. _String& operator<<(int i);
  299. _String& operator<<(TCHAR tch);
  300. _String& operator=(LPCTSTR psz) { Reset(); Append(psz); return *this; }
  301. int Length() const { return _cchLen; }
  302. BOOL Append(LPCTSTR psz);
  303. BOOL Append(const _String& str) { return Append(str, str.Length()); }
  304. BOOL Append(LPCTSTR psz, int cchLen);
  305. BOOL Grow(int cchLen) { return Append(NULL, cchLen); }
  306. BOOL Ensure(int cchLen);
  307. void Trim(int cchTrim = 1) { _pszBuf[_cchLen -= cchTrim] = TEXT('\0'); }
  308. void SetLength(int cchLen) { ASSERT(_cchLen < _cchBuf); _cchLen = cchLen; }
  309. void Chomp();
  310. protected:
  311. LPTSTR OriginalBuffer() const { return _pszBufOrig; }
  312. private:
  313. // Disallow the default copy constructor and assignment operator.
  314. // Since our class has pointers, a block copy is never correct.
  315. _String(const _String&); // never defined
  316. _String& operator=(const _String&); // never defined
  317. LPTSTR _pszBuf;
  318. int _cchLen;
  319. int _cchBuf;
  320. LPTSTR _pszBufOrig;
  321. };
  322. class String : public _String
  323. {
  324. public:
  325. explicit String() : _String(_szBuf, ARRAYSIZE(_szBuf)) { }
  326. explicit String(LPCTSTR psz) : _String(_szBuf, ARRAYSIZE(_szBuf)) { Append(psz); }
  327. String& operator=(LPCTSTR psz) { _String::operator=(psz); return *this; }
  328. private:
  329. /* Almost all strings are smaller than this */
  330. TCHAR _szBuf[MAX_PATH];
  331. };
  332. class OutputStringBuffer : public _String
  333. {
  334. public:
  335. OutputStringBuffer(LPTSTR pszBuf, UINT cchBuf)
  336. : _String(pszBuf, cchBuf)
  337. , _cchBufOrig(cchBuf) { }
  338. ~OutputStringBuffer();
  339. private:
  340. int _cchBufOrig;
  341. };
  342. /*****************************************************************************
  343. *
  344. * Custom output formats for "str << blah"
  345. *
  346. *****************************************************************************/
  347. class _StringFormat {
  348. public:
  349. operator LPCTSTR() const { return _pszDepotPath; }
  350. _StringFormat(LPCTSTR pszDepotPath) : _pszDepotPath(pszDepotPath) { }
  351. protected:
  352. LPCTSTR _pszDepotPath;
  353. };
  354. #define MakeStringFormat(T) \
  355. class T : public _StringFormat { \
  356. public: \
  357. T(LPCTSTR pszDepotPath) : _StringFormat(pszDepotPath) { } \
  358. }; \
  359. _String& operator<<(_String& str, T t); \
  360. MakeStringFormat(QuoteSpaces)
  361. MakeStringFormat(BranchOf)
  362. MakeStringFormat(FilenameOf)
  363. MakeStringFormat(ResolveBranchAndQuoteSpaces)
  364. class StringResource {
  365. public:
  366. operator UINT() const { return _ids; }
  367. StringResource(UINT ids) : _ids(ids) { }
  368. protected:
  369. UINT _ids;
  370. };
  371. _String& operator<<(_String& str, StringResource sr);
  372. #define StringBeginsWith(psz, sz) (StrCmpN(psz, sz, ARRAYSIZE(sz) - 1) == 0)
  373. /*****************************************************************************
  374. *
  375. * StringCache is a class that babysits a string pointer.
  376. *
  377. * _StringCache is the version that requires explicit
  378. * construction/destruction. It is safe to use in global structures.
  379. *
  380. *****************************************************************************/
  381. struct _StringCache {
  382. public:
  383. _StringCache& operator=(LPCTSTR psz);
  384. BOOL IsEmpty() const { return _psz == NULL; }
  385. operator LPTSTR() const { return Value(); }
  386. LPTSTR Value() const { return IsEmpty() ? TEXT("") : _psz; }
  387. public:
  388. LPTSTR _psz;
  389. };
  390. class StringCache : public _StringCache
  391. {
  392. public:
  393. StringCache() { _psz = NULL; }
  394. StringCache(LPCTSTR psz) { _psz = NULL; *this = psz; }
  395. ~StringCache() { *this = NULL; }
  396. StringCache& operator=(LPCTSTR psz)
  397. { *SAFECAST(_StringCache*,this) = psz; return *this; }
  398. };
  399. /*
  400. * match.cpp - Highly-specialized depot path matching class
  401. */
  402. class Match {
  403. public:
  404. Match(LPCTSTR pszPattern);
  405. ~Match() { delete [] _pszzPats; }
  406. BOOL Matches(LPCTSTR pszPath);
  407. private:
  408. void _AddPattern(LPTSTR pszPat, String& strPats);
  409. BOOL _Matches(LPCTSTR pszPat, LPCTSTR pszPath);
  410. private:
  411. LPTSTR _pszzPats;
  412. LPTSTR _pszEnd;
  413. };
  414. /*
  415. * pipe.cpp
  416. */
  417. class ChildProcess
  418. {
  419. public:
  420. explicit ChildProcess() { Construct(); }
  421. explicit ChildProcess(LPCTSTR pszCommand) { Construct(); Start(pszCommand); }
  422. void Start(LPCTSTR pszCommand);
  423. ~ChildProcess() { Stop(); }
  424. BOOL IsRunning() const { return _dwPid; }
  425. HANDLE Handle() const { return _hRead; }
  426. void Kill();
  427. void Stop();
  428. private:
  429. void Construct()
  430. {
  431. _hProcess = NULL;
  432. _hRead = NULL;
  433. _dwPid = 0;
  434. }
  435. private:
  436. HANDLE _hRead;
  437. HANDLE _hProcess;
  438. DWORD _dwPid;
  439. };
  440. class SDChildProcess : public ChildProcess
  441. {
  442. public:
  443. explicit SDChildProcess(LPCTSTR pszCommand);
  444. };
  445. /*
  446. * buffer.cpp
  447. */
  448. class IOBuffer
  449. {
  450. public:
  451. IOBuffer(HANDLE hRead) { Init(hRead); }
  452. void Init(HANDLE hRead) { _hRead = hRead; _cchBufUsed = 0; }
  453. BOOL NextLine(String &);
  454. private:
  455. enum {
  456. _cchBuf = MAX_PATH,
  457. };
  458. HANDLE _hRead;
  459. TCHAR _rgchBuf[_cchBuf];
  460. int _cchBufUsed; /* Number of bytes already in buffer */
  461. };
  462. /*****************************************************************************
  463. *
  464. * LVInfoTip - lvframe.cpp
  465. *
  466. * Special hack class to support extra-long infotips in listview.
  467. *
  468. *****************************************************************************/
  469. class LVInfoTip
  470. {
  471. public:
  472. void Attach(HWND hwnd);
  473. ~LVInfoTip() { FreeLastTipAlt(); }
  474. void SetInfoTip(NMLVGETINFOTIP *pgit, LPCTSTR pszTip);
  475. private:
  476. void FreeLastTipAlt();
  477. BOOL ThunkLastTip();
  478. static LRESULT SubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  479. static LPCTSTR GetSubclassProperty() { return TEXT("LVInfoTip"); }
  480. private:
  481. WNDPROC _wndprocPrev;
  482. BOOL _fGotInfoTip;
  483. LPCTSTR _pszLastTip;
  484. LPSSTR _pszLastTipAlt;
  485. };
  486. /*****************************************************************************
  487. *
  488. * TreeList - treelist.cpp
  489. *
  490. * A tree-like listview.
  491. *
  492. *****************************************************************************/
  493. /*
  494. * We maintain our own tree structure and add/delete items in the
  495. * listview as necessary as tree nodes are expanded/collapsed.
  496. */
  497. #define PTI_ONDEMAND RECAST(TreeItem*, -1)
  498. #define PTI_APPEND RECAST(TreeItem*, -1)
  499. class TreeItem {
  500. public:
  501. TreeItem * Parent() const { return _ptiParent; }
  502. TreeItem * NextSibling() const { return _ptiNext; }
  503. TreeItem * FirstChild() const { return _ptiChild; }
  504. TreeItem * NextVisible();
  505. BOOL IsExpanded() const { return _cVisKids > 0; }
  506. BOOL IsExpandable() const { return _ptiChild != NULL; }
  507. BOOL IsVisible();
  508. BOOL IsVisibleOrRoot();
  509. void SetExpandable() { SetFirstChild(PTI_ONDEMAND); }
  510. void SetNotExpandable() { SetFirstChild(NULL); }
  511. private:
  512. friend class Tree;
  513. BOOL IsSentinel() const { return this == NULL || this == PTI_ONDEMAND; }
  514. void SetFirstChild(TreeItem *pti) { ASSERT(_ptiChild->IsSentinel()); _ptiChild = pti; }
  515. private:
  516. TreeItem * _ptiParent;
  517. TreeItem * _ptiNext;
  518. TreeItem * _ptiChild;
  519. int _iDepth;
  520. int _iVisIndex;
  521. int _cVisKids;
  522. };
  523. #define TLN_GETDISPINFO 100 // Get pszText/cchTextMax given pti/iSubItem
  524. #define TLN_FILLCHILDREN 101 // Fill children of pti
  525. #define TLN_ITEMACTIVATE 102 // Default action on pti
  526. #define TLN_GETINFOTIP 103 // Get pszText/cchTextMax given pti
  527. #define TLN_DELETEITEM 104 // Destruct the node
  528. #define TLN_GETCONTEXTMENU 105 // Display a context menu
  529. struct NMTREELIST {
  530. NMHDR hdr;
  531. TreeItem *pti;
  532. int iSubItem;
  533. LPTSTR pszText;
  534. int cchTextMax; // Doubles as state
  535. };
  536. class Tree {
  537. public:
  538. Tree(TreeItem *ptiRoot);
  539. ~Tree();
  540. TreeItem* GetRoot() { return _ptiRoot; }
  541. BOOL Insert(TreeItem *pti, TreeItem *ptiParent, TreeItem *ptiAfter);
  542. void SetHWND(HWND hwnd);
  543. int Expand(TreeItem *pti);
  544. int Collapse(TreeItem *pti);
  545. int ToggleExpand(TreeItem *pti);
  546. void RedrawItem(TreeItem *pti);
  547. TreeItem *GetCurSel();
  548. void SetCurSel(TreeItem *pti);
  549. HIMAGELIST SetImageList(HIMAGELIST himl);
  550. public: //$$// make these protected someday
  551. LRESULT OnGetDispInfo(NMLVDISPINFO *plvd);
  552. LRESULT OnCacheHint(NMLVCACHEHINT *phint);
  553. LRESULT OnItemActivate(int iItem);
  554. LRESULT OnKeyDown(NMLVKEYDOWN *pkd);
  555. LRESULT OnClick(NMITEMACTIVATE *pia);
  556. LRESULT OnGetInfoTip(NMLVGETINFOTIP *pgit);
  557. LRESULT OnGetContextMenu(int iItem);
  558. LRESULT OnCopyToClipboard(int iMin, int iMax);
  559. private:
  560. void Recalc(TreeItem *pti);
  561. void UpdateCache(TreeItem *pti, int iItem);
  562. LRESULT SendNotify(int code, NMHDR *pnm);
  563. TreeItem* IndexToItem(int iItem);
  564. int InsertListviewItem(int iItem);
  565. void UpdateVisibleCounts(TreeItem *pti, int cDelta);
  566. void DeleteNode(TreeItem *pti);
  567. void SendDeleteNotify(TreeItem *pti);
  568. private:
  569. HWND _hwnd;
  570. TreeItem* _ptiRoot;
  571. int _iHint;
  572. TreeItem* _ptiHint;
  573. };
  574. /*****************************************************************************
  575. *
  576. * FrameWindow - window.cpp
  577. *
  578. * A window that frames an inner control. The inner control is resized
  579. * to fill the client area.
  580. *
  581. *****************************************************************************/
  582. #define FW_MSG(msg) case msg: return ON_##msg(uiMsg, wParam, lParam)
  583. class NO_VTABLE FrameWindow {
  584. public:
  585. static DWORD RunThread(FrameWindow *self, LPVOID lpParameter);
  586. protected:
  587. void SetAcceleratorTable(LPCTSTR pszAccel)
  588. {
  589. _haccel = LoadAccelerators(g_hinst, pszAccel);
  590. }
  591. BOOL SetWindowMenu(LPCTSTR pszMenu)
  592. {
  593. return SetMenu(_hwnd, LoadMenu(g_hinst, pszMenu));
  594. }
  595. virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  596. virtual ~FrameWindow() { }
  597. //
  598. // For talking back to yourself (typically from a base class back
  599. // to a derived class). Short-circuits the WndProc wrapper for
  600. // perf. Do not use cross-thread!
  601. //
  602. LRESULT SendSelfMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  603. {
  604. return HandleMessage(uMsg, wParam, lParam);
  605. }
  606. private:
  607. static LRESULT CALLBACK WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  608. HWND CreateFrameWindow();
  609. protected:
  610. HWND _hwnd;
  611. HWND _hwndChild;
  612. HACCEL _haccel;
  613. LPTSTR _pszQuery;
  614. };
  615. /*****************************************************************************
  616. *
  617. * LVFrame - lvframe.cpp
  618. *
  619. * A FrameWindow that frames a listview in report mode.
  620. *
  621. *****************************************************************************/
  622. #define LM_ITEMACTIVATE (WM_USER + 100) // wParam = iItem
  623. #define LM_GETINFOTIP (WM_USER + 101) // wParam = iItem, lParam -> NMLVGETINFOTIP
  624. #define LM_GETCONTEXTMENU (WM_USER + 102) // wParam = iItem
  625. #define LM_COPYTOCLIPBOARD (WM_USER + 103) // wParam = iMin, lParam = iMax (exclusive)
  626. #define LM_DELETEITEM (WM_USER + 104) // wParam = iItem, lParam = lParam
  627. typedef struct LVFCOLUMN {
  628. UINT cch;
  629. UINT ids;
  630. UINT fmt;
  631. } LVFCOLUMN;
  632. class NO_VTABLE LVFrame : public FrameWindow {
  633. typedef FrameWindow super;
  634. protected:
  635. enum { IDC_LIST = 1 };
  636. BOOL CreateChild(DWORD dwStyle, DWORD dwExStyle);
  637. BOOL AddColumns(const LVFCOLUMN *rgcol);
  638. void *GetLVItem(int iItem);
  639. int GetCurSel() { return ListView_GetCurSel(_hwndChild); }
  640. LRESULT HandleMessage(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  641. private:
  642. LRESULT ON_WM_NOTIFY(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  643. LRESULT ON_WM_COMMAND(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  644. LRESULT ON_WM_CONTEXTMENU(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  645. private:
  646. LVInfoTip _it;
  647. };
  648. /*****************************************************************************
  649. *
  650. * TLFrame - tlframe.cpp
  651. *
  652. * Wraps the Tree class. If I were less lazy, I would merge it into
  653. * this class, but right now Tree is a separate class because I stole
  654. * the code from sdflog...
  655. *
  656. *****************************************************************************/
  657. class NO_VTABLE TLFrame : public LVFrame {
  658. typedef LVFrame super;
  659. protected:
  660. TLFrame(TreeItem *ptiRoot) : _tree(ptiRoot) { }
  661. LRESULT HandleMessage(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  662. BOOL CreateChild(DWORD dwStyle, DWORD dwExStyle);
  663. TreeItem *TLGetCurSel() { return _tree.GetCurSel(); };
  664. private:
  665. LRESULT ON_WM_NOTIFY(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  666. LRESULT ON_LM_ITEMACTIVATE(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  667. LRESULT ON_LM_GETINFOTIP(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  668. LRESULT ON_LM_GETCONTEXTMENU(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  669. LRESULT ON_LM_COPYTOCLIPBOARD(UINT uiMsg, WPARAM wParam, LPARAM lParam);
  670. protected:
  671. Tree _tree;
  672. };
  673. /*****************************************************************************
  674. *
  675. * BGTask
  676. *
  677. *****************************************************************************/
  678. class BGTask
  679. {
  680. protected:
  681. BGTask() : _hDone(CreateEvent(NULL, TRUE, TRUE, NULL)), _fPending(FALSE) { }
  682. BOOL BGConstructed() const { return _hDone != NULL; }
  683. BOOL BGTaskPending() const { return _fPending; }
  684. ~BGTask();
  685. BOOL BGStartTask(LPTHREAD_START_ROUTINE pfn, LPVOID Context);
  686. void BGEndTask();
  687. LRESULT BGFilterSetCursor(LRESULT lres);
  688. private:
  689. BOOL _fPending;
  690. HANDLE _hDone;
  691. };
  692. /*****************************************************************************
  693. *
  694. * Parser
  695. *
  696. *****************************************************************************/
  697. class Substring
  698. {
  699. public:
  700. LPTSTR _pszMin; // First character of the substring
  701. LPTSTR _pszMax; // One past the last character of the substring
  702. explicit Substring() { }
  703. explicit Substring(LPCTSTR pszMin, LPCTSTR pszMax)
  704. : _pszMin(CCAST(LPTSTR, pszMin)),
  705. _pszMax(CCAST(LPTSTR, pszMax)) { }
  706. LPTSTR SetStart(LPCTSTR psz)
  707. {
  708. return _pszMin = CCAST(LPTSTR, psz);
  709. }
  710. LPTSTR Start() { return _pszMin; }
  711. SIZE_T Length() const { return _pszMax - _pszMin; }
  712. SIZE_T SetEnd(LPCTSTR psz)
  713. {
  714. _pszMax = CCAST(LPTSTR, psz);
  715. return Length();
  716. }
  717. LPTSTR Finalize() // This method works only on mutable substrings
  718. {
  719. *_pszMax = TEXT('\0');
  720. return _pszMin;
  721. }
  722. };
  723. LPTSTR Parse(LPCTSTR pszFormat, LPCTSTR pszParse, Substring *rgss);
  724. inline _String& operator<<(_String& str, Substring ss)
  725. {
  726. str.Append(ss._pszMin, (int)(ss._pszMax - ss._pszMin));
  727. return str;
  728. }
  729. /*****************************************************************************
  730. *
  731. * CommentParser - Parses checkin comments
  732. *
  733. *****************************************************************************/
  734. class NO_VTABLE CommentParser {
  735. public:
  736. virtual void SetDev(LPCTSTR psz) = 0;
  737. virtual void SetComment(LPCTSTR psz) = 0;
  738. void Reset() { _fHaveComment = FALSE; }
  739. void AddComment(LPTSTR psz);
  740. CommentParser() { Reset(); }
  741. private:
  742. BOOL _fHaveComment;
  743. };
  744. /*****************************************************************************
  745. *
  746. * Tokenizer
  747. *
  748. *****************************************************************************/
  749. class Tokenizer
  750. {
  751. public:
  752. explicit Tokenizer() { }
  753. explicit Tokenizer(LPCTSTR psz) { Restart(psz); }
  754. void Restart(LPCTSTR psz);
  755. LPCTSTR Unparsed() const { return _psz; }
  756. BOOL Token(String& str);
  757. BOOL Finished() const { return !*_psz; }
  758. private:
  759. LPCTSTR _psz;
  760. };
  761. /*****************************************************************************
  762. *
  763. * GetOpt
  764. *
  765. * pszParams is the list of switches that take parameters. By default,
  766. * switches do not take parameters.
  767. *
  768. *****************************************************************************/
  769. class GetOpt
  770. {
  771. public:
  772. GetOpt(LPCTSTR pszParams, LPCTSTR pszArg)
  773. : _pszParams(pszParams), _pszUnparsed(NULL), _tok(pszArg) { }
  774. TCHAR NextSwitch();
  775. BOOL Token() { return _tok.Token(_str); }
  776. BOOL Finished() { return _tok.Finished(); }
  777. LPCTSTR GetValue() const { return _pszValue; }
  778. Tokenizer GetTokenizer() const { return _tok; }
  779. private:
  780. LPCTSTR _pszParams;
  781. LPTSTR _pszUnparsed;
  782. LPTSTR _pszValue;
  783. Tokenizer _tok;
  784. String _str;
  785. };
  786. /*****************************************************************************
  787. *
  788. * WaitCursor
  789. *
  790. *****************************************************************************/
  791. class WaitCursor
  792. {
  793. public:
  794. explicit WaitCursor() : _hcur(SetCursor(g_hcurWait)) { }
  795. ~WaitCursor() { SetCursor(_hcur); }
  796. private:
  797. HCURSOR _hcur;
  798. };
  799. /*****************************************************************************
  800. *
  801. * Annoying version-checking functions
  802. *
  803. *****************************************************************************/
  804. inline BOOL VER1GE(UINT A,
  805. UINT a)
  806. { return A >= a; }
  807. inline BOOL VER2GE(UINT A, UINT B,
  808. UINT a, UINT b)
  809. { return A > a || (A == a && VER1GE(B,b)); }
  810. inline BOOL VER3GE(UINT A, UINT B, UINT C,
  811. UINT a, UINT b, UINT c)
  812. { return A > a || (A == a && VER2GE(B,C,b,c)); }
  813. inline BOOL VER4GE(UINT A, UINT B, UINT C, UINT D,
  814. UINT a, UINT b, UINT c, UINT d)
  815. { return A > a || (A == a && VER3GE(B,C,D,b,c,d)); }
  816. /*****************************************************************************
  817. *
  818. * Globals
  819. *
  820. *****************************************************************************/
  821. struct CGlobals
  822. {
  823. public:
  824. void Initialize();
  825. BOOL IsChurnEnabled() const { return _fChurn; }
  826. const _StringCache& GetSdOpts() const { return _pszSdOpts; }
  827. const _StringCache& GetUserName() const { return _rgpszSettings[SETTING_USERNAME]; }
  828. const _StringCache& GetClientName() const { return _rgpszSettings[SETTING_CLIENTNAME]; }
  829. const _StringCache& GetClientRoot() const { return _rgpszSettings[SETTING_CLIENTROOT]; }
  830. const _StringCache& GetFakeDir() const { return _pszFakeDir; }
  831. const _StringCache& GetLocalRoot() const { return _pszLocalRoot; }
  832. LPCTSTR GetSdPath() const { return _szSd; }
  833. String& FormatBugUrl(String& str, int iBug) const
  834. {
  835. str << _pszBugPagePre << iBug << _pszBugPagePost;
  836. return str;
  837. }
  838. void SetChurn(BOOL fChurn) { _fChurn = fChurn; }
  839. void SetSdOpts(LPCTSTR psz) { _pszSdOpts = psz; }
  840. BOOL IsVersion(UINT major) { return VER1GE(_Major(), major); }
  841. BOOL IsVersion(UINT major, UINT minor)
  842. { return VER2GE(_Major(), _Minor(), major, minor); }
  843. private:
  844. void _InitSdPath();
  845. void _InitInfo();
  846. void _InitFakeDir();
  847. void _InitServerVersion();
  848. void _InitBugPage();
  849. UINT _Major() { return _rguiVer[VERSION_MAJOR]; }
  850. UINT _Minor() { return _rguiVer[VERSION_MINOR]; }
  851. enum {
  852. SETTING_USERNAME,
  853. SETTING_CLIENTNAME,
  854. SETTING_CLIENTROOT,
  855. SETTING_LOCALDIR,
  856. SETTING_SERVERVERSION,
  857. SETTING_MAX
  858. };
  859. enum {
  860. VERSION_MAJOR,
  861. VERSION_MINOR,
  862. VERSION_BUILD,
  863. VERSION_QFE,
  864. VERSION_MAX,
  865. };
  866. private:
  867. BOOL _fChurn;
  868. _StringCache _pszSdOpts;
  869. _StringCache _pszLocalRoot;
  870. _StringCache _pszFakeDir;
  871. _StringCache _pszBugPagePre;
  872. _StringCache _pszBugPagePost;
  873. _StringCache _rgpszSettings[SETTING_MAX];
  874. UINT _rguiVer[VERSION_MAX];
  875. TCHAR _szSd[MAX_PATH];
  876. };
  877. extern CGlobals GlobalSettings;
  878. #endif