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.