home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
i
/
iv26_w_3.zip
/
EXAMPLES
/
IDRAW
/
TEDIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-12
|
12KB
|
404 lines
/*
* Copyright (c) 1987, 1988, 1989 Stanford University
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Stanford not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Stanford makes no representations about
* the suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// $Header: textedit.c,v 1.16 89/10/25 18:09:40 interran Exp $
// implements class TextEdit.
#include "tedit.h"
#include <InterViews/canvas.h>
#include <InterViews/event.h>
#include <InterViews/font.h>
#include <InterViews/painter.h>
#include <InterViews/textbuffer.h>
#include <InterViews/textdisplay.h>
#include <InterViews/transformer.h>
#include <ctype.h>
// Beware: only one instance of TextEdit can exist at any time!
static const int SBUFSIZE = 1000;
static char sbuf[SBUFSIZE];
TextEdit::TextEdit (const char* sample, int samplen) {
selecting = false;
dot = mark = 0;
text = new TextBuffer(sbuf, 0, SBUFSIZE);
display = new TextDisplay(true);
output = nil;
text->Insert(0, sample, samplen);
int lines = text->Height();
for (int i = 0; i < lines; ++i) {
int bol = text->LineIndex(i);
int eol = text->EndOfLine(bol);
display->ReplaceText(i, text->Text(bol, eol), eol - bol);
}
}
TextEdit::~TextEdit () {
delete text;
delete display;
}
const char* TextEdit::GetText (int& size) {
size = text->Length();
return text->Text();
}
void TextEdit::Redraw (
Painter* output, Canvas* canvas, int lineHt, boolean redraw
) {
TextEdit::output = output;
display->Draw(output, canvas);
display->LineHeight(lineHt);
Coord l = 0;
Coord b = 0 - display->Height();
Coord r = 0 + display->Width();
Coord t = 0;
display->Resize(l, b, r, t);
if (redraw) {
display->Redraw(l, b, r, t);
}
}
void TextEdit::Grasp (Event& e) {
Select(Locate(e.x, e.y));
selecting = true;
e.eventType = MotionEvent;
}
boolean TextEdit::Editing (Event& e) {
boolean editing = true;
if (e.eventType == KeyEvent && e.len > 0) {
editing = HandleKey(e.keystring[0]);
} else if (e.eventType == MotionEvent && selecting) {
SelectMore(Locate(e.x, e.y));
} else if (e.eventType == DownEvent) {
if (e.shift) {
SelectMore(Locate(e.x, e.y));
selecting = true;
} else if (Contains(e.x, e.y)) {
Select(Locate(e.x, e.y));
selecting = true;
} else {
editing = false;
}
} else if (e.eventType == UpEvent) {
selecting = false;
}
if (!editing) {
Select(dot);
display->CaretStyle(NoCaret);
}
return editing;
}
void TextEdit::Bounds (Coord& xmin, Coord& ymin, Coord& xmax, Coord& ymax) {
Transformer* t = output->GetTransformer();
display->Bounds(xmin, ymin, xmax, ymax);
if (t != nil) {
t->TransformRect(xmin, ymin, xmax, ymax);
}
}
boolean TextEdit::HandleKey (char c) {
boolean editing = true;
switch (c) {
case '\001' /* ^A */: BeginningOfLine(); break;
case '\005' /* ^E */: EndOfLine(); break;
case '\006' /* ^F */: ForwardCharacter(1); break;
case '\002' /* ^B */: BackwardCharacter(1); break;
case '\016' /* ^N */: ForwardLine(1); break;
case '\020' /* ^P */: BackwardLine(1); break;
case '\013' /* ^K */: DeleteRestOfLine(); break;
case '\004' /* ^D */: DeleteCharacter(1); break;
case '\010' /* ^H */: DeleteCharacter(-1); break;
case '\177' /* DEL */: DeleteCharacter(-1); break;
case '\011' /* TAB */: InsertCharacter(' '); break;
case '\027' /* ^W */: SelectWord(); break;
case '\025' /* ^U */: SelectLine(); break;
case '\015' /* RET */: InsertCharacter('\n'); break;
case '\033' /* ESC */: editing = false; break;
default:
if (!iscntrl(c)) {
InsertCharacter(c);
}
break;
}
return editing;
}
void TextEdit::InsertCharacter (char c) {
DeleteSelection();
InsertText(&c, 1);
}
void TextEdit::DeleteCharacter (int count) {
if (dot != mark) {
DeleteSelection();
} else {
DeleteText(count);
}
}
void TextEdit::InsertText (const char* s, int count) {
count = text->Insert(dot, s, count);
int sline = text->LineNumber(dot);
int fline = text->LineNumber(dot + count);
if (sline == fline) {
int offset = text->LineOffset(dot);
display->InsertText(sline, offset, text->Text(dot), count);
} else {
display->InsertLinesAfter(sline, fline-sline);
for (int i = sline; i <= fline; ++i) {
int bol = text->BeginningOfLine(text->LineIndex(i));
int eol = text->EndOfLine(bol);
display->ReplaceText(i, text->Text(bol, eol), eol-bol);
}
}
Select(dot + count);
}
void TextEdit::DeleteText (int count) {
int d = dot;
int c = count;
while (c > 0) {
d = text->NextCharacter(d);
--c;
}
while (c < 0) {
dot = text->PreviousCharacter(dot);
++c;
}
count = d - dot;
int sline = text->LineNumber(dot);
int fline = text->LineNumber(d);
text->Delete(dot, count);
if (sline == fline) {
int offset = text->LineOffset(dot);
display->DeleteText(sline, offset, count);
} else {
int bol = text->BeginningOfLine(dot);
int eol = text->EndOfLine(dot);
display->DeleteLinesAfter(sline, fline-sline);
display->ReplaceText(sline, text->Text(bol, eol), eol-bol);
}
Select(dot);
}
void TextEdit::DeleteRestOfLine () {
if (dot == mark) {
int bol = text->BeginningOfLine(dot);
if (dot == bol) {
Select(dot, text->BeginningOfNextLine(dot));
} else {
Select(dot, text->EndOfLine(dot));
}
}
DeleteSelection();
}
void TextEdit::DeleteSelection () {
if (dot != mark) {
DeleteText(mark - dot);
}
}
void TextEdit::BeginningOfLine () {
if (dot != mark) {
Select(min(mark, dot));
} else {
Select(text->BeginningOfLine(dot));
}
}
void TextEdit::EndOfLine () {
if (dot != mark) {
Select(max(mark, dot));
} else {
Select(text->EndOfLine(dot));
}
}
void TextEdit::ForwardCharacter (int count) {
if (dot != mark) {
Select(max(mark, dot));
} else {
int d = dot;
while (count > 0) {
d = text->NextCharacter(d);
--count;
}
Select(d);
}
}
void TextEdit::BackwardCharacter (int count) {
if (dot != mark) {
Select(min(mark, dot));
} else {
int d = dot;
while (count > 0) {
d = text->PreviousCharacter(d);
--count;
}
Select(d);
}
}
void TextEdit::ForwardLine (int count) {
if (dot != mark) {
Select(max(mark, dot));
} else {
int d = dot;
while (count > 0) {
d = text->BeginningOfNextLine(d);
--count;
}
Select(d);
}
}
void TextEdit::BackwardLine (int count) {
if (dot != mark) {
Select(min(mark, dot));
} else {
int d = dot;
while (count > 0) {
d = text->BeginningOfLine(text->EndOfPreviousLine(d));
--count;
}
Select(d);
}
}
void TextEdit::Select (int d) {
Select(d, d);
}
void TextEdit::SelectMore (int m) {
Select(dot, m);
}
void TextEdit::SelectLine () {
Select(text->BeginningOfLine(dot), text->BeginningOfNextLine(dot));
}
void TextEdit::SelectWord () {
int left = min(mark, dot);
int right = max(mark, dot);
Select(text->BeginningOfWord(text->PreviousCharacter(left)), right);
}
void TextEdit::Select (int d, int m) {
int oldl = min(dot, mark);
int oldr = max(dot, mark);
int newl = min(d, m);
int newr = max(d, m);
if (oldl == oldr && newl != newr) {
display->CaretStyle(NoCaret);
}
if (newr < oldl || newl > oldr) {
if (oldr > oldl) {
display->RemoveStyle(
text->LineNumber(oldl), text->LineOffset(oldl),
text->LineNumber(oldr-1), text->LineOffset(oldr-1),
Reversed
);
}
if (newr > newl) {
display->AddStyle(
text->LineNumber(newl), text->LineOffset(newl),
text->LineNumber(newr-1), text->LineOffset(newr-1),
Reversed
);
}
} else {
if (newl < oldl) {
display->AddStyle(
text->LineNumber(newl), text->LineOffset(newl),
text->LineNumber(oldl-1), text->LineOffset(oldl-1),
Reversed
);
} else if (newl > oldl) {
display->RemoveStyle(
text->LineNumber(oldl), text->LineOffset(oldl),
text->LineNumber(newl-1), text->LineOffset(newl-1),
Reversed
);
}
if (newr > oldr) {
display->AddStyle(
text->LineNumber(oldr), text->LineOffset(oldr),
text->LineNumber(newr-1), text->LineOffset(newr-1),
Reversed
);
} else if (newr < oldr) {
display->RemoveStyle(
text->LineNumber(newr), text->LineOffset(newr),
text->LineNumber(oldr-1), text->LineOffset(oldr-1),
Reversed
);
}
}
if (oldl != oldr && newl == newr) {
display->CaretStyle(BarCaret);
}
if (newl == newr) {
display->Caret(text->LineNumber(newl), text->LineOffset(newl));
}
dot = d;
mark = m;
}
boolean TextEdit::Contains (Coord x, Coord y) {
Transformer tr(output->GetTransformer());
tr.InvTransform(x, y);
int line = display->LineNumber(y);
int index = display->LineIndex(line, x);
return
x >= display->Left(line, text->BeginningOfLine(index)) &&
x <= display->Right(line, text->EndOfLine(index)) &&
y >= display->Base(line) &&
y <= display->Top(line);
}
int TextEdit::Locate (Coord x, Coord y) {
Transformer tr(output->GetTransformer());
tr.InvTransform(x, y);
int line = display->LineNumber(y);
int index = display->LineIndex(line, x);
int l = text->LineIndex(line);
int i = 0;
while (i < index) {
l = text->NextCharacter(l);
i += 1;
}
return l;
}