Mojmir Nebel's DOS - chat program


bugfix v 1.0  =>  v 1.1 applied, Franz Glaser, Sep-23,1998
Ver 1.21 Oct. 3-1999


{$A+,B-,D-,E+,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S+,T-,V+,X+}
{$M 8192,4096,16384}
{
*-*-*-*-*-*-*-*-*-* DOSChat *-*-*-*-*-*-*-*-*-*
Author: Mojmir Nebel
Quit program : F10
This program is freeware, you can copy it without any restrictions, but not
for comercial use !

Description :
DOSChat is chatting program for DOS. It uses simple interface for transfering
messages. All messages are written in one file on one computer (or server),
others read the messages from it. So that's why it should be faster computer.
Needed is to look at paths. If they're not right, you won't see the messages.
That's why i prefer one common disk, it's easier to access it. To change the
path/file with messages run this program with parameter. For example:
DOSChat \myroom
creates or uses myroom.msg in root directory
DOSChat myroom
creates (or uses) myroom.msg in current directory

History :
1.0  : The first version.
1.1  : Fixed some bugs
1.11 : Color difference in system mesagges (like %Login somebody)
1.2  : Colored messages available
1.21 : Fixed some bugs and prepared for changing colors of background etc.

System Requirements :
80286 processor or better.
4 kB of disk space
Network : One common disk.

Homepage :
http://fog.home-page.org

e-mail : mnebel@email.cz

Snail-mail :
Mojmir Nebel
Budovatelska 530
742 13 Studenka 2
Czech Republic
}
Program DOSChat;

Const MessNumber=20;
      NameLength=30;
      MessLength=120;
      { File Constants }
      ChatFile:String='\DOSChat.msg';
      WriteFile:String='\DOSChat.wri';
      ReadFile:String='\DOSChat.rea';
      ChatFileSize=MessNumber*(NameLength+Messlength); { Velikost souboru v Bytech }
      { Base Chat Constants }
      Time:word=5; { Number of seconds to delay }
      Ver='1.21';
      { Screen Constants }
      ScreenSeg=$B800; { Screen segment }
      DefaultBCKLow=$1;
      DefaultBCK:Byte=DefaultBCKLow*16;
      DefaultNameCol:Byte=$C;
      DefaultMessCol:Byte=$A;
      Loginout='%08';     { - should be the same }
      Systemsgcol=8;      { / }
      BackGroundCol=$78;
      Linestring:string='DOSChat (C)1998-1999 Mojmir Nebel (fog.home-page.org)';
      { Pro nacitani retezce }
      texy:byte=24;

Type ChatFileRec = record
                    Name:String[NameLength];
                    mess:string[MessLength];
                   end;
     ChatFileType = Array [1..MessNumber] of ChatFileRec;

Var f:file;
    fw,fr:file of byte;
    here:ChatFileType;      { Current messages }
    i,a,Count,timer:word;   { For Timer }
    OldInt1c:Procedure;     {***     ***}
    ReadFileFlag:boolean;
    Name,Message:String;    { Current user, message }
    TextAttribut,cnt,DefColor,DefNameColor,DefaultBCKL:byte;
    Extended:Boolean;
    ch:char;

{*-*-*-*-*-*-* File access procedures *-*-*-*-*-*-*-*}
Procedure MoveMessages;
var xx:byte;
begin
   for xx:=1 to messnumber-1 do
   begin
     here[xx].mess:=here[xx+1].mess;
     here[xx].name:=here[xx+1].name;
   end;
   here[messnumber].mess:=message;
   here[messnumber].name:=name;
end;
Function ExistFile(what:string):boolean;
var ff:file of byte;
    IORes:Integer;
begin
   Assign(ff,what);
   {$I-}
   Reset(ff);
   {$I+}
   if IOResult=0 then
   begin
     Close(ff);
     ExistFile:=True
   end else ExistFile:=False;
end;
Procedure ReadChatFile;
begin
   Assign(fr,ReadFile);
   {$I-}
   If not ExistFile(ReadFile) then
   begin
     Rewrite(fr);
     Close(fr);
   end;
   Assign(f,ChatFile);
   Reset(f,ChatFileSize);
   BlockRead(f,here,1);
   Close(f);
   Assign(fr,ReadFile);
   Erase(fr);
   {$I+}
end;
Procedure WriteChatFile;
begin
   repeat until not ExistFile(ReadFile);
   repeat until not ExistFile(WriteFile);
   Assign(fw,WriteFile);
   {$I-}
   Rewrite(fw);
   Close(fw);
   ReadChatFile;
   MoveMessages;
   Assign(f,ChatFile);
   Rewrite(f,ChatFileSize);
   Blockwrite(f,here,1);
   Close(f);
   Assign(fw,WriteFile);
   Erase(fw);
   {$I+}
end;
{*-*-*-*-*-*-*-* CRT procedures *-*-*-*-*-*-*}
Procedure MoveCursor(x,y:byte); Assembler;
asm
  mov ah,2
  xor bh,bh
  mov dl,x
  mov dh,y
  int 10h
end;
Procedure FastPutChar(offst:word;color:byte; Character:char); Assembler;
asm
    mov  ax,ScreenSeg
    mov  es,ax
    mov  di,offst
    cld
    mov  al,character
    stosb
    mov  al,color
    stosb
end;
Procedure ClrScr;Assembler;
asm
   mov ax,screenseg
   mov es,ax
   xor di,di
   cld
   mov cx,2000
@1:
   mov al,32
   stosb
   mov al,textattribut
   stosb
   loop @1
end;
Procedure wrxy(x,y:byte; s:string); { Write-on-X,Y }
var position,i:word;
Begin
   position:=(x*2)+(y*160)-160;
   for i:=1 to length(s) do
   begin
     FastPutChar(position,TextAttribut,s[i]);
     inc(position,2);
   end;
End;
Procedure ColorWrxy(x,y,col:byte; s:string);
begin
   textattribut:=col;
   wrxy(x,y,s);
end;
Procedure pozadi;
Var i:integer;
Begin
   textattribut:=Backgroundcol;
   clrscr;
   wrxy(40-(Length(Linestring) div 2),1,Linestring);
   for i:=80 to 1839 do FastPutChar(i*2,DefaultBCK,#32);
End;

Function UpcaseStr(s:string):string;
var st:string;
    zz:byte;
begin
   st:='';
   for zz:=1 to length(s) do st[zz]:=Upcase(s[zz]);
   st[0]:=Chr(length(s));
   Upcasestr:=st;
end;

Function GetColor(s:string; def:byte; sup:boolean):byte;
Const hexchars='0123456789ABCDEF';
var col:byte;
    cccc:integer;
    ss:string;
begin
   If s[1]<>'%' then
   begin
      GetColor:=Def;
      exit;
   end;
   if sup then
   begin
      GetColor:=Systemsgcol;
      exit;
   end;
   ss:=Copy(s,2,2);
   col:=((Pos(Upcase(ss[1]),hexchars)-1)*16)+(Pos(Upcase(ss[2]),hexchars)-1);
   GetColor:=col;
end;

Function GetStringWNumber(s:string; sup:boolean):String;
begin
   If (s[1]='%') and not sup
      then GetStringWNumber:=Copy(s,4,Length(s)-3)
      else GetStringWNumber:=s;
end;
Function IsLogInOut(n:string):boolean;
begin
   If (n='%Login') or (n='%Logout') then
      IsLogInOut:=True else
      IsLogInOut:=False;
end;
Function GetPos(s:string):shortint;
begin
   if s[1]<>'%' then
   begin
      GetPos:=0;
      exit;
   end;
   If IsLogInOut(s) then
   begin
      GetPos:=0;
      exit;
   end;
   GetPos:=-3;
end;
{*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* REFRESH *-*-*-*-*-*-*-*-*-*-*}
{-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- REFRESH -*-*-*-*-*-*-*-*-*-*-}
{*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* REFRESH *-*-*-*-*-*-*-*-*-*-*}
Procedure RefreshDisplay;
var c:word;
    posit,y:byte;
    ss,who:string;
    supcommand:boolean;
begin
   for c:=160 to 3679 do
   begin
     FastPutChar(c,DefaultBCK,#32);
     inc(c);
   end;
   c:=1;
   y:=2;
   repeat
   With here[c] do
   begin
     textattribut:=DefaultBCK+GetColor(Name,DefaultNameCol,IsLogInOut(name));
     Wrxy(0,y,GetStringWNumber(name,IsLogInOut(name)));
     Wrxy(length(name)+GetPos(name),y,':');
     textattribut:=DefaultBCK+GetColor(Mess,DefaultMessCol,IsLogInOut(name));
     Wrxy(length(name)+GetPos(name)+2,y,GetStringWNumber(mess,false));
     Inc(y);
     If Length(name)+Length(mess)+2 > 79 then Inc(y);
   end;
   inc(c);
   until (c=24) or (c=messnumber+1) or (y>22);
   textattribut:=$74;
   If (y>22) and (c<>messnumber+1) then Wrxy(46,25,'!!') else Wrxy(46,25,'  ');
end;
{*-*-*-*-*-*-*-* Interrupt procedures *-*-*-*-*-*-*-*}
Procedure GetVector(var OldTimer:Pointer);Assembler;
asm
    push ds
    cld
    mov ax,351ch
    int 21h
    mov ax,es
    les di,OldTimer
    xchg ax,bx
    stosw
    xchg ax,bx
    stosw
    pop ds
end;

Procedure SetVector(OldTimer:Pointer); Assembler;
asm
   push ds
   lds  dx,OldTimer
   mov  ax,251ch
   int  21h
   pop  ds
end;

{$F+}
Procedure MyInt1c; Interrupt;
begin
   asm
     push ax
     add  a,55
     cmp  a,1000
     jna  @OK
     sub  a,1000
     inc  count
@OK:
     mov  ax,count
     cmp  ax,time
     jnae @Go
     mov  al,1
     mov  ReadFileFlag,al
     xor  ax,ax
     mov  count,ax
@Go:
     pop  ax
   end;
   Inline($9C);               { Push Flags }
   OldInt1c;
end;
{$F-}
{*-*-*-*-*-*-* Keyboard *-*-*-*-*-*-*-*-*}
Function Keypressed:boolean; Assembler;
asm
  mov ah,0bh
  int 21h
end;
Function ReadKey:char; Assembler;
asm
   mov ah,7
   int 21h
end;
{*-*-*-*-*-*-* Other procedures *-*-*-*-*-*-*}
Procedure CommandLine;
Var sss:string;
begin
   If (Paramstr(1)='/?') or (ParamStr(1)='/h') or (ParamStr(1)='/H') then
   begin
      Writeln('DOSChat '+ver);
      Writeln;
      Writeln('DOSChat /?       ...this help.');
      Writeln('DOSChat filename ...another chat group (filename should be without extension)');
      Writeln;
      Writeln('Comments:');
      Writeln('This program is FREEWARE. DOSChat must NOT serve business.');
      Writeln;
      Writeln('(C)1998-1999 Mojmir Nebel');
      Writeln('Homepage: fog.home-page.org');
      Writeln('E-mail  : mnebel@email.cz');
      Writeln;
      Writeln('********* Mail **********');
      Writeln('Mojmir Nebel');
      Writeln('Budovatelska 530');
      Writeln('Studenka 2');
      Writeln('742 13');
      Writeln('Czech Republic');
      Writeln;
      Writeln('Send me tons of postcards !');
      halt;
   end;
   sss:=Paramstr(1);
   If Pos('.',sss)<>0 then
      delete(sss,Pos('.',sss),length(sss)-Pos('.',sss)+1);
   ChatFile:=sss+'.msg';
   WriteFile:=sss+'.msw';
   ReadFile:=sss+'.msr';
   Writeln('*********** DOSChat '+ver+' ***********');
   Writeln('Command line parameter entered, using this file:');
   Writeln(ChatFile);
   Writeln('Are you sure ? (Y/N)');
   If UpCase(Readkey)<>'Y' then halt;
   asm
     mov ax,3
     int 10h
   end;
end;
Procedure SelectColor(Name:string);
Var i,nc,mc:byte;
    nchange:boolean;
    cc:char;
begin
   textattribut:=7;
   Wrxy(0,5,'Select your color: ...change item, ...change color, ENTER...Continue');
   nc:=DefaultNameCol;
   mc:=DefaultMessCol;
   nchange:=True;
   ColorWrxy(1,7,$0b,'');
   ColorWrxy(Length(Name)+3,7,$07,' ');
   Repeat
    ColorWrxy(0,6,nc+DefaultBCK,Name+':');
    ColorWrxy(Length(name)+2,6,mc+DefaultBCK,'[This is a message]');
    cc:=Readkey;
    Case cc of
     #75: begin
            nchange:=True;
            ColorWrxy(1,7,$0b,'');
            ColorWrxy(Length(Name)+3,7,$07,'   ');
          end;
     #77: begin
            nchange:=False;
            ColorWrxy(1,7,$07,' ');
            ColorWrxy(Length(Name)+3,7,$0b,'');
          end;
     #72: If nchange then
          begin
             nc:=nc+1;
             if nc=DefaultBCKL then nc:=nc+1;
             if nc=$10 then nc:=0;
             if nc=DefaultBCKL then nc:=nc+1;
          end else
          begin
             mc:=mc+1;
             if mc=DefaultBCKL then mc:=mc+1;
             if mc=$10 then mc:=0;
             if mc=DefaultBCKL then mc:=mc+1;
          end;
     #80: If nchange then
          begin
             nc:=nc-1;
             if nc=DefaultBCKL then nc:=nc-1;
             if nc=$FF then nc:=$F;
             if nc=DefaultBCKL then nc:=nc-1;
          end else
          begin
             mc:=mc-1;
             if mc=DefaultBCKL then mc:=mc-1;
             if mc=$FF then mc:=$F;
             if mc=DefaultBCKL then mc:=mc-1;
          end;
    end;
   Until cc=#13;
   DefColor:=mc;
   DefNameColor:=nc;
end;

Function Setmycolor(cc:byte):string;
Const hexchars:String='0123456789ABCDEF';
begin
   Setmycolor:='%'+hexchars[(cc div 16)+1]+hexchars[(cc mod 16)+1];
end;

BEGIN
   asm
     mov ax,3
     int 10h
   end;
   textattribut:=7;
   if Test8086=0 then
   begin
      Wrxy(0,1,'Sorry, but you need better processor for this program !');
      MoveCursor(1,2);
      halt;
   end;
   a:=0;
   Count:=0;
   DefaultBCKL:=DefaultBCKLow;
   ReadFileFlag:=False;
   message:='';
   If ParamCount<>0 then CommandLine;

   repeat
     Wrxy(0,1,'***** DOSChat, version '+ver+' *****');
     Wrxy(0,2,'Enter your Name :          ');
     MoveCursor(18,1);
     readln(name);
     if name='' then write(^G);
     if (Pos('%',name)<>0) or
        (Pos('#',name)<>0) or
        (Pos('$',name)<>0) then
     begin
        write(^G);
        name:='';
     end;
   until name<>'';
   SelectColor(Name);
   MoveCursor(0,25);
   For i:=1 to MessNumber do
   begin
     here[i].name:=Loginout+'%Free';
     here[i].mess:=' ';
   end;
   If Not ExistFile(ChatFile) then WriteChatFile;
   ReadChatFile;
   Pozadi;
   GetVector(@OldInt1c);
   SetVector(Addr(MyInt1c));
   message:=Loginout+name;
   name:=+'%Login';
   MoveMessages;
   WriteChatFile;
   name:=Setmycolor(defnamecolor)+GetStringWNumber(message,false);
   message:='';
   RefreshDisplay;
   textattribut:=$74;
   Wrxy(49,25,'F10....Exit to OS');
   textattribut:=$7d;
   Wrxy(38,25,'< MAX');

   REPEAT
    repeat
     If ReadFileFlag then
     begin
       ReadChatFile;
       RefreshDisplay;
       ReadFileFlag:=false;
     end;
    until keypressed;

     textattribut:=Backgroundcol;
     ch:=readkey;
     if Ch=#0 then
     begin
       Extended:=True;
       ch:=readkey;
     end else Extended:=False;
     if not(ch=#13) and not(ch=#8) and not Extended and (cnt+2<messlength) then
     begin
       Message:=message+ch;
       Wrxy(cnt,texy,ch);
       Inc(cnt);
     end;
     if (ch=#8) and (cnt>0) then
     begin
        Dec(cnt);
        message[0]:=Chr(ord(message[0])-1);
        Wrxy(cnt,texy,' ');
     end;
     if ch=#13 then
     begin
       If message[1]<>'%' then message:=Setmycolor(DefColor)+message;
       If message[1]='%' then
       begin
         If (not (message[2] in ['0'..'9','a'..'f','A'..'F']) or
             not (message[3] in ['0'..'9','a'..'f','A'..'F'])) then
             message:=Setmycolor(DefColor)+message;
       end;
       MoveMessages;
       WriteChatFile;
       message:='';
       cnt:=0;
       For i:=0 to messlength-3 do Wrxy(i,texy,' ');
     end;

   UNTIL (Extended and (Ch='D')); { End while F10 pressed }

   SetVector(@OldInt1c);
   Randomize;
   message:=Loginout+GetStringWNumber(Name,false);
   name:=Loginout+'%Logout';
   MoveMessages;
   WriteChatFile;
   textattribut:=$07;
   clrscr;
   MoveCursor(0,0);
   Writeln('DOSChat, version '+ver+', (C)1998-99 Mojmir Nebel');
END.

This is translated version (Translated comments only)

Send me message to my e-mail if you don't understand something in this
source. You can (should) also send me Bug-reports.

Greetings:
All PAS-coders



URL  http://fog.jinak.cz/il1/index.html
DOWNLOAD LATEST VERSION from the new URL

TP-links