/* TUIpeer works in conjunction with an implementation of java.awt.Toolkit to provide a Text User Interface for programs using the Java AWT. Copyright (C) 1997-2000 Stuart D. Gathman This program 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 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma implementation #include #include "textdraw.h" #include Rect DrawingContext::clipRect() const { return cliprect.moverel(-translatey,-translatex); } string DrawingContext::asString() const { char buf[128]; sprintf(buf,"DrawingContext: clip(%d,%d,%d,%d), translate(%d,%d)", cliprect.c1,cliprect.r1,cliprect.width(),cliprect.height(), translatex,translatey ); return buf; } CHTYPE DrawingContext::get(int x,int y) const { return ACS_BLOCK; } void DrawingContext::writeStr(int x,int y,int n,const string &s,CHTYPE a) { int len = s.length(); const char *str = s.c_str(); CHTYPE *buf = (CHTYPE *)alloca(n * sizeof(CHTYPE)); int i; for (i = 0; i < len && i < n; ++i) buf[i] = str[i] | a; while (i < n) buf[i++] = ' ' | a; writeAttr(x,y,n,buf); } void DrawingContext::writeStr(int x,int y,const string &s,CHTYPE a) { writeStr(x,y,s.length(),s,a); } TextImage::TextImage(int w,int h): DrawingContext(Rect(0,0,h - 1,w - 1)) { data = 0; d = 0; resize(w,h); } void TextImage::resize(int w,int h) { delete [] data; delete [] d; imgwidth = w; imgheight = h; cliprect = Rect(0,0,h-1,w-1); int n = w * h; if (n <= 0 || h < 0) { data = 0; d = 0; return; } data = new CHTYPE[n]; d = new unsigned[h]; int i; for (i = 0; i < n; ++i) data[i] = A_NORMAL | ' '; for (i = 0; i < h; ++i) d[i] = i * w; } TextImage::~TextImage() { delete [] data; delete [] d; } void TextImage::writeAttr(int x,int y,int n,const CHTYPE *a) { x += translatex; y += translatey; Rect r1(cliprect.intersect(Rect(y,x,y,x + n - 1))); if (r1.isempty()) return; n = r1.width(); CHTYPE *p = rowdata(r1.r1); for (int i = r1.c1; i <= r1.c2; ++i) p[i] = a[i - x]; } void TextImage::copyArea(const Rect &r,int dx,int dy) { //Rect clip(Rect(0,0,imgheight - 1,imgwidth - 1)); //Rect src(r.moverel(translatey,translatex).intersect(clip)); //Rect r1(src.moverel(dy,dx).intersect(cliprect)); Rect src(r.intersect(cliprect)); Rect r1(src.moverel(dy,dx).intersect(cliprect)); if (dy <= 0) { if (r1.width() >= imgwidth && -dy < r1.height()) { for (int j = r1.r1; j <= r1.r2; ++j) { short tmp = d[j]; d[j] = d[j - dy]; d[j - dy] = tmp; } // FIXME: src has been trashed, do smaller copy to restore? } else { for (int j = r1.r1; j <= r1.r2; ++j) { int srcrow = j - dy; CHTYPE *p = rowdata(j); CHTYPE *src = rowdata(srcrow); if (dx <= 0) for (int i = r1.c1; i <= r1.c2; ++i) p[i] = src[i - dx]; else for (int i = r1.c2; i >= r1.c1; --i) p[i] = src[i - dx]; } } } else { if (r1.width() == imgwidth && dy < r1.height()) { for (int j = r1.r2; j >= r1.r1; --j) { short tmp = d[j]; d[j] = d[j - dy]; d[j - dy] = tmp; } // FIXME: src has been trashed, do smaller copy to restore? } else { for (int j = r1.r2; j >= r1.r1; --j) { int srcrow = j - dy; CHTYPE *p = rowdata(j); CHTYPE *src = rowdata(srcrow); if (dx <= 0) for (int i = r1.c1; i <= r1.c2; ++i) p[i] = src[i - dx]; else for (int i = r1.c2; i >= r1.c1; --i) p[i] = src[i - dx]; } } } } void TextImage::fillRect(const Rect &r,CHTYPE attr) { Rect r1(cliprect.intersect(r.moverel(translatey,translatex))); if (r1.isempty()) return; for (int j = r1.r1; j <= r1.r2; ++j) { CHTYPE *p = rowdata(j); for (int i = r1.c1; i <= r1.c2; ++i) p[i] = attr; } } IndirectContext::IndirectContext(DrawingContext *c): DrawingContext(Rect(-9999,-9999,9999,9999)) { dc = c; } void IndirectContext::setClip(const Rect &r) { cliprect = dc->clipRect().intersect(r.moverel(translatey,translatex)); } void IndirectContext::writeAttr(int x,int y,int n,const CHTYPE *a) { x += translatex; y += translatey; Rect r1(cliprect.intersect(Rect(y,x,y,x + n - 1))); dc->writeAttr(r1.c1,r1.r1,r1.width(),a); } void IndirectContext::copyArea(const Rect &r,int dx,int dy) { int x = translatex + dx; int y = translatey + dy; Rect r1(r.moverel(y,x).intersect(cliprect)); dc->copyArea(r1.moverel(-dy,-dx),dx,dy); } void IndirectContext::fillRect(const Rect &r,CHTYPE attr) { Rect r1(r.moverel(translatey,translatex).intersect(cliprect)); dc->fillRect(r1,attr); } IndirectContext DrawingContext::create() { return IndirectContext(this); } IndirectContext IndirectContext::create() { return IndirectContext(*this); } void DrawingContext::drawRect(int x,int y,int w,int h,CHTYPE attr,LDtype t) { CHTYPE *buf = (CHTYPE *)alloca(w * sizeof *buf); CHTYPE a = ACS_HLINE + attr; for (int i = 1; i < w - 1; ++i) buf[i] = a; buf[0] = ACS_ULCORNER + attr; buf[w - 1] = ACS_URCORNER + attr; writeAttr(x,y,w,buf); a = ACS_VLINE + attr; fillRect(Rect(Point(y + 1,x),1,h - 2),a); fillRect(Rect(Point(y + 1,x + w - 1),1,h - 2),a); buf[0] = ACS_LLCORNER + attr; buf[w - 1] = ACS_LRCORNER + attr; writeAttr(x,y + h - 1,w,buf); } void DrawingContext::clipRect(const Rect &r) { cliprect = r.moverel(translatey,translatex).intersect(cliprect); } CHTYPE TextImage::get(int x,int y) const { if (Rect(y,x,y,x).intersect(clipRect()).isempty()) return ACS_BLOCK; return rowdata(y)[x]; } CHTYPE IndirectContext::get(int x,int y) const { return dc->get(x + translatex,y + translatey); } DrawingContext::DrawingContext(const Rect &r): cliprect(r) { translatex = 0; translatey = 0; }