[comp.sys.next] finding line breaks in a Text object

simsong@daily-bugle.media.mit.edu (Simson L. Garfinkel) (01/11/91)

For the news reader, I had to be able to find the line breaks inside a Text object.  If you use the NeXT methods that return character offsets by lines, you actually get paragraphs, not lines.

If you want to get the *real* line breaks, the ones that are displayed on the screen, then you have to decode the internal variable "theBreaks."  It took me about 2 hours to figure out how to do that, and I'm posting the code here in case anybody else needs to do the similar thing:

/* This piece of code shows how to get line break information out of
 * a Text object.
 *
 * (C) 1990 MIT Media Lab.  By Simson L. Garfinkel
 */ 

#import "Thing.h"
#import <stdio.h>
#import <stdlib.h>
#import <appkit/ScrollView.h>
#import <appkit/Text.h>

@implementation Thing

- calc:sender
{
	Text		*text = [myScroller docView];
	int		line;
	int		pos;
	NXBreakArray	*theBreaks=0;
	int		nbreaks;
	NXLineDesc	*breaks;
	int		length = [text textLength];

	object_getInstanceVariable(text,"theBreaks",(void **)&theBreaks);

	nbreaks	= theBreaks->chunk.used;
	breaks  = theBreaks->breaks;

	for(pos=0,line=0;line<nbreaks && pos<length;line++){
		int	lineChange;
		int	endParagraph;
		int	len,nlen;
		char	*buf;

		lineChange	= breaks[line] & 0x8000;
		endParagraph	= breaks[line] & 0x4000;
		
		
		len	= breaks[line] & 0x2fff;
		buf	= malloc(len+1);
		
		nlen = [text getSubstring:buf start:pos length:len];
		buf[nlen] = '\000';
		
		printf("pos=%d len=%d eP=%d buf=%s",
		       pos,nlen,endParagraph,buf);
		
		free(buf);
		pos	+= len;

		if(lineChange!=0){
			/* "if the line change bit is set, the descriptor is
			 * the first field of a NXHeightChange...."
			 */
			line	+=  sizeof(NXHeightInfo)/sizeof(NXLineDesc);
		}
	}
	return self;
}

@end