TGTextEntry.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGTextEntry.cxx 35582 2010-09-22 13:38:27Z bellenot $
00002 // Author: Fons Rademakers   08/01/98
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 // TGTextEntry                                                          //
00026 //                                                                      //
00027 // A TGTextEntry is a one line text input widget.                       //
00028 //                                                                      //
00029 // Changing text in the text entry widget will generate the event:      //
00030 // kC_TEXTENTRY, kTE_TEXTCHANGED, widget id, 0.                         //
00031 // Hitting the enter key will generate:                                 //
00032 // kC_TEXTENTRY, kTE_ENTER, widget id, 0.                               //
00033 // Hitting the tab key will generate:                                   //
00034 // kC_TEXTENTRY, kTE_TAB, widget id, 0.                                 //
00035 //                                                                      //
00036 // This widget has the behaviour e.g. of the "Location" field in        //
00037 // netscape. That includes handling Control/Shift key modifiers and     //
00038 // scrolling the text.                                                  //
00039 //
00040 //
00041 // enum TGTextEntry::EEchoMode
00042 //
00043 // This enum type describes the ways in which TGTextEntry can display
00044 // its contents. The currently defined values are:
00045 //Begin_Html
00046 /*
00047 <ul>
00048 <li>  kNormal - display characters as they are entered. This is the default.
00049 <li>  kNoEcho - do not display anything.
00050 <li>  kPassword - display asterisks instead of the characters actually entered.
00051 </ul>
00052 */
00053 //End_Html
00054 // See also SetEchoMode(), GetEchoMode().
00055 //
00056 // enum TGTextEntry::EInsertMode
00057 //
00058 // This enum type describes the way how typed characters are
00059 // inserted in the text entry. This mode is switched by "Insert" key.
00060 //Begin_Html
00061 /*
00062 <ul>
00063 <li>  kInsert - typed character are inserted (cursor has shape of short line).
00064 <li>  kReplace - typed characters substitute already typed ones
00065                  (cursor has the shape of filled rectangle).
00066 </ul>
00067 */
00068 //End_Html
00069 //
00070 // enum TGWidget::ETextJustification
00071 //
00072 // This enum type (defined in TGWidget.h) describes the text alignment modes.
00073 // These modes are valid untill text fits the frame width
00074 //Begin_Html
00075 /*
00076 <ul>
00077 <li>  kTextLeft    - left-side text alignment
00078 <li>  kTextRight   - right-side text alignment
00079 <li>  kTextCenterX - center text alignment
00080 </ul>
00081 */
00082 //End_Html
00083 //
00084 //
00085 // The key press event handler converts a key press to some line editor action.
00086 // Here are the default key bindings:
00087 //Begin_Html
00088 /*
00089 <ul>
00090 <li><i> Left Arrow </i>
00091         Move the cursor one character leftwards.
00092         Scroll the text when cursor is out of frame.
00093 <li><i> Right Arrow </i>
00094         Move the cursor one character rightwards
00095         Scroll the text when cursor is out of frame.
00096 <li><i> Backspace </i>
00097         Deletes the character on the left side of the text cursor and moves the
00098         cursor one position to the left. If a text has been marked by the user
00099         (e.g. by clicking and dragging) the cursor will be put at the beginning
00100         of the marked text and the marked text will be removed.
00101 <li><i> Home </i>
00102         Moves the text cursor to the left end of the line. If mark is TRUE text
00103         will be marked towards the first position, if not any marked text will
00104         be unmarked if the cursor is moved.
00105 <li><i> End </i>
00106         Moves the text cursor to the right end of the line. If mark is TRUE text
00107         will be marked towards the last position, if not any marked text will
00108         be unmarked if the cursor is moved.
00109 <li><i> Delete </i>
00110         Deletes the character on the right side of the text cursor. If a text
00111         has been marked by the user (e.g. by clicking and dragging) the cursor
00112         will be put at the beginning of the marked text and the marked text will
00113         be removed.
00114 <li><i> Insert </i>
00115         Switches character insert mode.
00116 <li><i> Shift - Left Arrow </i>
00117         Mark text one character leftwards
00118 <li><i> Shift - Right Arrow </i>
00119         Mark text one character rightwards
00120 <li><i> Control - Left Arrow </i>
00121         Move the cursor one word leftwards
00122 <li><i> Control - Right Arrow </i>
00123         Move the cursor one word rightwards.
00124 <li><i> Control - Shift - Left Arrow </i>
00125         Mark text one word leftwards
00126 <li><i> Control - Shift - Right Arrow </i>
00127         Mark text one word rightwards
00128 <li><i> Control-A </i>
00129         Move the cursor to the beginning of the line
00130 <li><i> Control-B </i>
00131         Move the cursor one character leftwards
00132 <li><i> Control-C </i>
00133         Copy the marked text to the clipboard.
00134 <li><i> Control-D </i>
00135         Delete the character to the right of the cursor
00136 <li><i> Control-E </i>
00137         Move the cursor to the end of the line
00138 <li><i> Control-F </i>
00139         Move the cursor one character rightwards
00140 <li><i> Control-H </i>
00141         Delete the character to the left of the cursor
00142 <li><i> Control-K </i>
00143         Delete marked text if any or delete all
00144         characters to the right of the cursor
00145 <li><i> Control-U </i>
00146         Delete all characters on the line
00147 <li><i> Control-V </i>
00148         Paste the clipboard text into line edit.
00149 <li><i> Control-X </i>
00150         Cut the marked text, copy to clipboard.
00151 <li><i> Control-Y </i>
00152         Paste the clipboard text into line edit.
00153 </ul>
00154 All other keys with valid ASCII codes insert themselves into the line.
00155 */
00156 //End_Html
00157 //
00158 ////////////////////////////////////////////////////////////////////////////////
00159 
00160 //******************* TGTextEntry signals *************************************
00161 //______________________________________________________________________________
00162 // TGTextEntry::ReturnPressed()
00163 //
00164 //    This signal is emitted when the return or enter key is pressed.
00165 //
00166 //______________________________________________________________________________
00167 // TGTextEntry::TabPressed()
00168 //
00169 //    This signal is emitted when the <TAB> key is pressed.
00170 //    Use for changing focus.
00171 //
00172 //______________________________________________________________________________
00173 // TGTextEntry::ShiftTabPressed()
00174 //
00175 //    This signal is emitted when the <SHIFT> and <TAB> keys are pressed.
00176 //    Use for changing focus in reverse direction.
00177 //
00178 //______________________________________________________________________________
00179 // TGTextEntry::TextChanged(const char *text)
00180 //
00181 //    This signal is emitted every time the text has changed.
00182 //    The argument is the new text.
00183 //
00184 //______________________________________________________________________________
00185 // TGTextEntry::CursorOutLeft()
00186 //
00187 // This signal is emitted when cursor is going out of left side.
00188 //
00189 //______________________________________________________________________________
00190 // TGTextEntry::CursorOutRight()
00191 //
00192 // This signal is emitted when cursor is going out of right side.
00193 //
00194 //______________________________________________________________________________
00195 // TGTextEntry::CursorOutUp()
00196 //
00197 // This signal is emitted when cursor is going out of upper side.
00198 //
00199 //______________________________________________________________________________
00200 // TGTextEntry::CursorOutDown()
00201 //
00202 // This signal is emitted when cursor is going out of bottom side.
00203 //
00204 //______________________________________________________________________________
00205 // TGTextEntry::DoubleClicked()
00206 //
00207 // This signal is emitted when widget is double clicked.
00208 
00209 
00210 #include "TGTextEntry.h"
00211 #include "TGResourcePool.h"
00212 #include "TGToolTip.h"
00213 #include "TSystem.h"
00214 #include "TTimer.h"
00215 #include "TColor.h"
00216 #include "KeySymbols.h"
00217 #include "Riostream.h"
00218 #include "TClass.h"
00219 #include "TGMsgBox.h"
00220 
00221 
00222 TString      *TGTextEntry::fgClipboardText = 0;
00223 const TGFont *TGTextEntry::fgDefaultFont = 0;
00224 const TGGC   *TGTextEntry::fgDefaultSelectedGC = 0;
00225 const TGGC   *TGTextEntry::fgDefaultSelectedBackgroundGC = 0;
00226 const TGGC   *TGTextEntry::fgDefaultGC = 0;
00227 
00228 TGTextEntry *gBlinkingEntry = 0;
00229 
00230 //______________________________________________________________________________
00231 class TBlinkTimer : public TTimer {
00232 private:
00233    TGTextEntry   *fTextEntry;
00234 public:
00235    TBlinkTimer(TGTextEntry *t, Long_t ms) : TTimer(ms, kTRUE) { fTextEntry = t; }
00236    Bool_t Notify();
00237 };
00238 
00239 //______________________________________________________________________________
00240 Bool_t TBlinkTimer::Notify()
00241 {
00242    // Notify when timer times out and reset the timer.
00243 
00244    fTextEntry->HandleTimer(0);
00245    Reset();
00246    return kFALSE;
00247 }
00248 
00249 
00250 ClassImp(TGTextEntry)
00251 
00252 //______________________________________________________________________________
00253 TGTextEntry::TGTextEntry(const TGWindow *p, TGTextBuffer *text, Int_t id,
00254                          GContext_t norm, FontStruct_t font, UInt_t options,
00255                          ULong_t back) :
00256    TGFrame(p, 1, 1, options | kOwnBackground, back)
00257 {
00258    // Create a text entry widget. It will adopt the TGTextBuffer object
00259    // (i.e. the text buffer will be deleted by the text entry widget).
00260 
00261    TGGC *normgc   = fClient->GetResourcePool()->GetGCPool()->FindGC(norm);
00262 
00263    fWidgetId      = id;
00264    fMsgWindow     = p;
00265    if (normgc)
00266       fNormGC     = *normgc;
00267    else
00268       fNormGC     = GetDefaultGC();
00269    fFontStruct    = font;
00270    fText          = text;
00271 
00272    Init();
00273 }
00274 
00275 //______________________________________________________________________________
00276 TGTextEntry::TGTextEntry(const TGWindow *parent, const char *text, Int_t id) :
00277    TGFrame(parent, 1, 1, kSunkenFrame | kDoubleBorder | kOwnBackground, fgWhitePixel)
00278 {
00279    // Simple text entry constructor.
00280 
00281    fWidgetId      = id;
00282    fMsgWindow     = parent;
00283    fNormGC        = GetDefaultGC();
00284    fFontStruct    = GetDefaultFontStruct();
00285    fText          = new TGTextBuffer();
00286    fText->AddText(0, !text && !parent ? GetName() : text);
00287 
00288    Init();                             // default initialization
00289 }
00290 
00291 //______________________________________________________________________________
00292 TGTextEntry::TGTextEntry(const TString &contents, const TGWindow *parent, Int_t id) :
00293    TGFrame(parent, 1, 1, kSunkenFrame | kDoubleBorder | kOwnBackground, fgWhitePixel)
00294 {
00295    // Simple test entry constructor. Notice TString argument comes before the
00296    // parent argument (to make this ctor different from the first one taking a
00297    // const char*).
00298 
00299    fWidgetId      = id;
00300    fMsgWindow     = parent;
00301    fNormGC        = GetDefaultGC();
00302    fFontStruct    = GetDefaultFontStruct();
00303    fText          = new TGTextBuffer();
00304    fText->AddText(0, contents.Data());
00305 
00306    Init();                             // default initialization
00307 }
00308 
00309 //______________________________________________________________________________
00310 TGTextEntry::~TGTextEntry()
00311 {
00312    // Delete a text entry widget.
00313 
00314    delete fText;
00315    delete fCurBlink;
00316    delete fTip;
00317 
00318    if (this == gBlinkingEntry) gBlinkingEntry = 0;
00319 }
00320 
00321 //______________________________________________________________________________
00322 void TGTextEntry::Init()
00323 {
00324    // Do default initialization.
00325 
00326    fWidgetFlags = kWidgetWantFocus | kWidgetIsEnabled;
00327    fSelGC       = GetDefaultSelectedGC();
00328    fSelbackGC   = GetDefaultSelectedBackgroundGC()();
00329 
00330    fOffset = 0;
00331    // Set default maximum lenght to 4096. Can be changed with SetMaxLength() 
00332    fMaxLen = 4096;
00333    fFrameDrawn = kTRUE;
00334    fEdited = kFALSE;
00335    fEchoMode = kNormal;
00336    fAlignment= kTextLeft;
00337    fInsertMode = kInsert;
00338    fDefWidth = fDefHeight = 0;
00339 
00340    int tw, max_ascent, max_descent;
00341    tw = gVirtualX->TextWidth(fFontStruct, GetText(), fText->GetTextLength());
00342 
00343    if (tw < 1) {
00344       TString dummy('w', fText->GetBufferLength());
00345       tw = gVirtualX->TextWidth(fFontStruct, dummy.Data(), dummy.Length());
00346    }
00347    gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
00348    Resize(tw + 8, max_ascent + max_descent + 7);
00349 
00350    Int_t offset = IsFrameDrawn() ? 4 : 0;
00351    fCursorX     = offset ;
00352    fCursorIX    = fStartIX = fEndIX = fOffset = 0;
00353    fSelectionOn = fCursorOn = kFALSE;
00354    fCurBlink    = 0;
00355    fTip         = 0;
00356    fClipboard   = fClient->GetResourcePool()->GetClipboard();
00357 
00358    gVirtualX->SetCursor(fId, fClient->GetResourcePool()->GetTextCursor());
00359 
00360    gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00361                          kButtonPressMask | kButtonReleaseMask |
00362                          kButtonMotionMask, kNone, kNone);
00363 
00364    AddInput(kKeyPressMask | kFocusChangeMask |
00365             kEnterWindowMask | kLeaveWindowMask);
00366 
00367    SetWindowAttributes_t wattr;
00368    wattr.fMask = kWAWinGravity | kWABitGravity;
00369    wattr.fBitGravity = 1; // NorthWestGravity
00370    wattr.fWinGravity = 1;
00371    gVirtualX->ChangeWindowAttributes(fId, &wattr);
00372 
00373    SetWindowName();
00374    fHasOwnFont = kFALSE;
00375    fEditDisabled = kEditDisableHeight;
00376 }
00377 
00378 //______________________________________________________________________________
00379 TGDimension TGTextEntry::GetDefaultSize() const
00380 {
00381    // Return the default / minimal size of the widget.
00382 
00383    UInt_t w = (GetOptions() & kFixedWidth)  || (fDefWidth  == 0) ? fWidth  : fDefWidth;
00384    UInt_t h = (GetOptions() & kFixedHeight) || (fDefHeight == 0) ? fHeight : fDefHeight;
00385    return TGDimension(w, h);
00386 }
00387 
00388 //______________________________________________________________________________
00389 void TGTextEntry::SetDefaultSize(UInt_t w, UInt_t h)
00390 {
00391    // Set the default / minimal size of the widget.
00392 
00393    fDefWidth  = w;
00394    fDefHeight = h;
00395 }
00396 
00397 //______________________________________________________________________________
00398 void TGTextEntry::ReturnPressed()
00399 {
00400    // This signal is emitted when the return or enter key is pressed.
00401 
00402    SendMessage(fMsgWindow, MK_MSG(kC_TEXTENTRY, kTE_ENTER), fWidgetId, 0);
00403    fClient->ProcessLine(fCommand, MK_MSG(kC_TEXTENTRY, kTE_ENTER),fWidgetId, 0);
00404 
00405    Emit("ReturnPressed()");
00406 }
00407 
00408 //______________________________________________________________________________
00409 void TGTextEntry::ShiftTabPressed()
00410 {
00411    // This signal is emitted when <SHIFT> and <TAB> keys are pressed.
00412 
00413    Emit("ShiftTabPressed()");
00414 }
00415 
00416 //______________________________________________________________________________
00417 void TGTextEntry::TabPressed()
00418 {
00419    // This signal is emitted when the <TAB> key is pressed.
00420 
00421    SendMessage(fMsgWindow, MK_MSG(kC_TEXTENTRY, kTE_TAB), fWidgetId, 0);
00422    fClient->ProcessLine(fCommand, MK_MSG(kC_TEXTENTRY, kTE_TAB), fWidgetId, 0);
00423 
00424    Emit("TabPressed()");
00425 }
00426 
00427 //______________________________________________________________________________
00428 void TGTextEntry::TextChanged(const char *)
00429 {
00430    // This signal is emitted every time the text has changed.
00431 
00432    SendMessage(fMsgWindow, MK_MSG(kC_TEXTENTRY, kTE_TEXTCHANGED),fWidgetId, 0);
00433    fClient->ProcessLine(fCommand, MK_MSG(kC_TEXTENTRY, kTE_TEXTCHANGED),fWidgetId, 0);
00434 
00435    Emit("TextChanged(char*)", GetText());  // The argument is the new text.
00436 }
00437 
00438 //______________________________________________________________________________
00439 void TGTextEntry::CursorOutLeft()
00440 {
00441    // This signal is emitted when cursor is going out of left side.
00442 
00443    Emit("CursorOutLeft()");
00444 }
00445 
00446 //______________________________________________________________________________
00447 void TGTextEntry::CursorOutRight()
00448 {
00449    // This signal is emitted when cursor is going out of right side.
00450 
00451    Emit("CursorOutRight()");
00452 }
00453 
00454 //______________________________________________________________________________
00455 void TGTextEntry::CursorOutUp()
00456 {
00457    // This signal is emitted when cursor is going out of upper side.
00458 
00459    Emit("CursorOutUp()");
00460 }
00461 
00462 //______________________________________________________________________________
00463 void TGTextEntry::CursorOutDown()
00464 {
00465    // This signal is emitted when cursor is going out of bottom side.
00466 
00467    Emit("CursorOutDown()");
00468 }
00469 
00470 //______________________________________________________________________________
00471 void TGTextEntry::DoubleClicked()
00472 {
00473    // This signal is emitted when widget is double clicked.
00474 
00475    Emit("DoubleClicked()");
00476 }
00477 
00478 //______________________________________________________________________________
00479 TString TGTextEntry::GetDisplayText() const
00480 {
00481    // Returns the text that's currently displayed.  This is normally
00482    // the same as GetText(), but can be e.g.
00483    // "*****" if EEchoMode is kPassword or
00484    // ""      if it is kNoEcho.
00485 
00486    TString res;
00487 
00488    switch (GetEchoMode()) {
00489    case kNormal:
00490          res = GetText();
00491          break;
00492    case kNoEcho:
00493          res = "";
00494          break;
00495    case kPassword:
00496          res.Prepend('*', fText->GetTextLength());  // fill with '*'
00497          break;
00498    }
00499    return res;
00500 }
00501 
00502 //______________________________________________________________________________
00503 void TGTextEntry::SetState(Bool_t state)
00504 {
00505    // Set state of widget. If kTRUE=enabled, kFALSE=disabled.
00506 
00507    if (state) {
00508       SetFlags(kWidgetIsEnabled);
00509       SetBackgroundColor(fgWhitePixel);
00510    } else {
00511       ClearFlags(kWidgetIsEnabled);
00512       SetBackgroundColor(GetDefaultFrameBackground());
00513       fCursorOn = kFALSE;   // remove the cursor when disabling the widget
00514       if (fCurBlink) fCurBlink->Remove();
00515    }
00516    fClient->NeedRedraw(this);
00517 }
00518 
00519 //______________________________________________________________________________
00520 Int_t TGTextEntry::GetCharacterIndex(Int_t xcoord)
00521 {
00522    // Returns the index of the character to whose left edge xcoord is closest.
00523 
00524    int tw, ix, up, down, len;
00525 
00526    // check for out of boundaries first...
00527    TString dt = GetDisplayText();
00528    len = dt.Length();
00529    tw = gVirtualX->TextWidth(fFontStruct, dt.Data(), len);
00530    if (xcoord < 0) return 0;
00531    if (xcoord > tw) return len; // len-1
00532 
00533    // do a binary approximation
00534    up = len; //-1
00535    down = 0;
00536    while (up-down > 1) {
00537       ix = (up+down) >> 1;
00538       tw = gVirtualX->TextWidth(fFontStruct, fText->GetString(), ix);
00539       if (tw > xcoord)
00540          up = ix;
00541       else
00542          down = ix;
00543       if (tw == xcoord) break;
00544    }
00545    ix = down;
00546 
00547    // safety check...
00548    ix = TMath::Max(ix, 0);
00549    ix = TMath::Min(ix, len); // len-1
00550 
00551    return ix;
00552 }
00553 
00554 //______________________________________________________________________________
00555 void TGTextEntry::SetFrameDrawn(Bool_t enable)
00556 {
00557    // Sets the text entry to draw itself inside a two-pixel frame if
00558    // enable is kTRUE, and to draw itself without any frame if enable is
00559    // kFALSE. The default is kTRUE.
00560 
00561    if (fFrameDrawn == enable) return;
00562 
00563    fFrameDrawn = enable;
00564    fClient->NeedRedraw(this);
00565    // ChangedBy("SetFrameDrawn");  // emit signal ChangedBy
00566 }
00567 
00568 //______________________________________________________________________________
00569 void TGTextEntry::SetAlignment(ETextJustification mode)
00570 {
00571    // Sets the alignment of the text entry.
00572    // Possible values are kTextLeft(default), kTextRight, kTextCenterX.
00573    // See also GetAlignment().
00574 
00575    if ((mode == kTextRight ||
00576         mode == kTextCenterX ||
00577         mode == kTextLeft)) {
00578 
00579       SetWindowAttributes_t wattr;
00580       wattr.fMask = kWAWinGravity | kWABitGravity;
00581       wattr.fWinGravity = 1;
00582 
00583       if (mode == kTextLeft) {
00584          wattr.fBitGravity = 1;
00585       } else if (mode == kTextRight) {
00586          wattr.fBitGravity = 3;
00587       } else {
00588          wattr.fBitGravity = 5;
00589       }
00590 
00591       gVirtualX->ChangeWindowAttributes(fId, &wattr);
00592 
00593       fAlignment = mode;
00594       UpdateOffset();
00595       fClient->NeedRedraw(this);
00596       // ChangedBy("SetAlignment");  // emit signal ChangedBy
00597    }
00598 }
00599 
00600 //______________________________________________________________________________
00601 void TGTextEntry::SetInsertMode(EInsertMode mode)
00602 {
00603    // Sets the mode how characters are entered to the text entry.
00604 
00605    if (fInsertMode == mode) return;
00606 
00607    fInsertMode = mode;
00608    fClient->NeedRedraw(this);
00609    // ChangedBy("SetInsertMode");  // emit signal ChangedBy
00610 }
00611 
00612 //______________________________________________________________________________
00613 void TGTextEntry::SetText(const char *text, Bool_t emit)
00614 {
00615    // Sets text entry to text, clears the selection and moves
00616    // the cursor to the end of the line.
00617    // If necessary the text is truncated to fit MaxLength().
00618    // See also  GetText().
00619 
00620    TString oldText(GetText());
00621 
00622    fText->Clear();
00623    fText->AddText(0, text); // new text
00624 
00625    Int_t dif = fText->GetTextLength() - fMaxLen;
00626    if (dif > 0) fText->RemoveText(fMaxLen, dif);       // truncate
00627 
00628    End(kFALSE);
00629    if (oldText != GetText()) {
00630       if (emit)
00631          TextChanged();         // emit signal
00632       fClient->NeedRedraw(this);
00633    }
00634 }
00635 
00636 //______________________________________________________________________________
00637 void TGTextEntry::SetMaxLength(Int_t maxlen)
00638 {
00639    // Set the maximum length of the text in the editor.  If the text is
00640    // currently too long, it is chopped off at the limit. Any marked text will
00641    // be unmarked.  The cursor position is set to 0 and the first part of the
00642    // string is shown.
00643    // See  also GetMaxLength().
00644 
00645    fMaxLen = maxlen < 0 ? 0 : maxlen; // safety check for maxlen < 0
00646 
00647    Int_t dif = fText->GetTextLength() - fMaxLen;
00648    if (dif > 0) fText->RemoveText(fMaxLen, dif);    // truncate
00649 
00650    SetCursorPosition(0);
00651    Deselect();
00652 
00653    // ChangedBy("SetMaxLength");  // emit signal ChangedBy
00654 }
00655 
00656 //______________________________________________________________________________
00657 void TGTextEntry::SetEchoMode(EEchoMode mode)
00658 {
00659    // The echo modes available are:
00660    //Begin_Html
00661    // <ul>
00662    // <li> kNormal   - display characters as they are entered.  This is the default.
00663    // <li> kNoEcho   - do not display anything.
00664    // <li> kPassword - display asterisks instead of the characters actually entered.
00665    // </ul>
00666    //End_Html
00667    // It is always possible to cut and paste any marked text;  only the widget's own
00668    // display is affected.
00669    // See also GetEchoMode(), GetDisplayText().
00670 
00671    if (fEchoMode == mode) return;
00672 
00673    Int_t offset = IsFrameDrawn() ? 4 : 0;
00674    fEchoMode = mode;
00675    if (GetEchoMode() == kNoEcho) { fCursorX = offset; }
00676    UpdateOffset();
00677    fClient->NeedRedraw(this);
00678    // ChangedBy("SetEchoMode");  // emit signal ChangedBy
00679 }
00680 
00681 //______________________________________________________________________________
00682 TString TGTextEntry::GetMarkedText() const
00683 {
00684    // Returns the text marked by the user (e.g. by clicking and
00685    // dragging), or zero if no text is marked.
00686    // See also HasMarkedText().
00687 
00688    Int_t minP = MinMark();
00689    Int_t len = MaxMark() - minP;
00690    TString res(GetText()+minP,len);
00691    return res;
00692 }
00693 
00694 //______________________________________________________________________________
00695 void TGTextEntry::NewMark(Int_t newPos)
00696 {
00697    // New character mark at position pos.
00698    // See also SetCursorPosition().
00699 
00700    TString dt = GetDisplayText();
00701    Int_t offset = IsFrameDrawn() ? 4 : 0;
00702    Int_t x = fOffset + offset;
00703    Int_t len = dt.Length();
00704 
00705    Int_t pos = newPos < len ? newPos : len;
00706    fEndIX = pos < 0 ? 0 : pos;
00707 
00708    fSelectionOn = fSelectionOn && (fEndIX != fStartIX) && (GetEchoMode() != kNoEcho) ;
00709    SetCursorPosition(pos);
00710 
00711    if (fSelectionOn) {
00712       fEndX =  x + gVirtualX->TextWidth(fFontStruct, dt.Data() , fEndIX);
00713       fStartX = x + gVirtualX->TextWidth(fFontStruct, dt.Data() , fStartIX);
00714    }
00715 }
00716 
00717 //______________________________________________________________________________
00718 void TGTextEntry::SetCursorPosition(Int_t newPos)
00719 {
00720    // Set the cursor position to newPos.
00721    // See also NewMark().
00722 
00723    Int_t offset = IsFrameDrawn() ? 4 : 0;
00724    if (GetEchoMode() == kNoEcho) { fCursorX = offset; return; }
00725 
00726    UpdateOffset();
00727    TString dt = GetDisplayText();
00728 
00729    Int_t x = fOffset + offset;
00730    Int_t len = dt.Length();
00731 
00732    Int_t pos;
00733 
00734    if (newPos < len)
00735       pos = newPos;
00736    else {
00737       pos = len;
00738       if (newPos > len) CursorOutRight();
00739    }
00740 
00741    if (pos < 0) {
00742       fCursorIX = 0;
00743       CursorOutLeft();
00744    } else
00745       fCursorIX = pos;
00746 
00747    fCursorX = x + gVirtualX->TextWidth(fFontStruct, dt.Data(), fCursorIX);
00748 
00749    if (!fSelectionOn){
00750       fStartIX = fCursorIX;
00751       fStartX  = fCursorX;
00752    }
00753 }
00754 
00755 //______________________________________________________________________________
00756 void TGTextEntry::MarkWord(Int_t pos)
00757 {
00758    // Marks the word nearest to cursor position.
00759    // See also HandleDoubleClick().
00760 
00761    Int_t i = pos - 1;
00762    while (i >= 0 && isprint(GetText()[i]) && !isspace(GetText()[i])) i--;
00763    i++;
00764    Int_t newStartIX = i;
00765 
00766    i = pos;
00767    while (isprint(GetText()[i]) && !isspace(GetText()[i])) i++;
00768    while(isspace(GetText()[i])) i++;
00769 
00770    fSelectionOn = kTRUE;
00771    fStartIX = newStartIX;
00772    fEndIX = i;
00773    NewMark(i);
00774 }
00775 
00776 //______________________________________________________________________________
00777 void TGTextEntry::Insert(const char *newText)
00778 {
00779    // Removes any currently selected text, inserts newText,
00780    // sets it as the new contents of the text entry.
00781 
00782    TString old(GetText());
00783    TString t(newText);
00784 
00785    if (t.IsNull()) return;
00786 
00787    for (int i=0; i<t.Length(); i++) {
00788       if (t[i] < ' ') t[i] = ' '; // unprintable/linefeed becomes space
00789    }
00790 
00791    Int_t minP = MinMark();
00792    Int_t maxP = MaxMark();
00793    Int_t cp = fCursorIX;
00794 
00795    if (HasMarkedText()) {
00796       fText->RemoveText(minP, maxP-minP);
00797       cp = minP;
00798    }
00799 
00800    if (fInsertMode == kReplace) fText->RemoveText(cp,t.Length());
00801    Int_t ncp = TMath::Min(cp+t.Length(), GetMaxLength());
00802    fText->AddText(cp, t.Data());
00803    Int_t dlen = fText->GetTextLength()-GetMaxLength();
00804    if (dlen>0) fText->RemoveText(GetMaxLength(),dlen); // truncate
00805 
00806    SetCursorPosition(ncp);
00807    if (old != GetText()) TextChanged();
00808 }
00809 
00810 //______________________________________________________________________________
00811 void TGTextEntry::CursorRight(Bool_t mark, Int_t steps)
00812 {
00813    // Moves the cursor rightwards one or more characters.
00814    // See also CursorLeft().
00815 
00816    Int_t cp = fCursorIX + steps;
00817 
00818    if (cp == fCursorIX)  {
00819       if (!mark) {
00820          fSelectionOn = kFALSE;
00821          fEndIX = fStartIX = fCursorIX;
00822       }
00823    } else if (mark) {
00824       fSelectionOn = kTRUE;
00825       NewMark(cp);
00826    } else {
00827       fSelectionOn = kFALSE;
00828       SetCursorPosition(cp);
00829    }
00830 }
00831 
00832 //______________________________________________________________________________
00833 void TGTextEntry::CursorLeft(Bool_t mark, Int_t steps)
00834 {
00835    // Moves the cursor leftwards one or more characters.
00836    // See also CursorRight().
00837 
00838    CursorRight(mark, -steps);
00839 }
00840 
00841 //______________________________________________________________________________
00842 void TGTextEntry::CursorWordForward(Bool_t mark)
00843 {
00844    // Moves the cursor one word to the right.  If mark is kTRUE, the text
00845    // is marked.
00846    // See also CursorWordBackward().
00847 
00848    Int_t i = fCursorIX;
00849    while (i < (Int_t)fText->GetTextLength() && !isspace(GetText()[i])) ++i;
00850    while (i < (Int_t)fText->GetTextLength() && isspace(GetText()[i])) ++i;
00851    CursorRight(mark, i - fCursorIX);
00852 }
00853 
00854 //______________________________________________________________________________
00855 void TGTextEntry::CursorWordBackward(Bool_t mark)
00856 {
00857    // Moves the cursor one word to the left.  If mark is kTRUE, the text
00858    // is marked.
00859    // See also CursorWordForward().
00860 
00861    Int_t i = fCursorIX;
00862    while (i > 0 && isspace(GetText()[i-1])) --i;
00863    while (i > 0 && !isspace(GetText()[i-1])) --i;
00864    CursorLeft(mark,  fCursorIX - i);
00865 }
00866 
00867 //______________________________________________________________________________
00868 void TGTextEntry::Backspace()
00869 {
00870    // Deletes the character on the left side of the text cursor and moves the
00871    // cursor one position to the left. If a text has been marked by the user
00872    // (e.g. by clicking and dragging) the cursor will be put at the beginning
00873    // of the marked text and the marked text will be removed.
00874    // See also  Del().
00875 
00876    if (HasMarkedText())  {
00877       Del();
00878    } else if (fCursorIX > 0) {
00879       CursorLeft(kFALSE);
00880       Del();
00881    }
00882 }
00883 
00884 //______________________________________________________________________________
00885 void TGTextEntry::Del()
00886 {
00887    // Deletes the character on the right side of the text cursor. If a text
00888    // has been marked by the user (e.g. by clicking and dragging) the cursor
00889    // will be put at the beginning of the marked text and the marked text will
00890    // be removed.
00891    // See also Backspace().
00892 
00893    Int_t minP = MinMark();
00894    Int_t maxP = MaxMark();
00895 
00896    if (HasMarkedText())  {
00897       fText->RemoveText(minP, maxP-minP);
00898       fSelectionOn = kFALSE;
00899       SetCursorPosition(minP);
00900    }  else if (fCursorIX != (Int_t)fText->GetTextLength()) {
00901       fSelectionOn = kFALSE;
00902       fText->RemoveText(fCursorIX , 1);
00903       SetCursorPosition(fCursorIX);
00904    }
00905    TextChanged();
00906 }
00907 
00908 //______________________________________________________________________________
00909 void TGTextEntry::Remove()
00910 {
00911    // Deletes all characters on the right side of the cursor.
00912    // See also Del() Backspace().
00913 
00914    if (fCursorIX < (Int_t)fText->GetTextLength()) {
00915       fText->RemoveText(fCursorIX , fText->GetTextLength() - fCursorIX);
00916       SetCursorPosition(fCursorIX);
00917       TextChanged();                      // emit signal
00918    }
00919 }
00920 
00921 //______________________________________________________________________________
00922 void TGTextEntry::CopyText() const
00923 {
00924    // Copies the marked text to the clipboard, if there is any and
00925    // GetEchoMode() is kNormal.
00926    // See also  Cut() Paste().
00927 
00928    if (HasMarkedText() && GetEchoMode() == kNormal) {
00929       if (!fgClipboardText) fgClipboardText = new TString();
00930       *fgClipboardText = GetMarkedText();  // assign
00931       gVirtualX->SetPrimarySelectionOwner(fId);
00932    }
00933 }
00934 
00935 //______________________________________________________________________________
00936 void TGTextEntry::Paste()
00937 {
00938    // Inserts text at the cursor position, deleting any
00939    // previous marked text.
00940    // See also CopyText() Cut().
00941 
00942    if (gVirtualX->GetPrimarySelectionOwner() == kNone) {
00943       // No primary selection, so use the buffer
00944       if (fgClipboardText) Insert(fgClipboardText->Data());
00945    } else {
00946       gVirtualX->ConvertPrimarySelection(fId, fClipboard, 0);
00947    }
00948 }
00949 
00950 //______________________________________________________________________________
00951 void TGTextEntry::Cut()
00952 {
00953    // Copies the marked text to the clipboard and deletes it, if there is any.
00954    // See also CopyText() Paste().
00955 
00956    if (HasMarkedText()) {
00957       CopyText();
00958       Del();
00959    }
00960 }
00961 
00962 //______________________________________________________________________________
00963 void TGTextEntry::Clear(Option_t *)
00964 {
00965    // Clears up the text entry.
00966 
00967    SetText("");
00968 }
00969 
00970 //______________________________________________________________________________
00971 void TGTextEntry::Home(Bool_t mark)
00972 {
00973    // Moves the text cursor to the left end of the line. If mark is kTRUE text
00974    // will be marked towards the first position, if not any marked text will
00975    // be unmarked if the cursor is moved.
00976    // See also End().
00977 
00978    fOffset = 0;
00979    if (mark){
00980       fSelectionOn = kTRUE;
00981       fStartIX = fCursorIX;
00982       NewMark(0);
00983    } else {
00984       fSelectionOn = kFALSE;
00985       SetCursorPosition(0);
00986    }
00987 }
00988 
00989 //______________________________________________________________________________
00990 void TGTextEntry::End(Bool_t mark)
00991 {
00992    // Moves the text cursor to the right end of the line. If mark is kTRUE text
00993    // will be marked towards the last position, if not any marked text will
00994    // be unmarked if the cursor is moved.
00995    // See also Home().
00996 
00997    TString dt = GetDisplayText();
00998    Int_t len  = dt.Length();
00999 
01000    fOffset = (Int_t)GetWidth() - gVirtualX->TextWidth(fFontStruct, dt.Data(), len);
01001    if (fOffset > 0) fOffset = 0;
01002 
01003    if (mark){
01004       fSelectionOn = kTRUE;
01005       fStartIX = fCursorIX;
01006       NewMark(len);
01007    } else {
01008       fSelectionOn = kFALSE;
01009       SetCursorPosition(len);
01010    }
01011 }
01012 
01013 //______________________________________________________________________________
01014 void TGTextEntry::SelectAll()
01015 {
01016    // Selects all text (i.e. marks it) and moves the cursor to the
01017    // end. Useful when a default value has been inserted. If the user
01018    // types before clicking on the widget the selected text will be
01019    // erased.
01020 
01021    fSelectionOn = kTRUE;
01022    fStartIX = 0;
01023    NewMark(fText->GetTextLength());
01024    DoRedraw();
01025 }
01026 
01027 //______________________________________________________________________________
01028 void TGTextEntry::Deselect()
01029 {
01030    // Deselects all text (i.e. removes marking) and leaves the cursor at the
01031    // current position.
01032 
01033    fSelectionOn = kFALSE;
01034    fEndIX = fStartIX = fCursorIX;
01035    DoRedraw();
01036 }
01037 
01038 //______________________________________________________________________________
01039 void TGTextEntry::DrawBorder()
01040 {
01041    // Draw the border of the text entry widget.
01042 
01043    switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
01044       case kSunkenFrame | kDoubleBorder:
01045          gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
01046          gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
01047          gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
01048          gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
01049 
01050          gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
01051          gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
01052          gVirtualX->DrawLine(fId, GetBckgndGC()(),  1, fHeight-2, fWidth-2, fHeight-2);
01053          gVirtualX->DrawLine(fId, GetBckgndGC()(),  fWidth-2, 1, fWidth-2, fHeight-2);
01054          break;
01055 
01056       default:
01057          TGFrame::DrawBorder();
01058          break;
01059    }
01060 }
01061 
01062 //______________________________________________________________________________
01063 void TGTextEntry::DoRedraw()
01064 {
01065    // Draw the text entry widget.
01066 
01067    Int_t x, y, max_ascent, max_descent, h;
01068    Int_t offset = IsFrameDrawn() ? 4 : 0;
01069    TString dt  = GetDisplayText();               // text to be displayed
01070    Int_t len   = dt.Length();                    // length of displayed text
01071 
01072    // TGFrame::DoRedraw() == drawing border twice
01073    Int_t border = IsFrameDrawn() ? fBorderWidth : 0;
01074 
01075    gVirtualX->ClearArea(fId, border,  border,
01076             fWidth - (border << 1), fHeight - (border << 1));
01077 
01078    gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
01079 
01080    h = max_ascent + max_descent;
01081    y = (fHeight - h) >> 1 ;
01082    x = fOffset + offset;
01083 
01084    if (fEchoMode == kNoEcho) {
01085       fSelectionOn = kFALSE;
01086       fCursorX = offset;
01087    }
01088 
01089    if ((GetInsertMode() == kInsert) || (fEchoMode == kNoEcho)) {
01090       // line cursor
01091       if (fCursorOn) {
01092          gVirtualX->DrawLine(fId, GetBlackGC()(), fCursorX, y - 1,
01093                      fCursorX, h + 2);
01094       }
01095       gVirtualX->DrawString(fId, fNormGC(), x, y + max_ascent, dt.Data(), len);
01096 
01097    } else {
01098       // filled rectangle (block) cursor
01099       gVirtualX->DrawString(fId, fNormGC(), x, y + max_ascent, dt.Data(), len);
01100 
01101       if (fCursorOn) {
01102          Int_t ind       = fCursorIX < len-1 ? fCursorIX : len - 1;
01103          Int_t charWidth = ind < 0 ||  fCursorIX > len - 1 ? 4 :
01104                            gVirtualX->TextWidth(fFontStruct, &dt[ind],1);
01105 
01106          Int_t before = gVirtualX->TextWidth(fFontStruct, dt, fCursorIX) + x;
01107 
01108          gVirtualX->FillRectangle(fId, fSelbackGC , before, y ,
01109                                   charWidth , h + 1);
01110 
01111          if (fCursorIX < len)
01112             gVirtualX->DrawString(fId, fSelGC(), before, y + max_ascent, &dt[ind], 1);
01113       }
01114    }
01115 
01116    if (fSelectionOn) {
01117       int xs, ws, ixs, iws;
01118 
01119       xs  = TMath::Min(fStartX, fEndX);
01120       ws  = TMath::Abs(fEndX - fStartX);
01121       ixs = TMath::Min(fStartIX, fEndIX);
01122       iws = TMath::Abs(fEndIX - fStartIX);
01123 
01124       gVirtualX->FillRectangle(fId, fSelbackGC, xs, y, ws, h + 1);
01125 
01126       gVirtualX->DrawString(fId, fSelGC(), xs, y + max_ascent,
01127                             dt.Data() + ixs, iws);
01128    }
01129    if (IsFrameDrawn()) DrawBorder();
01130 }
01131 
01132 //______________________________________________________________________________
01133 Bool_t TGTextEntry::HandleKey(Event_t* event)
01134 {
01135    // The key press event handler converts a key press to some line editor
01136    // action. Here are the default key bindings:
01137    //Begin_Html
01138    //  <ul>
01139    //  <li><i> Left Arrow </i>
01140    //          Move the cursor one character leftwards.
01141    //          Scroll the text when  cursor is out of frame.
01142    //  <li><i> Right Arrow </i>
01143    //          Move the cursor one character rightwards
01144    //          Scroll the text when  cursor is out of frame.
01145    //  <li><i> Backspace </i>
01146    //          Deletes the character on the left side of the text cursor and moves the
01147    //          cursor one position to the left. If a text has been marked by the user
01148    //          (e.g. by clicking and dragging) the cursor will be put at the beginning
01149    //          of the marked text and the marked text will be removed.
01150    //  <li><i> Home </i>
01151    //          Moves the text cursor to the left end of the line. If mark is TRUE text
01152    //          will be marked towards the first position, if not any marked text will
01153    //          be unmarked if the cursor is moved.
01154    //  <li><i> End </i>
01155    //          Moves the text cursor to the right end of the line. If mark is TRUE text
01156    //          will be marked towards the last position, if not any marked text will
01157    //          be unmarked if the cursor is moved.
01158    //  <li><i> Delete </i>
01159    //          Deletes the character on the right side of the text cursor. If a text
01160    //          has been marked by the user (e.g. by clicking and dragging) the cursor
01161    //          will be put at the beginning of the marked text and the marked text will
01162    //          be removed.
01163    //  <li><i> Insert </i>
01164    //          Switches character insert mode.
01165    //  <li><i> Shift - Left Arrow </i>
01166    //          Mark text one character leftwards
01167    //  <li><i> Shift - Right Arrow </i>
01168    //          Mark text one character rightwards
01169    //  <li><i> Control - Left Arrow </i>
01170    //          Move the cursor one word leftwards
01171    //  <li><i> Control - Right Arrow </i>
01172    //          Move the cursor one word rightwards.
01173    //  <li><i> Control - Shift - Left Arrow </i>
01174    //          Mark text one word leftwards
01175    //  <li><i> Control - Shift - Right Arrow </i>
01176    //          Mark text one word rightwards
01177    //  <li><i> Control-A </i>
01178    //          Move the cursor to the beginning of the line
01179    //  <li><i> Control-B </i>
01180    //          Move the cursor one character leftwards
01181    //  <li><i> Control-C </i>
01182    //          Copy the marked text to the clipboard.
01183    //  <li><i> Control-D </i>
01184    //          Delete the character to the right of the cursor
01185    //  <li><i> Control-E </i>
01186    //          Move the cursor to the end of the line
01187    //  <li><i> Control-F </i>
01188    //          Move the cursor one character rightwards
01189    //  <li><i> Control-H </i>
01190    //          Delete the character to the left of the cursor
01191    //  <li><i> Control-K </i>
01192    //          Delete marked text if any or delete all
01193    //          characters to the right of the cursor
01194    //  <li><i> Control-U </i>
01195    //          Delete all characters on the line
01196    //  <li><i> Control-V </i>
01197    //          Paste the clipboard text into line edit.
01198    //  <li><i> Control-X </i>
01199    //          Cut the marked text, copy to clipboard.
01200    //  <li><i> Control-Y </i>
01201    //          Paste the clipboard text into line edit.
01202    //  </ul>
01203    //End_Html
01204    //  All other keys with valid ASCII codes insert themselves into the line.
01205 
01206    Int_t  n;
01207    char   tmp[10];
01208    UInt_t keysym;
01209 
01210    if (fTip && event->fType == kGKeyPress) fTip->Hide();
01211 
01212    if (!IsEnabled() || event->fType != kGKeyPress) return kTRUE;
01213 
01214    gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
01215    n = strlen(tmp);
01216    Int_t unknown = 0;
01217 
01218    if ((EKeySym)keysym  == kKey_Enter || (EKeySym)keysym  == kKey_Return) {
01219 
01220       ReturnPressed();                                      // emit signal
01221       if (!TestBit(kNotDeleted)) return kTRUE;
01222       fSelectionOn = kFALSE;
01223 
01224    } else if (event->fState & kKeyShiftMask && (EKeySym)keysym  == kKey_Backtab) {
01225          ShiftTabPressed();                               // emit signal
01226          fSelectionOn = kFALSE;
01227          return kTRUE;
01228 
01229    } else if ((EKeySym)keysym  == kKey_Tab) {
01230 
01231       TabPressed();                                         // emit signal
01232       fSelectionOn = kFALSE;
01233 
01234    } else if (event->fState & kKeyControlMask) {  // Cntrl key modifier pressed
01235       switch ((EKeySym)keysym & ~0x20) {     // treat upper and lower the same
01236       case kKey_A:
01237          Home(event->fState & kKeyShiftMask);
01238          break;
01239       case kKey_B:
01240          CursorLeft(event->fState & kKeyShiftMask);
01241          break;
01242       case kKey_C:
01243          CopyText();
01244          break;
01245       case kKey_D:
01246          Del();
01247          break;
01248       case kKey_E:
01249          End(event->fState & kKeyShiftMask);
01250          break;
01251       case kKey_F:
01252          CursorRight(event->fState & kKeyShiftMask);
01253          break;
01254       case kKey_H:
01255          Backspace();
01256          break;
01257       case kKey_K:
01258          HasMarkedText() ? Del() : Remove();
01259          break;
01260       case kKey_U:
01261          Home();
01262          Remove();
01263          break;
01264       case kKey_V:
01265          Paste();
01266          break;
01267       case kKey_X:
01268          Cut();
01269          break;
01270       case kKey_Y:
01271          Paste();
01272          break;
01273       case kKey_Right:
01274          CursorWordForward(event->fState & kKeyShiftMask);
01275          break;
01276       case kKey_Left:
01277          CursorWordBackward(event->fState & kKeyShiftMask);
01278          break;
01279       default:
01280          unknown++;
01281       }
01282    } else if (n && keysym <127 && keysym >=32  &&     // printable keys
01283                (EKeySym)keysym  != kKey_Delete &&
01284                (EKeySym)keysym  != kKey_Backspace) {
01285 
01286       Insert(tmp);
01287       fSelectionOn = kFALSE;
01288 
01289    } else {
01290       switch ((EKeySym)keysym) {
01291       case kKey_Down:
01292          CursorOutDown();
01293          break;
01294       case kKey_Up:
01295          CursorOutUp();
01296          break;
01297       case kKey_Left:
01298          CursorLeft(event->fState & kKeyShiftMask);
01299          break;
01300       case kKey_Right:
01301          CursorRight(event->fState & kKeyShiftMask);
01302          break;
01303       case kKey_Backspace:
01304          Backspace();
01305          break;
01306       case kKey_Home:
01307          Home(event->fState & kKeyShiftMask);
01308          break;
01309       case kKey_End:
01310          End(event->fState & kKeyShiftMask);
01311          break;
01312       case kKey_Delete:
01313          Del();
01314          break;
01315       case kKey_Insert:                     // switch on/off insert mode
01316          SetInsertMode(GetInsertMode() == kInsert ? kReplace : kInsert);
01317          break;
01318       default:
01319          unknown++;
01320       }
01321    }
01322 
01323    UpdateOffset();
01324    fClient->NeedRedraw(this);
01325 
01326    return kTRUE;
01327 }
01328 
01329 //______________________________________________________________________________
01330 Bool_t TGTextEntry::HandleButton(Event_t *event)
01331 {
01332    // Handle mouse button event in text entry widget.
01333 
01334    if (fTip) fTip->Hide();
01335 
01336    if (!IsEnabled()) return kTRUE;
01337 
01338    if (event->fType == kButtonPress) {
01339       SetFocus();
01340       if (fEchoMode == kNoEcho) return kTRUE;
01341 
01342       if (event->fCode == kButton1) {
01343          Int_t offset =  IsFrameDrawn() ? 4 : 0;
01344          Int_t x = fOffset + offset;
01345          Int_t position     = GetCharacterIndex(event->fX - x);
01346          fSelectionOn = kFALSE;
01347          SetCursorPosition(position);
01348          DoRedraw();
01349       } else if (event->fCode == kButton2) {
01350          if (gVirtualX->GetPrimarySelectionOwner() == kNone) {
01351             // No primary selection, so use the cut buffer
01352             PastePrimary(fClient->GetDefaultRoot()->GetId(), kCutBuffer, kFALSE);
01353          } else {
01354             gVirtualX->ConvertPrimarySelection(fId, fClipboard, event->fTime);
01355          }
01356       }
01357    }
01358    if (event->fType == kButtonRelease)
01359       if (event->fCode == kButton1)
01360          CopyText();
01361 
01362    return kTRUE;
01363 }
01364 
01365 //______________________________________________________________________________
01366 Bool_t TGTextEntry::HandleCrossing(Event_t *event)
01367 {
01368    // Handle mouse crossing event.
01369 
01370    if (event->fType == kEnterNotify) {
01371       if (fTip) fTip->Reset();
01372    } else {
01373       if (fTip) fTip->Hide();
01374    }
01375 
01376    return kTRUE;
01377 }
01378 
01379 //______________________________________________________________________________
01380 Bool_t TGTextEntry::HandleMotion(Event_t *event)
01381 {
01382    // Handle mouse motion event in the text entry widget.
01383 
01384    if (!IsEnabled() || (GetEchoMode() == kNoEcho)) return kTRUE;
01385 
01386    Int_t offset =  IsFrameDrawn() ? 4 : 0;
01387    Int_t x = fOffset + offset;
01388    Int_t position = GetCharacterIndex(event->fX - x); // + 1;
01389    fSelectionOn = kTRUE;
01390    NewMark(position);
01391    UpdateOffset();
01392    DoRedraw();
01393    return kTRUE;
01394 }
01395 
01396 //______________________________________________________________________________
01397 Bool_t TGTextEntry::HandleDoubleClick(Event_t *event)
01398 {
01399    // Handle mouse double click event in the text entry widget.
01400 
01401    if (!IsEnabled()) return kTRUE;
01402 
01403    Int_t offset = IsFrameDrawn() ? 4 : 0;
01404    Int_t x = fOffset + offset ;
01405 
01406    DoubleClicked();
01407    SetFocus();
01408    if (fEchoMode == kNoEcho) return kTRUE;
01409 
01410    Int_t position = GetCharacterIndex(event->fX  - x);
01411    MarkWord(position);
01412    return kTRUE;
01413 }
01414 
01415 //______________________________________________________________________________
01416 Bool_t TGTextEntry::HandleConfigureNotify(Event_t* event)
01417 {
01418    // Handles resize events for this widget.
01419 
01420    TGFrame::HandleConfigureNotify(event);
01421    UpdateOffset();
01422    return kTRUE;
01423 }
01424 
01425 //______________________________________________________________________________
01426 Bool_t TGTextEntry::HandleFocusChange(Event_t *event)
01427 {
01428    // Handle focus change event in text entry widget.
01429 
01430    if (!IsEnabled()) return kTRUE;
01431 
01432    // check this when porting to Win32
01433       if (event->fType == kFocusIn) {
01434          fCursorOn = kTRUE;
01435          if (!fCurBlink) fCurBlink = new TBlinkTimer(this, 500);
01436          fCurBlink->Reset();
01437          gBlinkingEntry = this;
01438          gSystem->AddTimer(fCurBlink);
01439       } else {
01440          fCursorOn = kFALSE;
01441           // fSelectionOn = kFALSE;        // "netscape location behavior"
01442          if (fCurBlink) fCurBlink->Remove();
01443          gBlinkingEntry = 0;
01444       }
01445       fClient->NeedRedraw(this);
01446    return kTRUE;
01447 }
01448 
01449 //______________________________________________________________________________
01450 Bool_t TGTextEntry::HandleSelection(Event_t *event)
01451 {
01452    // Handle text selection event.
01453 
01454    PastePrimary((Window_t)event->fUser[0], (Atom_t)event->fUser[3], kTRUE);
01455    return kTRUE;
01456 }
01457 
01458 //______________________________________________________________________________
01459 Bool_t TGTextEntry::HandleSelectionClear(Event_t * /*event*/)
01460 {
01461    // Handle selection clear event.
01462 
01463    fSelectionOn = kFALSE;
01464    fEndIX = fStartIX = fCursorIX;
01465    fClient->NeedRedraw(this);
01466    return kTRUE;
01467 }
01468 
01469 //______________________________________________________________________________
01470 Bool_t TGTextEntry::HandleSelectionRequest(Event_t *event)
01471 {
01472    // Handle request to send current clipboard contents to requestor window.
01473 
01474    Event_t reply;
01475    char   *buffer;
01476    Long_t  len;
01477    Atom_t targets[2];
01478    Atom_t type;
01479 
01480    reply.fType    = kSelectionNotify;
01481    reply.fTime    = event->fTime;
01482    reply.fUser[0] = event->fUser[0];     // requestor
01483    reply.fUser[1] = event->fUser[1];     // selection
01484    reply.fUser[2] = event->fUser[2];     // target
01485    reply.fUser[3] = event->fUser[3];     // property
01486 
01487    targets[0] = gVirtualX->InternAtom("TARGETS", kFALSE);
01488    targets[1] = gVirtualX->InternAtom("XA_STRING", kFALSE);
01489 
01490    if ((Atom_t)event->fUser[2] == targets[0]) {
01491       type = gVirtualX->InternAtom("XA_ATOM", kFALSE);
01492       gVirtualX->ChangeProperty((Window_t) event->fUser[0], (Atom_t) event->fUser[3],
01493                                 type, (UChar_t*) targets, (Int_t) 2);
01494 
01495       gVirtualX->SendEvent((Window_t)event->fUser[0], &reply);
01496       return kTRUE;
01497    }
01498 
01499    len = 0;
01500    if (fgClipboardText) len = fgClipboardText->Length();
01501    buffer = new char[len+1];
01502    if (fgClipboardText) strlcpy (buffer, fgClipboardText->Data(), len+1);
01503 
01504    gVirtualX->ChangeProperty((Window_t) event->fUser[0], (Atom_t) event->fUser[3],
01505                              (Atom_t) event->fUser[2], (UChar_t*) buffer,
01506                              (Int_t) len);
01507    delete [] buffer;
01508 
01509    gVirtualX->SendEvent((Window_t)event->fUser[0], &reply);
01510 
01511    return kTRUE;
01512 }
01513 
01514 //______________________________________________________________________________
01515 void TGTextEntry::PastePrimary(Window_t wid, Atom_t property, Bool_t del)
01516 {
01517    // Paste text from selection (either primary or cut buffer) into
01518    // text entry widget.
01519 
01520    TString data;
01521    Int_t   nchar;
01522 
01523    if (!IsEnabled()) return;
01524 
01525    gVirtualX->GetPasteBuffer(wid, property, data, nchar, del);
01526 
01527    if (nchar) Insert(data.Data());
01528    fClient->NeedRedraw(this);
01529 }
01530 
01531 //______________________________________________________________________________
01532 Bool_t TGTextEntry::HandleTimer(TTimer *)
01533 {
01534    // Handle cursor blink timer.
01535 
01536    fCursorOn = !fCursorOn;
01537    DoRedraw();
01538    return kTRUE;
01539 }
01540 
01541 //______________________________________________________________________________
01542 Bool_t TGTextEntry::IsCursorOutOfFrame()
01543 {
01544    // Returns kTRUE if cursor is out of frame.
01545 
01546    //   fCursorX = fOffset + 4 + gVirtualX->TextWidth(fFontStruct,
01547    //                                  GetDisplayText(), fCursorIX);
01548 
01549    Int_t offset =  IsFrameDrawn() ? 4 : 0;
01550    Int_t w = GetWidth();
01551    return ((fCursorX < offset) || (fCursorX > w-offset));
01552 }
01553 
01554 //______________________________________________________________________________
01555 void TGTextEntry::ScrollByChar()
01556 {
01557    // Shift position of cursor by one character.
01558 
01559    if (GetEchoMode() == kNoEcho) return;
01560 
01561    TString dt = GetDisplayText();
01562    Int_t len = dt.Length();
01563    Int_t ind = fCursorIX < len-1 ? fCursorIX : len-1;
01564    Int_t charWidth = ind < 0 ? 4 : gVirtualX->TextWidth(fFontStruct, &dt[ind],1);
01565    Int_t w = GetWidth();
01566    Int_t d;
01567    Int_t offset =  IsFrameDrawn() ? 4 : 0;
01568 
01569    if (fCursorX < offset) {
01570       fOffset += charWidth;
01571       fCursorX += charWidth;
01572       d = fCursorX;
01573 
01574       if (d < offset){          // correction
01575          d -= offset;
01576          fOffset -= d;
01577          fCursorX -= d;
01578          charWidth += d;
01579       }
01580    } else if (fCursorX > w-offset) {
01581       fOffset -= charWidth;
01582       fCursorX -= charWidth;
01583       d = w - fCursorX;
01584 
01585       if (d < offset) {        // correction
01586          d -= offset;
01587          fOffset += d;
01588          fCursorX += d;
01589          charWidth += d;
01590       }
01591    }
01592 }
01593 
01594 //______________________________________________________________________________
01595 void TGTextEntry::UpdateOffset()
01596 {
01597    // Updates start text offset according GetAlignment() mode,
01598    // if cursor is out of frame => scroll the text.
01599    // See also SetAlignment() and ScrollByChar().
01600 
01601    TString dt = GetDisplayText();
01602    Int_t textWidth = gVirtualX->TextWidth(fFontStruct, dt.Data() , dt.Length());
01603    Int_t offset = IsFrameDrawn() ? 4 : 0;
01604    Int_t w = GetWidth() - 2 * offset;   // subtract border twice
01605 
01606    if (textWidth > 0 && textWidth > w) {                          // may need to scroll.
01607       if (IsCursorOutOfFrame()) ScrollByChar();
01608    }
01609    else if (fAlignment == kTextRight)   fOffset = w - textWidth - 1;
01610    else if (fAlignment == kTextCenterX) fOffset = (w - textWidth)/2;
01611    else if (fAlignment == kTextLeft)    fOffset = 0;
01612 }
01613 
01614 //______________________________________________________________________________
01615 void TGTextEntry::SetToolTipText(const char *text, Long_t delayms)
01616 {
01617    // Set tool tip text associated with this text entry. The delay is in
01618    // milliseconds (minimum 250). To remove tool tip call method with
01619    // text = 0.
01620 
01621    if (fTip) {
01622       delete fTip;
01623       fTip = 0;
01624    }
01625 
01626    if (text && strlen(text))
01627       fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
01628 }
01629 
01630 //______________________________________________________________________________
01631 void TGTextEntry::SetFocus()
01632 {
01633    // Set focus to this text entry.
01634 
01635    if (gBlinkingEntry && (gBlinkingEntry != this)) {
01636       gBlinkingEntry->fCurBlink->Remove();
01637    }
01638    RequestFocus();
01639 }
01640 
01641 //_____________________________________________________________________
01642 void TGTextEntry::InsertText(const char *text, Int_t pos)
01643 {
01644    // Inserts text at position pos, clears the selection and moves
01645    // the cursor to the end of the line.
01646    // If necessary the text is truncated to fit MaxLength().
01647    // See also GetText(), SetText(), AppendText(), RemoveText().
01648 
01649    Int_t position = TMath::Min((Int_t)fText->GetTextLength(), pos);
01650    TString newText(GetText());
01651    newText.Insert(position, text);
01652    SetText(newText.Data());
01653 }
01654 
01655 //_____________________________________________________________________
01656 void TGTextEntry::AppendText(const char *text)
01657 {
01658    // Appends text to the end of text entry, clears the selection
01659    // and moves the cursor to the end of the line.
01660    // If necessary the text is truncated to fit MaxLength().
01661    // See also GetText(), InsertText(), SetText(), RemoveText().
01662 
01663    InsertText(text, fText->GetTextLength());
01664 }
01665 
01666 //_____________________________________________________________________
01667 void TGTextEntry::RemoveText(Int_t start, Int_t end)
01668 {
01669    // Removes text at the range, clears the selection and moves
01670    // the cursor to the end of the line.
01671    // See also GetText(), InsertText(), SetText(), AppendText().
01672 
01673    Int_t pos = TMath::Min(start, end);
01674    Int_t len = TMath::Abs(end-start);
01675    TString newText(GetText());
01676    newText.Remove(pos, len);
01677    SetText(newText.Data());
01678 }
01679 
01680 
01681 //______________________________________________________________________________
01682 void TGTextEntry::SetFont(FontStruct_t font, Bool_t local)
01683 {
01684    // Changes text font.
01685    // If local is kTRUE font is changed locally.
01686 
01687    if (font == fFontStruct) return;
01688 
01689    FontH_t v = gVirtualX->GetFontHandle(font);
01690 
01691    if (!v) return;
01692 
01693    if (local) {
01694       TGGC *gc = new TGGC(fNormGC); // copy
01695       fHasOwnFont = kTRUE;
01696       fNormGC = *gc;
01697       gc = new TGGC(fSelGC); // copy
01698       fSelGC = *gc;
01699    }
01700    fNormGC.SetFont(v);
01701    fSelGC.SetFont(v);
01702    fFontStruct = font;
01703    fClient->NeedRedraw(this);
01704 }
01705 
01706 //______________________________________________________________________________
01707 void TGTextEntry::SetFont(const char *fontName, Bool_t local)
01708 {
01709    // Changes text font specified by name.
01710    // If local is kTRUE font is changed locally.
01711 
01712    TGFont *font = fClient->GetFont(fontName);
01713    if (font) {
01714       SetFont(font->GetFontStruct(), local);
01715    }
01716 }
01717 
01718 //______________________________________________________________________________
01719 void TGTextEntry::SetFont(TGFont *font, Bool_t local)
01720 {
01721    // Changes text font specified by pointer to TGFont object.
01722    // If local is kTRUE font is changed locally.
01723 
01724    if (font) {
01725       SetFont(font->GetFontStruct(), local);
01726    }
01727 }
01728 
01729 //______________________________________________________________________________
01730 void TGTextEntry::SetTextColor(Pixel_t color, Bool_t local)
01731 {
01732    // Changes text color.
01733    // If local is true color is changed locally.
01734 
01735    if (local) {
01736       TGGC *gc = new TGGC(fNormGC); // copy
01737       fHasOwnFont = kTRUE;
01738       fNormGC = *gc;
01739    }
01740 
01741    fNormGC.SetForeground(color);
01742    fClient->NeedRedraw(this);
01743 }
01744 
01745 //______________________________________________________________________________
01746 void TGTextEntry::SetTextColor(TColor *color, Bool_t local)
01747 {
01748    // Changes text color.
01749    // If local is true color is changed locally.
01750 
01751    if (color) {
01752       SetTextColor(color->GetPixel(), local);
01753    }
01754 }
01755 
01756 //______________________________________________________________________________
01757 FontStruct_t TGTextEntry::GetDefaultFontStruct()
01758 {
01759    // Return default font structure in use.
01760 
01761    if (!fgDefaultFont)
01762       fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
01763    return fgDefaultFont->GetFontStruct();
01764 }
01765 
01766 //______________________________________________________________________________
01767 const TGGC &TGTextEntry::GetDefaultGC()
01768 {
01769    // Return default graphics context.
01770 
01771    if (!fgDefaultGC)
01772       fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
01773    return *fgDefaultGC;
01774 }
01775 
01776 //______________________________________________________________________________
01777 const TGGC &TGTextEntry::GetDefaultSelectedGC()
01778 {
01779    // Return selection graphics context.
01780 
01781    if (!fgDefaultSelectedGC)
01782       fgDefaultSelectedGC = gClient->GetResourcePool()->GetSelectedGC();
01783    return *fgDefaultSelectedGC;
01784 }
01785 
01786 //______________________________________________________________________________
01787 const TGGC &TGTextEntry::GetDefaultSelectedBackgroundGC()
01788 {
01789    // Return graphics context for highlighted frame background.
01790 
01791    if (!fgDefaultSelectedBackgroundGC)
01792       fgDefaultSelectedBackgroundGC = gClient->GetResourcePool()->GetSelectedBckgndGC();
01793    return *fgDefaultSelectedBackgroundGC;
01794 }
01795 
01796 //______________________________________________________________________________
01797 void TGTextEntry::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
01798 {
01799    // Save a text entry widget as a C++ statement(s) on output stream out.
01800 
01801    char quote = '"';
01802 
01803    // font + GC
01804    option = GetName()+5;         // unique digit id of the name
01805    TString parGC, parFont;
01806    parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
01807    parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
01808 
01809    if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC.GetGC())) {
01810       TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
01811       if (ufont) {
01812          ufont->SavePrimitive(out, option);
01813          parFont.Form("ufont->GetFontStruct()");
01814       }
01815 
01816       TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC.GetGC());
01817       if (userGC) {
01818          userGC->SavePrimitive(out, option);
01819          parGC.Form("uGC->GetGC()");
01820       }
01821    }
01822 
01823    if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
01824 
01825    out << "   TGTextEntry *";
01826    out << GetName() << " = new TGTextEntry(" << fParent->GetName()
01827        << ", new TGTextBuffer(" << GetBuffer()->GetBufferLength() << ")";
01828 
01829    if (fBackground == GetWhitePixel()) {
01830       if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
01831          if (fFontStruct == GetDefaultFontStruct()) {
01832             if (fNormGC() == GetDefaultGC()()) {
01833                if (fWidgetId == -1) {
01834                   out <<");" << endl;
01835                } else {
01836                   out << "," << fWidgetId << ");" << endl;
01837                }
01838             } else {
01839                out << "," << fWidgetId << "," << parGC.Data() << ");" << endl;
01840             }
01841          } else {
01842             out << "," << fWidgetId << "," << parGC.Data() << "," << parFont.Data()
01843                 <<");" << endl;
01844          }
01845       } else {
01846          out << "," << fWidgetId << "," << parGC.Data() << "," << parFont.Data()
01847              << "," << GetOptionString() << ");" << endl;
01848       }
01849    } else {
01850       out << "," << fWidgetId << "," << parGC.Data() << "," << parFont.Data()
01851           << "," << GetOptionString() << ",ucolor);" << endl;
01852    }
01853    if (option && strstr(option, "keep_names"))
01854       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
01855 
01856    out << "   " << GetName() << "->SetMaxLength(" << GetMaxLength() << ");" << endl;
01857 
01858    out << "   " << GetName() << "->SetAlignment(";
01859 
01860    if (fAlignment == kTextLeft)
01861       out << "kTextLeft);"    << endl;
01862 
01863    if (fAlignment == kTextRight)
01864       out << "kTextRight);"   << endl;
01865 
01866    if (fAlignment == kTextCenterX)
01867       out << "kTextCenterX);" << endl;
01868 
01869    out << "   " << GetName() << "->SetText(" << quote << GetText() << quote
01870        << ");" << endl;
01871 
01872    out << "   " << GetName() << "->Resize("<< GetWidth() << "," << GetName()
01873        << "->GetDefaultHeight());" << endl;
01874 
01875    if ((fDefWidth > 0) || (fDefHeight > 0)) {
01876       out << "   " << GetName() << "->SetDefaultSize(";
01877       out << fDefWidth << "," << fDefHeight << ");" << endl;
01878    }
01879 
01880    if (fTip) {
01881       TString tiptext = fTip->GetText()->GetString();
01882       tiptext.ReplaceAll("\n", "\\n");
01883       out << "   ";
01884       out << GetName() << "->SetToolTipText(" << quote
01885           << tiptext << quote << ");"  << endl;
01886    }
01887 }

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