aboutsummaryrefslogtreecommitdiffstats
path: root/edit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'edit.cpp')
-rw-r--r--edit.cpp515
1 files changed, 515 insertions, 0 deletions
diff --git a/edit.cpp b/edit.cpp
new file mode 100644
index 0000000..740a0f3
--- /dev/null
+++ b/edit.cpp
@@ -0,0 +1,515 @@
+// edit.cpp
+// Revision 7-feb-2005
+
+//#include "cursor.h"
+#include "graphics.h"
+#include "error.h"
+#include "trace.h"
+#include "util.h"
+#include "sysvar.h"
+
+#include "edit.h"
+
+using util::to_string;
+
+#include <sstream>
+#include <deque>
+
+#include <cassert>
+#define ASSERT assert
+
+namespace sysvar= blassic::sysvar;
+using namespace blassic::file;
+
+
+namespace {
+
+std::deque <std::string> history;
+
+size_t getmaxhistory ()
+{
+ return sysvar::get16 (sysvar::MaxHistory);
+}
+
+void showstring (BlFile & bf, const std::string & str)
+{
+ for (size_t i= 0, l= str.size (); i < l; ++i)
+ {
+ unsigned char c= str [i];
+ if (c < 32)
+ bf << '\\' << char (c + 'A');
+ else
+ bf << static_cast <char> (c);
+ }
+ bf.flush ();
+}
+
+class Edit {
+public:
+ Edit (BlFile & bf, std::string & str,
+ size_t npos, size_t inicol, bool lineend);
+ ~Edit ();
+ bool do_it ();
+private:
+ BlFile & bf;
+ std::string & str;
+ size_t npos;
+ size_t inicol;
+ size_t width;
+ bool textwindow;
+ size_t histsize;
+ size_t histpos;
+ bool intagmode;
+ bool lineend;
+
+ std::string savestr;
+
+ //void getwidth ();
+ void back ();
+ void forward ();
+ void deletechar ();
+ void showrest ();
+ void showinitial ();
+ void up ();
+ void down ();
+};
+
+Edit::Edit (BlFile & bf, std::string & str,
+ size_t npos, size_t inicol, bool lineend) :
+ bf (bf),
+ str (str),
+ npos (npos),
+ inicol (inicol),
+ width (bf.getwidth () ),
+ textwindow (bf.istextwindow () ),
+ histsize (history.size () ),
+ histpos (histsize),
+ intagmode (bf.istagactive () ),
+ lineend (lineend)
+{
+ TRACEFUNC (tr, "Edit::~Edit");
+ TRMESSAGE (tr, "lineend: " + to_string (lineend) );
+
+ if (textwindow)
+ graphics::synchronize_suspend ();
+ if (intagmode)
+ bf.tagoff ();
+}
+
+Edit::~Edit ()
+{
+ TRACEFUNC (tr, "Edit::~Edit");
+
+ if (textwindow)
+ graphics::synchronize_restart ();
+ if (intagmode)
+ bf.tag ();
+}
+
+void Edit::back ()
+{
+ if (textwindow)
+ {
+ --npos;
+ bf.movecharback ();
+ return;
+ }
+ if ( (npos-- + inicol) % width != 0)
+ bf.movecharback ();
+ else
+ {
+ bf.movecharup ();
+ bf.movecharforward (width - 1);
+ }
+}
+
+void Edit::forward ()
+{
+ ++npos;
+ if (textwindow)
+ {
+ bf.movecharforward ();
+ return;
+ }
+ if ( (npos + inicol) % width != 0)
+ bf.movecharforward ();
+ else
+ {
+ if (npos == str.size () )
+ {
+ //bf.movecharforward ();
+ //bf << '\n';
+ bf.endline ();
+ bf.flush ();
+ }
+ else
+ {
+ //bf << '\r';
+ //bf.flush ();
+ bf.movecharback (width - 1);
+ bf.movechardown ();
+ }
+ }
+}
+
+void Edit::deletechar ()
+{
+ if (npos < str.size () )
+ {
+ str.erase (npos, 1);
+ // Vil chapuza.
+ str+= ' ';
+ showrest ();
+ str.erase (str.size () - 1);
+ }
+}
+
+void Edit::showrest ()
+{
+ //TRACEFUNC (tr, "Edit::showrest");
+
+ if (npos == str.size () )
+ return;
+ //bf << str.substr (npos);
+ //bf.flush ();
+ showstring (bf, str.substr (npos) );
+
+ size_t l= str.size ();
+ size_t nlines= (l + inicol) / width;
+ size_t actualline= (npos + inicol) / width;
+ size_t actualcol= (npos + inicol) % width;
+ size_t lastcol= (l + inicol) % width;
+ if (lastcol == 0 && nlines > 0)
+ {
+ if (! textwindow)
+ {
+ #ifndef __WIN32__
+ --nlines;
+ // The cursor position remains
+ // in the last valid column.
+ lastcol= width - 1;
+ //lastcol= width;
+ #endif
+ }
+ }
+ bf.movecharup (nlines - actualline);
+ if (actualcol < lastcol)
+ {
+ //TRMESSAGE (tr, std::string ("moving back " +
+ // to_string (lastcol - actualcol) ) );
+ bf.movecharback (lastcol - actualcol);
+ }
+ else if (actualcol > lastcol)
+ {
+ //TRMESSAGE (tr, "moving forward");
+ bf.movecharforward (actualcol - lastcol);
+ }
+ else if (actualcol == width - 1)
+ {
+ // Without this the cursor sometimes keep in the next line.
+ bf.movecharback ();
+ bf.movecharforward ();
+ }
+}
+
+void Edit::showinitial ()
+{
+ //TRACEFUNC (tr, "Edit::showinitial");
+
+ //bf << '\r' << str;
+ //bf.flush ();
+
+ //bf << '\r';
+ //bf.movecharforward (inicol);
+
+ showstring (bf, str);
+
+ size_t l= str.size () + inicol;
+ size_t nlines= l / width;
+ size_t actualline= (npos + inicol) / width;
+ size_t actualcol= (npos + inicol) % width;
+ size_t lastcol= l % width;
+
+ #ifndef __WIN32__
+ if (lastcol == 0 && nlines > 0)
+ {
+ --nlines;
+ lastcol= width - 1;
+ }
+ #endif
+
+ bf.movecharup (nlines - actualline);
+ if (actualcol < lastcol)
+ bf.movecharback (lastcol - actualcol);
+ else
+ bf.movecharforward (actualcol - lastcol);
+ //bf << '\r';
+ //bf.flush ();
+ //movecharforward (npos);
+}
+
+void Edit::up ()
+{
+ if (histpos > 0)
+ {
+ if (histpos == histsize)
+ savestr= str;
+ std::string::size_type oldsize= str.size ();
+ --histpos;
+ str= history [histpos];
+ while (npos > 0)
+ back ();
+ std::string::size_type
+ actualsize= str.size ();
+ if (oldsize > actualsize)
+ {
+ showstring (bf, std::string (oldsize, ' ') );
+ npos= oldsize;
+ for (size_t i= 0; i < oldsize; ++i)
+ back ();
+ }
+ //showinitial ();
+ showstring (bf, str);
+ npos= actualsize;
+ }
+}
+
+void Edit::down ()
+{
+ if (histpos < histsize)
+ {
+ std::string::size_type oldsize= str.size ();
+ ++histpos;
+ if (histpos < histsize)
+ str= history [histpos];
+ else
+ str= savestr;
+ while (npos > 0)
+ back ();
+ std::string::size_type
+ actualsize= str.size ();
+ if (oldsize > actualsize)
+ {
+ showstring (bf, std::string (oldsize, ' ') );
+ npos= oldsize;
+ for (size_t i= 0; i < oldsize; ++i)
+ back ();
+ }
+ //showinitial ();
+ showstring (bf, str);
+ npos= actualsize;
+ }
+}
+
+bool Edit::do_it ()
+{
+ TRACEFUNC (tr, "Edit::do_it");
+
+ showinitial ();
+
+ bool editing= true;
+ bool retval= true;
+ while (editing)
+ {
+ bf.showcursor ();
+ //TRMESSAGE (tr, "Waiting key");
+ std::string key= bf.getkey ();
+ //TRMESSAGE (tr, "Received key");
+ bf.hidecursor ();
+ if (key.size () == 1)
+ {
+ unsigned char c= key [0];
+ switch (c)
+ {
+ case '\r': case '\n':
+ editing= false;
+ break;
+ case '\x1B':
+ editing= false;
+ retval= false;
+ break;
+ case '\t':
+ {
+ //size_t n= npos + 1;
+ //n+= 7 - (n % 8);
+ //n-= npos ;
+ size_t n= 8 - npos % 8;
+ str.insert (npos, n, ' ');
+ showrest ();
+ for (size_t i= 0; i < n; ++i)
+ forward ();
+ }
+ break;
+ case '\3': // Ctrl-C
+ editing= false;
+ retval= false;
+ break;
+ case '\5': // Ctrl-E, test debug
+ //bf << str.substr (npos) << '\n';
+ //bf.flush ();
+ showstring (bf, str.substr (npos) );
+ //bf << '\n';
+ bf.endline ();
+ bf.flush ();
+ showinitial ();
+ break;
+ case '\x8':
+ case '\x7F':
+ if (npos > 0)
+ {
+ back ();
+ deletechar ();
+ }
+ break;
+ default:
+ if (c >= ' ')
+ {
+ str.insert (npos, 1, c);
+ showrest ();
+ forward ();
+ }
+ }
+ }
+ else if (key == "RIGHT")
+ {
+ if (npos < str.size () )
+ {
+ forward ();
+ }
+ }
+ else if (key == "LEFT")
+ {
+ if (npos > 0)
+ {
+ back ();
+ }
+ }
+ else if (key == "DELETE")
+ {
+ if (npos < str.size () )
+ deletechar ();
+ }
+ else if (key == "HOME")
+ {
+ while (npos > 0)
+ back ();
+ }
+ else if (key == "END")
+ {
+ const size_t l= str.size ();
+ while (npos < l)
+ forward ();
+ }
+ else if (key == "UP")
+ up ();
+ else if (key == "DOWN")
+ down ();
+ }
+ //hidecursor ();
+
+ if (lineend)
+ {
+ // After exit, cursor must be positioned after the line edited.
+ //bf << str.substr (npos) << '\n';
+ bf << str.substr (npos);
+ bf.endline ();
+ bf.flush ();
+ }
+
+ if (retval)
+ {
+ size_t maxhist= getmaxhistory ();
+ if (maxhist == 0)
+ maxhist= 1;
+ if (histsize >= maxhist)
+ {
+ history.erase (history.begin (),
+ history.begin () + histsize - maxhist + 1);
+ }
+ if (! str.empty () && (history.empty () ||
+ history [history.size () - 1] != str) )
+ history.push_back (str);
+ }
+
+ return retval;
+}
+
+} // namespace
+
+bool blassic::edit::editline (BlFile & bf, std::string & str,
+ size_t npos, size_t inicol, bool lineend)
+{
+ TRACEFUNC (tr, "editline - string");
+ {
+ std::ostringstream oss;
+ oss << "Inicol: " << inicol;
+ TRMESSAGE (tr, oss.str () );
+ }
+
+ Edit edit (bf, str, npos, inicol, lineend);
+ return edit.do_it ();
+}
+
+#if 0
+
+bool editline (BlFile & bf, Program & program, BlLineNumber bln,
+ std::string & str)
+{
+ TRACEFUNC (tr, "editline - line number->string");
+
+ std::string buffer;
+ {
+ BlFileOutString bfos;
+ program.list (bln, bln, bfos);
+ buffer= bfos.str ();
+ if (buffer.empty () )
+ {
+ //bfos << bln << " \n";
+ bfos << bln << ' ';
+ bfos.endline ();
+ buffer= bfos.str ();
+ }
+ }
+ buffer.erase (buffer.size () - 1);
+ TRMESSAGE (tr, std::string (1, '\'') + buffer + '\'');
+
+ static const std::string number ("01234567890");
+ size_t inipos= buffer.find_first_of (number);
+ ASSERT (inipos != std::string::npos);
+ inipos= buffer.find_first_not_of (number, inipos);
+ ASSERT (inipos != std::string::npos);
+ ++inipos;
+
+ bool r;
+ if ( (r= editline (bf, buffer, inipos) ) == true)
+ str= buffer;
+ return r;
+}
+
+bool editline (BlFile & bf, Program & program, BlLineNumber bln)
+{
+ TRACEFUNC (tr, "editline - line number");
+
+ std::string buffer;
+ bool r;
+ if ( (r= editline (bf, program, bln, buffer) ) == true)
+ {
+ CodeLine code;
+ code.scan (buffer);
+ BlLineNumber nline= code.number ();
+ if (nline == LineDirectCommand)
+ throw ErrBlassicInternal;
+ else
+ {
+ if (code.empty () )
+ program.deletelines (nline, nline);
+ else
+ program.insert (code);
+ }
+ }
+ return r;
+}
+
+#endif
+
+// End of edit.cpp
Un proyecto texto-plano.xyz