|
|
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: file.c ! 14: * ! 15: * This file contains the high level routines that begin opening ! 16: * and saving files. ! 17: * ! 18: * Functions: ! 19: * Open() ! 20: * BuildFilterString() ! 21: * DoWeSave() ! 22: * Save() ! 23: * OpenCmdLineFile() ! 24: * FileInPath() ! 25: * ShowFileStatus() ! 26: * DifferentDirs() ! 27: * HasPath() ! 28: * WriteDWordPad() ! 29: * BuildDefSaveName() ! 30: * WriteTheFile() ! 31: * FormTempFileName() ! 32: * FileCat() ! 33: * ! 34: * Comments: ! 35: * ! 36: ****************************************************************************/ ! 37: ! 38: #include "dlgedit.h" ! 39: #include "dlgfuncs.h" ! 40: #include "dlgextrn.h" ! 41: #include "dialogs.h" ! 42: ! 43: #include <wchar.h> ! 44: ! 45: #include <commdlg.h> ! 46: ! 47: ! 48: /* ! 49: * File types. ! 50: */ ! 51: #define FILE_RES 0 // Resource (.RES) file. ! 52: #define FILE_DLG 1 // Dialog (.DLG) file. ! 53: #define FILE_INC 2 // Include (.H) file. ! 54: ! 55: STATICFN VOID BuildDefSaveName(INT FileType, LPTSTR pszFullFileName, ! 56: LPTSTR pszFileName, LPTSTR pszOtherFullFileName, LPTSTR pszOtherFileName, ! 57: LPTSTR pszFullFileNameBuffer, INT cchBuffer); ! 58: STATICFN BOOL WriteTheFile(LPTSTR pszFile, INT fmt); ! 59: STATICFN VOID FormTempFileName(LPTSTR pszBaseName, LPTSTR pszBuffer); ! 60: STATICFN VOID FileCat(LPTSTR pchName, LPTSTR pchCat, BOOL fChop); ! 61: ! 62: ! 63: ! 64: /************************************************************************ ! 65: * Open ! 66: * ! 67: * Handles opening of resource and include files. ! 68: * Saves current dialog in the resource. ! 69: * Might put up a message box. ! 70: * Cancels moves. ! 71: * Changes szFullResFile, pszResFile, szFullIncludeFile, pszIncludeFile ! 72: * Puts up dialog boxes. ! 73: * Restores dialog box from resource. ! 74: * Sets changed flags. ! 75: * ! 76: * Arguments: ! 77: * INT FileType - FILE_RESOURCE or FILE_INCLUDE. ! 78: * ! 79: * Returns: ! 80: * TRUE if successful, FALSE if not. ! 81: * ! 82: ************************************************************************/ ! 83: ! 84: BOOL Open( ! 85: INT FileType) ! 86: { ! 87: BOOL fSuccess; ! 88: BOOL fGotName; ! 89: OPENFILENAME ofn; ! 90: TCHAR szNewFileName[CCHMAXPATH]; ! 91: TCHAR szInitialDir[CCHMAXPATH]; ! 92: TCHAR szFilter[CCHTEXTMAX]; ! 93: INT idPrevDlg; ! 94: ! 95: /* ! 96: * Cancel any outstanding selection(s). ! 97: */ ! 98: CancelSelection(TRUE); ! 99: ! 100: /* ! 101: * Put current dialog back into the resource buffer. ! 102: */ ! 103: if (!SynchDialogResource()) ! 104: return FALSE; ! 105: ! 106: /* ! 107: * Begin setting up the globals and the open file dialog structure. ! 108: */ ! 109: fSuccess = FALSE; ! 110: *szNewFileName = CHAR_NULL; ! 111: ! 112: /* ! 113: * Build up the filter string. ! 114: */ ! 115: BuildFilterString(FileType, szFilter); ! 116: ! 117: ofn.lStructSize = sizeof(ofn); ! 118: ofn.hwndOwner = ghwndMain; ! 119: ofn.hInstance = NULL; ! 120: ofn.lpstrFilter = szFilter; ! 121: ofn.lpstrCustomFilter = NULL; ! 122: ofn.nMaxCustFilter = 0; ! 123: ofn.nFilterIndex = 1; ! 124: ofn.lpstrFile = szNewFileName; ! 125: ofn.nMaxFile = CCHMAXPATH; ! 126: ofn.lpstrFileTitle = NULL; ! 127: ofn.nMaxFileTitle = 0; ! 128: ! 129: if (FileType == FILE_INCLUDE) { ! 130: /* ! 131: * If there is a res file, set the default include file ! 132: * name to open to be the basename of the res file with ! 133: * a .H extension, if such a file exists. We use szInitialDir ! 134: * here as a temporary buffer. ! 135: */ ! 136: if (pszResFile) { ! 137: lstrcpy(szInitialDir, szFullResFile); ! 138: FileCat(szInitialDir, ids(IDS_DOTH), TRUE); ! 139: if (GetFileAttributes(szInitialDir) != -1) { ! 140: lstrcpy(szNewFileName, pszResFile); ! 141: FileCat(szNewFileName, ids(IDS_DOTH), TRUE); ! 142: } ! 143: } ! 144: ! 145: ofn.lpstrTitle = ids(IDS_INCOPENTITLE); ! 146: ofn.lpstrDefExt = ids(IDS_INCEXT); ! 147: } ! 148: else { ! 149: ofn.lpstrTitle = ids(IDS_RESOPENTITLE); ! 150: ofn.lpstrDefExt = ids(IDS_RESEXT); ! 151: } ! 152: ! 153: /* ! 154: * If they have already opened one res file, start looking for ! 155: * any new files to open in the same directory. Otherwise, just ! 156: * default to the current directory. ! 157: */ ! 158: if (pszResFile) { ! 159: lstrcpy(szInitialDir, szFullResFile); ! 160: *FileInPath(szInitialDir) = CHAR_NULL; ! 161: ofn.lpstrInitialDir = szInitialDir; ! 162: } ! 163: else { ! 164: ofn.lpstrInitialDir = NULL; ! 165: } ! 166: ! 167: ofn.Flags = OFN_HIDEREADONLY | OFN_SHOWHELP | OFN_FILEMUSTEXIST; ! 168: ofn.lCustData = 0; ! 169: ofn.lpfnHook = NULL; ! 170: ofn.lpTemplateName = NULL; ! 171: ! 172: /* ! 173: * Fire off the dialog box to open the file. ! 174: */ ! 175: EnteringDialog((FileType == FILE_INCLUDE) ? ! 176: DID_COMMONFILEOPENINCLUDE : DID_COMMONFILEOPENRES, ! 177: &idPrevDlg, TRUE); ! 178: fGotName = GetOpenFileName(&ofn); ! 179: EnteringDialog(idPrevDlg, NULL, FALSE); ! 180: if (fGotName) { ! 181: if (FileType == FILE_INCLUDE) { ! 182: if (OpenIncludeFile(szNewFileName)) { ! 183: /* ! 184: * Since we just loaded a new include file, we mark the ! 185: * resource as changed so that the .RES and .DLG files ! 186: * will be written out with the proper name in the ! 187: * DLGINCLUDE statement. ! 188: */ ! 189: gfResChged = TRUE; ! 190: fSuccess = TRUE; ! 191: } ! 192: } ! 193: else { ! 194: if (OpenResFile(szNewFileName)) ! 195: fSuccess = TRUE; ! 196: } ! 197: } ! 198: ! 199: ShowFileStatus(TRUE); ! 200: ! 201: return fSuccess; ! 202: } ! 203: ! 204: ! 205: ! 206: /************************************************************************ ! 207: * BuildFilterString ! 208: * ! 209: * This function creates a filter string to be passed into the ! 210: * standard file open and save dialogs. This will be something like: ! 211: * "Resource (*.res)\0*.res\0\0" ! 212: * ! 213: * Arguments: ! 214: * INT FileType - Flags for type of file, FILE_INCLUDE, FILE_RESOURCE ! 215: * or FILE_DLL. ! 216: * LPTSTR pszFilter - Where to return the filter string. ! 217: * ! 218: ************************************************************************/ ! 219: ! 220: VOID BuildFilterString( ! 221: INT FileType, ! 222: LPTSTR pszFilter) ! 223: { ! 224: INT idsFileSpecName; ! 225: INT idsFileSpec; ! 226: LPTSTR psz; ! 227: ! 228: if (FileType & FILE_INCLUDE) { ! 229: idsFileSpecName = IDS_DEFINCFILESPECNAME; ! 230: idsFileSpec = IDS_DEFINCFILESPEC; ! 231: } ! 232: else if (FileType & FILE_RESOURCE) { ! 233: idsFileSpecName = IDS_DEFRESFILESPECNAME; ! 234: idsFileSpec = IDS_DEFRESFILESPEC; ! 235: } ! 236: else { // Must be a DLL. ! 237: idsFileSpecName = IDS_DEFDLLFILESPECNAME; ! 238: idsFileSpec = IDS_DEFDLLFILESPEC; ! 239: } ! 240: ! 241: /* ! 242: * Build up the filter string. This will be something like: ! 243: * "Resource (*.res)\0*.res\0\0" ! 244: */ ! 245: psz = (LPTSTR)WriteSz(pszFilter, ids(idsFileSpecName)); ! 246: psz = (LPTSTR)WriteSz(psz, ids(idsFileSpec)); ! 247: *psz = CHAR_NULL; ! 248: } ! 249: ! 250: ! 251: ! 252: /************************************************************************ ! 253: * OpenCmdLineFile ! 254: * ! 255: * Handles opening of the resource file specified on the command line. ! 256: * ! 257: * Arguments: ! 258: * LPTSTR - pointer to the file name string ! 259: * ! 260: ************************************************************************/ ! 261: ! 262: VOID OpenCmdLineFile( ! 263: LPTSTR pszFileName) ! 264: { ! 265: TCHAR szFullPath[CCHMAXPATH]; ! 266: LPTSTR pszOnlyFileName; ! 267: ! 268: if (SearchPath(L".", pszFileName, ids(IDS_DOTRES), CCHMAXPATH, ! 269: szFullPath, &pszOnlyFileName) == -1) { ! 270: Message(MSG_CANTOPENRES, pszFileName); ! 271: } ! 272: else { ! 273: OpenResFile(szFullPath); ! 274: } ! 275: } ! 276: ! 277: ! 278: ! 279: /************************************************************************ ! 280: * DoWeSave ! 281: * ! 282: * This function checks to see if the include file or the resource file ! 283: * needs to be saved. It first checks the changed flags and if TRUE, ! 284: * asks the user if they want to save the file. If they say yes, it ! 285: * calls Save to do the actual work. ! 286: * ! 287: * Arguments: ! 288: * INT rgbFlags = FILE_RESOURCE or FILE_INCLUDE (but not both). ! 289: * ! 290: * Returns: ! 291: * IDYES - The user wanted to save the file AND the save ! 292: * was successful, or the file has not been changed. ! 293: * IDNO - The file had been changed but the user did not ! 294: * want it saved. ! 295: * IDCANCEL - The file had been changed, and either the user wanted ! 296: * it saved and the save failed, or they specified that ! 297: * they wanted the operation cancelled. ! 298: * ! 299: ************************************************************************/ ! 300: ! 301: INT DoWeSave( ! 302: INT rgbFlags) ! 303: { ! 304: LPTSTR pszFile; ! 305: INT MsgCode; ! 306: BOOL fChanged; ! 307: INT nRet = IDYES; ! 308: ! 309: /* ! 310: * First set variables for current case. ! 311: */ ! 312: if (rgbFlags & FILE_RESOURCE) { ! 313: fChanged = gfResChged; ! 314: MsgCode = MSG_CLOSING; ! 315: pszFile = pszResFile ? pszResFile : ids(IDS_UNTITLED); ! 316: } ! 317: else { ! 318: fChanged = gfIncChged; ! 319: MsgCode = MSG_INCLCLOSING; ! 320: pszFile = pszIncludeFile ? pszIncludeFile : ids(IDS_UNTITLED); ! 321: } ! 322: ! 323: if (fChanged) { ! 324: nRet = Message(MsgCode, pszFile); ! 325: if (nRet == IDYES) { ! 326: if (!Save(FILE_NOSHOW | rgbFlags)) ! 327: nRet = IDCANCEL; ! 328: } ! 329: } ! 330: ! 331: return nRet; ! 332: } ! 333: ! 334: ! 335: ! 336: /************************************************************************ ! 337: * Save ! 338: * ! 339: * Handles all saving of files based on menu choice. Does a ! 340: * CancelSelection and a SynchDialogResource. ! 341: * ! 342: * Arguments: ! 343: * INT rgbFlags - Can include FILE_SHOW, FILE_INCLUDE, FILE_SAVEAS. ! 344: * ! 345: * Returns: ! 346: * TRUE if the file was saved, FALSE if not. ! 347: * ! 348: ************************************************************************/ ! 349: ! 350: BOOL Save( ! 351: INT rgbFlags) ! 352: { ! 353: OPENFILENAME ofn; ! 354: BOOL fGotName; ! 355: LPTSTR pszFileName; ! 356: LPTSTR pszFileNameDlg; ! 357: LPTSTR pszFullFileName; ! 358: BOOL fSuccess = FALSE; ! 359: TCHAR szInitialDir[CCHMAXPATH]; ! 360: TCHAR szSaveFileName[CCHMAXPATH]; ! 361: TCHAR szSaveFileNameDlg[CCHMAXPATH]; ! 362: TCHAR szFilter[CCHTEXTMAX]; ! 363: INT idPrevDlg; ! 364: ! 365: /* ! 366: * Put current dialog back into the resource buffer. ! 367: */ ! 368: if (!SynchDialogResource()) ! 369: return FALSE; ! 370: ! 371: /* ! 372: * If the file being saved has not been named, force a "Save As". ! 373: */ ! 374: if ((rgbFlags & FILE_INCLUDE) ? !pszIncludeFile : !pszResFile) ! 375: rgbFlags |= FILE_SAVEAS; ! 376: ! 377: if (rgbFlags & FILE_SAVEAS) { ! 378: ofn.lStructSize = sizeof(ofn); ! 379: ofn.hwndOwner = ghwndMain; ! 380: ofn.hInstance = NULL; ! 381: ! 382: /* ! 383: * Build up the filter string. ! 384: */ ! 385: BuildFilterString(rgbFlags, szFilter); ! 386: ofn.lpstrFilter = szFilter; ! 387: ofn.lpstrCustomFilter = NULL; ! 388: ofn.nMaxCustFilter = 0; ! 389: ofn.nFilterIndex = 1; ! 390: ! 391: ofn.lpstrFile = szSaveFileName; ! 392: ofn.nMaxFile = CCHMAXPATH; ! 393: ofn.lpstrFileTitle = NULL; ! 394: ofn.nMaxFileTitle = 0; ! 395: ! 396: if (rgbFlags & FILE_INCLUDE) { ! 397: ofn.lpstrTitle = ids(IDS_INCSAVETITLE); ! 398: ofn.lpstrDefExt = ids(IDS_INCEXT); ! 399: BuildDefSaveName(FILE_INCLUDE, ! 400: szFullIncludeFile, pszIncludeFile, ! 401: szFullResFile, pszResFile, ! 402: szInitialDir, CCHMAXPATH); ! 403: } ! 404: else { ! 405: ofn.lpstrTitle = ids(IDS_RESSAVETITLE); ! 406: ofn.lpstrDefExt = ids(IDS_RESEXT); ! 407: BuildDefSaveName(FILE_RESOURCE, ! 408: szFullResFile, pszResFile, ! 409: szFullIncludeFile, pszIncludeFile, ! 410: szInitialDir, CCHMAXPATH); ! 411: } ! 412: ! 413: /* ! 414: * At this point, szInitialDir contains the full path to ! 415: * the suggested save file name. Find the end of the path, ! 416: * copy just the filename to the file name buffer and cut ! 417: * the filename portion off the initial directory buffer. ! 418: */ ! 419: pszFileName = FileInPath(szInitialDir); ! 420: lstrcpy(szSaveFileName, pszFileName); ! 421: *pszFileName = CHAR_NULL; ! 422: ofn.lpstrInitialDir = szInitialDir; ! 423: ! 424: ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_SHOWHELP; ! 425: ofn.lCustData = 0; ! 426: ofn.lpfnHook = NULL; ! 427: ofn.lpTemplateName = NULL; ! 428: ! 429: /* ! 430: * Fire off the dialog box to get the file name to use. ! 431: */ ! 432: EnteringDialog((rgbFlags & FILE_INCLUDE) ? ! 433: DID_COMMONFILESAVEINCLUDE : DID_COMMONFILESAVERES, ! 434: &idPrevDlg, TRUE); ! 435: fGotName = GetSaveFileName(&ofn); ! 436: EnteringDialog(idPrevDlg, NULL, FALSE); ! 437: if (fGotName) { ! 438: pszFullFileName = szSaveFileName; ! 439: pszFileName = FileInPath(szSaveFileName); ! 440: fSuccess = TRUE; ! 441: } ! 442: } ! 443: else { ! 444: if (rgbFlags & FILE_INCLUDE) { ! 445: pszFileName = pszIncludeFile; ! 446: pszFullFileName = szFullIncludeFile; ! 447: } ! 448: else { ! 449: pszFileName = pszResFile; ! 450: pszFullFileName = szFullResFile; ! 451: } ! 452: ! 453: fSuccess = TRUE; ! 454: } ! 455: ! 456: if (fSuccess) { ! 457: if (rgbFlags & FILE_INCLUDE) { ! 458: /* ! 459: * Save include file. ! 460: */ ! 461: if (!WriteTheFile(pszFullFileName, FILE_INC)) { ! 462: Message(MSG_CANTCREATE, pszFileName); ! 463: fSuccess = FALSE; ! 464: } ! 465: } ! 466: else { ! 467: /* ! 468: * Form the same name as the .res file but with ! 469: * a .dlg extension. ! 470: */ ! 471: lstrcpy(szSaveFileNameDlg, pszFullFileName); ! 472: pszFileNameDlg = FileInPath(szSaveFileNameDlg); ! 473: FileCat(pszFileNameDlg, ids(IDS_DOTDLG), TRUE); ! 474: ! 475: /* ! 476: * Save .RES file, then the .DLG file. It is done ! 477: * in this order so that makes wil notice that the ! 478: * .dlg file has a newer time stamp than the .res ! 479: * and will cause the .res to be rebuilt. This ! 480: * could be necessary to pick up other changes ! 481: * in the resources in a project. ! 482: */ ! 483: if (!WriteTheFile(pszFullFileName, FILE_RES)) { ! 484: Message(MSG_CANTCREATE, pszFileName); ! 485: fSuccess = FALSE; ! 486: } ! 487: else if (!WriteTheFile(szSaveFileNameDlg, FILE_DLG)) { ! 488: Message(MSG_CANTCREATE, pszFileNameDlg); ! 489: fSuccess = FALSE; ! 490: } ! 491: else { ! 492: /* ! 493: * Successfully saved both files. Update our ! 494: * globals. ! 495: */ ! 496: lstrcpy(szFullResFile, pszFullFileName); ! 497: pszResFile = FileInPath(szFullResFile); ! 498: gfResChged = FALSE; ! 499: } ! 500: } ! 501: } ! 502: ! 503: ShowFileStatus(TRUE); ! 504: ! 505: return fSuccess; ! 506: } ! 507: ! 508: ! 509: ! 510: /************************************************************************ ! 511: * BuildDefSaveName ! 512: * ! 513: * This function takes the filenames of the current resource and include ! 514: * files and builds the default filename that will be shown in the ! 515: * "Save As" dialog. If the current file is still untitled, it will ! 516: * attempt to pick a default name based on the other files name. ! 517: * ! 518: * To use, pass in the file type (FILE_RESOURCE or FILE_INCLUDE) and ! 519: * give the current file name and full file name of both the current ! 520: * file you are building, and the other type of file. The following ! 521: * rules will be followed, in order: ! 522: * ! 523: * 1. If the file name is valid (not NULL) and it is either the ! 524: * include file we are naming or it is the res file but there ! 525: * is no include file, it will copy the full file name to the ! 526: * output buffer. ! 527: * ! 528: * 2. If the other file name is valid, it will take this name, add the ! 529: * appropriate extension and copy it to the output buffer. ! 530: * ! 531: * 3. If neither of the file names are valid (they are BOTH untitled), ! 532: * it will assume the current directory and make a default file ! 533: * name with the appropriate extension. ! 534: * ! 535: * Rule 1 is a little complicated, but it's purpose is to make it so ! 536: * that if a default res file name is being requested, and they changed ! 537: * the directory and/or name for the include file that was just saved, ! 538: * the default directory and name for the res file will be the same ! 539: * directory and base name as the new include file directory and name. ! 540: * ! 541: * Arguments: ! 542: * INT FileType - Either FILE_RESOURE or FILE_INCLUDE. ! 543: * LPTSTR pszFullFileName - The full file name. This will only ! 544: * be used if pszFileName is not NULL. ! 545: * LPTSTR pszFileName - File name to use, or NULL if it is ! 546: * currently untitled. ! 547: * LPTSTR pszOtherFullFileName - Full file name of the other file. Only ! 548: * considered valid if pszOtherFileName is ! 549: * not NULL. ! 550: * LPTSTR pszOtherFileName - File name of the other file, or NULL if ! 551: * it is untitled. ! 552: * LPTSTR pszFullFileNameBuffer - Where to put the full file name. ! 553: * INT cchBuffer - Size of the buffer in characters. ! 554: * ! 555: ************************************************************************/ ! 556: ! 557: STATICFN VOID BuildDefSaveName( ! 558: INT FileType, ! 559: LPTSTR pszFullFileName, ! 560: LPTSTR pszFileName, ! 561: LPTSTR pszOtherFullFileName, ! 562: LPTSTR pszOtherFileName, ! 563: LPTSTR pszFullFileNameBuffer, ! 564: INT cchBuffer) ! 565: { ! 566: TCHAR szBuffer[CCHMAXPATH]; ! 567: ! 568: if (pszFileName && (FileType == FILE_INCLUDE || !pszOtherFileName)) { ! 569: /* ! 570: * Simple case. The file already has a title. ! 571: */ ! 572: lstrcpy(pszFullFileNameBuffer, pszFullFileName); ! 573: } ! 574: else if (pszOtherFileName) { ! 575: /* ! 576: * Copy the other files name and add the proper extension. ! 577: */ ! 578: lstrcpy(pszFullFileNameBuffer, pszOtherFullFileName); ! 579: FileCat(pszFullFileNameBuffer, ! 580: (FileType == FILE_INCLUDE) ? ids(IDS_DOTH) : ! 581: ids(IDS_DOTRES), TRUE); ! 582: } ! 583: else { ! 584: /* ! 585: * Pick a default name in the current directory and ! 586: * add the proper extension. ! 587: */ ! 588: lstrcpy(szBuffer, ids(IDS_DEFSAVENAME)); ! 589: FileCat(szBuffer, ! 590: (FileType == FILE_INCLUDE) ? ids(IDS_DOTH) : ! 591: ids(IDS_DOTRES), TRUE); ! 592: GetFullPathName(szBuffer, cchBuffer, pszFullFileNameBuffer, NULL); ! 593: } ! 594: } ! 595: ! 596: ! 597: ! 598: /************************************************************************ ! 599: * WriteTheFile ! 600: * ! 601: * This function accepts a pointer to a resource buffer and a format ! 602: * type. It writes the buffer out in the appropriate format. It ! 603: * gets the file name from pszFile, adding the appropriate extension ! 604: * for the type of file. The file is first written to a temporary file ! 605: * then the old file is removed and finally the new file is renamed. ! 606: * ! 607: * Arguments: ! 608: * LPTSTR pszFile - The name to save to. ! 609: * INT fmt - format to write the buffer out in, ! 610: * FILE_RES, FILE_INC or FILE_DLG. ! 611: * ! 612: * Returns: ! 613: * TRUE => File successfully written. ! 614: * FALSE => Failure in writing file. ! 615: * ! 616: ************************************************************************/ ! 617: ! 618: STATICFN BOOL WriteTheFile( ! 619: LPTSTR pszFile, ! 620: INT fmt) ! 621: { ! 622: TCHAR szTempFile[CCHMAXPATH]; /* Used for temporary filename */ ! 623: TCHAR szSrcFile[CCHMAXPATH]; /* Source file with proper extension */ ! 624: HANDLE hfWrite; ! 625: HCURSOR hcurSave; ! 626: BOOL fSuccess = FALSE; ! 627: WORD idsExt; ! 628: ! 629: hcurSave = SetCursor(hcurWait); ! 630: ! 631: switch (fmt) { ! 632: case FILE_RES: ! 633: idsExt = IDS_DOTRES; ! 634: break; ! 635: ! 636: case FILE_DLG: ! 637: idsExt = IDS_DOTDLG; ! 638: break; ! 639: ! 640: case FILE_INC: ! 641: idsExt = IDS_DOTH; ! 642: break; ! 643: } ! 644: ! 645: /* ! 646: * Append appropriate file name extension. ! 647: */ ! 648: lstrcpy(szSrcFile, pszFile); ! 649: FileCat(szSrcFile, ids(idsExt), fmt == FILE_DLG ? TRUE : FALSE); ! 650: ! 651: /* ! 652: * Generate appropriate temporary file name in the same directory. ! 653: * It is done in the same directory so that a simple rename can ! 654: * be done later. ! 655: */ ! 656: FormTempFileName(szSrcFile, szTempFile); ! 657: ! 658: if ((hfWrite = CreateFile(szTempFile, GENERIC_READ | GENERIC_WRITE, ! 659: FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, ! 660: NULL)) == (HANDLE)-1) ! 661: goto Exit; ! 662: ! 663: switch (fmt) { ! 664: case FILE_RES: ! 665: if (!WriteRes(hfWrite, szSrcFile)) ! 666: goto CloseAndExit; ! 667: ! 668: break; ! 669: ! 670: case FILE_DLG: ! 671: if (!WriteDlg(hfWrite, szSrcFile)) ! 672: goto CloseAndExit; ! 673: ! 674: break; ! 675: ! 676: case FILE_INC: ! 677: if (!WriteInc(hfWrite)) ! 678: goto CloseAndExit; ! 679: ! 680: break; ! 681: } ! 682: ! 683: CloseHandle((HANDLE)hfWrite); ! 684: DeleteFile(szSrcFile); ! 685: if (!MoveFile(szTempFile, szSrcFile)) { ! 686: DeleteFile(szTempFile); ! 687: goto Exit; ! 688: } ! 689: ! 690: fSuccess = TRUE; ! 691: ! 692: /* ! 693: * If we just wrote to the include file, read it to get the new ! 694: * file offsets, etc. ! 695: */ ! 696: if (fmt == FILE_INC) { ! 697: if (!OpenIncludeFile(szSrcFile)) ! 698: fSuccess = FALSE; ! 699: } ! 700: ! 701: Exit: ! 702: SetCursor(hcurSave); ! 703: return fSuccess; ! 704: ! 705: CloseAndExit: ! 706: CloseHandle(hfWrite); ! 707: DeleteFile(szTempFile); ! 708: SetCursor(hcurSave); ! 709: return fSuccess; ! 710: } ! 711: ! 712: ! 713: ! 714: /************************************************************************ ! 715: * FormTempFileName ! 716: * ! 717: * This function forms a temporary file name in the provided string. ! 718: * The provided string is assumed to have been filled with a filename ! 719: * that includes a path. The temp file will be created in the same ! 720: * directory as the file that is currently in the string. ! 721: * ! 722: * Arguments: ! 723: * LPTSTR pszBaseName - The base name (a filename that includes a path). ! 724: * LPTSTR pszBuffer - Where to return the ! 725: * ! 726: ************************************************************************/ ! 727: ! 728: STATICFN VOID FormTempFileName( ! 729: LPTSTR pszBaseName, ! 730: LPTSTR pszBuffer) ! 731: { ! 732: TCHAR szBuffer[CCHMAXPATH]; ! 733: LPTSTR psz; ! 734: ! 735: /* ! 736: * Cut the base file name down to just the path portion. ! 737: */ ! 738: lstrcpy(szBuffer, pszBaseName); ! 739: psz = FileInPath(szBuffer); ! 740: psz--; ! 741: *psz = TEXT('\0'); ! 742: ! 743: /* ! 744: * Create a temporary file in the same directory. ! 745: */ ! 746: GetTempFileName(szBuffer, L"dlg", 0, pszBuffer); ! 747: } ! 748: ! 749: ! 750: ! 751: /************************************************************************ ! 752: * FileInPath ! 753: * ! 754: * This function takes a path and returns a pointer to the file name ! 755: * portion of it. For instance, it will return a pointer to ! 756: * "abc.res" if it is given the following path: "c:\windows\abc.res". ! 757: * ! 758: * Arguments: ! 759: * LPTSTR pszPath - Path to look through. ! 760: * ! 761: ************************************************************************/ ! 762: ! 763: LPTSTR FileInPath( ! 764: LPTSTR pszPath) ! 765: { ! 766: LPTSTR psz; ! 767: ! 768: psz = pszPath + lstrlen(pszPath); ! 769: while (psz > pszPath) { ! 770: psz--; ! 771: if (*psz == CHAR_BACKSLASH || *psz == CHAR_COLON) { ! 772: psz++; ! 773: break; ! 774: } ! 775: } ! 776: ! 777: return psz; ! 778: } ! 779: ! 780: ! 781: ! 782: /************************************************************************ ! 783: * FileCat ! 784: * ! 785: * This function puts the extension pchCat on the file spec pch. ! 786: * If fChop, this is done regardless of whether pch has an extension ! 787: * or not (replacing the old extension). Otherwise, pchCat is added ! 788: * only if there is no extension on the spec pch. ! 789: * ! 790: * Arguments: ! 791: * LPTSTR pch - The file spec to "cat" the extension to. ! 792: * LPTSTR pchCat - The extension to "cat" on to pch, ! 793: * including the '.' ! 794: * ! 795: ************************************************************************/ ! 796: ! 797: STATICFN VOID FileCat( ! 798: LPTSTR pchName, ! 799: LPTSTR pchCat, ! 800: BOOL fChop) ! 801: { ! 802: LPTSTR pch; ! 803: ! 804: pch = pchName + lstrlen(pchName); ! 805: pch--; ! 806: ! 807: /* back up to '.' or '\\' */ ! 808: while (*pch != CHAR_DOT) { ! 809: if (*pch == CHAR_BACKSLASH || pch <= pchName) { ! 810: /* no extension, add one */ ! 811: lstrcat(pchName, pchCat); ! 812: return; ! 813: } ! 814: ! 815: pch--; ! 816: } ! 817: ! 818: if (fChop) ! 819: lstrcpy(pch, pchCat); ! 820: } ! 821: ! 822: ! 823: ! 824: /************************************************************************ ! 825: * ShowFileStatus ! 826: * ! 827: * This function displays the title of the Dialog Editor, along with ! 828: * the file names for the RES and H files with asterisks if they have ! 829: * changed. It displays this information only if one of these items ! 830: * has changed or if fForce is TRUE. ! 831: * ! 832: * Arguments: ! 833: * BOOL fForce - TRUE if the title should be updated even if the value ! 834: * of gfResChged or gfIncChged has not changed since the ! 835: * last call. This function should be called with fForce ! 836: * equal to TRUE if it is known that one of the file names ! 837: * has just been changed. ! 838: * ! 839: ************************************************************************/ ! 840: ! 841: VOID ShowFileStatus( ! 842: BOOL fForce) ! 843: { ! 844: static BOOL fResChgedSave = FALSE; ! 845: static BOOL fIncChgedSave = FALSE; ! 846: TCHAR szTitle[CCHTEXTMAX]; ! 847: ! 848: if (gfResChged != fResChgedSave || gfIncChged != fIncChgedSave || ! 849: fForce) { ! 850: lstrcpy(szTitle, ids(IDS_DLGEDIT)); ! 851: lstrcat(szTitle, L" - "); ! 852: lstrcat(szTitle, pszResFile ? pszResFile : ids(IDS_UNTITLED)); ! 853: if (gfResChged) ! 854: lstrcat(szTitle, L"*"); ! 855: ! 856: lstrcat(szTitle, L", "); ! 857: lstrcat(szTitle, pszIncludeFile ? pszIncludeFile : ids(IDS_UNTITLED)); ! 858: if (gfIncChged) ! 859: lstrcat(szTitle, L"*"); ! 860: ! 861: SetWindowText(ghwndMain, szTitle); ! 862: ! 863: fResChgedSave = gfResChged; ! 864: fIncChgedSave = gfIncChged; ! 865: } ! 866: } ! 867: ! 868: ! 869: ! 870: /************************************************************************ ! 871: * DifferentDirs ! 872: * ! 873: * This function returns TRUE if the given full paths are to files ! 874: * that are in different directories. ! 875: * ! 876: * Arguments: ! 877: * LPTSTR pszPath1 - First path. ! 878: * LPTSTR pszPath2 - Second path. ! 879: * ! 880: ************************************************************************/ ! 881: ! 882: BOOL DifferentDirs( ! 883: LPTSTR pszPath1, ! 884: LPTSTR pszPath2) ! 885: { ! 886: INT nLen1; ! 887: INT nLen2; ! 888: LPTSTR pszFile1; ! 889: LPTSTR pszFile2; ! 890: ! 891: pszFile1 = FileInPath(pszPath1); ! 892: pszFile2 = FileInPath(pszPath2); ! 893: ! 894: nLen1 = lstrlen(pszPath1) - lstrlen(pszFile1); ! 895: nLen2 = lstrlen(pszPath2) - lstrlen(pszFile2); ! 896: if (nLen1 != nLen2 || _wcsnicmp(pszPath1, pszPath2, nLen1) != 0) ! 897: return TRUE; ! 898: else ! 899: return FALSE; ! 900: } ! 901: ! 902: ! 903: ! 904: /************************************************************************ ! 905: * HasPath ! 906: * ! 907: * This function returns TRUE if the given filespec includes a path ! 908: * specification. It returns false if it is a filename without a ! 909: * path. ! 910: * ! 911: * A filespec is considered to have a path if a backslash character (\) ! 912: * is found in it. ! 913: * ! 914: * Arguments: ! 915: * LPTSTR pszFileSpec - File spec to check. ! 916: * ! 917: ************************************************************************/ ! 918: ! 919: BOOL HasPath( ! 920: LPTSTR pszFileSpec) ! 921: { ! 922: LPTSTR psz; ! 923: ! 924: for (psz = pszFileSpec; *psz; psz++) ! 925: if (*psz == CHAR_BACKSLASH) ! 926: return TRUE; ! 927: ! 928: return FALSE; ! 929: } ! 930: ! 931: ! 932: ! 933: /************************************************************************ ! 934: * WriteDWordPad ! 935: * ! 936: * This function writes nulls to the specified file until it is ! 937: * dword aligned. If the file is already dword aligned, nothing ! 938: * will be written. ! 939: * ! 940: * Arguments: ! 941: * HANDLE hf - The file to write to. ! 942: * DWORD cbFile - Where the file pointer is at in the file. ! 943: * ! 944: * Returns: ! 945: * TRUE if successful, FALSE otherwise. ! 946: * ! 947: ************************************************************************/ ! 948: ! 949: BOOL WriteDWordPad( ! 950: HANDLE hf, ! 951: DWORD cbFile) ! 952: { ! 953: static BYTE Buf[3] = {0, 0, 0}; ! 954: WORD cb; ! 955: ! 956: cb = (WORD)((4 - (((WORD)cbFile) & 3)) % 4); ! 957: if (cb) { ! 958: if (_lwrite((HFILE)hf, (LPSTR)Buf, cb) == -1) ! 959: return FALSE; ! 960: } ! 961: ! 962: return TRUE; ! 963: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.