Add Helper Functions

You need to add several functions to your C-language source file to support the EditFile application. These functions are as follows:

CheckFileName

Checks a filename for wildcards, adds the default filename extension if one is needed, and checks for the existence of the file.

SaveFile

Saves the contents of the editing buffer in a file.

QuerySaveFile

Prompts the user to save changes if the file has changed without having been saved.

SetNewBuffer

Frees the existing editing buffer and replaces it with a new one.

The CheckFileName function verifies that a filename is not empty and that it contains no wildcards. It also checks to see whether the file already exists by using the OpenFile function and the OF_EXIST option. If the file exists, CheckFileName prompts the user to see whether the file should be overwritten. Add the following statements:

BOOL CheckFileName(hWnd, pDest, pSrc)

HWND hWnd;

PSTR pDest, pSrc;

{

PSTR pTmp;

if(!pSrc[0])

return(FALSE); /* Indicates no filename was specified */

pTmp = pSrc;

while(*pTmp) { /* Searches the string for wildcards */

switch(*pTmp++) {

case '*':

case '?':

MessageBox(hWnd, “Wildcards not allowed.”,

NULL, MB_OK | MB_ICONEXCLAMATION);

return(FALSE);

}

}

AddExt(pSrc, DefExt); /* Adds the default extension

if needed */

if(OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0) {

sprintf(str, “Replace existing %s?”, pSrc);

if(MessageBox(hWnd, str, “EditFile”,

MB_OKCANCEL | MB_ICONHAND) == IDCANCEL);

return(FALSE);

}

strcpy(pDest, pSrc);

return(TRUE);

}

The SaveFile function uses the OF_CREATE option of the OpenFile function in order to open a file for writing. The OF_CREATE option directs OpenFile to delete the existing contents of the file. The SaveFile function then retrieves a file-buffer handle from the edit control, locks the buffer, and copies the contents to the file. Add the following statements:

BOOL SaveFile(hWnd)

HWND hWnd;

{

BOOL bSuccess;

int IOStatus; /* result of a file write */

if((hFile = OpenFile(FileName, &OfStruct,

OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0) {

sprintf(str, “Cannot write to %s.”, FileName);

MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);

return(FALSE);

}

hEditBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);

pEditBuffer = LocalLock(hEditBuffer);

hSaveCursor = SetCursor(hHourGlass);

IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));

close(hFile);

SetCursor(hSaveCursor);

if(IOStatus != strlen(pEditBuffer)) {

sprintf(str, “Error writing to %s.”, FileName);

MessageBox(hWnd, str, NULL, MB_OK | MB_ICONHAND);

bSuccess = FALSE;

}

else {

bSuccess = TRUE; /* Indicates the file was saved */

bChanges = FALSE; /* Indicates changes have been saved */

}

LocalUnlock(hEditBuffer);

return(bSuccess);

}

The EM_GETHANDLE message, sent by using the SendMessage function, directs the edit control to return the handle of its editing buffer. This buffer is located in local memory, so it is locked by using the LocalLock function. Once locked, the contents are written to the file by using the C run-time write function. The SetCursor function displays the hourglass cursor to indicate a lengthy operation. If write fails to write all bytes, the SaveFile function displays a message box. The LocalUnlock function unlocks the editing buffer before the SaveFile function returns.

The QuerySaveFile function checks for changes to the file and prompts the user to save or delete the changes, or cancel the operation. If the user wants to save the changes, the function prompts the user for a filename by using the Save As dialog box. Add the following statements:

BOOL QuerySaveFile(hWnd)

HWND hWnd;

{

int Response;

FARPROC lpSaveAsDlg;

if(bChanges) {

sprintf(str, “Save current changes: %s”, FileName);

Response = MessageBox(hWnd, str,

“EditFile”, MB_YESNOCANCEL | MB_ICONEXCLAMATION);

if(Response == IDYES) {

check_name:

if(!FileName[0]) {

lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);

Response = DialogBox(hInst, “SaveAs”,

hWnd, lpSaveAsDlg);

FreeProcInstance(lpSaveAsDlg);

if(Response == IDOK)

goto check_name;

else

return(FALSE);

}

SaveFile(hWnd);

}

else if(Response == IDCANCEL)

return(FALSE);

}

else

return(TRUE);

}

The SetNewBuffer function retrieves and frees the editing buffer before allocating and setting a new editing buffer. It then updates the edit control window. Add the following statements to the C-language source file:

void SetNewBuffer(hWnd, hNewBuffer, Title)

HWND hWnd;

HANDLE hNewBuffer;

PSTR Title;

{

HANDLE hOldBuffer;

hOldBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);

LocalFree(hOldBuffer);

if(!hNewBuffer) /* Allocates a buffer if none exists */

hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);

SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L);

InvalidateRect(hEditWnd, NULL, TRUE); /* Updates the buffer */

UpdateWindow(hEditWnd);

SetWindowText(hWnd, Title);

SetFocus(hEditWnd);

bChanges = FALSE;

}

The new text will not be displayed until the edit control repaints its client area. The InvalidateRect function invalidates part of the edit control's client area. The NULL argument means that the entire control needs repainting, and TRUE specifies that the background should be erased before repainting. All of this prepares the control for painting. The UpdateWindow function causes Windows to send the edit control a WM_PAINT message immediately.