Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!pasteur!ucbvax!VB.CC.CMU.EDU!SCS7317%OCVAXB From: SCS7317%OCVAXB@VB.CC.CMU.EDU (Christopher Seline) Newsgroups: comp.os.vms Subject: NEWS(DECNET/VMS) USENET on VMS reader user agent and DECNET mapper Message-ID: <8805270053.AA04994@ucbvax.Berkeley.EDU> Date: 24 May 88 23:00:00 GMT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The Internet Lines: 1360 $!.............................................................................. $! 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(' - 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