6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
42 #define COLOR_COMPRESSED RGB(0,0,255)
43 #define COLOR_SELECTION RGB(0,0,128)
46 static void format_date(const FILETIME
* ft
, TCHAR
* buffer
, int visible_cols
)
54 if (!ft
->dwLowDateTime
&& !ft
->dwHighDateTime
)
57 if (!FileTimeToLocalFileTime(ft
, &lft
))
58 {err
: _tcscpy(buffer
,_T("???")); return;}
60 if (!FileTimeToSystemTime(&lft
, &systime
))
63 if (visible_cols
& COL_DATE
) {
64 len
= GetDateFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
, BUFFER_LEN
);
69 if (visible_cols
& COL_TIME
) {
75 if (!GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &systime
, 0, buffer
+len
, BUFFER_LEN
-len
))
76 buffer
[len
] = _T('\0');
81 static void calc_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
85 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
87 if (rt
.right
> pane
->widths
[col
])
88 pane
->widths
[col
] = rt
.right
;
91 static void calc_tabbed_width(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
95 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
96 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
98 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
101 if (rt
.right
> pane
->widths
[col
])
102 pane
->widths
[col
] = rt
.right
;
106 static void output_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
, DWORD flags
)
108 int x
= dis
->rcItem
.left
;
109 RECT rt
= {x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
, dis
->rcItem
.top
, x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
, dis
->rcItem
.bottom
};
111 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_NOPREFIX
|flags
);
114 static void output_tabbed_text(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
116 int x
= dis
->rcItem
.left
;
117 RECT rt
= {x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
, dis
->rcItem
.top
, x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
, dis
->rcItem
.bottom
};
119 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
120 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
122 DrawText(dis
->hDC
, (LPTSTR
)str
, -1, &rt
, DT_SINGLELINE
|DT_EXPANDTABS
|DT_TABSTOP
|(2<<8));
125 static void output_number(Pane
* pane
, LPDRAWITEMSTRUCT dis
, int col
, LPCTSTR str
)
127 int x
= dis
->rcItem
.left
;
128 RECT rt
= {x
+pane
->positions
[col
]+Globals
.spaceSize
.cx
, dis
->rcItem
.top
, x
+pane
->positions
[col
+1]-Globals
.spaceSize
.cx
, dis
->rcItem
.bottom
};
137 // insert number separator characters
138 pos
= lstrlen(s
) % 3;
144 *d
++ = Globals
.num_sep
;
148 DrawText(dis
->hDC
, b
, d
-b
, &rt
, DT_RIGHT
|DT_SINGLELINE
|DT_NOPREFIX
|DT_END_ELLIPSIS
);
152 void draw_item(Pane
* pane
, LPDRAWITEMSTRUCT dis
, Entry
* entry
, int calcWidthCol
)
155 TCHAR buffer
[BUFFER_LEN
];
157 int visible_cols
= pane
->visible_cols
;
158 COLORREF bkcolor
, textcolor
;
159 RECT focusRect
= dis
->rcItem
;
162 #ifndef _NO_EXTENSIONS
169 attrs
= entry
->data
.dwFileAttributes
;
171 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
172 if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('.')
173 && entry
->data
.cFileName
[2]==_T('\0'))
175 #ifndef _NO_EXTENSIONS
176 else if (entry
->data
.cFileName
[0]==_T('.') && entry
->data
.cFileName
[1]==_T('\0'))
177 img
= IMG_FOLDER_CUR
;
180 #ifdef _NO_EXTENSIONS
183 (pane
->treePane
&& (dis
->itemState
&ODS_FOCUS
)))
184 img
= IMG_OPEN_FOLDER
;
188 LPCTSTR ext
= _tcsrchr(entry
->data
.cFileName
, '.');
192 if (is_exe_file(ext
))
193 img
= IMG_EXECUTABLE
;
194 else if (is_registered_type(ext
))
204 if (pane
->treePane
) {
206 img_pos
= dis
->rcItem
.left
+ entry
->level
*(IMAGE_WIDTH
+Globals
.spaceSize
.cx
);
208 if (calcWidthCol
== -1) {
210 int y
= dis
->rcItem
.top
+ IMAGE_HEIGHT
/2;
212 RECT rt_clip
= {dis
->rcItem
.left
, dis
->rcItem
.top
, dis
->rcItem
.left
+pane
->widths
[col
], dis
->rcItem
.bottom
};
213 HRGN hrgn_org
= CreateRectRgn(0, 0, 0, 0);
214 HRGN hrgn
= CreateRectRgnIndirect(&rt_clip
);
216 if (!GetClipRgn(dis
->hDC
, hrgn_org
)) {
217 DeleteObject(hrgn_org
);
221 // HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN));
222 ExtSelectClipRgn(dis
->hDC
, hrgn
, RGN_AND
);
225 if ((up
=entry
->up
) != NULL
) {
226 MoveToEx(dis
->hDC
, img_pos
-IMAGE_WIDTH
/2, y
, 0);
227 LineTo(dis
->hDC
, img_pos
-2, y
);
229 x
= img_pos
- IMAGE_WIDTH
/2;
232 x
-= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
236 && (up
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
239 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
240 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
242 } while((up
=up
->up
) != NULL
);
245 x
= img_pos
- IMAGE_WIDTH
/2;
247 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
, 0);
248 LineTo(dis
->hDC
, x
, y
);
252 && (entry
->next
->data
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
)
255 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
257 if (entry
->down
&& entry
->expanded
) {
258 x
+= IMAGE_WIDTH
+Globals
.spaceSize
.cx
;
259 MoveToEx(dis
->hDC
, x
, dis
->rcItem
.top
+IMAGE_HEIGHT
, 0);
260 LineTo(dis
->hDC
, x
, dis
->rcItem
.bottom
);
263 SelectClipRgn(dis
->hDC
, hrgn_org
);
264 if (hrgn_org
) DeleteObject(hrgn_org
);
265 // SelectObject(dis->hDC, holdPen);
266 } else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
) {
267 int right
= img_pos
+ IMAGE_WIDTH
- Globals
.spaceSize
.cx
;
269 if (right
> pane
->widths
[col
])
270 pane
->widths
[col
] = right
;
273 img_pos
= dis
->rcItem
.left
;
276 img_pos
= dis
->rcItem
.left
;
278 if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
279 pane
->widths
[col
] = IMAGE_WIDTH
;
282 if (calcWidthCol
== -1) {
283 focusRect
.left
= img_pos
-2;
285 #ifdef _NO_EXTENSIONS
286 if (pane
->treePane
&& entry
) {
289 DrawText(dis
->hDC
, entry
->data
.cFileName
, -1, &rt
, DT_CALCRECT
|DT_SINGLELINE
|DT_NOPREFIX
);
291 focusRect
.right
= dis
->rcItem
.left
+pane
->positions
[col
+1]+Globals
.spaceSize
.cx
+ rt
.right
+2;
295 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
)
296 textcolor
= COLOR_COMPRESSED
;
299 textcolor
= RGB(0,0,0);
301 if (dis
->itemState
& ODS_FOCUS
) {
302 textcolor
= RGB(255,255,255);
303 bkcolor
= COLOR_SELECTION
;
305 bkcolor
= RGB(255,255,255);
308 hbrush
= CreateSolidBrush(bkcolor
);
309 FillRect(dis
->hDC
, &focusRect
, hbrush
);
310 DeleteObject(hbrush
);
312 SetBkMode(dis
->hDC
, TRANSPARENT
);
313 SetTextColor(dis
->hDC
, textcolor
);
315 cx
= pane
->widths
[col
];
317 if (cx
&& img
!=IMG_NONE
) {
318 if (cx
> IMAGE_WIDTH
)
321 ImageList_DrawEx(Globals
.himl
, img
, dis
->hDC
,
322 img_pos
, dis
->rcItem
.top
, cx
,
323 IMAGE_HEIGHT
, bkcolor
, CLR_DEFAULT
, ILD_NORMAL
);
330 #ifdef _NO_EXTENSIONS
331 if (img
>= IMG_FOLDER_UP
)
338 if (calcWidthCol
== -1)
339 output_text(pane
, dis
, col
, entry
->data
.cFileName
, 0);
340 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
341 calc_width(pane
, dis
, col
, entry
->data
.cFileName
);
345 #ifdef _NO_EXTENSIONS
346 if (!pane
->treePane
) {
350 if (visible_cols
& COL_SIZE
) {
351 #ifdef _NO_EXTENSIONS
352 if (!(attrs
&FILE_ATTRIBUTE_DIRECTORY
))
357 *(DWORD
*)(&size
) = entry
->data
.nFileSizeLow
; //TODO: platform spefific
358 *(((DWORD
*)&size
)+1) = entry
->data
.nFileSizeHigh
;
360 _stprintf(buffer
, _T("%") LONGLONGARG
_T("d"), size
);
362 if (calcWidthCol
== -1)
363 output_number(pane
, dis
, col
, buffer
);
364 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
365 calc_width(pane
, dis
, col
, buffer
);//TODO: not ever time enough
372 if (visible_cols
& (COL_DATE
|COL_TIME
)) {
373 #ifndef _NO_EXTENSIONS
374 format_date(&entry
->data
.ftCreationTime
, buffer
, visible_cols
);
375 if (calcWidthCol
== -1)
376 output_text(pane
, dis
, col
, buffer
, 0);
377 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
378 calc_width(pane
, dis
, col
, buffer
);
381 format_date(&entry
->data
.ftLastAccessTime
, buffer
, visible_cols
);
382 if (calcWidthCol
== -1)
383 output_text(pane
, dis
, col
, buffer
, 0);
384 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
385 calc_width(pane
, dis
, col
, buffer
);
389 format_date(&entry
->data
.ftLastWriteTime
, buffer
, visible_cols
);
390 if (calcWidthCol
== -1)
391 output_text(pane
, dis
, col
, buffer
, 0);
392 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
393 calc_width(pane
, dis
, col
, buffer
);
397 #ifndef _NO_EXTENSIONS
398 if (entry
->bhfi_valid
) {
399 ((DWORD
*)&index
)[0] = entry
->bhfi
.nFileIndexLow
; //TODO: platform spefific
400 ((DWORD
*)&index
)[1] = entry
->bhfi
.nFileIndexHigh
;
402 if (visible_cols
& COL_INDEX
) {
403 _stprintf(buffer
, _T("%") LONGLONGARG
_T("X"), index
);
404 if (calcWidthCol
== -1)
405 output_text(pane
, dis
, col
, buffer
, DT_RIGHT
);
406 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
407 calc_width(pane
, dis
, col
, buffer
);
411 if (visible_cols
& COL_LINKS
) {
412 wsprintf(buffer
, _T("%d"), entry
->bhfi
.nNumberOfLinks
);
413 if (calcWidthCol
== -1)
414 output_text(pane
, dis
, col
, buffer
, DT_CENTER
);
415 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
416 calc_width(pane
, dis
, col
, buffer
);
423 // show file attributes
424 if (visible_cols
& COL_ATTRIBUTES
) {
425 #ifdef _NO_EXTENSIONS
426 _tcscpy(buffer
, _T(" \t \t \t \t "));
428 _tcscpy(buffer
, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
431 if (attrs
& FILE_ATTRIBUTE_NORMAL
) buffer
[ 0] = 'N';
433 if (attrs
& FILE_ATTRIBUTE_READONLY
) buffer
[ 2] = 'R';
434 if (attrs
& FILE_ATTRIBUTE_HIDDEN
) buffer
[ 4] = 'H';
435 if (attrs
& FILE_ATTRIBUTE_SYSTEM
) buffer
[ 6] = 'S';
436 if (attrs
& FILE_ATTRIBUTE_ARCHIVE
) buffer
[ 8] = 'A';
437 if (attrs
& FILE_ATTRIBUTE_COMPRESSED
) buffer
[10] = 'C';
438 #ifndef _NO_EXTENSIONS
439 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) buffer
[12] = 'D';
440 if (attrs
& FILE_ATTRIBUTE_ENCRYPTED
) buffer
[14] = 'E';
441 if (attrs
& FILE_ATTRIBUTE_TEMPORARY
) buffer
[16] = 'T';
442 if (attrs
& FILE_ATTRIBUTE_SPARSE_FILE
) buffer
[18] = 'P';
443 if (attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) buffer
[20] = 'Q';
444 if (attrs
& FILE_ATTRIBUTE_OFFLINE
) buffer
[22] = 'O';
445 if (attrs
& FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
) buffer
[24] = 'X';
449 if (calcWidthCol
== -1)
450 output_tabbed_text(pane
, dis
, col
, buffer
);
451 else if (calcWidthCol
==col
|| calcWidthCol
==COLUMNS
)
452 calc_tabbed_width(pane
, dis
, col
, buffer
);
458 if (flags.security) {
459 DWORD rights = get_access_mask();
461 tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
463 if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
464 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
465 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
466 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
467 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
468 if (rights & FILE_EXECUTE) buffer[12] = 'X';
469 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
470 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
471 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
472 if (rights & WRITE_DAC) buffer[22] = 'C';
473 if (rights & WRITE_OWNER) buffer[24] = 'O';
474 if (rights & SYNCHRONIZE) buffer[26] = 'S';
476 output_text(dis, col++, buffer, DT_LEFT, 3, psize);
479 if (flags.description) {
480 get_description(buffer);
481 output_text(dis, col++, buffer, 0, psize);
485 #ifdef _NO_EXTENSIONS
489 if ((dis
->itemState
&ODS_FOCUS
) && calcWidthCol
==-1) {
490 // Currently [04/2000] Wine neither behaves exactly the same
491 // way as WIN 95 nor like Windows NT...
493 DrawFocusRect(dis
->hDC
, &focusRect
);
499 if (!(GetVersion() & 0x80000000)) { // Windows NT?
500 LOGBRUSH lb
= {PS_SOLID
, RGB(255,255,255)};
501 hpen
= ExtCreatePen(PS_COSMETIC
|PS_ALTERNATE
, 1, &lb
, 0, 0);
503 hpen
= CreatePen(PS_DOT
, 0, RGB(255,255,255));
505 lastPen
= SelectPen(dis
->hDC
, hpen
);
506 lastBrush
= SelectObject(dis
->hDC
, GetStockObject(HOLLOW_BRUSH
));
507 SetROP2(dis
->hDC
, R2_XORPEN
);
508 Rectangle(dis
->hDC
, focusRect
.left
, focusRect
.top
, focusRect
.right
, focusRect
.bottom
);
509 SelectObject(dis
->hDC
, lastBrush
);
510 SelectObject(dis
->hDC
, lastPen
);