Blame lib/Xm/TextStrSo.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/ 
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$XConsortium: TextStrSo.c /main/14 1996/10/23 16:05:21 cde-osf $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/* (c) Copyright 1989, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
Packit b099d7
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
Packit b099d7
Packit b099d7
#define FIX_1320
Packit b099d7
Packit b099d7
#include <ctype.h>
Packit b099d7
#include <limits.h>
Packit b099d7
#include <X11/Xatom.h>
Packit b099d7
#include <X11/Xmd.h>
Packit b099d7
#include <Xm/AtomMgr.h>
Packit b099d7
#include <Xm/TextSelP.h>
Packit b099d7
#include <Xm/TextStrSoP.h>
Packit b099d7
#include <Xm/XmosP.h>
Packit b099d7
#include "XmI.h"		/* for _XmValidTimestamp() */
Packit b099d7
#include "TextI.h"
Packit b099d7
#include "TextStrSoI.h"
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static void AddWidget(XmTextSource source,
Packit b099d7
		      XmTextWidget tw);
Packit b099d7
static char * _XmStringSourceGetChar(XmSourceData data,
Packit b099d7
				     XmTextPosition position);
Packit b099d7
static int CountLines(XmTextSource source,
Packit b099d7
		      XmTextPosition start,
Packit b099d7
		      unsigned long length);
Packit b099d7
static void RemoveWidget(XmTextSource source,
Packit b099d7
			 XmTextWidget tw);
Packit b099d7
static void _XmStringSourceReadString(XmTextSource source,
Packit b099d7
				      int start,
Packit b099d7
				      XmTextBlock block);
Packit b099d7
static XmTextPosition ReadSource(XmTextSource source,
Packit b099d7
				 XmTextPosition position,
Packit b099d7
				 XmTextPosition last_position,
Packit b099d7
				 XmTextBlock block);
Packit b099d7
static XmTextStatus Replace(XmTextWidget initiator,
Packit b099d7
			    XEvent *event,
Packit b099d7
			    XmTextPosition *start,
Packit b099d7
			    XmTextPosition *end,
Packit b099d7
			    XmTextBlock block,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			    int call_callbacks);
Packit b099d7
#else
Packit b099d7
                            Boolean call_callbacks);
Packit b099d7
#endif /* NeedsWidePrototypes */
Packit b099d7
static void ScanParagraph(XmSourceData data,
Packit b099d7
			  XmTextPosition *new_position,
Packit b099d7
			  XmTextScanDirection dir,
Packit b099d7
			  int ddir,
Packit b099d7
			  XmTextPosition *last_char);
Packit b099d7
static XmTextPosition Scan(XmTextSource source,
Packit b099d7
			   XmTextPosition pos,
Packit b099d7
			   XmTextScanType sType,
Packit b099d7
			   XmTextScanDirection dir,
Packit b099d7
			   int count,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			   int include);
Packit b099d7
#else
Packit b099d7
                           Boolean include);
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
static Boolean GetSelection(XmTextSource source,
Packit b099d7
			    XmTextPosition *left,
Packit b099d7
			    XmTextPosition *right);
Packit b099d7
static void SetSelection(XmTextSource source,
Packit b099d7
			 XmTextPosition left,
Packit b099d7
			 XmTextPosition right,
Packit b099d7
			 Time set_time);
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7
#define TEXT_INCREMENT 1024
Packit b099d7
#define TEXT_INITIAL_INCREM 64
Packit b099d7
Packit b099d7
/* Convert a stream of bytes into a char*, BITS16*, or wchar_t* array. 
Packit b099d7
 * Return number of characters created.
Packit b099d7
 *
Packit b099d7
 * If num_chars == 1, don't add a null terminator, else if a null terminator
Packit b099d7
 * is present on the byte stream, convert it and add it to the character
Packit b099d7
 * array;  Count returned does not include NULL terminator (just like strlen).
Packit b099d7
 *
Packit b099d7
 * This routine assumes that a BITS16 is two-bytes;
Packit b099d7
 * the routine must be modified if these assumptions are incorrect.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/* ARGSUSED */
Packit b099d7
int
Packit b099d7
_XmTextBytesToCharacters(char * characters, 
Packit b099d7
			 char * bytes,
Packit b099d7
			 int num_chars, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			 int add_null_terminator,
Packit b099d7
#else
Packit b099d7
			 Boolean add_null_terminator,
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
			 int max_char_size)
Packit b099d7
{
Packit b099d7
  unsigned char * tmp_bytes;
Packit b099d7
  int num_bytes; 
Packit b099d7
  int count=0;
Packit b099d7
  BITS16 *bits16_ptr, temp_bits16;
Packit b099d7
  wchar_t *wchar_t_ptr;
Packit b099d7
  
Packit b099d7
  
Packit b099d7
  /* If 0 characters requested, or a null pointer passed, dont do
Packit b099d7
   * anything... just return 0 characters converted.
Packit b099d7
   */
Packit b099d7
  
Packit b099d7
  if (num_chars == 0 || bytes == NULL) return 0;
Packit b099d7
  
Packit b099d7
  switch (max_char_size) {
Packit b099d7
  case 1: {
Packit b099d7
    (void) memcpy((void*)characters, (void*)bytes, num_chars);
Packit b099d7
    count = num_chars;
Packit b099d7
    break;
Packit b099d7
  } /* end case 1 */
Packit b099d7
  case 2: {
Packit b099d7
    bits16_ptr = (BITS16 *) characters;
Packit b099d7
    tmp_bytes = (unsigned char*) bytes;
Packit b099d7
    for (
Packit b099d7
#ifndef NO_MULTIBYTE
Packit b099d7
	 num_bytes = mblen((char*)tmp_bytes, max_char_size), 
Packit b099d7
#else
Packit b099d7
	 num_bytes = *tmp_bytes ? 1 : 0,
Packit b099d7
#endif
Packit b099d7
	 temp_bits16 = 0; 
Packit b099d7
	 num_chars > 0 && num_bytes > 0;
Packit b099d7
	 num_chars--,
Packit b099d7
#ifndef NO_MULTIBYTE
Packit b099d7
	 num_bytes = mblen((char*)tmp_bytes, max_char_size), 
Packit b099d7
#else
Packit b099d7
	 num_bytes = *tmp_bytes ? 1 : 0,
Packit b099d7
#endif
Packit b099d7
	 temp_bits16 = 0, bits16_ptr ++) {
Packit b099d7
      if (num_bytes == 1) {
Packit b099d7
	temp_bits16 = (BITS16) *tmp_bytes++;
Packit b099d7
      } else {
Packit b099d7
	temp_bits16 = (BITS16) *tmp_bytes++;
Packit b099d7
	temp_bits16 = temp_bits16 << 8;
Packit b099d7
	temp_bits16 |= (BITS16) *tmp_bytes++;
Packit b099d7
      }
Packit b099d7
      *bits16_ptr = temp_bits16;
Packit b099d7
      count++;
Packit b099d7
    }
Packit b099d7
    /* if bytes is NULL terminated, characters should be too */
Packit b099d7
    if (add_null_terminator == True)
Packit b099d7
      *bits16_ptr = (BITS16) 0;  
Packit b099d7
    break;
Packit b099d7
  } /* end case 2 */
Packit b099d7
  default: {
Packit b099d7
    wchar_t_ptr = (wchar_t *)characters;
Packit b099d7
    count = mbstowcs(wchar_t_ptr, bytes, num_chars);
Packit b099d7
    if (add_null_terminator == True && count >= 0)
Packit b099d7
      wchar_t_ptr[count] = (wchar_t)0;
Packit b099d7
    break;
Packit b099d7
  } /* end default */
Packit b099d7
  } /* end switch */
Packit b099d7
  
Packit b099d7
  return count;
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Convert an array of char*, BITS16*, or wchar_t* into a stream of bytes.
Packit b099d7
 * Return the number of bytes placed into 'bytes'
Packit b099d7
 *
Packit b099d7
 * Null terminate the byte stream - caller better have alloc'ed enough space!
Packit b099d7
 */
Packit b099d7
Packit b099d7
/* ARGSUSED */
Packit b099d7
int
Packit b099d7
_XmTextCharactersToBytes(char * bytes,
Packit b099d7
			 char * characters,
Packit b099d7
			 int num_chars,
Packit b099d7
			 int max_char_size)
Packit b099d7
{
Packit b099d7
  unsigned char *temp_char;
Packit b099d7
  unsigned char *byte_ptr;
Packit b099d7
  int count = 0;
Packit b099d7
  int i, j;
Packit b099d7
  BITS16 *bits16_ptr, temp_bits16;
Packit b099d7
  wchar_t *wchars;
Packit b099d7
Packit b099d7
  if (num_chars == 0 || characters == 0) {
Packit b099d7
    *bytes = '\0';
Packit b099d7
    return 0;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  switch (max_char_size) {
Packit b099d7
  case 1: {
Packit b099d7
    (void) memcpy((void*)bytes, (void*)characters, num_chars);
Packit b099d7
    count = num_chars;
Packit b099d7
    break;
Packit b099d7
  } /* end case 1 */
Packit b099d7
  case 2: {
Packit b099d7
    bits16_ptr = (BITS16 *) characters;
Packit b099d7
    byte_ptr = (unsigned char*) bytes;
Packit b099d7
    temp_char = (unsigned char*) XtMalloc (max_char_size);
Packit b099d7
    for (i = 0; i < num_chars && *bits16_ptr != 0; i++, bits16_ptr++) {
Packit b099d7
      temp_bits16 = *bits16_ptr;
Packit b099d7
      /* create an array of chars; char[max_char_size - 1] contains the 
Packit b099d7
       * low order byte */
Packit b099d7
      for (j = max_char_size - 1; j >= 0; j--) {
Packit b099d7
	temp_char[j] = (unsigned char)(temp_bits16 & 0377);
Packit b099d7
	temp_bits16 = temp_bits16 >> 8;
Packit b099d7
      }
Packit b099d7
      /* start with high order byte.  If any byte is 0, skip it. */
Packit b099d7
      for (j = 0; j < max_char_size; j++) { 
Packit b099d7
	if (temp_char[j] > 0) {
Packit b099d7
	  *byte_ptr = temp_char[j];
Packit b099d7
	  byte_ptr++; count++;
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    XtFree ((char*)temp_char);
Packit b099d7
    if (count < num_chars) *byte_ptr = '\0';
Packit b099d7
    break;
Packit b099d7
  } /* end case 2 */
Packit b099d7
  default: {
Packit b099d7
    int nbytes;
Packit b099d7
Packit b099d7
    wchars = (wchar_t *)characters;
Packit b099d7
    for (i = 0; i < num_chars && *wchars != 0L; i++, wchars++) {
Packit b099d7
      nbytes = wctomb(bytes, *wchars);
Packit b099d7
      if (nbytes < 0)
Packit b099d7
	break; /* illegal char */
Packit b099d7
      count += nbytes;
Packit b099d7
      bytes += nbytes;
Packit b099d7
    }
Packit b099d7
    if (count >= 0)
Packit b099d7
      bytes[count] = '\0';
Packit b099d7
    break;
Packit b099d7
  } /* end default */
Packit b099d7
  } /* end switch */
Packit b099d7
  return (count);    /* return the number of bytes placed in bptr */
Packit b099d7
}
Packit b099d7
Packit b099d7
char * 
Packit b099d7
_XmStringSourceGetString(XmTextWidget tw,
Packit b099d7
			 XmTextPosition from,
Packit b099d7
			 XmTextPosition to,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			 int want_wchar)
Packit b099d7
#else
Packit b099d7
                         Boolean want_wchar)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
  char *buf;
Packit b099d7
  wchar_t *wc_buf;
Packit b099d7
  XmTextBlockRec block;
Packit b099d7
  int destpos;
Packit b099d7
  XmTextPosition pos, ret_pos;
Packit b099d7
  int return_val = 0;
Packit b099d7
Packit b099d7
  destpos = 0;
Packit b099d7
  if (!want_wchar) {
Packit b099d7
    /* NOTE: to - from could result in a truncated long. */
Packit b099d7
    buf = XtMalloc(((int)(to - from) + 1) * (int)tw->text.char_size);
Packit b099d7
    for (pos = from; pos < to; ) {
Packit b099d7
      pos = ReadSource(tw->text.source, pos, to, &block);
Packit b099d7
      if (block.length == 0)
Packit b099d7
	break;
Packit b099d7
      
Packit b099d7
      (void)memcpy((void*)&buf[destpos], (void*)block.ptr, block.length);
Packit b099d7
      destpos += block.length;
Packit b099d7
    }
Packit b099d7
    buf[destpos] = 0;
Packit b099d7
    return buf;
Packit b099d7
  } else { /* want buffer of wchar_t * data */
Packit b099d7
    /* NOTE: to - from could result in a truncated long. */
Packit b099d7
    buf = XtMalloc(((int)(to - from) + 1) * sizeof(wchar_t));
Packit b099d7
    wc_buf = (wchar_t *)buf;
Packit b099d7
    for (pos = from; pos < to; ) {
Packit b099d7
      ret_pos = ReadSource(tw->text.source, pos, to, &block);
Packit b099d7
      if (block.length == 0)
Packit b099d7
	break;
Packit b099d7
      
Packit b099d7
      /* NOTE: ret_pos - pos could result in a truncated long. */
Packit b099d7
      return_val =  mbstowcs(&wc_buf[destpos], block.ptr,
Packit b099d7
			     (unsigned int) (ret_pos - pos));
Packit b099d7
      if (return_val > 0) destpos += return_val;
Packit b099d7
      pos = ret_pos;
Packit b099d7
    }
Packit b099d7
    wc_buf[destpos] = (wchar_t)0L;
Packit b099d7
    return ((char*)wc_buf);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
static void 
Packit b099d7
AddWidget(XmTextSource source,
Packit b099d7
	  XmTextWidget tw)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  data->numwidgets++;
Packit b099d7
  data->widgets = (XmTextWidget *)
Packit b099d7
    XtRealloc((char *) data->widgets,
Packit b099d7
	      (unsigned) (sizeof(XmTextWidget) * data->numwidgets));
Packit b099d7
  data->widgets[data->numwidgets - 1] = tw;
Packit b099d7
  
Packit b099d7
  if (data->numwidgets == 1)
Packit b099d7
    _XmTextSetHighlight((Widget) tw, 0, tw->text.last_position, 
Packit b099d7
		       XmHIGHLIGHT_NORMAL);
Packit b099d7
  else {
Packit b099d7
    tw->text.highlight.list = (_XmHighlightRec *)
Packit b099d7
      XtRealloc((char *) tw->text.highlight.list, 
Packit b099d7
		data->widgets[0]->text.highlight.maximum *
Packit b099d7
		sizeof(_XmHighlightRec));
Packit b099d7
    tw->text.highlight.maximum = data->widgets[0]->text.highlight.maximum;
Packit b099d7
    tw->text.highlight.number = data->widgets[0]->text.highlight.number;
Packit b099d7
    memmove((void *) tw->text.highlight.list, 
Packit b099d7
	    (void *) data->widgets[0]->text.highlight.list,
Packit b099d7
	    (size_t) data->widgets[0]->text.highlight.number *
Packit b099d7
	    sizeof(_XmHighlightRec));
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  
Packit b099d7
  if (data->hasselection && data->numwidgets == 1) {
Packit b099d7
    Time select_time = XtLastTimestampProcessed(XtDisplay((Widget)tw));
Packit b099d7
    if (!select_time) select_time = _XmValidTimestamp((Widget)tw);
Packit b099d7
    if (!XmePrimarySource((Widget) data->widgets[0], select_time)) {
Packit b099d7
      (*source->SetSelection)(source, 1, 0, select_time);
Packit b099d7
    } else {
Packit b099d7
      XmAnyCallbackStruct cb;
Packit b099d7
      
Packit b099d7
      data->prim_time = select_time;
Packit b099d7
      cb.reason = XmCR_GAIN_PRIMARY;
Packit b099d7
      cb.event = NULL;
Packit b099d7
      XtCallCallbackList ((Widget) data->widgets[0],
Packit b099d7
			  data->widgets[0]->text.gain_primary_callback,
Packit b099d7
			  (XtPointer) &cb;;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/********************************<->***********************************/
Packit b099d7
static char * 
Packit b099d7
_XmStringSourceGetChar(XmSourceData data,
Packit b099d7
		       XmTextPosition position)       /* starting position */
Packit b099d7
{
Packit b099d7
  /* gap_size is the number of character in the gap, not number of bytes */
Packit b099d7
  register int gap_size;
Packit b099d7
  register XmTextPosition char_pos;
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  int char_size;
Packit b099d7
  
Packit b099d7
  if (tw->text.char_size > 1) {
Packit b099d7
    if (tw->text.char_size == 2)
Packit b099d7
      char_size = 2;
Packit b099d7
    else
Packit b099d7
      char_size = sizeof(wchar_t);
Packit b099d7
    char_pos = position * char_size;
Packit b099d7
    
Packit b099d7
    /* regardless of what it contains, data->ptr is treated as a char * ptr */
Packit b099d7
    if (data->ptr + char_pos < data->gap_start)
Packit b099d7
      return (&data->ptr[char_pos]);
Packit b099d7
    
Packit b099d7
    gap_size = (data->gap_end - data->gap_start) / char_size;
Packit b099d7
    if (position + gap_size >= data->maxlength)
Packit b099d7
      return ("");
Packit b099d7
    return (&data->ptr[(position + gap_size) * char_size]);
Packit b099d7
  } else {
Packit b099d7
    char_pos = position;
Packit b099d7
    /* regardless of what it contains, data->ptr is treated as a char * ptr */
Packit b099d7
    if (data->ptr + char_pos < data->gap_start)
Packit b099d7
      return (&data->ptr[char_pos]);
Packit b099d7
    
Packit b099d7
    gap_size = (data->gap_end - data->gap_start);
Packit b099d7
    if (char_pos + gap_size >= data->maxlength)
Packit b099d7
      return ("");
Packit b099d7
    return (&data->ptr[(char_pos + gap_size)]);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/*DELTA: length IS NOW TREATED AS NUMBER OF CHARACTERS - CALLERS MUST CHANGE*/
Packit b099d7
static int 
Packit b099d7
CountLines(XmTextSource source,
Packit b099d7
	   XmTextPosition start,
Packit b099d7
	   unsigned long length)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  int num_lines = 0;
Packit b099d7
  unsigned long seg_length;
Packit b099d7
  char *ptr;
Packit b099d7
  BITS16 *bits16_ptr, *bits16_gap_start, *bits16_gap_end;
Packit b099d7
  wchar_t *wchar_t_ptr, *wchar_t_gap_start, *wchar_t_gap_end;
Packit b099d7
  
Packit b099d7
  /* verify that the 'start' and 'length' parameters are reasonable */
Packit b099d7
  
Packit b099d7
  if (start + length > data->length)
Packit b099d7
    length = data->length - start;
Packit b099d7
  if (length == 0) return num_lines;
Packit b099d7
  
Packit b099d7
  seg_length = (data->gap_start - data->ptr) / (tw->text.char_size < 3 ?
Packit b099d7
						(int)tw->text.char_size :
Packit b099d7
						sizeof(wchar_t));
Packit b099d7
  
Packit b099d7
  /* make sure the segment length is not greater than the length desired */
Packit b099d7
  if (length < seg_length) seg_length = length;
Packit b099d7
  
Packit b099d7
  switch ((int)tw->text.char_size) {
Packit b099d7
  case 1: {
Packit b099d7
    /* setup the variables for the search of new lines before the gap */
Packit b099d7
    ptr = data->ptr + start;
Packit b099d7
    
Packit b099d7
    /* search up to gap */
Packit b099d7
    while (seg_length--) {
Packit b099d7
      if (*ptr++ == *(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    /* check to see if we need more data after the gap */
Packit b099d7
    if ((int)length > data->gap_start - (data->ptr + start)) {
Packit b099d7
      if (data->gap_start - (data->ptr + start) > 0) /* if we searched
Packit b099d7
						      * before gap,
Packit b099d7
						      * adjust length */
Packit b099d7
	length -= data->gap_start - (data->ptr + start);
Packit b099d7
      ptr = data->gap_end;
Packit b099d7
      
Packit b099d7
      /* continue search till length is completed */
Packit b099d7
      while (length--) {
Packit b099d7
	if (*ptr++ == *(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  } /* end case 1 */
Packit b099d7
  case 2: {
Packit b099d7
    /* setup the variables for the search of new lines before the gap */
Packit b099d7
    bits16_ptr = (BITS16 *) data->ptr;
Packit b099d7
    bits16_gap_start = (BITS16 *) data->gap_start;
Packit b099d7
    bits16_gap_end = (BITS16 *) data->gap_end;
Packit b099d7
    bits16_ptr += start;
Packit b099d7
    
Packit b099d7
    /* search up to gap */
Packit b099d7
    while (seg_length--) {
Packit b099d7
      if (*bits16_ptr++ == *(BITS16 *)(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    /* check to see if we need more data after the gap */
Packit b099d7
    if ((int)length > bits16_gap_start - ((BITS16 *)data->ptr + start)) {
Packit b099d7
      /* if we searched before gap, adjust length */
Packit b099d7
      if (bits16_gap_start - ((BITS16 *)data->ptr + start) > 0)
Packit b099d7
	length -= bits16_gap_start - ((BITS16 *)data->ptr + start);
Packit b099d7
      bits16_ptr = bits16_gap_end;
Packit b099d7
      
Packit b099d7
      /* continue search till length is completed */
Packit b099d7
      while (length--) {
Packit b099d7
	if (*bits16_ptr++ == *(BITS16 *)(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  } /* end case 2 */
Packit b099d7
  default: {
Packit b099d7
    /* setup the variables for the search of new lines before the gap */
Packit b099d7
    wchar_t_ptr = (wchar_t *) data->ptr;
Packit b099d7
    wchar_t_gap_start = (wchar_t *) data->gap_start;
Packit b099d7
    wchar_t_gap_end = (wchar_t *) data->gap_end;
Packit b099d7
    wchar_t_ptr += start;
Packit b099d7
    
Packit b099d7
    /* search up to gap */
Packit b099d7
    while (seg_length--) {
Packit b099d7
      if (*wchar_t_ptr++ == *(wchar_t *)(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    /* check to see if we need more data after the gap */
Packit b099d7
    if ((int)length > wchar_t_gap_start - ((wchar_t *)data->ptr + start)) {
Packit b099d7
      /* if we searched before gap, adjust length */
Packit b099d7
      if (wchar_t_gap_start - ((wchar_t *)data->ptr + start) > 0)
Packit b099d7
	length -= wchar_t_gap_start - ((wchar_t *)data->ptr + start);
Packit b099d7
      wchar_t_ptr = wchar_t_gap_end;
Packit b099d7
      
Packit b099d7
      /* continue search till length is completed */
Packit b099d7
      while (length--) {
Packit b099d7
	if (*wchar_t_ptr++ == *(wchar_t *)(data->PSWC_NWLN)) ++num_lines;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  } /* end default */
Packit b099d7
  } /* end switch */
Packit b099d7
  return num_lines;
Packit b099d7
}
Packit b099d7
Packit b099d7
static void 
Packit b099d7
RemoveWidget(XmTextSource source,
Packit b099d7
	     XmTextWidget tw)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  int i;
Packit b099d7
  for (i=0; i<data->numwidgets; i++) {
Packit b099d7
    if (data->widgets[i] == tw) {
Packit b099d7
      XmTextPosition left, right;
Packit b099d7
      Boolean had_selection = False;
Packit b099d7
      Time select_time =
Packit b099d7
	XtLastTimestampProcessed(XtDisplay((Widget)tw));
Packit b099d7
      
Packit b099d7
      if (data->hasselection) {
Packit b099d7
	(*source->GetSelection)(source, &left, &right);
Packit b099d7
	(*source->SetSelection)(source, 1, -999, select_time);
Packit b099d7
	had_selection = True;
Packit b099d7
      }
Packit b099d7
      data->numwidgets--;
Packit b099d7
      data->widgets[i] = data->widgets[data->numwidgets];
Packit b099d7
      if (i == 0 && data->numwidgets > 0 && had_selection)
Packit b099d7
	(*source->SetSelection)(source, left, right, select_time);
Packit b099d7
      if (data->numwidgets == 0) _XmStringSourceDestroy(source);
Packit b099d7
      return;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean *
Packit b099d7
_XmStringSourceGetPending(XmTextWidget tw)
Packit b099d7
{
Packit b099d7
  Boolean *pending;
Packit b099d7
  XmSourceData data = tw->text.source->data;
Packit b099d7
  int i;
Packit b099d7
  
Packit b099d7
  pending = (Boolean *)XtMalloc(data->numwidgets*sizeof(Boolean));
Packit b099d7
  for (i=0; i<data->numwidgets; i++) 
Packit b099d7
    pending[i] = ((XmTextWidget)data->widgets[i])->text.pendingoff;
Packit b099d7
Packit b099d7
  return pending;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmStringSourceSetPending(XmTextWidget tw,
Packit b099d7
			  Boolean *pending)
Packit b099d7
{
Packit b099d7
  XmSourceData data = tw->text.source->data;
Packit b099d7
  int i;
Packit b099d7
  
Packit b099d7
  if ((long)pending > 1)
Packit b099d7
    for (i=0; i<data->numwidgets; i++) 
Packit b099d7
      ((XmTextWidget)data->widgets[i])->text.pendingoff = pending[i];
Packit b099d7
  else
Packit b099d7
    for (i=0; i<data->numwidgets; i++) 
Packit b099d7
      ((XmTextWidget)data->widgets[i])->text.pendingoff = 
Packit b099d7
	(Boolean)(long)pending;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Determines where to move the gap and calls memmove to move the gap.
Packit b099d7
 */
Packit b099d7
/********************************<->***********************************/
Packit b099d7
void 
Packit b099d7
_XmStringSourceSetGappedBuffer(XmSourceData data,
Packit b099d7
			       XmTextPosition position) /* starting position */
Packit b099d7
{
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  int count, char_size = (tw->text.char_size < 3 ? 
Packit b099d7
			  (int)tw->text.char_size :
Packit b099d7
			  sizeof(wchar_t));
Packit b099d7
  
Packit b099d7
  /* if no change in gap placement, return */
Packit b099d7
  if (data->ptr + (position * char_size) == data->gap_start)
Packit b099d7
    return;
Packit b099d7
  
Packit b099d7
  if (data->ptr + (position * char_size) < data->gap_start) {
Packit b099d7
    /* move gap to the left */
Packit b099d7
    count = data->gap_start - 
Packit b099d7
      (data->ptr + (position * char_size));
Packit b099d7
    memmove(data->gap_end - count, data->ptr + (position*char_size), count);
Packit b099d7
    data->gap_start -= count; /* ie, data->gap_start = position; */
Packit b099d7
    data->gap_end -= count;   /* ie, data->gap_end = position + gap_size; */
Packit b099d7
  } else {
Packit b099d7
    /* move gap to the right */
Packit b099d7
    count = (data->ptr + 
Packit b099d7
	     (position * char_size)) - data->gap_start;
Packit b099d7
    memmove(data->gap_start, data->gap_end, count);
Packit b099d7
    data->gap_start += count; /* ie, data->gap_start = position; */
Packit b099d7
    data->gap_end += count;   /* ie, data->gap_end = position + gap_size; */
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/********************************<->***********************************/
Packit b099d7
/* The only caller of this routine expects to get char* in block */
Packit b099d7
static void 
Packit b099d7
_XmStringSourceReadString(XmTextSource source,
Packit b099d7
			  int start,
Packit b099d7
			  XmTextBlock block)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  int gap_size = data->gap_end - data->gap_start;
Packit b099d7
  int byte_start = start * (tw->text.char_size < 3 ?
Packit b099d7
			    (int)tw->text.char_size :
Packit b099d7
			    sizeof(wchar_t));
Packit b099d7
  
Packit b099d7
  if (data->ptr + byte_start + block->length <= data->gap_start)
Packit b099d7
    block->ptr = data->ptr + byte_start;
Packit b099d7
  else if (data->ptr + byte_start + gap_size >= data->gap_end)
Packit b099d7
    block->ptr = data->ptr + byte_start + gap_size;
Packit b099d7
  else {
Packit b099d7
    block->ptr = data->ptr + byte_start;
Packit b099d7
    block->length = data->gap_start - (data->ptr + byte_start);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Caller wants block to contain char*; _XmStringSourceReadString provides
Packit b099d7
 * char*, BITS16* or wchar_t*; so we need to modify what it gives us.
Packit b099d7
 */
Packit b099d7
static XmTextPosition 
Packit b099d7
ReadSource(XmTextSource source,
Packit b099d7
	   XmTextPosition position,       /* starting position */
Packit b099d7
	   XmTextPosition last_position,  /* The last position we're interested
Packit b099d7
					     in.  Don't return info about any
Packit b099d7
					     later positions. */
Packit b099d7
	   XmTextBlock block)            /* RETURN: text read in */
Packit b099d7
{
Packit b099d7
  XmTextPosition return_pos;
Packit b099d7
  int num_bytes;
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  int char_size = (tw->text.char_size < 3 ?
Packit b099d7
		   (int)tw->text.char_size :
Packit b099d7
		   sizeof(wchar_t));
Packit b099d7
  
Packit b099d7
  if (last_position > data->length) last_position = data->length;
Packit b099d7
  /* NOTE: the length calculation could result in a truncated long */
Packit b099d7
  block->length = (int)((last_position - position) * char_size);
Packit b099d7
  if (block->length < 0 ) block->length = 0;
Packit b099d7
  block->format = XmFMT_8_BIT;
Packit b099d7
  _XmStringSourceReadString(source, (int)position, block);
Packit b099d7
  
Packit b099d7
  if (block->length > 0) {
Packit b099d7
    if (data->old_length == 0) {
Packit b099d7
      data->value = (char *) 
Packit b099d7
	XtMalloc((unsigned)(block->length + 1) * (int)tw->text.char_size);
Packit b099d7
      data->old_length = block->length;
Packit b099d7
    } else if (block->length > data->old_length) {
Packit b099d7
      data->value = XtRealloc(data->value, (unsigned)
Packit b099d7
			      ((block->length + 1) * (int)tw->text.char_size));
Packit b099d7
      data->old_length = block->length;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    if ((int)tw->text.char_size == 1) {
Packit b099d7
      return_pos = position + block->length;
Packit b099d7
    } else {
Packit b099d7
      return_pos = position + (block->length / char_size);
Packit b099d7
      num_bytes = _XmTextCharactersToBytes(data->value, block->ptr, 
Packit b099d7
					   block->length / char_size,
Packit b099d7
					   (int)tw->text.char_size);
Packit b099d7
      block->length = num_bytes;
Packit b099d7
      block->ptr = data->value;
Packit b099d7
    }
Packit b099d7
    return return_pos;
Packit b099d7
  } else
Packit b099d7
    return 0;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmTextValidate(XmTextPosition * start,
Packit b099d7
		XmTextPosition * end,
Packit b099d7
		int maxsize)
Packit b099d7
{
Packit b099d7
  if (*start < 0) *start = 0;
Packit b099d7
  if (*start > maxsize) {
Packit b099d7
    *start = maxsize;
Packit b099d7
  }
Packit b099d7
  if (*end < 0) *end = 0;
Packit b099d7
  if (*end > maxsize) {
Packit b099d7
    *end = maxsize;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  if (*start > *end) { 
Packit b099d7
    XmTextPosition tmp; /* tmp variable for swapping positions */
Packit b099d7
    tmp = *end;    
Packit b099d7
    *end = *start;
Packit b099d7
    *start = tmp;
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
_XmTextModifyVerify(XmTextWidget initiator,
Packit b099d7
		    XEvent *event,
Packit b099d7
		    XmTextPosition *start,
Packit b099d7
		    XmTextPosition *end,
Packit b099d7
		    XmTextPosition *cursorPos,	/* RETURN, may be NULL if not */
Packit b099d7
		    XmTextBlock block,
Packit b099d7
		    XmTextBlock newblock,	/* RETURN */
Packit b099d7
		    Boolean *freeBlock)
Packit b099d7
{
Packit b099d7
  register XmSourceData data = initiator->text.source->data;
Packit b099d7
  register long delta;
Packit b099d7
  register int block_num_chars;  /* number of characters in the block */
Packit b099d7
  XmTextPosition newInsert = initiator->text.cursor_position;
Packit b099d7
  XmTextVerifyCallbackStruct tvcb;
Packit b099d7
  XmTextVerifyCallbackStructWcs wcs_tvcb;
Packit b099d7
  XmTextBlockRecWcs wcs_newblock;
Packit b099d7
  
Packit b099d7
  *freeBlock = False;
Packit b099d7
  
Packit b099d7
  if (*start == *end && block->length == 0) return False;
Packit b099d7
  
Packit b099d7
  _XmTextValidate(start, end, data->length);
Packit b099d7
  
Packit b099d7
    newblock->length = block->length; 	/* RETURNed values */
Packit b099d7
    newblock->format = block->format; 
Packit b099d7
    newblock->ptr = block->ptr; 
Packit b099d7
    
Packit b099d7
    if (!initiator->text.modify_verify_callback &&
Packit b099d7
        !initiator->text.wcs_modify_verify_callback) 
Packit b099d7
    {
Packit b099d7
        /* we have neither callback, so do expensive 
Packit b099d7
        ** computation only if cursorPos is needed 
Packit b099d7
        */
Packit b099d7
        if (cursorPos)
Packit b099d7
  	{
Packit b099d7
    	block_num_chars = _XmTextCountCharacters(block->ptr, block->length);
Packit b099d7
    	*cursorPos = *start + block_num_chars;
Packit b099d7
  	}
Packit b099d7
      return True;
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
    /* cursorPos may be needed to be returned. If not, and if the text is
Packit b099d7
    ** not editable, can drop out now
Packit b099d7
    */
Packit b099d7
    if (!cursorPos && !data->editable)
Packit b099d7
      return False;
Packit b099d7
  
Packit b099d7
    /* there is at least one callback, so block_num_chars is needed; 
Packit b099d7
    ** this is the potentially-expensive operation that we're trying to avoid 
Packit b099d7
    */
Packit b099d7
    block_num_chars = _XmTextCountCharacters(block->ptr, block->length);
Packit b099d7
    if (cursorPos) *cursorPos = *start + block_num_chars;
Packit b099d7
    
Packit b099d7
    if (!data->editable)	/* if cursorPos was needed, it's set; can now drop out */
Packit b099d7
      return False;
Packit b099d7
  
Packit b099d7
    /* we have at least one callback on editable text, and cursorPos may or may
Packit b099d7
    ** not need to be set. block_num_chars has been set, so perform some other 
Packit b099d7
    ** quick evaluations on whether or not the modify is reasonable. Then
Packit b099d7
    ** call one or both of the callbacks, and if necessary reset cursorPos.
Packit b099d7
    */
Packit b099d7
  
Packit b099d7
    delta = block_num_chars - (*end - *start);
Packit b099d7
    if (delta > 0 && (data->length + delta > data->maxallowed))
Packit b099d7
      return False;
Packit b099d7
  
Packit b099d7
  /* If both modify_verify and modify_verify_wcs are registered:
Packit b099d7
   *    - first call the char* callback, then
Packit b099d7
   *    - pass the modified data from the char* callback to the
Packit b099d7
   *      wchar_t callback.
Packit b099d7
   * If programmers set both callback lists, they get's what they asked for.
Packit b099d7
   */
Packit b099d7
  
Packit b099d7
  wcs_newblock.wcsptr = (wchar_t *)NULL;
Packit b099d7
  wcs_newblock.length = 0;
Packit b099d7
  
Packit b099d7
  /* If there are char* callbacks registered, call them. */
Packit b099d7
  if (initiator->text.modify_verify_callback) {
Packit b099d7
    /* Fill in the block to pass to the callback. */
Packit b099d7
    if (block->length) {
Packit b099d7
      newblock->ptr = (char *) XtMalloc(block->length + 1);
Packit b099d7
      *freeBlock = True;
Packit b099d7
      (void) memcpy((void*) newblock->ptr, (void*) block->ptr,
Packit b099d7
		    block->length);
Packit b099d7
      newblock->ptr[block->length] = '\0';
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    /* Call Verification Callback to indicate that text is being modified */
Packit b099d7
    tvcb.reason = XmCR_MODIFYING_TEXT_VALUE;
Packit b099d7
    tvcb.event = event;
Packit b099d7
    tvcb.currInsert = (XmTextPosition) (initiator->text.cursor_position);
Packit b099d7
    tvcb.newInsert = (XmTextPosition) (initiator->text.cursor_position);
Packit b099d7
    tvcb.startPos = *start;
Packit b099d7
    tvcb.endPos = *end;
Packit b099d7
    tvcb.doit = True;
Packit b099d7
    tvcb.text = newblock;
Packit b099d7
    XtCallCallbackList ((Widget) initiator,
Packit b099d7
			initiator->text.modify_verify_callback,
Packit b099d7
			(XtPointer) &tvcb);
Packit b099d7
    /* If doit flag is false, application wants to negate the action,
Packit b099d7
     * so free allocate space and return False.
Packit b099d7
     */
Packit b099d7
    if (!tvcb.doit) {
Packit b099d7
      if (newblock->ptr && newblock->ptr != block->ptr) 
Packit b099d7
	XtFree(newblock->ptr);
Packit b099d7
      *freeBlock = False;
Packit b099d7
      return False;
Packit b099d7
    } else {
Packit b099d7
      *start = tvcb.startPos;
Packit b099d7
      *end = tvcb.endPos;
Packit b099d7
      newInsert = tvcb.newInsert;
Packit b099d7
      _XmTextValidate (start, end, data->length);
Packit b099d7
      if (tvcb.text != newblock || tvcb.text->ptr != newblock->ptr) {
Packit b099d7
	newblock->length = tvcb.text->length;
Packit b099d7
	if (newblock->ptr && newblock->ptr != block->ptr) 
Packit b099d7
	  XtFree(newblock->ptr);
Packit b099d7
	*freeBlock = False;
Packit b099d7
	if (newblock->length) {
Packit b099d7
	  newblock->ptr = XtMalloc(newblock->length + 1);
Packit b099d7
	  *freeBlock = True;
Packit b099d7
	  (void)memcpy((void*)newblock->ptr, (void*)tvcb.text->ptr, 
Packit b099d7
		       tvcb.text->length);
Packit b099d7
	} else newblock->ptr = NULL;
Packit b099d7
      }
Packit b099d7
      newblock->format = tvcb.text->format;
Packit b099d7
      block_num_chars = _XmTextCountCharacters(newblock->ptr,
Packit b099d7
					       newblock->length);
Packit b099d7
      
Packit b099d7
      delta = block_num_chars - (*end - *start);
Packit b099d7
      
Packit b099d7
      if (delta > 0 && data->length + delta > data->maxallowed &&
Packit b099d7
	  (!UnderVerifyPreedit(initiator))) {
Packit b099d7
	if (newblock->ptr && newblock->ptr != block->ptr) 
Packit b099d7
	  XtFree(newblock->ptr);
Packit b099d7
	*freeBlock = False;
Packit b099d7
	return False;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  }  /* end if there are char* modify verify callbacks */
Packit b099d7
  
Packit b099d7
  if (initiator->text.wcs_modify_verify_callback) {
Packit b099d7
    wcs_newblock.wcsptr = (wchar_t *)XtMalloc((unsigned)sizeof(wchar_t) *
Packit b099d7
					      (newblock->length + 1));
Packit b099d7
    wcs_newblock.length = mbstowcs(wcs_newblock.wcsptr, newblock->ptr,
Packit b099d7
				   block_num_chars);
Packit b099d7
    if (wcs_newblock.length < 0) wcs_newblock.length = 0;
Packit b099d7
    wcs_tvcb.reason = XmCR_MODIFYING_TEXT_VALUE;
Packit b099d7
    wcs_tvcb.event = event;
Packit b099d7
    wcs_tvcb.currInsert = initiator->text.cursor_position;
Packit b099d7
    wcs_tvcb.newInsert = initiator->text.cursor_position;
Packit b099d7
    wcs_tvcb.startPos = *start;
Packit b099d7
    wcs_tvcb.endPos = *end;
Packit b099d7
    wcs_tvcb.doit = True;
Packit b099d7
    wcs_tvcb.text = &wcs_newblock;
Packit b099d7
    
Packit b099d7
    XtCallCallbackList((Widget) initiator,
Packit b099d7
		       initiator->text.wcs_modify_verify_callback,
Packit b099d7
		       (XtPointer) &wcs_tvcb);
Packit b099d7
    if (!wcs_tvcb.doit) {
Packit b099d7
      if (newblock->ptr && newblock->ptr != block->ptr)
Packit b099d7
	XtFree(newblock->ptr);
Packit b099d7
      *freeBlock = False;
Packit b099d7
      if (wcs_newblock.wcsptr) XtFree((char*)wcs_newblock.wcsptr);
Packit b099d7
      return False;
Packit b099d7
    } else {
Packit b099d7
      *start = wcs_tvcb.startPos;
Packit b099d7
      *end = wcs_tvcb.endPos;
Packit b099d7
      newInsert = wcs_tvcb.newInsert;
Packit b099d7
      _XmTextValidate (start, end, data->length);
Packit b099d7
      /* use newblock as a temporary holder and put the char*
Packit b099d7
       * data there */
Packit b099d7
      if (newblock->ptr && newblock->ptr != block->ptr) {
Packit b099d7
	XtFree(newblock->ptr);
Packit b099d7
	newblock->ptr = NULL;
Packit b099d7
      }
Packit b099d7
      *freeBlock = False;
Packit b099d7
      if (wcs_tvcb.text->length) {
Packit b099d7
	newblock->ptr = (char*) XtMalloc((unsigned)
Packit b099d7
					 (1 + wcs_tvcb.text->length) *
Packit b099d7
					 (int)initiator->text.char_size);
Packit b099d7
	*freeBlock = True;
Packit b099d7
	wcs_tvcb.text->wcsptr[wcs_tvcb.text->length] = (wchar_t) 0L;
Packit b099d7
	/* NOTE: wcstombs returns a long which could be truncated */
Packit b099d7
	newblock->length = (int) wcstombs(newblock->ptr, 
Packit b099d7
					  wcs_tvcb.text->wcsptr,
Packit b099d7
					  (wcs_tvcb.text->length + 1) *
Packit b099d7
					  (int)initiator->text.char_size);
Packit b099d7
	if (newblock->length < 0) newblock->length = 0;
Packit b099d7
      } else {
Packit b099d7
	newblock->ptr = NULL;
Packit b099d7
	newblock->length = 0;
Packit b099d7
      }
Packit b099d7
      
Packit b099d7
      block_num_chars = wcs_tvcb.text->length;
Packit b099d7
      delta = block_num_chars - (*end - *start);
Packit b099d7
      
Packit b099d7
      /* if the wcstombs found bad data, newblock->length is negative */
Packit b099d7
      if ((delta > 0 && data->length + delta > data->maxallowed &&
Packit b099d7
	  (!UnderVerifyPreedit(initiator))) ||
Packit b099d7
	  newblock->length < 0) {
Packit b099d7
	
Packit b099d7
	if (newblock->ptr && newblock->ptr != block->ptr)
Packit b099d7
	  XtFree(newblock->ptr);
Packit b099d7
	*freeBlock = False;
Packit b099d7
	if (wcs_newblock.wcsptr) XtFree((char*)wcs_newblock.wcsptr);
Packit b099d7
	return False;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    /* If we alloced space for the wcs_newblock, we need to clean it up */
Packit b099d7
    if (wcs_newblock.wcsptr) XtFree((char*)wcs_newblock.wcsptr);
Packit b099d7
    
Packit b099d7
  }  /* end if there are wide char modify verify callbacks */
Packit b099d7
  
Packit b099d7
  if (cursorPos)
Packit b099d7
  {
Packit b099d7
	  if (initiator->text.cursor_position != newInsert)	/* true only if we have callbacks */
Packit b099d7
	  {
Packit b099d7
	    if (newInsert > data->length + delta) {
Packit b099d7
	      *cursorPos = data->length + delta;
Packit b099d7
	    } else if (newInsert < 0) {
Packit b099d7
	      *cursorPos = 0;
Packit b099d7
	    } else {
Packit b099d7
	      *cursorPos = newInsert;
Packit b099d7
	    }
Packit b099d7
	  }
Packit b099d7
	  else
Packit b099d7
	    *cursorPos = *start + block_num_chars;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  return True;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static XmTextStatus 
Packit b099d7
Replace(XmTextWidget initiator,
Packit b099d7
        XEvent * event,		/* unused */
Packit b099d7
        XmTextPosition *start,
Packit b099d7
        XmTextPosition *end,
Packit b099d7
        XmTextBlock block,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
        int call_callbacks)	/* unused */
Packit b099d7
#else
Packit b099d7
        Boolean call_callbacks)	/* unused */
Packit b099d7
#endif
Packit b099d7
{
Packit b099d7
  register XmSourceData data = initiator->text.source->data;
Packit b099d7
  register int i;
Packit b099d7
  register long delta;
Packit b099d7
  register int block_num_chars;  /* number of characters in the block */
Packit b099d7
  int gap_size;
Packit b099d7
  int old_maxlength;
Packit b099d7
  int char_size = (initiator->text.char_size < 3 ?
Packit b099d7
		   (int)initiator->text.char_size :
Packit b099d7
		   sizeof(wchar_t));
Packit b099d7
  
Packit b099d7
  if (*start == *end && block->length == 0) return EditReject;
Packit b099d7
  
Packit b099d7
  _XmTextValidate(start, end, data->length);
Packit b099d7
  
Packit b099d7
  block_num_chars = _XmTextCountCharacters(block->ptr, block->length);
Packit b099d7
  delta = block_num_chars - (*end - *start);
Packit b099d7
  
Packit b099d7
  if (!data->editable ||
Packit b099d7
      (delta > 0 && data->length + delta > data->maxallowed &&
Packit b099d7
	(!UnderVerifyPreedit(initiator))))
Packit b099d7
    return EditError;
Packit b099d7
  
Packit b099d7
  /**********************************************************************/
Packit b099d7
  
Packit b099d7
  initiator->text.output->DrawInsertionPoint(initiator,
Packit b099d7
					     initiator->text.cursor_position,
Packit b099d7
					     off);
Packit b099d7
  
Packit b099d7
  /* Move the gap to the editing position (*start). */
Packit b099d7
  _XmStringSourceSetGappedBuffer(data, *start);
Packit b099d7
  
Packit b099d7
  for (i=0; i<data->numwidgets; i++) {
Packit b099d7
    _XmTextDisableRedisplay(data->widgets[i], TRUE);
Packit b099d7
    if (data->hasselection)
Packit b099d7
      _XmTextSetHighlight((Widget)data->widgets[i], data->left, 
Packit b099d7
			 data->right, XmHIGHLIGHT_NORMAL);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  old_maxlength = data->maxlength;
Packit b099d7
  if (data->length + delta >= data->maxlength) {
Packit b099d7
    int gap_start_offset, gap_end_offset;
Packit b099d7
    
Packit b099d7
    while (data->length + delta >= data->maxlength) {
Packit b099d7
      if (data->maxlength < TEXT_INCREMENT)
Packit b099d7
	data->maxlength *= 2;
Packit b099d7
      else
Packit b099d7
	data->maxlength += TEXT_INCREMENT;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    gap_start_offset = data->gap_start - data->ptr;
Packit b099d7
    gap_end_offset = data->gap_end - data->ptr;
Packit b099d7
    data->ptr = XtRealloc(data->ptr, (unsigned) 
Packit b099d7
			  ((data->maxlength) * char_size));
Packit b099d7
    data->gap_start = data->ptr + gap_start_offset;
Packit b099d7
    data->gap_end = data->ptr + gap_end_offset +
Packit b099d7
      (char_size * (data->maxlength - old_maxlength));
Packit b099d7
    if (gap_end_offset != (old_maxlength * char_size))
Packit b099d7
      memmove(data->gap_end, data->ptr + gap_end_offset, 
Packit b099d7
	      (char_size * old_maxlength) - gap_end_offset);
Packit b099d7
    /* Do something to move the allocated space into the buffer */
Packit b099d7
  } 
Packit b099d7
  
Packit b099d7
  /* NOTE: the value of delta could be truncated by cast to int. */
Packit b099d7
  data->length += (int) delta;
Packit b099d7
  
Packit b099d7
  if (data->hasselection && *start < data->right && *end > data->left) {
Packit b099d7
    if (*start <= data->left) {
Packit b099d7
      if (*end < data->right) {
Packit b099d7
	data->left = *end; /* delete encompasses left half of the
Packit b099d7
			      selection so move left endpoint */
Packit b099d7
      } else {
Packit b099d7
	data->right = data->left; /* delete encompasses the selection
Packit b099d7
				     so set selection to NULL */
Packit b099d7
      }
Packit b099d7
    } else {
Packit b099d7
      if (*end >= data->right) {
Packit b099d7
	data->right = *start; /* delete encompasses the right half of the
Packit b099d7
				 selection so move right endpoint */
Packit b099d7
      } else {
Packit b099d7
	data->right -= (*end - *start); /* delete is completely within the
Packit b099d7
					   selection so shrink the selection */
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  /* delete data */
Packit b099d7
  gap_size = data->gap_end - data->gap_start;
Packit b099d7
  /* expand the end of the gap to the right */
Packit b099d7
  if ((data->ptr + gap_size + (*end * char_size)) > data->gap_end)
Packit b099d7
    data->gap_end += ((*end - *start) * char_size);
Packit b099d7
  
Packit b099d7
  /* add data */
Packit b099d7
  /* copy the data into the gap_start and increment the gap start pointer */
Packit b099d7
  /* convert data from char* to characters and copy into the gapped buffer */
Packit b099d7
  if ((int)initiator->text.char_size == 1) {
Packit b099d7
    for (i=0; i < block->length; i++) {
Packit b099d7
      /* if (data->gap_start == data->gap_end) break; */
Packit b099d7
      *data->gap_start++ = block->ptr[i];
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
  } else {
Packit b099d7
    data->gap_start += char_size * 
Packit b099d7
      _XmTextBytesToCharacters(data->gap_start,
Packit b099d7
			       &block->ptr[0], 
Packit b099d7
			       block_num_chars, False,
Packit b099d7
			       (int)initiator->text.char_size);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  if (data->hasselection && data->left != data->right) {
Packit b099d7
    if (*end <= data->left) {
Packit b099d7
      data->left += delta;
Packit b099d7
      data->right += delta;
Packit b099d7
    }
Packit b099d7
    if (data->left > data->right)
Packit b099d7
      data->right = data->left;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  for (i=0; i<data->numwidgets; i++) {
Packit b099d7
    _XmTextInvalidate(data->widgets[i], *start, *end, delta);
Packit b099d7
    _XmTextUpdateLineTable((Widget) data->widgets[i], *start,
Packit b099d7
			   *end, block, True);
Packit b099d7
    if (data->hasselection)
Packit b099d7
      _XmTextSetHighlight((Widget)data->widgets[i], data->left, 
Packit b099d7
			 data->right, XmHIGHLIGHT_SELECTED);
Packit b099d7
    
Packit b099d7
    _XmTextEnableRedisplay(data->widgets[i]);
Packit b099d7
  }
Packit b099d7
  initiator->text.output->DrawInsertionPoint(initiator,
Packit b099d7
					     initiator->text.cursor_position, 
Packit b099d7
					     on);
Packit b099d7
  
Packit b099d7
  if (data->maxlength != TEXT_INITIAL_INCREM &&
Packit b099d7
      ((data->maxlength > TEXT_INCREMENT &&
Packit b099d7
	data->length <= data->maxlength - TEXT_INCREMENT) ||
Packit b099d7
       data->length <= data->maxlength >> 1)) {
Packit b099d7
    /* Move the gap to the last position. */
Packit b099d7
    _XmStringSourceSetGappedBuffer(data, data->length);
Packit b099d7
    
Packit b099d7
    data->maxlength = TEXT_INITIAL_INCREM;
Packit b099d7
    
Packit b099d7
    while (data->length >= data->maxlength) {
Packit b099d7
      if (data->maxlength < TEXT_INCREMENT)
Packit b099d7
	data->maxlength *= 2;
Packit b099d7
      else
Packit b099d7
	data->maxlength += TEXT_INCREMENT;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    data->ptr = XtRealloc(data->ptr, (unsigned) 
Packit b099d7
			  ((data->maxlength) * char_size));
Packit b099d7
    data->gap_start = data->ptr + (data->length * char_size);
Packit b099d7
    data->gap_end = data->ptr + ((data->maxlength - 1) * char_size);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  return EditDone;
Packit b099d7
}
Packit b099d7
Packit b099d7
#define Increment(data, position, direction)\
Packit b099d7
{\
Packit b099d7
  if (direction == XmsdLeft) {\
Packit b099d7
    if (position > 0) \
Packit b099d7
      position--;\
Packit b099d7
  } else {\
Packit b099d7
    if (position < data->length)\
Packit b099d7
      position++;\
Packit b099d7
  }\
Packit b099d7
}
Packit b099d7
Packit b099d7
#define Look(data, position, dir) \
Packit b099d7
    ((dir == XmsdLeft) \
Packit b099d7
      ? ((position) ? _XmStringSourceGetChar(data, position - 1) \
Packit b099d7
	            : NULL) \
Packit b099d7
      : ((position == data->length) ? NULL \
Packit b099d7
	                            : _XmStringSourceGetChar(data, position)))
Packit b099d7
   
Packit b099d7
static void 
Packit b099d7
ScanParagraph(XmSourceData data,
Packit b099d7
	      XmTextPosition *new_position,
Packit b099d7
	      XmTextScanDirection dir,
Packit b099d7
	      int ddir,
Packit b099d7
	      XmTextPosition *last_char)
Packit b099d7
{
Packit b099d7
  Boolean found = False;
Packit b099d7
  XmTextPosition position = *new_position;
Packit b099d7
  char mb_char[1 + MB_LEN_MAX];
Packit b099d7
  char * c;
Packit b099d7
  
Packit b099d7
  while (position >= 0 && position <= data->length) {
Packit b099d7
    /* DELTA: Look now returns a pointer */
Packit b099d7
    /* DELTA: EFFECIENCY: LEAVE AS SHORT*, INT*, ... COMPARE TO PSWC_NWLN */
Packit b099d7
    c = Look(data, position, dir);
Packit b099d7
    (void) _XmTextCharactersToBytes(mb_char, c, 1, 
Packit b099d7
				    (int)data->widgets[0]->text.char_size);
Packit b099d7
    if (mb_char && *mb_char == '\n') {
Packit b099d7
      /* DELTA: Look now returns a pointer */
Packit b099d7
      c = Look(data, position + ddir, dir);
Packit b099d7
      (void) _XmTextCharactersToBytes(mb_char, c, 1,
Packit b099d7
				      (int)data->widgets[0]->text.char_size);
Packit b099d7
      while (mb_char && isspace((unsigned char)*mb_char)) {
Packit b099d7
	if (*mb_char == '\n') {
Packit b099d7
	  found = True;
Packit b099d7
	  while (mb_char && isspace((unsigned char)*mb_char)) {
Packit b099d7
	    /* DELTA: Look now returns a pointer */
Packit b099d7
	    c = Look(data, position + ddir, dir);
Packit b099d7
	    (void) _XmTextCharactersToBytes(mb_char, c, 1,
Packit b099d7
					(int)data->widgets[0]->text.char_size);
Packit b099d7
	    Increment(data, position, dir);
Packit b099d7
	  }
Packit b099d7
	  break;
Packit b099d7
	}
Packit b099d7
	/* DELTA: Look now returns a pointer */
Packit b099d7
	c = Look(data, position + ddir, dir);
Packit b099d7
	(void) _XmTextCharactersToBytes(mb_char, c, 1,
Packit b099d7
					(int)data->widgets[0]->text.char_size);
Packit b099d7
	Increment(data, position, dir);
Packit b099d7
	/* BEGIN 3145 fix -- Do not bypass a nonspace character */
Packit b099d7
	if (!isspace((unsigned char)*c))
Packit b099d7
	  *last_char = (position) + ddir;
Packit b099d7
	/* END 3145 */
Packit b099d7
      }
Packit b099d7
      if (found) break;
Packit b099d7
    } else if (mb_char && !isspace((unsigned char)*mb_char)) {
Packit b099d7
      *last_char = (position) + ddir;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    if(((dir == XmsdRight) && (position == data->length)) ||
Packit b099d7
       ((dir == XmsdLeft) && (position == 0)))
Packit b099d7
      break;
Packit b099d7
    Increment(data, position, dir);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  *new_position = position;
Packit b099d7
}
Packit b099d7
Packit b099d7
static XmTextPosition 
Packit b099d7
Scan(XmTextSource source,
Packit b099d7
     XmTextPosition pos,
Packit b099d7
     XmTextScanType sType,
Packit b099d7
     XmTextScanDirection dir,
Packit b099d7
     int count,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
     int include)
Packit b099d7
#else
Packit b099d7
     Boolean include)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
  register long whiteSpace = -1;
Packit b099d7
  register XmTextPosition position = pos;
Packit b099d7
  register int i;
Packit b099d7
  XmTextPosition temp;
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw = (XmTextWidget)data->widgets[0];
Packit b099d7
  char * c;
Packit b099d7
  BITS16 * bits16_ptr;
Packit b099d7
  wchar_t * wchar_t_ptr;
Packit b099d7
  char mb_char[1 + MB_LEN_MAX];
Packit b099d7
  Boolean start_is_mb, cur_is_mb;  /* False == 1-byte char, else multi-byte */
Packit b099d7
  int num_bytes = 0;
Packit b099d7
  int ddir = (dir == XmsdRight) ? 1 : -1;
Packit b099d7
  
Packit b099d7
  switch (sType) {
Packit b099d7
  case XmSELECT_POSITION: 
Packit b099d7
    if (!include && count > 0)
Packit b099d7
      count -= 1;
Packit b099d7
    for (i = 0; i < count; i++) {
Packit b099d7
      Increment(data, position, dir);
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  case XmSELECT_WHITESPACE: 
Packit b099d7
  case XmSELECT_WORD:
Packit b099d7
    if (tw->text.char_size == 1) {
Packit b099d7
      char * c;
Packit b099d7
      for (i = 0; i < count; i++) {
Packit b099d7
	whiteSpace = -1;
Packit b099d7
	while (position >= 0 && position <= data->length) {
Packit b099d7
	  c = Look(data, position, dir);
Packit b099d7
	  if (c && isspace((unsigned char)*c)) {
Packit b099d7
	    if (whiteSpace < 0) whiteSpace = position;
Packit b099d7
#ifdef FIX_1320
Packit b099d7
	    if (*c == '\n') break;
Packit b099d7
#endif
Packit b099d7
	  } else if (whiteSpace >= 0)
Packit b099d7
	    break;
Packit b099d7
	  position += ddir;
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
    } else {
Packit b099d7
      for (i = 0; i < count; i++) {
Packit b099d7
	whiteSpace = -1;
Packit b099d7
	num_bytes = _XmTextCharactersToBytes(mb_char,
Packit b099d7
					     Look(data, position, dir),
Packit b099d7
					     1,(int)tw->text.char_size);
Packit b099d7
	start_is_mb = (num_bytes < 2 ? False : True);
Packit b099d7
	while (position >= 0 && position <= data->length) {
Packit b099d7
	  num_bytes = _XmTextCharactersToBytes(mb_char,
Packit b099d7
					       Look(data, position, dir),
Packit b099d7
					       1, (int)tw->text.char_size);
Packit b099d7
	  cur_is_mb = (num_bytes < 2 ? False : True);
Packit b099d7
	  if (!cur_is_mb && mb_char && 
Packit b099d7
	      isspace((unsigned char)*mb_char)) {
Packit b099d7
	    if (whiteSpace < 0) whiteSpace = position;
Packit b099d7
	  } else if ((sType == XmSELECT_WORD) &&
Packit b099d7
		     (start_is_mb ^ cur_is_mb)) {
Packit b099d7
	    if (whiteSpace < 0) whiteSpace = position;
Packit b099d7
	    break;
Packit b099d7
	  } else if (whiteSpace >= 0)
Packit b099d7
	    break;
Packit b099d7
	  position += ddir;
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
    if (!include) {
Packit b099d7
      if(whiteSpace < 0 && dir == XmsdRight)
Packit b099d7
	whiteSpace = data->length;
Packit b099d7
      position = whiteSpace;
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  case XmSELECT_LINE: 
Packit b099d7
    for (i = 0; i < count; i++) {
Packit b099d7
      while (position >= 0 && position <= data->length) {
Packit b099d7
	/* DELTA: Look now returns a pointer */
Packit b099d7
	if ((int)tw->text.char_size == 1) {
Packit b099d7
	  c = Look(data, position, dir);
Packit b099d7
	  if ((c == '\0') || (*c == *data->PSWC_NWLN))
Packit b099d7
	    break;
Packit b099d7
	}
Packit b099d7
	else if ((int)tw->text.char_size == 2) {
Packit b099d7
	  bits16_ptr = (BITS16 *) Look(data, position, dir);
Packit b099d7
	  if ((bits16_ptr == NULL) ||
Packit b099d7
	      (*bits16_ptr == *(BITS16 *)data->PSWC_NWLN))
Packit b099d7
	    break;
Packit b099d7
	}
Packit b099d7
	else { /* MB_CUR_MAX == 3 or 4 or more */
Packit b099d7
	  wchar_t_ptr = (wchar_t *) Look(data, position, dir);
Packit b099d7
	  if ((wchar_t_ptr == NULL) ||
Packit b099d7
	      (*wchar_t_ptr == *(wchar_t *)data->PSWC_NWLN))
Packit b099d7
	    break;
Packit b099d7
	}
Packit b099d7
	
Packit b099d7
	if(((dir == XmsdRight) && (position == data->length)) || 
Packit b099d7
	   ((dir == XmsdLeft) && (position == 0)))
Packit b099d7
	  break;
Packit b099d7
	Increment(data, position, dir);
Packit b099d7
      }
Packit b099d7
      if (i + 1 != count)
Packit b099d7
	Increment(data, position, dir);
Packit b099d7
    }
Packit b099d7
    if (include) {
Packit b099d7
      /* later!!!check for last char in file # eol */
Packit b099d7
      Increment(data, position, dir);
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  case XmSELECT_PARAGRAPH: 
Packit b099d7
    /* Muliple paragraph scanning is not guarenteed to work. */
Packit b099d7
    for (i = 0; i < count; i++) {
Packit b099d7
      XmTextPosition start_position = position; 
Packit b099d7
      XmTextPosition last_char = position; 
Packit b099d7
      
Packit b099d7
      /* if scanning forward, check for between paragraphs condition */
Packit b099d7
      if (dir == XmsdRight) {
Packit b099d7
	/* DELTA: Look now returns a pointer */
Packit b099d7
	c = Look(data, position, dir);
Packit b099d7
	(void) _XmTextCharactersToBytes(mb_char, 
Packit b099d7
					Look(data, position, dir), 
Packit b099d7
					1, (int)tw->text.char_size);
Packit b099d7
	/* if is space, go back to first non-space */
Packit b099d7
	while (mb_char && isspace((unsigned char)*mb_char)) {
Packit b099d7
	  if (position > 0)
Packit b099d7
	    position--;
Packit b099d7
	  else if (position == 0)
Packit b099d7
	    break;
Packit b099d7
	  (void) _XmTextCharactersToBytes(mb_char, 
Packit b099d7
					  Look(data, position, dir),
Packit b099d7
					  1, (int)tw->text.char_size);
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
      
Packit b099d7
      temp = position;
Packit b099d7
      ScanParagraph(data, &temp, dir, ddir, &last_char);
Packit b099d7
      position = temp;
Packit b099d7
      
Packit b099d7
      /*
Packit b099d7
       * If we are at the beginning of the paragraph and we are
Packit b099d7
       * scanning left, we need to rescan to find the character
Packit b099d7
       * at the beginning of the next paragraph.
Packit b099d7
       */  
Packit b099d7
      if (dir == XmsdLeft) {
Packit b099d7
	/* If we started at the beginning of the paragraph, rescan */
Packit b099d7
	if (last_char == start_position) {
Packit b099d7
	  temp = position;
Packit b099d7
	  ScanParagraph(data, &temp, dir, ddir, &last_char);
Packit b099d7
	}
Packit b099d7
	/*
Packit b099d7
	 * Set position to the last non-space 
Packit b099d7
	 * character that was scanned.
Packit b099d7
	 */
Packit b099d7
	position = last_char;
Packit b099d7
      }
Packit b099d7
      
Packit b099d7
      if (i + 1 != count)
Packit b099d7
	Increment(data, position, dir);
Packit b099d7
      
Packit b099d7
    }
Packit b099d7
    if (include) {
Packit b099d7
      Increment(data, position, dir);
Packit b099d7
    }
Packit b099d7
    break;
Packit b099d7
  case XmSELECT_ALL:
Packit b099d7
  default: 
Packit b099d7
    if (dir == XmsdLeft)
Packit b099d7
      position = 0;
Packit b099d7
    else
Packit b099d7
      position = data->length;
Packit b099d7
  }
Packit b099d7
  if (position < 0) position = 0;
Packit b099d7
  if (position > data->length) position = data->length;
Packit b099d7
  return(position);
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean 
Packit b099d7
GetSelection(XmTextSource source,
Packit b099d7
	     XmTextPosition *left,
Packit b099d7
	     XmTextPosition *right)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  
Packit b099d7
  if (data->hasselection && data->left < data->right && data->left >= 0) {
Packit b099d7
    *left = data->left;
Packit b099d7
    *right = data->right;
Packit b099d7
    return True;
Packit b099d7
  } else {
Packit b099d7
    *left = *right = 0;
Packit b099d7
    data->hasselection = False;
Packit b099d7
    data->take_selection = True;
Packit b099d7
  }
Packit b099d7
  return False;
Packit b099d7
}
Packit b099d7
Packit b099d7
static void 
Packit b099d7
SetSelection(XmTextSource source,
Packit b099d7
	     XmTextPosition left,
Packit b099d7
	     XmTextPosition right, /* if right == -999, then  we're in 
Packit b099d7
				      LoseSelection, so don't call 
Packit b099d7
				      XtDisownSelection.*/
Packit b099d7
	     Time set_time)
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw;
Packit b099d7
  int i;
Packit b099d7
  int oldleft, oldright;
Packit b099d7
  
Packit b099d7
  if (!XtIsRealized((Widget)data->widgets[0]) ||
Packit b099d7
      (left > right && !data->hasselection)) return;
Packit b099d7
  
Packit b099d7
  if (left < 0) left = right = 0;
Packit b099d7
  
Packit b099d7
  for (i=0; i<data->numwidgets; i++) {
Packit b099d7
    tw = (XmTextWidget)(data->widgets[i]);
Packit b099d7
    (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
Packit b099d7
					   off);
Packit b099d7
    _XmTextDisableRedisplay(data->widgets[i], FALSE);
Packit b099d7
    if (data->hasselection)
Packit b099d7
      _XmTextSetHighlight((Widget)data->widgets[i], data->left, 
Packit b099d7
			 data->right, XmHIGHLIGHT_NORMAL);
Packit b099d7
    
Packit b099d7
    data->widgets[i]->text.output->data->refresh_ibeam_off = True;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  oldleft = data->left;
Packit b099d7
  oldright = data->right;
Packit b099d7
  data->left = left;
Packit b099d7
  data->right = right;
Packit b099d7
  if (data->numwidgets > 0) {
Packit b099d7
    Widget widget = (Widget) data->widgets[0];
Packit b099d7
    tw = (XmTextWidget)widget;
Packit b099d7
    if (!set_time) set_time = _XmValidTimestamp(widget);
Packit b099d7
    
Packit b099d7
    if (left <= right) {
Packit b099d7
      if (data->take_selection || (oldleft == oldright && left != right)) {
Packit b099d7
	if (!XmePrimarySource(widget, set_time)) {
Packit b099d7
	  (*source->SetSelection)(source, 1, 0, set_time);
Packit b099d7
	} else {
Packit b099d7
	  XmAnyCallbackStruct cb;
Packit b099d7
	  
Packit b099d7
	  data->prim_time = set_time;
Packit b099d7
	  data->hasselection = True;
Packit b099d7
	  data->take_selection = False;
Packit b099d7
	  
Packit b099d7
	  cb.reason = XmCR_GAIN_PRIMARY;
Packit b099d7
	  cb.event = NULL;
Packit b099d7
	  XtCallCallbackList ((Widget) data->widgets[0], 
Packit b099d7
			      data->widgets[0]->text.gain_primary_callback,
Packit b099d7
			      (XtPointer) &cb;;
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
      if (data->hasselection && data->left < data->right) {
Packit b099d7
	for (i=0; i<data->numwidgets; i++) {
Packit b099d7
	  _XmTextSetHighlight((Widget) data->widgets[i], data->left,
Packit b099d7
			     data->right, XmHIGHLIGHT_SELECTED);
Packit b099d7
	}
Packit b099d7
      }
Packit b099d7
      if (left == right) tw->text.add_mode = False;
Packit b099d7
    } else {
Packit b099d7
      if (right != -999)
Packit b099d7
	XtDisownSelection(widget, XA_PRIMARY, set_time);
Packit b099d7
      data->hasselection = False;
Packit b099d7
      data->take_selection = True;
Packit b099d7
      tw->text.add_mode = False;
Packit b099d7
    }
Packit b099d7
  }
Packit b099d7
  for (i=0; i<data->numwidgets; i++) {
Packit b099d7
    tw = (XmTextWidget)(data->widgets[i]);
Packit b099d7
    _XmTextEnableRedisplay(data->widgets[i]);
Packit b099d7
    (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
Packit b099d7
					   on);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/* Public routines. */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmTextValueChanged(XmTextWidget initiator,
Packit b099d7
		    XEvent *event)
Packit b099d7
{
Packit b099d7
  XmAnyCallbackStruct cb;
Packit b099d7
  
Packit b099d7
  cb.reason = XmCR_VALUE_CHANGED;
Packit b099d7
  cb.event = event;
Packit b099d7
  if (initiator->text.value_changed_callback)
Packit b099d7
    XtCallCallbackList((Widget)initiator,
Packit b099d7
		       initiator->text.value_changed_callback, (XtPointer)&cb;;
Packit b099d7
}
Packit b099d7
Packit b099d7
XmTextSource 
Packit b099d7
_XmStringSourceCreate(char *value,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
		      int is_wchar)
Packit b099d7
#else
Packit b099d7
                      Boolean is_wchar)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
  XmTextSource source;
Packit b099d7
  XmSourceData data;
Packit b099d7
  int num_chars;
Packit b099d7
  char newline = '\n';
Packit b099d7
  wchar_t *wc_value;
Packit b099d7
  char * tmp_value;
Packit b099d7
  int char_size, max_char_size;
Packit b099d7
  int ret_value = 0;
Packit b099d7
Packit b099d7
  source = (XmTextSource) XtMalloc((unsigned) sizeof(XmTextSourceRec));
Packit b099d7
  data = source->data = (XmSourceData)
Packit b099d7
    XtMalloc((unsigned) sizeof(XmSourceDataRec));
Packit b099d7
  source->AddWidget = AddWidget;
Packit b099d7
  source->CountLines = CountLines;
Packit b099d7
  source->RemoveWidget = RemoveWidget;
Packit b099d7
  source->ReadSource = ReadSource;
Packit b099d7
  source->Replace = (ReplaceProc) Replace;
Packit b099d7
  source->Scan = Scan;
Packit b099d7
  source->GetSelection = GetSelection;
Packit b099d7
  source->SetSelection = SetSelection;
Packit b099d7
  
Packit b099d7
  data->source = source;
Packit b099d7
  switch (MB_CUR_MAX) {
Packit b099d7
  case 1: case 2: 
Packit b099d7
    max_char_size = char_size = MB_CUR_MAX;
Packit b099d7
    break;
Packit b099d7
  case 0: 
Packit b099d7
    max_char_size = char_size = 1;
Packit b099d7
    break;
Packit b099d7
  default: 
Packit b099d7
    max_char_size = MB_CUR_MAX;
Packit b099d7
    char_size = sizeof(wchar_t);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  if (is_wchar) {
Packit b099d7
    for (num_chars = 0, wc_value = (wchar_t*)value; 
Packit b099d7
	 wc_value[num_chars] != 0L;
Packit b099d7
	 num_chars++)
Packit b099d7
      /*EMPTY*/;
Packit b099d7
    
Packit b099d7
    data->maxlength = TEXT_INITIAL_INCREM;
Packit b099d7
    
Packit b099d7
    while ((num_chars + 1) >= data->maxlength) {
Packit b099d7
      if (data->maxlength < TEXT_INCREMENT)
Packit b099d7
	data->maxlength *= 2;
Packit b099d7
      else
Packit b099d7
	data->maxlength += TEXT_INCREMENT;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    data->old_length = 0;
Packit b099d7
    data->ptr = XtMalloc((unsigned)((data->maxlength) * char_size));
Packit b099d7
    tmp_value = XtMalloc((unsigned)((num_chars + 1) * max_char_size));
Packit b099d7
    ret_value = wcstombs(tmp_value, wc_value, (num_chars + 1) * max_char_size);
Packit b099d7
    data->value = NULL;  /* Scratch area for block->ptr conversions */
Packit b099d7
    /* Doesnt include NULL */
Packit b099d7
    if (ret_value < 0)
Packit b099d7
      data->length = 0;
Packit b099d7
    else 
Packit b099d7
      data->length = _XmTextBytesToCharacters(data->ptr, tmp_value, num_chars,
Packit b099d7
					      False, max_char_size);
Packit b099d7
    XtFree(tmp_value);
Packit b099d7
  } else {
Packit b099d7
    if (value)
Packit b099d7
      num_chars = _XmTextCountCharacters(value, strlen(value));
Packit b099d7
    else
Packit b099d7
      num_chars = 0;
Packit b099d7
    data->maxlength = TEXT_INITIAL_INCREM;
Packit b099d7
    
Packit b099d7
    while ((num_chars + 1) >= data->maxlength) {
Packit b099d7
      if (data->maxlength < TEXT_INCREMENT)
Packit b099d7
	data->maxlength *= 2;
Packit b099d7
      else
Packit b099d7
	data->maxlength += TEXT_INCREMENT;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    data->old_length = 0;
Packit b099d7
    data->ptr = XtMalloc((unsigned)((data->maxlength) * char_size));
Packit b099d7
    
Packit b099d7
    data->value = NULL;  /* Scratch area for block->ptr conversions */
Packit b099d7
    data->length = _XmTextBytesToCharacters(data->ptr, value, num_chars,
Packit b099d7
					    False, max_char_size);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  data->PSWC_NWLN = (char *) XtMalloc(char_size);
Packit b099d7
  _XmTextBytesToCharacters(data->PSWC_NWLN, &newline, 1, False, 
Packit b099d7
			   max_char_size);
Packit b099d7
  
Packit b099d7
  data->numwidgets = 0;
Packit b099d7
  data->widgets = (XmTextWidget *) XtMalloc((unsigned) sizeof(XmTextWidget));
Packit b099d7
  data->hasselection = False;
Packit b099d7
  data->take_selection = True;
Packit b099d7
  data->left = data->right = 0;
Packit b099d7
  data->editable = True;
Packit b099d7
  data->maxallowed = INT_MAX;
Packit b099d7
  data->gap_start = data->ptr + (data->length * char_size);
Packit b099d7
  data->gap_end = data->ptr + ((data->maxlength - 1) * char_size);
Packit b099d7
  data->prim_time = 0;
Packit b099d7
  return source;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmStringSourceDestroy(XmTextSource source)
Packit b099d7
{
Packit b099d7
  XtFree((char *) source->data->ptr);
Packit b099d7
  XtFree((char *) source->data->value);
Packit b099d7
  XtFree((char *) source->data->widgets);
Packit b099d7
  XtFree((char *) source->data->PSWC_NWLN);
Packit b099d7
  XtFree((char *) source->data);
Packit b099d7
  XtFree((char *) source);
Packit b099d7
  source = NULL;
Packit b099d7
}
Packit b099d7
Packit b099d7
char *
Packit b099d7
_XmStringSourceGetValue(XmTextSource source,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			int want_wchar)
Packit b099d7
#else
Packit b099d7
                        Boolean want_wchar)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  XmTextWidget tw = (XmTextWidget) data->widgets[0];
Packit b099d7
  XmTextBlockRec block;
Packit b099d7
  int length = 0;
Packit b099d7
  XmTextPosition pos = 0;
Packit b099d7
  XmTextPosition ret_pos = 0;
Packit b099d7
  XmTextPosition last_pos = 0;
Packit b099d7
  char * temp;
Packit b099d7
  wchar_t * wc_temp;
Packit b099d7
  int return_val;
Packit b099d7
Packit b099d7
  if (!want_wchar) {
Packit b099d7
    if (data->length > 0)
Packit b099d7
      temp = (char *) XtMalloc((unsigned)
Packit b099d7
			       (data->length + 1) * (int)tw->text.char_size);
Packit b099d7
    else
Packit b099d7
      return(XtNewString(""));
Packit b099d7
    
Packit b099d7
    last_pos = (XmTextPosition) data->length;
Packit b099d7
    
Packit b099d7
    while (pos < last_pos) {
Packit b099d7
      ret_pos = ReadSource(source, pos, last_pos, &block);
Packit b099d7
      if (block.length == 0)
Packit b099d7
	break;
Packit b099d7
      
Packit b099d7
      (void)memcpy((void*)&temp[length], (void*)block.ptr, block.length);
Packit b099d7
      length += block.length;
Packit b099d7
      pos = ret_pos;
Packit b099d7
    }
Packit b099d7
    temp[length] = '\0';
Packit b099d7
    return (temp);
Packit b099d7
  } else {
Packit b099d7
    
Packit b099d7
    if (data->length > 0)
Packit b099d7
      wc_temp = (wchar_t*)XtMalloc((unsigned)
Packit b099d7
				   (data->length+1) * sizeof(wchar_t));
Packit b099d7
    else {
Packit b099d7
      wc_temp = (wchar_t*)XtMalloc((unsigned) sizeof(wchar_t));
Packit b099d7
      wc_temp[0] = (wchar_t)0L;
Packit b099d7
      return (char*) wc_temp;
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    last_pos = (XmTextPosition) data->length;
Packit b099d7
    
Packit b099d7
    while (pos < last_pos) {
Packit b099d7
      ret_pos = ReadSource(source, pos, last_pos, &block);
Packit b099d7
      if (block.length == 0)
Packit b099d7
	break;
Packit b099d7
      
Packit b099d7
      /* NOTE: ret_pos - pos could result in a truncated long. */
Packit b099d7
      return_val = mbstowcs(&wc_temp[length], block.ptr, (int)(ret_pos - pos));
Packit b099d7
      if (return_val > 0) length += return_val;
Packit b099d7
      pos = ret_pos;
Packit b099d7
    }
Packit b099d7
    wc_temp[length] = (wchar_t)0L;
Packit b099d7
    return ((char*)wc_temp);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmStringSourceSetValue(XmTextWidget tw,
Packit b099d7
			char *value)
Packit b099d7
{
Packit b099d7
  XmTextSource source = tw->text.source;
Packit b099d7
  XmSourceData data = source->data;
Packit b099d7
  Boolean editable, freeBlock;
Packit b099d7
  int maxallowed;
Packit b099d7
  XmTextBlockRec block, newblock;
Packit b099d7
  XmTextPosition fromPos = 0; 
Packit b099d7
  XmTextPosition toPos = data->length;
Packit b099d7
  
Packit b099d7
  (*source->SetSelection)(source, 1, 0,
Packit b099d7
			  XtLastTimestampProcessed(XtDisplay(tw)));
Packit b099d7
  block.format = XmFMT_8_BIT;
Packit b099d7
  block.length = strlen(value);
Packit b099d7
  block.ptr = value;
Packit b099d7
  editable = data->editable;
Packit b099d7
  maxallowed = data->maxallowed;
Packit b099d7
  data->editable = TRUE;
Packit b099d7
  data->maxallowed = INT_MAX;
Packit b099d7
  _XmTextSetHighlight((Widget)tw, 0, tw->text.last_position, 
Packit b099d7
		     XmHIGHLIGHT_NORMAL);
Packit b099d7
  
Packit b099d7
  if (_XmTextModifyVerify(tw, NULL, &fromPos, &toPos,
Packit b099d7
			  NULL, &block, &newblock, &freeBlock)) {
Packit b099d7
    (void)(source->Replace)(tw, NULL, &fromPos, &toPos, &newblock, False);
Packit b099d7
    if (freeBlock && newblock.ptr) XtFree(newblock.ptr);
Packit b099d7
    _XmTextValueChanged(tw, NULL);
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  data->editable = editable;
Packit b099d7
  data->maxallowed = maxallowed;
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
_XmStringSourceHasSelection(XmTextSource source)
Packit b099d7
{
Packit b099d7
  return source->data->hasselection;
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
_XmStringSourceGetEditable(XmTextSource source)
Packit b099d7
{
Packit b099d7
  return source->data->editable;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmStringSourceSetEditable(XmTextSource source,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			   int editable)
Packit b099d7
#else
Packit b099d7
                           Boolean editable)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
  source->data->editable = editable;
Packit b099d7
}
Packit b099d7
Packit b099d7
int 
Packit b099d7
_XmStringSourceGetMaxLength(XmTextSource source)
Packit b099d7
{
Packit b099d7
  return source->data->maxallowed;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmStringSourceSetMaxLength(XmTextSource source,
Packit b099d7
			    int max)
Packit b099d7
{
Packit b099d7
  source->data->maxallowed = max;
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7