← DL-Pascal collection

cov07.pas

DOWNLOAD ORIGINAL FILE

{ DL-Pascal Coverage Section 7: CRT Unit              }
{ Exercises Write/WriteLn formatting, GotoXY,         }
{ WhereX/Y, Window, WindMin/Max, ClrScr, ClrEol,      }
{ DelLine, InsLine, Cursor, KeyPressed, ReadKey,      }
{ NextKey, Sound, TimerStart/Out, Plot, Line, Point,  }
{ Display, TextDisplay, UpdateRegion.                 }
{ NOTE: interactive tests (Read/ReadKey) are skipped  }
{ to allow unattended profiling run.                  }
{ Expected: runs without error, displays results.     }
{$D-C-R-}

PROGRAM Section7;

USES
   crt;

VAR
  i, j      : Integer;
  x, y      : Byte;
  w         : Word;
  b         : Boolean;
  c         : Char;
  s         : STRING[40];
  log       : Text;

PROCEDURE Check(msg : STRING; passed : Boolean);
BEGIN
  IF passed THEN
    WriteLn(log,'OK   ', msg)
  ELSE
    WriteLn(log,'FAIL ', msg);
END;

{ ---- Write / WriteLn formatting ---- }
PROCEDURE TestWrite;
BEGIN
  { Basic WriteLn }
  WriteLn(log,'TestWrite start');

  { Write without newline then WriteLn }
  Write(log,'ABC'); Write(log,'DEF'); WriteLn(log);
  WriteLn(log,'  above should be ABCDEF');

  { Integer formats }
  WriteLn(log,'Dec: ', 42);
  WriteLn(log,'Neg: ', -7);
  WriteLn(log,'Wid: ', 42:6);       { right-justified width 6 }
  WriteLn(log,'Zero:', 0:4);

  { Real formats }
  WriteLn(log,'Real: ', 3.14159:8:4);  { width 8, 4 decimal places }
  WriteLn(log,'Real: ', -2.5:7:2);
  WriteLn(log,'Sci:  ', 12345.678:12:3);

  { String formats }
  WriteLn(log,'Str:  ', 'Hello':10);  { right-justified }
  WriteLn(log,'Str:  ', 'Hi');

  { Char }
  WriteLn(log,'Char: ', 'A');
  WriteLn(log,'Char: ', Chr(66));   { 'B' }

  { Boolean }
  WriteLn(log,'Bool: ', True);
  WriteLn(log,'Bool: ', False);

  { Multiple items on one line }
  WriteLn(log,'x=', 3, ' y=', 4, ' sum=', 3+4);

  WriteLn(log,'TestWrite done');
END;

{ ---- GotoXY and WhereX/Y ---- }
PROCEDURE TestGotoXY;
BEGIN
  ClrScr;

  { Go to known position and check }
  GotoXY(1, 1);
  x := WhereX; y := WhereY;
  Check('GotoXY 1,1 X',   x = 1);
  Check('GotoXY 1,1 Y',   y = 1);

  GotoXY(5, 2);
  x := WhereX; y := WhereY;
  Check('GotoXY 5,2 X',   x = 5);
  Check('GotoXY 5,2 Y',   y = 2);

  GotoXY(1, 1);
  Write(log,'A');              { cursor moves to col 2 }
  x := WhereX;
  Check('WhereX after write', x = 2);

  { GotoXY out of range — should be ignored }
  GotoXY(5, 2);
  GotoXY(0, 0);            { invalid — no change }
  x := WhereX; y := WhereY;
  Check('GotoXY invalid X', x = 5);
  Check('GotoXY invalid Y', y = 2);

  ClrScr;
  GotoXY(1, 1);
END;

{ ---- Window and WindMin/Max ---- }
PROCEDURE TestWindow;
VAR wx1, wy1, wx2, wy2 : Byte;
BEGIN
  { Full screen window }
  Window(1, 1, 32, 4);
  wx1 := WindMinX; wy1 := WindMinY;
  wx2 := WindMaxX; wy2 := WindMaxY;
  Check('Full win MinX',   wx1 = 1);
  Check('Full win MinY',   wy1 = 1);
  Check('Full win MaxX',   wx2 = 32);
  Check('Full win MaxY',   wy2 = 4);

  { Sub-window }
  Window(5, 2, 20, 3);
  wx1 := WindMinX; wy1 := WindMinY;
  wx2 := WindMaxX; wy2 := WindMaxY;
  Check('Sub win MinX',    wx1 = 5);
  Check('Sub win MinY',    wy1 = 2);
  Check('Sub win MaxX',    wx2 = 20);
  Check('Sub win MaxY',    wy2 = 3);

  { Cursor in sub-window starts at 1,1 }
  GotoXY(1, 1);
  x := WhereX; y := WhereY;
  Check('Win cursor X',    x = 1);
  Check('Win cursor Y',    y = 1);

  { Restore full window }
  Window(1, 1, 32, 4);
  ClrScr;
  GotoXY(1, 1);
END;

{ ---- ClrScr / ClrEol ---- }
PROCEDURE TestClr;
BEGIN
  ClrScr;
  GotoXY(1, 1);
  WriteLn(log,'Line one');
  WriteLn(log,'Line two');
  Write(log,'Line thr');

  { ClrEol clears from cursor to end of line }
  GotoXY(5, 3);
  ClrEol;

  { After ClrEol cursor should stay at same position }
  x := WhereX; y := WhereY;
  Check('ClrEol X',   x = 5);
  Check('ClrEol Y',   y = 3);

  ClrScr;

  { After ClrScr cursor at 1,1 }
  x := WhereX; y := WhereY;
  Check('ClrScr X',   x = 1);
  Check('ClrScr Y',   y = 1);

  GotoXY(1, 1);
END;

{ ---- DelLine / InsLine ---- }
PROCEDURE TestDelInsLine;
BEGIN
  ClrScr;
  GotoXY(1, 1); WriteLn(log,'Row 1');
  GotoXY(1, 2); WriteLn(log,'Row 2');
  GotoXY(1, 3); WriteLn(log,'Row 3');
  GotoXY(1, 4); Write(log,'Row 4');

  { Delete line 1 — rows 2,3,4 move up }
  GotoXY(1, 1);
  DelLine;
  x := WhereX; y := WhereY;
  Check('DelLine Y',   y = 1);

  { InsLine insert blank line at cursor, rows below move down }
  GotoXY(1, 2);
  InsLine;
  x := WhereX; y := WhereY;
  Check('InsLine Y',   y = 2);

  ClrScr;
  GotoXY(1, 1);
END;

{ ---- Cursor ---- }
PROCEDURE TestCursor;
BEGIN
  { Turn cursor off }
  Cursor(False);
  { Write while cursor off should work normally }
  GotoXY(1, 1);
  Write(log,'Cursor off test   ');

  { Turn cursor back on }
  Cursor(True);
  Write(log,'Cursor on         ');
  WriteLn(log);
  Check('Cursor on/off',  True);  { just exercises the code path }

  Cursor(False);  { turn off for rest of tests }
END;

{ ---- Sound ---- }
PROCEDURE TestSound;
BEGIN
  { Play a few tones — exercises sound ROM routines }
  Sound(440, 50);   { A4 }
  Sound(523, 50);   { C5 }
  Sound(659, 50);   { E5 }
  Sound(880, 50);   { A5 }
  Check('Sound A4',   True);
  Check('Sound C5',   True);
  Check('Sound E5',   True);
  Check('Sound A5',   True);

  { Very low frequency }
  Sound(100, 30);
  Check('Sound low',  True);

  { Scale }
  FOR i := 1 TO 8 DO BEGIN
    Sound(200 * i, 40);
  END;
  Check('Sound scale', True);
END;

{ ---- TimerStart / TimerOut ---- }
PROCEDURE TestTimer;
VAR counter : Word;
BEGIN
  { Timer 0: 1 second (10 ticks at 10Hz) }
  counter := 0;
  TimerStart(0, 10);
  WHILE NOT TimerOut(0) DO BEGIN
    Inc(counter);
  END;
  Check('Timer0 fired',   TimerOut(0));
  Check('Timer0 counted', counter > 0);

  { Timer 1: very short (1 tick) }
  TimerStart(1, 1);
  REPEAT UNTIL TimerOut(1);
  Check('Timer1 fired',   True);

  { Timer 2: check it doesn't fire before started }
  TimerStart(2, 100);         { long timer }
  b := TimerOut(2);
  Check('Timer2 not yet',  NOT b);

  { Two timers independent }
  TimerStart(0, 2);
  TimerStart(1, 5);
  REPEAT UNTIL TimerOut(0);
  b := TimerOut(1);
  Check('Timers independent', NOT b);  { timer1 still running }

  REPEAT UNTIL TimerOut(1);
  Check('Timer1 done',    True);
END;

{ ---- KeyPressed / NextKey ---- }
PROCEDURE TestKeyboard;
BEGIN
  { No key pressed initially }
  b := KeyPressed;
  Check('No key initially', NOT b);

  { NextKey with no key should return 0 }
  w := NextKey;
  Check('NextKey empty',  w = 0);

  { KeyPressed still false after NextKey peek }
  Check('Still no key',   NOT KeyPressed);

  { Note: ReadKey not tested unattended }
  WriteLn(log,'  (ReadKey/Read skipped - interactive)');
END;

{ ---- Graphics: Plot, Line, Point, Display ---- }
PROCEDURE TestGraphics;
VAR px : Byte;
BEGIN
  { Plot a pixel and read it back }
  Plot(0, 0, 1);       { set pixel at 0,0 }
  px := Point(0, 0);
  Check('Plot/Point set',  px = 1);

  Plot(0, 0, 0);       { clear pixel }
  px := Point(0, 0);
  Check('Plot/Point clr',  px = 0);

  Plot(0, 0, 2);       { invert (was 0, becomes 1) }
  px := Point(0, 0);
  Check('Plot invert',     px = 1);

  Plot(0, 0, 2);       { invert again (becomes 0) }
  px := Point(0, 0);
  Check('Plot re-invert',  px = 0);

  { Point outside display returns 0 }
  px := Point(-1, 0);
  Check('Point outside',   px = 0);

  { Draw a line }
  Line(0, 0, 10, 0, 1);   { horizontal line }
  px := Point(5, 0);
  Check('Line pixel mid',  px = 1);
  px := Point(0, 0);
  Check('Line pixel start',px = 1);
  px := Point(10, 0);
  Check('Line pixel end',  px = 1);

  { Clear with col=0 }
  Line(0, 0, 10, 0, 0);
  px := Point(5, 0);
  Check('Line cleared',    px = 0);

  { UpdateRegion and Display }
  Plot(15, 15, 1);
  UpdateRegion(0, 0, 191, 63);
  Display;
  Check('Display done',    True);

  { TextDisplay — converts text buffer to graphics }
  GotoXY(1, 1);
  ClrScr;
  Write(log,'Graphics!');
  TextDisplay;
  Check('TextDisplay done',True);

  { Clean up }
  Line(0, 0, 191, 63, 0);
  Display;
  ClrScr;
  GotoXY(1, 1);
END;

{ ---- Write format edge cases ---- }
PROCEDURE TestWriteFormats;
BEGIN
  { Max integer }
  WriteLn(log,'MaxInt: ', 32767);
  WriteLn(log,'MinInt: ', -32768);

  { Zero padding via Str }
  Str(7:4, s);
  Check('Str width',   Length(s) = 4);

  { Real edge cases }
  WriteLn(log,'Zero real: ', 0.0:8:4);
  WriteLn(log,'Small:     ', 0.001:10:6);
  WriteLn(log,'Large:     ', 99999.9:10:1);

  { Negative real display }
  WriteLn(log,'NegReal:   ', -3.14:8:4);

  { Write Char vs String }
  Write(log,'C'); Write(log,'h'); Write(log,'a'); Write(log,'r'); WriteLn(log);
  WriteLn(log,'  above: Char');
END;

{ ---- Main ---- }
BEGIN
  Assign(log, '0:cov07.log');
  Rewrite(log);

  WriteLn(log,'=== Section 7: CRT Unit ===');
  WriteLn(log);

  WriteLn(log,'-- Write/WriteLn --');
  TestWrite;         WriteLn(log);

  WriteLn(log,'-- GotoXY/WhereXY --');
  TestGotoXY;        WriteLn(log);

  WriteLn(log,'-- Window --');
  TestWindow;        WriteLn(log);

  WriteLn(log,'-- ClrScr/ClrEol --');
  TestClr;           WriteLn(log);

  WriteLn(log,'-- DelLine/InsLine --');
  TestDelInsLine;    WriteLn(log);

  WriteLn(log,'-- Cursor --');
  TestCursor;        WriteLn(log);

  WriteLn(log,'-- Sound --');
  TestSound;         WriteLn(log);

  WriteLn(log,'-- Timer --');
  TestTimer;         WriteLn(log);

  WriteLn(log,'-- Keyboard --');
  TestKeyboard;      WriteLn(log);

  WriteLn(log,'-- Graphics --');
  TestGraphics;      WriteLn(log);

  WriteLn(log,'-- Write Formats --');
  TestWriteFormats;  WriteLn(log);

  WriteLn(log,'=== Section 7 complete ===');

  Close(log);
END.