[Back to TEXTWNDW SWAG index] [Back to Main SWAG index] [Original]

    { WRITTEN BY TIM SCHEMPP
      OCTOBER 21, 1993       }

    unit drawline;

    interface

       procedure horizline(x1,x2,y:integer; default:char);
       procedure vertline(x,y1,y2:integer; default:char);
       procedure rectlines(x1,y1,x2,y2:integer; default:char);

    { IF writetomemory IS SET TO TRUE, LINES WILL BE DRAWN AN AVERAGE OF
      ABOUT 15 TO 20 PERCENT FASTER THAN IF writetomemory IS SET TO FALSE.
      HOWEVER, IF DATA IS WRITTEN DIRECTLY TO VIDEO MEMORY, YOU ARE STUCK WITH
      THE SCREENS CURRENT COLORS (TEXTCOLOR AND TEXTBACKGROUND HAVE NO EFFECT).
      THE DEFAULT VALUE OF writetomemory IS FALSE. }

    var writetomemory:boolean;

    implementation
     uses crt; {for gotoxy, wherex and wherey}

         const symbols:array[1..40] of char=
                          ('³','´','µ','�','·','¸','¹','º','»','¼','½','¾','¿',
                           'À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì',
                           'Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','×','Ø','Ù',
                           'Ú');

               codes:array[1..40] of string[4]=
                        ('1010','1011','1012','2021','0021','0012','2022','2020',
                         '0022','2002','2001','1002','0011','1100','1101','0111',
                         '1110','0101','1111','1210','2120','2200','0220','2202',
                         '0222','2220','0202','2222','1202','2101','0212','0121',
                         '2100','1200','0210','0120','2121','1212','1001','0110');

                {THE SCREEN DIMENSIONS}
                screenwidth=80;   screenlength=25;

    {******}

    {READS A CHARACTER FROM VIDEO MEMORY AT THE GIVEN COORDINANTS}
    function Memread(col,row:integer):char;

      Const
        Seg = $B000; { Video memory address for color system  }
        Ofs = $8000; { For monochrome system, make Ofs = $0000 }
      Var
        SChar : Integer;
      Begin
              SChar := ((Row-1)*160) + ((Col-1)*2); { Compute starting location }
              memread:=chr(Mem[Seg:Ofs + SChar]);   { read character from memory}
      End;

    {******}

    {WRITES A CHARACTER DIRECTORY TO VIDEO MEMORY AT THE GIVEN COORDINATES}
    {NOTE: THE CURRENT COLORS AT THE GIVEN COORDINANTS ARE USED FOR DRAWING.}
    procedure Memwrite(col,row:integer; c:char);

      Const
        Seg = $B000; { Video memory address for color system  }
        Ofs = $8000; { For monochrome system, make Ofs = $0000 }
      Var
        SChar : Integer;
      Begin
              SChar := ((Row-1)*160) + ((Col-1)*2); { Compute starting location }
              Mem[Seg:Ofs + SChar]:=ord(c);         { write character to memory}
      End;

    {******}

       {PROCEDURE USED INTERNALLY TO CREATE A SET OF CHARACTER CODES}
       function getcode(c:char; direction:byte):char;
       var counter:integer;
       begin
        counter:=1;
        while (counter<=40) and (c<>symbols[counter]) do inc(counter);
        if counter>40 then getcode:='0' else getcode:=codes[counter,direction];
       end;

    {******}

       {PROCEDURE DRAWS A LINE IN TEXT MODE FROM (X1,Y) TO (X2,Y)}
       {DEFAULT IS EITHER '1' OR '2' FOR SINGLE OF DOUBLE LINES}
       procedure horizline(x1,x2,y:integer; default:char);

        var code:string[4];
            defaultchar:char;
            c,index:integer;
            xpos,ypos:integer;

        begin
         xpos:=wherex; ypos:=wherey;
         if x2<x1 then begin c:=x1; x1:=x2; x2:=c; end;
         if default='1' then defaultchar:=symbols[18]
                        else defaultchar:=symbols[27];
         for c:=x1 to x2 do
          begin
           code:='0000';
           if y<>0 then code[1]:=getcode(memread(c,y-1),3) else code[1]:='0';
           if (c=x2) and (x2=screenwidth) then code[2]:='0'
              else if (c=x2) then code[2]:=getcode(memread(x2+1,y),4)
                             else code[2]:=default;
           if y<>screenlength then code[3]:=getcode(memread(c,y+1),1)
                              else code[3]:='0';
           if (c=x1) and (x1=1) then code[4]:='0'
              else
               if (c=x1) then code[4]:=getcode(memread(x1-1,y),2)
                         else code[4]:=default;
           index:=1;
           while (index<=40) and (code<>codes[index]) do inc(index);
           if writetomemory then
             if index>40 then memwrite(c,y,defaultchar)
                         else memwrite(c,y,symbols[index])
                       else
             if index>40 then begin gotoxy(c,y); write(defaultchar); end
                         else begin gotoxy(c,y); write(symbols[index]); end;
          end; {counter}
          if not writetomemory then gotoxy(xpos,ypos);
       end;

    {******}

       {PROCEDURE DRAWS A LINE IN TEXT MODE FROM (X,Y1) TO (X,Y2)}
       {DEFAULT IS EITHER '1' OR '2' FOR SINGLE OF DOUBLE LINES}
       procedure vertline(x,y1,y2:integer; default:char);

        var code:string[4];
            defaultchar:char;
            c,index:integer;
            xpos,ypos:integer;

        begin
         xpos:=wherex; ypos:=wherey;
         if y2<y1 then begin c:=y1; y1:=y2; y2:=c; end;
         if default='1' then defaultchar:=symbols[1]
                        else defaultchar:=symbols[8];
         for c:=y1 to y2 do
          begin
           code:='0000';
           if (c=y2) and (y2=screenlength) then code[3]:='0'
              else if (c=y2) then code[3]:=getcode(memread(x,y2+1),1)
                             else code[3]:=default;
           if x<>screenwidth then code[2]:=getcode(memread(x+1,c),4)
                             else code[1]:='0';
           if x<>1 then code[4]:=getcode(memread(x-1,c),2)
                   else code[1]:='0';
           if (c=y1) and (y1=0) then code[1]:='0'
              else if (c=y1) then code[1]:=getcode(memread(x,y1-1),3)
                             else code[1]:=default;
           index:=1;
           while (index<=40) and (code<>codes[index]) do inc(index);

           if writetomemory then
                 if index>40 then memwrite(x,c,defaultchar)
                             else memwrite(x,c,symbols[index])
                            else
                 if index>40 then begin gotoxy(x,c); write(defaultchar) end
                             else begin gotoxy(x,c); write(symbols[index]); end;
          end; {counter}
         if not writetomemory then gotoxy(xpos,ypos);
        end;

    {******}

       {PROCEDURE DRAWS A RECTANGLE IN TEXT MODE}
       {DEFAULT IS EITHER '1' OR '2' FOR SINGLE OF DOUBLE LINES}
       procedure rectlines(x1,y1,x2,y2:integer; default:char);

       begin
        horizline(x1,x2,y1,default);
        horizline(x1,x2,y2,default);
        vertline(x1,y1,y2,default);
        vertline(x2,y1,y2,default);
       end;

    {******}

     begin
      writetomemory:=false;
     end. {unit}

     {-------------------   DEMO PROGRAM ------------------------}
     { ----------------      CUT HERE  --------------------------}

     { WRITTEN BY TIM SCHEMPP
      OCTOBER 21, 1993       }

       {THIS PROGRAM DEMONSTARTES THE USE OF THE UNIT drawline.  UNIT DRAWLINE
        WILL USE THE ASCII SET TO DRAW LINES.  WHEN LINE INTERSECTIONS ARE
        FOUND, THE PROCEDURES DESCIDE WHICH CHARACTER FITS BEST.  THUS MAKING
        IT VERY EASY TO CREATE VARIOUS TABLES AND OTHER SCREEN SET UPS.  THE
        UNIT ALSO HAS THE ABILITY TO WRITE DIRECTORY TO VIDEO MEMORY FOR
        A 15% TO 20% IMPROVEMENT IN SPEED.  SEE DRAWLINE.DOC FOR MORE INFO.}

    program demo;

     uses crt,drawline;

     var counter:integer;

     begin
      {SET THE SCREEN UP}
      textbackground(black);
      textcolor(white);
      clrscr;

      {THE CALL TO CLEAR SCREEN FILLED THE SCREEN WITH SPACES WITH A BLACK
       BACKGROUND AND A WHITE FOREGROUND.  IF writetomemory IS SET TO TRUE,
       ALL OF THE OUTPUT WILL BE WRITTEN WITH A BLACK BACKGROUND AND A WHITE
       FOREGROUND REGARDLESS OF TEXT ATTRIBUTE CHANGES.}

      {writetomemory:=true;} { <--- ADD THIS STATEMENT AND SEE COLOR DIFFERENCE}

      {WRITE SOME TEXT}
       gotoxy(22,6);
       textcolor(lightblue);
       write('LINE DRAWING DEMONSTARTATION PROGRAM');
       textcolor(yellow);
      {DRAW A RECTANGLE WITH DOUBLE LINES}
      rectlines(10,4,70,20,'2');
      {DRAW SOME HORIZONTAL SINGLE LINES}
      for counter:=9 to 19 do
       horizline(10,70,counter,'1');
      {DRAW SOME SINGLE VERTICLE LINES}
       counter:=20;
       while counter<=60 do
        begin
         vertline(counter,8,20,'1');
         inc(counter,10);
        end; {WHILE}
      {DRAW ONE LAST HORIZONTAL DOUBLE LINE}
       horizline(10,70,8,'2');

      repeat until keypressed;
     end.

[Back to TEXTWNDW SWAG index] [Back to Main SWAG index] [Original]