openfile_win32.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:40k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: openfile_win32.c 531 2006-01-04 12:56:13Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../../common/common.h"
  24. #include "../win.h"
  25. #include "openfile_win32.h"
  26. #include "interface.h"
  27. #include "resource.h"
  28. #if defined(TARGET_WINCE) || defined(TARGET_WIN32)
  29. #ifndef STRICT
  30. #define STRICT
  31. #endif
  32. #include <windows.h>
  33. #if _MSC_VER > 1000
  34. #pragma warning(disable : 4201)
  35. #endif
  36. #include <commctrl.h>
  37. #define OPENFILE_TYPES 50000
  38. #define EM_SETSYMBOLS       0x00DF
  39. #define SYMBOLS T("./:-1\~?#")
  40. #define MAXHISTORY 20
  41. #define IMG_FILE 0
  42. #define IMG_DIR 1
  43. #define IMG_PLAYLIST 2
  44. #define IMG_VIDEO 3
  45. #define IMG_AUDIO 4
  46. #define IMG_DIRUP 5
  47. typedef struct openitem
  48. {
  49. int Image;
  50. tchar_t FileName[MAXPATH];
  51. tchar_t Name[MAXPATH];
  52. tchar_t Ext[MAXPATH];
  53. filepos_t Size;
  54. int64_t Date;
  55. bool_t DisplayName;
  56. } openitem;
  57. typedef struct openfile
  58. {
  59. win Win;
  60. HWND WndList;
  61. HWND WndURL;
  62. HWND WndGo;
  63. int* CurrentFileType;
  64. int FileType;
  65. int FileTypeSingle;
  66. int FileTypeSave;
  67. int SortCol;
  68. int Class;
  69. int Flags;
  70. int Top;
  71. int TypesMenu;
  72. bool_t SortDir;
  73. bool_t Multiple;
  74. bool_t SelectDir;
  75. bool_t OwnSelect;
  76. bool_t NextFocus;
  77. bool_t OnlyName;
  78. bool_t OnlyNameState;
  79. bool_t KeyClick;
  80. int InUpdate;
  81. int LastClick;
  82. int DlgWidth[4];
  83. tchar_t Path[MAXPATH];
  84. tchar_t Base[MAXPATH];
  85. tchar_t Exts[1024];
  86. tchar_t Last[MAXPATH];
  87. tchar_t SaveName[MAXPATH];
  88. array Types;
  89. int HistoryCount;
  90. tchar_t* History[MAXHISTORY];
  91. } openfile;
  92. static const datatable Params[] =
  93. {
  94. { OPENFILE_FLAGS, TYPE_INT, DF_HIDDEN },
  95. { OPENFILE_CLASS, TYPE_INT, DF_HIDDEN },
  96. { OPENFILE_MULTIPLE, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
  97. { OPENFILE_FILETYPE, TYPE_INT, DF_SETUP|DF_HIDDEN },
  98. { OPENFILE_FILETYPE_SINGLE, TYPE_INT, DF_SETUP|DF_HIDDEN },
  99. { OPENFILE_FILETYPE_SAVE,TYPE_INT, DF_SETUP|DF_HIDDEN },
  100. { OPENFILE_PATH, TYPE_STRING, DF_SETUP|DF_HIDDEN },
  101. { OPENFILE_SORTCOL, TYPE_INT, DF_SETUP|DF_HIDDEN },
  102. { OPENFILE_SORTDIR, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
  103. { OPENFILE_WIDTH_NAME, TYPE_INT, DF_SETUP|DF_HIDDEN },
  104. { OPENFILE_WIDTH_TYPE, TYPE_INT, DF_SETUP|DF_HIDDEN },
  105. { OPENFILE_WIDTH_SIZE, TYPE_INT, DF_SETUP|DF_HIDDEN },
  106. { OPENFILE_WIDTH_DATE, TYPE_INT, DF_SETUP|DF_HIDDEN },
  107. { OPENFILE_ONLYNAME, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
  108. { OPENFILE_HISTORYCOUNT,TYPE_INT, DF_SETUP|DF_HIDDEN },
  109. { OPENFILE_SAVE_NAME, TYPE_STRING, DF_HIDDEN },
  110. { OPENFILE_SAVE_TYPE, TYPE_INT, DF_ENUMCLASS|DF_HIDDEN  },
  111. { OPENFILE_URL,   TYPE_STRING, DF_HIDDEN },
  112. { OPENFILE_LIST,   0, DF_HIDDEN },
  113. DATATABLE_END(OPENFILE_ID)
  114. };
  115. static int Enum(openfile* p, int* No, datadef* Param )
  116. {
  117. if (NodeEnumTable(No,Param,Params)==ERR_NONE)
  118. {
  119. if (Param->No == OPENFILE_SAVE_TYPE)
  120. Param->Format1 = p->Class;
  121. return ERR_NONE;
  122. }
  123. if (*No >= 0 && *No < p->HistoryCount)
  124. {
  125. memset(Param,0,sizeof(datadef));
  126. Param->No = OPENFILE_HISTORY + *No;
  127. Param->Type = TYPE_STRING;
  128. Param->Size = MAXDATA;
  129. Param->Flags = DF_HIDDEN | DF_SETUP;
  130. Param->Class = OPENFILE_ID;
  131. return ERR_NONE;
  132. }
  133. return ERR_INVALID_PARAM;
  134. }
  135. static int Get(openfile* p,int No,void* Data,int Size)
  136. {
  137. int Result = ERR_INVALID_PARAM;
  138. switch (No)
  139. {
  140. case OPENFILE_MULTIPLE: GETVALUE(p->Multiple,bool_t); break;
  141. case OPENFILE_CLASS: GETVALUE(p->Class,int); break;
  142. case OPENFILE_FLAGS: GETVALUE(p->Flags,int); break;
  143. case OPENFILE_FILETYPE: GETVALUE(p->FileType,int); break;
  144. case OPENFILE_FILETYPE_SINGLE: GETVALUE(p->FileTypeSingle,int); break;
  145. case OPENFILE_FILETYPE_SAVE: GETVALUE(p->FileTypeSave,int); break;
  146. case OPENFILE_PATH: GETSTRING(p->Path); break;
  147. case OPENFILE_SORTCOL: GETVALUE(p->SortCol,int); break;
  148. case OPENFILE_SORTDIR: GETVALUE(p->SortDir,bool_t); break;
  149. case OPENFILE_WIDTH_NAME: GETVALUE(p->DlgWidth[0],int); break;
  150. case OPENFILE_WIDTH_TYPE: GETVALUE(p->DlgWidth[1],int); break;
  151. case OPENFILE_WIDTH_SIZE: GETVALUE(p->DlgWidth[2],int); break;
  152. case OPENFILE_WIDTH_DATE: GETVALUE(p->DlgWidth[3],int); break;
  153. case OPENFILE_HISTORYCOUNT: GETVALUE(p->HistoryCount,int); break;
  154. case OPENFILE_ONLYNAME: GETVALUE(p->OnlyName,bool_t); break;
  155. case OPENFILE_SAVE_NAME: GETSTRING(p->SaveName); break;
  156. case OPENFILE_SAVE_TYPE: GETVALUE(p->FileTypeSave,int); break;
  157. }
  158. if (No >= OPENFILE_HISTORY && No < OPENFILE_HISTORY+p->HistoryCount && p->History[No-OPENFILE_HISTORY])
  159. GETSTRING(p->History[No-OPENFILE_HISTORY]);
  160. return Result;
  161. }
  162. static void SetColWidth(openfile* p, int Index,int Width)
  163. {
  164. ListView_SetColumnWidth(p->WndList,Index,WinUnitToPixelX(&p->Win,Width));
  165. }
  166. static int GetColWidth(openfile* p, int Index)
  167. {
  168. if (p->Win.Smartphone)
  169. return p->DlgWidth[Index]; // no GUI update possible
  170. return WinPixelToUnitX(&p->Win,ListView_GetColumnWidth(p->WndList,Index));
  171. }
  172. static int UpdateOnlyName(openfile* p)
  173. {
  174. int i;
  175. if (p->OnlyName != p->OnlyNameState)
  176. {
  177. WinMenuCheck(&p->Win,1,OPENFILE_ONLYNAME,p->OnlyName);
  178. p->OnlyNameState = p->OnlyName;
  179. if (p->OnlyName)
  180. {
  181. for (i=0;i<4;++i)
  182. p->DlgWidth[i] = GetColWidth(p,i);
  183. ShowWindow(p->WndList,SW_HIDE);
  184. SetColWidth(p,3,0);
  185. SetColWidth(p,2,0);
  186. SetColWidth(p,1,0);
  187. SetColWidth(p,0,300);
  188. ShowWindow(p->WndList,SW_SHOWNA);
  189. }
  190. else
  191. {
  192. ShowWindow(p->WndList,SW_HIDE);
  193. for (i=3;i>=0;--i)
  194. SetColWidth(p,i,max(15,p->DlgWidth[i]));
  195. ShowWindow(p->WndList,SW_SHOWNA);
  196. }
  197. }
  198. return ERR_NONE;
  199. }
  200. static int Set(openfile* p,int No,const void* Data,int Size)
  201. {
  202. int Result = ERR_INVALID_PARAM;
  203. switch (No)
  204. {
  205. case OPENFILE_MULTIPLE: SETVALUE(p->Multiple,bool_t,ERR_NONE); break;
  206. case OPENFILE_FLAGS: SETVALUE(p->Flags,int,ERR_NONE); break;
  207. case OPENFILE_CLASS: SETVALUE(p->Class,int,ERR_NONE); break;
  208. case OPENFILE_FILETYPE: SETVALUE(p->FileType,int,ERR_NONE); break;
  209. case OPENFILE_FILETYPE_SINGLE: SETVALUE(p->FileTypeSingle,int,ERR_NONE); break;
  210. case OPENFILE_FILETYPE_SAVE: SETVALUE(p->FileTypeSave,int,ERR_NONE); break;
  211. case OPENFILE_PATH: SETSTRING(p->Path); break;
  212. case OPENFILE_SORTCOL: SETVALUE(p->SortCol,int,ERR_NONE); break;
  213. case OPENFILE_SORTDIR: SETVALUE(p->SortDir,bool_t,ERR_NONE); break;
  214. case OPENFILE_WIDTH_NAME: SETVALUE(p->DlgWidth[0],int,ERR_NONE); break;
  215. case OPENFILE_WIDTH_TYPE: SETVALUE(p->DlgWidth[1],int,ERR_NONE); break;
  216. case OPENFILE_WIDTH_SIZE: SETVALUE(p->DlgWidth[2],int,ERR_NONE); break;
  217. case OPENFILE_ONLYNAME: SETVALUE(p->OnlyName,bool_t,UpdateOnlyName(p)); break;
  218. case OPENFILE_HISTORYCOUNT: SETVALUE(p->HistoryCount,int,ERR_NONE); break;
  219. case OPENFILE_SAVE_NAME: SETSTRING(p->SaveName); break;
  220. case OPENFILE_SAVE_TYPE: SETVALUE(p->FileTypeSave,int,ERR_NONE); break;
  221. }
  222. if (No >= OPENFILE_HISTORY && No < OPENFILE_HISTORY+p->HistoryCount)
  223. {
  224. free(p->History[No-OPENFILE_HISTORY]);
  225. p->History[No-OPENFILE_HISTORY] = tcsdup((tchar_t*)Data);
  226. Result = ERR_NONE;
  227. }
  228. return Result;
  229. }
  230. static void AddCol(openfile* p, int Index, const tchar_t* Name, int Width, int Format )
  231. {
  232. LVCOLUMN Col;
  233. Col.mask=LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
  234. Col.cx=WinUnitToPixelX(&p->Win,Width);
  235. Col.pszText=(tchar_t*)Name;
  236. Col.cchTextMax=tcslen(Name)+1;
  237. Col.fmt=Format;
  238. ListView_InsertColumn(p->WndList,Index,&Col);
  239. }
  240. static int CALLBACK CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  241. {
  242. openfile* p = (openfile*)lParamSort;
  243. openitem* a = (openitem*)lParam1;
  244. openitem* b = (openitem*)lParam2;
  245. int Result = 0;
  246. if (!a) return b?-1:0;
  247. if (!b) return 1;
  248. if (a->Image==IMG_DIR)
  249. if (b->Image==IMG_DIR)
  250. Result = tcsicmp(a->Name,b->Name);
  251. else
  252. Result = -1;
  253. else
  254. if (b->Image==IMG_DIR)
  255. Result = 1;
  256. else
  257. switch(p->SortCol)
  258. {
  259. case 0: 
  260. Result = tcsicmp(a->Name,b->Name); 
  261. break;
  262. case 1: 
  263. Result = tcsicmp(a->Ext,b->Ext); 
  264. if (!Result) 
  265. Result = tcsicmp(a->Name,b->Name);
  266. break;
  267. case 2: 
  268. if (a->Size == b->Size) 
  269. Result = tcsicmp(a->Name,b->Name);
  270. else
  271. Result = a->Size > b->Size ? 1:-1;
  272. break;
  273. case 3:
  274. if (a->Date == b->Date) 
  275. Result = tcsicmp(a->Name,b->Name);
  276. else
  277. Result = a->Date > b->Date ? 1:-1;
  278. break;
  279. }
  280. if (p->SortDir)
  281. Result = -Result;
  282. return Result;
  283. }
  284. static void SavePos(openfile* p)
  285. {
  286. LVITEM Item;
  287. int n;
  288. p->Last[0] = 0;
  289. for (n=0;n<ListView_GetItemCount(p->WndList);++n)
  290. if (ListView_GetItemState(p->WndList,n,LVIS_FOCUSED)==LVIS_FOCUSED)
  291. {
  292. Item.iItem=n;
  293. Item.iSubItem = 0;
  294. Item.mask=LVIF_PARAM;
  295. ListView_GetItem(p->WndList,&Item);
  296. if (Item.lParam)
  297. tcscpy_s(p->Last,TSIZEOF(p->Last),((openitem*)Item.lParam)->Name);
  298. break;
  299. }
  300. }
  301. static void ClearList(openfile* p)
  302. {
  303. LVITEM Item;
  304. int n;
  305. for (n=0;n<ListView_GetItemCount(p->WndList);++n)
  306. {
  307. Item.iItem=n;
  308. Item.iSubItem=0;
  309. Item.mask=LVIF_PARAM;
  310. ListView_GetItem(p->WndList,&Item);
  311. if (Item.lParam)
  312. free((void*)Item.lParam);
  313. }
  314. ListView_DeleteAllItems(p->WndList);
  315. }
  316. static void SelectAll(openfile* p)
  317. {
  318. LVITEM Item;
  319. int n;
  320. int State;
  321. p->OwnSelect = 1;
  322. for (n=0;n<ListView_GetItemCount(p->WndList);++n)
  323. {
  324. Item.iItem=n;
  325. Item.iSubItem=0;
  326. Item.mask=LVIF_PARAM;
  327. ListView_GetItem(p->WndList,&Item);
  328. State = 0;
  329. if (Item.lParam && (((openitem*)Item.lParam)->Image != IMG_DIR || p->SelectDir))
  330. State = LVIS_SELECTED;
  331. ListView_SetItemState(p->WndList,n,State,LVIS_SELECTED);
  332. }
  333. p->OwnSelect = 0;
  334. }
  335. static void UpdateSelectDir(openfile* p)
  336. {
  337. if (p->Flags & OPENFLAG_SINGLE) 
  338. return;
  339. if (p->Win.Smartphone)
  340. {
  341. WinMenuCheck(&p->Win,1,OPENFILE_SELECTDIR2,p->SelectDir);
  342. }
  343. else
  344. {
  345. TBBUTTONINFO Button;
  346. Button.cbSize = sizeof(Button);
  347. Button.dwMask = TBIF_STATE;
  348. Button.fsState = TBSTATE_ENABLED;
  349. if (p->SelectDir)
  350. Button.fsState |= TBSTATE_CHECKED;
  351. SendMessage(p->Win.WndTB,TB_SETBUTTONINFO,OPENFILE_SELECTDIR,(LPARAM)&Button);
  352. }
  353. }
  354. static void UpdateMultiple(openfile* p)
  355. {
  356. int Count,i;
  357. if (p->Flags & OPENFLAG_SINGLE) 
  358. return;
  359. if (p->Win.Smartphone)
  360. {
  361. WinMenuCheck(&p->Win,1,OPENFILE_MORE,p->Multiple);
  362. }
  363. else
  364. {
  365. TBBUTTONINFO Button;
  366. Button.cbSize = sizeof(Button);
  367. Button.dwMask = TBIF_STATE;
  368. Button.fsState = TBSTATE_ENABLED;
  369. if (p->Multiple)
  370. Button.fsState |= TBSTATE_CHECKED;
  371. SendMessage(p->Win.WndTB,TB_SETBUTTONINFO,OPENFILE_MORE,(LPARAM)&Button);
  372. }
  373. p->OwnSelect = 1;
  374. Count = ListView_GetItemCount(p->WndList);
  375. for (i=0;i<Count;++i)
  376. {
  377. int State = 0;
  378. if (!p->Multiple && ListView_GetItemState(p->WndList,i,LVIS_FOCUSED)==LVIS_FOCUSED)
  379. State = LVIS_SELECTED;
  380. ListView_SetItemState(p->WndList,i,State,LVIS_SELECTED);
  381. }
  382. p->OwnSelect = 0;
  383. }
  384. static void SetURLText(openfile* p,const tchar_t* s)
  385. {
  386. int Len = tcslen(s);
  387. ++p->InUpdate;
  388. SetWindowText(p->WndURL,s);
  389. if (p->Win.Smartphone)
  390. SendMessage(p->WndURL,EM_SETSEL,Len,Len);
  391. else
  392. SendMessage(p->WndURL,CB_SETEDITSEL,0,MAKEWORD(-1,-1));
  393. --p->InUpdate;
  394. }
  395. static void AddHistory(openfile* p,const tchar_t* s)
  396. {
  397. int i;
  398. for (i=0;i<p->HistoryCount;++i)
  399. if (p->History[i] && tcsicmp(p->History[i],s)==0)
  400. {
  401. for (;i>0;--i)
  402. SwapPChar(&p->History[i],&p->History[i-1]);
  403. break;
  404. }
  405. if (i==p->HistoryCount)
  406. {
  407. if (i<MAXHISTORY)
  408. p->HistoryCount++;
  409. else
  410. free(p->History[--i]);
  411. for (;i>0;--i)
  412. p->History[i] = p->History[i-1];
  413. p->History[0] = tcsdup(s);
  414. }
  415. if (!p->Win.Smartphone)
  416. {
  417. int i;
  418. SendMessage(p->WndURL,CB_RESETCONTENT,0,0);
  419. for (i=0;i<p->HistoryCount;++i)
  420. if (p->History[i])
  421. SendMessage(p->WndURL,CB_ADDSTRING,0,(LPARAM)p->History[i]);
  422. }
  423. SetURLText(p,s);
  424. }
  425. static void UpdateList(openfile* p, bool_t Silent, int ListMode)
  426. {
  427. streamdir DirItem;
  428. stream* Stream;
  429. int Result;
  430. openitem New;
  431. LVITEM Item;
  432. int No=0;
  433. int Pos=0;
  434. int State = LVIS_FOCUSED;
  435. int Len;
  436. const tchar_t* s;
  437. bool_t HasHost;
  438. if (!p->Multiple || (p->Flags & OPENFLAG_SINGLE))
  439. State |= LVIS_SELECTED; 
  440. Len = tcslen(p->Path);
  441. if (Len && (p->Path[Len-1] == '\' || p->Path[Len-1] == '/'))
  442. p->Path[--Len] = 0;
  443. tcscpy_s(p->Base,TSIZEOF(p->Base),p->Path);
  444. s = p->Path[0] ? p->Path : T("\");
  445. AddHistory(p,s);
  446. if (!ListMode)
  447. return;
  448. ++p->InUpdate;
  449. WaitBegin();
  450. ShowWindow(p->WndList,SW_HIDE);
  451. ClearList(p);
  452. Item.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
  453. Item.pszText=T("");
  454. Item.cchTextMax=1;
  455. Item.iSubItem=0;
  456. Stream = GetStream(p->Path,Silent);
  457. if (Stream)
  458. {
  459. s = GetMime(p->Path,NULL,0,&HasHost);
  460. if (*s)
  461. {
  462. Item.iImage=IMG_DIRUP;
  463. Item.iItem = No;
  464. Item.lParam = 0;
  465. ListView_InsertItem(p->WndList,&Item);
  466. ListView_SetItemText(p->WndList,No,0,T(".."));
  467. ListView_SetItemText(p->WndList,No,1,(tchar_t*)LangStr(OPENFILE_ID,OPENFILE_UP));
  468. ++No;
  469. }
  470. Result = Stream->EnumDir(Stream,p->Path,p->Exts,*p->CurrentFileType!=-1,&DirItem);
  471. if (ListMode==2 && Result == ERR_FILE_NOT_FOUND && UpperPath(p->Path,p->Last,TSIZEOF(p->Last)))
  472. {
  473. WaitEnd();
  474. --p->InUpdate;
  475. p->LastClick = -1;
  476. UpdateList(p,Silent,ListMode);
  477. return;
  478. }
  479. if (Result == ERR_NOT_DIRECTORY && !Silent)
  480. {
  481. New.FileName[0] = 0;
  482. New.Ext[0] = 0;
  483. New.Image = IMG_FILE;
  484. New.Size = 0;
  485. Item.lParam = (DWORD)malloc(sizeof(openitem));
  486. if (Item.lParam)
  487. {
  488. p->Last[0] = 0;
  489. Pos = No;
  490. State = LVIS_SELECTED;
  491. PostMessage(p->Win.Wnd,WM_COMMAND,PLATFORM_OK,0);
  492. *(openitem*)Item.lParam = New;
  493. Item.iItem = No;
  494. Item.iImage = New.Image;
  495. ListView_InsertItem(p->WndList,&Item);
  496. ++No;
  497. }
  498. }
  499. if (Result == ERR_NONE)
  500. Stream->Get(Stream,STREAM_BASE,p->Base,sizeof(p->Base));
  501. while (Result == ERR_NONE)
  502. {
  503. tchar_t Size[32];
  504. tchar_t Date[32];
  505. int i;
  506. for (i=0;i<No;++i)
  507. {
  508. LVITEM Item;
  509. Item.iItem=i;
  510. Item.iSubItem = 0;
  511. Item.mask=LVIF_PARAM;
  512. ListView_GetItem(p->WndList,&Item);
  513. if (Item.lParam && tcscmp(((openitem*)Item.lParam)->FileName,DirItem.FileName)==0)
  514. break;
  515. }
  516. if (i==No)
  517. {
  518. tchar_t DisplayName[MAXPATH];
  519. tcscpy_s(New.FileName,TSIZEOF(New.FileName),DirItem.FileName);
  520. New.DisplayName = DirItem.DisplayName[0] != 0;
  521. tcscpy_s(DisplayName,TSIZEOF(DisplayName),New.DisplayName?DirItem.DisplayName:DirItem.FileName);
  522. Size[0] = 0;
  523. Date[0] = 0;
  524. if (DirItem.Size < 0)
  525. {
  526. New.Image = IMG_DIR;
  527. New.Size = 0;
  528. New.Date = 0;
  529. tcscpy_s(New.Ext,TSIZEOF(New.Ext),LangStr(OPENFILE_ID,OPENFILE_DIR));
  530. tcscpy_s(New.Name,TSIZEOF(New.Name),DisplayName); //keep extension
  531. }
  532. else
  533. {
  534. switch (DirItem.Type)
  535. {
  536. case FTYPE_AUDIO: New.Image = IMG_AUDIO; break;
  537. case FTYPE_PLAYLIST: New.Image = IMG_PLAYLIST; break;
  538. case FTYPE_VIDEO: New.Image = IMG_VIDEO; break;
  539. default: New.Image = IMG_FILE; break;
  540. }
  541. New.Size = DirItem.Size;
  542. New.Date = DirItem.Date;
  543. SplitURL(DisplayName,NULL,0,NULL,0,New.Name,TSIZEOF(New.Name),New.Ext,TSIZEOF(New.Ext));
  544. tcsupr(New.Ext);
  545. if (New.Size >= 0)
  546. {
  547. if (New.Size < 10000*1024)
  548. stprintf_s(Size,TSIZEOF(Size),T("%d KB"),New.Size/1024);
  549. else
  550. stprintf_s(Size,TSIZEOF(Size),T("%d MB"),New.Size/(1024*1024));
  551. }
  552. if (New.Date >= 0)
  553. {
  554. FILETIME Time;
  555. SYSTEMTIME SysTime;
  556. Time.dwHighDateTime = (DWORD)(New.Date >> 32);
  557. Time.dwLowDateTime = (DWORD)(New.Date);
  558. if (FileTimeToSystemTime(&Time,&SysTime))
  559. GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&SysTime,NULL,Date,TSIZEOF(Date));
  560. }
  561. }
  562. Item.lParam = (DWORD)malloc(sizeof(openitem));
  563. if (Item.lParam)
  564. {
  565. *(openitem*)Item.lParam = New;
  566. Item.iItem = No;
  567. Item.iImage = New.Image;
  568. ListView_InsertItem(p->WndList,&Item);
  569. ListView_SetItemText(p->WndList,No,0,New.Name);
  570. ListView_SetItemText(p->WndList,No,1,New.Ext);
  571. ListView_SetItemText(p->WndList,No,2,Size);
  572. ListView_SetItemText(p->WndList,No,3,Date);
  573. ++No;
  574. }
  575. }
  576. Result = Stream->EnumDir(Stream,NULL,NULL,0,&DirItem);
  577. }
  578. NodeDelete((node*)Stream);
  579. }
  580. ListView_SortItems(p->WndList,CompareProc,p);
  581. ShowWindow(p->WndList,SW_SHOWNA);
  582. if (p->Last[0])
  583. {
  584. int i;
  585. for (i=0;i<No;++i)
  586. {
  587. LVITEM Item;
  588. Item.iItem=i;
  589. Item.iSubItem = 0;
  590. Item.mask=LVIF_PARAM;
  591. ListView_GetItem(p->WndList,&Item);
  592. if (Item.lParam && tcsicmp(((openitem*)Item.lParam)->Name,p->Last)==0)
  593. {
  594. Pos = i;
  595. break;
  596. }
  597. }
  598. }
  599. SetFocus(p->WndList);
  600. p->OwnSelect = 1;
  601. ListView_SetItemState(p->WndList,Pos,State,State);
  602. p->OwnSelect = 0;
  603. ListView_EnsureVisible(p->WndList,Pos,TRUE);
  604. WaitEnd();
  605. --p->InUpdate;
  606. }
  607. static void UpdateMenu(openfile* p)
  608. {
  609. int No;
  610. int* i;
  611. p->TypesMenu = WinMenuFind(&p->Win,OPENFILE_ALL_FILES);
  612. WinMenuInsert(&p->Win,p->TypesMenu,OPENFILE_ALL_FILES,OPENFILE_TYPES-1,LangStr(p->Class,0));
  613. ArrayClear(&p->Types);
  614. NodeEnumClass(&p->Types,p->Class);
  615. for (No=0,i=ARRAYBEGIN(p->Types,int);i!=ARRAYEND(p->Types,int);++i,++No)
  616. {
  617. const tchar_t* Name = LangStr(*i,NODE_NAME);
  618. if (Name[0] && UniqueExts(ARRAYBEGIN(p->Types,int),i))
  619. WinMenuInsert(&p->Win,p->TypesMenu,OPENFILE_ALL_FILES,OPENFILE_TYPES+No,Name);
  620. }
  621. }
  622. static void UpdateSort(openfile* p)
  623. {
  624. WinMenuCheck(&p->Win,1,OPENFILE_LABEL_NAME,p->SortCol==0);
  625. WinMenuCheck(&p->Win,1,OPENFILE_LABEL_TYPE,p->SortCol==1);
  626. WinMenuCheck(&p->Win,1,OPENFILE_LABEL_SIZE,p->SortCol==2);
  627. WinMenuCheck(&p->Win,1,OPENFILE_LABEL_DATE,p->SortCol==3);
  628. ListView_SortItems(p->WndList, CompareProc, (LPARAM)p);
  629. }
  630. static void UpdateFileType(openfile* p,int ListMode)
  631. {
  632. int No;
  633. int* i;
  634. int FileType;
  635. if (p->InUpdate)
  636. return;
  637. FileType = *p->CurrentFileType;
  638. if (FileType && FileType!=-1 && !NodeEnumClass(NULL,FileType))
  639. FileType = *p->CurrentFileType = 0;
  640. WinMenuCheck(&p->Win,p->TypesMenu,OPENFILE_TYPES-1,FileType==0);
  641. WinMenuCheck(&p->Win,p->TypesMenu,OPENFILE_ALL_FILES,FileType==-1);
  642. p->Exts[0]=0;
  643. for (No=0,i=ARRAYBEGIN(p->Types,int);i!=ARRAYEND(p->Types,int);++i,++No)
  644. {
  645. WinMenuCheck(&p->Win,p->TypesMenu,OPENFILE_TYPES+No,FileType==*i);
  646. if (FileType==*i || FileType==0 || FileType==-1)
  647. {
  648. const tchar_t *Exts = LangStr(*i,NODE_EXTS);
  649. if (Exts[0])
  650. {
  651. if (p->Exts[0]) tcscat_s(p->Exts,TSIZEOF(p->Exts),T(";"));
  652. tcscat_s(p->Exts,TSIZEOF(p->Exts),Exts);
  653. }
  654. }
  655. }
  656. p->Last[0] = 0;
  657. UpdateList(p,1,ListMode);
  658. }
  659. static void SetSaveName(openfile* p,int Pos)
  660. {
  661. LVITEM Item;
  662. Item.iItem=Pos;
  663. Item.iSubItem=0;
  664. Item.mask=LVIF_PARAM;
  665. if (ListView_GetItem(p->WndList,&Item) && Item.lParam && ((openitem*)Item.lParam)->Image != IMG_DIR)
  666. {
  667. int* i;
  668. SplitURL(((openitem*)Item.lParam)->FileName,NULL,0,NULL,0,p->SaveName,TSIZEOF(p->SaveName),p->SaveName,TSIZEOF(p->SaveName));
  669. for (i=ARRAYBEGIN(p->Types,int);i!=ARRAYEND(p->Types,int);++i)
  670. if (CheckExts(p->SaveName,LangStr(*i,NODE_EXTS)))
  671. {
  672. tchar_t *s = tcsrchr(p->SaveName,'.');
  673. if (s) *s = 0;
  674. p->FileTypeSave = *i;
  675. WinPropUpdate(&p->Win,&p->Win.Node,OPENFILE_FILETYPE_SAVE);
  676. break;
  677. }
  678. WinPropUpdate(&p->Win,&p->Win.Node,OPENFILE_SAVE_NAME);
  679. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_SAVE_NAME,1);
  680. }
  681. }
  682. static void Save(openfile* p)
  683. {
  684. player* Player = (player*)Context()->Player;
  685. if (Player)
  686. {
  687. tchar_t URL[MAXPATH];
  688. tchar_t Exts[MAXPATH];
  689. if (!p->SaveName[0])
  690. {
  691. ShowError(0,OPENFILE_ID,OPENFILE_EMPTYNAME);
  692. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_SAVE_NAME,1);
  693. return;
  694. }
  695. else
  696. {
  697. AbsPath(URL,TSIZEOF(URL),p->SaveName,p->Base);
  698. SplitURL(p->SaveName,NULL,0,NULL,0,NULL,0,Exts,TSIZEOF(Exts));
  699. if (!Exts[0])
  700. {
  701. tchar_t* s;
  702. tcscpy_s(Exts,TSIZEOF(Exts),LangStr(p->FileTypeSave,NODE_EXTS));
  703. s = tcschr(Exts,':');
  704. if (s) *s = 0;
  705. SetFileExt(URL,TSIZEOF(URL),Exts);
  706. }
  707. PlayerSaveList(Player,URL,p->FileTypeSave);
  708. }
  709. }
  710. WinClose(&p->Win);
  711. }
  712. static bool_t IsSelected(openfile* p)
  713. {
  714. int Count,i;
  715. Count = ListView_GetItemCount(p->WndList);
  716. for (i=0;i<Count;++i)
  717. if (ListView_GetItemState(p->WndList,i,LVIS_SELECTED)==LVIS_SELECTED)
  718. {
  719. LVITEM Item;
  720. Item.iItem=i;
  721. Item.iSubItem=0;
  722. Item.mask=LVIF_PARAM;
  723. if (ListView_GetItem(p->WndList,&Item) && Item.lParam && (((openitem*)Item.lParam)->Image != IMG_DIR || p->SelectDir))
  724. break;
  725. }
  726. return i<Count;
  727. }
  728. static void SelectIfNone(openfile* p,int Pos)
  729. {
  730. if (!IsSelected(p))
  731. {
  732. p->OwnSelect = 1;
  733. ListView_SetItemState(p->WndList,Pos,LVIS_SELECTED,LVIS_SELECTED);
  734. p->OwnSelect = 0;
  735. }
  736. }
  737. static void Add(openfile* p)
  738. {
  739. player* Player = (player*)Context()->Player;
  740. bool_t Add = (p->Flags & OPENFLAG_ADD) != 0;
  741. bool_t b;
  742. int Count,n,i;
  743. if (Player && IsSelected(p))
  744. {
  745. if (p->Class != SKIN_CLASS)
  746. {
  747. if (Add)
  748. {
  749. Player->Get(Player,PLAYER_LIST_COUNT,&n,sizeof(n));
  750. Add = n>0;
  751. }
  752. else
  753. {
  754. b = 0;
  755. Player->Set(Player,PLAYER_PLAY,&b,sizeof(b));
  756. n = 0;
  757. Player->Set(Player,PLAYER_LIST_COUNT,&n,sizeof(n));
  758. }
  759. }
  760. Count = ListView_GetItemCount(p->WndList);
  761. for (i=0;i<Count;++i)
  762. if (ListView_GetItemState(p->WndList,i,LVIS_SELECTED)==LVIS_SELECTED)
  763. {
  764. LVITEM Item;
  765. Item.iItem=i;
  766. Item.iSubItem=0;
  767. Item.mask=LVIF_PARAM;
  768. if (ListView_GetItem(p->WndList,&Item) && Item.lParam && (((openitem*)Item.lParam)->Image != IMG_DIR || p->SelectDir))
  769. {
  770. tchar_t URL[MAXPATH];
  771. if (((openitem*)Item.lParam)->FileName[0])
  772. AbsPath(URL,TSIZEOF(URL),((openitem*)Item.lParam)->FileName,p->Base);
  773. else
  774. tcscpy_s(URL,TSIZEOF(URL),p->Path);
  775. if (p->Class == SKIN_CLASS)
  776. {
  777. p->Win.Parent->Node.Set(&p->Win.Parent->Node,IF_SKINPATH,URL,TSIZEOF(URL));
  778. }
  779. else
  780. if (((openitem*)Item.lParam)->Image == IMG_DIR)
  781. n = PlayerAddDir(Player,n,URL,p->Exts,*p->CurrentFileType!=-1,0);
  782. else
  783. n = PlayerAdd(Player,n,URL,((openitem*)Item.lParam)->DisplayName?((openitem*)Item.lParam)->Name:NULL);
  784. }
  785. }
  786. if (!Add)
  787. p->Win.Result = 2;
  788. }
  789. WinClose(&p->Win);
  790. }
  791. static void Resize(openfile* p)
  792. {
  793. RECT r;
  794. int BorderX = WinUnitToPixelX(&p->Win,1);
  795. int BorderY = WinUnitToPixelY(&p->Win,1);
  796. int URLHeight;
  797. GetClientRect(p->Win.Wnd,&r);
  798. r.left += BorderX;
  799. r.right -= BorderX;
  800. if (p->Win.Smartphone)
  801. {
  802. URLHeight = WinUnitToPixelY(&p->Win,15);
  803. MoveWindow(p->WndURL,r.left,p->Top+BorderY,r.right-r.left,URLHeight-2*BorderY,0);
  804. }
  805. else
  806. {
  807. RECT Combo;
  808. int ButtonWidth = WinUnitToPixelX(&p->Win,30);
  809. SendMessage(p->WndURL,CB_SHOWDROPDOWN,0,0);
  810. r.right -= ButtonWidth;
  811. MoveWindow(p->WndURL,r.left,p->Top+BorderY,r.right-r.left-BorderX,WinUnitToPixelY(&p->Win,200),0);
  812. GetWindowRect(p->WndURL,&Combo);
  813. URLHeight = Combo.bottom - Combo.top + BorderY*2;
  814. MoveWindow(p->WndGo,r.right,p->Top+BorderY,ButtonWidth,URLHeight-BorderY*2,0);
  815. }
  816. GetClientRect(p->Win.Wnd,&r);
  817. r.top += p->Win.ToolBarHeight;
  818. MoveWindow(p->Win.WndDialog,r.left,r.top,r.right-r.left,URLHeight+p->Top,0);
  819. r.top += p->Top+URLHeight;
  820. MoveWindow(p->WndList,r.left,r.top,r.right-r.left,r.bottom-r.top,0);
  821. }
  822. static void InitMenu(openfile* p)
  823. {
  824. int i;
  825. if (!WinMenuEnable(&p->Win,1,OPENFILE_EMPTY,0))
  826. {
  827. WinMenuInsert(&p->Win,1,OPENFILE_HISTORY+1,OPENFILE_EMPTY,LangStr(OPENFILE_ID,OPENFILE_EMPTY));
  828. for (i=1;i<MAXHISTORY;++i)
  829. WinMenuDelete(&p->Win,1,OPENFILE_HISTORY+i);
  830. }
  831. if (p->HistoryCount>1)
  832. {
  833. for (i=1;i<MAXHISTORY;++i)
  834. WinMenuInsert(&p->Win,1,OPENFILE_EMPTY,OPENFILE_HISTORY+i,p->History[i]);
  835. WinMenuDelete(&p->Win,1,OPENFILE_EMPTY);
  836. }
  837. else
  838. WinMenuEnable(&p->Win,1,OPENFILE_EMPTY,0);
  839. }
  840. static bool_t DialogProc(openfile* p,int Msg, uint32_t wParam, uint32_t lParam, int* Result)
  841. {
  842. int i;
  843. switch (Msg)
  844. {
  845. case WM_KEYDOWN:
  846. if (wParam == VK_RETURN)
  847. PostMessage(p->Win.Wnd,WM_COMMAND,PLATFORM_OK,0);
  848. break;
  849. case WM_COMMAND:
  850. if (p->WndGo == (HWND)lParam && HIWORD(wParam)==BN_CLICKED && !p->InUpdate)
  851. SendMessage(p->Win.Wnd,WM_COMMAND,OPENFILE_GO,0);
  852. if (p->WndURL == (HWND)lParam)
  853. {
  854. if (p->Win.Smartphone)
  855. {
  856. switch (HIWORD(wParam))
  857. {
  858. case EN_SETFOCUS:
  859. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_URL,0);
  860. p->Win.CaptureKeys = 1;
  861. break;
  862. case EN_KILLFOCUS:
  863. p->Win.CaptureKeys = 0;
  864. break;
  865. }
  866. }
  867. else
  868. {
  869. switch (HIWORD(wParam))
  870. {
  871. case CBN_CLOSEUP:
  872. if (!p->InUpdate)
  873. {
  874. i = SendMessage(p->WndURL,CB_GETCURSEL,0,0);
  875. if (i!=CB_ERR && i>0 && i < p->HistoryCount)
  876. {
  877. SetURLText(p,p->History[i]);
  878. PostMessage(p->Win.Wnd,WM_COMMAND,OPENFILE_GO,0);
  879. }
  880. }
  881. break;
  882. case CBN_SETFOCUS:
  883. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_URL,0);
  884. p->Win.CaptureKeys = 1;
  885. break;
  886. case CBN_KILLFOCUS:
  887. p->Win.CaptureKeys = 0;
  888. break;
  889. }
  890. }
  891. }
  892. }
  893. return 0;
  894. }
  895. static const menudef MenuDef[] =
  896. {
  897. { 0,PLATFORM_ID, PLATFORM_OK },
  898. { 0,OPENFILE_ID, OPENFILE_FILTER },
  899. { 1,OPENFILE_ID, OPENFILE_ALL_FILES },
  900. { 0,PLATFORM_ID, PLATFORM_CANCEL },
  901. { 0,-1,-1 },
  902. { 0,OPENFILE_ID, OPENFILE_MORE },
  903. { 0,-1,-1 },
  904. { 0,OPENFILE_ID, OPENFILE_SELECTALL },
  905. { 0,-1,-1 },
  906. { 0,OPENFILE_ID, OPENFILE_SELECTDIR },
  907. MENUDEF_END
  908. };
  909. static const menudef MenuDefSingle[] =
  910. {
  911. { 0,PLATFORM_ID, PLATFORM_OK },
  912. { 0,OPENFILE_ID, OPENFILE_FILTER },
  913. { 1,OPENFILE_ID, OPENFILE_ALL_FILES },
  914. { 0,PLATFORM_ID, PLATFORM_CANCEL },
  915. MENUDEF_END
  916. };
  917. static const menudef MenuDefSmart[] =
  918. {
  919. { 0,PLATFORM_ID, PLATFORM_OK },
  920. { 0,OPENFILE_ID, OPENFILE_OPTIONS },
  921. { 1,OPENFILE_ID, OPENFILE_ENTERURL },
  922. { 1,OPENFILE_ID, OPENFILE_HISTORYMENU },
  923. { 2,OPENFILE_ID, OPENFILE_EMPTY },
  924. { 1,OPENFILE_ID, OPENFILE_MORE },
  925. { 1,OPENFILE_ID, OPENFILE_SELECTALL },
  926. { 1,OPENFILE_ID, OPENFILE_SELECTDIR2 },
  927. { 1,OPENFILE_ID, OPENFILE_SORT },
  928. { 2,OPENFILE_ID, OPENFILE_LABEL_NAME },
  929. { 2,OPENFILE_ID, OPENFILE_LABEL_TYPE },
  930. { 2,OPENFILE_ID, OPENFILE_LABEL_SIZE },
  931. { 2,OPENFILE_ID, OPENFILE_LABEL_DATE },
  932. { 1,OPENFILE_ID, OPENFILE_FILTER },
  933. { 2,OPENFILE_ID, OPENFILE_ALL_FILES },
  934. { 1,OPENFILE_ID, OPENFILE_ONLYNAME },
  935. { 1,PLATFORM_ID, PLATFORM_CANCEL },
  936. MENUDEF_END
  937. };
  938. static const menudef MenuDefSmartSingle[] =
  939. {
  940. { 0,PLATFORM_ID, PLATFORM_OK },
  941. { 0,OPENFILE_ID, OPENFILE_OPTIONS },
  942. { 1,OPENFILE_ID, OPENFILE_ENTERURL },
  943. { 1,OPENFILE_ID, OPENFILE_HISTORYMENU },
  944. { 2,OPENFILE_ID, OPENFILE_EMPTY },
  945. { 1,OPENFILE_ID, OPENFILE_SORT },
  946. { 2,OPENFILE_ID, OPENFILE_LABEL_NAME },
  947. { 2,OPENFILE_ID, OPENFILE_LABEL_TYPE },
  948. { 2,OPENFILE_ID, OPENFILE_LABEL_SIZE },
  949. { 2,OPENFILE_ID, OPENFILE_LABEL_DATE },
  950. { 1,OPENFILE_ID, OPENFILE_FILTER },
  951. { 2,OPENFILE_ID, OPENFILE_ALL_FILES },
  952. { 1,OPENFILE_ID, OPENFILE_ONLYNAME },
  953. { 1,PLATFORM_ID, PLATFORM_CANCEL },
  954. MENUDEF_END
  955. };
  956. static const menudef MenuDefSmartSingleSave[] =
  957. {
  958. { 0,OPENFILE_ID, OPENFILE_SAVE },
  959. { 0,OPENFILE_ID, OPENFILE_OPTIONS },
  960. { 1,OPENFILE_ID, OPENFILE_ENTERNAME },
  961. { 1,OPENFILE_ID, OPENFILE_ENTERURL },
  962. { 1,OPENFILE_ID, OPENFILE_HISTORYMENU },
  963. { 2,OPENFILE_ID, OPENFILE_EMPTY },
  964. { 1,OPENFILE_ID, OPENFILE_SORT },
  965. { 2,OPENFILE_ID, OPENFILE_LABEL_NAME },
  966. { 2,OPENFILE_ID, OPENFILE_LABEL_TYPE },
  967. { 2,OPENFILE_ID, OPENFILE_LABEL_SIZE },
  968. { 2,OPENFILE_ID, OPENFILE_LABEL_DATE },
  969. { 1,OPENFILE_ID, OPENFILE_FILTER },
  970. { 2,OPENFILE_ID, OPENFILE_ALL_FILES },
  971. { 1,OPENFILE_ID, OPENFILE_ONLYNAME },
  972. { 1,PLATFORM_ID, PLATFORM_CANCEL },
  973. MENUDEF_END
  974. };
  975. static int Command(openfile* p,int i)
  976. {
  977. if (i>=OPENFILE_HISTORY && i<OPENFILE_HISTORY+p->HistoryCount && !p->InUpdate)
  978. {
  979. SetURLText(p,p->History[i-OPENFILE_HISTORY]);
  980. PostMessage(p->Win.Wnd,WM_COMMAND,OPENFILE_GO,0);
  981. }
  982. else
  983. switch (i)
  984. {
  985. case OPENFILE_SAVE:
  986. Save(p);
  987. break;
  988. case PLATFORM_OK:
  989. if (p->Win.Focus && p->Win.Focus->Pin.No == OPENFILE_URL)
  990. SendMessage(p->Win.Wnd,WM_COMMAND,OPENFILE_GO,0);
  991. else
  992. if (p->Flags & OPENFLAG_SAVE)
  993. Save(p);
  994. else
  995. Add(p); 
  996. return ERR_NONE;
  997. case OPENFILE_TYPES-1:
  998. *p->CurrentFileType = 0;
  999. UpdateFileType(p,1);
  1000. break;
  1001. case OPENFILE_ALL_FILES:
  1002. *p->CurrentFileType = -1;
  1003. UpdateFileType(p,1);
  1004. break;
  1005. case OPENFILE_ONLYNAME:
  1006. p->OnlyName = !p->OnlyName;
  1007. UpdateOnlyName(p);
  1008. break;
  1009. case OPENFILE_LABEL_NAME:
  1010. case OPENFILE_LABEL_TYPE:
  1011. case OPENFILE_LABEL_SIZE:
  1012. case OPENFILE_LABEL_DATE:
  1013. if (i == OPENFILE_LABEL_DATE)
  1014. i = 3;
  1015. else
  1016. i -= OPENFILE_LABEL_NAME;
  1017. if (p->SortCol != i)
  1018. p->SortDir = 0;
  1019. else
  1020. p->SortDir = !p->SortDir;
  1021. p->SortCol = i;
  1022. UpdateSort(p);
  1023. break;
  1024. case OPENFILE_GO:
  1025. if (!p->InUpdate)
  1026. {
  1027. tcscpy_s(p->Last,TSIZEOF(p->Last),p->Path);
  1028. GetWindowText(p->WndURL,p->Path,TSIZEOF(p->Path));
  1029. if (tcsicmp(p->Last,p->Path)==0)
  1030. SavePos(p);
  1031. else
  1032. p->Last[0] = 0;
  1033. UpdateList(p,0,1);
  1034. }
  1035. break;
  1036. case OPENFILE_ENTERNAME:
  1037. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_SAVE_NAME,1);
  1038. break;
  1039. case OPENFILE_ENTERURL:
  1040. SendMessage(p->WndURL,EM_SETSYMBOLS,0,(LPARAM)SYMBOLS);
  1041. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_URL,1);
  1042. break;
  1043. case OPENFILE_SELECTDIR:
  1044. case OPENFILE_SELECTDIR2:
  1045. p->SelectDir = !p->SelectDir;
  1046. UpdateSelectDir(p);
  1047. break;
  1048. case OPENFILE_SELECTALL:
  1049. p->Multiple = 1;
  1050. UpdateMultiple(p);
  1051. SelectAll(p);
  1052. break;
  1053. case OPENFILE_MORE:
  1054. p->Multiple = !p->Multiple;
  1055. UpdateMultiple(p);
  1056. break;
  1057. }
  1058. if (i >= OPENFILE_TYPES && i < OPENFILE_TYPES+ARRAYCOUNT(p->Types,int))
  1059. {
  1060. *p->CurrentFileType = ARRAYBEGIN(p->Types,int)[i-OPENFILE_TYPES];
  1061. UpdateFileType(p,1);
  1062. }
  1063. return ERR_INVALID_PARAM;
  1064. }
  1065. static bool_t Proc(openfile* p,int Msg, uint32_t wParam, uint32_t lParam, int* Result)
  1066. {
  1067. LPNMLISTVIEW Notify;
  1068. int Style;
  1069. int FontSize;
  1070. wincontrol* Control;
  1071. bool_t HasHost;
  1072. tchar_t Mime[MAXMIME];
  1073. switch (Msg)
  1074. {
  1075. case WM_KEYDOWN:
  1076. if (wParam == VK_RETURN)
  1077. {
  1078. SendMessage(p->Win.Wnd,WM_COMMAND,OPENFILE_GO,0);
  1079. return 1;
  1080. }
  1081. if (wParam == VK_ESCAPE)
  1082. PostMessage(p->Win.Wnd,WM_CLOSE,0,0);
  1083. break;
  1084. case WM_INITMENUPOPUP:
  1085. InitMenu(p);
  1086. break;
  1087. case MSG_PREPARE:
  1088. p->CurrentFileType = (p->Flags & OPENFLAG_SINGLE) ? &p->FileTypeSingle : &p->FileType;
  1089. p->Last[0] = 0;
  1090. if (p->Win.Smartphone)
  1091. if (p->Flags & OPENFLAG_SAVE)
  1092. p->Win.MenuDef = MenuDefSmartSingleSave;
  1093. else
  1094. p->Win.MenuDef = (p->Flags & OPENFLAG_SINGLE) ? MenuDefSmartSingle : MenuDefSmart;
  1095. else
  1096. p->Win.MenuDef = (p->Flags & OPENFLAG_SINGLE) ? MenuDefSingle : MenuDef;
  1097. break;
  1098. case WM_CREATE:
  1099. if (p->Win.Smartphone)
  1100. {
  1101. p->WndGo = NULL;
  1102. p->WndURL = CreateWindow(T("EDIT"), NULL, WS_TABSTOP|WS_VISIBLE|WS_CHILD|WS_BORDER|ES_AUTOHSCROLL, 
  1103. 0,0,10,10,p->Win.WndDialog, NULL, p->Win.Module, NULL);
  1104. SetWindowLong(p->WndURL,GWL_USERDATA,1); // send back key to control
  1105. SendMessage(p->WndURL,EM_SETSYMBOLS,0,(LPARAM)SYMBOLS);
  1106. }
  1107. else
  1108. {
  1109. p->WndURL = CreateWindow(T("COMBOBOX"), NULL, WS_TABSTOP|WS_VISIBLE|WS_CHILD|CBS_DROPDOWN|CBS_AUTOHSCROLL, 
  1110. 0,0,10,10,p->Win.WndDialog, NULL, p->Win.Module, 0L);
  1111. p->WndGo = CreateWindow(T("BUTTON"),NULL,WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_NOTIFY,
  1112. 0,0,10,10,p->Win.WndDialog, NULL, p->Win.Module, NULL );
  1113. SetWindowText(p->WndGo,LangStr(OPENFILE_ID,OPENFILE_GO));
  1114. FontSize = 11;
  1115. SendMessage(p->WndGo,WM_SETFONT,(WPARAM)WinFont(&p->Win,&FontSize,0),0);
  1116. }
  1117. FontSize = 12;
  1118. SendMessage(p->WndURL,WM_SETFONT,(WPARAM)WinFont(&p->Win,&FontSize,0),0);
  1119. Style = WS_TABSTOP|WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL|LVS_REPORT|LVS_SHOWSELALWAYS;
  1120. if (p->Win.Smartphone)
  1121. Style |= LVS_NOCOLUMNHEADER;
  1122. p->WndList = CreateWindow(T("SysListView32"), NULL, Style,
  1123. 0,0,20,20, p->Win.Wnd, NULL, p->Win.Module, NULL);
  1124. ListView_SetExtendedListViewStyle(p->WndList,LVS_EX_FULLROWSELECT);
  1125. if (WinUnitToPixelX(&p->Win,72) >= 96*2)
  1126. ListView_SetImageList(p->WndList,
  1127. ImageList_LoadBitmap(p->Win.Module,MAKEINTRESOURCE(IDB_FICON32),32,0,0xFF00FF), LVSIL_SMALL);
  1128. else
  1129. ListView_SetImageList(p->WndList,
  1130. ImageList_LoadBitmap(p->Win.Module,MAKEINTRESOURCE(IDB_FICON16),16,0,0xFF00FF), LVSIL_SMALL);
  1131. AddCol(p,0,LangStr(OPENFILE_ID,OPENFILE_LABEL_NAME),max(15,p->DlgWidth[0]),LVCFMT_LEFT);
  1132. AddCol(p,1,LangStr(OPENFILE_ID,OPENFILE_LABEL_TYPE),max(15,p->DlgWidth[1]),LVCFMT_LEFT);
  1133. AddCol(p,2,LangStr(OPENFILE_ID,OPENFILE_LABEL_SIZE),max(15,p->DlgWidth[2]),LVCFMT_RIGHT);
  1134. AddCol(p,3,LangStr(OPENFILE_ID,OPENFILE_LABEL_DATE),max(15,p->DlgWidth[3]),LVCFMT_LEFT);
  1135. p->OnlyNameState = 0;
  1136. p->LastClick = -1;
  1137. p->Top = 0;
  1138. p->Win.LabelWidth = 40;
  1139. if (p->Flags & OPENFLAG_SAVE)
  1140. {
  1141. if (!p->FileTypeSave)
  1142. p->FileTypeSave = NodeEnumClass(NULL,p->Class);
  1143. p->Top += 2;
  1144. WinPropValue(&p->Win,&p->Top,&p->Win.Node,OPENFILE_SAVE_NAME);
  1145. p->Top += 2;
  1146. WinPropValue(&p->Win,&p->Top,&p->Win.Node,OPENFILE_SAVE_TYPE);
  1147. p->Top = WinUnitToPixelY(&p->Win,p->Top+2);
  1148. }
  1149. Control = WinPropNative(&p->Win,&p->Win.Node,OPENFILE_LIST);
  1150. Control->Control = p->WndList;
  1151. Control->ListView = 1;
  1152. Control->External = 1;
  1153. Control = WinPropNative(&p->Win,&p->Win.Node,OPENFILE_URL);
  1154. Control->Control = p->WndURL;
  1155. Control->External = 1;
  1156. p->SelectDir = 0;
  1157. Resize(p);
  1158. GetMime(p->Path,Mime,TSIZEOF(Mime),&HasHost);
  1159. UpdateMenu(p);
  1160. UpdateFileType(p,HasHost?0:2);
  1161. UpdateSort(p);
  1162. UpdateMultiple(p);
  1163. UpdateSelectDir(p);
  1164. UpdateOnlyName(p);
  1165. if (p->Flags & OPENFLAG_SAVE)
  1166. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_SAVE_NAME,1);
  1167. else
  1168. if (HasHost)
  1169. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_URL,1);
  1170. break;
  1171. case WM_DESTROY:
  1172. if (!p->OnlyNameState)
  1173. {
  1174. p->DlgWidth[0] = GetColWidth(p,0);
  1175. p->DlgWidth[1] = GetColWidth(p,1);
  1176. p->DlgWidth[2] = GetColWidth(p,2);
  1177. p->DlgWidth[3] = GetColWidth(p,3);
  1178. }
  1179. ClearList(p);
  1180. break;
  1181. case WM_SIZE:
  1182. Resize(p);
  1183. break;
  1184. case WM_NOTIFY:
  1185. Notify = (LPNMLISTVIEW) lParam;
  1186. if (Notify->hdr.hwndFrom == p->WndList)
  1187. {
  1188. if (Notify->hdr.code == NM_SETFOCUS)
  1189. WinPropFocus(&p->Win,&p->Win.Node,OPENFILE_LIST,0);
  1190. // mouse double click in multiple mode
  1191. if (p->Multiple && !(p->Flags & OPENFLAG_SINGLE) && 
  1192. Notify->hdr.code==LVN_ITEMACTIVATE && Notify->iItem==p->LastClick &&
  1193. Notify->ptAction.x >= 0 && Notify->ptAction.y >= 0)
  1194. {
  1195. LVITEM Item;
  1196. Item.iItem=Notify->iItem;
  1197. Item.iSubItem=0;
  1198. Item.mask=LVIF_PARAM;
  1199. if (ListView_GetItem(p->WndList,&Item) && Item.lParam && (((openitem*)Item.lParam)->Image != IMG_DIR || p->SelectDir))
  1200. {
  1201. SelectIfNone(p,Notify->iItem);
  1202. PostMessage(p->Win.Wnd,WM_COMMAND,PLATFORM_OK,0);
  1203. return 0;
  1204. }
  1205. }
  1206. if (Notify->hdr.code==LVN_ITEMACTIVATE || Notify->hdr.code==NM_CLICK)
  1207. {
  1208. LVITEM Item;
  1209. Item.iItem=Notify->iItem;
  1210. Item.iSubItem=0;
  1211. Item.mask=LVIF_PARAM;
  1212. p->LastClick = Notify->iItem;
  1213. if (ListView_GetItem(p->WndList,&Item))
  1214. {
  1215. tchar_t Path[MAXPATH];
  1216. if (!Item.lParam) // ".."
  1217. {
  1218. if (UpperPath(p->Path,p->Last,TSIZEOF(p->Last))) 
  1219. {
  1220. p->LastClick = -1;
  1221. UpdateList(p,1,1);
  1222. }
  1223. }
  1224. else
  1225. if (((openitem*)Item.lParam)->Image==IMG_DIR && !p->SelectDir) // directory
  1226. {
  1227. AbsPath(Path,TSIZEOF(Path),((openitem*)Item.lParam)->FileName,p->Base);
  1228. tcscpy_s(p->Path,TSIZEOF(p->Path),Path);
  1229. p->Last[0] = 0;
  1230. p->LastClick = -1;
  1231. UpdateList(p,1,1);
  1232. }
  1233. else
  1234. {
  1235. if (p->Multiple && !(p->Flags & OPENFLAG_SINGLE))
  1236. {
  1237. int State = ListView_GetItemState(p->WndList,Notify->iItem,LVIS_SELECTED) & LVIS_SELECTED;
  1238. p->OwnSelect = 1;
  1239. ListView_SetItemState(p->WndList,Notify->iItem,(State ^ LVIS_SELECTED)|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
  1240. p->OwnSelect = 0;
  1241. if (p->KeyClick)
  1242. keybd_event(VK_DOWN,1,0,0);
  1243. }
  1244. else
  1245. {
  1246. if (p->Flags & OPENFLAG_SAVE)
  1247. SetSaveName(p,Notify->iItem);
  1248. else
  1249. {
  1250. SelectIfNone(p,Notify->iItem);
  1251. PostMessage(p->Win.Wnd,WM_COMMAND,PLATFORM_OK,0);
  1252. }
  1253. }
  1254. }
  1255. }
  1256. p->KeyClick = 0;
  1257. }
  1258. if (Notify->hdr.code==LVN_KEYDOWN && ((LPNMLVKEYDOWN)lParam)->wVKey == VK_ESCAPE)
  1259. PostMessage(p->Win.Wnd,WM_CLOSE,0,0);
  1260. if (p->Multiple && !(p->Flags & OPENFLAG_SINGLE))
  1261. {
  1262. // manual focus and selection
  1263. if (Notify->hdr.code==LVN_KEYDOWN)
  1264. {
  1265. // pass one focus change after keyboard
  1266. LPNMLVKEYDOWN Key = (LPNMLVKEYDOWN) lParam;
  1267. if (Key->wVKey == VK_RETURN)
  1268. p->KeyClick = 1;
  1269. if (Key->wVKey == VK_UP ||
  1270. Key->wVKey == VK_PRIOR  ||
  1271. Key->wVKey == VK_HOME)
  1272. {
  1273. if (ListView_GetItemState(p->WndList,0,LVIS_FOCUSED)!=LVIS_FOCUSED)
  1274. p->NextFocus = 1;
  1275. }
  1276. if (Key->wVKey == VK_DOWN ||
  1277. Key->wVKey == VK_NEXT ||
  1278. Key->wVKey == VK_END)
  1279. {
  1280. if (ListView_GetItemState(p->WndList,ListView_GetItemCount(p->WndList)-1,LVIS_FOCUSED)!=LVIS_FOCUSED)
  1281. p->NextFocus = 1;
  1282. }
  1283. }
  1284. if (p->NextFocus && Notify->hdr.code==LVN_ITEMCHANGED && (Notify->uChanged & LVIF_STATE) && 
  1285. ((Notify->uOldState ^ Notify->uNewState) & LVIS_FOCUSED))
  1286. {
  1287. // clear NextFocus if the new focus has been set
  1288. if (Notify->uNewState & LVIS_FOCUSED)
  1289. p->NextFocus = 0;
  1290. if ((Notify->uOldState ^ Notify->uNewState) & LVIS_SELECTED)
  1291. {
  1292. // restore old selection
  1293. p->OwnSelect = 1;
  1294. ListView_SetItemState(p->WndList,Notify->iItem,Notify->uOldState & LVIS_SELECTED,LVIS_SELECTED);
  1295. p->OwnSelect = 0;
  1296. }
  1297. }
  1298. if (!p->OwnSelect && Notify->hdr.code==LVN_ITEMCHANGING && (Notify->uChanged & LVIF_STATE))
  1299. {
  1300. // let focus change pass (if NextFocus is set)
  1301. if (!p->NextFocus || !((Notify->uOldState ^ Notify->uNewState) & LVIS_FOCUSED))
  1302. {
  1303. *Result = 1;
  1304. return 1;
  1305. }
  1306. }
  1307. }
  1308. if (Notify->hdr.code==LVN_COLUMNCLICK)
  1309. {
  1310. if (p->SortCol != Notify->iSubItem)
  1311. p->SortDir = 0;
  1312. else
  1313. p->SortDir = !p->SortDir;
  1314. p->SortCol = Notify->iSubItem;
  1315. UpdateSort(p);
  1316. }
  1317. }
  1318. break;
  1319. }
  1320. return 0;
  1321. }
  1322. static void Delete(openfile* p)
  1323. {
  1324. int i;
  1325. #ifndef REGISTRY_GLOBAL
  1326. NodeRegSave(&p->Win.Node);
  1327. #endif
  1328. ArrayClear(&p->Types);
  1329. for (i=0;i<MAXHISTORY;++i)
  1330. free(p->History[i]);
  1331. }
  1332. static int Create(openfile* p)
  1333. {
  1334. p->OnlyName = p->Win.Smartphone;
  1335. p->DlgWidth[1] = 40;
  1336. p->DlgWidth[2] = 46;
  1337. p->DlgWidth[3] = 60;
  1338. p->Class = MEDIA_CLASS;
  1339. p->CurrentFileType = &p->FileType;
  1340. #ifdef TARGET_WIN32
  1341. p->DlgWidth[0] = 150;
  1342. p->Win.WinWidth = 320;
  1343. #else
  1344. p->DlgWidth[0] = 90;
  1345. p->Win.WinWidth = 180;
  1346. #endif
  1347. p->Win.WinHeight = 240;
  1348. p->Win.Flags |= WIN_DIALOG;
  1349. p->Win.OwnDialogSize = 1;
  1350. p->Win.Command = (wincommand)Command;
  1351. p->Win.Proc = Proc;
  1352. p->Win.DialogProc = DialogProc;
  1353. p->Win.Node.Enum = Enum;
  1354. p->Win.Node.Get = Get;
  1355. p->Win.Node.Set = Set;
  1356. return ERR_NONE;
  1357. }
  1358. static const nodedef OFile =
  1359. {
  1360. sizeof(openfile)|CF_GLOBAL,
  1361. OPENFILE_ID,
  1362. WIN_CLASS,
  1363. PRI_DEFAULT,
  1364. (nodecreate)Create,
  1365. (nodedelete)Delete,
  1366. };
  1367. void OpenFile_Init()
  1368. {
  1369. NodeRegisterClass(&OFile);
  1370. }
  1371. void OpenFile_Done()
  1372. {
  1373. NodeUnRegisterClass(OPENFILE_ID);
  1374. }
  1375. #endif