source: trunk/dll/avl.c@ 1039

Last change on this file since 1039 was 1039, checked in by Gregg Young, 17 years ago

Removed unnecessary xfrees and included fortify.h where needed; moved several misplaced (x)frees;

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: avl.c 1039 2008-07-05 22:16:21Z gyoung $
5
6 archiver.bb2 search, load, save and date parse
7
8 Copyright (c) 1993, 1998 M. Kimes
9 Copyright (c) 2004, 2008 Steven H.Levine
10
11 01 Aug 04 SHL Rework lstrip/rstrip usage
12 13 Aug 05 SHL Beautify with indent
13 13 Aug 05 SHL find_type: correct no sig exists bypass logic
14 13 Aug 05 SHL SBoxDlgProc: avoid dereferencing NULL signature
15 18 Aug 05 SHL Comments
16 31 Dec 05 SHL indent -i2
17 08 Dec 05 SHL load_archivers: allow empty startlist
18 30 Dec 05 SHL load_archivers: use get_archiver_line?(), clean nits
19 29 May 06 SHL SBoxDlgProc: support move, add, delete
20 30 May 06 SHL load_archivers: add reload support
21 16 Jun 06 SHL load_archivers: support signatures containing 0s
22 26 Jun 06 SHL load_archivers: remember where comments are
23 14 Jul 06 SHL Use Runtime_Error
24 29 Jul 06 SHL Use xfgets, xfgets_bstripcr
25 15 Aug 06 SHL Use Runtime_Error more
26 01 Nov 06 SHL Turn off leftover debug code
27 06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limit
28 19 Apr 07 SHL Use FreeDragInfoData
29 19 Apr 07 SHL Add more drag/drop error checking
30 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
31 25 Aug 07 SHL load_archivers: add missing close on error path
32 29 Feb 08 GKY Use xfree where appropriate
33 22 Jun 08 GKY Added free_archivers fot fortify checking
34
35***********************************************************************/
36
37#include <stdlib.h>
38#include <string.h>
39#include <ctype.h>
40#include <share.h>
41
42#define INCL_DOS
43#define INCL_WIN
44#define INCL_WINSTDDRAG
45#define INCL_LONGLONG
46
47#include "fm3dlg.h"
48#include "fm3str.h"
49#include "avl.h"
50#include "strutil.h" // GetPString
51#include "errutil.h" // Runtime_Error
52#include "fm3dll.h"
53#include "fortify.h"
54
55static PSZ pszSrcFile = __FILE__;
56
57static void fill_listbox(HWND hwnd, BOOL fShowAll, SHORT sOldSelect);
58
59//=== quick_find_type() ===
60
61ARC_TYPE *quick_find_type(CHAR * filespec, ARC_TYPE * topsig)
62{
63 ARC_TYPE *info, *found = NULL;
64 CHAR *p;
65
66 if (!arcsigsloaded)
67 load_archivers();
68 p = strrchr(filespec, '.');
69 if (p) {
70 p++;
71 info = (topsig) ? topsig : arcsighead;
72 while (info) {
73 if (info->ext && *(info->ext) && !stricmp(p, info->ext)) {
74 found = find_type(filespec, topsig);
75 break;
76 }
77 info = info->next;
78 }
79 }
80 return found;
81}
82
83//=== fill_listbox() fill or refill listbox from current archiver definitions ===
84
85static VOID fill_listbox(HWND hwnd, BOOL fShowAll, SHORT sOldSelect)
86{
87 ARC_TYPE *pat;
88 BOOL found = FALSE;
89 SHORT sSelect;
90
91 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_DELETEALL, MPVOID, MPVOID);
92
93 for (pat = arcsighead; pat; pat = pat->next) {
94 /*
95 * this inner loop tests for a dup signature entry and assures
96 * that only the entry at the top of the list gets used for
97 * conversion; editing any is okay
98 */
99 if (!fShowAll) {
100 ARC_TYPE *pat2;
101 BOOL isDup = FALSE;
102
103 for (pat2 = arcsighead;
104 pat2 && pat->siglen && pat2 != pat && !isDup; pat2 = pat2->next) {
105 isDup = pat2->siglen == pat->siglen &&
106 !memcmp(pat2->signature, pat->signature, pat->siglen);
107 } // for
108 if (isDup)
109 continue;
110 }
111
112 // If caller is editing archivers or entry useful to caller, show in listbox
113 if (fShowAll || (pat->id && pat->extract && pat->create)) {
114 sSelect = (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_INSERTITEM,
115 MPFROM2SHORT(LIT_END, 0),
116 MPFROMP(pat->id ? pat->id : "?"));
117 if (!found && *szDefArc && pat->id && !strcmp(szDefArc, pat->id)) {
118 // Highlight default
119 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
120 MPFROMSHORT(sSelect), MPFROMSHORT(TRUE));
121 found = TRUE;
122 }
123 }
124 else {
125 // Complain about odd entry
126 if (!pat->id || !*pat->id) {
127 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_INSERTITEM,
128 MPFROM2SHORT(LIT_END, 0),
129 MPFROMP(GetPString(IDS_UNKNOWNUNUSABLETEXT)));
130 }
131 else {
132 CHAR s[81];
133
134 sprintf(s, "%0.12s %s", pat->id, GetPString(IDS_UNUSABLETEXT));
135 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_INSERTITEM,
136 MPFROM2SHORT(LIT_END, 0), MPFROMP(s));
137 }
138 }
139 } // while scanning
140
141 // Try to reselect last selection unless user wants default selection
142 if (sOldSelect != LIT_NONE && !found) {
143 SHORT sItemCount =
144 (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMCOUNT,
145 MPVOID, MPVOID);
146
147 if (sOldSelect >= sItemCount)
148 sOldSelect = sItemCount - 1;
149 if (sOldSelect >= 0) {
150 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
151 MPFROMSHORT(sOldSelect), MPFROMSHORT(TRUE));
152 }
153 }
154
155 if (found)
156 PosOverOkay(hwnd);
157}
158
159ARC_TYPE *find_type(CHAR * filespec, ARC_TYPE * topsig)
160{
161 HFILE handle;
162 ULONG action;
163 ULONG len;
164 ULONG l;
165 ARC_TYPE *info;
166 CHAR *p;
167 // CHAR buffer[80];
168 CHAR buffer[4096]; // 06 Oct 07 SHL Protect against NTFS defect
169
170 if (!arcsigsloaded)
171 load_archivers();
172 if (!topsig)
173 topsig = arcsighead;
174 DosError(FERR_DISABLEHARDERR);
175 if (DosOpen(filespec,
176 &handle,
177 &action,
178 0,
179 0,
180 OPEN_ACTION_FAIL_IF_NEW |
181 OPEN_ACTION_OPEN_IF_EXISTS,
182 OPEN_FLAGS_FAIL_ON_ERROR |
183 OPEN_FLAGS_NOINHERIT |
184 OPEN_FLAGS_RANDOMSEQUENTIAL |
185 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0))
186 return NULL;
187 // Scan signatures
188 for (info = topsig; info; info = info->next) {
189 if (info->siglen == 0) {
190 // No signature -- check extension
191 p = strrchr(filespec, '.');
192 if (p) {
193 p++;
194 if (info->ext && *(info->ext) && !stricmp(p, info->ext))
195 break; // Matched
196
197 }
198 continue; // Next sig
199
200 }
201 // Try signature match
202 l = info->siglen;
203 l = min(l, 79);
204 if (!DosChgFilePtr(handle,
205 abs(info->file_offset),
206 (info->file_offset >= 0) ?
207 FILE_BEGIN : FILE_END, &len)) {
208 if (!DosRead(handle, buffer, l, &len) && len == l) {
209 if (!memcmp(info->signature, buffer, l))
210 break; // Matched
211
212 }
213 }
214 } // for
215
216 DosClose(handle); /* Either way, we're done for now */
217 return info; /* Return signature, if any */
218}
219
220VOID free_archivers(VOID)
221{
222 ARC_TYPE *pat, *next;
223
224 pat = arcsighead;
225 while (pat) {
226 next = pat->next;
227 xfree(pat->id, pszSrcFile, __LINE__);
228 xfree(pat->ext, pszSrcFile, __LINE__);
229 xfree(pat->list, pszSrcFile, __LINE__);
230 xfree(pat->extract, pszSrcFile, __LINE__);
231 xfree(pat->create, pszSrcFile, __LINE__);
232 xfree(pat->move, pszSrcFile, __LINE__);
233 xfree(pat->delete, pszSrcFile, __LINE__);
234 xfree(pat->signature, pszSrcFile, __LINE__);
235 xfree(pat->startlist, pszSrcFile, __LINE__);
236 xfree(pat->endlist, pszSrcFile, __LINE__);
237 xfree(pat->exwdirs, pszSrcFile, __LINE__);
238 xfree(pat->test, pszSrcFile, __LINE__);
239 xfree(pat->createrecurse, pszSrcFile, __LINE__);
240 xfree(pat->createwdirs, pszSrcFile, __LINE__);
241 xfree(pat->movewdirs, pszSrcFile, __LINE__);
242 xfree(pat, pszSrcFile, __LINE__);
243 pat = next;
244 }
245 arcsighead = NULL;
246}
247
248//=== free_arc_type() free allocated ARC_TYPE ===
249
250VOID free_arc_type(ARC_TYPE * pat)
251{
252 if (pat) {
253 xfree(pat->id, pszSrcFile, __LINE__);
254 xfree(pat->ext, pszSrcFile, __LINE__);
255 xfree(pat->list, pszSrcFile, __LINE__);
256 xfree(pat->extract, pszSrcFile, __LINE__);
257 xfree(pat->create, pszSrcFile, __LINE__);
258 xfree(pat->move, pszSrcFile, __LINE__);
259 xfree(pat->delete, pszSrcFile, __LINE__);
260 xfree(pat->signature, pszSrcFile, __LINE__);
261 xfree(pat->startlist, pszSrcFile, __LINE__);
262 xfree(pat->endlist, pszSrcFile, __LINE__);
263 xfree(pat->exwdirs, pszSrcFile, __LINE__);
264 xfree(pat->test, pszSrcFile, __LINE__);
265 xfree(pat->createrecurse, pszSrcFile, __LINE__);
266 xfree(pat->createwdirs, pszSrcFile, __LINE__);
267 xfree(pat->movewdirs, pszSrcFile, __LINE__);
268 free(pat);
269 }
270}
271
272static UINT cur_line_num; // Input file line counter
273
274//=== get_line_strip_comments() read line, strip comments and whitespace ===
275
276#define ARCHIVER_LINE_BYTES 256
277
278static PSZ get_line_strip_comments(PSZ pszIn, FILE * fp)
279{
280 PSZ psz = xfgets(pszIn, ARCHIVER_LINE_BYTES, fp, pszSrcFile, __LINE__);
281 PSZ psz2;
282
283 if (psz) {
284 cur_line_num++;
285 psz2 = strchr(pszIn, ';');
286 if (psz2)
287 *psz2 = 0; // Chop comment
288 bstripcr(pszIn); // Strip leading white and trailing white and CR/LF
289
290 }
291 return psz;
292}
293
294//=== get_line_strip_white() read line, strip whitespace ===
295
296static PSZ get_line_strip_white(PSZ pszIn, FILE * fp)
297{
298 PSZ psz =
299 xfgets_bstripcr(pszIn, ARCHIVER_LINE_BYTES, fp, pszSrcFile, __LINE__);
300
301 if (psz)
302 cur_line_num++;
303
304 return psz;
305}
306
307//=== load_archivers() load or reload archive definitions from archiver.bb2 ===
308
309INT load_archivers(VOID)
310{
311 FILE *fp;
312 CHAR sz[ARCHIVER_LINE_BYTES + 1];
313 CHAR *psz;
314 ARC_TYPE *pat = NULL;
315 ARC_TYPE *patLast = NULL;
316 UINT lines_per_arcsig = LINES_PER_ARCSIG;
317 UINT per_sig_comment_line_num = 0;
318 INT i;
319
320 // Free current signatures
321 if (arcsighead) {
322 for (pat = arcsighead; pat;) {
323 patLast = pat;
324 pat = pat->next;
325 free_arc_type(patLast);
326 }
327 arcsighead = NULL;
328 }
329
330 arcsigsmodified = FALSE;
331 arcsigs_header_lines = 0;
332 arcsigs_trailer_line_num = 0;
333
334 DosEnterCritSec();
335 psz = searchpath(GetPString(IDS_ARCHIVERBB2));
336 if (!psz || !*psz) {
337 DosExitCritSec();
338 return -1;
339 }
340 fp = _fsopen(psz, "r", SH_DENYWR);
341 DosExitCritSec();
342 if (!fp)
343 return -2;
344 strcpy(archiverbb2, psz); // Remember full path
345
346 cur_line_num = 0;
347
348 // Line 1 must contain number of lines per signature definition
349 if (!get_line_strip_comments(sz, fp)) {
350 fclose(fp);
351 return -3;
352 }
353 if (*sz)
354 lines_per_arcsig = atoi(sz);
355 if (!*sz || lines_per_arcsig < LINES_PER_ARCSIG) {
356 fclose(fp); // 25 Aug 07 SHL
357 return -3;
358 }
359
360 // Parse rest of file
361 // 1st non-blank line starts definition
362 // Need to determine header size and start of trailer
363
364 while (!feof(fp)) {
365 // If reading header
366 if (!arcsigs_header_lines) {
367 // Reading header - find header size and start of signtures
368 if (!get_line_strip_white(sz, fp))
369 break; // Unexpected EOF
370 if (stristr(sz, "-- Current Archivers --")) {
371 arcsigs_header_lines = cur_line_num;
372 continue;
373 }
374 if (!*sz || *sz == ';')
375 continue; // Header comment or blank line
376 else {
377 // Not a comment, must be start of signatures
378 PSZ psz2 = strchr(sz, ';');
379
380 if (psz2) {
381 *psz2 = 0; // Chop trailing comment
382 bstripcr(sz); // Strip leading white and trailing white and CR/LF
383 }
384 arcsigs_header_lines = cur_line_num - 1;
385 }
386 }
387 else {
388 // Reading defintiions
389 if (!get_line_strip_comments(sz, fp))
390 break; // EOF
391 }
392
393 // fixme to avoid allocating empty fields
394
395 // Remember start of per sig comments for next definition
396 if (per_sig_comment_line_num == 0)
397 per_sig_comment_line_num = cur_line_num;
398
399 if (*sz) {
400 // At start of defintion
401
402 pat = xmallocz(sizeof(ARC_TYPE), pszSrcFile, __LINE__);
403 if (!pat)
404 break;
405 pat->id = xstrdup(sz, pszSrcFile, __LINE__);
406
407 pat->comment_line_num = per_sig_comment_line_num;
408 pat->defn_line_num = cur_line_num;
409
410 if (!get_line_strip_comments(sz, fp)) // line 2 - extension
411 break;
412 if (*sz)
413 pat->ext = xstrdup(sz, pszSrcFile, __LINE__);
414 else
415 pat->ext = NULL;
416 if (!get_line_strip_comments(sz, fp)) // line 3 - offset to signature
417 break;
418 pat->file_offset = atol(sz);
419 if (!get_line_strip_comments(sz, fp)) // line 4 - list command
420 break;
421 if (*sz)
422 pat->list = xstrdup(sz, pszSrcFile, __LINE__);
423 else
424 pat->list = NULL;
425 if (!pat->list)
426 break; // Must have list command - fixme to complain
427 if (!get_line_strip_comments(sz, fp)) // line 5
428 break;
429 if (*sz)
430 pat->extract = xstrdup(sz, pszSrcFile, __LINE__);
431 else
432 pat->extract = NULL;
433 if (!get_line_strip_comments(sz, fp)) // line 6
434 break;
435 if (*sz)
436 pat->exwdirs = xstrdup(sz, pszSrcFile, __LINE__);
437 else
438 pat->exwdirs = NULL;
439 if (!get_line_strip_comments(sz, fp)) // line 7
440 break;
441 if (*sz)
442 pat->test = xstrdup(sz, pszSrcFile, __LINE__);
443 else
444 pat->test = NULL;
445 if (!get_line_strip_comments(sz, fp)) // line 8
446 break;
447 if (*sz)
448 pat->create = xstrdup(sz, pszSrcFile, __LINE__);
449 else
450 pat->create = NULL;
451 if (!get_line_strip_comments(sz, fp)) // line 9
452 break;
453 if (*sz)
454 pat->createwdirs = xstrdup(sz, pszSrcFile, __LINE__);
455 else
456 pat->createwdirs = NULL;
457 if (!get_line_strip_comments(sz, fp)) // line 10
458 break;
459 if (*sz)
460 pat->createrecurse = xstrdup(sz, pszSrcFile, __LINE__);
461 else
462 pat->createrecurse = NULL;
463 if (!get_line_strip_comments(sz, fp)) // line 11
464 break;
465 if (*sz)
466 pat->move = xstrdup(sz, pszSrcFile, __LINE__);
467 else
468 pat->move = NULL;
469 if (!get_line_strip_comments(sz, fp)) // line 12
470 break;
471 if (*sz)
472 pat->movewdirs = xstrdup(sz, pszSrcFile, __LINE__);
473 else
474 pat->movewdirs = NULL;
475 if (!get_line_strip_comments(sz, fp)) // line 13
476 break;
477 if (*sz)
478 pat->delete = xstrdup(sz, pszSrcFile, __LINE__);
479 else
480 pat->delete = NULL;
481 if (!get_line_strip_white(sz, fp)) // line 14
482 break;
483 i = literal(sz); // Translate \ escapes
484 if (i) {
485 pat->siglen = i;
486 pat->signature = xmalloc(i, pszSrcFile, __LINE__);
487 if (!pat->signature)
488 break;
489 memcpy(pat->signature, sz, i); // signature may not be a string
490 }
491 else {
492 pat->siglen = 0;
493 pat->signature = NULL;
494 }
495 if (!get_line_strip_white(sz, fp)) // line 15
496 break;
497 if (*sz)
498 pat->startlist = xstrdup(sz, pszSrcFile, __LINE__);
499 else
500 pat->startlist = NULL;
501 if (!get_line_strip_white(sz, fp)) // line 16
502 break;
503 if (*sz)
504 pat->endlist = xstrdup(sz, pszSrcFile, __LINE__);
505 else
506 pat->endlist = NULL;
507 if (!get_line_strip_comments(sz, fp)) // line 17
508 break;
509 pat->osizepos = atoi(sz);
510 if (!get_line_strip_comments(sz, fp)) // line 18
511 break;
512 pat->nsizepos = atoi(sz);
513 if (!get_line_strip_comments(sz, fp)) // line 19
514 break;
515 pat->fdpos = atoi(sz);
516 psz = strchr(sz, ',');
517 if (psz) {
518 psz++;
519 pat->datetype = atoi(psz);
520 }
521 if (!get_line_strip_comments(sz, fp)) // line 20
522 break;
523 pat->fdflds = atoi(sz);
524 if (!get_line_strip_comments(sz, fp)) // line 21
525 break;
526 pat->fnpos = atoi(sz);
527 psz = strchr(sz, ',');
528 if (psz) {
529 psz++;
530 pat->nameislast = (BOOL) (*psz && atol(psz) == 0) ? FALSE : TRUE;
531 psz = strchr(psz, ',');
532 if (psz) {
533 psz++;
534 pat->nameisnext = (BOOL) (*psz && atol(psz) == 0) ? FALSE : TRUE;
535 psz = strchr(psz, ',');
536 if (psz) {
537 psz++;
538 pat->nameisfirst = (BOOL) (*psz && atol(psz) == 0) ? FALSE : TRUE;
539 }
540 }
541 }
542 // Ignore unknown lines - must be newer file format
543 for (i = LINES_PER_ARCSIG; i < lines_per_arcsig; i++) {
544 if (!get_line_strip_comments(sz, fp))
545 break; // Unexpected EOF - fixme to complain
546 }
547
548 // Add to list, assume next and prev already NULL
549 if (!arcsighead)
550 arcsighead = patLast = pat;
551 else {
552 patLast->next = pat;
553 pat->prev = patLast;
554 patLast = pat;
555 }
556 pat = NULL; // Done with this defintion
557
558 arcsigs_trailer_line_num = cur_line_num + 1; // In case this is last defintion
559 per_sig_comment_line_num = 0;
560 } // if got definition
561
562 } // while more lines
563
564 fclose(fp);
565
566 free_arc_type(pat); // In case partial definition in progress
567
568 if (!arcsighead)
569 return -4;
570
571 arcsigsloaded = TRUE;
572
573 return 0;
574}
575
576#define TEST_DRAG 0 // fixme to be gone or to work
577
578static MRESULT EXPENTRY SDlgListboxSubclassProc(HWND hwnd, ULONG msg,
579 MPARAM mp1, MPARAM mp2)
580{
581 PFNWP pfnOldProc = (PFNWP) WinQueryWindowPtr(hwnd, QWL_USER);
582
583 PDRAGITEM pDItem;
584 PDRAGINFO pDInfo;
585 BOOL ok;
586
587 static BOOL emphasized = FALSE;
588 static PSZ DRMDRF_LBOX = "<DRM_LBOX,DRF_UNKNOWN>";
589 static PSZ DRM_LBOX = "DRM_LBOX";
590
591 switch (msg) {
592 case WM_BEGINDRAG:
593 {
594 LONG cur_ndx;
595 DRAGITEM ditem;
596 DRAGIMAGE dimage;
597 HWND hwndDrop;
598
599 // fprintf(stderr, "SDlgListboxSubclassProc: BEGINDRAG\n");
600 cur_ndx = WinQueryLboxSelectedItem(hwnd);
601
602 if (cur_ndx != LIT_NONE) {
603 pDInfo = DrgAllocDraginfo(1);
604 if (pDInfo) {
605 pDInfo->usOperation = DO_DEFAULT;
606 pDInfo->hwndSource = hwnd;
607
608 memset(&ditem, 0, sizeof(DRAGITEM));
609 ditem.hwndItem = hwnd;
610 ditem.ulItemID = 1;
611 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
612 ditem.hstrRMF = DrgAddStrHandle(DRMDRF_LBOX);
613 ditem.hstrContainerName = DrgAddStrHandle("");
614 ditem.hstrSourceName = DrgAddStrHandle("");
615 ditem.hstrTargetName = DrgAddStrHandle("");
616 // ditem.fsControl = 0;
617 ditem.fsSupportedOps = DO_MOVEABLE;
618
619 memset(&dimage, 0, sizeof(DRAGIMAGE));
620 dimage.cb = sizeof(DRAGIMAGE);
621 dimage.hImage = hptrFile;
622 dimage.cptl = 0;
623 dimage.fl = DRG_ICON;
624 dimage.sizlStretch.cx = 32;
625 dimage.sizlStretch.cy = 32;
626 dimage.cxOffset = -16;
627 dimage.cyOffset = 0;
628 DrgSetDragitem(pDInfo, &ditem, sizeof(DRAGITEM), 0); /* Index of DRAGITEM */
629 hwndDrop = DrgDrag(hwnd, pDInfo, &dimage, 1, /* One DRAGIMAGE */
630 VK_ENDDRAG, NULL);
631 if (!hwndDrop)
632 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgDrag");
633
634 DrgFreeDraginfo(pDInfo);
635 // WinSetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_ACTIVATE);
636 }
637 }
638 break;
639 }
640
641 case DM_DRAGOVER:
642 ok = FALSE;
643 if (!emphasized) {
644 POINTL ptl;
645 POINTL ptl2;
646
647 emphasized = TRUE;
648 ptl.x = SHORT1FROMMP(mp2);
649 ptl.y = SHORT2FROMMP(mp2);
650 ptl2 = ptl;
651 WinMapWindowPoints(HWND_DESKTOP, hwnd, &ptl2, 1);
652 // fprintf(stderr, "DRAGOVER mapped x y %d %d to %d %d\n", ptl.x, ptl.y, ptl2.x, ptl2.y);
653 WinPostMsg(hwnd, WM_BUTTON1CLICK,
654 MPFROM2SHORT((SHORT) ptl2.x, (SHORT) ptl2.y),
655 MPFROM2SHORT(HT_NORMAL, KC_NONE));
656 // fprintf(stderr, "DRAGOVER posted 0x%x WM_BUTTON1CLICK x y %d %d\n", hwnd, ptl2.x, ptl2.y);
657 }
658 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
659 if (pDInfo) {
660 if (!DrgAccessDraginfo(pDInfo)) {
661 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
662 "DrgAccessDraginfo");
663 }
664 else {
665 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
666 /* Check valid rendering mechanisms and data format */
667 ok = DrgVerifyRMF(pDItem, DRM_LBOX, NULL);
668 DrgFreeDraginfo(pDInfo);
669 }
670 }
671 return ok ? MRFROM2SHORT(DOR_DROP, DO_MOVE) :
672 MRFROM2SHORT(DOR_NEVERDROP, 0);
673
674 case DM_DRAGLEAVE:
675 if (emphasized) {
676 emphasized = FALSE;
677 // fixme to draw listbox item emphasized
678 // DrawTargetEmphasis(hwnd, emphasized);
679 // fprintf(stderr, "DRAGLEAVE\n");
680 fflush(stderr);
681 }
682 return 0;
683
684 case DM_DROPHELP:
685 DropHelp(mp1, mp2, hwnd, "fixme to give some help");
686 return 0;
687
688 case DM_DROP:
689 ok = FALSE;
690 if (emphasized) {
691 emphasized = FALSE;
692 // DrawTargetEmphasis(hwnd, emphasized);
693 }
694 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
695 if (pDInfo) {
696 if (!DrgAccessDraginfo(pDInfo)) {
697 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
698 "DrgAccessDraginfo");
699 }
700 else {
701 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
702 if (!pDItem)
703 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DM_DROP");
704 /* Check valid rendering mechanisms and data */
705 ok = DrgVerifyRMF(pDItem, DRM_LBOX, NULL)
706 && ~pDItem->fsControl & DC_PREPARE;
707 if (ok) {
708 // ret = FullDrgName(pDItem,buffer,buflen);
709 /* note: targetfail is returned to source for all items */
710 DrgSendTransferMsg(pDInfo->hwndSource, DM_ENDCONVERSATION,
711 MPFROMLONG(pDItem->ulItemID),
712 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
713 }
714 FreeDragInfoData(hwnd, pDInfo);
715 }
716 }
717 return 0;
718 } // switch
719 return pfnOldProc ? pfnOldProc(hwnd, msg, mp1, mp2) :
720 WinDefWindowProc(hwnd, msg, mp1, mp2);
721}
722
723//=== SBoxDlgProc() Select archiver to use or edit, supports list reorder too ===
724
725static PSZ pszCantFindMsg = "Can't find item %d";
726
727MRESULT EXPENTRY SBoxDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
728{
729 ARC_TYPE **ppatReturn; // Where to return selected archiver
730 ARC_TYPE *pat;
731 SHORT sSelect;
732 SHORT sItemCount;
733 CHAR szItemText[256];
734 CHAR szPCItemText[256]; // Parent or child item text
735 SHORT i;
736 BOOL fShowAll;
737
738 static SHORT sLastSelect = LIT_NONE;
739
740 switch (msg) {
741 case WM_INITDLG:
742 if (!arcsigsloaded)
743 load_archivers();
744 if (!(ARC_TYPE **) mp2) {
745 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
746 WinDismissDlg(hwnd, 0);
747 break;
748 }
749 /* Passed arg points to where to return selected archiver definition
750 * On input arg value controls selection list content
751 * If non-NULL, dup names are suppressed
752 * If NULL, all definitions are shown
753 */
754 ppatReturn = (ARC_TYPE **) mp2;
755 fShowAll = *ppatReturn == NULL;
756 if (*ppatReturn)
757 *ppatReturn = arcsighead; // Preset to first
758 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) ppatReturn);
759 fill_listbox(hwnd, fShowAll, sLastSelect);
760
761#ifdef TEST_DRAG // fixme
762 {
763 HWND hwnd2 = WinWindowFromID(hwnd, ASEL_LISTBOX);
764 PFNWP pfn = WinSubclassWindow(hwnd2,
765 SDlgListboxSubclassProc);
766
767 WinSetWindowPtr(hwnd2, QWL_USER, (PVOID) pfn);
768 }
769#endif // TEST_DRAG fixme
770
771 break;
772
773 case WM_COMMAND:
774 ppatReturn = (ARC_TYPE **) WinQueryWindowPtr(hwnd, QWL_USER);
775 switch (SHORT1FROMMP(mp1)) {
776 case DID_OK:
777 sSelect = (SHORT) WinSendDlgItemMsg(hwnd,
778 ASEL_LISTBOX,
779 LM_QUERYSELECTION,
780 MPFROMSHORT(LIT_FIRST), MPVOID);
781 if (sSelect == LIT_NONE) {
782 Runtime_Error(pszSrcFile, __LINE__, "list empty");
783 return 0;
784 }
785 pat = arcsighead;
786 if (*ppatReturn) {
787 // If dups hidden, find archiver with matching id
788 *szItemText = 0;
789 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMTEXT,
790 MPFROM2SHORT(sSelect, 255), MPFROMP(szItemText));
791 if (!*szItemText)
792 pat = NULL;
793 else {
794 for (; pat; pat = pat->next) {
795 if (pat->id && !strcmp(szItemText, pat->id))
796 break; // Found it
797 }
798 }
799 }
800 else {
801 // If dups not hidden, lookup by count
802 for (i = 0; pat && i < sSelect; i++, pat = pat->next) ; // Scan
803 }
804 if (pat && (!*ppatReturn || (pat->id && pat->extract && pat->create))) {
805 *ppatReturn = pat;
806 }
807 else {
808 Runtime_Error(pszSrcFile, __LINE__, "no match");
809 // Refuse to select
810 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
811 MPFROMSHORT(LIT_NONE), FALSE);
812 return 0;
813 }
814 sLastSelect = sSelect;
815 WinDismissDlg(hwnd, TRUE);
816 return 0;
817
818 case DID_CANCEL:
819 if (arcsigsmodified) {
820 if (saymsg(MB_YESNO,
821 hwnd,
822 GetPString(IDS_ADCHANGESINMEMTEXT),
823 GetPString(IDS_ADREWRITETEXT), NullStr) == MBID_YES) {
824 PSZ ab2 = searchpath(GetPString(IDS_ARCHIVERBB2)); // Rewrite without prompting
825
826 rewrite_archiverbb2(ab2);
827 }
828 }
829 sSelect = (SHORT) WinSendDlgItemMsg(hwnd,
830 ASEL_LISTBOX,
831 LM_QUERYSELECTION,
832 MPFROMSHORT(LIT_FIRST), MPVOID);
833 if (sSelect != LIT_NONE)
834 sLastSelect = sSelect;
835 *ppatReturn = NULL;
836 PostMsg(hwnd, WM_CLOSE, MPVOID, MPVOID); // fixme to understand why needed
837 return 0;
838
839 case ASEL_PB_ADD:
840 sSelect = (SHORT) WinSendDlgItemMsg(hwnd,
841 ASEL_LISTBOX,
842 LM_QUERYSELECTION,
843 MPFROMSHORT(LIT_FIRST), MPVOID);
844 if (sSelect != LIT_NONE) {
845 ARCDUMP ad;
846
847 memset(&ad, 0, sizeof(ARCDUMP));
848 ad.info = xmallocz(sizeof(ARC_TYPE), pszSrcFile, __LINE__);
849 if (ad.info) {
850 if (!WinDlgBox(HWND_DESKTOP,
851 hwnd,
852 ArcReviewDlgProc,
853 FM3ModHandle, AD_FRAME, MPFROMP(&ad))) {
854 free(ad.info);
855 }
856 else {
857 // Find self - assume all archivers listed since we are editing
858 for (i = 0, pat = arcsighead; pat && i < sSelect; pat = pat->next, i++) ; // Find self
859
860 if (!pat) {
861 if (arcsighead)
862 Runtime_Error(pszSrcFile, __LINE__, pszCantFindMsg, sSelect);
863 else
864 arcsighead = ad.info;
865 }
866 else {
867 // Insert before
868 if (pat->prev) {
869 ad.info->next = pat;
870 ad.info->prev = pat->prev;
871 pat->prev->next = ad.info;
872 pat->prev = ad.info;
873 }
874 else {
875 arcsighead = ad.info;
876 ad.info->next = pat;
877 pat->prev = ad.info;
878 }
879 }
880 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_INSERTITEM,
881 MPFROM2SHORT(sSelect, 0),
882 MPFROMP(ad.info->id ? ad.info->id : "?"));
883 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
884 MPFROMSHORT(sSelect - 1), MPFROMSHORT(TRUE));
885 arcsigsmodified = TRUE;
886 }
887 }
888 }
889 return 0;
890 case ASEL_PB_DELETE:
891 sSelect = (SHORT) WinSendDlgItemMsg(hwnd,
892 ASEL_LISTBOX,
893 LM_QUERYSELECTION,
894 MPFROMSHORT(LIT_FIRST), MPVOID);
895 if (sSelect != LIT_NONE) {
896 // Find self - assume all archivers listed since we are editing
897 for (i = 0, pat = arcsighead; pat && i < sSelect; pat = pat->next, i++) ; // Find self
898
899 if (!pat)
900 Runtime_Error(pszSrcFile, __LINE__, pszCantFindMsg, sSelect);
901 else {
902 // Delete current
903 if (pat->prev) {
904 pat->prev->next = pat->next;
905 if (pat->next)
906 pat->next->prev = pat->prev;
907 }
908 else {
909 arcsighead = pat->next;
910 if (pat->next)
911 pat->next->prev = pat->prev;
912 }
913 }
914 free_arc_type(pat);
915 arcsigsmodified = TRUE;
916 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_DELETEITEM,
917 MPFROM2SHORT(sSelect, 0), MPVOID);
918 sItemCount =
919 (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMCOUNT,
920 MPVOID, MPVOID);
921 if (sSelect >= sItemCount)
922 sSelect--;
923 if (sSelect >= 0) {
924 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
925 MPFROMSHORT(sSelect), MPFROMSHORT(TRUE));
926 }
927 }
928 return 0;
929 case ASEL_PB_UP:
930 sSelect = (SHORT) WinSendDlgItemMsg(hwnd,
931 ASEL_LISTBOX,
932 LM_QUERYSELECTION,
933 MPFROMSHORT(LIT_FIRST), MPVOID);
934 if (sSelect != LIT_NONE && sSelect > 0) {
935 // Find self - assume all archivers listed since we are editing
936 for (i = 0, pat = arcsighead; pat && i < sSelect; pat = pat->next, i++) ; // Find self
937 if (!pat || !pat->prev)
938 Runtime_Error(pszSrcFile, __LINE__, pszCantFindMsg, sSelect);
939 else {
940 ARC_TYPE *patGDad;
941 ARC_TYPE *patDad;
942 ARC_TYPE *patChild;
943
944 patChild = pat->next;
945 patDad = pat->prev;
946 patGDad = patDad->prev;
947 patDad->next = patChild;
948 if (patChild)
949 patChild->prev = patDad;
950 patDad->prev = pat;
951 pat->next = patDad;
952 if (patGDad) {
953 patGDad->next = pat;
954 pat->prev = patGDad;
955 }
956 else {
957 arcsighead = pat;
958 pat->prev = NULL;
959 }
960
961 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMTEXT,
962 MPFROM2SHORT(sSelect, 255), MPFROMP(szItemText));
963 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMTEXT,
964 MPFROM2SHORT(sSelect - 1, 255),
965 MPFROMP(szPCItemText));
966 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SETITEMTEXT,
967 MPFROMSHORT(sSelect), MPFROMP(szPCItemText));
968 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SETITEMTEXT,
969 MPFROMSHORT(sSelect - 1), MPFROMP(szItemText));
970 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
971 MPFROMSHORT(sSelect - 1), MPFROMSHORT(TRUE));
972 arcsigsmodified = TRUE;
973 }
974 }
975 return 0;
976 case ASEL_PB_DOWN:
977 sSelect =
978 (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYSELECTION,
979 MPFROMSHORT(LIT_FIRST), MPVOID);
980 sItemCount =
981 (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMCOUNT,
982 MPVOID, MPVOID);
983 if (sSelect != LIT_NONE && sSelect < sItemCount - 1) {
984 // Find self - assume all archivers listed since we are editing
985 for (i = 0, pat = arcsighead; pat && i < sSelect; pat = pat->next, i++) ; // Find self
986 if (!pat || !pat->next)
987 Runtime_Error(pszSrcFile, __LINE__, "Can't find item %d of %d",
988 sSelect, sItemCount);
989 else {
990 ARC_TYPE *patDad;
991 ARC_TYPE *patChild;
992
993 patDad = pat->prev;
994 patChild = pat->next;
995 pat->next = patChild->next;
996 patChild->next = pat;
997 pat->prev = patChild;
998 patChild->prev = patDad;
999 if (patDad) {
1000 patDad->next = patChild;
1001 patChild->prev = patDad;
1002 }
1003 else {
1004 arcsighead = patChild;
1005 patChild->prev = NULL;
1006 }
1007
1008 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMTEXT,
1009 MPFROM2SHORT(sSelect, 255), MPFROMP(szItemText));
1010 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYITEMTEXT,
1011 MPFROM2SHORT(sSelect + 1, 255),
1012 MPFROMP(szPCItemText));
1013 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SETITEMTEXT,
1014 MPFROMSHORT(sSelect), MPFROMP(szPCItemText));
1015 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SETITEMTEXT,
1016 MPFROMSHORT(sSelect + 1), MPFROMP(szItemText));
1017 WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_SELECTITEM,
1018 MPFROMSHORT(sSelect + 1), MPFROMSHORT(TRUE));
1019 arcsigsmodified = TRUE;
1020 }
1021 }
1022 return 0;
1023
1024 case ASEL_PB_REVERT:
1025 // Reload without checking in case changed outside
1026 sSelect =
1027 (SHORT) WinSendDlgItemMsg(hwnd, ASEL_LISTBOX, LM_QUERYSELECTION,
1028 MPFROMSHORT(LIT_FIRST), MPVOID);
1029 load_archivers();
1030 fill_listbox(hwnd, TRUE, sSelect);
1031 return 0;
1032
1033 case IDM_HELP:
1034 if (hwndHelp) {
1035 WinSendMsg(hwndHelp, HM_DISPLAY_HELP, MPFROM2SHORT(HELP_EDITARC, 0), // fixme to be HELP_SELARC
1036 MPFROMSHORT(HM_RESOURCEID));
1037 }
1038 }
1039 return 0; // WM_COMMAND
1040
1041 case WM_CONTROL:
1042 if (SHORT1FROMMP(mp1) == ASEL_LISTBOX && SHORT2FROMMP(mp1) == LN_ENTER)
1043 PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(DID_OK, 0), MPVOID);
1044 return 0;
1045
1046 case WM_CLOSE:
1047 WinDismissDlg(hwnd, FALSE);
1048 return 0;
1049
1050 default:
1051 break;
1052 }
1053 return WinDefDlgProc(hwnd, msg, mp1, mp2);
1054}
1055
1056/*
1057 see archiver.tmp
1058 02-08-96 23:55 1
1059 8 Feb 96 23:55:32 2
1060 8 Feb 96 11:55p 3
1061 96-02-08 23:55:32 4
1062 31-02-98 23:55 5
1063 */
1064
1065BOOL ArcDateTime(CHAR * dt, INT type, CDATE * cdate, CTIME * ctime)
1066{
1067 INT x;
1068 BOOL ret = FALSE;
1069 CHAR *p, *pp, *pd;
1070
1071 if (dt && cdate && ctime) {
1072 memset(cdate, 0, sizeof(CDATE));
1073 memset(ctime, 0, sizeof(CTIME));
1074 if (type) {
1075 p = dt;
1076 while (*p && *p == ' ')
1077 p++;
1078 pd = dt;
1079 switch (type) {
1080 case 1:
1081 cdate->month = atoi(pd);
1082 p = to_delim(pd, "-/.");
1083 if (p) {
1084 p++;
1085 cdate->day = atoi(p);
1086 pd = p;
1087 p = to_delim(pd, "-/.");
1088 if (p) {
1089 p++;
1090 cdate->year = atoi(p);
1091 if (cdate->year > 80 && cdate->year < 1900)
1092 cdate->year += 1900;
1093 else if (cdate->year < 1900)
1094 cdate->year += 2000;
1095 ret = TRUE;
1096 p = strchr(p, ' ');
1097 if (p) {
1098 while (*p && *p == ' ')
1099 p++;
1100 ctime->hours = atoi(p);
1101 p = to_delim(pd, ":.");
1102 if (p) {
1103 p++;
1104 ctime->minutes = atoi(p);
1105 p = to_delim(pd, ":.");
1106 if (p) {
1107 p++;
1108 ctime->seconds = atoi(p);
1109 }
1110 }
1111 }
1112 }
1113 }
1114 break;
1115
1116 case 2:
1117 cdate->day = atoi(p);
1118 p = strchr(p, ' ');
1119 if (p) {
1120 p++;
1121 for (x = 0; x < 12; x++) {
1122 if (!strnicmp(p, GetPString(IDS_JANUARY + x), 3))
1123 break;
1124 }
1125 if (x < 12) {
1126 cdate->month = x;
1127 p = strchr(p, ' ');
1128 if (p) {
1129 p++;
1130 cdate->year = atoi(p);
1131 if (cdate->year > 80 && cdate->year < 1900)
1132 cdate->year += 1900;
1133 else if (cdate->year < 1900)
1134 cdate->year += 2000;
1135 ret = TRUE;
1136 p = strchr(p, ' ');
1137 if (p) {
1138 while (*p && *p == ' ')
1139 p++;
1140 ctime->hours = atoi(p);
1141 p = to_delim(pd, ":.");
1142 if (p) {
1143 p++;
1144 ctime->minutes = atoi(p);
1145 p = to_delim(pd, ":.");
1146 if (p) {
1147 p++;
1148 ctime->seconds = atoi(p);
1149 }
1150 }
1151 }
1152 }
1153 }
1154 }
1155 break;
1156
1157 case 3:
1158 cdate->day = atoi(p);
1159 p = strchr(p, ' ');
1160 if (p) {
1161 p++;
1162 for (x = 0; x < 12; x++) {
1163 if (!strnicmp(p, GetPString(IDS_JANUARY + x), 3))
1164 break;
1165 }
1166 if (x < 12) {
1167 cdate->month = x;
1168 p = strchr(p, ' ');
1169 if (p) {
1170 p++;
1171 cdate->year = atoi(p);
1172 if (cdate->year > 80 && cdate->year < 1900)
1173 cdate->year += 1900;
1174 else if (cdate->year < 1900)
1175 cdate->year += 2000;
1176 ret = TRUE;
1177 p = strchr(p, ' ');
1178 if (p) {
1179 while (*p && *p == ' ')
1180 p++;
1181 ctime->hours = atoi(p);
1182 p = to_delim(pd, ":.");
1183 if (p) {
1184 p++;
1185 pp = p;
1186 ctime->minutes = atoi(p);
1187 p = to_delim(pd, ":.");
1188 if (p) {
1189 p++;
1190 ctime->seconds = atoi(p);
1191 p += 2;
1192 if (toupper(*p) == 'P')
1193 ctime->hours += 12;
1194 }
1195 else {
1196 p = pp;
1197 p += 2;
1198 if (toupper(*p) == 'P')
1199 ctime->hours += 12;
1200 }
1201 }
1202 }
1203 }
1204 }
1205 }
1206 break;
1207
1208 case 4:
1209 cdate->year = atoi(p);
1210 if (cdate->year > 80 && cdate->year < 1900)
1211 cdate->year += 1900;
1212 else if (cdate->year < 1900)
1213 cdate->year += 2000;
1214 p = to_delim(pd, "-/.");
1215 if (p) {
1216 p++;
1217 cdate->month = atoi(p);
1218 pd = p;
1219 p = to_delim(pd, "-/.");
1220 if (p) {
1221 p++;
1222 cdate->day = atoi(p);
1223 ret = TRUE;
1224 p = strchr(p, ' ');
1225 if (p) {
1226 while (*p && *p == ' ')
1227 p++;
1228 ctime->hours = atoi(p);
1229 p = to_delim(pd, ":.");
1230 if (p) {
1231 p++;
1232 ctime->minutes = atoi(p);
1233 p = to_delim(pd, ":.");
1234 if (p) {
1235 p++;
1236 ctime->seconds = atoi(p);
1237 }
1238 }
1239 }
1240 }
1241 }
1242 break;
1243
1244 case 5:
1245 cdate->day = atoi(pd);
1246 p = to_delim(pd, "-/.");
1247 if (p) {
1248 p++;
1249 cdate->month = atoi(p);
1250 pd = p;
1251 p = to_delim(pd, "-/.");
1252 if (p) {
1253 p++;
1254 cdate->year = atoi(p);
1255 if (cdate->year > 80 && cdate->year < 1900)
1256 cdate->year += 1900;
1257 else if (cdate->year < 1900)
1258 cdate->year += 2000;
1259 ret = TRUE;
1260 p = strchr(p, ' ');
1261 if (p) {
1262 while (*p && *p == ' ')
1263 p++;
1264 ctime->hours = atoi(p);
1265 p = to_delim(pd, ":.");
1266 if (p) {
1267 p++;
1268 ctime->minutes = atoi(p);
1269 p = to_delim(pd, ":.");
1270 if (p) {
1271 p++;
1272 ctime->seconds = atoi(p);
1273 }
1274 }
1275 }
1276 }
1277 }
1278 break;
1279
1280 default:
1281 break;
1282 }
1283 }
1284 }
1285 return ret;
1286}
1287
1288#pragma alloc_text(MISC9,quick_find_type,find_type)
1289#pragma alloc_text(AVL,load_archivers, get_line_strip_comments, get_line_strip_white, free_archivers)
1290#pragma alloc_text(FMARCHIVE,SBoxDlgProc,SDlgListboxSubclassProc)
1291#pragma alloc_text(ARCCNRS,ArcDateTime)
Note: See TracBrowser for help on using the repository browser.