|
|
1.1 root 1:
2: /******************************************************************************\
3: * This is a part of the Microsoft Source Code Samples.
4: * Copyright (C) 1993 Microsoft Corporation.
5: * All rights reserved.
6: * This source code is only intended as a supplement to
7: * Microsoft Development Tools and/or WinHelp documentation.
8: * See these sources for detailed information regarding the
9: * Microsoft samples programs.
10: \******************************************************************************/
11:
12: /****************************** Module Header *******************************
13: * Module Name: COMPLIST.C
14: *
15: * Supports a list of compitems, where each compitem represents
16: * a pair of matching files, or an unmatched file.
17: *
18: * Functions:
19: *
20: * complist_filedialog()
21: * complist_dirdialog()
22: * complist_args()
23: * complist_getitems()
24: * complist_delete()
25: * complist_savelist()
26: * complist_copyfiles()
27: * complist_dodlg_savelist()
28: * complist_dodlg_copyfiles()
29: * complist_match()
30: * complist_new()
31: * complist_dodlg_dir()
32: *
33: * Comments:
34: *
35: * We build lists of filenames from two pathnames (using the
36: * scandir module) and then traverse the two lists comparing names.
37: * Where the names match, we create a CompItem from the matching
38: * names. Where there is an unmatched name, we create a compitem for it.
39: *
40: * We may also be asked to create a complist for two individual files:
41: * here we create a single compitem for them as a matched pair even if
42: * the names don't match.
43: *
44: ****************************************************************************/
45:
46: #include <windows.h>
47: #include <stdlib.h>
48: #include <string.h>
49: #include <dos.h>
50: #include <direct.h>
51:
52: #include "gutils.h"
53: #include "state.h"
54: #include "windiff.h"
55: #include "wdiffrc.h"
56: #include "list.h"
57: #include "line.h"
58: #include "scandir.h"
59: #include "file.h"
60: #include "section.h"
61: #include "compitem.h"
62: #include "complist.h"
63: #include "view.h"
64:
65:
66: extern BOOL bAbort; /* defined in windiff.c Read only here */
67:
68: /*
69: * The COMPLIST handle is typedef-ed to be a pointer to one
70: * of these struct complist
71: */
72: struct complist {
73: DIRLIST left; /* left list of files */
74: DIRLIST right; /* right list of files */
75: LIST items; /* list of COMPITEMs */
76: };
77:
78: /* ---- module-wide data -------------------------------------*/
79:
80: /* data for communicating between the SaveList dlg and complist_savelist() */
81:
82: char dlg_file[256]; /* filename to save to */
83:
84: /* checkbox options */
85: BOOL dlg_identical, dlg_differ, dlg_left, dlg_right;
86:
87: /* data for Directory and SaveList */
88: char dialog_leftname[256];
89: char dialog_rightname[256];
90:
91: /*
92: * data used by dodlg_copyfiles
93: */
94: UINT dlg_options;
95: char dlg_root[256];
96:
97: /*------------------------timing for performance measurements-----------------*/
98:
99: static DWORD TickCount; /* time operation started, then time taken*/
100:
101:
102: int FAR PASCAL complist_dodlg_savelist(HWND hDlg, UINT message,
103: UINT wParam, long lParam);
104: int FAR PASCAL complist_dodlg_copyfiles(HWND hDlg, UINT message,
105: UINT wParam, long lParam);
106: BOOL complist_match(COMPLIST cl, VIEW view, BOOL fDeep, BOOL fExact);
107: COMPLIST complist_new(void);
108: int FAR PASCAL complist_dodlg_dir(HWND hDlg, unsigned message,
109: WORD wParam, LONG lParam);
110:
111:
112:
113: /***************************************************************************
114: * Function: complist_filedialog
115: *
116: * Purpose:
117: *
118: * Builds a complist by putting up two dialogs to allow the user to
119: * select two files. This will build a Complist with one CompItem (even
120: * if the names don't match).
121: *
122: ***************************************************************************/
123: COMPLIST
124: complist_filedialog(VIEW view)
125: {
126: COMPLIST cl;
127: OFSTRUCT os1, os2;
128: char fname[256], FileExt[256], FileOpenSpec[256];
129:
130: /* ask for the filenames */
131: lstrcpy(FileExt, ".c");
132: lstrcpy(FileOpenSpec, "*.*");
133: lstrcpy(fname,"");
134:
135: if (!complist_open("Select First File", FileExt, FileOpenSpec,
136: &os1, fname) )
137: return(NULL);
138:
139: lstrcpy(FileExt, ".c");
140: lstrcpy(FileOpenSpec, "*.*");
141: lstrcpy(fname,"");
142:
143: if (!complist_open("Select Second File", FileExt, FileOpenSpec,
144: &os2, fname) )
145: return(NULL);
146:
147: /* alloc a new structure */
148: cl = complist_new();
149:
150: cl->left = dir_buildlist(os1.szPathName, TRUE);
151: cl->right = dir_buildlist(os2.szPathName, TRUE);
152:
153:
154: /* register with the view (must be done after the list is non-null) */
155: view_setcomplist(view, cl);
156:
157: complist_match(cl, view, FALSE, TRUE);
158:
159: return(cl);
160: }/* complist_filedialog */
161:
162: /***************************************************************************
163: * Function: complist_dirdialog
164: *
165: * Purpose:
166: *
167: * Builds a new complist by querying the user for two directory
168: * names and scanning those in parallel.
169: *
170: * Names that match in the same directory will be paired - unmatched
171: * names will go in a compitem on their own.
172: *
173: ***************************************************************************/
174: COMPLIST
175: complist_dirdialog(VIEW view)
176: {
177: DLGPROC lpProc;
178: BOOL fOK;
179:
180: /* put up a dialog for the two pathnames */
181: lpProc = (DLGPROC)MakeProcInstance((WNDPROC)complist_dodlg_dir, hInst);
182: windiff_UI(TRUE);
183: fOK = DialogBox(hInst, "Directory", hwndClient, lpProc);
184: windiff_UI(FALSE);
185: FreeProcInstance(lpProc);
186:
187: if (!fOK) {
188: return(NULL);
189: }
190:
191: return complist_args( dialog_leftname, dialog_rightname
192: , view, FALSE );
193: } /* complist_dirdialog */
194:
195:
196: /***************************************************************************
197: * Function: complist_args
198: *
199: * Purpose:
200: *
201: * Given two pathname strings, scan the directories and traverse them
202: * in parallel comparing matching names.
203: *
204: ***************************************************************************/
205: COMPLIST
206: complist_args(LPSTR p1, LPSTR p2, VIEW view, BOOL fDeep)
207: {
208: COMPLIST cl;
209: char msg[256];
210:
211:
212: /* alloc a new complist */
213: cl = complist_new();
214:
215: cl->left = dir_buildlist(p1, TRUE);
216: /* check that we could find the paths, and report if not */
217: if (cl->left == NULL) {
218: wsprintf((LPTSTR)msg, "Couldn't find %s", p1);
219: MessageBox(NULL, msg, "Error", MB_OK | MB_ICONSTOP);
220: return(NULL);
221: }
222:
223: cl->right = dir_buildlist(p2, TRUE);
224: if (cl->right == NULL) {
225: wsprintf((LPTSTR)msg, "Couldn't find %s", p2);
226: MessageBox(NULL, msg, "Error", MB_OK | MB_ICONSTOP);
227: return(NULL);
228: }
229:
230: /* register with the view (must be done after building lists) */
231: view_setcomplist(view, cl);
232:
233: complist_match(cl, view, fDeep, TRUE);
234:
235: return(cl);
236: } /* complist_args */
237:
238: /***************************************************************************
239: * Function: complist_getitems
240: *
241: * Purpose:
242: *
243: * Gets the handle to the list of COMPITEMs. The list continues to be
244: * owned by the COMPLIST, so don't delete except by calling complist_delete.
245: *
246: ***************************************************************************/
247: LIST
248: complist_getitems(COMPLIST cl)
249: {
250: if (cl == NULL) {
251: return(NULL);
252: }
253:
254: return(cl->items);
255: }
256:
257: /***************************************************************************
258: * Function: complist_delete
259: *
260: * Purpose:
261: *
262: * Deletes a complist and all associated CompItems and DIRLISTs. Note this
263: * does not delete any VIEW - the VIEW owns the COMPLIST and not the other
264: * way around.
265: *
266: **************************************************************************/
267: void
268: complist_delete(COMPLIST cl)
269: {
270: COMPITEM item;
271:
272: if (cl == NULL) {
273: return;
274: }
275:
276: /* delete the two directory scan lists */
277: dir_delete(cl->left);
278: dir_delete(cl->right);
279:
280: /* delete the compitems in the list */
281: List_TRAVERSE(cl->items, item) {
282: compitem_delete(item);
283: }
284:
285: /* delete the list itself */
286: List_Destroy(&cl->items);
287:
288: gmem_free(hHeap, (LPSTR) cl, sizeof(struct complist));
289:
290: }
291:
292: /***************************************************************************
293: * Function: complist_savelist
294: *
295: * Purpose:
296: *
297: * Writes out to a text file the list of compitems as relative filenames
298: * one per line.
299: *
300: * If savename is non-null, use this as the filename for output; otherwise,
301: * query the user via a dialog for the filename and include options.
302: *
303: **************************************************************************/
304: void
305: complist_savelist(COMPLIST cl, LPSTR savename, UINT options)
306: {
307: DLGPROC lpProc;
308: static BOOL done_init = FALSE;
309: BOOL bOK;
310: int fh, state;
311: OFSTRUCT os;
312: char msg[256];
313: HCURSOR hcurs;
314: COMPITEM ci;
315: LPSTR pstr, lhead, rhead;
316: int nFiles = 0;
317:
318: if (!done_init) {
319: /* init the options once round - but keep the same options
320: * for the rest of the session.
321: */
322:
323: /* first init default options */
324: dlg_identical = FALSE;
325: dlg_differ = TRUE;
326: dlg_left = TRUE;
327: dlg_right = FALSE;
328:
329: dlg_file[0] = '\0';
330:
331: done_init = TRUE;
332: }
333:
334: if (cl == NULL) {
335: return;
336: }
337:
338: if (savename == NULL) {
339:
340: /* store the left and right rootnames so that dodlg_savelist
341: * can display them in the dialog.
342: */
343: pstr = dir_getroot_list(cl->left);
344: lstrcpy(dialog_leftname, pstr);
345: dir_freeroot_list(cl->left, pstr);
346:
347: pstr = dir_getroot_list(cl->right);
348: lstrcpy(dialog_rightname, pstr);
349: dir_freeroot_list(cl->right, pstr);
350:
351: lpProc = (DLGPROC)MakeProcInstance((WNDPROC)complist_dodlg_savelist, hInst);
352: windiff_UI(TRUE);
353: bOK = DialogBox(hInst, "SaveList", hwndClient, lpProc);
354: windiff_UI(FALSE);
355: FreeProcInstance(lpProc);
356:
357: if (!bOK) {
358: /* user cancelled from dialog box */
359: return;
360: }
361: savename = dlg_file;
362:
363: } else {
364: dlg_identical = (options & INCLUDE_SAME);
365: dlg_differ = (options & INCLUDE_DIFFER);
366: dlg_left = (options & INCLUDE_LEFTONLY);
367: dlg_right = (options & INCLUDE_RIGHTONLY);
368: }
369:
370:
371: /* try to open the file */
372: fh = OpenFile(savename, &os, OF_CREATE|OF_READWRITE|OF_SHARE_DENY_WRITE);
373: if (fh < 0) {
374: wsprintf((LPTSTR)msg, "Cannot open %s", savename);
375: windiff_UI(TRUE);
376: MessageBox(NULL, msg, "Windiff", MB_ICONSTOP|MB_OK);
377: windiff_UI(FALSE);
378: return;
379: }
380:
381: hcurs = SetCursor(LoadCursor(NULL, IDC_WAIT));
382:
383: /* write out the header line */
384: lhead = dir_getroot_list(cl->left);
385: rhead = dir_getroot_list(cl->right);
386: wsprintf((LPTSTR)msg, "-- %s : %s -- includes %s%s%s%s files\n",
387: lhead, rhead,
388: (LPSTR) (dlg_identical ? "identical," : ""),
389: (LPSTR) (dlg_left ? "left-only," : ""),
390: (LPSTR) (dlg_right ? "right-only," : ""),
391: (LPSTR) (dlg_differ ? "differing" : "") );
392: _lwrite(fh, msg, lstrlen(msg));
393: dir_freeroot_list(cl->left, lhead);
394: dir_freeroot_list(cl->right, rhead);
395:
396:
397: /* traverse the list of compitems looking for the
398: * ones we are supposed to include
399: */
400: List_TRAVERSE(cl->items, ci) {
401:
402: /* check if files of this type are to be listed */
403: state = compitem_getstate(ci);
404:
405: if ((state == STATE_SAME) && (!dlg_identical)) {
406: continue;
407: } else if ((state == STATE_DIFFER) && (!dlg_differ)) {
408: continue;
409: } else if ((state == STATE_FILELEFTONLY) && (!dlg_left)) {
410: continue;
411: } else if ((state == STATE_FILERIGHTONLY) && (!dlg_right)) {
412: continue;
413: }
414:
415: nFiles++;
416:
417: /* output the list line */
418: wsprintf((LPTSTR)msg, "%s", compitem_gettext_tag(ci));
419: _lwrite(fh, msg, lstrlen(msg));
420:
421: wsprintf((LPTSTR)msg, "\n");
422: _lwrite(fh, msg, strlen(msg));
423: }
424:
425: /* write tail line */
426: wsprintf((LPTSTR)msg, "-- %d files listed\n", nFiles);
427: _lwrite(fh, msg, lstrlen(msg));
428:
429: /* - close file and we are finished */
430: _lclose(fh);
431:
432: SetCursor(hcurs);
433: } /* complist_savelist */
434:
435: /***************************************************************************
436: * Function: complist_copyfiles
437: *
438: * Purpose:
439: *
440: * To copy files to a new directory newroot. if newroot is NULL, query the user
441: * via a dialog to get the new dir name and options.
442: *
443: * Options are either COPY_FROMLEFT or COPY_FROMRIGHT (indicating which
444: * tree is to be the source of the files, plus any or all of
445: * INCLUDE_SAME, INCLUDE_DIFFER and INCLUDE_LEFT (INCLUDE_LEFT
446: * and INCLUDE_RIGHT are treated the same here since the COPY_FROM* option
447: * indicates which side to copy from).
448: *
449: ***************************************************************************/
450: void
451: complist_copyfiles(COMPLIST cl, LPSTR newroot, UINT options)
452: {
453: int nFiles = 0;
454: int nFails = 0;
455: static BOOL done_init = FALSE;
456: LPSTR pstr;
457: char buffer[64];
458: DIRITEM diritem;
459: DLGPROC lpProc;
460: BOOL bOK;
461: COMPITEM ci;
462: int state;
463:
464: if (!done_init) {
465: /*
466: * one-time initialisation of dialog defaults
467: */
468: dlg_options = COPY_FROMLEFT|INCLUDE_LEFTONLY|INCLUDE_DIFFER;
469: dlg_root[0] = '\0';
470: done_init = TRUE;
471: }
472:
473: if (cl == NULL) {
474: return;
475: }
476:
477:
478: if (newroot == NULL) {
479: /*
480: * put up dialog to query rootname and options
481: */
482:
483: /* store the left and right rootnames so that the dlg proc
484: * can display them in the dialog.
485: */
486: pstr = dir_getroot_list(cl->left);
487: lstrcpy(dialog_leftname, pstr);
488: dir_freeroot_list(cl->left, pstr);
489:
490: pstr = dir_getroot_list(cl->right);
491: lstrcpy(dialog_rightname, pstr);
492: dir_freeroot_list(cl->right, pstr);
493:
494: do {
495: lpProc = (DLGPROC)MakeProcInstance((WNDPROC)complist_dodlg_copyfiles, hInst);
496: windiff_UI(TRUE);
497: bOK = DialogBox(hInst, "CopyFiles", hwndClient, lpProc);
498: windiff_UI(FALSE);
499: FreeProcInstance(lpProc);
500:
501: if (!bOK) {
502: /* user cancelled from dialog box */
503: return;
504: }
505: if (lstrlen(dlg_root) == 0) {
506: windiff_UI(TRUE);
507: MessageBox(NULL, "Please enter the directory name",
508: "Windiff", MB_ICONSTOP|MB_OK);
509: windiff_UI(FALSE);
510: }
511: } while (lstrlen(dlg_root) == 0);
512:
513: } else {
514: dlg_options = options;
515: lstrcpy(dlg_root, newroot);
516: }
517:
518: TickCount = GetTickCount();
519:
520: if (dlg_options & COPY_FROMLEFT) {
521: if (!dir_startcopy(cl->left))
522: return;
523: } else {
524: if (!dir_startcopy(cl->right))
525: return;
526: }
527:
528: /*
529: * traverse the list of compitems copying files as necessary
530: */
531: List_TRAVERSE(cl->items, ci) {
532:
533: if (bAbort){
534: break; /* fall into end_copy processing */
535: }
536: /* check if files of this type are to be copied */
537: state = compitem_getstate(ci);
538:
539: if ((state == STATE_SAME) && !(dlg_options & INCLUDE_SAME)) {
540: continue;
541: } else if ((state == STATE_DIFFER) && !(dlg_options & INCLUDE_DIFFER)) {
542: continue;
543: } else if (state == STATE_FILELEFTONLY) {
544: if (dlg_options & COPY_FROMRIGHT) {
545: continue;
546: }
547: if ((dlg_options & (INCLUDE_LEFTONLY | INCLUDE_RIGHTONLY)) == 0) {
548: continue;
549: }
550: } else if (state == STATE_FILERIGHTONLY) {
551: if (dlg_options & COPY_FROMLEFT) {
552: continue;
553: }
554: if ((dlg_options & (INCLUDE_LEFTONLY | INCLUDE_RIGHTONLY)) == 0) {
555: continue;
556: }
557: }
558:
559: if (dlg_options & COPY_FROMLEFT) {
560: diritem = file_getdiritem(compitem_getleftfile(ci));
561: } else {
562: diritem = file_getdiritem(compitem_getrightfile(ci));
563: }
564:
565: /*
566: * copy the file to the new root directory
567: */
568: if (dir_copy(diritem, dlg_root) == FALSE) {
569: nFails++;
570: pstr = dir_getrelname(diritem);
571: wsprintf((LPTSTR)buffer, "failed to copy %s", pstr);
572: dir_freerelname(diritem, pstr);
573:
574: if (MessageBox(NULL, buffer, "Error", MB_OKCANCEL | MB_ICONSTOP) == IDCANCEL)
575: /* user pressed cancel - abort current operation*/
576: /* fall through to end-copy processing */
577: break;
578:
579: } else {
580: nFiles++;
581: }
582:
583: wsprintf((LPTSTR)buffer, "%4d files requested. Copying...", nFiles);
584: SetStatus(buffer);
585:
586:
587: /*
588: * allow user interface to continue
589: */
590: if (Poll()) {
591: /* abort requested */
592: TickCount = GetTickCount()-TickCount;
593: windiff_UI(TRUE);
594: MessageBox(hwndClient, "Copy Aborted",
595: "WinDiff", MB_OK|MB_ICONINFORMATION);
596: windiff_UI(FALSE);
597: break;
598: }
599:
600: } /* traverse */
601: if (dlg_options & COPY_FROMLEFT) {
602: nFails = dir_endcopy(cl->left);
603: } else {
604: nFails = dir_endcopy(cl->right);
605: }
606: TickCount = GetTickCount()-TickCount;
607:
608: if (nFails<0) {
609: wsprintf((LPTSTR)buffer, "Copy Complete: %d files failed", -nFails);
610: } else {
611: wsprintf((LPTSTR)buffer, "Copy Complete %d files copied", nFails);
612: }
613: windiff_UI(TRUE);
614: MessageBox(hwndClient, buffer, "WinDiff", MB_OK|MB_ICONINFORMATION);
615: windiff_UI(FALSE);
616:
617: buffer[0] = '\0';
618: SetStatus(buffer);
619: } /* complist_copyfiles */
620:
621:
622: /***************************************************************************
623: * Function: complist_match
624: *
625: * Purpose:
626: *
627: * Matches up two lists of filenames
628: *
629: * Commentsz:
630: *
631: * We can find out from the DIRLIST handle whether the original list
632: * was a file or a directory name.
633: * If the user typed:
634: * two file names - match these two item even if the names differ
635: *
636: * two dirs - match only those items whose names match
637: *
638: * one file and one dir
639: * - try to find a file of that name in the dir.
640: *
641: * This function returns TRUE if the complist_match was ok, or FALSE if it was
642: * aborted in some way.
643: *
644: ***************************************************************************/
645: BOOL
646: complist_match(COMPLIST cl, VIEW view, BOOL fDeep, BOOL fExact)
647: {
648: LPSTR lname;
649: LPSTR rname;
650: DIRITEM leftitem, rightitem;
651: int cmpvalue;
652:
653: TickCount = GetTickCount();
654:
655: if (dir_isfile(cl->left) ) {
656:
657: if (dir_isfile(cl->right)) {
658: /* two files */
659:
660: /* there should be one item in each list - make
661: * a compitem by matching these two and append it to the
662: * list
663: */
664: compitem_new(dir_firstitem(cl->left),
665: dir_firstitem(cl->right), cl->items, fExact);
666:
667: view_newitem(view);
668:
669: TickCount = GetTickCount() - TickCount;
670: return TRUE;
671: }
672: /* left is file, right is dir */
673: leftitem = dir_firstitem(cl->left);
674: rightitem = dir_firstitem(cl->right);
675: lname = dir_getrelname(leftitem);
676: while (rightitem != NULL) {
677: rname = dir_getrelname(rightitem);
678: cmpvalue = lstrcmpi(lname, rname);
679: dir_freerelname(rightitem, rname);
680:
681: if (cmpvalue == 0) {
682: /* this is the match */
683: compitem_new(leftitem, rightitem, cl->items, fExact);
684: view_newitem(view);
685:
686: dir_freerelname(leftitem, lname);
687:
688: TickCount = GetTickCount() - TickCount;
689: return(TRUE);
690: }
691:
692: rightitem = dir_nextitem(cl->right, rightitem, fDeep);
693: }
694: /* not found */
695: dir_freerelname(leftitem, lname);
696: compitem_new(leftitem, NULL, cl->items, fExact);
697: view_newitem(view);
698: TickCount = GetTickCount() - TickCount;
699: return(TRUE);
700:
701: } else if (dir_isfile(cl->right)) {
702:
703: /* left is dir, right is file */
704:
705: /* loop through the left dir, looking for
706: * a file that has the same name as rightitem
707: */
708:
709: leftitem = dir_firstitem(cl->left);
710: rightitem = dir_firstitem(cl->right);
711: rname = dir_getrelname(rightitem);
712: while (leftitem != NULL) {
713: lname = dir_getrelname(leftitem);
714: cmpvalue = lstrcmpi(lname, rname);
715: dir_freerelname(leftitem, lname);
716:
717: if (cmpvalue == 0) {
718: /* this is the match */
719: compitem_new(leftitem, rightitem, cl->items, fExact);
720: view_newitem(view);
721:
722: dir_freerelname(rightitem, rname);
723:
724: TickCount = GetTickCount() - TickCount;
725: return(TRUE);
726: }
727:
728: leftitem = dir_nextitem(cl->left, leftitem, fDeep);
729: }
730: /* not found */
731: dir_freerelname(rightitem, rname);
732: compitem_new(NULL, rightitem, cl->items, fExact);
733: view_newitem(view);
734: TickCount = GetTickCount() - TickCount;
735: return(TRUE);
736: }
737:
738: /* two directories */
739:
740: /* traverse the two lists in parallel comparing the relative names*/
741:
742: leftitem = dir_firstitem(cl->left);
743: rightitem = dir_firstitem(cl->right);
744: while ((leftitem != NULL) && (rightitem != NULL)) {
745:
746: lname = dir_getrelname(leftitem);
747: rname = dir_getrelname(rightitem);
748: cmpvalue = utils_CompPath(lname, rname);
749: dir_freerelname(leftitem, lname);
750: dir_freerelname(rightitem, rname);
751:
752: if (cmpvalue == 0) {
753: compitem_new(leftitem, rightitem, cl->items, fExact);
754: if (view_newitem(view)) {
755: TickCount = GetTickCount() - TickCount;
756: return(FALSE);
757: }
758: leftitem = dir_nextitem(cl->left, leftitem, fDeep);
759: rightitem = dir_nextitem(cl->right, rightitem, fDeep);
760:
761: } else if (cmpvalue < 0) {
762: compitem_new(leftitem, NULL, cl->items, fExact);
763: if (view_newitem(view)) {
764: TickCount = GetTickCount() - TickCount;
765: return(FALSE);
766: }
767: leftitem = dir_nextitem(cl->left, leftitem, fDeep);
768: } else {
769: compitem_new(NULL, rightitem, cl->items, fExact);
770: if (view_newitem(view)) {
771: TickCount = GetTickCount() - TickCount;
772: return(FALSE);
773: }
774: rightitem = dir_nextitem(cl->right, rightitem, fDeep);
775: }
776: }
777:
778:
779: /* any left over are unmatched */
780: while (leftitem != NULL) {
781: compitem_new(leftitem, NULL, cl->items, fExact);
782: if (view_newitem(view)) {
783: TickCount = GetTickCount() - TickCount;
784: return(FALSE);
785: }
786: leftitem = dir_nextitem(cl->left, leftitem, fDeep);
787: }
788: while (rightitem != NULL) {
789: compitem_new(NULL, rightitem, cl->items, fExact);
790: if (view_newitem(view)) {
791: TickCount = GetTickCount() - TickCount;
792: return(FALSE);
793: }
794: rightitem = dir_nextitem(cl->right, rightitem, fDeep);
795: }
796: TickCount = GetTickCount() - TickCount;
797: return(TRUE);
798: } /* complist_match */
799:
800: /* return time last operation took in milliseconds */
801: DWORD complist_querytime(void)
802: { return TickCount;
803: }
804:
805:
806: /***************************************************************************
807: * Function: complist_dodlg_savelist
808: *
809: * Purpose:
810: *
811: * Dialog to query about filename and types of files. Init dlg fields from
812: * the dlg_* variables, and save state to the dlg_* variables on dialog
813: * close. return TRUE for OK, or FALSE for cancel (from the dialogbox()
814: * using EndDialog).
815: *
816: **************************************************************************/
817: int FAR PASCAL
818: complist_dodlg_savelist(HWND hDlg, UINT message, UINT wParam, long lParam)
819: {
820: static char buffer[256];
821:
822: switch(message) {
823:
824:
825: case WM_INITDIALOG:
826: SendDlgItemMessage(hDlg, IDD_IDENTICAL, BM_SETCHECK,
827: dlg_identical ? 1 : 0, 0);
828: SendDlgItemMessage(hDlg, IDD_DIFFER, BM_SETCHECK,
829: dlg_differ ? 1 : 0, 0);
830: SendDlgItemMessage(hDlg, IDD_LEFT, BM_SETCHECK,
831: dlg_left ? 1 : 0, 0);
832: SendDlgItemMessage(hDlg, IDD_RIGHT, BM_SETCHECK,
833: dlg_right ? 1 : 0, 0);
834:
835: SetDlgItemText(hDlg, IDD_FILE, dlg_file);
836:
837: /* convert 'left tree' into the right name */
838: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_leftname);
839: SendDlgItemMessage(hDlg, IDD_LEFT, WM_SETTEXT, 0, (DWORD) (LPSTR) buffer);
840:
841: /* convert 'right tree' msg into correct path */
842: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_rightname);
843: SendDlgItemMessage(hDlg, IDD_RIGHT, WM_SETTEXT, 0, (DWORD) (LPSTR) buffer);
844:
845:
846: return(TRUE);
847:
848: case WM_COMMAND:
849: switch (GET_WM_COMMAND_ID(wParam, lParam)) {
850:
851: case IDOK:
852: dlg_identical = (SendDlgItemMessage(hDlg, IDD_IDENTICAL,
853: BM_GETCHECK, 0, 0) == 1);
854: dlg_differ = (SendDlgItemMessage(hDlg, IDD_DIFFER,
855: BM_GETCHECK, 0, 0) == 1);
856: dlg_left = (SendDlgItemMessage(hDlg, IDD_LEFT,
857: BM_GETCHECK, 0, 0) == 1);
858: dlg_right = (SendDlgItemMessage(hDlg, IDD_RIGHT,
859: BM_GETCHECK, 0, 0) == 1);
860: GetDlgItemText(hDlg, IDD_FILE, dlg_file, sizeof(dlg_file));
861:
862: EndDialog(hDlg, TRUE);
863: break;
864:
865: case IDCANCEL:
866: EndDialog(hDlg, FALSE);
867: break;
868: }
869: }
870: return(FALSE);
871: } /* complist_dodlg_savelist */
872:
873: /***************************************************************************
874: * Function: complist_dodlg_copyfiles
875: *
876: * Purpose:
877: *
878: * dialog to get directory name and inclusion options. Init dlg fields from
879: * the dlg_* variables, and save state to the dlg_* variables on dialog
880: * close. return TRUE for OK, or FALSE for cancel (from the dialogbox()
881: * using EndDialog).
882: *
883: **************************************************************************/
884: int FAR PASCAL
885: complist_dodlg_copyfiles(HWND hDlg, UINT message, UINT wParam, long lParam)
886: {
887: static char buffer[256];
888:
889: switch(message) {
890:
891:
892: case WM_INITDIALOG:
893: /*
894: * set checkboxes and directory field to defaults
895: */
896: CheckDlgButton(hDlg, IDD_IDENTICAL,
897: (dlg_options & INCLUDE_SAME) ? 1 : 0);
898:
899: CheckDlgButton(hDlg, IDD_DIFFER,
900: (dlg_options & INCLUDE_DIFFER) ? 1 : 0);
901:
902: CheckDlgButton(hDlg, IDD_LEFT,
903: (dlg_options & (INCLUDE_LEFTONLY|INCLUDE_RIGHTONLY)) ? 1 : 0);
904:
905: SetDlgItemText(hDlg, IDD_DIR1, dlg_root);
906:
907: /*
908: * set 'copy from' buttons to have the full pathname
909: */
910: SetDlgItemText(hDlg, IDD_FROMLEFT, dialog_leftname);
911: SetDlgItemText(hDlg, IDD_FROMRIGHT, dialog_rightname);
912:
913: /*
914: * set default radio button for copy from, and set
915: * the text on the 'files only in...' checkbox to
916: * indicate which path is being selected
917: */
918: if (dlg_options & COPY_FROMLEFT) {
919: CheckRadioButton(hDlg, IDD_FROMLEFT, IDD_FROMRIGHT,
920: IDD_FROMLEFT);
921:
922: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_leftname);
923: SetDlgItemText(hDlg, IDD_LEFT, buffer);
924: } else {
925: CheckRadioButton(hDlg, IDD_FROMLEFT, IDD_FROMRIGHT,
926: IDD_FROMRIGHT);
927:
928: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_rightname);
929: SetDlgItemText(hDlg, IDD_LEFT, buffer);
930: }
931:
932: return(TRUE);
933:
934: case WM_COMMAND:
935: switch (GET_WM_COMMAND_ID(wParam, lParam)) {
936:
937: case IDD_FROMLEFT:
938: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_leftname);
939: SetDlgItemText(hDlg, IDD_LEFT, buffer);
940:
941: dlg_options &= ~(COPY_FROMRIGHT);
942: dlg_options |= COPY_FROMLEFT;
943: break;
944:
945: case IDD_FROMRIGHT:
946: wsprintf((LPTSTR)buffer, "Files only in %s", (LPSTR) dialog_rightname);
947: SetDlgItemText(hDlg, IDD_LEFT, buffer);
948:
949: dlg_options &= ~(COPY_FROMLEFT);
950: dlg_options |= COPY_FROMRIGHT;
951: break;
952:
953: case IDOK:
954: if (SendDlgItemMessage(hDlg, IDD_IDENTICAL,
955: BM_GETCHECK, 0, 0) == 1) {
956: dlg_options |= INCLUDE_SAME;
957: } else {
958: dlg_options &= ~INCLUDE_SAME;
959: }
960: if (SendDlgItemMessage(hDlg, IDD_DIFFER,
961: BM_GETCHECK, 0, 0) == 1) {
962: dlg_options |= INCLUDE_DIFFER;
963: } else {
964: dlg_options &= ~INCLUDE_DIFFER;
965: }
966: if (SendDlgItemMessage(hDlg, IDD_LEFT,
967: BM_GETCHECK, 0, 0) == 1) {
968: dlg_options |= INCLUDE_LEFTONLY;
969: } else {
970: dlg_options &= ~INCLUDE_LEFTONLY;
971: }
972: GetDlgItemText(hDlg, IDD_DIR1, dlg_root, sizeof(dlg_root));
973:
974: EndDialog(hDlg, TRUE);
975: break;
976:
977: case IDCANCEL:
978: EndDialog(hDlg, FALSE);
979: break;
980: }
981: }
982: return(FALSE);
983: } /* complist_dodlg_copyfiles */
984:
985: /***************************************************************************
986: * Function: complist_new
987: *
988: * Purpose:
989: *
990: * Allocates a new complist and initialise it
991: *
992: **************************************************************************/
993: COMPLIST
994: complist_new(void)
995: {
996: COMPLIST cl;
997:
998: cl = (COMPLIST) gmem_get(hHeap, sizeof(struct complist));
999: cl->left = NULL;
1000: cl->right = NULL;
1001: cl->items = List_Create();
1002:
1003: return(cl);
1004: } /* complist_new */
1005:
1006: /***************************************************************************
1007: * Function: complist_dodlg_dir
1008: *
1009: * Purpose:
1010: *
1011: * Dialog box function to ask for two directory names.
1012: * no listing of files etc - just two edit fields in which the
1013: * user can type a file or a directory name.
1014: *
1015: * Initialises the names from win.ini, and stores them to win.ini first.
1016: *
1017: **************************************************************************/
1018: int FAR PASCAL
1019: complist_dodlg_dir(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
1020: {
1021: static char path[256];
1022: static char buffer[256];
1023:
1024: switch (message) {
1025:
1026: case WM_INITDIALOG:
1027:
1028: /* fill the edit fields with the current
1029: * directory as a good starting point
1030: */
1031: _getcwd(path, sizeof(path));
1032: AnsiLowerBuff(path, strlen(path));
1033: GetProfileString(APPNAME, "NameLeft", path, buffer, 256);
1034: SetDlgItemText(hDlg, IDD_DIR1, buffer);
1035: GetProfileString(APPNAME, "NameRight", path, buffer, 256);
1036: SetDlgItemText(hDlg, IDD_DIR2, buffer);
1037: return(TRUE);
1038:
1039: case WM_COMMAND:
1040: switch (LOWORD(wParam)) {
1041: case IDCANCEL:
1042: EndDialog(hDlg, FALSE);
1043: return(TRUE);
1044:
1045: case IDOK:
1046: /* fetch the text from the dialog, and remember
1047: * it in win.ini
1048: */
1049:
1050: GetDlgItemText(hDlg, IDD_DIR1,
1051: dialog_leftname, sizeof(dialog_leftname));
1052: WriteProfileString(APPNAME, "NameLeft", dialog_leftname);
1053:
1054: GetDlgItemText(hDlg, IDD_DIR2,
1055: dialog_rightname, sizeof(dialog_rightname));
1056:
1057: EndDialog(hDlg, TRUE);
1058: return(TRUE);
1059: }
1060: break;
1061: }
1062: return(FALSE);
1063: } /* complist_dodlg_dir */
1064:
1065: /***************************************************************************
1066: * Function: complist_open
1067: *
1068: * Purpose:
1069: *
1070: * Puts up dialog asking the user to select an existing file to open.
1071: *
1072: * Parameters:
1073: *
1074: * prompt - message to user indicating purpose of file
1075: * (to be displayed somewhere in dialog box.
1076: *
1077: * ext - default file extension if user enters file without
1078: * extension.
1079: *
1080: * spec - default file spec (eg *.*)
1081: *
1082: * osp - OFSTRUCT representing file, if successfully open.
1083: *
1084: * fn - buffer where filename (just final element) is returned.
1085: *
1086: * Returns:
1087: *
1088: * TRUE - if file selected and exists (tested with OF_EXIST).
1089: *
1090: * FALSE - if dialog cancelled. If user selects a file that we cannot
1091: * open, we complain and restart the dialog.
1092: *
1093: * Comments:
1094: *
1095: * if TRUE is returned, the file will have been successfully opened,
1096: * for reading and then closed again.
1097: *
1098: **************************************************************************/
1099:
1100: BOOL FAR PASCAL
1101: complist_open(LPSTR prompt, LPSTR ext, LPSTR spec, OFSTRUCT FAR *osp, LPSTR fn)
1102: {
1103: OPENFILENAME ofn;
1104: char achFilters[256];
1105: char achPath[256];
1106: LPSTR chp;
1107: int fh;
1108:
1109: /* build filter-pair buffer to contain one pair - the spec filter,
1110: * twice (one of the pair should be the filter, the second should be
1111: * the title of the filter - we don't have a title so we use the
1112: * filter both times. remember double null at end of list of strings.
1113: */
1114: lstrcpy(achFilters, spec); // filter + null
1115: chp = &achFilters[lstrlen(achFilters)+1]; //2nd string just after null
1116: lstrcpy(chp, spec); // filter name (+null)
1117: chp[lstrlen(chp)+1] = '\0'; // double null at end of list
1118: /*
1119: * initialise arguments to dialog proc
1120: */
1121: ofn.lStructSize = sizeof(OPENFILENAME);
1122: ofn.hwndOwner = NULL;
1123: ofn.hInstance = NULL;
1124: ofn.lpstrFilter = achFilters;
1125: ofn.lpstrCustomFilter = (LPSTR)NULL;
1126: ofn.nMaxCustFilter = 0L;
1127: ofn.nFilterIndex = 1L; // first filter pair in list
1128: achPath[0] = '\0';
1129: ofn.lpstrFile = achPath; // we need to get the full path to open
1130: ofn.nMaxFile = sizeof(achPath);
1131: ofn.lpstrFileTitle = fn; // return final elem of name here
1132: ofn.nMaxFileTitle = sizeof(fn);
1133: ofn.lpstrInitialDir = NULL;
1134: ofn.lpstrTitle = prompt; // dialog title is good place for prompt text
1135: ofn.Flags = OFN_FILEMUSTEXIST |
1136: OFN_HIDEREADONLY |
1137: OFN_PATHMUSTEXIST;
1138: ofn.lpstrDefExt = ext;
1139: ofn.nFileOffset = 0;
1140: ofn.nFileExtension = 0;
1141: ofn.lCustData = 0;
1142:
1143: /*
1144: * loop until the user cancels, or selects a file that we can open
1145: */
1146: do {
1147: if (!GetOpenFileName(&ofn)) {
1148: return(FALSE);
1149: }
1150:
1151: fh = OpenFile(achPath, osp, OF_READ);
1152:
1153: if (fh == HFILE_ERROR) {
1154: if (MessageBox(NULL, "File Could Not Be Opened", "File Open",
1155: MB_OKCANCEL|MB_ICONSTOP) == IDCANCEL) {
1156: return(FALSE);
1157: }
1158: }
1159: } while (fh == HFILE_ERROR);
1160:
1161: _lclose(fh);
1162:
1163: return(TRUE);
1164: }
1165:
1166: /***************************************************************************
1167: * Function: complist_getroot_left
1168: *
1169: * Purpose:
1170: *
1171: * Gets the root names of the left tree used to build this complist.
1172: *
1173: **************************************************************************/
1174: LPSTR
1175: complist_getroot_left(COMPLIST cl)
1176: {
1177: return( dir_getroot_list(cl->left));
1178: }
1179:
1180: /***************************************************************************
1181: * Function: complist_getroot_right
1182: *
1183: * Purpose:
1184: *
1185: * Gets the root names of the right tree used to build this complist.
1186: *
1187: **************************************************************************/
1188: LPSTR
1189: complist_getroot_right(COMPLIST cl)
1190: {
1191: return( dir_getroot_list(cl->right));
1192: }
1193: /***************************************************************************
1194: * Function: complist_freeroot_*
1195: *
1196: * Purpose:
1197: *
1198: * Frees up memory allocated in a call to complist_getroot*()
1199: *
1200: **************************************************************************/
1201: void
1202: complist_freeroot_left(COMPLIST cl, LPSTR path)
1203: {
1204: dir_freeroot_list(cl->left, path);
1205: }
1206:
1207: void
1208: complist_freeroot_right(COMPLIST cl, LPSTR path)
1209: {
1210: dir_freeroot_list(cl->right, path);
1211: }
1212:
1213:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.