[alt.sources.patches] Changes to X11 and Gnu Emacs to support attribute on region gnu.emacs

handa@etl.go.jp (Kenichi Handa) (12/22/89)

Archive-name: emacs-attribute/handa
Original-posting-by: handa@etl.go.jp (Kenichi Handa)
Original-subject: attribute on region
Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)

[This is a patch to  from gnu.emacs.]


A few weeks ago, I posted the followings:

>   I have modified buffer.[ch], dispextern.h, dispnew.h,
>   xdisp.c, x11term.h and wrote attribute.el for setting
>   character attributes between two markers.
>   If there's many requests,  I'll post the patches.

and have gotten about 20 requests by now.  I think it's
enough for posting the patches in this news group.  Here it
is.

---
Ken'ichi HANDA

PS. Send me bug reports.  Any comments are welcome.  Please
correct my poor-English document :-).

==================================================================
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README
#	  diffs
#	  attribute.el
#	  attribute.el.nemacs
#	  COPYING
#
sed 's/^X//' << 'SHAR_EOF' > README &&
XRemarks on attribute package
XWritten by K.Handa, Electrotechnical Lab., (handa@etl.go.jp), 1989
X
XThis package is for setting character attribute for GNU
XEmacs under X window environment.  Currently supported
Xattributes are underline and inverse.
X
X
XCOPYRIGHT NOTICE
X
X   This program is distributed under the terms of the GNU
X   EMACS GENERAL PUBLIC LICENSE which is distributed along
X   with GNU Emacs by the Free Software Foundation.
X
X   This program is distributed in the hope that it will be
X   useful, but WITHOUT ANY WARRANTY; without even the
X   implied warranty of MERCHANTABILITY or FITNESS FOR A
X   PARTICULAR PURPOSE.  See the GNU EMACS GENERAL PUBLIC
X   LICENSE for more details.
X
X   You should have received a copy of the GNU EMACS GENERAL
X   PUBLIC LICENSE along with this file; see the file
X   COPYING.  If not, write to the Free Software Foundation,
X   675 Mass Ave, Cambridge, MA 02139, USA.
X
X
XFILES
X
X   README -- this file
X   COPYING -- GNU EMACS GENERAL PUBLIC LICENSE 
X   diffs -- patch file for GNU Emacs 18.55
X   attribute.el -- user interface written in Emacslisp
X   attribute.el.nemacs -- same as above but for Nemacs
X
X
XINSTALLATION for GNU Emacs
X
X   1) Apply the patch file 'diffs' to source code of GNU
X   Emacs 18.55 and install Emacs again.
X
X   2) Copy attribute.el into a scope of 'load-path' variable
X   of Emacs.
X
X   3) byte-compile-file attribute.el at your option.
X
X
XINSTALLATION for Nemacs
X
X   1) Copy attribute.el.nemacs into a scope of 'load-path'
X   variable of Nemacs and rename it to attribute.el.
X
X   2) byte-compile-file attribute.el at your option.
X
X
XATTENTION
X
X   1) This package works only when you run emacs as a client
X   of X.
X
X   2) Source code of Nemacs (Japanese version of GNU Emacs)
X   has already been applied the patch.  In addition, Nemacs
X   is equipped with point-type-marker (See info of Nemacs).
X   'attribute.el.nemacs' uses markers of this type to
X   indicate end boundary of attribute, which makes it easier
X   to modify (i.e. deleting or inserting text) attributed
X   region.
X
X   3) I have had very short time for testing this package.
X   Please send bug reports and suggestions to
X   handa@etl.go.jp.
SHAR_EOF
chmod 0666 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > diffs &&
Xdiff -arcN emacs-18.55/src/buffer.c emacs-18.55-with-attr/src/buffer.c
X*** emacs-18.55/src/buffer.c	Mon Aug 28 19:14:32 1989
X--- emacs-18.55-with-attr/src/buffer.c	Thu Dec  7 14:09:19 1989
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* 89.11.24 modified for attribute of characters by K.Handa */
X+ 
X  /* Buffer manipulation primitives for GNU Emacs.
X     Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
X  
X***************
X*** 239,244 ****
X--- 241,250 ----
X    b->auto_save_modified = 0;
X    b->auto_save_file_name = Qnil;
X    b->read_only = Qnil;
X+ /* patch for attribute of characters by K.Handa 89.11.21 */
X+   b->underlined_region = Qnil;
X+   b->inversed_region = Qnil;
X+ /* end of patch */
X    reset_buffer_local_variables(b);
X  }
X  
X***************
X*** 1122,1127 ****
X--- 1128,1137 ----
X    XFASTINT (buffer_local_flags.read_only) = -1;
X    XFASTINT (buffer_local_flags.major_mode) = -1;
X    XFASTINT (buffer_local_flags.mode_name) = -1;
X+ /* patch for attribute of characters by K.Handa 89.11.21 */
X+   XFASTINT (buffer_local_flags.underlined_region) = -1;
X+   XFASTINT (buffer_local_flags.inversed_region) = -1;
X+ /* end of patch */
X    
X    XFASTINT (buffer_local_flags.mode_line_format) = 1;
X    XFASTINT (buffer_local_flags.abbrev_mode) = 2;
X***************
X*** 1309,1314 ****
X--- 1319,1338 ----
X  Note that this is overridden by the variable\n\
X  truncate-partial-width-windows if that variable is non-nil\n\
X  and this buffer is not full-screen width.");
X+ 
X+ /* patch for attribute of characters by K.Handa 89.11.21 */
X+   DEFVAR_PER_BUFFER ("underlined-region", &bf_cur->underlined_region,
X+     "*Underlined region of current buffer.  Should be a list of\n\
X+ LENGTH and several numbers of MARKER_i, where MARKER_i indicates\n\
X+ underline starting point if 'i' is even and underline ending point\n\
X+ if 'i' is odd.  LENGTH is a length of this list.");
X+ 
X+   DEFVAR_PER_BUFFER ("inversed-region", &bf_cur->inversed_region,
X+     "*Inversed region of current buffer.  Should be a list of\n\
X+ LENGTH and several numbers of MARKER_i, where MARKER_i indicates\n\
X+ inverse starting point if 'i' is even and inverse ending point\n\
X+ if 'i' is odd.  LENGTH is a length of this list.");
X+ /* end of patch */
X  
X    DEFVAR_PER_BUFFER ("default-directory", &bf_cur->directory,
X      "Name of default directory of current buffer.  Should end with slash.");
Xdiff -arcN emacs-18.55/src/buffer.h emacs-18.55-with-attr/src/buffer.h
X*** emacs-18.55/src/buffer.h	Mon Aug 28 15:05:15 1989
X--- emacs-18.55-with-attr/src/buffer.h	Thu Dec  7 14:06:23 1989
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* 89.11.21 modified for attribute of characters by K.Handa */
X+ 
X  /* Header file for the buffer manipulation primitives.
X     Copyright (C) 1985, 1986 Free Software Foundation, Inc.
X  
X***************
X*** 153,158 ****
X--- 155,164 ----
X      Lisp_Object overwrite_mode;
X      /* non-nil means abbrev mode is on.  Expand abbrevs automatically. */
X      Lisp_Object abbrev_mode;
X+ /* patch for attribute of characters by K.Handa 89.11.21 */
X+     Lisp_Object underlined_region;
X+     Lisp_Object inversed_region;
X+ /* end of patch */
X  };
X  
X  extern struct buffer *bf_cur;		/* points to the current buffer */
Xdiff -arcN emacs-18.55/src/dispextern.h emacs-18.55-with-attr/src/dispextern.h
X*** emacs-18.55/src/dispextern.h	Mon Aug 28 15:05:33 1989
X--- emacs-18.55-with-attr/src/dispextern.h	Thu Dec  7 13:50:44 1989
X***************
X*** 1,3 ****
X--- 1,6 ----
X+ /* 89.11.24 modified for attribute of characters by K.Handa */
X+ /* Currently supported attributes are underline and inverse. */
X+ 
X  /* Interface definitions for display code.
X     Copyright (C) 1985 Free Software Foundation, Inc.
X  
X***************
X*** 61,66 ****
X--- 64,71 ----
X      struct display_line *next;	/* Chain for free lines. */
X      short   length;		/* the number of valid characters in body */
X      char    highlighted;	/* 1 means write this line in standout mode */
X+ /* patch for attribute by K.Handa  89.11.21 */
X+     char    attribute[MScreenWidth + 4]; /* attribute of each character */
X      char    physical;		/* Mark bit for gc'ing, in update_screen */
X      char    body[MScreenWidth + 4];	/* the actual text of the line */
X  };
X***************
X*** 69,71 ****
X--- 74,82 ----
X   to start output in it at `hpos' (origin 0, may be negative) */
X  
X  struct display_line *get_display_line (), *new_display_line ();
X+ 
X+ /* patch for attribute by K.Handa  89.11.21 */
X+ #define ATTR_UNDERLINE	1
X+ #define ATTR_INVERSE	2
X+ extern char *attribute_p;	/* oops! */
X+ /* end of patch */
Xdiff -arcN emacs-18.55/src/dispnew.c emacs-18.55-with-attr/src/dispnew.c
X*** emacs-18.55/src/dispnew.c	Mon Aug 28 19:14:34 1989
X--- emacs-18.55-with-attr/src/dispnew.c	Thu Dec  7 15:20:41 1989
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* 89.11.24 modified for attribute of characters by K.Handa */
X+ 
X  /* Newly written part of redisplay code.
X     Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
X  
X***************
X*** 71,76 ****
X--- 73,85 ----
X  #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
X  #endif
X  
X+ /* patch for attribute of characters  by K.Handa 89.11.21 */
X+ /* Global variable to notify writechars (in x11term.c) the current address
X+    of corresponding attribute.
X+    I hate this solution! :-( :-( :-( */
X+ char *attribute_p;
X+ /* end of patch */
X+ 
X  /* Nonzero means do not assume anything about current
X   contents of actual terminal screen */
X  
X***************
X*** 324,330 ****
X--- 333,347 ----
X        hpos -= line->length;
X        line->length += hpos;
X        while (--hpos >= 0)
X+ /* patch for attribute by K.Handa  89.11.21 */
X+ /* original line is
X  	*p++ = ' ';
X+    and new lines are */
X+ 	{
X+ 	  line->attribute[p - line->body] = 0;
X+ 	  *p++ = ' ';
X+ 	}
X+ /* end of patch */
X      }
X  
X    DesiredScreen[vpos + 1] = line;
X***************
X*** 402,407 ****
X--- 419,426 ----
X  	  if (start > 0)
X  	    {
X  	      bcopy (l2->body, l1->body, start);
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	      bcopy (l2->attribute, l1->attribute, start);
X  	      if (l1->length < start && l1->length < l2->length)
X  		l1->length = min (start, l2->length);
X  	    }
X***************
X*** 408,414 ****
X--- 427,442 ----
X  	  if (l2->length > end && l1->length < l2->length)
X  	    {
X  	      while (l1->length < end)
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X  		l1->body[l1->length++] = ' ';
X+    and new lines are */
X+  		{
X+ 		  l1->attribute[l1->length] = 0;
X+ 		  l1->body[l1->length++] = ' ';
X+ 		}
X+ 	      bcopy (l2->attribute+end, l1->attribute+end, l2->length-end);
X+ /* end of patch */
X  	      bcopy (l2->body + end, l1->body + end, l2->length - end);
X  	      l1->length = l2->length;
X  	    }
X***************
X*** 444,450 ****
X--- 472,487 ----
X  	      fin = l2->length;
X  	      if (fin > end) fin = end;
X  	      while (l1->length < start)
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X  		l1->body[l1->length++] = ' ';
X+    and new lines are */
X+ 		{
X+ 		  l1->attribute[l1->length] = ' ';
X+ 		  l1->body[l1->length++] = ' ';
X+ 		}
X+ 	      bcopy (l2->attribute+start, l1->attribute+start, fin-start);
X+ /* end of patch */
X  	      bcopy (l2->body + start, l1->body + start, fin - start);
X  	      l1->length = fin;
X  	    }
X***************
X*** 522,527 ****
X--- 559,566 ----
X    XFASTINT (w->last_modified) = bf_modified;
X  
X    reassert_line_highlight (0, cursY);
X+ /* patch for attribute by K.Handa  89.11.24 */
X+   attribute_p = p->attribute + hpos;
X    write_chars (p->body + hpos, 1);
X    fflush (stdout);
X    ++cursX;
X***************
X*** 788,793 ****
X--- 827,834 ----
X       int vpos;
X  {
X    register char *obody, *nbody, *op1, *op2, *np1;
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+   register char *oattr, *nattr;
X    int tem;
X    int osp, nsp, m1, m2, olen, nlen;
X    int save;
X***************
X*** 814,819 ****
X--- 855,862 ----
X      {
X        obody = old -> body;
X        olen = old->length;
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+       oattr = old -> attribute;
X        if (! old->highlighted)
X  	{
X  	  /* Note obody[-1] is old->physical, which is always 0 or 1.  */
X***************
X*** 839,844 ****
X--- 882,889 ----
X  
X    nbody = new -> body;
X    nlen = new->length;
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+   nattr = new -> attribute;
X  
X    /* Pretend trailing spaces are not there at all,
X       unless for one reason or another we must write all spaces.  */
X***************
X*** 847,853 ****
X--- 892,902 ----
X    if (! new->highlighted)
X      {
X        if (!must_write_spaces)
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+ /* original line is
X  	while (nbody[nlen - 1] == ' ')
X+    and new line is */
X+ 	while (nbody[nlen - 1] == ' ' && nattr[olen - 1] == 0)
X  	  nlen--;
X      }
X    else
X***************
X*** 866,879 ****
X--- 915,938 ----
X  
X        for (i = 0; i < nlen; i++)
X  	{
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+ /* original line is
X  	  if (i >= olen || nbody[i] != obody[i])
X+    and new line is */
X+ 	  if (i >= olen || nbody[i] != obody[i] || nattr[i] != oattr[i])
X  	    {
X  	      /* We found a non-matching char.  */
X  	      topos (vpos, i);
X  	      for (j = 1; (i + j < nlen &&
X+ /* patch for attribute  by K.Handa 89.11.25 */
X+ /* original line is
X  			   (i + j >= olen || nbody[i+j] != obody[i+j]));
X+    and new line is */
X+ 			   (i + j >= olen || nbody[i+j] != obody[i+j] || nattr[i+j] != oattr[i+j]));
X  		   j++);
X  	      /* Output this run of non-matching chars.  */ 
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	      attribute_p = nattr + i;
X  	      write_chars (nbody + i, j);
X  	      i += j - 1;
X  	      /* Now find the next non-match.  */
X***************
X*** 895,900 ****
X--- 954,961 ----
X        if (nlen > nsp)
X  	{
X  	  topos (vpos, nsp);
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	  attribute_p = nattr + nsp;
X  	  write_chars (nbody + nsp, nlen - nsp);
X  	}
X        return;
X***************
X*** 905,911 ****
X--- 966,976 ----
X    nbody[nlen] = 0;
X  
X    /* Compute number of leading blanks in old and new contents.  */
X+ /* patch for attribute by K.Handa  89.11.24 */
X+   attribute_p = oattr;
X    osp = count_blanks (obody);
X+ /* patch for attribute by K.Handa  89.11.24 */
X+   attribute_p = nattr;
X    if (!new->highlighted)
X      nsp = count_blanks (nbody);
X    else
X***************
X*** 912,918 ****
X--- 977,987 ----
X      nsp = 0;
X  
X    /* Compute number of matching chars starting with first nonblank.  */
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X    m1 = count_match (obody + osp, nbody + nsp);
X+    and new line is */
X+   m1 = count_match2 (obody + osp, oattr + osp, nbody + nsp, nattr + nsp);
X  
X    /* Spaces in new match implicit space past the end of old.  */
X    /* A bug causing this to be a no-op was fixed in 18.29.  */
X***************
X*** 919,925 ****
X--- 988,998 ----
X    if (!must_write_spaces && osp + m1 == olen)
X      {
X        np1 = nbody + nsp;
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X        while (np1[m1] == ' ')
X+    and new line is */
X+       while (np1[m1] == ' ' && nattr[nsp+m1] == 0)
X  	m1++;
X      }
X  
X***************
X*** 933,939 ****
X--- 1006,1016 ----
X    op1 = obody + olen;
X    np1 = nbody + nlen;
X    op2 = op1 + m1 - min (olen - osp, nlen - nsp);
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X    while (op1 > op2 && op1[-1] == np1[-1])
X+    and new line is */
X+   while (op1 > op2 && op1[-1] == np1[-1] && oattr[op1-obody-1] == nattr[np1-nbody-1])
X      {
X        op1--;
X        np1--;
X***************
X*** 999,1004 ****
X--- 1076,1083 ----
X  	     going to be "at the margin" after the text is done) */
X  	  if (nlen == screen_width)
X  	    olen = 0;
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	  attribute_p = new->attribute + nsp + m1;
X  	  write_chars (nbody + nsp + m1, nlen - tem);
X  #ifdef obsolete
X  /* the following code loses disastrously if tem == nlen.
X***************
X*** 1011,1027 ****
X--- 1090,1120 ----
X  	  if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
X  	    {
X  	      /* m2 must be zero, and tem must equal nsp + m1 */
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	      attribute_p = nattr + tem;
X  	      write_chars (nbody + tem, nlen - tem - 1);
X  	      clear_end_of_line (olen);
X  	      olen = 0;		/* Don't let it be cleared again later */
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	      attribute_p = nattr + nlen - 1;
X  	      write_chars (nbody + nlen - 1, 1);
X  	    }
X  	  else
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X  	    write_chars (nbody + nsp + m1, nlen - tem);
X+    and new lines are */
X+ 	    {
X+ 	      attribute_p = nattr + nsp + m1;
X+ 	      write_chars (nbody + nsp + m1, nlen - tem);
X+ 	    }
X+ /* end of patch */
X  #endif
X  	}
X        else if (nlen > olen)
X  	{
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	  attribute_p = nattr + nsp + m1;
X  	  write_chars (nbody + nsp + m1, olen - tem);
X  	  insert_chars (nbody + nsp + m1 + olen - tem, nlen - olen);
X  	  olen = nlen;
X***************
X*** 1028,1033 ****
X--- 1121,1128 ----
X  	}
X        else if (olen > nlen)
X  	{
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	  attribute_p = nattr + nsp + m1;
X  	  write_chars (nbody + nsp + m1, nlen - tem);
X  	  delete_chars (olen - nlen);
X  	  olen = nlen;
X***************
X*** 1047,1053 ****
X--- 1142,1152 ----
X       char *str;
X  {
X    register char *p = str;
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X    while (*str++ == ' ');
X+    and new line is */
X+   while (*str++ == ' ' && *attribute_p++ == 0);
X    return str - p - 1;
X  }
X  
X***************
X*** 1057,1062 ****
X--- 1156,1170 ----
X    register char *p1 = str1;
X    register char *p2 = str2;
X    while (*p1++ == *p2++);
X+   return p1 - str1 - 1;
X+ }
X+ 
X+ count_match2 (str1, attr1, str2, attr2)
X+      char *str1, *attr1, *str2, *attr2;
X+ {
X+   register char *p1 = str1;
X+   register char *p2 = str2;
X+   while (*p1++ == *p2++ && *attr1++ == *attr2++);
X    return p1 - str1 - 1;
X  }
X  
Xdiff -arcN emacs-18.55/src/x11term.c emacs-18.55-with-attr/src/x11term.c
X*** emacs-18.55/src/x11term.c	Mon Aug 28 19:14:46 1989
X--- emacs-18.55-with-attr/src/x11term.c	Tue Dec 19 20:26:47 1989
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* 89.11.24 modified for attribute of characters by K.Handa */
X+ 
X  /* X Communication module for terminals which understand the X protocol.
X     Copyright (C) 1988 Free Software Foundation, Inc.
X  
X***************
X*** 172,177 ****
X--- 174,180 ----
X  Window XXwindow;
X  GC XXgc_norm,XXgc_rev,XXgc_curs,XXgc_temp;
X  XGCValues XXgcv;
X+ GC XXgc_line, XXgc_line_rev;	/* patch for attribute by K.Handa  89.3.13 */
X  Cursor EmacsCursor;
X  Pixmap SinkPixmap, SinkMaskPixmap;
X  
X***************
X*** 199,204 ****
X--- 202,215 ----
X  static char  *temp_borderWidth;
X  static char  *temp_internalBorder;
X  
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* a little tricky way :-( */
X+ extern XDrawImageString ();
X+ (*_XDrawImageString)() = XDrawImageString;
X+ #define XDrawImageString(d, w, gc, x, y, string, attr, length) \
X+   XDrawImageStringWithAttribute(d, w, gc, x, y, string, attr, length)
X+ /* end of patch */
X+ 
X  struct _xdeftab 
X  {
X    char *iname;			/* instance name */
X***************
X*** 480,485 ****
X--- 491,498 ----
X  			 tempX*XXfontw+XXInternalBorder,
X  			 tempY*XXfonth+XXInternalBorder+XXbase,
X  			 &ActiveScreen[tempY+1]->body[tempX],
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 			 &ActiveScreen[tempY+1]->attribute[tempX],
X  			 numcols);
X  }
X  
X***************
X*** 523,528 ****
X--- 536,543 ----
X  				  first*XXfontw+XXInternalBorder,
X  				  cursY*XXfonth+XXInternalBorder+XXbase,
X  				  &DesiredScreen[cursY + 1]->body[first],
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 				  &DesiredScreen[cursY + 1]->attribute[first],
X  				  temp_length);
X  		if (temp_length < screen_width)
X  			x_clear_end_of_line (temp_length);
X***************
X*** 564,569 ****
X--- 579,586 ----
X  			cursX*XXfontw+XXInternalBorder,
X  			cursY*XXfonth+XXInternalBorder+XXbase,
X  			start,
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 		        attribute_p,
X  			(end - start) + 1);
X        XTtopos (cursY, (end - start) + 1);
X  
X***************
X*** 587,592 ****
X--- 604,611 ----
X  		      (VisibleX * XXfontw+XXInternalBorder),
X  		      VisibleY * XXfonth+XXInternalBorder+XXbase,
X  		      start,
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 	              attribute_p,
X  		      ((end - start) + 1));
X      VisibleX = VisibleX + (end - start) + 1;
X    }
X***************
X*** 696,701 ****
X--- 715,722 ----
X  				    VisibleX*XXfontw+XXInternalBorder,
X  				    VisibleY*XXfonth+XXInternalBorder+XXbase,
X  				    &ActiveScreen[VisibleY+1]->body[VisibleX],
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 				    &ActiveScreen[VisibleY+1]->attribute[VisibleX],
X  				    1);
X  		else if (CursorOutline) {
X  			XDrawImageString(XXdisplay, XXwindow, XXgc_norm,
X***************
X*** 702,707 ****
X--- 723,730 ----
X  				    VisibleX*XXfontw+XXInternalBorder,
X  				    VisibleY*XXfonth+XXInternalBorder+XXbase,
X  				    &ActiveScreen[VisibleY+1]->body[VisibleX],
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 				    &ActiveScreen[VisibleY+1]->attribute[VisibleX],
X  				    1);
X  			XDrawRectangle (XXdisplay, XXwindow, XXgc_norm,
X  					VisibleX*XXfontw+XXInternalBorder,
X***************
X*** 712,717 ****
X--- 735,742 ----
X  				    VisibleX*XXfontw+XXInternalBorder,
X  				    VisibleY*XXfonth+XXInternalBorder+XXbase,
X  				    &ActiveScreen[VisibleY+1]->body[VisibleX],
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ 				    &ActiveScreen[VisibleY+1]->attribute[VisibleX],
X  				    1);
X  	      }
X  	else {
X***************
X*** 729,735 ****
X--- 754,764 ----
X  			XDrawImageString(XXdisplay, XXwindow, XXgc_curs,
X  				    VisibleX*XXfontw+XXInternalBorder,
X  				    VisibleY*XXfonth+XXInternalBorder+XXbase,
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ /* original line is
X  				    " ", 1);
X+    and new line is */
X+ 				    " ", "\0", 1);
X  	      }
X  
X  	CursorExists = !CursorExists;
X***************
X*** 2021,2026 ****
X--- 2050,2060 ----
X  	XXgc_temp = XXgc_norm;
X  	XXgc_norm = XXgc_rev;
X  	XXgc_rev = XXgc_temp;
X+ /* patch for attribute by K.Handa  89.12.19 */
X+ 	XXgc_temp = XXgc_line;
X+ 	XXgc_line = XXgc_line_rev;
X+ 	XXgc_line_rev = XXgc_temp;
X+ /* end of patch */	
X  
X  	if (!strcmp (mous_color, "white"))
X  	  mous_color = "black";
X***************
X*** 2352,2357 ****
X--- 2386,2405 ----
X      XXgc_norm = XCreateGC(XXdisplay, XXwindow,
X  			  GCFont|GCForeground|GCBackground,
X  			  &XXgcv);
X+ /* patch for attribute by K.Handa  89.3.13, 89.11.24 */
X+     XXgcv.function = reversevideo ? GXclear : GXset;
X+     XXgcv.line_width = 1;
X+     XXgcv.line_style = LineSolid;
X+     XXgc_line =
X+       XCreateGC(XXdisplay, XXwindow,
X+ 		GCFunction|GCLineWidth|GCLineStyle|GCForeground|GCBackground,
X+ 		&XXgcv);
X+     XXgcv.function = reversevideo ? GXset : GXclear;
X+     XXgc_line_rev =
X+       XCreateGC(XXdisplay, XXwindow,
X+ 		GCFunction|GCLineWidth|GCLineStyle|GCForeground|GCBackground,
X+ 		&XXgcv);
X+ /* end of patch */
X      XXgcv.foreground = back;
X      XXgcv.background = fore;
X      XXgc_rev = XCreateGC(XXdisplay, XXwindow,
X***************
X*** 2392,2397 ****
X--- 2440,2481 ----
X      XMapWindow (XXdisplay, XXwindow);
X      XFlush (XXdisplay);
X  }
X+ 
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ XDrawImageStringWithAttribute(display, d, gc, x, y, string, attr, length)
X+      Display *display;
X+      Drawable d;
X+      GC gc;
X+      int x, y;
X+      unsigned char *string, *attr;
X+      int length;
X+ {
X+   unsigned char	*p = string, *endp = string + length;
X+   unsigned attribute_bits = *attr;
X+   int len = 0;
X+   int underline_height = y - 1;
X+   GC gctemp, gci = (gc == XXgc_norm) ? XXgc_rev : XXgc_norm;
X+ 
X+   if (length == 0) return;
X+ 
X+   for (;;) {
X+     if (p >= endp || *attr != attribute_bits) { /* state changed */
X+       len = p - string;
X+       gctemp = (attribute_bits & ATTR_INVERSE) ? gci : gc;
X+ 	(*_XDrawImageString)(display, d, gctemp, x, y, string, len);
X+       if (attribute_bits & ATTR_UNDERLINE) {
X+ 	gctemp = (gctemp == XXgc_norm) ? XXgc_line : XXgc_line_rev;
X+ 	XDrawLine(display, d, gctemp, x, underline_height,
X+ 		  x + XXfontw * len, underline_height);
X+       }
X+       attribute_bits = *attr;
X+       x += XXfontw * len;
X+       if ((string = p) >= endp) break;;
X+     }
X+     p++; attr++;
X+   }
X+ }
X+ /* end of patch */
X  
X  #endif /* HAVE_X_WINDOWS */
X  
Xdiff -arcN emacs-18.55/src/xdisp.c emacs-18.55-with-attr/src/xdisp.c
X*** emacs-18.55/src/xdisp.c	Mon Aug 28 15:05:11 1989
X--- emacs-18.55-with-attr/src/xdisp.c	Fri Dec 15 23:36:48 1989
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* 89.11.24 modified for attribute of characters by K.Handa */
X+ 
X  /* Display generation from window structure and buffer text.
X     Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
X  
X***************
X*** 1167,1172 ****
X--- 1169,1179 ----
X    return 1;
X  }
X  
X+ /* patch for attribute by K.Handa  89.11.24 */
X+ #define APOS(amark) \
X+   ((XTYPE(amark) == Lisp_Marker && XMARKER (amark)->buffer) \
X+    ? Fmarker_position (amark) : end)
X+ 
X  /* Display one line of window w, starting at position `start' in w's buffer.
X   Display starting at horizontal position `hpos',
X    which is normally zero or negative.
X***************
X*** 1219,1224 ****
X--- 1226,1237 ----
X        ? XINT (bf_cur->selective_display)
X  	: !NULL (bf_cur->selective_display) ? -1 : 0;
X    int selective_e = selective && !NULL (bf_cur->selective_display_ellipses);
X+ /* patch for attribute of characters by K.Handa  89.11.21 */
X+   char attribute_bits = 0;
X+   char *attrp, *attrstartp;
X+   Lisp_Object underline, umark, inverse, imark;
X+   int upos, ipos;
X+ /* end of patch */
X  
X    hpos += XFASTINT (w->left);
X    line = get_display_line (vpos, XFASTINT (w->left));
X***************
X*** 1239,1244 ****
X--- 1252,1290 ----
X  
X    startp = line->body + XFASTINT (w->left);
X    endp = startp + width;
X+ /* patch for attribute by K.Handa  89.11.24 */
X+   attrp = line->attribute + (p1 - line->body);
X+   attrstartp = line->attribute + (startp - line->body);
X+ 
X+   if (!NULL(bf_cur->underlined_region)
X+       && XTYPE (bf_cur->underlined_region) == Lisp_Cons) {
X+     underline = Fcdr (bf_cur->underlined_region);
X+     umark = Fcar (underline);
X+     while (!NULL(umark) && start >= (upos = APOS (umark))) {
X+       underline = Fcdr (underline);
X+       umark = Fcar (underline);
X+       attribute_bits ^= ATTR_UNDERLINE;
X+     }
X+     if (NULL(underline)) upos = end;
X+   }  else {
X+     underline = umark = Qnil;
X+     upos = end;
X+   }
X+   if (!NULL(bf_cur->inversed_region)
X+       && XTYPE (bf_cur->inversed_region) == Lisp_Cons) {
X+     inverse = Fcdr (bf_cur->inversed_region);
X+     imark = Fcar (inverse);
X+     while (!NULL(imark) && start >= (ipos = APOS (imark))) {
X+       inverse = Fcdr (inverse);
X+       imark = Fcar (inverse);
X+       attribute_bits ^= ATTR_INVERSE;
X+     }
X+     if (NULL(inverse)) ipos = end;
X+   }  else {
X+     inverse = imark = Qnil;
X+     ipos = end;
X+   }
X+ /* end of patch */
X  
X    /* Loop generating characters.
X     Stop at end of buffer, before newline,
X***************
X*** 1266,1271 ****
X--- 1312,1337 ----
X  
X  	  p = &CharAt (pos);
X  	}
X+ /* patch for attribute of characters by K.Handa 89.11.21 */
X+       while (pos >= upos) {
X+ 	attribute_bits ^= ATTR_UNDERLINE;
X+ 	if (!NULL (underline)) {
X+ 	  underline = Fcdr (underline);
X+ 	  umark = Fcar (underline);
X+ 	  upos = APOS (umark);
X+ 	} else
X+ 	  upos = end;
X+       }
X+       while (pos >= ipos) {
X+ 	attribute_bits ^= ATTR_INVERSE;
X+ 	if (!NULL (inverse)) {
X+ 	  inverse = Fcdr (inverse);
X+ 	  imark = Fcar (inverse);
X+ 	  ipos = APOS (imark);
X+ 	} else
X+ 	  ipos = end;
X+       }
X+ /* end of patch */
X        c = *p++;
X        if (c >= 040 && c < 0177)
X  	{
X***************
X*** 1343,1348 ****
X--- 1409,1420 ----
X  	    *p1 = (7 & c) + '0';
X  	  p1++;
X  	}
X+ /* patch for attribute by K.Handa  89.11.24 */
X+       while (attrp < line->attribute + (p1 - line->body)) {
X+ 	if (attrstartp <= attrp) *attrp = attribute_bits;
X+ 	attrp++;
X+       }
X+ /* end of patch */
X        pos++;
X      }
X  
SHAR_EOF
chmod 0666 diffs || echo "restore of diffs fails"
sed 's/^X//' << 'SHAR_EOF' > attribute.el &&
X;; attribute.el
X;; Set character attribute for Emacs under X window environment.
X;; Code by K. HANDA, Electrotechnical Lab., JAPAN, 1989.
X
X;; This program is distributed under the terms of the GNU
X;; EMACS GENERAL PUBLIC LICENSE which is distributed along
X;; with GNU Emacs by the Free Software Foundation.
X
X;; This program is distributed in the hope that it will be
X;; useful, but WITHOUT ANY WARRANTY; without even the
X;; implied warranty of MERCHANTABILITY or FITNESS FOR A
X;; PARTICULAR PURPOSE.  See the GNU EMACS GENERAL PUBLIC
X;; LICENSE for more details.
X
X;; You should have received a copy of the GNU EMACS GENERAL
X;; PUBLIC LICENSE along with this file; see the file
X;; COPYING.  If not, write to the Free Software Foundation,
X;; 675 Mass Ave, Cambridge, MA 02139, USA.
X
X;; Change Log
X;; 89.11.28 Created by K.Handa
X;; 89.12.10 Update screen after attributes are changed.  by K.Handa
X
X(provide 'attribute)
X
X(defun attribute-on-region (attr &optional from to)
X  "Set an charater attribute ATTR within the region on.\n\
XCurrently supported attributes are 'underline' and 'inverse'.\n\
XCalled from program, takes two optional arguments FROM and TO.\n\
XIf FROM or TO is NIL, (point-min) or (point-max) is used instead.\n\
XInformation of attribute is stored in buffer local variables\n\
Xunderlined-region and inversed-region, but manipulating these variabels\n\
Xdirectly may cause serious problems."
X  (interactive
X   (list
X    (attribute-symbol-read)
X    (mark)
X    (point)))
X  (attribute-on-off-region attr from to 'on))
X
X(defun attribute-off-region (attr &optional from to)
X  "Set an charater attribute ATTR within the region off.\n\
XSee the function attribute-on-region for the detail."
X  (interactive
X   (list
X    (attribute-symbol-read)
X    (mark)
X    (point)))
X  (attribute-on-off-region attr from to nil))
X
X(defun attribute-symbol-read ()
X  (intern (completing-read
X	   "Attribute: " '(("inverse") ("underline")) nil t)))
X
X(defun attribute-get-attribute (&optional pos)
X  "Return a list of attribute ranges at POS.\n\
XAn attribute range is a list of attribute type, the starting point,\n\
Xand the ending point.\n\
XPOS is optional argument and the default is the current point."
X  (if (not pos) (setq pos (point)))
X  (let (return attr)
X    (if (and underlined-region
X	     (setq attr (attribute-starting-point underlined-region pos)))
X	(setq return (cons (list 'underline (car attr) (car (cdr attr)))
X			   return)))
X    (if (and inversed-region
X	     (setq attr (attribute-starting-point inversed-region pos)))
X	(setq return (cons (list 'inverse (car attr) (car (cdr attr)))
X			   return)))
X    return))
X
X(defun attribute-starting-point (attr pos)
X  (while (and (setq attr (cdr attr))
X	      (>= pos (car (cdr attr))))
X    (setq attr (cdr attr)))
X  (if attr
X      (if (>= pos (car attr)) attr)))
X
X(defun attribute-on-off-region (attr &optional from to on)
X  (let ((min (point-min)) (max (point-max)))
X    (if (or (not from) (< from min)) (setq from min)
X      (if (> from max) (setq from max)))
X    (if (or (not to) (> to max)) (setq to max)
X      (if (< to min) (setq to min))))
X  (if (> from to) (let ((temp from)) (setq from to) (setq to temp)))
X  (attribute-record-region-modified from to)
X  (let* ((attribute (cond ((eq attr 'underline) 'underlined-region)
X			  ((eq attr 'inverse) 'inversed-region)
X			  ;;; ((eq attr 'highlight) 'highlighted-region)
X			  (t nil))))
X    (if attribute
X	(progn
X	  (if (not (symbol-value attribute))
X	      (set attribute (list 1)))
X	  (attribute-modify-attribute attribute from to (if on 1 0)))
X      (error "Invalid ATTR(%s)" attr))))
X
X(defun attribute-modify-attribute (attr from to set)
X  (let* ((attr-value (symbol-value attr))
X	 (len (car attr-value))
X	 (i1 1) i2)
X;    (let (m1 m2)			; at first, erase invalid block
X;      (while (< i1 len)
X;	(setq m1 (nth i1 attr-value) m2 (nth (1+ i1) attr-value))
X;	(if (or (not m1) (not m2) (= m1 m2))
X;	    (progn
X;	      (set-marker m1 nil)
X;	      (set-marker m2 nil)
X;	      (rplacd (nthcdr (1- i1) attr-value)
X;		      (nthcdr (+ i1 2) attr-value))
X;	      (rplaca attr-value (- len 2)))
X;	  (setq i1 (+ i1 2)))))
X    (setq i1 1)
X    (while (and (< i1 len) (> from (nth i1 attr-value)))
X      (setq i1 (1+ i1)))
X    (setq i2 i1)
X    (while (and (< i2 len) (>= to (nth i2 attr-value)))
X      (setq i2 (1+ i2)))
X    (if (= i1 i2)			; if within the same area
X	(if (= (% i1 2) set)		;   if within the same attribute area
X	    (let ((m1 (make-marker)) (m2 (make-marker)))
X	      (set-marker m1 from)
X	      (set-marker m2 to)
X	      ; (set-marker-type m2 'point-type) ; for Nemacs
X	      (rplacd (nthcdr (1- i1) attr-value)
X		      (cons m1 (cons m2 (nthcdr i1 attr-value))))))
X					; else laid across block border
X      (if (= (% i1 2) set)		;   if 'from' is out of attribute area
X	  (move-marker (nth i1 attr-value) from)
X	(setq i1 (1- i1)))
X      (if (= (% i2 2) set)		;   if 'to' is out of attribute area
X	  (progn
X	    (setq i2 (1- i2))
X	    (move-marker (nth i2 attr-value) to)))
X      (if (< i1 (1- i2))		;   if the list should be reduced
X	  (let ((i i1))
X	    (while (< (setq i (1+ i)) i2)
X	      (set-marker (nth i attr-value) nil))
X	    (rplacd (nthcdr i1 attr-value) (nthcdr i2 attr-value)))))
X    (rplaca attr-value (length attr-value))
X    (if (= (car attr-value) 1) (set attr nil))))
X
X;; There should be a better way! :-(
X(defun attribute-record-region-modified (from to)
X  (subst-char-in-region from to 0 0 'noundo))
SHAR_EOF
chmod 0666 attribute.el || echo "restore of attribute.el fails"
sed 's/^X//' << 'SHAR_EOF' > attribute.el.nemacs &&
X;; attribute.el
X;; Set character attribute for Emacs under X window environment.
X;; Code by K. HANDA, Electrotechnical Lab., JAPAN, 1989.
X
X;; This program is distributed under the terms of the GNU
X;; EMACS GENERAL PUBLIC LICENSE which is distributed along
X;; with GNU Emacs by the Free Software Foundation.
X
X;; This program is distributed in the hope that it will be
X;; useful, but WITHOUT ANY WARRANTY; without even the
X;; implied warranty of MERCHANTABILITY or FITNESS FOR A
X;; PARTICULAR PURPOSE.  See the GNU EMACS GENERAL PUBLIC
X;; LICENSE for more details.
X
X;; You should have received a copy of the GNU EMACS GENERAL
X;; PUBLIC LICENSE along with this file; see the file
X;; COPYING.  If not, write to the Free Software Foundation,
X;; 675 Mass Ave, Cambridge, MA 02139, USA.
X
X;; Change Log
X;; 89.11.28 Created by K.Handa
X;; 89.12.10 Update screen after attributes are changed.  by K.Handa
X
X(provide 'attribute)
X
X(defun attribute-on-region (attr &optional from to)
X  "Set an charater attribute ATTR within the region on.\n\
XCurrently supported attributes are 'underline' and 'inverse'.\n\
XCalled from program, takes two optional arguments FROM and TO.\n\
XIf FROM or TO is NIL, (point-min) or (point-max) is used instead.\n\
XInformation of attribute is stored in buffer local variables\n\
Xunderlined-region and inversed-region, but manipulating these variabels\n\
Xdirectly may cause serious problems."
X  (interactive
X   (list
X    (attribute-symbol-read)
X    (mark)
X    (point)))
X  (attribute-on-off-region attr from to 'on))
X
X(defun attribute-off-region (attr &optional from to)
X  "Set an charater attribute ATTR within the region off.\n\
XSee the function attribute-on-region for the detail."
X  (interactive
X   (list
X    (attribute-symbol-read)
X    (mark)
X    (point)))
X  (attribute-on-off-region attr from to nil))
X
X(defun attribute-symbol-read ()
X  (intern (completing-read
X	   "Attribute: " '(("inverse") ("underline")) nil t)))
X
X(defun attribute-get-attribute (&optional pos)
X  "Return a list of attribute ranges at POS.\n\
XAn attribute range is a list of attribute type, the starting point,\n\
Xand the ending point.\n\
XPOS is optional argument and the default is the current point."
X  (if (not pos) (setq pos (point)))
X  (let (return attr)
X    (if (and underlined-region
X	     (setq attr (attribute-starting-point underlined-region pos)))
X	(setq return (cons (list 'underline (car attr) (car (cdr attr)))
X			   return)))
X    (if (and inversed-region
X	     (setq attr (attribute-starting-point inversed-region pos)))
X	(setq return (cons (list 'inverse (car attr) (car (cdr attr)))
X			   return)))
X    return))
X
X(defun attribute-starting-point (attr pos)
X  (while (and (setq attr (cdr attr))
X	      (>= pos (car (cdr attr))))
X    (setq attr (cdr attr)))
X  (if attr
X      (if (>= pos (car attr)) attr)))
X
X(defun attribute-on-off-region (attr &optional from to on)
X  (let ((min (point-min)) (max (point-max)))
X    (if (or (not from) (< from min)) (setq from min)
X      (if (> from max) (setq from max)))
X    (if (or (not to) (> to max)) (setq to max)
X      (if (< to min) (setq to min))))
X  (if (> from to) (let ((temp from)) (setq from to) (setq to temp)))
X  (attribute-record-region-modified from to)
X  (let* ((attribute (cond ((eq attr 'underline) 'underlined-region)
X			  ((eq attr 'inverse) 'inversed-region)
X			  ;;; ((eq attr 'highlight) 'highlighted-region)
X			  (t nil))))
X    (if attribute
X	(progn
X	  (if (not (symbol-value attribute))
X	      (set attribute (list 1)))
X	  (attribute-modify-attribute attribute from to (if on 1 0)))
X      (error "Invalid ATTR(%s)" attr))))
X
X(defun attribute-modify-attribute (attr from to set)
X  (let* ((attr-value (symbol-value attr))
X	 (len (car attr-value))
X	 (i1 1) i2)
X;    (let (m1 m2)			; at first, erase invalid block
X;      (while (< i1 len)
X;	(setq m1 (nth i1 attr-value) m2 (nth (1+ i1) attr-value))
X;	(if (or (not m1) (not m2) (= m1 m2))
X;	    (progn
X;	      (set-marker m1 nil)
X;	      (set-marker m2 nil)
X;	      (rplacd (nthcdr (1- i1) attr-value)
X;		      (nthcdr (+ i1 2) attr-value))
X;	      (rplaca attr-value (- len 2)))
X;	  (setq i1 (+ i1 2)))))
X    (setq i1 1)
X    (while (and (< i1 len) (> from (nth i1 attr-value)))
X      (setq i1 (1+ i1)))
X    (setq i2 i1)
X    (while (and (< i2 len) (>= to (nth i2 attr-value)))
X      (setq i2 (1+ i2)))
X    (if (= i1 i2)			; if within the same area
X	(if (= (% i1 2) set)		;   if within the same attribute area
X	    (let ((m1 (make-marker)) (m2 (make-marker)))
X	      (set-marker m1 from)
X	      (set-marker m2 to)
X	      (set-marker-type m2 'point-type)
X	      (rplacd (nthcdr (1- i1) attr-value)
X		      (cons m1 (cons m2 (nthcdr i1 attr-value))))))
X					; else laid across block border
X      (if (= (% i1 2) set)		;   if 'from' is out of attribute area
X	  (move-marker (nth i1 attr-value) from)
X	(setq i1 (1- i1)))
X      (if (= (% i2 2) set)		;   if 'to' is out of attribute area
X	  (progn
X	    (setq i2 (1- i2))
X	    (move-marker (nth i2 attr-value) to)))
X      (if (< i1 (1- i2))		;   if the list should be reduced
X	  (let ((i i1))
X	    (while (< (setq i (1+ i)) i2)
X	      (set-marker (nth i attr-value) nil))
X	    (rplacd (nthcdr i1 attr-value) (nthcdr i2 attr-value)))))
X    (rplaca attr-value (length attr-value))
X    (if (= (car attr-value) 1) (set attr nil))))
X
X;; There should be a better way! :-(
X(defun attribute-record-region-modified (from to)
X  (subst-char-in-region from to 0 0 'noundo))
SHAR_EOF
chmod 0666 attribute.el.nemacs || echo "restore of attribute.el.nemacs fails"
sed 's/^X//' << 'SHAR_EOF' > COPYING &&
X		 GNU EMACS GENERAL PUBLIC LICENSE
X		    (Clarified 11 Feb 1988)
X
X Copyright (C) 1985, 1987, 1988 Richard M. Stallman
X Everyone is permitted to copy and distribute verbatim copies
X of this license, but changing it is not allowed.  You can also
X use this wording to make the terms for other programs.
X
X  The license agreements of most software companies keep you at the
Xmercy of those companies.  By contrast, our general public license is
Xintended to give everyone the right to share GNU Emacs.  To make
Xsure that you get the rights we want you to have, we need to make
Xrestrictions that forbid anyone to deny you these rights or to ask you
Xto surrender the rights.  Hence this license agreement.
X
X  Specifically, we want to make sure that you have the right to give
Xaway copies of Emacs, that you receive source code or else can get it
Xif you want it, that you can change Emacs or use pieces of it in new
Xfree programs, and that you know you can do these things.
X
X  To make sure that everyone has such rights, we have to forbid you to
Xdeprive anyone else of these rights.  For example, if you distribute
Xcopies of Emacs, you must give the recipients all the rights that you
Xhave.  You must make sure that they, too, receive or can get the
Xsource code.  And you must tell them their rights.
X
X  Also, for our own protection, we must make certain that everyone
Xfinds out that there is no warranty for GNU Emacs.  If Emacs is
Xmodified by someone else and passed on, we want its recipients to know
Xthat what they have is not what we distributed, so that any problems
Xintroduced by others will not reflect on our reputation.
X
X  Therefore we (Richard Stallman and the Free Software Fundation,
XInc.) make the following terms which say what you must do to be
Xallowed to distribute or change GNU Emacs.
X
X			COPYING POLICIES
X
X  1. You may copy and distribute verbatim copies of GNU Emacs source code
Xas you receive it, in any medium, provided that you conspicuously and
Xappropriately publish on each copy a valid copyright notice "Copyright
X(C) 1988 Free Software Foundation, Inc." (or with whatever year is
Xappropriate); keep intact the notices on all files that refer to this
XLicense Agreement and to the absence of any warranty; and give any
Xother recipients of the GNU Emacs program a copy of this License
XAgreement along with the program.  You may charge a distribution fee
Xfor the physical act of transferring a copy.
X
X  2. You may modify your copy or copies of GNU Emacs source code or
Xany portion of it, and copy and distribute such modifications under
Xthe terms of Paragraph 1 above, provided that you also do the following:
X
X    a) cause the modified files to carry prominent notices stating
X    that you changed the files and the date of any change; and
X
X    b) cause the whole of any work that you distribute or publish,
X    that in whole or in part contains or is a derivative of GNU Emacs
X    or any part thereof, to be licensed at no charge to all third
X    parties on terms identical to those contained in this License
X    Agreement (except that you may choose to grant more extensive
X    warranty protection to some or all third parties, at your option).
X
X    c) if the modified program serves as a text editor, cause it when
X    started running in the simplest and usual way, to print an
X    announcement including a valid copyright notice "Copyright (C)
X    1988 Free Software Foundation, Inc." (or with the year that is
X    appropriate), saying that there is no warranty (or else, saying
X    that you provide a warranty) and that users may redistribute the
X    program under these conditions, and telling the user how to view a
X    copy of this License Agreement.
X
X    d) You may charge a distribution fee for the physical act of
X    transferring a copy, and you may at your option offer warranty
X    protection in exchange for a fee.
X
XMere aggregation of another unrelated program with this program (or its
Xderivative) on a volume of a storage or distribution medium does not bring
Xthe other program under the scope of these terms.
X
X  3. You may copy and distribute GNU Emacs (or a portion or derivative of it,
Xunder Paragraph 2) in object code or executable form under the terms of
XParagraphs 1 and 2 above provided that you also do one of the following:
X
X    a) accompany it with the complete corresponding machine-readable
X    source code, which must be distributed under the terms of
X    Paragraphs 1 and 2 above; or,
X
X    b) accompany it with a written offer, valid for at least three
X    years, to give any third party free (except for a nominal
X    shipping charge) a complete machine-readable copy of the
X    corresponding source code, to be distributed under the terms of
X    Paragraphs 1 and 2 above; or,
X
X    c) accompany it with the information you received as to where the
X    corresponding source code may be obtained.  (This alternative is
X    allowed only for noncommercial distribution and only if you
X    received the program in object code or executable form alone.)
X
XFor an executable file, complete source code means all the source code for
Xall modules it contains; but, as a special exception, it need not include
Xsource code for modules which are standard libraries that accompany the
Xoperating system on which the executable file runs.
X
X  4. You may not copy, sublicense, distribute or transfer GNU Emacs
Xexcept as expressly provided under this License Agreement.  Any attempt
Xotherwise to copy, sublicense, distribute or transfer GNU Emacs is void and
Xyour rights to use GNU Emacs under this License agreement shall be
Xautomatically terminated.  However, parties who have received computer
Xsoftware programs from you with this License Agreement will not have
Xtheir licenses terminated so long as such parties remain in full compliance.
X
X  5. If you wish to incorporate parts of GNU Emacs into other free programs
Xwhose distribution conditions are different, write to the Free Software
XFoundation.  We have not yet worked out a simple rule that can be stated
Xhere, but we will often permit this.  We will be guided by the two goals of
Xpreserving the free status of all derivatives of our free software and of
Xpromoting the sharing and reuse of software.
X
XYour comments and suggestions about our licensing policies and our
Xsoftware are welcome!  Please contact the Free Software Foundation, Inc.,
X675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
X
X			   NO WARRANTY
X
X  BECAUSE GNU EMACS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
XNO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
XWHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
XRICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GNU EMACS "AS IS"
XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
XAND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE GNU EMACS
XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
XSERVICING, REPAIR OR CORRECTION.
X
X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE
XFOUNDATION, INC., RICHARD M. STALLMAN, AND/OR ANY OTHER PARTY WHO MAY
XMODIFY AND REDISTRIBUTE GNU EMACS AS PERMITTED ABOVE, BE LIABLE TO YOU
XFOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
XSPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
XINABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
XBEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
XFAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
XFREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN
XADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
XOTHER PARTY.
SHAR_EOF
chmod 0666 COPYING || echo "restore of COPYING fails"
exit 0