    // @(#)root/treeviewer:$Name:  $:$Id: TTVLVContainer.cxx,v 1.10 2003/07/15 14:25:22 brun Exp $
    //Author : Andrei Gheata   16/08/00

    /*************************************************************************
     * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
     * All rights reserved.                                                  *
     *                                                                       *
     * For the licensing terms see $ROOTSYS/LICENSE.                         *
     * For the list of contributors see $ROOTSYS/README/CREDITS.             *
     *************************************************************************/

    #include "TTVLVContainer.h"
    #include "TTreeViewer.h"
    #include "TGPicture.h"
    #include "TGLabel.h"
    #include "TGButton.h"
    #include "TGTextEntry.h"
    #include "TGToolTip.h"
    #include "TList.h"

    ClassImp(TGItemContext)

    //////////////////////////////////////////////////////////////////////////
    // TGItemContext  -  empty object used as context menu support for      //
    // TGLVTreeEntries                                                      //
    //////////////////////////////////////////////////////////////////////////

    //______________________________________________________________________________
     TGItemContext::TGItemContext()
    {
       fItem = 0;
    }
    //______________________________________________________________________________
     void TGItemContext::Draw(Option_t *)
    {
       fItem->GetContainer()->GetViewer()->ProcessMessage(MK_MSG(kC_CONTAINER, kCT_ITEMDBLCLICK), kButton1, 0);
    }
    //______________________________________________________________________________
     void TGItemContext::EditExpression()
    {
       fItem->GetContainer()->GetViewer()->EditExpression();
    }
    //______________________________________________________________________________
     void TGItemContext::Empty()
    {
       fItem->Empty();
    }
    //______________________________________________________________________________
     void TGItemContext::RemoveItem()
    {
       fItem->GetContainer()->GetViewer()->RemoveItem();
    }
    //______________________________________________________________________________
     void TGItemContext::Scan()
    {
       fItem->GetContainer()->GetViewer()->SetScanMode();
       fItem->GetContainer()->GetViewer()->ProcessMessage(MK_MSG(kC_CONTAINER, kCT_ITEMDBLCLICK), kButton1, 0);
    }
    //______________________________________________________________________________
     void TGItemContext::SetExpression(const char *name, const char *alias, Bool_t cut)
    {
       fItem->SetExpression(name, alias, cut);
    }

    ClassImp(TTVLVEntry)

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    // TGTreeLVEntry is a TGLVEntry that has a name of a variable to be     //
    // draw by the TTreeViewer GUI, and an alias for it.                    //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    //______________________________________________________________________________
    TTVLVEntry::TTVLVEntry(const TGWindow *p,
                                 const TGPicture *bigpic, const TGPicture *smallpic,
                                 TGString *name, TGString **subnames,
                                 EListViewMode ViewMode)
                  :TGLVEntry(p, bigpic, smallpic, name, subnames, ViewMode)
    {
       // TGTreeLVEntry constructor.

       // both alias and true name are initialized to name
       fTrueName.InitialCapacity(1000);
       fContainer = (TTVLVContainer *) p;

       fTip = 0;
       fIsCut = kFALSE;
       fTrueName = name->GetString();
       fContext = new TGItemContext();
       fContext->Associate(this);

       AddInput(kEnterWindowMask | kLeaveWindowMask);
    }
    //______________________________________________________________________________
    TTVLVEntry::~TTVLVEntry()
    {
    // TGTreeLVEntry destructor
       if (fTip) delete fTip;
       delete fContext;
    }
    //______________________________________________________________________________
    const char *TTVLVEntry::ConvertAliases()
    {
    // Convert all aliases into true names
       TList *list = GetContainer()->GetViewer()->ExpressionList();
       fConvName = fTrueName;
       TString start(fConvName);
       TIter next(list);
       TTVLVEntry* item;
       while (!FullConverted()) {
          next.Reset();
          start = fConvName;
          while ((item=(TTVLVEntry*)next())) {
             if (item != this)
                fConvName.ReplaceAll(item->GetAlias(), item->GetTrueName());
          }
          if (fConvName == start) {
             Warning(item->GetAlias(), "Cannot convert aliases for this expression.");
             return(fConvName.Data());
          }
       }
       return(fConvName.Data());
    }
    //______________________________________________________________________________
    Bool_t TTVLVEntry::FullConverted()
    {
    // Return true if converted name is alias free
       TList *list = GetContainer()->GetViewer()->ExpressionList();
       TIter next(list);
       TTVLVEntry* item;
       while ((item=(TTVLVEntry*)next())) {
          if (item != this) {
             if (fConvName.Contains(item->GetAlias())) return kFALSE;
          }
       }
       return kTRUE;
    }
    //______________________________________________________________________________
    void TTVLVEntry::CopyItem(TTVLVEntry *dest)
    {
       // Copy this item's name and alias to an other.
       if (!dest) return;
       dest->SetExpression(fTrueName.Data(), fAlias.Data(), fIsCut);
       TString alias = dest->GetAlias();
       if (!alias.BeginsWith("~") && !alias.Contains("empty")) dest->PrependTilde();
    }
    //______________________________________________________________________________
    Bool_t TTVLVEntry::HandleCrossing(Event_t *event)
    {
    // Handle mouse crossing event.
       if (fTip) {
          if (event->fType == kEnterNotify)
             fTip->Reset();
          else
             fTip->Hide();
       }
       return kTRUE;
    }
    //______________________________________________________________________________
    Bool_t TTVLVEntry::HasAlias()
    {
       // Check if alias name is not empty.

       if (fAlias.Length()) return kTRUE;
       return kFALSE;
    }
    //______________________________________________________________________________
    void TTVLVEntry::PrependTilde()
    {
    // Prepend a ~ to item alias
       fAlias = "~" + fAlias;
       SetItemName(fAlias.Data());
    }
    //______________________________________________________________________________
    void TTVLVEntry::SetItemName(const char* name)
    {
    // redraw this entry with new name
       if (fName) delete fName;
       fName = new TGString(name);
       Int_t max_ascent, max_descent;
       fTWidth = gVirtualX->TextWidth(fFontStruct, fName->GetString(), fName->GetLength());
       gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
       fTHeight = max_ascent + max_descent;
       gVirtualX->ClearWindow(fId);
       Resize(GetDefaultSize());
       fClient->NeedRedraw(this);
    }
    //______________________________________________________________________________
    void TTVLVEntry::SetCutType(Bool_t type)
    {
          if (fIsCut && type) return;
          if (!fIsCut && !type) return;
          if (type) {
             SetSmallPic(fClient->GetPicture("selection_t.xpm"));
             SetToolTipText("Selection expression. Drag to scissors to activate");
          } else
             SetSmallPic(fClient->GetPicture("expression_t.xpm"));
          fIsCut = type;
    }
    //______________________________________________________________________________
    void TTVLVEntry::SetExpression(const char* name, const char* alias, Bool_t cutType)
    {
       // Set the true name, alias and type of the expression, then refresh it
       SetItemName(alias);
       SetAlias(alias);
       SetTrueName(name);
       ULong_t *itemType = (ULong_t *) GetUserData();
       if (*itemType & TTreeViewer::kLTPackType) {
          if (strlen(name))
             SetSmallPic(fClient->GetPicture("pack_t.xpm"));
          else
             SetSmallPic(fClient->GetPicture("pack-empty_t.xpm"));
       }
       if ((*itemType & TTreeViewer::kLTDragType) && strlen(name) && !fIsCut)
          SetToolTipText("Double-click to draw. Drag and drop. Use Edit/Expression or context menu to edit.");
       if (*itemType & TTreeViewer::kLTDragType) SetCutType(cutType);
    }
    //______________________________________________________________________________
    void TTVLVEntry::Empty()
    {
       // clear all names and alias
       SetExpression("","-empty-");
       ULong_t *itemType = (ULong_t *) GetUserData();
       if (itemType && (*itemType & TTreeViewer::kLTDragType))
          SetToolTipText("User-defined expression/cut. Double-click to edit");
    }
    //______________________________________________________________________________
    void TTVLVEntry::SetToolTipText(const char *text, Long_t delayms)
    {
       // Set tool tip text associated with this item. The delay is in
       // milliseconds (minimum 250). To remove tool tip call method with text = 0
       if (fTip) {
          delete fTip;
          fTip = 0;
       }

       if (text && strlen(text))
          fTip = new TGToolTip(fClient->GetRoot(), this, text, delayms);
    }
    //______________________________________________________________________________
    void TTVLVEntry::SetSmallPic(const TGPicture *spic)
    {
       const TGPicture *cspic = fSmallPic;
       fSmallPic = spic;
       fCurrent = fSmallPic;
       if (fSelPic) delete fSelPic;
       fSelPic = 0;
       if (fActive) {
          fSelPic = new TGSelectedPicture(fClient, fCurrent);
       }
       DoRedraw();
       fClient->FreePicture(cspic);
    }

    ClassImp(TTVLVContainer)

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    //   TTVLVContainer                                                     //
    //                                                                      //
    // This class represent the list view container for the.                //
    // TreeView class. It is a TGLVContainer with item dragging             //
    // capabilities for the TTVLVEntry objects inside.                      //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    //______________________________________________________________________________
    TTVLVContainer::TTVLVContainer(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options)
              :TGLVContainer(p, w, h,options | kSunkenFrame)
    {
       // TGLVContainer constructor

       fListView = 0;
       fViewer = 0;
       fExpressionList = new TList;
       fCursor = gVirtualX->CreateCursor(kMove);
       fDefaultCursor = gVirtualX->CreateCursor(kPointer);
       fMapSubwindows = kTRUE;
    }

    //______________________________________________________________________________
    TTVLVContainer::~TTVLVContainer()
    {
       // TGLVContainer destructor

       delete fExpressionList;
    }

    //______________________________________________________________________________
    const char* TTVLVContainer::Cut()
    {
       // return the cut entry

       TGFrameElement *el = (TGFrameElement *) fList->At(3);
       if (el) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (f) return f->ConvertAliases();
          return 0;
       }
       return 0;
    }

    //______________________________________________________________________________
    TTVLVEntry * TTVLVContainer::ExpressionItem(Int_t index)
    {
       // return the expression item at specific position

       TGFrameElement *el = (TGFrameElement *) fList->At(index);
       if (el) {
          TTVLVEntry *item = (TTVLVEntry *) el->fFrame;
          return item;
       }
       return 0;
    }

    //______________________________________________________________________________
    TList* TTVLVContainer::ExpressionList()
    {
       // return the list of user-defined expressions

       fExpressionList->Clear();
       TIter next(fList);
       TGFrameElement *el;
       while ((el = (TGFrameElement*)next())) {
          TTVLVEntry *item = (TTVLVEntry *)el->fFrame;
          if (item) {
             ULong_t *itemType = (ULong_t *) item->GetUserData();
             if ((*itemType & TTreeViewer::kLTExpressionType) &&
                (*itemType & TTreeViewer::kLTDragType)) fExpressionList->Add(item);
          }
       }
       return fExpressionList;
    }

    //______________________________________________________________________________
    const char* TTVLVContainer::Ex()
    {
       // return the expression on X

       TGFrameElement *el = (TGFrameElement *) fList->At(0);
       if (el) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (f) return f->ConvertAliases();
          return 0;
       }
       return 0;
    }

    //______________________________________________________________________________
    const char* TTVLVContainer::Ey()
    {
       // return the expression on Y

       TGFrameElement *el = (TGFrameElement *) fList->At(1);
       if (el) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (f) return f->ConvertAliases();
          return 0;
       }
       return 0;
    }

    //______________________________________________________________________________
    const char* TTVLVContainer::Ez()
    {
       // return the expression on Z

       TGFrameElement *el = (TGFrameElement *) fList->At(2);
       if (el) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (f) return f->ConvertAliases();
          return 0;
       }
       return 0;
    }

    //______________________________________________________________________________
    const char* TTVLVContainer::ScanList()
    {
       // return the cut entry

       TGFrameElement *el = (TGFrameElement *) fList->At(4);
       if (el) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (f) return f->GetTrueName();
          return 0;
       }
       return 0;
    }

    //______________________________________________________________________________
    Bool_t TTVLVContainer::HandleButton(Event_t *event)
    {
       // Handle mouse button event in container.

       int total, selected;

       if (event->fType == kButtonPress) {
          fXp = event->fX;
          fYp = event->fY;
          if (fLastActive) {
             fLastActive->Activate(kFALSE);
             fLastActive = 0;
          }
          total = selected = 0;

          TGFrameElement *el;
          TIter next(fList);
          while ((el = (TGFrameElement *) next())) {
             TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
             ++total;
             if (f->GetId() == (Window_t)event->fUser[0]) {  // fUser[0] = subwindow
                f->Activate(kTRUE);
                if (f->GetTip()) (f->GetTip())->Hide();
                fX0 = f->GetX();
                fY0 = f->GetY();
                ++selected;
                fLastActive = f;
             } else {
                f->Activate(kFALSE);
             }
          }

          if (fTotal != total || fSelected != selected) {
             fTotal = total;
             fSelected = selected;
             SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
                         fTotal, fSelected);
          }

          if (selected == 1 && event->fCode == 1) {
             ULong_t *itemType = (ULong_t *) fLastActive->GetUserData();
             if (*itemType & TTreeViewer::kLTDragType) {
                fDragging = kTRUE;
                gVirtualX->SetCursor(fId,fCursor);
                fXp = event->fX;
                fYp = event->fY;
             }
          }
       }

       if (event->fType == kButtonRelease) {
          if (fDragging) {
             fDragging = kFALSE;
               gVirtualX->SetCursor(fId,fDefaultCursor);
               fLastActive->Move(fX0,fY0);
               TGFrameElement *el;
               TIter next(fList);
               while ((el = (TGFrameElement *) next())) {
                  TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
                  if ((f == fLastActive) || !f->IsActive()) continue;
                  ULong_t *itemType = (ULong_t *) f->GetUserData();
                  fLastActive->Activate(kFALSE);
                  if (!(*itemType & TTreeViewer::kLTPackType)) {
                     // dragging items to expressions
                     ((TTVLVEntry *) fLastActive)->CopyItem(f);
                     if (*itemType & TTreeViewer::kLTDragType)
                        f->SetToolTipText("Double-click to draw. Drag and drop. Use Edit/Expression or context menu to edit.");
                  } else {
                     if (strlen(((TTVLVEntry *) fLastActive)->GetTrueName())) {
                        // dragging to scan box
                        if (!strlen(f->GetTrueName())) {
                           f->SetTrueName(((TTVLVEntry *)fLastActive)->GetTrueName());
                           f->SetSmallPic(fClient->GetPicture("pack_t.xpm"));
                        } else {
                           TString name(2000);
                           TString dragged = ((TTVLVEntry *)fLastActive)->ConvertAliases();
                           name  = f->GetTrueName();
                           if ((name.Length()+dragged.Length()) < 228) {
                              name += ":";
                              name += dragged;
                              f->SetTrueName(name.Data());
                           } else {
                              Warning("HandleButton",
                                      "Name too long. Can
                           }
                        }
                     }
                  }
                  fLastActive = f;
                  if (fViewer) {
                      char msg[2000];
                      msg[0] = 0;
                      sprintf(msg, "Content : %s", f->GetTrueName());
                      fViewer->Message(msg);
                  }
               }
               if ((TMath::Abs(event->fX - fXp) < 2) && (TMath::Abs(event->fY - fYp) < 2)) {
                  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                              event->fCode, (event->fYRoot << 16) | event->fXRoot);
               }
          } else {
             SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                         event->fCode, (event->fYRoot << 16) | event->fXRoot);
          }
       }
       return kTRUE;
    }

    //______________________________________________________________________________
    Bool_t TTVLVContainer::HandleMotion(Event_t *event)
    {
       // Handle mouse motion events.

       Int_t xf0, xff, yf0, yff;
       Int_t xpos = event->fX - (fXp-fX0);
       Int_t ypos = event->fY - (fYp-fY0);

       if (fDragging) {
          TGFrameElement *el;
          ULong_t *itemType;
          TIter next(fList);
          while ((el = (TGFrameElement *) next())) {
             TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
             if (f == fLastActive) {
                if (f->GetTip()) (f->GetTip())->Hide();
                continue;
             }
             xf0 = f->GetX();
             yf0 = f->GetY();
             xff = f->GetX() + f->GetWidth();
             yff = f->GetY() + f->GetHeight();
             itemType = (ULong_t *) f->GetUserData();
             if (*itemType & TTreeViewer::kLTExpressionType) {
                if (xpos>xf0 && xpos<xff && ypos>yf0 && ypos<yff) {
                   f->Activate(kTRUE);
                } else {
                   f->Activate(kFALSE);
                }
             }
          }
          if ((fXp - event->fX) > 10) {
             fListView->SetHsbPosition(0);
             fListView->SetVsbPosition(0);
          }
          fLastActive->Move(xpos, ypos);
          gVirtualX->RaiseWindow(fLastActive->GetId());
          SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER,(EWidgetMessageTypes)4),event->fX, event->fY);
       }
       return kTRUE;
    }

    //______________________________________________________________________________
    void TTVLVContainer::EmptyAll()
    {
       // Clear all names and aliases for expression type items

       TGFrameElement *el;
       TIter next(fList);
       while ((el = (TGFrameElement *) next())) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          UInt_t *userData = (UInt_t *) f->GetUserData();
          if (*userData & TTreeViewer::kLTExpressionType) {
             if (*userData & TTreeViewer::kLTPackType) {
                f->SetSmallPic(fClient->GetPicture("pack-empty_t.xpm"));
                f->SetTrueName("");
             } else {
                f->Empty();
             }
          }
       }
    }

    //______________________________________________________________________________
    void TTVLVContainer::RemoveNonStatic()
    {
       // remove all non-static items from the list view, except expressions

       TGFrameElement *el;
       TIter next(fList);
       while ((el = (TGFrameElement *) next())) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          UInt_t *userData = (UInt_t *) f->GetUserData();
          if (!((*userData) & TTreeViewer::kLTExpressionType)) {
             RemoveItem(f);
          }
       }
    }

    //______________________________________________________________________________
    void TTVLVContainer::SelectItem(const char* name)
    {
       // select an item

       if (fLastActive) {
          fLastActive->Activate(kFALSE);
          fLastActive = 0;
       }
       TGFrameElement *el;
       fSelected = 0;
       TIter next(fList);
       while ((el = (TGFrameElement *) next())) {
          TTVLVEntry *f = (TTVLVEntry *) el->fFrame;
          if (!strcmp(f->GetItemName()->GetString(),name)) {
             f->Activate(kTRUE);
             fLastActive = (TGLVEntry *) f;
             fSelected++;
          } else {
             f->Activate(kFALSE);
          }
       }
    }

    ClassImp(TGSelectBox)

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    //   TGSelectBox                                                        //
    //                                                                      //
    // This class represent a specialized expression editor for             //
    // TTVLVEntry 'true name' and 'alias' data members.                     //
    // It is a singleton in order to be able to use it for several          //
    // expressions.                                                         //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    enum ETransientFrameCommands {
       kTFDone,
       kTFCancel
    };

    TGSelectBox* TGSelectBox::fInstance = 0;

    //______________________________________________________________________________
    TGSelectBox::TGSelectBox(const TGWindow *p, const TGWindow *main,
                             UInt_t w, UInt_t h)
                :TGTransientFrame(p, main, w, h)
    {
       // TGSelectBox constructor

       if (!fInstance) {
          fInstance = this;
          fViewer = (TTreeViewer *)fMain;
          if (!fViewer) Error("TGSelectBox", "Must be started from viewer");
          fEntry = 0;
          fLayout = new TGLayoutHints(kLHintsTop | kLHintsCenterY | kLHintsExpandX, 0, 0, 0, 2);
          fBLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 2, 2, 2);
          fBLayout1= new TGLayoutHints(kLHintsTop | kLHintsRight, 2, 0, 2, 2);

          fLabel = new TGLabel(this, "");
          AddFrame(fLabel,fLayout);

          fTe = new TGTextEntry(this, new TGTextBuffer(2000));
          fTe->SetToolTipText("Type an expression using C++ syntax. Click other expression/leaves to paste them here.");
          AddFrame(fTe, fLayout);

          fLabelAlias = new TGLabel(this, "Alias");
          AddFrame(fLabelAlias,fLayout);

          fTeAlias = new TGTextEntry(this, new TGTextBuffer(100));
          fTeAlias->SetToolTipText("Define an alias for this expression. Do NOT use leading strings of other aliases.");
          AddFrame(fTeAlias, fLayout);

          fBf = new TGHorizontalFrame(this, 10, 10);

          fCANCEL = new TGTextButton(fBf, "&Cancel", kTFCancel);
          fCANCEL->Associate(this);
          fBf->AddFrame(fCANCEL, fBLayout);

          fDONE = new TGTextButton(fBf, "&Done", kTFDone);
          fDONE->Associate(this);
          fBf->AddFrame(fDONE, fBLayout1);

          AddFrame(fBf, fLayout);

          MapSubwindows();
          Resize(GetDefaultSize());

    //      SetBackgroundColor(color);
          Window_t wdum;
          Int_t ax, ay;
          gVirtualX->TranslateCoordinates(main->GetId(), GetParent()->GetId(), 25,
                            (Int_t)(((TGFrame *) main)->GetHeight() - fHeight) >> 1,
                            ax, ay, wdum);
          MoveResize(ax, ay, w, GetDefaultHeight());
          MapWindow();
       }
    }

    //______________________________________________________________________________
    TGSelectBox::~TGSelectBox()
    {
       // TGSelectBox destructor

       fInstance = 0;
       delete fLabel;
       delete fTe;
       delete fLabelAlias;
       delete fTeAlias;
       delete fDONE;
       delete fCANCEL;
       delete fBf;
       delete fLayout;
       delete fBLayout;
       delete fBLayout1;
    }

    //______________________________________________________________________________
    void TGSelectBox::CloseWindow()
    {
       // close the select box

       gVirtualX->UnmapWindow(GetId());
       delete this;
    }

    //______________________________________________________________________________
    TGSelectBox * TGSelectBox::GetInstance()
    {
       // return the pointer to the instantiated singleton

       return fInstance;
    }

    //______________________________________________________________________________
    void TGSelectBox::GrabPointer()
    {
       // just focus the cursor inside

       Event_t event;
       event.fType = kButtonPress;
       event.fCode = kButton1;
       Int_t position = fTe->GetCursorPosition();
       fTe->HandleButton(&event);
       fTe->SetCursorPosition(position);
    }

    //______________________________________________________________________________
    void TGSelectBox::SetLabel(const char* title)
    {
       fLabel->SetText(new TGString(title));
    }

    //______________________________________________________________________________
    void TGSelectBox::SaveText()
    {
       // save the edited entry true name and alias

       if (fEntry) {

          Bool_t cutType;
          TString name(fTe->GetText());
          if (name.Length())
             fEntry->SetToolTipText("Double-click to draw. Drag and drop. Use Edit/Expression or context menu to edit.");
          else
             fEntry->SetToolTipText("User-defined expression/cut. Double-click to edit");
          // Set type of item to "cut" if containing boolean operators
          cutType = name.Contains("<") || name.Contains(">") || name.Contains("=") ||
                    name.Contains("!") || name.Contains("&") || name.Contains("|");
          TString alias(fTeAlias->GetText());
          if (!alias.BeginsWith("~") && !alias.Contains("empty")) fTeAlias->InsertText("~", 0);
          fEntry->SetExpression(fTe->GetText(), fTeAlias->GetText(), cutType);

          if (fOldAlias.Contains("empty")) {
             fOldAlias = fTeAlias->GetText();
             return;
          }
          TList *list = fViewer->ExpressionList();
          TIter next(list);
          TTVLVEntry* item;
          while ((item=(TTVLVEntry*)next())) {
             if (item != fEntry) {
                TString name = item->GetTrueName();
                name.ReplaceAll(fOldAlias.Data(), fTeAlias->GetText());
                item->SetTrueName(name.Data());
             }
          }
       }
    }

    //______________________________________________________________________________
    void TGSelectBox::SetEntry(TTVLVEntry *entry)
    {
       // connect one entry

       fEntry = entry;
       fTe->SetText(entry->GetTrueName());
       fTeAlias->SetText(entry->GetAlias());
       fOldAlias = entry->GetAlias();
    }

    //______________________________________________________________________________
    void TGSelectBox::InsertText(const char* text)
    {
       Int_t start = fTe->GetCursorPosition();
       fTe->InsertText(text, fTe->GetCursorPosition());
       fTe->SetCursorPosition(start+strlen(text));
    }

    //______________________________________________________________________________
    Bool_t TGSelectBox::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
    {
       // Message interpreter

       switch (GET_MSG(msg)) {
          case kC_TEXTENTRY:
             switch (GET_SUBMSG(msg)) {
                case kTE_ENTER:
                   if (ValidateAlias()) SaveText();
                   break;
                default:
                   break;
             }
             break;
          case kC_COMMAND:
             switch (GET_SUBMSG(msg)) {
                case kCM_BUTTON:
                   switch (parm1) {
                      case kTFDone:
                         if (!ValidateAlias()) break;
                         SaveText();
                         CloseWindow();
                         break;
                      case kTFCancel:
                         CloseWindow();
                         break;
                      default:
                         break;
                   }
                   break;
                default:
                   break;
             }
             break;
          default:
             if (parm2) break;       // just to avoid warning on CC compiler
             break;
       }
       return kTRUE;
    }

    //______________________________________________________________________________
    Bool_t TGSelectBox::ValidateAlias()
    {
       // return true if edited alias is not a leading string of other expression aliases

       if (!strcmp(fTeAlias->GetText(), "-empty-") || !strlen(fTeAlias->GetText())) {
          fViewer->Warning("ValidateAlias", "You should define the alias first.");
          return kFALSE;
       }
       TList *list = fViewer->ExpressionList();
       TIter next(list);
       TTVLVEntry* item;
       while ((item=(TTVLVEntry*)next())) {
          if (item != fEntry) {
             TString itemalias(item->GetAlias());
             if (itemalias.Contains(fTeAlias->GetText())) {
                fViewer->Warning("ValidAlias", "Alias can not be the leading string of other alias.");
                return kFALSE;
             }
          }
       }
       return kTRUE;
    }