You could let ctl-arrow say which characters should be considered
printable.  I did this for emacs-18.58 with the patch below, see its
modified doc string.  It should be easy to do the same thing to v19;
search the code for regexp 'ctl.arrow' to find all places to fix.
[I only display char 0241 and up as printable, because 0240 is buggy
in some fonts, and little used because it's blank anyway.]


Hallvard.


diff -c2 emacs-18.58/src/buffer.c~ emacs-18.58/src/buffer.c
*** emacs-18.58/src/buffer.c~	Thu Feb 20 10:20:41 1992
--- emacs-18.58/src/buffer.c	Thu Feb 20 13:41:11 1992
***************
*** 1267,1273 ****
  
    DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow,
!     "*Non-nil means display control chars with uparrow.\n\
! Nil means use backslash and octal digits.\n\
! Automatically becomes local when set in any fashion.");
  
    DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines,
--- 1267,1275 ----
  
    DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow,
!     "*t means display control chars with uparrow.\n\
! Nil or 0 means use backslash and octal digits.\n\
! Otherwise assume that meta chars > \"\\240\" (M-SPACE) are printable.\n\
! If it is an integer, meta chars >= ctl-arrow are assumed to be printable.\n\
! Automatically becomes local when set in any fashion.");
  
    DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines,
diff -c2 emacs-18.58/src/buffer.h~ emacs-18.58/src/buffer.h
*** emacs-18.58/src/buffer.h~	Sat Jan  5 01:12:49 1991
--- emacs-18.58/src/buffer.h	Thu Feb 20 13:41:12 1992
***************
*** 269,270 ****
--- 269,275 ----
  
  extern void reset_buffer ();
+ 
+ /* Compute more convenient value from ctl-arrow object.      */
+ /* Remember to guard against users setting ctl-arrow < 0200. */
+ #define CTL_ARROW_CONV(obj) (NULL (obj) ? 0 : EQ (obj, Qt) ? 0400 : \
+ 			     XTYPE (obj) == Lisp_Int ? XINT (obj) : 0241)
diff -c2 emacs-18.58/src/indent.c~ emacs-18.58/src/indent.c
*** emacs-18.58/src/indent.c~	Thu Feb 20 10:20:46 1992
--- emacs-18.58/src/indent.c	Thu Feb 20 13:41:12 1992
***************
*** 79,83 ****
    register int post_tab;
    register int tab_width = XINT (current_buffer->tab_width);
!   int ctl_arrow = !NULL (current_buffer->ctl_arrow);
  
    if (point == last_known_column_point
--- 79,83 ----
    register int post_tab;
    register int tab_width = XINT (current_buffer->tab_width);
!   int ctl_arrow = CTL_ARROW_CONV (current_buffer->ctl_arrow);
  
    if (point == last_known_column_point
***************
*** 134,138 ****
  	}
        else
! 	col += (ctl_arrow && c < 0200) ? 2 : 4;
      }
  
--- 134,138 ----
  	}
        else
! 	col += ctl_arrow ? (c < 0200 ? 2 : c < ctl_arrow ? 4 : 1) : 4;
      }
  
***************
*** 298,302 ****
    register int end = ZV;
    register int tab_width = XINT (current_buffer->tab_width);
!   register int ctl_arrow = !NULL (current_buffer->ctl_arrow);
  
    Lisp_Object val;
--- 298,302 ----
    register int end = ZV;
    register int tab_width = XINT (current_buffer->tab_width);
!   register int ctl_arrow = CTL_ARROW_CONV (current_buffer->ctl_arrow);
  
    Lisp_Object val;
***************
*** 325,332 ****
  	  col = col / tab_width * tab_width;
  	}
!       else if (ctl_arrow && (c < 040 || c == 0177))
!         col++;
!       else if (c < 040 || c >= 0177)
!         col += 3;
      }
  
--- 325,332 ----
  	  col = col / tab_width * tab_width;
  	}
!       else if (c < 040 || c == 0177)
! 	col += ctl_arrow ? 1 : 3;
!       else if (c >= 0200 && !(ctl_arrow && c >= ctl_arrow))
! 	 col += 3;
      }
  
***************
*** 355,359 ****
    register int c;
    register int tab_width = XFASTINT (current_buffer->tab_width);
!   register int ctl_arrow = !NULL (current_buffer->ctl_arrow);
    int selective
      = XTYPE (current_buffer->selective_display) == Lisp_Int
--- 355,359 ----
    register int c;
    register int tab_width = XFASTINT (current_buffer->tab_width);
!   register int ctl_arrow = CTL_ARROW_CONV (current_buffer->ctl_arrow);
    int selective
      = XTYPE (current_buffer->selective_display) == Lisp_Int
***************
*** 430,434 ****
  	}
        else
! 	hpos += (ctl_arrow && c < 0200) ? 2 : 4;
  
        /* Handle right margin.  */
--- 430,434 ----
  	}
        else
! 	hpos += ctl_arrow ? (c < 0200 ? 2 : c < ctl_arrow ? 4 : 1) : 4;
  
        /* Handle right margin.  */
diff -c2 emacs-18.58/src/xdisp.c~ emacs-18.58/src/xdisp.c
*** emacs-18.58/src/xdisp.c~	Thu Feb 20 10:21:01 1992
--- emacs-18.58/src/xdisp.c	Thu Feb 20 13:41:13 1992
***************
*** 1265,1269 ****
    register unsigned char *p1prev;
    int tab_width = XINT (current_buffer->tab_width);
!   int ctl_arrow = !NULL (current_buffer->ctl_arrow);
    int width = XFASTINT (w->width) - 1
      - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
--- 1265,1269 ----
    register unsigned char *p1prev;
    int tab_width = XINT (current_buffer->tab_width);
!   int ctl_arrow = CTL_ARROW_CONV (current_buffer->ctl_arrow);
    int width = XFASTINT (w->width) - 1
      - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
***************
*** 1392,1395 ****
--- 1392,1401 ----
  	  p1++;
  	}
+       else if (ctl_arrow && c >= ctl_arrow)
+ 	{
+ 	  if (p1 >= startp)
+ 	    *p1 = c;
+ 	  p1++;
+ 	}
        else
  	{
***************
*** 1942,1945 ****
--- 1948,1952 ----
    unsigned char *p1start = new_screen->contents[vpos] + hpos;
    int window_width = XFASTINT (w->width);
+   int ctl_arrow = CTL_ARROW_CONV (buffer_defaults.ctl_arrow);
  
    if (tab_width <= 0 || tab_width > 20) tab_width = 8;
***************
*** 1977,1981 ****
  	  while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
  	}
!       else if (c < 0200 && buffer_defaults.ctl_arrow)
  	{
  	  if (p1 >= start)
--- 1984,1988 ----
  	  while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
  	}
!       else if (c < 0200 && ctl_arrow)
  	{
  	  if (p1 >= start)
***************
*** 1984,1987 ****
--- 1991,2000 ----
  	  if (p1 >= start && p1 < end)
  	    *p1 = c ^ 0100;
+ 	  p1++;
+ 	}
+       else if (ctl_arrow && c >= ctl_arrow)
+ 	{
+ 	  if (p1 >= start)
+ 	    *p1 = c;
  	  p1++;
  	}