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 >
C/C++ Source or Header  |  1992-03-12  |  12KB  |  404 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. // $Header: textedit.c,v 1.16 89/10/25 18:09:40 interran Exp $
  24. // implements class TextEdit.
  25.  
  26. #include "tedit.h"
  27. #include <InterViews/canvas.h>
  28. #include <InterViews/event.h>
  29. #include <InterViews/font.h>
  30. #include <InterViews/painter.h>
  31. #include <InterViews/textbuffer.h>
  32. #include <InterViews/textdisplay.h>
  33. #include <InterViews/transformer.h>
  34. #include <ctype.h>
  35.  
  36. // Beware: only one instance of TextEdit can exist at any time!
  37.  
  38. static const int SBUFSIZE = 1000;
  39. static char sbuf[SBUFSIZE];
  40.  
  41. TextEdit::TextEdit (const char* sample, int samplen) {
  42.     selecting = false;
  43.     dot = mark = 0;
  44.     text = new TextBuffer(sbuf, 0, SBUFSIZE);
  45.     display = new TextDisplay(true);
  46.     output = nil;
  47.  
  48.     text->Insert(0, sample, samplen);
  49.     int lines = text->Height();
  50.     for (int i = 0; i < lines; ++i) {
  51.         int bol = text->LineIndex(i);
  52.         int eol = text->EndOfLine(bol);
  53.         display->ReplaceText(i, text->Text(bol, eol), eol - bol);
  54.     }
  55. }
  56.  
  57. TextEdit::~TextEdit () { 
  58.     delete text;
  59.     delete display;
  60. }
  61.  
  62. const char* TextEdit::GetText (int& size) { 
  63.     size = text->Length();
  64.     return text->Text();
  65. }
  66.  
  67. void TextEdit::Redraw (
  68.     Painter* output, Canvas* canvas, int lineHt, boolean redraw
  69. ) {
  70.     TextEdit::output = output;
  71.     display->Draw(output, canvas);
  72.  
  73.     display->LineHeight(lineHt);
  74.     Coord l = 0;
  75.     Coord b = 0 - display->Height();
  76.     Coord r = 0 + display->Width();
  77.     Coord t = 0;
  78.     display->Resize(l, b, r, t);
  79.     if (redraw) {
  80.     display->Redraw(l, b, r, t);
  81.     }
  82. }
  83.  
  84. void TextEdit::Grasp (Event& e) {
  85.     Select(Locate(e.x, e.y));
  86.     selecting = true;
  87.     e.eventType = MotionEvent;
  88. }
  89.  
  90. boolean TextEdit::Editing (Event& e) {
  91.     boolean editing = true;
  92.  
  93.     if (e.eventType == KeyEvent && e.len > 0) {
  94.         editing = HandleKey(e.keystring[0]);
  95.     } else if (e.eventType == MotionEvent && selecting) {
  96.         SelectMore(Locate(e.x, e.y));
  97.     } else if (e.eventType == DownEvent) {
  98.         if (e.shift) {
  99.             SelectMore(Locate(e.x, e.y));
  100.             selecting = true;
  101.         } else if (Contains(e.x, e.y)) {
  102.             Select(Locate(e.x, e.y));
  103.             selecting = true;
  104.         } else {
  105.             editing = false;
  106.         }
  107.     } else if (e.eventType == UpEvent) {
  108.         selecting = false;
  109.     }
  110.  
  111.     if (!editing) {
  112.     Select(dot);
  113.         display->CaretStyle(NoCaret);
  114.     }
  115.     return editing;
  116. }
  117.  
  118. void TextEdit::Bounds (Coord& xmin, Coord& ymin, Coord& xmax, Coord& ymax) {
  119.     Transformer* t = output->GetTransformer();
  120.  
  121.     display->Bounds(xmin, ymin, xmax, ymax);
  122.     if (t != nil) {
  123.         t->TransformRect(xmin, ymin, xmax, ymax);
  124.     }
  125. }
  126.  
  127. boolean TextEdit::HandleKey (char c) {
  128.     boolean editing = true;
  129.  
  130.     switch (c) {
  131.         case '\001' /* ^A  */:  BeginningOfLine(); break;
  132.         case '\005' /* ^E  */:  EndOfLine(); break;
  133.         case '\006' /* ^F  */:  ForwardCharacter(1); break;
  134.         case '\002' /* ^B  */:  BackwardCharacter(1); break;
  135.         case '\016' /* ^N  */:  ForwardLine(1); break;
  136.         case '\020' /* ^P  */:  BackwardLine(1); break;
  137.         case '\013' /* ^K  */:  DeleteRestOfLine(); break;
  138.         case '\004' /* ^D  */:  DeleteCharacter(1); break;
  139.         case '\010' /* ^H  */:  DeleteCharacter(-1); break;
  140.         case '\177' /* DEL */:  DeleteCharacter(-1); break;
  141.         case '\011' /* TAB */:  InsertCharacter(' '); break;
  142.         case '\027' /* ^W  */:  SelectWord(); break;
  143.         case '\025' /* ^U  */:  SelectLine(); break;
  144.         case '\015' /* RET */:  InsertCharacter('\n'); break;
  145.         case '\033' /* ESC */:  editing = false; break;
  146.         default:
  147.             if (!iscntrl(c)) {
  148.                 InsertCharacter(c);
  149.             }
  150.             break;
  151.     }
  152.     return editing;
  153. }
  154.  
  155. void TextEdit::InsertCharacter (char c) {
  156.     DeleteSelection();
  157.     InsertText(&c, 1);
  158. }
  159.  
  160. void TextEdit::DeleteCharacter (int count) {
  161.     if (dot != mark) {
  162.         DeleteSelection();
  163.     } else {
  164.         DeleteText(count);
  165.     }
  166. }
  167.  
  168. void TextEdit::InsertText (const char* s, int count) {
  169.     count = text->Insert(dot, s, count);
  170.     int sline = text->LineNumber(dot);
  171.     int fline = text->LineNumber(dot + count);
  172.     if (sline == fline) {
  173.         int offset = text->LineOffset(dot);
  174.         display->InsertText(sline, offset, text->Text(dot), count);
  175.     } else {
  176.         display->InsertLinesAfter(sline, fline-sline);
  177.         for (int i = sline; i <= fline; ++i) {
  178.             int bol = text->BeginningOfLine(text->LineIndex(i));
  179.             int eol = text->EndOfLine(bol);
  180.             display->ReplaceText(i, text->Text(bol, eol), eol-bol);
  181.         }
  182.     }
  183.     Select(dot + count);
  184. }
  185.  
  186. void TextEdit::DeleteText (int count) {
  187.     int d = dot;
  188.     int c = count;
  189.     while (c > 0) {
  190.         d = text->NextCharacter(d);
  191.         --c;
  192.     }
  193.     while (c < 0) {
  194.         dot = text->PreviousCharacter(dot);
  195.         ++c;
  196.     }
  197.     count = d - dot;
  198.     int sline = text->LineNumber(dot);
  199.     int fline = text->LineNumber(d);
  200.     text->Delete(dot, count);
  201.     if (sline == fline) {
  202.         int offset = text->LineOffset(dot);
  203.         display->DeleteText(sline, offset, count);
  204.     } else {
  205.         int bol = text->BeginningOfLine(dot);
  206.         int eol = text->EndOfLine(dot);
  207.         display->DeleteLinesAfter(sline, fline-sline);
  208.         display->ReplaceText(sline, text->Text(bol, eol), eol-bol);
  209.     }
  210.     Select(dot);
  211. }
  212.  
  213. void TextEdit::DeleteRestOfLine () {
  214.     if (dot == mark) {
  215.     int bol = text->BeginningOfLine(dot);
  216.     if (dot == bol) {
  217.         Select(dot, text->BeginningOfNextLine(dot));
  218.     } else {
  219.         Select(dot, text->EndOfLine(dot));
  220.     }
  221.     }
  222.     DeleteSelection();
  223. }
  224.  
  225. void TextEdit::DeleteSelection () {
  226.     if (dot != mark) {
  227.         DeleteText(mark - dot);
  228.     }
  229. }
  230.  
  231. void TextEdit::BeginningOfLine () {
  232.     if (dot != mark) {
  233.         Select(min(mark, dot));
  234.     } else {
  235.         Select(text->BeginningOfLine(dot));
  236.     }
  237. }
  238.  
  239. void TextEdit::EndOfLine () {
  240.     if (dot != mark) {
  241.         Select(max(mark, dot));
  242.     } else {
  243.         Select(text->EndOfLine(dot));
  244.     }
  245. }
  246.  
  247. void TextEdit::ForwardCharacter (int count) {
  248.     if (dot != mark) {
  249.         Select(max(mark, dot));
  250.     } else {
  251.         int d = dot;
  252.         while (count > 0) {
  253.             d = text->NextCharacter(d);
  254.             --count;
  255.         }
  256.         Select(d);
  257.     }
  258. }
  259.  
  260. void TextEdit::BackwardCharacter (int count) {
  261.     if (dot != mark) {
  262.         Select(min(mark, dot));
  263.     } else {
  264.         int d = dot;
  265.         while (count > 0) {
  266.             d = text->PreviousCharacter(d);
  267.             --count;
  268.         }
  269.         Select(d);
  270.     }
  271. }
  272.  
  273. void TextEdit::ForwardLine (int count) {
  274.     if (dot != mark) {
  275.         Select(max(mark, dot));
  276.     } else {
  277.         int d = dot;
  278.         while (count > 0) {
  279.             d = text->BeginningOfNextLine(d);
  280.             --count;
  281.         }
  282.         Select(d);
  283.     }
  284. }
  285.  
  286. void TextEdit::BackwardLine (int count) {
  287.     if (dot != mark) {
  288.         Select(min(mark, dot));
  289.     } else {
  290.         int d = dot;
  291.         while (count > 0) {
  292.             d = text->BeginningOfLine(text->EndOfPreviousLine(d));
  293.             --count;
  294.         }
  295.         Select(d);
  296.     }
  297. }
  298.  
  299. void TextEdit::Select (int d) {
  300.     Select(d, d);
  301. }
  302.  
  303. void TextEdit::SelectMore (int m) {
  304.     Select(dot, m);
  305. }
  306.  
  307. void TextEdit::SelectLine () {
  308.     Select(text->BeginningOfLine(dot), text->BeginningOfNextLine(dot));
  309. }
  310.  
  311. void TextEdit::SelectWord () {
  312.     int left = min(mark, dot);
  313.     int right = max(mark, dot);
  314.     Select(text->BeginningOfWord(text->PreviousCharacter(left)), right);
  315. }
  316.  
  317. void TextEdit::Select (int d, int m) {
  318.     int oldl = min(dot, mark);
  319.     int oldr = max(dot, mark);
  320.     int newl = min(d, m);
  321.     int newr = max(d, m);
  322.     if (oldl == oldr && newl != newr) {
  323.         display->CaretStyle(NoCaret);
  324.     }
  325.     if (newr < oldl || newl > oldr) {
  326.         if (oldr > oldl) {
  327.             display->RemoveStyle(
  328.                 text->LineNumber(oldl), text->LineOffset(oldl),
  329.                 text->LineNumber(oldr-1), text->LineOffset(oldr-1),
  330.                 Reversed
  331.             );
  332.         }
  333.         if (newr > newl) {
  334.             display->AddStyle(
  335.                 text->LineNumber(newl), text->LineOffset(newl),
  336.                 text->LineNumber(newr-1), text->LineOffset(newr-1),
  337.                 Reversed
  338.             );
  339.         }
  340.     } else {
  341.         if (newl < oldl) {
  342.             display->AddStyle(
  343.                 text->LineNumber(newl), text->LineOffset(newl),
  344.                 text->LineNumber(oldl-1), text->LineOffset(oldl-1),
  345.                 Reversed
  346.             );
  347.         } else if (newl > oldl) {
  348.             display->RemoveStyle(
  349.                 text->LineNumber(oldl), text->LineOffset(oldl),
  350.                 text->LineNumber(newl-1), text->LineOffset(newl-1),
  351.                 Reversed
  352.             );
  353.         }
  354.         if (newr > oldr) {
  355.             display->AddStyle(
  356.                 text->LineNumber(oldr), text->LineOffset(oldr),
  357.                 text->LineNumber(newr-1), text->LineOffset(newr-1),
  358.                 Reversed
  359.             );
  360.         } else if (newr < oldr) {
  361.             display->RemoveStyle(
  362.                 text->LineNumber(newr), text->LineOffset(newr),
  363.                 text->LineNumber(oldr-1), text->LineOffset(oldr-1),
  364.                 Reversed
  365.             );
  366.         }
  367.     }
  368.     if (oldl != oldr && newl == newr) {
  369.         display->CaretStyle(BarCaret);
  370.     }
  371.     if (newl == newr) {
  372.         display->Caret(text->LineNumber(newl), text->LineOffset(newl));
  373.     }
  374.     dot = d;
  375.     mark = m;
  376. }
  377.  
  378. boolean TextEdit::Contains (Coord x, Coord y) {
  379.     Transformer tr(output->GetTransformer());
  380.     tr.InvTransform(x, y);
  381.     int line = display->LineNumber(y);
  382.     int index = display->LineIndex(line, x);
  383.  
  384.     return
  385.         x >= display->Left(line, text->BeginningOfLine(index)) &&
  386.         x <= display->Right(line, text->EndOfLine(index)) &&
  387.         y >= display->Base(line) &&
  388.         y <= display->Top(line);
  389. }
  390.  
  391. int TextEdit::Locate (Coord x, Coord y) {
  392.     Transformer tr(output->GetTransformer());
  393.     tr.InvTransform(x, y);
  394.     int line = display->LineNumber(y);
  395.     int index = display->LineIndex(line, x);
  396.     int l = text->LineIndex(line);
  397.     int i = 0;
  398.     while (i < index) {
  399.         l = text->NextCharacter(l);
  400.         i += 1;
  401.     }
  402.     return l;
  403. }
  404.