summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/write/scrollhz.c
blob: 814995f14cd0d6d4739f538372f64b3d80dac7ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/************************************************************/
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
/************************************************************/

#define NOCLIPBOARD
#define NOGDICAPMASKS
#define NOCTLMGR
#define NOVIRTUALKEYCODES
#define NOWINMESSAGES
#define NOKEYSTATE
#define NOSYSCOMMANDS
#define NOICON
#define NOATOM
#define NOFONT
#define NOBRUSH
#define NOCLIPBOARD
#define NOCREATESTRUCT
#define NODRAWTEXT
#define NOMB
#define NOMETAFILE
#define NOOPENFILE
#define NOPEN
#define NOREGION
#define NOSOUND
#define NOWH
#define NOWNDCLASS
#define NOCOMM
#define NOFONT
#define NOBRUSH
#include <windows.h>
#include "mw.h"
#define NOUAC
#include "cmddefs.h"
#include "wwdefs.h"
#include "dispdefs.h"
#include "fmtdefs.h"

extern long             ropErase;
extern struct WWD       *pwwdCur;
extern struct WWD       rgwwd[];
extern int              wwCur;
extern int              docCur;
extern typeCP           cpMacCur;
extern struct FLI       vfli;

int NEAR    FOnScreenRect(RECT *);


/* P U T  C P  I N  W W  H Z */
PutCpInWwHz(cp)
typeCP cp;
 /* Ensure that cp is in wwCur */
 /* Make sure it's not off to left or right, too. */

    { /* Just check for horizontal bounding; vertical is done
        by call to CpBeginLine below. */
    int dxpRoom, xp, xpMin;
    int dlT;
    typeCP cpBegin;

    UpdateWw(wwCur, false);
    cpBegin = CpBeginLine(&dlT, cp);
    FormatLine(docCur, cpBegin, (**(pwwdCur->hdndl))[dlT].ichCpMin, cpMacCur, flmSandMode);
/* xpMin is a dummy here */
    xp = DxpDiff(0, (int)(cp - vfli.cpMin), &xpMin) + vfli.xpLeft;
    xpMin = pwwdCur->xpMin;
/* we have: xp = desired position, xpMin = amount of horizontal scroll */
/* width of space in window for text */
    dxpRoom = (pwwdCur->xpMac - xpSelBar);
    if (xp < xpMin )
        { /* cp is left of screen */
        AdjWwHoriz(max(0, xp - min(dxpRoom - 1, cxpAuto)) - xpMin);
        }
    else if (xp >= xpMin + dxpRoom)
        { /* cp is right of screen */
        register int dxpRoomT = min(xpRightMax, xp + min(dxpRoom - 1, cxpAuto))
          - dxpRoom + 1;

        AdjWwHoriz(max(0, dxpRoomT) - xpMin);
        }
    }


/* A D J  W W  H O R I Z */
AdjWwHoriz(dxpScroll)
int dxpScroll;
    {
    /* Scroll a window horizontally */
    if (dxpScroll != 0)
        {
        RECT rc;

/* Reset the value of the horizontal scroll bar */
        SetScrollPos( pwwdCur->hHScrBar,
                      pwwdCur->sbHbar,
                      pwwdCur->xpMin + dxpScroll,
                      TRUE);

#ifdef ENABLE   /* HideSel() */
        HideSel();
#endif /* ENABLE */

        ClearInsertLine();

        SetRect( (LPRECT)&rc, xpSelBar, 0, pwwdCur->xpMac, pwwdCur->ypMac );
        ScrollCurWw( &rc, -dxpScroll, 0 );
        TrashWw(wwCur);
        pwwdCur->xpMin += dxpScroll;

        if (pwwdCur->fRuler)
            {
            UpdateRuler();
            }

        }
    }




/* Scroll specified subrectangle of current window by specified amount */
#include <stdlib.h>
ScrollCurWw( prc, dxp, dyp )
register RECT    *prc;
int     dxp,dyp;
{

 extern int vfScrollInval;
 RECT rcClear;
 if (dxp && dyp)
    return; /* Scroll in both dimensions is an illegal case */

 if (!(dxp || dyp))
    return; /* no scrolling to do */

#if 1
    /** 
        The previous old, old code was getting flaky. (7.14.91) v-dougk
     **/
    if (ScrollDC(pwwdCur->hDC,dxp,dyp,(LPRECT)prc,(LPRECT)prc,NULL,&rcClear))
    {
        PatBlt( pwwdCur->hDC, rcClear.left, rcClear.top, 
            rcClear.right-rcClear.left+1, rcClear.bottom-rcClear.top+1, ropErase );

        if (dxp)
            vfScrollInval =  FALSE;
        else 
            vfScrollInval =  (rcClear.bottom-rcClear.top+1) > abs(dyp); 

         if (vfScrollInval)
         {
            InvalidateRect(pwwdCur->wwptr,&rcClear,FALSE);
            UpdateInvalid();  
         }
    }
    else
        vfScrollInval = FALSE;
    return;
#else

 int FCheckPopupRect( HWND, LPRECT );
 extern int vfScrollInval;
 HDC hDC;
 int dxpAbs = (dxp < 0) ? -dxp : dxp;
 int dypAbs = (dyp < 0) ? -dyp : dyp;
 struct RS { int left, top, cxp, cyp; }
                     rsSource, rsDest, rsClear;
 /* Set rsSource, rsDest, rsClear == prc */

 if ((rsSource.cxp = imin( prc->right, pwwdCur->xpMac ) -
                     (rsSource.left = imax( 0, prc->left ))) <= 0)
        /* Rectangle is null or illegal in X-dimension */
    return;
 if ((rsSource.cyp = imin( prc->bottom, pwwdCur->ypMac ) -
                (rsSource.top = imax( pwwdCur->ypMin, prc->top ))) <= 0)
        /* Rectangle is null or illegal in Y-dimension */
    return;
 bltbyte( &rsSource, &rsDest, sizeof (struct RS ));
 bltbyte( &rsSource, &rsClear, sizeof (struct RS ));

 hDC = pwwdCur->hDC;

 if ((dxpAbs < rsSource.cxp) && (dypAbs < rsSource.cyp))
     {  /* A Real scroll, not the bogus case when we just clear exposed area */
        /* NOTE: We do not bother to compute rsSource.cxp or rsSource.cyp,
           as they are not needed by BitBlt or PatBlt */

        /* If there are PopUp windows, use ScrollWindow to avoid getting
           bogus bits from some popup. Since this is slow, only do it if there
           is some popup that overlaps the scroll rect */
     if ( AnyPopup() )
        {
        extern HANDLE hMmwModInstance;
        static FARPROC lpFCheckPopupRect = (FARPROC)NULL;

        /* First time through, inz ptr to thunk */

        if (lpFCheckPopupRect == NULL)
            lpFCheckPopupRect = MakeProcInstance( (FARPROC) FCheckPopupRect,
                                                  hMmwModInstance );
        EnumWindows( lpFCheckPopupRect, (LONG) (LPRECT) prc );
        }

        /* Under windows 2.0, must also check for any part of the scroll
           rectangle being off the screen (not possible in tiling environment).
           If so, use ScrollWindow to avoid getting bogus bits from outside
           the screen. */
     if (!FOnScreenRect( prc ))
        vfScrollInval = TRUE;

     if (vfScrollInval)
         {   /* vfScrollInval also tells UpdateWw that invalid region
                may have changed */

         extern BOOL vfEraseWw;

         ScrollWindow( pwwdCur->wwptr, dxp, dyp, (LPRECT)prc, (LPRECT)prc );
         vfEraseWw = TRUE;
         UpdateInvalid();    /* Marks repaint area as invalid in our
                                structures so we don't think bits grabbed
                                from a popup are valid */
         vfEraseWw = FALSE;
         return;
         }

     if (dxp != 0)
        rsDest.cxp -= (rsClear.cxp = dxpAbs);
     else
            /* dxp==dyp==0 case is caught below */
        rsDest.cyp -= (rsClear.cyp = dypAbs);

     if (dxp < 0)
        {
        rsSource.left += dxpAbs;
        rsClear.left += rsDest.cxp;
        }
     else if (dxp > 0)
        {
        rsDest.left += dxpAbs;
        }
     else if (dyp < 0)
        {
        rsSource.top += dypAbs;
        rsClear.top += rsDest.cyp;
        }
     else if (dyp > 0)
        {
        rsDest.top += dypAbs;
        }
     else
        return;

    BitBlt( hDC,
            rsDest.left, rsDest.top,
            rsDest.cxp,  rsDest.cyp,
            hDC,
            rsSource.left, rsSource.top,
            SRCCOPY );
    }


#ifdef SMFONT
 /* Vertical refresh will be so bindingly fast, that we do not need to erase the
 old text. */
 if (dxp != 0)
    {
    PatBlt(hDC, rsClear.left, rsClear.top, rsClear.cxp, rsClear.cyp, ropErase);
    }
#else /* not SMFONT */
 PatBlt( hDC, rsClear.left, rsClear.top, rsClear.cxp, rsClear.cyp, ropErase );
#endif /* SMFONT */
#endif
}



int FCheckPopupRect( hwnd, lprc )
HWND hwnd;
LPRECT lprc;
{   /* If the passed window is not a popup, return TRUE;
       If the passed window is a popup, and its coordinates overlap
       those of the passed rect, set vfScrollInval to TRUE and return FALSE.
       Otherwise, return TRUE.
       This is a window enumeration function: a return of TRUE means
       continue enumerating windows, a return of FALSE means
       stop the enumeration */

 extern int vfScrollInval;
 RECT rc;
 POINT ptTopLeft, ptBottomRight;
 RECT rcResult;

 if ( !(GetWindowLong( hwnd, GWL_STYLE ) & WS_POPUP) )
        /* Window is not a popup */
    return TRUE;

 /* Get popup rectangle in screen coordinates */

 GetWindowRect( hwnd, (LPRECT) &rc );

 /* Convert rc from screen coordinates to current document window coordinates */

 ptTopLeft.x = rc.left;
 ptTopLeft.y = rc.top;
 ptBottomRight.x = rc.right;
 ptBottomRight.y = rc.bottom;

 ScreenToClient( pwwdCur->wwptr, (LPPOINT) &ptTopLeft );
 ScreenToClient( pwwdCur->wwptr, (LPPOINT) &ptBottomRight );

 rc.left = ptTopLeft.x;
 rc.top = ptTopLeft.y;
 rc.right = ptBottomRight.x;
 rc.bottom = ptBottomRight.y;

 IntersectRect( (LPRECT) &rcResult, (LPRECT) &rc, (LPRECT)lprc );
 if ( !IsRectEmpty( (LPRECT) &rcResult ) )
    {   /* Popup overlaps passed rectangle */
    vfScrollInval = TRUE;
    return FALSE;
    }

 return TRUE;
}




/* S C R O L L  L E F T */
ScrollLeft(dxp)
int dxp;
        { /* Scroll current window left dxp pixels */
        if ((dxp = min(xpRightLim - pwwdCur->xpMin, dxp)) >0)
                AdjWwHoriz(dxp);
        else
                _beep();
        }


/* S C R O L L  R I G H T */
ScrollRight(dxp)
int dxp;
        {
        if ((dxp = min(pwwdCur->xpMin, dxp)) > 0)
                AdjWwHoriz(-dxp);
        else
                _beep();
        }






/* F O N S C R E E N R E C T

    Returns TRUE iff the rectangle is entirely within the screen
    boundaries.
    Assumes the rectangle belongs to the current window.

 */

int NEAR
FOnScreenRect(prc)
register RECT *prc;
{

    POINT ptTopLeft, ptBottomRight;
    int cxScreen = GetSystemMetrics( SM_CXSCREEN );
    int cyScreen = GetSystemMetrics( SM_CYSCREEN );

    ptTopLeft.x = prc->left;
    ptTopLeft.y = prc->top;
    ptBottomRight.x = prc->right;
    ptBottomRight.y = prc->bottom;

    ClientToScreen( pwwdCur->wwptr, (LPPOINT) &ptTopLeft );
    ClientToScreen( pwwdCur->wwptr, (LPPOINT) &ptBottomRight );

    if ((ptTopLeft.x <= 0) || (ptTopLeft.y <= 0) ||
        (ptBottomRight.x >= cxScreen) || (ptBottomRight.y >= cyScreen))
        return FALSE;

    return TRUE;
}