{Main program for APM News System}

%external %string (79) Copyright %alias "NEWS_(C)_RMM_FDC_85" = -
   "Copyright (C) 1985 Richard M. Marshall and Frank D. Cringle"

%include "News.Inc"
%include "Inc:Util.Imp"
%include "IE:Terminal.Inc"
%include "IE:IE.Inc"
%include "Inc:FS.Imp"
%include "Inc:FSUtil.Imp"
%include "Inc:CharIO.Imp"

%constant %string Introductory Document = "News:Intro.Txt",    { on News Host }
                  Action Help           = "News:Action.Hlp",
                  Temp File             = "$News_Temp$",
                  Other Temp File       = "$News_Orig$"

%constant %string Match All = "ALL"

@16_3FA0 %byte Rows, Cols

%begin
   %record (Topic fm) %name Actual Topics,
                            Current Actual Topic
   %record (Seen fm)  %name Topics,
                            Current Topic,
                            Last Topic
   %string (255) Seen File
   %string (255) Wanted Topic
   %integer Wanted
   %integer Quit = No,
            Write Back = Yes,
            Topic Direction = Forwards,
            Default Direction = Forwards,
            Ignore = No,
            Last Row = Rows - 1
   %byte Ch

   {-SET UP-}

   %routine Set Up
      %own %string (32) Seen User

      {INTRODUCTION}

      %routine Introduction
         %string (255) S
         %integer Left,
                  Right,
                  I

         Clear Screen
         Cursor (0, 0)
         S = "Welcome to the news system " . First Name
         I = 80 - Length (S)
         Right = I//2
         Left = I - Right
         Feature
         Graph On
         Horizontal %for I = 1, 1, Left
         Graph Off
         Put String (S)
         Graph On
         Horizontal %for I = 1, 1, Right
         Graph Off
         Normal
         Select Host (News Host)
         Open Input (1, Introductory Document)
         Select Input (1)
         Display File (2, 2, Last Row, -1, Yes)
         Close Input
         Select Host (Home Host)
      %end {Introduction}

      {DALLAS}

      %routine Dallas
         %own %integer Bits = 0
         %own %string (255) Param = {Match All} "ALL"

         %constant %integer Reverse Bit = 2_10000000000000000000000000000000,
                            Ignore  Bit = 2_11000000000000000000000000000000

         Define Param ("Topic",
                       Param,
                       PAM Major)

         Define Boolean Params ("Reverse,X,Ignore,N",
                                 Bits,
                                 PAM Major)

         Seen User = User Name

         Define Param ("User - the directory for the NEWS.SEEN file",
                       Seen User,
                       0)

         Process Parameters (CLI Param)

         Default Direction = Backwards %if Bits&Reverse Bit # 0
         %if Bits&Ignore Bit # 0 %start
            Ignore = Yes 
            Write Back = No
         %finish
         Wanted Topic = Param
      %end {Dallas}

      {-LOAD TOPICS-}

      %routine Load Topics
         %record (Seen fm) %name T,
                                 V,
                                 Vanished == Nil,
                                 Last == Nil
         %record (Topic fm) %name AT
         %byte Found
         %record (Seen fm) Seen Pattern
         %record (Seen fm) %name New Topic
         %record (Range fm) Range Pattern
         %record (Range fm) %name New Range 

         Actual Topics == Read Topics

         %if Exists (Seen File) %start
            Topics == Read Seen File (Seen File)
         %else
            Topics == Nil
            Introduction
         %finish

         T == Topics
         AT == Actual Topics
         %while T ## Nil %cycle
            {Check for deletions}
            %if AT == Nil %or -
                T_Topic # AT_Topic %start
               {A topic has been deleted}
               V == T         {keep it}
               T == T_Next    {move on}
               V_Next == Vanished   {keep vanished ones on a list}
               Vanished == V
               {N.B. At does not move on}
            %else
               Last == T
               T == T_Next
               AT == AT_Next
            %finish
         %repeat
         %while AT ## Nil %cycle
            {There are new topics}
            {First check to see if it is a vanished one reappeared}
            V == Vanished
            Found = No
            %while V ## Nil %cycle
               %exit %if V_Topic = AT_Topic
               V == V_Next
            %repeat
            {make up a new entry}
            New Topic == New (Seen Pattern)
            New Topic_Topic = AT_Topic
            %if V == Nil %start
               New Range == New (Range Pattern)
               New Topic_Ranges == New Range
               New Range_From = 0               {indicate it is unread}
               New Range_To = 0
               New Range_Next == Nil
               New Topic_Subscribed = Yes
            %else
               New Topic_Ranges == V_Ranges
               New Topic_Subscribed = V_Subscribed
               V_Topic = ""                     {cannot be matched against}
                     {Deleting it would require a great deal of list poking}
                     {which is really not worth the effort}
            %finish
            New Topic_Last == Nil
            New Topic_Next == Nil
            {Now add New Topic to list}
            %if Last == Nil %start
               Topics == New Topic
            %else
               Last_Next == New Topic
               New Topic_Last == Last 
            %finish
            Last == New Topic
            At == AT_Next
         %repeat

         Current Topic == Topics
         Last Topic == Nil
      %end {Load Topics}

      {-MAIN CODE OF SET UP-}

      Set User
      Dallas

      Terminal Model = Default Terminal
      Set Up Terminal
      Set Terminal Characteristics

      Home Host = Current Host
      News Host = Connect to Host(News Server)
      Select Host (Home Host)

      Seen File = Seen User . ":" . Seen File Name

      Load Topics
   %end {Set Up}

   {-PAKTC-}

   %routine PAKTC
      %byte Ch

      Right
      Put String ("Press any key to Continue")
      Normal
      Right
      %cycle
         Ch = Get Key
         %if Ch = '?' %start
            Clear Line
            Feature
            Put String -
           ("The SPACE bar is the biggest key on the keyboard, just press that")
            Normal
         %else
            %exit
         %finish
      %repeat
      %signal Total Abort %if Ch = EM
   %end {PAKTC}

   {-TOPIC OPENED-}

   %predicate Topic Opened
      %byte Ch

      {PICKED}

      %predicate Picked
         %integer First Length, 
                  Message Number
         %byte Ch

         Clear Screen
         Feature
         Put String ("New topic ")
         Put String (Current Topic_Topic)
         Normal
         Flush Symbols
         %unless Open News File (Current Topic_Topic, 0) %start
            Feature
            Put String (" currently unavailable - try again later")  
            PAKTC
            %false
         %finish
         Message Number = 1         {explanation of what group is about}
         First Length = Move To Message (Message Number, No)
         %if First Length > 0 %start
            Display File (2, 2, Last Row, First Length, No)
         %else
            Cursor (0, 2)
            Put String ("Someone deleted message #1 !")
         %finish

         Cursor (60, 0)
         Feature
         Put String ("Subscribe? (Y/N)")
         Normal
         Right
         %cycle
            Ch = Get Key
            Ch = Ch - ('a' - 'A') %if 'a' <= Ch <= 'z'
            %if Ch = 'N' %start
               Close News File
               Current Topic_Ranges_To = 1
               Current Topic_Ranges_From = 1
               Current Topic_Subscribed = No
               %false
            %else %if Ch = 'Y' %or -
                      Ch = ' '
               Current Topic_Ranges_To = 1
               Current Topic_Ranges_From = 1
               Current Topic_Subscribed = Yes
               %true
            %else %if Ch = EM      
               %signal Total Abort
            %else %if Ch = 'Q' 
               Quit = Yes
               %false
            %else %if Ch = Left Key
               Topic Direction = Backwards
               %false
            %else %if Ch = Right Key
               %false
            %else %if Ch = '?'
               Cursor (0, Last Row)
               Clear Line
               Feature
               Put String -
("Y, SPACE subscribe; N unsubscribe; LEFT previous topic; RIGHT next topic; Q quit")
               Normal
               Cursor (77, 0)
            %else
               Put Symbol (BEL)
            %finish
         %repeat
      %end {Picked}
   
      {-MAIN CODE OF TOPIC OPENED-}

      %if (Ignore = No %and -
           Current Topic_Ranges_From = 0) %start
         {New topic}
         %true %if Picked
         %false
      %else
         %if (Ignore = No %and -
              Current Topic_Subscribed = No) %or -
             Wanted = No %start
            %false
         %else
            %unless Open News File (Current Topic_Topic, 0) %start
               Feature
               Clear Screen
               Feature
               Put String ("Topic ")
               Put String (Current Topic_Topic)
               Put String (" currently unavailable - try again later")  
               PAKTC
               %false
            %finish
            %true
         %finish
      %finish
      %true       {compiler bug}
   %end {Topic Opened}

   {-SCAN ITEMS-}

   %routine Scan Items
      %integer Message Length,
               Message Number,
               Next = Default Direction,
               First Line
      %byte Skip = No,
                   Defaulting = Yes
      %own %byte To Last = No

      %record %format Reply fm (%byte Operation,
                                %short Number,
                                %record (Reply fm) %name Next)
      %constant %byte Cancel = 0,
                      Reply = 1,
                      Posting = 2
      %record (Reply fm) Reply Pattern
      %record (Reply fm) %name Replies == Nil,
                               Last Reply == Nil

      {DISPLAY HEADER}

      %routine Display Header
         %integer CY 
         %byte Ch,
               Last Ch = 0

         Clear Screen
         Feature
         Put String ("Message ");   Put Integer (Message Number)
         Put String (" of "); Put Integer (Last Message)
         Put String (" in topic ")
         Put String (Current Topic_Topic)
         Normal
         CY = 1
         Cursor (0, CY)
         %cycle
            Read Symbol (Ch)
            Message Length = Message Length - 1
            %if Ch = NL %start
               CY = CY + 1
               Cursor (0, CY)
            %else
               Safe Put Symbol (Ch)
            %finish
            %exit %if Last Ch = NL %and-
                      Ch = NL
            Last Ch = Ch
         %repeat
         First Line = CY
      %end {Display Header}

      {MARK AS READ}

      %routine Mark As Read (%integer Number)
         %record (Range fm) %name R, Other
         %record (Range fm) Range Pattern

         %return %if Ignore = Yes
         {Check to see if already read}
         R == Current Topic_Ranges
         %cycle
            %return %if R_From <= Number <= R_To
            R == R_Next
         %repeat %until R == Nil
         {Not already marked, so check to see if it is an extension}
         R == Current Topic_Ranges
         %cycle
            %if R_To + 1 = Number %start
               Other == R_Next
               %if Other ## Nil %and -
                   Other_From - 1 = Number %start
                  {join the two ranges}
                  R_To = Other_To
                  R_Next == Other_Next
                  Dispose (Other)
               %else
                  {just extend this one}
                  R_To = Number
               %finish
               %return
            %else %if Number + 1 = R_From 
               {extend backwards}
               R_From = Number
               %return
            %finish
            R == R_Next
         %repeat %until R == Nil
         {Need to add an Island}
         Other == New (Range Pattern)
         Other_From = Number
         Other_To = Number
         {Now insert it}
         R == Current Topic_Ranges
         %cycle
            %if R_Next == Nil %start
               {Add island at the end}
               R_Next == Other
               Other_Next == Nil
               %return
            %else %if R_Next_From < Number
               R == R_Next
            %else
               {insert between two items}
               Other_Next == R_Next
               R_Next == Other
               %return
            %finish
         %repeat
      %end {Mark As Read}

      {ENQUIRE}

      %routine Enquire
         %byte Ch,
               State = No,
               Read = No

         {ADD REPLY}

         %routine Add Reply (%byte Operation)
            %record (Reply fm) %name New Reply

            New Reply == New (Reply Pattern)
            New Reply_Operation = Operation
            New Reply_Number = Message Number
            New Reply_Next == Nil
            %if Replies == Nil %start
               Replies == New Reply
            %else 
               Last Reply_Next == New Reply
            %finish
            Last Reply == New Reply
         %end {Add Reply}

         {KILL MESSAGE}

         %routine Kill Message
            {This checks to see if we are allowed to kill a message}
            %constant %integer Max Killer = 6
            %constant %string (12) %array Killers (0:Max Killer) =
               "RMM",
               "FDC",
               "NEWS_S",
               "GDMR",
               "JHB",
               "RWT",
               "PDS"
            %integer I,
                     L,
                     Ok = No
            %byte Ch
            %string (12) Name

            %for I = 0, 1, Max Killer %cycle
               Ok = Yes %and %exit %if Killers (I) = User Name
            %repeat
            %if Ok = No %start
               L = Move To Message (Message Number, No)
               Skip Symbol %for I = 1, 1, 6
               Name = ""
               %cycle
                  Read Symbol (Ch)
                  %exit %if Ch <= ' '
                  Name = Name . To String (Ch)
               %repeat
               Ok = Yes %if User Name = Name
            %finish
            Cursor (60, 0)
            %if Ok = Yes %start
               Cursor (60, 0)
               Erase Line
               Feature
               Put String ("Really cancel?")
               Normal
               Right
               %cycle
                  Ch = Get Key
                  Ch = Ch - ('a' - 'A') %if 'a' <= Ch <= 'z'
                  %if Ch = 'Y' %or -
                      Ch = 'C' %start
                     Mark As Read (Message Number)
                     Add Reply (Cancel)
                     Cursor (60, 0)
                     Erase Line
                     Cursor (69, 0)
                     Put String ("(Cancelled)")
                     %exit
                  %else %if Ch = 'N' %or -
                            Ch = 'L'
                     %exit
                  %else %if Ch = '?'
                     Cursor (60, 0)
                     Feature
                     Put String ("Y cancel; N leave  ")
                     Normal
                  %finish
               %repeat
            %else
               Put String ("(Sorry)")
            %finish
         %end {Kill Message}

         {ADD POSTING}

         %routine Add Posting
            %integer SI
            
            SI = Message Number
            Message Number = -1
            Add Reply (Posting)
            Message Number = SI
         %end {Add Posting}

         {GIVE HELP}

         %routine Give Help

            Open Input (2, Action Help)
            Select Input (2)
            Display File (0, 0, Last Row, -1, Yes)
            Message Length = Move To Message (Message Number, No)
            Display Header
            %if Message Length = 0 %start
               State = Yes 
            %else
               State = No
            %finish
         %end {Give Help}

         {MOVE TO NUMBER}

         %predicate Moved To Number (%integer Start)
            %integer I = 0,
                     Length = 0,
                     L
            %byte Ch

            Cursor (60, 0)
            Feature
            Put String ("#:")
            Normal
            Put String ("     ")
            Cursor (63, 0)
            %if Start > 0 %start
               I = Start - '0'
               Length = 1
               Put Symbol (Start)
            %finish
            %cycle
               Ch = Get Key
               %if Ch = CR %or -
                   Ch = ' ' %start
                  %exit
               %else %if Ch = DEL
                  %if Length  > 0 %start
                     Length  = Length  - 1
                     I = I // 10
                     Put Symbol (BS)
                     Put Symbol (' ')
                     Put Symbol (BS)
                  %finish
               %else %if Ch = BS %or -
                         Ch = CAN
                  Cursor (60, 0)
                  Erase Line
                  -> Out
               %else %if '0' <= Ch <= '9'
                  Put Symbol (Ch)
                  I = I*10 + Ch - '0'
                  Length = Length + 1
               %else
                  Put Symbol (BEL)
               %finish
            %repeat  
            I = Last Message %if I > Last Message
            L = Move To Message (I, No)
            %if L > 0 %start
               Mark As Read (Message Number)
               Message Number = I
               Next = No
               %true
            %finish
         Out:
            Cursor (60, 0)
            Erase Line
            Cursor (72, 0)
            Put String ("(Failed)")
            %false
         %end {Move To Number}

         {READ DELETED}

         %routine Read Deleted
            %integer I = 0,
                     Length = 0,
                     L
            %byte Ch

            Cursor (60, 0)
            Feature
            Put String ("Magic:")
            Normal
            Put Symbol (' ')
            Cursor (67, 0)
            %cycle
               Ch = Get Key
               %if Ch = CR %or -
                   Ch = ' ' %start
                  %exit
               %else %if Ch = DEL
                  %if Length  > 0 %start
                     Length  = Length  - 1
                     I = I // 10
                     Put Symbol (BS)
                     Put Symbol (' ')
                     Put Symbol (BS)
                  %finish
               %else %if Ch = BS %or -
                         Ch = CAN
                  Cursor (60, 0)
                  Erase Line
                  %return
               %else %if '0' <= Ch <= '9'
                  Put Symbol (Ch)
                  I = I*10 + Ch - '0'
                  Length = Length + 1
               %else
                  Put Symbol (BEL)
               %finish
            %repeat  
            I = Last Message %if I > Last Message
            L = Move To Message (I, No)
            Clear Screen
            Feature
            Put String ("Message ");   Put Integer (I)
            Put String (" of "); Put Integer (Last Message)
            Put String (" in topic ")
            Put String (Current Topic_Topic)
            Put String (" (Cancelled)") %if L = 0
            Normal
            Display File (2, 2, Last  Row, -1 , Yes)
         %end {Read Deleted}

         {SAVE IN FILE}

         %routine Save In File
            %string (255) S
            %byte Ch,
                  New
            %integer L,
                     I

            %on 3, 9 %start
               Cursor (60, 0)
               Erase Line
               Cursor (72, 0)
               Put String ("(Failed)")
               %return
            %finish

            Cursor (60, 0)
            Feature
            Put String ("File:")
            Normal
            Put String ("      ")
            Cursor (66, 0)
            S = ""
            %cycle
               Ch = Get Key
               %if Ch = CR %start
                  %exit
               %else %if Ch = DEL
                  %if Length (S) > 0 %start
                     Length (S) = Length (S) - 1
                     Put Symbol (BS)
                     Put Symbol (' ')
                     Put Symbol (BS)
                  %finish
               %else %if Ch = BS %or -
                         Ch = CAN
                  -> Out
               %else %if Ch > ' '
                  Put Symbol (Ch)
                  S = S . To String (Ch)
               %else
                  Put Symbol (BEL)
               %finish
            %repeat  
            Cursor (59, 0)
            Select Host (Home Host)
            %if Exists (S) %start
               New = No
            %else
               New = Yes
            %finish
            Open Append (2, S)
            Select Output (2)
            Select Host (News Host)
            %if New = No %start
               Put Symbol (FF)
               New Line
            %finish
            L = Move To Message (Message Number, No)
            %for I = 1, 1, L %cycle
               Select Host (News Host)
               Read Symbol (Ch)
               %if Ch >= ' ' %or -
                   Ch = NL %or -
                   Ch = TAB %start
                  Select Host (Home Host)
                  Print Symbol (Ch)
               %finish
            %repeat
            Select Host (Home Host)
            Close Output
         Out:
            Select Host (News Host)
            Cursor (60, 0)
            Erase Line
            Message Length = Move To Message (Message Number, No)
            Display Header
            State = No
         %end {Save In File}

         {DIRECTORY}

         %routine Directory (%record (Seen fm) %name T,
                             %byte Open)
            %integer Top = 0,
                     Bottom = Last Row
            %integer L,
                     CY,
                     Number
            %string (255) From,
                         Subject

            {GET SUBJECT}

            %routine Get Subject
               %string (255) Line
               %byte Ch
               %integer I
               
               From = ""
               Subject = ""
               Line = ""
               %cycle
                  Read Symbol (Ch)
                  L = L - 1
                  %if Ch = NL %start
                     %if Line -> ("Subject: ") . Subject %start
                     %else %if Line -> ("From: ") . From
                     %finish
                     Line = ""
                  %else
                     Line =  Line . To String (Ch)
                  %finish
               %repeat %until L = 0 %or -
                              (Subject # "" %and -
                               From # "")
               %for I = 1, 1, Length (From) %cycle
                  %if Char No (From, I) = ' ' %start
                     Length (From) = I - 1
                     %exit
                  %finish
               %repeat
            %end {Get Subject}

            {SAFE PUT STRING}

            %routine Safe Put String (%string (255) S)
               %integer I

               Safe Put Symbol (Char No (S, I)) %for I = 1, 1, Length (S)
            %end {Safe Put String}

            {MAIN CODE OF DIRECTORY}

            %if Open = No %start
               %unless Open News File (T_Topic, 0) %start
                  %return 
               %finish
            %finish
            Number = 1
            CY = Top
            Feature
            Cursor (0, Top);     Clear Line
            Put Symbol ('#')
            Cursor (5, Top);     Put String ("From")
            Cursor (15, Top);    Put String ("Subject")
            Normal 
            CY = Top + 1
            %cycle
               L = Move To Message (Number, Forwards)
               %if L > 0 %start
                  Cursor (0, CY)
                  Clear Line
                  Get Subject
                  Put Integer (Number)
                  Cursor (5, CY);   Put String (From)
                  Cursor (15, CY);  Safe Put String (Subject)
                  CY = CY + 1 
                  %if CY = Bottom %start
                     %exit %if Number = Last Message
                     Cursor (0, Bottom)
                     Feature
                     Put String ("--More--")
                     Normal
                     %cycle
                        Ch = Get Key
                        %if Ch = 'q' %or -
                            Ch = 'Q' %start
                           Clear Line
                           -> Exit Route
                        %else %if Ch = CR
                           Forward Scroll (Top + 1, Bottom - 1)
                           CY = Bottom - 1
                           %exit
                        %else %if Ch = ' '
                           CY = Top + 1
                           %exit
                        %else %if Ch = '?'
                           Clear Line
                           Feature
                           Put String -
                                 ("Q - Quit; RETURN next line; SPACE next page")
                           Normal
                        %else
                           Put Symbol (BEL)
                        %finish
                     %repeat
                     Clear Line
                  %finish
               %else
                  %exit
               %finish
            %repeat %until Number = Last Message
         Exit Route:
            Close News File %if Open = No
            %for L = CY, 1, Bottom %cycle
               Cursor (0, L)
               Clear Line
            %repeat
            Feature
            PAKTC
         %end {Directory}

         {TOPIC SUBSCRIPTIONS}

         %routine Topic Subscriptions
            %integer Top Line = 3,
                     Bottom Line = Last Row
{*Bug*      %record (Seen fm) %name %array Screen (0:3, Top Line:Bottom Line)

      {Screen does not work because of compiler bug}

   %integer %array A Screen (0:3, Top Line:Bottom Line)

            %integer X = 0, 
                     Y = Top Line
            %byte Finished = No

            {YES IT IS}

            %routine Yes It Is
               %if Terminal Characteristics&Reverse Text Ability # 0 %start
                  Reverse On
               %else
                  Normal
               %finish
            %end {Yes It Is}

            {NO IT ISNT}

            %routine No It Isnt
               %if Terminal Characteristics&Reverse Text Ability # 0 %start
                  Normal
               %else
                  Dim On
               %finish
            %end {No It Isnt}

            {HEADING}

            %routine Heading
               Cursor (0, 0)
               Clear Line
               Feature
               Put String( -
"Cursor keys to move; I for Info; SPACE to change; RETURN to Select; X to Exit")
               Cursor (0, 1)
               Clear Line
               Yes It Is
               Put String ("(Subscribed)")
               Normal
               Right;   Right
               No It Isnt
               Put String ("(Unsubscribed)")
               Normal
               Cursor (0, 2)
               Clear Line
            %end {Heading}

            {PAINT}

            %routine Paint
               %integer X,
                        Y
               %record (Seen fm) %name T == Topics
               
               %for Y = Top Line, 1, Bottom Line %cycle
                  Cursor (0, Y)
                  Clear Line
                  Right;   Right
                  %for X = 0, 1, 3 %cycle
{*Bug*               Screen (X, Y) == T         {Record in screen array}
      A Screen (X, Y) = Addr (T)
                     %unless T == Nil %start
                        Cursor (X*20 + 2, Y) %unless X = 0
                        %if T_Subscribed = Yes %start
                           Yes It Is
                        %else
                           No It Isnt
                        %finish
                        Put String (T_Topic)
                        T == T_Next
                     %finish
                  %repeat
               %repeat
               Normal
            %end {Paint}

            {ACTION}

            %routine Action
               %byte Ch,
                     Closed = No
               %record (Seen fm) %name T
               %integer DX = 0,
                        DY = 0

               {DISPLAY INTRO}

               %routine Display Intro
                  %integer L, 
                           N

                  %if Closed = No %start
                     Close News File
                     Closed = Yes
                  %finish
                  %if Open News File (T_Topic, 0) %start
                  %finish
                  Select Input (News Stream)
                  N = 1
                  L = Move To Message (N, No)
                  Display File (3, 3, Last Row, L, Yes)
                  Close News File
                  Paint
               %end {Display Intro}

               {MAIN CODE OF ACTION}

               Cursor (X*20, Y)
{*Bug*           T == Screen (X, Y)
      T == Record (A Screen (X, Y))
               Ch = Get Key
               Ch = Ch - ('a' - 'A') %if 'a' <= Ch <= 'z'
               %if Ch = CR %start
                  Finished = Yes
                  Wanted Topic = Match All
                  Ignore = Yes
                  Last Topic == Current Topic
                  Current Topic == T
                  Topic Direction = No
                  Skip = Yes
                  %return
               %else %if Ch = 'X'
                  %if Closed = Yes %start
                     %if Open News File (Current Topic_Topic, 0) %start
                        Message Length = Move To Message (Message Number, No)
                     %finish
                  %finish
                  Finished = Yes
               %else %if Ch = EM
                  %signal Total Abort
               %else %if Ch = 'I'
                  Display Intro
               %else %if Ch = 'D'
                  Closed = Yes
                  Directory (T, No)
                  Heading
                  Paint
               %else %if Ch = Up Key
                  DY = -1
               %else %if Ch = Down Key
                  DY = 1
               %else %if Ch = Left Key
                  DX = -1
               %else %if Ch = Right Key
                  DX = 1
               %else %if Ch = ' '
                  Right
                  %if T_Subscribed = Yes %start
                     T_Subscribed = No
                     No It Isnt
                     %if X = 3 %start
                        DX = 1
                        DY = 1
                     %else
                        DX = 1
                     %finish
                  %else
                     T_Subscribed = Yes
                     Yes It Is
                  %finish
                  Right
                  Put String (T_Topic)
                  Normal
               %else
                  Put Symbol (BEL)
                  %return
               %finish
               %cycle
                  X = X + DX
                  X = 0 %if X > 3
                  X = 3 %if X < 0
                  Y = Y + DY
                  Y = Top Line %if Y > Bottom Line
                  Y = Bottom Line %if Y < Top Line
               %repeat %until {*Bug* Screen (X, Y) ## Nil} A Screen (X, Y) # 0
            %end {Action}

            {MAIN CODE OF TOPIC SUBSCRIPTIONS}

            Heading
            Paint
            %cycle
              Action
            %repeat %until Finished = Yes
         %end {Topic Subscriptions}

         {THIS DIRECTORY}

         %routine This Directory
            Directory (Current Topic, Yes)
            Message Length = Move To Message (Message Number, No)
            Display Header
            State = No
         %end {This Directory}

         {MOVE TO LAST MESSAGE}

         %routine Move To Last Message
            %integer L

            Message Number = Last Message + 1
            Next = Backwards
         %end {Move To Last Message}

         {MAIN CODE OF ENQUIRE}

         State = Yes %if Message Length = 0
         Defaulting = No
         Next = Default Direction
         Cancel Input
         %cycle
            Cursor (60, 0)
            Feature
            Put String ("Action:")
            Normal
            Put Symbol (' ')
            Ch = Get Key
            Ch = Ch - ('a' - 'A') %if 'a' <= Ch <= 'z'
            %if Ch = 'Y' %or -
                Ch = CR %or -
                Ch = Keypad Enter %start
               Display File (First Line, 1, Last Row, Message Length, No) %if State = No
               State = Yes
            %else %if Ch = ' '
               %if State = No %start
                  Display File (First Line, 1, Last Row, Message Length, No)
                  State = Yes
               %else
                  Next = Default Direction
                  Defaulting = Yes
                  Read = Yes
                  %exit
               %finish
            %else %if (Ch = Up Key %or -
                       Ch = '-')
               %if Message Number > 1 %start
                  %if Default Direction = Forwards %start
                     Next = Backwards
                  %else
                     Next = Forwards
                  %finish
               %else
                  {Same as left key, almost}
                  To Last = Yes
                  Skip = Yes
                  Topic Direction = Backwards
               %finish
               %exit
            %else %if Ch = Down Key
               Next = Default Direction
               %exit
            %else %if Ch = 'N'
               Defaulting = Yes
               Next = Default Direction
               Read = Yes
               %exit
            %else %if Ch = 'P'
               Erase Line
               Cursor (71, 0)
               Put String ("(Posting)")
               Add Posting
            %else %if Ch = 'Q'
               Quit = Yes
               Read = Yes %if State = Yes
               %exit
            %else %if Ch = 'R' %and -
                      Message Number > 1
               Erase Line
               Cursor (73, 0)
               Put String ("(Reply)")
               Add Reply (Reply)
            %else %if Ch = 'X'
               Quit = Yes
               Write Back = No
               %exit
            %else %if Ch = EM
               %signal Total Abort
            %else %if Ch = Right Key
               Skip = Yes
               %exit
            %else %if Ch = Left Key
               Skip = Yes
               Topic Direction = Backwards
               %exit
            %else %if Ch = 'I' %or -
                      Ch = 'E'
               Next = Default Direction
               Defaulting = Yes
               %exit
            %else %if Ch = '<'
               Message Number = 1
               Next = No
               %exit
            %else %if Ch = '>'
               Move To Last Message
               %exit
            %else %if Ch = 'C'
               Kill Message
            %else %if Ch = '?'
               Give Help
            %else %if Ch = 'U'
               Current Topic_Subscribed = No
               Skip = Yes
               %exit
            %else %if Ch = '#'
               %exit %if Moved To Number (0)
            %else %if '1' <= Ch <= '9'
               %exit %if Moved To Number (Ch)
            %else %if Ch = 'S'
               Save In File
            %else %if Ch = 'T'
               Topic Subscriptions
               %exit
            %else %if Ch = 'D'
               This Directory
            %else %if Ch = 'M'
               Read Deleted
            %else
               Put Symbol (BEL)
            %finish
         %repeat
         Mark As Read (Message Number) %if Read = Yes
         Clear Line
      %end {Enquire}

      {ARTICLE OPERATIONS}

      %routine Article Operations
         %string (255) Subject,
                      Line,
                      Second
         %record (Reply fm) %name Last
         %integer Done,
                  Size,
                  I,
                  Number,
                  Edit X,
                  Edit Y

         {COUNT GET LINE}

         %routine Count Get Line
            %byte Ch

            Select Host (News Host)
            Line = ""
            %while size > 0 %cycle
               Read Symbol (Ch)
               Size = Size - 1
               Line = Line . Tostring(Ch)
               %exit %if Ch = NL
            %repeat
            Select Host (Home Host)
         %end {Count Get Line}


         {MAIN CODE OF ARTICLE OPERATIONS}

         Clear Screen

         %while Replies ## Nil %cycle

            %if Replies_Operation = Cancel %start
               Cancel Message (Current Topic_Topic, Replies_Number)
               Close News File
            %else %if Quit = No

               Select Host (Home Host)

               %if Replies_Operation = Reply %start
                  Number = Replies_Number
   
                  Select Host (News Host)

                  %unless Open News File (Current Topic_Topic, 0) %start
                     %exit
                  %finish

                  Size = Move To Message (Number, No)
                  %if Size > 0 %and -
                      Number = Replies_Number %start
                     Subject = ""
                     Select Host (Home Host)
                     Open Output (2, Other Temp File)
                     Select Output (2)
                     Select Input (News Stream)
                     %while Size > 0 %cycle
                        Count Get Line
                        Print Symbol ('>')
                        Print Symbol (' ') %if Charno (Line, 1) # '>'
                        Print String (Line)
                        %if Subject = "" %and Line -> ("Subject:") . Line %start
                           Subject = Line
                        %finish
                     %repeat

                     Close Output
                     Second = Other Temp File
                     Select Host (News Host)
                     Close News File

                     Select Host (Home Host)
                     %unless Subject -> ("RE:") %start
                        Subject = " RE:" . Subject
                     %finish
                     Open Output (2, Temp File)
                     Select Output (2)
                     Print String ("Subject:" . Subject)
                     Print String ("In-reply-to: Message #")
                     Write (Number, 0)
                     New Line
                     Close Output
                     Edit X = 1
                     Edit Y = 3
                  %else
                     Clear Screen
                     Feature 
                     Put String ("Message #")
                     Put Integer (Number)
                     Put String (" has been cancelled")
                     PAKTC
                     Close News File
                     -> Go On
                  %finish
               %else
                  {doing a posting}
                  Open Output (2, Temp File)
                  Select Output (2)
                  Print String ("Subject: ")
                  New Line
                  Close Output
                  Second = ""
                  Edit X = 10
                  Edit Y = 1
               %finish

               Done = Edit (Temp File, Second, Temp File, Edit X, Edit Y)
   
               Clear Screen

               %if Done = Yes %start
                  %unless Post (Temp File, Current Topic_Topic) %start
                     PAKTC
                     %exit
                  %finish
               %else
                  Feature
                  Put String ("Edit Aborted - no reply sent")
                  PAKTC
               %finish
            %finish
         Go On:
            Last == Replies
            Replies == Replies_Next
            Dispose (Last)
         %repeat  
         Close News File
      %end {Article Operations}

      {-AREADY READ-}
         
      %predicate Already Read (%integer Number)
         %record (Range fm) %name R == Current Topic_Ranges

         %false %if Ignore = Yes %or -
                    %not (1 <= Number <= Last Message)
         %cycle
            %true %if R_From <= Number <= R_To
            R == R_Next
         %repeat %until R == Nil
         %false
      %end {Already Read}

      %integer Was

      {-MAIN CODE OF SCAN ITEMS-}

   Read Posting:
      %if Current Topic_Ranges_To < Last Message %or -
          Ignore = Yes %start
         Topic Direction = Forwards
         %if Default Direction = Forwards %and -
             To Last = No %start
            %if Ignore = No %start
               Message Number = Current Topic_Ranges_To
            %else
               Message Number = 1
               Next = No
            %finish
         %else
            Message Number = Last Message + 1      {Guaranteed to find last}
            Next = Backwards                       {actual item}
            To Last = No
         %finish
         %cycle
            Was = Message Number
            Message Length = Move To Message (Message Number, Next)
            %if Message Length > 0 %and -
                ((Defaulting = Yes %and -
                  %not Already Read (Message Number)) %or -
                 Defaulting = No) %start
               Display Header
               Enquire
            %else
               Mark As Read (Message Number)
               %if Was = Message Number %and -
                   Next # No %start
                  {This is a hack for the case when there are cancelled}
                  {messages at the end file}
                  Mark As Read (Last Message)
                  %exit 
               %finish
               Next = Default Direction
            %finish

            { Skip contiguous blocks of already read stuff }
            %if Defaulting = Yes %start
               %cycle
                  %if Default Direction = Forwards %start
                     Message Number = Message Number + 1 
                  %else
                     Message Number = Message Number - 1
                  %finish
               %repeat %until %not Already Read (Message Number)
               %if Default Direction = Forwards %start
                  Message Number = Message Number - 1
               %else
                  Message Number = Message Number + 1 
               %finish
            %finish

         %repeat %until (Message Number >= Last Message %and -
                         Next = Forwards) %or -
                        (Message Number = 1 %and -
                         Next = Backwards) %or -
                        Quit = Yes %or -
                        Skip = Yes

      %finish
      Close News File

      %if Replies ## Nil %start
         Article Operations 
         %unless Open News File (Current Topic_Topic, 0) %start
            %return
         %finish
         -> Read Posting 
      %finish
   %end {Scan Items}

   {-CLOSE DOWN-}

   %routine Close Down
      Disconnect Host (News Host)
      Select Host (Home Host)
      Write Seen File (Seen File, Topics) %if Write Back = Yes
      Cursor (0, Last Row)
      Clear Line
      Reset Terminal
   %end {Close Down}

   {--MAIN CODE OF READNEWS--}

   %on %event 1,2,3,4,5,6,7,8,9,10,11,12,13,Total Abort,15 %start
      {N.B.  Event 15 is used by other modules to report fatal conditions}
      Close News File      { Safe, even if not open }
      Disconnect Host (News Host)
      Select Host (Home Host)
      Cursor (0, Last Row)
      Clear Line
      Reset Terminal
      %if Event_Event = 15 %start
         Select Output (0)
         Print String ("ReadNews fails: " . Event_Message)
         New Line
         %stop
      %else %if Event_Event = Total Abort
         Print String ("ReadNews aborted")
         New Line
         %stop
      %else 
         Print String ("Screwed up at line: ")
         Write (Event_Line, 0)
         Newline
         Signal (Event_Sub << 4 + Event_Event)      { Not literal indeed ! }
      %finish
   %finish

   Set Up
   %cycle

      %if Wanted Topic = Match All %start
         Wanted = Yes
      %else %if Wanted Topic = Current Topic_Topic
         Wanted = Yes
      %else 
         Wanted = No
      %finish
         
      Scan Items %if Topic Opened
   
      %if Topic Direction = Forwards %start
         Last Topic == Current Topic
         Current Topic == Current Topic_Next 
      %else %if Topic Direction = Backwards
         %if Last Topic ## Nil %start
            Current Topic == Last Topic
            Last Topic == Last Topic_Last
         %else
            Clear Screen
            Feature
            Put String ("No unread items in previous topics")
            PAKTC
            Topic Direction = Forwards
         %finish
      %finish

      %if Current Topic == Nil %and -
          Quit = No %start
         Clear Screen
         Feature
         Put String ("No (more) news.  Quit or read old news ? (Q/R)")
         Normal
         Right
         %cycle
            Ch = Get Key
            %if Ch = 'q' %or -
                Ch = 'Q' %or -
                Ch = ' ' %start
               Quit = Yes
               %exit
            %else %if Ch = EM
               %signal Total Abort
            %else %if Ch = '?'
               Cursor (0, 2)
               Feature
               Put String ("Q, SPACE quit; R, RETURN to read old news") 
               Normal
               Cursor (48, 0)
            %else %if Ch = 'r' %or -
                      Ch = 'R' %or -
                      Ch = CR
               Ignore = Yes
               Current Topic == Topics
               %exit
            %else
               Put Symbol (BEL)
            %finish
         %repeat
      %finish

   %repeat %until Quit = Yes
   Close Down
%end
