[comp.sys.mac.programmer] Please help with this code fragment!

bhil@ohs.UUCP (Brian T. Hill) (05/04/90)

Help!  In a program I'm writing (trACE(c) Test Generator), I need to draw
my own TE.  TEUpdate won't draw the text to the printer, or an offscreen
bit map, or into a picture definition.  Anyway, the function I wrote seems
to work fine, but it sometimes breaks down under system 6.0.5.  The problem
is that (under system 6.0.5) the startChar of the last style run is one more
than it should be.  My function follows.  PLEASE help.  I've mentioned this
problem to this newsgroup once before, without reply.


/*
 * drawtext.c
 *
 * trACE) Test Generator
 *
 * This file contains routines to draw text.  These routines are kept apart
 * from the rest of the program because they are believed to be a kludge;
 * that is, there is probably a better way of doing this, but I don't know
 * of any (better or worse).
 * "What?!" you say?  "Why not use 'TEUpdate()'?"  Unfortunately, it doesn't
 * work when printing, in a picture definition, in offscreen bitmaps, etc.
 *
 * 03 April 1990
 *
 * Brian T. Hill
 *
 */

#include "testgen.h"

extern struct windowstuff quesWindow;

TGDrawTextObject(objectList textobject){
	RgnHandle	oldclip;	/* restore clip region */
	RgnHandle	thisRgn;	/* region defined by the text rect */
	int	oldfont, oldmode, oldsize;	/* restore text settings */
	Style		oldface;
	TEStyleHandle	theStyleHdl;
	TEHandle	theTE;
	TextStyle	theStyle;	/* font, face, size, color */
	int		lineheight, fontascent;	/* returned by TEGetStyle() */
	CharsHandle	textHandle;	/* text to be drawn with DrawText() */
	int		run = 0;	/* the current style run */
	int		runlen;		/* the length of this style run */
	int		leftinrun;	/* number of characters left in run */
	int		howmany;	/* number of characters to write */
	int		start;		/* first character to write */
	int		line = (-1);	/* current line */
	int		linelen;	/* number of characters in line */
	int	leftinline = 0;	/* the number of characters left in the line */
	int	height = 0;	/* vertical coordinate from which to draw */
	short int	enough = 0;	/* flag to stop when enough is drawn */
	Rect		r;
		

	/*
	 * Get the current clipRgn so we can restore it later.  Then set the
	 * clipRgn to include only the part of the text box that will be
	 * displayed.
	 */
	oldclip = NewRgn();
	GetClip(oldclip);
	
	r = (**textobject).bounds;
	InsetRect(&r, 2, 2);
	thisRgn = NewRgn();
	RectRgn(thisRgn, &r);
	SectRgn(thePort->clipRgn, thisRgn, thePort->clipRgn);

	/*
	 * save the text settings
	 */
	oldfont = thePort->txFont;
	oldface = thePort->txFace;
	oldmode = thePort->txMode;
	oldsize = thePort->txSize;
	
	theTE = (** (textField) (**textobject).object).theTE;
	textHandle = TEGetText(theTE);
	MoveHHi(textHandle);
	HLock(textHandle);

	theStyleHdl = GetStylHandle(theTE);

	if (((**textobject).flags & transparentflag) == 0L)
		EraseRect(&(**textobject).bounds);

	/*
	 * outer loop:
	 *   Goes through this loop once for each style run.  This way,
	 *   we only need to get
	 *   and set the styles once for each run.
	 */
	while (run < (**theStyleHdl).nRuns && !enough){
		TEGetStyle(((**theStyleHdl).runs)[run].startChar,
				&theStyle, &lineheight, &fontascent, theTE);

		TextFont(theStyle.tsFont);
		TextFace(theStyle.tsFace);
		TextSize(theStyle.tsSize);
		
		runlen = ((**theStyleHdl).runs)[run+1].startChar -
					(**theStyleHdl).runs[run].startChar;

/*
 * This part shouldn't be commented out unless System 6.0.5 is running.
 *
 * 		if (run == (**theStyleHdl).nRuns - 1)
 * 			runlen--;
 */		

		leftinrun = runlen;
		
		/*
		 * inner loop:
		 *   As long as there are more characters in the current
		 *   style run, we don't need to change the styles.
		 *   So, we'll stay in this loop.
		 */
		while (leftinrun){
			if (!leftinline){
				if (height > (**textobject).bounds.bottom - 2){
					enough = 1;
					break;
				}
				line++;
				height = TEGetHeight(line+1, 0, theTE);
			
				/*
				 * Skip the font ascent:
				 */
				height -= (*(**theStyleHdl).lhTab)[line].lhHeight;
				height += (*(**theStyleHdl).lhTab)[line].lhAscent;
			
				height += (**textobject).bounds.top + 2;
				MoveTo((**textobject).bounds.left + 3, height);
				linelen = (**theTE).lineStarts[line+1] - (**theTE).lineStarts[line];
				leftinline = linelen;
			}
		
			/*
			 * leftinline:
			 *   We need to move the pen location to start a new
			 *   line.  This may still be within the current style
			 *   run.  Also, Inside Macintosh (Vol. I, page 172)
			 *   cautions not to call DrawText() with a byte count
			 *   greater than 255.
			 */
			if (leftinline > leftinrun)
				howmany = leftinrun;
			else
				howmany = leftinline;
			if (howmany > 255)
				howmany = 255;
			
			start = ((**theStyleHdl).runs)[run+1].startChar;			
/*
 * This part shouldn't be commented out unless System 6.0.5 is running.
 *
 *			if (run == (**theStyleHdl).nRuns - 1)
 *				start--;
 */		

			DrawText(*textHandle, start - leftinrun, howmany);

			leftinrun -= howmany;
			leftinline -= howmany;
		}
		
		run++;
	}
	
	/*
	 * restore clipRgn and text settings
	 */
	SetClip(oldclip);
	DisposeRgn(oldclip);
	DisposeRgn(thisRgn);
	thePort->txFont = oldfont;
	thePort->txFace = oldface;
	thePort->txMode = oldmode;
	thePort->txSize = oldsize;
	HUnlock(textHandle);	/* Don't dispose this;  it's a handle to the actual TE text. */
}



Brian T. Hill		bhil%ohs@iconsys.icon.com
(801) 227-8778		bhil@ohs
			ohs!bhil@uunet.uu.net

Rights to this code fragment belong to Board of Education of Alpine School
District, American Fork, Utah.