*** TextEd.c.orig	Wed Feb  8 13:16:40 1995
--- TextEd.c	Tue Mar  7 15:32:12 1995
***************
*** 2665,2671 ****
  int deleted;
      {
  	long ref, position;
! 	int i, n;
  	
  	w->texted.mult = 1;
  	ref = w->texted.cursor_position;
--- 2665,2671 ----
  int deleted;
      {
  	long ref, position;
! 	int n;
  	
  	w->texted.mult = 1;
  	ref = w->texted.cursor_position;
***************
*** 2715,2729 ****
  		XeTextRegion *r = &w->texted.regions[n];
  		if (r->mode == XeTextHighlight_UNUSED)
  			continue;
! 		for (i = 0; i < XtNumber(r->range); ++i)
! 			if (ref <= r->range[i])
! 				if (deleted == 0)
! 					r->range[i] +=
! 						w->texted.cursor_position-ref;
! 				else if (ref + deleted > r->range[i])
! 					r->range[i] = ref;
! 				else
! 					r->range[i] -= deleted;
  		XeUpdateTextRegion(w, r, False); /* Should fine tune? --msa */
  	    }
  	ChangeWidgetSize(w, True); /* ..only if larger! */
--- 2715,2736 ----
  		XeTextRegion *r = &w->texted.regions[n];
  		if (r->mode == XeTextHighlight_UNUSED)
  			continue;
! 		if (ref < r->range[0] ||
! 		    (ref == r->range[0] && r->range[0] < r->range[1]))
! 			if (deleted == 0)
! 				r->range[0] += w->texted.cursor_position-ref;
! 			else if (ref + deleted > r->range[0])
! 				r->range[0] = ref;
! 			else
! 				r->range[0] -= deleted;
! 		if (ref < r->range[1] ||
! 		    (ref == r->range[1] && r->range[1] < r->range[0]))
! 			if (deleted == 0)
! 				r->range[1] += w->texted.cursor_position-ref;
! 			else if (ref + deleted > r->range[1])
! 				r->range[1] = ref;
! 			else
! 				r->range[1] -= deleted;
  		XeUpdateTextRegion(w, r, False); /* Should fine tune? --msa */
  	    }
  	ChangeWidgetSize(w, True); /* ..only if larger! */
***************
*** 3872,3878 ****
--- 3879,3930 ----
  		_XeTextFeedContent(t->text.inserting, value, length);
  	EndEditing(t, 0);
      }
+ 
+ 
  /*
+ ** XeTextChangeMode
+ **	first insert the (value, length) portion as in XeTextInsert, but
+ **	with side effect that any mode changes introduced by this text
+ **	will override even currently locked modes, and additionally all
+ **	touched attributes will be merged into the locked modes. If the
+ **	same locked attribute is touched multiple times, the last value
+ **	will remain locked.
+ **
+ **	After insert, change the mode of amount characters counting from the
+ **	current insert point. Only modes that are currently locked in the
+ **	insert point are affected.
+ **
+ **	This function does not move insert point, unless the (value, length)
+ **	contains something that cause it to be moved in the standard
+ **	'XeTextInsert' manner.
+ **
+ ** *NOTE*
+ **	Although the (value, length) can contain any string and works almost
+ **	like in XeTextInsert, the primary purpose of this function is that
+ **	the string contains only control sequences only affecting the mode.
+ */
+ void XeTextChangeMode(w, value, length, amount)
+ Widget w;
+ char *value;
+ long length;
+ long amount;
+     {
+ 	XeTextEdWidget t = (XeTextEdWidget)w;
+ 	if (!IsTextEdWidget(w))
+ 		return;
+ 	if (!StartEditing(t, XeTextInsertMode_CURRENT, (XEvent *)NULL))
+ 		return;
+ 	if (length > 0 && value)
+ 	    {
+ 		_XeTextLock(t->text.inserting, FALSE);
+ 		_XeTextFeedContent(t->text.inserting, value, length);
+ 		_XeTextLock(t->text.inserting, TRUE);
+ 	    }
+ 	_XeTextChangeMode(t->text.inserting, amount);
+ 	EndEditing(t, 0);
+     }
+ 
+ /*
  ** XeTextSetInsertionPosition
  **	move the current insert (cursor) position to the specified
  **	position. Current insert point is closed, if it is open.
***************
*** 3889,3894 ****
--- 3941,3947 ----
  
  	StartMoving(t);
  	XeOffset2Locations(t, &position, 1, &t->texted.cursor_location, &xy);
+ 	t->texted.cursor_position = position;
  	UpdateCursorPosition(t, False, True, True);
  	EndMoving(t);
      }
*** TextEd.h.orig	Mon Jan 30 16:05:23 1995
--- TextEd.h	Tue Mar  7 12:33:33 1995
***************
*** 199,204 ****
--- 199,214 ----
  #endif
  	 );
  
+ void XeTextChangeMode
+ 	(
+ #if NeedFunctionPrototypes
+ 	 Widget,	/* TextEd Widget pointer */
+ 	 char *,	/* Pointer to octets to be inserted (modes) */
+ 	 long,		/* Number of octets to insert */
+ 	 long		/* Number of characters to modify after insert */
+ #endif
+ 	 );
+ 
  void XeTextReplaceTagged
  	(
  #if NeedFunctionPrototypes
*** TextImport.c.orig	Tue Feb  7 15:57:07 1995
--- TextImport.c	Tue Mar  7 16:55:30 1995
***************
*** 2353,2359 ****
  /*
  ** SplitSnip
  **	Split Snip t into two at offset, and return the pointer to the
! **	*NEW* snip, which represents the fisrt part of the split.
  **
  **	*** No checks is made. Function assumes the offset <= length.
  */
--- 2353,2359 ----
  /*
  ** SplitSnip
  **	Split Snip t into two at offset, and return the pointer to the
! **	*NEW* snip, which represents the first part of the split.
  **
  **	*** No checks is made. Function assumes the offset <= length.
  */
***************
*** 2564,2569 ****
--- 2564,2698 ----
  	    }
  	return t;
      }
+ 
+ static void CopyLockedModes(cx, t)
+ Context *cx;
+ Snip *t;
+     {
+ 	unsigned long old_font, new_font;
+ 
+ 	old_font = FontSelectInfo(t->mode);
+ 
+ 	t->mode.bits &= ~cx->lock.bits;
+ 	t->mode.bits |= cx->lock.bits & cx->mode.bits;
+ 	if (cx->lock.tag)
+ 		t->mode.tag = cx->lock.tag;
+ 	if (cx->lock.size_modification)
+ 		t->mode.size_modification = cx->mode.size_modification;
+ 	new_font = FontSelectInfo(t->mode);
+ 	/*
+ 	** If mode change affected the font selection, then we must
+ 	** move the snip content into a matching SnipData chunk.
+ 	** (argh.. this mode change function proves to be nastier than
+ 	** I expected... --msa )
+ 	*/
+ 	if (!t->widget && old_font != new_font && t->content.head)
+ 	    {
+ 		int n = t->content.head->bytes * t->length;
+ 
+ 		if (cx->used + n > cx->size ||
+ 		    cx->head->character_set != t->content.head->character_set||
+ 		    new_font != cx->fontinfo)
+ 		    {
+ 			FlushAppend(cx);
+ 			if (cx->size < n)
+ 			    {
+ 				/* Need to reallocate larger head block */
+ 				DerefDataHeader(cx->head);
+ 				cx->size = n>HEAD_MIN_SIZE ? n : HEAD_MIN_SIZE;
+ 				cx->head = (SnipData *)
+ 					XtCalloc(1, XtOffsetOf(SnipData, s[0])
+ 						 + cx->size);
+ 				cx->head->refs = 1; /* cx ref is counted ! */
+ 			    }	
+ 			cx->fontinfo = new_font;
+ 			cx->head->bytes = t->content.head->bytes;
+ 			cx->head->font = NULL;
+ 			cx->head->character_set=t->content.head->character_set;
+ 			cx->first = t;
+ 		    }
+ 		memcpy(&cx->head->s[cx->used], t->data, n);
+ 		cx->head->refs += 1;
+ 		DerefDataHeader(t->content.head);
+ 		t->content.head = cx->head;
+ 		t->data = &cx->head->s[cx->used];
+ 		cx->used += n;
+ 	    }
+ 	t->valid = FALSE;	/* This snip requires new layout */
+     }
+ 
+ /*
+ ** _XeTextChangeMode
+ **	Change the mode of the next 'amount' characters. Only the 'locked'
+ **	modes defined in the current insert context will be changed.
+ **
+ **	amount > 0, change forward from current point,
+ **	amount < 0, change backward from current point
+ */
+ void _XeTextChangeMode(context, amount)
+ XeTextInsertContext context;
+ long amount;
+     {
+ 	Snip *t;
+ 	Snip **h;
+ 	int offset, vlength;
+ 	Context *cx = (Context *)context;
+ 
+ 	if (cx == NULL)
+ 		return;
+ 	h = cx->last ? &cx->last->next : cx->list;
+ 	if (amount > 0)
+ 	    {
+ 		/*
+ 		** Change forward
+ 		*/
+ 		for (t = *h; t != NULL; t = t->next)
+ 			if (IsEditableContent(t->mode.bits))
+ 			    {
+ 				amount -= (vlength = VirtualLength(t));
+ 				if (amount < 0)
+ 				    {
+ 					offset = amount + vlength;
+ 					if (offset > 0 && offset < vlength)
+ 					    {
+ 						t = SplitSnip(cx, t, offset);
+ 						CopyLockedModes(cx, t);
+ 					    }
+ 					break;
+ 				    }
+ 				CopyLockedModes(cx, t);
+ 			    }
+ 	    }
+ 	else if (amount < 0 && *h != NULL)
+ 	    {
+ 		/*
+ 		** Change backward
+ 		*/
+ 		for (t = *h; ; t = PreviousSnip(t))
+ 		    {
+ 			if (IsEditableContent(t->mode.bits))
+ 			    {
+ 				vlength = VirtualLength(t);
+ 				amount += vlength;
+ 				if (amount == 0)
+ 					break;
+ 				else if (amount > 0)
+ 				    {
+ 					if (amount < vlength)
+ 					    {
+ 						(void)SplitSnip(cx, t, amount);
+ 						CopyLockedModes(cx, t);
+ 					    }
+ 					break;
+ 				    }
+ 				CopyLockedModes(cx, t);
+ 			    }
+ 			else if (t->back == cx->list)
+ 				break;
+ 		    }
+ 	    }
+     }
+ 
  
  /*
  ** _XeTextInsertLocation
*** TextImport.h.orig	Tue Feb  7 13:34:41 1995
--- TextImport.h	Tue Mar  7 11:15:48 1995
***************
*** 71,76 ****
--- 71,84 ----
  #endif
  	 );
  
+ void _XeTextChangeMode
+ 	(
+ #if NeedFunctionPrototypes
+ 	 XeTextInsertContext,	/* Context Pointer */
+ 	 long			/* Characters to Modify */
+ #endif
+ 	 );
+ 
  Snip *_XeTextEndContent
  	(
  #if NeedFunctionPrototypes
