1 /* The routines in this file provide drivers for display and input under
2    the Microsoft Windows environment on an IBM-PC or compatible
3    computer.
4 
5    Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions.
6 
7    It should not be compiled if the WINDOW_MSWIN symbol is not set */
8 
9 #define termdef 1           /* don't define term external */
10 
11 #include    "estruct.h"
12 #include    "elang.h"
13 #include    <stdio.h>
14 #include    <time.h>
15 #include    "eproto.h"
16 #include    "edef.h"
17 
18 #include    "mswin.h"
19 
20 #define     NPAUSE  1000    /* pause for fence-showing, 1 second */
21 #define     MARGIN  8       /* size of minimal margin and */
22 #define     SCRSIZ  20      /* scroll size for extended lines */
23 
24 /* terminal interface table entries */
25 
26 static int   PASCAL mswnop();
27 static int   PASCAL mswopen();
28 static int   PASCAL mswgetc();
29 static int   PASCAL mswputc();
30 static int   PASCAL mswflush();
31 static int   PASCAL mswbeep();
32 static int   PASCAL mswmove();
33 static int   PASCAL msweeol();
34 static int   PASCAL msweeop();
35 static int   PASCAL mswbeep();
36 static int   PASCAL mswrev();
37 static int   PASCAL mswrez();
38 #if COLOR
39 static int   PASCAL mswsetfor();
40 static int   PASCAL mswsetback();
41 #endif
42 static int   PASCAL mswsleep();
43 static int   PASCAL mswnewscr();
44 static int   PASCAL mswdelscr();
45 static int   PASCAL mswselscr();
46 static int   PASCAL mswsizscr();
47 static int   PASCAL mswtopscr();
48 
49 /* Standard terminal interface dispatch table.
50 */
51 NOSHARE TERM term    = {
52         128,
53         128,
54         HUGE,
55         HUGE,
56         0,
57         0,
58 	MARGIN,
59 	SCRSIZ,
60 	NPAUSE,
61         mswopen,    /* t_open: Open terminal at the start */
62         mswnop,     /* t_close: Close terminal at end */
63 	mswnop,     /* t_kopen: Open keyboard */
64 	mswnop,     /* t_kclose: close keyboard */
65 	mswgetc,    /* t_getchar: Get character from keyboard */
66         mswputc,    /* t_putchar: Put character to display */
67         mswflush,   /* t_flush: Flush output buffers */
68         mswmove,    /* t_move: Move the cursor, origin 0 */
69         msweeol,    /* t_eeol: Erase to end of line */
70         msweeop,    /* t_eeop: Erase to end of page */
71 	mswnop,     /* t_clrdesk: Clear the page totally */
72 	mswbeep,    /* t_beep: Sound beep */
73 	mswrev,     /* t_rev: set reverse video state */
74 	mswrez,     /* t_rez: change screen resolution */
75 #if	COLOR
76 	mswsetfor,  /* t_setfor: set forground color */
77 	mswsetback, /* t_setback: set background color */
78 #endif
79 	mswsleep,   /* t_sleep: wait a while */
80 	mswnewscr,  /* t_newscr: create new "screen" display */
81 	mswdelscr,  /* t_delscr: destroy "screen" display */
82 	mswselscr,  /* t_selscr: select "screen" display for IO */
83 	mswsizscr,  /* t_sizscr: resize "screen" display */
84         mswtopscr   /* t_topscr: bring "screen" to top */
85 };
86 
87 #define MAXMLHIST   8       /* must be a power of 2 */
88 #define MLHISTMASK  0x7     /* corresponding bit mask */
89 static char *MLHistory[MAXMLHIST] = {NULL};
90     /* circular history of the last few message line entries */
91 static int  MLHistOld = 0;  /* index of the oldest message */
92 static int  MLHistNew = 0;  /* index of the first empty slot */
93 
94 static HWND hIOWnd;         /* current window where I/Os take place */
95 
96 static int  UpdateRow;      /* Row being updated (-1 for no update) */
97 
98 static struct {
99     int leftmost;
100     int rightmost;      /* -1 indicates the range is empty */
101 } UpdateCol;                /* Columns to invalidate on UpdateRow */
102 
103 static SCREEN *IOScr;       /* Screen affected by the I/Os */
104 
105 #if     COLOR
106 static int  ForgColor;      /* current selection of foreground and */
107 static int  BackColor;      /* background colors */
108 #endif
109 
110 /* PushMLHist:  store the last message line contents in the history */
111 /* ==========                                                       */
112 
PushMLHist(void)113 static void PASCAL  PushMLHist (void)
114 {
115     char    *ml;
116     int     i, e;
117 
118     for (e = MLSIZE - 1; e >= 0; e--) if (MLBuf[e] != ' ') break;
119         /* e = index of the last non-space char */
120     if (e < 0) return;
121     if ((ml = MLHistory[MLHistNew] = room (e + 2)) != NULL) {
122         for (i = 0; i <= e; i++) *ml++ = MLBuf[i];
123         *ml = '\0';     /* terminate the string */
124 	MLHistNew = (MLHistNew + 1) & MLHISTMASK;
125 	if (MLHistOld == MLHistNew) {
126 	    /* the history is full. This old entry needs to be discarded */
127 	    free (MLHistory[MLHistOld]);
128 	    MLHistOld = (MLHistOld + 1) & MLHISTMASK;
129 	}
130     }
131 } /* PushMLHist */
132 
133 /* MLHistDlgProc:   dialog proc for the Message Line History */
134 /* =============                                             */
135 
MLHistDlgProc(HWND hDlg,UINT wMsg,UINT wParam,LONG lParam)136 int EXPORT FAR PASCAL  MLHistDlgProc (HWND hDlg, UINT wMsg,
137                                       UINT wParam, LONG lParam)
138 {
139     switch (wMsg) {
140 
141     case WM_INITDIALOG:
142         {
143             char    s[50];
144 
145             strcpy (s, PROGNAME);
146             strcat (s, TEXT330);
147             SetWindowText (hDlg, s);
148         }
149         /*-fill the list box */
150         while (MLHistOld != MLHistNew) {
151             SendDlgItemMessage (hDlg, ID_HIST, LB_ADDSTRING, 0,
152                                 (DWORD)MLHistory[MLHistOld]);
153             free (MLHistory[MLHistOld]);
154             MLHistOld = (MLHistOld + 1) & MLHISTMASK;
155         }
156 	/*-scroll the last message into view */
157         {
158             int     i;
159 
160             i = SendDlgItemMessage (hDlg, ID_HIST, LB_GETCOUNT, 0, 0L);
161             SendDlgItemMessage (hDlg, ID_HIST, LB_SETCURSEL, i - 1, 0L);
162             SendDlgItemMessage (hDlg, ID_HIST, LB_SETCURSEL, -1, 0L);
163         }
164 	return TRUE;
165 
166     case WM_COMMAND:
167 	if (NOTIFICATION_CODE != BN_CLICKED) break;
168 	if (LOWORD(wParam) == 1) {
169 	    EndDialog (hDlg, 0);
170 	    return TRUE;
171 	}
172 	break;
173     }
174     return FALSE;
175 } /* MLHistDlgProc */
176 
177 /* mlhistory:   displays the message line history box */
178 /* =========                                          */
179 
180 /* This function is needed because the message line only shows the last
181    message. If a macro fails, it usually generates a slew of errors
182    (each beginning by a \n). Eventually, calling this function in the
183    core editor loop will pop up a dialog box showing up to MAXMLHIST-1
184    past messages */
185 
mlhistory(void)186 PASCAL mlhistory (void)
187 {
188     FARPROC     ProcInstance;
189 
190     PushMLHist ();
191     mlferase ();
192     ProcInstance = MakeProcInstance ((FARPROC)MLHistDlgProc,
193 			             hEmacsInstance);
194     DialogBox (hEmacsInstance, "MLHIST", hFrameWnd, ProcInstance);
195     FreeProcInstance (ProcInstance);
196 } /* mlhistory */
197 
ChangeUpdateRow(int newrow)198 static void PASCAL ChangeUpdateRow (int newrow)
199 /* Set UpdateRow to newrow, invalidating the changed cells in the
200    previous update row */
201 {
202     if ((UpdateCol.rightmost >= 0) && (UpdateRow >= 0)) {
203         InvalidateCells (hIOWnd, UpdateCol.leftmost, UpdateRow,
204                          UpdateCol.rightmost, UpdateRow);
205     }
206     UpdateRow = newrow;
207 } /* ChangeUpdateRow */
208 
209 /*****************************************/
210 /* mswopen: initialize windows interface */
211 /* =======                               */
212 
mswopen()213 static int PASCAL mswopen ()
214 {
215     static BOOL FirstTime = TRUE;
216 
217     if (FirstTime) {
218 	int     x;
219 
220 	revexist = TRUE;
221 	eolexist = TRUE;
222 	strcpy (sres, "MSWIN");		/* $SRES emacs variable */
223 	strcpy(os, "MSWIN");		/* $OS emacs variable */
224 	MLBuf = (char*)room(MLSIZE);
225 	for (x = 0; x < MLSIZE;) MLBuf[x++] = ' ';
226 	FirstTime = FALSE;
227     }
228     UpdateRow = -1;
229     UpdateCol.rightmost = -1;
230     UpdateCol.leftmost = HUGE; /* empty range */
231     return 0;
232 } /* mswopen */
233 
234 /***************************************************/
235 /* mswgetc: get character from keyboard (or mouse) */
236 /* =======                                         */
237 
mswgetc()238 static int PASCAL mswgetc ()
239 {
240     return GetInput ();
241 } /* mswgetc */
242 
243 /*************************************/
244 /* mswputc: put character to display */
245 /* =======                           */
246 
mswputc(c)247 static int PASCAL mswputc (c)
248 int     c;  /* character to write (or 0 for dummy write) */
249 {
250     if (UpdateRow != CurrentRow) {
251         ChangeUpdateRow (CurrentRow);
252         UpdateCol.rightmost = -1;
253         UpdateCol.leftmost = HUGE; /* empty range */
254     }
255 
256     /*-set the colors and reverse status in the display buffer */
257     if (hIOWnd != hFrameWnd) {  /* not supported on message line */
258 	register VIDEO   *vp;
259 
260 	vp = IOScr->s_physical[UpdateRow];
261 	vp->v_fcolor = ForgColor;
262 	vp->v_bcolor = BackColor;
263     }
264 
265     /*-update the cursor's position and the UpdateCol range. Update the
266        message line buffer if that's where the fun is */
267     if (c != 0) {
268 	if (CurrentCol < UpdateCol.leftmost) UpdateCol.leftmost = CurrentCol;
269 	if (CurrentCol > UpdateCol.rightmost) UpdateCol.rightmost = CurrentCol;
270 	if (hIOWnd == hFrameWnd) {          /* message line */
271 	    if (c == '\b') {
272 	        if (CurrentCol > 0) MLBuf[--CurrentCol] = ' ';
273 	    }
274 	    else {
275 	        if (c == '\n') PushMLHist();
276 	        else {
277 		    MLBuf[CurrentCol] = c;
278 		    if (CurrentCol < MLSIZE - 1) ++CurrentCol;
279 		}
280 	    }
281 	}
282 	else ++CurrentCol;
283     }
284     return 0;
285 } /* mswputc */
286 
287 /**************************************************/
288 /* mswflush:    update display from output buffer */
289 /* ========                                       */
290 
mswflush()291 static int PASCAL mswflush ()
292 {
293     ChangeUpdateRow (-1);
294     if (!InternalRequest && (hIOWnd == hFrameWnd)) UpdateWindow (hIOWnd);
295     /* note: we do not update screens in real time */
296     MoveEmacsCaret (hIOWnd, CurrentCol, CurrentRow);
297         /* some caret movement is directly handled by the driver (see
298 	   mswputc) */
299     return 0;
300 } /* mswflush */
301 
302 /****************************/
303 /* mswmove: move the cursor */
304 /* =======                  */
305 
mswmove(int newrow,int newcol)306 static int PASCAL mswmove (int newrow, int newcol)
307 {
308     /*-perform IO windows switching depending on the addressed row: if
309        beyond the IO screen, the message line is addressed*/
310     if (!IOScr || (newrow >= IOScr->s_nrow)) {
311         if (hIOWnd != hFrameWnd) {
312             ChangeUpdateRow (-1);
313             hIOWnd = hFrameWnd;
314         }
315         CurrentRow = 0;
316     }
317     else {
318         if (hIOWnd != IOScr->s_drvhandle) {
319             ChangeUpdateRow (-1);
320             hIOWnd = IOScr->s_drvhandle;
321         }
322         CurrentRow = newrow;
323     }
324 
325     CurrentCol = newcol;
326 
327     /*-update the caret */
328     MoveEmacsCaret (hIOWnd, CurrentCol, CurrentRow);
329     return 0;
330 } /* mswmove */
331 
332 /*********************************/
333 /* msweeol: erase to end of line */
334 /* =======                       */
335 
msweeol()336 static int PASCAL msweeol ()
337 {
338     mswputc (0);    /* ensure change of row is properly handled */
339     UpdateCol.leftmost = min(UpdateCol.leftmost,CurrentCol);
340     if (hIOWnd == hFrameWnd) {          /* message line */
341 	int     x;
342 
343 	for (x = CurrentCol; x < MLSIZE;) MLBuf[x++] = ' ';
344 	UpdateCol.rightmost = MLSIZE - 1;
345     }
346     else {
347 	UpdateCol.rightmost = IOScr->s_ncol;
348     }
349     mswflush ();
350     return 0;
351 } /* msweeol */
352 
353 /*********************************/
354 /* msweeop: erase to end of page */
355 /* =======                       */
356 
msweeop()357 static int PASCAL msweeop ()
358 {
359     if (hIOWnd == hFrameWnd) {          /* message line */
360 	msweeol ();     /* only one line here */
361 	return 0;
362     }
363     mswputc (0);    /* ensure change of row is properly handled */
364     UpdateCol.leftmost = min(UpdateCol.leftmost,CurrentCol);
365     InvalidateCells (hIOWnd, UpdateCol.leftmost, UpdateRow,
366 		     IOScr->s_ncol, UpdateRow);
367     if (CurrentRow + 1 < IOScr->s_nrow) {
368 	register int	r;
369 	register VIDEO  *vp;
370 
371 	/*-propagate the colors and reverse status */
372 	for (r = CurrentRow + 1; r < IOScr->s_nrow; r++) {
373 	    vp = IOScr->s_physical[r];
374 	    vp->v_fcolor = ForgColor;
375 	    vp->v_bcolor = BackColor;
376 	}
377 	/*-flag the area for repaint */
378 	InvalidateCells (hIOWnd, 0, CurrentRow + 1,
379 			 IOScr->s_ncol, IOScr->s_nrow);
380     }
381     mswflush ();
382     return 0;
383 } /* msweeop */
384 
385 /*************************/
386 /* mswbeep: sound a beep */
387 /* =======               */
388 
mswbeep()389 static int PASCAL mswbeep ()
390 {
391     MessageBeep (0);
392     return 0;
393 } /* mswbeep */
394 
395 /************************************/
396 /* mswrev:  set reverse video state */
397 /* ======                           */
398 
mswrev(state)399 static int PASCAL mswrev (state)
400 int     state;      /* TRUE = reverse, FALSE = normal */
401 {
402     /* nothing to do: the description of reverse video fields is kept
403        up to date in the physical screen by the display.c code */
404     return 0;
405 } /* mswrev */
406 
407 /************************************/
408 /* mswrez:  change "resolution"     */
409 /* ======                           */
410 
mswrez(res)411 static int PASCAL mswrez (res)
412 char    *res;
413 {
414     return TRUE;   /* $SRES is read-only in MSWIN, but returning an
415 		      error may break existing macros */
416 } /* mswrez */
417 
418 #if COLOR
419 /* mswsetfor:   set foreground color */
420 /* =========                         */
421 
mswsetfor(color)422 static int  PASCAL mswsetfor (color)
423 int     color;
424 {
425     ForgColor = color;
426     return 0;
427 } /* mswsetfor */
428 
429 /* mswsetback:  set background color */
430 /* ==========                        */
431 
mswsetback(color)432 static int  PASCAL mswsetback (color)
433 int     color;
434 {
435     BackColor = color;
436     return 0;
437 } /* mswsetback */
438 #endif
439 
440 /* mswsleep:    wait a specified time (in ms) in an unobtrusive way */
441 /* ========                                                         */
442 
mswsleep(int t)443 static int PASCAL   mswsleep (int t)
444 {
445     return TakeANap (t);
446 } /* mswsleep */
447 
448 /* mswnewscr:   create new MDI window for new screen */
449 /* =========                                         */
450 
mswnewscr(SCREEN * sp)451 static int PASCAL mswnewscr (SCREEN *sp)
452 /* called by screen.c after the screen structure has been allocated. The
453    size of the screen will be determined by the window's size. returns
454    TRUE if successful. */
455 {
456     MDICREATESTRUCT cs;
457     BOOL    Maximized;
458 
459 #if WINDOW_MSWIN32
460     Maximized = (GetWindowLong((HWND)SendMessage (hMDIClientWnd,
461                                                   WM_MDIGETACTIVE,
462                                                   0, 0L),
463                                 GWL_STYLE) & WS_MAXIMIZE);
464 #else
465     Maximized = HIWORD(SendMessage (hMDIClientWnd, WM_MDIGETACTIVE, 0, 0L));
466 #endif
467     if (Maximized) {
468         restorescreen (FALSE, 0);   /* de-maximize previous one */
469     }
470     if (first_screen == NULL) Maximized = TRUE;
471     cs.szClass = ScreenClassName;
472     cs.szTitle = sp->s_screen_name;
473     cs.hOwner = hEmacsInstance;
474     cs.x = CW_USEDEFAULT;
475     cs.y = CW_USEDEFAULT;
476     cs.cx = CW_USEDEFAULT;
477     cs.cy = CW_USEDEFAULT;
478     if (Maximized) cs.style = WS_MAXIMIZE;
479     else cs.style = 0;
480     cs.style |= WS_HSCROLL | WS_VSCROLL;
481     cs.lParam = (DWORD)sp;
482     sp->s_virtual = NULL;     /* not NULL will testify of success */
483     InternalRequest = TRUE;
484     SendMessage (hMDIClientWnd, WM_MDICREATE, 0, (DWORD)(LPSTR)&cs);
485     if (sp->s_virtual) {
486         if (hFrameWnd == GetActiveWindow ()) SetFocus (sp->s_drvhandle);
487     }
488     InternalRequest = FALSE;
489     if (!sp->s_virtual) {
490         mswdelscr (sp);     /* failed, cleanup! */
491         return FALSE;
492     }
493     return TRUE;
494 } /* mswnewscr */
495 
496 /* mswdelscr:   destroys an MDI window for a disappearing screen */
497 /* =========                                                     */
498 
mswdelscr(SCREEN * sp)499 static int PASCAL mswdelscr (SCREEN *sp)
500 /* called by screen.c before the screen structure is deallocated */
501 {
502     if (sp->s_drvhandle == hIOWnd) mswflush ();
503     if (sp == IOScr) mswselscr (first_screen);
504         /* hopefully, at this time, sp!=first_screen */
505     SendMessage (hMDIClientWnd, WM_MDIDESTROY, (UINT)sp->s_drvhandle, 0L);
506 } /* mswdelscr */
507 
508 /* mswselscr:   select a window/screen combination for the next IOs */
509 /* =========                                                        */
510 
mswselscr(SCREEN * sp)511 static int PASCAL mswselscr (SCREEN *sp)
512 {
513     hIOWnd = sp->s_drvhandle;
514     IOScr = sp;
515 } /* mswselscr */
516 
517 /* mswsizscr:   resize an MDI window to fit the associated screen */
518 /* =========                                                      */
519 
mswsizscr(SCREEN * sp)520 static int PASCAL mswsizscr (SCREEN *sp)
521 /* called by Emacs when the screen's dimensions have been changed. A resize
522    through the MS-Windows interface is handled by the ReSize function in
523    mswdisp.c */
524 {
525     HWND    hScrWnd;
526     BOOL    Maximized;
527     int     RetryCount = -1;    /* prevents infinite loop if frame
528 				   window can't be resized properly */
529     BOOL    FrameIconic;
530 
531     WINDOWPLACEMENT WindowPlacement;
532 
533     if (InternalRequest) return;
534     InternalRequest = TRUE;
535     hScrWnd = sp->s_drvhandle;
536 
537     {   /*-If this is iconized, we have to restore it first to be
538 	   allowed to change its size. If it is the active MDI child and
539 	   is maximized, we will actually resize the frame window so, if
540 	   the later is maximized, we restore it first. */
541 
542 #if WINDOW_MSWIN32
543 	HWND   hActiveScr;
544 
545 	hActiveScr = (HWND)SendMessage (hMDIClientWnd, WM_MDIGETACTIVE, 0, 0L);
546         Maximized = (hScrWnd == hActiveScr) &&
547                     (GetWindowLong(hScrWnd, GWL_STYLE) & WS_MAXIMIZE);
548 #else
549 	DWORD   ActiveScr;
550 
551 	ActiveScr = SendMessage (hMDIClientWnd, WM_MDIGETACTIVE, 0, 0L);
552         Maximized = (hScrWnd == LOWORD(ActiveScr)) && HIWORD(ActiveScr);
553 #endif
554 	if (IsIconic (hScrWnd)) {
555 	    SendMessage (hMDIClientWnd, WM_MDIRESTORE, (UINT)hScrWnd, 0L);
556 	}
557         if (Maximized && IsZoomed (hFrameWnd)) {
558             ShowWindow (hFrameWnd, SW_RESTORE);
559         }
560     }
561     FrameIconic = IsIconic (hFrameWnd);
562     do {/*-Now, proceed with resizing... */
563 	int     Delta;
564 	RECT    TargetRect, BoundingRect;   /* in MDIClient coordinates */
565 	RECT    OldClientRect;
566 	POINT   ClientSize;
567 
568 	GetClientRect (hScrWnd, &OldClientRect);
569 	MinimumClientSize (hScrWnd, sp->s_ncol, sp->s_nrow,
570                            &ClientSize.x, &ClientSize.y);
571 	if (Maximized) {
572 	    if (((OldClientRect.bottom == ClientSize.y)
573 	         && (OldClientRect.right == ClientSize.x))
574                 || (RetryCount > 0)) break; /* exit the resize loop */
575 	    ++RetryCount;
576 	    BoundingRect.left = BoundingRect.top = 0;
577 	    BoundingRect.right = GetSystemMetrics (SM_CXSCREEN);
578 	    BoundingRect.bottom = GetSystemMetrics (SM_CYSCREEN);
579 
580             if (FrameIconic && Win31API) {
581                 GetWindowPlacement (hFrameWnd, &WindowPlacement);
582                 TargetRect = WindowPlacement.rcNormalPosition;
583             }
584             else {
585 	        GetWindowRect (hFrameWnd, &TargetRect);
586 	    }
587 	}
588 	else {
589 	    GetClientRect (hMDIClientWnd, &BoundingRect);
590 	    GetWindowRect (hScrWnd, &TargetRect);
591 	    ScreenToClient (hMDIClientWnd, (LPPOINT)&TargetRect.right);
592 	    ScreenToClient (hMDIClientWnd, (LPPOINT)&TargetRect.left);
593 	}
594 
595         /*-process change of width: we move the right edge. If it would
596 	   go off bounds, we move the left edge back to compensate, but
597 	   never below 0 */
598 	Delta = ClientSize.x - OldClientRect.right;
599 	if ((TargetRect.right + Delta) > BoundingRect.right) {
600 	    TargetRect.left += (BoundingRect.right - TargetRect.right)
601                                - Delta;
602 	    TargetRect.right = BoundingRect.right;
603 	    if (TargetRect.left < 0) {
604 		TargetRect.right -= TargetRect.left;
605 		TargetRect.left = 0;
606 	    }
607 	}
608 	else TargetRect.right += Delta;
609 
610 	/*-process change of height: we move the bottom edge. If it
611 	   would go off screen, we move the top edge up to compensate,
612 	   but never beyond 0 */
613 	Delta = ClientSize.y - OldClientRect.bottom;
614 	if ((TargetRect.bottom + Delta) > BoundingRect.bottom) {
615 	    TargetRect.top += (BoundingRect.bottom - TargetRect.bottom)
616                               - Delta;
617 	    TargetRect.bottom = BoundingRect.bottom;
618 	    if (TargetRect.top < 0) {
619 		TargetRect.bottom -= TargetRect.top;
620 		TargetRect.top = 0;
621 	    }
622 	}
623 	else TargetRect.bottom += Delta;
624 
625         if (Maximized && FrameIconic && Win31API) {
626             WindowPlacement.rcNormalPosition = TargetRect;
627             SetWindowPlacement (hFrameWnd, &WindowPlacement);
628         }
629         else {
630 	    SetWindowPos (Maximized ? hFrameWnd : hScrWnd, 0,
631                         TargetRect.left, TargetRect.top,
632 	                TargetRect.right - TargetRect.left,
633 	                TargetRect.bottom - TargetRect.top,
634                         SWP_DRAWFRAME | SWP_NOZORDER);
635         }
636     } while (Maximized);    /* if Maximized, we loop once in case a
637 			       change of menu bar height has prevented
638 			       us from getting the expected client size
639 			       */
640     InternalRequest = FALSE;
641 } /* mswsizscr */
642 
643 /* mswtopscr:   bring a screen's window to top. */
644 /* =========                                    */
645 
mswtopscr(SCREEN * sp)646 static int PASCAL mswtopscr (SCREEN *sp)
647 
648 /* called by screen.c when selecting a screen for current */
649 {
650     if (!InternalRequest) {
651 	InternalRequest = TRUE;
652 	SendMessage (hMDIClientWnd, WM_MDIACTIVATE,
653 		     (UINT)sp->s_drvhandle, 0L);
654 #if WINDOW_MSWIN32
655     if (GetWindowLong(sp->s_drvhandle, GWL_STYLE) & WS_MAXIMIZE) {
656 #else
657     if (HIWORD(SendMessage (hMDIClientWnd, WM_MDIGETACTIVE, 0, 0L))) {
658 #endif
659 	    /* we have a maximized screen. Since we activated it under
660 	       InternalRequest, the new size has not yet been processed
661 	       by emacs, so we have to fix that */
662 	    newwidth (TRUE, DisplayableColumns (sp->s_drvhandle, 0, &EmacsCM));
663 	    newsize (TRUE, DisplayableRows (sp->s_drvhandle, 0, &EmacsCM));
664 	}
665 	InternalRequest = FALSE;
666     }
667 } /* mswtopscr */
668 
669 /*************************/
670 /* mswnop:  No Operation */
671 /* ======                */
672 
673 static int PASCAL mswnop ()
674 {
675     return 0;
676 }
677