'===========================================================================
' Subject: SPLIT/MERGE TEXT SCREEN FOR QB     Date: 01-12-98 (16:22)       
'  Author: The ABC Programmer                 Code: QB, QBasic, PDS        
'  Origin: voxel@freenet.edmonton.ab.ca     Packet: TEXT.ABC
'===========================================================================
'====================[ Split/Merge Text Screen]=====================
' Creates a neat split/merge effect to change text screens.
' Programmed by William Yu  (100% Public Domain) for QB/QBasic/PDS
'
' Not as speedy as the PB version (check January 1998 ABC Packet)
' If nothing else, this source code simulates the PEEK$/POKE$
' found in PB.  Check Peek$/PokeIt for the routines.
'===================================================================

DEFINT A-Z
DECLARE SUB DrawBox (X%, Y%, XX%, YY%, C%, BC%, Solid%, CharSet%)
DECLARE SUB SplitScreen (Scr1() AS STRING, Scr$)
DECLARE SUB MergeScreen (Scr1() AS STRING)
DECLARE FUNCTION Peek$ (Address%, Length%)
DECLARE SUB PokeIt (Address%, ScrImg AS STRING)

CONST Height = 25   '' Works for ANY Height, too bad you don't have that many.

DIM Scr1(1 TO Height) AS STRING
DIM Scr2(1 TO Height) AS STRING

WIDTH 80, Height
DEF SEG = &HB800   '' Works fine with Monochrome as well (&HB000)
SCREEN 0, 0, 0, 1

FOR N = 0 TO Height * 160 STEP 160     '' Create some random characters
  PokeIt N, STRING$(160, CHR$(RND * 255))
NEXT N
DrawBox 1, 1, 40, INT(Height / 2), 11, 5, 0, 2
DrawBox 3, 2, 38, INT(Height / 2) - 1, 11, 5, 1, 2
DrawBox 41, 1, 80, INT(Height / 2), 11, 5, 0, 2
DrawBox 1, INT(Height / 2) + 1, 40, Height - 1, 11, 5, 0, 2
DrawBox 41, INT(Height / 2) + 1, 80, Height - 1, 11, 5, 0, 2
LOCATE 5, 10: COLOR 15: PRINT "Hello World!"
Screen1$ = Peek$(0, Height * 160)      '' Save entire screen as String
FOR N = 1 TO Height
  Scr2(N) = Peek$((N - 1) * 160, 160)   '' Save entire screen to Array
NEXT N

DrawBox 1, 1, 40, INT(Height / 2), 15, 1, 1, 1     '' Create another screen
DrawBox 3, 2, 38, INT(Height / 2) - 1, 11, 3, 1, 1
DrawBox 41, 1, 80, INT(Height / 2), 15, 1, 1, 1
DrawBox 1, INT(Height / 2) + 1, 40, Height - 1, 15, 1, 1, 1
DrawBox 41, INT(Height / 2) + 1, 80, Height - 1, 15, 1, 1, 1
Screen2$ = Peek$(0, Height * 160)
FOR N = 1 TO Height
  Scr1(N) = Peek$((N - 1) * 160, 160)  '' Save it
NEXT N

I = 0
DO                                     '' The loop
  IF I = 0 THEN
    SplitScreen Scr1(), Screen1$
    MergeScreen Scr2()
  ELSE
    SplitScreen Scr2(), Screen2$
  END IF
  I = NOT I
LOOP UNTIL INKEY$ <> ""


END

SUB DrawBox (X%, Y%, XX%, YY%, C%, BC%, Solid%, CharSet%)
'' Routine to draw a simple 2D box.

 IF CharSet% = 1 THEN
   Char1$ = "Ú"
   CharHoz$ = "Ä"
   Char2$ = "¿"
   CharVert$ = "³"
   Char3$ = "À"
   Char4$ = "Ù"
 ELSE
   Char1$ = "É"
   CharHoz$ = "Í"
   Char2$ = "»"
   CharVert$ = "º"
   Char3$ = "È"
   Char4$ = "¼"
 END IF

 COLOR C%, BC%
 A = (XX% - X%) - 1
 LOCATE Y%, X%: PRINT Char1$; STRING$(A, CharHoz$); Char2$
 FOR I = Y% + 1 TO YY% - 1
   LOCATE I, X%: PRINT CharVert$;
   IF Solid% THEN PRINT SPACE$(A);
   LOCATE I, XX%: PRINT CharVert$;
 NEXT I
 LOCATE YY%, X%: PRINT Char3$; STRING$(A, CharHoz$); Char4$;
END SUB

SUB MergeScreen (Scr1() AS STRING)
''====================================================================
'' Inputs: Src1() is the screen image that you want to merge.
''
'' Basically just a reverse of SplitScreen, still a mess :)
''--------------------------------------------------------------------
M = Height - (Height MOD 2) - 1'' What?  Cool eh? <g>
HalfH = INT(Height / 2) - 1
K = 1
PCOPY 0, 1
DO
  X = 0
  T! = TIMER
  FOR N = 1 + (HalfH - K) TO HalfH
    PokeIt X * 160, MID$(Scr1(N + 1), M, 78 - (M - 3))
    PokeIt X * 160 + 82 + M - 3, MID$(Scr1(N + 1), 81, 78 - (M - 3))
    CALL PokeIt((X + HalfH + 2 + (HalfH - K)) * 160, MID$(Scr1(X + HalfH + 2), M, 78 - (M - 3)))
    CALL PokeIt((X + HalfH + 2 + (HalfH - K)) * 160 + 82 + M - 3, MID$(Scr1(X + HalfH + 2), 81, 78 - (M - 3)))
    X = X + 1
  NEXT N
  PCOPY 0, 1
  'DO: LOOP UNTIL TIMER - T! > .01
  M = M - 2
  K = K + 1
LOOP UNTIL M < 0
END SUB

FUNCTION Peek$ (Address%, Length%)
  DEF SEG = &HB800
  A$ = ""
  FOR I = Address% TO (Address% + Length% - 1)
    A$ = A$ + CHR$(PEEK(I))
  NEXT I
  Peek$ = A$
END FUNCTION

SUB PokeIt (Address%, ScrImg AS STRING)
  DEF SEG = &HB800
  N = 0
  FOR I = Address% TO (Address% + LEN(ScrImg) - 1)
    N = N + 1
    POKE I, ASC(MID$(ScrImg, N, 1))
  NEXT I
END SUB

SUB SplitScreen (Scr1() AS STRING, Scr$)
''====================================================================
'' Inputs: Src1() is the current screen image that you want to split.
''         Scr$ is the saved screen you wish to reveal.
''--------------------------------------------------------------------
M = 1
HalfH = INT(Height / 2) - 1
K = HalfH
PCOPY 0, 1
DO
  X = 0
  T! = TIMER
  PokeIt 0, Scr$ 'Perhaps not the best approach, but I'm lazy, this will do.
                'my original plan was to... eh, nevermind.
  FOR N = 1 + (HalfH - K) TO HalfH
    ''Hmmmm, why try to understand?  Just marvel that it actually works. :)
    PokeIt X * 160, MID$(Scr1(N + 1), M, 78 - (M - 3))
    PokeIt X * 160 + 82 + M - 3, MID$(Scr1(N + 1), 81, 78 - (M - 3))
    CALL PokeIt((X + HalfH + 2 + (HalfH - K)) * 160, MID$(Scr1(X + HalfH + 2), M, 78 - (M - 3)))
    CALL PokeIt((X + HalfH + 2 + (HalfH - K)) * 160 + 82 + M - 3, MID$(Scr1(X + HalfH + 2), 81, 78 - (M - 3)))
    X = X + 1
  NEXT N
  PCOPY 0, 1
  'DO: LOOP UNTIL TIMER - T! > .01'' oooh look, precision timing
  M = M + 4
  K = K - 1
LOOP UNTIL K < 0 OR M > 81
END SUB
