123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- %
- % DISPCH.SL - Dispatch table utilities
- %
- % Author: William F. Galway
- % Symbolic Computation Group
- % Computer Science Dept.
- % University of Utah
- % Date: 25 July 1982
- % Copyright (c) 1982 University of Utah
- %
- % The dispatch table (determining "keyboard bindings") is the 256 element
- % vector "MainDispatch", AUGMENTED by association lists for C-X
- % (and possibly other prefix) characters. We actually use an association
- % list of association lists: the top level is a list of
- % (prefixchar . association-list), the second level is a list of
- % (character_to_follow_prefix_char . procedure). Associated with every
- % buffer is a list of forms to evaluate which will establish that buffer's
- % mode(s)--namely, the keyboard bindings that are in effect for that
- % buffer.
- % csp 7/7/82
- % - Put all dispatch list and mode functions together, and collected
- % some into this file from EMODE1.
- % - Modified EstablishCurrentMode to invoke DefinePrefixChars directly.
- % Generalized the idea of adding to a dispatch list with the function
- % AddToKeyList.
- % - Modified mode lists to EVAL entries rather than APPLYing functions
- % to NIL.
- % AS 7/12/82
- % - Added C-X D (Dired), C-X K (Kill Buffer), M-C-L (Previous BUffer)
- % commands to Basic Dispatch list.
- % - Separated out read-only text commands into ReadOnlyTextDispatchList.
- % AS 7/21/82
- % - Attached C-V and M-V to new scroll-window functions.
- % WFG 25 July 1982
- % - Dired stuff commented back out for now. ModeEstablishProcedures
- % renamed to be ModeEstablishExpressions.
- % AS 7/15/82
- % - Changed AddToKeyList to add the new definition at the end of the
- % list, so that it will override existing definitions.
- % - Added C-Q.
- % AS 8/2/82
- % - Revised $Iterate to use delayed prompting feature.
- % WFG 23 August 1982
- % - Changed AddToKeyList to call EstablishCurrentMode iff *EMODE is T.
- (FLUID
- '(
- MainDispatch % Dispatch table (vector), an entry for each key
- PrefixAssociationLists % Additional dispatch information for
- % prefixed characters.
- % List of declared prefix characters.
- PrefixCharacterList
- SelfInsertCharacter % Character being dispatched upon.
- last_operation % The "last" routine dispatched to (before the
- % "current operation").
- % List of expressions to be evaluated. Each expression is expected to
- % modify (add to?) the dispatch table.
- ModeEstablishExpressions
- FundamentalTextMode % See below
- ))
- % Create MainDispatch vector, 256 entries in all.
- (setf MainDispatch (MkVect 255))
- % List of valid prefix characters.
- (setf PrefixCharacterList NIL)
- % Add a new prefix character and associated prompt.
- (DE define_prefix_character (chr prompt-string)
- (setf PrefixCharacterList
- (cons (cons chr prompt-string) PrefixCharacterList)))
- % Set up initial list of valid prefix characters. Note that ESC (etc?)
- % aren't implemented as "prefix characters", (although, perhaps they should
- % be?) NOTE: there seems to be something wrong in that we're using this
- % general tool for only one prefix character. (Note that M-X is not a
- % prefix character.)
- (define_prefix_character (char (cntrl X)) "C-X ")
- % Generate a list of character codes, or a single character, from a list of
- % "character descriptors". Syntax is similar to that for the "Char"
- % macro.
- (DM CharSequence (chlist)
- (prog (processed-list)
- (setf processed-list
- (for (in chr-descriptor (cdr chlist))
- (collect (DoChar chr-descriptor))))
- % If there was a single character in the list, just return the
- % character code.
- (return
- (cond
- % Just return the character code if a single character.
- ((equal (length processed-list) 1)
- (car processed-list))
- % Otherwise, return the (quoted) list of character codes.
- (T
- `(quote ,processed-list))))))
- % Return T if character has meta bit set.
- (DS MetaP (chr)
- (GreaterP chr 127))
- % Convert character to meta-character.
- (DS MakeMeta (chr)
- (LOR chr 8#200))
- % Return character with meta bit "stripped off"--converts meta to normal char.
- (DS UnMeta (chr)
- (LAND chr 8#177))
- % This version of "UpperCaseP" also handles meta-characters.
- (DE X-UpperCaseP (chr)
- (cond
- ((MetaP chr)
- (UpperCaseP (UnMeta chr)))
- (T
- (UpperCaseP chr))))
- (DE X-Char-DownCase (chr)
- (cond
- ((MetaP chr)
- (MakeMeta (Char-DownCase (UnMeta chr))))
- (T
- (Char-DownCase chr))))
- % Set up a "clear" dispatch table.
- (DE ClearDispatch ()
- (progn
- (for (from i 0 255 1)
- (do (Undefine i)))
- (setf PrefixAssociationLists NIL)))
- % Set up the keyboard dispatch table for a character or "extended character".
- % If the character is uppercase, define the equivalent lower case character
- % also.
- (DE SetKey (xchar op)
- (cond
- ((NumberP xchar) % Add table entry for a simple character code.
- (progn
- (setf (indx MainDispatch xchar) op)
- (cond
- ((X-UpperCaseP xchar)
- (setf (indx MainDispatch (X-Char-DownCase xchar)) op)))))
- % If a valid prefixed character.
- ((and (PairP xchar) (Atsoc (car xchar) PrefixCharacterList))
- (prog (prefix-char assoc-entry)
- (setf prefix-char (car xchar))
- % Look up the prefix character in the a-list of a-lists.
- (setf assoc-entry (Atsoc prefix-char PrefixAssociationLists))
- % Add the prefix character if no entry present yet.
- (cond
- ((null assoc-entry)
- (setf PrefixAssociationLists
- (cons
- (setf assoc-entry (cons prefix-char NIL))
- PrefixAssociationLists))))
- % Now, add the prefixed character to the association list. Note
- % that in case of duplicate entries the last one added is the one
- % that counts. (Perhaps we should go to a little more work and
- % DelQIP any old entry?)
- (RPLACD assoc-entry
- % (cadr xchar) is the prefixed character.
- (cons (cons (cadr xchar) op) (cdr assoc-entry)))
- % Define the lower case version of the character, if relevent.
- (cond
- ((X-UpperCaseP (cadr xchar))
- (RPLACD assoc-entry
- (cons (cons
- (X-Char-DownCase (cadr xchar))
- op)
- (cdr assoc-entry)))))))
- % If we get here, SetKey was given a bad argument
- (T
- % (Use EMODEerror instead?)
- (Error 666 "Bad argument for SetKey"))))
- % Procedure to define a character as "self inserting".
- (DE MakeSelfInserting (chr)
- (SetKey chr 'InsertSelfCharacter))
- % Define a character so that it just "dings" bell.
- (DE Undefine (chr)
- (SetKey chr 'Ding))
- (FLUID '(new-oper))
- % Dispatch on next command character, "remember" the associated operation.
- (DE Dispatcher ()
- (progn
- (Dispatch (GetNextCommandCharacter))
- (setf last_operation new-oper)))
- % Dispatch on a character, "remember" the associated dispatch routine.
- (DE Dispatch (chr)
- (prog (oper)
- (setf oper (indx MainDispatch chr))
- (setf new-oper oper)
- (apply oper NIL)))
- % Read another character, and then perform appropriate operation from
- % appropriate prefix "table" (association list).
- (DE do-prefix ()
- (prog (prefix-entry char-entry chr)
- (setf prefix-entry (atsoc SelfInsertCharacter PrefixAssociationLists))
- (cond
- % "Complain" if no entry.
- ((null prefix-entry)
- (ding))
- % Otherwise, read a character and look up its entry.
- (T
- (setf chr
- (prompt_for_character
- % Prompt string for prefix
- (cdr (Atsoc SelfInsertCharacter PrefixCharacterList))))
- (setf char-entry (Atsoc chr prefix-entry))
- (cond
- ((null char-entry)
- (progn
- % Make note of the fact that we ding!
- (setf new-oper 'ding)
- (ding)))
- (T
- (apply (setf new-oper (cdr char-entry)) NIL)))))))
- % Treat next command character" as "Meta-character". (This routine is
- % normally invoked by the "escape" character.)
- (DE EscapeAsMeta ()
- (dispatch (LOR 8#200 (prompt_for_character "M-"))))
- % Treat the next character as a "control-meta-character". (This routine is
- % normally invoked by cntrl-Z.)
- (DE DoControlMeta ()
- (dispatch (LOR 8#200 (LAND 8#37 (prompt_for_character "M-C-")))))
- (FLUID '(pushed_back_characters))
- % Get command character, processing keyboard macros (someday! ), etc.
- % Parity mask is used to clear "parity bit" for those terminals that don't
- % have a meta key. It should be 8#177 in that case. Should be 8#377 for
- % terminals with a meta key. (Probably the wrong place to do this--if we
- % also expect to handle keyboard macros! )
- (DE GetNextCommandCharacter ()
- (cond
- % re-read any pushed back stuff.
- (pushed_back_characters
- (progn
- (setf SelfInsertCharacter (car pushed_back_characters))
- (setf pushed_back_characters (cdr pushed_back_characters))))
- (T
- (setf SelfInsertCharacter (Land parity_mask (PBIN))))))
- % "Push back" a character.
- (DE push_back (chr)
- (setf pushed_back_characters (cons chr pushed_back_characters)))
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Manipulating mode tables
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Set up dispatch table for current buffer, by evaluating the expressions
- % in ModeEstablishExpressions.
- (De EstablishCurrentMode ()
- (progn
- (ClearDispatch)
- % Use reverse so things on front of list are evaluated last. (So that
- % later incremental changes are added later.)
- (for (in x (reverse ModeEstablishExpressions))
- (do
- (cond
- ((pairp x) (eval x))
- (t
- (error 667
- (bldmsg
- "%r is not a valid ""mode establish expression"" (non-list)"))))))
- % csp 7/782
- % Prefix chars are totally global anyway, so let them be
- % established here, and let them override regular key defns.
- (DefinePrefixChars)))
- % This list of (character-sequence . operation) defines a partial set
- % of bindings for text mode (and other derived modes). This list
- % contains only commands that don't modify the buffer.
- (setf ReadOnlyTextDispatchList (list
- % These commands are read-only commands for text mode.
- (cons (char (cntrl @)) 'SetMark)
- (cons (char (cntrl A)) '$BeginningOfLine)
- (cons (char (cntrl B)) '$BackwardCharacter)
- (cons (char (cntrl E)) '$EndOfLine)
- (cons (char (cntrl F)) '$ForwardCharacter)
- (cons (char (cntrl N)) '$ForwardLine)
- (cons (char (cntrl P)) '$BackwardLine)
- (cons (char (cntrl R)) 'reverse_string_search)
- (cons (char (cntrl S)) 'forward_string_search)
- (cons (char (cntrl V)) 'scroll-window-up-page-command)
- (cons (char (meta (cntrl B))) 'backward_sexpr)
- (cons (char (meta (cntrl F))) 'forward_sexpr)
- (cons (char (meta B)) 'backward_word)
- (cons (char (meta F)) 'forward_word)
- (cons (char (meta V)) 'scroll-window-down-page-command)
- (cons (char (meta W)) 'copy_region)
- (cons (char (meta <)) '$BeginningOfBuffer)
- (cons (char (meta >)) '$EndOfBuffer)
- (cons (CharSequence (cntrl X) (cntrl X)) 'ExchangePointAndMark)
- % Note that these two would be nice to have for other "data modes" than
- % text. But current versions aren't generic enough.
- (cons (CharSequence (cntrl X) 1) 'OneWindow)
- (cons (CharSequence (cntrl X) 2) 'TwoRfaceWindows)
- ))
- % This list of (character-sequence . operation) defines bindings for text mode
- % (and other derived modes). TextDispatchList includes the initial contents of
- % ReadOnlyTextDispatchList (above). Be sure to put read-only commands on that
- % list!
- (setf TextDispatchList
- (append
- (list
- (cons (char !)) 'insert_matching_paren)
- (cons (char (cntrl D)) '$DeleteForwardCharacter)
- (cons (char (cntrl K)) 'kill_line)
- (cons (char (cntrl O)) 'OpenLine)
- (cons (char (cntrl Q)) 'InsertNextCharacter)
- (cons (char (cntrl T)) 'transpose_characters)
- (cons (char (cntrl W)) 'kill_region)
- (cons (char (cntrl Y)) 'insert_kill_buffer)
- (cons (char (meta (cntrl K))) 'kill_forward_sexpr)
- (cons (char (meta (cntrl RUBOUT))) 'kill_backward_sexpr)
- (cons (char (meta D)) 'kill_forward_word)
- (cons (char (meta Y)) 'unkill_previous)
- (cons (char (meta RUBOUT)) 'kill_backward_word)
- (cons (char DELETE) '$DeleteBackwardCharacter)
- (cons (char LF) '$CRLF)
- (cons (char CR) '$CRLF)
- (cons (char (meta !%)) 'Query-Replace-Command)
- (cons (CharSequence (cntrl X) (cntrl R)) 'CntrlXread)
- (cons (CharSequence (cntrl X) (cntrl S)) 'save_file)
- (cons (CharSequence (cntrl X) (cntrl W)) 'CntrlXwrite)
- )
- ReadOnlyTextDispatchList
- ))
- % Add the (chr opr) binding to a list with name listname.
- (de AddToKeyList (listname chr opr)
- (let*
- ((old-list (eval listname))
- (old-binding (atsoc chr old-list))
- (binding (cons chr opr)))
- (cond
- % If the binding isn't already in the a-list.
- ((null old-binding)
- % Add the new binding (Destructively to the end, so it's sure to
- % override any old stuff).
- (set listname (aconc old-list binding)))
- % Otherwise, replace the old operation in the binding.
- (T
- (setf (cdr old-binding) opr)))
- % Update the current mode if EMODE is running, in case it's affected by
- % the list we just modified.
- (cond
- (*EMODE
- (EstablishCurrentMode)))))
- % Add a new key binding to "text mode".
- (de SetTextKey (chr opr)
- (AddToKeyList 'TextDispatchList chr opr))
- % Add a new key binding to "Lisp mode".
- (de SetLispKey (chr opr)
- (AddToKeyList 'LispDispatchList chr opr))
- % Execute the expressions in this list to establish "Fundamental Text Mode".
- (setf FundamentalTextMode
- '((SetKeys TextDispatchList)
- (SetKeys BasicDispatchList)
- (NormalSelfInserts)))
- (de SetKeys (lis)
- (for (in x lis) (do (SetKey (car x) (cdr x)))))
- (de NormalSelfInserts ()
- (for (from i 32 126) (do (MakeSelfInserting i))))
- (setf BasicDispatchList
- (list
- (cons (char ESC) 'EscapeAsMeta)
- (cons (char (cntrl U)) '$Iterate)
- (cons (char (cntrl Z)) 'DoControlMeta)
- % NOT basic?
- (cons (CharSequence (cntrl X) (cntrl B)) 'PrintBufferNames)
- (cons (CharSequence (cntrl X) B) 'ChooseBuffer)
- %Dired stuff commented out for now.
- %? (cons (CharSequence (cntrl X) D) 'dired-command)
- % window-kill-buffer not implemented yet?
- %? (cons (CharSequence (cntrl X) K) 'window-kill-buffer)
- % "C-X N" switches to "next window" (or "other window" if in "two
- % window mode").
- (cons (CharSequence (cntrl X) N) 'next_window)
- % "C-X O" does the same as "C-X N"
- (cons (CharSequence (cntrl X) O) 'next_window)
- % "C-X P" moves to "previous window".
- (cons (CharSequence (cntrl X) P) 'previous_window_command)
- % C-X C-Z causes us to exit to monitor.
- (cons (CharSequence (cntrl X) (cntrl Z)) 'QUIT)
- % M-C-Z causes us to rebind the channels for "normal" I/O, and
- % leave EMODE.
- (cons (char (meta (cntrl Z))) 'OldFace)
- %Dired stuff commented out for now.
- %? (cons (char (meta (cntrl L))) 'SelectPreviousBuffer)
- (cons (char (cntrl L)) 'FullRefresh)
- % Two ways to invoke the help function.
- (cons (char (meta !/ )) '$HelpDispatch)
- (cons (char (meta !?)) '$HelpDispatch)
- (cons (CharSequence (cntrl X) (cntrl F)) 'find_file)
- (cons (CharSequence (cntrl X) (cntrl P)) 'WriteScreenPhoto)
- (cons (char (meta X)) 'execute_command)))
- % Define the prefix characters given in PrefixCharacterList.
- (de DefinePrefixChars ()
- (for (in prefix-entry PrefixCharacterList)
- (do
- % car gives character code for prefix.
- (SetKey (car prefix-entry) 'do-prefix))))
- % IS THE FOLLOWING REALLY APPROPRIATE TO DISPATCH?
- % Simulate EMACS's C-U, C-U meaning 4, C-U C-U meaning 16, etc., and C-U
- % <integer> meaning <integer>. This command suffers from the flaw of
- % simply iterating the following command, instead of giving it a
- % parameter. Thus, for example, C-U C-A won't do what you expect.
- % Written by Alan Snyder, HP labs.
- (fluid '(prompt-immediately prompt-was-output))
- % C-U handler.
- (de $iterate ()
- (let ((arg 1)
- (ch (char (control U)))
- (previous-ch nil)
- (prompt "")
- (prompt-immediately nil)
- )
- (while T
- (cond ((eqn ch (char (control U)))
- (if previous-ch (setq prompt (concat prompt " ")))
- (setq prompt (concat prompt "C-U"))
- (setq arg (times arg 4))
- )
- % Note check for non-meta character. (Since DigitP blows up
- % otherwise? Test may be obsolete??)
- ((and (LessP ch 128) (digitp ch))
- (if (and previous-ch (digitp previous-ch))
- (setq arg (plus (times arg 10) (char-digit ch)))
- % ELSE
- (setq arg (char-digit ch))
- (setq prompt (concat prompt " "))
- )
- (setq prompt (concat prompt (string ch)))
- )
- (t (exit)))
- (setq previous-ch ch)
- (setq ch (prompt_for_character prompt))
- (setq prompt-immediately prompt-was-output)
- )
- (for (from i 1 arg 1)
- (do (dispatch ch)
- % NOTE KLUDGE! Need to work this out better!
- (setf last_operation new-oper)))
- ))
- % Convert from character code to digit.
- (de char-digit (c)
- (cond ((digitp c) (difference (char-int c) (char-int (char 0))))))
|