home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
readsum.zip
/
READSUM.CMD
< prev
next >
Wrap
OS/2 REXX Batch file
|
1994-12-18
|
22KB
|
711 lines
/* rexx */
/*
Date: 12/17/94 - version 1
Author: Jamie Hoglund
Contact: jhoglund@cscns.com
70244,3234@compuserve.com
Script: 2/3
This is the main display Script to select from a list of
Summaries generated by the Uqwk Offline reader program.
-------------------------------------------------------------------------
Note: Configuration can be done by editing this file.
Use your editors "Search" function to search for
lines that have the string: "@CFG" in them.
-------------------------------------------------------------------------
Input: SortFil
GroupFil
Output: GroupFil is updated.
You may wish to change Groupfil and Sortfil to be command
line arguments, this will allow several "selection" files to
exist, (Unfortunately This script doesn't directly support a
'Selection Base'
The first menu is a list of newsgroups. Select from these, a
list of articles that may be selected from.
Help in doing this is available by pressing F1.
The Display uses ansii codes, and is configured for a monochrome
monitor. This is configurable in the CsrAttrib() procedure.
Instructions are there.
The keyboard is redefined, so if you prefer to use other than the
Default keys, look under Redefine Redefine_keys & Restore_Keys.
these are redefined using Ansii codes. Make sure that if you update
Redefine_Keys, you also update Restore_keys.
Dll's required: None!
Bugs:
Redefining and Resetting the keyboard repeatedly seems to cause
problems. This appears to be ANSI.SYS running out of memory.
If you run into this, type ES <Enter>
ES <ENTER> until you are prompted to save changes.
Start a new command session, and the program will work again.
(Changing the procedures Redefine_keys and Restore_keys so that the
keyboard is only redefined once would fix this, but your keyboard
would remain redefined, causing potential problems elsewhere...)
This Bug won't show up unless you run and re-run the program
_several_ times, or use "Search:" _Several_ times.
If you discover any more bugs, or fix one, Please let me
know.
Jamie Hoglund jhoglund@cscns.com
*/
/* Configuration information */
SortFil = "SortFil.Tmp" /*Article data, Output by Sortsum.CMD @CFG*/
GroupFil = "Groups.Tmp" /*Groups and Tag info, Output by Sortsum.CMD @CFG*/
TempFil = "Groups.Bak" /*for re-writing Groupfil, Backup. @CFG*/
/* end of file configuration, if using OS/2, should be all that's needed */
/* make sure files exist */
If Length(Stream(Sortfil,"C","Query exists")) = 0 then do
Say SortFil" - Does not exist, must run sortsum.cmd, or re-configure"
exit
end
If Length(Stream(Groupfil,"C","Query exists")) = 0 then do
Say GroupFil" - Does not exist, must run sortsum.cmd, or re-configure"
exit
end
/* Solve problems with CTRL-C and Ansii codes */
call on halt Name ExitProc /* make sure CTRL-C won't trash screen */
CALL ON ERROR NAME ExitProc
CALL ON FAILURE NAME ExitProc
CALL REDEFINE_KEYS /* re-assign Keyboard */
I = 0
DO UNTIL LINES(GroupFil) = 0
Gbuf = Linein(GroupFil)
Parse var Gbuf Sp Anum Gbuf
I = I + 1
GroupDat.1.I = " Tagged:"Count_Tagged(Anum)" "Gbuf" ("Length(Anum)")" /* text displayed */
GroupDat.2.I = Sp /* file seek position */
GroupDat.3.I = Length(Anum) /* number of articles */
GroupDat.4.I = Anum /* Tagged article information */
END
GroupDat.1.0 = I /* number of groups, in element 1.0, for display */
/* assign a dummy Current group, this is for newsgroup selection level. */
Current_group = 0
GroupDat.4.0 = copies("0",I)
GroupDat.3.0 = I
HelpText = "Helptext.txt" /* file used for online 'help' */
Screen_Len = 23
Screen_Top = 1
/* main display loop */
Do Forever
/* initialize variables for newsgroup selection */
Current_group = 0 /* used for Read_tagged, GroupDat.0.4 = "0" */
DisplayArray = "GroupDat.1"
Title = "News Groups"
Valid_Input = "Search: KU KD KR KL KH KE ES PU PD F1 CR NU"
HelpChapter = 1 /* newsgroup selection level */
Call Display /* returns Q (And TAG.x) */
IF Q = 0 then /* Pressed escape, or KR */
Leave
IF Q < 0 | DATATYPE(Q,"N")= 0 then
Iterate
/* Initialize variables for Readin_Articles */
Articles = GroupDat.3.Q
Apos = GroupDat.2.Q
Call ReadIn_Articles
Current_Group = Q
/* initialize variables for Article selection */
HelpChapter = 2
ArticleDat.2.0 = Articles /* number of subject lines */
DisplayArray = "ArticleDat.2"
Parse Var GroupDat.1.Q Garbage Title Garbage /* Get newsgroup name */
Valid_Input = "Tag: Search: KU KD KH KE ES PU PD TG F1 TA UT CR"
Call Display /* display article selection */
IF Q > 0 then /* Update tagged string/Flags */
Call Put_Tagged
End
Call Write_Tagged
/* Close files, clean-up and exit */
Call exitProc
/*
put articles from Sortfil into array ArticleDat.[1-3].n
Articles - Number of article (summary lines) to read in
Apos - Seek position where articles begin
---------------------------------------------------------
ArticleDat.1.n - Article numbers
ArticleDat.2.n - Subject line (text)
ArticleDat.3.n - Newsgroup number
*/
ReadIn_Articles:
/* Position File pointer at line 1 of newsgroup articles */
I = Linein(SortFil,1,0)
Call Stream SortFil,"C","Seek = "Apos
Do I = 1 to Articles
/* get a line of sorted input, Translate for delimiters */
ABuf = Translate( LineIn(SortFil)," "D2c(254),D2C(254)" ")
ArticleDat.1.I = Word(Abuf,3)
ArticleDat.3.I = Word(Abuf,1)
Vbuf = Word(Abuf,2)
/* detect Re: subjects */
If Right(Word(ABuf,2),2)=D2C(253)":" then
Vbuf = ">"Left(Vbuf,Length(Vbuf)-4)
ArticleDat.2.I = Translate(Vbuf," ",D2C(254))
end
Call Stream SortFil,"c","close"
Return
/*
Write tagged info to GroupFil
TempFil is deleted, Groupfil is renamed to tempfil,
Groupfil is written, TempFil is deleted.
*/
Write_Tagged:
/* 'Fancy' Yes/No prompt */
Q = "Do you wish to save changes ? [Y/N] "
Call Charout ,D2C(27)"[K"Locate(23,1)||Q||CsrAttrib("Reverse")"Y"LOCATE(23,LENGTH(Q)+1)
PULL Q GARBAGE
Call Charout ,CsrAttrib("NORMAL")
/* Write changes unless operator presses Crsr-Left, Escape or No.
YyNn have been redefined to Yes/No+CR */
IF Q <> "NO" & Q <> "ES" & Q <> "KL" then do
Say "Keeping changes"
if Length(Stream(TempFil,"C","Query Exists")) > 0 then
'@del 'tempfil' >nul' /* OS dependent command. @CFG */
Call Stream GroupFil,"C","Close"
'@ren 'GroupFil' 'Tempfil' >nul' /* OS dependent command @CFG */
DO I = 1 to GroupDat.1.0 /* GroupDat.1.0 = Number of groups */
Parse Var GroupDat.1.I G1 Gbuf G2
Call Lineout GroupFil,GroupDat.2.I" "GroupDat.4.I" "Gbuf
end
Call Stream GroupFil,"C","Close"
'@del 'tempfil' >nul' /* OS dependent command @CFG */
end
Else
Say "Abandoning changes"
Return
/* Count the number of tagged articles */
Count_Tagged: Procedure
ARG D
X = 0
DO I = 1 to LENGTH(D)
if SUBSTR(D,I,1) = "1" then
X = X + 1
end /* do */
RETURN X
/* Process every Byte in a string, and adjust tag.n as needed
Current_Group = The group # to calculate
GroupDat.4.Current_Group = string of "0"'s and "1"'s
-----------------------------------------------------
Tag.[n] = array of "*"," "
Tag_Total = Number of elements with "*"
*/
Read_Tagged:
Current_Tagged = GroupDat.4.Current_group
Do I = 1 to Length(Current_Tagged)
Tag.I = TRANSLATE(SUBSTR(Current_Tagged,I,1)," *","01")
If Tag.I = "*" then
Tag_Total = Tag_Total + 1
end /* do */
return
/*
Opposite of Read_Tagged, Assign a string from TAG.[n]
Tag.[n]
Current_Group
Groupdat.3.Current_Group
-------------------------
GroupDat.4.Current_Group is updated
*/
Put_Tagged:
Current_Tagged = ""
Q = 0
DO I = 1 to GroupDat.3.Current_group
Current_Tagged = Current_Tagged||Translate(Tag.I,"10","* ")
end
GroupDat.4.Current_group = Current_Tagged
/* Update newsgroup selection menu text */
Parse Var GroupDat.1.Current_Group Garbage Gbuf
GroupDat.1.Current_Group = " Tagged:"Tag_Total" "Gbuf /* text displayed */
RETURN
/*
DisplayArray - name of array to display, (Left 70 characters are displayed)
Screen_Len - Length of screen
Screen_Top - Top of screen
Title - title on top of list.
HelpText - Text File to use for help.
HelpChapter - Chapter used in HelpText
Valid_Input - Case Sensitive String of valid options:
"Tag: Search: KU KD KR KL KH KE ES PU PD TG F1 TA UT NU CR"
------------------------------
Q Exit key (Selected element)
Tag.n array of Tagged ArrayName. members " "|"*" for tagged untagged
Tag_Total Number of tagged items
Uses: CsrAttrib(),Locate(),View_Refresh,tag_it,Up_Tag,Down_Tag,Dec_Flip
Inc_Flip,Search_All,Help_View,Toggle(),Whistle,Redefine_keys
Restore_keys
*/
Display:
/* Screen Counter variables */
Scr_Bot = Screen_Top + Screen_Len;Dsp_Top = Screen_Top + 1;Dsp_Bot = Scr_Bot - 1
Page = 0; Page_Len = Dsp_Bot - Dsp_Top
Total_Page = Format(Value(DisplayArray".0") / Page_Len,5,0)
/* array Counter variables */
Ar_Now = 1;Ar_Hi = Value(DisplayArray".0");Ar_Lo = 1
/* tag array counter variables */
Tag_Now = 1;Tag_Pos=Dsp_Top;Tag_Total = 0
/* top and bottom menu bars */
Buf = " F1-Help Up-Dn Pgup-Pgdn Enter Esc *-tag Press F1 for help"
TopScreen = Locate(Screen_Top,1)||CsrAttrib("REVERSE")" "CENTER(TITLE,72)||CsrAttrib("NORMAL")
BotScreen = locate(Scr_Bot,1)||csrattrib("reverse")||Center(Buf,79)||csrAttrib("normal")
/* display top and bottom bars, Put cursor in top of display area
and show "Working.." while Tag.Array is being processed*/
Call Charout ,TopScreen||BotScreen||Locate(Dsp_Top,1)
Call Charout ,Locate(Scr_Bot,1)||CsrAttrib("reverse")"Working.."
/* assign all tag elements to current_group, update tag_total */
Call Read_Tagged
/* Redefine keyboard with ANSII codes, Note: Remmed out,
because we already did it, If you are using this routine else-where,
un-rem this. */
/* CALL REDEFINE_KEYS */
Call charout ,CsrAttrib("Normal")
Call View_Refresh
Call Charout ,Locate(Scr_Bot,1)||BotScreen
/* main loop */
Do Forever
/* get valid input */
Do until WordPos(Word(Q,1),Valid_Input ) > 0 | datatype(Q,"N")
Call Charout ,TopScreen||D2C(13)||CsrAttrib("Reverse")||"Tagged:"Tag_Total||Locate(Scr_Bot,1)
Do until lines() = 0 /* this loop is for flushing Keyboard buffer */
Q = Linein()
call Charout,BotScreen||locate(scr_bot,1)
end
If length(Q) = 0 then
Q = "CR"
end
Parse Var Q Q Op
SELECT
When Q = "PU" then do /* Pgup */
ar_now = Ar_Now - ((Page_Len*2)+2)
Tag_Now = Ar_Now
If Tag_Now < 1 then
tag_Now = 1
Call View_Refresh
end
When Q = "PD" then do /* PgDn */
Tag_Now = Ar_Now
call view_refresh
If Tag_Now > Ar_Hi then
Tag_Now = Ar_Hi
end
When Q = "ES" | Q = "KL" then do /* Escape or Crsr-Left */
Q = 0
Leave
End
When Q = "TG" then
call tag_it
WHEN Q = "KU" then /* Crsr-Up */
Call Up_tag
WHEN Q = "KD" then do /* Crsr-Down */
IF Tag_now <= Ar_Hi then
CALL DOWN_TAG
end
When Q = "KE" then do /* Keyboard-END */
Ar_Now = Ar_Hi - Page_Len
Tag_Now = Ar_Now
If Tag_Now < 1 then
tag_Now = 1
Call View_Refresh
end
When Q = "UT" then do /* un-tag all, DEL */
Do I = 1 to Ar_Hi
Tag.I = " "
end /* do */
Do I = Dsp_Top to Dsp_Bot
Call Charout ,Locate(I,3)" "
end /* do */
Tag_Total = 0
End
When Q = "TA" then do /* Tag-All, INS */
Do I = 1 to Ar_Hi
Tag.I = "*"
end /* do */
Tag_Total = Ar_Hi
ar_now = Ar_Now - (Page_Len+2)
Call view_refresh
End
When Q = "KH" then do /* Keyboard-HOME */
Ar_Now = 1;Tag_Now = 1
call View_Refresh
end /* Do */
When Q = "Search:" then /* Search, Keyboard "/" */
Call Search_All
When Q = "Tag:" then do /* Tag by number, Keyboard "-" */
If Datatype(Op,"N") = 1 then do
If Op < (Ar_Hi+1) then do
Q = Tag.Op
Tag.Op = Toggle(Tag.Op,"*"," ")
If Q = " " then Tag_Total = Tag_Total + 1
else
Tag_Total = Tag_Total - 1
end
end
ar_now = Ar_Now - (Page_Len+2) /* redisplay screen, reflect tagged article */
call View_Refresh
End
When Q = "F1" then /* Help, Keyboard-F1 */
Call Help_view
When Q = "KR" then do /* Keyboard - Right */
Q = Tag_Now
Leave
end
WHEN Q = "CR" then do /* Keyboard enter */
Q = Tag_Now
If WORDPOS("CR",Valid_Input) > 0 then /* is it allowed? */
leave
end
When Datatype(Q,"N") = 1 then do /* Keyboard 0-99999... */
If Q < (Ar_Hi+1) & WORDPOS("NU",Valid_Input) > 0 then /* is it allowed? */
Leave
end /* Do */
Otherwise
end /* do */
End
return
/* refresh the display */
View_Refresh:
If Ar_Now > Ar_Hi then
Ar_Now = Ar_Hi
If Ar_Now < 1 then
Ar_Now = 1
DspVar_Lo = Ar_now
Tag_Now = Ar_Now
/* begin display of current page */
Do Scr_Pass = Dsp_top to Dsp_Bot
If Ar_Now > Ar_Hi then do
Ar_Now = Ar_Hi
Q = "Quiet"
end
If Ar_Now < 1 then
Ar_Now = 1
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")
If Q = "Quiet" then
Buffer = Locate(Scr_Pass,1)||D2C(27)"[K"
Ar_Now = Ar_Now + 1
Call Charout ,Buffer
end
TAG_POS = Dsp_Top
Call charout ,Locate(Tag_Pos,1)">"
DspVar_Hi = Ar_now - 1
Return
/* Cursor Up tag routine */
Up_Tag:
Old_Tag_Now = Tag_Now
Old_Tag_Pos = Tag_Pos
Tag_Now = Dec_Flip(Tag_now,DspVar_Lo,DspVar_Hi)
Tag_Pos = Dec_Flip(TAG_POS,Dsp_top,Dsp_Bot)
if Old_Tag_Now < tag_Now then do
ar_now = Ar_Now - ((Page_Len*2)+2);Tag_Now = Ar_Now
If Tag_Now < 1 then
tag_Now = 1
Call View_Refresh
End
Else
If Old_Tag_now > Tag_Now then do
Call Charout ,Locate(Old_Tag_Pos,1)" "
Call Charout ,Locate(Tag_Pos,1)">"
end
return
Down_Tag:
Old_Tag_Now = Tag_Now
Old_Tag_Pos = Tag_Pos
Tag_Now = Inc_Flip(Tag_Now,DspVAr_Hi,DspVar_lo)
Tag_Pos = Inc_Flip(TAG_POS,Dsp_Bot,Dsp_top)
if Old_Tag_Now > tag_Now then do
Old_Tag_Pos = Dsp_Top
Tag_Now = Ar_Now
call view_refresh
If Tag_Now > Ar_Hi then
Tag_Now = Ar_Hi
end
If Old_Tag_now < Tag_Now then do
Call Charout ,Locate(Old_Tag_Pos,1)" "
Call Charout ,Locate(Tag_Pos,1)">"
end
else
Tag_Pos = Old_Tag_Pos
return
Tag_It:
Tag.TAG_NOW = toggle(tag.Tag_NOW," ","*")
call charout ,Locate(Tag_Pos,3)||tag.Tag_Now
If Tag.Tag_Now = " " then
Tag_total = Dec_Flip(Tag_Total,0,0) /* decrement to 0 */
else
Tag_total = Inc_Flip(tag_total,Ar_Hi,Ar_Hi)
call Down_Tag
return
/* restore keys, Read search string, and redefine keys */
Search_All:
Call Restore_Keys
rc = charout(,D2C(27)"[27;'\^[]';13p") /* escape is cancel */
Call Charout ,CsrAttrib("Reverse")||Locate(Scr_Bot,1)"Search: "
Op = Linein()
Call Redefine_Keys
If POS("\^[]",Op) > 0 then Do /* pressed escape */
Call Charout ,BotScreen;return;end
Call Charout,Locate(Scr_Bot,1)"Searching for "Op" ..."
Do I = Tag_Now to Ar_Hi
Call Whistle
If Pos(Translate(OP),Translate(Value(DisplayArray".I"))) > 0 then do
Ar_Now = I
Tag_Now = I
Call Charout ,CsrAttrib("Normal")||CsrAttrib("Blink")
Call View_Refresh
call charout ,BotScreen||D2C(7)
Return
end /* Do */
end /* do */
Call Charout,Locate(Scr_Bot,1)CsrAttrib("reverse")||D2C(27)"[KString Not found"D2C(7)
return
/* 'Help system' uses a chapter and File variables */
Help_View:
H = CsrAttrib("High")||D2C(27)"[K"
L = CsrAttrib("Normal")
I = 0
/* Read up until Title */
Do Until lines(HelpText) =0 | I = HelpChapter
Buf = Linein(HelpText)
If Translate(Word(Buf,1)) = "TITLE" then Do
Parse Var Buf Buf Title
I = I + 1
end
end /* do */
I = 0
/* read in the help text */
Do until Lines(HelpText) = 0
Buf = Linein(HelpText)
Parse VAr Buf Key Text
If Translate(KEY) = "TITLE" then /* Leave if there is a next chapter */
Leave
If Left(Buf,1) = "#" then
Iterate
I = I + 1
If Left(Buf,1)<>" " then /* Highlight if line doesn't begin with a space */
HelpText.I = H" "Key" "L" "Text
Else
HelpText.I = " "Buf
end /* do */
Call Stream HelpText,"C","Close"
Max = I
helpBar = Locate(Screen_Top,1)||D2C(27)"[K"CsrAttrib("Reverse")Center(Title,80)CsrAttrib("Normal")
Say HelpBar
Do I = 1 to (Screen_Len - 2)
Say D2C(27)"[K"
end /* do */
H = 0
DO Forever
/* clear window */
Call Charout ,Locate(Screen_Top+1,1)
Do I = 1 to (Screen_Len - 1)
Say D2C(27)"[K"
end /* do */
Call Charout ,Locate(Screen_Top+1,1)
/* read all of it */
Do I = 1 to (Screen_Len-2)
H = H + 1
If H > Max then do
Max = 0
leave
end
Say HelpText.H
End
Call Charout ,Locate(Scr_bot,1)
Pull QHelp
If QHelp = "ES" | max = 0 then
leave
Call Charout ,Locate(Dsp_Top,1)
end /* do */
Call Charout ,TopScreen||BotScreen
/* update display */
Ar_Now = Ar_Now - (Page_Len +1)
Tag_Now = Ar_Now
Call View_Refresh
return
Toggle: Procedure
arg V, on, off
If V = on then
v = off
else
V = on
return V
Inc_Flip: Procedure
ARG V,MX,MN
V = V + 1
If V > Mx then V = Mn
return V
Dec_Flip: Procedure
ARG V,MN,MX
V = V - 1
If V < Mn then
V = MX
return V
/* display a rotating bar */
Whistle:
if Symbol("WhistleX") <> "VAR" then do
WhistleIcon.1 = "-"d2c(8)
WhistleIcon.2 = "\"d2c(8)
WhistleIcon.3 = "|"d2c(8)
WhistleIcon.4 = "/"d2c(8)
WhistleIcon.5 = "-"d2c(8)
WhistleIcon.6 = "\"d2c(8)
WhistleIcon.7 = "|"d2c(8)
WhistleIcon.8 = "/"d2c(8)
WhistleX = 0
WhistleY = 1
end
If WhistleX = 150 then do
Rc = Charout(,WhistleIcon.WhistleY)
WhistleY = WhistleY + 1
WhistleX = 0
If WhistleY > 8 then
WhistleY = 1
End
WhistleX = WhistleX + 1
return
/* Ansi Procedures for moving the cursor */
Locate: Procedure /* charout(,Locate(Row,Col)) */
Row = arg(1)
Col = Arg(2)
return D2C(27)"["Row";"col"H"
/* change screen attributes
attributes: NORMAL HIGH LOW ITALIC UNDERLINE BLINK RAPID REVERSE
BLINK Has been used to accent found key number
HIGH Has been used to accent Item number
Normal Has been used to accent the item itself
Reverse Has been used to define top & Bottom bars
You should be able to change the codes & define your own personal
color scheme.
*/
CsrAttrib: Procedure
Arg A
attr = "NORMAL HIGH LOW ITALIC UNDERLINE BLINK RAPID REVERSE"
return D2C(27)"["WORDPOS(A,ATTR) - 1";m"
/* Redefine keys using Ansi used so Pull doesn't require a CR at the end
This routina along with restore keys can be used to define the keyboard
to your own personal taste. Make sure to restore all keys you define
using restore keys though.
Format for Ansi redefine: esc[Keycode;"Redefinition"p
*/
Redefine_keys:procedure
ESC = D2C(27)
rc = charout(,esc"[0;72;'KU';13p") /* Keyboard Up */
rc = charout(,esc"[0;80;'KD';13p") /* Keyboard down */
rc = charout(,esc"[0;77;'KR';13p") /* Keyboard right */
rc = charout(,esc"[0;75;'KL';13p") /* Keyboard left */
rc = charout(,esc"[0;71;'KH';13p") /* Keyboard Home */
rc = charout(,esc"[0;79;'KE';13p") /* Keyboard End */
rc = charout(,esc"[0;59;'F1';13p") /* F1 */
rc = charout(,esc"[27;'ES';13p") /* Escape */
rc = charout(,esc"[0;73;'PU';13p") /* Page-up */
rc = charout(,esc"[0;81;'PD';13p") /* Page down */
rc = charout(,esc"[0;82;'TA';13p") /* Tag all, (Insert) */
rc = charout(,esc"[0;83;'UT';13p") /* Untag all, (Del) */
rc = charout(,esc"[42;'TG';13p") /* Tag item, "*" */
Rc = charout(,esc"['/';' Search: ';13p") /* Search key "/" */
Rc = charout(,esc"['-';' Tag: 'p") /* Tag item by number */
Rc = Charout(,esc"['y';'YYes';13p") /* append CR to Y/N for prompts */
Rc = Charout(,esc"['Y';'YYes';13p")
Rc = Charout(,esc"['n';'NNo';13p")
Rc = Charout(,esc"['N';'NNo';13p")
RETURN
/* reset keys to default values */
Restore_Keys: Procedure
ESC = D2C(27)
rc = charout(,esc"[0;72p")
rc = charout(,esc"[0;80p")
rc = charout(,esc"[0;77p")
rc = charout(,esc"[0;75p")
rc = charout(,esc"[0;71p")
rc = charout(,esc"[0;79p")
rc = charout(,esc"[0;59p")
rc = charout(,esc"[27p")
rc = charout(,esc"[0;73p")
rc = charout(,esc"[0;81p")
rc = charout(,esc"[0;82p")
rc = charout(,esc"[0;83p")
rc = charout(,esc"[42p")
Rc = charout(,esc"['/'p")
Rc = charout(,esc"['-'p")
Rc = Charout(,esc"['y'p")
Rc = Charout(,esc"['Y'p")
Rc = Charout(,esc"['n'p")
Rc = Charout(,esc"['N'p")
RETURN
/* Make sure screen is O.K., Restore keys, Close files, and exit */
ExitProc:
Call Charout ,CsrAttrib("NORMAL")
/* Put keyboard back to normal */
Call Restore_keys
Call Stream GroupFil,"c","close"
Call Stream SortFil,"c","close"
Exit