home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / bbs / rosuncr.arc / ROSMSG.INC < prev    next >
Text File  |  1991-08-11  |  18KB  |  576 lines

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