📄 area.c
字号:
/* ------------------------------------------------------------------------- *//* * Copyright (c) 1999 * GMRS Software GmbH, Innsbrucker Ring 159, 81669 Munich, Germany. * http://www.gmrs.de * All rights reserved. * Author: Arno Unkrig (arno.unkrig@gmrs.de) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by GMRS Software GmbH. * 4. The name of GMRS Software GmbH may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY GMRS SOFTWARE GMBH ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GMRS SOFTWARE GMBH BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. *//* ------------------------------------------------------------------------- */#ident "$Id: Area.C,v 1.7 1999/11/02 17:57:49 arno Exp $"#include <stdlib.h>#include <string.h>#include <iostream.h>#include "Area.h"#include "string.h"#define LATIN1_nbsp 160/* ------------------------------------------------------------------------- */#define malloc_array(type, size)\((type *) malloc(sizeof(type) * (size)))#define realloc_array(array, type, size) \((array) = (type *) realloc((array), sizeof(type) * (size)))#define copy_array(from, to, type, count) \((void) memcpy((to), (from), (count) * sizeof(type)))/* ------------------------------------------------------------------------- */Line::Line(size_type l) : length_(l), cells_(malloc_array(Cell, l)){ Cell *p, *end = cells_ + l; for (p = cells_; p != end; p++) p->clear();}Line::Line(const char *p) : length_(strlen(p)), cells_(malloc_array(Cell, length_)){ Cell *q = cells_, *end = q + length_; while (q != end) { q->character = *p++; q->attribute = Cell::NONE; q++; }}Line::Line(const string &s) : length_(s.length()), cells_(malloc_array(Cell, length_)){ const char *p = s.c_str(); Cell *q = cells_, *end = q + length_; while (q != end) { q->character = *p++; q->attribute = Cell::NONE; q++; }}Line::~Line(){ free(cells_);}/* ------------------------------------------------------------------------- */voidLine::resize(size_type l){ if (l == length()) return; realloc_array(cells_, Cell, l); for (size_type x = length(); x < l; x++) cells_[x].clear(); length_ = l;}voidLine::insert(const Line &l, size_type x){ enlarge(x + l.length()); const Cell *p = l.cells_, *end = p + l.length(); Cell *q = cells_ + x; while (p != end) *q++ = *p++;}voidLine::insert(const char *p, size_type x){ enlarge(x + strlen(p)); Cell *q = cells_ + x; while (*p) q++->character = *p++;}voidLine::insert(const string &s, size_type x){ insert(s.c_str(), x);}voidLine::append(char c){ size_type x = length_; resize(x + 1); cells_[x].character = c; cells_[x].attribute = Cell::NONE;}voidLine::append(const Line &l){ size_type x = length_; enlarge(x + l.length_); const Cell *p = l.cells_, *end = p + l.length(); Cell *q = cells_ + x; while (p != end) *q++ = *p++;}voidLine::append(const char *p){ size_type x = length_; enlarge(x + strlen(p)); Cell *q = cells_ + x; for (; *p; ++p, ++q) { q->character = *p; q->attribute = Cell::NONE; }}voidLine::add_attribute(char addition){ Cell *p = cells_, *end = cells_ + length_; while(p != end) p++->attribute |= addition;}/* ------------------------------------------------------------------------- */bool Area::use_backspaces = true;/* ------------------------------------------------------------------------- */Area::Area() : width_(0), height_(0), cells_(malloc_array(Cell *, 0)){}Area::Area( size_type w /*= 0*/ , size_type h /*= 0*/ , char c /*= ' '*/ , char a /*= Cell::NONE*/) : width_(w), height_(h), cells_(malloc_array(Cell *, h)){ for (size_type y = 0; y < h; y++) { Cell *p = cells_[y] = malloc_array(Cell, w), *end = p + w; while (p != end) { p->character = c; p->attribute = a; p++; } }}Area::Area(const char *p) : width_(strlen(p)), height_(1), cells_(malloc_array(Cell *, 1)){ cells_[0] = malloc_array(Cell, width_); Cell *q = cells_[0], *end = q + width_; while (q != end) { q->character = *p++; q->attribute = Cell::NONE; q++; }}Area::Area(const string &s) : width_(s.length()), height_(1), cells_(malloc_array(Cell *, 1)){ cells_[0] = malloc_array(Cell, width_); Cell *q = cells_[0]; for (string::size_type i = 0; i < s.length(); ++i) { q->character = s[i]; q->attribute = Cell::NONE; q++; }}Area::Area(const Line &l) : width_(l.length_), height_(1), cells_(malloc_array(Cell *, 1)){ cells_[0] = malloc_array(Cell, width_); copy_array(l.cells_, cells_[0], Cell, width_);}Area::~Area(){ for (size_type y = 0; y < height(); y++) free(cells_[y]); free(cells_);}/* ------------------------------------------------------------------------- */const Area &Area::operator>>=(size_type rs){ if (rs > 0) { resize(width_ + rs, height_); for (size_type y = 0; y < height_; y++) { Cell *c = cells_[y]; memmove(c + rs, c, (width_ - rs) * sizeof(Cell)); for (size_type x = 0; x < rs; x++) { c[x].character = ' '; c[x].attribute = Cell::NONE; } } } return *this;}voidArea::resize(size_type w, size_type h){ size_type y_max = h < height() ? h : height(); if (w > width()) { for (size_type y = 0; y < y_max; y++) { realloc_array(cells_[y], Cell, w); Cell *p = cells_[y] + width(), *end = cells_[y] + w; while (p != end) p++->clear(); } } else if (w < width()) { for (size_type y = 0; y < y_max; y++) { realloc_array(cells_[y], Cell, w); } } if (h > height()) { realloc_array(cells_, Cell *, h); for (size_type y = height(); y < h; y++) { Cell *p = cells_[y] = malloc_array(Cell, w), *end = p + w; while (p != end) p++->clear(); } } else if (h < height()) { for (size_type y = h; y < height(); y++) free(cells_[y]); realloc_array(cells_, Cell *, h); } width_ = w; height_ = h;}voidArea::enlarge(size_type w, size_type h){ if (w > width() || h > height()) { resize(w > width() ? w : width(), h > height() ? h : height()); }}voidArea::insert(const Area &a, size_type x, size_type y){ enlarge(x + a.width(), y + a.height()); for (size_type i = 0; i < a.height(); i++) { const Cell *p = a.cells_[i], *end = p + a.width(); Cell *q = cells_[y + i] + x; while (p != end) *q++ = *p++; }}voidArea::insert( const Area &a, size_type x, size_type y, size_type w, size_type h, int halign, int valign){ if (halign != LEFT && a.width() < w) x += ( halign == CENTER ? (w - a.width()) / 2 : halign == RIGHT ? w - a.width() : 0 ); if (valign != TOP && a.height() < h) y += ( valign == MIDDLE ? (h - a.height()) / 2 : valign == BOTTOM ? h - a.height() : 0 ); insert(a, x, y);}voidArea::insert(const Cell &c, size_type x, size_type y){ enlarge(x + 1, y + 1); cells_[y][x] = c;}voidArea::fill(const Cell &c, size_type x, size_type y, size_type w, size_type h){ enlarge(x + w, y + h); for (size_type yy = y; yy < y + h; yy++) { Cell *p = &cells_[yy][x]; for (size_type i = 0; i < w; i++) *p++ = c; }}voidArea::insert(const Cell *p, size_type count, size_type x, size_type y){ enlarge(x + count, y + 1); Cell *q = &cells_[y][x]; while (count--) *q++ = *p++;}voidArea::insert(char c, size_type x, size_type y){ enlarge(x + 1, y + 1); cells_[y][x].character = c;}voidArea::insert(const string &s, size_type x, size_type y){ enlarge(x + s.length(), y + 1); Cell *cell = &cells_[y][x]; for (string::size_type i = 0; i < s.length(); i++) { cell->character = s[i]; cell->attribute = Cell::NONE; cell++; }}voidArea::prepend(int n){ if (n <= 0) return; realloc_array(cells_, Cell *, height() + n); memmove(cells_ + n, cells_, height() * sizeof(*cells_)); for (int y = 0; y < n; ++y) { Cell *p = cells_[y] = malloc_array(Cell, width()), *end = p + width(); while (p != end) p++->clear(); } height_ += n;}const Area &Area::operator+=(const Area &x){ insert(x, 0, height()); return *this;}voidArea::fill(char c, size_type x, size_type y, size_type w, size_type h){ enlarge(x + w, y + h); for (size_type yy = y; yy < y + h; yy++) { Cell *p = &cells_[yy][x]; for (size_type i = 0; i < w; i++) p++->character = c; }}voidArea::add_attribute(char addition){ for (size_type y = 0; y < height(); y++) { Cell *p = cells_[y], *end = p + width(); while (p != end && p->character == ' ') ++p; Cell *q = p; while (p != end) { if (p++->character != ' ') { while (q < p) q++->attribute |= addition; } } }}voidArea::add_attribute( char addition, size_type x, size_type y, size_type w, size_type h){ enlarge(x + w, y + h); for (size_type yy = y; yy < y + h; yy++) { Cell *p = &cells_[yy][x], *end = p + w; while (p != end) p++->attribute |= addition; }}/* ------------------------------------------------------------------------- */ostream &backspace(ostream &os) { return os << '\b'; }ostream &operator<<(ostream &os, const Area &a){ for (Area::size_type y = 0; y < a.height(); y++) { const Cell *cell = a.cells_[y], *end = cell + a.width(); while ( end != cell && end[-1].character == ' ' && (end[-1].attribute & (Cell::UNDERLINE | Cell::STRIKETHROUGH)) == 0 ) end--; for (const Cell *p = cell; p != end; p++) { char c = p->character; char a = p->attribute; if (c == (char) LATIN1_nbsp) c = ' '; if (a == Cell::NONE) { os << c; } else { if (Area::use_backspaces) { /* * No LESS / terminal combination that I know of supports * dash-backspace-character as "strikethrough". Pity. */ if (a & Cell::STRIKETHROUGH) os << '-' << backspace; /* * No LESS that I know of can combine underlining and boldface. In * practice, boldface always takes precedence. * * It's not a good idea to optimize an underlined space as a single * underscore (as opposed to underscore-backspace-space) -- this * would not look nice next to an underlined character. */ if ((a & Cell::UNDERLINE) ) os << '_' << backspace; if ((a & Cell::BOLD ) && c != ' ') os << c << backspace; os << c; } else { os << (c == ' ' && (a & Cell::UNDERLINE) ? '_' : c); } } } os << endl; } return os;}/* ------------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -