|
|
1.1 root 1: /*
2: avio.c -- AVIO action routines
3:
4: Implements scrollbars, sets up an AVIO Presentation Space
5: */
6: #define INCL_AVIO
7: #define INCL_DEV
8: #define INCL_VIO
9: #define INCL_WINWINDOWMGR
10: #define INCL_WINSYS
11: #define INCL_WINMESSAGEMGR
12: #define INCL_WINTRACKRECT
13: #define INCL_WINFRAMEMGR
14: #define INCL_WINSCROLLBARS
15: #include <os2.h>
16: #include <string.h> /* One strlen() call in the Blast() macro */
17: #include "avio.h" /* Get Avio-prefixed routine prototypes */
18: /*
19: Constants
20: */
21: char Blank[2] = { 0x20, 0x07 }; /* <Space> + EGA white attribute */
22: /*
23: Macros to make the code more readable
24: */
25: /* Upper and Lower Bound Calculations */
26: #define Abs(a) (((a) > 0) ? (a) : (-(a)))
27: #define Min(a,b) (((a) < (b)) ? (a) : (b))
28: #define Max(a,b) (((a) > (b)) ? (a) : (b))
29: #define LowerBound(pos, disp, lbound) Max(pos - disp, lbound)
30: #define UpperBound(pos, disp, ubound) Min(pos + disp, ubound)
31:
32: /* Scroll Bar Abbreviations */
33: #define DisableSB(hSB) WinSetParent(hSB, HWND_OBJECT, TRUE)
34: #define EnableSB(hSB) WinSetParent(hSB, hWndFrame, TRUE)
35: #define SetScroll(h, pos, max) \
36: WinSendMsg(h, SBM_SETSCROLLBAR, MPFROM2SHORT(pos, 0), MPFROM2SHORT(0, max))
37:
38: /* Scrollbar redraw macros */
39: #define UpdateOn(c, hsb) if (!(++c)) WinEnableWindowUpdate(hsb, TRUE)
40: #define UpdateOff(c, hsb) if (!(c--)) WinEnableWindowUpdate(hsb, FALSE)
41: #define UpdateFrame(sb) \
42: WinSendMsg(hWndFrame, WM_UPDATEFRAME, MPFROMLONG(sb), 0L)
43:
44: /* Scrolling Macros */
45: #define ClearScreen() ScrollUp(-1) /* Scroll up an "infinite" # lines */
46: #define ScrollDown(n) VioScrollDn(0, 0, -1, -1, n, Blank, hVPS)
47: #define ScrollUp(n) VioScrollUp(0, 0, -1, -1, n, Blank, hVPS)
48:
49: /* RectL -> SWP conversion macros */
50: #define lcx(r) ((r.xRight - r.xLeft) + 1)
51: #define lcy(r) ((r.yTop - r.yBottom) + 1)
52:
53: /* Miscellaneous macros */
54: #define Blast(l, x, y) VioWrtCharStr(l, Min(strlen(l), cxChScreen), x, y, hVPS)
55: #define CalcChars(sPg, sCh) \
56: ((sCh) ? (Max(((sPg) / (sCh)), 0)) : 0)
57: #define SetCellSize(h,w) VioSetDeviceCellSize(h, w, hVPS)
58: #define Value(value) WinQuerySysValue(HWND_DESKTOP, value)
59: /*
60: File-Local Variables
61: */
62: HDC hDC; /* Device Context */
63: HVPS hVPS; /* Virtual PS */
64: int iTopLine; /* PS Line of window corner */
65: int iCurCol; /* Current column of window corner */
66: int cxChPage; /* Width and height of our window, in characters */
67: int cyChPage;
68: int iMaxHorz; /* Scroll bar upper bounds */
69: int iMaxVert;
70: BOOL fNeedHorz; /* Do we need the scroll bars or not? */
71: BOOL fNeedVert;
72: HWND hWndHorzSB; /* Window handles of ScrollBar windows */
73: HWND hWndVertSB;
74: extern HWND hWndFrame; /* Client, frame windows */
75: extern HWND hWndClient;
76: PFNWP pfnOldClient; /* Old Client Window Procedure pointer */
77: PFNWP pfnOldFrame; /* Old Frame Window Procedure pointer */
78: SHORT cyChPS; /* Number of rows in AVIO PS */
79: SHORT cxChPS; /* Number of cols in AVIO PS */
80: SHORT cyChScreen; /* Number of rows in display space */
81: SHORT cxChScreen; /* Number of cols in display space */
82: PFNQL pfnQueryLine;
83: /*
84: Measurements used to help make the window look nice
85: */
86: LONG cxConstant, cyConstant; /* Miscellaneous frame lens */
87: int cxMaxFrame, cyMaxFrame; /* Maximum frame widths */
88: LONG lChWidth, lChHeight;
89: SHORT cxMaxClient, cyMaxClient; /* Client area bounds */
90: BOOL fCreatedPS; /* AVIO PS created */
91: int cHUpdate = -1; /* Keep track of updates */
92: int cVUpdate = -1;
93: /*
94: Local prototypes
95: */
96: void FixScroll(BOOL, BOOL, HWND, ULONG, int *, int, int *);
97: void UpdateScrollBars(RECTL);
98: void Refresh(void);
99: void Update(USHORT, USHORT, USHORT);
100: /*
101: The actual routines
102: */
103: void AvioInit(PLBINFO plbi) {
104: /*
105: Initialize Presentation Space, Device Context, Scroll Bars
106: */
107: VIOCURSORINFO vci;
108: /*
109: Initialize the line buffer info
110: */
111: cyChScreen = plbi->sRows;
112: cxChScreen = plbi->sCols;
113: cyChPS = plbi->sPSrows;
114: cxChPS = plbi->sPScols;
115: pfnQueryLine = plbi->pfnQL;
116: /*
117: One Time Initializations...
118: */
119: if (!fCreatedPS) {
120: /*
121: Create the AVIO Presentation Space, with one attribute byte
122: */
123: hDC = WinOpenWindowDC(hWndClient); /* Open the device context */
124: VioCreatePS(&hVPS, cyChPS, cxChPS + 1, 0, 1, 0);
125: VioAssociate(hDC, hVPS); /* Link the PS with the DC */
126: /*
127: Turn off the cursor (set invisible attribute)
128: */
129: VioGetCurType(&vci, hVPS);
130: vci.attr = -1;
131: VioSetCurType(&vci, hVPS);
132: /*
133: Measure the frame components
134: */
135: cxConstant = 0;
136: cyConstant = Value(SV_CYTITLEBAR) + Value(SV_CYMENU);
137: /*
138: Snag scroll bar info
139: */
140: hWndHorzSB = WinWindowFromID(hWndFrame, FID_HORZSCROLL);
141: hWndVertSB = WinWindowFromID(hWndFrame, FID_VERTSCROLL);
142: fNeedHorz = fNeedVert = TRUE;
143: /*
144: Setup the Client and Frame routines
145: */
146: pfnOldFrame = WinSubclassWindow(hWndFrame, AvioFrameWndProc);
147: pfnOldClient = WinSubclassWindow(hWndClient, AvioClientWndProc);
148: fCreatedPS = TRUE;
149: }
150: /*
151: Repaint the screen
152: */
153: iTopLine = iCurCol = 0;
154: AvioStartup(plbi->fLargeFont);
155: }
156:
157: void AvioStartup(BOOL fLargeFont) {
158: /*
159: Clear the screen, set the font, redraw the area
160: */
161: RECTL rclFrame;
162:
163: ClearScreen();
164: AvioLargeFont(fLargeFont);
165: WinQueryWindowRect(hWndFrame, &rclFrame);
166: UpdateScrollBars(rclFrame);
167: Update(0, cyChPS, 0);
168: }
169:
170: void AvioScroll(USHORT SB_Command, USHORT Position, BOOL Horizontal) {
171: /*
172: Process the scroll bar messages
173:
174: These routines are symmetric; in fact, SB_LINELEFT = SB_LINEUP, etc...
175: so one might note that this could be condensed. It's left expanded for
176: speed and clarity. The scrollbar values are bounded to stay inside
177: the Presentation Space.
178: */
179: if (Horizontal) { /* Horizontal Scroll Bar */
180: switch (SB_Command) {
181: case SB_LINELEFT:
182: iCurCol = LowerBound(iCurCol, 1, 0); break;
183: case SB_LINERIGHT:
184: iCurCol = UpperBound(iCurCol, 1, iMaxHorz); break;
185: case SB_PAGELEFT:
186: iCurCol = LowerBound(iCurCol, cxChPage, 0); break;
187: case SB_PAGERIGHT:
188: iCurCol = UpperBound(iCurCol, cxChPage, iMaxHorz); break;
189: case SB_SLIDERTRACK:
190: iCurCol = (SHORT) Position;
191: default: break;
192: }
193: if (SB_Command != SB_SLIDERTRACK)
194: SetScroll(hWndHorzSB, iCurCol, iMaxHorz);
195:
196: } else { /* Vertical Scroll Bar */
197: switch (SB_Command) {
198: case SB_LINEUP:
199: iTopLine = LowerBound(iTopLine, 1, 0); break;
200: case SB_LINEDOWN:
201: iTopLine = UpperBound(iTopLine, 1, iMaxVert); break;
202: case SB_PAGEUP:
203: iTopLine = LowerBound(iTopLine, cyChPage, 0); break;
204: case SB_PAGEDOWN:
205: iTopLine = UpperBound(iTopLine, cyChPage, iMaxVert);break;
206: case SB_SLIDERTRACK:
207: iTopLine = (SHORT) Position;
208: default: break;
209: }
210: if (SB_Command != SB_SLIDERTRACK)
211: SetScroll(hWndVertSB, iTopLine, iMaxVert);
212: }
213: Refresh();
214: }
215:
216: MRESULT AvioSize(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
217: /*
218: Do the default AVIO sizing, and kyfe a few values
219: */
220: RECTL rclFrame;
221:
222: if (!fCreatedPS) return 0L;
223: /*
224: Update the scroll bars, and the screen
225: */
226: WinQueryWindowRect(hWndFrame, &rclFrame);
227: UpdateScrollBars(rclFrame);
228: /*
229: Now, do the normal AVIO processing
230: */
231: return WinDefAVioWindowProc(hWnd, msg, mp1, mp2);
232: }
233:
234: void Update(USHORT usLineNum, USHORT usHowMany, USHORT usStartLine) {
235: /*
236: Updates N lines starting from START line on screen.
237: Starts at saved line LINENUM.
238: */
239: USHORT i; /* Loop index variable */
240: USHORT usWhichLine = usLineNum; /* Line number to be queried */
241: char *szLine;
242:
243: for (i = usStartLine; i < (usStartLine + usHowMany); i++) {
244: szLine = (*pfnQueryLine)(usWhichLine++); /* Get the line */
245: if (szLine) Blast(szLine, i, 0); /* Print it out */
246: }
247: }
248:
249: void Refresh(void) {
250: /*
251: Do the origin shifting and screen updating
252: */
253: SHORT Delta;
254: int static iOldTopLine = 0;
255:
256: VioSetOrg(0, iCurCol, hVPS); /* Get the free AVIO horizontal shift */
257: Delta = iTopLine - iOldTopLine; /* Compute vertical shift */
258: if (Abs(Delta) < cyChPS) {
259: if (Delta < 0) { /* Scroll Up -- make Delta positive*/
260: ScrollDown(-Delta);
261: Update(iTopLine, -Delta, 0);
262: } else { /* Scroll Down by Delta */
263: ScrollUp(Delta);
264: Update(iTopLine + cyChPS - Delta, Delta, cyChPS - Delta);
265: }
266: } else AvioRedraw(); /* Redo the entire screen */
267: iOldTopLine = iTopLine;
268: }
269:
270: void AvioClose(void) {
271: /*
272: Termination routines
273: */
274: /*
275: Destroy the Presentation Space
276: */
277: VioAssociate(NULL, hVPS);
278: VioDestroyPS(hVPS);
279: fCreatedPS = FALSE;
280: }
281:
282: void AvioPaint(HWND hWnd) {
283: /*
284: Paint the AVIO presentation space by telling it to show itself.
285: A possible optimization here is to repaint only the update region.
286: */
287: static HPS hPS;
288: static RECTL RectL;
289:
290: hPS = WinBeginPaint(hWnd, (HPS) NULL, &RectL);
291: VioShowPS(cyChPS, cxChPS, 0, hVPS);
292: WinEndPaint(hPS);
293: }
294:
295: MRESULT AvioMinMax(PSWP pSWP) {
296: /*
297: Handle WM_MINMAX messages, to make sure frame doesn't get too big
298: */
299: if (pSWP->fs & (SWP_MAXIMIZE | SWP_RESTORE)) {
300: if (pSWP->fs & SWP_MAXIMIZE) {
301: /*
302: Save cx, cy values for later origin displacement
303: */
304: int Oldcx = pSWP->cx;
305: int Oldcy = pSWP->cy;
306: /*
307: Displace, and change to maximum size
308: */
309: pSWP->x += (Oldcx -
310: (pSWP->cx = cxMaxFrame + (int) (Value(SV_CXSIZEBORDER) << 1)));
311: pSWP->y += (Oldcy -
312: (pSWP->cy = cyMaxFrame + (int) (Value(SV_CYSIZEBORDER) << 1)));
313: }
314: /*
315: Now, fix the scroll bars
316: */
317: AvioAdjustFramePos(pSWP);
318: return TRUE;
319: }
320: return FALSE;
321: }
322:
323: void AvioClear(void) { ClearScreen(); }
324:
325: void AvioAdjustFramePos(PSWP pSWP) {
326: /*
327: Trap WM_ADJUSTWINDOWPOS messages to the frame with this routine.
328: Keep the window sized right, and control scrollbar visibility.
329: */
330: RECTL rclFrame;
331:
332: if (!(pSWP->cx && pSWP->cy)) return; /* Null area... */
333: if (pSWP->fs & SWP_MINIMIZE) return; /* Iconic... */
334: /*
335: Make sure the dimensions are in range
336: */
337: pSWP->cx = Min(pSWP->cx, (cxMaxFrame + (SHORT)(Value(SV_CXSIZEBORDER)<<1)));
338: pSWP->cy = Min(pSWP->cy, (cyMaxFrame + (SHORT)(Value(SV_CYSIZEBORDER)<<1)));
339: /*
340: Update the scroll bars
341: */
342: rclFrame.xLeft = (LONG) pSWP->x;
343: rclFrame.xRight = (LONG) (pSWP->x + pSWP->cx - 1);
344: rclFrame.yBottom = (LONG) pSWP->y;
345: rclFrame.yTop = (LONG) (pSWP->y + pSWP->cy - 1);
346: UpdateScrollBars(rclFrame);
347:
348: return;
349: }
350:
351: void AvioTrackFrame(HWND hWnd, MPARAM mpTrackFlags) {
352: /*
353: Takes action on WM_TRACKFRAME message
354: */
355: static TRACKINFO tiTrackInfo;
356: /*
357: Get the tracking information in the TrackInfo structure
358: */
359: WinSendMsg(hWnd, WM_QUERYTRACKINFO, mpTrackFlags, &tiTrackInfo);
360: WinTrackRect(hWnd, NULL, &tiTrackInfo);
361: }
362:
363: void AvioQueryTrackInfo(PTRACKINFO pTI) {
364: /*
365: Routine which processes WM_QUERYTRACKINFO messages to the frame.
366: Call this routine after the default one to change various parameters.
367:
368: Note: In reality, since we have a menu bar, we should make the
369: minimum width of the window something such that it does not "fold."
370: */
371: BOOL fMove;
372: /*
373: Get the grid set up for byte alignment (unless moving)
374:
375: cxGrid is set to half character width so that arrow keys
376: will function when sizing (they try to size by half a
377: character)
378: */
379: fMove = ((pTI->fs & TF_MOVE) == TF_MOVE);
380: pTI->fs |= TF_GRID;
381: pTI->cxGrid = (fMove) ? 1 : ((SHORT) (lChWidth >> 1));
382: pTI->cyGrid = (fMove) ? 1 : ((SHORT) lChHeight);
383: /*
384: Bound the frame.
385: Maximum: Sizing Border, Scrollbars, Title, Menus, client region
386: */
387: pTI->ptlMaxTrackSize.x = (LONG) (pTI->cxBorder << 1) + (LONG) cxMaxFrame;
388: pTI->ptlMaxTrackSize.y = (LONG) (pTI->cyBorder << 1) + (LONG) cyMaxFrame;
389: }
390:
391: void AvioRedraw(void) {
392: /*
393: Clear, then redraw the entire Presentation Space
394: */
395: ClearScreen();
396: Update(iTopLine, cyChPS, 0);
397: }
398:
399: MRESULT CALLBACK AvioClientWndProc
400: (HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
401: /*
402: Window Procedure which traps messages to the Client area
403: */
404: switch (msg) {
405: case WM_PAINT: /* Paint the AVIO way! */
406: AvioPaint(hWnd);
407: break;
408:
409: case WM_SIZE: /* Size the AVIO way! */
410: return AvioSize(hWnd, msg, mp1, mp2);
411: break;
412:
413: case WM_HSCROLL:
414: AvioScroll(HIUSHORT(mp2), LOUSHORT(mp2), TRUE);
415: break;
416:
417: case WM_VSCROLL:
418: AvioScroll(HIUSHORT(mp2), LOUSHORT(mp2), FALSE);
419: break;
420:
421: case WM_ERASEBACKGROUND:
422: break;
423:
424: case WM_TRACKFRAME:
425: AvioTrackFrame(hWnd, mp1);
426: break;
427:
428: case WM_MINMAXFRAME: /* Limit Maximized window size */
429: AvioMinMax((PSWP) mp1);
430:
431: /* fall through */
432:
433: default: return (*pfnOldClient)(hWnd, msg, mp1, mp2);
434: }
435: return 0;
436: }
437:
438: MRESULT CALLBACK AvioFrameWndProc(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2)
439: /*
440: Force the frame to stay small enough (no larger than the PS)
441: */
442: {
443: BOOL rc; /* Return code from WM_QUERYTRACKINFO */
444:
445: switch(msg) {
446: case WM_ADJUSTWINDOWPOS: /* Calculate scroll bar adjustments */
447: AvioAdjustFramePos(mp1);
448: break;
449:
450: case WM_QUERYTRACKINFO: /* Get default, then process message */
451: rc = (BOOL) (*pfnOldFrame)(hWnd, msg, mp1, mp2);
452: AvioQueryTrackInfo((PTRACKINFO) mp2);
453: return rc;
454:
455: default: break;
456: }
457: return (*pfnOldFrame)(hWnd, msg, mp1, mp2);
458: }
459:
460: void UpdateScrollBars(RECTL rclClient) {
461: /*
462: This routine fixes up the scroll bars when the window is resized, or
463: when the font size is changed.
464:
465: Parameters: The dimensions of the frame window
466: Result: Updates the scrollbars, enabling/disabling as needed
467: */
468: BOOL fNeededHorz = fNeedHorz; /* Did we need the scrollbars then? */
469: BOOL fNeededVert = fNeedVert;
470: /*
471: Compute the client rectangle, without the scrollbars
472: */
473: WinCalcFrameRect(hWndFrame, &rclClient, TRUE);
474: /*
475: Compute page width -- do we need the horizontal scroll bar?
476: */
477: cxChPage = (int) CalcChars(lcx(rclClient), lChWidth);
478: fNeedHorz = ((iMaxHorz = Max(cxChScreen - cxChPage, 0)) > 0);
479: /*
480: Compute page height -- do we need the vertical scroll bar?
481: */
482: cyChPage = (int) CalcChars(lcy(rclClient), lChHeight);
483: fNeedVert = ((iMaxVert = Max(cyChScreen - cyChPage, 0)) > 0);
484: /*
485: Maintain scrollbar integrity
486: */
487: iCurCol = Min(iCurCol, iMaxHorz);
488: iTopLine = Min(iTopLine, iMaxVert);
489: /*
490: Now, update the scrollbars as necessary
491: */
492: FixScroll(fNeededHorz, fNeedHorz, hWndHorzSB,
493: FCF_HORZSCROLL, &iCurCol, iMaxHorz, &cHUpdate);
494:
495: FixScroll(fNeededVert, fNeedVert, hWndVertSB,
496: FCF_VERTSCROLL, &iTopLine, iMaxVert, &cVUpdate);
497: /*
498: Now, update the screen to be visually consistent
499: */
500: Refresh();
501: }
502:
503: void FixScroll(fNeeded, fNeed, hWnd, flScroll, piPos, iMax, pc)
504: /*
505: This routine makes the necessary scrollbar adjustments, and
506: also enables/disables them.
507: */
508: BOOL fNeeded; /* Whether we used to need the scrollbar */
509: BOOL fNeed; /* Whether we need the scrollbar now */
510: HWND hWnd; /* Handle to the scrollbar window */
511: ULONG flScroll; /* FCF_xxxxSCROLL flag (for the scrollbar) */
512: int *piPos; /* Current location of scrollbar thumb */
513: int iMax; /* New maximum for the scrollbar */
514: int *pc; /* Counter for WinEnableWindowUpdate recursion */
515: {
516: if (fNeed) { /* Enable the scroll bar -- we didn't need it before */
517: if (!fNeeded) {
518: EnableSB(hWnd);
519: UpdateOff((*pc), hWnd);
520: UpdateFrame(flScroll);
521: UpdateOn((*pc), hWnd);
522: }
523: SetScroll(hWnd, (*piPos) = Min((*piPos), iMax), iMax);
524: } else { /* Disable the scroll bar, we no longer need it */
525: if (fNeeded) {
526: DisableSB(hWnd);
527: UpdateOff((*pc), hWnd);
528: UpdateFrame(flScroll);
529: UpdateOn((*pc), hWnd);
530: }
531: }
532: }
533:
534: void AvioLargeFont(BOOL fLargeFont) {
535: static BOOL fFirst = TRUE; // Need to init?
536: static LONG lSmallHt, lSmallWd, lLargeHt, lLargeWd; // Font sizes
537: SWP swp;
538:
539: if (fFirst) {
540: /*
541: The first time through, get the small and large font sizes
542: */
543: DevQueryCaps(hDC, CAPS_CHAR_HEIGHT, 1L, &lLargeHt);
544: DevQueryCaps(hDC, CAPS_CHAR_WIDTH, 1L, &lLargeWd);
545: DevQueryCaps(hDC, CAPS_SMALL_CHAR_HEIGHT, 1L, &lSmallHt);
546: DevQueryCaps(hDC, CAPS_SMALL_CHAR_WIDTH, 1L, &lSmallWd);
547: fFirst = FALSE;
548: }
549: /*
550: Set the character size with VioSetDeviceCellSize
551: */
552: SetCellSize( (SHORT) (lChHeight = ((fLargeFont) ? lLargeHt : lSmallHt)),
553: (SHORT) (lChWidth = ((fLargeFont) ? lLargeWd : lSmallWd)) );
554: /*
555: Compute maximum size of client area
556: */
557: cxMaxClient = (cxChPS * (SHORT) lChWidth);
558: cxMaxFrame = cxMaxClient + (SHORT) cxConstant;
559: cyMaxClient = (cyChPS * (SHORT) lChHeight);
560: cyMaxFrame = cyMaxClient + (SHORT) cyConstant;
561: /*
562: Send a WM_ADJUSTFRAMEPOS message
563: */
564: WinQueryWindowPos(hWndFrame, &swp);
565: if (swp.fs & SWP_MAXIMIZE) {
566: AvioMinMax(&swp);
567: WinSetMultWindowPos(hWndFrame, &swp, 1);
568: } else {
569: swp.fs = SWP_ACTIVATE | SWP_MOVE | SWP_SHOW | SWP_SIZE;
570: WinSetWindowPos(hWndFrame, NULL, swp.x, swp.y,
571: Min(cxMaxFrame, swp.cx), Min(cyMaxFrame, swp.cy), swp.fs);
572: }
573: AvioAdjustFramePos(&swp); /* Fix up the frame, scroll bars */
574: AvioPaint(hWndClient); /* Repaint with new characters */
575: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.