home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / top2src.zip / TOPLINK.ZIP / TOPLINK.PAS < prev    next >
Pascal/Delphi Source File  |  1996-09-29  |  39KB  |  1,479 lines

  1. Program TOPLink;
  2. {$V-}
  3. {$M 16384,0,0}
  4. Uses Crt, Dos, FosComR, Ansi_Drv, TOPErrT, TOPLSupp, MulAware, UnixDate, Reg;
  5.  
  6. Const
  7.    fmReadOnly  = $00;
  8.    fmWriteOnly = $01;
  9.    fmReadWrite = $02;
  10.  
  11.    fmDenyAll   = $10;
  12.    fmDenyWrite = $20;
  13.    fmDenyRead  = $30;
  14.    fmDenyNone  = $40;
  15.  
  16.    RecLock = 0;
  17.    RecUnlock = 1;
  18.  
  19.    ProgVerStr = ' v2.00';
  20.  
  21.    FC : char = '[';
  22.    BC : char = ']';
  23.  
  24. Type
  25.   Str30 = String[30];
  26.   Str255 = String[255];
  27.  
  28. Type
  29.   IDXRec = Record
  30.              StructLength : Word;
  31.              Alias : String[30];
  32.              RealName : String[40];
  33.              Baud : Word;
  34.              Location : String[30];
  35.              Gender : Integer;
  36.              Quiet : Boolean;
  37.              Task : Word;
  38.              LastAccess : LongInt;
  39.              Channel : LongInt;
  40.              ChannelListed : Boolean;
  41.              Security : Word;
  42.              Actions : Boolean;
  43.            end;
  44.  
  45. Type
  46.   NodeRec = Record
  47.              StructLength : Word;
  48.              Kind : Integer;
  49.              From : Integer;
  50.              DoneTo : Integer;
  51.              Gender : Integer;
  52.              Alias : Str30;
  53.              Data : Str255;
  54.              Channel : LongInt;
  55.              MinSec : Word;
  56.              MaxSec : Word;
  57.              Data1 : LongInt;
  58.            end;
  59.  
  60. Type
  61.   ConfigRec = Record
  62.                 SystemName : String[31];
  63.                 GiveTimeSlice : Boolean;
  64.                 StripAnsi : Boolean;
  65.                 StripTOP : Boolean;
  66.                 ShowBBSName : Boolean;
  67.                 SendDelay : byte;
  68.                 CheckingDelay : byte;
  69.                 DCommandsOn : Boolean;
  70.                 BBSCommandsOn : Boolean;
  71.                 Channel : LongInt;
  72.                 MinSecurity : Word;
  73.                 MaxNodes : Word;
  74.                 CrashProt : Word;
  75.               end;
  76. Const
  77.   ConfigData : ConfigRec
  78.                = ( SystemName : 'An Unknown System';
  79.                    GiveTimeSlice : True;
  80.                    StripAnsi : False;
  81.                    StripTOP : True;
  82.                    ShowBBSName : True;
  83.                    SendDelay : 6;
  84.                    CheckingDelay : 1;
  85.                    DCommandsOn : True;
  86.                    BBSCommandsOn : True;
  87.                    Channel : 1;
  88.                    MinSecurity : 0;
  89.                    MaxNodes : 10;
  90.                    CrashProt : 30);
  91. Type
  92.   RegisterRec = record
  93.                   TheReg : string;
  94.                   TheName : string;
  95.                 end;
  96. Const
  97.   RegisterData : RegisterRec
  98.                = ( TheReg : '00000000000';
  99.                    TheName : 'UNREGISTERED');
  100.  
  101. Var
  102.   Com : byte;
  103.   BBSName : String;
  104.   IPCDir : String;
  105.   Node : Word;
  106.   NodeData : NodeRec;
  107.   NodeStr : String;
  108.   LastTime : LongInt;
  109.   Skips : Array [1..50] of String[80];
  110.   LinesRCVD : Word;
  111.   SavedScr : Array [1..4000] of byte;
  112.   LastPoll : LongInt;
  113.   Registered : Boolean;
  114.  
  115. Procedure Check_Register;
  116. begin
  117.   Registered := ValidateKey(RegisterData.TheName+#0, RegisterData.TheReg,
  118.                             17476, 38162);
  119. end;
  120.  
  121. Procedure Deinit;
  122. Var
  123.   B : byte;
  124.   f : File of byte;
  125. begin
  126.   Assign (F, IPCDir + 'NODEIDX2.TCH');
  127.   Reset (f);
  128.   Repeat Until FLock(RecLock, FileRec(f).Handle, Node, 1) = 0;
  129.   Seek (f, Node);
  130.   b := 0;
  131.   {$I-}
  132.   Repeat
  133.     Write (f,b);
  134.   Until IOResult = 0;
  135.   {$I+}
  136.   Repeat Until FLock(RecUnlock, FileRec(f).Handle, Node, 1) = 0;
  137.   Close (f);
  138. end;
  139.  
  140. Procedure WriteField (Num : byte);
  141. begin
  142.   TextAttr := $1E;
  143.   With ConfigData do
  144.   Case Num of
  145.     1 :
  146.     begin
  147.       GotoXY (25,4);
  148.       Write (' '+SystemName+Spaces(31-Length (SystemName)));
  149.     end;
  150.     2 :
  151.     begin
  152.       GotoXY (25,5);
  153.       If StripAnsi then Write (' On  ') else Write (' Off ');
  154.     end;
  155.     3 :
  156.     begin
  157.       GotoXY (25,6);
  158.       If StripTOP then Write (' Off ') else Write (' On  ');
  159.     end;
  160.     4 :
  161.     begin
  162.       GotoXY (25,7);
  163.       If ShowBBSName then Write (' On  ') else Write (' Off ');
  164.     end;
  165.     5 :
  166.     begin
  167.       GotoXY (25,8);
  168.       Write (' ',SendDelay,'ms ');
  169.     end;
  170.     6 :
  171.     begin
  172.       GotoXY (25,9);
  173.       Write (' ',CheckingDelay,'s ');
  174.     end;
  175.     7 :
  176.     begin
  177.       GotoXY (25,10);
  178.       If DCommandsOn then Write (' On  ') else Write (' Off ');
  179.     end;
  180.     8 :
  181.     begin
  182.       GotoXY (25,11);
  183.       If BBSCommandsOn then Write (' On  ') else Write (' Off ');
  184.     end;
  185.     9 :
  186.     begin
  187.       GotoXY (25,12);
  188.       If GiveTimeSlice then Write (' On  ') else Write (' Off ');
  189.     end;
  190.     10:
  191.     begin
  192.       GotoXY(25,13);
  193.       Write(' ',Channel:10,' ');
  194.     end;
  195.     11:
  196.     begin
  197.       GotoXY(25,14);
  198.       Write(' ',MinSecurity:5, ' ');
  199.     end;
  200.     12:
  201.     begin
  202.       GotoXY(25,15);
  203.       Write(' ',MaxNodes:3,' ');
  204.     end;
  205.     13:
  206.     begin
  207.       GotoXY(25,16);
  208.       Write(' ',CrashProt:5,' ');
  209.     end;
  210.   end;
  211. end;
  212.  
  213. Procedure InitCFGScr;
  214. Var
  215.   Loop : Word;
  216. begin
  217.   TextAttr := $71;
  218.   ClrScr;
  219.   GotoXY (1,2);
  220.   For loop := 1 to 1920 do Write ('░');
  221.   Textbackground (blue);
  222.   GotoXY (1,1);
  223.   Textbackground (7);
  224.   Textcolor (red);
  225.   Write (' TOPLink'+ProgVerStr);
  226.   Textcolor (0);
  227.   Write (' Configuration - Copyright 1996 Paul Sidorsky, ISMWare');
  228.   ClrEol;
  229.   GotoXY (1,25);
  230.   Textcolor (Red);
  231.   Write (' Help: ');
  232.   Textcolor (0);
  233.   Write ('Use cursor keys to select a choice.');
  234.   ClrEol;
  235.   WindowBorder (4,3,60,17,White,7);
  236.   TextAttr := $7F;
  237.   GotoXY (27,3);
  238.   Write ('┤ Config ├');
  239.   GotoXY (6,4);
  240.   Textcolor (0);
  241.   Writeln ('Your BBS Name:');
  242.   GotoXY (6,5);
  243.   Writeln ('Ansi Stripping:');
  244.   GotoXY (6,6);
  245.   Writeln ('TOP Code Sending: ');
  246.   GotoXY (6,7);
  247.   Writeln ('Show BBS Name:');
  248.   GotoXY (6,8);
  249.   Writeln ('Sending Delay:');
  250.   GotoXY (6,9);
  251.   Writeln ('Checking Delay:');
  252.   GotoXY (6,10);
  253.   Writeln ('Direct Text:');
  254.   GotoXY (6,11);
  255.   Writeln ('BBS Commands:');
  256.   GotoXY (6,12);
  257.   Writeln ('Give Time Slices:');
  258.   GotoXY(6, 13);
  259.   Writeln('Channel Number:');
  260.   GotoXY(6, 14);
  261.   Writeln('Minimum Security:');
  262.   GotoXY(6, 15);
  263.   Writeln('MaxNodes Setting:');
  264.   GotoXY(6, 16);
  265.   TextAttr := $78;
  266.   Writeln('Crash Prot. Delay:');
  267.   For Loop := 1 to 14 do WriteField (Loop);
  268. end;
  269.  
  270. Procedure GetField (Num : Byte);
  271. var
  272.   S : String[30];
  273.   I, Err : Integer;
  274.   L : LongInt;
  275. begin
  276.   With ConfigData do
  277.   Case Num of
  278.     1 :
  279.     begin
  280.       Textcolor (15);
  281.       GotoXY (26,4);
  282.       CursorNorm;
  283.       GetString (SystemName,30, SystemName);
  284.       CursorOff;
  285.     end;
  286.     2 : StripAnsi := not StripAnsi;
  287.     3 : StripTOP := not StripTOP;
  288.     4 : ShowBBSName := not ShowBBSName;
  289.     5 : If SendDelay <> 15 then Inc (SendDelay) else SendDelay := 0;
  290.     6 : If CheckingDelay <> 5 then Inc (CheckingDelay) else CheckingDelay := 0;
  291.     7 : DCommandsOn := not DCommandsOn;
  292.     8 : BBSCommandsOn := not BBSCommandsOn;
  293.     9 : GiveTimeSlice := not GiveTimeSlice;
  294.     10:
  295.     begin
  296.       Repeat
  297.         Textcolor (15);
  298.         GotoXY (26,13);
  299.         CursorNorm;
  300.         Str(ConfigData.Channel, S);
  301.         GetString (S, 10, S);
  302.         CursorOff;
  303.         Val(S, L, Err);
  304.       Until (L >= 0);
  305.       ConfigData.Channel := L;
  306.     end;
  307.     11:
  308.     begin
  309.       Repeat
  310.         Textcolor (15);
  311.         GotoXY (26,14);
  312.         CursorNorm;
  313.         Str(ConfigData.MinSecurity, S);
  314.         GetString (S, 5, S);
  315.         CursorOff;
  316.         Val(S, I, Err);
  317.       Until (I >= 0) AND (I <= 32767);
  318.       ConfigData.MinSecurity := I;
  319.     end;
  320.     12:
  321.     begin
  322.       Repeat
  323.         Textcolor (15);
  324.         GotoXY (26,15);
  325.         CursorNorm;
  326.         Str(ConfigData.MaxNodes, S);
  327.         GetString (S, 3, S);
  328.         CursorOff;
  329.         Val(S, I, Err);
  330.       Until (I >= 0) AND (I <= 255);
  331.       ConfigData.MaxNodes := I;
  332.     end;
  333.     13:
  334.     begin
  335. {      Repeat
  336.         Textcolor (15);
  337.         GotoXY (26,16);
  338.         CursorNorm;
  339.         Str(ConfigData.CrashProt, S);
  340.         GetString (S, 5, S);
  341.         CursorOff;
  342.         Val(S, I, Err);
  343.       Until (I >= 0) AND (I <= 32767);
  344.       ConfigData.CrashProt := I;}
  345.     end;
  346.   end;
  347.   WriteField (Num);
  348. end;
  349.  
  350. Procedure GetCFGChoice;
  351. Const
  352.   HelpLine : Array [1..13] of String[70] = (
  353.     'The name of your BBS system',
  354.     'Controls if incoming ANSI is stripped',
  355.     'Whether or not TOP codes in outgoing text is stripped',
  356.     'Controls if the BBS name is displayed in front of incoming text',
  357.     'Delay between each character sent to the com port in milliseconds',
  358.     'Delay between checking for incoming messages',
  359.     'Whether or not users are allowed to use direct text',
  360.     'Whether or not the linked BBS can send TOPLink commands',
  361.     'Whether or not time slices should be given to the operating system',
  362.     'Channel number that TOPLink will use, or 0 for global',
  363.     'Minimum security need to see and use TOPLink',
  364.     'MaxNodes setting from TOP.CFG.  BOTH SETTINGS MUST BE THE SAME!',
  365.     'Unused.  Be sure to set CrashProtDelay in TOP.CFG to 0!'
  366.     );
  367.  
  368.   Procedure WriteBottom (message : String);
  369.   Var
  370.     X,Y : byte;
  371.     Save : Word;
  372.   begin
  373.     X := WhereX; Y := WhereY;
  374.     Save := TextAttr;
  375.     GotoXY (1,25);
  376.     TextAttr := $74;  Write (' ESC');
  377.     TextAttr := $70;  Write (' Exit │');
  378.     TextAttr := $70;
  379.     Write (#32+Message);
  380.     ClrEol;
  381.     GotoXY (X,Y);
  382.     TextAttr := Save;
  383.   end;
  384.  
  385. Var
  386.   Loc : Byte;
  387.   VideoMem : Array[1..4000] of byte absolute $B800:0000;
  388.   Done : Boolean;
  389.   Key : Word;
  390.  
  391.   Procedure HighLight (Num : byte);
  392.   Var
  393.     L : byte;
  394.   begin
  395.     For l := 0 to 18 do VideoMem [(Num)*160 + 330 + 2*l] := $2E;
  396.   end;
  397.   Procedure UnHighLight (Num : byte);
  398.   Var
  399.     L : byte;
  400.   begin
  401.     For l := 0 to 18 do VideoMem [(Num)*160 + 330 + 2*l] := $70;
  402.   end;
  403.  
  404. begin
  405.   CursorOff;
  406.   Loc := 1;
  407.   Done := False;
  408.   Repeat
  409.     HighLight (Loc);
  410.     WriteBottom (HelpLine[Loc]);
  411.     Key := Get_Key;
  412.     Case Key of
  413.       328 :
  414.       begin
  415.         UnHighLight (Loc);
  416.         Dec(Loc);
  417.         If Loc = 0 then Loc := 13;
  418.       end;
  419.       336 :
  420.       begin
  421.         UnHighLight(Loc);
  422.         Inc(Loc);
  423.         If Loc = 14 then Loc := 1;
  424.       end;
  425.       13 : GetField (Loc);
  426.       27 : Done := True;
  427.     end;
  428.   Until Done;
  429. end;
  430.  
  431. Procedure SaveConfig;
  432. Var
  433.   ExeFile    : file;
  434.   HeaderSize : word;
  435.   FileName : String;
  436.  
  437. begin
  438.   FileName := ParamStr (0);
  439.   Writeln ('Writing configuration to ', FileName);
  440.   Assign (ExeFile, FileName);
  441.   Reset (ExeFile, 1);
  442.   Seek      (ExeFile, 8);
  443.   Blockread (ExeFile, HeaderSize, Sizeof (HeaderSize));
  444.   Seek      (ExeFile, Longint(16) * (seg(ConfigData)
  445.             - PrefixSeg + HeaderSize) + ofs (ConfigData) - 256);
  446.   Blockwrite (ExeFile, ConfigData, sizeof (ConfigData));
  447.   Close      (ExeFile);
  448. end;
  449.  
  450. Procedure SaveReg;
  451. Var
  452.   ExeFile    : file;
  453.   HeaderSize : word;
  454.   FileName : String;
  455.  
  456. begin
  457.   FileName := ParamStr (0);
  458.   Writeln ('Writing registration info. to ', FileName, '.');
  459.   Assign (ExeFile, FileName);
  460.   Reset (ExeFile, 1);
  461.   Seek      (ExeFile, 8);
  462.   Blockread (ExeFile, HeaderSize, Sizeof (HeaderSize));
  463.   Seek      (ExeFile, Longint(16) * (seg(RegisterData)
  464.             - PrefixSeg + HeaderSize) + ofs (RegisterData) - 256);
  465.   Blockwrite (ExeFile, RegisterData, sizeof (RegisterData));
  466.   Close      (ExeFile);
  467. end;
  468.  
  469. Procedure Enter_Reg;
  470. begin
  471.   Writeln;
  472.   Writeln ('TOPLink Registration'); Writeln;
  473.   Writeln('Your registration code and named will be saved to the file');
  474.   Writeln(ParamStr(0), '.');
  475.   Writeln;
  476.   Write ('Your name (please note it is case sensitive): ');
  477.   Readln (RegisterData.TheName);
  478.   Write ('Registration Code: ');
  479.   Readln (RegisterData.TheReg);
  480.   Writeln;
  481.   Check_Register;
  482.   If Registered then Writeln ('The registration code checks out.  Thank you for registering!')
  483.   else
  484.   begin
  485.     Writeln ('The registration code doesn''t check out.  Make sure you''ve entered');
  486.     Writeln ('everything correctly!'+#7);
  487.     Writeln;
  488.     Writeln ('Name and registration code not saved.');
  489.     Halt (1);
  490.   end;
  491.   Writeln;
  492.   If Not FExists (ParamStr (0)) then Writeln ('Error: The file '+ParamStr(0)+' could not be written to.'+#7)
  493.   else SaveReg;
  494. end;
  495.  
  496. Procedure ConfigureTOPLink;
  497. begin
  498.   InitCFGScr;
  499.   GetCFGChoice;
  500.   If Ask2Save then
  501.   begin
  502.     SaveConfig;
  503.   end;
  504.   Writeln('TOPLink'+ProgVerStr+' Configuration ended.');
  505.   Writeln('Copyright 1996 Paul Sidorsky, ISMWare.  All Rights Reserved.');
  506.   Writeln('Original Configuration Copyright 1994 by David Ong.');
  507. end;
  508.  
  509. Procedure Init_Program;
  510. Var
  511.   Error : Integer;
  512. begin
  513.   Writeln;
  514.   Writeln ('TOPLink'+ProgVerStr+' - Links TOP to another teleconference over the modem!');
  515.   Writeln ('Copyright 1996 Paul Sidorsky, ISMWare.');
  516.   Writeln ('Original program Copyright 1994 by David Ong.');
  517.   Writeln;
  518.   If UpStr(ParamStr (1)) = '/CONFIG' then
  519.   begin
  520.     ConfigureTOPLink;
  521.     Halt;
  522.   end;
  523.   If UpStr(ParamStr (1)) = '/REGISTER' then
  524.   begin
  525.     Enter_Reg;
  526.     Halt;
  527.   end;
  528.   If ParamCount < 3 then
  529.   begin
  530.     Writeln ('Command line parameter(s) missing!');
  531.     Writeln;
  532.     Writeln ('Usage: TOPLINK <comport> <BBS Name> <work path> <node>');
  533.     Writeln;
  534.     Writeln ('<comport>    Is the com port you are going to use.');
  535.     Writeln ('             COM1 = 1, COM2 = 2, etc.');
  536.     Writeln ('<BBS Name>   Is the name of the BBS you are linking too');
  537.     Writeln ('<work path>  Is the path to TOP''s work directory.');
  538.     Writeln ('<node>       Is the node number that TOPLink should use (0-255)');
  539.     Writeln;
  540.     Writeln ('Eg: TOPLINK 2 ISMWare d:\top\workdir 4');
  541.     Writeln ('For further help refer to TOPLINK.DOC');
  542.     Halt;
  543.   end;
  544.   Val (ParamStr(1), Com, Error);
  545.   If Error <> 0 then
  546.   begin
  547.     Writeln ('Invalid COM port passed!');
  548.     Halt;
  549.   end;
  550.   BBSName := ParamStr(2);
  551.   If BBSName[0] > #30 then BBSName[0] := #30;
  552.   IPCDir := ParamStr(3);
  553.   If IPCDir[Length(IPCDir)] <> '\' then IPCDir := IPCDir + '\';
  554.   If not FExists (IPCDir + 'NODEIDX.TCH') then
  555.   begin
  556.     Writeln ('Error: The NODEIDX.TCH file was not found in the ', UpStr(IPCDir), ' directory!');
  557.     Writeln ('Make sure TOP uses the same work path and has been previously run or is'#13#10'currently running.');
  558.     Halt;
  559.   end;
  560.   If not FExists (IPCDir + 'NODEIDX2.TCH') then
  561.   begin
  562.     Writeln ('Error: The NODEIDX2.TCH file was not found in the ', UpStr(IPCDir), ' directory!');
  563.     Writeln ('Make sure TOP uses the same work path and has been previously run or is'#13#10'currently running.');
  564.     Halt;
  565.   end;
  566. end;
  567.  
  568. Function CmdLineNode : byte;
  569. Var
  570.   L : Integer;
  571.   Error : Integer;
  572. begin
  573.   Val (ParamStr(4), L, Error);
  574.   If (Error <> 0) or (L <= 0) or (L > 255) then
  575.   begin
  576.     Writeln ('Invalid node passed!');
  577.     Writeln ('Node must be from 0 to 255');
  578.     Halt;
  579.   end;
  580.   CmdLineNode := L;
  581. end;
  582.  
  583. Procedure TakeNode;
  584. Var
  585.   L : byte;
  586.   B : byte;
  587.   f : File of byte;
  588.   IDXFile : File of IDXRec;
  589.   IDXData : IDXRec;
  590. begin
  591.   L := 0;
  592.   Assign (f, IPCDir + 'MSG'+NodeStr+'.TCH');
  593.   Rewrite (f);
  594.   Close (f);
  595.   Assign (f, IPCDir + 'MIX'+NodeStr+'.TCH');
  596.   Rewrite (f);
  597.   Close (f);
  598.   Assign (F, IPCDir + 'NODEIDX2.TCH');
  599.   Reset (f);
  600.   Repeat Until FLock(RecLock, FileRec(f).Handle, Node, 1) = 0;
  601.   Seek (f, Node);
  602.   b := 1;
  603.   {$I-}
  604.   Repeat
  605.     Write (f,b);
  606.   Until IOResult = 0;
  607.   {$I+}
  608.   Repeat Until FLock(RecUnlock, FileRec(f).Handle, Node, 1) = 0;
  609.   Close (f);
  610.   Assign (IDXFile, IPCDir + 'NODEIDX.TCH');
  611.   Reset (IDXFile);
  612.   Repeat Until FLock(RecLock, FileRec(IDXFile).Handle, Node * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  613.   Seek (IDXFile, Node);
  614.   FillChar (IDXData, SizeOf(IDXData), #0);
  615.   IDXData.StructLength := SizeOf(IDXData);
  616.   IDXData.Alias := 'APLink'+ProgVerStr+#0;
  617.   IDXData.Alias[0] := 'R';
  618.   IDXData.RealName := 'APLink'#0;
  619.   IDXData.RealName[0] := 'R';
  620.   IDXData.Baud := 0;
  621.   If registered then
  622.   begin
  623.     IDXData.Location := 'egistered'+#0;
  624.     IDXData.Location[0] := 'R';
  625.   end
  626.   else
  627.   begin
  628.     IDXData.Location := 'NREGISTERED'+#0;
  629.     IDXData.Location[0] := 'U';
  630.   end;
  631.   IDXData.Gender := 0;
  632.   IDXData.Quiet := False;
  633.   IDXData.Task := 0;
  634.   IDXData.LastAccess := TodayInUnix;
  635.   IDXData.Channel := ConfigData.Channel;
  636.   IDXData.ChannelListed := True;
  637.   IDXData.Security := 65535;
  638.   IDXData.Actions := True;
  639.   {$I-}
  640.   Repeat
  641.     Write (IDXFile, IDXData);
  642.   Until IOResult = 0;
  643.   {$I+}
  644.   Repeat Until FLock(RecUnlock, FileRec(IDXFile).Handle, Node * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  645.   Close (IDXFile);
  646. end;
  647.  
  648. Procedure SendMSG (N : Word; NodeData : NodeRec);
  649. Var
  650.   b : byte;
  651.   f : File of byte;
  652.   NodeFile : File of NodeRec;
  653.   X : Integer;
  654. begin
  655.   Assign (f, IPCDir + 'MIX' + PaddedNum(N)+'.TCH');
  656.   Reset (f);
  657.   b := 0;
  658.   X := 0;
  659.   If not Eof (f) then
  660.   begin
  661.     Repeat
  662.       {$I-}
  663.       Repeat Until FLock(RecLock, FileRec(f).Handle, X, 1) = 0;
  664.       Repeat
  665.         Read (f,b);
  666.       Until IOResult = 0;
  667.       {$I+}
  668.       Repeat Until FLock(RecUnlock, FileRec(f).Handle, X, 1) = 0;
  669.       Inc(X);
  670.       If Eof (f) then
  671.       begin
  672.         Repeat Until FLock(RecLock, FileRec(f).Handle, X, 1) = 0;
  673.         b := 0;
  674.         Write (f,b);
  675.         Repeat Until FLock(RecUnlock, FileRec(f).Handle, X, 1) = 0;
  676.       end;
  677.     Until B = 0;
  678.   end
  679.   else
  680.   begin
  681.     Repeat Until FLock(RecLock, FileRec(f).Handle, X, 1) = 0;
  682.     Write (f,b);
  683.     Repeat Until FLock(RecUnlock, FileRec(f).Handle, X, 1) = 0;
  684.     Inc(X);
  685.   end;
  686.   b := 1;
  687.   Dec(X);
  688.   Repeat Until FLock(RecLock, FileRec(f).Handle, X, 1) = 0;
  689.   Seek (f, FilePos(f) - 1);
  690.   {$I-}
  691.   Repeat
  692.     Write (f,b);
  693.   Until IOResult = 0;
  694.   {$I+}
  695.   Assign (NodeFile, IPCDir + 'MSG' + PaddedNum(N)+'.TCH');
  696.   Reset (NodeFile);
  697.   Repeat Until FLock(RecLock, FileRec(NodeFile).Handle, X * SizeOf(NodeData), SizeOf(NodeData)) = 0;
  698.   Seek (NodeFile, FilePos(f) - 1);
  699.   {$I-}
  700.   Repeat
  701.     Write (NodeFile, NodeData);
  702.   Until IOResult = 0;
  703.   {$I+}
  704.   Repeat Until FLock(RecUnlock, FileRec(NodeFile).Handle, X * SizeOf(NodeData), SizeOf(NodeData)) = 0;
  705.   Close (NodeFile);
  706.   Repeat Until FLock(RecUnlock, FileRec(f).Handle, X, 1) = 0;
  707.   Close (f);
  708.   Assign (F, IPCDir + 'CHGIDX.TCH');
  709.   Reset (f);
  710.   Seek (f, N);
  711.   b := 1;
  712.   {$I-}
  713.   Repeat
  714.     Write (f,b);
  715.   Until IOResult = 0;
  716.   {$I+}
  717.   Close (f);
  718. end;
  719.  
  720. Procedure BroadCast (T : Integer; Alias : Str30; Data : Str255);
  721. Var
  722.   IDX2 : File of byte;
  723.   L : Word;
  724.   b : byte;
  725. begin
  726.   FillChar (NodeData, SizeOf(NodeData), #0);
  727.   Alias := Alias + #0;
  728.   Data := Data + #0;
  729.   NodeData.StructLength := SizeOf(NodeData);
  730.   NodeData.Kind := T;
  731.   NodeData.From := Node;
  732.   NodeData.Doneto := -1;
  733.   NodeData.Gender := 0;
  734.   NodeData.Alias := Minus1 (Alias);
  735.   NodeData.Alias[0] := Alias[1];
  736.   NodeData.Data := Minus1 (Data);
  737.   NodeData.Data[0] := Data[1];
  738.   NodeData.Channel := ConfigData.Channel;
  739.   NodeData.MinSec := ConfigData.MinSecurity;
  740.   NodeData.MaxSec := 65535;
  741.   NodeData.Data1 := 0;
  742.   Assign (IDX2, IPCDir + 'NODEIDX2.TCH');
  743.   {$I-}
  744.   Repeat
  745.     Reset (IDX2);
  746.   Until IOResult = 0;
  747.   {$I+}
  748.   For L := 0 to (ConfigData.MaxNodes - 1) do
  749.   begin
  750.     {$I-}
  751.     Repeat Until FLock(RecLock, FileRec(IDX2).Handle, FilePos(IDX2), 1) = 0;
  752.     Repeat
  753.       Read (IDX2, b);
  754.     Until IOResult = 0;
  755.     {$I+}
  756.     Repeat Until FLock(RecUnlock, FileRec(IDX2).Handle, FilePos(IDX2), 1) = 0;
  757.     If (L <> Node) and (b=1) then SendMSG (L, NodeData);
  758.   end;
  759.   Close (IDX2);
  760. end;
  761.  
  762. Procedure Init_TOP;
  763. begin
  764.   Node := CmdLineNode;
  765.   Writeln ('Logging onto TOP as node ', Node);
  766.   Str (Node, NodeStr);
  767.   NodeStr := PaddedNum (Node);
  768.   TakeNode;
  769.   BroadCast (2, 'TOPLink'+ProgVerStr, ''); { TOPLink enters Pub }
  770.   Fos_Init (Com);
  771.   Delay (900);
  772. end;
  773.  
  774. Procedure Init_Screen;
  775. Var
  776.   L : Word;
  777. begin
  778.   TextAttr := $71;  { Grey on blue }
  779.   ClrScr;
  780.   { Put background in, skipping the bottom line to create a status bar }
  781.   For L := 1 to 1920 do Write ('░');
  782.   TextAttr := $74;
  783.   GotoXY (1,1);   ClrEol;
  784.   GotoXY (1,1);  Writeln ('  TOPLink'+ProgVerStr+' Copyright 1996 Paul Sidorsky, ISMWare.  All Rights Reserved.');
  785.   WindowBorder (2,3,77,19, White, Blue);
  786.   GotoXY (5,3);
  787.   Write (' Com Port: ', Com, ' ');
  788.   GotoXY (60,3);
  789.   Write (' Node: ', Node, ' ');
  790.   GotoXY (72,3); Write ('┬');
  791.   For L := 4 to 18 do
  792.   begin
  793.     GotoXY (72,L);
  794.     Write ('│');
  795.   end;
  796.   WindowBorder (2,19,77,23, White, Blue);
  797.   GotoXY (2,19); Write ('├');
  798.   GotoXY (72,19); Write ('┴');
  799.   GotoXY (77,19); Write ('┤');
  800.   GotoXY (3,20);
  801.   Textcolor (lightcyan);  Write ('L');
  802.   Textcolor (15); Write (')inked to: ');
  803.   Textcolor (Yellow); Write (BBSName);
  804.   GotoXY (3,21);
  805.   Textcolor (lightcyan);  Write ('A');
  806.   Textcolor (15); Write (')nsi Stripping is: ');
  807.   Textcolor (Yellow);
  808.   If ConfigData.StripAnsi then Write ('On ') else Write ('Off');
  809.   GotoXY (40,21);
  810.   Textcolor (lightcyan);  Write ('B');
  811.   Textcolor (15); Write (')BS Name Displaying is: ');
  812.   Textcolor (Yellow);
  813.   If ConfigData.ShowBBSName then Write ('On ') else Write ('Off');
  814.   GotoXY (3,22);
  815.   Textcolor (lightcyan);  Write ('S');
  816.   Textcolor (15); Write (')end TOP codes: ');
  817.   Textcolor (Yellow);
  818.   If ConfigData.StripTOP then Write ('Off ') else Write ('On ');
  819.   GotoXY (40,22);
  820.   Textcolor (lightcyan);  Write ('D');
  821.   Textcolor (15); Write (')irect Text is: ');
  822.   Textcolor (Yellow);
  823.   If ConfigData.DCommandsOn then Write ('On ') else Write ('Off');
  824.   If not registered then
  825.   begin
  826.     GotoXY (67,25);
  827.     Textcolor (Red+Blink);
  828.     Textbackground (LightGray);
  829.     Write ('Unregistered');
  830.   end
  831.   else
  832.   begin
  833.     GotoXY (67,25);
  834.     Textcolor (Red);
  835.     Textbackground (LightGray);
  836.     Write ('Registered');
  837.   end;
  838.   GotoXY (2,25);
  839.   Textcolor (0);
  840.   Write ('<ESC> Exits TOPLink and disengages the link');
  841. end;
  842.  
  843. Procedure Turn2Link;
  844. Var
  845.   IDXFile : File of IDXRec;
  846.   IDXData : IDXRec;
  847. begin
  848.   Assign (IDXFile, IPCDir + 'NODEIDX.TCH');
  849.   Reset (IDXFile);
  850.   Repeat Until FLock(RecLock, FileRec(IDXFile).Handle, Node * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  851.   Seek (IDXFile, Node);
  852.   FillChar (IDXData, SizeOf(IDXData), #0);
  853.   IDXData.StructLength := SizeOf(IDXData);
  854.   IDXData.Alias := Minus1 (BBSName)+#0;
  855.   IDXData.Alias[0] := BBSName[1];
  856.   IDXData.RealName := 'OPLink'#0;
  857.   IDXData.RealName[0] := 'T';
  858.   IDXData.Baud := 0;
  859.   If registered then
  860.   begin
  861.     IDXData.Location := 'egistered'+#0;
  862.     IDXData.Location[0] := 'R';
  863.   end
  864.   else
  865.   begin
  866.     IDXData.Location := 'NREGISTERED'+#0;
  867.     IDXData.Location[0] := 'U';
  868.   end;
  869.   IDXData.Gender := 0;
  870.   IDXData.Quiet := False;
  871.   IDXData.Task := 0;
  872.   IDXData.LastAccess := TodayInUnix;
  873.   IDXData.Channel := ConfigData.Channel;
  874.   IDXData.ChannelListed := True;
  875.   IDXData.Security := 65535;
  876.   IDXData.Actions := True;
  877.   {$I-}
  878.   Repeat
  879.     Write (IDXFile, IDXData);
  880.   Until IOResult = 0;
  881.   {$I+}
  882.   Repeat Until FLock(RecUnlock, FileRec(IDXFile).Handle, Node * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  883.   Close (IDXFile);
  884.   BroadCast (22, 'TOPLink'+ProgVerStr, BBSName);
  885. end;
  886.  
  887. Function MSGWait : boolean;
  888. Var
  889.   b : byte;
  890.   f : File of byte;
  891. begin
  892.   Assign (f, IPCDir + 'CHGIDX.TCH');
  893.   Reset (f);
  894.   Repeat Until FLock(RecLock, FileRec(f).Handle, Node, 1) = 0;
  895.   Seek (f, Node);
  896.   {$I-}
  897.   Repeat
  898.     Read (f,b);
  899.   Until IOResult = 0;
  900.   {$I+}
  901.   Repeat Until FLock(RecUnlock, FileRec(f).Handle, Node, 1) = 0;
  902.   MSGWait := b = 1;
  903.   Close (f);
  904. end;
  905.  
  906. Function NodeUser (I : Integer) : String;
  907. Var
  908.   IDXFile : File of IDXRec;
  909.   IDXData : IDXRec;
  910. begin
  911.   If I >= 0 then
  912.   begin
  913.     Assign (IDXFile, IPCDir + 'NODEIDX.TCH');
  914.     Reset (IDXFile);
  915.     Repeat Until FLock(RecLock, FileRec(IDXFile).Handle, I * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  916.     Seek (IDXFile, I);
  917.     {$I-}
  918.     Repeat
  919.       Read (IDXFile, IDXData);
  920.     Until IOResult = 0;
  921.     {$I+}
  922.     NodeUser := CStr (IDXData.Alias);
  923.     Repeat Until FLock(RecUnlock, FileRec(IDXFile).Handle, I * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  924.     Close (IDXFile);
  925.   end
  926.   else NodeUser := 'everyone';
  927. end;
  928.  
  929. Function NodeGender (I : Integer) : Boolean;
  930. Var
  931.   IDXFile : File of IDXRec;
  932.   IDXData : IDXRec;
  933. begin
  934.   If I >= 0 then
  935.   begin
  936.     Assign (IDXFile, IPCDir + 'NODEIDX.TCH');
  937.     Reset (IDXFile);
  938.     Repeat Until FLock(RecLock, FileRec(IDXFile).Handle, I * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  939.     Seek (IDXFile, I);
  940.     {$I-}
  941.     Repeat
  942.       Read (IDXFile, IDXData);
  943.     Until IOResult = 0;
  944.     {$I+}
  945.     Repeat Until FLock(RecUnlock, FileRec(IDXFile).Handle, I * SizeOf(IDXData), SizeOf(IDXData)) = 0;
  946.     Close (IDXFile);
  947.     NodeGender := IDXData.Gender = 1;
  948.   end
  949.   else NodeGender := False;
  950. end;
  951.  
  952. Function ReplaceAll (s : String) : String;
  953. Var
  954.   Replace : String;
  955.   p : byte;
  956. begin
  957.   While Pos ('%m', s) <> 0 do
  958.   begin
  959.     Replace := Cstr(NodeData.Alias);
  960.     p := Pos ('%m',s);
  961.     Delete (s, p, 2);
  962.     Insert (Replace, s, p);
  963.   end;
  964.   While Pos ('%y', s) <> 0 do
  965.   begin
  966.     If NodeData.DoneTo = Node then Replace := 'you' else
  967.     Replace := NodeUser(NodeData.DoneTo);
  968.     p := Pos ('%y',s);
  969.     Delete (s, p, 2);
  970.     Insert (Replace, s, p);
  971.   end;
  972.   While Pos ('%h', s) <> 0 do
  973.   begin
  974.     If NodeGender (NodeData.From) then Replace := 'her'
  975.     else Replace := 'his';
  976.     p := Pos ('%h',s);
  977.     Delete (s, p, 2);
  978.     Insert (Replace, s, p);
  979.   end;
  980.   While Pos ('%s', s) <> 0 do
  981.   begin
  982.     If NodeData.DoneTo = Node then Replace := 'r'
  983.     else Replace := '''s';
  984.     p := Pos ('%s',s);
  985.     Delete (s, p, 2);
  986.     Insert (Replace, s, p);
  987.   end;
  988.   While Pos ('%f', s) <> 0 do
  989.   begin
  990.     If NodeGender (NodeData.From) then Replace := 'herself'
  991.     else Replace := 'himself';
  992.     p := Pos ('%f',s);
  993.     Delete (s, p, 2);
  994.     Insert (Replace, s, p);
  995.   end;
  996.   While Pos ('%e', s) <> 0 do
  997.   begin
  998.     If NodeGender (NodeData.From) then Replace := 'she'
  999.     else Replace := 'he';
  1000.     p := Pos ('%e',s);
  1001.     Delete (s, p, 2);
  1002.     Insert (Replace, s, p);
  1003.   end;
  1004.   ReplaceAll := s;
  1005. end;
  1006.  
  1007. Procedure Send2Scr (MSG : String; LocalMSG : String; SendFos : Boolean);
  1008. Var
  1009.   X, Y : byte;
  1010.   L : Word;
  1011.   Save : Word;
  1012. begin
  1013.   Save := TextAttr;
  1014.   Textbackground (0); Textcolor (15);
  1015.   X := WhereX; Y := WhereY;
  1016.   If SendFos then Fos_String (Com, MSG, ConfigData.SendDelay);
  1017.   For L := 1 to Length (msg) do Ansi_Write (Msg[L]);
  1018.   If Y <> 15 then
  1019.   begin
  1020.     Ansi_Write (#13);   Ansi_Write (#10);
  1021.   end;
  1022.   Window (73,4,77,18);
  1023.   GotoXY (1, Y);
  1024.   Textbackground (1); Textcolor (Yellow);
  1025.   Write (LocalMSG);
  1026.   Window (3,4,71,18);
  1027.   GotoXY (X,Y+1);
  1028.   If Y = 15 then
  1029.   begin
  1030.     asm
  1031.     Mov ah,6
  1032.     mov al,1
  1033.     mov ch,3
  1034.     mov cl,2
  1035.     mov dh,17
  1036.     mov dl,70
  1037.     mov bh,$0F
  1038.     int $10     { Scroll Screen }
  1039.     end;
  1040.     asm
  1041.     Mov ah,6
  1042.     mov al,1
  1043.     mov ch,3
  1044.     mov cl,72
  1045.     mov dh,17
  1046.     mov dl,75
  1047.     mov bh,$1F
  1048.     int $10     { Scroll Screen }
  1049.     end;
  1050.     GotoXY (1,15);
  1051.   end;
  1052.   TextAttr := Save;
  1053. end;
  1054.  
  1055. Procedure Send (NodeData : NodeRec);
  1056. Var
  1057.   s : string;
  1058.   L : byte;
  1059.   NodeData2 : NodeRec;
  1060. begin
  1061.   s := '';
  1062.   If (NodeData.Kind = 6) and (NodeData.Data[0] = '*') then
  1063.   begin
  1064.     For L := 1 to 255 do
  1065.       s[l-1] := NodeData.Data[l];
  1066.     s := CStr (s);
  1067.     If ConfigData.DCommandsOn then Send2Scr (S+#13,'DTxt',True);
  1068.     FillChar (NodeData2, SizeOf(NodeData2), #0);
  1069.     NodeData2.StructLength := SizeOf(NodeData2);
  1070.     NodeData2.Kind := 35;
  1071.     NodeData2.From := Node;
  1072.     NodeData2.Doneto := -1;
  1073.     NodeData2.Gender := 0;
  1074.     NodeData2.Alias := Minus1 (BBSName)+#0;
  1075.     NodeData2.Alias[0] := BBSName[1];
  1076.     If ConfigData.DCommandsOn then
  1077.     begin
  1078.       NodeData2.Data := '- Direct Text Sent --'+#0;
  1079.       NodeData2.Data[0] := '-';
  1080.     end
  1081.     else
  1082.     begin
  1083.       NodeData2.Data := '- Direct Text is ^^0FOFF^^0C --'+#0;
  1084.       NodeData2.Data[0] := '-';
  1085.     end;
  1086.     NodeData2.Channel := ConfigData.Channel;
  1087.     NodeData2.MinSec := ConfigData.MinSecurity;
  1088.     NodeData2.MaxSec := 65535;
  1089.     SendMSG (NodeData.From, NodeData2);
  1090.   end
  1091.   else if NodeData.Kind = 48 then
  1092.   begin
  1093.     NodeData2.Kind := 49;
  1094.     NodeData2.From := Node;
  1095.     NodeData2.DoneTo := -1;
  1096.     NodeData2.Gender := 0;
  1097.     NodeData2.Alias := Minus1(BBSName)+#0;
  1098.     NodeData2.Alias[0] := BBSName[1];
  1099.     NodeData2.Data := '';
  1100.     NodeData2.Data[0] := #0;
  1101.     NodeData2.Channel := ConfigData.Channel;
  1102.     NodeData2.MinSec := 0;
  1103.     NodeData2.MaxSec := 65535;
  1104.     SendMsg(NodeData.From, NodeData2);
  1105.   end
  1106.   else
  1107.   begin
  1108.     Case NodeData.Kind of
  1109.       1 : s := 'From '+CStr(NodeData.Alias)+ ': '+ CStr(NodeData.Data);
  1110.       2 : s := CStr(NodeData.Alias) + ' just entered the teleconference.';
  1111.       3 : s := CStr(NodeData.Alias) + ' just left the teleconference.';
  1112.       4 : s := CStr (NodeData.Alias) + ' has entered the Profile Editor.';
  1113.       5 : s := CStr (NodeData.Alias) + ' has returned from the Profile Editor.';
  1114.       7 : s := CStr(NodeData.Alias) + ' '+CStr (NodeData.Data);
  1115.       8 : s := CStr(NodeData.Alias) + '''s ' + CStr (NodeData.Data);
  1116.       9,10,11,12 :
  1117.       begin
  1118.         if (NodeData.Data[0] <> '%') AND ((NodeData.Data[1] <> 'P') AND (NodeData.Data[1] <> 'p')) then
  1119.           s := ReplaceAll(CStr(NodeData.Data));
  1120.       end;
  1121.       16 : s := CStr (NodeData.Alias)+' has changed genders and is now '
  1122.            +CStr(NodeData.Data)+'.';
  1123.       19 : s := CStr(NodeData.Alias)+' has just vanished from the teleconference.';
  1124.       22 : s := CStr(NodeData.Alias)+' has just transformed into a link to '
  1125.            +Cstr(NodeData.Data)+'.';
  1126.       23 : s := '('+ NodeUser(NodeData.From)+'): '+CStr(NodeData.Data);
  1127.       24 : s := 'The link to '+CStr(NodeData.Data)+' has just disintegrated.';
  1128.       26 : s := CStr(NodeData.Alias)+' has just been tossed out of the teleconference.';
  1129.       27 : s := CStr(NodeData.Alias)+' has just been zapped off of the system.';
  1130.       35 : s := CStr(NodeData.Data);
  1131.       36 : s := CStr(NodeData.Alias)+' has just entered this channel.';
  1132.       37 : s := CStr(NodeData.Alias)+' has just changed to a different channel.';
  1133.       39 : s := 'From '+NodeUser(NodeData.From)+', to '+NodeUser(NodeData.DoneTo)+': '+CStr(NodeData.Data);
  1134.       46 : s := CStr(NodeData.Alias)+' has just entered a private chat.';
  1135.       47 : s := CStr(NodeData.Alias)+' has just returned from a private chat.';
  1136.       50 : s := CStr(NodeData.Alias)+' has just changed the channel topic to "'+CStr(NodeData.Data)+'".';
  1137.       55 : s := CStr(NodeData.Alias)+' has just appointed '+NodeUser(NodeData.DoneTo)+' as a channel moderator.';
  1138.     end;
  1139.     If s <> '' then
  1140.     begin
  1141.       s := FC + s + BC;
  1142.       If ConfigData.StripTOP then s := KillTOPCodes (s);
  1143.       Send2Scr (S+#13, 'Sent',True);
  1144.     end;
  1145.   end;
  1146. end;
  1147.  
  1148. Procedure GetMSGs;
  1149. Var
  1150.   b : byte;
  1151.   z : byte;
  1152.   f : file of byte;
  1153.   X : Integer;
  1154.   NodeFile : File of NodeRec;
  1155. begin
  1156.   z := 0;
  1157.   X := 0;
  1158.   Assign (f, IPCDir + 'MIX'+NodeStr+'.TCH');
  1159.   Assign (NodeFile, IPCDir + 'MSG'+NodeStr+'.TCH');
  1160.   Reset (f);
  1161.   Reset (NodeFile);
  1162.   Repeat
  1163.     Repeat Until FLock(RecLock, FileRec(f).Handle, X, 1) = 0;
  1164.     {$I-}
  1165.     Repeat
  1166.       Read (f,b);
  1167.     Until IOResult = 0;
  1168.     if b = 1 then
  1169.     begin
  1170.       Seek (f, FilePos (f) - 1);
  1171.       Repeat
  1172.         Write (f,z);
  1173.       Until IOResult = 0;
  1174.       Repeat Until FLock(RecLock, FileRec(NodeFile).Handle, X * SizeOf(NodeData), SizeOf(NodeData)) = 0;
  1175.       Seek(NodeFile, X);
  1176.       Repeat
  1177.         Read (NodeFile, NodeData);
  1178.       Until IOResult = 0;
  1179.       Repeat Until FLock(RecUnlock, FileRec(NodeFile).Handle, X * SizeOf(NodeData), SizeOf(NodeData)) = 0;
  1180.       Send (NodeData);
  1181.     end;
  1182.     {$I+}
  1183.     Repeat Until FLock(RecUnlock, FileRec(f).Handle, X, 1) = 0;
  1184.     Inc(X);
  1185.   Until Eof (f);
  1186.   Close (f);
  1187.   Close (NodeFile);
  1188.   b := 0;
  1189.   Assign (f, IPCDir + 'CHGIDX.TCH');
  1190.   Reset (f);
  1191.   Seek (f, Node);
  1192.   {$I-}
  1193.   Repeat
  1194.     Write (f,b);
  1195.   Until IOResult = 0;
  1196.   {$I+}
  1197.   Close (f);
  1198. end;
  1199.  
  1200. Procedure Process (ch : Char);
  1201. Var
  1202.   Save : Word;
  1203.   X,Y : byte;
  1204.   Old : String;
  1205. begin
  1206.   Save := TextAttr;
  1207.   X := WhereX; Y := WhereY;
  1208.   Window (1,1,80,25);
  1209.   Case ch of
  1210.     'A' :
  1211.     begin
  1212.       ConfigData.StripAnsi := not ConfigData.StripAnsi;
  1213.       Textbackground (blue);
  1214.       GotoXY (3,21);
  1215.       Textcolor (lightcyan);  Write ('A');
  1216.       Textcolor (15); Write (')nsi Stripping is: ');
  1217.       Textcolor (Yellow);
  1218.       If ConfigData.StripAnsi then Write ('On ') else Write ('Off');
  1219.     end;
  1220.     'B' :
  1221.     begin
  1222.       ConfigData.ShowBBSName := Not ConfigData.ShowBBSName;
  1223.       Textbackground (blue);
  1224.       GotoXY (40,21);
  1225.       Textcolor (lightcyan);  Write ('B');
  1226.       Textcolor (15); Write (')BS Name Displaying is: ');
  1227.       Textcolor (Yellow);
  1228.       If ConfigData.ShowBBSName then Write ('On ') else Write ('Off');
  1229.     end;
  1230.     'L':
  1231.     begin
  1232.       Old := BBSName;
  1233.       Textbackground (blue); Textcolor (LightCyan);
  1234.       GotoXY (15,20);
  1235.       GetString (BBSName, 29, BBSName);
  1236.       If Old <> BBSName then Turn2Link;
  1237.       GotoXY (3,20);
  1238.       Textcolor (lightcyan);  Write ('L');
  1239.       Textcolor (15); Write (')inked to: ');
  1240.       Textcolor (Yellow); Write (BBSName, Spaces (31 - Length(BBSName)));
  1241.     end;
  1242.     'S':
  1243.     begin
  1244.       ConfigData.StripTOP := not ConfigData.StripTOP;
  1245.       Textbackground (blue);
  1246.       GotoXY (3,22);
  1247.       Textcolor (lightcyan);  Write ('S');
  1248.       Textcolor (15); Write (')end TOP codes: ');
  1249.       Textcolor (Yellow);
  1250.       If ConfigData.StripTOP then Write ('Off ') else Write ('On ');
  1251.     end;
  1252.     '$' :
  1253.     begin
  1254.       SaveScreen (SavedScr);
  1255.       TextAttr := $07;
  1256.       ClrScr;
  1257.       Writeln;
  1258.       Writeln ('Type EXIT to return to TOPLink...');
  1259.       SwapVectors;
  1260.       Exec (GetEnv ('COMSPEC'), '');
  1261.       SwapVectors;
  1262.       RestoreScreen (SavedScr);
  1263.     end;
  1264.     'D' :
  1265.     begin
  1266.       ConfigData.DCommandsOn := not ConfigData.DCommandsOn;
  1267.       GotoXY (40,22);
  1268.       Textbackground (blue);
  1269.       Textcolor (lightcyan);  Write ('D');
  1270.       Textcolor (15); Write (')irect Text is: ');
  1271.       Textcolor (Yellow);
  1272.       If ConfigData.DCommandsOn then Write ('On ') else Write ('Off');
  1273.     end;
  1274.   end;
  1275.   Window (3,4,71,18);
  1276.   TextAttr := Save;
  1277.   GotoXY (X,Y);
  1278. end;
  1279.  
  1280. Function InSkips (s : String) : Boolean;
  1281. Var
  1282.   L : byte;
  1283.   IsIn : Boolean;
  1284. begin
  1285.   IsIn := False;
  1286.   For L := 1 to 50 do
  1287.     If s = Skips[L] then IsIn := True;
  1288.   InSkips := IsIn;
  1289. end;
  1290.  
  1291. Procedure TOPCommands (s : string);
  1292. Var
  1293.   F : File of byte;
  1294.   L : Word;
  1295.   b : byte;
  1296.   Names : String;
  1297.  
  1298. begin
  1299.   s := UpStr (s);
  1300.   If Pos ('(TOP:WHO)', s) <> 0 then
  1301.   begin
  1302.     Send2Scr (FC+'Looking around '+ConfigData.SystemName+' you see:'+BC+#13,'-Who',True);
  1303.     Assign (F, IPCDir + 'NODEIDX2.TCH');
  1304.     Reset (f);
  1305.     Names := '';
  1306.     For L := 0 to (ConfigData.MaxNodes - 1) do
  1307.     begin
  1308.       Repeat Until FLock(RecLock, FileRec(f).Handle, L, 1) = 0;
  1309.       {$I-}
  1310.       Repeat
  1311.         Read (f,b);
  1312.       Until IOResult = 0;
  1313.       {$I+}
  1314.       If (b = 1) and (L <> Node) then Names := Names + NodeUser (L) + ', ';
  1315.       If Length (Names) > 220 then
  1316.       begin
  1317.         Names := Names + ',';
  1318.         Send2Scr (FC+Names+BC+#13,'-Who', True);
  1319.         Names := '';
  1320.       end;
  1321.       Repeat Until FLock(RecUnlock, FileRec(f).Handle, L, 1) = 0;
  1322.     end;
  1323.     Dec (Names[0],2);
  1324.     Names := Names + '.';
  1325.     Send2Scr (FC+Names+BC+#13,'-Who', True);
  1326.     Close (f);
  1327.   end;
  1328.   If Pos ('(TOP:VER)', s) <> 0 then
  1329.   begin
  1330.     Send2Scr (FC+' TOPLink'+ProgVerStr+' (c) 1994 by David Ong, All Rights Reserved '+BC+#13,'-Ver',True);
  1331.   end;
  1332. end;
  1333.  
  1334. Procedure LinkMode;
  1335. Var
  1336.   s : String;
  1337.   ch : Char;
  1338.   L : Word;
  1339.   key : Char;
  1340.  
  1341. begin
  1342.   Window (3,4,71,18);
  1343.   s := '';
  1344.   LastTime := MemL[$40:$6C];
  1345.   TextAttr := $0F;
  1346.   ClrScr;
  1347.   Fos_String (Com, #13,0);
  1348.   Delay (100);
  1349.   Send2Scr (FC+' TOPLink'+ProgVerStr+' Activated '+BC+#13, 'Sent', True);
  1350.   Repeat
  1351.     While Fos_Avail(Com) do
  1352.     begin
  1353.       Ch:=Fos_Receive(Com);
  1354.       If not (ch in [#0,#10,#13]) then s := s + ch
  1355.       else
  1356.       begin
  1357.         While s[Length(s)] = #32 do Dec (s[0]);
  1358.         If ConfigData.StripANSI then s := KillAnsi (s);
  1359.         If not (s[1] in [#13,#10])
  1360.         then
  1361.         begin
  1362.           If (KillAnsi(s) <> '') and (s[Ord(s[0])] <> BC)
  1363.           and not InSkips (KillAnsi(s))
  1364.           then
  1365.           begin
  1366.             If ConfigData.ShowBBSName then BroadCast (23, BBSName, s)
  1367.             else BroadCast (9,'',s);
  1368.             Send2Scr (s,'Brod',False);
  1369.             If ConfigData.BBSCommandsOn then TOPCommands (s);
  1370.             Inc (LinesRCVD);
  1371.             If LinesRCVD > 110 then
  1372.             begin
  1373.               If not Registered then
  1374.                 BroadCast (9,'','^^8FThis version of TOPLink is UNREGISTERED!^^0E');
  1375.               LinesRCVD := 0;
  1376.             end;
  1377.           end
  1378.           else
  1379.             If KillAnsi(s) <> '' then Send2Scr (s, 'Rcvd',False);
  1380.         end;
  1381.         s := '';
  1382.       end;
  1383.     end;
  1384.     If MSGWait then GetMSGs;
  1385.     Repeat
  1386.       If ConfigData.GiveTimeSlice then TimeSlice;
  1387.       If Keypressed then
  1388.       begin
  1389.         key := Upcase(Readkey);
  1390.         Process (Key);
  1391.       end;
  1392.     Until ((MemL[$40:$6C] - LastTime) / 18.2) > ConfigData.CheckingDelay;
  1393.     LastTime := MemL[$40:$6C];
  1394.   Until (key = #27) {or not (Fos_Carrier(Com))};
  1395.   Fos_String (Com, #13,0);
  1396.   Send2Scr (FC+' TOPLink'+ProgVerStr+' Deactivated '+BC+#13,'Sent', True);
  1397.   BroadCast (24, 'TOPLink'+ProgVerStr, '');
  1398.   Delay (1000);
  1399.   Window (1,1,80,25);
  1400.   TextAttr := $07;
  1401.   ClrScr;
  1402.   Writeln ('TOPLink'+ProgVerStr+' ended.');
  1403. end;
  1404.  
  1405. Procedure Init_Other;
  1406. Var
  1407.   F : Text;
  1408.   FileName : String;
  1409.   Count : byte;
  1410. begin
  1411.   FileName := ParamStr (0);
  1412.   While (FileName[length (FileName)] <> '\') And (Length (FileName) > 0) do Dec (FileName[0]);
  1413.   FileName := FileName + 'DONTSHOW.TXT';
  1414.   If not FExists (FileName) then
  1415.   begin
  1416.     Writeln;
  1417.     Writeln ('The file: ', FileName, ' could not be found/read');
  1418.     Writeln ('All text will be shown.');
  1419.     Writeln;
  1420.     Delay (5000);
  1421.   end
  1422.   else
  1423.   begin
  1424.     Assign (f, FileName);
  1425.     Reset (f);
  1426.     Count := 1;
  1427.     While not (Eof (f)) and (Count <> 51) do
  1428.     begin
  1429.       Readln (f, Skips[Count]);
  1430.       Inc (Count);
  1431.     end;
  1432.     Close (f);
  1433.   end;
  1434. end;
  1435.  
  1436. Procedure InitVars;
  1437. Var
  1438.   L : byte;
  1439. begin
  1440.   Check_Register;
  1441.   FileMode:=fmReadWrite+FmDenyNone;
  1442.   For L := 1 to 50 do Skips[L] := '';
  1443.   LinesRCVD := 0;
  1444. end;
  1445.  
  1446. Procedure KeepAlive;
  1447. Var
  1448.   F : File of IDXRec;
  1449.   NodeTmp : IDXRec;
  1450.   X : Word;
  1451. begin
  1452.   if TodayInUnix >= (LastPoll + ConfigData.CrashProt) then
  1453.   begin
  1454.     Assign (F, IPCDir + 'NODEIDX.TCH');
  1455.     Reset (F);
  1456.     {$I-}
  1457.     Repeat Until FLock(RecLock, FileRec(F).Handle, (Node * SizeOf(NodeTmp)), SizeOf(NodeTmp)) = 0;
  1458.     Seek(F, Node);
  1459.     Read(F, NodeTmp);
  1460.     NodeTmp.LastAccess := TodayInUnix;
  1461.     Seek(F, Node);
  1462.     Write(F, NodeTmp);
  1463.     Repeat Until FLock(RecUnlock, FileRec(F).Handle, (Node * Sizeof(NodeTmp)), SizeOf(NodeTmp)) = 0;
  1464.     {$I+}
  1465.     Close(F);
  1466.   end;
  1467. end;
  1468.  
  1469. begin
  1470.   InitVars;
  1471.   Init_Program;
  1472.   Init_TOP;
  1473.   Init_Other;
  1474.   Init_Screen;
  1475.   Turn2Link;
  1476.   LinkMode;
  1477.   DeInit;
  1478. end.
  1479.