home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
sprint
/
texmac.zip
/
GLOSS.SPM
< prev
next >
Wrap
Text File
|
1991-11-23
|
21KB
|
720 lines
; Copyright (c) 1988 Borland International. All Rights Reserved
;
; NAME: GLOSS.SPM
; VERSION: 1.01
; DESCRIPTION: Glossary Macro Package for Sprint
; LAST UPDATE: September 9, 1988, 6/19/91 RDT to ensure HOME dir is used right
; ALWAYS make sure QA is handled to look in HOME dir if it exists
; I did this by modifying GlossQDName and trying to always use it
; instead of QA itself
;
; NOTES: This file must be compiled and loaded AFTER CORE.SPM any other macro
; packages.
; Should probably merge in all the macrocoll stuff from nother,
; since it's more logical and useful to only use macro recording under
; the auspices of Glossary
;
; These macros use QB to hold a definition file, and QC to hold a string.
; The glossary function defaults to a glossary file called "standard.spg".
; The name is stored in QA. When a new glossary name is chosen, its name
; is placed in QA. It is the responsibility of the UI to insure that
; QA is initialized to the proper glossary name on Start-up.
; You should probably not use either one, or at least, if you use QC, set
; it to be empty when you're done. (At the expense of speed, you can do the
; same to QB.) If the glossary has been modified, you should really write
; it out (silently): "mark (to QB if modf (write QA))"
; when the user exits, without asking. Alternatively, the write can be done
; (or done with query) each time the glossary is actually modified. In order
; for this to work, the macros should not use QB for *anything* else, because
; a length-test is done to determine if the glossary file has been loaded.
;
; The glossary file has the following structure:
; char. 255
; Item name
; char. 255
; Hard newline (char. 10)
; Item text
; Hard newline
;
; The first character of the item text may be a '%'. In that case, it is a
; flag to indicate that the item text is to be executed as a MACRO, rather than
; pasting the item text into the file.
; Macros may have an optional comment at the end, as usually, the comment is
; separated from the text of the macro by a semicolon. This comment will appear
; as a description of the macro when using GlossList.
;
; An initial value of 254 for the expansion indicates it is a keyboard recording
; and should be pushed back.
; Keyboard recordings may have comments too, entered as a description when user
; ends the record. This description is separated from the the recording by 254
; character, and will appear in GlossList.
;
; Any other character as the first character in the item text is taken to be a
; literal character to be inserted.
; As you can see, this means that strings in the glossary are not allowed to
; contain character numbers 255/254, or start with a '%'. Names are restricted
; to be just tokens.
;
; These operations are available:
;
; GlossChange load new glossary file
; GlossDefine1 add new item, ask for name, expansion in clipboard
; GlossDefine2 add new item, name in QD, expansion in clipboard
; GlossDefineKey add recording in QF to glossary, ask for name
; GlossInsertText Insert glossary text from QC, reading ruler if present
; GlossLookup1 expand item, find name in text
; GlossLookup2 expand item, ask for name
; GlossLookup3 expand item, name in QD
; GlossLookup4 expand item, try from file, else prompt, ENTER = pick
; GlossDelete delete item, ask for name
; GlossRename rename item, ask for name, ask for new name
; GlossMakeList Display menu of items, return name in QC
; GlossPickList Display menu of items, expand picked item
; GlossQDName Take file name in QA, move to QD, prepending home dir
; GlossList list all items
; GlossErase erase all items
; GlossSave save all items if modified and length != 0
; GlossWrite always save all items
; GlossEnsure load all items
;
;----------------------------------------------
; Q register usage: see SP.SPM for table
;-------------------------------------------===
; NUMBERED MARK USAGE:
; see SP.SPM
;----------------------------------------------
; CONTENTS:
; SECTION: Routines whose definitions are to be removed.
; SECTION: Routines that MUST exist for the compiler to work
; SECTION: Variables -- all the variables are declared here
; SECTION: Forward declarations -- In order to keep the main list
; of macros in alphabetical order, a few of them have to be
; declared ahead of time -- like a FORWARD declaration
; in Pascal
; SECTION: Automatically-called macro definitions (Main, Init,
; EditKeys, MacroKeys, etc.)
; SECTION: General and command macros in alphabetical order
; SECTION: Menus (leaves first, root last)
; SECTION: Control and function keys
; -----------------------------------------------------------------
; Deletions
; -----------------------------------------------------------------
; Compiler-Required Definitions
; -----------------------------------------------------------------
; Variables
int GlossType
; -----------------------------------------------------------------
; Forward Declarations
GlossDefineRest :
GlossDefineStart :
GlossDeleteRest :
GlossFound :
GlossFoundMsg :
GlossGetName :
GlossInsertText :
GlossLookupRest :
GlossMakeList :
GlossPickList :
GlossPrep :
GlossQDName :
GlossSave :
TimeDate :
; -----------------------------------------------------------------
; Automatically-Called Macro Definitions
; -----------------------------------------------------------------
; General Macros
; Prompt for new glossary name, create one if name doesn't exist
GlossChange : ; RDT, changed
GlossSave ; save any existing glossary
set QB "" ; force a reread of new file
; set QD ""
GlossQDName ; put QA in QD and massage
message "\nGlossary to use: " set QD ; allow user to change QD/QA
if (!length QD) (set QD "*.spg") ; to force a list if no entry
set QD fchange "%.SPG" QD
13 QCap
if !(2 exist QD) {
1 Bell
message "\nCould not find `"
message QD
if (ask "'. Create it? ") {
set QB "" ; clear out anything that was in swap file
open QD
if !stopped (write "%")
(set QA QD) else (message "\nIllegal glossary name")
close
}
}
else (set QA QD) ; result should be pathed .SPG file in QA
; Get a name, and return T or F depending upon whether the name is in
; the glossary.
GlossCheckName :
GlossGetName
GlossFoundMsg
; Add a new name, asking the user for the name. If a region is
; selected, add that text. Otherwise, use what is in the clipboard.
GlossDefine1 :
GlossDefineStart
if (select = 1) {
copy togmark
Unselect
}
else if (select > 1)
(error "You cannot glossarize columns of text, only regions.")
message "\nEnter the name for this item: "
1->GlossType
GlossGetName
GlossDefineRest
; Add a new name. The new name is in QD and the expansion is in the
; clipboard.
GlossDefine2 :
GlossDefineStart
set QC QD
1->GlossType
GlossDefineRest
; Take the keyboard recording in QF and place it in the glossary.
; Ask for name, Check length of QF, give error if to long (> 1024 keys)
; Keyboard recording will be marked by having a first character byte value
; of 254 (feh).
GlossDefineKey :
if (length QF > 1024) error "Recording too long to play back."
else if (length QF==1) { ; user canceled immediately
message "\nRecording Canceled."
return
}
GlossDefineStart ; check exist QA, if recording was short enough...
message "\nEnter the name for this recording: "
GlossGetName
set QD "" message "\nDescription (Enter for none): "
set QD ; description in QD
mark {
to QF
254 insert ; mark item as recording
toend 254 insert insert QD ; add description
}
2->GlossType GlossDefineRest
; Do the rest of the work for GlossDefine*
GlossDefineRest :
if GlossFound {
message "\nDo you want to replace the existing `"
message QC
if (ask "'? ") GlossDeleteRest
else return
}
mark {
to QB
f toend
insert QC ; name between 255's
'^J' insert ; new line
if (GlossType = 2) insert QF ; keyboard recording: in QF
else undelete ; macro or text: in clipboard
'^J' insert ; new line
r (to current = 255) c ; go to start of expansion text
mark {
while (255 csearch) del ; sanitize the text to be glossarized
}
if current = '%' { ; if a macro, remove all NL's and Tabs
while ('^J' csearch) (32 -> current)
r to (current = 255) while ('^I' csearch) (32->current)
}
}
; Set up for GlossDefine*
GlossDefineStart : ; RDT, changed
; set Q0 "spedit.exe" NeedDisk
GlossQDName ; massage QA
if !(2 exist QD) {
1 Bell
message "\nCould not find `"
message QD
if (ask "'. Create it? ") {
; GlossQDName ; unnecessary now
open QD
write "%"
close
}
}
; Ask for a name and delete the glossary entry.
GlossDelete :
message "\nGlossary item to delete (Enter for list): "
if GlossCheckName {
GlossDeleteRest
if (!length QB) {
mark {
to QB
GlossQDName 1 write QD
}
}
draw
message "\nItem deleted."
}
; Delete the glossary entry contained in QC. The entry is known to exist.
GlossDeleteRest :
mark {
to QB
1 search QC
mark {
toeol
255 csearch
erase tomark
}
}
; Make sure that the glossary is loaded. If not, error out. Note
; that a zero-length glossary file will always be reread.
GlossEnsure : ; RDT, changed
; set Q0 "spedit.exe" NeedDisk
GlossQDName ; put QA in QD and massage
mark {
to QB
if (!length && !(2 read QD))
(error "Glossary file not found.")
}
; Erase the glossary.
GlossErase : ; remove gloss file
GlossEnsure
set QB ""
mark (to QB 0->modf)
GlossQDName
fdelete QD
; Prepare the name in QC and check whether it exists. Return T/F
GlossFound :
12 GlossPrep
GlossEnsure
mark (to QC while !isend ToLower) ; convert name to lowercase
mark {
to QB
if (1 search QC) 1
else 0
}
; Prepare the name in QC and check whether it exists. Return T/F and
; print a message if it doesn't.
GlossFoundMsg :
if !GlossFound {
message "\nNo glossary entry for `"
message QC
message "'."
1 Bell
0
}
else 1
; Ask the user for a name of an item and make sure that it is a legal
; name.
GlossGetName :
set QC ""
set QC ; get the name
mark {
to QC ; make sure it's a simple name
while ((f past istoken) && !isend) {
if stopped {
message "\nThat name is invalid. Please enter another: "
set QC ; hope this always works (setting itself inside qswitch!)
r toend
} abort
}
}
if !length QC { ; if QC empty get name from list
if stopped{
GlossMakeList ; force a name into QC
} abort
}
; Insert Glossary expansion. If it contained a ruler, read it.
GlossInsertText :
insert QC
mark(to QC '^K' csearch) ? (readruler refill)
; List all the glossary items. This is going to be put into a fixed
; file name in a buffer. We use QC for intermediate storage of the
; list because of the problem of getting back to where we were in QB
; if we were to switch into the file to copy the name each time.
GlossList :
GlossEnsure
status "\nBuilding glossary list..."
0->append
set Q0 fchange "%.SPR" QA ; under name
if 0 QWild 10 set Q0 flist Q0
if (buffind Q0 || open Q0) clear ; erase if needed
; 70->rightmargin 0->indent 15->leftmargin insertruler ; ensure proper alignment
insert "List for " insert QA insert " as of " TimeDate
insert "^J^JDefined Glossary Items^J"
insert "----------------------^J"
mark {
to QB
while (255 csearch) { ; find entry name
c copy (to (current = 255)) QC ; copy name in QC
toeol c ; to entry on next line
copy (to (current = 255) r c) QD ; put entry in QD
mark {to QD ; look at entry
if (current = '%') { ; this is a Sprint Macro
erase (to current =';') ; look for comment
del erase past iswhite ; go to text of comment
insert "MACRO: " } ; insert glossary type
if (current = 254) { ; this is a record
del erase to (current = 254)
del insert "RECORDING: " }
if (current = '^K') { ; this is a ruler line
del
insert "RULER: "
toeol c r del
}
else (r c) ; normal text
if (to isnl) (erase toend insert "...") ; too long...
buffind Q0 toend insert QC ; entry name
tosol ToUpper toeol ; Names in init caps
'^I' insert insert QD '^J' insert ; tab and expansion
}
}
}
; 0->modf ; allow quitting with no prompt
r toend ; Top of file.
; Pull word out from text, Return True if found, false if no entry
GlossLookupStart :
int GlossTmp
mark {
if isgray (r past iswhite) ; if between words, do prev
r past istoken
if inruler {
set QC ""
0->GlossTmp
}
else mark {
past istoken
copy tomark QC ; get the word
GlossFound->GlossTmp
if GlossTmp (erase tomark)
}
}
GlossTmp
; #1: Find the word just before the cursor, or the word
; that the cursor is in, and replace it with the glossary entry.
GlossLookup1 :
if GlossLookupStart GlossLookupRest
else {
if !length QC message "\nEntry not defined."
else {
message "\nNo glossary entry for `"
message QC
message "'."
}
1 Bell
}
; #2: Ask the user for the name and insert the expansion.
GlossLookup2 :
message "\nGlossary item to insert (Enter for list): "
if GlossCheckName GlossLookupRest
; #3: Use the name in QD and insert name and insert the expansion.
GlossLookup3 :
set QC QD
if GlossFoundMsg GlossLookupRest
; #4: Try #1, if not found, prompt, if user presses [ENTER] give list
GlossLookup4 :
if record (stopped error "Glossary not available while recording" return)
if GlossLookupStart GlossLookupRest ;try to expand from file
else { ; could not expand from file, so ask user
; message "\nGlossary item (Enter for list): "
; GlossGetName
GlossMakeList ; skip the user input and draw the list
if GlossFoundMsg GlossLookupRest
}
; used by GlossLookup*. This routine locates and inserts the expansion.
; if it's a macro, it executes it.
GlossLookupRest :
mark {
to QB ; contains the glossary
1 search QC ; the name is known to exist
toeol ; end of line name is on
f c ; next line: expansion
mark {
255 csearch ; find end of expansion
r c ; don't take 255
0->append ; don't add to QC (just in case)
copy tomark QC ; copy expansion to QC
}
}
mark {
to QC ; process this expansion
current case {
'%' del 1->GlossType, ; check if macro, and delete leading '%'
254 del 2->GlossType ; keyboard recording
if (254 csearch) (erase toend), ; get rid of description
$ 0->GlossType ; plain text
}
}
GlossType case { ; case must do stuff outside of QC
1 if ((length QC) < 512) {
set QG QC ; put it in Q for MacroExecute again, I spose this is dumb
macro QC
}
else error "Macro too long", ; execute the macro
2 mark(to QC copy toend QF) keypushback QC, ; push back the keyboard recording, and place into QF too for macro iterate, RDT
$ GlossInsertText ; insert text
}
; Display menu, return the chosen name in QC
GlossMakeList :
GlossEnsure ; force load of glossary
if !(length QB) (error "No entries are defined")
0->append
set QC "" ; clear QC to receive list
mark {
to QB
while (255 csearch) { ; find entries
c ; jump 255
copy (to (current = 255)) QD ; copy entry in scratch Qreg
mark (to QC toend ; go to end of QC in imenu format:
insert "^I\""
insert QD insert "\",^J") ; tab, entry between quotes,
toeol c ; to return value, comma new line
to current = 255 ; skip expansion
}
to QC
insert "imenu \"Glossary Items\" {" ; build menu
toend r (del del) insert "$}" ; delete last new line and comma
}
if ((length QC) < 1024) {
status "\n"
macro QC ; display menu to choose from
set QC Q0 ; glossary to expand in QC
}
else error "Too many entries for menu"
; Merge two glossary files together.
; QA contains name of glossary to add items to.
; system will prompt for name of glossary to add to it.
GlossMerge : ; RDT, changed
GlossEnsure
set QD home ;"" ; put home in to suggest correct location
mark { to QD toend insert "*.SPG" } ; append extension
message "\nGlossary to merge with '" QA "': " ; current gloss
set QD
if (!length QD) (set QD "*.spg") ; to force a list if no entry
set QD fchange "%.SPG" QD ; name is in QD
if !(2 exist QD) {
stopped error "Glossary file not found"
return
}
if stopped {
2 open QD draw ; open glossary to be merged
while (255 csearch) {
c ; skip the 255
copy (to current = 255) QC ; name in QC
while GlossFound { ; item was found so allow user to decide outcome
set Q0 QC
mark(to Q0 del insert "DUPLICATE ITEM: " toend r del)
menu Q0 {
"Replace existing definition" 0,
"Add under new name" 1,
"Don't merge (skip)" 2
}
case {
0 GlossDeleteRest, ; erase existing definition
1 message "\nNew name for " QC ": " GlossGetName, ; get a new name
2 set QC "" break
}
} ; end while
toeol c
if length QC { ; if we are adding a definition
copy (to current = 255 r c ) ; leave off end of record
GlossDefineRest ; name in QC, expansion in kills buffer
}
}
close ; put away glossary
}
close
GlossPickList : ; display a menu, let user pick from it
status "\nBuilding glossary menu..."
GlossMakeList
GlossLookupRest
; Prepare the name by inserting 255s. The argument is the Q register
; number.
GlossPrep :
mark {
qswitch
if current != 255 { ; if not prepared already....
255 insert
f toend
255 insert
}
}
; Make path name for Glossary file name in QD
GlossQDName :
set QD QA ; get stored gloss file name in scratch QD
set Q0 home ; put home into Q0 for test and massage
0 QCap ; cap home
if (length Q0) { ; if there's a home env. var. massage QD
mark { to Q0 ; go into Q0
if !(3 search "[/\\\\:]") { ; if there're no slashes or it's not a drive
toend insert '\\' } ; put in a slash at the right end
}; end Q0 mark
mark { to QD ; Now go into the QD register
if !(3 search "[/\\\\:]") { ; if there're no slashes in QA/QD, it's not a pathed name
r toend ; get in front of QA
insert Q0 ; which should be empty or contain HOME Env var
; if empty, current dir. is default
}
} ; end QD mark
} ; result of all this should be QD containing massaged version of QA, the current gloss file name
; Rename an existing glossary item. Ask the user for an item name,
; make sure that it exists, ask for another name, and make sure that it
; *doesn't* exist, and then do the rename operation.
GlossRename :
message "\nGlossary item to be renamed (Enter for list): "
if !GlossCheckName return
set QD QC ; save the first name; we'll need it again
message "\nRename '"
message QD
message "' to be: "
GlossGetName
if GlossFound {
message "\nThe new name `"
message QC
message "' already exists."
1 Bell
return
}
else {
mark {
to QB
1 search QD
replace found QC
}
message "\nItem renamed."
}
; Save the glossary if it is modified and has a nonzero length.
GlossSave :
mark {
to QB
if (length && modf) {
message "\nSave changes to glossary file '" QA "'"
if ask "(Y,N,ESC)?" {
; set Q0 "spedit.exe" NeedDisk
GlossQDName 1 write QD
}
}
}
; Always write the glossary.
GlossWrite :
; set Q0 "spedit.exe" NeedDisk
GlossQDName
mark (to QB write QD)
; -----------------------------------------------------------------
; Menus
;GlossMenu :
; menu "Glossary" {
; "Expand item from file" GlossLookup1,
; "Insert item by name" GlossLookup2,
; "Pick item from menu" GlossPickList,
; "Define item" GlossDefine1,
; "Rename item" GlossRename,
; "List items" GlossList,
; "delete item" GlossDelete,
; "Save glossary file" GlossSave
; }
KeyAssignGloss :
do {
status "\nTo which key should the glossary item be assigned: "
KeyGet->x if (x = '^[') abort
if (x KeyCanAssign) {
status "\nBuilding glossary menu"
GlossMakeList ; get the name in QC
set QD ""
mark {
to QD ; build assign command in QD
"set QD \""
insert QC ; name
insert "\" glosslookup3"
}
x macro QD ; and bind it.
break
}
else KeyAssignError
}
KeyRecordEnd : ; end keyboard recording and insert keys in Glossary
if record { MacroCollEnd
GlossDefineKey
} ; see keyrecordgloss
KeyRecordGloss : ; Start recording keys for glossary
mode "Keyboard recording on. Use Alt-) to end recording."
MacroCollBegin
F1A9H : KeyRecordEnd ; Alt-)