' Gambas class file Public Enum BEGIN, {END}, INSERT, DELETE 'Public View As Editor Public Type As Integer Public X As Integer Public Y As Integer Public SX As Integer Public SY As Integer Public XA As Integer Public YA As Integer Public Text As String Public Overwrite As Boolean ' /**---- GCommand -----------------------------------------------------------*/ ' ' struct GCommandDocument ' { ' public: ' GEditor *view; ' int cx; ' int cy; ' int sx; ' int sy; ' int sx2; ' int sy2; ' ' GCommandDocument() { } ' GCommandDocument(GDocument *doc); ' void process(GDocument *doc) const; ' void print() const; ' bool equals(GCommandDocument *o) const; ' }; ' Public Sub _new(hDoc As CDocument, iType As Integer, Optional sText As String, bOverwrite As Boolean) With hDoc.Current Type = iType X = .Column Y = .Line SX = .SelectionColumn SY = .SelectionLine XA = hDoc.XAfter YA = hDoc.YAfter Text = sText Overwrite = bOverwrite End With End Public Sub Print() Print ["BEGIN", "END", "INSERT", "DELETE"][Type];; Print "X =";; X;; "Y =";; Y;; "SX =";; SX;; "SY =";; SY;; "XA =";; XA;; "YA =";; YA;; "Text =";; Quote(Text) End Static Public Sub _call(hDoc As CDocument, iType As Integer, Optional sText As String, bOverwrite As Boolean) As CCommand Return New CCommand(hDoc, iType, sText, bOverwrite) End ' GCommandDocument::GCommandDocument(GDocument *doc) ' { ' view = doc->currentView(); ' ' view->getCursor(&cy, &cx); ' ' if (doc->hasSelection()) ' doc->getSelection(&sy, &sx, &sy2, &sx2, false); // TODO: store insertMode ' else ' sx = sy = sx2 = sy2 = -1; ' } ' ' void GCommandDocument::process(GDocument *doc) const ' { ' //qDebug("goto %d %d", cx, cy); ' view->cursorGoto(cy, cx, false); ' if (sx >= 0) ' { ' //qDebug("select %d %d %d %d", sx, sy, sx2, sy2); ' doc->startSelection(view, sy, sx); ' doc->endSelection(sy2, sx2); ' } ' } ' ' void GCommandDocument::print() const ' { ' qDebug("- %d %d [%d %d %d %d]", cx, cy, sx, sy, sx2, sy2); ' } ' ' Public Sub Equals(hOther As CCommand) As Boolean ' ' If hOther.X = X And If hOther.Y = Y And If hOther.SX = SX And If hOther.SY = SY Then Return True ' ' End ' bool GCommandDocument::equals(GCommandDocument *o) const ' { ' return view == o->view && cx == o->cx && cy == o->cy ' && sx == o->sx && sy == o->sy && sx2 == o->sx2 && sy2 == o->sy2; ' } ' ' class GCommand ' { ' public: ' enum Type ' { ' None, Begin, End, Move, Insert, Delete, Indent, Unindent ' }; ' GCommandDocument info; ' ' virtual ~GCommand() { } ' virtual Type type() const { return None; } ' virtual int nest() const { return 0; } ' virtual void print() const { } ' virtual bool merge(GCommand *) const { return false; } ' virtual void process(GDocument *doc, bool undo) const { } ' virtual bool linked() const { return false; } ' virtual bool remove(GCommand *) const { return false; } ' }; ' ' class GBeginCommand: public GCommand ' { ' public: ' bool _linked; ' ' GBeginCommand(GCommandDocument *info, bool linked = false) { _linked = linked; this->info = *info; } ' Type type() const { return Begin; } ' void print() const { qDebug("Begin"); info.print(); } ' int nest() const { return 1; } ' bool linked() const { return _linked; } ' void process(GDocument *doc, bool undo) const { info.process(doc); } ' }; ' ' class GEndCommand: public GCommand ' { ' public: ' bool _linked; ' ' GEndCommand(bool linked = false) { _linked = linked; } ' Type type() const { return End; } ' void print() const { qDebug("End"); } ' int nest() const { return -1; } ' bool linked() const { return _linked; } ' bool remove(GCommand *o) const { return (o->type() == Begin); } ' }; ' ' class GDeleteCommand: public GCommand ' { ' public: ' int x, y, x2, y2; ' GString str; ' ' GDeleteCommand(GCommandDocument *info, int y, int x, int y2, int x2, const GString &str) ' { ' this->x = x; this->y = y; this->x2 = x2; this->y2 = y2; this->str = str; ' this->info = *info; ' } ' ' Type type() const { return Delete; } ' void print() const { qDebug("Delete: (%d %d)-(%d %d): '%s'", x, y, x2, y2, TO_UTF8(str.getString())); info.print(); } ' ' bool merge(GCommand *c) const ' { ' if (c->type() != type()) ' return false; ' ' GDeleteCommand *o = (GDeleteCommand *)c; ' ' if (info.view != o->info.view) ' return false; ' ' if (x2 != o->x || y2 != o->y || o->y != o->y2) ' return false; ' ' o->str.prepend(str); ' o->x = x; ' o->y = y; ' //o->info = info; ' return true; ' } ' ' void process(GDocument *doc, bool undo) const ' { ' if (undo) ' doc->insert(y, x, str); ' else ' doc->remove(y, x, y2, x2); ' ' info.process(doc); ' } ' }; ' ' class GInsertCommand: public GDeleteCommand ' { ' public: ' GInsertCommand(GCommandDocument *info, int y, int x, int y2, int x2, const GString &str): ' GDeleteCommand(info, y, x, y2, x2, str) {} ' Type type() const { return Insert; } ' void print() const { qDebug("Insert: (%d %d)-(%d %d): '%s'", x, y, x2, y2, TO_UTF8(str.getString())); info.print(); } ' ' bool merge(GCommand *c) const ' { ' if (c->type() != type()) ' return false; ' ' if (str.length() && str.isNewLine(0)) ' return false; ' ' GInsertCommand *o = (GInsertCommand *)c; ' ' if (o->info.view != info.view) ' return false; ' ' if (o->str.length() && o->str.isNewLine(str.length() - 1)) ' return false; ' ' if (x != o->x2 || y != o->y2) ' return false; ' ' o->str += str; ' o->x2 = x2; ' o->y2 = y2; ' return true; ' } ' ' void process(GDocument *doc, bool undo) const ' { ' GDeleteCommand::process(doc, !undo); ' } ' }; '