|
|
1.1 root 1: /****************************************************************************/
2: /* */
3: /* Microsoft Confidential */
4: /* */
5: /* Copyright (c) Microsoft Corp. 1987, 1991 */
6: /* All Rights Reserved */
7: /* */
8: /****************************************************************************/
9: /****************************** Module Header *******************************
10: * Module Name: file.c
11: *
12: * Contains routines for handling files.
13: *
14: * History:
15: *
16: ****************************************************************************/
17:
18: #include "imagedit.h"
19: #include "dialogs.h"
20:
21: #include <string.h>
22:
23: #include <commdlg.h>
24:
25:
26: #ifdef WIN16
27: typedef BOOL (APIENTRY *LPOFNHOOKPROC) (HWND, UINT, WPARAM, LONG);
28: #endif
29:
30:
31: STATICFN VOID NEAR AddFilterString(PSTR pszBuf, PSTR pszType, PSTR pszExt,
32: BOOL fFirst);
33: STATICFN PSTR NEAR DefExtFromFilter(INT index, PSTR pszFilter);
34: STATICFN BOOL NEAR LoadFile(PSTR pszFullFileName);
35: STATICFN INT NEAR GetTypeFromExt(PSTR pszFileName);
36: STATICFN VOID NEAR FileCat(PSTR pchName, PSTR pchCat);
37:
38:
39: static OPENFILENAME ofn;
40:
41:
42:
43: /************************************************************************
44: * SetFileName
45: *
46: * Updates the globals that contain the file name of the currently
47: * loaded file. This routine will also cause the title bar to
48: * be udpated with the new name.
49: *
50: * Arguments:
51: *
52: * History:
53: *
54: ************************************************************************/
55:
56: VOID SetFileName(
57: PSTR pszFullFileName)
58: {
59: CHAR szTitle[CCHMAXPATH];
60: WIN32_FIND_DATA ffbuf;
61: CHAR *pch;
62:
63: if (pszFullFileName) {
64: HANDLE hfind;
65: strcpy(gszFullFileName, pszFullFileName);
66: gpszFileName = FileInPath(gszFullFileName);
67:
68: if((hfind = FindFirstFile( pszFullFileName, &ffbuf)) !=
69: INVALID_HANDLE_VALUE) {
70:
71: strcpy(gpszFileName, ffbuf.cFileName);
72: FindClose(hfind);
73: }
74:
75: }
76: else {
77: *gszFullFileName = '\0';
78: gpszFileName = NULL;
79: }
80:
81: strcpy(szTitle, ids(IDS_PGMTITLE));
82: strcat(szTitle, " - ");
83: pch = gpszFileName ? gpszFileName : ids(IDS_UNTITLED);
84: strncat(szTitle, pch, sizeof(szTitle) - strlen(szTitle));
85: szTitle[CCHMAXPATH-1] = '\0';
86: SetWindowText(ghwndMain, szTitle);
87: }
88:
89:
90:
91: /************************************************************************
92: * FileInPath
93: *
94: * This function takes a path and returns a pointer to the file name
95: * portion of it. For instance, it will return a pointer to
96: * "abc.res" if it is given the following path: "c:\windows\abc.res".
97: *
98: * Arguments:
99: * PSTR pstrPath - Path to look through.
100: *
101: * History:
102: *
103: ************************************************************************/
104:
105: PSTR FileInPath(
106: PSTR pstrPath)
107: {
108: PSTR pstr;
109:
110: pstr = pstrPath + strlen(pstrPath);
111: while (pstr > pstrPath) {
112: pstr = FAR2NEAR(AnsiPrev(pstrPath, pstr));
113: if (*pstr == '\\' || *pstr == ':' || *pstr == '/') {
114: pstr = FAR2NEAR(AnsiNext(pstr));
115: break;
116: }
117: }
118:
119: return pstr;
120: }
121:
122:
123:
124: /************************************************************************
125: * ClearResource
126: *
127: * Resets the editor back to a neutral state before editing any image.
128: * This function can be called before starting to edit a new file
129: * (but not just a new image). Files should be saved before calling
130: * this routine, because the entire image list is destroyed.
131: *
132: * History:
133: *
134: ************************************************************************/
135:
136: VOID ClearResource(VOID)
137: {
138: ImageLinkFreeList();
139:
140: SetFileName(NULL);
141:
142: gnImages = 0;
143: fImageDirty = FALSE;
144: fFileDirty = FALSE;
145: gpImageCur = NULL;
146:
147: /*
148: * Hide the workspace and view windows.
149: */
150: ShowWindow(ghwndWork, SW_HIDE);
151: ViewShow(FALSE);
152:
153: /*
154: * Destroy the image DC's.
155: */
156: ImageDCDelete();
157:
158: /*
159: * Update the properties bar.
160: */
161: PropBarClearPos();
162: PropBarClearSize();
163: PropBarUpdate();
164: }
165:
166:
167:
168: /************************************************************************
169: * OpenDlg
170: *
171: *
172: *
173: * Arguments:
174: *
175: * History:
176: *
177: ************************************************************************/
178:
179: BOOL OpenDlg(
180: PSTR pszFileName,
181: INT iType)
182: {
183: BOOL fGotName;
184: INT idDlg;
185: INT idPrevDlg;
186: CHAR szFilter[CCHTEXTMAX];
187:
188: pszFileName[0] = '\0';
189:
190: switch (iType) {
191: case FT_BITMAP:
192: case FT_ICON:
193: case FT_CURSOR:
194: AddFilterString(szFilter, ids(IDS_BMPFILTER),
195: ids(IDS_BMPFILTEREXT), TRUE);
196: AddFilterString(szFilter, ids(IDS_ICOFILTER),
197: ids(IDS_ICOFILTEREXT), FALSE);
198: AddFilterString(szFilter, ids(IDS_CURFILTER),
199: ids(IDS_CURFILTEREXT), FALSE);
200: AddFilterString(szFilter, ids(IDS_ALLFILTER),
201: ids(IDS_ALLFILTEREXT), FALSE);
202:
203: ofn.nFilterIndex = iType + 1;
204: idDlg = DID_COMMONFILEOPEN;
205:
206: break;
207:
208: case FT_PALETTE:
209: AddFilterString(szFilter, ids(IDS_PALFILTER),
210: ids(IDS_PALFILTEREXT), TRUE);
211: AddFilterString(szFilter, ids(IDS_ALLFILTER),
212: ids(IDS_ALLFILTEREXT), FALSE);
213:
214: ofn.nFilterIndex = 1;
215: idDlg = DID_COMMONFILEOPENPAL;
216:
217: break;
218: }
219:
220: ofn.lStructSize = sizeof(OPENFILENAME);
221: ofn.hwndOwner = ghwndMain;
222: ofn.hInstance = NULL;
223: ofn.lpstrFilter = szFilter;
224: ofn.lpstrCustomFilter = NULL;
225: ofn.nMaxCustFilter = 0;
226: ofn.lpstrFile = pszFileName;
227: ofn.nMaxFile = CCHMAXPATH;
228: ofn.lpstrFileTitle = NULL;
229: ofn.nMaxFileTitle = 0;
230: ofn.lpstrInitialDir = NULL;
231: ofn.lpstrTitle = NULL;
232: ofn.Flags = OFN_HIDEREADONLY | OFN_SHOWHELP | OFN_FILEMUSTEXIST |
233: OFN_ENABLEHOOK;
234: ofn.nFileOffset = 0;
235: ofn.nFileExtension = 0;
236: ofn.lpstrDefExt = (LPCSTR)DefExtFromFilter((INT)ofn.nFilterIndex - 1,
237: (PSTR)ofn.lpstrFilter);
238: ofn.lCustData = 0;
239: ofn.lpfnHook = (LPOFNHOOKPROC)MakeProcInstance(
240: (FARPROC)GetOpenFileNameHook, ghInst);
241: ofn.lpTemplateName = NULL;
242:
243: EnteringDialog(idDlg, &idPrevDlg, TRUE);
244: fGotName = GetOpenFileName(&ofn);
245: EnteringDialog(idPrevDlg, NULL, FALSE);
246:
247: FreeProcInstance((FARPROC)ofn.lpfnHook);
248:
249: return fGotName;
250: }
251:
252:
253:
254: /************************************************************************
255: * SaveAsDlg
256: *
257: *
258: *
259: * Arguments:
260: *
261: * History:
262: *
263: ************************************************************************/
264:
265: BOOL SaveAsDlg(
266: PSTR pszFileName,
267: INT iType)
268: {
269: INT idDlg;
270: BOOL fGotName;
271: INT idPrevDlg;
272: CHAR szFilter[CCHTEXTMAX];
273:
274: switch (iType) {
275: case FT_BITMAP:
276: AddFilterString(szFilter, ids(IDS_BMPFILTER),
277: ids(IDS_BMPFILTEREXT), TRUE);
278:
279: ofn.lpstrDefExt = ids(IDS_DEFEXTBMP);
280: idDlg = DID_COMMONFILESAVE;
281:
282: break;
283:
284: case FT_ICON:
285: AddFilterString(szFilter, ids(IDS_ICOFILTER),
286: ids(IDS_ICOFILTEREXT), TRUE);
287:
288: ofn.lpstrDefExt = ids(IDS_DEFEXTICO);
289: idDlg = DID_COMMONFILESAVE;
290:
291: break;
292:
293: case FT_CURSOR:
294: AddFilterString(szFilter, ids(IDS_CURFILTER),
295: ids(IDS_CURFILTEREXT), TRUE);
296:
297: ofn.lpstrDefExt = ids(IDS_DEFEXTCUR);
298: idDlg = DID_COMMONFILESAVE;
299:
300: break;
301:
302: case FT_PALETTE:
303: AddFilterString(szFilter, ids(IDS_PALFILTER),
304: ids(IDS_PALFILTEREXT), TRUE);
305:
306: ofn.lpstrDefExt = ids(IDS_DEFEXTPAL);
307: idDlg = DID_COMMONFILESAVEPAL;
308:
309: break;
310: }
311:
312: ofn.lStructSize = sizeof(OPENFILENAME);
313: ofn.hwndOwner = ghwndMain;
314: ofn.hInstance = NULL;
315: ofn.lpstrFilter = szFilter;
316: ofn.lpstrCustomFilter = NULL;
317: ofn.nMaxCustFilter = 0;
318: ofn.nFilterIndex = 1;
319: ofn.lpstrFile = pszFileName;
320: ofn.nMaxFile = CCHMAXPATH;
321: ofn.lpstrFileTitle = NULL;
322: ofn.nMaxFileTitle = 0;
323: ofn.lpstrInitialDir = NULL;
324: ofn.lpstrTitle = NULL;
325: ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_SHOWHELP;
326: ofn.nFileOffset = 0;
327: ofn.nFileExtension = 0;
328: ofn.lCustData = 0;
329: ofn.lpfnHook = NULL;
330: ofn.lpTemplateName = NULL;
331:
332: EnteringDialog(idDlg, &idPrevDlg, TRUE);
333: fGotName = GetSaveFileName(&ofn);
334: EnteringDialog(idPrevDlg, NULL, FALSE);
335:
336: return fGotName;
337: }
338:
339:
340:
341: /************************************************************************
342: * GetOpenFileNameHook
343: *
344: * This function is the hook function for the Common Dialogs
345: * GetOpenFileName funtion. It is used to be sure the default
346: * extension that is used when the function exits is the same
347: * as the image file type that the user specifies they want
348: * opened.
349: *
350: * Arguments:
351: *
352: * History:
353: *
354: ************************************************************************/
355:
356: DIALOGPROC GetOpenFileNameHook(
357: HWND hwnd,
358: UINT msg,
359: WPARAM wParam,
360: LPARAM lParam)
361: {
362: switch (msg) {
363: case WM_INITDIALOG:
364: /*
365: * Tell Windows to set the focus for me.
366: */
367: return TRUE;
368:
369: case WM_COMMAND:
370: /*
371: * Did they change the type of file from the File Type
372: * combo box?
373: */
374: if (LOWORD(wParam) == DID_COMMDLG_TYPECOMBO &&
375: HIWORD(wParam) == CBN_SELCHANGE) {
376: INT iSelect;
377:
378: /*
379: * Get the selected file type, then change the default
380: * extension field of the ofn structure to match it.
381: * This ensures that the proper default extension
382: * gets added to the end of the file name if the user
383: * does not specify an extension explicitly.
384: */
385: if ((iSelect = (INT)SendDlgItemMessage(hwnd,
386: DID_COMMDLG_TYPECOMBO, CB_GETCURSEL, 0, 0L))
387: != CB_ERR) {
388: ofn.lpstrDefExt = (LPCSTR)DefExtFromFilter(
389: iSelect, (PSTR)ofn.lpstrFilter);
390: }
391: }
392:
393: break;
394: }
395:
396: /*
397: * Process the message normally.
398: */
399: return FALSE;
400: }
401:
402:
403:
404: /************************************************************************
405: * AddFilterString
406: *
407: * This function adds a filter string pair to a filter string for
408: * use by the common dialog open/save file functions. The string
409: * pair will be added to the end of the given filter string, unless
410: * fFirst is TRUE, in which case it will be written out to the
411: * start of the buffer. A double null will always be written out
412: * at the end of the filter string.
413: *
414: * Arguments:
415: * PSTR pszBuf - Buffer to write to.
416: * PSTR pszType - Type string. Something like "Icon files (*.ico)".
417: * PSTR pszExt - Extension string. Something like "*.ico".
418: * BOOL fFirst - TRUE if this is the first filter string in the
419: * buffer. If FALSE, the new filter string pair will
420: * be added to the end of pszBuf.
421: *
422: * History:
423: *
424: ************************************************************************/
425:
426: STATICFN VOID NEAR AddFilterString(
427: PSTR pszBuf,
428: PSTR pszType,
429: PSTR pszExt,
430: BOOL fFirst)
431: {
432: PSTR psz;
433:
434: psz = pszBuf;
435:
436: /*
437: * If this is not the first filter string pair, skip to the
438: * terminating double null sequence.
439: */
440: if (!fFirst) {
441: while (*psz || *(psz + 1))
442: psz++;
443:
444: psz++;
445: }
446:
447: strcpy(psz, pszType);
448: psz += strlen(pszType) + 1; strcpy(psz, pszExt);
449: psz += strlen(pszExt) + 1;
450: *psz = '\0';
451: }
452:
453:
454:
455: /************************************************************************
456: * DefExtFromFilter
457: *
458: * This function returns the default extension for the given index
459: * from the specified filter string chain. The filter string chain
460: * is in the format expected by the GetSaveFileName function.
461: *
462: * It will return NULL if the filter extension found is "*.*".
463: *
464: * Arguments:
465: * INT index - Zero based index to the filter string.
466: * PSTR pszFilter - Pointer to the start of the filter chain.
467: *
468: * History:
469: *
470: ************************************************************************/
471:
472: STATICFN PSTR NEAR DefExtFromFilter(
473: INT index,
474: PSTR pszFilter)
475: {
476: if (!pszFilter)
477: return NULL;
478:
479: /*
480: * Skip to the specified filter string pair.
481: */
482: while (index--) {
483: pszFilter += strlen(pszFilter) + 1;
484: pszFilter += strlen(pszFilter) + 1;
485: }
486:
487: /*
488: * Skip the first string, then skip the '*' and the '.'.
489: */
490: pszFilter += strlen(pszFilter) + 1 + 1 + 1;
491:
492: /*
493: * If the string found was "*.*", return NULL for the default
494: * extension.
495: */
496: if (*pszFilter == '*')
497: return NULL;
498:
499: /*
500: * Return a pointer to the default extension. This will be
501: * something like "bmp" or "ico".
502: */
503: return pszFilter;
504: }
505:
506:
507:
508: /************************************************************************
509: * VerifySaveFile
510: *
511: * Prompts the user if they want to save the current file to disk.
512: * If Yes, calls the appropriate save routine.
513: *
514: * Returns:
515: * Returns TRUE if either the file was not dirty (no save was done)
516: * or if it was and the user did not want to save it or the file
517: * was dirty and the user wanted to save it and the save was
518: * successful.
519: *
520: * Returns FALSE if the user cancelled the operation, or an error
521: * occured with the save.
522: *
523: * History:
524: *
525: ************************************************************************/
526:
527: BOOL VerifySaveFile(VOID)
528: {
529: if (fImageDirty || fFileDirty) {
530: switch (Message(MSG_SAVEFILE,
531: gpszFileName ? gpszFileName : ids(IDS_UNTITLED))) {
532: case IDYES:
533: return SaveFile(FALSE);
534:
535: case IDNO:
536: fImageDirty = FALSE;
537: break;
538:
539: case IDCANCEL:
540: return FALSE;
541: }
542: }
543:
544: return TRUE;
545: }
546:
547:
548:
549: /************************************************************************
550: * SaveFile
551: *
552: * Does a save of the current file. If the file is untitled, it
553: * will ask the user for a file name.
554: *
555: * Arguments:
556: * BOOL fSaveAs - TRUE to force a Save As operation (always prompts
557: * for the file name).
558: *
559: * Returns:
560: * Returns TRUE if the save was successful.
561: *
562: * Returns FALSE if the user cancelled the operation, or an error
563: * occured with the save.
564: *
565: * History:
566: *
567: ************************************************************************/
568:
569: BOOL SaveFile(
570: BOOL fSaveAs)
571: {
572: CHAR szFileName[CCHMAXPATH];
573:
574: if (gnImages == 0) {
575: Message(MSG_NOIMAGES);
576: return FALSE;
577: }
578:
579: if (gpszFileName)
580: strcpy(szFileName, gszFullFileName);
581: else
582: *szFileName = '\0';
583:
584: if (fSaveAs || !gpszFileName) {
585: if (!SaveAsDlg(szFileName, giType))
586: return FALSE;
587: }
588:
589: switch (giType) {
590: case FT_BITMAP:
591: return SaveBitmapFile(szFileName);
592:
593: case FT_ICON:
594: case FT_CURSOR:
595: return SaveIconCursorFile(szFileName, giType);
596: }
597:
598: return FALSE;
599: }
600:
601:
602:
603: /************************************************************************
604: * OpenAFile
605: *
606: * Prompts for a file name to open and then does the loading of it.
607: *
608: * History:
609: *
610: ************************************************************************/
611:
612: BOOL OpenAFile(VOID)
613: {
614: CHAR szFileName[CCHMAXPATH];
615:
616: if (OpenDlg(szFileName, giType)) {
617: /*
618: * Clear out the current resource.
619: */
620: ClearResource();
621:
622: LoadFile(szFileName);
623:
624: return TRUE;
625: }
626: else {
627: return FALSE;
628: }
629: }
630:
631:
632:
633: /************************************************************************
634: * LoadFile
635: *
636: * Loads the specified file for editing.
637: *
638: * Arguments:
639: * PSTR pszFullFileName - Full path name to the file to load.
640: *
641: * History:
642: *
643: ************************************************************************/
644:
645: STATICFN BOOL NEAR LoadFile(
646: PSTR pszFullFileName)
647: {
648: switch (GetTypeFromExt(pszFullFileName)) {
649: case FT_BITMAP:
650: return LoadBitmapFile(pszFullFileName);
651:
652: case FT_ICON:
653: return LoadIconCursorFile(pszFullFileName, TRUE);
654:
655: case FT_CURSOR:
656: return LoadIconCursorFile(pszFullFileName, FALSE);
657: }
658:
659: return FALSE;
660: }
661:
662:
663:
664: /************************************************************************
665: * GetTypeFromExt
666: *
667: * Returns the type of file based on it's file name extension.
668: *
669: * Arguments:
670: * PSTR pszFileName - File name to check.
671: *
672: * History:
673: *
674: ************************************************************************/
675:
676: STATICFN INT NEAR GetTypeFromExt(
677: PSTR pszFileName)
678: {
679: PSTR pszExt;
680:
681: pszExt = pszFileName + strlen(pszFileName) - 3;
682:
683: if (strcmpi(pszExt, ids(IDS_DEFEXTICO)) == 0)
684: return FT_ICON;
685: else if (strcmpi(pszExt, ids(IDS_DEFEXTCUR)) == 0)
686: return FT_CURSOR;
687: else
688: return FT_BITMAP;
689: }
690:
691:
692:
693: /************************************************************************
694: * OpenCmdLineFile
695: *
696: * Handles opening of the file specified on the command line.
697: *
698: * History:
699: * Nov 7, 1989 Byron Dazey - Created
700: *
701: ************************************************************************/
702:
703: VOID OpenCmdLineFile(
704: PSTR pstrFileName)
705: {
706: CHAR szFullPath[CCHMAXPATH];
707: OFSTRUCT OfStruct;
708:
709: strcpy(szFullPath, pstrFileName);
710:
711: /*
712: * If the file name does not already have an extension,
713: * assume it is a bitmap file and add a .BMP extension
714: * to it.
715: */
716: FileCat(szFullPath, ids(IDS_DOTBMP));
717:
718: if ((HFILE)OpenFile(szFullPath, &OfStruct, OF_EXIST) == (HFILE)-1) {
719: Message(MSG_CANTOPEN, pstrFileName);
720: }
721: else {
722: LoadFile(OfStruct.szPathName);
723: }
724: }
725:
726:
727:
728: /************************************************************************
729: * FileCat
730: *
731: * This function checks for an extension on the give file name.
732: * If an extension is not found, the extension specified by
733: * pchCat is added to the file name.
734: *
735: * Arguments:
736: * PSTR pch = The file spec to "cat" the extension to.
737: * PSTR pchCat = The extension to "cat" on to pch,
738: * including the '.'
739: *
740: * History:
741: *
742: ************************************************************************/
743:
744: STATICFN VOID NEAR FileCat(
745: PSTR pchName,
746: PSTR pchCat)
747: {
748: PSTR pch;
749:
750: pch = pchName + strlen(pchName);
751: pch = FAR2NEAR(AnsiPrev(pchName, pch));
752:
753: /* back up to '.' or '\\' */
754: while (*pch != '.') {
755: if (*pch == '\\' || pch <= pchName) {
756: /* no extension, add one */
757: strcat(pchName, pchCat);
758: return;
759: }
760:
761: pch = FAR2NEAR(AnsiPrev(pchName, pch));
762: }
763: }
764:
765:
766:
767: /************************************************************************
768: * MyFileRead
769: *
770: *
771: *
772: * Arguments:
773: *
774: * History:
775: *
776: ************************************************************************/
777:
778: BOOL MyFileRead(
779: HFILE hf,
780: LPSTR lpBuffer,
781: UINT nBytes,
782: PSTR pszFileName,
783: INT iType)
784: {
785: register UINT cb;
786:
787: cb = _lread((HFILE)hf, lpBuffer, nBytes);
788:
789: if (cb == -1) {
790: Message(MSG_READERROR, pszFileName);
791: return FALSE;
792: }
793: else if (cb != nBytes) {
794: Message((iType == FT_BITMAP) ? MSG_BADBMPFILE : MSG_BADICOCURFILE,
795: pszFileName);
796: return FALSE;
797: }
798: else {
799: return TRUE;
800: }
801: }
802:
803:
804:
805: /************************************************************************
806: * MyFileWrite
807: *
808: *
809: *
810: * Arguments:
811: *
812: * History:
813: *
814: ************************************************************************/
815:
816: BOOL MyFileWrite(
817: HFILE hf,
818: LPSTR lpBuffer,
819: UINT nBytes,
820: PSTR pszFileName)
821: {
822: register UINT cb;
823:
824: cb = _lwrite((HFILE)hf, lpBuffer, nBytes);
825:
826: if (cb == -1 || cb != nBytes) {
827: Message(MSG_WRITEERROR, pszFileName);
828: return FALSE;
829: }
830: else {
831: return TRUE;
832: }
833: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.