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