home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug184.arc / ROS34.LBR / ROSMSG.IZC / ROSMSG.INC
Text File  |  1979-12-31  |  16KB  |  508 lines

  1. { ROSMSG.INC - Remote Operating System Message Sub-system }
  2.  
  3. overlay procedure mesg_enter(to_ctrl: char);
  4. { Enter a new message }
  5.   type
  6.     TextPtr     = ^TextRecord;
  7.     TextRecord  =
  8.       record
  9.         LineNo  : integer;                  { Line number }
  10.         TextMsg : message;                  { Summary index }
  11.         next    : TextPtr                   { Pointer to next element on list }
  12.       end;
  13.   var
  14.     stop_msg: boolean;
  15.     msg_status: record_status;
  16.     ch: char;
  17.     last_line, to_loc: integer;
  18.     TextBase, TextLast, this: TextPtr;
  19.     to_fn: firstname;
  20.     to_ln: lastname;
  21.     subj: subject;
  22.     key: StrName;
  23.     temp_user_rec: user_list;
  24.  
  25.   procedure mesg_input(var last_line: integer);
  26.   { Input message }
  27.     var
  28.       ch: char;
  29.       this: TextPtr;
  30.       msg: StrStd;
  31.     begin
  32.       Writeln(USR);
  33.       msg := ' ';
  34.       next_inpstr := '';
  35.       while (not brk) and (msg <> '') do
  36.         begin
  37.           msg := next_inpstr;
  38.           Write(USR, last_line:2, '> ');
  39.           GetStr(msg, ch, len_msg, 'AEW');
  40.           Writeln(USR);
  41.           if msg <> ''
  42.             then if MaxAvail > 256
  43.                  then
  44.                    begin
  45.                      new(this);
  46.                      if TextBase = nil
  47.                        then TextBase := this
  48.                        else TextLast^.next := this;
  49.                      TextLast := this;
  50.                      TextLast^.LineNo := last_line;
  51.                      TextLast^.TextMsg := msg;
  52.                      TextLast^.next := nil;
  53.                      last_line := succ(last_line)
  54.                    end
  55.                  else
  56.                    begin
  57.                      Writeln(USR, 'Insufficient memory to continue message entry.');
  58.                      msg := ''
  59.                    end
  60.         end
  61.     end;
  62.  
  63.   procedure mesg_edit;
  64.   { Edit selected line from message }
  65.     var
  66.       ch: char;
  67.       i: integer;
  68.       this: TextPtr;
  69.       msg: StrStd;
  70.     begin
  71.       Writeln(USR);
  72.       i := strint(prompt('Line number', 2, 'E'));
  73.       this := TextBase;
  74.       while (i <> this^.LineNo) and (this <> nil) do
  75.         this := this^.next;
  76.       if this <> nil
  77.         then
  78.           begin
  79.             msg := this^.TextMsg;
  80.             Write(USR, i:2, '> ');
  81.             GetStr(msg, ch, len_msg, 'AEW');
  82.             Writeln(USR);
  83.             if msg <> ''
  84.               then this^.TextMsg := msg;
  85.           end
  86.         else Writeln(USR, 'Line not found.')
  87.     end;
  88.  
  89.   procedure mesg_print;
  90.   { Display message currently being edited }
  91.     var
  92.       this: TextPtr;
  93.     begin
  94.       Writeln(USR, 'From: ', user_rec.fn, ' ', user_rec.ln);
  95.       if to_fn = ''
  96.         then Writeln(USR, '  To: ALL')
  97.         else Writeln(USR, '  To: ', to_fn, ' ', to_ln);
  98.       Writeln(USR, '  Re: ', subj);
  99.       Writeln(USR);
  100.       this := TextBase;
  101.       while (not brk) and (this <> nil) do
  102.         begin
  103.           Writeln(USR, this^.LineNo:2, ': ', this^.TextMsg);
  104.           this := this^.next
  105.         end
  106.     end;
  107.  
  108.   procedure mesg_save(to_loc: integer; subj: subject; var stop_msg: boolean);
  109.   { Save message to disk }
  110.     var
  111.       start, line_count: integer;
  112.       this: TextPtr;
  113.       file_time: tad_array;
  114.       str: StrTAD;
  115.     begin
  116.       Writeln(USR);
  117.       if (msg_status = private) and (user_rec.access >= val_acc) and (valid_pw)
  118.         then if ask('Do you want this message to be public')
  119.                then msg_status := public;
  120.       start := filesize(mesg_file);
  121.       seek(mesg_file, start);
  122.       line_count := 0;
  123.       this := TextBase;
  124.       while this <> nil do
  125.         begin
  126.           Write(mesg_file, this^.TextMsg);
  127.           line_count := succ(line_count);
  128.           this := this^.next
  129.         end;
  130.  
  131.       if line_count > 0
  132.         then
  133.           begin
  134.             GetTAD(file_time);
  135.             str := FormTAD(file_time);
  136.             seek(summ_file, 0);
  137.             read(summ_file, summ_rec);
  138.             with summ_rec do
  139.               begin
  140.                 date      := file_time;
  141.                 status    := msg_status;
  142.                 area      := AreaSet;
  143.                 num       := succ(num);
  144.                 num_prev  := 0;
  145.                 num_next  := 0;
  146.                 user_from := user_loc;
  147.                 user_to   := to_loc;
  148.                 subject   := subj;
  149.                 st_rec    := start;
  150.                 size      := line_count
  151.               end;
  152.             seek(summ_file, 0);
  153.             Write(summ_file, summ_rec);
  154.             seek(summ_file, filesize(summ_file));
  155.             Write(summ_file, summ_rec);
  156.  
  157.             mesg_insert(2);
  158.  
  159.             case msg_status of
  160.               private: Write(USR, 'Private');
  161.               public:  Write(USR, 'Public')
  162.             end;
  163.             Writeln(USR, ' message ', summ_rec.num, ' filed ', str)
  164.           end
  165.         else Writeln(USR, 'Empty message not filed.');
  166.       stop_msg := TRUE
  167.     end;
  168.  
  169.   procedure mesg_quit(var stop_msg: boolean);
  170.   { Return to command mode }
  171.     begin
  172.       Writeln(USR);
  173.       Writeln(USR, 'Message not filed.');
  174.       stop_msg := TRUE
  175.     end;
  176.  
  177.   begin { mesg_enter }
  178.     if user_rec.access < val_acc
  179.       then list('D');
  180.     Writeln(USR);
  181.     Writeln(USR, 'From: ', user_rec.fn, ' ', user_rec.ln);
  182.     OK := FALSE;
  183.     msg_status := private;
  184.     repeat
  185.       if (user_rec.access < val_acc) or
  186.          (to_ctrl = 'S') or
  187.          ((to_ctrl = 'A') and (summ_rec.user_from = 0))
  188.         then
  189.           begin
  190.             to_fn := 'SYSOP';
  191.             Writeln(USR, '  To: ', to_fn)
  192.           end
  193.       else if (to_ctrl = 'A') and (summ_rec.user_from > 0)
  194.         then
  195.           begin
  196.             to_loc := summ_rec.user_from;
  197.             OK := TRUE;
  198.             GetRec(DatF, to_loc, temp_user_rec);
  199.             to_fn := temp_user_rec.fn;
  200.             to_ln := temp_user_rec.ln;
  201.             Writeln(USR, '  To: ', to_fn, ' ', to_ln)
  202.           end
  203.         else to_fn := prompt('To FIRST name [C/R for ALL]', len_fn, 'ES');
  204.       if to_fn = ''
  205.         then
  206.           begin
  207.             to_loc := 0;
  208.             msg_status := public;
  209.             OK := TRUE
  210.           end
  211.       else if to_fn = 'SYSOP'
  212.         then to_ln := ''
  213.       else if to_ctrl <> 'A'
  214.         then to_ln := prompt('LAST name', len_ln, 'ES');
  215.       if not OK
  216.         then
  217.           begin
  218.             key := pad(to_ln, len_ln) + pad(to_fn, len_fn);
  219.             FindKey(IdxF, to_loc, key);
  220.             if not OK
  221.               then Writeln(USR, to_fn, ' ', to_ln, ' not known on system.')
  222.           end
  223.     until (not online) or OK;
  224.     if not valid_pw
  225.       then
  226.         begin
  227.           subj := 'Password problem';
  228.           Writeln(USR, '  Re: ', subj)
  229.         end
  230.     else if user_rec.access < val_acc
  231.       then
  232.         begin
  233.           subj := 'New user';
  234.           Writeln(USR, '  Re: ', subj)
  235.         end
  236.       else subj := prompt('Subject', len_subj, 'E');
  237.     Writeln(USR);
  238.     Writeln(USR, 'To return to command mode, enter an empty line.');
  239.     Writeln(USR, 'Ready for message...');
  240.     TextBase := nil;
  241.     last_line := 1;
  242.     mesg_input(last_line);
  243.     stop_msg := FALSE;
  244.     repeat
  245.       Writeln(USR);
  246.       case select('Edit command', 'ContinueEditListSaveQuit') of
  247.         'C': mesg_input(last_line);
  248.         'E': mesg_edit;
  249.         'L': mesg_print;
  250.         'S': mesg_save(to_loc, subj, stop_msg);
  251.         'Q': mesg_quit(stop_msg);
  252.         '?': list('E')
  253.       end
  254.     until (not online) or stop_msg;
  255.     while TextBase <> nil do
  256.       begin
  257.         this := TextBase;                   { Get rid of list elements }
  258.         TextBase := TextBase^.next;
  259.         dispose(this)
  260.       end
  261.   end;
  262.  
  263. overlay procedure mesg_quick_scan;
  264. { Print abbreviated summary of messages }
  265.   var
  266.     private: boolean;
  267.     sep: char;
  268.     num, line_count: integer;
  269.   begin
  270.     line_count := 0;
  271.     private := FALSE;
  272.     num := mesg_start('Start');
  273.     MesgCurr := MesgBase;
  274.     while (MesgCurr <> nil) and (MesgCurr^.MesgNo < num) do
  275.       MesgCurr := MesgCurr^.next;
  276.     Writeln(USR);
  277.     while (not brk) and (MesgCurr <> nil) do
  278.       begin
  279.         if (MesgCurr^.TypMsg = 1) or (MesgCurr^.TypMsg = 2)
  280.           then
  281.             begin
  282.               private := TRUE;
  283.               sep := '*'
  284.             end
  285.           else sep := ':';
  286.         seek(summ_file, MesgCurr^.SummLoc);
  287.         read(summ_file, summ_rec);
  288.         Writeln(USR, MesgCurr^.MesgNo, sep, ' ', summ_rec.subject);
  289.         MesgCurr := MesgCurr^.next;
  290.         if user_rec.lines <> 99
  291.           then
  292.             begin
  293.               line_count := succ(line_count);
  294.               if line_count mod user_rec.lines = 0
  295.                 then pause
  296.             end
  297.       end;
  298.     if private
  299.       then
  300.         begin
  301.           Writeln(USR);
  302.           Writeln(USR, '"*" marks messages to or from you.')
  303.         end
  304.   end;
  305.  
  306. overlay procedure mesg_summary;
  307. { Message summary }
  308.   var
  309.     num, first_line, last_line, line_count: integer;
  310.   begin
  311.     line_count := 0;
  312.     num := mesg_start('Start');
  313.     MesgCurr := MesgBase;
  314.     while (MesgCurr <> nil) and (MesgCurr^.MesgNo < num) do
  315.       MesgCurr := MesgCurr^.next;
  316.     while (not brk) and (MesgCurr <> nil) do
  317.       begin
  318.         mesg_header_list(MesgCurr^.SummLoc, first_line, last_line);
  319.         MesgCurr := MesgCurr^.next;
  320.         if user_rec.lines <> 99
  321.           then
  322.             begin
  323.               line_count := succ(line_count);
  324.               if line_count mod (user_rec.lines div 5) = 0
  325.                 then pause
  326.             end
  327.       end
  328.   end;
  329.  
  330. overlay procedure mesg_read;
  331. { Read message }
  332.   var
  333.     ch: char;
  334.     update: boolean;
  335.     i, num, first_line, last_line, line_count: integer;
  336.   begin
  337.     OK := TRUE;
  338.     num := mesg_start('Start');
  339.     MesgCurr := MesgBase;
  340.     while (MesgCurr <> nil) and (MesgCurr^.MesgNo < num) do
  341.       MesgCurr := MesgCurr^.next;
  342.     while (not brk) and (MesgCurr <> nil) and OK do
  343.       begin
  344.         if MesgCurr^.MesgNo > user_rec.lasthi
  345.           then user_rec.lasthi := MesgCurr^.MesgNo;
  346.         mesg_header_list(MesgCurr^.SummLoc, first_line, last_line);
  347.         line_count := 4;
  348.         i := 1;
  349.         seek(mesg_file, first_line);
  350.         while (not brk) and (i <= last_line) do
  351.           begin
  352.             read(mesg_file, mesg_rec);
  353.             Writeln(USR, mesg_rec);
  354.             i := succ(i);
  355.             if user_rec.lines <> 99
  356.               then
  357.                 begin
  358.                   line_count := succ(line_count);
  359.                   if line_count mod user_rec.lines = 0
  360.                     then pause
  361.                 end
  362.           end;
  363.         update := (summ_rec.user_to = user_loc) and (summ_rec.status = private);
  364.         if update
  365.           then summ_rec.status := read;
  366.         if user_rec.access >= 250
  367.           then
  368.             begin
  369.               repeat
  370.                 Writeln(USR);
  371.                 ch := select('Message command', 'DeleteIndividualMovePublicRead');
  372.                 case ch of
  373.                   'D': mesg_delete;
  374.                   'I': summ_rec.status := private;
  375.                   'M': summ_rec.area := strint(prompt('Message area', 3, 'E'));
  376.                   'P': summ_rec.status := public;
  377.                   'R': summ_rec.status := read;
  378.                   '?': Writeln(USR, '<D>elete, <I>ndividual (private), <M>ove, <P>ublic, <R>ead')
  379.                 end
  380.               until (not online) or (ch <> '?');
  381.               if ch <> 'D'
  382.                 then MesgCurr := MesgCurr^.next;
  383.               update := update or (ch in ['I', 'M', 'P', 'R'])
  384.             end
  385.         else if (summ_rec.user_from = user_loc) or (summ_rec.user_to = user_loc)
  386.           then
  387.             begin
  388.               Writeln(USR);
  389.               if ask('DELETE this message')
  390.                 then mesg_delete
  391.                 else
  392.                   begin
  393.                     Writeln(USR, 'Message retained.');
  394.                     MesgCurr := MesgCurr^.next
  395.                   end
  396.             end
  397.           else MesgCurr := MesgCurr^.next;
  398.         if update
  399.           then
  400.             begin
  401.               seek(summ_file, pred(FilePos(summ_file)));
  402.               Write(summ_file, summ_rec)
  403.             end;
  404.         Writeln(USR);
  405.         if MesgCurr <> nil
  406.           then if user_rec.lines = 99
  407.                  then OK := TRUE
  408.                  else OK := ask('READ next message')
  409.       end
  410.   end;
  411.  
  412. overlay procedure mesg_kill;
  413. { Delete message }
  414.   var
  415.     num: integer;
  416.   begin
  417.     num := mesg_start('Message');
  418.     MesgCurr := MesgBase;
  419.     while (MesgCurr <> nil) and (MesgCurr^.MesgNo < num) do
  420.       MesgCurr := MesgCurr^.next;
  421.    if MesgCurr^.MesgNo = num
  422.       then
  423.         begin
  424.           seek(summ_file, MesgCurr^.SummLoc);
  425.           read(summ_file, summ_rec);
  426.           if (user_loc = summ_rec.user_from) or (user_loc = summ_rec.user_to) or
  427.              (user_rec.access >= 250)
  428.             then mesg_delete
  429.             else Writeln(USR, 'Message not to or from you.')
  430.         end
  431.       else Writeln(USR, 'Message not found.')
  432.   end;
  433.  
  434. overlay procedure mesg_area_change(req: Str10);
  435. { Change message area }
  436.   const
  437.     col_width = 12;
  438.   var
  439.     col_count, col_limit: integer;
  440.     this: AreaPtr;
  441.     pr: StrPr;
  442.   begin
  443.     col_limit := max(1, user_rec.columns div col_width);
  444.     pr := 'Message area';
  445.     if user_rec.help_level > 1
  446.       then pr := pr + ' [press "?" for menu]';
  447.     if req = ''
  448.       then req := prompt(pr, 10, 'ES?');
  449.     while req <> '' do
  450.       begin
  451.         this := AreaBase;
  452.         if req = '?'
  453.           then
  454.             begin
  455.               Writeln(USR, 'Available message areas:');
  456.               Writeln(USR);
  457.               while (not brk) and (this <> nil) do
  458.                 begin
  459.                   if user_rec.access >= this^.AreaAccs
  460.                     then Writeln(USR, pad(this^.AreaName, 14), this^.AreaDesc);
  461.                   this := this^.next
  462.                 end;
  463.               Writeln(USR);
  464.               req := prompt(pr, 10, 'ES?')
  465.             end
  466.         else if req <> ''
  467.           then
  468.             begin
  469.               while (req <> this^.AreaName) and (this <> nil) do
  470.                 this := this^.next;
  471.               if (req = this^.AreaName) and (user_rec.access >= this^.AreaAccs)
  472.                 then
  473.                   begin
  474.                     AreaSet := this^.Area;
  475.                     AreaReq := req;
  476.                     req := '';
  477.                     mesg_build_index(AreaSet);
  478.                     mesg_directory
  479.                   end
  480.                 else
  481.                   begin
  482.                     Writeln(USR, '"', req, '" not found.  Available message areas:');
  483.                     Writeln(USR);
  484.                     col_count := 0;
  485.                     this := AreaBase;
  486.                     while (not brk) and (this <> nil) do
  487.                       begin
  488.                         if user_rec.access >= this^.AreaAccs
  489.                           then
  490.                             begin
  491.                               Write(USR, pad(this^.AreaName, col_width));
  492.                               col_count := succ(col_count);
  493.                               if 0 = col_count mod col_limit
  494.                                 then Writeln(USR)
  495.                             end;
  496.                         this := this^.next
  497.                       end;
  498.                     if 0 <> col_count mod col_limit
  499.                       then Writeln(USR);
  500.                     Writeln(USR);
  501.                     req := prompt(pr, 10, 'ES?')
  502.                   end
  503.             end
  504.       end
  505.   end;
  506.  
  507.  Writeln(USR);
  508.