home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / STATUSBA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  9.1 KB  |  343 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of TStatusBar
  6. //----------------------------------------------------------------------------
  7. #include <owl/owlpch.h>
  8. #include <owl/statusba.h>
  9. #include <owl/statusba.rh>
  10.  
  11. //
  12. // Local class to manage the mode indicator strings
  13. //
  14. class TModeStrings {
  15.   public:
  16.     // constructor
  17.     TModeStrings() : ModeBuff(0), ModeStrings(0), NumModes(0) {}
  18.    ~TModeStrings()
  19.     {
  20.       delete [] ModeBuff;
  21.       delete [] ModeStrings;
  22.     }
  23.  
  24.     void Init(TModule* module, uint16 resId, const char* defaultModes);
  25.    
  26.     // access
  27.     int          Count() const            { return NumModes; }
  28.     const char*  operator [](int i) const { return ModeStrings[i]; }
  29.  
  30.   private:
  31.     int    NumModes;
  32.     char*  ModeBuff;
  33.     char** ModeStrings;
  34. };
  35.  
  36. //
  37. // Gets the mode string array from a single resource string, like:
  38. //   "EXT|CAPS|NUM|SCRL|OVR|REC"
  39. // using the provided default string if resource not found.
  40. //
  41. void
  42. TModeStrings::Init(TModule* module, uint16 resId, const char* defaultModes)
  43. {
  44.   if (!ModeStrings) {
  45.     string modeResString(module->LoadString(resId));
  46.     ModeBuff = strnewdup(modeResString.length() > 0 ?
  47.                          modeResString.c_str() :
  48.                          defaultModes);
  49.     NumModes = 1;
  50.     for (char* p = ModeBuff; *p; p++)
  51.       if (*p == '|') {
  52.         *p = 0;
  53.         NumModes++;
  54.       }
  55.  
  56.     typedef char* pchar;
  57.     ModeStrings = new pchar[NumModes];
  58.     p = ModeBuff;
  59.     for (int i = 0; i < NumModes; i++) {
  60.       ModeStrings[i] = p;
  61.       p += strlen(p) + 1;
  62.     }
  63.   }
  64. }
  65.  
  66. //
  67. // Static mode string object, & default mode indicator strings
  68. //
  69. static TModeStrings ModeOnStrings;
  70. static TModeStrings ModeOffStrings;
  71. static char         DefOnModes[] =  "EXT|CAPS|NUM|SCRL|OVR|REC";
  72. static char         DefOffModes[] = "   |    |   |    |   |   ";
  73.  
  74. IMPLEMENT_CASTABLE(TStatusBar);
  75.  
  76. TStatusBar::TStatusBar(TWindow*              parent,
  77.                        TGadget::TBorderStyle borderStyle,
  78.                        uint                  modeIndicators,
  79.                        TFont*                font,
  80.                        TModule*              module)
  81. :
  82.   TMessageBar(parent, font, module)
  83. {
  84.   BorderStyle = borderStyle;
  85.   ModeIndicators = modeIndicators;
  86.   ModeIndicatorState = 0;
  87.   NumModeIndicators = 0;
  88.   ModeOnStrings.Init(GetModule(), IDS_MODES, DefOnModes);
  89.   ModeOffStrings.Init(GetModule(), IDS_MODESOFF, DefOffModes);
  90.  
  91.   if (BorderStyle == TGadget::Plain || BorderStyle == TGadget::Embossed)
  92.     HighlightLine = false;
  93.  
  94.   else
  95.     Spacing.Value = 2;  // Hilight line + 1/4-em margin on raised & recessed
  96.  
  97.   switch (BorderStyle) {
  98.     case TGadget::Raised:
  99.     case TGadget::Recessed:
  100.       //
  101.       // we want one border height along the top and bottom and 1/2 an em quad
  102.       // along the left and right so we will set pixels and compute the lengths
  103.       // ourselves
  104.       //
  105.       Margins.Units = TMargins::Pixels;
  106.       Margins.Left = Margins.Right = LayoutUnitsToPixels(4);
  107.       Margins.Top = Margins.Bottom = GetSystemMetrics(SM_CYBORDER);
  108.       break;
  109.  
  110.     case TGadget::Plain:
  111.       Margins.Units = TMargins::BorderUnits;
  112.       Margins.Left = Margins.Top = Margins.Right = Margins.Bottom = -1;
  113.       break;
  114.   }
  115.  
  116.   Gadgets->SetBorderStyle(BorderStyle); // Set border style for first gadget
  117.  
  118.   //
  119.   // create text gadgets for any mode indicators the user requested,
  120.   // using provided border style.
  121.   //
  122.   TScreenDC   dc;
  123.  
  124.   dc.SelectObject(*Font);
  125.  
  126.   for (int i = 0; i < ModeOnStrings.Count(); i++)
  127.     if (ModeIndicators & (1 << i)) {
  128.       const int    SMALL_MARGIN = 1;
  129.       int          maxLen = max(strlen(ModeOnStrings[i]), strlen(ModeOffStrings[i]));
  130.       TTextGadget* gadget = new TTextGadget(0, BorderStyle,
  131.                                             TTextGadget::Left, maxLen,
  132.                                             ModeOffStrings[i]);
  133.       TMargins     margins = gadget->GetMargins();
  134.  
  135.       //
  136.       // use small left and right margins
  137.       //
  138.       margins.Left = margins.Right = SMALL_MARGIN;
  139.       gadget->SetMargins(margins);
  140.  
  141.       //
  142.       // turn off shrink wrapping for the width and choose a width that is
  143.       // custom fit for the string
  144.       //
  145.       gadget->SetShrinkWrap(false, true);
  146.       TMessageBar::Insert(*gadget);
  147.  
  148.       TSize        onExtent;
  149.       dc.GetTextExtent(ModeOnStrings[i], strlen(ModeOnStrings[i]), onExtent);
  150.       TSize        offExtent;
  151.       dc.GetTextExtent(ModeOffStrings[i], strlen(ModeOffStrings[i]), offExtent);
  152.       TSize extent(max(onExtent.cx, offExtent.cx), onExtent.cy);
  153.  
  154.       int          left, top, right, bottom;
  155.       gadget->GetOuterSizes(left, right, top, bottom);
  156.  
  157.       extent.cx += left + right;
  158.       gadget->SetSize(extent);
  159.  
  160.       NumModeIndicators++;
  161.     }
  162. }
  163.  
  164. bool
  165. TStatusBar::IsModeIndicator(TGadget* gadget)
  166. {
  167.   int      nonModeIndicators = NumGadgets - NumModeIndicators;
  168.   TGadget* g = Gadgets;
  169.  
  170.   for (int i = 0; i < nonModeIndicators; i++) {
  171.     if (gadget == g)
  172.       return false;
  173.  
  174.     g = g->NextGadget();
  175.   }
  176.  
  177.   return true;
  178. }
  179.  
  180. //
  181. //
  182. //
  183. void
  184. TStatusBar::PositionGadget(TGadget*, TGadget* next, TPoint& origin)
  185. {
  186.   int  cxBorder = GetSystemMetrics(SM_CXBORDER);
  187.  
  188.   if (BorderStyle == TGadget::Plain)
  189.     origin.x -= cxBorder;  // overlap the borders
  190.  
  191.   //
  192.   // leave extra spacing between the mode indicators
  193.   //
  194.   if (IsModeIndicator(next))
  195.     switch (Spacing.Units) {
  196.       case TMargins::Pixels:
  197.         origin.x += Spacing.Value;
  198.         break;
  199.  
  200.       case TMargins::LayoutUnits:
  201.         origin.x += LayoutUnitsToPixels(Spacing.Value);
  202.         break;
  203.  
  204.       case TMargins::BorderUnits:
  205.         origin.x += Spacing.Value * cxBorder;
  206.         break;
  207.     }
  208. }
  209.  
  210. //
  211. // insert a gadget. default placement is just after the gadget to the left of
  212. // the status mode indicators
  213. //
  214. void
  215. TStatusBar::Insert(TGadget& gadget, TPlacement placement, TGadget* sibling)
  216. {
  217.   gadget.SetBorderStyle(BorderStyle);
  218.   if (!sibling)
  219.     sibling = operator[](NumGadgets - NumModeIndicators - 1);
  220.   TMessageBar::Insert(gadget, placement, sibling);
  221. }
  222.  
  223. //
  224. // return gadget at a given index, except mode indicator gadgets
  225. //
  226. TGadget*
  227. TStatusBar::operator [](uint index)
  228. {
  229.   PRECONDITION(index < NumGadgets - NumModeIndicators);
  230.  
  231.   for (TGadget* g = Gadgets; index > 0; index--)
  232.     g = g->NextGadget();
  233.  
  234.   return g;
  235. }
  236.  
  237. //
  238. // Get the text gadget & the mode string associated with a mode indicator
  239. //
  240. bool
  241. TStatusBar::GetGadgetAndStrings(TModeIndicator mode, TTextGadget*& gadget,
  242.                                 const char*& strOn, const char*& strOff)
  243. {
  244.   if ((ModeIndicators & mode) == 0) {
  245.     return false;  // tracing
  246.   }
  247.   else {
  248.     uint  slot = NumGadgets - 1;
  249.  
  250.     for (int index = ModeOnStrings.Count() - 1; (1 << index) > mode; index--)
  251.       if (ModeIndicators & (1 << index))
  252.         slot--;
  253.  
  254.     strOn  = ModeOnStrings[index];
  255.     strOff = ModeOffStrings[index];
  256.  
  257.     for (gadget = (TTextGadget*)Gadgets; slot > 0; slot--)
  258.       gadget = (TTextGadget*)gadget->NextGadget();
  259.  
  260.     return true;
  261.   }
  262. }
  263.  
  264. void
  265. TStatusBar::ToggleModeIndicator(TModeIndicator mode)
  266. {
  267.   SetModeIndicator(mode, !GetModeIndicator(mode));
  268. }
  269.  
  270. void
  271. TStatusBar::SetModeIndicator(TModeIndicator mode, bool on)
  272. {
  273.   TTextGadget*  gadget;
  274.   const char*   strOn;
  275.   const char*   strOff;
  276.  
  277.   if (GetGadgetAndStrings(mode, gadget, strOn, strOff))
  278.     gadget->SetText(on ? strOn : strOff);
  279.  
  280.   if (on)
  281.     ModeIndicatorState |= mode;
  282.   else
  283.     ModeIndicatorState &= ~mode;
  284. }
  285.  
  286. bool
  287. TStatusBar::PreProcessMsg(MSG& msg)
  288. {
  289.   if (msg.message == WM_KEYDOWN) {
  290.  
  291.     switch (msg.wParam) {
  292.       case VK_SCROLL:
  293.  
  294.         if (ModeIndicators & ScrollLock) {
  295.           //ScrollLockModeChange();
  296.           ToggleModeIndicator(ScrollLock);
  297.         }
  298.         break;
  299.  
  300.       case VK_INSERT:
  301.         if (ModeIndicators & Overtype) {
  302.           //
  303.           // Skip if CTRL+INS or SHIFT+INS
  304.           //
  305.           if (((::GetKeyState(VK_CONTROL) & 0x8000) == 0) &&
  306.               ((::GetKeyState(VK_SHIFT)   & 0x8000) == 0))
  307.           //OvertypeModeChange();
  308.           ToggleModeIndicator(Overtype);
  309.         }
  310.         break;
  311.  
  312.       case VK_CAPITAL:
  313.         if (ModeIndicators & CapsLock)
  314.           ToggleModeIndicator(CapsLock);
  315.         break;
  316.  
  317.       case VK_NUMLOCK:
  318.         if (ModeIndicators & NumLock)
  319.           ToggleModeIndicator(NumLock);
  320.         break;
  321.     }
  322.   }
  323.  
  324.   return false;
  325. }
  326.  
  327. //
  328. //  Make sure that we are in sync with the physical KB indicators
  329. //
  330. bool
  331. TStatusBar::IdleAction(long idleCount)
  332. {
  333.   if (idleCount == 0) {
  334.     if ((::GetKeyState(VK_SCROLL) & 0x0001) != GetModeIndicator(ScrollLock))
  335.       ToggleModeIndicator(ScrollLock);
  336.     if ((::GetKeyState(VK_CAPITAL) & 0x0001) != GetModeIndicator(CapsLock))
  337.       ToggleModeIndicator(CapsLock);
  338.     if ((::GetKeyState(VK_NUMLOCK) & 0x0001) != GetModeIndicator(NumLock))
  339.       ToggleModeIndicator(NumLock);
  340.   }
  341.   return TMessageBar::IdleAction(idleCount);
  342. }
  343.