|
|
1.1 root 1: /*************************************************************
2:
3: This module contains subroutines for nead.c that specifically
4: deal with the Open file interface. Most of the routines were
5: taken from Charles Petzold's book "Programming the OS/2
6: Presentation Manager" and were slightly modified.
7:
8: Procedures in this file:
9: OpenFile() Asks user for new file name and opens it
10: OpenFileProc() Dialog proc that prompts user for file name
11: FillDirListBox() Fills the directory list box
12: FillFileListBox() Fills the file list box
13:
14: **************************************************************/
15: #include "nead.h"
16:
17: /************ External GLOBALS *******************************/
18:
19: extern CHAR szFileName[CCHMAXPATH];
20: extern CHAR szEAName[MAXEANAME+1];
21: extern USHORT usRetEAType;
22: extern BOOL FILE_ISOPEN;
23: extern BOOL FILE_CHANGED;
24: extern BOOL COMMAND_LINE_FILE;
25: extern CHAR *pAlloc,*szEditBuf,*szAscii,*szScratch;
26: extern HOLDFEA *pHoldFEA;
27: extern DELETELIST *pDelList;
28: extern EADATA ConvTable[EATABLESIZE];
29:
30: /*************************************************************/
31:
32:
33: /*
34: * Function name: OpenFile()
35: *
36: * Parameters: hwnd which is the current window handle.
37: * usMode which will attempt to load the file from the command
38: * line iff usMode == ARGFILE which is set in main(). Otherwise,
39: * the selector box is brought up for the user to select from.
40: *
41: * Returns: TRUE iff a file is open upon exit.
42: *
43: * Purpose: This routine handles opening a new file. It will also query the
44: * user for the disposition of the current file if it has been
45: * modified before loading the new file.
46: *
47: * Usage/Warnings: Routine should be bullet proof as it does its own
48: * error checking. It assumes that hwnd points to the
49: * correct window with the name listbox in it.
50: *
51: * Calls: WriteEAs(), Free_FEAList()
52: */
53:
54: BOOL OpenFile(HWND hwnd,USHORT usMode)
55: {
56: CHAR szOldFile[CCHMAXPATH];
57: USHORT usRet;
58:
59: strcpy(szOldFile,szFileName); /* Save name of the currently open file */
60:
61: if(usMode != ARGFILE) /* It isn't the command line file */
62: {
63: if(!WinDlgBox(HWND_DESKTOP, /* Get the file name from the user */
64: hwnd,
65: OpenFileProc,
66: NULL,
67: IDD_OPENBOX,
68: NULL))
69: {
70: strcpy(szFileName,szOldFile); /* They canceled, restore old file */
71: return(FILE_ISOPEN);
72: }
73: }
74:
75: if(FILE_CHANGED) /* Give them a chance to save modifications */
76: {
77: usRet=WinMessageBox(HWND_DESKTOP,hwnd,
78: "The current file has been changed. Do you \
79: wish to save the changes before proceeding?",
80: "Warning",NULL,MB_YESNOCANCEL | MB_ICONQUESTION);
81: switch(usRet)
82: {
83: case MBID_YES:
84: WriteEAs();
85: break;
86: case MBID_CANCEL:
87: return FILE_ISOPEN;
88: }
89: }
90:
91: if(FILE_ISOPEN) /* Free up everything associated with the current file */
92: {
93: Free_FEAList(pHoldFEA,pDelList);
94: FILE_ISOPEN = FALSE;
95: }
96:
97: if(QueryEAs(szFileName)) /* We were successful */
98: {
99: HOLDFEA *pFEA=pHoldFEA;
100:
101: FILE_ISOPEN = TRUE;
102: FILE_CHANGED = FALSE;
103:
104: WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_DELETEALL,0L,0L); /* Fill L-box */
105:
106: while(pFEA)
107: {
108: WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
109: MPFROM2SHORT(LIT_END,0),
110: MPFROMP(pFEA->szName));
111: pFEA = pFEA->next;
112: }
113: }
114: else /* We couldn't query the EAs */
115: {
116: *szFileName = '\000';
117: WinSetDlgItemText(hwnd,IDD_FNAME,szFileName);
118: return(FILE_ISOPEN = FALSE);
119: }
120: WinSetDlgItemText(hwnd,IDD_FNAME,szFileName);
121: pDelList = NULL;
122: return(TRUE);
123: }
124:
125:
126: /*
127: * Function name: OpenFileProc()
128: *
129: * Parameters: hwnd, msg, mp1, mp2. Standard PM Dialog Proc params.
130: * Expects no user pointer.
131: *
132: * Returns: TRUE if user selects OK, FALSE if Cancel is selected.
133: *
134: * Purpose: This proc handles the user interface to select a file name.
135: * Some elementary checks are done to make sure the filename is
136: * valid.
137: *
138: * Usage/Warnings: The interface is NOT foolproof as it is possible to
139: * continue with a non-existant file name. Also, users
140: * are not currently allowed to view/edit the EAs attached
141: * to a directory.
142: *
143: * Calls: FillDirListBox(), FillFileListBox(), ParseFileName()
144: */
145:
146: MRESULT EXPENTRY OpenFileProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
147: {
148: static CHAR szCurrentPath[CCHMAXPATH]={'.', '\\', '*', '\000'},
149: szBuffer[CCHMAXPATH];
150: CHAR szParsedPath[CCHMAXPATH];
151: SHORT sSelect;
152:
153: switch(msg)
154: {
155: case WM_INITDLG:
156: FillDirListBox(hwnd,szCurrentPath);
157: FillFileListBox(hwnd);
158: WinSendDlgItemMsg(hwnd, IDD_FILEEDIT,EM_SETTEXTLIMIT,
159: MPFROM2SHORT(CCHMAXPATH,0),NULL);
160: return 0L;
161:
162: case WM_CONTROL:
163: if(SHORT1FROMMP(mp1) == IDD_DIRLIST || /* An lbox item is selected */
164: SHORT1FROMMP(mp1) == IDD_FILELIST)
165: {
166: sSelect = (USHORT) WinSendDlgItemMsg(hwnd, /* Get item->szBuffer */
167: SHORT1FROMMP(mp1),
168: LM_QUERYSELECTION, 0L, 0L);
169:
170: WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
171: LM_QUERYITEMTEXT,
172: MPFROM2SHORT(sSelect, sizeof(szBuffer)),
173: MPFROMP(szBuffer));
174: }
175:
176: switch(SHORT1FROMMP(mp1))
177: {
178: case IDD_DIRLIST: /* Item was in the directory lbox */
179: switch(SHORT2FROMMP(mp1))
180: {
181: case LN_ENTER: /* Go to the select drive/dir */
182: if(*szBuffer == ' ')
183: DosSelectDisk(*(szBuffer+1) - '@');
184: else
185: DosChDir(szBuffer);
186:
187: FillDirListBox(hwnd, szCurrentPath);
188: FillFileListBox(hwnd);
189:
190: WinSetDlgItemText(hwnd, IDD_FILEEDIT, "");
191: return 0L;
192: }
193: break;
194:
195: case IDD_FILELIST: /* Item was in the file lbox */
196: switch(SHORT2FROMMP(mp1))
197: {
198: case LN_SELECT: /* Copy name to entry field */
199: WinSetDlgItemText(hwnd, IDD_FILEEDIT, szBuffer);
200: return 0L;
201:
202: case LN_ENTER: /* Try to query the file */
203: if(ParseFileName(szFileName, szBuffer) != FILE_VALID)
204: return 0; /* Some error, don't finish */
205: WinDismissDlg(hwnd, TRUE);
206: return 0L;
207: }
208: break;
209: }
210: break;
211:
212: case WM_COMMAND:
213: switch(LOUSHORT(mp1))
214: {
215: case DID_OK: /* Try to query file in the entry field */
216: WinQueryDlgItemText(hwnd, IDD_FILEEDIT,
217: sizeof(szBuffer), szBuffer);
218:
219: switch(ParseFileName(szParsedPath, szBuffer))
220: {
221: case FILE_INVALID: /* Can't open the file */
222: WinAlarm(HWND_DESKTOP, WA_ERROR);
223: FillDirListBox(hwnd, szCurrentPath);
224: FillFileListBox(hwnd);
225: return 0L;
226:
227: case FILE_PATH: /* It was an incomplete path name */
228: strcpy(szCurrentPath,szBuffer);
229: FillDirListBox(hwnd, szCurrentPath);
230: FillFileListBox(hwnd);
231: WinSetDlgItemText(hwnd, IDD_FILEEDIT, "");
232: return 0L;
233:
234: case FILE_VALID: /* It was valid */
235: strcpy(szFileName, szParsedPath);
236: WinDismissDlg(hwnd, TRUE);
237: return 0L;
238: }
239: break;
240:
241: case DID_CANCEL:
242: WinDismissDlg(hwnd, FALSE);
243: return 0L;
244: }
245: break;
246: }
247: return WinDefDlgProc(hwnd, msg, mp1, mp2);
248: }
249:
250:
251: /*
252: * Function name: FillDirListBox()
253: *
254: * Parameters: hwnd points to the current window handle
255: * pcCurrentPath points to a buffer which will be filled in
256: * with the current path.
257: *
258: * Returns: VOID
259: *
260: * Purpose: This routine is called by OpenFileProc to fill in the directory
261: * list box
262: *
263: * Usage/Warnings: Adequete error checking is NOT done on the return
264: * values of the system calls. Also, it is remotely
265: * possible that the calls to add to the list box could fail.
266: *
267: * Calls:
268: */
269:
270: VOID FillDirListBox(HWND hwnd, CHAR *pcCurrentPath)
271: {
272: static CHAR szDrive [] = " :";
273: FILEFINDBUF findbuf;
274: HDIR hDir = 1;
275: SHORT sDrive;
276:
277: ULONG ulCurPathLen, ulDriveMap, ulSearchCount = 1, ulDriveNum;
278:
279: DosQCurDisk(&ulDriveNum, &ulDriveMap);
280: *pcCurrentPath = (CHAR) ulDriveNum + '@';
281: *(pcCurrentPath+1) = ':';
282: *(pcCurrentPath+2) = '\\';
283: ulCurPathLen = CCHMAXPATH;
284: DosQCurDir(0L, pcCurrentPath + 3, &ulCurPathLen);
285:
286: WinSetDlgItemText(hwnd, IDD_PATH, pcCurrentPath);
287: WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_DELETEALL, NULL, NULL);
288:
289: for(sDrive = ('A'-'A'); sDrive <= ('Z'-'A'); sDrive++)
290: {
291: if(ulDriveMap & (1L << sDrive))
292: {
293: *(szDrive+1) = (CHAR) sDrive + 'A';
294:
295: WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_INSERTITEM,
296: MPFROM2SHORT(LIT_END, 0),
297: MPFROMP(szDrive));
298: }
299: }
300: DosFindFirst("*", &hDir, FILE_DIRECTORY | FILE_ALL, &findbuf,
301: sizeof(findbuf), &ulSearchCount, FIL_STANDARD);
302: while(ulSearchCount)
303: {
304: if((findbuf.attrFile & FILE_DIRECTORY) &&
305: (findbuf.achName[0] != '.' || findbuf.achName[1]))
306:
307: WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_INSERTITEM,
308: MPFROM2SHORT(LIT_SORTASCENDING, 0),
309: MPFROMP(findbuf.achName));
310:
311: if(DosFindNext(hDir, &findbuf, sizeof(findbuf), &ulSearchCount))
312: break;
313: }
314: }
315:
316:
317: /* This routine is called by OpenFileProc to fill the file list box */
318:
319: /*
320: * Function name: FillFileListBox()
321: *
322: * Parameters: hwnd points to the current window handle
323: *
324: * Returns: VOID
325: *
326: * Purpose: This routine is called by OpenFileProc to fill in the file
327: * list box with files in the current directory.
328: *
329: * Usage/Warnings: Adequete error checking is NOT done on the return
330: * values of the system calls. Also, it is remotely
331: * possible that the calls to add to the list box could fail.
332: *
333: * Calls:
334: */
335:
336: VOID FillFileListBox(HWND hwnd)
337: {
338: FILEFINDBUF findbuf;
339: HDIR hDir = 1;
340: ULONG ulSearchCount = 1; /* Read 1 entry at a time */
341:
342: WinSendDlgItemMsg(hwnd, IDD_FILELIST, LM_DELETEALL, NULL, NULL);
343:
344: DosFindFirst("*", &hDir, FILE_ALL, &findbuf, sizeof(findbuf),
345: &ulSearchCount, FIL_STANDARD);
346: while(ulSearchCount)
347: {
348: WinSendDlgItemMsg(hwnd, IDD_FILELIST, LM_INSERTITEM,
349: MPFROM2SHORT(LIT_SORTASCENDING, 0),
350: MPFROMP(findbuf.achName));
351:
352: if(DosFindNext(hDir, &findbuf, sizeof(findbuf), &ulSearchCount))
353: break;
354: }
355: }
356:
357:
358: /*
359: * Function name: ParseFileName()
360: *
361: * Parameters: pcOut points to a buffer for the return file specification.
362: * pcIn points to the buffer containing the raw input spec.
363: *
364: * Returns: FILE_INVALID if pcIn had invalid drive or no directory
365: * FILE_PATH if pcIn was empty or had just a path/no file name.
366: * FILE_VALID if pcIn point to good file.
367: *
368: * Purpose: This routine changes drive and directory as per pcIn string.
369: *
370: * Usage/Warnings: Note that pcOut is only valid if FILE_VALID is returned.
371: * in place of strupr(), a codepage should be fetched and
372: * DosCaseMap() should be used to allow for extended chars.
373: * This routine could use some cleanup work.
374: *
375: * Calls:
376: */
377:
378: SHORT ParseFileName(CHAR *pcOut, CHAR *pcIn)
379: {
380: CHAR *pcLastSlash, *pcFileOnly ;
381: ULONG ulDriveMap, ulDirLen = CCHMAXPATH, ulDriveNum;
382:
383: strupr(pcIn); /* Does NOT handle extended chars, should use DosCaseMap */
384:
385: if(*pcIn == '\000') /* If string is empty, return FILE_PATH */
386:
387: return FILE_PATH;
388:
389: /* Get drive from input string or use current drive */
390:
391: if(*(pcIn+1) == ':') /* Yup, they specified a drive */
392: {
393: if(DosSelectDisk(*pcIn - '@')) /* Change to selected drive */
394: return FILE_INVALID;
395: pcIn += 2;
396: }
397: DosQCurDisk(&ulDriveNum, &ulDriveMap); /* Get current drive */
398:
399: *pcOut++ = (CHAR) ulDriveNum + '@'; /* Build drive letter */
400: *pcOut++ = ':';
401: *pcOut++ = '\\';
402:
403: if(*pcIn == '\000') /* If rest of the string is empty, return FILE_PATH */
404: return FILE_PATH;
405:
406: /* Search for the last backslash. If none, it could be a directory. */
407:
408: if(!(pcLastSlash = strrchr(pcIn, '\\'))) /* No slashes? */
409: {
410: if(!DosChDir(pcIn))
411: return FILE_PATH; /* It was a directory */
412:
413: DosQCurDir(0L, pcOut, &ulDirLen); /* Get current dir & attach input fn */
414:
415: if(*(pcOut+strlen(pcOut)-1) != '\\')
416: strcat(pcOut++, "\\");
417:
418: strcat(pcOut, pcIn);
419: return FILE_VALID;
420: }
421:
422: /* If the only backslash is at the beginning, change to root */
423:
424: if(pcIn == pcLastSlash)
425: {
426: DosChDir("\\");
427:
428: if(*(pcIn+1) == '\000')
429: return FILE_PATH;
430:
431: strcpy(pcOut, pcIn+1);
432: return FILE_VALID;
433: }
434:
435: /* Attempt to change directory -- Get current dir if OK */
436:
437: *pcLastSlash = NULL;
438:
439: if(DosChDir(pcIn))
440: return FILE_INVALID;
441:
442: DosQCurDir(0L, pcOut, &ulDirLen);
443:
444: /* Append input filename if any */
445:
446: pcFileOnly = pcLastSlash+1;
447:
448: if(*pcFileOnly == '\000')
449: return FILE_PATH;
450:
451: if(*(pcOut+strlen(pcOut)-1) != '\\')
452: strcat(pcOut++, "\\");
453:
454: strcat(pcOut, pcFileOnly);
455: return FILE_VALID;
456: }
457:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.