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