|
|
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.