I don't know if this will answer all your questions regarding text object manipulation, but this may give you more of a foundation. The following text is from a section of lite-c code specifically for doing stuff with text objects and their strings. A few of the functions are based on handling active buffering (meaning they can be changed on the fly and it handles it accordingly) for multiple text objects. I'll follow up with the header file and between the two I hope you can gleen something useful from it.

teletype.c code (used to present text in typewriter form, 1 char after the other. If you were to remove the wait instructions between the str_cpy's they'd appear immediately)

Code:
// // // // // // // // // //
// teletype.c
// Quantum Mechanic     2008
// // // // // // // // // //
#include "teletype.h"

// ****************************************************************************
// ROUTINE: TTteletype_init
// ----------------------------------------------------------------------------
// INPUT:
//		>	NULL
// OUTPUT:
//		>	NULL
// PURPOSE:
//  initialize teletype variables
// ----------------------------------------------------------------------------
void		TTteletype_init(void)
{
	var cnt = 0;
	for( cnt = 0 ; cnt < TTtxt1.strings ; cnt++ ) str_cpy( (TTtxt1.pstring)[cnt], ">" );
	for( cnt = 0 ; cnt < TTtxt2.strings ; cnt++ ) str_cpy( (TTtxt2.pstring)[cnt], ">" );
	for( cnt = 0 ; cnt < TTtxt3.strings ; cnt++ ) str_cpy( (TTtxt3.pstring)[cnt], ">" );
	for( cnt = 0 ; cnt < TTtxt4.strings ; cnt++ ) str_cpy( (TTtxt4.pstring)[cnt], ">" );
	str_cpy( (TTtxtInfo.pstring)[0], "INFOBAR - USED TO DISPLAY MISCELLANEOUS INFORMATION - ALSO CHANGES BORDER COLOR DEPENDING ON EXISTING CONDITIONS");
	
	reset1(TTtxt1,VISIBLE); // make the text object invisible (reset it's visible flag)
	reset1(TTtxt2,VISIBLE);
	reset1(TTtxt3,VISIBLE);
	reset1(TTtxt4,VISIBLE);
}
// ****************************************************************************
// ROUTINE: TTteletype_clearvars
// ----------------------------------------------------------------------------
// INPUT:
//		>	NULL
// OUTPUT:
//		>	NULL
// PURPOSE:
//  just clears the holder strings
// ----------------------------------------------------------------------------
void		TTteletype_clearvars(void)
{
	var cnt = 0;
}	
// ****************************************************************************
// ROUTINE: TT_addText
// ----------------------------------------------------------------------------
// INPUT:
//		>	tx						text object pointer
//		>	toNbr					text object number used for line position counter
//		>	istring					the string we want to add to tx
//		>	trunc					at how many chars do we truncate the input string
// OUTPUT:
//		>	NULL
// PURPOSE:
//  looks at the current line number (where the cursor would be) string of tx
//  and adds the input text to tx (it str_cpy's the string into tx).
//  if vTT_Cline[toNbr] == tx.strings, then call TT_scrollup on tx then add string.
// SIGNIFICANT CALLS:
//		c>	TT_scrollup
// SIGNIFICANT FLAGS:
//		f>	TTaddTextBUSY
// ----------------------------------------------------------------------------
void		TT_addText(TEXT* tx, var toNbr, STRING* istring, var trunc, var slowvar)
{
	char*	pdest	= NULL;
	char*	psrc	= NULL;
	STRING*	buff	= "#1024";
	int		cnt = 0;	// character counter
	var		lc = 0;		// line number we're on
	
	if(vTTaddTextBUSY) return;
	vTTaddTextBUSY = 1;
	lc = vTT_Cline[toNbr];	// get the current line (which equates to tx.string[x])
	vTT_TotalLines = tx.strings - 1;
	// add the input string to the text object
	str_cpy( buff, istring );				// first copy it to a buffer so our pointer is uncorrupted
	str_cpy( (tx.pstring)[lc], "#1024");	// for safety, buffer the output target string with more than enough spaces to avoid a pointer overrun!!!
	pdest = (tx.pstring)[lc]->chars;		// otherwise doing pointer arithmetic allows adding past the internal length of the string and hoses up
	psrc = buff->chars;
	vTT_LineLength = str_len(buff);			// get the length of the input string
	for( cnt = 0 ; cnt < trunc ; cnt++ )
	{
		pdest[cnt] = 17; // this is the pseudo-cursor placed first, then replaced with the actual character
		wait(slowvar);
		pdest[cnt] = psrc[cnt];
		if( cnt == _INT(vTT_LineLength) ) break; // if cnt == input string length, break loop
	}
	if( lc >= vTT_TotalLines )
	{
		lc = vTT_TotalLines; // if so, set position to last string
		TT_scrollup(tx, 1);  // scroll up 1 line
		while(vTTscrollupBUSY) wait(1);
	}
	lc++;
	if( lc > vTT_TotalLines )
		lc = vTT_TotalLines;
	vTT_Cline[toNbr] = lc; // update the line position variable for the text object
	vTTaddTextBUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TT_scrollup
// ----------------------------------------------------------------------------
// INPUT:
//			tx						text object pointer
//			howmany					how many lines to scroll up
// OUTPUT:
//			NULL
// PURPOSE:
//  scrolls up the contents of a text object by copying the contents of the
//  next line's contents to the current line and continuing on until it reachs
//  the number of strings in the text object
// SIGNIFICANT CALLS:
//		c>	NULL
// SIGNIFICANT FLAGS:
//		f>	vTTscrollupBUSY
// ----------------------------------------------------------------------------
void		TT_scrollup(TEXT* tx, var howmany)
{
	var		cnt		= 0;
	var		cnt2	= 0;
	var		totl	= 0;
	if(vTTscrollupBUSY) return;
	vTTscrollupBUSY = 1;
	totl = tx.strings;
	if(howmany > totl) howmany = totl;
	for( cnt2 = 0 ; cnt2 < howmany ; cnt2++ )
	{
		for( cnt = 0 ; cnt < (totl-1) ; cnt++ )
		{
			str_cpy( (tx.pstring)[cnt], (tx.pstring)[cnt + 1] );
			//wait(1);
		}
		str_cpy( (tx.pstring)[totl-1], ">" );
	}
	vTTscrollupBUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TTqueue
// ----------------------------------------------------------------------------
// INPUT:
//		>	tn						text object index number
//		>	slowvar					used as a delay for displaying the string
//		>	istring					the input string
// OUTPUT:
//		>	NULL
// PURPOSE:
//  given the text object object index number, a delay value and input string,
//  store all the information in a queue(stack) and output them to the corresponding
//  text object targets. The queue handles multiple calls even while processing.
//  Also sets the text coloring associated with a particular text object target.
// SIGNIFICANT CALLS:
//		c>	TT_addText
// SIGNIFICANT FLAGS:
//		f>	
// ----------------------------------------------------------------------------
void		TTqueue(var tn, var slowvar, STRING* istring)
{
	static var		lc = 0;			// tracks which buffer line we're on. basically a line pointer to line being handled
	static var		la = 0;			// tracks which line to add the incoming string to. basically a line pointer
	static var		queueBUSY = 0;	// used to ensure added strings don't interfere with current processing but get processed afterwards
	TEXT*			tttemp = NULL;	// used as a temp text object pointer
	
// 1) assign the text object target to the text pointer array for this index
// 2) store the index for the text object target (1 = TTtxt1, etc...) used to retrieve the line number for a particular text object
// 3) store the truncation value for the associated text object target
// 4) store the input string in the queue strings
// 5) store the delay value
// 6) set the color vector for the text object target
	switch(tn)
	{
		case 1:
			pTTq[la] = TTtxt1; vTTqindex[la] = 1; vTTqtrunc[la] = TTtxt1trunc; break;
		case 2:
			pTTq[la] = TTtxt2; vTTqindex[la] = 2; vTTqtrunc[la] = TTtxt2trunc; break;
		case 3:
			pTTq[la] = TTtxt3; vTTqindex[la] = 3; vTTqtrunc[la] = TTtxt3trunc; break;
		case 4:
			pTTq[la] = TTtxt4; vTTqindex[la] = 4; vTTqtrunc[la] = TTtxt4trunc; break;
		default:
			pTTq[la] = TTtxt1; vTTqindex[la] = 1; vTTqtrunc[la] = TTtxt1trunc;
	}
	str_cpy( (sTTq.pstring)[la], istring ); // store the input string
	vTTqdelay[la] = slowvar;				// store the delay for this string
	la++;									// increment the line counter
	if(queueBUSY) return;
	queueBUSY = 1;
	while( lc < la )
	{
		tttemp = pTTq[lc]; // retrieve the current text object pointer from the array into a local temp, makes it easier on the following calls
		switch(vTTqindex[lc])				// set the active color triplet for the current text object
		{
			case 1: vec_set(tttemp.blue, TTtxt1coloractive); break;
			case 2: vec_set(tttemp.blue, TTtxt2coloractive); break;
			case 3: vec_set(tttemp.blue, TTtxt3coloractive); break;
			case 4: vec_set(tttemp.blue, TTtxt4coloractive); break;
			default: vec_set(tttemp.blue, TTtxt1coloractive);
		}
		while(vTTaddTextBUSY) wait(1); // wait for addText to finish
		TT_addText(tttemp, vTTqindex[lc] , (sTTq.pstring)[lc], vTTqtrunc[lc], vTTqdelay[lc]); // send the current queue string to addText
		while(vTTaddTextBUSY) wait(1); // wait for addText to finish
		switch(vTTqindex[lc])				// set the inactive color triplet for the current text object
		{
			case 1: vec_set(tttemp.blue, TTtxt1colorinactive); break;
			case 2: vec_set(tttemp.blue, TTtxt2colorinactive); break;
			case 3: vec_set(tttemp.blue, TTtxt3colorinactive); break;
			case 4: vec_set(tttemp.blue, TTtxt4colorinactive); break;
			default: vec_set(tttemp.blue, TTtxt1colorinactive);
		}
		lc++; // increment current line pointer
		wait(1);
	}
	lc = 0;
	la = 0;
	queueBUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TTqueueFile
// ----------------------------------------------------------------------------
// INPUT:
//		>	tn						text object index number
//		>	slowvar					variable passed as a delay value
//		>	fn						filename string
// OUTPUT:
//		>	NULL
// PURPOSE:
//  using the queue function, outputs the contents of given text file to a
//  text object.
// SIGNIFICANT CALLS:
//		c>	TTqueue
// SIGNIFICANT FLAGS:
//		f>	vTT_BUSY
// ----------------------------------------------------------------------------
void		TTqueueFile(var tn, var slowvar, STRING* fn)
{
	var		ferr = 0;			// file operations return var
	STRING*	buff = "#1024";		// holds the incoming string from the file

	if(vTT_qFile_BUSY) return;
	vTT_qFile_BUSY = 1;
	vTT_FileHandle = file_open_read(fn);
	if(!vTT_FileHandle) return;
	ferr = file_str_read(vTT_FileHandle, buff);
	while(ferr > 0)
	{
		TTqueue(tn, slowvar, buff);
		ferr = file_str_read(vTT_FileHandle, buff);
		wait(1);
	}
	file_close(vTT_FileHandle);
	vTT_qFile_BUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TTclearText
// ----------------------------------------------------------------------------
// INPUT:
//		>	tn						text object index number
// OUTPUT:
//		>	NULL
// PURPOSE:
//  clears a text object and resets the line counter
// SIGNIFICANT CALLS:
//		c>	
// SIGNIFICANT FLAGS:
//		f>	
// ----------------------------------------------------------------------------
void		TTclearText(var tn)
{
	var cnt = 0;
	var tot = 0;
	TEXT* tttemp = NULL;

	if( TTcheckFlags(23) ) return; // all flags except vTT_clrAll_BUSY (8)  [ 31 - 8 = 23 ]
	vTT_clr_BUSY = 1;
	switch(tn)
	{
		case 1: tttemp = TTtxt1; break;
		case 2: tttemp = TTtxt2; break;
		case 3: tttemp = TTtxt3; break;
		case 4: tttemp = TTtxt4; break;
		default: tttemp = TTtxt1; tn = 1; // this makes sure a valid index is always used
	}
	tot = tttemp.strings;
	avar = tn;
	for(cnt = 0; cnt < tot ; cnt++)
	{
		str_cpy( (tttemp.pstring)[cnt], ">" );
		//wait(1);
	}
	vTT_Cline[tn] = 0;
	vTT_clr_BUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TTclearText
// ----------------------------------------------------------------------------
// INPUT:
//		>	tn						text object index number
// OUTPUT:
//		>	NULL
// PURPOSE:
//  clears a text object and resets the line counter
// SIGNIFICANT CALLS:
//		c>	
// SIGNIFICANT FLAGS:
//		f>	
// ----------------------------------------------------------------------------
void		TTclearTextAll(void)
{
	if( TTcheckFlags(31) ) return; // all flags
	vTT_clrAll_BUSY = 1;
	TTclearText(1);
	while(vTT_clr_BUSY) wait(1);
	TTclearText(2);
	while(vTT_clr_BUSY) wait(1);
	TTclearText(3);
	while(vTT_clr_BUSY) wait(1);
	TTclearText(4);
	while(vTT_clr_BUSY) wait(1);
	vTT_clrAll_BUSY = 0;
	return;
}
// ****************************************************************************
// ROUTINE: TTcheckFlags
// ----------------------------------------------------------------------------
// INPUT:
//		>	NULL
// OUTPUT:
//		>	var						if any active flag is set this return a 1
// PURPOSE:
//  checks all the active function flags and returns a bit mask encoded variable.
//  i.e. each flag represents a bit position in the returned value as well as
//  setting a global variable with the result.
// SIGNIFICANT CALLS:
//		c>	
// SIGNIFICANT FLAGS:
//		f>	ALL active function flags
// ----------------------------------------------------------------------------
var			TTcheckFlags(var vmask)
{
	var a = 0;
	a = 0;
	if( vmask & 1 )
		if(vTT_qFile_BUSY)	a += 1;
	if( vmask & 2 )
		if(vTTaddTextBUSY)	a += 2;
	if( vmask & 4 )
		if(vTTscrollupBUSY)	a += 4;
	if( vmask & 8 )
		if(vTT_clrAll_BUSY)	a += 8;
	if( vmask & 16 )
		if(vTT_clr_BUSY)	a += 16;
	vTT_FlagCheck = a;
	return(a);
}
// ****************************************************************************
// ROUTINE: 
// ----------------------------------------------------------------------------
// INPUT:
//		>	
// OUTPUT:
//		>	
// PURPOSE:
//  
// SIGNIFICANT CALLS:
//		c>	
// SIGNIFICANT FLAGS:
//		f>	
// ----------------------------------------------------------------------------
void		TTshowInfo(STRING* istring)
{
	str_cpy( (TTtxtInfo.pstring)[0], istring );
	return;
}

// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING TESTING
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

void		TTtest1(void)
{
	if( TTcheckFlags(31) ) return; // see if any of the functions are active
	TTclearText(2);
	while(vTT_clr_BUSY) wait(1);
	TTqueueFile(2,1,"systems\\syscheck.txt");
	while(vTT_qFile_BUSY) wait(1);
	wait(-2);
	TTclearText(2);
	while(vTT_clr_BUSY) wait(1);
	TTqueueFile(2,1,"systems\\interface.txt");
	while(vTT_qFile_BUSY) wait(1);
}
void		TTtest2(void)
{
	if( TTcheckFlags(31) ) return; // see if any of the functions are active
	TTclearText(2);
	while(vTT_clr_BUSY) wait(1);
	TTqueueFile(2,1,"systems\\syscheck.txt");
	while(vTT_qFile_BUSY) wait(1);
}
void		TTtest3(void)
{
	if( TTcheckFlags(1) ) return;
	for(vTT_temp = 0; vTT_temp < 2 ; vTT_temp++)
	{
		TTqueue(2, 1, "test 2-1 @ 1");
		TTqueue(4, 1, "test 4-1 @ 1");
		TTqueue(3, 1, "test 3-1 @ 1");
		TTqueue(3, 1, "test 3-2");
		TTqueue(2, 1, "test 2-2");
		TTqueue(4, 1, "test 4-2");
	}
}
	
void		TTclear3(void)
{
	if( TTcheckFlags(31) ) return;
	TTclearText(3);
	while(vTT_clr_BUSY) wait(1);
}

void		TTforceFlagCheck(void)
{
	TTcheckFlags(31);
}



Last edited by quantum69; 07/29/08 07:27.

------------------------------------
Quantum Mechanic
Better living at the subatomic level