home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / bbs / turbobbs / mailsys.inc < prev    next >
Text File  |  1985-08-23  |  18KB  |  694 lines

  1. const
  2.   numsects = 9;
  3.   sectchar = '9';
  4.   maxlength = 24;
  5.  
  6. type
  7.   messages = record
  8.               number:  integer;
  9.               sender:  integer;
  10.               recver:  integer;
  11.               subject: name;
  12.               date:    name;
  13.               private: boolean;
  14.               section: byte;
  15.               repto:   integer;
  16.               reply:   integer;
  17.               recved:  boolean;
  18.             end;
  19.   sectname = array[0..numsects] of person;
  20.   messtext = array[1..24] of line;
  21.  
  22. const
  23.   sect : sectname = ('Section 0: All',
  24.                      'Section 1: General',
  25.                      'Section 2: Ohio Scientific',
  26.                      'Section 3: Kaypro, CP/M',
  27.                      'Section 4: Buy and Sell',
  28.                      'Section 5: 6502',
  29.                      'Section 6: Turbo Pascal',
  30.                      'Section 7: C',
  31.                      'Section 8: CompuServe',
  32.                      'Section 9: 6809');
  33.   maxmess = 52;   { <-- Maximum number of messages - this limit due to CP/M
  34.                     maximum directory size of 64 files on Kaypro.}
  35.  
  36. var
  37.   messagefile: file of messages;
  38.   count,
  39.   nextmess: integer;
  40.   messtable: array[1..maxmess] of messages;
  41.   preformat: boolean;
  42.  
  43. function namemess(number: integer): name;
  44.  
  45.   var
  46.     filename: name;
  47.  
  48.   begin
  49.     str((10000 + number):6, filename);
  50.     namemess := 'MESS' + copy(filename, 3, 4) + '.TXT';
  51.   end;
  52.  
  53. procedure kill(x: integer);
  54.  
  55.   var
  56.     victim: text;
  57.  
  58.   begin
  59.     assign(victim, namemess(x));
  60.     erase(victim);
  61.   end;
  62.  
  63. function secure(tabloc: byte): boolean;
  64.  
  65.   begin
  66.     with messtable[tabloc] do
  67.       secure := ((usernum <> sender)
  68.                 and (usernum <> recver)
  69.                 and (access < 5))
  70.                 or (usernum = 0);
  71.   end;
  72.  
  73. procedure listsections;
  74.  
  75.   var
  76.     loopvar : integer;
  77.     temp    : line;
  78.  
  79.   begin
  80.     if cts then begin
  81.       clearsc;
  82.       lineout('Sections:' + cr + lf);
  83.       for loopvar := 1 to numsects do begin
  84.         lineout(sect[loopvar]);
  85.       end;
  86.     end;
  87.   end;
  88.  
  89. procedure status;
  90.  
  91.   var
  92.     temp: line;
  93.  
  94.   begin
  95.     if cts then begin
  96.       lineout(cr + lf + 'Caller: ' + caller);
  97.       str(access:1, temp);
  98.       lineout('Access level: ' + temp);
  99.       str(count:2, temp);
  100.       lineout('System has ' + temp + ' messages;');
  101.       str(nextmess:4, temp);
  102.       lineout('Next message is: ' + temp);
  103.     end;
  104.   end;
  105.  
  106. procedure initmess;
  107.  
  108.   begin
  109.     if cts then lineout(cr + lf + 'Initializing message system...');
  110.     count := 0;
  111.     assign(messagefile, 'MESSAGES.BBS');
  112.     reset(messagefile);
  113.     repeat
  114.       count := count + 1;
  115.       read(messagefile, messtable[count]);
  116.     until (count = maxmess) or eof(messagefile);
  117.     close(messagefile);
  118.     unload;
  119.     nextmess := messtable[count].number + 1;
  120.     messopen := true;
  121.     status;
  122.   end;
  123.  
  124. function findmessage(x: integer): byte;
  125.  
  126.   var
  127.     loop: byte;
  128.  
  129.   begin
  130.     loop := 0;
  131.     repeat
  132.       loop := loop + 1;
  133.     until (loop >= count) or (messtable[loop].number >= x);
  134.     if messtable[loop].number = x
  135.       then findmessage := loop
  136.       else findmessage := 0;
  137.   end;
  138.  
  139. function getname(usernum: integer): person;
  140.  
  141.   var
  142.     tempid: sysid;
  143.  
  144.   begin
  145.     seek(idfile, usernum-1);
  146.     read(idfile, tempid);
  147.     getname := tempid.user;
  148.   end;
  149.  
  150. procedure header(tabloc: byte);
  151.  
  152.   var
  153.     temp: line;
  154.  
  155.   begin
  156.     if cts then with messtable[tabloc] do begin
  157.       str(number:4, temp);
  158.       stringout(cr + lf);
  159.       if private then stringout('Private ');
  160.       stringout('Message #' + temp);
  161.       temp := getname(sender);
  162.       stringout(' is from: ' + temp);
  163.       if recver > 0 then temp := getname(recver) else temp := 'ALL';
  164.       stringout(' to: ' + temp);
  165.       if recved then lineout(' (X)') else lineout(space);
  166.       stringout('Subj: ' + subject);
  167.       if clockin then stringout('  Time: ' + date);
  168.       if sectsin then stringout('  ' + sect[section]);
  169.       lineout(space);
  170.     end;
  171.   end;
  172.  
  173. procedure destroy(tabloc: byte);
  174.  
  175.   var
  176.     loop: byte;
  177.  
  178.   begin
  179.     if tabloc > 1 then begin
  180.       kill(messtable[tabloc].number);
  181.       for loop := tabloc+1 to count do
  182.         messtable[loop-1] := messtable[loop];
  183.       count := count - 1;
  184.       lineout('Message deleted.');
  185.     end;
  186.   end;
  187.  
  188. procedure readfile(tabloc: byte);
  189.  
  190.   begin
  191.     if cts then begin
  192.       outfile(namemess(messtable[tabloc].number));
  193.       if (messtable[tabloc].recver = usernum) and (usernum > 0)
  194.         then messtable[tabloc].recved := true;
  195.       if cts and (tabloc > 1) and not secure(tabloc) then begin
  196.         if getcap('Delete (Y/N)? ') = 'Y' then destroy(tabloc);
  197.       end;
  198.     end;
  199.   end;
  200.  
  201. procedure readmess(number: integer);
  202.  
  203.   var
  204.     tabloc: byte;
  205.     tempcs: name;
  206.  
  207.   begin
  208.     tabloc := findmessage(number);
  209.     if tabloc = 0 then lineout('Message not found.')
  210.       else if (secure(tabloc) and messtable[tabloc].private)
  211.         then lineout('Private message.')
  212.         else begin
  213.           header(tabloc);
  214.           tempcs := cs;
  215.           cs := cr + lf;
  216.           readfile(tabloc);
  217.           cs := tempcs;
  218.         end;
  219.   end;
  220.  
  221. procedure delmessage(x: integer);
  222.  
  223.   var
  224.     tabloc: byte;
  225.  
  226.   begin;
  227.     tabloc := findmessage(x);
  228.     if cts then begin
  229.       if tabloc > 1 then begin
  230.         if not secure(tabloc) then begin
  231.           header(tabloc);
  232.           if getcap('Are you sure (Y/N)? ') = 'Y' then destroy(tabloc);
  233.         end
  234.         else lineout('You can''t delete that message.');
  235.       end
  236.       else lineout('Message not found.');
  237.     end;
  238.   end;
  239.  
  240. function getnumber(prompt: line): integer;
  241.  
  242.   var
  243.     temp: name;
  244.     code: integer;
  245.     messnum: integer;
  246.  
  247.   begin
  248.     repeat
  249.       code := 0;
  250.       temp := getinput(prompt + 'which number? ', 14, echo);
  251.       if temp = '*' then messnum := lastmess+1 else val(temp, messnum, code);
  252.       if (code=0) and (messnum >= nextmess)
  253.         then lineout('Message number too high.');
  254.     until (temp = '') or ((code = 0) and (messnum < nextmess)) or not cts;
  255.     if (temp = '') or not cts then getnumber := 0 else getnumber := messnum;
  256.   end;
  257.  
  258. function getid(prompt: line): integer;
  259.  
  260.   var
  261.     temp: person;
  262.  
  263.   begin
  264.     temp := allcaps(getinput(prompt, 28, echo));
  265.     if temp = '' then getid := 0 else getid := findid(temp);
  266.   end;
  267.  
  268. procedure deletex;
  269.  
  270.   begin
  271.     if cts then begin
  272.       delmessage(getnumber('Delete: '));
  273.     end;
  274.   end;
  275.  
  276. procedure quickscan;
  277.  
  278.   var
  279.     loop: byte;
  280.     first: integer;
  281.  
  282.   begin
  283.     if cts then begin
  284.       first := getnumber('Start at ');
  285.       clearsc;
  286.       for loop := 1 to count do
  287.         if (messtable[loop].number >= first)
  288.           and not (secure(loop) and messtable[loop].private)
  289.           and cts and not cancelled
  290.           then header(loop);
  291.     end;
  292.   end;
  293.  
  294. procedure readind;
  295.  
  296.   var
  297.    messnum: integer;
  298.    tabloc : byte;
  299.  
  300.   begin
  301.     repeat
  302.       messnum := getnumber('Read (enter 0 to quit): ');
  303.       if messnum > 0 then readmess(messnum);
  304.     until (messnum = 0) or not cts;
  305.   end;
  306.  
  307. procedure messagesearch(first:byte; fromnum, tonum:integer; sectnum:byte);
  308.  
  309.   var
  310.     loop: byte;
  311.     inch: char;
  312.     oldnum: integer;
  313.     matched: boolean;
  314.  
  315.   begin
  316.     matched := false;
  317.     inch := null;
  318.     loop := first;
  319.     while cts and (loop <= count) and (inch <> 'Q') do begin
  320.       oldnum := messtable[loop].number;
  321.       if ((fromnum = 0) or (fromnum = messtable[loop].sender))
  322.         and ((tonum = 0) or (tonum = messtable[loop].recver))
  323.         and ((sectnum = 0) or (sectnum = messtable[loop].section))
  324.         and not (secure(loop) and messtable[loop].private)
  325.       then begin
  326.         matched := true;
  327.         cancelled := false;
  328.         header(loop);
  329.         inch := getcap('Read (Y/N/Quit)? ');
  330.         if inch = 'Y' then readfile(loop);
  331.       end;
  332.       if messtable[loop].number = oldnum then loop := loop + 1;
  333.     end;
  334.     if cts and not matched then lineout('No messages found.');
  335.   end;
  336.  
  337. function getfirst: byte;
  338.  
  339.   var
  340.     startmess, test : integer;
  341.     temp            : name;
  342.     prompt          : line;
  343.     loop            : byte;
  344.  
  345.   begin
  346.     repeat
  347.       prompt := 'Start at which message (? for stats, * for new)? ';
  348.       temp := getinput(prompt, 14, echo);
  349.       val(temp, startmess, test);
  350.       if temp = '?' then status;
  351.       if temp = '*' then startmess := lastmess + 1;
  352.     until (temp = '*') or ((test = 0) and (startmess < nextmess)) or not cts;
  353.     loop := 0;
  354.     repeat loop := loop + 1;
  355.       until (messtable[loop].number >= startmess) or (loop = count);
  356.     getfirst := loop;
  357.   end;
  358.  
  359. procedure readfrom;
  360.  
  361.   var
  362.     fromnum: integer;
  363.     first: byte;
  364.  
  365.   begin
  366.     if cts then begin
  367.       fromnum := getid('Enter name of sender: ');
  368.       if fromnum < 1
  369.         then stringout('Not a registered user name.')
  370.         else begin
  371.           first := getfirst;
  372.           messagesearch(first, fromnum, 0, 0);
  373.         end;
  374.     end;
  375.   end;
  376.  
  377. procedure readto;
  378.  
  379.   var
  380.     tonum: integer;
  381.     first: byte;
  382.  
  383.   begin
  384.     if cts then begin
  385.       tonum := getid('Enter name of addressee: ');
  386.       if tonum < 1
  387.         then stringout('Not a registered user name.')
  388.         else begin
  389.           first := getfirst;
  390.           messagesearch(first, 0, tonum, 0);
  391.         end;
  392.     end;
  393.   end;
  394.  
  395. procedure readsect;
  396.  
  397.   var
  398.     sectnum, first: byte;
  399.     inch: char;
  400.  
  401.   begin
  402.     if cts then repeat
  403.       if sectsin then
  404.        inch := getcap('Enter section number (0 for all, ? for list): ')
  405.        else inch := '1';
  406.       case inch of
  407.         '?'          : listsections;
  408.         '0'..sectchar: begin
  409.                          first := getfirst;
  410.                          messagesearch(first,0,0,integer(inch)-integer('0'));
  411.                        end;
  412.       end;
  413.     until (inch <> '?') or not cts;
  414.   end;
  415.  
  416. procedure readmenu;
  417.  
  418.   begin
  419.     if cts then begin
  420.       clearsc;
  421.       lineout('Read Menu:');
  422.       lineout(cr + lf + '[A]ll messages;');
  423.       lineout('[I]ndividual;');
  424.       lineout('[F]rom a certain user;');
  425.       lineout('[T]o a certain user;');
  426.       if sectsin then lineout('by [S]ection number;');
  427.       lineout(cr + lf + 'Hint: Use A* to read new messages since last call.')
  428.     end;
  429.   end;
  430.  
  431. procedure receive;
  432.  
  433.   var
  434.     uchar: char;
  435.  
  436.   begin
  437.     if cts then begin
  438.       if not expert then readmenu;
  439.       repeat
  440.         uchar := getcap('Read mode: (A,I,F,T,S, or ? for menu)? ');
  441.         if uchar = '?' then readmenu;
  442.       until (uchar in ['A','I','F','T','S',cr]) or not cts;
  443.       if uchar = 'I' then readind;
  444.       if cts and (uchar <> 'I') then begin
  445.         case uchar of
  446.           'A': messagesearch(getfirst,0,0,0);
  447.           'F': readfrom;
  448.           'T': readto;
  449.           'S': readsect;
  450.         end;
  451.       end;
  452.     end;
  453.   end;
  454.  
  455. procedure closemess;
  456.  
  457.   var
  458.     loop: byte;
  459.  
  460.   begin
  461.     rewrite(messagefile);
  462.     for loop := 1 to count do
  463.       write(messagefile, messtable[loop]);
  464.     close(messagefile);
  465.     messopen := false;
  466.   end;
  467.  
  468. {make "enter" an overlay procedure and make filesys another one to save space}
  469. procedure enter;
  470.  
  471.   var
  472.     tabloc: byte;
  473.     messbuff: messtext;
  474.     linenum: byte;
  475.     inch: char;
  476.  
  477.   procedure compose(var block: messtext; var linenum: byte);
  478.  
  479.     var
  480.       temp: name;
  481.  
  482.     begin
  483.       lineout(cr + lf + 'Enter message text: 24 lines of 80 chars max.');
  484.       lineout('An empty line ends entry. "." at start of line forces new line.');
  485.       lineout(space);
  486.       if linenum < 24 then repeat
  487.         linenum := linenum + 1;
  488.         str(linenum:2, temp);
  489.         stringout(temp + ': ');
  490.         block[linenum] := inputstring(echo);
  491.       until (linenum = 24) or (block[linenum] = '') or not cts;
  492.       if block[linenum] = '' then linenum := linenum - 1;
  493.     end;
  494.  
  495.   procedure list(var block: messtext; first, last: byte);
  496.  
  497.     var
  498.       loop: byte;
  499.       temp: name;
  500.  
  501.     begin
  502.       if (first > 0) and (last > 0) and cts then begin
  503.         loop := first;
  504.         while (loop <= last) and (not cancelled) and cts do begin
  505.           str(loop:2, temp);
  506.           stringout(temp + ': ');
  507.           lineout(block[loop]);
  508.           loop := loop + 1;
  509.         end;
  510.         lineout(space);
  511.       end;
  512.     end;
  513.  
  514.   procedure delline(var block: messtext; linenum: byte; var maxline: byte);
  515.  
  516.     var temp: char;
  517.         loop: byte;
  518.  
  519.     begin
  520.       list(block, linenum, linenum);
  521.       if cts and (linenum > 0) then begin
  522.         temp := getcap('Delete: are you sure (Y/N)? ');
  523.         if temp = 'Y' then begin
  524.           for loop := linenum+1 to maxline do block[loop-1] := block[loop];
  525.           block[maxline] := '';
  526.           maxline := pred(maxline);
  527.           lineout('Line deleted.');
  528.         end;
  529.       end;
  530.     end;
  531.  
  532.   procedure edit(var block: messtext; linenum: byte);
  533.  
  534.     var
  535.       oldstring: line;
  536.       newstring: line;
  537.       posn     : integer;
  538.  
  539.     begin
  540.       if (linenum > 0) and cts then begin
  541.         list(block, linenum, linenum);
  542.         oldstring := getinput('Enter string to replace: ', 80, echo);
  543.         newstring := getinput('Enter replacement: ', 80, echo);
  544.         posn := pos(oldstring, block[linenum]);
  545.         if posn <> 0 then begin
  546.           delete(block[linenum], posn, length(oldstring));
  547.           insert(newstring, block[linenum], posn);
  548.           list(block, linenum, linenum);
  549.         end
  550.         else lineout('Old string not found.');
  551.         lineout(space);
  552.       end;
  553.     end;
  554.  
  555.   procedure replace(var block: messtext; linenum: byte);
  556.  
  557.     begin
  558.       if (linenum > 0) and cts then begin
  559.         lineout('Old line:');
  560.         list(block, linenum, linenum);
  561.         lineout('Enter new line:');
  562.         stringout('? ');
  563.         block[linenum] := inputstring(echo);
  564.       end;
  565.     end;
  566.  
  567.   function whichline(linenum: byte): byte;
  568.  
  569.     var
  570.       temp: name;
  571.       code: integer;
  572.       x   : integer;
  573.  
  574.     begin
  575.       repeat
  576.         str(linenum:2, temp);
  577.         temp := getinput(' Which line? (1 - ' + temp + ')? ', 14, echo);
  578.         val(temp, x, code);
  579.       until ((x in [1..linenum]) and (code=0)) or (temp='') or not cts;
  580.       if (temp='') or not cts then whichline := 0 else whichline := x;
  581.     end;
  582.  
  583.   procedure newheader(var entry: messages);
  584.  
  585.     var
  586.       temp: char;
  587.       tonum: integer;
  588.  
  589.     begin
  590.       if cts then begin
  591.         entry.sender := usernum;
  592.         tonum := getid('Who to (RETURN or ENTER key for ALL)? ');
  593.         if tonum = 0 then lineout('Message to: ALL');
  594.         entry.recver := tonum;
  595.         entry.subject := getinput('Subject (14 characters max.)? ', 14, echo);
  596.         if clockin then begin
  597.           clock(month, date, hour, min, sec);
  598.           entry.date := time(month, date, hour, min, sec);
  599.         end;
  600.         if sectsin then repeat
  601.           temp := getcap('Which section (or "?" for list)? ');
  602.           if temp = '?' then listsections;
  603.           if temp in ['1'..sectchar] then entry.section := integer(temp)-integer('0');
  604.         until (temp in  ['1'..sectchar]) or not cts
  605.         else entry.section := 1;
  606.         if tonum > 0 then entry.private := getcap('Private message (Y/N)? ')='Y'
  607.         else entry.private := false;
  608.         entry.reply := 0;
  609.         entry.repto := 0;
  610.         entry.number := nextmess;
  611.         entry.recved := false;
  612.       end;
  613.     end;
  614.  
  615.   procedure storemess(var block: messtext; tabloc, lastline: byte);
  616.  
  617.     var
  618.       outfile: text;
  619.       linenum: byte;
  620.  
  621.     begin
  622.       if cts then begin
  623.         lineout('Writing message to disk...');
  624.         assign(outfile, namemess(nextmess));
  625.         rewrite(outfile);
  626.         linenum := 1;
  627.         while linenum <= lastline do begin
  628.           if (copy(block[linenum],1,1) = '.') or preformat then begin
  629.             writeln(outfile);
  630.             if not preformat then
  631.               block[linenum] := copy(block[linenum], 2, length(block[linenum])-1);
  632.           end
  633.           else write(outfile, ' ');
  634.           write(outfile, block[linenum]);
  635.           linenum := linenum + 1;
  636.         end;
  637.         writeln(outfile);
  638.         close(outfile);
  639.         unload;
  640.         nextmess := nextmess + 1;
  641.         count := count + 1;
  642.       end;
  643.     end;
  644.  
  645.   procedure editmenu;
  646.  
  647.     begin
  648.       if cts then begin
  649.         lineout(cr + lf + 'Edit menu:' + cr + lf);
  650.         lineout('[A]bort;');
  651.         lineout('[C]ontinue;');
  652.         lineout('[D]elete line;');
  653.         lineout('[E]dit a string in a line;');
  654.         lineout('[L]ist from line;');
  655.         lineout('[P]reformatted store (store with lines formatted as entered);');
  656.         lineout('[R]eplace one entire line;');
  657.         lineout('[S]tore Message in "No-Wrap" format.' + cr + lf);
  658.       end;
  659.     end;
  660.  
  661.   begin
  662.     preformat := false;
  663.     if cts then begin
  664.       if access < 2 then lineout('This ID cannot enter messages: Read [W]elcome file.')
  665.       else begin
  666.         tabloc := count + 1;
  667.         if tabloc > maxmess then lineout('No message space left.')
  668.         else begin
  669.           newheader(messtable[tabloc]);
  670.           linenum := 0;
  671.           compose(messbuff, linenum);
  672.           if not expert then editmenu;
  673.           repeat
  674.             inch := getcap('Edit command: A,C,D,E,L,P,R,S or ? for menu? ');
  675.             case inch of
  676.               'C': compose(messbuff, linenum);
  677.               'D': delline(messbuff, whichline(linenum), linenum);
  678.               'E': edit(messbuff, whichline(linenum));
  679.               'L': list(messbuff, whichline(linenum), linenum);
  680.               'P': begin preformat := true; storemess(messbuff, tabloc, linenum); end;
  681.               'R': replace(messbuff, whichline(linenum));
  682.               'S': storemess(messbuff, tabloc, linenum);
  683.               '?': editmenu;
  684.             end;
  685.           until (inch = abort)
  686.             or (inch = 'A')
  687.             or (inch = 'S')
  688.             or (inch = 'P')
  689.             or not cts;
  690.         end;  {2nd else}
  691.       end;  {1st else}
  692.     end; {if cts}
  693.   end; {enter}
  694. əəəəəəəəəə