#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xfuncs.h>
#include <X11/Xos.h>
#include <X11/Xmu/CharSet.h>
#include <X11/Xmu/Misc.h>
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/MultiSrcP.h>
#include <X11/Xaw/XawImP.h>
#include "XawI18n.h"
#include "Private.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAGIC_VALUE ((XawTextPosition)-1)
#define streq(a, b) (strcmp((a), (b)) == 0)
#ifdef X_NOT_POSIX
#define Off_t long
#define Size_t unsigned int
#else
#define Off_t off_t
#define Size_t size_t
#endif
static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int);
static int ReplaceText(Widget, XawTextPosition, XawTextPosition,
XawTextBlock*);
static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
XawTextScanDirection, int, Bool);
static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
XawTextBlock*);
static void XawMultiSrcClassInitialize(void);
static void XawMultiSrcDestroy(Widget);
static void XawMultiSrcInitialize(Widget, Widget, ArgList, Cardinal*);
static Boolean XawMultiSrcSetValues(Widget, Widget, Widget,
ArgList, Cardinal*);
static void XawMultiSrcGetValuesHook(Widget, ArgList, Cardinal*);
static MultiPiece *AllocNewPiece(MultiSrcObject, MultiPiece*);
static void BreakPiece(MultiSrcObject, MultiPiece*);
static Boolean CvtMultiTypeToString(Display*, XrmValuePtr, Cardinal*,
XrmValuePtr, XrmValuePtr, XtPointer*);
static void CvtStringToMultiType(XrmValuePtr, Cardinal*,
XrmValuePtr, XrmValuePtr);
static MultiPiece *FindPiece(MultiSrcObject, XawTextPosition,
XawTextPosition*);
static void FreeAllPieces(MultiSrcObject);
static FILE *InitStringOrFile(MultiSrcObject, Bool);
static void LoadPieces(MultiSrcObject, FILE*, char*);
static void RemovePiece(MultiSrcObject, MultiPiece*);
static void RemoveOldStringOrFile(MultiSrcObject, Bool);
static String StorePiecesInString(MultiSrcObject);
static Bool WriteToFile(String, String);
static void GetDefaultPieceSize(Widget, int, XrmValue*);
#define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field)
static XtResource resources[] = {
{
XtNstring,
XtCString,
XtRString,
sizeof(XtPointer),
offset(string),
XtRPointer,
NULL
},
{
XtNtype,
XtCType,
XtRMultiType,
sizeof(XawAsciiType),
offset(type),
XtRImmediate,
(XtPointer)XawAsciiString
},
{
XtNdataCompression,
XtCDataCompression,
XtRBoolean,
sizeof(Boolean),
offset(data_compression),
XtRImmediate,
(XtPointer)False
},
{
XtNpieceSize,
XtCPieceSize,
XtRInt,
sizeof(XawTextPosition),
offset(piece_size),
XtRCallProc,
(XtPointer)GetDefaultPieceSize
},
#ifdef OLDXAW
{
XtNcallback,
XtCCallback,
XtRCallback,
sizeof(XtPointer),
offset(callback),
XtRCallback,
(XtPointer)NULL
},
#endif
{
XtNuseStringInPlace,
XtCUseStringInPlace,
XtRBoolean,
sizeof(Boolean),
offset(use_string_in_place),
XtRImmediate,
(XtPointer)False
},
{
XtNlength,
XtCLength,
XtRInt,
sizeof(int),
offset(multi_length),
XtRImmediate,
(XtPointer)MAGIC_VALUE
},
};
#undef offset
#define superclass (&textSrcClassRec)
MultiSrcClassRec multiSrcClassRec = {
{
(WidgetClass)superclass,
"MultiSrc",
sizeof(MultiSrcRec),
XawMultiSrcClassInitialize,
NULL,
False,
XawMultiSrcInitialize,
NULL,
NULL,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
False,
False,
False,
False,
XawMultiSrcDestroy,
NULL,
NULL,
XawMultiSrcSetValues,
NULL,
NULL,
XawMultiSrcGetValuesHook,
NULL,
XtVersion,
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
ReadText,
ReplaceText,
Scan,
Search,
XtInheritSetSelection,
XtInheritConvertSelection,
},
{
NULL,
},
};
WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
static XrmQuark Qstring, Qfile;
static void
XawMultiSrcClassInitialize(void)
{
XawInitializeWidgetSet();
Qstring = XrmPermStringToQuark(XtEstring);
Qfile = XrmPermStringToQuark(XtEfile);
XtAddConverter(XtRString, XtRMultiType, CvtStringToMultiType, NULL, 0);
XtSetTypeConverter(XtRMultiType, XtRString, CvtMultiTypeToString, NULL, 0,
XtCacheNone, NULL);
}
static void
XawMultiSrcInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
MultiSrcObject src = (MultiSrcObject)cnew;
FILE *file;
#ifdef OLDXAW
src->multi_src.changes = False;
#else
src->text_src.changed = False;
#endif
src->multi_src.allocated_string = False;
if (src->multi_src.use_string_in_place && src->multi_src.string == NULL)
src->multi_src.use_string_in_place = False;
file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
LoadPieces(src, file, NULL);
if (file != NULL)
fclose(file);
src->text_src.text_format = XawFmtWide;
}
static XawTextPosition
ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
{
MultiSrcObject src = (MultiSrcObject)w;
XawTextPosition count, start;
MultiPiece *piece = FindPiece(src, pos, &start);
text->format = XawFmtWide;
text->firstPos = pos;
text->ptr = (char *)(piece->text + (pos - start));
count = piece->used - (pos - start);
text->length = Max(0, (length > count) ? count : length);
return (pos + text->length);
}
static int
ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos,
XawTextBlock *u_text_p)
{
MultiSrcObject src = (MultiSrcObject)w;
MultiPiece *start_piece, *end_piece, *temp_piece;
XawTextPosition start_first, end_first;
int length, firstPos;
wchar_t *wptr;
Bool local_artificial_block = False;
XawTextBlock text;
if (u_text_p->length == 0)
text.length = 0;
else if (u_text_p->format == XawFmtWide) {
local_artificial_block = False;
text.firstPos = u_text_p->firstPos;
text.length = u_text_p->length;
text.ptr = u_text_p->ptr;
}
else {
local_artificial_block = True;
text.firstPos = 0;
text.length = u_text_p->length;
text.ptr = (char*)_XawTextMBToWC(XtDisplay(XtParent(w)),
&u_text_p->ptr[u_text_p->firstPos],
&text.length);
}
if (src->text_src.edit_mode == XawtextRead)
return (XawEditError);
start_piece = FindPiece(src, startPos, &start_first);
end_piece = FindPiece(src, endPos, &end_first);
if (start_piece != end_piece) {
temp_piece = start_piece->next;
if (((start_piece->used = startPos - start_first) == 0)
&& !(start_piece->next == NULL && start_piece->prev == NULL))
RemovePiece(src, start_piece);
while (temp_piece != end_piece) {
temp_piece = temp_piece->next;
RemovePiece(src, temp_piece->prev);
}
end_piece->used -= endPos - end_first;
if (end_piece->used != 0)
memmove(end_piece->text, end_piece->text + endPos - end_first,
end_piece->used * sizeof(wchar_t));
}
else {
if ((start_piece->used -= endPos - startPos) == 0) {
if (!(start_piece->next == NULL && start_piece->prev == NULL))
RemovePiece(src, start_piece);
}
else {
memmove(start_piece->text + (startPos - start_first),
start_piece->text + (endPos - start_first),
(start_piece->used - (startPos - start_first)) *
sizeof(wchar_t));
if (src->multi_src.use_string_in_place &&
((src->multi_src.length - (endPos - startPos))
< src->multi_src.piece_size - 1))
start_piece->text[src->multi_src.length - (endPos - startPos)] =
(wchar_t)0;
}
}
src->multi_src.length += text.length -(endPos - startPos);
if ( text.length != 0) {
start_piece = FindPiece(src, startPos, &start_first);
length = text.length;
firstPos = text.firstPos;
while (length > 0) {
wchar_t *ptr;
int fill;
if (src->multi_src.use_string_in_place) {
if (start_piece->used == src->multi_src.piece_size - 1) {
start_piece->used = src->multi_src.length =
src->multi_src.piece_size - 1;
start_piece->text[src->multi_src.length] = (wchar_t)0;
return (XawEditError);
}
}
if (start_piece->used == src->multi_src.piece_size) {
BreakPiece(src, start_piece);
start_piece = FindPiece(src, startPos, &start_first);
}
fill = Min((int)(src->multi_src.piece_size - start_piece->used), length);
ptr = start_piece->text + (startPos - start_first);
memmove(ptr + fill, ptr, (start_piece->used -
(startPos - start_first)) * sizeof(wchar_t));
wptr =(wchar_t *)text.ptr;
(void)wcsncpy(ptr, wptr + firstPos, fill);
startPos += fill;
firstPos += fill;
start_piece->used += fill;
length -= fill;
}
}
if (local_artificial_block == True)
XtFree(text.ptr);
if (src->multi_src.use_string_in_place)
start_piece->text[start_piece->used] = (wchar_t)0;
#ifdef OLDXAW
src->multi_src.changes = True;
XtCallCallbacks(w, XtNcallback, NULL);
#endif
return (XawEditDone);
}
static XawTextPosition
Scan(Widget w, register XawTextPosition position, XawTextScanType type,
XawTextScanDirection dir, int count, Bool include)
{
MultiSrcObject src = (MultiSrcObject)w;
register char inc;
MultiPiece *piece;
XawTextPosition first, first_eol_position = position;
register wchar_t *ptr;
int cnt = count;
if (type == XawstAll) {
if (dir == XawsdRight)
return (src->multi_src.length);
return (0);
}
if (position > src->multi_src.length)
position = src->multi_src.length;
if (dir == XawsdRight) {
if (position == src->multi_src.length)
return (src->multi_src.length);
inc = 1;
}
else {
if (position == 0)
return (0);
inc = -1;
position--;
}
piece = FindPiece(src, position, &first);
if (piece->used == 0)
return (0);
ptr = (position - first) + piece->text;
switch (type) {
case XawstEOL:
case XawstParagraph:
case XawstWhiteSpace:
case XawstAlphaNumeric:
for (; cnt > 0 ; cnt--) {
Bool non_space = False, first_eol = True;
while (True) {
register wchar_t c;
if (ptr < piece->text) {
piece = piece->prev;
if (piece == NULL)
return (0);
ptr = piece->text + piece->used - 1;
c = *ptr;
}
else if (ptr >= piece->text + piece->used) {
piece = piece->next;
if (piece == NULL)
return (src->multi_src.length);
ptr = piece->text;
}
c = *ptr;
ptr += inc;
position += inc;
if (type == XawstAlphaNumeric) {
if (!iswalnum(c)) {
if (non_space)
break;
}
else
non_space = True;
}
else if (type == XawstWhiteSpace) {
if (iswspace(c)) {
if (non_space)
break;
}
else
non_space = True;
}
else if (type == XawstEOL) {
if (c == _Xaw_atowc(XawLF))
break;
}
else {
if (first_eol) {
if (c == _Xaw_atowc(XawLF)) {
first_eol_position = position;
first_eol = False;
}
}
else
if (c == _Xaw_atowc(XawLF))
break;
else if (!iswspace(c))
first_eol = True;
}
}
}
if (!include) {
if (type == XawstParagraph)
position = first_eol_position;
if (count)
position -= inc;
}
break;
case XawstPositions:
position += count * inc;
break;
default:
break;
}
if (dir == XawsdLeft)
position++;
if (position >= src->multi_src.length)
return (src->multi_src.length);
if (position < 0)
return (0);
return (position);
}
static XawTextPosition
Search(Widget w, register XawTextPosition position, XawTextScanDirection dir,
XawTextBlock *text)
{
MultiSrcObject src = (MultiSrcObject)w;
register int count = 0;
wchar_t *ptr;
wchar_t *wtarget;
int wtarget_len;
Display *d = XtDisplay(XtParent(w));
MultiPiece *piece;
wchar_t *buf;
XawTextPosition first;
register char inc;
int cnt;
if (dir == XawsdRight)
inc = 1;
else {
inc = -1;
if (position == 0)
return (XawTextSearchError);
position--;
}
wtarget_len = text->length;
if (text->format == XawFmtWide)
wtarget = &(((wchar_t*)text->ptr) [text->firstPos]);
else {
wtarget = _XawTextMBToWC(d, &text->ptr[text->firstPos], &wtarget_len);
}
buf = (wchar_t *)XtMalloc(sizeof(wchar_t) * wtarget_len);
(void)wcsncpy(buf, wtarget, wtarget_len);
piece = FindPiece(src, position, &first);
ptr = (position - first) + piece->text;
while (True) {
if (*ptr == (dir == XawsdRight ? *(buf + count)
: *(buf + wtarget_len - count - 1))) {
if (count == text->length - 1)
break;
else
count++;
}
else {
if (count != 0) {
position -=inc * count;
ptr -= inc * count;
}
count = 0;
}
ptr += inc;
position += inc;
while (ptr < piece->text) {
cnt = piece->text - ptr;
piece = piece->prev;
if (piece == NULL) {
XtFree((char *)buf);
return (XawTextSearchError);
}
ptr = piece->text + piece->used - cnt;
}
while (ptr >= piece->text + piece->used) {
cnt = ptr - (piece->text + piece->used);
piece = piece->next;
if (piece == NULL) {
XtFree((char *)buf);
return (XawTextSearchError);
}
ptr = piece->text + cnt;
}
}
XtFree((char *)buf);
if (dir == XawsdLeft)
return(position);
return(position - (wtarget_len - 1));
}
static Boolean
XawMultiSrcSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
MultiSrcObject src = (MultiSrcObject)cnew;
MultiSrcObject old_src = (MultiSrcObject)current;
XtAppContext app_con = XtWidgetToApplicationContext(cnew);
Bool total_reset = False, string_set = False;
FILE *file;
unsigned int i;
if (old_src->multi_src.use_string_in_place
!= src->multi_src.use_string_in_place) {
XtAppWarning(app_con,
"MultiSrc: The XtNuseStringInPlace resources "
"may not be changed.");
src->multi_src.use_string_in_place =
old_src->multi_src.use_string_in_place;
}
for (i = 0; i < *num_args ; i++)
if (streq(args[i].name, XtNstring)) {
string_set = True;
break;
}
if (string_set || old_src->multi_src.type != src->multi_src.type) {
RemoveOldStringOrFile(old_src, string_set);
src->multi_src.allocated_string = old_src->multi_src.allocated_string;
file = InitStringOrFile(src, string_set);
LoadPieces(src, file, NULL);
if (file != NULL)
fclose(file);
#ifndef OLDXAW
for (i = 0; i < src->text_src.num_text; i++)
XawTextSetSource(src->text_src.text[i], cnew, 0);
#else
XawTextSetSource(XtParent(cnew), cnew, 0);
#endif
total_reset = True;
}
if (old_src->multi_src.multi_length != src->multi_src.multi_length)
src->multi_src.piece_size = src->multi_src.multi_length + 1;
if ( !total_reset && old_src->multi_src.piece_size
!= src->multi_src.piece_size) {
String mb_string = StorePiecesInString(old_src);
if (mb_string != 0) {
FreeAllPieces(old_src);
LoadPieces(src, NULL, mb_string);
XtFree(mb_string);
}
else {
XtAppWarningMsg(app_con,
"convertError", "multiSource", "XawError",
XtName(XtParent((Widget)old_src)), NULL, NULL);
XtAppWarningMsg(app_con,
"convertError", "multiSource", "XawError",
"Non-character code(s) in buffer.", NULL, NULL);
}
}
return (False);
}
static void
XawMultiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
{
MultiSrcObject src = (MultiSrcObject)w;
unsigned int i;
if (src->multi_src.type == XawAsciiString) {
for (i = 0; i < *num_args ; i++) {
if (streq(args[i].name, XtNstring)) {
if (src->multi_src.use_string_in_place)
*((char **)args[i].value) = (char *)
src->multi_src.first_piece->text;
else if (_XawMultiSave(w))
*((char **)args[i].value) = (char *)src->multi_src.string;
break;
}
}
}
}
static void
XawMultiSrcDestroy(Widget w)
{
RemoveOldStringOrFile((MultiSrcObject) w, True);
}
void
_XawMultiSourceFreeString(Widget w)
{
MultiSrcObject src = (MultiSrcObject)w;
if (src->multi_src.allocated_string) {
XtFree((char *)src->multi_src.string);
src->multi_src.allocated_string = False;
src->multi_src.string = NULL;
}
}
Bool
_XawMultiSave(Widget w)
{
MultiSrcObject src = (MultiSrcObject)w;
XtAppContext app_con = XtWidgetToApplicationContext(w);
char *mb_string;
if (src->multi_src.use_string_in_place)
return (True);
if (src->multi_src.type == XawAsciiFile) {
#ifdef OLDXAW
if (!src->multi_src.changes)
#else
if (!src->text_src.changed)
#endif
return (True);
mb_string = StorePiecesInString(src);
if (mb_string != 0) {
if (WriteToFile(mb_string, (String)src->multi_src.string) == False) {
XtFree(mb_string);
return (False);
}
XtFree(mb_string);
#ifndef OLDXAW
src->text_src.changed = False;
#else
src->multi_src.changes = False;
#endif
return (True);
}
else {
XtAppWarningMsg(app_con,
"convertError", "multiSource", "XawError",
"Due to illegal characters, file not saved.",
NULL, NULL);
return (False);
}
}
else {
mb_string = StorePiecesInString(src);
if (mb_string == 0) {
XtAppWarningMsg(app_con,
"convertError", "multiSource", "XawError",
XtName(XtParent((Widget)src)), NULL, NULL);
return (False);
}
if (src->multi_src.allocated_string == True)
XtFree((char *)src->multi_src.string);
else
src->multi_src.allocated_string = True;
src->multi_src.string = mb_string;
}
#ifdef OLDXAW
src->multi_src.changes = False;
#else
src->text_src.changed = False;
#endif
return (True);
}
Bool
_XawMultiSaveAsFile(Widget w, _Xconst char* name)
{
MultiSrcObject src = (MultiSrcObject)w;
String mb_string;
Bool ret;
mb_string = StorePiecesInString(src);
if (mb_string != 0) {
ret = WriteToFile(mb_string, (char *)name);
XtFree(mb_string);
return (ret);
}
XtAppWarningMsg(XtWidgetToApplicationContext(w),
"convertError", "multiSource", "XawError",
XtName(XtParent(w)), NULL, NULL);
return (False);
}
static void
RemoveOldStringOrFile(MultiSrcObject src, Bool checkString)
{
FreeAllPieces(src);
if (checkString && src->multi_src.allocated_string) {
XtFree((char *)src->multi_src.string);
src->multi_src.allocated_string = False;
src->multi_src.string = NULL;
}
}
static Bool
WriteToFile(String string, String name)
{
int fd;
if (((fd = creat(name, 0666)) == -1)
|| (write(fd, string, strlen(string)) == -1))
return (False);
if (close(fd) == -1)
return (False);
return (True);
}
static String
StorePiecesInString(MultiSrcObject src)
{
wchar_t *wc_string;
char *mb_string;
int char_count = src->multi_src.length;
XawTextPosition first;
MultiPiece *piece;
wc_string = (wchar_t*)XtMalloc((char_count + 1) * sizeof(wchar_t));
for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
first += piece->used, piece = piece->next)
(void)wcsncpy(wc_string + first, piece->text, piece->used);
wc_string[char_count] = 0;
if (src->multi_src.data_compression) {
FreeAllPieces(src);
LoadPieces(src, NULL, (char *)wc_string);
}
mb_string = _XawTextWCToMB(XtDisplayOfObject((Widget)src),
wc_string, &char_count);
XtFree((char*)wc_string);
return (mb_string);
}
static FILE *
InitStringOrFile(MultiSrcObject src, Bool newString)
{
mode_t open_mode = 0;
const char *fdopen_mode = NULL;
int fd;
FILE *file;
Display *d = XtDisplayOfObject((Widget)src);
if (src->multi_src.type == XawAsciiString) {
if (src->multi_src.string == NULL)
src->multi_src.length = 0;
else if (!src->multi_src.use_string_in_place) {
int length;
String temp = XtNewString((char *)src->multi_src.string);
if (src->multi_src.allocated_string)
XtFree((char *)src->multi_src.string);
src->multi_src.allocated_string = True;
src->multi_src.string = temp;
length = strlen((char *)src->multi_src.string);
(void)_XawTextMBToWC(d, (char *)src->multi_src.string, &length);
src->multi_src.length = (XawTextPosition)length;
}
else {
src->multi_src.length = strlen((char *)src->multi_src.string);
if (src->multi_src.length > src->multi_src.multi_length)
src->multi_src.multi_length = src->multi_src.length;
if (src->multi_src.multi_length == MAGIC_VALUE)
src->multi_src.piece_size = src->multi_src.length;
else
src->multi_src.piece_size = src->multi_src.multi_length + 1;
}
return (NULL);
}
src->multi_src.is_tempfile = False;
switch (src->text_src.edit_mode) {
case XawtextRead:
if (src->multi_src.string == NULL)
XtErrorMsg("NoFile", "multiSourceCreate", "XawError",
"Creating a read only disk widget and no file specified.",
NULL, 0);
open_mode = O_RDONLY;
fdopen_mode = "r";
break;
case XawtextAppend:
case XawtextEdit:
if (src->multi_src.string == NULL) {
src->multi_src.string = "*multi-src*";
src->multi_src.is_tempfile = True;
}
else {
#ifdef O_NOFOLLOW
open_mode = O_RDWR | O_NOFOLLOW;
#else
open_mode = O_RDWR;
#endif
fdopen_mode = "r+";
}
break;
default:
XtErrorMsg("badMode", "multiSourceCreate", "XawError",
"Bad editMode for multi source; must be "
"Read, Append or Edit.", NULL, NULL);
}
if (newString || src->multi_src.is_tempfile) {
String temp = XtNewString((char *)src->multi_src.string);
if (src->multi_src.allocated_string)
XtFree((char *)src->multi_src.string);
src->multi_src.string = temp;
src->multi_src.allocated_string = True;
}
if (!src->multi_src.is_tempfile) {
if ((fd = open((char *)src->multi_src.string, open_mode, 0666)) != -1) {
if ((file = fdopen(fd, fdopen_mode)) != NULL) {
(void)fseek(file, 0, SEEK_END);
src->multi_src.length = (XawTextPosition)ftell(file);
return(file);
}
}
{
String params[2];
Cardinal num_params = 2;
params[0] = (String)src->multi_src.string;
params[1] = strerror(errno);
XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
"openError", "multiSourceCreate", "XawWarning",
"Cannot open file %s; %s", params, &num_params);
}
}
src->multi_src.length = 0;
return (NULL);
}
static void
LoadPieces(MultiSrcObject src, FILE *file, char *string)
{
Display *d = XtDisplayOfObject((Widget)src);
wchar_t* local_str, *ptr;
MultiPiece* piece = NULL;
XawTextPosition left;
int bytes = sizeof(wchar_t);
char* temp_mb_holder = NULL;
int local_length = src->multi_src.length;
if (string != NULL) {
local_str = _XawTextMBToWC(d, (char *)string, &local_length);
src->multi_src.length = (XawTextPosition) local_length;
}
else if (src->multi_src.type != XawAsciiFile) {
local_length = src->multi_src.string ?
strlen((char *)src->multi_src.string) : 0;
local_str = _XawTextMBToWC(d, (char *)src->multi_src.string,
&local_length);
}
else {
if (src->multi_src.length != 0) {
temp_mb_holder =
XtMalloc((src->multi_src.length + 1) * sizeof(unsigned char));
fseek(file, 0, 0);
src->multi_src.length = fread(temp_mb_holder,
(Size_t)sizeof(unsigned char),
(Size_t)src->multi_src.length, file);
if (src->multi_src.length <= 0)
XtAppErrorMsg(XtWidgetToApplicationContext ((Widget) src),
"readError", "multiSource", "XawError",
"fread returned error.", NULL, NULL);
local_length = src->multi_src.length;
local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
src->multi_src.length = local_length;
if (local_str == 0) {
String params[2];
Cardinal num_params;
static char err_text[] =
"<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
params[0] = XtName(XtParent((Widget)src));
params[1] = src->multi_src.string;
num_params = 2;
XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
"readLocaleError", "multiSource", "XawError",
"%s: The file `%s' contains characters "
"not representable in this locale.",
params, &num_params);
src->multi_src.length = sizeof err_text;
local_length = src->multi_src.length;
local_str = _XawTextMBToWC(d, err_text, &local_length);
src->multi_src.length = local_length;
}
}
else
local_str = (wchar_t*)temp_mb_holder;
}
if (src->multi_src.use_string_in_place) {
piece = AllocNewPiece(src, piece);
piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
piece->text = (wchar_t*)src->multi_src.string;
return;
}
ptr = local_str;
left = local_length;
do {
piece = AllocNewPiece(src, piece);
piece->text = (wchar_t*)XtMalloc((unsigned)(src->multi_src.piece_size
* bytes));
piece->used = Min(left, src->multi_src.piece_size);
if (piece->used != 0)
(void)wcsncpy(piece->text, ptr, piece->used);
left -= piece->used;
ptr += piece->used;
} while (left > 0);
if (temp_mb_holder)
XtFree((char*)temp_mb_holder);
}
static MultiPiece *
AllocNewPiece(MultiSrcObject src, MultiPiece *prev)
{
MultiPiece *piece = XtNew(MultiPiece);
if (prev == NULL) {
src->multi_src.first_piece = piece;
piece->next = NULL;
}
else {
if (prev->next != NULL)
(prev->next)->prev = piece;
piece->next = prev->next;
prev->next = piece;
}
piece->prev = prev;
return (piece);
}
static void
FreeAllPieces(MultiSrcObject src)
{
MultiPiece *next, *first = src->multi_src.first_piece;
#ifdef DEBUG
if (first->prev != NULL)
printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n");
#endif
for (; first != NULL ; first = next) {
next = first->next;
RemovePiece(src, first);
}
}
static void
RemovePiece(MultiSrcObject src, MultiPiece *piece)
{
if (piece->prev == NULL)
src->multi_src.first_piece = piece->next;
else
piece->prev->next = piece->next;
if (piece->next != NULL)
piece->next->prev = piece->prev;
if (!src->multi_src.use_string_in_place)
XtFree((char *)piece->text);
XtFree((char *)piece);
}
static MultiPiece *
FindPiece(MultiSrcObject src, XawTextPosition position, XawTextPosition *first)
{
MultiPiece *old_piece, *piece;
XawTextPosition temp;
for (old_piece = NULL, piece = src->multi_src.first_piece, temp = 0;
piece; old_piece = piece, piece = piece->next)
if ((temp += piece->used) > position) {
*first = temp - piece->used;
return (piece);
}
*first = temp - (old_piece ? old_piece->used : 0);
return (old_piece);
}
#define HALF_PIECE (src->multi_src.piece_size >> 1)
static void
BreakPiece(MultiSrcObject src, MultiPiece *piece)
{
MultiPiece *cnew = AllocNewPiece(src, piece);
cnew->text = (wchar_t *)
XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
(void)wcsncpy(cnew->text, piece->text + HALF_PIECE,
src->multi_src.piece_size - HALF_PIECE);
piece->used = HALF_PIECE;
cnew->used = src->multi_src.piece_size - HALF_PIECE;
}
static void
CvtStringToMultiType(XrmValuePtr args, Cardinal *num_args,
XrmValuePtr fromVal, XrmValuePtr toVal)
{
static XawAsciiType type = XawAsciiString;
XrmQuark q;
char name[7];
XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
q = XrmStringToQuark(name);
if (q == Qstring)
type = XawAsciiString;
if (q == Qfile)
type = XawAsciiFile;
else {
toVal->size = 0;
toVal->addr = NULL;
XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType);
}
toVal->size = sizeof(XawAsciiType);
toVal->addr = (XPointer)&type;
}
static Boolean
CvtMultiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
XrmValuePtr fromVal, XrmValuePtr toVal,
XtPointer *data)
{
static String buffer;
Cardinal size;
switch (*(XawAsciiType *)fromVal->addr) {
case XawAsciiFile:
buffer = XtEfile;
break;
case XawAsciiString:
buffer = XtEstring;
break;
default:
XawTypeToStringWarning(dpy, XtRAsciiType);
toVal->addr = NULL;
toVal->size = 0;
return (False);
}
size = strlen(buffer) + 1;
if (toVal->addr != NULL) {
if (toVal->size < size) {
toVal->size = size;
return (False);
}
strcpy((char *)toVal->addr, buffer);
}
else
toVal->addr = (XPointer)buffer;
toVal->size = sizeof(String);
return (True);
}
static void
GetDefaultPieceSize(Widget w, int offset, XrmValue *value)
{
static XPointer pagesize;
if (pagesize == 0) {
pagesize = (XPointer)((long)_XawGetPageSize());
if (pagesize < (XPointer)BUFSIZ)
pagesize = (XPointer)BUFSIZ;
}
value->addr = (XPointer)&pagesize;
}