_THE MEWEL WINDOW SYSTEM_ by Al Stevens [LISTING ONE] /* ------------ memopad.h ------------- */ /* -------- window identifiers ----------- */ #define ID_MAIN 1 #define ID_MDICLIENT 2 #define ID_EDITOR 3 #define ID_FIRSTEDITOR 100 /* ------- menu command identifiers -------- */ #define ID_NEWFILE 5 #define ID_OPENFILE 6 #define ID_SAVE 7 #define ID_SAVEAS 8 #define ID_PRINT 9 #define ID_EXIT 10 #define IDM_WINDOWTILE 12 #define IDM_WINDOWCASCADE 13 #define IDM_WINDOWICONS 14 #define IDM_WINDOWCLOSEALL 15 #define ID_HELP 99 /* -------- string identifiers --------- */ #define IDS_TITLE 0 #define IDS_HELP 1 #define IDS_ERROR 2 #define IDS_OVERWRITE 3 #define IDS_WRITEERROR 4 #define IDS_SELECTERROR 5 #define IDS_NOFILE 6 #define IDS_FORMFEED 7 #define IDS_UNTITLED 8 [LISTING TWO] #include #include "memopad.h" #include "fileopen.dlg" MPmenu MENU BEGIN POPUP "~File" BEGIN MENUITEM "~New", ID_NEWFILE SHADOW MENUITEM "~Open...", ID_OPENFILE MENUITEM "~Save", ID_SAVE MENUITEM "Save ~As...", ID_SAVEAS MENUITEM SEPARATOR MENUITEM "~Print", ID_PRINT MENUITEM SEPARATOR MENUITEM "E~xit", ID_EXIT END POPUP "~Window" BEGIN MENUITEM "~Tile", IDM_WINDOWTILE SHADOW MENUITEM "~Cascade", IDM_WINDOWCASCADE MENUITEM "Arrange ~Icons", IDM_WINDOWICONS MENUITEM "Close ~All", IDM_WINDOWCLOSEALL END MENUITEM "~Help", ID_HELP HELP END STRINGTABLE BEGIN IDS_TITLE, "MemoPad" IDS_HELP, "MemoPad is a multiple document\ memo processor. You can have\ several *.PAD documents open at\ one time. It demonstrates the\ MDI document feature of MEWEL." IDS_ERROR, "Error!" IDS_OVERWRITE, "Overwrite Existing File?" IDS_WRITEERROR, "Cannot write file" IDS_SELECTERROR, "Select an open document first" IDS_NOFILE, "No such file" IDS_FORMFEED, "Send a Form Feed?" IDS_UNTITLED, "Untitled" END [LISTING THREE] /* ------------ memopad.c -------------- */ #include #include #include #include #include #include #include "memopad.h" long FAR PASCAL FrameWndProc(HWND, WORD, WORD, DWORD); long FAR PASCAL EditorProc(HWND, WORD, WORD, DWORD); void NewFile(void); void SelectFile(void); void SaveFile(BOOL); void PrintPad(void); void OpenWindow(char *); void LoadFile(HWND, char *, int); void BuildEditor(HWND); HWND GetEditorHandle(void); int ErrorMessage(int); char EditorClass[] = "Editor"; char FrameClass[] = "FrameClass"; char Untitled[26]; HWND hClient; HWND hEditor; HWND hFrame; int hInstance; void main(void) { MSG event; WNDCLASS wndclass; CLIENTCREATESTRUCT ccs; char Title[26]; WinInit(); WinUseSysColors(NULLHWND, TRUE); MDIInitialize(); /* Register the Editor Document Window */ memset (&wndclass, 0, sizeof (wndclass)); wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = EditorProc ; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = EditorClass; if (!RegisterClass (&wndclass)) exit(1); /* Register the Frame Window */ memset (&wndclass, 0, sizeof (wndclass)); wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = FrameWndProc ; wndclass.lpszMenuName = "MPMenu"; wndclass.lpszClassName = FrameClass; if (!RegisterClass (&wndclass)) exit(1); /* Open the Resource File */ hInstance = OpenResourceFile("MEMOPAD"); LoadString(hInstance, IDS_UNTITLED, Untitled, 25); /* Create the frame window */ LoadString(hInstance, IDS_TITLE, Title, 25); hFrame = CreateWindow( FrameClass, Title, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, SYSTEM_COLOR, ID_MAIN, NULLHWND, NULLHWND, hInstance, (LPSTR) NULL ); /* display the frame window */ ShowWindow(hFrame, SW_SHOW); /* create the MDI client window */ ccs.hWindowMenu = GetSubMenu(GetMenu(hFrame), 1); ccs.idFirstChild = ID_FIRSTEDITOR; hClient = CreateWindow("mdiclient", NULL, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0,0,0,0, SYSTEM_COLOR, ID_MDICLIENT, hFrame, NULL, hInstance, (LPSTR) &ccs); ShowWindow(hClient, SW_SHOW); /* set focus for keyboard users */ SetFocus(hFrame); /* message loop */ while (GetMessage(&event, NULLHWND, 0, 0)) { TranslateMessage(&event); DispatchMessage(&event); } CloseResourceFile(hInstance); exit(0); } /* wndproc for the frame window */ long FAR PASCAL FrameWndProc(HWND hWnd, WORD message, WORD wParam, DWORD lParam) { HWND hwndCheck; char Hmsg[501]; switch (message) { case WM_HELP: LoadString(hInstance, IDS_HELP, Hmsg, 500); MessageBox(hFrame, Hmsg, NULL, MB_OK); break; case WM_COMMAND: switch (wParam) { case ID_NEWFILE: NewFile(); break; case ID_OPENFILE: SelectFile(); break; case ID_SAVE: SaveFile(FALSE); break; case ID_SAVEAS: SaveFile(TRUE); break; case ID_PRINT: PrintPad(); break; case ID_EXIT: PostQuitMessage(0); break; case IDM_WINDOWTILE: SendMessage(hClient,WM_MDITILE,0,0); break; case IDM_WINDOWCASCADE: SendMessage(hClient,WM_MDICASCADE,0,0); break; case IDM_WINDOWICONS: SendMessage(hClient,WM_MDIICONARRANGE,0,0); break; case IDM_WINDOWCLOSEALL: while ((hwndCheck = GetWindow(hClient, GW_CHILD)) != NULLHWND) SendMessage(hClient, WM_MDIDESTROY, hwndCheck, 0); break; default: break; } break; default: break; } return DefFrameProc(hWnd,hClient,message,wParam,lParam); } /* The New command. Open an empty editor window */ void NewFile(void) { OpenWindow(Untitled); } /* The Open... command. Select a file */ void SelectFile(void) { char FileName[64]; if (DlgOpenFile(hFrame, "*.PAD", FileName)) { HWND hWnd, hEditor; /* test to see if the document is already open */ if ((hWnd = FindWindow(EditorClass, FileName)) != NULLHWND) { /* document is open, activate its window */ BringWindowToTop(hWnd); OpenIcon(hWnd); hEditor = GetTopWindow(hWnd); SetFocus(hEditor); } else OpenWindow(FileName); } } /* get the current active editor window handle */ HWND GetEditorHandle(void) { HWND hCurEd; hCurEd = GetFocus(); if (!IsChild(hClient, GetParent(hCurEd))) hCurEd = NULLHWND; return hCurEd; } /* Save the notepad file */ void SaveFile(BOOL SaveAs) { char FileName[64]; HWND hCurEd, hEditor; char *text; FILE *fp; /* get the handle of the active notepad editor window */ if ((hCurEd = GetEditorHandle()) != NULLHWND) { hEditor = GetParent(hCurEd); /* --- get the editor window's file name --- */ GetWindowText(hEditor, FileName, 64); /* get a name for untitled window or Save As command */ if (SaveAs || strcmp(FileName, Untitled) == 0) { if (!DlgOpenFile(hFrame, "*.PAD", FileName)) return; if (access(FileName, 0) == 0) { char omsg[81]; LoadString(hInstance, IDS_OVERWRITE, omsg, 80); if (MessageBox(hFrame, omsg, NULL, MB_YESNO) == IDNO) return; } SetWindowText(hEditor, FileName); } /* - get the address of the editor text - */ text = (char *) SendMessage(hCurEd, EM_GETHANDLE,0,0); if ((fp = fopen(FileName, "wt")) != NULL) { fwrite(text, strlen(text), 1, fp); fclose(fp); } else ErrorMessage(IDS_WRITEERROR); } else ErrorMessage(IDS_SELECTERROR); } /* open a document window and load a file */ void OpenWindow(char *FileName) { MDICREATESTRUCT mcs; HWND hWnd, hEditor; struct stat sb; if (strcmp(FileName, Untitled) && stat(FileName, &sb)) { ErrorMessage(IDS_NOFILE); return; } mcs.szTitle = FileName; mcs.szClass = EditorClass; mcs.hOwner = hInstance; mcs.lParam = NULL; mcs.x = mcs.y = mcs.cy = mcs.cx = CW_USEDEFAULT; mcs.style = WS_CLIPCHILDREN; /* tell the client window to create the document window */ hWnd = SendMessage(hClient, WM_MDICREATE, 0, (LONG) (LPMDICREATESTRUCT) &mcs); hEditor = GetTopWindow(hWnd); SetFocus(hEditor); if (strcmp(FileName, Untitled)) LoadFile(hEditor, FileName, (int) sb.st_size); } /* wndproc for the editor window */ long FAR PASCAL EditorProc(HWND hWnd, WORD message, WORD wParam, DWORD lParam) { RECT rc; int rtn; switch (message) { case WM_SIZE: /* Resize the edit control box. */ GetClientRect (hWnd, &rc); WinSetSize(GetTopWindow(hWnd), rc.bottom-rc.top+1, rc.right-rc.left+1); break; case WM_SETFOCUS: { rtn = DefMDIChildProc(hWnd,message,wParam,lParam); /* Set the focus on the editor window */ SetFocus(GetTopWindow(hWnd)); return rtn; } case WM_CREATE: /* create the file window's editor box */ BuildEditor(hWnd); break; default: break; } return DefMDIChildProc(hWnd, message, wParam, lParam); } /* Create the editor window */ void BuildEditor(HWND hWnd) { CreateWindow( "edit", NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, SYSTEM_COLOR, ID_EDITOR, hWnd, NULLHWND, hInstance, (LPSTR) NULL); } /* Load the notepad file into the editor text buffer */ void LoadFile(HWND hEditor, char *FileName, int tLen) { int bfsize; char *Buf; FILE *fp; Buf = (char *) SendMessage(hEditor, EM_GETHANDLE, 0, (long) &bfsize); if (bfsize < tLen+1) { Buf = LocalReAlloc(Buf, tLen+1, 0); SendMessage(hEditor, EM_SETHANDLE, tLen+1, (long) Buf); } if (Buf != NULL) { if ((fp = fopen(FileName, "rt")) != NULL) { memset (Buf, 0, tLen+1); fread(Buf, tLen, 1, fp); SendMessage(hEditor, WM_SETTEXT, 0, (long) Buf); fclose(fp); } } } /* print the current notepad */ void PrintPad(void) { char FileName[64]; HWND hCurEd; if ((hCurEd = GetEditorHandle()) != NULLHWND) { char *text; char msg[81]; HWND hEditor = GetParent(hCurEd); /* --- get the editor window's file name --- */ GetWindowText(hEditor, FileName, 64); /* ---------- print the file name ---------- */ fputs("\r\n", stdprn); fputs(FileName, stdprn); fputs(":\r\n\n", stdprn); /* ---- get the address of the editor text ----- */ text = (char *) SendMessage(hCurEd, EM_GETHANDLE,0,0); /* ------- print the notepad text --------- */ while (*text) { if (*text == '\n') fputc('\r', stdprn); fputc(*text++, stdprn); } /* ------- follow with a form feed? --------- */ LoadString(hInstance, IDS_FORMFEED, msg, 80); if (MessageBox(hFrame, msg, NULL, MB_YESNO) == IDYES) fputc('\f', stdprn); } else ErrorMessage(IDS_SELECTERROR); } /* Error message handler */ int ErrorMessage(int ErrorNumber) { char ErrorMsg[81]; char Error[26]; LoadString(hInstance, ErrorNumber, ErrorMsg, 80); LoadString(hInstance, IDS_ERROR, Error, 26); MessageBeep(0); return MessageBox(hFrame, ErrorMsg, Error, MB_OK); } [LISTING FOUR] /* ------------ fileopen.h --------------- */ /* ------- file open dialog box identifiers --------- */ #define ID_FILEOPEN 20 #define ID_PATH 21 #define ID_FILES 22 #define ID_FILENAME 23 #define ID_DRIVE 24 [LISTING SIX] /* ----------- fileopen.c ------------- */ #include #include #include "fileopen.h" static int pascal DlgFnOpen(HDLG, WORD, WORD, DWORD); static BOOL InitDlgBox(HDLG); static void StripPath(char *); static char OrigSpec[80]; static char FileSpec[80]; static char FileName[80]; static int FileSelected; #define HasWildCards(s) (strchr(s, '?') || strchr(s, '*')) /* Dialog Box to select a file from the disk system */ int pascal DlgOpenFile(HWND hParent, BYTE *Fpath, BYTE *Fname) { HDLG hDlg; int rtn; extern int hInstance; hDlg = LoadDialog(hInstance, MAKEINTRESOURCE(ID_FILEOPEN), hParent, DlgFnOpen); strncpy(FileSpec, Fpath, sizeof(FileSpec)); strcpy(OrigSpec, FileSpec); if ((rtn = DialogBox(hDlg)) == TRUE) strcpy(Fname, FileName); else *Fname = '\0'; return rtn; } /* Process dialog box messages */ static int pascal DlgFnOpen(HDLG hDlg, WORD msg, WORD wParam, DWORD lParam) { switch (msg) { case WM_INITDIALOG: if (!InitDlgBox(hDlg)) EndDialog(hDlg, 0); return TRUE; case WM_COMMAND: switch (wParam) { case ID_FILENAME: /* allow user to modify the file spec */ GetDlgItemText(hDlg, ID_FILENAME, FileName, 64); if (HasWildCards(FileName)) { strcpy(OrigSpec, FileName); StripPath(OrigSpec); } break; case IDOK: if (HasWildCards(FileName)) { /* no file name yet */ strcpy(FileSpec, FileName); if (InitDlgBox(hDlg)) { SetDlgItemText(hDlg, ID_FILENAME, FileSpec); strcpy(OrigSpec, FileSpec); } } else EndDialog(hDlg, 1); return TRUE; case IDCANCEL: EndDialog(hDlg, 0); return TRUE; case ID_FILES: switch (HIWORD(lParam)) { case LBN_SELCHANGE : /* selected a different filename */ DlgDirSelect(hDlg, FileName, ID_FILES); SetDlgItemText(hDlg, ID_FILENAME, FileName); FileSelected = TRUE; break; case LBN_DBLCLK : /* chose a file name */ DlgDirSelect(hDlg, FileName, ID_FILES); EndDialog(hDlg, 1); return TRUE; } break; case ID_DRIVE: switch (HIWORD(lParam)) { case LBN_SELCHANGE : /* selected different drive/dir */ DlgDirSelect(hDlg, FileName, ID_DRIVE); strcat(FileName, OrigSpec); strcpy(FileSpec, FileName); SetDlgItemText(hDlg, ID_FILENAME, FileSpec); break; case LBN_DBLCLK : /* chose drive/dir */ if (InitDlgBox(hDlg)) SetDlgItemText(hDlg, ID_FILENAME, FileSpec); else strcpy(FileSpec, OrigSpec); return TRUE; } break; default: break; } } return FALSE; } /* Initialize the dialog box */ static BOOL InitDlgBox(HDLG hDlg) { FileSelected = FALSE; SetDlgItemText(hDlg, ID_FILENAME, FileSpec); if (!DlgDirList(hDlg, FileSpec, ID_FILES, ID_PATH, 0)) return FALSE; /* MEWEL DlgDirList should do this, but does not */ StripPath(FileSpec); return DlgDirList(hDlg, "*.*", ID_DRIVE, 0, 0xc010); } /* Strip the drive and path information from a file spec */ static void StripPath(char *filespec) { char *cp, *cp1; cp = strchr(filespec, ':'); if (cp != NULL) cp++; else cp = filespec; while (TRUE) { cp1 = strchr(cp, '\\'); if (cp1 == NULL) break; cp = cp1+1; } strcpy(filespec, cp); }