TGTextEdit.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGTextEdit.cxx 35582 2010-09-22 13:38:27Z bellenot $
00002 // Author: Fons Rademakers   3/7/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 /**************************************************************************
00012 
00013     This source is based on Xclass95, a Win95-looking GUI toolkit.
00014     Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
00015 
00016     Xclass95 is free software; you can redistribute it and/or
00017     modify it under the terms of the GNU Library General Public
00018     License as published by the Free Software Foundation; either
00019     version 2 of the License, or (at your option) any later version.
00020 
00021 **************************************************************************/
00022 
00023 //////////////////////////////////////////////////////////////////////////
00024 //                                                                      //
00025 // TGTextEdit                                                           //
00026 //                                                                      //
00027 // A TGTextEdit is a specialization of TGTextView. It provides the      //
00028 // text edit functionality to the static text viewing widget.           //
00029 // For the messages supported by this widget see the TGView class.      //
00030 //                                                                      //
00031 //////////////////////////////////////////////////////////////////////////
00032 
00033 #include "TGTextEdit.h"
00034 #include "TGTextEditDialogs.h"
00035 #include "TGResourcePool.h"
00036 #include "TSystem.h"
00037 #include "TMath.h"
00038 #include "TTimer.h"
00039 #include "TGMenu.h"
00040 #include "TGMsgBox.h"
00041 #include "TGFileDialog.h"
00042 #include "TGScrollBar.h"
00043 #include "KeySymbols.h"
00044 #include "Riostream.h"
00045 
00046 
00047 static const char *gFiletypes[] = { "All files",     "*",
00048                                     "Text files",    "*.txt",
00049                                     "ROOT macros",   "*.C",
00050                                     0,               0 };
00051 static char *gPrinter      = 0;
00052 static char *gPrintCommand = 0;
00053 
00054 
00055 TGGC *TGTextEdit::fgCursor0GC;
00056 TGGC *TGTextEdit::fgCursor1GC;
00057 
00058 
00059 ///////////////////////////////////////////////////////////////////////////////
00060 class TGTextEditHist : public TList {
00061 
00062 public:
00063    TGTextEditHist() {}
00064    virtual ~TGTextEditHist() { Delete(); }
00065 
00066    Bool_t Notify() { // 
00067       TObject *obj = Last();
00068       if (!obj) return kFALSE;
00069 
00070       obj->Notify(); // execute undo action
00071       RemoveLast();
00072       delete obj;
00073       return kTRUE;
00074    }
00075 };
00076 
00077 ///////////////////////////////////////////////////////////////////////////////
00078 class TGTextEditCommand : public TObject {
00079 protected:
00080    TGTextEdit     *fEdit;
00081    TGLongPosition  fPos;
00082 
00083 public:
00084    TGTextEditCommand(TGTextEdit *te) : fEdit(te) {
00085       fPos = fEdit->GetCurrentPos();
00086       fEdit->GetHistory()->Add(this);
00087    }
00088    void SetPos(TGLongPosition pos) { fPos = pos; }
00089 };
00090 
00091 ///////////////////////////////////////////////////////////////////////////////
00092 class TInsCharCom : public TGTextEditCommand {
00093 
00094 public:
00095    TInsCharCom(TGTextEdit *te, char ch) : TGTextEditCommand(te) {
00096       fEdit->InsChar(ch);
00097    }
00098    Bool_t Notify() { // 
00099       fEdit->SetCurrent(fPos);
00100       fEdit->NextChar();
00101       fEdit->DelChar();
00102       return kTRUE;
00103    }
00104 };
00105 
00106 ///////////////////////////////////////////////////////////////////////////////
00107 class TDelCharCom : public TGTextEditCommand {
00108 
00109 private:
00110    char fChar;
00111 
00112 public:
00113    TDelCharCom(TGTextEdit *te) : TGTextEditCommand(te)  {
00114       fPos.fX--;
00115       fChar = fEdit->GetText()->GetChar(fPos);
00116       fEdit->DelChar();
00117    }
00118    Bool_t Notify() { // 
00119       if (fChar > 0) {
00120          fEdit->SetCurrent(fPos);
00121          fEdit->InsChar(fChar);
00122       } else {
00123          fPos.fY--;
00124          fEdit->BreakLine();
00125       }
00126       return kTRUE;
00127    }
00128 };
00129 
00130 ///////////////////////////////////////////////////////////////////////////////
00131 class TBreakLineCom : public TGTextEditCommand {
00132 
00133 public:
00134    TBreakLineCom(TGTextEdit *te) : TGTextEditCommand(te)  {
00135       fEdit->BreakLine();
00136       fPos.fX = 0;
00137       fPos.fY++;
00138    }
00139 
00140    Bool_t Notify() { //
00141       fEdit->SetCurrent(fPos);
00142       fEdit->DelChar();
00143       return kTRUE;
00144    }
00145 };
00146 
00147 ///////////////////////////////////////////////////////////////////////////////
00148 class TInsTextCom : public TGTextEditCommand {
00149 private:
00150    TGLongPosition  fEndPos;
00151 
00152 public:
00153    char            fChar;
00154 
00155    TInsTextCom(TGTextEdit *te) : TGTextEditCommand(te), fChar(0)  {
00156    }
00157 
00158    void SetEndPos(TGLongPosition end) {
00159       fEndPos = end;
00160    }
00161 
00162    Bool_t Notify() { //
00163       fEdit->GetText()->DelText(fPos, fEndPos);
00164 
00165       if (fChar > 0) {
00166          fEdit->GetText()->InsChar(fPos, fChar);
00167       } else if (fPos.fY != fEndPos.fY) {
00168          fEdit->GetText()->BreakLine(fPos);
00169       }
00170       fEdit->SetCurrent(fPos);
00171       fEdit->Update();
00172       return kTRUE;
00173    }
00174 };
00175 
00176 ///////////////////////////////////////////////////////////////////////////////
00177 class TDelTextCom : public TGTextEditCommand {
00178 
00179 private:
00180    TGText         *fText;
00181    TGLongPosition  fEndPos;
00182    Bool_t          fBreakLine;
00183 
00184 public:
00185    TDelTextCom(TGTextEdit *te, TGText *txt) : TGTextEditCommand(te)  {
00186       fText = new TGText(txt);
00187       fBreakLine = kFALSE;
00188    }
00189 
00190    virtual ~TDelTextCom() {  delete fText; }
00191 
00192    void SetEndPos(TGLongPosition end) {
00193       fEndPos = end;
00194    }
00195 
00196    void SetBreakLine(Bool_t on) { fBreakLine = on; }
00197 
00198    Bool_t Notify() { //
00199       TGLongPosition start_src, end_src;
00200       start_src.fX = start_src.fY = 0;
00201       end_src.fY   = fText->RowCount() - 1;
00202       end_src.fX   = fText->GetLineLength(end_src.fY) - 1;
00203 
00204       fEdit->GetText()->InsText(fPos, fText, start_src, end_src);
00205 
00206       if (fBreakLine) {
00207          fEndPos.fY++;
00208          fEdit->GetText()->BreakLine(fEndPos);
00209          fEndPos.fX = fEdit->GetText()->GetLineLength(fEndPos.fY);
00210       } else {
00211          fEndPos.fX++;
00212       }
00213 
00214       fEdit->SetCurrent(fEndPos);
00215       fEdit->Update();
00216       return kTRUE;
00217    }
00218 };
00219 
00220 
00221 ClassImp(TGTextEdit)
00222 
00223 
00224 //______________________________________________________________________________
00225 TGTextEdit::TGTextEdit(const TGWindow *parent, UInt_t w, UInt_t h, Int_t id,
00226                        UInt_t sboptions, ULong_t back) :
00227      TGTextView(parent, w, h, id, sboptions, back)
00228 {
00229    // Create a text edit widget.
00230 
00231    Init();
00232 }
00233 
00234 //______________________________________________________________________________
00235 TGTextEdit::TGTextEdit(const TGWindow *parent, UInt_t w, UInt_t h, TGText *text,
00236                        Int_t id, UInt_t sboptions, ULong_t back) :
00237      TGTextView(parent, w, h, text, id, sboptions, back)
00238 {
00239    // Create a text edit widget. Initialize it with the specified text buffer.
00240 
00241    Init();
00242 }
00243 
00244 //______________________________________________________________________________
00245 TGTextEdit::TGTextEdit(const TGWindow *parent, UInt_t w, UInt_t h,
00246                        const char *string, Int_t id, UInt_t sboptions,
00247                        ULong_t back) :
00248      TGTextView(parent, w, h, string, id, sboptions, back)
00249 {
00250    // Create a text edit widget. Initialize it with the specified string.
00251 
00252    Init();
00253 }
00254 
00255 //______________________________________________________________________________
00256 TGTextEdit::~TGTextEdit()
00257 {
00258    // Cleanup text edit widget.
00259 
00260    if (TGSearchDialog::SearchDialog()) {
00261       TQObject::Disconnect(TGSearchDialog::SearchDialog(), 0, this);
00262    }
00263    delete fCurBlink;
00264    delete fMenu;
00265    delete fHistory;
00266 }
00267 
00268 //______________________________________________________________________________
00269 void TGTextEdit::Init()
00270 {
00271    // Initiliaze a text edit widget.
00272 
00273    fCursor0GC   = GetCursor0GC()();
00274    fCursor1GC   = GetCursor1GC()();
00275    fCursorState = 1;
00276    fCurrent.fY  = fCurrent.fX = 0;
00277    fInsertMode  = kInsert;
00278    fCurBlink    = 0;
00279    fSearch      = 0;
00280    fEnableMenu  = kTRUE;
00281    fEnableCursorWithoutFocus = kTRUE;
00282 
00283    gVirtualX->SetCursor(fCanvas->GetId(), fClient->GetResourcePool()->GetTextCursor());
00284 
00285    // create popup menu with default editor actions
00286    fMenu = new TGPopupMenu(fClient->GetDefaultRoot());
00287    fMenu->AddEntry("New", kM_FILE_NEW);
00288    fMenu->AddEntry("Open...", kM_FILE_OPEN);
00289    fMenu->AddSeparator();
00290    fMenu->AddEntry("Close", kM_FILE_CLOSE);
00291    fMenu->AddEntry("Save", kM_FILE_SAVE);
00292    fMenu->AddEntry("Save As...", kM_FILE_SAVEAS);
00293    fMenu->AddSeparator();
00294    fMenu->AddEntry("Print...", kM_FILE_PRINT);
00295    fMenu->AddSeparator();
00296    fMenu->AddEntry("Cut", kM_EDIT_CUT);
00297    fMenu->AddEntry("Copy", kM_EDIT_COPY);
00298    fMenu->AddEntry("Paste", kM_EDIT_PASTE);
00299    fMenu->AddEntry("Select All", kM_EDIT_SELECTALL);
00300    fMenu->AddSeparator();
00301    fMenu->AddEntry("Find...", kM_SEARCH_FIND);
00302    fMenu->AddEntry("Find Again", kM_SEARCH_FINDAGAIN);
00303    fMenu->AddEntry("Goto...", kM_SEARCH_GOTO);
00304 
00305    fMenu->Associate(this);
00306 
00307    fHistory = new TGTextEditHist();
00308 }
00309 
00310 //______________________________________________________________________________
00311 void TGTextEdit::SetMenuState()
00312 {
00313    // Enable/disable menu items in function of what is possible.
00314 
00315    if (fText->RowCount() == 1 && fText->GetLineLength(0) <= 0) {
00316       fMenu->DisableEntry(kM_FILE_CLOSE);
00317       fMenu->DisableEntry(kM_FILE_SAVE);
00318       fMenu->DisableEntry(kM_FILE_SAVEAS);
00319       fMenu->DisableEntry(kM_FILE_PRINT);
00320       fMenu->DisableEntry(kM_EDIT_SELECTALL);
00321       fMenu->DisableEntry(kM_SEARCH_FIND);
00322       fMenu->DisableEntry(kM_SEARCH_FINDAGAIN);
00323       fMenu->DisableEntry(kM_SEARCH_GOTO);
00324    } else {
00325       fMenu->EnableEntry(kM_FILE_CLOSE);
00326       fMenu->EnableEntry(kM_FILE_SAVE);
00327       fMenu->EnableEntry(kM_FILE_SAVEAS);
00328       fMenu->EnableEntry(kM_FILE_PRINT);
00329       fMenu->EnableEntry(kM_EDIT_SELECTALL);
00330       fMenu->EnableEntry(kM_SEARCH_FIND);
00331       fMenu->EnableEntry(kM_SEARCH_FINDAGAIN);
00332       fMenu->EnableEntry(kM_SEARCH_GOTO);
00333    }
00334 
00335    if (IsSaved())
00336       fMenu->DisableEntry(kM_FILE_SAVE);
00337    else
00338       fMenu->EnableEntry(kM_FILE_SAVE);
00339 
00340    if (fIsMarked) {
00341       fMenu->EnableEntry(kM_EDIT_CUT);
00342       fMenu->EnableEntry(kM_EDIT_COPY);
00343    } else {
00344       fMenu->DisableEntry(kM_EDIT_CUT);
00345       fMenu->DisableEntry(kM_EDIT_COPY);
00346    }
00347 }
00348 
00349 //______________________________________________________________________________
00350 Long_t TGTextEdit::ReturnLongestLineWidth()
00351 {
00352    // Return width of longest line in widget.
00353 
00354    Long_t linewidth = TGTextView::ReturnLongestLineWidth();
00355    linewidth += 3*fScrollVal.fX;
00356    return linewidth;
00357 }
00358 
00359 //______________________________________________________________________________
00360 void TGTextEdit::Clear(Option_t *)
00361 {
00362    // Clear text edit widget.
00363 
00364    fCursorState = 1;
00365    fCurrent.fY = fCurrent.fX = 0;
00366    TGTextView::Clear();
00367 }
00368 
00369 //______________________________________________________________________________
00370 Bool_t TGTextEdit::SaveFile(const char *filename, Bool_t saveas)
00371 {
00372    // Save file. If filename==0 ask user via dialog for a filename, if in
00373    // addition saveas==kTRUE always ask for new filename. Returns
00374    // kTRUE if file was correctly saved, kFALSE otherwise.
00375 
00376    if (!filename) {
00377       Bool_t untitled = !strlen(fText->GetFileName()) ? kTRUE : kFALSE;
00378       if (untitled || saveas) {
00379          static TString dir(".");
00380          static Bool_t overwr = kFALSE;
00381          TGFileInfo fi;
00382          fi.fFileTypes = gFiletypes;
00383          fi.fIniDir    = StrDup(dir);
00384          fi.fOverwrite = overwr;
00385          new TGFileDialog(fClient->GetDefaultRoot(), this, kFDSave, &fi);
00386          overwr = fi.fOverwrite;
00387          if (fi.fFilename && strlen(fi.fFilename)) {
00388             dir = fi.fIniDir;
00389             return fText->Save(fi.fFilename);
00390          }
00391          return kFALSE;
00392       }
00393       return fText->Save(fText->GetFileName());
00394    }
00395 
00396    return fText->Save(filename);
00397 }
00398 
00399 //______________________________________________________________________________
00400 Bool_t TGTextEdit::Copy()
00401 {
00402    // Copy text.
00403 
00404    if (!fIsMarked || ((fMarkedStart.fX == fMarkedEnd.fX) && 
00405        (fMarkedStart.fY == fMarkedEnd.fY))) {
00406       return kFALSE;
00407    }
00408 
00409    TGTextView::Copy();
00410 
00411    Bool_t del = !fCurrent.fX && (fCurrent.fY == fMarkedEnd.fY) && !fMarkedEnd.fX;
00412    del = del || (!fMarkedEnd.fX && (fCurrent.fY != fMarkedEnd.fY));
00413    del = del && fClipText->AsString().Length() > 0;
00414 
00415    if (del) {
00416       TGLongPosition pos;
00417       pos.fY = fClipText->RowCount();
00418       pos.fX = 0;
00419       fClipText->InsText(pos, 0);
00420    }
00421 
00422    return kTRUE;
00423 }
00424 
00425 //______________________________________________________________________________
00426 Bool_t TGTextEdit::Cut()
00427 {
00428    // Cut text.
00429 
00430    if (!Copy()) {
00431       return kFALSE;
00432    }
00433    Delete();
00434 
00435    return kTRUE;
00436 }
00437 
00438 //______________________________________________________________________________
00439 Bool_t TGTextEdit::Paste()
00440 {
00441    // Paste text into widget.
00442 
00443    if (fReadOnly) {
00444       return kFALSE;
00445    }
00446 
00447    if (fIsMarked) {
00448       TString sav = fClipText->AsString();
00449       TGTextView::Copy();
00450       Delete();
00451       fClipText->Clear();
00452       fClipText->LoadBuffer(sav.Data());
00453    }
00454 
00455    gVirtualX->ConvertPrimarySelection(fId, fClipboard, 0);
00456 
00457    return kTRUE;
00458 }
00459 
00460 //______________________________________________________________________________
00461 void TGTextEdit::Print(Option_t *) const
00462 {
00463    // Send current buffer to printer.
00464 
00465    TString msg;
00466 
00467    msg.Form("%s -P%s\n", gPrintCommand, gPrinter);
00468    FILE *p = gSystem->OpenPipe(msg.Data(), "w");
00469    if (p) {
00470       char   *buf1, *buf2;
00471       Long_t  len;
00472       ULong_t i = 0;
00473       TGLongPosition pos;
00474 
00475       pos.fX = pos.fY = 0;
00476       while (pos.fY < fText->RowCount()) {
00477          len = fText->GetLineLength(pos.fY);
00478          if (len < 0) len = 0;
00479          buf1 = fText->GetLine(pos, len);
00480          buf2 = new char[len + 2];
00481          strncpy(buf2, buf1, (UInt_t)len);
00482          buf2[len]   = '\n';
00483          buf2[len+1] = '\0';
00484          while (buf2[i] != '\0') {
00485             if (buf2[i] == '\t') {
00486                ULong_t j = i+1;
00487                while (buf2[j] == 16)
00488                   j++;
00489                strcpy(buf2+i+1, buf2+j);
00490             }
00491             i++;
00492          }
00493          fwrite(buf2, sizeof(char), strlen(buf2)+1, p);
00494 
00495          delete [] buf1;
00496          delete [] buf2;
00497          pos.fY++;
00498       }
00499       gSystem->ClosePipe(p);
00500 
00501       Bool_t untitled = !strlen(fText->GetFileName()) ? kTRUE : kFALSE;
00502       msg.Form("Printed: %s\nLines: %ld\nUsing: %s -P%s",
00503                untitled ? "Untitled" : fText->GetFileName(),
00504                fText->RowCount() - 1, gPrintCommand, gPrinter);
00505       new TGMsgBox(fClient->GetDefaultRoot(), this, "Editor", msg.Data(),
00506                    kMBIconAsterisk, kMBOk, 0);
00507    } else {
00508       msg.Form("Could not execute: %s -P%s\n", gPrintCommand, gPrinter);
00509       new TGMsgBox(fClient->GetDefaultRoot(), this, "Editor", msg.Data(),
00510                    kMBIconExclamation, kMBOk, 0);
00511    }
00512 }
00513 
00514 //______________________________________________________________________________
00515 void TGTextEdit::Delete(Option_t *)
00516 {
00517    // Delete selection.
00518 
00519    if (!fIsMarked || fReadOnly) {
00520       return;
00521    }
00522 
00523    if (fMarkedStart.fX == fMarkedEnd.fX &&
00524        fMarkedStart.fY == fMarkedEnd.fY) {
00525       Long_t len = fText->GetLineLength(fCurrent.fY);
00526 
00527       if (fCurrent.fY == fText->RowCount()-1 && fCurrent.fX == len) {
00528          gVirtualX->Bell(0);
00529          return;
00530       }
00531 
00532       new TDelCharCom(this);
00533       return;
00534    }
00535 
00536    TGLongPosition pos, endPos;
00537    Bool_t delast = kFALSE;
00538 
00539    endPos.fX = fMarkedEnd.fX - 1;
00540    endPos.fY = fMarkedEnd.fY;
00541 
00542    if (endPos.fX == -1) {
00543       pos = fCurrent;
00544       if (endPos.fY > 0) {
00545          SetCurrent(endPos);
00546          DelChar();
00547          endPos.fY--;
00548          SetCurrent(pos);
00549       }
00550       endPos.fX = fText->GetLineLength(endPos.fY);
00551       if (endPos.fX < 0) {
00552          endPos.fX = 0;
00553       }
00554       delast = kTRUE;
00555    }
00556 
00557    // delete command for undo
00558    TDelTextCom *dcom = new TDelTextCom(this, fClipText);
00559    dcom->SetPos(fMarkedStart);
00560    dcom->SetEndPos(endPos);
00561 
00562    if (delast || ((fText->GetLineLength(endPos.fY) == endPos.fX+1) && 
00563        (fClipText->RowCount() > 1))) {
00564       TGLongPosition p = endPos;
00565 
00566       p.fY--;
00567       if (!delast) p.fX++;
00568       dcom->SetEndPos(p);
00569       dcom->SetBreakLine(kTRUE);
00570    }
00571 
00572    fText->DelText(fMarkedStart, endPos);
00573 
00574    pos.fY = ToObjYCoord(fVisible.fY);
00575 
00576    if (fMarkedStart.fY < pos.fY) {
00577       pos.fY = fMarkedStart.fY;
00578    }
00579    pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
00580    if (fMarkedStart.fX < pos.fX) {
00581       pos.fX = fMarkedStart.fX;
00582    }
00583 
00584    Int_t th = (Int_t)ToScrYCoord(fText->RowCount());
00585    Int_t ys = (Int_t)ToScrYCoord(fMarkedStart.fY);
00586    th = th < 0 ? 0 : th;
00587    ys = ys < 0 ? 0 : ys;
00588 
00589    // clear
00590    if ((th < 0) || (th < (Int_t)fCanvas->GetHeight())) {
00591       gVirtualX->ClearArea(fCanvas->GetId(), 0, ys,
00592                                fCanvas->GetWidth(), fCanvas->GetHeight() - ys);
00593    }
00594 
00595    UpdateRegion(0, ys, fCanvas->GetWidth(), UInt_t(fCanvas->GetHeight() - ys));
00596 
00597    SetVsbPosition((ToScrYCoord(pos.fY) + fVisible.fY)/fScrollVal.fY);
00598    SetHsbPosition((ToScrXCoord(pos.fX, pos.fY) + fVisible.fX)/fScrollVal.fX);
00599    SetSBRange(kHorizontal);
00600    SetSBRange(kVertical);
00601    SetCurrent(fMarkedStart);
00602 
00603    SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_ISMARKED), fWidgetId, kFALSE);
00604    UnMark();
00605 
00606    // only to make sure that IsSaved() returns true in case everything has
00607    // been deleted
00608    if (fText->RowCount() == 1 && fText->GetLineLength(0) == 0) {
00609       delete fText;
00610       fText = new TGText();
00611       fText->Clear();
00612    }
00613 }
00614 
00615 //______________________________________________________________________________
00616 Bool_t TGTextEdit::Search(const char *string, Bool_t direction,
00617                           Bool_t caseSensitive)
00618 {
00619    // Search for string in the specified direction. If direction is true
00620    // the search will be in forward direction.
00621 
00622    if (!IsMapped()) return kFALSE;
00623 
00624    if (gTQSender && (gTQSender == TGSearchDialog::SearchDialog())) {
00625       caseSensitive = TGSearchDialog::SearchDialog()->GetType()->fCaseSensitive;
00626       direction = TGSearchDialog::SearchDialog()->GetType()->fDirection;
00627       fSearch = TGSearchDialog::SearchDialog()->GetType();
00628    }
00629 
00630    TGLongPosition pos;
00631    if (!fText->Search(&pos, fCurrent, string, direction, caseSensitive)) {
00632       fCurrent.fX = 1;
00633       fCurrent.fY = 1;
00634 
00635       if (!fText->Search(&pos, fCurrent, string, direction, caseSensitive)) { //try again
00636          TString msg;
00637          msg.Form("Couldn't find \"%s\"", string);
00638          gVirtualX->Bell(20);
00639          new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "TextEdit",
00640                       msg.Data(), kMBIconExclamation, kMBOk, 0);
00641          return kFALSE;
00642       }
00643       return kTRUE;
00644    }
00645    UnMark();
00646    fIsMarked = kTRUE;
00647    fMarkedStart.fY = fMarkedEnd.fY = pos.fY;
00648    fMarkedStart.fX = pos.fX;
00649    fMarkedEnd.fX = fMarkedStart.fX + strlen(string);
00650 
00651    if (direction) {
00652       SetCurrent(fMarkedEnd);
00653    } else {
00654       SetCurrent(fMarkedStart);
00655    }
00656 
00657    pos.fY = ToObjYCoord(fVisible.fY);
00658    if (fCurrent.fY < pos.fY ||
00659        ToScrYCoord(fCurrent.fY) >= (Int_t)fCanvas->GetHeight()) {
00660       pos.fY = fMarkedStart.fY;
00661    }
00662    pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
00663 
00664    if (fCurrent.fX < pos.fX ||
00665        ToScrXCoord(fCurrent.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
00666       pos.fX = fMarkedStart.fX;
00667    }
00668 
00669    SetVsbPosition((ToScrYCoord(pos.fY)+fVisible.fY)/fScrollVal.fY);
00670    SetHsbPosition((ToScrXCoord(pos.fX, pos.fY)+fVisible.fX)/fScrollVal.fX);
00671 
00672    UpdateRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
00673                 UInt_t(ToScrYCoord(fMarkedEnd.fY+1)-ToScrYCoord(fMarkedEnd.fY)));
00674 
00675    return kTRUE;
00676 }
00677 
00678 //______________________________________________________________________________
00679 Bool_t TGTextEdit::Replace(TGLongPosition textPos, const char *oldText,
00680                            const char *newText, Bool_t direction, Bool_t caseSensitive)
00681 {
00682    // Replace text starting at textPos.
00683 
00684    TGLongPosition pos;
00685    if (!fText->Replace(textPos, oldText, newText, direction, caseSensitive)) {
00686       return kFALSE;
00687    }
00688    UnMark();
00689    fIsMarked = kTRUE;
00690    fMarkedStart.fY = fMarkedEnd.fY = textPos.fY;
00691    fMarkedStart.fX = textPos.fX;
00692    fMarkedEnd.fX = fMarkedStart.fX + strlen(newText);
00693 
00694    if (direction) {
00695       SetCurrent(fMarkedEnd);
00696    } else {
00697       SetCurrent(fMarkedStart);
00698    }
00699 
00700    pos.fY = ToObjYCoord(fVisible.fY);
00701    if (fCurrent.fY < pos.fY ||
00702        ToScrYCoord(fCurrent.fY) >= (Int_t)fCanvas->GetHeight()) {
00703       pos.fY = fMarkedStart.fY;
00704    }
00705    pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
00706    if (fCurrent.fX < pos.fX ||
00707        ToScrXCoord(fCurrent.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
00708       pos.fX = fMarkedStart.fX;
00709    }
00710 
00711    SetVsbPosition((ToScrYCoord(pos.fY)+fVisible.fY)/fScrollVal.fY);
00712    SetHsbPosition((ToScrXCoord(pos.fX, pos.fY)+fVisible.fX)/fScrollVal.fX);
00713 
00714    UpdateRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
00715                 UInt_t(ToScrYCoord(fMarkedEnd.fY+1)-ToScrYCoord(fMarkedEnd.fY)));
00716 
00717    return kTRUE;
00718 }
00719 
00720 //______________________________________________________________________________
00721 Bool_t TGTextEdit::Goto(Long_t line, Long_t column)
00722 {
00723    // Goto the specified line.
00724 
00725    if (line < 0)
00726       line = 0;
00727    if (line >= fText->RowCount())
00728       line = fText->RowCount() - 1;
00729    if (column < 0)
00730       column = 0;
00731    if (column > fText->GetLineLength(line))
00732       column = fText->GetLineLength(line);
00733 
00734    TGLongPosition gotopos, pos;
00735    gotopos.fY = line;
00736    gotopos.fX = column;
00737    SetCurrent(gotopos);
00738 
00739    pos.fY = ToObjYCoord(fVisible.fY);
00740    if (fCurrent.fY < pos.fY ||
00741        ToScrYCoord(fCurrent.fY) >= (Int_t)fCanvas->GetHeight())
00742       pos.fY = gotopos.fY;
00743 
00744    SetVsbPosition((ToScrYCoord(pos.fY)+fVisible.fY)/fScrollVal.fY);
00745    SetHsbPosition(0);
00746 
00747    UnMark();
00748    fIsMarked = kTRUE;
00749    fMarkedStart.fY = fMarkedEnd.fY = line;
00750    fMarkedStart.fX = 0;
00751    fMarkedEnd.fX = fCanvas->GetWidth();
00752 
00753    return kTRUE;
00754 }
00755 
00756 //______________________________________________________________________________
00757 void TGTextEdit::SetInsertMode(EInsertMode mode)
00758 {
00759    // Sets the mode how characters are entered.
00760 
00761    if (fInsertMode == mode) return;
00762 
00763    fInsertMode = mode;
00764 }
00765 
00766 //______________________________________________________________________________
00767 void TGTextEdit::CursorOff()
00768 {
00769    // If cursor if on, turn it off.
00770 
00771    if (fCursorState == 1) {
00772       DrawCursor(2);
00773    }
00774    fCursorState = 2;
00775 }
00776 
00777 //______________________________________________________________________________
00778 void TGTextEdit::CursorOn()
00779 {
00780    // Turn cursor on.
00781 
00782    DrawCursor(1);
00783    fCursorState = 1;
00784 
00785    if (fCurBlink) {
00786       fCurBlink->Reset();
00787    }
00788 }
00789 
00790 //______________________________________________________________________________
00791 void TGTextEdit::SetCurrent(TGLongPosition new_coord)
00792 {
00793    // Make the specified position the current position.
00794 
00795    CursorOff();
00796 
00797    fCurrent.fY = new_coord.fY;
00798    fCurrent.fX = new_coord.fX;
00799 
00800    CursorOn();
00801 
00802    SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_DATACHANGE), fWidgetId, 0);
00803    DataChanged();
00804 }
00805 
00806 //______________________________________________________________________________
00807 void TGTextEdit::DrawCursor(Int_t mode)
00808 {
00809    // Draw cursor. If mode = 1 draw cursor, if mode = 2 erase cursor.
00810 
00811    char count = -1;
00812    char cursor = ' ';
00813    if (fCurrent.fY >= fText->RowCount() || fCurrent.fX > fText->GetLineLength(fCurrent.fY) || fReadOnly) {
00814       return;
00815    }
00816 
00817    if (fCurrent.fY >= ToObjYCoord(fVisible.fY) &&
00818        fCurrent.fY <= ToObjYCoord(fVisible.fY+fCanvas->GetHeight()) &&
00819        fCurrent.fX >= ToObjXCoord(fVisible.fX, fCurrent.fY) &&
00820        fCurrent.fX <= ToObjXCoord(fVisible.fX+fCanvas->GetWidth(),fCurrent.fY)) {
00821       if (fCurrent.fY < fText->RowCount()) {
00822          count = fText->GetChar(fCurrent);
00823       }
00824       if (count == -1 || count == '\t') {
00825          cursor = ' ';
00826       } else {
00827          cursor = count;
00828       }
00829 
00830       if (mode == 2) {
00831          if (fIsMarked && count != -1) {
00832             if ((fCurrent.fY > fMarkedStart.fY && fCurrent.fY < fMarkedEnd.fY) ||
00833                 (fCurrent.fY == fMarkedStart.fY && fCurrent.fX >= fMarkedStart.fX &&
00834                  fCurrent.fY < fMarkedEnd.fY) ||
00835                 (fCurrent.fY == fMarkedEnd.fY && fCurrent.fX < fMarkedEnd.fX &&
00836                  fCurrent.fY > fMarkedStart.fY) ||
00837                 (fCurrent.fY == fMarkedStart.fY && fCurrent.fY == fMarkedEnd.fY &&
00838                  fCurrent.fX >= fMarkedStart.fX && fCurrent.fX < fMarkedEnd.fX &&
00839                  fMarkedStart.fX != fMarkedEnd.fX)) {
00840                // back ground fillrectangle
00841                gVirtualX->FillRectangle(fCanvas->GetId(), fSelbackGC(),
00842                                      Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00843                                      Int_t(ToScrYCoord(fCurrent.fY)),
00844                                      UInt_t(ToScrXCoord(fCurrent.fX+1, fCurrent.fY) -
00845                                      ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00846                                      UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)));
00847                if (count != -1)
00848                   gVirtualX->DrawString(fCanvas->GetId(), fSelGC(), (Int_t)ToScrXCoord(fCurrent.fX,fCurrent.fY),
00849                        Int_t(ToScrYCoord(fCurrent.fY+1) - fMaxDescent), &cursor, 1);
00850             } else {
00851                gVirtualX->ClearArea(fCanvas->GetId(),
00852                                     Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00853                                     Int_t(ToScrYCoord(fCurrent.fY)),
00854                                     UInt_t(ToScrXCoord(fCurrent.fX+1, fCurrent.fY) -
00855                                     ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00856                                     UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)));
00857                if (count != -1)
00858                   gVirtualX->DrawString(fCanvas->GetId(), fNormGC(), (Int_t)ToScrXCoord(fCurrent.fX,fCurrent.fY),
00859                        Int_t(ToScrYCoord(fCurrent.fY+1) - fMaxDescent), &cursor, 1);
00860             }
00861          } else {
00862             gVirtualX->ClearArea(fCanvas->GetId(),
00863                                  Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00864                                  Int_t(ToScrYCoord(fCurrent.fY)),
00865                                  UInt_t(ToScrXCoord(fCurrent.fX+1, fCurrent.fY) -
00866                                  ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00867                                  UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)));
00868             gVirtualX->DrawString(fCanvas->GetId(), fNormGC(), (Int_t)ToScrXCoord(fCurrent.fX,fCurrent.fY),
00869                        Int_t(ToScrYCoord(fCurrent.fY+1) - fMaxDescent), &cursor, 1);
00870          }
00871       } else {
00872          if (mode == 1) {
00873             gVirtualX->FillRectangle(fCanvas->GetId(), fCursor1GC,
00874                                      Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
00875                                      Int_t(ToScrYCoord(fCurrent.fY)),
00876                                      2,
00877                                      UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)));
00878          }
00879       }
00880    }
00881 }
00882 
00883 //______________________________________________________________________________
00884 void TGTextEdit::AdjustPos()
00885 {
00886    // Adjust current position.
00887 
00888    TGLongPosition pos;
00889    pos.fY = fCurrent.fY;
00890    pos.fX = fCurrent.fX;
00891 
00892    if (pos.fY < ToObjYCoord(fVisible.fY)) {
00893       pos.fY = ToObjYCoord(fVisible.fY);
00894    } else if (ToScrYCoord(pos.fY+1) >= (Int_t) fCanvas->GetHeight()) {
00895       pos.fY = ToObjYCoord(fVisible.fY + fCanvas->GetHeight())-1;
00896    }
00897    if (pos.fX < ToObjXCoord(fVisible.fX, pos.fY)) {
00898       pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
00899    } else if (ToScrXCoord(pos.fX, pos.fY) >= (Int_t) fCanvas->GetWidth()) {
00900       pos.fX = ToObjXCoord(fVisible.fX + fCanvas->GetWidth(), pos.fY)-1;
00901    }
00902    if (pos.fY != fCurrent.fY || pos.fX != fCurrent.fX) {
00903       SetCurrent(pos);
00904    }
00905 }
00906 
00907 //______________________________________________________________________________
00908 Bool_t TGTextEdit::HandleTimer(TTimer *t)
00909 {
00910    // Handle timer cursor blink timer.
00911 
00912    if (t != fCurBlink) {
00913       TGTextView::HandleTimer(t);
00914       return kTRUE;
00915    }
00916 
00917    if (fCursorState == 1) {
00918       fCursorState = 2;
00919    } else {
00920       fCursorState = 1;
00921    }
00922 
00923    DrawCursor(fCursorState);
00924 
00925    return kTRUE;
00926 }
00927 
00928 //______________________________________________________________________________
00929 Bool_t TGTextEdit::HandleSelection(Event_t *event)
00930 {
00931    // Handle selection notify event.
00932 
00933    TString data;
00934    Int_t   nchar;
00935 
00936    gVirtualX->GetPasteBuffer((Window_t)event->fUser[0], (Atom_t)event->fUser[3],
00937                              data, nchar, kFALSE);
00938 
00939    if (!nchar) return kTRUE;
00940 
00941    delete fClipText;
00942 
00943    fClipText = new TGText;
00944    fClipText->LoadBuffer(data.Data());
00945 
00946    TGLongPosition start_src, end_src, pos;
00947 
00948    pos.fX = pos.fY = 0;
00949    start_src.fY = start_src.fX = 0;
00950    end_src.fY = fClipText->RowCount()-1;
00951    end_src.fX = fClipText->GetLineLength(end_src.fY)-1;
00952 
00953    if (end_src.fX < 0) {
00954       end_src.fX = 0;
00955    }
00956 
00957    // undo command
00958    TInsTextCom *icom = new TInsTextCom(this);
00959    icom->fChar = fText->GetChar(fCurrent);
00960    fText->InsText(fCurrent, fClipText, start_src, end_src);
00961 
00962    fIsMarked = kFALSE;
00963 
00964    fExposedRegion.fX = 0;
00965    fExposedRegion.fY = ToScrYCoord(fCurrent.fY);
00966 
00967    pos.fY = fCurrent.fY + fClipText->RowCount()-1;
00968    pos.fX = fClipText->GetLineLength(fClipText->RowCount()-1);
00969 
00970    if (start_src.fY == end_src.fY) {
00971       pos.fX = pos.fX + fCurrent.fX;
00972    }
00973 
00974    icom->SetEndPos(pos);
00975 
00976    // calculate exposed region
00977    fExposedRegion.fW = fCanvas->GetWidth();
00978    fExposedRegion.fH = fCanvas->GetHeight() - fExposedRegion.fY;
00979 
00980    SetCurrent(pos);
00981 
00982    if (ToScrYCoord(pos.fY) >= (Int_t)fCanvas->GetHeight()) {
00983       pos.fY = ToScrYCoord(pos.fY) + fVisible.fY - fCanvas->GetHeight()/2;
00984       fExposedRegion.fX = fExposedRegion.fY = 0;
00985       fExposedRegion.fH = fCanvas->GetHeight();
00986    } else {
00987       pos.fY = fVisible.fY;
00988    }
00989    if (ToScrXCoord(pos.fX, fCurrent.fY) >= (Int_t) fCanvas->GetWidth()) {
00990       pos.fX = ToScrXCoord(pos.fX, fCurrent.fY) + fVisible.fX + fCanvas->GetWidth()/2;
00991    } else if (ToScrXCoord(pos.fX, fCurrent.fY < 0) && pos.fX != 0) {
00992       if (fVisible.fX - (Int_t)fCanvas->GetWidth()/2 > 0) {
00993          pos.fX = fVisible.fX - fCanvas->GetWidth()/2;
00994       } else {
00995          pos.fX = 0;
00996       }
00997    } else {
00998       pos.fX = fVisible.fX;
00999    }
01000 
01001    SetSBRange(kHorizontal);
01002    SetSBRange(kVertical);
01003    SetVsbPosition(pos.fY/fScrollVal.fY);
01004    SetHsbPosition(pos.fX/fScrollVal.fX);
01005 
01006    fClient->NeedRedraw(this);
01007 
01008    return kTRUE;
01009 }
01010 
01011 static Bool_t gDbl_clk = kFALSE;
01012 static Bool_t gTrpl_clk = kFALSE;
01013 
01014 //______________________________________________________________________________
01015 Bool_t TGTextEdit::HandleButton(Event_t *event)
01016 {
01017    // Handle mouse button event in text edit widget.
01018 
01019    if (event->fWindow != fCanvas->GetId()) {
01020       return kFALSE;
01021    }
01022 
01023    TGLongPosition pos;
01024 
01025    TGTextView::HandleButton(event);
01026 
01027    if (event->fType == kButtonPress) {
01028       SetFocus();
01029       //Update();
01030 
01031       if (event->fCode == kButton1 || event->fCode == kButton2) {
01032          pos.fY = ToObjYCoord(fVisible.fY + event->fY);
01033          if (pos.fY >= fText->RowCount()) {
01034             pos.fY = fText->RowCount()-1;
01035          }
01036          pos.fX = ToObjXCoord(fVisible.fX+event->fX, pos.fY);
01037          if (pos.fX >= fText->GetLineLength(pos.fY)) {
01038             pos.fX = fText->GetLineLength(pos.fY);
01039          }
01040          while (fText->GetChar(pos) == 16) {
01041             pos.fX++;
01042          }
01043 
01044          SetCurrent(pos);
01045 
01046          TGTextLine *line = fText->GetCurrentLine();
01047          char *word = line->GetWord(pos.fX);
01048          Clicked((const char*)word);   // emit signal
01049          delete [] word;
01050       }
01051       if (event->fCode == kButton2) {
01052          if (gVirtualX->GetPrimarySelectionOwner() != kNone) {
01053             gVirtualX->ConvertPrimarySelection(fId, fClipboard, event->fTime);
01054             Update();
01055             return kTRUE;
01056          }
01057       }
01058       if (event->fCode == kButton3) {
01059          // do not handle during guibuilding
01060          if (fClient->IsEditable() || !fEnableMenu) {
01061             return kTRUE;
01062          }
01063          SetMenuState();
01064          fMenu->PlaceMenu(event->fXRoot, event->fYRoot, kFALSE, kTRUE);
01065       }
01066       gDbl_clk = kFALSE;
01067       gTrpl_clk = kFALSE;
01068    }
01069 
01070    return kTRUE;
01071 }
01072 
01073 //______________________________________________________________________________
01074 Bool_t TGTextEdit::HandleDoubleClick(Event_t *event)
01075 {
01076    // Handle double click event.
01077 
01078    if (event->fWindow != fCanvas->GetId()) {
01079       return kFALSE;
01080    }
01081 
01082    if (event->fCode != kButton1) {
01083       return kFALSE;
01084    } 
01085    if (!fText->GetCurrentLine()->GetText()) {// empty line
01086       return kFALSE;
01087    }
01088 
01089    SetFocus();
01090    TGLongPosition pos;
01091    pos.fY = ToObjYCoord(fVisible.fY + event->fY);
01092 
01093    if (gDbl_clk && (event->fTime - fgLastClick < 350)) { // triple click
01094       fgLastClick  = event->fTime;
01095       gDbl_clk = kFALSE;
01096       gTrpl_clk = kTRUE;
01097       fMarkedStart.fY = fMarkedEnd.fY = pos.fY;
01098       fIsMarked = kTRUE;
01099       fMarkedStart.fX = 0;
01100       fMarkedEnd.fX = strlen(fText->GetCurrentLine()->GetText());
01101       Marked(kTRUE);
01102       UpdateRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
01103                  UInt_t(ToScrYCoord(fMarkedEnd.fY + 1) - ToScrYCoord(fMarkedStart.fY)));
01104       return kTRUE;
01105    }
01106 
01107    if (gTrpl_clk && (event->fTime - fgLastClick < 350)) { // 4 click
01108       fgLastClick  = event->fTime;
01109       gTrpl_clk = kFALSE;
01110       fIsMarked = kTRUE;
01111       fMarkedStart.fY = 0;
01112       fMarkedStart.fX = 0;
01113       fMarkedEnd.fY = fText->RowCount()-1;
01114       fMarkedEnd.fX = fText->GetLineLength(fMarkedEnd.fY);
01115       if (fMarkedEnd.fX < 0) {
01116          fMarkedEnd.fX = 0;
01117       }
01118       UpdateRegion(0, 0, fCanvas->GetWidth(), fCanvas->GetHeight());
01119       return kTRUE;
01120    }
01121 
01122    gDbl_clk = kTRUE;
01123    gTrpl_clk = kFALSE;
01124 
01125    if (pos.fY >= fText->RowCount()) {
01126       pos.fY = fText->RowCount() - 1;
01127    }
01128    pos.fX = ToObjXCoord(fVisible.fX + event->fX, pos.fY);
01129   
01130    if (pos.fX >= fText->GetLineLength(pos.fY)) {
01131       pos.fX = fText->GetLineLength(pos.fY);
01132    }
01133    while (fText->GetChar(pos) == 16) {
01134       pos.fX++;
01135    }
01136 
01137    SetCurrent(pos);
01138 
01139    fMarkedStart.fY = fMarkedEnd.fY = pos.fY;
01140    char *line = fText->GetCurrentLine()->GetText();
01141    UInt_t len = (UInt_t)fText->GetCurrentLine()->GetLineLength();
01142    Int_t start = pos.fX;
01143    Int_t end = pos.fX;
01144    Int_t i = pos.fX;
01145 
01146    if (line[i] == ' ' || line[i] == '\t') {
01147       while (start >= 0) {
01148          if (line[start] == ' ' || line[start] == '\t') --start;
01149          else break;
01150       }
01151       ++start;
01152       while (end < (Int_t)len) {
01153          if (line[end] == ' ' || line[end] == '\t') ++end;
01154          else break;
01155       }
01156    } else if (isalnum(line[i])) {
01157       while (start >= 0) {
01158          if (isalnum(line[start])) --start;
01159          else break;
01160       }
01161       ++start;
01162       while (end < (Int_t)len) {
01163          if (isalnum(line[end])) ++end;
01164          else break;
01165       }
01166    } else {
01167       while (start >= 0) {
01168          if (isalnum(line[start]) || line[start] == ' ' || line[start] == '\t') {
01169             break;
01170          } else {
01171             --start;
01172          }
01173       }
01174       ++start;
01175       while (end < (Int_t)len) {
01176          if (isalnum(line[end]) || line[end] == ' ' || line[end] == '\t') {
01177             break;
01178          } else {
01179             ++end;
01180          }
01181       }
01182    }
01183 
01184    fMarkedStart.fX = start;
01185    fIsMarked = kTRUE;
01186    fMarkedEnd.fX = end;
01187    Marked(kTRUE);
01188 
01189    len = end - start; //length
01190    char *word = new char[len + 1];
01191    word[len] = '\0';
01192    strncpy(word, line+start, (UInt_t)len);
01193    DoubleClicked((const char *)word);  // emit signal
01194 
01195    delete [] word;
01196 //   delete [] line;
01197 
01198    UpdateRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
01199                 UInt_t(ToScrYCoord(fMarkedEnd.fY + 1) - ToScrYCoord(fMarkedStart.fY)));
01200 
01201    return kTRUE;
01202 }
01203 
01204 //______________________________________________________________________________
01205 Bool_t TGTextEdit::HandleMotion(Event_t *event)
01206 {
01207    // Handle mouse motion event in text edit widget.
01208 
01209    TGLongPosition pos;
01210    if (event->fWindow != fCanvas->GetId()) {
01211       return kTRUE;
01212    }
01213 
01214    if (fScrolling == -1) {
01215       pos.fY = ToObjYCoord(fVisible.fY+event->fY);
01216       if (pos.fY >= fText->RowCount()) {
01217          pos.fY = fText->RowCount()-1;
01218       }
01219       pos.fX = ToObjXCoord(fVisible.fX+event->fX, pos.fY);
01220       if (pos.fX > fText->GetLineLength(pos.fY)) {
01221          pos.fX = fText->GetLineLength(pos.fY);
01222       }
01223       if (fText->GetChar(pos) == 16) {
01224          if (pos.fX < fCurrent.fX) {
01225             pos.fX = fCurrent.fX;
01226          }
01227          if (pos.fX > fCurrent.fX) {
01228             do {
01229                pos.fX++;
01230             } while (fText->GetChar(pos) == 16);
01231          }
01232       }
01233       event->fY = (Int_t)ToScrYCoord(pos.fY);
01234       event->fX = (Int_t)ToScrXCoord(pos.fX, pos.fY);
01235       if (pos.fY != fCurrent.fY || pos.fX != fCurrent.fX) {
01236          TGTextView::HandleMotion(event);
01237          SetCurrent(pos);
01238       }
01239    }
01240    return kTRUE;
01241 }
01242 
01243 //______________________________________________________________________________
01244 Bool_t TGTextEdit::HandleKey(Event_t *event)
01245 {
01246    // The key press event handler converts a key press to some line editor
01247    // action.
01248 
01249    Bool_t mark_ok = kFALSE;
01250    char   input[10];
01251    Int_t  n;
01252    UInt_t keysym;
01253 
01254    if (event->fType == kGKeyPress) {
01255       gVirtualX->LookupString(event, input, sizeof(input), keysym);
01256       n = strlen(input);
01257 
01258       AdjustPos();
01259 
01260       switch ((EKeySym)keysym) {   // ignore these keys
01261          case kKey_Shift:
01262          case kKey_Control:
01263          case kKey_Meta:
01264          case kKey_Alt:
01265          case kKey_CapsLock:
01266          case kKey_NumLock:
01267          case kKey_ScrollLock:
01268             return kTRUE;
01269          default:
01270             break;
01271       }
01272       if (event->fState & kKeyControlMask) {   // Cntrl key modifier pressed
01273          switch((EKeySym)keysym & ~0x20) {   // treat upper and lower the same
01274             case kKey_A:
01275                SelectAll();
01276                return kTRUE;
01277             case kKey_B:
01278                mark_ok = kTRUE;
01279                PrevChar();
01280                break;
01281             case kKey_C:
01282                Copy();
01283                return kTRUE;
01284             case kKey_D:
01285                if (fIsMarked) {
01286                   Cut();
01287                } else {
01288                   Long_t len = fText->GetLineLength(fCurrent.fY);
01289                   if (fCurrent.fY == fText->RowCount()-1 && fCurrent.fX == len) {
01290                      gVirtualX->Bell(0);
01291                      return kTRUE;
01292                   }
01293                   NextChar();
01294                   new TDelCharCom(this);
01295                }
01296                break;
01297             case kKey_E:
01298                mark_ok = kTRUE;
01299                End();
01300                break;
01301             case kKey_H:
01302                if (fCurrent.fX || fCurrent.fY) new TDelCharCom(this);
01303                else gVirtualX->Bell(0);
01304                break;
01305             case kKey_K:
01306                End();
01307                fIsMarked = kTRUE;
01308                Mark(fCurrent.fX, fCurrent.fY);
01309                Cut();
01310                break;
01311             case kKey_U:
01312                Home();
01313                UnMark();
01314                fMarkedStart.fY = fMarkedEnd.fY = fCurrent.fY;
01315                fMarkedStart.fX = fMarkedEnd.fX = fCurrent.fX;
01316                End();
01317                fIsMarked = kTRUE;
01318                Mark(fCurrent.fX, fCurrent.fY);
01319                Cut();
01320                break;
01321             case kKey_V:
01322             case kKey_Y:
01323                Paste();
01324                return kTRUE;
01325             case kKey_X:
01326                Cut();
01327                return kTRUE;
01328             case kKey_Z:
01329                fHistory->Notify();  // undo action
01330                return kTRUE;
01331             case kKey_F:
01332                Search(kFALSE);
01333                return kTRUE;
01334             case kKey_L:
01335             {   
01336                Long_t ret = fCurrent.fY+1;
01337                new TGGotoDialog(fClient->GetDefaultRoot(), this, 400, 150, &ret);
01338                if (ret > -1) {
01339                   ret--;   // user specifies lines starting at 1
01340                   Goto(ret);
01341                }
01342                return kTRUE;
01343             }
01344             case kKey_Home:
01345                {
01346                   TGLongPosition pos;
01347                   pos.fY = 0;
01348                   pos.fX = 0;
01349                   SetHsbPosition(0);
01350                   SetVsbPosition(0);
01351                   SetCurrent(pos);
01352                }
01353                break;
01354             case kKey_End:
01355                {
01356                   TGLongPosition pos;
01357                   pos.fY = fText->RowCount()-1;
01358                   pos.fX = fText->GetLineLength(pos.fY);
01359                   if (fVsb && fVsb->IsMapped())
01360                      SetVsbPosition((ToScrYCoord(pos.fY)+fVisible.fY)/fScrollVal.fY);
01361                   SetCurrent(pos);
01362                }
01363                break;
01364             default:
01365                return kTRUE;
01366          }
01367       }
01368       if (n && keysym >= 32 && keysym < 127 &&     // printable keys
01369           !(event->fState & kKeyControlMask) &&
01370           (EKeySym)keysym != kKey_Delete &&
01371           (EKeySym)keysym != kKey_Backspace) {
01372 
01373          if (fIsMarked) {
01374             Cut();
01375          }
01376          new TInsCharCom(this, input[0]);
01377 
01378       } else {
01379 
01380          switch ((EKeySym)keysym) {
01381             case kKey_F3:
01382                // typically FindAgain action
01383                SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_F3), fWidgetId,
01384                            kTRUE);
01385                SetMenuState();
01386                if (fMenu->IsEntryEnabled(kM_SEARCH_FINDAGAIN)) {
01387                   SendMessage(this, MK_MSG(kC_COMMAND, kCM_MENU),
01388                               kM_SEARCH_FINDAGAIN, 0);
01389                   FindAgain();
01390                }
01391                break;
01392             case kKey_Delete:
01393                if (fIsMarked) {
01394                   Cut();
01395                } else {
01396                   Long_t len = fText->GetLineLength(fCurrent.fY);
01397                   if (fCurrent.fY == fText->RowCount()-1 && fCurrent.fX == len) {
01398                      gVirtualX->Bell(0);
01399                      return kTRUE;
01400                   }
01401                   NextChar();
01402                   new TDelCharCom(this);
01403                }
01404                break;
01405             case kKey_Return:
01406             case kKey_Enter:
01407                new TBreakLineCom(this);
01408                break;
01409             case kKey_Tab:
01410                new TInsCharCom(this, '\t');
01411                break;
01412             case kKey_Backspace:
01413                if (fIsMarked) {
01414                   Cut();
01415                } else {
01416                   if (fCurrent.fX || fCurrent.fY) {
01417                      new TDelCharCom(this);
01418                   } else {
01419                      gVirtualX->Bell(0);
01420                   }
01421                }
01422                break;
01423             case kKey_Left:
01424                mark_ok = kTRUE;
01425                PrevChar();
01426                break;
01427             case kKey_Right:
01428                mark_ok = kTRUE;
01429                NextChar();
01430                break;
01431             case kKey_Up:
01432                mark_ok = kTRUE;
01433                LineUp();
01434                break;
01435             case kKey_Down:
01436                mark_ok = kTRUE;
01437                LineDown();
01438                break;
01439             case kKey_PageUp:
01440                mark_ok = kTRUE;
01441                ScreenUp();
01442                break;
01443             case kKey_PageDown:
01444                mark_ok = kTRUE;
01445                ScreenDown();
01446                break;
01447             case kKey_Home:
01448                mark_ok = kTRUE;
01449                Home();
01450                break;
01451             case kKey_End:
01452                mark_ok = kTRUE;
01453                End();
01454                break;
01455             case kKey_Insert:           // switch on/off insert mode
01456                SetInsertMode(GetInsertMode() == kInsert ? kReplace : kInsert);
01457                break;
01458             default:
01459                break;
01460          }
01461       }
01462       if ((event->fState & kKeyShiftMask) && mark_ok) {
01463          fIsMarked = kTRUE;
01464          Mark(fCurrent.fX, fCurrent.fY);
01465          Copy();
01466          SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_ISMARKED), fWidgetId,
01467                      kTRUE);
01468          Marked(kTRUE);
01469       } else {
01470          UnMark();
01471          SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_ISMARKED),
01472                         fWidgetId, kFALSE);
01473          fMarkedStart.fY = fMarkedEnd.fY = fCurrent.fY;
01474          fMarkedStart.fX = fMarkedEnd.fX = fCurrent.fX;
01475       }
01476    }
01477    return kTRUE;
01478 }
01479 
01480 //______________________________________________________________________________
01481 Bool_t TGTextEdit::HandleCrossing(Event_t *event)
01482 {
01483    // Handle mouse crossing event.
01484 
01485    if (event->fWindow != fCanvas->GetId()) {
01486       return kTRUE;
01487    }
01488    if (gVirtualX->GetInputFocus() != fCanvas->GetId()) {
01489       if (event->fType == kEnterNotify) {
01490          if (!fCurBlink) {
01491             fCurBlink = new TViewTimer(this, 500);
01492          }
01493          fCurBlink->Reset();
01494          gSystem->AddTimer(fCurBlink);
01495       } else {
01496          if (fCurBlink) fCurBlink->Remove();
01497          if (!fEnableCursorWithoutFocus && (fCursorState == 1)) {
01498             DrawCursor(2);
01499             fCursorState = 2;
01500          } else if (fCursorState == 2) {
01501             DrawCursor(1);
01502             fCursorState = 1;
01503          }
01504       }
01505    }
01506 
01507    TGTextView::HandleCrossing(event);
01508 
01509    return kTRUE;
01510 }
01511 
01512 //______________________________________________________________________________
01513 Bool_t TGTextEdit::HandleFocusChange(Event_t *event)
01514 {
01515    // Handle focus change event in text edit widget.
01516 
01517    if (event->fWindow != fCanvas->GetId()) {
01518       return kTRUE;
01519    }
01520 
01521    // check this when porting to Win32
01522    if ((event->fCode == kNotifyNormal) && (event->fState != kNotifyPointer)) {
01523       if (event->fType == kFocusIn) {
01524          if (!fCurBlink) {
01525             fCurBlink = new TViewTimer(this, 500);
01526          }
01527          fCurBlink->Reset();
01528          gSystem->AddTimer(fCurBlink);
01529       } else {
01530          if (fCurBlink) fCurBlink->Remove();
01531          if (fCursorState == 2) {
01532             DrawCursor(1);
01533             fCursorState = 1;
01534          }
01535       }
01536       fClient->NeedRedraw(this);
01537    }
01538    return kTRUE;
01539 }
01540 
01541 //______________________________________________________________________________
01542 void TGTextEdit::Search(Bool_t close)
01543 {
01544    // Invokes search dialog.
01545 
01546    static TGSearchType *srch = 0;
01547    Int_t ret = 0;
01548    
01549    if (!srch) srch = new TGSearchType;
01550    srch->fClose = close;
01551 
01552    if (!close) {
01553       if (!TGSearchDialog::SearchDialog()) {
01554          TGSearchDialog::SearchDialog() = new TGSearchDialog(fClient->GetDefaultRoot(),
01555                                                         fCanvas, 400, 150, srch, &ret);
01556       }
01557       TGSearchDialog::SearchDialog()->Connect("TextEntered(char *)", "TGTextEdit", 
01558                                           this, "Search(char *,Bool_t,Bool_t)");
01559       TGSearchDialog::SearchDialog()->MapRaised();
01560    } else {
01561       new TGSearchDialog(fClient->GetDefaultRoot(), fCanvas, 400, 150, srch, &ret);
01562       if (ret) {
01563          Search(srch->fBuffer);
01564       }
01565    }
01566 }
01567 
01568 //______________________________________________________________________________
01569 Bool_t TGTextEdit::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
01570 {
01571    // Process context menu messages.
01572 
01573    TString msg2;
01574    TGTextView::ProcessMessage(msg, parm1, parm2);
01575 
01576    switch(GET_MSG(msg)) {
01577       case kC_COMMAND:
01578          switch(GET_SUBMSG(msg)) {
01579             case kCM_MENU:
01580                switch (parm1) {
01581                   case kM_FILE_NEW:
01582                   case kM_FILE_CLOSE:
01583                   case kM_FILE_OPEN:
01584                      if (!IsSaved()) {
01585                         Int_t retval;
01586                         Bool_t untitled = !strlen(fText->GetFileName()) ? kTRUE : kFALSE;
01587 
01588                         msg2.Form("Save \"%s\"?",
01589                                   untitled ? "Untitled" : fText->GetFileName());
01590                         new TGMsgBox(fClient->GetDefaultRoot(), this, "Editor", 
01591                                      msg2.Data(), kMBIconExclamation, 
01592                                      kMBYes | kMBNo | kMBCancel, &retval);
01593 
01594                         if (retval == kMBCancel)
01595                            return kTRUE;
01596                         if (retval == kMBYes)
01597                            if (!SaveFile(0))
01598                               return kTRUE;
01599                      }
01600                      Clear();
01601                      if (parm1 == kM_FILE_CLOSE) {
01602                         SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_CLOSE),
01603                                     fWidgetId, 0);
01604                         Closed();
01605                      }
01606                      if (parm1 == kM_FILE_OPEN) {
01607                         TGFileInfo fi;
01608                         fi.fFileTypes = gFiletypes;
01609                         new TGFileDialog(fClient->GetDefaultRoot(), this, kFDOpen, &fi);
01610                         if (fi.fFilename && strlen(fi.fFilename)) {
01611                            LoadFile(fi.fFilename);
01612                            SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_OPEN),
01613                                        fWidgetId, 0);
01614                            Opened();
01615                         }
01616                      }
01617                      break;
01618                   case kM_FILE_SAVE:
01619                      if (SaveFile(0)) {
01620                         SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_SAVE),
01621                                     fWidgetId, 0);
01622                         Saved();
01623                      }
01624                      break;
01625                   case kM_FILE_SAVEAS:
01626                      if (SaveFile(0, kTRUE)) {
01627                         SendMessage(fMsgWindow, MK_MSG(kC_TEXTVIEW, kTXT_SAVE),
01628                                     fWidgetId, 0);
01629                         SavedAs();
01630                      }
01631                      break;
01632                   case kM_FILE_PRINT:
01633                      {
01634                         Int_t ret = 0;
01635                         if (!gPrinter) {
01636                            gPrinter = StrDup("892_2_cor"); // use gEnv
01637                            gPrintCommand = StrDup("xprint");
01638                         }
01639                         new TGPrintDialog(fClient->GetDefaultRoot(), this, 400, 150,
01640                                           &gPrinter, &gPrintCommand, &ret);
01641                         if (ret)
01642                            Print();
01643                      }
01644                      break;
01645                   case kM_EDIT_CUT:
01646                      Cut();
01647                      break;
01648                   case kM_EDIT_COPY:
01649                      Copy();
01650                      break;
01651                   case kM_EDIT_PASTE:
01652                      Paste();
01653                      break;
01654                   case kM_EDIT_SELECTALL:
01655                      SelectAll();
01656                      break;
01657                   case kM_SEARCH_FIND:
01658                      {
01659                         Search(kFALSE);
01660                      }
01661                      break;
01662                   case kM_SEARCH_FINDAGAIN:
01663                      if (!fSearch) {
01664                         SendMessage(this, MK_MSG(kC_COMMAND, kCM_MENU),
01665                                     kM_SEARCH_FIND, 0);
01666                         return kTRUE;
01667                      }
01668                      if (!Search(fSearch->fBuffer, fSearch->fDirection,
01669                                  fSearch->fCaseSensitive)) {
01670                         msg2.Form("Couldn't find \"%s\"", fSearch->fBuffer);
01671                         new TGMsgBox(fClient->GetDefaultRoot(), this, "Editor", 
01672                                      msg2.Data(), kMBIconExclamation, kMBOk, 0);
01673                      }
01674                      break;
01675                   case kM_SEARCH_GOTO:
01676                      {
01677                         Long_t ret = fCurrent.fY+1;
01678                         new TGGotoDialog(fClient->GetDefaultRoot(), this, 400, 150, &ret);
01679                         if (ret > -1) {
01680                            ret--;   // user specifies lines starting at 1
01681                            Goto(ret);
01682                         }
01683                      }
01684                      break;
01685                   default:
01686                      printf("No action implemented for menu id %ld\n", parm1);
01687                      break;
01688                }
01689             default:
01690                break;
01691          }
01692          break;
01693 
01694       default:
01695          break;
01696    }
01697    return kTRUE;
01698 }
01699 
01700 //______________________________________________________________________________
01701 void TGTextEdit::InsChar(char character)
01702 {
01703    // Insert a character in the text edit widget.
01704 
01705    if (fReadOnly) return;
01706 
01707    char *charstring = 0;
01708    TGLongPosition pos;
01709 
01710    if (character == '\t') {
01711       pos.fX = fCurrent.fX;
01712       pos.fY = fCurrent.fY;
01713       fText->InsChar(pos, '\t');
01714       pos.fX++;
01715       while (pos.fX & 0x7) {
01716          pos.fX++;
01717       }
01718       fText->ReTab(pos.fY);
01719       UpdateRegion(0, (Int_t)ToScrYCoord(pos.fY), fCanvas->GetWidth(),
01720                    UInt_t(ToScrYCoord(pos.fY+1) - ToScrYCoord(pos.fY)));
01721       SetSBRange(kHorizontal);
01722       if (ToScrXCoord(pos.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
01723          if (pos.fX != fText->GetLineLength(fCurrent.fY)) {
01724             SetHsbPosition((fVisible.fX+fCanvas->GetWidth()/2)/fScrollVal.fX);
01725          } else {
01726             SetHsbPosition(fVisible.fX/fScrollVal.fX);
01727          }
01728       }
01729       SetCurrent(pos);
01730       return;
01731    } else {
01732       if (fInsertMode == kReplace) {
01733          fCurrent.fX++;
01734          new TDelCharCom(this);
01735       }
01736       fText->InsChar(fCurrent, character);
01737       pos.fX = fCurrent.fX + 1;
01738       pos.fY = fCurrent.fY;
01739       charstring = new char[2];
01740       charstring[1] = '\0';
01741       charstring[0] = character;
01742    }
01743    SetSBRange(kHorizontal);
01744    if (ToScrXCoord(pos.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
01745       if (pos.fX != fText->GetLineLength(fCurrent.fY)) {
01746          SetHsbPosition((fVisible.fX+fCanvas->GetWidth()/2)/fScrollVal.fX);
01747       } else {
01748          SetHsbPosition(fVisible.fX/fScrollVal.fX+strlen(charstring));
01749       }
01750       if (!fHsb)
01751          gVirtualX->DrawString(fCanvas->GetId(), fNormGC(),
01752                                (Int_t)ToScrXCoord(fCurrent.fX, fCurrent.fY),
01753                                Int_t(ToScrYCoord(fCurrent.fY+1) - fMaxDescent),
01754                                charstring, strlen(charstring));
01755    } else {
01756       gVirtualX->CopyArea(fCanvas->GetId(), fCanvas->GetId(), fNormGC(),
01757                           (Int_t)ToScrXCoord(fCurrent.fX, fCurrent.fY),
01758                           (Int_t)ToScrYCoord(fCurrent.fY), fCanvas->GetWidth(),
01759                           UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)),
01760                           (Int_t)ToScrXCoord(pos.fX, fCurrent.fY),
01761                           (Int_t)ToScrYCoord(fCurrent.fY));
01762       gVirtualX->ClearArea(fCanvas->GetId(),
01763                            Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
01764                            Int_t(ToScrYCoord(fCurrent.fY)),
01765                            UInt_t(ToScrXCoord(fCurrent.fX+strlen(charstring), fCurrent.fY) -
01766                            ToScrXCoord(fCurrent.fX, fCurrent.fY)),
01767                            UInt_t(ToScrYCoord(fCurrent.fY+1)-ToScrYCoord(fCurrent.fY)));
01768       gVirtualX->DrawString(fCanvas->GetId(), fNormGC(),
01769                             Int_t(ToScrXCoord(fCurrent.fX, fCurrent.fY)),
01770                             Int_t(ToScrYCoord(fCurrent.fY+1) - fMaxDescent),
01771                             charstring, strlen(charstring));
01772       fCursorState = 2;  // the ClearArea effectively turned off the cursor
01773    }
01774    delete [] charstring;
01775    SetCurrent(pos);
01776 }
01777 
01778 //______________________________________________________________________________
01779 void TGTextEdit::DelChar()
01780 {
01781    // Delete a character from the text edit widget.
01782 
01783    if (fReadOnly) {
01784       return;
01785    }
01786 
01787    char *buffer;
01788    TGLongPosition pos, pos2;
01789    Long_t len;
01790 
01791    pos.fY = fCurrent.fY;
01792    pos.fX = fCurrent.fX;
01793    UInt_t h = 0;
01794 
01795    if (fCurrent.fX > 0) {
01796       Int_t y = (Int_t)ToScrYCoord(pos.fY);
01797       h = UInt_t(ToScrYCoord(pos.fY+2) - y);
01798       if (!y) h = h << 1;
01799 
01800       pos.fX--;
01801 
01802       if (fText->GetChar(pos) == 16) {
01803          do {
01804             pos.fX++;
01805             fText->DelChar(pos);
01806             pos.fX -= 2;
01807          } while (fText->GetChar(pos) != '\t');
01808 
01809          pos.fX++;
01810          fText->DelChar(pos);
01811          pos.fX--;
01812          fText->ReTab(pos.fY);
01813          UpdateRegion(0, y, fCanvas->GetWidth(), h);
01814       } else {
01815          pos.fX = fCurrent.fX;
01816          fText->DelChar(pos);
01817          pos.fX = fCurrent.fX - 1;
01818       }
01819       if (ToScrXCoord(fCurrent.fX-1, fCurrent.fY) < 0) {
01820          SetHsbPosition((fVisible.fX-fCanvas->GetWidth()/2)/fScrollVal.fX);
01821       }
01822       SetSBRange(kHorizontal);
01823       UpdateRegion(0, y, fCanvas->GetWidth(), h);
01824    } else {
01825       if (fCurrent.fY > 0) {
01826          len = fText->GetLineLength(fCurrent.fY);
01827          if (len > 0) {
01828             buffer = fText->GetLine(fCurrent, len);
01829             pos.fY--;
01830             pos.fX = fText->GetLineLength(fCurrent.fY-1);
01831             fText->InsText(pos, buffer);
01832             pos.fY++;
01833             delete [] buffer;
01834          } else {
01835             pos.fX = fText->GetLineLength(fCurrent.fY-1);
01836          }
01837 
01838          pos2.fY = ToScrYCoord(fCurrent.fY+1);
01839          pos.fY = fCurrent.fY - 1;
01840          fText->DelLine(fCurrent.fY);
01841          len = fText->GetLineLength(fCurrent.fY-1);
01842 
01843          if (ToScrXCoord(pos.fX, fCurrent.fY-1) >= (Int_t)fCanvas->GetWidth()) {
01844             SetHsbPosition((ToScrXCoord(pos.fX, pos.fY)+fVisible.fX-fCanvas->GetWidth()/2)/fScrollVal.fX);
01845          }
01846 
01847          h = UInt_t(fCanvas->GetHeight() - ToScrYCoord(fCurrent.fY));
01848 
01849          gVirtualX->CopyArea(fCanvas->GetId(), fCanvas->GetId(), fNormGC(), 0,
01850                              Int_t(pos2.fY), fWidth, h, 0, (Int_t)ToScrYCoord(fCurrent.fY));
01851          if (ToScrYCoord(pos.fY) < 0) {
01852             SetVsbPosition(fVisible.fY/fScrollVal.fY-1);
01853          }
01854          UpdateRegion(0, (Int_t)ToScrYCoord(pos.fY), fCanvas->GetWidth(), h);
01855          SetSBRange(kVertical);
01856          SetSBRange(kHorizontal);
01857       }
01858    }
01859    SetCurrent(pos);
01860 }
01861 
01862 //______________________________________________________________________________
01863 void TGTextEdit::BreakLine()
01864 {
01865    // Break a line.
01866 
01867    if (fReadOnly) return;
01868 
01869    TGLongPosition pos;
01870    fText->BreakLine(fCurrent);
01871    if (ToScrYCoord(fCurrent.fY+2) <= (Int_t)fCanvas->GetHeight()) {
01872       gVirtualX->CopyArea(fCanvas->GetId(), fCanvas->GetId(), fNormGC(), 0,
01873                           (Int_t)ToScrYCoord(fCurrent.fY+1), fCanvas->GetWidth(),
01874                           UInt_t(fCanvas->GetHeight()-(ToScrYCoord(fCurrent.fY+2)-
01875                           ToScrYCoord(fCurrent.fY))),
01876                           0, (Int_t)ToScrYCoord(fCurrent.fY+2));
01877       UpdateRegion(0, (Int_t)ToScrYCoord(fCurrent.fY), fCanvas->GetWidth(),
01878                   UInt_t(ToScrYCoord(fCurrent.fY+2) - ToScrYCoord(fCurrent.fY)));
01879 
01880       if (fVisible.fX != 0) {
01881          SetHsbPosition(0);
01882       }
01883       SetSBRange(kHorizontal);
01884       SetSBRange(kVertical);
01885    } else {
01886       SetSBRange(kHorizontal);
01887       SetSBRange(kVertical);
01888       SetVsbPosition(fVisible.fY/fScrollVal.fY + 1);
01889       UpdateRegion(0, (Int_t)ToScrYCoord(fCurrent.fY), fCanvas->GetWidth(),
01890                    UInt_t(ToScrYCoord(fCurrent.fY+1) - ToScrYCoord(fCurrent.fY)));
01891    }
01892    pos.fY = fCurrent.fY+1;
01893    pos.fX = 0;
01894    SetCurrent(pos);
01895 }
01896 
01897 //______________________________________________________________________________
01898 void TGTextEdit::ScrollCanvas(Int_t new_top, Int_t direction)
01899 {
01900    // Scroll the canvas to new_top in the kVertical or kHorizontal direction.
01901 
01902    CursorOff();
01903 
01904    TGTextView::ScrollCanvas(new_top, direction);
01905 
01906    CursorOn();
01907 }
01908 
01909 //______________________________________________________________________________
01910 void TGTextEdit::DrawRegion(Int_t x, Int_t y, UInt_t width, UInt_t height)
01911 {
01912    // Redraw the text edit widget.
01913 
01914    CursorOff();
01915 
01916    TGTextView::DrawRegion(x, y, width, height);
01917 
01918    CursorOn();
01919 }
01920 
01921 //______________________________________________________________________________
01922 void TGTextEdit::PrevChar()
01923 {
01924    // Go to the previous character.
01925 
01926    if (fCurrent.fY == 0 && fCurrent.fX == 0) {
01927       gVirtualX->Bell(0);
01928       return;
01929    }
01930 
01931    TGLongPosition pos;
01932    Long_t len;
01933 
01934    pos.fY = fCurrent.fY;
01935    pos.fX = fCurrent.fX;
01936    if (fCurrent.fX > 0) {
01937       pos.fX--;
01938       while (fText->GetChar(pos) == 16) {
01939          pos.fX--;
01940       }
01941 
01942       if (ToScrXCoord(pos.fX, pos.fY) < 0) {
01943          if (fVisible.fX-(Int_t)fCanvas->GetWidth()/2 >= 0) {
01944             SetHsbPosition((fVisible.fX-fCanvas->GetWidth()/2)/fScrollVal.fX);
01945          } else {
01946             SetHsbPosition(0);
01947          }
01948       }
01949    } else {
01950       if (fCurrent.fY > 0) {
01951          pos.fY = fCurrent.fY - 1;
01952          len = fText->GetLineLength(pos.fY);
01953          if (ToScrYCoord(fCurrent.fY) <= 0) {
01954             SetVsbPosition(fVisible.fY/fScrollVal.fY-1);
01955          }
01956          if (ToScrXCoord(len, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
01957             SetHsbPosition((ToScrXCoord(len, pos.fY)+fVisible.fX -
01958                             fCanvas->GetWidth()/2)/fScrollVal.fX);
01959          }
01960          pos.fX = len;
01961       }
01962    }
01963    SetCurrent(pos);
01964 }
01965 
01966 //______________________________________________________________________________
01967 void TGTextEdit::NextChar()
01968 {
01969    // Go to next character.
01970 
01971    Long_t len = fText->GetLineLength(fCurrent.fY);
01972 
01973    if (fCurrent.fY == fText->RowCount()-1 && fCurrent.fX == len) {
01974       gVirtualX->Bell(0);
01975       return;
01976    }
01977 
01978    TGLongPosition pos;
01979    pos.fY = fCurrent.fY;
01980    if (fCurrent.fX < len) {
01981       if (fText->GetChar(fCurrent) == '\t') {
01982          pos.fX = fCurrent.fX + 8 - (fCurrent.fX & 0x7);
01983       } else {
01984          pos.fX = fCurrent.fX + 1;
01985       }
01986 
01987       if (ToScrXCoord(pos.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
01988          SetHsbPosition(fVisible.fX/fScrollVal.fX+(fCanvas->GetWidth()/2)/fScrollVal.fX);
01989       }
01990    } else {
01991       if (fCurrent.fY < fText->RowCount()-1) {
01992          pos.fY = fCurrent.fY + 1;
01993          if (ToScrYCoord(pos.fY+1) >= (Int_t)fCanvas->GetHeight()) {
01994             SetVsbPosition(fVisible.fY/fScrollVal.fY+1);
01995          }
01996          SetHsbPosition(0);
01997          pos.fX = 0;
01998       }
01999    }
02000    SetCurrent(pos);
02001 }
02002 
02003 //______________________________________________________________________________
02004 void TGTextEdit::LineUp()
02005 {
02006    // Make current position first line in window by scrolling up.
02007 
02008    TGLongPosition pos;
02009    Long_t len;
02010    if (fCurrent.fY > 0) {
02011       pos.fY = fCurrent.fY - 1;
02012       if (ToScrYCoord(fCurrent.fY) <= 0) {
02013          SetVsbPosition(fVisible.fY/fScrollVal.fY-1);
02014       }
02015       len = fText->GetLineLength(fCurrent.fY-1);
02016       if (fCurrent.fX > len) {
02017          if (ToScrXCoord(len, pos.fY) <= 0) {
02018             if (ToScrXCoord(len, pos.fY) < 0) {
02019                SetHsbPosition(ToScrXCoord(len, pos.fY)+
02020                             (fVisible.fX-fCanvas->GetWidth()/2)/fScrollVal.fX);
02021             } else {
02022                SetHsbPosition(0);
02023             }
02024          }
02025          pos.fX = len;
02026       } else {
02027          pos.fX = ToObjXCoord(ToScrXCoord(fCurrent.fX, fCurrent.fY)+fVisible.fX, pos.fY);
02028       }
02029 
02030       while (fText->GetChar(pos) == 16) {
02031          pos.fX++;
02032       }
02033       SetCurrent(pos);
02034    }
02035 }
02036 
02037 //______________________________________________________________________________
02038 void TGTextEdit::LineDown()
02039 {
02040    // Move one line down.
02041 
02042    TGLongPosition pos;
02043    Long_t len;
02044    if (fCurrent.fY < fText->RowCount()-1) {
02045       len = fText->GetLineLength(fCurrent.fY+1);
02046       pos.fY = fCurrent.fY + 1;
02047       if (ToScrYCoord(pos.fY+1) > (Int_t)fCanvas->GetHeight()) {
02048          SetVsbPosition(fVisible.fY/fScrollVal.fY+1);
02049       }
02050       if (fCurrent.fX > len) {
02051          if (ToScrXCoord(len, pos.fY) <= 0) {
02052             if (ToScrXCoord(len, pos.fY) < 0) {
02053                SetHsbPosition((ToScrXCoord(len, pos.fY)+fVisible.fX-fCanvas->GetWidth()/2)/fScrollVal.fX);
02054             } else {
02055                SetHsbPosition(0);
02056             }
02057          }
02058          pos.fX = len;
02059       } else {
02060          pos.fX = ToObjXCoord(ToScrXCoord(fCurrent.fX, fCurrent.fY)+fVisible.fX, pos.fY);
02061       }
02062 
02063       while (fText->GetChar(pos) == 16) {
02064          pos.fX++;
02065       }
02066       SetCurrent(pos);
02067    }
02068 }
02069 
02070 //______________________________________________________________________________
02071 void TGTextEdit::ScreenUp()
02072 {
02073    // Move one screen up.
02074 
02075    TGLongPosition pos;
02076    pos.fX = fCurrent.fX;
02077    pos.fY = fCurrent.fY - (ToObjYCoord(fCanvas->GetHeight())-ToObjYCoord(0))-1;
02078    if (fVisible.fY - (Int_t)fCanvas->GetHeight() >= 0) { // +1
02079       SetVsbPosition((fVisible.fY - fCanvas->GetHeight())/fScrollVal.fY);
02080    } else {
02081       pos.fY = 0;
02082       SetVsbPosition(0);
02083    }
02084    while (fText->GetChar(pos) == 16) {
02085       pos.fX++;
02086    }
02087    SetCurrent(pos);
02088 }
02089 
02090 //______________________________________________________________________________
02091 void TGTextEdit::ScreenDown()
02092 {
02093    // Move one screen down.
02094 
02095    TGLongPosition pos;
02096    pos.fX = fCurrent.fX;
02097    pos.fY = fCurrent.fY + (ToObjYCoord(fCanvas->GetHeight()) - ToObjYCoord(0));
02098    Long_t count = fText->RowCount()-1;
02099    if ((Int_t)fCanvas->GetHeight() < ToScrYCoord(count)) {
02100       SetVsbPosition((fVisible.fY+fCanvas->GetHeight())/fScrollVal.fY);
02101    } else {
02102       pos.fY = count;
02103    }
02104    while (fText->GetChar(pos) == 16) {
02105       pos.fX++;
02106    }
02107    SetCurrent(pos);
02108 }
02109 
02110 //______________________________________________________________________________
02111 void TGTextEdit::Home()
02112 {
02113    // Move to beginning of line.
02114 
02115    TGLongPosition pos;
02116    pos.fY = fCurrent.fY;
02117    pos.fX = 0;
02118    SetHsbPosition(0);
02119    SetCurrent(pos);
02120 }
02121 
02122 //______________________________________________________________________________
02123 void TGTextEdit::End()
02124 {
02125    // Move to end of line.
02126 
02127    TGLongPosition pos;
02128    pos.fY = fCurrent.fY;
02129    pos.fX = fText->GetLineLength(pos.fY);
02130    if (ToScrXCoord(pos.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()) {
02131       SetHsbPosition((ToScrXCoord(pos.fX, pos.fY) + fVisible.fX - fCanvas->GetWidth()/2)/fScrollVal.fX);
02132    }
02133    SetCurrent(pos);
02134 }
02135 
02136 //______________________________________________________________________________
02137 const TGGC &TGTextEdit::GetCursor0GC()
02138 {
02139    // Return selection graphics context for text cursor.
02140    
02141    if (!fgCursor0GC) {
02142       fgCursor0GC = new TGGC(GetDefaultSelectedGC());
02143       fgCursor0GC->SetFunction(kGXxor);
02144    }
02145    return *fgCursor0GC;
02146 }
02147 
02148 //______________________________________________________________________________
02149 const TGGC &TGTextEdit::GetCursor1GC()
02150 {
02151    // Return default graphics context for text cursor.
02152    
02153    if (!fgCursor1GC) {
02154       fgCursor1GC = new TGGC(GetDefaultGC());
02155       fgCursor1GC->SetFunction(kGXand);
02156    }
02157    return *fgCursor1GC;
02158 }
02159 
02160 //______________________________________________________________________________
02161 void TGTextEdit::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
02162 {
02163    // Save a text edit widget as a C++ statement(s) on output stream out
02164 
02165    char quote = '"';
02166    out << "   TGTextEdit *";
02167    out << GetName() << " = new TGTextEdit(" << fParent->GetName()
02168        << "," << GetWidth() << "," << GetHeight()
02169        << ");"<< endl;
02170    if (option && strstr(option, "keep_names"))
02171       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02172 
02173    if (IsReadOnly()) {
02174       out << "   " << GetName() << "->SetReadOnly(kTRUE);" << endl;
02175    }
02176 
02177    if (!IsMenuEnabled()) {
02178       out << "   " << GetName() << "->EnableMenu(kFALSE);" << endl;
02179    }
02180 
02181    if (fCanvas->GetBackground() != TGFrame::fgWhitePixel) {
02182       out << "   " << GetName() << "->ChangeBackground(" << fCanvas->GetBackground() << ");" << endl;
02183    }
02184 
02185    TGText *txt = GetText();
02186    Bool_t fromfile = strlen(txt->GetFileName()) ? kTRUE : kFALSE;
02187    TString fn;
02188 
02189    if (fromfile) {
02190       const char *filename = txt->GetFileName();
02191       fn = gSystem->ExpandPathName(gSystem->UnixPathName(filename));
02192    } else {
02193       fn = TString::Format("Txt%s", GetName()+5);
02194       txt->Save(fn.Data());
02195    }
02196    out << "   " << GetName() << "->LoadFile(" << quote << fn.Data() << quote << ");" << endl;
02197 }

Generated on Tue Jul 5 14:22:05 2011 for ROOT_528-00b_version by  doxygen 1.5.1