home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / readsum.zip / READSUM.CMD < prev    next >
OS/2 REXX Batch file  |  1994-12-18  |  22KB  |  711 lines

  1. /* rexx */
  2. /* 
  3. Date: 12/17/94 - version 1
  4. Author: Jamie Hoglund
  5. Contact: jhoglund@cscns.com
  6.          70244,3234@compuserve.com
  7. Script: 2/3
  8.    
  9.    This is the main display Script to select from a list of
  10.    Summaries generated by the Uqwk Offline reader program.
  11.   
  12. -------------------------------------------------------------------------
  13.          Note: Configuration can be done by editing this file. 
  14.                Use your editors "Search" function to search for 
  15.                lines that have the string: "@CFG" in them.
  16. -------------------------------------------------------------------------
  17.  
  18.    Input: SortFil
  19.           GroupFil
  20.  
  21.    Output: GroupFil is updated.
  22.  
  23.    You may wish to change Groupfil and Sortfil to be command
  24.    line arguments, this will allow several "selection" files to
  25.    exist, (Unfortunately This script doesn't directly support a 
  26.    'Selection Base'
  27.  
  28.    The first menu is a list of newsgroups. Select from these, a
  29.    list of articles that may be selected from.
  30.  
  31.    Help in doing this is available by pressing F1.
  32.  
  33.    The Display uses ansii codes, and is configured for a monochrome
  34.    monitor. This is configurable in the CsrAttrib() procedure.
  35.    Instructions are there.
  36.  
  37.    The keyboard is redefined, so if you prefer to use other than the 
  38.    Default keys, look under Redefine Redefine_keys & Restore_Keys.
  39.    these are redefined using Ansii codes. Make sure that if you update
  40.    Redefine_Keys, you also update Restore_keys.
  41.  
  42.    Dll's required: None!
  43.  
  44.    Bugs:
  45.  
  46.    Redefining and Resetting the keyboard repeatedly seems to cause
  47.    problems. This appears to be ANSI.SYS running out of memory.
  48.    If you run into this, type ES <Enter>
  49.    ES <ENTER> until you are prompted to save changes.
  50.  
  51.    Start a new command session, and the program will work again. 
  52.    (Changing the procedures Redefine_keys and Restore_keys so that the
  53.    keyboard is only redefined once would fix this, but your keyboard
  54.    would remain redefined, causing potential problems elsewhere...)
  55.  
  56.    This Bug won't show up unless you run and re-run the program
  57.    _several_ times, or use "Search:" _Several_ times.
  58.    
  59.    If you discover any more bugs, or fix one, Please let me
  60.    know.
  61.  
  62.    Jamie Hoglund   jhoglund@cscns.com
  63.  */
  64.  
  65. /* Configuration information */
  66. SortFil = "SortFil.Tmp"        /*Article data, Output by Sortsum.CMD         @CFG*/
  67. GroupFil  = "Groups.Tmp"       /*Groups and Tag info, Output by Sortsum.CMD  @CFG*/
  68. TempFil   = "Groups.Bak"       /*for re-writing Groupfil, Backup.            @CFG*/
  69. /* end of file configuration, if using OS/2, should be all that's needed */
  70.  
  71. /* make sure files exist */
  72. If Length(Stream(Sortfil,"C","Query exists")) = 0 then do
  73.   Say SortFil"  - Does not exist, must run sortsum.cmd, or re-configure"
  74.   exit
  75. end
  76. If Length(Stream(Groupfil,"C","Query exists")) = 0 then do
  77.   Say GroupFil"  - Does not exist, must run sortsum.cmd, or re-configure"
  78.   exit
  79. end
  80.  
  81.  
  82. /* Solve problems with CTRL-C and Ansii codes */
  83. call on halt Name ExitProc     /* make sure CTRL-C won't trash screen */
  84. CALL ON ERROR NAME ExitProc 
  85. CALL ON FAILURE NAME ExitProc
  86. CALL REDEFINE_KEYS            /* re-assign Keyboard */
  87.  
  88. I = 0
  89. DO UNTIL LINES(GroupFil) = 0
  90.   Gbuf = Linein(GroupFil)
  91.   Parse var Gbuf Sp Anum Gbuf
  92.   I = I + 1
  93.   GroupDat.1.I = "  Tagged:"Count_Tagged(Anum)" "Gbuf"   ("Length(Anum)")"   /* text displayed */
  94.   GroupDat.2.I = Sp            /* file seek position */
  95.   GroupDat.3.I = Length(Anum)  /* number of articles */
  96.   GroupDat.4.I = Anum          /* Tagged article information */
  97. END
  98.  
  99. GroupDat.1.0 = I  /* number of groups, in element 1.0, for display */
  100. /* assign a dummy Current group, this is for newsgroup selection level. */
  101. Current_group = 0
  102. GroupDat.4.0 = copies("0",I)
  103. GroupDat.3.0 = I
  104.  
  105. HelpText     = "Helptext.txt"  /* file used for online 'help' */
  106.   Screen_Len   = 23
  107.   Screen_Top   = 1
  108.  
  109. /* main display loop */
  110. Do Forever
  111.   /* initialize variables for newsgroup selection */  
  112.   Current_group = 0 /* used for Read_tagged, GroupDat.0.4 = "0" */
  113.   DisplayArray = "GroupDat.1"
  114.   Title        = "News Groups"
  115.   Valid_Input = "Search: KU KD KR KL KH KE ES PU PD F1 CR NU"
  116.   HelpChapter = 1  /* newsgroup selection level */
  117.   Call Display     /* returns Q (And TAG.x) */
  118.   IF Q = 0 then    /* Pressed escape, or KR */
  119.     Leave
  120.   IF Q < 0 | DATATYPE(Q,"N")= 0 then
  121.     Iterate
  122.   /* Initialize variables for Readin_Articles */
  123.   Articles = GroupDat.3.Q
  124.   Apos = GroupDat.2.Q
  125.   Call ReadIn_Articles
  126.   Current_Group = Q
  127.  
  128.   /* initialize variables for Article selection */
  129.   HelpChapter = 2
  130.   ArticleDat.2.0 = Articles       /* number of subject lines */
  131.   DisplayArray = "ArticleDat.2"
  132.   Parse Var GroupDat.1.Q Garbage Title Garbage  /* Get newsgroup name */
  133.   Valid_Input = "Tag: Search: KU KD KH KE ES PU PD TG F1 TA UT CR"
  134.   Call Display  /* display article selection */
  135.   IF Q > 0 then      /* Update tagged string/Flags */
  136.     Call Put_Tagged
  137. End
  138. Call Write_Tagged
  139.  
  140. /* Close files, clean-up and exit */
  141. Call exitProc
  142.  
  143. /* 
  144.   put articles from Sortfil into array ArticleDat.[1-3].n
  145.  
  146.   Articles - Number of article (summary lines) to read in
  147.   Apos     - Seek position where articles begin
  148.  ---------------------------------------------------------
  149.   ArticleDat.1.n - Article numbers
  150.   ArticleDat.2.n - Subject line (text)
  151.   ArticleDat.3.n - Newsgroup number
  152. */
  153. ReadIn_Articles:
  154. /* Position File pointer at line 1 of newsgroup articles */
  155. I = Linein(SortFil,1,0)
  156. Call Stream SortFil,"C","Seek = "Apos  
  157. Do I = 1 to Articles
  158.   /* get a line of sorted input, Translate for delimiters */
  159.   ABuf = Translate( LineIn(SortFil)," "D2c(254),D2C(254)" ")
  160.   ArticleDat.1.I = Word(Abuf,3)
  161.   ArticleDat.3.I = Word(Abuf,1)
  162.   Vbuf = Word(Abuf,2)
  163.   /* detect Re: subjects */
  164.   If Right(Word(ABuf,2),2)=D2C(253)":" then
  165.     Vbuf = ">"Left(Vbuf,Length(Vbuf)-4)
  166.   ArticleDat.2.I = Translate(Vbuf," ",D2C(254))
  167. end
  168. Call Stream SortFil,"c","close"
  169. Return
  170.  
  171. /* 
  172.    Write tagged info to GroupFil
  173.  
  174.    TempFil is deleted, Groupfil is renamed to tempfil, 
  175.    Groupfil is written, TempFil is deleted.
  176. */
  177. Write_Tagged:
  178. /* 'Fancy' Yes/No prompt */
  179. Q = "Do you wish to save changes ? [Y/N] "
  180. Call Charout ,D2C(27)"[K"Locate(23,1)||Q||CsrAttrib("Reverse")"Y"LOCATE(23,LENGTH(Q)+1)
  181. PULL Q GARBAGE
  182. Call Charout ,CsrAttrib("NORMAL")
  183.  
  184. /*  Write changes unless operator presses Crsr-Left, Escape or No.
  185.  YyNn have been redefined to Yes/No+CR */
  186. IF Q <> "NO" & Q <> "ES" & Q <> "KL" then do
  187.  Say "Keeping changes"
  188.  if Length(Stream(TempFil,"C","Query Exists")) > 0 then
  189.    '@del 'tempfil' >nul'           /* OS dependent command.   @CFG */
  190.  Call Stream GroupFil,"C","Close" 
  191.  '@ren 'GroupFil' 'Tempfil' >nul'  /* OS dependent command @CFG */
  192.  DO I = 1 to GroupDat.1.0  /* GroupDat.1.0 = Number of groups */ 
  193.    Parse Var GroupDat.1.I G1 Gbuf G2  
  194.    Call Lineout GroupFil,GroupDat.2.I" "GroupDat.4.I" "Gbuf
  195.  end 
  196.    Call Stream GroupFil,"C","Close"
  197.    '@del 'tempfil' >nul'        /* OS  dependent command @CFG */
  198. end
  199. Else
  200.   Say "Abandoning changes"
  201. Return
  202.  
  203.  
  204. /* Count the number of tagged articles */
  205. Count_Tagged: Procedure
  206. ARG D
  207. X = 0
  208. DO I = 1 to LENGTH(D)
  209.  if SUBSTR(D,I,1) = "1" then
  210.   X = X + 1
  211. end /* do */
  212. RETURN X
  213.  
  214. /* Process every Byte in a string, and adjust tag.n as needed 
  215.    Current_Group = The group # to calculate
  216.    GroupDat.4.Current_Group = string of "0"'s and "1"'s
  217.    -----------------------------------------------------
  218.    Tag.[n] = array of "*"," "
  219.    Tag_Total = Number of elements with "*"
  220. */
  221. Read_Tagged:
  222. Current_Tagged = GroupDat.4.Current_group
  223. Do I = 1 to Length(Current_Tagged) 
  224.   Tag.I = TRANSLATE(SUBSTR(Current_Tagged,I,1)," *","01")
  225.   If Tag.I = "*" then
  226.    Tag_Total = Tag_Total + 1
  227. end /* do */
  228. return
  229.  
  230. /*  
  231.     Opposite of Read_Tagged,  Assign a string from TAG.[n]
  232.     Tag.[n]
  233.     Current_Group
  234.     Groupdat.3.Current_Group
  235.     -------------------------
  236.     GroupDat.4.Current_Group is updated
  237. */
  238. Put_Tagged:
  239. Current_Tagged = ""
  240. Q = 0
  241. DO I = 1 to GroupDat.3.Current_group
  242.   Current_Tagged = Current_Tagged||Translate(Tag.I,"10","* ")
  243. end 
  244.  
  245. GroupDat.4.Current_group = Current_Tagged
  246. /* Update newsgroup selection menu text */
  247. Parse Var GroupDat.1.Current_Group Garbage Gbuf
  248. GroupDat.1.Current_Group = "  Tagged:"Tag_Total" "Gbuf  /* text displayed */
  249. RETURN
  250.  
  251. /*
  252. DisplayArray - name of array to display, (Left 70 characters are displayed)
  253. Screen_Len   - Length of screen
  254. Screen_Top   - Top of screen
  255. Title        - title on top of list.
  256. HelpText     - Text File to use for help.
  257. HelpChapter  - Chapter used in HelpText
  258. Valid_Input  - Case Sensitive String of valid options:
  259.                "Tag: Search: KU KD KR KL KH KE ES PU PD TG F1 TA UT NU CR"
  260. ------------------------------
  261. Q     Exit key (Selected element)
  262. Tag.n array of Tagged ArrayName. members " "|"*" for tagged untagged
  263. Tag_Total   Number of tagged items
  264.  
  265. Uses: CsrAttrib(),Locate(),View_Refresh,tag_it,Up_Tag,Down_Tag,Dec_Flip
  266.       Inc_Flip,Search_All,Help_View,Toggle(),Whistle,Redefine_keys
  267.       Restore_keys
  268. */
  269. Display:
  270. /* Screen Counter variables */
  271. Scr_Bot = Screen_Top + Screen_Len;Dsp_Top = Screen_Top + 1;Dsp_Bot = Scr_Bot - 1
  272. Page = 0; Page_Len = Dsp_Bot - Dsp_Top
  273. Total_Page = Format(Value(DisplayArray".0") / Page_Len,5,0)
  274.  
  275. /* array Counter variables */
  276. Ar_Now = 1;Ar_Hi = Value(DisplayArray".0");Ar_Lo = 1
  277.  
  278. /* tag array counter variables */
  279. Tag_Now = 1;Tag_Pos=Dsp_Top;Tag_Total = 0
  280.  
  281. /* top and bottom menu bars */
  282. Buf = "                     F1-Help Up-Dn Pgup-Pgdn Enter Esc *-tag Press F1 for help"
  283. TopScreen = Locate(Screen_Top,1)||CsrAttrib("REVERSE")"       "CENTER(TITLE,72)||CsrAttrib("NORMAL")
  284. BotScreen = locate(Scr_Bot,1)||csrattrib("reverse")||Center(Buf,79)||csrAttrib("normal")
  285.  
  286. /* display top and bottom bars, Put cursor in top of display area 
  287. and show "Working.." while Tag.Array is being processed*/
  288. Call Charout ,TopScreen||BotScreen||Locate(Dsp_Top,1)
  289. Call Charout ,Locate(Scr_Bot,1)||CsrAttrib("reverse")"Working.."
  290.  
  291. /* assign all tag elements to current_group, update tag_total */
  292. Call Read_Tagged
  293.  
  294. /* Redefine keyboard with ANSII codes, Note: Remmed out, 
  295. because we already did it, If you are using this routine else-where,
  296. un-rem this. */
  297. /* CALL REDEFINE_KEYS */
  298.  
  299. Call charout ,CsrAttrib("Normal")
  300. Call View_Refresh
  301. Call Charout ,Locate(Scr_Bot,1)||BotScreen
  302.  
  303. /* main loop */
  304. Do Forever
  305.   /* get valid input */
  306.   Do until WordPos(Word(Q,1),Valid_Input ) > 0 | datatype(Q,"N")
  307.    Call Charout ,TopScreen||D2C(13)||CsrAttrib("Reverse")||"Tagged:"Tag_Total||Locate(Scr_Bot,1)
  308.  
  309.    Do until lines() = 0 /* this loop is for flushing Keyboard buffer */
  310.     Q = Linein()
  311.     call Charout,BotScreen||locate(scr_bot,1)
  312.    end
  313.    If length(Q) = 0 then
  314.      Q = "CR"
  315.   end
  316. Parse Var Q Q Op
  317.  
  318. SELECT
  319. When Q = "PU" then do                 /* Pgup */
  320.  ar_now = Ar_Now - ((Page_Len*2)+2)
  321.  Tag_Now = Ar_Now
  322.  If Tag_Now < 1 then
  323.    tag_Now = 1
  324.  Call View_Refresh
  325. end
  326. When Q = "PD" then do               /* PgDn */
  327.  Tag_Now = Ar_Now
  328.  call view_refresh
  329.  If Tag_Now > Ar_Hi then
  330.    Tag_Now = Ar_Hi
  331.  end
  332. When Q = "ES" | Q = "KL" then do    /* Escape or Crsr-Left */
  333.  Q = 0
  334.  Leave
  335. End
  336. When Q = "TG" then 
  337.   call tag_it
  338. WHEN Q = "KU" then                 /* Crsr-Up */
  339.   Call Up_tag
  340. WHEN Q = "KD" then do              /* Crsr-Down */
  341. IF Tag_now <= Ar_Hi then
  342.   CALL DOWN_TAG
  343. end
  344. When Q = "KE" then do             /* Keyboard-END */
  345.   Ar_Now = Ar_Hi - Page_Len
  346.   Tag_Now = Ar_Now
  347.   If Tag_Now < 1 then
  348.     tag_Now = 1
  349.     Call View_Refresh
  350. end
  351. When Q = "UT" then do            /* un-tag all, DEL */
  352. Do I = 1 to Ar_Hi
  353.    Tag.I = " "
  354. end /* do */
  355. Do I = Dsp_Top to Dsp_Bot
  356.    Call Charout ,Locate(I,3)" "
  357. end /* do */
  358. Tag_Total = 0
  359. End
  360. When Q = "TA" then do         /* Tag-All, INS */
  361. Do I = 1 to Ar_Hi
  362.    Tag.I = "*"
  363. end /* do */
  364. Tag_Total = Ar_Hi
  365. ar_now = Ar_Now - (Page_Len+2)
  366. Call view_refresh
  367. End
  368.  
  369. When Q = "KH" then do          /* Keyboard-HOME */
  370.    Ar_Now = 1;Tag_Now = 1
  371.    call View_Refresh
  372. end  /* Do */
  373.  
  374. When Q = "Search:" then        /* Search, Keyboard "/" */
  375.  Call Search_All
  376.  
  377. When Q = "Tag:" then do        /* Tag by number, Keyboard "-" */
  378.  If Datatype(Op,"N") = 1 then do
  379.    If Op < (Ar_Hi+1) then do
  380.     Q = Tag.Op
  381.     Tag.Op = Toggle(Tag.Op,"*"," ")
  382.     If Q = " " then Tag_Total = Tag_Total + 1
  383.     else
  384.     Tag_Total = Tag_Total - 1
  385.     end
  386.  end
  387.  ar_now = Ar_Now - (Page_Len+2)  /* redisplay screen, reflect tagged article */
  388.  call View_Refresh
  389. End
  390.  
  391. When Q = "F1" then          /* Help, Keyboard-F1 */
  392.  Call Help_view
  393.  
  394. When Q = "KR" then do       /* Keyboard - Right */
  395.  Q = Tag_Now
  396.  Leave
  397. end
  398. WHEN Q = "CR" then do       /* Keyboard enter */
  399.  Q = Tag_Now
  400.  If WORDPOS("CR",Valid_Input) > 0 then /* is it allowed? */
  401.   leave
  402. end  
  403. When Datatype(Q,"N") = 1 then do  /* Keyboard 0-99999... */
  404.    If Q < (Ar_Hi+1) & WORDPOS("NU",Valid_Input) > 0 then  /* is it allowed? */
  405.      Leave
  406. end  /* Do */
  407. Otherwise 
  408.  
  409. end /* do */
  410. End
  411. return
  412.  
  413. /* refresh the display */
  414. View_Refresh:
  415.      If Ar_Now > Ar_Hi then
  416.        Ar_Now = Ar_Hi
  417.      If Ar_Now < 1 then
  418.        Ar_Now = 1
  419.      DspVar_Lo = Ar_now
  420.      Tag_Now = Ar_Now
  421.  
  422.    /* begin display of current page */
  423.    Do Scr_Pass = Dsp_top to Dsp_Bot
  424.      If Ar_Now > Ar_Hi then do
  425.        Ar_Now = Ar_Hi
  426.        Q = "Quiet"
  427.      end
  428.      If Ar_Now < 1 then
  429.        Ar_Now = 1
  430.      Buffer = Locate(Scr_Pass,1)||D2C(27)"[K  "Tag.AR_NOW||CsrAttrib("HIGH")||Left(Ar_Now,5)CsrAttrib("Normal")||Strip(left(Value(DisplayArray".Ar_Now"),70),"T")
  431.      If Q = "Quiet" then
  432.        Buffer = Locate(Scr_Pass,1)||D2C(27)"[K"
  433.      Ar_Now = Ar_Now + 1
  434.      Call Charout ,Buffer
  435.    end    
  436.    TAG_POS = Dsp_Top
  437.    Call charout ,Locate(Tag_Pos,1)">"
  438.    DspVar_Hi = Ar_now - 1
  439. Return
  440.  
  441. /* Cursor Up tag routine */
  442. Up_Tag:
  443.   Old_Tag_Now = Tag_Now
  444.   Old_Tag_Pos = Tag_Pos
  445.   Tag_Now = Dec_Flip(Tag_now,DspVar_Lo,DspVar_Hi)
  446.   Tag_Pos = Dec_Flip(TAG_POS,Dsp_top,Dsp_Bot)
  447.   if Old_Tag_Now < tag_Now then do
  448.     ar_now = Ar_Now - ((Page_Len*2)+2);Tag_Now = Ar_Now
  449.     If Tag_Now < 1 then
  450.       tag_Now = 1
  451.     Call View_Refresh
  452.   End
  453.   Else
  454.   If Old_Tag_now > Tag_Now then do
  455.     Call Charout ,Locate(Old_Tag_Pos,1)" "
  456.     Call Charout ,Locate(Tag_Pos,1)">"
  457.   end
  458. return
  459.  
  460. Down_Tag:
  461.   Old_Tag_Now = Tag_Now
  462.   Old_Tag_Pos = Tag_Pos
  463.   Tag_Now = Inc_Flip(Tag_Now,DspVAr_Hi,DspVar_lo)
  464.   Tag_Pos = Inc_Flip(TAG_POS,Dsp_Bot,Dsp_top)
  465.   if Old_Tag_Now > tag_Now then do
  466.     Old_Tag_Pos = Dsp_Top
  467.     Tag_Now = Ar_Now    
  468.     call view_refresh
  469.     If Tag_Now > Ar_Hi then
  470.        Tag_Now = Ar_Hi
  471.   end
  472.   If Old_Tag_now < Tag_Now then do
  473.     Call Charout ,Locate(Old_Tag_Pos,1)" "
  474.     Call Charout ,Locate(Tag_Pos,1)">"
  475.   end
  476.   else
  477.     Tag_Pos = Old_Tag_Pos
  478. return
  479.  
  480. Tag_It:
  481. Tag.TAG_NOW = toggle(tag.Tag_NOW," ","*")
  482. call charout ,Locate(Tag_Pos,3)||tag.Tag_Now
  483. If Tag.Tag_Now = " " then 
  484.   Tag_total = Dec_Flip(Tag_Total,0,0) /* decrement to 0 */
  485.  else
  486.   Tag_total = Inc_Flip(tag_total,Ar_Hi,Ar_Hi)
  487. call Down_Tag
  488. return
  489.  
  490. /* restore keys, Read search string, and redefine keys */
  491. Search_All:
  492. Call Restore_Keys
  493. rc = charout(,D2C(27)"[27;'\^[]';13p") /* escape is cancel */
  494. Call Charout ,CsrAttrib("Reverse")||Locate(Scr_Bot,1)"Search: "
  495. Op = Linein()
  496. Call Redefine_Keys
  497. If POS("\^[]",Op) > 0 then Do /* pressed escape */
  498.  Call Charout ,BotScreen;return;end
  499.  
  500. Call Charout,Locate(Scr_Bot,1)"Searching for "Op" ..."
  501. Do I = Tag_Now to Ar_Hi
  502.    Call Whistle
  503.    If Pos(Translate(OP),Translate(Value(DisplayArray".I"))) > 0 then do
  504.       Ar_Now = I
  505.       Tag_Now = I
  506.       Call Charout ,CsrAttrib("Normal")||CsrAttrib("Blink")
  507.       Call View_Refresh
  508.       call charout ,BotScreen||D2C(7)
  509.       Return
  510.    end  /* Do */
  511. end /* do */
  512. Call Charout,Locate(Scr_Bot,1)CsrAttrib("reverse")||D2C(27)"[KString Not found"D2C(7)
  513. return
  514.  
  515. /* 'Help system' uses a chapter and File variables */
  516. Help_View:
  517. H = CsrAttrib("High")||D2C(27)"[K"
  518. L = CsrAttrib("Normal")
  519. I = 0
  520. /* Read up until Title */
  521. Do Until lines(HelpText) =0 | I = HelpChapter
  522.    Buf = Linein(HelpText)
  523.    If Translate(Word(Buf,1)) = "TITLE" then Do
  524.      Parse Var Buf Buf Title
  525.      I = I + 1
  526.    end
  527. end /* do */
  528. I = 0
  529. /* read in the help text */
  530. Do until Lines(HelpText) = 0    
  531.    Buf = Linein(HelpText)
  532.    Parse VAr Buf Key Text
  533.    If Translate(KEY) = "TITLE" then  /* Leave if there is a next chapter */
  534.      Leave
  535.    If Left(Buf,1) = "#" then
  536.      Iterate
  537.    I = I + 1
  538.    If Left(Buf,1)<>" " then /* Highlight if line doesn't begin with a space */
  539.    HelpText.I = H" "Key" "L" "Text
  540.    Else
  541.    HelpText.I = "  "Buf
  542. end /* do */
  543. Call Stream HelpText,"C","Close"
  544. Max = I
  545.  
  546. helpBar = Locate(Screen_Top,1)||D2C(27)"[K"CsrAttrib("Reverse")Center(Title,80)CsrAttrib("Normal")
  547. Say HelpBar
  548. Do I = 1 to (Screen_Len - 2)
  549.    Say D2C(27)"[K"
  550. end /* do */
  551. H = 0
  552. DO Forever
  553.  
  554.   /* clear window */  
  555.   Call Charout ,Locate(Screen_Top+1,1)
  556.   Do I = 1 to (Screen_Len - 1)
  557.    Say D2C(27)"[K"
  558.   end /* do */
  559.   Call Charout ,Locate(Screen_Top+1,1)
  560.   /* read all of it */
  561.   Do I = 1 to (Screen_Len-2)
  562.     H = H + 1
  563.     If H > Max then do
  564.       Max = 0
  565.       leave
  566.     end
  567.     Say HelpText.H
  568.   End
  569.   Call Charout ,Locate(Scr_bot,1)
  570.   Pull QHelp
  571.   If QHelp = "ES" | max = 0 then
  572.     leave
  573.   Call Charout ,Locate(Dsp_Top,1)
  574. end /* do */
  575. Call  Charout ,TopScreen||BotScreen
  576. /* update display */
  577. Ar_Now = Ar_Now - (Page_Len +1)
  578. Tag_Now = Ar_Now
  579. Call View_Refresh
  580. return
  581.  
  582. Toggle: Procedure
  583. arg V, on, off
  584. If V = on then 
  585.   v = off
  586. else
  587.   V = on
  588. return V
  589.  
  590. Inc_Flip: Procedure
  591. ARG V,MX,MN
  592. V = V + 1
  593. If V > Mx then V = Mn
  594. return V
  595.  
  596. Dec_Flip: Procedure
  597. ARG V,MN,MX
  598. V = V - 1
  599. If V < Mn then
  600. V = MX
  601. return V
  602.  
  603. /* display a rotating bar */
  604. Whistle:
  605. if Symbol("WhistleX") <> "VAR" then do
  606. WhistleIcon.1 = "-"d2c(8)
  607. WhistleIcon.2 = "\"d2c(8)
  608. WhistleIcon.3 = "|"d2c(8)
  609. WhistleIcon.4 = "/"d2c(8)
  610. WhistleIcon.5 = "-"d2c(8)
  611. WhistleIcon.6 = "\"d2c(8)
  612. WhistleIcon.7 = "|"d2c(8)
  613. WhistleIcon.8 = "/"d2c(8)
  614. WhistleX = 0
  615. WhistleY = 1
  616. end
  617. If WhistleX = 150 then do
  618.    Rc = Charout(,WhistleIcon.WhistleY)
  619.    WhistleY = WhistleY + 1
  620.    WhistleX = 0
  621.    If WhistleY > 8 then
  622.     WhistleY = 1
  623. End
  624.    WhistleX = WhistleX + 1
  625. return
  626.  
  627. /* Ansi Procedures for moving the cursor */
  628. Locate: Procedure   /*  charout(,Locate(Row,Col)) */
  629. Row = arg(1)
  630. Col = Arg(2)
  631. return D2C(27)"["Row";"col"H"
  632.  
  633. /*  change screen attributes
  634. attributes: NORMAL HIGH LOW ITALIC UNDERLINE BLINK RAPID REVERSE 
  635.  
  636. BLINK Has been used to accent found key number
  637. HIGH  Has been used to accent Item number
  638. Normal Has been used to accent the item itself
  639. Reverse Has been used to define top & Bottom bars
  640.  
  641. You should be able to change the codes & define your own personal
  642. color scheme.
  643. */
  644. CsrAttrib: Procedure
  645. Arg A
  646. attr = "NORMAL HIGH LOW ITALIC UNDERLINE BLINK RAPID REVERSE"
  647. return D2C(27)"["WORDPOS(A,ATTR) - 1";m"
  648.  
  649. /* Redefine keys using Ansi used so Pull doesn't require a CR at the end
  650.  
  651.   This routina along with restore keys can be used to define the keyboard
  652.   to your own personal taste. Make sure to restore all keys you define
  653.   using restore keys though.
  654.  
  655.   Format for Ansi redefine: esc[Keycode;"Redefinition"p
  656.  */
  657. Redefine_keys:procedure
  658. ESC = D2C(27)
  659.   rc = charout(,esc"[0;72;'KU';13p")        /* Keyboard Up */
  660.   rc = charout(,esc"[0;80;'KD';13p")        /* Keyboard down */
  661.   rc = charout(,esc"[0;77;'KR';13p")        /* Keyboard right */
  662.   rc = charout(,esc"[0;75;'KL';13p")        /* Keyboard left */
  663.   rc = charout(,esc"[0;71;'KH';13p")        /* Keyboard Home */
  664.   rc = charout(,esc"[0;79;'KE';13p")        /* Keyboard End */
  665.   rc = charout(,esc"[0;59;'F1';13p")        /* F1 */
  666.   rc = charout(,esc"[27;'ES';13p")          /* Escape */
  667.   rc = charout(,esc"[0;73;'PU';13p")        /* Page-up */
  668.   rc = charout(,esc"[0;81;'PD';13p")        /* Page down */
  669.   rc = charout(,esc"[0;82;'TA';13p")        /* Tag all, (Insert) */
  670.   rc = charout(,esc"[0;83;'UT';13p")        /* Untag all, (Del) */
  671.   rc = charout(,esc"[42;'TG';13p")          /* Tag item, "*" */
  672.   Rc = charout(,esc"['/';' Search: ';13p")  /* Search key "/" */
  673.   Rc = charout(,esc"['-';' Tag: 'p")        /* Tag item by number */
  674.   Rc = Charout(,esc"['y';'YYes';13p")    /* append CR to Y/N for prompts */
  675.   Rc = Charout(,esc"['Y';'YYes';13p")
  676.   Rc = Charout(,esc"['n';'NNo';13p")
  677.   Rc = Charout(,esc"['N';'NNo';13p")
  678. RETURN
  679. /* reset keys to default values */
  680. Restore_Keys: Procedure
  681.   ESC = D2C(27)
  682.   rc = charout(,esc"[0;72p")
  683.   rc = charout(,esc"[0;80p")
  684.   rc = charout(,esc"[0;77p")
  685.   rc = charout(,esc"[0;75p")
  686.   rc = charout(,esc"[0;71p")
  687.   rc = charout(,esc"[0;79p")
  688.   rc = charout(,esc"[0;59p")
  689.   rc = charout(,esc"[27p")
  690.   rc = charout(,esc"[0;73p")
  691.   rc = charout(,esc"[0;81p")
  692.   rc = charout(,esc"[0;82p")
  693.   rc = charout(,esc"[0;83p")
  694.   rc = charout(,esc"[42p")
  695.   Rc = charout(,esc"['/'p")
  696.   Rc = charout(,esc"['-'p")
  697.   Rc = Charout(,esc"['y'p")
  698.   Rc = Charout(,esc"['Y'p")
  699.   Rc = Charout(,esc"['n'p")
  700.   Rc = Charout(,esc"['N'p")
  701. RETURN
  702.  
  703. /* Make sure screen is O.K., Restore keys, Close files, and exit */
  704. ExitProc:
  705. Call Charout ,CsrAttrib("NORMAL")
  706. /* Put keyboard back to normal */
  707. Call Restore_keys
  708. Call Stream GroupFil,"c","close"
  709. Call Stream SortFil,"c","close"
  710. Exit
  711.