⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty.cc

📁 早期freebsd实现
💻 CC
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.     Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "driver.h"#ifndef USHRT_MAX#define USHRT_MAX 65535#endif#define TAB_WIDTH 8static 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;static int draw_flag = 1;enum {  UNDERLINE_MODE = 01,  BOLD_MODE = 02,  VDRAW_MODE = 04,  HDRAW_MODE = 010};// 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 *num = f->get_internal_name();  long n;  if (num != 0 && (n = strtol(num, 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 0void 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;}#endifclass glyph {  static glyph *free_list;public:  glyph *next;  unsigned short hpos;  unsigned char code;  unsigned char mode;  void *operator new(size_t);  void operator delete(void *);  inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }};glyph *glyph::free_list = 0;void *glyph::operator new(size_t){  if (!free_list) {    const int BLOCK = 1024;    free_list = (glyph *)new char[sizeof(glyph)*BLOCK];    for (int i = 0; i < BLOCK - 1; i++)      free_list[i].next = free_list + i + 1;    free_list[BLOCK - 1].next = 0;  }  glyph *p = free_list;  free_list = free_list->next;  p->next = 0;  return p;}void glyph::operator delete(void *p){  if (p) {    ((glyph *)p)->next = free_list;    free_list = (glyph *)p;  }}class tty_printer : public printer {  glyph **lines;  int nlines;  int cached_v;  int cached_vpos;  void add_char(unsigned char, int, int, unsigned char);public:  tty_printer();  ~tty_printer();  void set_char(int, font *, const environment *, int);  void draw(int code, int *p, int np, const environment *env);  void begin_page(int) { }  void end_page(int page_length);  font *make_font(const char *);};tty_printer::tty_printer() : cached_v(0){  nlines = 66;  lines = new glyph *[nlines];  for (int i = 0; i < nlines; i++)    lines[i] = 0;}tty_printer::~tty_printer(){  a_delete lines;}void tty_printer::set_char(int i, font *f, const environment *env, int w){  if (w != font::hor)    fatal("width of character not equal to horizontal resolution");  add_char(f->get_code(i), env->hpos, env->vpos, ((tty_font *)f)->get_mode());}void tty_printer::add_char(unsigned char c, int h, int v, unsigned char mode){#if 0  // This is too expensive.  if (h % font::hor != 0)    fatal("horizontal position not a multiple of horizontal resolution");#endif  int hpos = h / font::hor;  if (hpos < 0) {    error("character to the left of first column discarded");    return;  }  if (hpos > USHRT_MAX) {    error("character with ridiculously large horizontal position discarded");    return;  }  int vpos;  if (v == cached_v && cached_v != 0)    vpos = cached_vpos;  else {    if (v % font::vert != 0)      fatal("vertical position not a multiple of vertical resolution");    vpos = v / font::vert;    if (vpos > nlines) {      glyph **old_lines = lines;      lines = new glyph *[vpos + 1];      memcpy(lines, old_lines, nlines*sizeof(glyph *));      for (int i = nlines; i <= vpos; i++)	lines[i] = 0;      a_delete old_lines;      nlines = vpos + 1;    }    // Note that the first output line corresponds to groff    // position font::vert.    if (vpos <= 0) {      error("character above first line discarded");      return;    }    cached_v = v;    cached_vpos = vpos;  }  glyph *g = new glyph;  g->hpos = hpos;  g->code = c;  g->mode = mode;  // The list will be reversed later.  After reversal, it must be in  // increasing order of hpos, with HDRAW characters before VDRAW  // characters before normal characters at each hpos, and otherwise  // in order of occurrence.  for (glyph **pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)    if (int((*pp)->hpos) < hpos	|| ((*pp)->hpos == hpos && (*pp)->draw_mode() >= g->draw_mode()))      break;  g->next = *pp;  *pp = g;}void tty_printer::draw(int code, int *p, int np, const environment *env){  if (code != 'l' || !draw_flag)    return;  if (np != 2) {    error("2 arguments required for line");    return;  }  if (p[0] == 0) {    // vertical line    int v = env->vpos;    int len = p[1];    if (len < 0) {      v += len;      len = -len;    }    while (len >= 0) {      add_char('|', env->hpos, v, VDRAW_MODE);      len -= font::vert;      v += font::vert;    }  }  if (p[1] == 0) {    // horizontal line    int h = env->hpos;    int len = p[0];    if (len < 0) {      h += len;      len = -len;    }    while (len >= 0) {      add_char('-', h, env->vpos, HDRAW_MODE);      len -= font::hor;      h += font::hor;    }  }}void tty_printer::end_page(int page_length){  if (page_length % font::vert != 0)    error("vertical position at end of page not multiple of vertical resolution");  int lines_per_page = page_length / font::vert;  for (int last_line = nlines; last_line > 0; last_line--)    if (lines[last_line - 1])      break;#if 0  if (last_line > lines_per_page) {    error("characters past last line discarded");    do {      --last_line;      while (lines[last_line]) {	glyph *tem = lines[last_line];	lines[last_line] = tem->next;	delete tem;      }    } while (last_line > lines_per_page);  }#endif  for (int i = 0; i < last_line; i++) {    glyph *p = lines[i];    lines[i] = 0;    glyph *g = 0;    while (p) {      glyph *tem = p->next;      p->next = g;      g = p;      p = tem;    }    int hpos = 0;        glyph *nextp;    for (p = g; p; delete p, p = nextp) {      nextp = p->next;      if (nextp && p->hpos == nextp->hpos) {	if (p->draw_mode() == HDRAW_MODE && nextp->draw_mode() == VDRAW_MODE) {	  nextp->code = '+';	  continue;	}	if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {	  nextp->code = p->code;	  continue;	}	if (!overstrike_flag)	  continue;      }      if (hpos > int(p->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 > int(p->hpos))	      break;	    putchar('\t');	    hpos = next_tab_pos;	  }	}	for (; hpos < int(p->hpos); hpos++)	  putchar(' ');      }      assert(hpos == p->hpos);      if (p->mode & UNDERLINE_MODE) {	putchar('_');	putchar('\b');      }      if (p->mode & BOLD_MODE) {	putchar(p->code);	putchar('\b');      }      putchar(p->code);      hpos++;    }    putchar('\n');  }  if (form_feed_flag) {    if (last_line < lines_per_page)      putchar('\f');  }  else {    for (; last_line < lines_per_page; last_line++)      putchar('\n');  }}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:vhfbuoBUd")) != 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 'd':      // Ignore \D commands.      draw_flag = 0;      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 [-hfvbuodBU] [-F dir] [files ...]\n",	  program_name);  exit(1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -