if (!space_string) { /* Make a blank line */
char *p;
space_string = (char *)malloc(HTScreenWidth+1);
for (p=space_string; p<space_string+HTScreenWidth; p++)
*p = ' '; /* Used for printfs later */
space_string[HTScreenWidth] = '\0';
}
return self;
}
/* Free Entire Text
** ----------------
*/
PUBLIC void HText_free ARGS1(HText *,self)
{
HTAnchor_setDocument(self->node_anchor, (HyperDoc *)0);
while(YES) { /* Free off line array */
HTLine * l = self->last_line;
l->next->prev = l->prev;
l->prev->next = l->next; /* Unlink l */
self->last_line = l->prev;
free(l);
if (l == self->last_line) break; /* empty */
};
while(self->first_anchor) { /* Free off anchor array */
TextAnchor * l = self->first_anchor;
self->first_anchor = l->next;
free(l);
}
free(self);
}
/* Display Methods
** ---------------
*/
/* Clear the screen (on screen-mode systems)
** ----------------
*/
PUBLIC void clear_screen NOARGS
{
#ifdef VM
#ifdef NEWLIB
int newlib_ncmd = 2;
char newlib_cmd[2][80];
#else /* not NEWLIB - real VM */
system("CLRSCRN"); /* Clear screen */
#endif /* not NEWLIB */
#else /* Not VM */
/* Do nothing */
#endif /* Not VM */
if (HTMainText) HTMainText->stale = YES;
}
/* Output a line
** -------------
*/
PRIVATE void display_line ARGS1(HTLine *,line)
{
printf("%s%s\n", SPACES(line->offset), line->data);
}
/* Output the title line
** ---------------------
*/
PRIVATE void display_title ARGS1(HText *,text)
{
CONST char * title = HTAnchor_title(text->node_anchor);
char percent[20], format[20];
if (text->lines > (DISPLAY_LINES-1)) {
#ifdef NOPE
sprintf(percent, " (p%d of %d)",
(text->top_of_screen/(DISPLAY_LINES-1)) + 1,
(text->lines-1)/(DISPLAY_LINES-1) + 1);
sprintf(percent, " (%d%%)",
100*(text->top_of_screen+DISPLAY_LINES-1)/ /* Seen */
(text->lines)); /* Total */
#else
sprintf(percent, " (%d/%d)",
text->top_of_screen+DISPLAY_LINES-1, /* Seen */
text->lines); /* Total */
#endif
} else {
percent[0] = 0; /* Null string */
}
sprintf(format, "%%%d.%ds%%s\n", /* Generate format string */
HTScreenWidth-strlen(percent),
HTScreenWidth-strlen(percent));
if (TRACE) fprintf(stderr, "FORMAT IS `%s'\n", format);
printf(format, title, percent);
}
/* Fill the screen with blank after the file
** --------------------------
*/
PRIVATE void fill_screen ARGS1(int,n)
{
if (n<=0) return;
if (!interactive) return;
#ifndef VIOLA
printf("%s\n", end_mark);
n--;
for (; n; n--) {
printf("\n");
}
#endif
}
/* Output a page
** -------------
*/
PRIVATE void display_page ARGS2(HText *,text, int,line_number)
{
HTLine * line = text->last_line->prev;
int i;
CONST char * title = HTAnchor_title(text->node_anchor);
int lines_of_text = title ? DISPLAY_LINES-1 : DISPLAY_LINES;
int last_screen = text->lines - lines_of_text;
/* Constrain the line number to be within the document
*/
if (text->lines <= lines_of_text) line_number = 0;
else if (line_number>last_screen) line_number = last_screen;
else if (line_number < 0) line_number = 0;
for(i=0, line = text->last_line->next; /* Find line */
i<line_number && (line!=text->last_line);
i++, line=line->next) /* Loop */;
/* Can we just scroll to it?
*/
if (!text->stale && (line_number>=text->top_of_screen) &&
(line_number < text->top_of_screen + DISPLAY_LINES)) { /* Yes */
lines_of_text = line_number - text->top_of_screen;
line = text->next_line;
text->top_of_screen = line_number;
} else {
clear_screen(); /* No */
text->top_of_screen = line_number;
if (title) display_title(text);
}
/* print it
*/
if (line) {
for(i=0;
i< lines_of_text && (line != text->last_line); i++) {
display_line(line);
line = line->next;
}
fill_screen(lines_of_text - i);
}
text->next_line = line; /* Line after screen */
text->stale = NO; /* Display is up-to-date */
}
/* Object Building methods
** -----------------------
**
** These are used by a parser to build the text in an object
*/
PUBLIC void HText_beginAppend ARGS1(HText *,text)
{
text->permissible_split = 0;
text->in_line_1 = YES;
}
/* Add a new line of text
** ----------------------
**
** On entry,
**
** split is zero for newline function, else number of characters
** before split.
** text->display_on_the_fly
** may be set to indicate direct output of the finished line.
** On exit,
** A new line has been made, justified according to the
** current style. Text after the split (if split nonzero)
** is taken over onto the next line.
**
** If display_on_the_fly is set, then it is decremented and
** the finished line is displayed.
*/
#define new_line(text) split_line(text, 0)