home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
emxtutor.zip
/
emxsrcd1.zip
/
emx
/
src
/
emxdoc
/
text.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-19
|
10KB
|
466 lines
/* text.c -- Text output
Copyright (c) 1993-1995 Eberhard Mattes
This file is part of emxdoc.
emxdoc is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
emxdoc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with emxdoc; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "emxdoc.h"
#include "text.h"
#include "lb.h"
static int text_width = 70;
static int format_width;
static int format_margin;
static struct lb *lb;
static struct lbh *lbh = NULL;
static void text_indent (int margin)
{
uchar *s;
int i;
i = margin - output_x;
if (i > 0)
{
s = alloca (i);
memset (s, ' ', i);
write_nstring (s, i);
}
}
static void text_para (void)
{
if (para_flag)
{
para_flag = FALSE;
write_nl ();
}
}
static int isblank (const uchar *p)
{
while (*p != 0)
if (*p++ != ' ')
return FALSE;
return TRUE;
}
void text_output (const uchar *p, int may_break)
{
if (opt_b == 0)
{
if (may_break && output_x + strlen (p) > format_width)
write_nl ();
text_indent (format_margin);
write_string (p);
}
else
{
int rc;
if (may_break && isblank (p))
rc = lb_glue (lb, strlen (p), NULL);
else
rc = lb_word (lb, strlen (p), p, NULL);
if (rc != 0)
fatal ("lb_glue or lb_word failed, rc=%d", rc);
}
}
static int text_elements (int margin, int width, int newline)
{
const struct element *ep, *ep2;
int i, spaces, line, rc;
enum style style_stack[STYLE_STACK_SIZE];
int style_sp;
enum style style = STYLE_NORMAL;
style_sp = 0;
style_stack[style_sp] = style;
line = output_line_no; spaces = 0;
format_width = width; format_margin = margin;
if (opt_b != 0)
{
rc = lb_init (&lb, margin, width);
if (rc != 0)
fatal ("lb_init failed, rc=%d", rc);
if (output_x > margin)
lb_first_lmargin (lb, output_x);
}
for (ep = elements; ep->el != EL_END; ++ep)
switch (ep->el)
{
case EL_WORD:
case EL_PUNCT:
if (spaces != 0)
{
format_spaces (spaces, STYLE_NORMAL); spaces = 0;
}
if (ep->wp->special != NULL && ep->wp->special->text != NULL)
format_output (ep->wp->special->text, FALSE);
else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
? ep->wp->style : style), FALSE);
else
format_string (ep->wp->str, style_stack[style_sp], FALSE);
break;
case EL_SPACE:
if (opt_b == 0)
{
spaces += ep->n;
i = 0;
ep2 = ep + 1;
while (ep2->el != EL_END && ep2->el != EL_SPACE)
{
if (ep2->el == EL_WORD || ep2->el == EL_PUNCT)
i += strlen (ep2->wp->str);
++ep2;
}
if (output_x + spaces + i > format_width)
{
write_nl ();
spaces = 0;
}
}
else
format_spaces (ep->n, STYLE_NORMAL);
break;
case EL_BREAK:
if (opt_b == 0)
{
if (output_x != 0 || ep->n)
{
write_nl (); spaces = 0;
}
}
else
lb_penalty (lb, -10000);
break;
case EL_STYLE:
if (style_sp + 1 >= STYLE_STACK_SIZE)
fatal ("%s:%d: Style stack overflow", input_fname, line_no);
style_stack[++style_sp] = ep->n;
break;
case EL_ENDSTYLE:
if (style_sp == 0)
fatal ("%s:%d: Style stack underflow", input_fname, line_no);
--style_sp;
break;
default:
abort ();
}
if (opt_b != 0)
{
struct lb_node lbn;
if (lbh != NULL)
lb_use_hyphenation (lb, lbh);
rc = lb_format (lb);
if (rc != 0)
fatal ("lb_format failed, rc=%d", rc);
for (;;)
{
rc = lb_next (lb, &lbn);
if (rc != 0)
fatal ("lb_next failed, rc=%d", rc);
if (lbn.type == LBN_END)
break;
switch (lbn.type)
{
case LBN_WORD:
case LBN_PRE:
case LBN_POST:
text_indent (margin);
write_string (lbn.word);
break;
case LBN_GLUE:
text_indent (margin);
write_fmt ("%*s", lbn.value, "");
break;
case LBN_NEWLINE:
write_nl ();
break;
default:
abort ();
}
}
lb_exit (&lb);
}
if (newline && output_x > margin)
write_nl ();
return output_line_no - line;
}
void text_heading1 (void)
{
env_stack[0].tmargin = 0;
write_nl ();
write_nl ();
}
void text_heading2 (uchar *s)
{
if (tg_level == 0)
{
if (para_flag)
write_nl ();
write_nl ();
}
write_line (s);
strset (s, tg_underline);
write_line (s);
}
void text_see_also_start (void)
{
if (para_flag)
write_nl ();
}
void text_see_also_end (const uchar *s)
{
write_string (" See also: ");
make_elements (s);
text_elements (output_x, text_width, TRUE);
}
void text_description_item (const uchar *s)
{
write_nl ();
text_para ();
make_elements (s);
text_elements (env_stack[env_sp-1].tmargin, text_width, FALSE);
if (output_x + 2 <= env_stack[env_sp].tmargin)
write_string (" ");
else
write_nl ();
}
void text_enumerate_item (void)
{
write_nl ();
text_para ();
text_indent (env_stack[env_sp-1].tmargin);
write_fmt ("%d.", ++env_stack[env_sp].counter);
}
void text_itemize_item (void)
{
write_nl ();
text_para ();
text_indent (env_stack[env_sp-1].tmargin);
write_string ("- ");
}
void text_list_item (const uchar *s)
{
write_nl ();
text_para ();
make_elements (s);
text_elements (env_stack[env_sp-1].tmargin, text_width, TRUE);
write_nl ();
}
void text_copy (void)
{
if (para_flag)
write_nl ();
text_elements (env_stack[env_sp].tmargin, text_width, TRUE);
}
void text_verbatim_start (enum tag tag_end, int *ptmargin)
{
switch (tag_end)
{
case TAG_ENDHEADERS:
break;
case TAG_ENDSAMPLECODE:
write_nl ();
write_line (" Example:");
write_nl ();
break;
case TAG_ENDEXAMPLE:
*ptmargin += 4;
write_nl ();
break;
default:
write_nl ();
break;
}
}
static void add_compat (uchar *dst, uchar *compat)
{
int i, len;
len = strlen (dst);
i = 78 - len - strlen (compat) - 2;
if (i > 0)
{
memset (dst + len, ' ', i);
len += i;
}
dst[len++] = '[';
strcpy (dst+len, compat);
strcat (dst+len, "]");
compat[0] = 0;
}
void text_verbatim_line (enum tag tag_end, int tmargin, uchar *compat)
{
uchar buf[512];
memset (buf, ' ', tmargin);
strcpy (buf + tmargin, input);
if (tag_end == TAG_ENDHEADERS && compat[0] != 0)
add_compat (buf, compat);
write_line (buf);
}
void text_function (void)
{
env_stack[0].tmargin = 0;
write_nl ();
write_line("---------------------------------------"
"---------------------------------------");
}
void text_prototype_start (uchar *compat)
{
uchar buf[512];
if (compat[0] != 0)
{
buf[0] = 0;
add_compat (buf, compat);
write_string (buf);
}
write_nl ();
}
void text_prototype_end (void)
{
text_elements (0, 78, TRUE);
env_stack[0].tmargin = 4;
}
void text_toc_line (const uchar *s, const struct toc *tp)
{
write_string (s);
write_line (tp->title);
}
void text_table_start (int do_indent, int *ptmargin)
{
if (do_indent)
*ptmargin += 4;
write_nl ();
}
void text_table_line (const uchar *s, int tmargin)
{
make_elements (s);
if (text_elements (tmargin, 78, TRUE) > 1)
fatal ("%s:%d: Table entry too long", input_fname, line_no);
}
void text_sample_file (const uchar *s)
{
if (para_flag)
write_nl ();
write_string (" Example: See ");
write_line (s);
}
void text_libref_section (const uchar *s)
{
if (para_flag)
write_nl ();
write_fmt (" %s", s);
write_nl ();
para_flag = TRUE;
}
void text_hyphenation (const char *name)
{
FILE *f;
char line[128], *p;
int line_no, rc;
if (opt_b == 0)
return;
rc = lbh_init (&lbh);
if (rc != 0)
fatal ("lb_init failed, rc=%d", rc);
f = fopen (name, "rt");
if (f == NULL)
{
perror (name);
exit (1);
}
line_no = 0;
while (fgets (line, sizeof (line), f) != NULL)
{
++line_no;
p = strchr (line, '\n');
if (p == NULL)
fatal ("%s:%d: Line too long", name, line_no);
*p = 0;
rc = lbh_word (lbh, line);
if (rc != 0)
fatal ("lbh_word failed, rc=%d", rc);
}
if (ferror (f))
{
perror (name);
exit (1);
}
fclose (f);
}