/* 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 #include "textbrowse.h" #include "textdraw.h" #include #include #include #include TextBrowse::TextBrowse(TextArray &r): TextSelection(r) { echoChar = 0; } TextBrowse::~TextBrowse() { } void TextBrowse::key(int k) { BrowserBase::key(k); } void TextBrowse::select(long start,long end) { TextSelection::select(start,end); move(getRow(),getCol()); } void TextBrowse::move(int r,int c) { const char *s; if (r < 0 || r >= txt.size()) r = txt.size(); while (c < 0 && r > 0 && (s = txt[--r])) { virtpos line(s); c += line.mapidx(strlen(s)) + 1; } s = txt[r]; if (s) { virtpos line(s); line.mappos(c); if (c > getCol()) { while (c > line.pos && s[line.mappos(++c)]) ; } if (s[line.idx]) c = line.pos; } else c = 0; Rect r1(0,0,height - 1,width - 1); // entire window if (r < topline) { int dist = topline - r; topline = r; slide(r1,DIR_DOWN,dist); } else if (r >= topline + height) { int dist = r - height + 1 - topline; topline += dist; slide(r1,DIR_UP,dist); } if (c < leftcol) { int dist = leftcol - c; leftcol = c; slide(r1,DIR_RIGHT,dist); } else if (c >= leftcol + width) { int dist = c - width + 1 - leftcol; leftcol += dist; slide(r1,DIR_LEFT,dist); } TextSelection::setCursor(r,c); setCursor(c - leftcol,r - topline); } void TextBrowse::setCursor(int x,int y) { Component::setCursor(x,y); } void TextBrowse::selectionChanged(int orow,int ocol,int nrow,int ncol) { orow -= topline; nrow -= topline; ocol -= leftcol; ncol -= leftcol; if (orow == nrow) repaint(Rect(nrow,ocol,nrow,ncol)); else { repaint(Rect(orow,ocol,orow,width)); if (++orow < nrow) repaint(Rect(orow,0,nrow - 1,width)); repaint(Rect(nrow,0,nrow,ncol)); } } void TextBrowse::paint(DrawingContext *dc) { Rect r(dc->clipRect()); for (int i = r.r1; i <= r.r2; ++i) { CHTYPE *buf = (CHTYPE *)alloca(r.width() * sizeof *buf); int row = topline + i; virtpos v(txt[row]); v.expand(leftcol + r.c1,buf,r.width()); if (echoChar) { int len = strlen(txt[row]); for (int c = r.c1; c <= r.c2; ++c) { if (v.mappos(c) < len) { int i = c - r.c1; buf[i] = (buf[i] & A_ATTRIBUTES) | (unsigned char)echoChar; } } } for (int c = r.c1; c <= r.c2; ++c) { int i = c - r.c1; buf[i] = (buf[i] & 255) | textAttr; } if (rowSelected(row)) for (int c = r.c1; c <= r.c2; ++c) if (isSelected(row,leftcol + c)) buf[c - r.c1] ^= A_REVERSE; dc->writeAttr(r.c1,i,r.width(),buf); } } CHTYPE TextBrowse::operator()(int row, int col) const { if (col < 0 || row < 0) return ' '; const char *s = txt[row]; if (!s) return ' '; int idx = virtpos(s).mappos(col); if (!s[idx]) return ' '; return (unsigned char)s[idx]; } void TextBrowse::getyx(int &y,int &x) const { y = getRow(); x = getCol(); } void TextBrowse::print() { string cmd("pr -l64 -f -h \"" + getname() + "\" | lp -s"); FILE *p = popen(cmd.c_str(),"w"); if (p) { for (int i = 0; i < txt.size(); ++i) { fputs(txt[i],p); fputc('\n',p); } } if (!p || pclose(p)) { int rc = errno; ErrMsg m(5,10,"Error printing document","%s", sys_errlist[rc]); m.run(); } else { ErrMsg m(5,10,"Printing Complete","Press Enter"); m.run(); } } void TextBrowse::slide(const Rect &r,Dir d,int cnt) { //fprintf(stderr,"TextBrowse::slide((%d,%d,%d,%d),%d,%d)%c\n", // r.c1,r.r1,r.width(),r.height(),d,cnt,dc ? 'V' : ' '); if (!dc) return; int dx = 0,dy = 0; switch (d) { case DIR_UP: dy = -cnt; break; case DIR_DOWN: dy = cnt; break; case DIR_LEFT: dx = -cnt; break; case DIR_RIGHT: dx = cnt; break; default: abort(); } Rect loc(Point(0,0),width,height); // component size Rect r1(r.intersect(loc)); // src rect Rect r2(r1.moverel(dy,dx).intersect(loc)); // dst rect // we broke something about copyArea when implementing lightweight // components, so always redrawing makes it usable for now. if (/*true||*/ r2.isempty()) { repaint(loc); // just repaint entire screen return; } Rect r0(r1.enclose(r2)); // repaint rect if (r0.r1 < r2.r1) r0.r2 = r2.r1 - 1; if (r0.r2 > r2.r2) r0.r1 = r2.r2 + 1; if (r0.c1 < r2.c1) r0.c2 = r2.c1 - 1; if (r0.c2 > r2.c2) r0.c1 = r2.c2 + 1; //fprintf(stderr,"copy((%d,%d,%d,%d),%d,%d)\n", // r1.c1,r1.r1,r1.width(),r1.height(),dx,dy); //pause(); dc->copyArea(r1,dx,dy); repaint(r0); } // position the cursor when we get the focus void TextBrowse::getfocus() { setCursor(getCol() - leftcol,getRow() - topline); } Dimension TextBrowse::size() const { return Dimension(width,height); } void TextBrowse::show(bool v) { if (v) setCursor(getCol() - leftcol,getRow() - topline); Component::show(v); }