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.