|
|
1.1 root 1: /*
2: avio.c -- AVIO handling routines
3: For a cleaner implementation, look at the BROWSE application.
4:
5: Implements scrollbars, sets up an AVIO Presentation Space
6: Intrinsically linked with a circular queue routine
7:
8: Created by Microsoft Corporation, 1989
9: */
10:
11: #define INCL_AVIO
12: #define INCL_DEV
13: #define INCL_VIO
14: #define INCL_WIN
15: #include <os2.h>
16: #include "global.h"
17: #include "circleq.h" /* Get Circular Buffer routines */
18: #include "avio.h" /* Prototype our routines */
19: #include <stdio.h> /* Needed to open LOG file */
20: /*
21: Constants
22: */
23: #define AVIO_PS_ROWS 25 /* Dimensions of the AVIO PS */
24: #define AVIO_PS_COLUMNS MAXLINELEN
25: #define CATTRBYTES 1 /* 1 or 3 attribute bytes/cell */
26: #define DEFPAGEWIDTH 5 /* Default pagesizes */
27: #define DEFPAGEHEIGHT 5
28:
29: char Blank[2] = { 0x20, 0x07 };
30:
31: /*
32: Macros to make the code more readable
33: */
34: /* Upper and Lower Bound Calculations */
35: #define Abs(a) (((a) > 0) ? (a) : (-(a)))
36: #define LowerBound(pos, disp, lbound) Max(pos - disp, lbound)
37: #define UpperBound(pos, disp, ubound) Min(pos + disp, ubound)
38:
39: /* Scroll Bar Abbreviations */
40:
41: #define DisableSB(hSB) WinSetParent(hSB, HWND_OBJECT, FALSE)
42: #define EnableSB(hSB) WinSetParent(hSB, hWndSBParent, FALSE)
43: #define HBarHeight() (fNeedHorz ? lHSBHeight : 0L)
44: #define VBarWidth() (fNeedVert ? lVSBWidth : 0L)
45: #define SetScroll(h, pos, max) \
46: WinSendMsg(h, SBM_SETSCROLLBAR, MPFROM2SHORT(pos, 0), MPFROM2SHORT(0, max))
47: #define UpdateFrame(sb) \
48: WinSendMsg(hWndSBParent, WM_UPDATEFRAME, MPFROMLONG(sb), 0L)
49: #define UpdateOff(w) WinEnableWindowUpdate(w, FALSE)
50: #define UpdateOn(w) WinEnableWindowUpdate(w, TRUE)
51:
52: /* Scrolling Macros */
53: #define ClearScreen() ScrollUp(-1)
54: #define ScrollDown(n) VioScrollDn(0, 0, -1, -1, n, Blank, hVPS)
55: #define ScrollUp(n) VioScrollUp(0, 0, -1, -1, n, Blank, hVPS)
56: #define SetCursor(x, y) VioSetCurPos((USHORT) x, (USHORT) y, hVPS)
57:
58: /* Miscellaneous */
59: /*
60: If partial ANSI emulation is desired, use:
61: VioSetCurPos((USHORT) x, (USHORT) y, hVPS); \
62: VioWrtTTY(l->szText, l->cch, hVPS)
63: */
64: #define Blast(l, x, y) VioWrtCharStr(l->szText, l->cch, x, y, hVPS)
65: /*
66: Calculate the number of characters in a page
67: For nicer behavior, you can do rounding here
68: */
69: #define CalcChars(pPg, pCh, default) \
70: ((pCh) ? (Max((int) ((pPg) / ((SHORT) pCh)), 0)) : (default))
71: #define Value(value) WinQuerySysValue(HWND_DESKTOP, value)
72: /*
73: File-Local Variables
74: */
75: HDC hDC; /* Device Context */
76: HVPS hVPS; /* Virtual PS */
77: int iTopLine; /* PS Line of window corner */
78: int iCurCol; /* Current column of window corner */
79: int cchPgWidth; /* Width and height of our window */
80: int cchPgHeight;
81: int cchMaxHorz; /* Scroll bar upper bounds */
82: int cchMaxVert;
83: BOOL fNeedHorz; /* Do we need the scroll bars or not? */
84: BOOL fNeedVert;
85: HWND hWndHScroll; /* Window handles of ScrollBar windows */
86: HWND hWndVScroll;
87: HWND hWndSBParent; /* Could mooch off the value in main(), but won't */
88: /*
89: Measurements used to help make the window look nice
90: */
91: LONG lChWidth, lChHeight; /* Character size */
92: LONG lHSBHeight, lVSBWidth; /* Scrollbar measurements */
93: LONG lMiscWidth, lMiscHeight; /* Border, titlebar, ... */
94: int iMaxWidth, iMaxHeight; /* Client area bounds */
95: int iMaxFrameWidth, iMaxFrameHeight; /* Frame window bounds */
96: BOOL fCreated; /* AVIO PS created */
97: int rc; /* Return code */
98: VIOCURSORINFO vci;
99: /*
100: Local prototypes
101: */
102: void GetMeasurements(void);
103: void Update(USHORT, USHORT, USHORT, BOOL);
104: void Refresh(BOOL);
105: void WantCursor(BOOL);
106: void SetScrollPos(void);
107: void SetScrollPosHorz(void);
108: void SetScrollPosVert(void);
109: /*
110: The actual routines
111: */
112: void GetMeasurements(void) {
113: /*
114: Get display parameters
115: */
116: /*
117: Scroll bar widths and heights
118: */
119: lHSBHeight = Value(SV_CYHSCROLL);
120: lVSBWidth = Value(SV_CXVSCROLL);
121: /*
122: Non-PS widths and heights
123: */
124: lMiscHeight = (Value(SV_CYSIZEBORDER) << 1) /* A border on each side */
125: + Value(SV_CYTITLEBAR) /* The title bar... */
126: + Value(SV_CYMENU) /* ...and the menu bar */
127: + Value(SV_CYBYTEALIGN); /* ...and alignment */
128:
129: lMiscWidth = (Value(SV_CXSIZEBORDER) << 1);/* A border on each side */
130: /*
131: Height and width of characters
132: */
133: rc = DevQueryCaps(hDC, CAPS_CHAR_HEIGHT, 1L, &lChHeight);
134: rc = DevQueryCaps(hDC, CAPS_CHAR_WIDTH, 1L, &lChWidth);
135: /*
136: Compute size of client and frame windows
137: */
138: iMaxWidth = (AVIO_PS_COLUMNS * (int) lChWidth);
139: iMaxHeight = (AVIO_PS_ROWS * (int) lChHeight);
140: iMaxFrameWidth = (iMaxWidth + (int) lMiscWidth);
141: iMaxFrameHeight = (iMaxHeight + (int) lMiscHeight);
142: /*
143: Compute cursor attributes
144: */
145: vci.yStart = (USHORT) 0;
146: vci.cEnd = (USHORT) lChHeight - 1;
147: vci.cx = 0;
148: }
149:
150: void AvioInit(HWND hWndFrame, HWND hWndClient) {
151: /*
152: Initialize Presentation Space, Device Context, Scroll Bars
153: */
154: /*
155: Create the AVIO Presentation Space
156: */
157: hDC = WinOpenWindowDC(hWndClient);
158: VioCreatePS(&hVPS, AVIO_PS_ROWS, AVIO_PS_COLUMNS, 0, CATTRBYTES, 0);
159: VioAssociate(hDC, hVPS);
160: fCreated = TRUE;
161: /*
162: Turn on the cursor and home it
163: */
164: WantCursor(TRUE);
165: SetCursor(0, 0);
166: /*
167: Snag scroll bar info
168: */
169: hWndHScroll = WinWindowFromID(hWndFrame, FID_HORZSCROLL);
170: hWndVScroll = WinWindowFromID(hWndFrame, FID_VERTSCROLL);
171: hWndSBParent = WinQueryWindow(hWndHScroll, QW_PARENT, FALSE);
172: fNeedHorz = fNeedVert = TRUE;
173: /*
174: Get character height in pixels, etc...
175: */
176: GetMeasurements();
177: }
178:
179: void AvioStartup(HWND hWndClient) {
180: SWP swp;
181: /*
182: Initialize the queue
183: */
184: QueInit();
185: /*
186: Initialize the screen
187: */
188: ClearScreen();
189: WinQueryWindowPos(hWndClient, &swp);
190: AvioSize(hWndClient, WM_NULL, NULL, MPFROM2SHORT(swp.cx, swp.cy));
191: }
192:
193: void AvioScroll(USHORT SB_Command, USHORT usPosition, BOOL fHorizontal) {
194: /*
195: Process the scroll bar messages
196:
197: These routines are symmetric; in fact, SB_LINELEFT = SB_LINEUP, etc...
198: so one might note that this could be condensed. It's left expanded for
199: speed and clarity. I bound the values each way so that we stay inside
200: the AVIO presentation space.
201: */
202: if (fHorizontal) { /* Horizontal Scroll Bar */
203: switch (SB_Command) {
204: case SB_LINELEFT:
205: iCurCol = LowerBound(iCurCol, 1, 0); break;
206: case SB_LINERIGHT:
207: iCurCol = UpperBound(iCurCol, 1, cchMaxHorz); break;
208: case SB_PAGELEFT:
209: iCurCol = LowerBound(iCurCol, cchPgWidth, 0); break;
210: case SB_PAGERIGHT:
211: iCurCol = UpperBound(iCurCol, cchPgWidth, cchMaxHorz); break;
212: case SB_SLIDERTRACK:
213: iCurCol = (SHORT) usPosition;
214: default: break;
215: }
216: if (SB_Command != SB_SLIDERTRACK)
217: SetScroll(hWndHScroll, iCurCol, cchMaxHorz);
218:
219: } else { /* Vertical Scroll Bar */
220: switch (SB_Command) {
221: case SB_LINEUP:
222: iTopLine = LowerBound(iTopLine, 1, 0); break;
223: case SB_LINEDOWN:
224: iTopLine = UpperBound(iTopLine, 1, cchMaxVert); break;
225: case SB_PAGEUP:
226: iTopLine = LowerBound(iTopLine, cchPgHeight, 0); break;
227: case SB_PAGEDOWN:
228: iTopLine = UpperBound(iTopLine, cchPgHeight, cchMaxVert); break;
229: case SB_SLIDERTRACK:
230: iTopLine = (SHORT) usPosition;
231: default: break;
232: }
233: if (SB_Command != SB_SLIDERTRACK)
234: SetScroll(hWndVScroll, iTopLine, cchMaxVert);
235: }
236: Refresh(FALSE);
237: }
238:
239: MRESULT AvioSize(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
240: /*
241: Do the default AVIO sizing, and kyfe a few values
242: */
243: if (!fCreated) return 0L;
244: /*
245: Compute height and width of page in characters
246:
247: The scrollbars have already been subtracted out,
248: since we are called by the client area.
249: */
250: cchPgHeight = CalcChars(SHORT2FROMMP(mp2), lChHeight, DEFPAGEHEIGHT);
251: cchPgWidth = CalcChars(SHORT1FROMMP(mp2), lChWidth, DEFPAGEWIDTH);
252: /*
253: Adjust scrollbar maximums
254: */
255: cchMaxVert = Max(AVIO_PS_ROWS - cchPgHeight, 0);
256: cchMaxHorz = Max(AVIO_PS_COLUMNS - cchPgWidth, 0);
257: /*
258: Maintain scrollbar integrity
259: */
260: fNeedHorz = (cchMaxHorz > 0);
261: fNeedVert = (cchMaxVert > 0);
262: SetScroll(hWndHScroll, iCurCol = Min(iCurCol, cchMaxHorz), cchMaxHorz);
263: SetScroll(hWndVScroll, iTopLine = Min(iTopLine,cchMaxVert), cchMaxVert);
264: /*
265: Do the Scroll Bar shifting
266: */
267: Refresh(FALSE);
268: /*
269: Now, do the normal AVIO processing
270: */
271: return WinDefAVioWindowProc(hWnd, msg, mp1, mp2);
272: }
273:
274: void Update
275: (USHORT usLineNum, USHORT usHowMany, USHORT usStartLine, BOOL fForced) {
276: /*
277: Updates usHowMany lines starting from usStartLine on screen.
278: Starts at saved line usLineNum. If fForced is set, all lines
279: in range are displayed; otherwise it's lazy.
280: */
281: USHORT i; /* Loop index */
282: USHORT usWhichLine = usLineNum; /* Line to be queried */
283: Line l; /* Line to be output */
284:
285: for (i = usStartLine; i < (usStartLine + usHowMany); i++) {
286: l = QueQuery(usWhichLine++); /* Get the line */
287: if (!l->fDrawn || fForced) {
288: if (l->cch) Blast(l, i, 0); /* Print it out */
289: if (!l->fComplete) SetCursor(i, l->cch);
290: l->fDrawn = TRUE;
291: }
292: }
293: }
294:
295: void Refresh(BOOL fRedraw) {
296: /*
297: fRedraw forces full redraw if set
298: */
299: SHORT sDelta;
300: int static iOldTopLine = -AVIO_PS_ROWS;
301:
302: VioSetOrg(0, iCurCol, hVPS); /* Get the free AVIO horizontal shift */
303: sDelta = iTopLine - iOldTopLine; /* Compute vertical shift */
304: if ((Abs(sDelta) < AVIO_PS_ROWS) && !fRedraw) {
305: if (sDelta < 0) { /* Scroll Up -- make sDelta positive*/
306: ScrollDown(-sDelta);
307: Update(iTopLine, -sDelta, 0, TRUE);
308: } else { /* Scroll Down by sDelta */
309: ScrollUp(sDelta);
310: Update(iTopLine + cchPgHeight - sDelta, sDelta,
311: cchPgHeight - sDelta, TRUE);
312: }
313: } else AvioRedraw(); /* Redo the entire screen */
314: iOldTopLine = iTopLine;
315: }
316:
317: void AvioClose (void) {
318: /*
319: Termination routines
320: */
321: /*
322: Destroy the Presentation Space
323: */
324: VioAssociate(NULL, hVPS);
325: VioDestroyPS(hVPS);
326: fCreated = FALSE;
327: }
328:
329: void AvioPaint(HWND hWnd) {
330: static HPS hPS;
331: static RECTL rcl;
332:
333: hPS = WinBeginPaint(hWnd, NULL, &rcl);
334: VioShowPS(AVIO_PS_ROWS, AVIO_PS_COLUMNS, 0, hVPS);
335: WinEndPaint(hPS);
336: }
337:
338: MRESULT AvioMinMax(PSWP pSWP) {
339: /*
340: Control Maximizing
341: */
342: if (pSWP->fs & (SWP_MAXIMIZE | SWP_RESTORE)) {
343: if (pSWP->fs & SWP_MAXIMIZE) {
344: /*
345: Save cx, cy values for later origin displacement
346: */
347: int iOldcx = pSWP->cx;
348: int iOldcy = pSWP->cy;
349: /*
350: Displace, and change to maximum size
351: */
352: pSWP->x += (iOldcx - (pSWP->cx = iMaxFrameWidth));
353: pSWP->y += (iOldcy - (pSWP->cy = iMaxFrameHeight));
354: }
355: /*
356: Now, fix the scroll bars
357: */
358: AvioAdjustFrame(pSWP);
359: return TRUE;
360: }
361: return FALSE;
362: }
363:
364: void AvioClear(void) { ClearScreen(); }
365:
366: void AvioAdjustFrame(PSWP pSWP) {
367: /*
368: Trap WM_ADJUSTWINDOWPOS messages to the frame with this routine.
369: Keep the window sized right, and control scrollbar visibility.
370: */
371: BOOL fNeededHorz = fNeedHorz;
372: BOOL fNeededVert = fNeedVert;
373: /*
374: Do scrollbar enable/disable calculations (but don't update the screen)
375: */
376: if (pSWP->fs & SWP_MINIMIZE) fNeedHorz = fNeedVert = FALSE;
377: if ((pSWP->cx * pSWP->cy) == 0) return;
378: /*
379: Do we need them?
380: */
381: fNeedVert = (pSWP->cy < (SHORT) (iMaxFrameHeight));
382: fNeedHorz = (pSWP->cx < (SHORT) (iMaxFrameWidth + VBarWidth()));
383: fNeedVert = (pSWP->cy < (SHORT) (iMaxFrameHeight + HBarHeight()));
384: /*
385: Do width calculations to make sure we're staying small enough.
386: The Tracking Rectangle shouldn't allow us to get too big.
387: */
388: /*
389: Check if we're stretching too far
390: */
391: pSWP->cx = Min(pSWP->cx, iMaxFrameWidth + (int) VBarWidth());
392: pSWP->cy = Min(pSWP->cy, iMaxFrameHeight + (int) HBarHeight());
393: /*
394: ...if so, fix, then add them!
395: */
396: AvioSize(NULL, WM_NULL, NULL, MPFROM2SHORT(
397: pSWP->cx - (int) (lMiscWidth + VBarWidth()),
398: pSWP->cy - (int) (lMiscHeight + HBarHeight()) ));
399:
400: if (fNeedHorz) {
401: if (!fNeededHorz) {
402: EnableSB(hWndHScroll);
403: UpdateOff(hWndHScroll);
404: UpdateFrame(FCF_HORZSCROLL);
405: UpdateOn(hWndHScroll);
406: }
407: } else {
408: if (fNeededHorz) {
409: DisableSB(hWndHScroll);
410: UpdateOff(hWndHScroll);
411: UpdateFrame(FCF_HORZSCROLL);
412: UpdateOn(hWndHScroll);
413: }
414: }
415: if (fNeedVert) {
416: if (!fNeededVert) {
417: EnableSB(hWndVScroll);
418: UpdateOff(hWndVScroll);
419: UpdateFrame(FCF_VERTSCROLL);
420: UpdateOn(hWndVScroll);
421: }
422: } else {
423: if (fNeededVert) {
424: DisableSB(hWndVScroll);
425: UpdateOff(hWndVScroll);
426: UpdateFrame(FCF_VERTSCROLL);
427: UpdateOn(hWndVScroll);
428: }
429: }
430: }
431:
432: void AvioTrackFrame(HWND hWnd, MPARAM mpTrackFlags) {
433: /*
434: Takes action on WM_TRACKFRAME message
435: */
436: static TRACKINFO tiTrackInfo;
437: /*
438: Get the tracking information in the TrackInfo structure
439: */
440: WinSendMsg(hWnd, WM_QUERYTRACKINFO, mpTrackFlags, &tiTrackInfo);
441: WinTrackRect(hWnd, NULL, &tiTrackInfo);
442: }
443:
444: void AvioQueryTrackInfo(PTRACKINFO pTI) {
445: /*
446: Forces the frame to be byte aligned and bounded
447: */
448: BOOL fMove;
449: /*
450: Get the grid set up for byte alignment
451:
452: Set cxGrid to half a character width, because sizing
453: from the keyboard tries to move by half characters.
454: Also, make sure we can move the window freely.
455: */
456: fMove = ((pTI->fs & TF_MOVE) == TF_MOVE);
457: pTI->fs |= TF_GRID;
458: pTI->cxGrid = (fMove) ? 1 : ((SHORT) (lChWidth << 1));
459: pTI->cyGrid = (fMove) ? 1 : ((SHORT) lChHeight);
460: /*
461: Bound the frame now
462: */
463: pTI->ptlMinTrackSize.x = (pTI->cxBorder << 1) + lMiscWidth;
464: pTI->ptlMinTrackSize.y = (pTI->cyBorder << 1) + lMiscHeight;
465: pTI->ptlMaxTrackSize.x = iMaxFrameWidth + lVSBWidth + (pTI->cxBorder <<1);
466: pTI->ptlMaxTrackSize.y = iMaxFrameHeight + lHSBHeight + (pTI->cyBorder <<1);
467: }
468:
469: BOOL AvioUpdateLines(BOOL fPage, BOOL *fPaging) {
470: /*
471: Update the display
472: */
473: int cLines;
474:
475: cLines = QueUpdateHead(AVIO_PS_ROWS, fPage, *fPaging);
476: if (cLines == AVIO_PS_ROWS) *fPaging = TRUE;
477: if (cLines > 0) {
478: ScrollUp(cLines);
479: Update(iTopLine + AVIO_PS_ROWS - cLines, cLines,
480: AVIO_PS_ROWS - cLines, TRUE);
481: }
482: Update(iTopLine, cchPgHeight, 0, FALSE);
483: return TRUE;
484: }
485:
486: void AvioRedraw(void) {
487: /*
488: Clear, then redraw the entire Presentation Space
489: */
490: ClearScreen();
491: Update(iTopLine, cchPgHeight, 0, TRUE);
492: }
493:
494: void WantCursor(BOOL fYes) {
495: /*
496: Do the underscore cursor
497: */
498: vci.attr = (USHORT) (fYes ? 0 : -1);
499: vci.yStart = 0;
500: vci.cEnd = (USHORT) lChHeight - 1;
501: vci.cx = 0;
502: VioSetCurType(&vci, hVPS);
503: }
504:
505: void AvioPageUp(void) {
506: /*
507: Execute the Page Up instruction
508: */
509: int cLines;
510:
511: cLines = QuePageUp(AVIO_PS_ROWS);
512: ScrollDown(cLines);
513: Update(iTopLine, cLines, 0, TRUE);
514: }
515:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.