home *** CD-ROM | disk | FTP | other *** search
- /* The routines in this file provide support for various OS-related
- functions under the Microsoft Windows environment on an IBM-PC or
- compatible computer.
-
- Must be compiled with Borland C++ 2.0.
-
- It should not be compiled if the WINDOW_MSWIN symbol is not set */
-
- #include "estruct.h"
- #include "elang.h"
- #include <stdio.h>
- #include <time.h>
- #include "eproto.h"
- #include "edef.h"
-
- #define OEMRESOURCE 1 /* to have access to OBM_CLOSE from windows.h */
- #include "mswin.h"
-
- #define MAXPARAM 10 /* max command line parameters */
- #define TXTSIZ NFILEN /* all purpose string length */
- #define T_SLEEP 1 /* Sleep timer ID */
-
- extern char *itoa (int value, char *string, int radix);
- extern int putenv (const char *name);
-
- /* message codes for EmacsBroadcast */
- #define EMACS_BROADCAST 0x2000
- #define EMACS_STARTING 0x2001
- #define EMACS_ENDING 0x2010
-
- /* variables */
- static char *argv[MAXPARAM];
- static int argc;
-
- static CATCHBUF ExitCatchBuf;
-
- static int Sleeping = 0; /* flag for TakeANap() */
- static int TimeSlice;
- static BOOL LongOperation = FALSE; /* for longop() and GetCharacter() */
- static BOOL HourglassOn = FALSE; /* between SetHourglass & UpdateCursor */
- static BOOL SystemModal = FALSE; /* indicates that the Yes/No message
- box should be system-modal */
-
- static int BroadcastVal; /* used by the EmacsBroadcast function */
-
- static FARPROC MDIClientProc;
-
- /* prototypes */
- static void near pascal MessageLoop (BOOL WaitMode);
- static BOOL near pascal UpdateCursor (HWND hWnd, WORD wParam, DWORD lParam);
- static void near pascal SetHourglass (BOOL hg);
-
- /* timeset: return a system-dependant time string */
- /* ======= */
-
- char * PASCAL timeset (void)
- {
- long Time;
- struct tm *T;
- static char section [] = "intl";
- static int iDate, iTime;
- static char sDate[2], sTime[2], sAMPM[2][5];
- static char buf [TXTSIZ];
- int day, month, year, hour;
-
- time (&Time);
- T = localtime (&Time);
- iDate = GetProfileInt (section, "iDate", 0);
- iTime = GetProfileInt (section, "iTime", 0);
- GetProfileString (section, "sDate", "/", sDate, 2);
- GetProfileString (section, "sTime", ":", sTime, 2);
- GetProfileString (section, "s1159", "AM", sAMPM[0], 5);
- GetProfileString (section, "s2359", "PM", sAMPM[1], 5);
- day = T->tm_mday;
- month = T->tm_mon + 1;
- year = T->tm_year % 100;
- hour = T->tm_hour;
- wsprintf (buf, "%02d%s%02d%s%02d %02d%s%02d%s%02d %s",
- iDate==1 ? day : iDate==2 ? year : month, sDate,
- iDate==1 ? month : iDate==2 ? month : day, sDate,
- iDate==1 ? year : iDate==2 ? day : year,
- iTime==1 ? hour : (hour % 12) ? (hour % 12) : 12,
- sTime, T->tm_min, sTime, T->tm_sec,
- iTime==1 ? "" : sAMPM [hour / 12]);
- return buf;
- } /* timeset */
-
- /* longop: to be called regularly while a long operation is in progress */
- /* ======== */
-
- PASCAL longop (int f)
-
- /* f is TRUE to set long operation status and FALSE to reset that status */
- /* when a long operation is signaled at least twice, the hourglass
- cursor comes up */
- /* While the long operation is in progress, this function runs the
- message loop approximately every 100 ms to yield to other
- applications and allow a reduced set of commands (among which quit)
- to be input by the user */
- {
- static DWORD LastYield; /* time of last yield in milliseconds */
-
- if (f) {
- if (!LongOperation) {
- LongOperation = TRUE;
- LastYield = GetCurrentTime ();
- }
- else { /* 2nd (or more) call in a row, let's yield if enough
- time has elapsed */
- DWORD Time;
-
- if ((Time = GetCurrentTime ()) - LastYield >= TimeSlice) {
- SetHourglass (TRUE);
- LastYield = Time;
- MessageLoop (FALSE);
- }
- }
- }
- else {
- if (LongOperation) {
- LongOperation = FALSE;
- SetHourglass (FALSE);
- }
- }
- } /* longop */
-
- /* mlyesno: ask a yes/no question */
- /* ======= */
-
- PASCAL mlyesno (char *prompt)
-
- /* This function replaces the mlyesno from input.c. Instead of asking a
- question on the message line, it pops up a message box */
- {
- if (MessageBox (hFrameWnd, prompt, ProgName,
- MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION |
- (SystemModal ? MB_SYSTEMMODAL : 0)) == IDYES) return TRUE;
- return FALSE;
- } /* mlyesno */
-
- /* mlabort: display a serious error message (proposes abort) */
- /* ======= */
-
- PASCAL mlabort (char *s)
- {
- char text[NSTRING]; /* hopefully sufficient! */
-
- while (*s == '%') s++; /* remove those strange % signs in some messages */
- strcpy (text, s);
- strcat (text, "\tAbort ");
- strcat (text, ProgName);
- strcat (text, " ?");
- if (MessageBox (hFrameWnd, text, NULL,
- MB_YESNO | MB_DEFBUTTON2 |
- MB_ICONHAND | MB_APPLMODAL) == IDYES) {
- eexitval = -1;
- Throw (ExitCatchBuf, ABORT);
- }
- } /* mlabort */
-
- /* WinInit: all the window initialization crap... */
- /* ======= */
-
- BOOL far pascal WinInit (LPSTR lpCmdLine, int nCmdShow)
-
- /* returns FALSE if failed init */
- {
- WNDCLASS wc;
- HMENU hSysMenu;
- char FrameClassName [TXTSIZ];
- char text [TXTSIZ];
- POINT InitPos;
- int Colors;
- int i;
- static char HomeDir [NFILEN] = "HOME=";
-
- InitializeFarStorage ();
- WinFlags = GetWinFlags ();
-
- i = GetModuleFileName (hEmacsInstance, text, NFILEN);
- for (; i >= 0; i--) {
- if (text[i] == '\\') {
- text[i] = '\0'; /* transform file name into dir name */
- break;
- }
- }
- if (i > 0) {
- strcat (HomeDir, text);
- putenv (HomeDir); /* set HOME environment var to point to
- MicroEMACS executable directory */
- }
-
- HelpEngineFile[0] = '\0';
-
- /*-read the profile */
- TimeSlice = GetProfileInt (ProgName, "TimeSlice", 100);
- Colors = GetProfileInt (ProgName, "Colors", 0);
- GetProfileString (ProgName, "HelpFile", "mewin.hlp", text, TXTSIZ);
- MainHelpFile = copystr (text);
- MainHelpUsed = FALSE;
-
- GetProfileString (ProgName, "InitialSize", "", text, TXTSIZ);
- strlwr (text);
- if (strstr (text, "optimize")) {
- InitPos.x = InitPos.y = 0;
- }
- else {
- InitPos.x = InitPos.y = CW_USEDEFAULT;
- }
- if (nCmdShow == SW_SHOWNORMAL) {
- if (strstr (text, "maximize")) {
- nCmdShow = SW_SHOWMAXIMIZED;
- }
- else if (strstr (text, "minimize") || strstr (text, "icon")) {
- nCmdShow = SW_SHOWMINNOACTIVE;
- }
- }
-
- /*-Register the frame window class */
- strcpy (FrameClassName, ProgName);
- strcat (FrameClassName, "_frame");
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = FrameWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = FRMWNDEXTRA;
- wc.hInstance = hEmacsInstance;
- wc.hIcon = LoadIcon (hEmacsInstance, "AppIcon");
- wc.hCursor = NULL;
- wc.hbrBackground= COLOR_WINDOW + 1;
- wc.lpszMenuName = "Menu";
- wc.lpszClassName= FrameClassName;
- RegisterClass (&wc);
-
- /*-Register the MDI child (screen) window class */
- strcpy (text, ProgName);
- strcat (text, "_screen");
- ScreenClassName = copystr(text);
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = ScrWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = SCRWNDEXTRA;
- wc.hInstance = hEmacsInstance;
- wc.hIcon = LoadIcon (hEmacsInstance, "ScreenIcon");
- wc.hCursor = NULL;
- wc.hbrBackground= COLOR_WINDOW + 1;
- wc.lpszMenuName = NULL;
- wc.lpszClassName= ScreenClassName;
- RegisterClass (&wc);
-
- /*-Create the frame window */
- hFrameWnd = CreateWindow (FrameClassName, /* class */
- ProgName, /* title */
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
- InitPos.x, /* positions */
- InitPos.y,
- CW_USEDEFAULT, /* dimensions */
- CW_USEDEFAULT,
- NULL, /* parent handle */
- NULL, /* menu */
- hEmacsInstance,
- NULL);
-
- if (hFrameWnd == 0) return FALSE;
-
- if (Colors == 0) {
- /* try to detect monochrome displays */
- HDC hDC;
-
- hDC = GetDC (hFrameWnd);
- ColorDisplay = (GetDeviceCaps (hDC, NUMCOLORS) > 2);
- ReleaseDC (hFrameWnd, hDC);
- }
- else {
- ColorDisplay = (Colors > 2);
- }
-
- ShowWindow (hFrameWnd, nCmdShow);
-
- hScreenCursor = LoadCursor (hEmacsInstance, "ScreenCursor");
- hTrackCursor = hScreenCursor;
- hNotQuiescentCursor = LoadCursor (hEmacsInstance,
- "NotQuiescentCursor");
- hHourglass = LoadCursor (NULL, IDC_WAIT);
-
- in_init (); /* sets up the input stream */
-
- argv [0] = ProgName; /* dummy program name */
- {
- register char *s;
-
- argc = 1;
- s = copystr (lpCmdLine);
- while (*s != '\0') {
- argv[argc] = s;
- if (++argc >= MAXPARAM) goto ParsingDone;
- while (*++s != ' ') if (*s == '\0') goto ParsingDone;
- *s = '\0';
- while (*++s == ' ');
- }
- }
- ParsingDone:
- return TRUE;
- } /* WinInit */
-
- /* SetFrameCaption: sets the frame window's text according to the app Id */
- /* =============== */
-
- static void pascal near SetFrameCaption (void)
- {
- char text[sizeof(PROGNAME)+19];
- char *t;
- int Id;
-
- strcpy (text, ProgName);
- Id = GetWindowWord (hFrameWnd, GWW_FRMID);
- if (Id) {
- for (t = text; *t != '\0'; t++) ; /* look for the end of text */
- *t++ = ' ';
- *t++ = '#';
- itoa (Id, t, 10); /* append the App Id */
- }
- SetWindowText (hFrameWnd, text);
- } /* SetFrameCaption */
-
- /* BroadcastEnumProc: used by EmacsBroadcast */
- /* ================= */
- BOOL EXPORT far pascal BroadcastEnumProc (HWND hWnd, DWORD lParam)
- {
- if ((hWnd != LOWORD(lParam)) &&
- (GetClassLong (hWnd, GCL_WNDPROC) == (DWORD)FrameWndProc)) {
- if (HIWORD(lParam) != 0) {
- PostMessage (hWnd, WM_COMMAND, EMACS_BROADCAST, lParam);
- }
- if (HIWORD(lParam) == EMACS_STARTING) {
- /*-compute highest application Id */
- int Id;
-
- Id = GetWindowWord (hWnd, GWW_FRMID);
- if (Id == 0) Id = 1;
- ++Id;
- BroadcastVal = max(BroadcastVal, Id);
- }
- else {
- /*-compute number of applications */
- BroadcastVal++;
- }
- }
- return TRUE;
- } /* BroadcastEnumProc */
-
- /* EmacsBroadcast: send a broadcast message to all Emacs applications */
- /* ============== */
-
- static int pascal near EmacsBroadcast (WORD MsgCode, HWND hWnd)
-
- /* If MsgCode is not zero, the broadcast is sent as a WM_COMMAND to all
- the Emacs frame windows, except the one specified by hWnd. The wParam
- of that message is EMACS_BROADCAST, the HIWORD of lParam is set to
- MsgCode and the LOWORD of lParam is set to hWnd.
-
- The value returned by this function depends on MsgCode:
-
- - If MsgCode is EMACS_STARTING, the function returns the Id assigned to
- the calling Emacs instance: 0 if it is alone or 1 plus the highest Id
- found, discounting the instance identified by hWnd (note that for
- this purpose, an instance that has an Id of 0 is equivalent to a
- "highest Id" of 1).
-
- - If MsgCode is EMACS_ENDING or 0, the function returns the number of
- emacs instances found, not counting the one identified by hWnd.
-
- */
- {
- FARPROC ProcInstance;
-
- ProcInstance = MakeProcInstance ((FARPROC)BroadcastEnumProc,
- hEmacsInstance);
- BroadcastVal = 0;
- EnumWindows (ProcInstance, MAKELONG(hWnd, MsgCode));
- FreeProcInstance (ProcInstance);
- return BroadcastVal;
- } /* EmacsBroadcast */
-
- /* MDIClientSubProc: Subclassing window proc for the MDI Client window */
- /* ================ */
-
- LONG EXPORT far pascal MDIClientSubProc (HWND hWnd, WORD wMsg, WORD wParam,
- LONG lParam)
- {
- switch (wMsg) {
- case WM_SETCURSOR:
- if (UpdateCursor (hWnd, wParam, lParam)) return TRUE;
- goto DefaultProc;
-
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- case WM_CHAR:
- case WM_SYSCHAR:
- if (EatKey (wMsg, wParam, lParam)) break;
- goto DefaultProc;
-
- case WM_PARENTNOTIFY:
- if (notquiescent) break; /* blocks mouse selection of an MDI
- child (except on caption clicks!)
- */
- goto DefaultProc;
-
- default:
- DefaultProc:
- return CallWindowProc (MDIClientProc, hWnd, wMsg, wParam, lParam);
- }
- return 0L;
- } /* MDIClientSubProc */
-
- /* FrameInit: Frame window's WM_CREATE */
- /* ========= */
-
- void far pascal FrameInit (CREATESTRUCT *cs)
- {
- RECT Rect;
- CLIENTCREATESTRUCT ccs;
- HMENU hMenu;
-
- /*-advertise our birth to other Emacs instances and set the frame's
- caption with an Id if necessary */
- SetWindowWord (hFrameWnd, GWW_FRMID,
- EmacsBroadcast (EMACS_STARTING, hFrameWnd));
- SetFrameCaption ();
-
- /*-add "optimize" to system menu */
- hMenu = GetSystemMenu (hFrameWnd, 0);
- InsertMenu (hMenu, SC_MAXIMIZE, MF_BYCOMMAND | MF_ENABLED, SC_OPTIMIZE,
- "&Optimize");
-
- /*-initialize fonts and Cell Metrics */
- FontInit ();
-
- /*-Create the MDI Client window */
- hMDIClientWnd = NULL; /* the NULL initial value allows
- DefFrameProc to behave properly if
- FrameInit fails */
- ccs.hWindowMenu = GetScreenMenuHandle ();
- ccs.idFirstChild = IDM_FIRSTCHILD;
- GetClientRect (hFrameWnd, &Rect);
- hMDIClientWnd = CreateWindow ("MDICLIENT", /* class */
- NULL, /* title */
- WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL |
- WS_HSCROLL | WS_VISIBLE, /* style */
- 0, /* positions */
- 0,
- Rect.right, /* dimensions */
- Rect.bottom - EmacsCM.MLHeight,
- hFrameWnd, /* parent handle */
- NULL, /* menu */
- hEmacsInstance,
- (LPSTR) (LPCLIENTCREATESTRUCT) &ccs);
- if (hMDIClientWnd) {
- /* we subclass the MDIClient */
- FARPROC ProcInstance;
-
- MDIClientProc = (FARPROC)GetWindowLong (hMDIClientWnd, GWL_WNDPROC);
- ProcInstance = MakeProcInstance ((FARPROC)MDIClientSubProc,
- hEmacsInstance);
- SetWindowLong (hMDIClientWnd, GWL_WNDPROC, ProcInstance);
- }
- } /* FrameInit */
-
- /* CloseEmacs: handle WM_CLOSE of WM_QUERYENDSESSION messages */
- /* ========== */
-
- static BOOL near pascal CloseEmacs (WORD wMsg)
-
- /* returns TRUE if emacs should exit */
- {
- if (eexitflag) return TRUE; /* emacs has already quited */
- if (wMsg == WM_QUERYENDSESSION) SystemModal = TRUE;
- if (fbusy != FWRITING) { /* no file write in progress */
- quit (FALSE, 0); /* check if it's ok with emacs to terminate */
- }
- else { /* there is, indeed a file write in progress
- MessageBeep (0); /* wake the user up! */
- if (MessageBox (hFrameWnd, TEXT333,
- /* "File write in progress. Quit later!" */
- ProgName,
- MB_OKCANCEL | MB_ICONSTOP |
- (SystemModal ? MB_SYSTEMMODAL : 0)) == IDCANCEL) {
- quit (TRUE, 0); /* give up! */
- }
- }
- if (wMsg == WM_QUERYENDSESSION) SystemModal = FALSE;
- if (eexitflag) { /* emacs agrees to quit */
- ClipboardCleanup (); /* close clipboard if we had it open */
- if (fbusy != FALSE) ffclose (); /* cleanup file IOs */
- return TRUE;
- }
- update (TRUE); /* restore the caret that quit() moved into
- the message line */
- return FALSE; /* we refuse to die! */
- } /* CloseEmacs */
-
- /* ScrWndProc: MDI child (screen) window function */
- /* ========== */
- LONG EXPORT far pascal ScrWndProc (HWND hWnd, WORD wMsg, WORD wParam,
- LONG lParam)
- {
- switch (wMsg) {
-
- case WM_CREATE:
- { /*-init WindowWords for ScrReSize function */
- RECT Rect;
-
- GetClientRect (hWnd, &Rect);
- SetWindowWord (hWnd, GWW_SCRCX, Rect.right);
- SetWindowWord (hWnd, GWW_SCRCY, Rect.bottom);
- }
- { /*-setup the stuff for display.c */
- SCREEN *sp;
-
- sp = (SCREEN*)(((MDICREATESTRUCT*)(((CREATESTRUCT*)lParam)->
- lpCreateParams))->lParam);
- SetWindowLong (hWnd, GWL_SCRPTR, (DWORD)sp);
- sp->s_drvhandle = hWnd;
- }
- goto DefaultProc;
-
- case WM_DESTROY:
- vtfreescr ((SCREEN*)GetWindowLong (hWnd, GWL_SCRPTR));
- break;
-
- case WM_KILLFOCUS:
- EmacsCaret (FALSE);
- goto DefaultProc;
- case WM_SETFOCUS:
- EmacsCaret (TRUE);
- goto DefaultProc;
- case WM_ACTIVATE:
- if (wParam) EmacsCaret (TRUE);
- goto DefaultProc;
-
- case WM_MDIACTIVATE:
- if (wParam) { /* this one is becoming active */
- if (!InternalRequest) {
- InternalRequest = TRUE;
- select_screen ((SCREEN *) GetWindowLong (hWnd, GWL_SCRPTR),
- FALSE);
- InternalRequest = FALSE;
- }
- else {
- SCREEN *sp;
-
- sp = (SCREEN*)GetWindowLong (hWnd, GWL_SCRPTR);
- if (sp->s_virtual == NULL) {
- /* this is initialization time! */
- vtinitscr (sp, DisplayableRows (hWnd, 0, &EmacsCM),
- DisplayableColumns (hWnd, 0, &EmacsCM));
- }
- }
- }
- goto DefaultProc;
-
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- case WM_CHAR:
- case WM_SYSCHAR:
- if (EatKey (wMsg, wParam, lParam)) break;
- goto DefaultProc;
-
- case WM_MOUSEMOVE:
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- MouseMessage (hWnd, wMsg, wParam, lParam);
- break;
-
- case WM_SETCURSOR:
- if (UpdateCursor (hWnd, wParam, lParam)) return TRUE;
- goto DefaultProc;
-
- case WM_PAINT:
- ScrPaint (hWnd);
- break;
-
- case WM_SIZE:
- if (!IsIconic (hFrameWnd)) {
- if (wParam == SIZEICONIC) EmacsCaret (FALSE);
- ScrReSize (hWnd, wParam, LOWORD(lParam), HIWORD(lParam));
- }
- goto DefaultProc;
-
- case WM_GETMINMAXINFO:
- GetMinMaxInfo (hWnd, (LPPOINT)lParam);
- goto DefaultProc;
-
- case WM_MOUSEACTIVATE:
- if (notquiescent) break; /* blocks mouse selection of an MDI
- child's caption */
- goto DefaultProc;
-
- case WM_SYSCOMMAND:
- switch (wParam & 0xFFF0) {
- case SC_RESTORE:
- case SC_SIZE:
- case SC_MAXIMIZE:
- case SC_MINIMIZE:
- case SC_NEXTWINDOW:
- case SC_PREVWINDOW:
- if (notquiescent) break; /* sizing commands disabled */
- goto DefaultProc;
- case SC_CLOSE:
- if (!notquiescent) {
- SCREEN *sp;
-
- /* this must be done here, before any MDI mumbo-jumbo */
- sp = (SCREEN*)GetWindowLong (hWnd, GWL_SCRPTR);
- if (sp == first_screen) {
- cycle_screens (FALSE, 0);
- }
- if (sp != first_screen) {
- unlist_screen (sp);
- free_screen (sp);
- }
- update (TRUE); /* to restore the caret */
- }
- break;
- case SC_MOVE:
- if (notquiescent) {
- /* prevent moving an MDI client other than the already
- active one, since it would transfer the activation */
- if (hWnd != LOWORD(SendMessage (hMDIClientWnd,
- WM_MDIGETACTIVE,
- 0, 0L))) break;
- }
- goto DefaultProc;
- default:
- goto DefaultProc;
- }
- break;
-
- default:
- DefaultProc:
- return DefMDIChildProc (hWnd, wMsg, wParam, lParam);
- }
- return 0L;
- } /* ScrWndProc */
-
- /* FrameWndProc: frame window function */
- /* ============ */
- LONG EXPORT far pascal FrameWndProc (HWND hWnd, WORD wMsg, WORD wParam,
- LONG lParam)
- {
- switch (wMsg) {
-
- case WM_INITMENUPOPUP:
- InitMenuPopup (wParam, lParam);
- goto DefaultProc;
-
- case WM_MENUCHAR:
- {
- LONG Code;
-
- Code = DefFrameProc (hWnd, hMDIClientWnd, wMsg, wParam, lParam);
- if (HIWORD(Code) != 0) return Code; /* matches a menu command */
- if (EatKey (wMsg, wParam, lParam)) return MAKELONG(0,1);
- /* MicroEMACS ate that character, close the current menu! */
- else return Code;
- }
-
- case WM_COMMAND:
- if (wParam == EMACS_BROADCAST) {
- int Id;
-
- switch (HIWORD(lParam)) {
- case EMACS_STARTING:
- /* another instance of emacs is starting. If our ID was
- 0, it should now be 1 */
- if (GetWindowWord (hFrameWnd, GWW_FRMID) == 0) {
- SetWindowWord (hFrameWnd, GWW_FRMID, 1);
- SetFrameCaption ();
- }
- break;
- case EMACS_ENDING:
- /* another instance of emacs is ending. If we are now
- alone, let's switch our Id back to 0 */
- Id = EmacsBroadcast (0, LOWORD(lParam));
- /* Id here is the number of Emacs applications, except
- the dying one */
- if (Id == 1) {
- SetWindowWord (hFrameWnd, GWW_FRMID, 0);
- SetFrameCaption ();
- }
- break;
- }
- }
- else {
- if (!MenuCommand (wParam, lParam)) goto DefaultProc;
- }
- break;
-
- case WM_SYSCOMMAND:
- switch (wParam & 0xFFF0) {
- case SC_RESTORE:
- if (IsIconic (hFrameWnd)) goto DefaultProc;
- case SC_SIZE:
- case SC_MAXIMIZE:
- if (notquiescent) break; /* sizing commands disabled */
- goto DefaultProc;
- case SC_OPTIMIZE:
- if (notquiescent) break;
- if (IsZoomed (hFrameWnd) || IsIconic (hFrameWnd)) {
- /* must restore it first */
- ShowWindow (hFrameWnd, SW_RESTORE);
- }
- MoveWindow (hFrameWnd, 0, 0,
- GetSystemMetrics (SM_CXSCREEN),
- GetSystemMetrics (SM_CYSCREEN)
- - GetSystemMetrics (SM_CYICON)
- - GetSystemMetrics (SM_CYCAPTION)
- - GetSystemMetrics (SM_CYBORDER),
- TRUE);
- break;
- default:
- goto DefaultProc;
- }
- break;
-
- case WM_SETCURSOR:
- if (UpdateCursor (hWnd, wParam, lParam)) return TRUE;
- goto DefaultProc;
-
- case WM_TIMER:
- if (wParam == T_SLEEP) {
- --Sleeping; /* signal wake up to TakeANap() */
- break;
- }
- goto DefaultProc;
-
- case WM_PAINT: /* must be the message line */
- MLPaint ();
- break;
-
- case WM_SIZE: /* must adjust the MDIClient's size to fit the
- Message Line */
- MoveWindow (hMDIClientWnd, 0, 0,
- LOWORD(lParam), HIWORD(lParam) - EmacsCM.MLHeight, TRUE);
- break;
-
- case WM_NCLBUTTONDBLCLK:
- { /* This corrects a Windows 3.0 bug that prevents a maximized
- child from being closed by double-clicking the close-box.
- See "Windows 3: A Developer's Guide" by Jeffrey M.
- Richter, page 480 */
- RECT Rect;
- HBITMAP hBmp;
- BITMAP Bmp;
- DWORD MDIGetActivateResult;
-
- if (wParam != HTMENU) goto DefaultProc;
- MDIGetActivateResult = SendMessage (hMDIClientWnd,
- WM_MDIGETACTIVE, 0, 0);
- if (!HIWORD(MDIGetActivateResult)) goto DefaultProc;
- GetWindowRect (hWnd, &Rect);
- Rect.top += GetSystemMetrics(SM_CYCAPTION) +
- GetSystemMetrics (SM_CYFRAME);
- Rect.left += GetSystemMetrics(SM_CXFRAME);
- hBmp = LoadBitmap (NULL, MAKEINTRESOURCE(OBM_CLOSE));
- GetObject (hBmp, sizeof(BITMAP), (LPSTR)(LPBITMAP)&Bmp);
- Rect.bottom = Rect.top + Bmp.bmHeight;
- Rect.right = Rect.left + Bmp.bmWidth / 2;
- if (!PtInRect(&Rect, MAKEPOINT(lParam))) goto DefaultProc;
- SendMessage(LOWORD(MDIGetActivateResult), WM_SYSCOMMAND,
- SC_CLOSE, lParam);
- }
- break;
-
- case WM_ACTIVATE:
- EmacsCaret (wParam);
- /* This call matters only when the active MDI Child is
- iconic, in which case it never receives the focus and
- thus fails to create the caret (that should still appear
- if we are getting input on the message line) */
- goto DefaultProc;
-
- case WM_CREATE:
- hFrameWnd = hWnd;
- FrameInit ((CREATESTRUCT *)lParam);
- goto DefaultProc;
-
- case WM_QUERYENDSESSION:
- if (CloseEmacs (wMsg)) return 1L;
- break;
-
- case WM_CLOSE:
- if (CloseEmacs (wMsg)) goto DefaultProc;
- break;
-
- case WM_DESTROY:
- if (MainHelpUsed) WinHelp (hFrameWnd, MainHelpFile, HELP_QUIT, NULL);
- if (HelpEngineFile[0] != '\0') WinHelp (hFrameWnd, HelpEngineFile,
- HELP_QUIT, NULL);
- EmacsBroadcast (EMACS_ENDING, hFrameWnd);
- PostQuitMessage (0);
- break;
-
- default:
- DefaultProc:
- return DefFrameProc (hWnd, hMDIClientWnd, wMsg, wParam, lParam);
- }
- return 0L;
- } /* FrameWndProc */
-
- /* WinMain: Application entry point */
- /* ======= */
-
- int pascal WinMain (HANDLE hInstance, HANDLE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow)
- {
- hEmacsInstance = hInstance;
- if (!WinInit (lpCmdLine, nCmdShow)) return -1;
-
- switch (Catch (ExitCatchBuf)) {
- case 0:
- emacs (argc, argv);
- /* If we exit through an emacs command, we pass here. Otherwise
- (exit through a close in system menu or a windows session
- termination), the application terminates from the call to
- mswgetc that received the signal */
- case ABORT:
- eexitflag = TRUE;
- longop (FALSE);
- PostMessage (hFrameWnd, WM_CLOSE, 0, 0L);
- for (;;) MessageLoop (TRUE);/* go into message loop until WM_QUIT */
- /* case TRUE:
- break; */
- }
- return eexitval;
- } /* WinMain */
-
- /* ModifyCursor: forces a WM_SETCURSOR */
- /* ============ */
-
- static void pascal near ModifyCursor (void)
- {
- POINT pt;
-
- GetCursorPos (&pt);
- SetCursorPos (pt.x, pt.y);
- } /* ModifyCursor */
-
- /* MessageLoop: Main message loop */
- /* =========== */
-
- static void near pascal MessageLoop (BOOL WaitMode)
-
- /* If WaitMode is TRUE this function uses GetMessage the first time and
- PeekMessage after that, until the input queue is empty and there is
- something in the in_put pipe. Thus, WM_PAINTs are processed and the
- input queue is emptied into the in_put pipe.
- If WaitMode is FALSE, this function uses PeekMessage from the
- beginning and returns only when the input queue is empty. In that
- case, WM_PAINTs are not processed, but the processor still gets
- relinquished. Note that while peeking for messages, this function
- returns if the in_put pipe is about to overflow */
- {
- MSG Msg;
- BOOL Peeking;
-
- ++notquiescent; /* this restrics some actions in nested calls */
- ModifyCursor ();
-
- do {
- Peeking = !WaitMode;
- for (;;) {
- if(defferupdate) {
- ShowEmacsCaret (FALSE);
- update (TRUE);
- ShowEmacsCaret (TRUE);
- }
- if (Peeking) {
- if (!in_room (5)) break; /* input stream about to overflow */
- if (!PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE)) break;
- }
- else {
- longop (FALSE); /* we are going to wait for input */
- GetMessage (&Msg, NULL, 0, 0);
- Peeking = TRUE; /* from now on... */
- }
- if (Msg.message == WM_QUIT) { /* time to leave... */
- JettisonFarStorage ();
- if (hEmacsFont) DeleteObject (hEmacsFont);
- Throw (ExitCatchBuf, TRUE);
- /* we're gone out of business ! */
- /* **************************** */
- }
- if (!TranslateMDISysAccel (hMDIClientWnd, &Msg)) {
- TranslateMessage (&Msg);
- DispatchMessage (&Msg);
- }
- }
- } while (WaitMode && !in_check ()); /* keep waiting if pipe is empty */
-
- --notquiescent;
- ModifyCursor ();
- return;
- } /* MessageLoop */
-
- /* GetInput: wait for user input (called by mswgetc from mswdrv.c) */
- /* ======== */
-
- /* The returned value is the next character from the input stream */
-
- int far pascal GetInput (void)
- {
- if (!in_check ()) {
- ShowEmacsCaret (TRUE);
- MessageLoop (TRUE);
- ShowEmacsCaret (FALSE);
- }
- return in_get (); /* return next character */
- } /* GetInput */
-
- /* TakeANap: put emacs to sleep for a few milliseconds */
- /* ======== */
-
- int far pascal TakeANap (int t)
- /* this function is used by mswsleep(). It returns TRUE unless the timer
- could not be created. Note that for a null time, it simply
- relinquishes the processor */
- {
- if ((t == 0) ||
- (!SetTimer (hFrameWnd, T_SLEEP, t, (FARPROC)NULL))) {
- ShowEmacsCaret (TRUE);
- MessageLoop (FALSE); /* let's do one relinquish anyway */
- ShowEmacsCaret (FALSE);
- if (t == 0) return TRUE;
- else return FALSE;
- }
- ShowEmacsCaret (TRUE);
- Sleeping = 1; /* this gets reset by WM_TIMER processing */
- do {
- MessageLoop (FALSE);
- WaitMessage ();
- } while (Sleeping > 0);
- ShowEmacsCaret (FALSE);
- KillTimer (hFrameWnd, T_SLEEP);
- return TRUE;
- } /* TakeANap */
-
- /* UpdateCursor: sets the apropriate Emacs cursor shape */
- /* ============ */
-
- static BOOL near pascal UpdateCursor (HWND hWnd, WORD wParam, DWORD lParam)
-
- /* this function should be called on each WM_SETCURSOR message, to
- display the appropriate cursor. It returns TRUE if all processing has
- been done (the calling window function should return TRUE). it
- returns FALSE if the default window proc sould be called. */
- {
- HCURSOR hCursor;
-
- switch (LOWORD(lParam)) { /* hit-test area code as in WM_NCHITTEST */
- case HTCLIENT:
- if (HourglassOn) hCursor = hHourglass;
- else {
- if (wParam == hFrameWnd) {
- if (notquiescent) hCursor = hNotQuiescentCursor;
- else hCursor = NULL;
- }
- else { /* a screen window or the MDIClient */
- if (notquiescent) hCursor = hNotQuiescentCursor;
- else if (wParam == hMDIClientWnd) {
- hCursor = NULL;
- }
- else if (mouseflag) {
- if (MouseTracking) hCursor = hTrackCursor;
- else hCursor = hScreenCursor;
- }
- else hCursor = 0;
- }
- }
- if (!hCursor) hCursor = LoadCursor (NULL, IDC_ARROW);
- break;
- case HTHSCROLL:
- case HTVSCROLL:
- case HTREDUCE:
- if ((wParam == hMDIClientWnd) || (wParam == hFrameWnd)) return FALSE;
- case HTBOTTOM:
- case HTBOTTOMLEFT:
- case HTBOTTOMRIGHT:
- case HTLEFT:
- case HTRIGHT:
- case HTTOP:
- case HTTOPLEFT:
- case HTTOPRIGHT:
- case HTSIZE:
- case HTZOOM:
- /* all those are unuseable when notquiescent */
- if (notquiescent) {
- if (HourglassOn) hCursor = hHourglass;
- else hCursor = hNotQuiescentCursor;
- }
- else return FALSE;
- break;
- default:
- return FALSE;
- }
- SetCursor (hCursor);
- return TRUE;
- } /* UpdateCursor */
-
- /* SetHourglass: sets or removes the hourglass cursor */
- /* ============ */
-
- static void near pascal SetHourglass (BOOL hg)
-
- /* hg = TRUE sets the hourglass, hg = FALSE removes it */
- {
- POINT Point;
- HWND hWnd;
-
- if (hg == HourglassOn) return; /* nothing to do */
- HourglassOn = hg;
- GetCursorPos (&Point);
- hWnd = WindowFromPoint (Point);
- if (hWnd && (GetWindowTask (hWnd) == GetCurrentTask ())) {
- /* the cursor is above one of MicroEMACS's windows */
- SetCursorPos (Point.x, Point.y);
- /* this should cause a dummy cursor movement to be processed,
- ending up in UpdateCursor being invoked */
- }
- } /* SetHourglass */
-