Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
539
cde/lib/tt/demo/CoEd/libCoEd/CoEdTextChange.C
Normal file
539
cde/lib/tt/demo/CoEd/libCoEd/CoEdTextChange.C
Normal file
@@ -0,0 +1,539 @@
|
||||
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
|
||||
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
|
||||
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
||||
//%% (c) Copyright 1993, 1994 Novell, Inc.
|
||||
//%% $XConsortium: CoEdTextChange.C /main/3 1995/10/20 17:07:30 rswiston $
|
||||
/*
|
||||
* CoEdTextChange.cc
|
||||
*
|
||||
* Copyright (c) 1991 by Sun Microsystems. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the names of Sun
|
||||
* Microsystems and its subsidiaries not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Sun Microsystems and its
|
||||
* subsidiaries make no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
* Sun Microsystems and its subsidiaries disclaim all warranties with
|
||||
* regard to this software, including all implied warranties of
|
||||
* merchantability and fitness. In no event shall Sun Microsystems or
|
||||
* its subsidiaries be liable for any special, indirect or
|
||||
* consequential damages or any damages whatsoever resulting from loss
|
||||
* of use, data or profits, whether in an action of contract,
|
||||
* negligence or other tortious action, arising out of or in
|
||||
* connection with the use or performance of this software.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <limits.h>
|
||||
#include "CoEdTextVersion.h"
|
||||
#include "CoEdTextChange.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
CoEdTextChange::
|
||||
CoEdTextChange()
|
||||
{
|
||||
_start = 0;
|
||||
_end = 0;
|
||||
_text = 0;
|
||||
_appliesTo = 0;
|
||||
_causer = 0;
|
||||
_changeNum = 0;
|
||||
_charsAdded = 0;
|
||||
_next = 0;
|
||||
_prev = 0;
|
||||
}
|
||||
|
||||
CoEdTextChange::
|
||||
CoEdTextChange( long start, long end, const char *text,
|
||||
const CoEdTextVersion *appliesTo, const CoEdSiteID *causer,
|
||||
int changeNum )
|
||||
{
|
||||
_next = 0;
|
||||
_prev = 0;
|
||||
_start = start;
|
||||
_end = end;
|
||||
if (text != 0) {
|
||||
_text = strdup( text );
|
||||
} else {
|
||||
_text = 0;
|
||||
}
|
||||
_charsAdded = ((_text == 0) ? 0 : strlen( _text ))
|
||||
- (_end - _start);
|
||||
_appliesTo = appliesTo->copy();
|
||||
_causer = causer->copy();
|
||||
_changeNum = changeNum;
|
||||
}
|
||||
|
||||
CoEdTextChange::
|
||||
CoEdTextChange( const CoEdTextChange &change )
|
||||
{
|
||||
_next = 0;
|
||||
_prev = 0;
|
||||
_start = change._start;
|
||||
_end = change._end;
|
||||
if (change._text != 0) {
|
||||
_text = strdup( change._text );
|
||||
} else {
|
||||
_text = 0;
|
||||
}
|
||||
_charsAdded = change._charsAdded;
|
||||
_appliesTo = change._appliesTo->copy();
|
||||
_causer = change._causer->copy();
|
||||
_changeNum = change._changeNum;
|
||||
}
|
||||
|
||||
CoEdTextChange::
|
||||
CoEdTextChange( Tt_message msg, CoEdStatus &status )
|
||||
{
|
||||
unsigned char *data;
|
||||
int len;
|
||||
|
||||
_next = 0;
|
||||
_prev = 0;
|
||||
_charsAdded = 0;
|
||||
//
|
||||
// Extract arg 0: CoEdTextVersion
|
||||
//
|
||||
Tt_status ttErr = tt_message_arg_bval( msg, 0, &data, &len );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_bval(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
_appliesTo = new CoEdTextVersion( data, len, status );
|
||||
if (status != CoEdOK) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
// Extract arg 1: changeNum
|
||||
//
|
||||
int argVal;
|
||||
ttErr = tt_message_arg_ival( msg, 1, &argVal );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_ival(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
_changeNum = argVal;
|
||||
//
|
||||
// Extract arg 2: start
|
||||
//
|
||||
ttErr = tt_message_arg_ival( msg, 2, &argVal );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_ival(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
_start = argVal;
|
||||
//
|
||||
// Extract arg 3: end
|
||||
//
|
||||
ttErr = tt_message_arg_ival( msg, 3, &argVal );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_ival(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
_end = argVal;
|
||||
//
|
||||
// Extract arg 4: text
|
||||
//
|
||||
char *temp = tt_message_arg_val( msg, 4 );
|
||||
ttErr = tt_ptr_error( temp );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_val(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
if (temp == 0) {
|
||||
_text = 0;
|
||||
} else {
|
||||
_text = strdup( temp );
|
||||
if (_text == 0) {
|
||||
fprintf( stderr, "libCoEd: ran out of memory!\n" );
|
||||
status = CoEdErrNoMem;
|
||||
return;
|
||||
}
|
||||
tt_free( temp );
|
||||
}
|
||||
_charsAdded = _end - _start
|
||||
+ ((_text == 0) ? 0 : strlen( _text ));
|
||||
//
|
||||
// Extract who caused the change.
|
||||
//
|
||||
temp = tt_message_sender( msg );
|
||||
ttErr = tt_ptr_error( temp );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_sender(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
status = (CoEdStatus)ttErr;
|
||||
return;
|
||||
}
|
||||
_causer = new CoEdSiteID( temp );
|
||||
if (_causer == 0) {
|
||||
fprintf( stderr, "libCoEd: ran out of memory!\n" );
|
||||
status = CoEdErrNoMem;
|
||||
return;
|
||||
}
|
||||
tt_free( temp );
|
||||
status = CoEdOK;
|
||||
}
|
||||
|
||||
CoEdTextChange::
|
||||
~CoEdTextChange()
|
||||
{
|
||||
if (_text != 0) {
|
||||
free( (char *)_text );
|
||||
}
|
||||
if (_appliesTo != 0) {
|
||||
delete _appliesTo;
|
||||
}
|
||||
if (_causer != 0) {
|
||||
delete _causer;
|
||||
}
|
||||
}
|
||||
|
||||
CoEdStatus CoEdTextChange::
|
||||
broadcast( const char *path ) const
|
||||
{
|
||||
//
|
||||
// Create the message.
|
||||
//
|
||||
Tt_message msg = tt_pnotice_create( TT_FILE, "Text_File_Changed" );
|
||||
Tt_status ttErr = tt_ptr_error( msg );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_pnotice_create(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Set the file of the message.
|
||||
//
|
||||
ttErr = tt_message_file_set( msg, path );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_file_set(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Add arg 0: CoEdTextVersion
|
||||
//
|
||||
unsigned long len;
|
||||
unsigned char *data;
|
||||
CoEdStatus err = _appliesTo->serialize( &data, &len );
|
||||
if (err != CoEdOK) {
|
||||
fprintf( stderr, "libCoEd: CoEdTextVersion::serialize(): %d\n",
|
||||
(int)err );
|
||||
return err;
|
||||
}
|
||||
ttErr = tt_message_barg_add( msg, TT_IN, "CoEdTextVersion", data,
|
||||
(int)len );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_barg_add(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Add arg 1: changeNum
|
||||
//
|
||||
ttErr = tt_message_iarg_add( msg, TT_IN, "int", (int)_changeNum );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_iarg_add(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Add arg 2: start
|
||||
//
|
||||
ttErr = tt_message_iarg_add( msg, TT_IN, "int", (int)_start );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_iarg_add(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Add arg 3: end
|
||||
//
|
||||
ttErr = tt_message_iarg_add( msg, TT_IN, "int", (int)_end );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_iarg_add(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Add arg 4: text
|
||||
//
|
||||
if (_text == 0) {
|
||||
ttErr = tt_message_arg_add( msg, TT_IN, "string", "" );
|
||||
} else {
|
||||
ttErr = tt_message_arg_add( msg, TT_IN, "string", _text );
|
||||
}
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_arg_add(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
//
|
||||
// Send the message.
|
||||
//
|
||||
#ifdef DEBUG
|
||||
static Tt_message oldMsg = 0;
|
||||
if (oldMsg == 0) {
|
||||
oldMsg = msg;
|
||||
return CoEdOK;
|
||||
} else {
|
||||
ttErr = tt_message_send( oldMsg );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_send(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
ttErr = tt_message_destroy( oldMsg );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_destroy(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
oldMsg = 0;
|
||||
}
|
||||
#endif DEBUG
|
||||
ttErr = tt_message_send( msg );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_send(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
ttErr = tt_message_destroy( msg );
|
||||
if (ttErr != TT_OK) {
|
||||
fprintf( stderr, "libCoEd: tt_message_destroy(): %s\n",
|
||||
tt_status_message( ttErr ));
|
||||
return (CoEdStatus)ttErr;
|
||||
}
|
||||
return CoEdOK;
|
||||
}
|
||||
|
||||
//
|
||||
// This method serves two purposes. First, it takes chng2Xlate,
|
||||
// and adjusts it forward in time over this change, so that we
|
||||
// will be able to apply the modified chng2Xlate to our local
|
||||
// text (to which this change has already been applied).
|
||||
// Second, since the _un_modified chng2Xlate is being put into the
|
||||
// history list _before_ this change, we need to modify this
|
||||
// change so that it makes sense when applied to a text that
|
||||
// has already had the unmodified chng2Xlate applied to it.
|
||||
//
|
||||
void CoEdTextChange::
|
||||
interTranslate( CoEdTextChange &chng2Xlate )
|
||||
{
|
||||
//
|
||||
// First, adjust chng2Xlate forward in time over this change.
|
||||
//
|
||||
int directionToLean = (chng2Xlate._end > _end) ? 1 : 0;
|
||||
long xlatdStart = adjustPt( chng2Xlate._start, *chng2Xlate._causer,
|
||||
directionToLean );
|
||||
directionToLean = (chng2Xlate._start < _start) ? -1 : 0;
|
||||
long xlatdEnd = adjustPt( chng2Xlate._end, *chng2Xlate._causer,
|
||||
directionToLean );
|
||||
//
|
||||
// Second, adjust this change into a form that makes
|
||||
// sense if chng2Xlate had already been applied when
|
||||
// it was time to apply this change.
|
||||
//
|
||||
directionToLean = (_end > chng2Xlate._end) ? 1 : 0;
|
||||
long _startNew = chng2Xlate.adjustPt( _start, *_causer,
|
||||
directionToLean );
|
||||
directionToLean = (_start < chng2Xlate._start) ? -1 : 0;
|
||||
long _endNew = chng2Xlate.adjustPt( _end, *_causer, directionToLean );
|
||||
//
|
||||
// Now, modify this change and chng2Xlate, as calculated.
|
||||
//
|
||||
_start = _startNew;
|
||||
_end = _endNew;
|
||||
//_appliesTo->update( *chng2Xlate._causer, chng2Xlate._changeNum );
|
||||
chng2Xlate._start = xlatdStart;
|
||||
chng2Xlate._end = xlatdEnd;
|
||||
//chng2Xlate._appliesTo->update( *_causer, _changeNum );
|
||||
}
|
||||
|
||||
void CoEdTextChange::
|
||||
translateOver( const CoEdTextChange &chng2Hurdle )
|
||||
{
|
||||
int directionToLean = (_end > chng2Hurdle._end) ? 1 : 0;
|
||||
long newStart = chng2Hurdle.adjustPt( _start, *_causer,
|
||||
directionToLean );
|
||||
directionToLean = (_start < chng2Hurdle._start) ? -1 : 0;
|
||||
long newEnd = chng2Hurdle.adjustPt( _end, *_causer,
|
||||
directionToLean );
|
||||
//_appliesTo->update( *chng2Hurdle._causer, chng2Hurdle._changeNum );
|
||||
_start = newStart;
|
||||
_end = newEnd;
|
||||
}
|
||||
|
||||
long CoEdTextChange::
|
||||
adjustPt( long pt, const CoEdSiteID &ptOwner, int directionToLean ) const
|
||||
{
|
||||
if (pt < _start) {
|
||||
return pt;
|
||||
}
|
||||
if (pt > _end) {
|
||||
return pt + charsAddedBy();
|
||||
}
|
||||
//
|
||||
// pt lies within our change, so it needs to be adjusted to
|
||||
// one end of our change. First, check if the caller has
|
||||
// a preference.
|
||||
//
|
||||
if (directionToLean < 0) {
|
||||
return _start;
|
||||
} else if (directionToLean > 0) {
|
||||
return _start + charsAddedBy();
|
||||
} else {
|
||||
//
|
||||
// The caller has no preference, so decide by order
|
||||
// of CoEdSiteID.
|
||||
//
|
||||
if (*_causer < ptOwner) {
|
||||
return _start + charsAddedBy();
|
||||
} else {
|
||||
return _start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoEdTextChange::
|
||||
print( FILE *f )
|
||||
{
|
||||
fprintf( f, "[%3d, %3d] %2d: <", _start, _end, _charsAdded );
|
||||
if (_text == 0) {
|
||||
fprintf( f, "%6s", ">" );
|
||||
} else {
|
||||
fprintf( f, "%-5.5s>", _text );
|
||||
}
|
||||
fprintf( f, " #%2d ", _changeNum );
|
||||
_causer->print( f );
|
||||
fputs( " ", f );
|
||||
_appliesTo->print( f );
|
||||
fputs( "\n", f );
|
||||
}
|
||||
|
||||
CoEdTextChangeList::
|
||||
CoEdTextChangeList()
|
||||
{
|
||||
_head = 0;
|
||||
_tail = 0;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
CoEdTextChangeList::
|
||||
~CoEdTextChangeList()
|
||||
{
|
||||
CoEdTextChange *curr = _head;
|
||||
CoEdTextChange *prev;
|
||||
while (curr != 0) {
|
||||
prev = curr;
|
||||
curr = curr->_next;
|
||||
delete prev;
|
||||
}
|
||||
}
|
||||
|
||||
void CoEdTextChangeList::
|
||||
push( CoEdTextChange *change )
|
||||
{
|
||||
change->_next = _head;
|
||||
change->_prev = 0;
|
||||
if (_tail == 0) {
|
||||
_tail = change;
|
||||
} else {
|
||||
_head->_prev = change;
|
||||
}
|
||||
_head = change;
|
||||
_count++;
|
||||
}
|
||||
|
||||
void CoEdTextChangeList::
|
||||
append( CoEdTextChange *change )
|
||||
{
|
||||
change->_next = 0;
|
||||
change->_prev = _tail;
|
||||
if (_head == 0) {
|
||||
_head = change;
|
||||
} else {
|
||||
_tail->_next = change;
|
||||
}
|
||||
_tail = change;
|
||||
_count++;
|
||||
}
|
||||
|
||||
void CoEdTextChangeList::
|
||||
insertBefore( CoEdTextChange *change1, CoEdTextChange *change2 )
|
||||
{
|
||||
if (_head == change2) {
|
||||
push( change1 );
|
||||
return;
|
||||
}
|
||||
change1->_next = change2;
|
||||
change1->_prev = change2->_prev;
|
||||
change2->_prev->_next = change1;
|
||||
change2->_prev = change1;
|
||||
_count++;
|
||||
}
|
||||
|
||||
void CoEdTextChangeList::
|
||||
insertAfter( CoEdTextChange *change2, CoEdTextChange *change1 )
|
||||
{
|
||||
if (_tail == change1) {
|
||||
append( change2 );
|
||||
return;
|
||||
}
|
||||
change2->_next = change1->_next;
|
||||
change2->_prev = change1;
|
||||
change1->_next->_prev = change2;
|
||||
change1->_next = change2;
|
||||
_count++;
|
||||
}
|
||||
|
||||
CoEdTextChange *CoEdTextChangeList::
|
||||
remove( CoEdTextChange *change )
|
||||
{
|
||||
if (change == _head) {
|
||||
_head = change->_next;
|
||||
} else {
|
||||
change->_prev->_next = change->_next;
|
||||
}
|
||||
if (change == _tail) {
|
||||
_tail = change->_prev;
|
||||
} else {
|
||||
change->_next->_prev = change->_prev;
|
||||
}
|
||||
change->_next = 0;
|
||||
change->_prev = 0;
|
||||
_count--;
|
||||
return change;
|
||||
}
|
||||
|
||||
void CoEdTextChangeList::
|
||||
print( FILE *f, char *indent )
|
||||
{
|
||||
CoEdTextChange *curr = _head;
|
||||
while (curr != 0) {
|
||||
fprintf( f, indent );
|
||||
curr->print( f );
|
||||
curr = curr->_next;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user