Mercurial > vba-clojure
comparison src/win32/7zip/OpenArchive.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include "../stdafx.h" | |
2 #include "../resource.h" | |
3 #include <windows.h> | |
4 #include <mmsystem.h> | |
5 #include <cstdio> | |
6 #include <cerrno> | |
7 #include <cassert> | |
8 #include <cstring> | |
9 #include <map> | |
10 #include <vector> | |
11 #include <algorithm> | |
12 #include "7zip.h" | |
13 //#include "G_main.h" | |
14 //#include "G_dsound.h" | |
15 #include "OpenArchive.h" | |
16 | |
17 LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); | |
18 static int s_archiveFileChooserResult = -1; | |
19 | |
20 static HWND s_parentHWND = NULL; | |
21 void SetArchiveParentHWND(void* hwnd) { s_parentHWND = (HWND)hwnd; } | |
22 static HWND GetArchiveParentHWND() { return s_parentHWND ? s_parentHWND : AfxGetApp()->m_pMainWnd->GetSafeHwnd(); } | |
23 | |
24 static char Str_Tmp [2048]; | |
25 | |
26 struct ArchiveFileChooserInfo | |
27 { | |
28 ArchiveFileChooserInfo(ArchiveFile& theArchive, const char** ignoreExtensions, int& numIgnoreExtensions) : archive(theArchive) | |
29 { | |
30 tryagain: | |
31 int numItems = archive.GetNumItems(); | |
32 for(int i = 0; i < numItems; i++) | |
33 { | |
34 if(archive.GetItemSize(i)) | |
35 { | |
36 const char* name = archive.GetItemName(i); | |
37 const char* ext = strrchr(name, '.'); | |
38 bool ok = true; | |
39 if(ext++) | |
40 { | |
41 for(int j = 0; j < numIgnoreExtensions; j++) | |
42 { | |
43 const char* ext2 = ignoreExtensions[j]; | |
44 const char* wild = strchr(ext2, '*'); | |
45 if(!wild) | |
46 { | |
47 if(!_stricmp(ext, ext2)) | |
48 { | |
49 ok = false; | |
50 break; | |
51 } | |
52 } | |
53 else // very limited (end only) wildcard support | |
54 { | |
55 if(!_strnicmp(ext, ext2, wild - ext2)) | |
56 { | |
57 ok = false; | |
58 break; | |
59 } | |
60 } | |
61 } | |
62 } | |
63 if(ok) | |
64 { | |
65 ArchiveFileChooserInfo::FileInfo fi = { name, i }; | |
66 files.push_back(fi); | |
67 } | |
68 } | |
69 } | |
70 | |
71 if(files.empty() && numIgnoreExtensions) | |
72 { | |
73 // try again without any exclusions if we excluded everything in the archive | |
74 numIgnoreExtensions = 0; | |
75 goto tryagain; | |
76 } | |
77 | |
78 // strip away prefix paths that are common to all the files | |
79 bool stripping = !files.empty(); | |
80 while(stripping) | |
81 { | |
82 const char* firstName = files[0].name.c_str(); | |
83 const char* slash = strchr(firstName, '\\'); | |
84 const char* slash2 = strchr(firstName, '/'); | |
85 slash = max(slash, slash2); | |
86 if(!slash++) | |
87 break; | |
88 for(size_t i = 1; i < files.size(); i++) | |
89 if(strncmp(firstName, files[i].name.c_str(), slash - firstName)) | |
90 stripping = false; | |
91 if(stripping) | |
92 for(size_t i = 0; i < files.size(); i++) | |
93 files[i].name = files[i].name.substr(slash - firstName, files[i].name.length() - (slash - firstName)); | |
94 } | |
95 | |
96 // sort by filename | |
97 std::sort(files.begin(), files.end(), FileInfo::Sort); | |
98 } | |
99 | |
100 //protected: | |
101 | |
102 struct FileInfo | |
103 { | |
104 std::string name; | |
105 int itemIndex; | |
106 | |
107 static bool Sort(const FileInfo& elem1, const FileInfo& elem2) | |
108 { | |
109 int comp = elem1.name.compare(elem2.name); | |
110 return comp ? (comp < 0) : (elem1.itemIndex < elem2.itemIndex); | |
111 } | |
112 }; | |
113 | |
114 ArchiveFile& archive; | |
115 std::vector<FileInfo> files; | |
116 }; | |
117 | |
118 static void ClearLayoutStates(); | |
119 | |
120 int ChooseItemFromArchive(ArchiveFile& archive, bool autoChooseIfOnly1, const char** ignoreExtensions, int numIgnoreExtensions) | |
121 { | |
122 int prevNumIgnoreExtensions = numIgnoreExtensions; | |
123 archive.m_userMadeSelection = false; | |
124 | |
125 // prepare a list of files to choose from the archive | |
126 ArchiveFileChooserInfo info (archive, ignoreExtensions, numIgnoreExtensions); | |
127 | |
128 // based on our list, decide which item in the archive to choose | |
129 | |
130 // check if there's nothing | |
131 if(info.files.size() < 1) | |
132 { | |
133 MessageBox(GetArchiveParentHWND(), "The archive is either empty or encrypted.", "Nothing to load!", MB_OK | MB_ICONWARNING); | |
134 return -1; | |
135 } | |
136 | |
137 // warn if all the files in the archive have extensions we should ignore | |
138 if(numIgnoreExtensions != prevNumIgnoreExtensions) | |
139 { | |
140 CString msg; | |
141 msg.Format("The archive appears to only contain the wrong type of files.\n\n(in \"%s\")", archive.GetArchiveFileName()); | |
142 int answer = MessageBox(GetArchiveParentHWND(), msg, "Warning", MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2); | |
143 if(answer == IDCANCEL) | |
144 return -1; | |
145 } | |
146 | |
147 // if there's only 1 item, choose it | |
148 if(info.files.size() == 1 && autoChooseIfOnly1 && numIgnoreExtensions == prevNumIgnoreExtensions) | |
149 return info.files[0].itemIndex; | |
150 | |
151 // bring up a dialog to choose the index if there's more than 1 | |
152 DialogBoxParam(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_ARCHIVEFILECHOOSER), GetArchiveParentHWND(), (DLGPROC) ArchiveFileChooser,(LPARAM) &info); | |
153 archive.m_userMadeSelection = (s_archiveFileChooserResult != -1); | |
154 return s_archiveFileChooserResult; | |
155 } | |
156 | |
157 | |
158 | |
159 | |
160 #define DEFAULT_EXTENSION ".tmp" | |
161 #define DEFAULT_CATEGORY "vba" | |
162 | |
163 static struct TempFiles | |
164 { | |
165 struct TemporaryFile | |
166 { | |
167 TemporaryFile(const char* cat, const char* ext) | |
168 { | |
169 if(!ext || !*ext) ext = DEFAULT_EXTENSION; | |
170 if(!cat || !*cat) cat = DEFAULT_CATEGORY; | |
171 category = cat; | |
172 | |
173 char tempPath [2048]; | |
174 GetTempPath(2048, tempPath); | |
175 //GetTempFileName(tempPath, cat, 0, filename, ext); // alas | |
176 | |
177 char*const fname = tempPath + strlen(tempPath); | |
178 unsigned short start = (unsigned short)(timeGetTime() & 0xFFFF); | |
179 unsigned short n = start + 1; | |
180 while(n != start) | |
181 { | |
182 _snprintf(fname, 2048 - (fname - tempPath), "%s%04X%s", cat, n, ext); | |
183 FILE* file = fopen(tempPath, "wb"); | |
184 if(file) | |
185 { | |
186 // mark the temporary file as read-only and (whatever this does) temporary | |
187 DWORD attributes = GetFileAttributes(tempPath); | |
188 attributes |= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_TEMPORARY; | |
189 SetFileAttributes(tempPath, attributes); | |
190 | |
191 fclose(file); | |
192 | |
193 // add it to our registry of files that need to be deleted, in case we fail to terminate properly | |
194 TempFiles::AddEntryToGarbageRegistry(tempPath); | |
195 | |
196 break; | |
197 } | |
198 n++; | |
199 } | |
200 strcpy(filename, tempPath); | |
201 } | |
202 TemporaryFile(const TemporaryFile& copy) | |
203 { | |
204 strcpy(filename, copy.filename); | |
205 category = copy.category; | |
206 } | |
207 TemporaryFile() | |
208 { | |
209 filename[0] = 0; | |
210 // category[0] = 0; // error | |
211 } | |
212 bool Delete(bool returnFalseOnRegistryRemovalFailure=false) | |
213 { | |
214 if(!*filename) | |
215 return true; // guess it already didn't exist | |
216 | |
217 // remove read-only attribute so Windows will let us delete it | |
218 // (our temporary files are read-only to discourage other apps from tampering) | |
219 DWORD attributes = GetFileAttributes(filename); | |
220 if(attributes & FILE_ATTRIBUTE_READONLY) | |
221 SetFileAttributes(filename, attributes & ~FILE_ATTRIBUTE_READONLY); | |
222 | |
223 if(_unlink(filename) == 0 || errno != EACCES) | |
224 { | |
225 // remove it from our registry of files that need to be deleted, to reduce accumulation | |
226 bool removed = TempFiles::RemoveEntryFromGarbageRegistry(filename); | |
227 | |
228 *filename = '\0'; | |
229 return removed || !returnFalseOnRegistryRemovalFailure; // successfully deleted or already didn't exist, return true unless registry removal failure notification was requested and that failed | |
230 } | |
231 | |
232 // restore read-only if we couldn't delete it (not sure if this ever succeeds or matters though) | |
233 if(attributes & FILE_ATTRIBUTE_READONLY) | |
234 SetFileAttributes(filename, attributes); | |
235 | |
236 return false; // failed to delete read-only or in-use file | |
237 } | |
238 char filename [MAX_PATH]; | |
239 std::string category; | |
240 }; | |
241 | |
242 std::vector<TemporaryFile> tempFiles; | |
243 | |
244 const char* GetFile(const char* category, const char* extension) | |
245 { | |
246 tempFiles.push_back(TemporaryFile(category, extension)); | |
247 return tempFiles.back().filename; | |
248 } | |
249 | |
250 void ReleaseFile(const char* filename) | |
251 { | |
252 for(int i = (int)tempFiles.size()-1; i >= 0; i--) | |
253 { | |
254 if(!strcmp(filename, tempFiles[i].filename)) | |
255 { | |
256 if(tempFiles[i].Delete()) | |
257 tempFiles.erase(tempFiles.begin() + i); | |
258 } | |
259 } | |
260 } | |
261 | |
262 void ReleaseCategory(const char* cat, const char* exceptionFilename) | |
263 { | |
264 for(int i = (int)tempFiles.size()-1; i >= 0; i--) | |
265 { | |
266 if(!strcmp(cat, tempFiles[i].category.c_str()) && | |
267 (!exceptionFilename || | |
268 strcmp(exceptionFilename, tempFiles[i].filename))) | |
269 { | |
270 if(tempFiles[i].Delete()) | |
271 tempFiles.erase(tempFiles.begin() + i); | |
272 } | |
273 } | |
274 } | |
275 | |
276 // delete all temporary files on shutdown | |
277 ~TempFiles() | |
278 { | |
279 for(size_t i = 0; i < tempFiles.size(); i++) | |
280 { | |
281 tempFiles[i].Delete(); | |
282 } | |
283 | |
284 TempFiles::CleanOutGarbageRegistry(); | |
285 } | |
286 | |
287 // run this on startup to delete any files that we failed to delete last time | |
288 // in case we crashed or were forcefully terminated | |
289 TempFiles() | |
290 { | |
291 TempFiles::CleanOutGarbageRegistry(); | |
292 } | |
293 | |
294 static void AddEntryToGarbageRegistry(const char* filename) | |
295 { | |
296 char gbgFile[2048]; | |
297 GetTempPath(2048, gbgFile); | |
298 strcat(gbgFile, "VBATempFileRecords"); | |
299 char key[64]; | |
300 int i = 0; | |
301 while(true) | |
302 { | |
303 sprintf(key, "File%d", i); | |
304 GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); | |
305 if(!*Str_Tmp) | |
306 break; | |
307 i++; | |
308 } | |
309 WritePrivateProfileString("Files", key, filename, gbgFile); | |
310 } | |
311 static bool RemoveEntryFromGarbageRegistry(const char* filename) | |
312 { | |
313 char gbgFile[2048]; | |
314 GetTempPath(2048, gbgFile); | |
315 strcat(gbgFile, "VBATempFileRecords"); | |
316 char key[64]; | |
317 int i = 0; | |
318 int deleteSlot = -1; | |
319 while(true) | |
320 { | |
321 sprintf(key, "File%d", i); | |
322 GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); | |
323 if(!*Str_Tmp) | |
324 break; | |
325 if(!strcmp(Str_Tmp, filename)) | |
326 deleteSlot = i; | |
327 i++; | |
328 } | |
329 --i; | |
330 if(i >= 0 && deleteSlot >= 0) | |
331 { | |
332 if(i != deleteSlot) | |
333 { | |
334 sprintf(key, "File%d", i); | |
335 GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); | |
336 sprintf(key, "File%d", deleteSlot); | |
337 WritePrivateProfileString("Files", key, Str_Tmp, gbgFile); | |
338 } | |
339 sprintf(key, "File%d", i); | |
340 if(0 == WritePrivateProfileString("Files", key, NULL, gbgFile)) | |
341 return false; | |
342 } | |
343 if(i <= 0 && deleteSlot == 0) | |
344 _unlink(gbgFile); | |
345 return true; | |
346 } | |
347 | |
348 private: | |
349 static void CleanOutGarbageRegistry() | |
350 { | |
351 char gbgFile[2048]; | |
352 GetTempPath(2048, gbgFile); | |
353 strcat(gbgFile, "VBATempFileRecords"); | |
354 | |
355 char key[64]; | |
356 int i = 0; | |
357 while(true) | |
358 { | |
359 sprintf(key, "File%d", i); | |
360 GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); | |
361 if(!*Str_Tmp) | |
362 break; | |
363 TemporaryFile temp; | |
364 strcpy(temp.filename, Str_Tmp); | |
365 if(!temp.Delete(true)) | |
366 i++; | |
367 } | |
368 } | |
369 | |
370 } s_tempFiles; | |
371 | |
372 | |
373 const char* GetTempFile(const char* category, const char* extension) | |
374 { | |
375 return s_tempFiles.GetFile(category, extension); | |
376 } | |
377 void ReleaseTempFile(const char* filename) | |
378 { | |
379 s_tempFiles.ReleaseFile(filename); | |
380 } | |
381 void ReleaseTempFileCategory(const char* cat, const char* exceptionFilename) | |
382 { | |
383 if(!cat || !*cat) cat = DEFAULT_CATEGORY; | |
384 s_tempFiles.ReleaseCategory(cat, exceptionFilename); | |
385 } | |
386 | |
387 | |
388 | |
389 // example input Name: "C:\games.zip" | |
390 // example output LogicalName: "C:\games.zip|Metroid.gba" | |
391 // example output PhysicalName: "C:\Documents and Settings\User\Local Settings\Temp\VBA\rom7A37.gba" | |
392 // assumes arguments are character buffers with 2048 bytes each | |
393 bool ObtainFile(const char* Name, char *const & LogicalName, char *const & PhysicalName, const char* category, const char** ignoreExtensions, int numIgnoreExtensions) | |
394 { | |
395 restart: | |
396 char ArchivePaths [2048]; | |
397 strcpy(LogicalName, Name); | |
398 strcpy(PhysicalName, Name); | |
399 strcpy(ArchivePaths, Name); | |
400 char* bar = strchr(ArchivePaths, '|'); | |
401 if(bar) | |
402 { | |
403 PhysicalName[bar - ArchivePaths] = 0; // doesn't belong in the physical name | |
404 LogicalName[bar - ArchivePaths] = 0; // we'll reconstruct the logical name as we go | |
405 *bar++ = 0; // bar becomes the next logical archive path component | |
406 } | |
407 | |
408 bool userSelected = false; | |
409 | |
410 while(true) | |
411 { | |
412 ArchiveFile archive (PhysicalName, LogicalName); | |
413 if(!archive.IsCompressed()) | |
414 { | |
415 if(archive.GetNumItems() > 0) | |
416 return true; | |
417 else | |
418 { | |
419 // failed or cancelled... backtrack to outermost archive if not already there | |
420 char* div = NULL; | |
421 if(LogicalName[strlen(LogicalName)-1] == '|') | |
422 { | |
423 LogicalName[strlen(LogicalName)-1] = '\0'; | |
424 div = strrchr(LogicalName, '|'); | |
425 } | |
426 if(div && userSelected) | |
427 goto restart; | |
428 else | |
429 return false; | |
430 } | |
431 } | |
432 else | |
433 { | |
434 int item = -1; | |
435 bool forceManual = false; | |
436 if(bar && *bar) // try following the in-archive part of the logical path | |
437 { | |
438 char* bar2 = strchr(bar, '|'); | |
439 if(bar2) *bar2++ = 0; | |
440 int numItems = archive.GetNumItems(); | |
441 for(int i = 0; i < numItems; i++) | |
442 { | |
443 if(archive.GetItemSize(i)) | |
444 { | |
445 const char* itemName = archive.GetItemName(i); | |
446 if(!_stricmp(itemName, bar)) | |
447 { | |
448 item = i; // match found, now we'll auto-follow the path | |
449 break; | |
450 } | |
451 } | |
452 } | |
453 if(item < 0) | |
454 { | |
455 forceManual = true; // we don't want it choosing something else without user permission | |
456 bar = NULL; // remaining archive path is invalid | |
457 } | |
458 else | |
459 bar = bar2; // advance to next archive path part | |
460 } | |
461 if(item < 0) | |
462 item = ChooseItemFromArchive(archive, !forceManual, ignoreExtensions, numIgnoreExtensions); | |
463 | |
464 userSelected |= archive.m_userMadeSelection; | |
465 | |
466 const char* TempFileName = s_tempFiles.GetFile(category, strrchr(archive.GetItemName(item), '.')); | |
467 if(!archive.ExtractItem(item, TempFileName)) | |
468 s_tempFiles.ReleaseFile(TempFileName); | |
469 s_tempFiles.ReleaseFile(PhysicalName); | |
470 strcpy(PhysicalName, TempFileName); | |
471 _snprintf(LogicalName + strlen(LogicalName), 2048 - (strlen(LogicalName)+1), "|%s", archive.GetItemName(item)); | |
472 } | |
473 } | |
474 } | |
475 | |
476 | |
477 | |
478 struct ControlLayoutInfo | |
479 { | |
480 int controlID; | |
481 | |
482 enum LayoutType // what to do when the containing window resizes | |
483 { | |
484 NONE, // leave the control where it was | |
485 RESIZE_END, // resize the control | |
486 MOVE_START, // move the control | |
487 }; | |
488 LayoutType horizontalLayout; | |
489 LayoutType verticalLayout; | |
490 }; | |
491 struct ControlLayoutState | |
492 { | |
493 int x,y,width,height; | |
494 bool valid; | |
495 ControlLayoutState() : valid(false) {} | |
496 }; | |
497 | |
498 static ControlLayoutInfo controlLayoutInfos [] = { | |
499 {IDC_LIST1, ControlLayoutInfo::RESIZE_END, ControlLayoutInfo::RESIZE_END}, | |
500 {IDOK, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, | |
501 {ID_CANCEL, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, | |
502 }; | |
503 static const int numControlLayoutInfos = sizeof(controlLayoutInfos)/sizeof(*controlLayoutInfos); | |
504 | |
505 static ControlLayoutState s_layoutState [numControlLayoutInfos]; | |
506 static int s_windowWidth = 182, s_windowHeight = 113; | |
507 | |
508 | |
509 LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
510 { | |
511 RECT r, r2; | |
512 int dx1, dy1, dx2, dy2; | |
513 static std::map<int,int> s_listToItemsMap; | |
514 | |
515 switch(uMsg) | |
516 { | |
517 case WM_INITDIALOG: | |
518 { | |
519 //Clear_Sound_Buffer(); | |
520 | |
521 //if(Full_Screen) | |
522 //{ | |
523 // while (ShowCursor(false) >= 0); | |
524 // while (ShowCursor(true) < 0); | |
525 //} | |
526 | |
527 for(int i = 0; i < numControlLayoutInfos; i++) | |
528 s_layoutState[i].valid = false; | |
529 | |
530 GetWindowRect(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), &r); | |
531 dx1 = (r.right - r.left) / 2; | |
532 dy1 = (r.bottom - r.top) / 2; | |
533 | |
534 GetWindowRect(hDlg, &r2); | |
535 dx2 = (r2.right - r2.left) / 2; | |
536 dy2 = (r2.bottom - r2.top) / 2; | |
537 | |
538 //SetWindowPos(hDlg, NULL, max(0, r.left + (dx1 - dx2)), max(0, r.top + (dy1 - dy2)), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); | |
539 SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); | |
540 | |
541 ArchiveFileChooserInfo& info = *(ArchiveFileChooserInfo*)lParam; | |
542 std::vector<ArchiveFileChooserInfo::FileInfo>& files = info.files; | |
543 ArchiveFile& archive = info.archive; | |
544 | |
545 std::string title = "Choose File in "; | |
546 title += archive.GetArchiveTypeName(); | |
547 title += " Archive"; | |
548 SetWindowText(hDlg, title.c_str()); | |
549 | |
550 // populate list | |
551 for(size_t i = 0; i < files.size(); i++) | |
552 { | |
553 int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_ADDSTRING, (WPARAM) 0, (LONG) (LPTSTR) files[i].name.c_str()); | |
554 s_listToItemsMap[listIndex] = files[i].itemIndex; | |
555 } | |
556 | |
557 SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); | |
558 | |
559 { | |
560 RECT r3; | |
561 GetClientRect(hDlg, &r3); | |
562 s_windowWidth = r3.right - r3.left; | |
563 s_windowHeight = r3.bottom - r3.top; | |
564 } | |
565 | |
566 return true; | |
567 } break; | |
568 | |
569 case WM_SIZING: | |
570 { | |
571 // enforce a minimum window size | |
572 | |
573 LPRECT r = (LPRECT) lParam; | |
574 int minimumWidth = 281; | |
575 int minimumHeight = 117; | |
576 if(r->right - r->left < minimumWidth) | |
577 if(wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT) | |
578 r->left = r->right - minimumWidth; | |
579 else | |
580 r->right = r->left + minimumWidth; | |
581 if(r->bottom - r->top < minimumHeight) | |
582 if(wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT) | |
583 r->top = r->bottom - minimumHeight; | |
584 else | |
585 r->bottom = r->top + minimumHeight; | |
586 return TRUE; | |
587 } | |
588 | |
589 case WM_SIZE: | |
590 { | |
591 // resize or move controls in the window as necessary when the window is resized | |
592 | |
593 int prevDlgWidth = s_windowWidth; | |
594 int prevDlgHeight = s_windowHeight; | |
595 | |
596 int dlgWidth = LOWORD(lParam); | |
597 int dlgHeight = HIWORD(lParam); | |
598 | |
599 int deltaWidth = dlgWidth - prevDlgWidth; | |
600 int deltaHeight = dlgHeight - prevDlgHeight; | |
601 | |
602 for(int i = 0; i < numControlLayoutInfos; i++) | |
603 { | |
604 ControlLayoutInfo layoutInfo = controlLayoutInfos[i]; | |
605 ControlLayoutState& layoutState = s_layoutState[i]; | |
606 | |
607 HWND hCtrl = GetDlgItem(hDlg,layoutInfo.controlID); | |
608 | |
609 int x,y,width,height; | |
610 if(layoutState.valid) | |
611 { | |
612 x = layoutState.x; | |
613 y = layoutState.y; | |
614 width = layoutState.width; | |
615 height = layoutState.height; | |
616 } | |
617 else | |
618 { | |
619 RECT r; | |
620 GetWindowRect(hCtrl, &r); | |
621 POINT p = {r.left, r.top}; | |
622 ScreenToClient(hDlg, &p); | |
623 x = p.x; | |
624 y = p.y; | |
625 width = r.right - r.left; | |
626 height = r.bottom - r.top; | |
627 } | |
628 | |
629 switch(layoutInfo.horizontalLayout) | |
630 { | |
631 case ControlLayoutInfo::RESIZE_END: width += deltaWidth; break; | |
632 case ControlLayoutInfo::MOVE_START: x += deltaWidth; break; | |
633 default: break; | |
634 } | |
635 switch(layoutInfo.verticalLayout) | |
636 { | |
637 case ControlLayoutInfo::RESIZE_END: height += deltaHeight; break; | |
638 case ControlLayoutInfo::MOVE_START: y += deltaHeight; break; | |
639 default: break; | |
640 } | |
641 | |
642 SetWindowPos(hCtrl, 0, x,y, width,height, 0); | |
643 | |
644 layoutState.x = x; | |
645 layoutState.y = y; | |
646 layoutState.width = width; | |
647 layoutState.height = height; | |
648 layoutState.valid = true; | |
649 } | |
650 | |
651 s_windowWidth = dlgWidth; | |
652 s_windowHeight = dlgHeight; | |
653 | |
654 RedrawWindow(hDlg, NULL, NULL, RDW_INVALIDATE); | |
655 } | |
656 break; | |
657 | |
658 case WM_COMMAND: | |
659 switch(LOWORD(wParam)) | |
660 { | |
661 case IDC_LIST1: | |
662 if(HIWORD(wParam) == LBN_DBLCLK) | |
663 { | |
664 POINT pos; | |
665 GetCursorPos(&pos); | |
666 int clickedItem = LBItemFromPt(GetDlgItem(hDlg, IDC_LIST1), pos, FALSE); | |
667 if(clickedItem != -1) | |
668 { | |
669 SendMessage(hDlg, WM_COMMAND, IDOK, 0); | |
670 } | |
671 } | |
672 return TRUE; | |
673 | |
674 case IDOK: | |
675 { | |
676 int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); | |
677 s_archiveFileChooserResult = s_listToItemsMap[listIndex]; | |
678 s_listToItemsMap.clear(); | |
679 //if(Full_Screen) | |
680 //{ | |
681 // while (ShowCursor(true) < 0); | |
682 // while (ShowCursor(false) >= 0); | |
683 //} | |
684 EndDialog(hDlg, false); | |
685 } return TRUE; | |
686 | |
687 case ID_CANCEL: | |
688 case IDCANCEL: | |
689 s_archiveFileChooserResult = -1; | |
690 s_listToItemsMap.clear(); | |
691 //if(Full_Screen) | |
692 //{ | |
693 // while (ShowCursor(true) < 0); | |
694 // while (ShowCursor(false) >= 0); | |
695 //} | |
696 EndDialog(hDlg, false); | |
697 return TRUE; | |
698 } | |
699 | |
700 case WM_CLOSE: | |
701 s_archiveFileChooserResult = -1; | |
702 s_listToItemsMap.clear(); | |
703 //if(Full_Screen) | |
704 //{ | |
705 // while (ShowCursor(true) < 0); | |
706 // while (ShowCursor(false) >= 0); | |
707 //} | |
708 EndDialog(hDlg, false); | |
709 return TRUE; | |
710 } | |
711 | |
712 return false; | |
713 } |