#include "TGMenu.h"
#include "TGResourcePool.h"
#include "TTimer.h"
#include "TMath.h"
#include "TSystem.h"
#include "TList.h"
#include "Riostream.h"
#include "KeySymbols.h"
#include "TQConnection.h"
#include "TParameter.h"
const TGGC   *TGPopupMenu::fgDefaultGC = 0;
const TGGC   *TGPopupMenu::fgDefaultSelectedGC = 0;
const TGGC   *TGPopupMenu::fgDefaultSelectedBackgroundGC = 0;
const TGFont *TGPopupMenu::fgDefaultFont = 0;
const TGFont *TGPopupMenu::fgHilightFont = 0;
const TGGC   *TGMenuTitle::fgDefaultGC = 0;
const TGGC   *TGMenuTitle::fgDefaultSelectedGC = 0;
const TGFont *TGMenuTitle::fgDefaultFont = 0;
ClassImp(TGMenuBar)
ClassImp(TGMenuTitle)
ClassImpQ(TGPopupMenu)
class TPopupDelayTimer : public TTimer {
private:
   TGPopupMenu   *fPopup;   
public:
   TPopupDelayTimer(TGPopupMenu *p, Long_t ms) : TTimer(ms, kTRUE) { fPopup = p; }
   Bool_t Notify();
};
Bool_t TPopupDelayTimer::Notify()
{
   
   fPopup->HandleTimer(0);
   Reset();
   return kFALSE;
}
TGMenuBar::TGMenuBar(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options)
   : TGHorizontalFrame(p, w, h, options | kHorizontalFrame)
{
   
   fCurrent       = 0;
   fTitles        = new TList;
   fStick         = kTRUE;
   fDefaultCursor = fClient->GetResourcePool()->GetGrabCursor();
   fTrash         = new TList();
   gVirtualX->GrabButton(fId, kButton1, kAnyModifier,
                       kButtonPressMask | kButtonReleaseMask | kEnterWindowMask,
                       kNone, kNone);
   fKeyNavigate = kFALSE;
   fMenuMore = new TGPopupMenu(gClient->GetRoot());
   fMenuMore->AddLabel("Hidden Menus");
   fMenuMore->AddSeparator();
   fMenuBarMoreLayout = new TGLayoutHints(kLHintsTop | kLHintsRight);
   fWithExt = kFALSE;
   fOutLayouts = new TList();
   fNeededSpace = new TList();
}
TGMenuBar::~TGMenuBar()
{
   
   
   TGFrameElement *el;
   TGMenuTitle    *t;
   Int_t           keycode;
   if (!MustCleanup()) {
      fTrash->Delete();
   }
   delete fTrash;
   const TGMainFrame *main = (TGMainFrame *)GetMainFrame();
   if (!MustCleanup()) {
      TIter next(fList);
      while ((el = (TGFrameElement *) next())) {
         t = (TGMenuTitle *) el->fFrame;
         if ((keycode = t->GetHotKeyCode()) != 0 && main) {
            main->RemoveBind(this, keycode, kKeyMod1Mask);
         }
      }
   }
   
   if (fTitles && !MustCleanup()) fTitles->Delete();
   delete fTitles;
   delete fOutLayouts;
   fNeededSpace->Delete();
   delete fNeededSpace;
   delete fMenuMore;
   delete fMenuBarMoreLayout;
}
void TGMenuBar::Layout()
{
   
   
   if (GetDefaultWidth() > GetWidth()) {
      while (!(GetDefaultWidth() < GetWidth() || 
               GetList()->GetSize() <= 1)) {
         TGFrameElement* entry = GetLastOnLeft();
         TGMenuTitle* menuTitle = (TGMenuTitle*) entry->fFrame;
         fNeededSpace->AddLast(new TParameter<Int_t>("", menuTitle->GetWidth() + 
                                                         entry->fLayout->GetPadLeft() + 
                                                         entry->fLayout->GetPadRight() ) );
         fOutLayouts->AddLast( entry->fLayout );
         fMenuMore->AddPopup( menuTitle->GetName(), menuTitle->GetMenu() );
         menuTitle->GetMenu()->Connect("PoppedUp()", "TGMenuBar", this, "PopupConnection()");
         RemovePopup( menuTitle->GetName() );
      }
   }
   if (fNeededSpace->GetSize() > 0) {
      Int_t neededWidth = ((TParameter<Int_t>*) fNeededSpace->Last())->GetVal();
      Bool_t fit = kFALSE;
      if (fNeededSpace->GetSize() > 1)
         fit = GetDefaultWidth() + neededWidth + 5 < GetWidth();
      else 
         fit = GetDefaultWidth() + neededWidth - 7 < GetWidth();
      while (fit) {
         TGMenuEntry* menu = (TGMenuEntry*) fMenuMore->GetListOfEntries()->Last();
         TGLayoutHints* layout = (TGLayoutHints*) fOutLayouts->Last();
         ULong_t  hints = layout->GetLayoutHints();
         TGPopupMenu* beforeMenu = 0;
         if (hints & kLHintsRight) {
            TGFrameElement* entry = GetLastOnLeft();
            TGMenuTitle* beforeMenuTitle = (TGMenuTitle*) entry->fFrame;
            beforeMenu = beforeMenuTitle->GetMenu();
         }
         menu->GetPopup()->Disconnect("PoppedUp()", this, "PopupConnection()");
         AddPopup( menu->GetName(), menu->GetPopup(), layout, beforeMenu );
         fOutLayouts->Remove( fOutLayouts->Last() );
         fNeededSpace->Remove( fNeededSpace->Last() );
         fMenuMore->DeleteEntry(menu);
         if (fNeededSpace->GetSize() > 0) {
            neededWidth = ((TParameter<Int_t>*)fNeededSpace->Last())->GetVal();
            if (fNeededSpace->GetSize() > 1)
               fit = GetDefaultWidth() + neededWidth + 5 < GetWidth();
            else 
               fit = GetDefaultWidth() + neededWidth - 7 < GetWidth();
         } else 
            fit = kFALSE;
      }
   }
   if (fNeededSpace->GetSize() > 0) {
      if (!fWithExt) {
         AddPopup(">>", fMenuMore, fMenuBarMoreLayout,
                  ((TGMenuTitle*)((TGFrameElement*)GetList()->First())->fFrame)->GetMenu());
         fWithExt = kTRUE;
      }
   } else {
      RemovePopup(">>");
      fWithExt = kFALSE;
   }
   MapSubwindows();
   TGHorizontalFrame::Layout();
}
TGFrameElement* TGMenuBar::GetLastOnLeft()
{
   
   
   TIter next(GetList());
   while (TGFrameElement *entry = (TGFrameElement*) next()) {
   
      TGMenuTitle* menuTitle = (TGMenuTitle*) entry->fFrame;
      TGLayoutHints* tmpLayout = (TGLayoutHints*) entry->fLayout;
      ULong_t  hints = tmpLayout->GetLayoutHints();
      if (hints & kLHintsRight && menuTitle->GetMenu() != fMenuMore) {
         return entry;
      }
   }
   return ((TGFrameElement*)GetList()->Last());
}
void TGMenuBar::PopupConnection()
{
   
   
   
   TList* slots = fMenuMore->GetListOfSignals();
   TIter next (slots);
   while (TList* connlist = (TList*) next()) {
   
      const char* signal_name = connlist->GetName();
      TIter next2(connlist);
      while (TQConnection* conn = (TQConnection*) next2()) {
         const char* slot_name = conn->GetName();
         void* receiver = conn->GetReceiver();
         fMenuMore->Disconnect(signal_name, receiver, slot_name);
      }
   }
   fMenuMore->fMsgWindow = 0;
   
   TGMenuEntry* currentEntry = fMenuMore->GetCurrent();
   if (currentEntry->GetType() != kMenuPopup) return;
   
   TGPopupMenu* currentMenu = currentEntry->GetPopup();
   slots = currentMenu->GetListOfSignals();
   TIter next3 (slots);
   while (TList* connlist = (TList*) next3()) {
   
      const char* signal_name = connlist->GetName();
      if (strcmp(signal_name, "Activated(int)") == 0) {
         TIter next2(connlist);
         while (TQConnection* conn = (TQConnection*) next2()) {
            const char* slot_name = conn->GetName();
            const char* class_name = conn->GetClassName();
            void* receiver = conn->GetReceiver();
            fMenuMore->Connect(signal_name, class_name, receiver, slot_name);
         }
      }
   }
   fMenuMore->fMsgWindow = currentMenu->fMsgWindow;
}
void TGMenuBar::BindKeys(Bool_t on)
{
   
   
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Left), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Right), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Up), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Down), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Enter), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Return), kAnyModifier, on);
   gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Escape), kAnyModifier, on);
   if (fCurrent && fCurrent->GetMenu()) {
      BindMenu(fCurrent->GetMenu(), on);
   }
}
void TGMenuBar::BindMenu(TGPopupMenu* subMenu, Bool_t on) 
{
   
   TGMenuEntry *e;
   TIter next(subMenu->GetListOfEntries());
   
   while ((e = (TGMenuEntry*)next())) {
      Int_t hot = 0;
      if ( e->GetType() == kMenuPopup )
         BindMenu(e->GetPopup(), on);
      if (e->GetLabel()) {
         hot = e->GetLabel()->GetHotChar();
      }
      if (!hot) continue;
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), 0, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyMod2Mask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyMod2Mask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask  | kKeyMod2Mask, on);
      gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask | kKeyMod2Mask, on);
   }
}
void TGMenuBar::BindHotKey(Int_t keycode, Bool_t on)
{
   
   const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
   if (!main) return;
   if (on) {
      
      main->BindKey(this, keycode, kKeyMod1Mask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyShiftMask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyLockMask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyMod2Mask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
      main->BindKey(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
   } else {
      main->RemoveBind(this, keycode, kKeyMod1Mask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyShiftMask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyLockMask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyMod2Mask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
      main->RemoveBind(this, keycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
   }
}
void TGMenuBar::AddPopup(TGHotString *s, TGPopupMenu *menu, TGLayoutHints *l,
                         TGPopupMenu *before)
{
   
   
   
   TGMenuTitle *t;
   Int_t keycode;
   AddFrameBefore(t = new TGMenuTitle(this, s, menu), l, before);
   fTitles->Add(t);  
   if ((keycode = t->GetHotKeyCode()) != 0) {
      BindHotKey(keycode, kTRUE);
   }
}
void TGMenuBar::AddTitle(TGMenuTitle *title, TGLayoutHints *l, TGPopupMenu *before)
{
   
   Int_t keycode;
   AddFrameBefore(title, l, before);
   fTitles->Add(title);  
   if ((keycode = title->GetHotKeyCode()) != 0) {
      BindHotKey(keycode, kTRUE);
   }
}
void TGMenuBar::AddPopup(const char *s, TGPopupMenu *menu, TGLayoutHints *l,
                         TGPopupMenu *before)
{
   
   
   AddPopup(new TGHotString(s), menu, l, before);
}
TGPopupMenu *TGMenuBar::AddPopup(const TString &s, Int_t padleft, Int_t padright,
                                 Int_t padtop, Int_t padbottom)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   ULong_t hints = kLHintsTop;
   if (padleft)  {
      hints |= kLHintsLeft;
   } else {
      hints |= kLHintsRight;
   }
   TGLayoutHints *l = new TGLayoutHints(hints, padleft, padright,
                                               padtop, padbottom);
   fTrash->Add(l);
   TGPopupMenu *menu = new TGPopupMenu(fClient->GetDefaultRoot());
   AddPopup(new TGHotString(s), menu, l, 0);
   fTrash->Add(menu);
   return menu;
}
void TGMenuBar::AddFrameBefore(TGFrame *f, TGLayoutHints *l,
                               TGPopupMenu *before)
{
   
   
   
   if (f->IsA() != TGMenuTitle::Class()) {
      Error("AddFrameBefore", "may only add TGMenuTitle objects to a menu bar");
      return;
   }
   if (!before) {
      AddFrame(f, l);
      return;
   }
   TGFrameElement *nw;
   nw = new TGFrameElement;
   nw->fFrame  = f;
   nw->fLayout = l ? l : fgDefaultHints;
   nw->fState  = 1;
   TGFrameElement *el;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      TGMenuTitle *t = (TGMenuTitle *) el->fFrame;
      if (t->GetMenu() == before) {
         fList->AddBefore(el, nw);
         return;
      }
   }
   fList->Add(nw);
}
TGPopupMenu *TGMenuBar::GetPopup(const char *s)
{
   
   
   
   if (!GetList()) return 0;
   TGFrameElement *el;
   TIter next(GetList());
   TString str = s;
   while ((el = (TGFrameElement *) next())) {
      TGMenuTitle *t = (TGMenuTitle *) el->fFrame;
      if (str == t->GetName())
         return t->GetMenu();
   }
   return 0;
}
TGPopupMenu *TGMenuBar::RemovePopup(const char *s)
{
   
   
   
   if (!GetList()) return 0;
   TGFrameElement *el;
   TIter next(GetList());
   TString str = s;
   while ((el = (TGFrameElement *) next())) {
      TGMenuTitle *t = (TGMenuTitle *) el->fFrame;
      if (str == t->GetName()) {
         Int_t keycode;
         if ((keycode = t->GetHotKeyCode())) {
            BindHotKey(keycode, kFALSE);  
         }
         TGPopupMenu *m = t->GetMenu();
         fTitles->Remove(t);
         t->DestroyWindow();
         RemoveFrame(t);
         delete t;
         return m;
      }
   }
   return 0;
}
Bool_t TGMenuBar::HandleMotion(Event_t *event)
{
   
   if (fKeyNavigate) return kTRUE;
   Int_t        dummy;
   Window_t     wtarget;
   TGMenuTitle *target = 0;
   fStick = kFALSE; 
   gVirtualX->TranslateCoordinates(fId, fId, event->fX, event->fY,
                                   dummy, dummy, wtarget);
   if (wtarget) target = (TGMenuTitle*) fClient->GetWindowById(wtarget);
   if (fCurrent && target && (target != fCurrent)) {
      
      TGFrameElement *el;
      TIter next(fList);
      while ((el = (TGFrameElement *) next()))
         ((TGMenuTitle*)el->fFrame)->SetState(kFALSE);
      fStick   = kTRUE;
      fCurrent = target;
      target->SetState(kTRUE);
   }
   return kTRUE;
}
Bool_t TGMenuBar::HandleButton(Event_t *event)
{
   
   Int_t        dummy;
   Window_t     wtarget;
   TGMenuTitle *target;
   
   
   if (event->fType == kButtonPress) {
      gVirtualX->TranslateCoordinates(fId, fId, event->fX, event->fY,
                                      dummy, dummy, wtarget);
      target = (TGMenuTitle*) fClient->GetWindowById(wtarget);
      if (target != 0) {
         fStick = kTRUE;
         if (target != fCurrent) {
            
            TGFrameElement *el;
            TIter next(fList);
            while ((el = (TGFrameElement *) next()))
               ((TGMenuTitle*)el->fFrame)->SetState(kFALSE);
            fStick   = kTRUE;
            fCurrent = target;
            target->SetState(kTRUE);
            gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
                                   kPointerMotionMask, kNone, fDefaultCursor);
         }
      }
   }
   if (event->fType == kButtonRelease) {
      if (fStick) {
         fStick = kFALSE;
         return kTRUE;
      }
      TGFrameElement *el;
      TIter next(fList);
      while ((el = (TGFrameElement *) next()))
         ((TGMenuTitle*)el->fFrame)->SetState(kFALSE);
      gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  
      if (fCurrent != 0) {
         target   = fCurrent; 
         fCurrent = 0;
         if (!fKeyNavigate)
            target->DoSendMessage();
      }
      fKeyNavigate = kFALSE;
   }
   return kTRUE;
}
Bool_t TGMenuBar::HandleKey(Event_t *event)
{
   
   TGMenuTitle *target = 0;
   TGFrameElement *el;
   void *dummy;
   Int_t    ax, ay;
   Window_t wdummy;
   TIter next(fList);
   if (event->fType == kGKeyPress) {
      UInt_t keysym;
      char tmp[2];
      gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
      if (event->fState & kKeyMod1Mask) {
         while ((el = (TGFrameElement *) next())) {
            target = (TGMenuTitle *) el->fFrame;
            if ((Int_t)event->fCode == target->GetHotKeyCode()) {
               RequestFocus();
               fKeyNavigate = kTRUE;
               break;
            }
         }
         if (el == 0) target = 0;
      } else {
         fKeyNavigate = kTRUE;
         if (fCurrent) {
            TGFrameElement *cur  = 0;
            TGPopupMenu    *menu = 0;
            next.Reset();
            el = 0;
            while ((el = (TGFrameElement *) next())) {
               if (el->fFrame == fCurrent) {
                  cur = el;
                  menu = ((TGMenuTitle*)el->fFrame)->GetMenu();
                  break;
               }
            }
            if (!menu || !menu->fPoppedUp) return kFALSE;
            TGMenuEntry *ce = 0;
            TGPopupMenu* currentMenu = fCurrent->GetMenu();
            TGMenuEntry* currentEntry = currentMenu->GetCurrent();
            while ( currentEntry ) {
               if ( currentEntry->GetType() == kMenuPopup )
                  currentMenu = currentEntry->GetPopup();
               if ( currentEntry != currentMenu->GetCurrent() )
                  currentEntry = currentMenu->GetCurrent();
               else
                  currentEntry = 0;
            }
            TIter next2(currentMenu->GetListOfEntries());
            while ((ce = (TGMenuEntry*)next2())) {
               UInt_t hot = 0;
               if (ce->GetLabel()) hot = ce->GetLabel()->GetHotChar();
               if (!hot || (hot != keysym)) continue;
               currentMenu->Activate(ce);
               if (ce->GetType() != kMenuPopup) {
                  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
                  fCurrent->SetState(kFALSE);
                  currentMenu->fStick = kFALSE;
                  Event_t ev;
                  ev.fType = kButtonRelease;
                  ev.fWindow = currentMenu->GetId();
                  fCurrent = 0;
                  return currentMenu->HandleButton(&ev);
               }
               else {
                  gVirtualX->TranslateCoordinates(currentMenu->fId,
                                 (ce->fPopup->GetParent())->GetId(),
                                  ce->fEx+currentMenu->fMenuWidth, ce->fEy,
                                  ax, ay, wdummy);
                  ce->fPopup->PlaceMenu(ax-5, ay-1, kFALSE, kFALSE);
               }
            }
            ce = menu->GetCurrent();
            TGPopupMenu *submenu = 0;
            while (ce && (ce->GetType() == kMenuPopup)) {
               submenu = ce->GetPopup();
               if (!submenu->fPoppedUp) break;
               ce =  submenu->GetCurrent();
               menu = submenu;
            }
            switch ((EKeySym)keysym) {
               case kKey_Left:
                  if ((submenu) && (submenu->fPoppedUp)) {
                     submenu->EndMenu(dummy);
                     break;
                  }
                  el = (TGFrameElement*)fList->Before(cur);
                  if (!el) el = (TGFrameElement*)fList->Last();
                  break;
               case kKey_Right:
                  if (submenu) {
                     if (submenu->fPoppedUp) {
                        if (!submenu->GetCurrent()) {
                           ce = (TGMenuEntry*)submenu->GetListOfEntries()->First();
                        } else {
                           submenu->EndMenu(dummy);
                        }
                     }
                     else {
                        gVirtualX->TranslateCoordinates(menu->fId,
                                       (submenu->GetParent())->GetId(),
                                       ce->fEx+menu->fMenuWidth, ce->fEy,
                                       ax, ay, wdummy);
                        submenu->PlaceMenu(ax-5, ay-1, kFALSE, kFALSE);
                     }
                     break;
                  }
                  el = (TGFrameElement*)fList->After(cur);
                  if (!el) el = (TGFrameElement*)fList->First();
                  break;
               case kKey_Up:
                  if (ce) ce = (TGMenuEntry*)menu->GetListOfEntries()->Before(ce);
                  while (ce && ((ce->GetType() == kMenuSeparator) ||
                         (ce->GetType() == kMenuLabel) ||
                         !(ce->GetStatus() & kMenuEnableMask))) {
                     ce = (TGMenuEntry*)menu->GetListOfEntries()->Before(ce);
                  }
                  if (!ce) ce = (TGMenuEntry*)menu->GetListOfEntries()->Last();
                  break;
               case kKey_Down:
                  if (ce) ce = (TGMenuEntry*)menu->GetListOfEntries()->After(ce);
                  while (ce && ((ce->GetType() == kMenuSeparator) ||
                         (ce->GetType() == kMenuLabel) ||
                         !(ce->GetStatus() & kMenuEnableMask))) {
                     ce = (TGMenuEntry*)menu->GetListOfEntries()->After(ce);
                  }
                  if (!ce) ce = (TGMenuEntry*)menu->GetListOfEntries()->First();
                  break;
               case kKey_Enter:
               case kKey_Return:
                  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
                  fCurrent->SetState(kFALSE);
                  menu->fStick = kFALSE;
                  Event_t ev;
                  ev.fType = kButtonRelease;
                  ev.fWindow = menu->GetId();
                  fCurrent = 0;
                  return menu->HandleButton(&ev);
               case kKey_Escape:
                  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
                  fCurrent->SetState(kFALSE);
                  fStick = kFALSE;
                  fCurrent = 0;
                  return menu->EndMenu(dummy);
               default:
                  break;
            }
            if (ce) menu->Activate(ce);
            el = el ? el : cur;
            if (el) target = (TGMenuTitle*)el->fFrame;
         } else {
            return kFALSE;
         }
      }
      if (target != 0) {
         fStick = kTRUE;
         if (target != fCurrent) {
            
            next.Reset();
            while ((el = (TGFrameElement *) next()))
               ((TGMenuTitle*)el->fFrame)->SetState(kFALSE);
            fCurrent = target;
            target->SetState(kTRUE);
            fStick   = kTRUE;
            gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
                                   kPointerMotionMask, kNone, fDefaultCursor);
            TGMenuEntry *ptr;
            TIter nexte(target->GetMenu()->GetListOfEntries());
            while ((ptr = (TGMenuEntry *) nexte())) {
               if ((ptr->GetStatus() & kMenuEnableMask) &&
                  !(ptr->GetStatus() & kMenuHideMask) &&
                   (ptr->GetType() != kMenuSeparator) &&
                   (ptr->GetType() != kMenuLabel)) break;
            }
            if (ptr)
               target->GetMenu()->Activate(ptr);
            return kTRUE;
         }
      } else {
         return kFALSE;
      }
   }
   if (event->fType == kKeyRelease) {
      if (fStick) {
         fStick = kFALSE;
         return kTRUE;
      }
      gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  
      next.Reset();
      while ((el = (TGFrameElement *) next()))
         ((TGMenuTitle*)el->fFrame)->SetState(kFALSE);
      if (fCurrent != 0) {
         target   = fCurrent; 
         fCurrent = 0;
         target->DoSendMessage();
      }
   }
   return kTRUE;
}
TGPopupMenu::TGPopupMenu(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options)
    : TGFrame(p, w, h, options | kOwnBackground)
{
   
   fNormGC        = GetDefaultGC()();
   fSelGC         = GetDefaultSelectedGC()();
   fSelbackGC     = GetDefaultSelectedBackgroundGC()();
   fFontStruct    = GetDefaultFontStruct();
   fHifontStruct  = GetHilightFontStruct();
   fDefaultCursor = fClient->GetResourcePool()->GetGrabCursor();
   
   
   GCValues_t    gcval;
   gcval.fMask = kGCFont;
   gcval.fFont = gVirtualX->GetFontHandle(fFontStruct);
   gVirtualX->ChangeGC(fNormGC, &gcval);
   gVirtualX->ChangeGC(fSelGC, &gcval);
   fDelay     = 0;
   fEntryList = new TList;
   
   fBorderWidth = 3;
   fMenuHeight  = 6;
   fMenuWidth   = 8;
   fXl          = 16;
   fMsgWindow   = p;
   fStick       = kTRUE;
   fCurrent     = 0;
   fHasGrab     = kFALSE;
   fPoppedUp    = kFALSE;
   fMenuBar     = 0;
   fEntrySep    = 3;
   SetWindowAttributes_t wattr;
   wattr.fMask             = kWAOverrideRedirect | kWASaveUnder;
   wattr.fOverrideRedirect = kTRUE;
   wattr.fSaveUnder        = kTRUE;
   gVirtualX->ChangeWindowAttributes(fId, &wattr);
   AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask);
}
TGPopupMenu::~TGPopupMenu()
{
   
   if (fEntryList) fEntryList->Delete();
   delete fEntryList;
   delete fDelay;
}
void TGPopupMenu::AddEntry(TGHotString *s, Int_t id, void *ud,
                           const TGPicture *p, TGMenuEntry *before)
{
   
   
   
   
   TGMenuEntry *nw = new TGMenuEntry;
   nw->fLabel    = s;
   nw->fPic      = p;
   nw->fType     = kMenuEntry;
   nw->fEntryId  = id;
   nw->fUserData = ud;
   nw->fPopup    = 0;
   nw->fStatus   = kMenuEnableMask;
   nw->fEx       = 2;
   nw->fEy       = fMenuHeight-2;
   if (before)
      fEntryList->AddBefore(before, nw);
   else
      fEntryList->Add(nw);
   UInt_t tw, pw = 0;
   tw = gVirtualX->TextWidth(fHifontStruct, s->GetString(), s->GetLength());
   if (p) {
      pw = p->GetWidth();
      if (pw+12 > fXl) { fMenuWidth += pw+12-fXl; fXl = pw+12; }
   }
   Int_t max_ascent, max_descent;
   nw->fEw = tw + pw +18+12;
   fMenuWidth = TMath::Max(fMenuWidth, nw->fEw);
   gVirtualX->GetFontProperties(fHifontStruct, max_ascent, max_descent);
   nw->fEh = max_ascent + max_descent + fEntrySep;
   fMenuHeight += nw->fEh;
   if (before)
      Reposition();
   else
      Resize(fMenuWidth, fMenuHeight);
}
void TGPopupMenu::AddEntry(const char *s, Int_t id, void *ud,
                           const TGPicture *p, TGMenuEntry *before)
{
   
   
   AddEntry(new TGHotString(s), id, ud, p, before);
}
void TGPopupMenu::AddSeparator(TGMenuEntry *before)
{
   
   
   TGMenuEntry *nw = new TGMenuEntry;
   nw->fLabel    = 0;
   nw->fPic      = 0;
   nw->fType     = kMenuSeparator;
   nw->fEntryId  = -1;
   nw->fUserData = 0;
   nw->fPopup    = 0;
   nw->fStatus   = kMenuEnableMask;
   nw->fEx       = 2;
   nw->fEy       = fMenuHeight-2;
   if (before)
      fEntryList->AddBefore(before, nw);
   else
      fEntryList->Add(nw);
   nw->fEw = 0;
   nw->fEh = 4;
   fMenuHeight += nw->fEh;
   if (before)
      Reposition();
   else
      Resize(fMenuWidth, fMenuHeight);
}
void TGPopupMenu::AddLabel(TGHotString *s, const TGPicture *p,
                           TGMenuEntry *before)
{
   
   
   
   
   TGMenuEntry *nw = new TGMenuEntry;
   nw->fLabel    = s;
   nw->fPic      = p;
   nw->fType     = kMenuLabel;
   nw->fEntryId  = -1;
   nw->fUserData = 0;
   nw->fPopup    = 0;
   nw->fStatus   = kMenuEnableMask | kMenuDefaultMask;
   nw->fEx       = 2;
   nw->fEy       = fMenuHeight-2;
   if (before)
      fEntryList->AddBefore(before, nw);
   else
      fEntryList->Add(nw);
   UInt_t tw, pw = 0;
   tw = gVirtualX->TextWidth(fHifontStruct, s->GetString(), s->GetLength());
   if (p) {
      pw = p->GetWidth();
      if (pw+12 > fXl) { fMenuWidth += pw+12-fXl; fXl = pw+12; }
   }
   Int_t max_ascent, max_descent;
   nw->fEw = tw + pw +18+12;
   fMenuWidth = TMath::Max(fMenuWidth, nw->fEw);
   gVirtualX->GetFontProperties(fHifontStruct, max_ascent, max_descent);
   nw->fEh = max_ascent + max_descent + fEntrySep;
   fMenuHeight += nw->fEh;
   if (before)
      Reposition();
   else
      Resize(fMenuWidth, fMenuHeight);
}
void TGPopupMenu::AddLabel(const char *s, const TGPicture *p,
                           TGMenuEntry *before)
{
   
   
   AddLabel(new TGHotString(s), p, before);
}
void TGPopupMenu::AddPopup(TGHotString *s, TGPopupMenu *popup,
                           TGMenuEntry *before)
{
   
   
   
   TGMenuEntry *nw = new TGMenuEntry;
   nw->fLabel    = s;
   nw->fPic      = 0;
   nw->fType     = kMenuPopup;
   nw->fEntryId  = -2;
   nw->fUserData = 0;
   nw->fPopup    = popup;
   nw->fStatus   = kMenuEnableMask;
   nw->fEx       = 2;
   nw->fEy       = fMenuHeight-2;
   if (before)
      fEntryList->AddBefore(before, nw);
   else
      fEntryList->Add(nw);
   UInt_t tw = gVirtualX->TextWidth(fHifontStruct, s->GetString(),
                                    s->GetLength());
   Int_t max_ascent, max_descent;
   nw->fEw = tw +8+18+12;
   fMenuWidth = TMath::Max(fMenuWidth, nw->fEw);
   gVirtualX->GetFontProperties(fHifontStruct, max_ascent, max_descent);
   nw->fEh = max_ascent + max_descent + fEntrySep;
   fMenuHeight += nw->fEh;
   if (before)
      Reposition();
   else
      Resize(fMenuWidth, fMenuHeight);
}
void TGPopupMenu::AddPopup(const char *s, TGPopupMenu *popup,
                           TGMenuEntry *before)
{
   
   
   AddPopup(new TGHotString(s), popup, before);
}
void TGPopupMenu::Reposition()
{
   
   
   
   fMenuHeight = 6;
   fMenuWidth  = 8;
   fXl         = 16;
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next())) {
      if (ptr->fStatus & kMenuHideMask) continue;
      if (ptr->fPic) {
         UInt_t pw = ptr->fPic->GetWidth();
         if (pw+12 > fXl) { fMenuWidth += pw+12-fXl; fXl = pw+12; }
      }
      ptr->fEx     = 2;
      ptr->fEy     = fMenuHeight-2;
      fMenuWidth   = TMath::Max(fMenuWidth, ptr->fEw);
      fMenuHeight += ptr->fEh;
   }
   Resize(fMenuWidth, fMenuHeight);
}
void TGPopupMenu::PlaceMenu(Int_t x, Int_t y, Bool_t stick_mode, Bool_t grab_pointer)
{
   
   
   
   
   void *ud;
   EndMenu(ud);
   Int_t  rx, ry;
   UInt_t rw, rh;
   fStick = stick_mode;
   fCurrent = 0;
   
   gVirtualX->GetWindowSize(fParent->GetId(), rx, ry, rw, rh);
   if (x < 0) x = 0;
   if (x + fMenuWidth > rw) x = rw - fMenuWidth;
   if (y < 0) y = 0;
   if (y + fMenuHeight > rh) y = rh - fMenuHeight;
   Move(x, y);
   MapRaised();
   if (grab_pointer) {
      gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
                             kPointerMotionMask, kNone, fDefaultCursor);
      fHasGrab = kTRUE;
   } else {
      fHasGrab = kFALSE;
   }
   fPoppedUp = kTRUE;
   PoppedUp();
   if (fMenuBar) fMenuBar->BindKeys(kTRUE);
   fClient->RegisterPopup(this);
}
Int_t TGPopupMenu::EndMenu(void *&userData)
{
   
   
   Int_t id;
   if (fDelay) fDelay->Remove();
   
   if (fCurrent != 0) {
      
      fCurrent->fStatus &= ~kMenuActiveMask;
      if (fCurrent->fType == kMenuPopup) {
         id = fCurrent->fPopup->EndMenu(userData);
      } else {
         
         if (fCurrent->fStatus & kMenuEnableMask) {
            id       = fCurrent->fEntryId;
            userData = fCurrent->fUserData;
         } else {
            id       = -1;
            userData = 0;
         }
      }
   } else {
      
      id       = -1;
      userData = 0;
   }
   
   UnmapWindow();
   gClient->UnregisterPopup(this);
   if (fMenuBar) fMenuBar->BindKeys(kFALSE);
   if (fPoppedUp) {
      fPoppedUp = kFALSE;
      PoppedDown();
   }
   return id;
}
Bool_t TGPopupMenu::HandleButton(Event_t *event)
{
   
   int   id;
   void *ud;
   if (event->fType == kButtonRelease) {
      if (fStick) {
         fStick = kFALSE;
         return kTRUE;
      }
      
      
      id = EndMenu(ud);
      if (fHasGrab) gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  
      if (fCurrent != 0) {
         fCurrent->fStatus &= ~kMenuActiveMask;
         if (fCurrent->fStatus & kMenuEnableMask) {
            SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_MENU), id,
                        (Long_t)ud);
            Activated(id);
         }
      }
   }
   return kTRUE;
}
Bool_t TGPopupMenu::HandleCrossing(Event_t *event)
{
   
   if (event->fType == kEnterNotify) {
      TGMenuEntry *ptr;
      TIter next(fEntryList);
      while ((ptr = (TGMenuEntry *) next())) {
         if (ptr->fStatus & kMenuHideMask) continue;
         if ((event->fX >= ptr->fEx) && (event->fX <= ptr->fEx+(Int_t)fMenuWidth-10) &&
             (event->fY >= ptr->fEy) && (event->fY <= ptr->fEy+(Int_t)ptr->fEh))
            break;
      }
      Activate(ptr);
   } else {
      Activate((TGMenuEntry*)0);
   }
   if (fMenuBar) fMenuBar->fKeyNavigate = kFALSE;
   return kTRUE;
}
Bool_t TGPopupMenu::HandleMotion(Event_t *event)
{
   
   TGFrame::HandleMotion(event);
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   fStick = kFALSE;   
   while ((ptr = (TGMenuEntry *) next())) {
      if (ptr->fStatus & kMenuHideMask) continue;
      if ((event->fX >= ptr->fEx) && (event->fX <= ptr->fEx+(Int_t)fMenuWidth-4) &&  
          (event->fY >= ptr->fEy) && (event->fY <= ptr->fEy+(Int_t)ptr->fEh))
         break;
   }
   Activate(ptr);
   return kTRUE;
}
void TGPopupMenu::Activate(TGMenuEntry *entry)
{
   
   if (entry == fCurrent) return;
   
   if (fCurrent != 0) {
      void *ud;
      if (entry == 0 && fCurrent->fType == kMenuPopup) return;
      if (fCurrent->fType == kMenuPopup) fCurrent->fPopup->EndMenu(ud);
      fCurrent->fStatus &= ~kMenuActiveMask;
      DrawEntry(fCurrent);
   }
   if (fDelay) fDelay->Remove();
   
   if (entry) {
      entry->fStatus |= kMenuActiveMask;
      DrawEntry(entry);
      if (entry->fType == kMenuPopup) {
         if (!fDelay) fDelay = new TPopupDelayTimer(this, 350);
         fDelay->Reset();
         gSystem->AddTimer(fDelay);
         
         
      } else if (entry->fType == kMenuEntry) {
         
         SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_MENUSELECT),
                     entry->fEntryId, (Long_t)entry->fUserData);
         Highlighted(entry->fEntryId);
      }
   }
   fCurrent = entry;
}
Bool_t TGPopupMenu::HandleTimer(TTimer *)
{
   
   
   if (fCurrent != 0) {
      if (fCurrent->fType == kMenuPopup) {
         Int_t    ax, ay;
         Window_t wdummy;
         gVirtualX->TranslateCoordinates(fId,
                                       (fCurrent->fPopup->GetParent())->GetId(),
                                       fCurrent->fEx+fMenuWidth, fCurrent->fEy,
                                       ax, ay, wdummy);
         fCurrent->fPopup->PlaceMenu(ax-5, ay-1, kFALSE, kFALSE);
      }
   }
   fDelay->Remove();
   return kTRUE;
}
void TGPopupMenu::DoRedraw()
{
   
   TGFrame::DoRedraw();
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      DrawEntry(ptr);
}
void TGPopupMenu::DrawEntry(TGMenuEntry *entry)
{
   
   FontStruct_t  font;
   GCValues_t    gcval;
   if (entry->fStatus & kMenuHideMask)
      return;
   if (entry->fStatus & kMenuDefaultMask) {
      font = fHifontStruct;
      gcval.fMask = kGCFont;
      gcval.fFont = gVirtualX->GetFontHandle(font);
      gVirtualX->ChangeGC(fNormGC, &gcval);
      gVirtualX->ChangeGC(fSelGC, &gcval);
   } else {
      font = fFontStruct;
   }
   int max_ascent, max_descent;
   gVirtualX->GetFontProperties(font, max_ascent, max_descent);
   int tx = entry->fEx + fXl;
   int ty = entry->fEy + max_ascent;
   switch (entry->fType) {
      case kMenuPopup:
      case kMenuLabel:
      case kMenuEntry:
         if ((entry->fStatus & kMenuActiveMask) && entry->fType != kMenuLabel) {
            gVirtualX->FillRectangle(fId, fSelbackGC, entry->fEx+1, entry->fEy-1,
                                     fMenuWidth-6, max_ascent + max_descent + fEntrySep);
            if (entry->fType == kMenuPopup)
               DrawTrianglePattern(fSelGC, fMenuWidth-10, entry->fEy+fEntrySep, fMenuWidth-6, entry->fEy+11);
            if (entry->fStatus & kMenuCheckedMask)
               DrawCheckMark(fSelGC, 6, entry->fEy+fEntrySep, 14, entry->fEy+11);
            if (entry->fStatus & kMenuRadioMask)
               DrawRCheckMark(fSelGC, 6, entry->fEy+fEntrySep, 14, entry->fEy+11);
            if (entry->fPic != 0)
               entry->fPic->Draw(fId, fSelGC, 8, entry->fEy+1);
            entry->fLabel->Draw(fId,
                           (entry->fStatus & kMenuEnableMask) ? fSelGC : GetShadowGC()(),
                           tx, ty);
         } else {
            gVirtualX->FillRectangle(fId, GetBckgndGC()(), entry->fEx+1, entry->fEy-1,
                                     fMenuWidth-6, max_ascent + max_descent + fEntrySep);
            if (entry->fType == kMenuPopup)
               DrawTrianglePattern(fNormGC, fMenuWidth-10, entry->fEy+fEntrySep, fMenuWidth-6, entry->fEy+11);
            if (entry->fStatus & kMenuCheckedMask)
               DrawCheckMark(fNormGC, 6, entry->fEy+fEntrySep, 14, entry->fEy+11);
            if (entry->fStatus & kMenuRadioMask)
               DrawRCheckMark(fNormGC, 6, entry->fEy+fEntrySep, 14, entry->fEy+11);
            if (entry->fPic != 0)
               entry->fPic->Draw(fId, fNormGC, 8, entry->fEy+1);
            if (entry->fStatus & kMenuEnableMask) {
               entry->fLabel->Draw(fId, fNormGC, tx, ty);
            } else {
               entry->fLabel->Draw(fId, GetHilightGC()(), tx+1, ty+1);
               entry->fLabel->Draw(fId, GetShadowGC()(), tx, ty);
            }
         }
         break;
      case kMenuSeparator:
         gVirtualX->DrawLine(fId, GetShadowGC()(),  2, entry->fEy, fMenuWidth-fEntrySep, entry->fEy);
         gVirtualX->DrawLine(fId, GetHilightGC()(), 2, entry->fEy+1, fMenuWidth-fEntrySep, entry->fEy+1);
         break;
   }
   
   if (entry->fStatus & kMenuDefaultMask) {
      gcval.fFont = gVirtualX->GetFontHandle(fFontStruct);
      gVirtualX->ChangeGC(fNormGC, &gcval);
      gVirtualX->ChangeGC(fSelGC, &gcval);
   }
}
void TGPopupMenu::DrawBorder()
{
   
   gVirtualX->DrawLine(fId, GetBckgndGC()(), 0, 0, fMenuWidth-2, 0);
   gVirtualX->DrawLine(fId, GetBckgndGC()(), 0, 0, 0, fMenuHeight-2);
   gVirtualX->DrawLine(fId, GetHilightGC()(), 1, 1, fMenuWidth-fEntrySep, 1);
   gVirtualX->DrawLine(fId, GetHilightGC()(), 1, 1, 1, fMenuHeight-fEntrySep);
   gVirtualX->DrawLine(fId, GetShadowGC()(),  1, fMenuHeight-2, fMenuWidth-2, fMenuHeight-2);
   gVirtualX->DrawLine(fId, GetShadowGC()(),  fMenuWidth-2, fMenuHeight-2, fMenuWidth-2, 1);
   gVirtualX->DrawLine(fId, GetBlackGC()(), 0, fMenuHeight-1, fMenuWidth-1, fMenuHeight-1);
   gVirtualX->DrawLine(fId, GetBlackGC()(), fMenuWidth-1, fMenuHeight-1, fMenuWidth-1, 0);
}
void TGPopupMenu::DrawTrianglePattern(GContext_t gc, Int_t l, Int_t t,
                                      Int_t r, Int_t b)
{
   
   
   Point_t  points[3];
   int m = (t + b) >> 1;
   points[0].fX = l;
   points[0].fY = t;
   points[1].fX = l;
   points[1].fY = b;
   points[2].fX = r;
   points[2].fY = m;
   gVirtualX->FillPolygon(fId, gc, points, 3);
}
void TGPopupMenu::DrawCheckMark(GContext_t gc, Int_t l, Int_t t, Int_t, Int_t b)
{
   
   Segment_t seg[6];
   t = (t + b - 8) >> 1; ++t;
   seg[0].fX1 = 1+l; seg[0].fY1 = 3+t; seg[0].fX2 = 3+l; seg[0].fY2 = 5+t;
   seg[1].fX1 = 1+l; seg[1].fY1 = 4+t; seg[1].fX2 = 3+l; seg[1].fY2 = 6+t;
   seg[2].fX1 = 1+l; seg[2].fY1 = 5+t; seg[2].fX2 = 3+l; seg[2].fY2 = 7+t;
   seg[3].fX1 = 3+l; seg[3].fY1 = 5+t; seg[3].fX2 = 7+l; seg[3].fY2 = 1+t;
   seg[4].fX1 = 3+l; seg[4].fY1 = 6+t; seg[4].fX2 = 7+l; seg[4].fY2 = 2+t;
   seg[5].fX1 = 3+l; seg[5].fY1 = 7+t; seg[5].fX2 = 7+l; seg[5].fY2 = 3+t;
   gVirtualX->DrawSegments(fId, gc, seg, 6);
}
void TGPopupMenu::DrawRCheckMark(GContext_t gc, Int_t l, Int_t t, Int_t r, Int_t b)
{
   
   Segment_t seg[5];
   t = (t + b - 5) >> 1; ++t;
   l = (l + r - 5) >> 1; ++l;
   seg[0].fX1 = 1+l; seg[0].fY1 = 0+t; seg[0].fX2 = 3+l; seg[0].fY2 = 0+t;
   seg[1].fX1 = 0+l; seg[1].fY1 = 1+t; seg[1].fX2 = 4+l; seg[1].fY2 = 1+t;
   seg[2].fX1 = 0+l; seg[2].fY1 = 2+t; seg[2].fX2 = 4+l; seg[2].fY2 = 2+t;
   seg[3].fX1 = 0+l; seg[3].fY1 = 3+t; seg[3].fX2 = 4+l; seg[3].fY2 = 3+t;
   seg[4].fX1 = 1+l; seg[4].fY1 = 4+t; seg[4].fX2 = 3+l; seg[4].fY2 = 4+t;
   gVirtualX->DrawSegments(fId, gc, seg, 5);
}
void TGPopupMenu::DefaultEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next())) {
      if (ptr->fEntryId == id)
         ptr->fStatus |= kMenuDefaultMask;
      else
         ptr->fStatus &= ~kMenuDefaultMask;
   }
}
void TGPopupMenu::EnableEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) {
         ptr->fStatus |= kMenuEnableMask;
         if (ptr->fStatus & kMenuHideMask) {
            ptr->fStatus &= ~kMenuHideMask;
            Reposition();
         }
         break;
      }
}
void TGPopupMenu::DisableEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) { ptr->fStatus &= ~kMenuEnableMask; break; }
}
Bool_t TGPopupMenu::IsEntryEnabled(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         return (ptr->fStatus & kMenuEnableMask) ? kTRUE : kFALSE;
   return kFALSE;
}
void TGPopupMenu::HideEntry(Int_t id)
{
   
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) {
         ptr->fStatus |=  kMenuHideMask;
         ptr->fStatus &= ~kMenuEnableMask;
         Reposition();
         break;
      }
}
Bool_t TGPopupMenu::IsEntryHidden(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         return (ptr->fStatus & kMenuHideMask) ? kTRUE : kFALSE;
   return kFALSE;
}
void TGPopupMenu::CheckEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) { ptr->fStatus |= kMenuCheckedMask; break; }
}
void TGPopupMenu::CheckEntryByData(void *user_data)
{
   
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fUserData == user_data) { ptr->fStatus |= kMenuCheckedMask; break; }
}
void TGPopupMenu::UnCheckEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) { ptr->fStatus &= ~kMenuCheckedMask; break; }
}
Bool_t TGPopupMenu::IsEntryChecked(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         return (ptr->fStatus & kMenuCheckedMask) ? kTRUE : kFALSE;
   return kFALSE;
}
void TGPopupMenu::RCheckEntry(Int_t id, Int_t IDfirst, Int_t IDlast)
{
   
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         ptr->fStatus |= kMenuRadioMask | kMenuRadioEntryMask;
      else
         if (ptr->fEntryId >= IDfirst && ptr->fEntryId <= IDlast) {
            ptr->fStatus &= ~kMenuRadioMask;
            ptr->fStatus |=  kMenuRadioEntryMask;
         }
}
Bool_t TGPopupMenu::IsEntryRChecked(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         return (ptr->fStatus & kMenuRadioMask) ? kTRUE : kFALSE;
   return kFALSE;
}
TGMenuEntry *TGPopupMenu::GetEntry(Int_t id)
{
   
   
   
   
   
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id)
         return ptr;
   return 0;
}
TGMenuEntry *TGPopupMenu::GetEntry(const char *s)
{
   
   
   
   
   
   
   
   
   return (TGMenuEntry*) fEntryList->FindObject(s);
}
void TGPopupMenu::DeleteEntry(Int_t id)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr->fEntryId == id) {
         fEntryList->Remove(ptr);
         delete ptr;
         Reposition();
         if (fCurrent == ptr)
            fCurrent = 0;
         return;
      }
}
void TGPopupMenu::DeleteEntry(TGMenuEntry *entry)
{
   
   TGMenuEntry *ptr;
   TIter next(fEntryList);
   while ((ptr = (TGMenuEntry *) next()))
      if (ptr == entry) {
         fEntryList->Remove(ptr);
         delete ptr;
         Reposition();
         if (fCurrent == ptr)
            fCurrent = 0;
         return;
      }
}
const TGGC &TGPopupMenu::GetDefaultGC()
{
   
   if (!fgDefaultGC)
      fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
   return *fgDefaultGC;
}
const TGGC &TGPopupMenu::GetDefaultSelectedGC()
{
   
   if (!fgDefaultSelectedGC)
      fgDefaultSelectedGC = gClient->GetResourcePool()->GetSelectedGC();
   return *fgDefaultSelectedGC;
}
const TGGC &TGPopupMenu::GetDefaultSelectedBackgroundGC()
{
   
   if (!fgDefaultSelectedBackgroundGC)
      fgDefaultSelectedBackgroundGC = gClient->GetResourcePool()->GetSelectedBckgndGC();
   return *fgDefaultSelectedBackgroundGC;
}
FontStruct_t TGPopupMenu::GetDefaultFontStruct()
{
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetMenuFont();
   return fgDefaultFont->GetFontStruct();
}
FontStruct_t TGPopupMenu::GetHilightFontStruct()
{
   
   if (!fgHilightFont)
      fgHilightFont = gClient->GetResourcePool()->GetMenuHiliteFont();
   return fgHilightFont->GetFontStruct();
}
TGMenuTitle::TGMenuTitle(const TGWindow *p, TGHotString *s, TGPopupMenu *menu,
                         GContext_t norm, FontStruct_t font, UInt_t options)
    : TGFrame(p, 1, 1, options)
{
   
   
   fLabel      = s;
   fMenu       = menu;
   fFontStruct = font;
   fSelGC      = GetDefaultSelectedGC()();
   fNormGC     = norm;
   fState      = kFALSE;
   fTitleId    = -1;
   Int_t hotchar;
   if (s && (hotchar = s->GetHotChar()) != 0)
      fHkeycode = gVirtualX->KeysymToKeycode(hotchar);
   else
      fHkeycode = 0;
   UInt_t tw = 0;
   Int_t  max_ascent, max_descent;
   if (fLabel)
      tw = gVirtualX->TextWidth(fFontStruct, fLabel->GetString(), fLabel->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   Resize(tw + 8, max_ascent + max_descent + 7);
   if (p && p->InheritsFrom(TGMenuBar::Class())) {
      TGMenuBar *bar = (TGMenuBar*)p;
      fMenu->SetMenuBar(bar);
   }
}
void TGMenuTitle::SetState(Bool_t state)
{
   
   fState = state;
   if (state) {
      if (fMenu != 0) {
         Int_t    ax, ay;
         Window_t wdummy;
         gVirtualX->TranslateCoordinates(fId, (fMenu->GetParent())->GetId(),
                                         0, 0, ax, ay, wdummy);
         
         fMenu->PlaceMenu(ax-1, ay+fHeight, kTRUE, kFALSE); 
      }
   } else {
      if (fMenu != 0) {
         fTitleId = fMenu->EndMenu(fTitleData);
      }
   }
   fOptions &= ~(kSunkenFrame | kRaisedFrame);
   fClient->NeedRedraw(this);
}
void TGMenuTitle::DoRedraw()
{
   
   TGFrame::DoRedraw();
   int x, y, max_ascent, max_descent;
   x = y = 4;
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   if (fState) {
      gVirtualX->SetForeground(fNormGC, GetDefaultSelectedBackground());
      gVirtualX->FillRectangle(fId,fNormGC, 0, 0, fWidth, fHeight);
      gVirtualX->SetForeground(fNormGC, GetForeground());
      fLabel->Draw(fId, fSelGC, x, y + max_ascent);
   } else {
      gVirtualX->SetForeground(fNormGC,GetDefaultFrameBackground());
      gVirtualX->FillRectangle(fId,fNormGC, 0, 0, fWidth, fHeight);
      gVirtualX->SetForeground(fNormGC, GetForeground());
      fLabel->Draw(fId, fNormGC, x, y + max_ascent);
   }
}
void TGMenuTitle::DoSendMessage()
{
   
   if (fMenu)
      if (fTitleId != -1) {
         SendMessage(fMenu->fMsgWindow, MK_MSG(kC_COMMAND, kCM_MENU), fTitleId,
                     (Long_t)fTitleData);
         fMenu->Activated(fTitleId);
      }
}
FontStruct_t TGMenuTitle::GetDefaultFontStruct()
{
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetMenuFont();
   return fgDefaultFont->GetFontStruct();
}
const TGGC &TGMenuTitle::GetDefaultGC()
{
   
   if (!fgDefaultGC)
      fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
   return *fgDefaultGC;
}
const TGGC &TGMenuTitle::GetDefaultSelectedGC()
{
   
   if (!fgDefaultSelectedGC)
      fgDefaultSelectedGC = gClient->GetResourcePool()->GetSelectedGC();
   return *fgDefaultSelectedGC;
}
void TGPopupMenu::SavePrimitive(ostream &out, Option_t *option )
{
   
   char quote = '"';
   out << "   TGPopupMenu *";
   out << GetName() << " = new TGPopupMenu(gClient->GetRoot()"
       << "," << GetWidth() << "," << GetHeight() << "," << GetOptionString() << ");" << endl;
   Bool_t hasradio = kFALSE;
   Int_t r_first, r_last, r_active;
   r_active = r_first = r_last = -1;
   TGMenuEntry *mentry;
   TIter next(GetListOfEntries());
   while ((mentry = (TGMenuEntry *) next())) {
      const char *text;
      Int_t i, lentext, hotpos;
      char *outext;
      switch (mentry->GetType()) {
         case kMenuEntry:
            text = mentry->GetName();
            lentext = mentry->fLabel->GetLength();
            hotpos = mentry->fLabel->GetHotPos();
            outext = new char[lentext+2];
            i=0;
            while (lentext) {
               if (i == hotpos-1) {
                  outext[i] = '&';
                  i++;
               }
               outext[i] = *text;
               i++; text++; lentext--;
            }
            outext[i]=0;
            out << "   " << GetName() << "->AddEntry(" << quote
                << gSystem->ExpandPathName(gSystem->UnixPathName(outext)) 
                << quote << "," << mentry->GetEntryId();
            if (mentry->fUserData) {
               out << "," << mentry->fUserData;
            }
            if (mentry->fPic) {
               out << ",gClient->GetPicture(" << quote
                   << gSystem->ExpandPathName(gSystem->UnixPathName(mentry->fPic->GetName()))
                   << quote << ")";
            }
            out << ");" << endl;
            delete [] outext;
            break;
         case kMenuPopup:
            out << endl;
            out << "   // cascaded menu " << quote << mentry->GetName() << quote <<endl;
            mentry->fPopup->SavePrimitive(out, option);
            text = mentry->GetName();
            lentext = mentry->fLabel->GetLength();
            hotpos = mentry->fLabel->GetHotPos();
            outext = new char[lentext+2];
            i=0;
            while (lentext) {
               if (i == hotpos-1) {
                  outext[i] = '&';
                  i++;
               }
               outext[i] = *text;
               i++; text++; lentext--;
            }
            outext[i]=0;
            out << "   " << GetName() << "->AddPopup(" << quote
                << outext << quote << "," << mentry->fPopup->GetName()
                << ");" << endl;
            delete [] outext;
            break;
         case kMenuLabel:
            out << "   " << GetName() << "->AddLabel(" << quote
                << mentry->GetName() << quote;
            if (mentry->fPic) {
               out << ",gClient->GetPicture(" << quote
                   << mentry->fPic->GetName()
                   << quote << ")";
            }
            out << ");" << endl;
            break;
         case kMenuSeparator:
            out << "   " << GetName() << "->AddSeparator();" << endl;
            break;
      }
      if (!(mentry->GetStatus() & kMenuEnableMask)) {
         out<< "   " << GetName() << "->DisableEntry(" << mentry->GetEntryId()
            << ");" << endl;
      }
      if (mentry->GetStatus() & kMenuHideMask) {
         out<< "   " << GetName() << "->HideEntry(" << mentry->GetEntryId()
            << ");" << endl;
      }
      if (mentry->GetStatus() & kMenuCheckedMask) {
         out<< "   " << GetName() << "->CheckEntry(" << mentry->GetEntryId()
            << ");" << endl;
      }
      if (mentry->GetStatus() & kMenuDefaultMask) {
         out<< "   "<< GetName() << "->DefaultEntry(" << mentry->GetEntryId()
            << ");" << endl;
      }
      if (mentry->GetStatus() & kMenuRadioEntryMask) {
         switch (hasradio) {
            case kFALSE:
               r_first = mentry->GetEntryId();
               hasradio = kTRUE;
               if (IsEntryRChecked(mentry->GetEntryId())) r_active = mentry->GetEntryId();
               break;
            case kTRUE:
               r_last = mentry->GetEntryId();
               if (IsEntryRChecked(mentry->GetEntryId())) r_active = mentry->GetEntryId();
            break;
         }
      } else if (hasradio) {
         out << "   " << GetName() << "->RCheckEntry(" << r_active << "," << r_first
             << "," << r_last << ");" << endl;
         hasradio = kFALSE;
         r_active = r_first = r_last = -1;
      }
   }
}
void TGMenuTitle::SavePrimitive(ostream &out, Option_t *option )
{
    
   char quote = '"';
   out << endl;
   out << "   // " << quote << fLabel->GetString() << quote <<" menu" << endl;
   fMenu->SavePrimitive(out, option);
   const char *text = fLabel->GetString();
   Int_t lentext = fLabel->GetLength();
   Int_t hotpos = fLabel->GetHotPos();
   char *outext = new char[lentext+2];
   Int_t i=0;
   while (lentext) {
      if (i == hotpos-1) {
         outext[i] = '&';
         i++;
      }
      outext[i] = *text;
      i++; text++; lentext--;
   }
   outext[i]=0;
   out << "   " << fParent->GetName() << "->AddPopup(" << quote << outext
       << quote << "," << fMenu->GetName();
   delete [] outext;
}
void TGMenuBar::SavePrimitive(ostream &out, Option_t *option )
{
    
   out << endl;
   out << "   // menu bar" << endl;
   out << "   TGMenuBar *";
   out << GetName() << " = new TGMenuBar(" << fParent->GetName()
       << "," << GetWidth() << "," << GetHeight() << "," << GetOptionString() << ");" << endl;
   if (!fList) return;
   TGFrameElement *el;
   TIter next(fList);
   while ((el = (TGFrameElement *)next())) {
      el->fFrame->SavePrimitive(out, option);
      el->fLayout->SavePrimitive(out, option);
      out << ");" << endl;
   }
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.