home *** CD-ROM | disk | FTP | other *** search
- This file describes changes required to the Turbo Professional TPWINDOW unit
- (version 4.00 or 4.01) in order to add capabilities for "exploding windows."
- Exploding windows are those which start small and quickly grow to their full
- size on screen. When such a window is erased from the screen, it shrinks
- gradually away to nothing.
-
- Special thanks to David Gerrold, who significantly improved the aesthetics of
- the original exploding windows by making them start from a smaller box and
- grow more smoothly to their final size. This version incorporates his changes.
-
- Turbo Professional is a commercial library of 400 procedures and functions for
- Turbo Pascal 4.0. Contact TurboPower Software at 408-438-8608 for more
- information about this product. You must already own Turbo Professional in
- order for this file to be of much use.
-
- To use this file, print it out or read it into a multi-file text editor while
- you edit the TPWINDOW.PAS source file. Then follow the directions below to
- modify your copy of TPWINDOW. Once the edits are made you should be able to
- recompile the TPWINDOW unit.
-
- The changes made here are transparent to the calling program. That is,
- existing programs will continue to work unchanged. To activate exploding
- windows, set the boolean constant Explode to True prior to calling MakeWindow.
- You can have a mixture of exploding and normal windows by changing the value
- of Explode to the desired value prior to calling MakeWindow each time.
-
- You can also modify the constant ExplodeDelay, which specifies the number of
- milliseconds delay per stage of the explosion. The default value of 15 ms
- seemed right to us, but you may prefer a shorter or longer value.
-
- Also, you can change the constant SoundFlagW to enable sound effects while
- windows explode and implode. The example program demonstrates this -- give it
- a try!
-
- Generally, the parameters SaveWindow and ClearWindow that are passed to
- MakeWindow should be False when exploding windows are in use. A side effect of
- exploding windows is to clear the window when it explodes. Setting SaveWindow
- to True thus effectively disables exploding windows. The DrawFrame parameter
- to MakeWindow may be either True or False when using exploding windows.
-
- A demonstration program, DEMO.PAS, is also supplied with this file. Once
- you've modified TPWINDOW, compile DEMO.PAS to see how the explosions and
- implosions look and feel.
-
- This file also incorporates additional changes to TPWINDOW, including a new
- routine (SelectTopWindow) that allows "no-flash" selection of tiled windows.
-
- ************************************************************************
-
- Modifications to TPWINDOW.PAS source code
-
- I + in the left hand margin means to insert a new line
- D - in the left hand margin means to delete existing line
- Surrounding lines are shown for reference
-
- ************************************************************************
- Starting at line 1
-
- {$S-,R-,I-,V-,B-}
-
- I + {Deactivate the following define if exploding windows are not desired.
- I + Saves about 2200 bytes of code space which cannot be removed by the
- I + Turbo smart linker.}
- I + {$DEFINE ExplodingWindows}
-
- ************************************************************************
- Starting around line 16
-
- uses
- TPCrt;
- I +
- I + {$IFDEF ExplodingWindows}
- I + const
- I + Explode : Boolean = False; {True to make exploding windows}
- I + ExplodeDelay : Word = 15; {Milliseconds per stage of explosion}
- I + SoundFlagW : Boolean = True; {True to make sound during explosions}
- I + {$ENDIF}
-
- ************************************************************************
- Starting around line 48
-
- function SetTopWindow(W : WindowPtr) : Boolean;
- {-Put already active window on top of stack, returning true if successful}
- I +
- I + function SelectTopWindow(W : WindowPtr) : Boolean;
- I + {-Make an already active, tiled window the current one}
- I +
- I + function SelectTiledWindow(W : WindowPtr) : Boolean;
- I + {-Display or reselect (tiled) window}
-
- ************************************************************************
- Starting around line 59
-
- implementation
-
- type
- D - BufferArray = array[1..MaxInt] of Char; {Will hold screen image}
- I + BufferArray = array[0..MaxInt] of Char; {Will hold screen image}
-
- ************************************************************************
- Starting around line 87
-
- HeaderP : ^string; {Stores frame title, nil if none}
- I + {$IFDEF ExplodingWindows}
- I + Exploding : Boolean; {True if window displays and erases in stages}
- I + ExploDelay : Word; {Milliseconds per stage of explosion}
- I + {$ENDIF}
- end;
-
- ************************************************************************
- Starting around line 268
-
- {Initialize remaining fields}
- I + WAttr := MapColor(WindowAttr);
- I + HAttr := MapColor(HeaderAttr);
- I + if (XHigh-XLow < 2) or (YHigh-YLow < 2) then
- I + DrawFrame := False;
- if DrawFrame then begin
- {Correct for size of frame}
-
- ************************************************************************
- Starting around line 276
-
- {Store current frame array}
- Frame := FrameChars;
- I + FAttr := MapColor(FrameAttr);
- end else begin
-
- ************************************************************************
- Starting around line 282
-
- YH := YHigh;
- D - Frame := #0#0#0#0#0#0;
- I + Frame := ' ';
- I + FAttr := WAttr;
- end;
-
- ************************************************************************
- Starting around line 287
-
- YH1 := YHigh;
- D - WAttr := MapColor(WindowAttr);
- D - FAttr := MapColor(FrameAttr);
- D - HAttr := MapColor(HeaderAttr);
- I + {Make sure window coordinates are legal}
- I + if (XL > XH) or (YL > YH) then begin
- I + DisposeWindow(W);
- I + Exit;
- I + end;
- Framed := DrawFrame;
-
- ************************************************************************
- Starting around line 295
-
- DisplayedOnce := False;
-
- I + {$IFDEF ExplodingWindows}
- I + {Initialize for exploding windows}
- I + if (XH1-XL1 < 2) and (YH1-YL1 < 2) then
- I + Exploding := False
- I + else
- I + Exploding := Explode;
- I + ExploDelay := ExplodeDelay;
- I + {$ENDIF}
- I +
- {Store cursor information for this window}
-
- ************************************************************************
- Starting around line 305
- Add all of the following routines immediately after the MakeWindow function.
- The new routines are not interfaced.
-
- {$IFDEF ExplodingWindows}
- procedure ClearRegion(XL, YL, XH, YH, Attr : Byte);
- {-Clear a region with specified attribute}
- var
- WordsPerRow, Row : Word;
- Span : string;
- begin
- WordsPerRow := Succ(XH-XL);
- Span[0] := Chr(WordsPerRow);
- FillChar(Span[1], WordsPerRow, ' ');
- for Row := YL to YH do
- FastWrite(Span, Row, XL, Attr);
- end;
-
- procedure SetDeltas(var SD, BD : Real; var Frames : Integer);
- {-Compute dimensions for exploding frame}
- begin
- Frames := Round(BD);
- if SD < 1.0 then
- SD := 1.0/Succ(Frames);
- SD := SD/BD;
- BD := 1.0;
- end;
-
- procedure ComputeDeltas(W : WindowPtr;
- var XD, YD : Real;
- var Frames : Integer);
- {-Compute information for exploding frame boundaries}
- begin
- with WindowP(W)^ do begin
- XD := Succ(XH1-XL1)/2.0-0.55; {Fudge factor}
- YD := Succ(YH1-YL1)/2.0-0.55;
- if XD < YD then
- SetDeltas(XD, YD, Frames)
- else
- SetDeltas(YD, XD, Frames);
- end;
- end;
-
- procedure ExplodeWindow(W : WindowPtr);
- {-Explode a window}
- var
- XD, YD, dX, dY : Real;
- Frames, F : Integer;
- cXL, cXH, cYL, cYH : Byte;
- begin
- with WindowP(W)^ do begin
- {Compute the smallest frame that will fit}
- ComputeDeltas(W, XD, YD, Frames);
- {Draw a series of frames}
- FrameChars := Frame;
- F := Pred(Frames);
- while F >= 0 do begin
- {Erase region}
- dX := F*XD;
- dY := F*YD;
- cXL := Trunc(XL1+dX);
- cYL := Trunc(YL1+dY);
- cXH := Round(XH1-dX);
- cYH := Round(YH1-dY);
- ClearRegion(cXL, cYL, cXH, cYH, WAttr);
- if Framed then
- {Draw frame around window}
- FrameWindow(cXL, cYL, cXH, cYH, FAttr, FAttr, '');
- {Make a sound}
- if SoundFlagW then
- Sound(1320-F*35);
- if (Frames > 10) and (F > 1) then
- {Use only half the frames for big windows}
- Dec(F);
- Dec(F);
- Delay(ExploDelay);
- end;
- NoSound;
- end;
- end;
-
- procedure RestoreRect(W : WindowPtr; XLc, YLc, XHc, YHc : Byte);
- {-Restore a rectangular screen chunk from the Covers buffer}
- var
- fBPR, cBPR, R : Byte;
- fOfs, cOfs : Word;
- begin
- with WindowP(W)^ do begin
- {Get the bytes per row in full window and in chunk}
- fBPR := 2*Succ(XH1-XL1);
- cBPR := Succ(XHc-XLc);
- {Get the first address to use in the Covers buffer}
- fOfs := fBPR*(YLc-YL1)+2*(XLc-XL1);
- {Get the first address on the screen to restore}
- cOfs := 2*(CurrentWidth*Pred(YLc)+Pred(XLc));
- {Restore row by row}
- for R := YLc to YHc do begin
- MoveScreen(Covers^[fOfs], MemW[VideoSegment:cOfs], cBPR);
- Inc(fOfs, fBPR);
- Inc(cOfs, 2*CurrentWidth);
- end;
- end;
- end;
-
- procedure ImplodeWindow(W : WindowPtr);
- {-Erase an exploding window from the screen}
- var
- XD, YD, dX, dY : Real;
- Frames, F : Integer;
- pXL, pXH, pYL, pYH : Byte;
- cXL, cXH, cYL, cYH : Byte;
- begin
- with WindowP(W)^ do begin
- {Compute the smallest frame that will fit}
- ComputeDeltas(W, XD, YD, Frames);
- {Restore underlying screen in stages}
- pXL := XL1;
- pXH := XH1;
- pYL := YL1;
- pYH := YH1;
- FrameChars := Frame;
- F := 1;
- while F < Frames do begin
- dX := F*XD;
- dY := F*YD;
- cXL := Trunc(XL1+dX);
- cYL := Trunc(YL1+dY);
- cXH := Round(XH1-dX);
- cYH := Round(YH1-dY);
- if YL1 <> YH1 then begin
- RestoreRect(W, pXL, pYL, pXH, cYL);
- RestoreRect(W, pXL, cYH, pXH, pYH);
- end;
- if XL1 <> XH1 then begin
- RestoreRect(W, pXL, cYL, cXL, cYH);
- RestoreRect(W, cXH, cYL, pXH, cYH);
- end;
- if Framed then
- {Draw frame around window}
- FrameWindow(cXL, cYL, cXH, cYH, FAttr, HAttr, '');
- pXL := cXL;
- pXH := cXH;
- pYL := cYL;
- pYH := cYH;
- if SoundFlagW then
- {Make a sound}
- Sound(1320-F*35);
- if (Frames > 10) and (F < Frames-2) then
- {Use only half the frames for big windows}
- Inc(F);
- Inc(F);
- Delay(ExploDelay);
- end;
- {Assure core is restored}
- RestoreWindow(XL1, YL1, XH1, YH1, False, Pointer(Covers));
- NoSound;
- end;
- end;
- {$ENDIF}
-
- procedure SetCurrentWindow(W : WindowPtr);
- {-Set the parameters for the current window}
- begin
- with WindowP(W)^ do begin
- Window(XL, YL, XH, YH);
- GoToXY(CursorX, CursorY);
- SetCursorSize(CStart, CEnd);
- CurrentWindow := W;
- end;
- end;
-
- procedure SaveCurrentWindow(W : WindowPtr);
- {-Save state of current window}
- begin
- with WindowP(W)^ do
- GetCursorInfo(CStart, CEnd, CursorX, CursorY, Clear);
- end;
-
- ************************************************************************
- Starting around line 328
-
- Fr := FrameChars;
- end;
- D - end else with WindowP(CurrentWindow)^ do
- I + end else
- {Save current window settings}
- D - GetCursorInfo(CStart, CEnd, CursorX, CursorY, False);
- I + SaveCurrentWindow(CurrentWindow);
-
- {Set the default text attribute}
-
- ************************************************************************
- Starting around line 343
-
- if Save and DisplayedOnce then
- {Previous image of window available to restore}
- RestoreWindow(XL1, YL1, XH1, YH1, False, Pointer(Holds))
- else begin
- {No previous image to restore}
- D - if Clear then
- D - {Clear the window}
- D - ClrScr;
- I + {$IFDEF ExplodingWindows}
- I + if Exploding then
- I + ExplodeWindow(W);
- I + {$ENDIF}
- if Framed then begin
- {Draw frame around window}
- FrameChars := Frame;
- FrameWindow(XL1, YL1, XH1, YH1, FAttr, HAttr, StringFromHeap(HeaderP));
- end;
- I + if Clear then
- I + {Clear the window}
- I + ClrScr;
- end;
-
- {Set the cursor for this window}
- D - GoToXY(CursorX, CursorY);
- D - SetCursorSize(CStart, CEnd);
- I + SetCurrentWindow(W);
-
- Active := True;
-
- ************************************************************************
- Starting around line 378
-
- with WindowP(CurrentWindow)^ do begin
- if Save then
- {Save what window currently holds}
- if SaveWindow(XL1, YL1, XH1, YH1, False, Pointer(Holds)) then ;
- {Save cursor information}
- GetCursorInfo(CStart, CEnd, CursorX, CursorY, not(Save));
- I + {$IFDEF ExplodingWindows}
- I + if Exploding then
- I + ImplodeWindow(CurrentWindow)
- I + else
- I + {$ENDIF}
- {Restore screen}
- RestoreWindow(XL1, YL1, XH1, YH1, False, Pointer(Covers));
- Active := False;
- end;
-
- ************************************************************************
- Starting around line 469
- Add the following two routines immediately after the SetTopWindow function.
-
- function SelectTopWindow(W : WindowPtr) : Boolean;
- {-Make an already active, tiled window the current one}
- var
- TempStack : WindowStackP;
- U, V : WindowPtr;
- begin
- SelectTopWindow := False;
- if (W = nil) or not WindowIsActive(W) then
- Exit;
- if CurrentWindow <> W then begin
- {Save the state of the current window}
- SaveCurrentWindow(CurrentWindow);
- {Remove windows from stack until desired window is taken off}
- TempStack := nil;
- repeat
- V := WindowStack^.Top;
- U := PopStack(WindowStack);
- if V <> W then
- if not PushStack(TempStack, V) then
- Exit;
- until V = W;
- {Put remaining windows back on stack}
- V := TempStack^.Top;
- while V <> nil do begin
- if not PushStack(WindowStack, V) then
- Exit;
- V := PopStack(TempStack);
- end;
- {Put desired window on top of stack}
- if not PushStack(WindowStack, W) then
- Exit;
- {Select the desired window for writing}
- TextAttr := WindowP(W)^.WAttr;
- SetCurrentWindow(W);
- end;
- SelectTopWindow := True;
- end;
-
- function SelectTiledWindow(W : WindowPtr) : Boolean;
- {-Display or reselect tiled window}
- begin
- if WindowIsActive(W) then
- SelectTiledWindow := SelectTopWindow(W)
- else
- SelectTiledWindow := DisplayWindow(W);
- end;
-
- ************************************************************************
- That's all, folks.