Source code of Windows XP (NT5)
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.

581 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: cclvctl.h
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef _CCLVCTL_H_
  11. #define _CCLVCTL_H_
  12. // cclvctl.h : header file
  13. //
  14. #include <objbase.h>
  15. #include <atlbase.h>
  16. #include <atlcom.h>
  17. #include "imagemap.h"
  18. #include "ndmgr.h"
  19. #include "fontlink.h"
  20. #include "amcnav.h"
  21. #include "dd.h"
  22. #include "columninfo.h"
  23. // Don't let macro override CWnd method
  24. #undef SubclassWindow
  25. class CAMCView;
  26. class CCCListViewCtrl;
  27. class CResultItem;
  28. class CListFontLinker : public CFontLinker
  29. {
  30. public:
  31. CListFontLinker (CCCListViewCtrl* pListCtrl) : m_pListCtrl (pListCtrl)
  32. { ASSERT (m_pListCtrl != NULL); }
  33. protected:
  34. virtual bool IsAnyItemLocalizable () const;
  35. virtual std::wstring GetItemText (NMCUSTOMDRAW* pnmcd) const;
  36. private:
  37. CCCListViewCtrl* const m_pListCtrl;
  38. };
  39. class CSysColorImageList : public CImageList
  40. {
  41. public:
  42. CSysColorImageList (HINSTANCE hInst, UINT nID)
  43. : m_hInst (hInst),
  44. m_hRsrc (::FindResource (m_hInst, MAKEINTRESOURCE (nID), RT_BITMAP))
  45. {
  46. CreateSysColorImageList();
  47. }
  48. void OnSysColorChange ()
  49. {
  50. DeleteImageList();
  51. CreateSysColorImageList();
  52. }
  53. operator HIMAGELIST() const
  54. {
  55. return (CImageList::operator HIMAGELIST());
  56. }
  57. private:
  58. void CreateSysColorImageList ()
  59. {
  60. CBitmap bmp;
  61. bmp.Attach (AfxLoadSysColorBitmap (m_hInst, m_hRsrc));
  62. /*
  63. * get the dimensions of the bitmap
  64. */
  65. BITMAP bm;
  66. bmp.GetBitmap (&bm);
  67. /*
  68. * assume square images (cx == cy)
  69. */
  70. Create (bm.bmHeight, bm.bmHeight, ILC_COLORDDB, bm.bmWidth / bm.bmHeight, 2);
  71. Add (&bmp, CLR_NONE);
  72. }
  73. HINSTANCE m_hInst;
  74. HRSRC m_hRsrc;
  75. };
  76. class CAMCHeaderCtrl : public CHeaderCtrl
  77. {
  78. public:
  79. bool IsColumnHidden(int iCol);
  80. protected:
  81. afx_msg void OnSetFocus(CWnd *pOldWnd);
  82. afx_msg BOOL OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message );
  83. DECLARE_MESSAGE_MAP()
  84. };
  85. class CFocusHandler
  86. {
  87. public:
  88. virtual void OnKeyboardFocus(UINT nState, UINT nStateMask) = 0;
  89. };
  90. /////////////////////////////////////////////////////////////////////////////
  91. // CAMCListView
  92. class CAMCListView :
  93. public CListView,
  94. public CAMCNavigator,
  95. public CFocusHandler,
  96. public CMMCViewDropTarget,
  97. public CEventSource<CListViewActivationObserver>
  98. {
  99. // Construction
  100. public:
  101. CAMCListView() :
  102. m_bVirtual(false),
  103. m_iDropTarget(-1),
  104. m_pAMCView(NULL),
  105. m_bColumnsNeedToBeRestored(true),
  106. m_bColumnsBeingRestored(false)
  107. {
  108. DEBUG_INCREMENT_INSTANCE_COUNTER(CAMCListView);
  109. }
  110. ~CAMCListView()
  111. {
  112. if (m_header.m_hWnd)
  113. m_header.UnsubclassWindow();
  114. DEBUG_DECREMENT_INSTANCE_COUNTER(CAMCListView);
  115. }
  116. // CFocusHandler implementation
  117. virtual void OnKeyboardFocus(UINT nState, UINT nStateMask);
  118. // CAMCNavigator implementation
  119. virtual BOOL ChangePane(AMCNavDir eDir);
  120. virtual BOOL TakeFocus(AMCNavDir eDir);
  121. SC ScOnColumnsAttributeChanged(NMHEADER *pNMHeader, UINT code);
  122. // Setup header width/order/hiddenness from columninfolist data.
  123. SC ScRestoreColumnsFromPersistedData();
  124. SC ScGetColumnInfoList(CColumnInfoList *pColumnsList);
  125. SC ScModifyColumns(const CColumnInfoList& colInfoList);
  126. SC ScSaveColumnInfoList();
  127. SC ScGetDefaultColumnInfoList(CColumnInfoList& columnsList);
  128. SC ScResetColumnStatusData();
  129. // Overrides
  130. // ClassWizard generated virtual function overrides
  131. //{{AFX_VIRTUAL(CAMCListView)
  132. public:
  133. virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
  134. virtual BOOL OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo );
  135. protected:
  136. virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
  137. virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
  138. //}}AFX_VIRTUAL
  139. public:
  140. virtual SC ScDropOnTarget(bool bHitTestOnly, IDataObject * pDataObject, CPoint pt, bool& bCopyOperation);
  141. virtual void RemoveDropTargetHiliting();
  142. void SetVirtual()
  143. {
  144. m_bVirtual = true;
  145. }
  146. bool IsInLargeIconMode() const
  147. {
  148. return (GetMode() == LVS_ICON);
  149. }
  150. bool IsInSmallIconMode() const
  151. {
  152. return (GetMode() == LVS_SMALLICON);
  153. }
  154. bool IsInListMode() const
  155. {
  156. return (GetMode() == LVS_LIST);
  157. }
  158. bool IsInReportMode() const
  159. {
  160. return (GetMode() == LVS_REPORT);
  161. }
  162. bool IsInFilteredReportMode() const
  163. {
  164. if (!IsInReportMode())
  165. return (false);
  166. CWnd* pwndHeader = GetHeaderCtrl();
  167. if (pwndHeader == NULL)
  168. return (false);
  169. return (pwndHeader->GetStyle() & HDS_FILTERBAR);
  170. }
  171. DWORD SetExtendedListViewStyle (DWORD dwExStyle, DWORD dwExMask = 0)
  172. {
  173. return (SendMessage (LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle));
  174. }
  175. CAMCView* GetAMCView() const
  176. {
  177. return (m_pAMCView);
  178. }
  179. CAMCHeaderCtrl* GetHeaderCtrl() const;
  180. bool AreColumnsNeedToBeRestored() const { return m_bColumnsNeedToBeRestored;}
  181. void SetColumnsNeedToBeRestored(bool b = false) {m_bColumnsNeedToBeRestored = b;}
  182. bool IsColumnHidden(int iCol) const;
  183. protected:
  184. //{{AFX_MSG(CAMCListView)
  185. afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  186. afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
  187. afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  188. afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  189. afx_msg void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags);
  190. afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
  191. afx_msg void OnBeginRDrag(NMHDR* pNMHDR, LRESULT* pResult);
  192. afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
  193. afx_msg void OnSetFocus(CWnd* pOldWnd);
  194. afx_msg void OnPaint();
  195. afx_msg void OnSize(UINT nType, int cx, int cy);
  196. afx_msg void OnBeginTrack(NMHDR * pNotifyStruct, LRESULT * result);
  197. //}}AFX_MSG
  198. afx_msg LRESULT OnColumnPersistedDataChanged (WPARAM, LPARAM);
  199. DECLARE_MESSAGE_MAP()
  200. private:
  201. bool m_bVirtual;
  202. CAMCView* m_pAMCView;
  203. mutable CAMCHeaderCtrl m_header; // mutable so GetHeaderCtrl can call CWnd::SubclassWindow
  204. int m_iDropTarget;
  205. CColumnInfoList m_defaultColumnInfoList;
  206. INodeCallback* GetNodeCallback();
  207. HNODE GetScopePaneSelNode();
  208. void SelectDropTarget(int iDropTarget);
  209. bool ActivateSelf (bool fNotify = true);
  210. bool NeedsCustomPaint ();
  211. SC ScGetDropTarget(const CPoint& point, HNODE& hNode, bool& bScope, LPARAM& lvData, int& iDrop);
  212. DWORD GetMode () const
  213. {
  214. return (GetStyle() & LVS_TYPEMASK);
  215. }
  216. private:
  217. // For columns
  218. static const UINT m_nColumnPersistedDataChangedMsg;
  219. // To allow hidden column width changes.
  220. bool m_bColumnsBeingRestored;
  221. // We dont care if restore is success or failure.
  222. bool m_bColumnsNeedToBeRestored;
  223. };
  224. /////////////////////////////////////////////////////////////////////////////
  225. // CCCListViewCtrl window
  226. class CCCListViewCtrl :
  227. public IMMCListView,
  228. public CComObjectRoot,
  229. public CEventSource<CListViewObserver>,
  230. public CTiedObject
  231. {
  232. // Construction
  233. public:
  234. CCCListViewCtrl();
  235. virtual ~CCCListViewCtrl();
  236. // initialization
  237. SC ScInitialize();
  238. BEGIN_COM_MAP(CCCListViewCtrl)
  239. COM_INTERFACE_ENTRY(IMMCListView)
  240. END_COM_MAP()
  241. typedef struct _SortParams
  242. {
  243. BOOL bAscending; // sort direction
  244. BOOL bLexicalSort; // apply default sort to all items
  245. int nCol; // Which column to sort on.
  246. COMPONENTID OwnerID;
  247. void * lpListView; // CCCListViewCtrl *
  248. IResultDataComparePtr spResultCompare; // Snap-in component interface
  249. IResultDataCompareExPtr spResultCompareEx; // "
  250. LPNODECALLBACK lpNodeCallback;
  251. LPARAM lpUserParam; // parameter user passes in
  252. HNODE hSelectedNode; // Currently selected node in scope pane.
  253. } SortParams;
  254. //DECLARE_AGGREGATABLE(CCCListViewCtrl)
  255. //DECLARE_REGISTRY(CNodeInitObject, _T("NODEMGR.NodeInitObject.1"), _T("NODEMGR.NodeInitObject.1"), IDS_NODEINIT_DESC, THREADFLAGS_BOTH)
  256. // Operations
  257. public:
  258. #ifdef IMPLEMENT_LIST_SAVE // See nodemgr.idl (t-dmarm)
  259. long GetColCount() const { return m_colCount; }
  260. long GetItemCount() const { return m_itemCount; }
  261. #endif
  262. CAMCListView* GetListViewPtr() const { return m_pListView; }
  263. CListCtrl& GetListCtrl() const { return m_pListView->GetListCtrl(); }
  264. CAMCHeaderCtrl* GetHeaderCtrl() const { return m_pListView->GetHeaderCtrl(); }
  265. bool AreColumnsNeedToBeRestored() const { return m_pListView->AreColumnsNeedToBeRestored();}
  266. void SetColumnsNeedToBeRestored(bool b = true) {m_pListView->SetColumnsNeedToBeRestored(b);}
  267. bool IsColumnHidden(int iCol) const {return m_pListView->IsColumnHidden(iCol);}
  268. SC ScGetAMCView(CAMCView **ppAMCView);
  269. HWND GetListViewHWND() const { return m_pListView->GetSafeHwnd(); }
  270. BOOL IsVirtual() const { return m_bVirtual; }
  271. BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext=NULL);
  272. SC ScAttachToListPad (HWND hwnd, HWND* phwnd); // NULL hwnd == detach
  273. BOOL IsListPad () const { return m_SavedHWND != NULL; }
  274. LRESULT OnCustomDraw (NMLVCUSTOMDRAW* plvcd);
  275. void OnSysColorChange();
  276. // IMMCListView Methods
  277. STDMETHOD(GetListStyle) ();
  278. STDMETHOD(SetListStyle) (long nNewValue);
  279. STDMETHOD(GetViewMode) ();
  280. STDMETHOD(SetViewMode) (long nViewMode);
  281. STDMETHOD(InsertItem) (LPOLESTR str, long iconNdx, LPARAM lParam, long state, COMPONENTID ownerID, long itemIndex, CResultItem*& pri);
  282. STDMETHOD(DeleteItem) (HRESULTITEM itemID, long nCol);
  283. STDMETHOD(FindItemByLParam) (COMPONENTID ownerID, LPARAM lParam, CResultItem*& pri);
  284. STDMETHOD(InsertColumn) (int nCol, LPCOLESTR str, long nFormat, long width);
  285. STDMETHOD(DeleteColumn) (int nCol);
  286. STDMETHOD(DeleteAllItems) (COMPONENTID ownerID);
  287. STDMETHOD(SetColumn) (long nCol, LPCOLESTR str, long nFormat, long width);
  288. STDMETHOD(GetColumn) (long nCol, LPOLESTR* str, LPLONG nFormat, int FAR* width);
  289. STDMETHOD(GetColumnCount) (int* pnColCnt);
  290. STDMETHOD(SetItem) (int nIndex, CResultItem* pri, long nCol, LPOLESTR str, long nImage, LPARAM lParam, long nState, COMPONENTID ownerID);
  291. STDMETHOD(GetItem) (int nIndex, CResultItem*& pri, long nCol, LPOLESTR* str, int FAR *nImage, LPARAM* lParam, unsigned int FAR *nState, BOOL* pbScopeItem);
  292. STDMETHOD(GetNextItem) (COMPONENTID ownerID, long nIndex, UINT nState, CResultItem*& pri, long& nIndexNextItem);
  293. STDMETHOD(GetLParam) (long nItem, CResultItem*& pri);
  294. STDMETHOD(ModifyItemState) (long nItem, CResultItem* pri, UINT add, UINT remove);
  295. STDMETHOD(SetIcon) (long nID, HICON hIcon, long nLoc);
  296. STDMETHOD(SetImageStrip) (long nID, HBITMAP hbmSmall, HBITMAP hbmLarge, long nStartLoc, long cMask);
  297. STDMETHOD(MapImage) (COMPONENTID nID, long nLoc, int far *pResult);
  298. STDMETHOD(Reset) ();
  299. STDMETHOD(Arrange) (long style);
  300. STDMETHOD(UpdateItem) (HRESULTITEM itemID);
  301. STDMETHOD(Sort) (LPARAM lUserParam, long* lpParams);
  302. STDMETHOD(SetItemCount) (int nItemCount, DWORD dwOptions);
  303. STDMETHOD(SetVirtualMode) (BOOL bVirtual);
  304. STDMETHOD(Repaint) (BOOL bErase);
  305. STDMETHOD(SetChangeTimeOut) (ULONG lTimeout);
  306. STDMETHOD(SetColumnFilter) (int nCol, DWORD dwType, MMC_FILTERDATA* pFilterData);
  307. STDMETHOD(GetColumnFilter) (int nCol, DWORD* dwType, MMC_FILTERDATA* pFilterData);
  308. STDMETHOD(SetColumnSortIcon) (int nNewCol, int nOldCol, BOOL bAscending, BOOL bSetSortIcon);
  309. STDMETHOD(SetLoadMode) (BOOL bState);
  310. STDMETHOD(GetColumnInfoList) (CColumnInfoList *pColumnsList);
  311. STDMETHOD(ModifyColumns) (const CColumnInfoList& columnsList);
  312. STDMETHOD(RenameItem) (HRESULTITEM itemID);
  313. STDMETHOD(GetDefaultColumnInfoList)( CColumnInfoList& columnsList);
  314. STDMETHOD(OnModifyItem)(CResultItem* pri);
  315. void CutSelectedItems(BOOL b);
  316. bool UseFontLinking() const;
  317. UINT GetSelectedCount()
  318. { return (GetListCtrl().GetSelectedCount()); }
  319. // these methods implement access to enumerations for AMCView
  320. SC Scget_ListItems( PPNODES ppNodes );
  321. SC Scget_SelectedItems( PPNODES ppNodes);
  322. SC ScSelect( PNODE pNode);
  323. SC ScDeselect( PNODE pNode);
  324. SC ScIsSelected( PNODE pNode, PBOOL pIsSelected);
  325. SC ScSelectAll();
  326. // method used from Nodes collections
  327. SC ScValidateItem( int iItem, bool &bScopeNode );
  328. // method transfering requests from Nodes to AMCView (for scope nodes only)
  329. SC ScGetScopeNodeForItem ( int iItem, PPNODE ppNode );
  330. // Columns access methods
  331. SC Scget_Columns( PPCOLUMNS Columns );
  332. SC ScItem( long Index, PPCOLUMN ppColumn );
  333. SC Scget_Count( PLONG pCount );
  334. SC ScEnumNext(int &pos, PDISPATCH & pDispatch); // should return the next element.
  335. SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, int &pos);
  336. SC ScEnumReset(int &pos);
  337. // methods called from Column instances
  338. SC ScName( /*[out, retval]*/ BSTR *Name, int iColIndex );
  339. SC Scget_Width( /*[out, retval]*/ PLONG Width, int iColIndex );
  340. SC Scput_Width( /*[in]*/ long Width, int iColIndex );
  341. SC Scget_DisplayPosition( /*[out, retval]*/ PLONG DisplayPosition, int iColIndex );
  342. SC Scput_DisplayPosition( /*[in]*/ long Index, int iColIndex );
  343. SC Scget_Hidden( /*[out, retval]*/ PBOOL Hidden, int iColIndex );
  344. SC Scput_Hidden( /*[in]*/ BOOL Hidden , int iColIndex );
  345. SC ScSetAsSortColumn( /*[in]*/ ColumnSortOrder SortOrder, int iColIndex );
  346. SC ScIsSortColumn( PBOOL IsSortColumn, int iColIndex );
  347. // Column/Columns implementation helpers
  348. struct ColumnData
  349. {
  350. int iColumnWidth;
  351. int iColumnOrder;
  352. bool bIsHidden;
  353. // initialization
  354. void Init() { iColumnWidth = 0; iColumnOrder = -1; bIsHidden = false; }
  355. ColumnData() { Init(); }
  356. // comparison
  357. bool operator == (const ColumnData& other) const
  358. { return ( 0 == memcmp(this, &other, sizeof(ColumnData)) ); }
  359. };
  360. SC ScGetColumnData( int iZeroBasedColIndex, ColumnData *pColData );
  361. SC ScSetColumnData( int iZeroBasedColIndex, const ColumnData& ColData );
  362. SC ScFindResultItem ( PNODE pNode, int &iItem );
  363. private:
  364. // helper methods
  365. SC ScGetNodesEnum ( bool bSelectedItemsOnly, PPNODES ppNodes );
  366. SC ScAllocResultItem ( CResultItem*& pResultItem, COMPONENTID id, LPARAM lSnapinData, int nImage);
  367. SC ScFreeResultItem ( CResultItem* pResultItem);
  368. SC ScRedrawItem (int nIndex);
  369. SC ScGetItemIndexFromHRESULTITEM(const HRESULTITEM& itemID, int& nIndex);
  370. SC ScRedrawHeader(bool bRedraw);
  371. protected:
  372. CAMCListView* m_pListView; // current list (points to m_StandardList or m_VirtualList)
  373. CAMCListView* m_pStandardList;
  374. CAMCListView* m_pVirtualList;
  375. HWND m_SavedHWND;
  376. WINDOWPLACEMENT m_wp;
  377. CWnd* m_pParentWnd;
  378. //void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  379. //void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  380. long m_itemCount; // internal item counter
  381. long m_nScopeItems; // scope item count
  382. long m_colCount; // internal column counter
  383. // ImageList members
  384. CImageList m_smallIL;
  385. CImageList m_largeIL;
  386. CImageIndexMap m_resultIM;
  387. // Header Sorting (Up/Down arrow) Icons.
  388. CSysColorImageList m_headerIL;
  389. // Sorting members
  390. SortParams m_sortParams;
  391. static int CALLBACK SortCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM pSortParams);
  392. static int SnapinCompare(SortParams* pSortParams, CResultItem* pri1, CResultItem* pri2);
  393. static int SnapinCompareEx(SortParams* pSortParams, CResultItem* pri1, CResultItem* pri2);
  394. static int CALLBACK DefaultCompare(LPARAM lParam1, LPARAM lParam2, LPARAM pSortParams);
  395. private:
  396. CListFontLinker m_FontLinker;
  397. NodesPtr m_spAllNodes;
  398. NodesPtr m_spSelNodes;
  399. ColumnsPtr m_spColumns;
  400. BOOL m_bVirtual;
  401. BOOL m_bFiltered; // filtering on now
  402. BOOL m_bEnsureFocusVisible; // force focused item to be visible
  403. BOOL m_bLoading;
  404. BOOL m_bDeferredSort;
  405. void SetFilterHeader(void);
  406. SC ScSetImageLists ();
  407. int ResultItemToIndex (CResultItem* pri) const;
  408. CResultItem* IndexToResultItem (int nItem);
  409. };
  410. ////////////////////////////////////////////////////////////////////////////
  411. // CQFilterDll
  412. //
  413. // This class dynamically loads and initializes the quickfilter DLL.
  414. // A single instance of the class should be declared at the global level.
  415. //
  416. class CQFilterDll
  417. {
  418. public:
  419. CQFilterDll()
  420. {
  421. m_hModule = LoadLibrary(_T("qfctrl.dll"));
  422. if (m_hModule != NULL)
  423. {
  424. void (*pfnInitQuickFilter)();
  425. pfnInitQuickFilter = (void (*)())GetProcAddress(m_hModule, "InitQuickFilter");
  426. if (pfnInitQuickFilter != NULL)
  427. (*pfnInitQuickFilter)();
  428. }
  429. }
  430. CQFilterDll::~CQFilterDll()
  431. {
  432. if (m_hModule != NULL)
  433. FreeLibrary(m_hModule);
  434. }
  435. private:
  436. HMODULE m_hModule;
  437. };
  438. /*+-------------------------------------------------------------------------*
  439. * CHiddenColumnInfo
  440. *
  441. * Contains information about a hidden column in report view: a flag
  442. * indicating it's hidden and its width when it's not hidden.
  443. *
  444. * This class is stored in HDITEM.lParam for hidden columns, so it *must*
  445. * be the same size as an LPARAM.
  446. *--------------------------------------------------------------------------*/
  447. class CHiddenColumnInfo
  448. {
  449. public:
  450. CHiddenColumnInfo (LPARAM lParam_) : lParam (lParam_)
  451. {
  452. COMPILETIME_ASSERT (sizeof(CHiddenColumnInfo) == sizeof(LPARAM));
  453. }
  454. CHiddenColumnInfo (int cx_, bool fHidden_) : cx (cx_), fHidden (fHidden_)
  455. {
  456. COMPILETIME_ASSERT (sizeof(CHiddenColumnInfo) == sizeof(LPARAM));
  457. }
  458. union
  459. {
  460. LPARAM lParam;
  461. struct
  462. {
  463. int cx : 16;
  464. int fHidden : 1;
  465. };
  466. };
  467. };
  468. #endif _CCLVCTL_H_