PageRenderTime 62ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/base/shell/explorer/shell/pane.cpp

https://bitbucket.org/arty/arty-newcc-reactos
C++ | 998 lines | 701 code | 218 blank | 79 comment | 192 complexity | 6aef27343c7af62cc1345098fcc4b866 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. //
  19. // Explorer clone
  20. //
  21. // pane.cpp
  22. //
  23. // Martin Fuchs, 23.07.2003
  24. //
  25. #include <precomp.h>
  26. #include "../resource.h"
  27. enum IMAGE {
  28. IMG_NONE=-1, IMG_FILE=0, IMG_DOCUMENT, IMG_EXECUTABLE,
  29. IMG_FOLDER, IMG_OPEN_FOLDER, IMG_FOLDER_PLUS,IMG_OPEN_PLUS, IMG_OPEN_MINUS,
  30. IMG_FOLDER_UP, IMG_FOLDER_CUR
  31. };
  32. #define IMAGE_WIDTH 16
  33. #define IMAGE_HEIGHT 13
  34. static const TCHAR* g_pos_names[COLUMNS] = {
  35. TEXT(""), /* symbol */
  36. TEXT("Name"),
  37. TEXT("Type"),
  38. TEXT("Size"),
  39. TEXT("CDate"),
  40. TEXT("ADate"),
  41. TEXT("MDate"),
  42. TEXT("Index/Inode"),
  43. TEXT("Links"),
  44. TEXT("Attributes"),
  45. TEXT("Security"),
  46. TEXT("Content")
  47. };
  48. static const int g_pos_align[] = {
  49. 0,
  50. HDF_LEFT, /* Name */
  51. HDF_LEFT, /* Type */
  52. HDF_RIGHT, /* Size */
  53. HDF_LEFT, /* CDate */
  54. HDF_LEFT, /* ADate */
  55. HDF_LEFT, /* MDate */
  56. HDF_LEFT, /* Index */
  57. HDF_RIGHT, /* Links */
  58. HDF_CENTER, /* Attributes */
  59. HDF_LEFT, /* Security */
  60. HDF_LEFT /* Content / Description */
  61. };
  62. Pane::Pane(HWND hparent, int id, int id_header, Entry* root, bool treePane, int visible_cols)
  63. : super(CreateWindow(TEXT("ListBox"), TEXT(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
  64. LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY,
  65. 0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0)),
  66. _root(root),
  67. _visible_cols(visible_cols),
  68. _treePane(treePane)
  69. {
  70. // insert entries into listbox
  71. Entry* entry = _root;
  72. if (entry)
  73. insert_entries(entry);
  74. init();
  75. create_header(hparent, id_header);
  76. }
  77. Pane::~Pane()
  78. {
  79. ImageList_Destroy(_himl);
  80. }
  81. LRESULT Pane::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
  82. {
  83. switch(nmsg) {
  84. case WM_HSCROLL:
  85. set_header();
  86. break;
  87. case WM_SETFOCUS: {
  88. FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0);
  89. child->set_focus_pane(this);
  90. ListBox_SetSel(_hwnd, TRUE, 1);
  91. /*@todo check menu items */
  92. break;}
  93. case WM_KEYDOWN: {
  94. FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0);
  95. if (wparam == VK_TAB) {
  96. /*@todo SetFocus(g_Globals.hdrivebar) */
  97. child->switch_focus_pane();
  98. }
  99. break;}
  100. }
  101. return super::WndProc(nmsg, wparam, lparam);
  102. }
  103. bool Pane::create_header(HWND hparent, int id)
  104. {
  105. HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ/*@todo |HDS_BUTTONS + sort orders*/,
  106. 0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0);
  107. if (!hwnd)
  108. return false;
  109. SetWindowFont(hwnd, GetStockFont(DEFAULT_GUI_FONT), FALSE);
  110. HD_ITEM hdi;
  111. hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_FORMAT;
  112. for(int idx=0; idx<COLUMNS; idx++) {
  113. hdi.pszText = (TCHAR*)g_pos_names[idx];
  114. hdi.fmt = HDF_STRING | g_pos_align[idx];
  115. hdi.cxy = _widths[idx];
  116. Header_InsertItem(hwnd, idx, &hdi);
  117. }
  118. _hwndHeader = hwnd;
  119. return true;
  120. }
  121. void Pane::init()
  122. {
  123. _himl = ImageList_LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0));
  124. SetWindowFont(_hwnd, _out_wrkr._hfont, FALSE);
  125. // read the color for compressed files from registry
  126. HKEY hkeyExplorer = 0;
  127. DWORD len = sizeof(_clrCompressed);
  128. if (RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkeyExplorer) ||
  129. RegQueryValueEx(hkeyExplorer, TEXT("AltColor"), 0, NULL, (LPBYTE)&_clrCompressed, &len) || len!=sizeof(_clrCompressed))
  130. _clrCompressed = RGB(0,0,255);
  131. if (hkeyExplorer)
  132. RegCloseKey(hkeyExplorer);
  133. // calculate column widths
  134. _out_wrkr.init_output(_hwnd);
  135. calc_widths(true);
  136. }
  137. // calculate prefered width for all visible columns
  138. bool Pane::calc_widths(bool anyway)
  139. {
  140. int col, x, cx, spc=3*_out_wrkr._spaceSize.cx;
  141. int entries = ListBox_GetCount(_hwnd);
  142. int orgWidths[COLUMNS];
  143. int orgPositions[COLUMNS+1];
  144. HFONT hfontOld;
  145. HDC hdc;
  146. int cnt;
  147. if (!anyway) {
  148. memcpy(orgWidths, _widths, sizeof(orgWidths));
  149. memcpy(orgPositions, _positions, sizeof(orgPositions));
  150. }
  151. for(col=0; col<COLUMNS; col++)
  152. _widths[col] = 0;
  153. hdc = GetDC(_hwnd);
  154. hfontOld = SelectFont(hdc, _out_wrkr._hfont);
  155. for(cnt=0; cnt<entries; cnt++) {
  156. Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt);
  157. DRAWITEMSTRUCT dis;
  158. dis.CtlType = 0;
  159. dis.CtlID = 0;
  160. dis.itemID = 0;
  161. dis.itemAction = 0;
  162. dis.itemState = 0;
  163. dis.hwndItem = _hwnd;
  164. dis.hDC = hdc;
  165. dis.rcItem.left = 0;
  166. dis.rcItem.top = 0;
  167. dis.rcItem.right = 0;
  168. dis.rcItem.bottom = 0;
  169. /*dis.itemData = 0; */
  170. draw_item(&dis, entry, COLUMNS);
  171. }
  172. SelectObject(hdc, hfontOld);
  173. ReleaseDC(_hwnd, hdc);
  174. x = 0;
  175. for(col=0; col<COLUMNS; col++) {
  176. _positions[col] = x;
  177. cx = _widths[col];
  178. if (cx) {
  179. cx += spc;
  180. if (cx < IMAGE_WIDTH)
  181. cx = IMAGE_WIDTH;
  182. _widths[col] = cx;
  183. }
  184. x += cx;
  185. }
  186. _positions[COLUMNS] = x;
  187. ListBox_SetHorizontalExtent(_hwnd, x);
  188. // no change?
  189. if (!memcmp(orgWidths, _widths, sizeof(orgWidths)))
  190. return FALSE;
  191. // don't move, if only collapsing an entry
  192. if (!anyway && _widths[0]<orgWidths[0] &&
  193. !memcmp(orgWidths+1, _widths+1, sizeof(orgWidths)-sizeof(int))) {
  194. _widths[0] = orgWidths[0];
  195. memcpy(_positions, orgPositions, sizeof(orgPositions));
  196. return FALSE;
  197. }
  198. InvalidateRect(_hwnd, 0, TRUE);
  199. return TRUE;
  200. }
  201. static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols)
  202. {
  203. SYSTEMTIME systime;
  204. FILETIME lft;
  205. int len = 0;
  206. *buffer = TEXT('\0');
  207. if (!ft->dwLowDateTime && !ft->dwHighDateTime)
  208. return;
  209. if (!FileTimeToLocalFileTime(ft, &lft))
  210. {err: lstrcpy(buffer,TEXT("???")); return;}
  211. if (!FileTimeToSystemTime(&lft, &systime))
  212. goto err;
  213. if (visible_cols & COL_DATE) {
  214. len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN);
  215. if (!len)
  216. goto err;
  217. }
  218. if (visible_cols & COL_TIME) {
  219. if (len)
  220. buffer[len-1] = ' ';
  221. buffer[len++] = ' ';
  222. if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len))
  223. buffer[len] = TEXT('\0');
  224. }
  225. }
  226. void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
  227. {
  228. TCHAR buffer[BUFFER_LEN];
  229. DWORD attrs;
  230. int visible_cols = _visible_cols;
  231. COLORREF bkcolor, textcolor;
  232. RECT focusRect = dis->rcItem;
  233. enum IMAGE img;
  234. int img_pos, cx;
  235. int col = 0;
  236. if (entry) {
  237. attrs = entry->_data.dwFileAttributes;
  238. if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
  239. if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('.')
  240. && entry->_data.cFileName[2]==TEXT('\0'))
  241. img = IMG_FOLDER_UP;
  242. else if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('\0'))
  243. img = IMG_FOLDER_CUR;
  244. else if ((_treePane && (dis->itemState&ODS_FOCUS)))
  245. img = IMG_OPEN_FOLDER;
  246. else
  247. img = IMG_FOLDER;
  248. } else {
  249. if (attrs & ATTRIBUTE_EXECUTABLE)
  250. img = IMG_EXECUTABLE;
  251. else if (entry->_type_name)
  252. img = IMG_DOCUMENT;
  253. else
  254. img = IMG_FILE;
  255. }
  256. } else {
  257. attrs = 0;
  258. img = IMG_NONE;
  259. }
  260. if (_treePane) {
  261. if (entry) {
  262. img_pos = dis->rcItem.left + entry->_level*(IMAGE_WIDTH+_out_wrkr._spaceSize.cx);
  263. if (calcWidthCol == -1) {
  264. int x;
  265. int y = dis->rcItem.top + IMAGE_HEIGHT/2;
  266. Entry* up;
  267. RECT rt_clip;
  268. HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0);
  269. HRGN hrgn;
  270. rt_clip.left = dis->rcItem.left;
  271. rt_clip.top = dis->rcItem.top;
  272. rt_clip.right = dis->rcItem.left+_widths[col];
  273. rt_clip.bottom = dis->rcItem.bottom;
  274. hrgn = CreateRectRgnIndirect(&rt_clip);
  275. if (!GetClipRgn(dis->hDC, hrgn_org)) {
  276. DeleteObject(hrgn_org);
  277. hrgn_org = 0;
  278. }
  279. //HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN));
  280. ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND);
  281. DeleteObject(hrgn);
  282. if ((up=entry->_up) != NULL) {
  283. MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0);
  284. LineTo(dis->hDC, img_pos-2, y);
  285. x = img_pos - IMAGE_WIDTH/2;
  286. do {
  287. x -= IMAGE_WIDTH+_out_wrkr._spaceSize.cx;
  288. if (up->_next) {
  289. #ifndef _LEFT_FILES
  290. bool following_child = (up->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory?
  291. if (!following_child)
  292. {
  293. for(Entry*n=up->_next; n; n=n->_next)
  294. if (n->_down) { // any file with NTFS sub-streams?
  295. following_child = true;
  296. break;
  297. }
  298. }
  299. if (following_child)
  300. #endif
  301. {
  302. MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
  303. LineTo(dis->hDC, x, dis->rcItem.bottom);
  304. }
  305. }
  306. } while((up=up->_up) != NULL);
  307. }
  308. x = img_pos - IMAGE_WIDTH/2;
  309. MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
  310. LineTo(dis->hDC, x, y);
  311. if (entry->_next) {
  312. #ifndef _LEFT_FILES
  313. bool following_child = (entry->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory?
  314. if (!following_child)
  315. {
  316. for(Entry*n=entry->_next; n; n=n->_next)
  317. if (n->_down) { // any file with NTFS sub-streams?
  318. following_child = true;
  319. break;
  320. }
  321. }
  322. if (following_child)
  323. #endif
  324. LineTo(dis->hDC, x, dis->rcItem.bottom);
  325. }
  326. if (entry->_down && entry->_expanded) {
  327. x += IMAGE_WIDTH + _out_wrkr._spaceSize.cx;
  328. MoveToEx(dis->hDC, x, dis->rcItem.top+IMAGE_HEIGHT, 0);
  329. LineTo(dis->hDC, x, dis->rcItem.bottom);
  330. }
  331. SelectClipRgn(dis->hDC, hrgn_org);
  332. if (hrgn_org) DeleteObject(hrgn_org);
  333. //SelectObject(dis->hDC, holdPen);
  334. } else if (calcWidthCol==col || calcWidthCol==COLUMNS) {
  335. int right = img_pos + IMAGE_WIDTH - _out_wrkr._spaceSize.cx;
  336. if (right > _widths[col])
  337. _widths[col] = right;
  338. }
  339. } else {
  340. img_pos = dis->rcItem.left;
  341. }
  342. } else {
  343. img_pos = dis->rcItem.left;
  344. if (calcWidthCol==col || calcWidthCol==COLUMNS)
  345. _widths[col] = IMAGE_WIDTH;
  346. }
  347. if (calcWidthCol == -1) {
  348. focusRect.left = img_pos -2;
  349. if (attrs & FILE_ATTRIBUTE_COMPRESSED)
  350. textcolor = _clrCompressed;
  351. else
  352. textcolor = RGB(0,0,0);
  353. if (dis->itemState & ODS_FOCUS) {
  354. textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT);
  355. bkcolor = GetSysColor(COLOR_HIGHLIGHT);
  356. } else {
  357. bkcolor = GetSysColor(COLOR_WINDOW);
  358. }
  359. HBRUSH hbrush = CreateSolidBrush(bkcolor);
  360. FillRect(dis->hDC, &focusRect, hbrush);
  361. DeleteObject(hbrush);
  362. SetBkMode(dis->hDC, TRANSPARENT);
  363. SetTextColor(dis->hDC, textcolor);
  364. cx = _widths[col];
  365. if (cx && img!=IMG_NONE) {
  366. if (cx > IMAGE_WIDTH)
  367. cx = IMAGE_WIDTH;
  368. if (entry->_icon_id > ICID_NONE)
  369. g_Globals._icon_cache.get_icon(entry->_icon_id).draw(dis->hDC, img_pos, dis->rcItem.top, cx, GetSystemMetrics(SM_CYSMICON), bkcolor, 0);
  370. else
  371. ImageList_DrawEx(_himl, img, dis->hDC,
  372. img_pos, dis->rcItem.top, cx,
  373. IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
  374. }
  375. }
  376. if (!entry)
  377. return;
  378. ++col;
  379. // output file name
  380. if (calcWidthCol == -1)
  381. _out_wrkr.output_text(dis, _positions, col, entry->_display_name, 0);
  382. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  383. calc_width(dis, col, entry->_display_name);
  384. ++col;
  385. // output type/class name
  386. if (visible_cols & COL_TYPE) {
  387. if (calcWidthCol == -1)
  388. _out_wrkr.output_text(dis, _positions, col, entry->_type_name? entry->_type_name: TEXT(""), 0);
  389. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  390. calc_width(dis, col, entry->_type_name? entry->_type_name: TEXT(""));
  391. }
  392. ++col;
  393. // display file size
  394. if (visible_cols & COL_SIZE) {
  395. ULONGLONG size = ((ULONGLONG)entry->_data.nFileSizeHigh << 32) | entry->_data.nFileSizeLow;
  396. _stprintf(buffer, TEXT("%") LONGLONGARG TEXT("d"), size);
  397. if (calcWidthCol == -1)
  398. _out_wrkr.output_number(dis, _positions, col, buffer);
  399. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  400. calc_width(dis, col, buffer); ///@todo not in every case time enough
  401. }
  402. ++col;
  403. // display file date
  404. if (visible_cols & (COL_DATE|COL_TIME)) {
  405. format_date(&entry->_data.ftCreationTime, buffer, visible_cols);
  406. if (calcWidthCol == -1)
  407. _out_wrkr.output_text(dis, _positions, col, buffer, 0);
  408. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  409. calc_width(dis, col, buffer);
  410. ++col;
  411. format_date(&entry->_data.ftLastAccessTime, buffer, visible_cols);
  412. if (calcWidthCol == -1)
  413. _out_wrkr.output_text(dis,_positions, col, buffer, 0);
  414. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  415. calc_width(dis, col, buffer);
  416. ++col;
  417. format_date(&entry->_data.ftLastWriteTime, buffer, visible_cols);
  418. if (calcWidthCol == -1)
  419. _out_wrkr.output_text(dis, _positions, col, buffer, 0);
  420. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  421. calc_width(dis, col, buffer);
  422. ++col;
  423. } else
  424. col += 3;
  425. if (entry->_bhfi_valid) {
  426. ULONGLONG index = ((ULONGLONG)entry->_bhfi.nFileIndexHigh << 32) | entry->_bhfi.nFileIndexLow;
  427. if (visible_cols & COL_INDEX) {
  428. _stprintf(buffer, TEXT("%") LONGLONGARG TEXT("X"), index);
  429. if (calcWidthCol == -1)
  430. _out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT);
  431. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  432. calc_width(dis, col, buffer);
  433. ++col;
  434. }
  435. if (visible_cols & COL_LINKS) {
  436. wsprintf(buffer, TEXT("%d"), entry->_bhfi.nNumberOfLinks);
  437. if (calcWidthCol == -1)
  438. _out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT);
  439. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  440. calc_width(dis, col, buffer);
  441. ++col;
  442. }
  443. } else
  444. col += 2;
  445. // show file attributes
  446. if (visible_cols & COL_ATTRIBUTES) {
  447. lstrcpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t \t \t \t "));
  448. if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N';
  449. else {
  450. if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R';
  451. if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H';
  452. if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S';
  453. if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A';
  454. if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C';
  455. if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D';
  456. if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E';
  457. if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T';
  458. if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P';
  459. if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q';
  460. if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O';
  461. if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X';
  462. if (attrs & ATTRIBUTE_EXECUTABLE) buffer[26] = 'x';
  463. if (attrs & ATTRIBUTE_SYMBOLIC_LINK) buffer[28] = 'L';
  464. }
  465. if (calcWidthCol == -1)
  466. _out_wrkr.output_tabbed_text(dis, _positions, col, buffer);
  467. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  468. calc_tabbed_width(dis, col, buffer);
  469. }
  470. ++col;
  471. /*TODO
  472. if (flags.security) {
  473. DWORD rights = get_access_mask();
  474. tcscpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t "));
  475. if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
  476. if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
  477. if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
  478. if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
  479. if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
  480. if (rights & FILE_EXECUTE) buffer[12] = 'X';
  481. if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
  482. if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
  483. if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
  484. if (rights & WRITE_DAC) buffer[22] = 'C';
  485. if (rights & WRITE_OWNER) buffer[24] = 'O';
  486. if (rights & SYNCHRONIZE) buffer[26] = 'S';
  487. output_text(dis, col++, buffer, DT_LEFT, 3, psize);
  488. }
  489. if (flags.description) {
  490. get_description(buffer);
  491. output_text(dis, col++, buffer, 0, psize);
  492. }
  493. */
  494. ++col;
  495. // output content / symbolic link target / comment
  496. if (visible_cols & COL_CONTENT) {
  497. if (calcWidthCol == -1)
  498. _out_wrkr.output_text(dis, _positions, col, entry->_content? entry->_content: TEXT(""), 0);
  499. else if (calcWidthCol==col || calcWidthCol==COLUMNS)
  500. calc_width(dis, col, entry->_content? entry->_content: TEXT(""));
  501. }
  502. }
  503. void Pane::calc_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
  504. {
  505. RECT rt = {0, 0, 0, 0};
  506. DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
  507. if (rt.right > _widths[col])
  508. _widths[col] = rt.right;
  509. }
  510. void Pane::calc_tabbed_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
  511. {
  512. RECT rt = {0, 0, 0, 0};
  513. /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
  514. DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
  515. DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
  516. if (rt.right > _widths[col])
  517. _widths[col] = rt.right;
  518. }
  519. // insert listbox entries after index idx
  520. int Pane::insert_entries(Entry* dir, int idx)
  521. {
  522. Entry* entry = dir;
  523. if (!entry)
  524. return idx;
  525. for(; entry; entry=entry->_next) {
  526. #ifndef _LEFT_FILES
  527. if (_treePane &&
  528. !(entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && // not a directory?
  529. !entry->_down) // not a file with NTFS sub-streams?
  530. continue;
  531. #endif
  532. // don't display entries "." and ".." in the left pane
  533. if (_treePane && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
  534. && entry->_data.cFileName[0]==TEXT('.'))
  535. if (entry->_data.cFileName[1]==TEXT('\0') ||
  536. (entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0')))
  537. continue;
  538. if (idx != -1)
  539. ++idx;
  540. ListBox_InsertItemData(_hwnd, idx, entry);
  541. if (_treePane && entry->_expanded)
  542. idx = insert_entries(entry->_down, idx);
  543. }
  544. return idx;
  545. }
  546. void Pane::set_header()
  547. {
  548. HD_ITEM item;
  549. int scroll_pos = GetScrollPos(_hwnd, SB_HORZ);
  550. int i=0, x=0;
  551. item.mask = HDI_WIDTH;
  552. item.cxy = 0;
  553. for(; i<COLUMNS; i++) {
  554. if (x + _widths[i] >= scroll_pos)
  555. break;
  556. x += _widths[i];
  557. Header_SetItem(_hwndHeader, i, &item);
  558. }
  559. if (i < COLUMNS) {
  560. x += _widths[i];
  561. item.cxy = x - scroll_pos;
  562. Header_SetItem(_hwndHeader, i++, &item);
  563. for(; i<COLUMNS; i++) {
  564. item.cxy = _widths[i];
  565. x += _widths[i];
  566. Header_SetItem(_hwndHeader, i, &item);
  567. }
  568. }
  569. }
  570. // calculate one prefered column width
  571. void Pane::calc_single_width(int col)
  572. {
  573. HFONT hfontOld;
  574. int x, cx;
  575. int cnt;
  576. HDC hdc;
  577. int entries = ListBox_GetCount(_hwnd);
  578. _widths[col] = 0;
  579. hdc = GetDC(_hwnd);
  580. hfontOld = SelectFont(hdc, _out_wrkr._hfont);
  581. for(cnt=0; cnt<entries; cnt++) {
  582. Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt);
  583. DRAWITEMSTRUCT dis;
  584. dis.CtlType = 0;
  585. dis.CtlID = 0;
  586. dis.itemID = 0;
  587. dis.itemAction = 0;
  588. dis.itemState = 0;
  589. dis.hwndItem = _hwnd;
  590. dis.hDC = hdc;
  591. dis.rcItem.left = 0;
  592. dis.rcItem.top = 0;
  593. dis.rcItem.right = 0;
  594. dis.rcItem.bottom = 0;
  595. /*dis.itemData = 0; */
  596. draw_item(&dis, entry, col);
  597. }
  598. SelectObject(hdc, hfontOld);
  599. ReleaseDC(_hwnd, hdc);
  600. cx = _widths[col];
  601. if (cx) {
  602. cx += 3*_out_wrkr._spaceSize.cx;
  603. if (cx < IMAGE_WIDTH)
  604. cx = IMAGE_WIDTH;
  605. }
  606. _widths[col] = cx;
  607. x = _positions[col] + cx;
  608. for(; col<COLUMNS; col++) {
  609. _positions[col+1] = x;
  610. x += _widths[col];
  611. }
  612. ListBox_SetHorizontalExtent(_hwnd, x);
  613. }
  614. int Pane::Notify(int id, NMHDR* pnmh)
  615. {
  616. switch(pnmh->code) {
  617. case HDN_TRACK:
  618. case HDN_ENDTRACK: {
  619. HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
  620. int idx = phdn->iItem;
  621. int dx = phdn->pitem->cxy - _widths[idx];
  622. int i;
  623. ClientRect clnt(_hwnd);
  624. // move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB)
  625. Header_SetItem(_hwndHeader, idx, phdn->pitem);
  626. _widths[idx] += dx;
  627. for(i=idx; ++i<=COLUMNS; )
  628. _positions[i] += dx;
  629. {
  630. int scroll_pos = GetScrollPos(_hwnd, SB_HORZ);
  631. RECT rt_scr;
  632. RECT rt_clip;
  633. rt_scr.left = _positions[idx+1]-scroll_pos;
  634. rt_scr.top = 0;
  635. rt_scr.right = clnt.right;
  636. rt_scr.bottom = clnt.bottom;
  637. rt_clip.left = _positions[idx]-scroll_pos;
  638. rt_clip.top = 0;
  639. rt_clip.right = clnt.right;
  640. rt_clip.bottom = clnt.bottom;
  641. if (rt_scr.left < 0) rt_scr.left = 0;
  642. if (rt_clip.left < 0) rt_clip.left = 0;
  643. ScrollWindowEx(_hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE);
  644. rt_clip.right = _positions[idx+1];
  645. RedrawWindow(_hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW);
  646. if (pnmh->code == HDN_ENDTRACK) {
  647. ListBox_SetHorizontalExtent(_hwnd, _positions[COLUMNS]);
  648. if (GetScrollPos(_hwnd, SB_HORZ) != scroll_pos)
  649. set_header();
  650. }
  651. }
  652. return 0;
  653. }
  654. case HDN_DIVIDERDBLCLICK: {
  655. HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
  656. HD_ITEM item;
  657. calc_single_width(phdn->iItem);
  658. item.mask = HDI_WIDTH;
  659. item.cxy = _widths[phdn->iItem];
  660. Header_SetItem(_hwndHeader, phdn->iItem, &item);
  661. InvalidateRect(_hwnd, 0, TRUE);
  662. break;}
  663. default:
  664. return super::Notify(id, pnmh);
  665. }
  666. return 0;
  667. }
  668. OutputWorker::OutputWorker()
  669. {
  670. _hfont = CreateFont(-MulDiv(8,GetDeviceCaps(WindowCanvas(0),LOGPIXELSY),72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TEXT("MS Sans Serif"));
  671. }
  672. void OutputWorker::init_output(HWND hwnd)
  673. {
  674. TCHAR b[16];
  675. WindowCanvas canvas(hwnd);
  676. if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, TEXT("1000"), 0, b, 16) > 4)
  677. _num_sep = b[1];
  678. else
  679. _num_sep = TEXT('.');
  680. FontSelection font(canvas, _hfont);
  681. GetTextExtentPoint32(canvas, TEXT(" "), 1, &_spaceSize);
  682. }
  683. void OutputWorker::output_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str, DWORD flags)
  684. {
  685. int x = dis->rcItem.left;
  686. RECT rt;
  687. rt.left = x+positions[col]+_spaceSize.cx;
  688. rt.top = dis->rcItem.top;
  689. rt.right = x+positions[col+1]-_spaceSize.cx;
  690. rt.bottom = dis->rcItem.bottom;
  691. DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags);
  692. }
  693. void OutputWorker::output_tabbed_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str)
  694. {
  695. int x = dis->rcItem.left;
  696. RECT rt;
  697. rt.left = x+positions[col]+_spaceSize.cx;
  698. rt.top = dis->rcItem.top;
  699. rt.right = x+positions[col+1]-_spaceSize.cx;
  700. rt.bottom = dis->rcItem.bottom;
  701. /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
  702. DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
  703. DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
  704. }
  705. void OutputWorker::output_number(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str)
  706. {
  707. int x = dis->rcItem.left;
  708. RECT rt;
  709. LPCTSTR s = str;
  710. TCHAR b[128];
  711. LPTSTR d = b;
  712. int pos;
  713. rt.left = x+positions[col]+_spaceSize.cx;
  714. rt.top = dis->rcItem.top;
  715. rt.right = x+positions[col+1]-_spaceSize.cx;
  716. rt.bottom = dis->rcItem.bottom;
  717. if (*s)
  718. *d++ = *s++;
  719. // insert number separator characters
  720. pos = lstrlen(s) % 3;
  721. while(*s)
  722. if (pos--)
  723. *d++ = *s++;
  724. else {
  725. *d++ = _num_sep;
  726. pos = 3;
  727. }
  728. DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS);
  729. }
  730. BOOL Pane::command(UINT cmd)
  731. {
  732. switch(cmd) {
  733. case ID_VIEW_NAME:
  734. if (_visible_cols) {
  735. _visible_cols = 0;
  736. calc_widths(true);
  737. set_header();
  738. InvalidateRect(_hwnd, 0, TRUE);
  739. MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd));
  740. if (menu_info) {
  741. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED);
  742. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND);
  743. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
  744. }
  745. }
  746. break;
  747. case ID_VIEW_ALL_ATTRIBUTES:
  748. if (_visible_cols != COL_ALL) {
  749. _visible_cols = COL_ALL;
  750. calc_widths(true);
  751. set_header();
  752. InvalidateRect(_hwnd, 0, TRUE);
  753. MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd));
  754. if (menu_info) {
  755. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND);
  756. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED);
  757. CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
  758. }
  759. }
  760. break;
  761. case ID_PREFERED_SIZES: {
  762. calc_widths(true);
  763. set_header();
  764. InvalidateRect(_hwnd, 0, TRUE);
  765. break;}
  766. /*@todo more command ids... */
  767. default:
  768. return FALSE;
  769. }
  770. return TRUE;
  771. }
  772. MainFrameBase* Pane::get_frame()
  773. {
  774. HWND owner = GetParent(_hwnd);
  775. return (MainFrameBase*)owner;
  776. }