[comp.os.vms] NEWS

SCS7317%OCVAXB@VB.CC.CMU.EDU (Christopher Seline) (05/25/88)

Later today I will post NEWS(DECNET/VMS) to INFO-VAX.

This product allows any user to read USENET off a UNIX, or ULTRIX machine
on your DECNET.  The program is small and requires no maintenance once it
is compiled.  There is no administrative overhead on the UNIX/ULTRIX machine.

Later this summer, I will post a program that interfaces NEWS(DECNET/VMS)
to VMSMAIL.  With this additional program, your site can receive USENET
articles via MAIL.  THIS IS NOT A UUCP IMPLEMENTATION.  It mearly allows
you to receive articles from any site that can send you mail.

                                     
Christopher Seline

scs7317@oberlin.bitnet
scs7317%ocvaxa@vb.cc.cmu.edu (internet)
bellcore!oberlin!ocvaxa!scs7317  (UUCP)

SCS7317%OCVAXB@VB.CC.CMU.EDU (Christopher Seline) (05/25/88)

$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by SCS7317
$! on Tuesday 24-MAY-1988 18:55:41.32
$!
$! It contains the following 3 files:
$! MAP.BAS MAP.PAS NEWS.TPU
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o);
Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;
Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1);
ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop
x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1);
If Current_Character='`' then Move_Horizontal(1);else
Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="MAP.BAS"
$ Check_Sum_is=1149044145
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X10 rem MAP -  hack tolook for news on a DECNET
X20 rem it isn't pretty (and it doesn't use DAP (which it should)) but
X30 rem it works.  Which is the number one important thing in the real world
X40 rem and all you programmers out there had better not forget it.
X100 print "Map -- Check your entire DECNET for sites running USENET"
X105 print
X130 print "It checks invisible nodes...and dead nodes....infact"
X140 print "It checks every possible node........"
X150 print
X200 for a = 1 to 74000
X202 if a = 68 then goto 400
X205 e = 0
X207 close #1
X210 when error in
X220 open str$(a)+'::"/usr/lib/news/active"' as file #1, access read
X230 use
X240 e = 1
X250 print a ,ert$(err)
X260 end when
X300 if e = 0 then close #1
X305 if e = 1 then goto 400
X310 print using "######",a;
X320 print " active"
X330 ac$=ac$ + " " + str$(a)
X400 next a
X510 print
V520 if ac$="" then print "No news easily found.  A more sophisticated utility i
Xs needed."
X530 if ac$<>"" then print "news at "; ac$
X540 print
X550 print "done."
$ GoSub Convert_File
$ File_is="MAP.PAS"
$ Check_Sum_is=1867919516
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xprogram map (input,output);
X
X(* MAP.PAS`009This is a unsupported part of the NEWS(DECNET/VMS) suite.
X
X   MAP.PAS`009Looks around your DECNET from any node suitably configured
X`009 `009for NEWS(DECNET/VMS).  You should pick the one closest to
X`009`009you, and DEFINE it as NEWS_FARSITE.
X
X   MAP.PAS`009works in the most crude way possible.  A more sophisticated
X`009`009technique (using DAP) would be nice, but...then again, 
X`009`009this works.
X*)
X
XVAR node, stat : integer;
X    node_spec : varying [200] of char :='';
X    infil : text;
X
XBEGIN
X   WRITELN('MAP X01  --  Map Your DECNET');
X   WRITELN('             Looking for sites suitable to be NEWS_FARSITE');
X   WRITELN;
X   for node := 1  TO 99000 DO
X`009BEGIN
X`009   node_spec := dec(node,5) + '::"/usr/lib/news/active"';
X`009   write(dec(node,5) + '::  ');
X`009   OPEN(`009file_variable `009:= infil,
X`009`009`009file_name`009:= node_spec,
X`009`009`009history`009`009:= READONLY,
X`009`009`009sharing`009`009:= READONLY,
X`009`009    `009error`009`009:= CONTINUE);
X`009   stat := status(infil);
X`009   IF (stat = 0)
X`009`009THEN writeln('SUCCESS!!!  This could be used as news_farsite')
X`009`009ELSE 
X`009`009`009begin
X`009`009`009write   ('Not this node. STATUS :=');
X`009`009`009writeln (stat);
X`009`009`009end;
X`009   CLOSE(infil, error`009`009:= CONTINUE);
X`009
X
X`009END;
X                    
X
XEND.
X                           
$ GoSub Convert_File
$ File_is="NEWS.TPU"
$ Check_Sum_is=1728655159
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X! NEWS-news.tpu - a program to let people read news in comfort (scrolling
X! backwards, automatic pause, etc) 
X!
X!`009news.tpu Copyright 1988 (c) Christopher Seline
X!`009ALL RIGHTS RESERVED
X!
X!`009TO USE THIS PRODUCT YOU MUST OBTAIN A LICENSE
X!
X!`009USE OF THIS PRODUCT MORE THAN FIVE (5) TIMES
X!`009WITHOUT A LICENSE IS A CRIME.  TO OBTAIN A LICENSE
X!`009SEND THE LICENSING FEE TO:
X!`009`009Christopher Seline
X!`009`009127 Green Bay Rd.
X!`009`009Winnetka, IL  60093
X!
X!`009LICENSING FEE:
X!`009`009Cluster license $250`009(per cluster)
X!`009`009Machine license $100`009(per machine)
X!`009`009Personal license$020`009(per user)
X!
X!
X 
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                     installing this program
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!
X! If you have lost the detailed instructions:
X! rename this file to SYS$LOGIN:NEWS.TPU
X! issue the DCL command  EDIT/TPU/NOSEC/COM=SYS$LOGIN:NEWS.TPU
X!`009Now, the following command will invoke news
X!`009`009$ edit/tpu/sec=sys$login:news
X!`009Don't forget to define NEWS_FARSITE to some decnet node.
X!`009`009use MAP.PAS or MAP.BAS to figureout what to name it.
X!
X
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                    INITIALIZATION PROCEDURES
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X
XPROCEDURE tpu$init_procedure;
X! TPU calls this procedure automatically when it starts up.
X! After it exits, TPU will wait for bound keys and do their routines.
X    init_define_constants;
X    init_first; 
X    init_determine_mode;
X    init_PopUp_intro_text;
X    init_subscribe;                 
X    init_moveto_first_group_with_news;
XENDPROCEDURE;
X
X!----------
XPROCEDURE init_define_constants;
X
V    message_window_length := 3;  `009`009`009`009! size of the message window, 
Xin lines
V    status_text := "(X03.50) ^Z to exit    ? for help    ";`009! text to be dis
Xplayed on the window's status line
X    spool_dir := "news_spool:";`009`009`009`009! spool area if enabled
X    page_scroll_amount := 19;
X
V    $remote := 1; $sync := 2; $local := 3; $unknown := -1;  $mode := $unknown;`
X009`009`009! GLOBAL MODE
V!`009$mode indicates what mode NEWS operates in.  That is, where it looks for f
Xiles 
X!`009`009$remote`009`009--  All files are on NEWS_FARSITE
V!`009`009$sync`009`009--  active. is on NEWS_FARSITE, but some news articles ar
Xe kept in NEWS_SPOOL,
X!`009`009`009`009    so check there first
X!`009`009$local`009`009--  All files are in NEWS_SPOOL (including active).
V!`009`009`009`009    In $local mode, NEWS does not use DECNET at all.  (unless 
Xyou've defined
X!`009`009`009`009    NEWS_SPOOL to be on a DECNET NODE.
X
V    no := 0; yes := 1; help_visited := no; keypad_help_visited := no;`009`009! 
XGLOBAL HELP BUFFER STATUS
V                                                                               
X         ! change these to $ form
XENDPROCEDURE;
X
X!---------                
XPROCEDURE init_first
XLOCAL main_window_length;
Xon_error`009! kill error messages
Xendon_error;
X                              
V    main_window_length := GET_INFO(SCREEN, "visible_length") - message_window_l
Xength;
X    SET(PROMPT_AREA, main_window_length+1, 1, NONE);    
X                          
V    text_buffer := CREATE_BUFFER("Text");`009`009! create a buffer to hold the 
Xtext
X    SET(EOB_TEXT, text_buffer, "[END OF NEWS ITEM]");
X    SET(NO_WRITE, text_buffer);
X 
V    text_window := CREATE_WINDOW(1, main_window_length, ON);`009! create the ma
Xin text window
X    MAP(text_window, text_buffer);
X
V    message_buffer := CREATE_BUFFER("Message Buffer");`009! Create a message bu
Xffer for TPU messages,
V    SET(NO_WRITE, message_buffer); `009`009`009! for debugging, and map it into
X a window
X    SET(SYSTEM, message_buffer);
X    SET(EOB_TEXT, message_buffer, "");
V    message_window := CREATE_WINDOW(25-message_window_length, message_window_le
Xngth, OFF);
X    MAP(message_window, message_buffer);
X
X
XSET(FACILITY_NAME, "NEWS");`009`009`009`009! some initializtion   
XSET(MESSAGE_FLAGS, 15);`009`009`009`009`009! all message info
XSET(SUCCESS, OFF);
XSET(INFORMATIONAL, OFF);
X
Vjournal_open('nl:');`009`009`009`009`009! hack to prevent W-TPU$NOJOURNAL messa
Xge
X
Xenable_bell;
X
XENDPROCEDURE;
X
X
X!----------         
XPROCEDURE    init_determine_mode
Xlocal junk, junk1;
Xon_error 
Vjunk1 := 1;`009`009`009`009`009! indicate error, we expect an error when checki
Xng for local spooling
Xendon_error;
X
Xunmap(message_window);`009`009`009`009! stiffle RMS error messages
X
X! this procedure also creates active                                           
Xactive := CREATE_BUFFER ('active');`009`009! buffer holds /usr/lib/news/active
XPOSITION (active);
XSET (NO_WRITE, active);
XSET (SYSTEM, active);       
XSET (TIMER, ON, "Loading active");
X
Vmessage("");message("");message("");message("");! why can we intercept them w/ 
Xon ERR!!!!
X
XREAD_FILE(spool_dir + 'active.');
XIF beginning_of(active) = end_of(active) THEN
X   READ_FILE('news_farsite::"/usr/lib/news/active"');
X   $mode := $remote
X   ELSE
X   $mode := $local;
XENDIF;
X
XSET (TIMER, OFF);
X
XIF end_of(active) = beginning_of(active) THEN
X   message("I could not load active.");
X   message("USE q TO ABORT");
X   message("USE q TO ABORT");
X   message("USE q TO ABORT");
X   five_map;
X   abort;
XENDIF;
X
X
XIF $mode = $remote THEN
X! determine if spooling exists.....
Xjunk := create_buffer("junk");
Xposition(junk);
Xjunk1 := 0;
XREAD_FILE (spool_dir + 'news-spooling-exists.');
VIF junk1 <> 1 then $mode := $sync; ENDIF;`009! if the file was sucessfully open
Xed then we have local spooling of remote files
X
XENDIF;
X                                     
XIF $mode = $remote THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (remote)") ELSE
XIF $mode = $local  THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (local)")  ELSE
XIF $mode = $sync   THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (sync)")   ELSE
X`009`009`009MESSAGE("NEWS(DECNET/VMS) V00.90 (BUG)");
XENDIF;ENDIF;ENDIF;`009! why can't the CASE statement deal with variables!
X
Xmap(message_window,message_buffer);`009`009! UNstiffle messages
X
XENDPROCEDURE;
X
X!----------
XPROCEDURE init_PopUp_intro_text;
XPOSITION (BEGINNING_OF(text_buffer));
X
X! THIS IS WHERE INTRODUCTORY TEXT GOES
X
V copy_text("                news.tpu Copyright (c) 1988 Christopher Seline"); s
Xplit_line;
X copy_text("                              ALL RIGHTS RESERVED "); split_line;
X copy_text(" "); split_line;
V!copy_text("    USE OF THIS PRODUCT MORE THAN FIVE (5) TIMES WITHOUT A LICENSE 
XIS A"); split_line;
V!copy_text("    CRIME.  TO OBTAIN A LICENSE SEND THE LICENSING FEE TO: "); spli
Xt_line;
X!copy_text("    `009Christopher Seline "); split_line;
X!copy_text("`009127 Green Bay Rd."); split_line;
X!copy_text("`009Winnetka, IL  60093 "); split_line;
X!copy_text(" "); split_line;
X!copy_text("    LICENSING FEE:"); split_line;
X!copy_text("         Cluster license $250`009(per cluster)"); split_line;
X!copy_text("         Machine license $100`009(per machine)"); split_line;
X!copy_text("         Personal license$020`009(per user)"); split_line;
X copy_text(" "); split_line;
X copy_text(" "); split_line;
X 
V copy_text("                  Press the SPACE BAR for next USENET message"); sp
Xlit_line;
X!
XENDPROCEDURE; 
X
X
X!----------
XPROCEDURE init_subscribe
X
Xsubscribe := CREATE_BUFFER ('subscribe','sys$login:News_Subscribe.dat');
XSET (NO_WRITE, subscribe);
XSET (SYSTEM, subscribe);
XPOSITION (subscribe);
XIF (BEGINNING_OF (subscribe) = END_OF (subscribe)) ! null or file not found
X   THEN                                    
X   message ("Can't find your news subscription -- subscribing for you.");
X   message ("This takes several minutes -- so sit back and relax...");
X   subscribe_create;
XENDIF;
Xupdate_banner;
XENDPROCEDURE;
X                                                                         
X
X           
V!------------------------------------------------------------------------------
X-
XPROCEDURE subscribe_create
XLOCAL a,b;
XPOSITION (subscribe);
VCOPY_TEXT (active);`009`009`009`009`009! copy active buffer into subscribe buff
Xer
X
XIF (BEGINNING_OF (subscribe) = END_OF (subscribe)) ! null or file not found
X   THEN                                    
X   message ("!!BUG -- reached subscribe_create with NULL active buffer");
X   abort;
XENDIF;            
X
X
X! now we need to massage the data   
VMAP (text_window, subscribe);`009`009`009`009! let them watch us massage the da
Xta
VPOSITION (BEGINNING_OF (subscribe));`009`009`009! leave only column one and two
X, delete column three and four
Xloop
X    exitif mark(none) = END_OF(subscribe);`009`009! exit loop at end of buffer
X
X    a := select_column_two;`009`009`009`009! set last message read column
V    b := INT(a) - 20;`009`009   `009`009`009! 20 is a magic number for how many
X messages to mark as unread
X    IF b < 1 THEN b := 1; ENDIF;
X    replace_column_two (b);
X
X    position (search(' ',FORWARD));`009`009`009! delete last two columns
X    move_horizontal (+1);
X    position (search(' ',FORWARD));
X    split_line;
X    erase_line;
Xupdate(current_window);
Xendloop;
X                   
V!move_group_to_top ("comp.os.vms");                      ! these groups will be
X read first
X!move_group_to_top ("rec.arts.comics");
X!move_group_to_top ("rec.humor");
X!move_group_to_top ("rec.arts.drwho");
X!move_group_to_top ("rec.arts.startrek");
Xmove_group_to_top ("news.announce.newusers");
X
VPOSITION (BEGINNING_OF (subscribe)); `009`009`009`009! unsubscribe control grou
Xp
Xposition(SEARCH (LINE_BEGIN & 'control', FORWARD, NO_EXACT));
Xreplace_column_two (99999);`009! 99999 magic number for unsubscribed
X
X
XPOSITION (BEGINNING_OF (subscribe));
Xmap(text_window,text_buffer);
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE move_group_to_top (group_name)
XLOCAL group_name, j1, j2;
X! move a group to the top of subscribe buffer
V! note, unlike most routines, this one does not restore original position in bu
Xffers
X
XPOSITION (BEGINNING_OF (subscribe));
Xj1 := SEARCH (LINE_BEGIN & group_name & ' ', FORWARD, NO_EXACT);
XIF j1 = 0 THEN return; ENDIF;`009`009`009! return if it doesn't exist
Xposition(j1);
X
Xj2 := current_line;
Xerase_line;
XPOSITION (BEGINNING_OF (subscribe));
Xcopy_text(j2);
Xsplit_line;
XENDPROCEDURE;
X      
X
X
V!------------------------------------------------------------------------------
X-
VPROCEDURE     init_moveto_first_group_with_news;`009`009! move to first group w
Xith something in it to read 
X
Xmove_to_group_with_pending_news;
X
XENDPROCEDURE;
X 
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
V!                                    PROCEDURES -- MANY BOUND TO KEYS -- MANY H
XELPER FUNCTIONS
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE page_down;
X! scroll down almost one screensworth
X    SCROLL(text_window, page_scroll_amount);
XENDPROCEDURE;
X
X                                  
X             
V!------------------------------------------------------------------------------
X-             
XPROCEDURE page_up;
X! scroll up almost one screensworth                                            
X    SCROLL(text_window, -page_scroll_amount);
XENDPROCEDURE;
X
X
X             
V!------------------------------------------------------------------------------
X-                                       
XPROCEDURE line_down 
Xlocal a;
X! scroll down one line
X    a:=mark(none);
X    SCROLL(text_window, 1);
X    If a = mark(none) THEN`009`009`009`009! we haven't moved
X      move_vertical(+1);
X    ENDIF;
XENDPROCEDURE;
X
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE line_up
Xlocal a;
X! scroll up one line
X    a:=mark(none);
X    SCROLL(text_window, -1);
X    If (a = mark(none)) THEN`009`009`009`009! we haven't moved
X      move_vertical(-1);
X    ENDIF;
XENDPROCEDURE;
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE go_to_group;
Xmessage("Go to exact group is no longer supported");
XENDPROCEDURE;   
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE go_to_group_NOexact
XLOCAL group_name, j1,j2,j3;                                                    
X! go to a new group....no need to find exact name
X
Xon_error`009! kill error messages
X!    if error = tpu$_strnotfound then
X!`009message ("couldn't find it");
X!    endif;
Xendon_error;
X      
X
Xj1 := CURRENT_BUFFER;
XPOSITION (subscribe);            
Xj3 := MARK (none);`009! where we were if search fails
X              
Xgroup_name := READ_LINE ('GO TO WHICH GROUP (NOexact name): ');
X
Xmove_vertical(+1);`009`009`009! so we don't find current line
Xj2 := SEARCH ( group_name , FORWARD, NO_EXACT);
X
XIF j2 = 0 THEN       `009`009`009`009! try from beginning of buffer
X`009POSITION (BEGINNING_OF (subscribe));
X`009j2 := SEARCH ( group_name , FORWARD, NO_EXACT);
XENDIF;                                          
X
XIF j2 = 0 THEN`009`009`009`009`009! couldn't find it anywhere
X   MESSAGE ("Can't find the group you refered to: "+ group_name);
X   POSITION (j3);`009! move to old place in subscribe
X   POSITION (j1);`009! move to old buffer
X   RETURN(0);             
XENDIF;                                          
X
XPOSITION (j2);
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
X
Vif mark(none) = j3 then message ("This is the only group that matches: "+ group
X_name); 
X   endif;
X
Xposition(text_buffer);      
Xzero_text_buffer;
Xupdate_banner;`009`009`009`009`009! indicate new group and position
X      `009
XENDPROCEDURE;   
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE update_banner`009`009! update status_line to current grp & position
VLOCAL s1,s2, subs_current, a2, active_top, active_bot, diff,arg;               
X                
X
Vposition (subscribe);   `009`009`009`009! get subscribed group & next mesg. num
Xber
Xs1 := select_column_one;
Xs2 := select_column_two;
Xsubs_current := INT(s2);                                                   
X
Vposition (BEGINNING_OF(active));`009`009`009!move to same group in active as in
X subscribe                       
Xarg := SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT);
Vif arg = 0 THEN   `009`009`009`009`009! subscribe has groups that no longer exi
Xst in active;
X   sync_subscribe;
X   return(0); 
XENDIF;
Xposition(arg);
Xa2 := select_column_two;        
Xactive_top    := int (a2);  
Xactive_bot    := int (select_column_three);
XIF active_bot > subs_current THEN subs_current := active_bot; ENDIF;
Xdiff := active_top - subs_current;
XIF diff < 0 THEN diff := 0; ENDIF;                
X
XIF subs_current = 99999 then
VSET(STATUS_LINE, text_window, REVERSE, status_text + '    ' + s1 + ': Unsubscri
Xbed');
X`009ELSE
VSET(STATUS_LINE, text_window, REVERSE, status_text + '    ' + s1 + ':' + STR(su
Xbs_current)+'     '+str(diff)+' left');
X      `009ENDIF;
Xupdate(current_window);
XENDPROCEDURE;
X                                                                               
X
V`012                                                                           
X    
V!------------------------------------------------------------------------------
X-
Xprocedure sync_subscribe`009`009`009`009! called if subscribe is out of whack
V;!!!!!LOCAL ac_tmp, sub_tmp, a, b;`009       `009`009! this happens if a new gr
Xoup is added or deleted from active
X
Xdisable_bell;
Xmessage("Since I last checked groups have been added or deleted from active");
Xmessage("So, I'm going to sync subscribe to active.");
Xmessage ("This takes several minutes -- so sit back and relax...");
X
X! first makes copies of subscribe and active
X
X
Xac_tmp := CREATE_BUFFER("ac_tmp");  
Xset(No_write, ac_tmp);
Xposition(ac_tmp);  copy_text(active);
X
Xsub_tmp := CREATE_BUFFER("sub_tmp");  set(No_write, sub_tmp);
Xposition(sub_tmp); copy_text(subscribe);
X
Xmap(text_window,sub_tmp);
Xposition(beginning_of(sub_tmp));
Vloop`009`009`009! check each group in subscribe, if it isn't in active then del
Xete it from subscribe
X    exitif mark(none) = END_OF(sub_tmp);
X    a1:= mark(none);
X    a := select_column_one;
X    position(beginning_of(ac_tmp));
X    b := search(LINE_BEGIN & a & ' ', FORWARD, NO_EXACT);
X    if b = 0 then
X       position(a1);
X       erase_line;
X       message ("Deleted "+a);
X     ELSE
X       position(b); 
X       erase_line;`009! erase each line -- any left will be not in subscribe
X       position(a1);
X       move_vertical (+1);
X    ENDIF;
X    update(text_window);
Xendloop;
X      
Xif beginning_of(ac_tmp) <> end_of(ac_tmp) THEN
X   map(text_Window,ac_tmp);
V   POSITION (BEGINNING_OF (ac_tmp));`009`009`009! leave only column one and two
X, delete column three and four
X   loop
X       exitif mark(none) = END_OF(ac_tmp);`009`009! exit loop at end of buffer
X       message('Added ' + select_column_one);
X       a := select_column_two;`009`009`009`009! set last message read column
V       b := INT(a) - 20;`009`009   `009`009! 20 is a magic number for how many 
Xmessages to mark as unread
X       IF b < 1 THEN b := 1; ENDIF;
X       replace_column_two (b);
X
X       position (search(' ',FORWARD));`009`009`009! delete last two columns
X       move_horizontal (+1);
X       position (search(' ',FORWARD));
X       split_line;
X       erase_line;
X   update(text_window);
X   endloop;
X   position(sub_tmp);
X   copy_text(ac_tmp);
X   update(text_window);
XENDIF;
X
Xerase(subscribe);
Xposition(subscribe);
Xcopy_text(sub_tmp);
X    
Xposition(beginning_of(subscribe));
Xposition(beginning_of(active));
Xposition(beginning_of(text_buffer));
Xmap(text_window,text_buffer);      
Xenable_bell;
XENDPROCEDURE;
X
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE catch_up`009`009! mark current group as read
XLOCAL s1, a2, active_top,x;
Xx := mark(none);
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
X
Xposition (BEGINNING_OF(active));! move to same group in active
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa2 := select_column_two;
Xactive_top    := int (a2);
X
Xposition(subscribe);
Xreplace_column_two (active_top);`009! update subscribe mesg#
X
Xupdate_banner;
Xzero_text_buffer;
Xposition(x);
XENDPROCEDURE;
X           
X                                                       
V!------------------------------------------------------------------------------
X-
XPROCEDURE UN_catch_up`009`009! mark this group as UNread
XLOCAL s1, a3, active_bottom, old_pos;
X
Xold_pos := mark(none);
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
X
Xposition (BEGINNING_OF(active));! move to same group in active
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa3 := select_column_three;
Xactive_bottom := int (a3);
X                          
Xposition(subscribe);
Xreplace_column_two (active_bottom);`009! update subscribe mesg#
X
Xposition(old_pos);
Xzero_text_buffer; 
Xupdate_banner;
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE Unsubscribe
XLOCAL x;
Xx := mark(none);
Xposition(subscribe); 
Xreplace_column_two (99999);`009! 99999 magic number for unsubscribed
Xposition(x);  `009   `009`009! This will be a bug when a group his 99999
Xzero_text_buffer;
Xupdate_banner;
XENDPROCEDURE
X
X
V!------------------------------------------------------------------------------
X-
VPROCEDURE Subscribe_proc`009`009`009`009! resubscribe to unsubscribed news grou
Xp
XLOCAL x;
Xx := mark(none);
Xposition(subscribe); 
XUn_catch_up;
Xposition(x);
Xupdate_banner;
XENDPROCEDURE
X
X
X
X                                                       
X`012
V!------------------------------------------------------------------------------
X-
XPROCEDURE next_news_message     
VLOCAL i3,j1,j2,j3,s1,s2,s1a, s4,spool,news_file,subs_current,i,a1,a2,a3,active_
Xbottom,active_top,spool_file;
X! read in next message
X
X
Xupdate_banner;`009`009`009! Indicate which group and message this is
Xdisable_bell;`009`009`009! no beeping
X
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
Xs1a:= s1;
Xs2 := select_column_two;
Xsubs_current := INT(s2);
X
XIF subs_current = 99999 THEN `009! if unsubscribed then recurse till OK
X`009next_group;
X      `009next_news_message;
X`009return(0);
XENDIF;
X                
X!move to same group in active as in subscribe                       
Xposition (BEGINNING_OF(active));
Xi := SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT);
Xposition(i);
X           
Xa1 := select_column_one;
Xa2 := select_column_two;
Xa3 := select_column_three;
Xactive_bottom := int (a3);      
Xactive_top    := int (a2);                                          
X                
X! create file name
XIF subs_current < active_bottom THEN subs_current := active_bottom; ENDIF;
XIF subs_current > active_top    THEN`009! Nothing Left to READ?
V`009message('Nothing left to read in group ' + s1 + ' -- Moving to next Group')
X;
X`009next_group; RETURN; ENDIF;
X                                     
Xspool := s1;
XTRANSLATE(spool,'_', '.');`009`009! convert to VMS  Name
XTRANSLATE(s1,   '/', '.');         `009! convert to Unix Name
X
Vnews_file := 'news_farsite::"/usr/spool/news/' + s1 + '/' + STR(subs_current) +
X '"' ;
X     
Xspool_file := spool_dir + spool + '_' + STR(subs_current)+ '.';
X                                  
Xsubs_current := subs_current + 1;
Xposition(subscribe); 
Xreplace_column_two (subs_current);`009! update subscribe mesg#
X
X!read in file                                          
XPOSITION (text_buffer);
XERASE (text_buffer);
XSET (TIMER, ON, 'Retrieving.');
X
XIf ($mode = $local)  or ($mode = $sync) THEN READ_FILE ( spool_file ); ENDIF;
X  
XIf ($mode = $remote) `009`009`009THEN READ_FILE ( news_file );  ENDIF;
X
XIf ($mode = $sync) and (BEGINNING_OF (text_buffer)= END_OF (text_buffer))
X   THEN READ_FILE ( news_file ); ENDIF;                      
X
XPOSITION (BEGINNING_OF (text_buffer));
VIF (BEGINNING_OF (text_buffer)= END_OF (text_buffer))`009! null or file not fou
Xnd
X   THEN 
X     message ("Null News Body -- Hope that's OK");
X     message("");
X   ELSE
V     underline_subject_line;          `009`009`009! underline subject if got ne
Xws
XENDIF;                      
X
X
XSET (TIMER, OFF);
Xenable_bell;
X
XENDPROCEDURE;                                                         
X
X
X`012
V!------------------------------------------------------------------------------
X-
VPROCEDURE next_group;`009`009`009      ! still needs to skip comletely read gro
Xups
X
Xposition(subscribe);            
Xif mark(none) = end_of(current_buffer)then 
X`009message ('ARGH -- End of News Groups (no more to read)'); 
X`009move_vertical(-1);
X`009return(0);
XENDIF;
Xmove_vertical(+1);`009`009`009`009! move to next group
Xmove_to_group_with_pending_news;
X
Xupdate_banner;        
X
XENDPROCEDURE;
X                                                                               
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE move_to_group_with_pending_news
X! checks current group -- if current group has news it does not move forward
X
XLOCAL s1,s2,subs_current,a2,active_top,active_bot,diff;
X
Xposition(subscribe);
X! check for end of news groups
Xif mark(none) = end_of(current_buffer)then 
X`009message ('argh -- End of News Groups (no more to read)'); 
X`009move_vertical(-1);                                      
X`009return(0);
XENDIF;
X
X! if its an unsubscribed group, skip it
Xs1 := select_column_one;
Xs2 := select_column_two;
Xsubs_current := INT(s2);                                        
X
XIF subs_current = 99999 THEN `009! if unsubscribed then recurse till OK
X`009next_group;
X`009return(0);
XENDIF;
X
Vposition (BEGINNING_OF(active));`009`009`009!move to same group in active as in
X subscribe                       
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa2 := select_column_two;        
Xactive_top    := int (a2);  
Xactive_bot    := int (select_column_three);
XIF active_bot > subs_current THEN subs_current := active_bot; ENDIF;
Xdiff := active_top - subs_current;
XIF diff < 0 THEN diff := 0; ENDIF;                
X
XIF diff = 0 THEN`009`009`009! recurse till locate group with items to read
X   next_group;
X   return(0);
XENDIF;       
X
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE zero_text_buffer;`009`009`009`009! erase text buffer
VIF end_of(text_buffer) <> beginning_of(text_buffer) THEN! but don't bother unle
Xss there is text in it
X   erase(text_buffer);
XENDIF;
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE space_bar
XLOCAL here;                                                             
Xhere := MARK(none);
Xpage_down;
XIF here = mark(none) THEN`009`009`009`009! we didn't move
X   next_news_message;`009`009`009`009`009! so at end of mesg
XENDIF;
XENDPROCEDURE;
X      
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE exit_news;
X
XWRITE_FILE (subscribe, 'sys$login:NEWS_SUBSCRIBE.dat');
Xdisable_bell;
Xmessage ('Thank You For Using NEWS(DECNET/VMS)`009  `009:-)');
Xquit;
XENDPROCEDURE;                                                  
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE keypad_help;
X
XIf keypad_help_visited = no THEN
X  keypad_help_init;
X  keypad_help_visited := yes;
X  return;
XENDIF;                
X                     
XMAP(text_window, keypad_help_buffer);
X
XENDPROCEDURE
X
X
X
XPROCEDURE keypad_help_init;
Xkeypad_help_buffer := create_buffer('keypad_help_buffer');
XSET(NO_WRITE, keypad_help_buffer);
XSET(SYSTEM, keypad_help_buffer);
XSET(EOB_TEXT, keypad_help_buffer, "");
X          
XMAP(text_window, keypad_help_buffer);
Xposition(keypad_help_buffer);
X
X!`012
Xcopy_text ('NEWS keypad for VT100 series terminals'); split_line;
Xcopy_text (''); split_line;
Vcopy_text ('      _________________________________     _______________________
X__________'); split_line;  
Vcopy_text ('      |   ^   |   |   |       |       |     |       |       |      
X |       |'); split_line;
Vcopy_text ('      |   |   |   V   |       |       |     | Find  | Help  | Pause
X |       |'); split_line;
Vcopy_text ('      |_______|_______|_______|_______|     |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X | Next  |'); split_line;
Vcopy_text ('                                            |       |       |      
X | Group |'); split_line;
Vcopy_text ('                                            |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('        CTRL/R    - Refresh                 |_______|_______|______
X_| Next  |'); split_line;
Vcopy_text ('        CTRL/Z    - Exit                    |     Next      |Prev  
X |Message|'); split_line;
Vcopy_text ('                                            |     Screen    |Screen
X |       |'); split_line;
Vcopy_text ('                                            |_______________|______
X_|_______|'); split_line;
Xcopy_text (''); split_line;
Xposition(beginning_of(keypad_help_buffer));
X
X!    
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE news_help;
X! give them help                                                               
X
XIf help_visited = no THEN
X  news_help_init;
X  help_visited := yes;
X  return;
XENDIF;
X                     
XMAP(text_window, help_buffer);
X
XENDPROCEDURE
X
X
X
XPROCEDURE news_help_init;
Xhelp_buffer := create_buffer('help_buffer');
XSET(NO_WRITE, help_buffer);
XSET(SYSTEM, help_buffer);
XSET(EOB_TEXT, help_buffer, "");
X
XMAP(text_window, help_buffer);
Xposition(help_buffer);
X
Vcopy_text(' NEWS keyboard help:                                                
X            '); split_line;
Vcopy_text('              n      - get next message                             
X            '); split_line;
Vcopy_text('              N      - moves to next group                          
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('              s      - Saves current message to a file              
X            '); split_line;
Vcopy_text('              g      - go to a group by name                        
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('              c      - Catch-up    (marks all messages in current gr
Xoup as read)'); split_line;
Vcopy_text("              u      - Unsubscribe           (you'll never see this 
Xgroup again)"); split_line;
Vcopy_text('              #      - read article by number       (skips interveni
Xng articles)'); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('         CTRL/W      - refresh screen                               
X            '); split_line;
Vcopy_text('         CTRL/Z      - exit                                         
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('         <Space Bar> - Displays next screen full of text            
X            '); split_line;
Vcopy_text('                     - If there is no more text, it gets next messag
Xe           '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Xcopy_text("                            Press <1> to Exit Help"); 
XENDPROCEDURE;                              
X              
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE disable_bell;
VSET (BELL, ALL      ,OFF);                                                     
X                           
XSET (BELL, BROADCAST, ON);
XENDPROCEDURE;        
X
XPROCEDURE enable_bell;
XSET (BELL, ALL      ,ON );
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE my_undefined_key;
Xmessage ('');`009`009`009! this rings bell as long as broadcast is set = all
XENDPROCEDURE;
X                                      
XPROCEDURE one_map;`009`009! map text_buffer with USENET news to screen
XMAP(text_window, text_buffer);
Xupdate_banner;
XENDPROCEDURE;
X
XPROCEDURE two_map;`009`009! map subscribe to screen
X`009`009`009`009! allow arrows keys to select group
XMAP (text_window, subscribe);
XENDPROCEDURE;
X                                           
XPROCEDURE three_map;
XMAP (text_window, active);
XENDPROCEDURE; 
X
XPROCEDURE five_map;
XMAP (text_window, message_buffer);
XENDPROCEDURE;
X
XPROCEDURE six_map;
XMAP (text_window, ac_tmp);
XENDPROCEDURE; 
X
XPROCEDURE seven_map;
XMAP (text_window, sub_tmp);
XENDPROCEDURE; 
X
X
X
XPROCEDURE end_of_line
Xposition (search (LINE_END, FORWARD, EXACT));
XENDPROCEDURE;                    
X
X
XPROCEDURE begin_of_line;
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
XENDPROCEDURE;        
X
X
XPROCEDURE save_mesg`009`009`009! write current message to disk
XLOCAL save_name;
Xsave_name := READ_LINE ('Save current message to file: ');
Xif length(save_name) = 0 then return(0); endif;
XWRITE_FILE (text_buffer, save_name);
Xmessage('file written');`009! add: check if written sucessfully
XENDPROCEDURE;
X            
X                                         
XPROCEDURE select_column_one
XLOCAL j1;   `009`009`009`009! returns column one as a string
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xj1 := search (LINE_BEGIN & SCAN(' '),FORWARD);
XRETURN (SUBSTR(j1,1,999));
XENDPROCEDURE;
X                
X                   
XPROCEDURE select_column_two 
XLOCAL a, b, c, d;       ! returns column two as a string
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
X
Xa  := current_line + ' ';
Xb  := INDEX  (a, ' ');
Xa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (a, ' ');
Xd  := SUBSTR (a, 1, c - 1);
X                            
XRETURN(SUBSTR(d,1,999));
XENDPROCEDURE;                                  
X                 
X
XPROCEDURE select_column_three
XLOCAL a, b, c, d, e; `009`009`009`009`009! returns column three as a string
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));`009`009! LINE ->> STRING
Xa  := current_line + ' ';
X
Xb  := INDEX  (a, ' ');
Xa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (a, ' ');
Xa  := SUBSTR (a, c+1, 999);
X                         
Xd  := INDEX  (a, ' ');`009`009`009! extract column three
Xe  := SUBSTR (a, 1, d-1);
X
XRETURN (SUBSTR(e,1,999));
XENDPROCEDURE;          
X
X     
XPROCEDURE replace_column_two (thing)
XLOCAL  a, aa, aaa, line, x3, b, c, d, thing1;
X
Xthing1 := STR(thing);`009`009`009! precede w/ 0's
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));       `009! LINE ->> STRING
Xa  := current_line + ' ';
X
Xb  := INDEX  (a, ' ');
Xaa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (aa, ' ');
Xaaa:= SUBSTR (aa, c, 999);
X
Xline := SUBSTR(a,1,b) + thing1 + aaa;
Xedit (line, TRIM_TRAILING);
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xcopy_text(line); 
Xsplit_line;
Xerase_line;                            
Xmove_vertical (-1);
XENDPROCEDURE;                                  
X                                    
X                         
XPROCEDURE go_to_article
XLOCAL a1, numb , x;
X
Xa1 := READ_LINE ('Go to which article number: ');
Xif a1 = "" THEN return(0); ENDIF;
Xnumb := INT(a1);
Xif numb = 0 then return; endif;
X
Xx := mark(none);
Xposition(subscribe); 
Xreplace_column_two (numb); 
Xposition(x);
Xnext_news_message;
X
XENDPROCEDURE;
X
X
XPROCEDURE top_of_buf;
Xposition(beginning_of(current_buffer));
XENDPROCEDURE;
X           
X
XPROCEDURE bot_of_buf;
Xposition(end_of(current_buffer));
XENDPROCEDURE;
X            
X
Xprocedure author;
Xmessage("Written By Christopher Seline (11/Apr/88)");
Xmessage("SCS7317@oberlin.bitnet");
XENDPROCEDURE;
X
XPROCEDURE try;
Xmessage('try1');
X                       
XENDPROCEDURE;
X              
XPROCEDURE underline_line
XLOCAL r1,r2;
X! bug -- only underlines in one buffer at a time
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xr1 := MARK (none);
Xposition (search (LINE_END, FORWARD, EXACT));
Xr2 := MARK (none);
X                
Xunderline_x2 := CREATE_RANGE (r1,r2,UNDERLINE);
Xr1 := 0; 
Xr2 := 0;             
XENDPROCEDURE;                                   
X
XPROCEDURE underline_subject_line
XLOCAL 
X   r1,r2,j3 ;
X        
Xj3 := mark (none);
Xr1 := search ('subject',FORWARD,NO_EXACT);
XIF r1 = 0 THEN return(0); ENDIF; !No Subject
Xposition (r1);
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xr1 := MARK (none);
Xposition (search (LINE_END, FORWARD, EXACT));
Xr2 := MARK (none);
X
Xunderline_i1 := CREATE_RANGE (r1,r2,UNDERLINE);
Xr1 := 0; 
Xr2 := 0;             
X
Xposition (j3);
XENDPROCEDURE;
X
X
X
X
VPROCEDURE scroll_line_to(dest_line)`009`009`009`009! scrolls the screen so that
X the current line is at the line # specified by dest_line
VLOCAL old_position;`009`009`009`009`009`009! preserves the cursor position thro
Xugh the scroll
X    old_position := MARK(NONE);
X    SCROLL(CURRENT_WINDOW,
X           GET_INFO(CURRENT_WINDOW, "current_row")-dest_line);
X    POSITION(old_position);
XENDPROCEDURE;
X
X
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                     K E Y   B I N D I N G S
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X    
VSET(SELF_INSERT, "TPU$KEY_MAP_LIST", OFF);`009! make it so typing keys won't se
Xlf-insert
VSET(UNDEFINED_KEY, "TPU$KEY_MAP_LIST", "my_undefined_key");`009! and specify wh
Xat to do when an undefined key is pressed
XDEFINE_KEY("exit_news", CTRL_Z_KEY);`009`009! exit
XDEFINE_KEY("quit",KEY_NAME('q')); 
XDEFINE_KEY("author", KEY_NAME("A"));
XDEFINE_KEY("page_down", KP0);`009`009`009! page down
XDEFINE_KEY("page_up", PERIOD);`009`009`009! page up
XDEFINE_KEY("line_down", DOWN);`009`009`009! scroll down
XDEFINE_KEY("line_up", UP);`009`009`009! scroll up 
XDEFINE_KEY("go_to_article", KEY_NAME("#"));`009! goto article #
XDEFINE_KEY("go_to_group", KEY_NAME("G"));`009! Goto Group EXACT
XDEFINE_KEY("go_to_group_NOexact", KEY_NAME("g"));! Goto Group NOEXACT
XDEFINE_KEY("go_to_group_NOexact", PF1);`009`009! Goto Group NOEXACT
XDEFINE_KEY("next_group", KEY_NAME('N'));`009! next group
XDEFINE_KEY("next_group", COMMA        );`009! next group
XDEFINE_KEY("space_bar", KEY_NAME(" "));`009     `009! NEXT THING
XDEFINE_KEY("next_news_message", ENTER);
XDEFINE_KEY("next_news_message", KEY_NAME('n'));
XDEFINE_KEY("attach", KEY_NAME('P'));`009`009! PAUSE news
XDEFINE_KEY("attach", PF3          );
XDEFINE_KEY("catch_up",KEY_NAME('c'));  `009`009! mark group as read
XDEFINE_KEY("UN_catch_up",KEY_NAME('C'));`009`009! mark group as UNread
XDEFINE_KEY("keypad_help", PF2);
XDEFINE_KEY("news_help", KEY_NAME('?'));    
XDEFINE_KEY("news_help", KEY_NAME('h'));
XDEFINE_KEY ("one_map", KEY_NAME("1"));
XDEFINE_KEY ("two_map", KEY_NAME("2"));     
XDEFINE_KEY ("three_map", KEY_NAME("3"));   
XDEFINE_KEY ("five_map", KEY_NAME("5"));
XDEFINE_KEY ("six_map", KEY_NAME("6"));
XDEFINE_KEY ("seven_map", KEY_NAME("7"));
X
XDEFINE_KEY ("top_of_buf",KEY_NAME("<"));
XDEFINE_KEY ("bot_of_buf",KEY_NAME(">"));
XDEFINE_KEY ("save_mesg", KEY_NAME('s'));`009`009! save to disk
XDEFINE_KEY ("subscribe_proc", KEY_NAME('U'));`009`009! UNunsubscribe
XDEFINE_KEY ("unsubscribe", KEY_NAME('u'));
XDEFINE_KEY ("refresh",   CTRL_L_KEY);
XDEFINE_KEY ("refresh",   CTRL_R_KEY);
XDEFINE_KEY ("refresh",   CTRL_W_KEY);
X                               
X! for debugging
X
XDEFINE_KEY ("try"              , KEY_NAME("~"));
X                                         
X
X
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X
X!SAVE("SYS$LOGIN:news");
XSAVE("students:[scs7317.trans]news_inprog");
XQUIT;
X
$ GoSub Convert_File
$ Exit

SCS7317%OCVAXB@VB.CC.CMU.EDU (Christopher Seline) (05/25/88)

.lm 3
.rm 72
.sp1
.ap
.p 0,1,3
.enable bar

.c74;-----------------------------------
.c74;|              NEWS               |
.c74;|   USENET News reading utility   |
.c74;|          User's manual          |
.c74;-----------------------------------


.c74;version 3.00
.c74;(c) 1988 Christopher Seline

.sk 4
^&Conventions used in this document:\&

.begin bar
Sections that describe advanced concepts are denoted by 
vertical bars in the left margin.  This information is intended for
the more experienced user, and can be skipped at the first reading.
.end bar

.sk 4
.c74;***   ^&Introduction\&   ***


^&About USENET News\&

"News" is a utility that enables users on a network site not directly on
USENET (e.g., bitnet users) to read the news 
that is circulated around the world on USENET,
commonly known as netnews.  Netnews is a huge bulletin board of sorts:
a forum of open discussion and/or announcements on many
topics in which all of 
the thousands of readers are welcome to participate.  

Netnews is divided into well over 200 newsgroups, each of which
is devoted to a particular topic.  The
subject names are split first into general areas, then into more specific
topics.  The root classifications are:
.lit
		news -  about netnews   	sci  -  science
		comp -  computers		soc  -  social
		rec  -  recreation		misc -  miscellaneous
		talk -  discussions
.el
There are other initial names of groups that are specific to the
network site.  For example, 'att' denotes newsgroups 
specific to AT_&T, and can only be read by users 
using an AT_&T node.

Beyond these classifications, the newsgroup names get progressively
more specific.
Examples:  comp.sys.ibm.pc, rec.arts.startrek,
soc.college, and rec.auto.  Each newsgroup
name should be sufficiently descriptive of the topic discussed.

When you read netnews for the first time, the first newsgroup you
go into will be "news.announce.newusers".  READ EVERY ARTICLE IN IT.
It contains information and guidelines about netnews that every reader
is expected to know.


^&Getting started with NEWS\&

Before running news, it is necessary to define the variable
'news__farsite', like so:
.sk1
.c74;define news__farsite [local-value]

This is a code that tells NEWS how to contact the nearest USENET
site.  Since this will be a different value on each system, your
system manager will tell you what your local value is.  It is
easiest to put this definition in your login.com file, so you
don't have to remember it each time you read the news.

News is a VAX TPU (Text Processing Utility) program.  This means that
to run the program, you invoke the TPU editor with a special
command file.  This file should be stored in
a public directory.  Here is how the program is run
at Oberlin:
.sk1
.c74;edit/tpu/sec=softlib:[share]news
                  
Your system manager will be able to tell you where the program is on
your system.  Replace 'softlib:[share]news' above with the appropriate
directory and file name.

To make this procedure easier, you can define the above command as
something else in your login.com file, like so:
.sk1
.c74;$define news edit/tpu/sec=softlib:[share]news

Again, replace this filename with the one specific to your system.
After this is done, simply type 'news' to run the program.

.sk3
.c74;***   ^&Your First NEWS Session\&   ***

^&Establishing the link to netnews\&

When you run NEWS for the first time it takes a minute to
create a necessary information file in your directory.  NEWS will
tell you that it is creating a new subscription for you.

Every time you invoke NEWS it will take several moments to access netnews
at your USENET site.  It should blink 'Loading active' near the bottom
right corner of the screen until it establishes the link.  

If there
is an outright error in accessing the 
USENET node, you will know right away,
and will be prompted to hit 'q' to quit.  If this happens, 
either the link is temporarily down or you
are trying to access the USENET node incorrectly (due to an incorrect
news__farsite value).  If you are
sure you have the correct news__farsite value defined, try again later.

If it blinks 'Loading active' for more than a few minutes, either 
the network load is too high or the USENET node is 
having problems of its own.  Try again later.

^&Screen layout\&

The screen is split into two sections, separated by a bar of inverse
text.  The top (largest) part of the screen is the main display area;
this is where the news articles are displayed.  The area below the bar
is where NEWS program messages and error messages are displayed.

The inverse-video bar acts as a status
line, and also reminds you of two important commands:  <CTRL>-Z to exit,
and '?' for help.  The status information includes the newsgroup you
are currently reading, the current article number, and the number of
remaining articles in that newsgroup.

The article number is probably already quite high.  This is because
the numbers have not been reset since the newsgroup began.  You cannot
read the articles before the one that NEWS starts you at;  they have
been discarded due to old age.

^&On-line help\&

On-line command information is displayed with '?' or 'h'.  Hit '1'
to return to reading the news.  On VT-100 type terminals, 
keypad information is also
available with the PF2 key.  '1' exits this help screen as well.

^&Newsgroup subscriptions\&

When you run NEWS for the first time, you are automatically 'subscribed'
to all the newsgroups, meaning you have the opportunity to read articles
in every group.  Since you will probably not be interested in
all the topics, you will want to un-subscribe to most groups.
After you un-subscribe to a newsgroup, you will not see any of its
articles again unless you re-subscribe to it.  See
the section titled 'Selecting newsgroups' for a discussion of how to
choose your subscriptions.

Remember to read everything in 'news.announce.newusers' before moving
on to the rest of netnews.  
.page
.c74;***   ^&Reading Articles\&   ***

The up and down arrows scroll the screen in
both directions.  However, there are easier ways to page through
the articles.

The space bar scrolls down to next screen.  If you are at the end of 
an article, this will also move to the next article.  If you are
at the end of the last article in a newsgroup, it will move to the
next available newsgroup and wait for further instructions before
reading any articles.

Note that when you advance to the next article there is a delay
as the program blinks 'Retrieving' in the message window.  This is
because it takes time to grab the file from the USENET node.  

Other commands:
.lm 9
.p -6,1,3

>#####Go to the end of the current article.  

<#####Go to the top of the current article.

n#####Advances to next article, even if you have not seen all of the
current article.

_######Go to a particular article number, which NEWS prompts you for.
If you skip forward, NEWS will count the skipped articles as read when
you exit.  This means that when you re-enter NEWS, your current position 
in that newsgroup will be 
beyond those missed articles.

s#####Save the current article to a file.  NEWS will prompt you for a 
filename and inform you when the process is complete.

c#####Catch up in the newsgroup.  This marks all the active articles
as read, so you can start fresh with all future articles.  This is a
good way to rationalize not sifting through all the remaining articles.

C#####Un-catch up.  This returns your current article number to the
first active (and unread) article in the newsgroup.
.sk1

The following commands utilize the keypad on VT-100 type terminals:
.lm 9
.p -6,1,3

<0>###Page down.  This differs from the space bar in that it will not
advance any further when it reaches the end of the current article.

<_.>###Page up.  As with '0', this will not move beyond the
current article.
.lm 14
.p -11,1,3

<ENTER>###Advance to the next message.  Identical to the 'n' command. 

.page
.c74;***   ^&Selecting Newsgroups\&   ***
.lm 3
.p 0,1,3

^&Moving between newsgroups\&

The following commands allow you to choose your current newsgroup:
.lm 9
.p -6,1,3

N#####Go to the next subscribed newsgroup.  
Note the difference between 'N' and 'n'.

g#####Go to the next non-specific newsgroup.  NEWS will prompt you for
a newsgroup name, and will advance to the next newsgroup that contains
the requested string.  For example, enter 'ibm' and it will move to the
next newsgroup that has 'ibm' in its name.  If it does not find the
specified keyword in any newsgroups, it will remain in the current group.  

G#####Go to the next specific newsgroup.  This time, when NEWS prompts
you for a newsgroup name, you must enter the full name of the newsgroup,
such as 'comp.sys.ibm.pc'.  If it does not find the specified newsgroup,
it will remain in the current group.

Also, on the VT-100 keypad:

<,>###Go to the next subscribed newsgroup.  Identical to the 'N' command.

PF1###Go to the next non-specific newsgroup.  Identical to the 'g' command.

.lm 3
.p 0,1,3
With all commands that change the current newsgroup,
NEWS will wait for you to decide if you want to read articles in
that newsgroup.  Hit the space bar or 'n' to read the first article.
.sk1

^&Subscribing to specific newsgroups\&

The following commands allow you to choose which newsgroups to read
and which ones to skip next time you read netnews.
.lm 9
.p -6,1,3

u#####Unsubscribe to the current newsgroup.  If you are reading an article,
NEWS will advance to the next available newsgroup and wait for instructions.

U#####Un-unsubscribe to the current newsgroup.  Returns the current article
number to the first unread article.

2#####(on the regular keyboard)  Display the list of newsgroups.  This
will replace the article area on the screen with a list of all newsgroups
available, as well as your current article number in that newsgroup.  
You can scroll around with the same commands as you use to
read messages - the arrow keys, the space bar, '<', '>', and the keypad.  
'1' returns you to the current article.
.lm 3
.p 0,1,3

The 'u' and 'U' commands are made considerably easier through the '2'
command.  With the newsgroup list on the screen, 'u' and 'U' affect the
newsgroup marked by the cursor at the top of the screen.  Note that
when you unsubscribe to an article, the current article number changes
to 99999, and un-unsubscribing changes it back to the first unread article.

.begin bar
What the '2' command is actually doing is making the newsgroup list buffer
the active buffer in TPU.  The '3' command will name the newsgroup file
as the active buffer.  The '1' command
returns the article buffer to be the active buffer (note that this is why
'1' exits help screens and returns to netnews).  

The newsgroup file contains the list of newsgroups
in your home directory.  One can edit this file outside of NEWS, putting
the important newsgroups at the top of the list.  Deleting newsgroups
from this list, even if you think you will never ever want to read
them, is not recommended.  The extra
information the file contains is the number of 
the latest posted article in the
newsgroup, and the subscription status of that newsgroup.
.end bar

.sk3
.c74;***   ^&Miscellaneous commands\&   ***

To exit news, type Control-Z.  This causes NEWS to remember which
articles you read, so that the next time you read news you are at the
same point in all your subscribed newsgroups.  'q' also exits the
program, but does not remember which messages you read.

To refresh the screen, type Control-W or Control-R.

.begin bar
The 'P' command pauses NEWS, returning to the operating system
temporarily.  This allows you to read mail, etc. and still
remain in the NEWS program.  On VT-100 terminals, the PF3 key
also executes this command.

To use this feature, NEWS must be invoked with SPAWN#NEWS in DCL.  To
re-enter NEWS, use the ATTACH#[process-name] command, where
[process-name] was the name given by SPAWN to your command level
process when you invoked NEWS.

'5' assigns the message buffer (normally seen at the bottom of the
screen) to be the current buffer.  See 'Selecting Newsgroups:
Subscribing to specific newsgroups' for a discussion of swapping
buffers.
.end bar

.page
.c74;***   ^&Command Summary\&   ***
.lit


	    ?,h		help
	<space bar>	page down, even through articles
	     n		next article
	     N		next newsgroup
	     #		go to article number
	     c		catch-up to latest article
	     C		un-catch-up (return to last unread article)
	     g		go to non-specific newsgroup
	     G		go to specific newsgroup
	     s		save article to file
	     u		unsubscribe to current newsgroup
	     U		un-unsubscribe to newsgroup
	     <		top of article
	     >		bottom of article
	     ^Z		exit (remember read articles)
	     q		quit (don't remember read articles)
	   ^R,^W	redraw screen
	     1		make text buffer active
	     2		make newsgroup buffer active
|	     3		make complete newsgroup file active
|	     5		make message buffer active
|	     p		pause

.el
.c74;VT-100 Keypad commands:
.lit

	    PF2		keypad help
	     0		page down
	     . 		page up
	  <enter>	next article
	     ,		next newsgroup
	    PF1		go to non-specific newsgroup
|	    PF3		pause
.el

.page
.c74;***   Program Messages   ***

"Can't find the group you referred to: [group-name]"

You asked to go to a newsgroup (with either g or G) and NEWS could
not find a group by that name.  You are returned to the newsgroup
and article you are currently reading.

"Nothing left to read in group [group-name] -- Moving to next Group"

This is what happens when you finish the last article in a newsgroup
and hit the space bar or 'n'.  
Note that although it moves to the next group,
it does not start reading the articles; hit 'n' or the space bar again
to continue.

"Null News Body -- Hope that's OK"

NEWS tried to read an article that turned out to be empty.  This is
most likely due to a numbering error in netnews, so you're not
missing anything.

SCS7317%OCVAXB%VB.CC.CMU.EDU%KL.SRI.COM%lbl%sfsu1.hepnet@LBL.GOV (05/28/88)

Received: from KL.SRI.COM by LBL.Gov with INTERNET ;
          Thu, 26 May 88 16:20:30 PDT
Received: from VB.CC.CMU.EDU by KL.SRI.COM with TCP; Tue 24 May 88 16:00:11-PDT
Date: Tue, 24 May 88 19:00 EDT
From: Christopher Seline <SCS7317%OCVAXB@VB.CC.CMU.EDU>
Subject: NEWS(DECNET/VMS)  USENET on VMS  reader user agent and DECNET mapper
To: info-vax@KL.SRI.COM
X-VMS-To: CMCCVB::IN%"info-vax@kl.sri.com"
 
$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by SCS7317
$! on Tuesday 24-MAY-1988 18:55:41.32
$!
$! It contains the following 3 files:
$! MAP.BAS MAP.PAS NEWS.TPU
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o);
Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;
Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1);
ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop
x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1);
If Current_Character='`' then Move_Horizontal(1);else
Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="MAP.BAS"
$ Check_Sum_is=1149044145
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X10 rem MAP -  hack tolook for news on a DECNET
X20 rem it isn't pretty (and it doesn't use DAP (which it should)) but
X30 rem it works.  Which is the number one important thing in the real world
X40 rem and all you programmers out there had better not forget it.
X100 print "Map -- Check your entire DECNET for sites running USENET"
X105 print
X130 print "It checks invisible nodes...and dead nodes....infact"
X140 print "It checks every possible node........"
X150 print
X200 for a = 1 to 74000
X202 if a = 68 then goto 400
X205 e = 0
X207 close #1
X210 when error in
X220 open str$(a)+'::"/usr/lib/news/active"' as file #1, access read
X230 use
X240 e = 1
X250 print a ,ert$(err)
X260 end when
X300 if e = 0 then close #1
X305 if e = 1 then goto 400
X310 print using "######",a;
X320 print " active"
X330 ac$=ac$ + " " + str$(a)
X400 next a
X510 print
V520 if ac$="" then print "No news easily found.  A more sophisticated utility i
Xs needed."
X530 if ac$<>"" then print "news at "; ac$
X540 print
X550 print "done."
$ GoSub Convert_File
$ File_is="MAP.PAS"
$ Check_Sum_is=1867919516
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xprogram map (input,output);
X
X(* MAP.PAS`009This is a unsupported part of the NEWS(DECNET/VMS) suite.
X
X   MAP.PAS`009Looks around your DECNET from any node suitably configured
X`009 `009for NEWS(DECNET/VMS).  You should pick the one closest to
X`009`009you, and DEFINE it as NEWS_FARSITE.
X
X   MAP.PAS`009works in the most crude way possible.  A more sophisticated
X`009`009technique (using DAP) would be nice, but...then again, 
X`009`009this works.
X*)
X
XVAR node, stat : integer;
X    node_spec : varying [200] of char :='';
X    infil : text;
X
XBEGIN
X   WRITELN('MAP X01  --  Map Your DECNET');
X   WRITELN('             Looking for sites suitable to be NEWS_FARSITE');
X   WRITELN;
X   for node := 1  TO 99000 DO
X`009BEGIN
X`009   node_spec := dec(node,5) + '::"/usr/lib/news/active"';
X`009   write(dec(node,5) + '::  ');
X`009   OPEN(`009file_variable `009:= infil,
X`009`009`009file_name`009:= node_spec,
X`009`009`009history`009`009:= READONLY,
X`009`009`009sharing`009`009:= READONLY,
X`009`009    `009error`009`009:= CONTINUE);
X`009   stat := status(infil);
X`009   IF (stat = 0)
X`009`009THEN writeln('SUCCESS!!!  This could be used as news_farsite')
X`009`009ELSE 
X`009`009`009begin
X`009`009`009write   ('Not this node. STATUS :=');
X`009`009`009writeln (stat);
X`009`009`009end;
X`009   CLOSE(infil, error`009`009:= CONTINUE);
X`009
X
X`009END;
X                    
X
XEND.
X                           
$ GoSub Convert_File
$ File_is="NEWS.TPU"
$ Check_Sum_is=1728655159
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X! NEWS-news.tpu - a program to let people read news in comfort (scrolling
X! backwards, automatic pause, etc) 
X!
X!`009news.tpu Copyright 1988 (c) Christopher Seline
X!`009ALL RIGHTS RESERVED
X!
X!`009TO USE THIS PRODUCT YOU MUST OBTAIN A LICENSE
X!
X!`009USE OF THIS PRODUCT MORE THAN FIVE (5) TIMES
X!`009WITHOUT A LICENSE IS A CRIME.  TO OBTAIN A LICENSE
X!`009SEND THE LICENSING FEE TO:
X!`009`009Christopher Seline
X!`009`009127 Green Bay Rd.
X!`009`009Winnetka, IL  60093
X!
X!`009LICENSING FEE:
X!`009`009Cluster license $250`009(per cluster)
X!`009`009Machine license $100`009(per machine)
X!`009`009Personal license$020`009(per user)
X!
X!
X 
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                     installing this program
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!
X! If you have lost the detailed instructions:
X! rename this file to SYS$LOGIN:NEWS.TPU
X! issue the DCL command  EDIT/TPU/NOSEC/COM=SYS$LOGIN:NEWS.TPU
X!`009Now, the following command will invoke news
X!`009`009$ edit/tpu/sec=sys$login:news
X!`009Don't forget to define NEWS_FARSITE to some decnet node.
X!`009`009use MAP.PAS or MAP.BAS to figureout what to name it.
X!
X
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                    INITIALIZATION PROCEDURES
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X
XPROCEDURE tpu$init_procedure;
X! TPU calls this procedure automatically when it starts up.
X! After it exits, TPU will wait for bound keys and do their routines.
X    init_define_constants;
X    init_first; 
X    init_determine_mode;
X    init_PopUp_intro_text;
X    init_subscribe;                 
X    init_moveto_first_group_with_news;
XENDPROCEDURE;
X
X!----------
XPROCEDURE init_define_constants;
X
V    message_window_length := 3;  `009`009`009`009! size of the message window, 
Xin lines
V    status_text := "(X03.50) ^Z to exit    ? for help    ";`009! text to be dis
Xplayed on the window's status line
X    spool_dir := "news_spool:";`009`009`009`009! spool area if enabled
X    page_scroll_amount := 19;
X
V    $remote := 1; $sync := 2; $local := 3; $unknown := -1;  $mode := $unknown;`
X009`009`009! GLOBAL MODE
V!`009$mode indicates what mode NEWS operates in.  That is, where it looks for f
Xiles 
X!`009`009$remote`009`009--  All files are on NEWS_FARSITE
V!`009`009$sync`009`009--  active. is on NEWS_FARSITE, but some news articles ar
Xe kept in NEWS_SPOOL,
X!`009`009`009`009    so check there first
X!`009`009$local`009`009--  All files are in NEWS_SPOOL (including active).
V!`009`009`009`009    In $local mode, NEWS does not use DECNET at all.  (unless 
Xyou've defined
X!`009`009`009`009    NEWS_SPOOL to be on a DECNET NODE.
X
V    no := 0; yes := 1; help_visited := no; keypad_help_visited := no;`009`009! 
XGLOBAL HELP BUFFER STATUS
V                                                                               
X         ! change these to $ form
XENDPROCEDURE;
X
X!---------                
XPROCEDURE init_first
XLOCAL main_window_length;
Xon_error`009! kill error messages
Xendon_error;
X                              
V    main_window_length := GET_INFO(SCREEN, "visible_length") - message_window_l
Xength;
X    SET(PROMPT_AREA, main_window_length+1, 1, NONE);    
X                          
V    text_buffer := CREATE_BUFFER("Text");`009`009! create a buffer to hold the 
Xtext
X    SET(EOB_TEXT, text_buffer, "[END OF NEWS ITEM]");
X    SET(NO_WRITE, text_buffer);
X 
V    text_window := CREATE_WINDOW(1, main_window_length, ON);`009! create the ma
Xin text window
X    MAP(text_window, text_buffer);
X
V    message_buffer := CREATE_BUFFER("Message Buffer");`009! Create a message bu
Xffer for TPU messages,
V    SET(NO_WRITE, message_buffer); `009`009`009! for debugging, and map it into
X a window
X    SET(SYSTEM, message_buffer);
X    SET(EOB_TEXT, message_buffer, "");
V    message_window := CREATE_WINDOW(25-message_window_length, message_window_le
Xngth, OFF);
X    MAP(message_window, message_buffer);
X
X
XSET(FACILITY_NAME, "NEWS");`009`009`009`009! some initializtion   
XSET(MESSAGE_FLAGS, 15);`009`009`009`009`009! all message info
XSET(SUCCESS, OFF);
XSET(INFORMATIONAL, OFF);
X
Vjournal_open('nl:');`009`009`009`009`009! hack to prevent W-TPU$NOJOURNAL messa
Xge
X
Xenable_bell;
X
XENDPROCEDURE;
X
X
X!----------         
XPROCEDURE    init_determine_mode
Xlocal junk, junk1;
Xon_error 
Vjunk1 := 1;`009`009`009`009`009! indicate error, we expect an error when checki
Xng for local spooling
Xendon_error;
X
Xunmap(message_window);`009`009`009`009! stiffle RMS error messages
X
X! this procedure also creates active                                           
Xactive := CREATE_BUFFER ('active');`009`009! buffer holds /usr/lib/news/active
XPOSITION (active);
XSET (NO_WRITE, active);
XSET (SYSTEM, active);       
XSET (TIMER, ON, "Loading active");
X
Vmessage("");message("");message("");message("");! why can we intercept them w/ 
Xon ERR!!!!
X
XREAD_FILE(spool_dir + 'active.');
XIF beginning_of(active) = end_of(active) THEN
X   READ_FILE('news_farsite::"/usr/lib/news/active"');
X   $mode := $remote
X   ELSE
X   $mode := $local;
XENDIF;
X
XSET (TIMER, OFF);
X
XIF end_of(active) = beginning_of(active) THEN
X   message("I could not load active.");
X   message("USE q TO ABORT");
X   message("USE q TO ABORT");
X   message("USE q TO ABORT");
X   five_map;
X   abort;
XENDIF;
X
X
XIF $mode = $remote THEN
X! determine if spooling exists.....
Xjunk := create_buffer("junk");
Xposition(junk);
Xjunk1 := 0;
XREAD_FILE (spool_dir + 'news-spooling-exists.');
VIF junk1 <> 1 then $mode := $sync; ENDIF;`009! if the file was sucessfully open
Xed then we have local spooling of remote files
X
XENDIF;
X                                     
XIF $mode = $remote THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (remote)") ELSE
XIF $mode = $local  THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (local)")  ELSE
XIF $mode = $sync   THEN`009MESSAGE("NEWS(DECNET/VMS) V00.90 (sync)")   ELSE
X`009`009`009MESSAGE("NEWS(DECNET/VMS) V00.90 (BUG)");
XENDIF;ENDIF;ENDIF;`009! why can't the CASE statement deal with variables!
X
Xmap(message_window,message_buffer);`009`009! UNstiffle messages
X
XENDPROCEDURE;
X
X!----------
XPROCEDURE init_PopUp_intro_text;
XPOSITION (BEGINNING_OF(text_buffer));
X
X! THIS IS WHERE INTRODUCTORY TEXT GOES
X
V copy_text("                news.tpu Copyright (c) 1988 Christopher Seline"); s
Xplit_line;
X copy_text("                              ALL RIGHTS RESERVED "); split_line;
X copy_text(" "); split_line;
V!copy_text("    USE OF THIS PRODUCT MORE THAN FIVE (5) TIMES WITHOUT A LICENSE 
XIS A"); split_line;
V!copy_text("    CRIME.  TO OBTAIN A LICENSE SEND THE LICENSING FEE TO: "); spli
Xt_line;
X!copy_text("    `009Christopher Seline "); split_line;
X!copy_text("`009127 Green Bay Rd."); split_line;
X!copy_text("`009Winnetka, IL  60093 "); split_line;
X!copy_text(" "); split_line;
X!copy_text("    LICENSING FEE:"); split_line;
X!copy_text("         Cluster license $250`009(per cluster)"); split_line;
X!copy_text("         Machine license $100`009(per machine)"); split_line;
X!copy_text("         Personal license$020`009(per user)"); split_line;
X copy_text(" "); split_line;
X copy_text(" "); split_line;
X 
V copy_text("                  Press the SPACE BAR for next USENET message"); sp
Xlit_line;
X!
XENDPROCEDURE; 
X
X
X!----------
XPROCEDURE init_subscribe
X
Xsubscribe := CREATE_BUFFER ('subscribe','sys$login:News_Subscribe.dat');
XSET (NO_WRITE, subscribe);
XSET (SYSTEM, subscribe);
XPOSITION (subscribe);
XIF (BEGINNING_OF (subscribe) = END_OF (subscribe)) ! null or file not found
X   THEN                                    
X   message ("Can't find your news subscription -- subscribing for you.");
X   message ("This takes several minutes -- so sit back and relax...");
X   subscribe_create;
XENDIF;
Xupdate_banner;
XENDPROCEDURE;
X                                                                         
X
X           
V!------------------------------------------------------------------------------
X-
XPROCEDURE subscribe_create
XLOCAL a,b;
XPOSITION (subscribe);
VCOPY_TEXT (active);`009`009`009`009`009! copy active buffer into subscribe buff
Xer
X
XIF (BEGINNING_OF (subscribe) = END_OF (subscribe)) ! null or file not found
X   THEN                                    
X   message ("!!BUG -- reached subscribe_create with NULL active buffer");
X   abort;
XENDIF;            
X
X
X! now we need to massage the data   
VMAP (text_window, subscribe);`009`009`009`009! let them watch us massage the da
Xta
VPOSITION (BEGINNING_OF (subscribe));`009`009`009! leave only column one and two
X, delete column three and four
Xloop
X    exitif mark(none) = END_OF(subscribe);`009`009! exit loop at end of buffer
X
X    a := select_column_two;`009`009`009`009! set last message read column
V    b := INT(a) - 20;`009`009   `009`009`009! 20 is a magic number for how many
X messages to mark as unread
X    IF b < 1 THEN b := 1; ENDIF;
X    replace_column_two (b);
X
X    position (search(' ',FORWARD));`009`009`009! delete last two columns
X    move_horizontal (+1);
X    position (search(' ',FORWARD));
X    split_line;
X    erase_line;
Xupdate(current_window);
Xendloop;
X                   
V!move_group_to_top ("comp.os.vms");                      ! these groups will be
X read first
X!move_group_to_top ("rec.arts.comics");
X!move_group_to_top ("rec.humor");
X!move_group_to_top ("rec.arts.drwho");
X!move_group_to_top ("rec.arts.startrek");
Xmove_group_to_top ("news.announce.newusers");
X
VPOSITION (BEGINNING_OF (subscribe)); `009`009`009`009! unsubscribe control grou
Xp
Xposition(SEARCH (LINE_BEGIN & 'control', FORWARD, NO_EXACT));
Xreplace_column_two (99999);`009! 99999 magic number for unsubscribed
X
X
XPOSITION (BEGINNING_OF (subscribe));
Xmap(text_window,text_buffer);
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE move_group_to_top (group_name)
XLOCAL group_name, j1, j2;
X! move a group to the top of subscribe buffer
V! note, unlike most routines, this one does not restore original position in bu
Xffers
X
XPOSITION (BEGINNING_OF (subscribe));
Xj1 := SEARCH (LINE_BEGIN & group_name & ' ', FORWARD, NO_EXACT);
XIF j1 = 0 THEN return; ENDIF;`009`009`009! return if it doesn't exist
Xposition(j1);
X
Xj2 := current_line;
Xerase_line;
XPOSITION (BEGINNING_OF (subscribe));
Xcopy_text(j2);
Xsplit_line;
XENDPROCEDURE;
X      
X
X
V!------------------------------------------------------------------------------
X-
VPROCEDURE     init_moveto_first_group_with_news;`009`009! move to first group w
Xith something in it to read 
X
Xmove_to_group_with_pending_news;
X
XENDPROCEDURE;
X 
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
V!                                    PROCEDURES -- MANY BOUND TO KEYS -- MANY H
XELPER FUNCTIONS
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X++++++++++++++++++++++++++++++++++++++++++++++++++++
X
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE page_down;
X! scroll down almost one screensworth
X    SCROLL(text_window, page_scroll_amount);
XENDPROCEDURE;
X
X                                  
X             
V!------------------------------------------------------------------------------
X-             
XPROCEDURE page_up;
X! scroll up almost one screensworth                                            
X    SCROLL(text_window, -page_scroll_amount);
XENDPROCEDURE;
X
X
X             
V!------------------------------------------------------------------------------
X-                                       
XPROCEDURE line_down 
Xlocal a;
X! scroll down one line
X    a:=mark(none);
X    SCROLL(text_window, 1);
X    If a = mark(none) THEN`009`009`009`009! we haven't moved
X      move_vertical(+1);
X    ENDIF;
XENDPROCEDURE;
X
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE line_up
Xlocal a;
X! scroll up one line
X    a:=mark(none);
X    SCROLL(text_window, -1);
X    If (a = mark(none)) THEN`009`009`009`009! we haven't moved
X      move_vertical(-1);
X    ENDIF;
XENDPROCEDURE;
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE go_to_group;
Xmessage("Go to exact group is no longer supported");
XENDPROCEDURE;   
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE go_to_group_NOexact
XLOCAL group_name, j1,j2,j3;                                                    
X! go to a new group....no need to find exact name
X
Xon_error`009! kill error messages
X!    if error = tpu$_strnotfound then
X!`009message ("couldn't find it");
X!    endif;
Xendon_error;
X      
X
Xj1 := CURRENT_BUFFER;
XPOSITION (subscribe);            
Xj3 := MARK (none);`009! where we were if search fails
X              
Xgroup_name := READ_LINE ('GO TO WHICH GROUP (NOexact name): ');
X
Xmove_vertical(+1);`009`009`009! so we don't find current line
Xj2 := SEARCH ( group_name , FORWARD, NO_EXACT);
X
XIF j2 = 0 THEN       `009`009`009`009! try from beginning of buffer
X`009POSITION (BEGINNING_OF (subscribe));
X`009j2 := SEARCH ( group_name , FORWARD, NO_EXACT);
XENDIF;                                          
X
XIF j2 = 0 THEN`009`009`009`009`009! couldn't find it anywhere
X   MESSAGE ("Can't find the group you refered to: "+ group_name);
X   POSITION (j3);`009! move to old place in subscribe
X   POSITION (j1);`009! move to old buffer
X   RETURN(0);             
XENDIF;                                          
X
XPOSITION (j2);
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
X
Vif mark(none) = j3 then message ("This is the only group that matches: "+ group
X_name); 
X   endif;
X
Xposition(text_buffer);      
Xzero_text_buffer;
Xupdate_banner;`009`009`009`009`009! indicate new group and position
X      `009
XENDPROCEDURE;   
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE update_banner`009`009! update status_line to current grp & position
VLOCAL s1,s2, subs_current, a2, active_top, active_bot, diff,arg;               
X                
X
Vposition (subscribe);   `009`009`009`009! get subscribed group & next mesg. num
Xber
Xs1 := select_column_one;
Xs2 := select_column_two;
Xsubs_current := INT(s2);                                                   
X
Vposition (BEGINNING_OF(active));`009`009`009!move to same group in active as in
X subscribe                       
Xarg := SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT);
Vif arg = 0 THEN   `009`009`009`009`009! subscribe has groups that no longer exi
Xst in active;
X   sync_subscribe;
X   return(0); 
XENDIF;
Xposition(arg);
Xa2 := select_column_two;        
Xactive_top    := int (a2);  
Xactive_bot    := int (select_column_three);
XIF active_bot > subs_current THEN subs_current := active_bot; ENDIF;
Xdiff := active_top - subs_current;
XIF diff < 0 THEN diff := 0; ENDIF;                
X
XIF subs_current = 99999 then
VSET(STATUS_LINE, text_window, REVERSE, status_text + '    ' + s1 + ': Unsubscri
Xbed');
X`009ELSE
VSET(STATUS_LINE, text_window, REVERSE, status_text + '    ' + s1 + ':' + STR(su
Xbs_current)+'     '+str(diff)+' left');
X      `009ENDIF;
Xupdate(current_window);
XENDPROCEDURE;
X                                                                               
X
V`012                                                                           
X    
V!------------------------------------------------------------------------------
X-
Xprocedure sync_subscribe`009`009`009`009! called if subscribe is out of whack
V;!!!!!LOCAL ac_tmp, sub_tmp, a, b;`009       `009`009! this happens if a new gr
Xoup is added or deleted from active
X
Xdisable_bell;
Xmessage("Since I last checked groups have been added or deleted from active");
Xmessage("So, I'm going to sync subscribe to active.");
Xmessage ("This takes several minutes -- so sit back and relax...");
X
X! first makes copies of subscribe and active
X
X
Xac_tmp := CREATE_BUFFER("ac_tmp");  
Xset(No_write, ac_tmp);
Xposition(ac_tmp);  copy_text(active);
X
Xsub_tmp := CREATE_BUFFER("sub_tmp");  set(No_write, sub_tmp);
Xposition(sub_tmp); copy_text(subscribe);
X
Xmap(text_window,sub_tmp);
Xposition(beginning_of(sub_tmp));
Vloop`009`009`009! check each group in subscribe, if it isn't in active then del
Xete it from subscribe
X    exitif mark(none) = END_OF(sub_tmp);
X    a1:= mark(none);
X    a := select_column_one;
X    position(beginning_of(ac_tmp));
X    b := search(LINE_BEGIN & a & ' ', FORWARD, NO_EXACT);
X    if b = 0 then
X       position(a1);
X       erase_line;
X       message ("Deleted "+a);
X     ELSE
X       position(b); 
X       erase_line;`009! erase each line -- any left will be not in subscribe
X       position(a1);
X       move_vertical (+1);
X    ENDIF;
X    update(text_window);
Xendloop;
X      
Xif beginning_of(ac_tmp) <> end_of(ac_tmp) THEN
X   map(text_Window,ac_tmp);
V   POSITION (BEGINNING_OF (ac_tmp));`009`009`009! leave only column one and two
X, delete column three and four
X   loop
X       exitif mark(none) = END_OF(ac_tmp);`009`009! exit loop at end of buffer
X       message('Added ' + select_column_one);
X       a := select_column_two;`009`009`009`009! set last message read column
V       b := INT(a) - 20;`009`009   `009`009! 20 is a magic number for how many 
Xmessages to mark as unread
X       IF b < 1 THEN b := 1; ENDIF;
X       replace_column_two (b);
X
X       position (search(' ',FORWARD));`009`009`009! delete last two columns
X       move_horizontal (+1);
X       position (search(' ',FORWARD));
X       split_line;
X       erase_line;
X   update(text_window);
X   endloop;
X   position(sub_tmp);
X   copy_text(ac_tmp);
X   update(text_window);
XENDIF;
X
Xerase(subscribe);
Xposition(subscribe);
Xcopy_text(sub_tmp);
X    
Xposition(beginning_of(subscribe));
Xposition(beginning_of(active));
Xposition(beginning_of(text_buffer));
Xmap(text_window,text_buffer);      
Xenable_bell;
XENDPROCEDURE;
X
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE catch_up`009`009! mark current group as read
XLOCAL s1, a2, active_top,x;
Xx := mark(none);
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
X
Xposition (BEGINNING_OF(active));! move to same group in active
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa2 := select_column_two;
Xactive_top    := int (a2);
X
Xposition(subscribe);
Xreplace_column_two (active_top);`009! update subscribe mesg#
X
Xupdate_banner;
Xzero_text_buffer;
Xposition(x);
XENDPROCEDURE;
X           
X                                                       
V!------------------------------------------------------------------------------
X-
XPROCEDURE UN_catch_up`009`009! mark this group as UNread
XLOCAL s1, a3, active_bottom, old_pos;
X
Xold_pos := mark(none);
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
X
Xposition (BEGINNING_OF(active));! move to same group in active
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa3 := select_column_three;
Xactive_bottom := int (a3);
X                          
Xposition(subscribe);
Xreplace_column_two (active_bottom);`009! update subscribe mesg#
X
Xposition(old_pos);
Xzero_text_buffer; 
Xupdate_banner;
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE Unsubscribe
XLOCAL x;
Xx := mark(none);
Xposition(subscribe); 
Xreplace_column_two (99999);`009! 99999 magic number for unsubscribed
Xposition(x);  `009   `009`009! This will be a bug when a group his 99999
Xzero_text_buffer;
Xupdate_banner;
XENDPROCEDURE
X
X
V!------------------------------------------------------------------------------
X-
VPROCEDURE Subscribe_proc`009`009`009`009! resubscribe to unsubscribed news grou
Xp
XLOCAL x;
Xx := mark(none);
Xposition(subscribe); 
XUn_catch_up;
Xposition(x);
Xupdate_banner;
XENDPROCEDURE
X
X
X
X                                                       
X`012
V!------------------------------------------------------------------------------
X-
XPROCEDURE next_news_message     
VLOCAL i3,j1,j2,j3,s1,s2,s1a, s4,spool,news_file,subs_current,i,a1,a2,a3,active_
Xbottom,active_top,spool_file;
X! read in next message
X
X
Xupdate_banner;`009`009`009! Indicate which group and message this is
Xdisable_bell;`009`009`009! no beeping
X
Xposition (subscribe);   `009! get subscribed group & next mesg. #
Xs1 := select_column_one;
Xs1a:= s1;
Xs2 := select_column_two;
Xsubs_current := INT(s2);
X
XIF subs_current = 99999 THEN `009! if unsubscribed then recurse till OK
X`009next_group;
X      `009next_news_message;
X`009return(0);
XENDIF;
X                
X!move to same group in active as in subscribe                       
Xposition (BEGINNING_OF(active));
Xi := SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT);
Xposition(i);
X           
Xa1 := select_column_one;
Xa2 := select_column_two;
Xa3 := select_column_three;
Xactive_bottom := int (a3);      
Xactive_top    := int (a2);                                          
X                
X! create file name
XIF subs_current < active_bottom THEN subs_current := active_bottom; ENDIF;
XIF subs_current > active_top    THEN`009! Nothing Left to READ?
V`009message('Nothing left to read in group ' + s1 + ' -- Moving to next Group')
X;
X`009next_group; RETURN; ENDIF;
X                                     
Xspool := s1;
XTRANSLATE(spool,'_', '.');`009`009! convert to VMS  Name
XTRANSLATE(s1,   '/', '.');         `009! convert to Unix Name
X
Vnews_file := 'news_farsite::"/usr/spool/news/' + s1 + '/' + STR(subs_current) +
X '"' ;
X     
Xspool_file := spool_dir + spool + '_' + STR(subs_current)+ '.';
X                                  
Xsubs_current := subs_current + 1;
Xposition(subscribe); 
Xreplace_column_two (subs_current);`009! update subscribe mesg#
X
X!read in file                                          
XPOSITION (text_buffer);
XERASE (text_buffer);
XSET (TIMER, ON, 'Retrieving.');
X
XIf ($mode = $local)  or ($mode = $sync) THEN READ_FILE ( spool_file ); ENDIF;
X  
XIf ($mode = $remote) `009`009`009THEN READ_FILE ( news_file );  ENDIF;
X
XIf ($mode = $sync) and (BEGINNING_OF (text_buffer)= END_OF (text_buffer))
X   THEN READ_FILE ( news_file ); ENDIF;                      
X
XPOSITION (BEGINNING_OF (text_buffer));
VIF (BEGINNING_OF (text_buffer)= END_OF (text_buffer))`009! null or file not fou
Xnd
X   THEN 
X     message ("Null News Body -- Hope that's OK");
X     message("");
X   ELSE
V     underline_subject_line;          `009`009`009! underline subject if got ne
Xws
XENDIF;                      
X
X
XSET (TIMER, OFF);
Xenable_bell;
X
XENDPROCEDURE;                                                         
X
X
X`012
V!------------------------------------------------------------------------------
X-
VPROCEDURE next_group;`009`009`009      ! still needs to skip comletely read gro
Xups
X
Xposition(subscribe);            
Xif mark(none) = end_of(current_buffer)then 
X`009message ('ARGH -- End of News Groups (no more to read)'); 
X`009move_vertical(-1);
X`009return(0);
XENDIF;
Xmove_vertical(+1);`009`009`009`009! move to next group
Xmove_to_group_with_pending_news;
X
Xupdate_banner;        
X
XENDPROCEDURE;
X                                                                               
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE move_to_group_with_pending_news
X! checks current group -- if current group has news it does not move forward
X
XLOCAL s1,s2,subs_current,a2,active_top,active_bot,diff;
X
Xposition(subscribe);
X! check for end of news groups
Xif mark(none) = end_of(current_buffer)then 
X`009message ('argh -- End of News Groups (no more to read)'); 
X`009move_vertical(-1);                                      
X`009return(0);
XENDIF;
X
X! if its an unsubscribed group, skip it
Xs1 := select_column_one;
Xs2 := select_column_two;
Xsubs_current := INT(s2);                                        
X
XIF subs_current = 99999 THEN `009! if unsubscribed then recurse till OK
X`009next_group;
X`009return(0);
XENDIF;
X
Vposition (BEGINNING_OF(active));`009`009`009!move to same group in active as in
X subscribe                       
Xposition(SEARCH (LINE_BEGIN & s1 & ' ', FORWARD, NO_EXACT));
Xa2 := select_column_two;        
Xactive_top    := int (a2);  
Xactive_bot    := int (select_column_three);
XIF active_bot > subs_current THEN subs_current := active_bot; ENDIF;
Xdiff := active_top - subs_current;
XIF diff < 0 THEN diff := 0; ENDIF;                
X
XIF diff = 0 THEN`009`009`009! recurse till locate group with items to read
X   next_group;
X   return(0);
XENDIF;       
X
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE zero_text_buffer;`009`009`009`009! erase text buffer
VIF end_of(text_buffer) <> beginning_of(text_buffer) THEN! but don't bother unle
Xss there is text in it
X   erase(text_buffer);
XENDIF;
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE space_bar
XLOCAL here;                                                             
Xhere := MARK(none);
Xpage_down;
XIF here = mark(none) THEN`009`009`009`009! we didn't move
X   next_news_message;`009`009`009`009`009! so at end of mesg
XENDIF;
XENDPROCEDURE;
X      
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE exit_news;
X
XWRITE_FILE (subscribe, 'sys$login:NEWS_SUBSCRIBE.dat');
Xdisable_bell;
Xmessage ('Thank You For Using NEWS(DECNET/VMS)`009  `009:-)');
Xquit;
XENDPROCEDURE;                                                  
X
X             
V!------------------------------------------------------------------------------
X-
XPROCEDURE keypad_help;
X
XIf keypad_help_visited = no THEN
X  keypad_help_init;
X  keypad_help_visited := yes;
X  return;
XENDIF;                
X                     
XMAP(text_window, keypad_help_buffer);
X
XENDPROCEDURE
X
X
X
XPROCEDURE keypad_help_init;
Xkeypad_help_buffer := create_buffer('keypad_help_buffer');
XSET(NO_WRITE, keypad_help_buffer);
XSET(SYSTEM, keypad_help_buffer);
XSET(EOB_TEXT, keypad_help_buffer, "");
X          
XMAP(text_window, keypad_help_buffer);
Xposition(keypad_help_buffer);
X
X!`012
Xcopy_text ('NEWS keypad for VT100 series terminals'); split_line;
Xcopy_text (''); split_line;
Vcopy_text ('      _________________________________     _______________________
X__________'); split_line;  
Vcopy_text ('      |   ^   |   |   |       |       |     |       |       |      
X |       |'); split_line;
Vcopy_text ('      |   |   |   V   |       |       |     | Find  | Help  | Pause
X |       |'); split_line;
Vcopy_text ('      |_______|_______|_______|_______|     |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X | Next  |'); split_line;
Vcopy_text ('                                            |       |       |      
X | Group |'); split_line;
Vcopy_text ('                                            |_______|_______|______
X_|_______|'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('                                            |       |       |      
X |       |'); split_line;
Vcopy_text ('        CTRL/R    - Refresh                 |_______|_______|______
X_| Next  |'); split_line;
Vcopy_text ('        CTRL/Z    - Exit                    |     Next      |Prev  
X |Message|'); split_line;
Vcopy_text ('                                            |     Screen    |Screen
X |       |'); split_line;
Vcopy_text ('                                            |_______________|______
X_|_______|'); split_line;
Xcopy_text (''); split_line;
Xposition(beginning_of(keypad_help_buffer));
X
X!    
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE news_help;
X! give them help                                                               
X
XIf help_visited = no THEN
X  news_help_init;
X  help_visited := yes;
X  return;
XENDIF;
X                     
XMAP(text_window, help_buffer);
X
XENDPROCEDURE
X
X
X
XPROCEDURE news_help_init;
Xhelp_buffer := create_buffer('help_buffer');
XSET(NO_WRITE, help_buffer);
XSET(SYSTEM, help_buffer);
XSET(EOB_TEXT, help_buffer, "");
X
XMAP(text_window, help_buffer);
Xposition(help_buffer);
X
Vcopy_text(' NEWS keyboard help:                                                
X            '); split_line;
Vcopy_text('              n      - get next message                             
X            '); split_line;
Vcopy_text('              N      - moves to next group                          
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('              s      - Saves current message to a file              
X            '); split_line;
Vcopy_text('              g      - go to a group by name                        
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('              c      - Catch-up    (marks all messages in current gr
Xoup as read)'); split_line;
Vcopy_text("              u      - Unsubscribe           (you'll never see this 
Xgroup again)"); split_line;
Vcopy_text('              #      - read article by number       (skips interveni
Xng articles)'); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('         CTRL/W      - refresh screen                               
X            '); split_line;
Vcopy_text('         CTRL/Z      - exit                                         
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('         <Space Bar> - Displays next screen full of text            
X            '); split_line;
Vcopy_text('                     - If there is no more text, it gets next messag
Xe           '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Vcopy_text('                                                                    
X            '); split_line;
Xcopy_text("                            Press <1> to Exit Help"); 
XENDPROCEDURE;                              
X              
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE disable_bell;
VSET (BELL, ALL      ,OFF);                                                     
X                           
XSET (BELL, BROADCAST, ON);
XENDPROCEDURE;        
X
XPROCEDURE enable_bell;
XSET (BELL, ALL      ,ON );
XENDPROCEDURE;
X
X
V!------------------------------------------------------------------------------
X-
XPROCEDURE my_undefined_key;
Xmessage ('');`009`009`009! this rings bell as long as broadcast is set = all
XENDPROCEDURE;
X                                      
XPROCEDURE one_map;`009`009! map text_buffer with USENET news to screen
XMAP(text_window, text_buffer);
Xupdate_banner;
XENDPROCEDURE;
X
XPROCEDURE two_map;`009`009! map subscribe to screen
X`009`009`009`009! allow arrows keys to select group
XMAP (text_window, subscribe);
XENDPROCEDURE;
X                                           
XPROCEDURE three_map;
XMAP (text_window, active);
XENDPROCEDURE; 
X
XPROCEDURE five_map;
XMAP (text_window, message_buffer);
XENDPROCEDURE;
X
XPROCEDURE six_map;
XMAP (text_window, ac_tmp);
XENDPROCEDURE; 
X
XPROCEDURE seven_map;
XMAP (text_window, sub_tmp);
XENDPROCEDURE; 
X
X
X
XPROCEDURE end_of_line
Xposition (search (LINE_END, FORWARD, EXACT));
XENDPROCEDURE;                    
X
X
XPROCEDURE begin_of_line;
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
XENDPROCEDURE;        
X
X
XPROCEDURE save_mesg`009`009`009! write current message to disk
XLOCAL save_name;
Xsave_name := READ_LINE ('Save current message to file: ');
Xif length(save_name) = 0 then return(0); endif;
XWRITE_FILE (text_buffer, save_name);
Xmessage('file written');`009! add: check if written sucessfully
XENDPROCEDURE;
X            
X                                         
XPROCEDURE select_column_one
XLOCAL j1;   `009`009`009`009! returns column one as a string
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xj1 := search (LINE_BEGIN & SCAN(' '),FORWARD);
XRETURN (SUBSTR(j1,1,999));
XENDPROCEDURE;
X                
X                   
XPROCEDURE select_column_two 
XLOCAL a, b, c, d;       ! returns column two as a string
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
X
Xa  := current_line + ' ';
Xb  := INDEX  (a, ' ');
Xa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (a, ' ');
Xd  := SUBSTR (a, 1, c - 1);
X                            
XRETURN(SUBSTR(d,1,999));
XENDPROCEDURE;                                  
X                 
X
XPROCEDURE select_column_three
XLOCAL a, b, c, d, e; `009`009`009`009`009! returns column three as a string
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));`009`009! LINE ->> STRING
Xa  := current_line + ' ';
X
Xb  := INDEX  (a, ' ');
Xa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (a, ' ');
Xa  := SUBSTR (a, c+1, 999);
X                         
Xd  := INDEX  (a, ' ');`009`009`009! extract column three
Xe  := SUBSTR (a, 1, d-1);
X
XRETURN (SUBSTR(e,1,999));
XENDPROCEDURE;          
X
X     
XPROCEDURE replace_column_two (thing)
XLOCAL  a, aa, aaa, line, x3, b, c, d, thing1;
X
Xthing1 := STR(thing);`009`009`009! precede w/ 0's
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
XIF LENGTH(thing1) < 5 THEN thing1 := "0"+thing1; ENDIF;
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));       `009! LINE ->> STRING
Xa  := current_line + ' ';
X
Xb  := INDEX  (a, ' ');
Xaa  := SUBSTR (a, b+1, 999);
X
Xc  := INDEX  (aa, ' ');
Xaaa:= SUBSTR (aa, c, 999);
X
Xline := SUBSTR(a,1,b) + thing1 + aaa;
Xedit (line, TRIM_TRAILING);
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xcopy_text(line); 
Xsplit_line;
Xerase_line;                            
Xmove_vertical (-1);
XENDPROCEDURE;                                  
X                                    
X                         
XPROCEDURE go_to_article
XLOCAL a1, numb , x;
X
Xa1 := READ_LINE ('Go to which article number: ');
Xif a1 = "" THEN return(0); ENDIF;
Xnumb := INT(a1);
Xif numb = 0 then return; endif;
X
Xx := mark(none);
Xposition(subscribe); 
Xreplace_column_two (numb); 
Xposition(x);
Xnext_news_message;
X
XENDPROCEDURE;
X
X
XPROCEDURE top_of_buf;
Xposition(beginning_of(current_buffer));
XENDPROCEDURE;
X           
X
XPROCEDURE bot_of_buf;
Xposition(end_of(current_buffer));
XENDPROCEDURE;
X            
X
Xprocedure author;
Xmessage("Written By Christopher Seline (11/Apr/88)");
Xmessage("SCS7317@oberlin.bitnet");
XENDPROCEDURE;
X
XPROCEDURE try;
Xmessage('try1');
X                       
XENDPROCEDURE;
X              
XPROCEDURE underline_line
XLOCAL r1,r2;
X! bug -- only underlines in one buffer at a time
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xr1 := MARK (none);
Xposition (search (LINE_END, FORWARD, EXACT));
Xr2 := MARK (none);
X                
Xunderline_x2 := CREATE_RANGE (r1,r2,UNDERLINE);
Xr1 := 0; 
Xr2 := 0;             
XENDPROCEDURE;                                   
X
XPROCEDURE underline_subject_line
XLOCAL 
X   r1,r2,j3 ;
X        
Xj3 := mark (none);
Xr1 := search ('subject',FORWARD,NO_EXACT);
XIF r1 = 0 THEN return(0); ENDIF; !No Subject
Xposition (r1);
X
Xposition (search (LINE_BEGIN, REVERSE, EXACT));
Xr1 := MARK (none);
Xposition (search (LINE_END, FORWARD, EXACT));
Xr2 := MARK (none);
X
Xunderline_i1 := CREATE_RANGE (r1,r2,UNDERLINE);
Xr1 := 0; 
Xr2 := 0;             
X
Xposition (j3);
XENDPROCEDURE;
X
X
X
X
VPROCEDURE scroll_line_to(dest_line)`009`009`009`009! scrolls the screen so that
X the current line is at the line # specified by dest_line
VLOCAL old_position;`009`009`009`009`009`009! preserves the cursor position thro
Xugh the scroll
X    old_position := MARK(NONE);
X    SCROLL(CURRENT_WINDOW,
X           GET_INFO(CURRENT_WINDOW, "current_row")-dest_line);
X    POSITION(old_position);
XENDPROCEDURE;
X
X
X`012
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X!                                                     K E Y   B I N D I N G S
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X    
VSET(SELF_INSERT, "TPU$KEY_MAP_LIST", OFF);`009! make it so typing keys won't se
Xlf-insert
VSET(UNDEFINED_KEY, "TPU$KEY_MAP_LIST", "my_undefined_key");`009! and specify wh
Xat to do when an undefined key is pressed
XDEFINE_KEY("exit_news", CTRL_Z_KEY);`009`009! exit
XDEFINE_KEY("quit",KEY_NAME('q')); 
XDEFINE_KEY("author", KEY_NAME("A"));
XDEFINE_KEY("page_down", KP0);`009`009`009! page down
XDEFINE_KEY("page_up", PERIOD);`009`009`009! page up
XDEFINE_KEY("line_down", DOWN);`009`009`009! scroll down
XDEFINE_KEY("line_up", UP);`009`009`009! scroll up 
XDEFINE_KEY("go_to_article", KEY_NAME("#"));`009! goto article #
XDEFINE_KEY("go_to_group", KEY_NAME("G"));`009! Goto Group EXACT
XDEFINE_KEY("go_to_group_NOexact", KEY_NAME("g"));! Goto Group NOEXACT
XDEFINE_KEY("go_to_group_NOexact", PF1);`009`009! Goto Group NOEXACT
XDEFINE_KEY("next_group", KEY_NAME('N'));`009! next group
XDEFINE_KEY("next_group", COMMA        );`009! next group
XDEFINE_KEY("space_bar", KEY_NAME(" "));`009     `009! NEXT THING
XDEFINE_KEY("next_news_message", ENTER);
XDEFINE_KEY("next_news_message", KEY_NAME('n'));
XDEFINE_KEY("attach", KEY_NAME('P'));`009`009! PAUSE news
XDEFINE_KEY("attach", PF3          );
XDEFINE_KEY("catch_up",KEY_NAME('c'));  `009`009! mark group as read
XDEFINE_KEY("UN_catch_up",KEY_NAME('C'));`009`009! mark group as UNread
XDEFINE_KEY("keypad_help", PF2);
XDEFINE_KEY("news_help", KEY_NAME('?'));    
XDEFINE_KEY("news_help", KEY_NAME('h'));
XDEFINE_KEY ("one_map", KEY_NAME("1"));
XDEFINE_KEY ("two_map", KEY_NAME("2"));     
XDEFINE_KEY ("three_map", KEY_NAME("3"));   
XDEFINE_KEY ("five_map", KEY_NAME("5"));
XDEFINE_KEY ("six_map", KEY_NAME("6"));
XDEFINE_KEY ("seven_map", KEY_NAME("7"));
X
XDEFINE_KEY ("top_of_buf",KEY_NAME("<"));
XDEFINE_KEY ("bot_of_buf",KEY_NAME(">"));
XDEFINE_KEY ("save_mesg", KEY_NAME('s'));`009`009! save to disk
XDEFINE_KEY ("subscribe_proc", KEY_NAME('U'));`009`009! UNunsubscribe
XDEFINE_KEY ("unsubscribe", KEY_NAME('u'));
XDEFINE_KEY ("refresh",   CTRL_L_KEY);
XDEFINE_KEY ("refresh",   CTRL_R_KEY);
XDEFINE_KEY ("refresh",   CTRL_W_KEY);
X                               
X! for debugging
X
XDEFINE_KEY ("try"              , KEY_NAME("~"));
X                                         
X
X
V!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
X+++++++++++++++++++++++++++++++++++++++++++++++++
X
X!SAVE("SYS$LOGIN:news");
XSAVE("students:[scs7317.trans]news_inprog");
XQUIT;
X
$ GoSub Convert_File
$ Exit

SCS7317%OCVAXB%VB.CC.CMU.EDU%KL.SRI.COM%lbl%sfsu1.hepnet@LBL.GOV (05/28/88)

Received: from KL.SRI.COM by LBL.Gov with INTERNET ;
          Thu, 26 May 88 16:14:11 PDT
Received: from VB.CC.CMU.EDU by KL.SRI.COM with TCP; Tue 24 May 88 16:04:03-PDT
Date: Tue, 24 May 88 19:04 EDT
From: Christopher Seline <SCS7317%OCVAXB@VB.CC.CMU.EDU>
Subject: NEWS(DECNET/VMS)  USENET on VMS  manual for NEWS
To: info-vax@KL.SRI.COM
X-VMS-To: CMCCVB::IN%"info-vax@kl.sri.com"
 
.lm 3
.rm 72
.sp1
.ap
.p 0,1,3
.enable bar
 
.c74;-----------------------------------
.c74;|              NEWS               |
.c74;|   USENET News reading utility   |
.c74;|          User's manual          |
.c74;-----------------------------------
 
 
.c74;version 3.00
.c74;(c) 1988 Christopher Seline
 
.sk 4
^&Conventions used in this document:\&
 
.begin bar
Sections that describe advanced concepts are denoted by 
vertical bars in the left margin.  This information is intended for
the more experienced user, and can be skipped at the first reading.
.end bar
 
.sk 4
.c74;***   ^&Introduction\&   ***
 
 
^&About USENET News\&
 
"News" is a utility that enables users on a network site not directly on
USENET (e.g., bitnet users) to read the news 
that is circulated around the world on USENET,
commonly known as netnews.  Netnews is a huge bulletin board of sorts:
a forum of open discussion and/or announcements on many
topics in which all of 
the thousands of readers are welcome to participate.  
 
Netnews is divided into well over 200 newsgroups, each of which
is devoted to a particular topic.  The
subject names are split first into general areas, then into more specific
topics.  The root classifications are:
.lit
		news -  about netnews   	sci  -  science
		comp -  computers		soc  -  social
		rec  -  recreation		misc -  miscellaneous
		talk -  discussions
.el
There are other initial names of groups that are specific to the
network site.  For example, 'att' denotes newsgroups 
specific to AT_&T, and can only be read by users 
using an AT_&T node.
 
Beyond these classifications, the newsgroup names get progressively
more specific.
Examples:  comp.sys.ibm.pc, rec.arts.startrek,
soc.college, and rec.auto.  Each newsgroup
name should be sufficiently descriptive of the topic discussed.
 
When you read netnews for the first time, the first newsgroup you
go into will be "news.announce.newusers".  READ EVERY ARTICLE IN IT.
It contains information and guidelines about netnews that every reader
is expected to know.
 
 
^&Getting started with NEWS\&
 
Before running news, it is necessary to define the variable
'news__farsite', like so:
.sk1
.c74;define news__farsite [local-value]
 
This is a code that tells NEWS how to contact the nearest USENET
site.  Since this will be a different value on each system, your
system manager will tell you what your local value is.  It is
easiest to put this definition in your login.com file, so you
don't have to remember it each time you read the news.
 
News is a VAX TPU (Text Processing Utility) program.  This means that
to run the program, you invoke the TPU editor with a special
command file.  This file should be stored in
a public directory.  Here is how the program is run
at Oberlin:
.sk1
.c74;edit/tpu/sec=softlib:[share]news
                  
Your system manager will be able to tell you where the program is on
your system.  Replace 'softlib:[share]news' above with the appropriate
directory and file name.
 
To make this procedure easier, you can define the above command as
something else in your login.com file, like so:
.sk1
.c74;$define news edit/tpu/sec=softlib:[share]news
 
Again, replace this filename with the one specific to your system.
After this is done, simply type 'news' to run the program.
 
.sk3
.c74;***   ^&Your First NEWS Session\&   ***
 
^&Establishing the link to netnews\&
 
When you run NEWS for the first time it takes a minute to
create a necessary information file in your directory.  NEWS will
tell you that it is creating a new subscription for you.
 
Every time you invoke NEWS it will take several moments to access netnews
at your USENET site.  It should blink 'Loading active' near the bottom
right corner of the screen until it establishes the link.  
 
If there
is an outright error in accessing the 
USENET node, you will know right away,
and will be prompted to hit 'q' to quit.  If this happens, 
either the link is temporarily down or you
are trying to access the USENET node incorrectly (due to an incorrect
news__farsite value).  If you are
sure you have the correct news__farsite value defined, try again later.
 
If it blinks 'Loading active' for more than a few minutes, either 
the network load is too high or the USENET node is 
having problems of its own.  Try again later.
 
^&Screen layout\&
 
The screen is split into two sections, separated by a bar of inverse
text.  The top (largest) part of the screen is the main display area;
this is where the news articles are displayed.  The area below the bar
is where NEWS program messages and error messages are displayed.
 
The inverse-video bar acts as a status
line, and also reminds you of two important commands:  <CTRL>-Z to exit,
and '?' for help.  The status information includes the newsgroup you
are currently reading, the current article number, and the number of
remaining articles in that newsgroup.
 
The article number is probably already quite high.  This is because
the numbers have not been reset since the newsgroup began.  You cannot
read the articles before the one that NEWS starts you at;  they have
been discarded due to old age.
 
^&On-line help\&
 
On-line command information is displayed with '?' or 'h'.  Hit '1'
to return to reading the news.  On VT-100 type terminals, 
keypad information is also
available with the PF2 key.  '1' exits this help screen as well.
 
^&Newsgroup subscriptions\&
 
When you run NEWS for the first time, you are automatically 'subscribed'
to all the newsgroups, meaning you have the opportunity to read articles
in every group.  Since you will probably not be interested in
all the topics, you will want to un-subscribe to most groups.
After you un-subscribe to a newsgroup, you will not see any of its
articles again unless you re-subscribe to it.  See
the section titled 'Selecting newsgroups' for a discussion of how to
choose your subscriptions.
 
Remember to read everything in 'news.announce.newusers' before moving
on to the rest of netnews.  
.page
.c74;***   ^&Reading Articles\&   ***
 
The up and down arrows scroll the screen in
both directions.  However, there are easier ways to page through
the articles.
 
The space bar scrolls down to next screen.  If you are at the end of 
an article, this will also move to the next article.  If you are
at the end of the last article in a newsgroup, it will move to the
next available newsgroup and wait for further instructions before
reading any articles.
 
Note that when you advance to the next article there is a delay
as the program blinks 'Retrieving' in the message window.  This is
because it takes time to grab the file from the USENET node.  
 
Other commands:
.lm 9
.p -6,1,3
 
>#####Go to the end of the current article.  
 
<#####Go to the top of the current article.
 
n#####Advances to next article, even if you have not seen all of the
current article.
 
_######Go to a particular article number, which NEWS prompts you for.
If you skip forward, NEWS will count the skipped articles as read when
you exit.  This means that when you re-enter NEWS, your current position 
in that newsgroup will be 
beyond those missed articles.
 
s#####Save the current article to a file.  NEWS will prompt you for a 
filename and inform you when the process is complete.
 
c#####Catch up in the newsgroup.  This marks all the active articles
as read, so you can start fresh with all future articles.  This is a
good way to rationalize not sifting through all the remaining articles.
 
C#####Un-catch up.  This returns your current article number to the
first active (and unread) article in the newsgroup.
.sk1
 
The following commands utilize the keypad on VT-100 type terminals:
.lm 9
.p -6,1,3
 
<0>###Page down.  This differs from the space bar in that it will not
advance any further when it reaches the end of the current article.
 
<_.>###Page up.  As with '0', this will not move beyond the
current article.
.lm 14
.p -11,1,3
 
<ENTER>###Advance to the next message.  Identical to the 'n' command. 
 
.page
.c74;***   ^&Selecting Newsgroups\&   ***
.lm 3
.p 0,1,3
 
^&Moving between newsgroups\&
 
The following commands allow you to choose your current newsgroup:
.lm 9
.p -6,1,3
 
N#####Go to the next subscribed newsgroup.  
Note the difference between 'N' and 'n'.
 
g#####Go to the next non-specific newsgroup.  NEWS will prompt you for
a newsgroup name, and will advance to the next newsgroup that contains
the requested string.  For example, enter 'ibm' and it will move to the
next newsgroup that has 'ibm' in its name.  If it does not find the
specified keyword in any newsgroups, it will remain in the current group.  
 
G#####Go to the next specific newsgroup.  This time, when NEWS prompts
you for a newsgroup name, you must enter the full name of the newsgroup,
such as 'comp.sys.ibm.pc'.  If it does not find the specified newsgroup,
it will remain in the current group.
 
Also, on the VT-100 keypad:
 
<,>###Go to the next subscribed newsgroup.  Identical to the 'N' command.
 
PF1###Go to the next non-specific newsgroup.  Identical to the 'g' command.
 
.lm 3
.p 0,1,3
With all commands that change the current newsgroup,
NEWS will wait for you to decide if you want to read articles in
that newsgroup.  Hit the space bar or 'n' to read the first article.
.sk1
 
^&Subscribing to specific newsgroups\&
 
The following commands allow you to choose which newsgroups to read
and which ones to skip next time you read netnews.
.lm 9
.p -6,1,3
 
u#####Unsubscribe to the current newsgroup.  If you are reading an article,
NEWS will advance to the next available newsgroup and wait for instructions.
 
U#####Un-unsubscribe to the current newsgroup.  Returns the current article
number to the first unread article.
 
2#####(on the regular keyboard)  Display the list of newsgroups.  This
will replace the article area on the screen with a list of all newsgroups
available, as well as your current article number in that newsgroup.  
You can scroll around with the same commands as you use to
read messages - the arrow keys, the space bar, '<', '>', and the keypad.  
'1' returns you to the current article.
.lm 3
.p 0,1,3
 
The 'u' and 'U' commands are made considerably easier through the '2'
command.  With the newsgroup list on the screen, 'u' and 'U' affect the
newsgroup marked by the cursor at the top of the screen.  Note that
when you unsubscribe to an article, the current article number changes
to 99999, and un-unsubscribing changes it back to the first unread article.
 
.begin bar
What the '2' command is actually doing is making the newsgroup list buffer
the active buffer in TPU.  The '3' command will name the newsgroup file
as the active buffer.  The '1' command
returns the article buffer to be the active buffer (note that this is why
'1' exits help screens and returns to netnews).  
 
The newsgroup file contains the list of newsgroups
in your home directory.  One can edit this file outside of NEWS, putting
the important newsgroups at the top of the list.  Deleting newsgroups
from this list, even if you think you will never ever want to read
them, is not recommended.  The extra
information the file contains is the number of 
the latest posted article in the
newsgroup, and the subscription status of that newsgroup.
.end bar
 
.sk3
.c74;***   ^&Miscellaneous commands\&   ***
 
To exit news, type Control-Z.  This causes NEWS to remember which
articles you read, so that the next time you read news you are at the
same point in all your subscribed newsgroups.  'q' also exits the
program, but does not remember which messages you read.
 
To refresh the screen, type Control-W or Control-R.
 
.begin bar
The 'P' command pauses NEWS, returning to the operating system
temporarily.  This allows you to read mail, etc. and still
remain in the NEWS program.  On VT-100 terminals, the PF3 key
also executes this command.
 
To use this feature, NEWS must be invoked with SPAWN#NEWS in DCL.  To
re-enter NEWS, use the ATTACH#[process-name] command, where
[process-name] was the name given by SPAWN to your command level
process when you invoked NEWS.
 
'5' assigns the message buffer (normally seen at the bottom of the
screen) to be the current buffer.  See 'Selecting Newsgroups:
Subscribing to specific newsgroups' for a discussion of swapping
buffers.
.end bar
 
.page
.c74;***   ^&Command Summary\&   ***
.lit
 
 
	    ?,h		help
	<space bar>	page down, even through articles
	     n		next article
	     N		next newsgroup
	     #		go to article number
	     c		catch-up to latest article
	     C		un-catch-up (return to last unread article)
	     g		go to non-specific newsgroup
	     G		go to specific newsgroup
	     s		save article to file
	     u		unsubscribe to current newsgroup
	     U		un-unsubscribe to newsgroup
	     <		top of article
	     >		bottom of article
	     ^Z		exit (remember read articles)
	     q		quit (don't remember read articles)
	   ^R,^W	redraw screen
	     1		make text buffer active
	     2		make newsgroup buffer active
|	     3		make complete newsgroup file active
|	     5		make message buffer active
|	     p		pause
 
.el
.c74;VT-100 Keypad commands:
.lit
 
	    PF2		keypad help
	     0		page down
	     . 		page up
	  <enter>	next article
	     ,		next newsgroup
	    PF1		go to non-specific newsgroup
|	    PF3		pause
.el
 
.page
.c74;***   Program Messages   ***
 
"Can't find the group you referred to: [group-name]"
 
You asked to go to a newsgroup (with either g or G) and NEWS could
not find a group by that name.  You are returned to the newsgroup
and article you are currently reading.
 
"Nothing left to read in group [group-name] -- Moving to next Group"
 
This is what happens when you finish the last article in a newsgroup
and hit the space bar or 'n'.  
Note that although it moves to the next group,
it does not start reading the articles; hit 'n' or the space bar again
to continue.
 
"Null News Body -- Hope that's OK"
 
NEWS tried to read an article that turned out to be empty.  This is
most likely due to a numbering error in netnews, so you're not
missing anything.