From 64785765065a526d152c6e36b4ed6c12bcf69e12 Mon Sep 17 00:00:00 2001 From: CSRG Date: Sun, 4 Aug 1991 20:14:22 -0800 Subject: [PATCH] BSD 4_3_Net_2 development Work on file usr/src/usr.bin/groff/macros/tmac.tty Work on file usr/src/usr.bin/groff/grotty/grotty.cc Synthesized-from: CSRG/cd2/net.2 --- usr/src/usr.bin/groff/grotty/grotty.cc | 361 +++++++++++++++++++++++++ usr/src/usr.bin/groff/macros/tmac.tty | 44 +++ 2 files changed, 405 insertions(+) create mode 100644 usr/src/usr.bin/groff/grotty/grotty.cc create mode 100644 usr/src/usr.bin/groff/macros/tmac.tty diff --git a/usr/src/usr.bin/groff/grotty/grotty.cc b/usr/src/usr.bin/groff/grotty/grotty.cc new file mode 100644 index 0000000000..05555ad902 --- /dev/null +++ b/usr/src/usr.bin/groff/grotty/grotty.cc @@ -0,0 +1,361 @@ +// -*- C++ -*- +/* Copyright (C) 1989, 1990 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.uucp) + +This file is part of groff. + +groff 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 1, or (at your option) any later +version. + +groff 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 groff; see the file LICENSE. If not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "driver.h" + +#ifndef USHRT_MAX +#define USHRT_MAX 65535 +#endif + +#define DEFAULT_LINES_PER_PAGE 66 + +#define TAB_WIDTH 8 + +static int horizontal_tab_flag = 0; +static int form_feed_flag = 0; +static int bold_flag = 1; +static int underline_flag = 1; +static int overstrike_flag = 1; + +enum { UNDERLINE_MODE = 01, BOLD_MODE = 02 }; + +// Mode to use for bold-underlining. +static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; + +class tty_font : public font { + tty_font(const char *); + unsigned char mode; +public: + ~tty_font(); + unsigned char get_mode() { return mode; } +#if 0 + void handle_x_command(int argc, const char **argv); +#endif + static tty_font *load_tty_font(const char *); +}; + +tty_font *tty_font::load_tty_font(const char *s) +{ + tty_font *f = new tty_font(s); + if (!f->load()) { + delete f; + return 0; + } + const char *s = f->get_internal_name(); + long n; + if (s != 0 && (n = strtol(s, 0, 0)) != 0) + f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE)); + if (!underline_flag) + f->mode &= ~UNDERLINE_MODE; + if (!bold_flag) + f->mode &= ~BOLD_MODE; + if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE)) + f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode; + return f; +} + +tty_font::tty_font(const char *nm) +: font(nm), mode(0) +{ +} + +tty_font::~tty_font() +{ +} + +#if 0 +void tty_font::handle_x_command(int argc, const char **argv) +{ + if (argc >= 1 && strcmp(argv[0], "bold") == 0) + mode |= BOLD_MODE; + else if (argc >= 1 && strcmp(argv[0], "underline") == 0) + mode |= UNDERLINE_MODE; +} +#endif + +// hpos and vpos must be non-adjacent, to work round a bug in g++ 1.37.1 + +struct glyph { + unsigned short hpos; + unsigned short serial; + unsigned short vpos; + unsigned char code; + unsigned char mode; +}; + +class tty_printer : public printer { + enum { INITIAL_VEC_SIZE = 32 }; + glyph *vec; + int vec_used; + int vec_size; + int lines_per_page; + int columns_per_page; +public: + tty_printer(); + ~tty_printer(); + void set_char(int, font *, const environment *, int); + void begin_page(int) { } + void end_page(); + font *make_font(const char *); +}; + +tty_printer::tty_printer() +: vec_used(0), vec_size(0), vec(0) +{ + if (font::paperlength == 0) + lines_per_page = DEFAULT_LINES_PER_PAGE; + else if (font::paperlength % font::vert != 0) + fatal("paperlength not a multiple of vertical resolution"); + else + lines_per_page = font::paperlength/font::vert; + if (lines_per_page > USHRT_MAX || lines_per_page <= 0) + fatal("ridiculous paperlength"); + columns_per_page = font::paperwidth/font::hor; + // If columns_per_page is zero, we won't truncate. + if (columns_per_page < 0) + columns_per_page = 0; +} + +tty_printer::~tty_printer() +{ + delete vec; +} + +void tty_printer::set_char(int i, font *f, const environment *env, int w) +{ + int h = env->hpos; + if (h % font::hor != 0) + fatal("horizontal position not a multiple of horizontal resolution"); + h /= font::hor; + if (h < 0) { + error("character to the left of first column discarded"); + return; + } + if (columns_per_page != 0 && h >= columns_per_page) { + error("character to the right of last column discarded"); + return; + } + if (h > USHRT_MAX) { + error("character with ridiculously large horizontal position discarded"); + return; + } + int v = env->vpos; + if (v % font::vert != 0) + fatal("vertical position not a multiple of vertical resolution"); + v /= font::vert; + // Note that the first output line corresponds to groff position font::vert. + if (v <= 0) { + error("character above first line discarded"); + return; + } + if (v > lines_per_page) { + error("character below last line discarded"); + return; + } + if (w != font::hor) + fatal("width of character not equal to horizontal resolution"); + if (vec_used >= vec_size) { + if (vec_size == 0) + vec_size = INITIAL_VEC_SIZE; + else { + if (vec_size > USHRT_MAX/2) { + if (vec_size >= USHRT_MAX) + fatal("too many characters on the page"); + vec_size = USHRT_MAX; + } + else + vec_size *= 2; + } + glyph *old_vec = vec; + vec = new glyph [vec_size]; + if (vec_used) + memcpy(vec, old_vec, vec_used*sizeof(glyph)); + delete old_vec; + } + // We need a stable sort, but qsort is not stable, so we fake it. + vec[vec_used].serial = vec_used; + vec[vec_used].hpos = h; + vec[vec_used].vpos = v; + vec[vec_used].code = f->get_code(i); + vec[vec_used].mode = ((tty_font *)f)->get_mode(); + vec_used++; +} + +extern "C" { +static int compare_glyph(void *p1, void *p2) +{ + int v1 = ((glyph *)p1)->vpos; + int v2 = ((glyph *)p2)->vpos; + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + int h1 = ((glyph *)p1)->hpos; + int h2 = ((glyph *)p2)->hpos; + if (h1 < h2) + return -1; + if (h1 > h2) + return 1; + if (((glyph *)p1)->serial < ((glyph *)p2)->serial) + return -1; + return 1; +} +} + +void tty_printer::end_page() +{ + qsort(vec, vec_used, sizeof(glyph), compare_glyph); + int hpos = 0; + int vpos = 1; + // We have already discarded characters with vpos < 1 or > lines_per_page. + for (int i = 0; i < vec_used; i++) { + assert(vpos <= vec[i].vpos); + if (!overstrike_flag + && i + 1 < vec_used + && vec[i].hpos == vec[i + 1].hpos + && vec[i].vpos == vec[i + 1].vpos) + continue; + for (; vpos < vec[i].vpos; vpos++) { + putchar('\n'); + hpos = 0; + } + if (hpos > vec[i].hpos) { + putchar('\b'); + hpos--; + } + else { + if (horizontal_tab_flag) { + for (;;) { + int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH; + if (next_tab_pos > vec[i].hpos) + break; + putchar('\t'); + hpos = next_tab_pos; + } + } + for (; hpos < vec[i].hpos; hpos++) + putchar(' '); + } + assert(hpos == vec[i].hpos && vpos == vec[i].vpos); + if (isalnum(vec[i].code) && vec[i].mode & UNDERLINE_MODE) { + putchar('_'); + putchar('\b'); + } + if (vec[i].mode & BOLD_MODE) { + putchar(vec[i].code); + putchar('\b'); + } + putchar(vec[i].code); + hpos++; + } + if (form_feed_flag) { + if (hpos != 0) { + putchar('\n'); + vpos++; + } + if (vpos <= lines_per_page) + putchar('\f'); + } + else { + for (; vpos <= lines_per_page; vpos++) + putchar('\n'); + } + vec_used = 0; +} + +font *tty_printer::make_font(const char *nm) +{ + return tty_font::load_tty_font(nm); +} + +printer *make_printer() +{ + return new tty_printer; +} + +static void usage(); + +int main(int argc, char **argv) +{ + program_name = argv[0]; + static char stderr_buf[BUFSIZ]; + setbuf(stderr, stderr_buf); + int c; + while ((c = getopt(argc, argv, "F:vhfbuoBU")) != EOF) + switch(c) { + case 'v': + { + extern const char *version_string; + fprintf(stderr, "grotty version %s\n", version_string); + fflush(stderr); + break; + } + case 'b': + // Do not embolden by overstriking. + bold_flag = 0; + break; + case 'u': + // Do not underline. + underline_flag = 0; + break; + case 'o': + // Do not overstrike (other than emboldening and underlining). + overstrike_flag = 0; + break; + case 'B': + // Do bold-underlining as bold. + bold_underline_mode = BOLD_MODE; + break; + case 'U': + // Do bold-underlining as underlining. + bold_underline_mode = UNDERLINE_MODE; + break; + case 'h': + // Use horizontal tabs. + horizontal_tab_flag = 1; + break; + case 'f': + form_feed_flag = 1; + break; + case 'F': + font::command_line_font_dir(optarg); + break; + case '?': + usage(); + break; + default: + assert(0); + } + if (optind >= argc) + do_file("-"); + else { + for (int i = optind; i < argc; i++) + do_file(argv[i]); + } + delete pr; + exit(0); +} + +static void usage() +{ + fprintf(stderr, "usage: %s [-hfvbuoBU] [-F dir] [files ...]\n", + program_name); + exit(1); +} diff --git a/usr/src/usr.bin/groff/macros/tmac.tty b/usr/src/usr.bin/groff/macros/tmac.tty new file mode 100644 index 0000000000..755761bcb5 --- /dev/null +++ b/usr/src/usr.bin/groff/macros/tmac.tty @@ -0,0 +1,44 @@ +.\" +.\" +.nr _C \n(.C +.cp 0 +.nroff +.ftr CW B +.ftr C B +.ftr CR B +.po 0 +.de tty-char +.if !c\\$1 .char \\$1 \\$2 +.. +.tty-char \(14 1/4 +.tty-char \(12 1/2 +.tty-char \(34 1/4 +.tty-char \(fi fi +.tty-char \(fl fl +.tty-char \(Fi ffi +.tty-char \(Fl ffl +.tty-char \(<- <- +.tty-char \(-> -> +.tty-char \(<> <-> +.tty-char \(lA <= +.tty-char \(rA => +.tty-char \(<= <= +.tty-char \(>= => +.tty-char \(hA <=> +.tty-char \(ua ^ +.tty-char \(da v +.tty-char \(uA ^ +.tty-char \(dA v +.tty-char \(em -- +.tty-char \(en - +.tty-char \(ru _ +.tty-char \(ul _ +.tty-char \(br | +.tty-char \(bv | +.tty-char \(sl / +.tty-char \(+- +- +.tty-char \(co (C) +.tty-char \(co (C) +.tty-char \(*G gamma +.tty-char \(*E epsilon +.cp \n(_C -- 2.20.1