[comp.emacs] ^Q & ^S Gnu problem: Summary

creps@silver.bacs.indiana.edu (11/23/87)

   Sorry I'm so late getting this posted, but I've had hundreds of things
to do the past few weeks. I didn't reply to individual requests for the
^Q ^S flow control problems because I had so many requests, I decided to
post the solutions.
-	-	-	-	-	-	-	-	-
Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
	creps@silver.bacs.indiana.edu
"F-14 Tomcat! There IS no substitute."

-	-	-	-	-	-	-	-	-	-

   This is a summary of how to correct the Gnu Emacs flow control problem.
The most popular method seems to be binding ^Q and ^S to do nothing at all,
and putting Gnu into cbreak mode.
Steps:
   1. (set-input-mode nil t)
	This puts Emacs into cbreak mode so that ^Q and ^S aren't
	interpreted as commands.
   2. Rebind ^Q and ^S to do nothing.
      (global-set-key "\C-S" 'ignore)
      (global-set-key "\C-Q" 'ignore)
   3. Bind two unused sequences to handle what ^Q and ^S were supposed
      to do.
      (global-set-key "??? (a key sequence)" 'quote-char)
      (global-set-key "??? (a key sequence)" 'isearch-forward)
      ... (any other key sequences containing ^Q & ^S)

Below are specific solutions I received via email. I've edited them for
brevity:


from Tony Brancato:
;; Create 'enable-flow-control' command which disables C-s, C-q characters
(defun null-command (&rest a)
  "This command does absolutely nothing.   Nice for flow-control."
  (interactive "P"))

(defun enable-flow-control (&rest a)
  "This command forces gnu-emacs to use the cretinous ^S/^Q flow
control protocol.  It rebinds C-s and C-q to 'null-command', and 
C-] to 'isearch-forward'.  Use this command when you use gnu-emacs
from a terminal using ^S/^Q flow control (e.g., any DCA terminal).
Beware, however, that C-x C-s will no longer work, nor will any 
other command bound to a key sequence with C-s or C-q in it.  You
may wish to rebind those commands using the global-set-key function."
  (interactive "P")
  ;; use cbreak mode and ^S/^Q for flow control
  (set-input-mode nil t)
  (global-set-key "\C-s" 'null-command)
  (global-set-key "\C-q" 'null-command)
  (setq search-repeat-char 29)
  (global-set-key "\C-]" 'isearch-forward))

(enable-flow-control)

-	-	-	-	-	-	-	-	-

from David W. Talmage:
;;; Following is bletcherous kludge stolen from bobcat.el, mutated
;;; to replace ^S/^Q with something more friendly, specifically
;;; ^\/^^

(defun evade-flow-control ()
  "Replace ^S with ^\ and ^Q with ^^."
  (interactive)
  (let ((the-table (make-string 128 0)))
    (let ((i 0))
      (while (< i 128)
        (aset the-table i i)
        (setq i (1+ i))))
    ;; Swap ^S and ^\
    (aset the-table ?\034 ?\^s)
    (aset the-table ?\^s ?\034)
    ;; Swap ^Q and ^^
    (aset the-table ?\036 ?\^q)
    (aset the-table ?\^q ?\036)
    (setq flow-control-evasion t)
    (setq keyboard-translate-table the-table)))

;;; Following undoes the bletcherous kludge and retruns ^S/^Q to their normal
;;; state.  We could just set keyboard-translate-table to nil, but will do
;;; things the hard way to avoid breaking translate tables used by
;;; individual lusers.

(defun unevade-flow-control ()
  "Return ^S and ^Q to their normal mappings."
  (interactive)
  (cond ((null flow-control-evasion) nil)
        (t ;;; Swap back ^S
         (aset keyboard-translate-table ?\034 ?\034)
         (aset keyboard-translate-table ?\^s ?\^s)
         ;; Swap ^Q and ^^
         (aset keyboard-translate-table ?\036 ?\036)
         (aset keyboard-translate-table ?\^q ?\^q)
         (setq flow-control-evasion nil))))

;;; Following are desirable initializations for all users at Villanova
;;; (load-library "meese")
(evade-flow-control)

-	-	-	-	-	-	-	-	-

from Tom Ekberg (I tried it with \C- instead of ^):
(global-set-key "^S" 'ignore)
(global-set-key "^Q" 'ignore)

-	-	-	-	-	-	-	-	-

from John Robinson:
(set-input-mode nil t)
in youur .emacs.  This makes emacs run in CBREAK mode.  ^S and ^Q will
never make it to emacs, so you'll have to get to the functions bound
there (isearch and quote-char) some other way.  The trouble is that
incremental-search wants to interpret ^S internally and there is no
way to rebind this character; however, you can set
keyboard-translate-table to use ^\ and ^^ in their place.

Documentation on set-input-mode:

 set-input-mode:
 Set mode of reading keyboard input.
 First arg non-nil means use input interrupts; nil means use CBREAK mode.
 Second arg non-nil means use ^S/^Q flow control for output to terminal
  (no effect except in CBREAK mode).

Documentation on keyboard-translate-table:

 keyboard-translate-table's value is nil

 Documentation:
 String used as translate table for keyboard input, or nil.
 Each character is looked up in this string and the contents used instead.
 If string is of length N, character codes N and up are untranslated.

-	-	-	-	-	-	-	-	-

from Jack Repenning:
;; Make the identity translation table, if necessary.
(if (not keyboard-translate-table)
    (progn (setq keyboard-translate-table (make-string 128 0))
	   (let ((i 0))
	     (while (< i 128)
	       (aset keyboard-translate-table i i)
	       (setq i (1+ i))))))

(defvar xon-xoff-mode nil
  "Controls the xon-xoff mode.
If this variable is nil, xon-xoff-mode is off.")
       
(defun xon-xoff-mode (arg)
  "Xon-xoff mode's good if you want too use ^s and ^q for flow-control.
Turns Xon-xoff mode on if ARG > 0, off if ARG < 0.
With ARG = 0, Xon-xoff-mode toggles.
Interactively:
	no prefix, or prefix = 0:	Toggle
	prefix > 0:			Turn Xon-Xoff on
	prefix < 0:			Turn Xon-Xoff off
If Xon-xoff-mode is on, all ^^ typed by the user will be translated to ^q
before they are interpreted in any way. Likewise ^\ will be translated to ^s.
If the options C-Q-Replacement and C-S-Replacement are set, there values will
be used instead of ^^ and ^\. ^q and ^s will be used for flow-control in
xon-xoff-mode.
"
  (interactive "p")

  (if (not current-prefix-arg) (setq arg 0))

  (setq xon-xoff-mode
	(if (and (zerop arg) (boundp xon-xoff-mode))
	    (not xon-xoff-mode)
	  (> arg 0)))

  (set-input-mode nil xon-xoff-mode)

  (if xon-xoff-mode
      (progn (aset keyboard-translate-table
		   (if (boundp 'C-S-Replacement)
		       C-S-Replacement
		     ?\^\\)
		   ?\^s)
	     (aset keyboard-translate-table 
		   (if (boundp 'C-Q-Replacement)
		       C-Q-Replacement
		     ?\^^)
		   ?\^q))

    (aset keyboard-translate-table ?\^s ?\^s)
    (aset keyboard-translate-table ?\^q ?\^q)))

;; (xon-xoff-mode 1)

-	-	-	-	-	-	-	-	-

from John P. Nelson:
To enable normal flow control operation, enter the command:

(set-input-mode nil t)

To remap the control keys, you can use the "keyboard translate-table"
facility.  This is what we use:

(setq keyboard-translate-table (concat (char-to-string 0)
				       (char-to-string 1)
				       (char-to-string 2)
				       (char-to-string 3)
				       (char-to-string 4)
				       (char-to-string 5)  
				       (char-to-string 6)
				       (char-to-string 7)
				       (char-to-string 8)
				       (char-to-string 9)
				       (char-to-string 10)
				       (char-to-string 11)
				       (char-to-string 12)
				       (char-to-string 13)
				       (char-to-string 14)
				       (char-to-string 15)
				       (char-to-string 16)
				       (char-to-string 17)
				       (char-to-string 18)
				       (char-to-string 19)
				       (char-to-string 20)
				       (char-to-string 21)
				       (char-to-string 22)
				       (char-to-string 23)
				       (char-to-string 24)
				       (char-to-string 25)
				       (char-to-string 26)
				       (char-to-string 27)
				       (char-to-string 19)
				       (char-to-string 29)
				       (char-to-string 17)))

-	-	-	-	-	-	-	-	-

from Joe Ramey:
;; Turn on CBREAK and flow control
(set-input-mode nil t)
;; Make a translate table that does the identity translation.
(setq keyboard-translate-table (make-string 128 0))
(let ((i 0))
  (while (< i 128)
    (aset keyboard-translate-table i i)
    (setq i (1+ i))))
;; Now alter translations of some characters.
(aset keyboard-translate-table ?\^\\ ?\^s)
(aset keyboard-translate-table ?\^^ ?\^q)

-	-	-	-	-	-	-	-	-

from Mike Dove:
;;;
;;; bindings so I can use flow control because of stupid w60's in 43 lines
;;;
(set-input-mode nil t)
(global-set-key "\eq" 'quoted-insert)
(global-set-key "\C-\\" 'isearch-forward)
(global-set-key "\e\C-\\" 'isearch-forward-regexp)
(global-set-key "\e\C-r" 'isearch-backward-regexp)
(global-set-key "\C-xs" 'save-buffer)
(global-set-key "\es" 'save-some-buffers)

-	-	-	-	-	-	-	-	-

from Claude Laferriere:
	What we did was to disable the sending of flow control
by the terminals.  You can do that in the setup for a VT2220 and VT100
series terminals as well.  Note that, usually, this does not create a
problem since the ^S is sent by the terminal when the buffer is at the
high water mark, with still some space left in it.  For that reason,
disabling the sending of ^S simply means that the buffer gets filled
up to a fuller level than before but, because of the extra room left
in it, it does not matter.

-	-	-	-	-	-	-	-	-

from Doug Tiarks:
(set-input-mode nil t)

weltyc@nysernic.UUCP (11/24/87)

In article <20600011@silver> creps@silver.bacs.indiana.edu writes:
>
>   Sorry I'm so late getting this posted, but I've had hundreds of things
>to do the past few weeks. I didn't reply to individual requests for the
>^Q ^S flow control problems because I had so many requests, I decided to
>post the solutions.
>-	-	-	-	-	-	-	-	-
>      (global-set-key "\C-S" 'ignore)
>      (global-set-key "\C-Q" 'ignore)

	This has probably already been discussed, so if it has I
really don't want to fan the flames on this whole ^s/^q question.  I
usually ignore the postings about it, but something about this posting
caught my eye.  i noticed that most people wanted to bind ^S and ^Q to
functions that dont do anything.  The only reason I am posting this is
in case there was an oversight!  Any reason why you didn't just:
(global-unset-key "\c-s")
(global-unset-key "\c-q")

	Once again, if this has been mulled over already then don't
even bother responding, I really don't care, I just thought that maybe
someone hadn't realized that you could unbind a keystroke.  Of course,
you have to unbind it in all the local maps, too - but doing a global
set-key wouldn't fix that either....


Christopher Welty  ---  Asst. Director, RPI CS Labs
weltyc@cs.rpi.edu       ...!rutgers!nysernic!weltyc