convert line ends
[canaan.git] / prj / cam / src / editor / menus.cpp
blob4ca11d0e25b6f9beda98c7d3a6000ea88916e03b
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Source: r:/t2repos/thief2/src/editor/menus.cpp,v $
8 // $Author: henrys $
9 // $Date: 1999/10/29 19:18:50 $
10 // $Revision: 1.7 $
12 // @Note (toml 08-03-97): This is a temporary solution that will have to be
13 // rethought when dynamic menus are supported. No sub-menus right now
15 #include <windows.h>
16 #include <lg.h>
18 #include <appagg.h>
19 #include <wappapi.h>
21 #include <dynarray.h>
22 #include <str.h>
23 #include <hashpp.h>
24 #include <hshpptem.h>
25 #include <winmenu.h>
26 #include <config.h>
28 #include <menus.h>
29 #include <command.h>
30 #include <mprintf.h>
32 // Must be last header
33 #include <dbmem.h>
35 ///////////////////////////////////////////////////////////////////////////////
37 #define kMenuCommandBase 1000
39 class cMenuCommands
41 public:
42 ~cMenuCommands();
44 unsigned NewCommand(const char *);
45 const char * Lookup(unsigned);
46 void ClearAll();
48 private:
49 cDynArray<const char *> m_CommandTexts;
52 ///////////////////////////////////////
54 inline cMenuCommands::~cMenuCommands()
56 ClearAll();
59 ///////////////////////////////////////
61 inline unsigned cMenuCommands::NewCommand(const char * pszCommand)
63 m_CommandTexts.Append(strdup(pszCommand));
64 return kMenuCommandBase + m_CommandTexts.Size() - 1;
67 ///////////////////////////////////////
69 inline const char * cMenuCommands::Lookup(unsigned id)
71 unsigned index = id - kMenuCommandBase;
72 if (index < m_CommandTexts.Size())
73 return m_CommandTexts[index];
74 else
75 return NULL;
78 ///////////////////////////////////////
80 void cMenuCommands::ClearAll()
82 for (int i = 0; i < m_CommandTexts.Size(); i++)
83 free((void *)(m_CommandTexts[i]));
84 m_CommandTexts.SetSize(0);
87 ///////////////////////////////////////////////////////////////////////////////
89 class cMenuSet
91 public:
92 cMenuSet();
93 ~cMenuSet();
95 void BeginMenu(const char * = NULL);
96 void AddItem(const char *, unsigned id);
97 void AddSeparator();
98 void EndMenu();
100 void AttachToWindow(HWND hWnd);
101 void DetachFromWindow();
103 void DestroyAll();
105 cWinMenu* GetMenuByNumber(int number);
107 private:
108 HWND m_hWnd;
109 int m_iCurrentMenu;
110 cDynArray<cWinMenu *> m_Menus;
111 cDynArray<int> m_MenuStack;
115 ///////////////////////////////////////
117 inline cMenuSet::cMenuSet()
118 : m_hWnd(0),
119 m_iCurrentMenu(-1)
123 ///////////////////////////////////////
125 inline cMenuSet::~cMenuSet()
127 DestroyAll();
130 ///////////////////////////////////////
132 inline void cMenuSet::BeginMenu(const char * pszSubMenuName)
134 cWinMenu * pMenu = new cWinMenu();
136 pMenu->CreateMenu();
137 m_Menus.Append(pMenu);
139 m_MenuStack.Append(m_iCurrentMenu);
141 int oldMenu = m_iCurrentMenu;
143 m_iCurrentMenu = (int)m_Menus.Size() - 1;
145 if (m_iCurrentMenu != 0)
146 m_Menus[oldMenu]->AppendMenu(MF_POPUP, (uint)(HMENU)(*pMenu), pszSubMenuName);
150 ///////////////////////////////////////
152 inline void cMenuSet::EndMenu()
154 m_iCurrentMenu = m_MenuStack[m_MenuStack.Size() - 1];
155 m_MenuStack.SetSize(m_MenuStack.Size() - 1);
158 ///////////////////////////////////////
160 inline void cMenuSet::AddItem(const char * pszMenuItemName, unsigned id)
162 if (m_Menus.Size() != 0)
163 m_Menus[m_iCurrentMenu]->AppendMenu(MF_STRING, id, pszMenuItemName);
166 ///////////////////////////////////////
168 inline void cMenuSet::AddSeparator()
170 if (m_Menus.Size() != 0)
171 m_Menus[m_iCurrentMenu]->AppendMenu(MF_SEPARATOR, 0, 0);
174 ///////////////////////////////////////
176 void cMenuSet::AttachToWindow(HWND hWnd)
178 if (m_Menus.Size() == 0)
179 return;
181 if (!hWnd)
182 return;
184 if (m_hWnd)
185 SetMenu(m_hWnd, NULL);
187 m_hWnd = hWnd;
189 SetMenu(m_hWnd, *(m_Menus[0]));
192 ///////////////////////////////////////
194 void cMenuSet::DetachFromWindow()
196 if (m_hWnd)
197 SetMenu(m_hWnd, NULL);
198 m_hWnd = NULL;
201 ///////////////////////////////////////
203 void cMenuSet::DestroyAll()
205 if (m_Menus.Size() == 0)
206 return;
208 int iFirst = (m_hWnd) ? 1 : 0;
210 for (int i = iFirst; i < m_Menus.Size(); i++)
212 delete m_Menus[i];
214 m_iCurrentMenu = -1;
215 m_MenuStack.SetSize(0);
216 m_Menus.SetSize(0);
219 ///////////////////////////////////////
221 cWinMenu* cMenuSet::GetMenuByNumber(int number)
223 return (m_Menus[number]);
226 ///////////////////////////////////////////////////////////////////////////////
228 typedef cStrHashTable<BOOL> cMenusInProgress;
230 ///////////////////////////////////////////////////////////////////////////////
232 static cMenuCommands g_MenuCommands;
233 static cMenuSet g_MenuSet;
235 ///////////////////////////////////////////////////////////////////////////////
237 #define kMaxMenuConfigEntry 512
239 void ParseMenu(const char * pszMenuText, const char * pszMenuTag, cMenuSet & menuSet, cMenusInProgress & menusInProgress)
241 cStr menuDefStr;
242 BOOL foundMenu = config_get_raw(pszMenuTag,
243 menuDefStr.GetBuffer(kMaxMenuConfigEntry),
244 kMaxMenuConfigEntry);
245 menuDefStr.ReleaseBuffer();
246 menuDefStr.Trim();
248 if (foundMenu && !menuDefStr.IsEmpty())
250 if (menusInProgress.Lookup(pszMenuTag, &foundMenu))
251 return;
253 menusInProgress.Insert(pszMenuTag, TRUE);
254 menuSet.BeginMenu(pszMenuText);
256 cStr continuationMenuTag(pszMenuTag);
257 int iCurrentPart = 0;
259 continuationMenuTag += "_0";
261 while (foundMenu)
263 int indexNextEntry = 0;
264 int indexSemicolon = 0;
266 cStr menuEntry;
267 cStr menuText;
268 cStr menuValue;
270 while (menuDefStr[indexNextEntry])
272 // Find semicolon
273 indexSemicolon = indexNextEntry + menuDefStr.SpanExcluding("|", indexNextEntry);
275 // If the string is non-zero, deal with it
276 if (indexSemicolon - indexNextEntry != 0)
278 menuDefStr.Mid(menuEntry, indexNextEntry, indexSemicolon - indexNextEntry);
280 int indexColon = menuEntry.Find(':');
281 if (indexColon != -1)
283 menuEntry.Mid(menuText, 0, indexColon);
284 menuEntry.Mid(menuValue, indexColon + 1, menuEntry.GetLength() - (indexColon + 1));
286 else
288 menuText = menuEntry;
289 menuValue = menuEntry;
291 menuText.Trim();
292 menuValue.Trim();
294 if (menuValue.Find("menu_") == 0)
296 ParseMenu(menuText, menuValue, menuSet, menusInProgress);
298 else if (menuText.Find("sep") == 0)
300 menuSet.AddSeparator();
302 else
304 menuSet.AddItem(menuText, g_MenuCommands.NewCommand(menuValue));
309 menuEntry.Empty();
310 menuText.Empty();
311 menuValue.Empty();
313 // Skip to the next non-semicolon
314 indexNextEntry = indexSemicolon + menuDefStr.SpanIncluding("|", indexSemicolon);
316 iCurrentPart++;
317 continuationMenuTag[continuationMenuTag.GetLength() - 1] = '0' + iCurrentPart;
319 foundMenu = config_get_raw(continuationMenuTag,
320 menuDefStr.GetBuffer(kMaxMenuConfigEntry),
321 kMaxMenuConfigEntry);
322 menuDefStr.ReleaseBuffer();
323 menuDefStr.Trim();
325 menuSet.EndMenu();
326 menusInProgress.Delete(pszMenuTag);
328 else
329 menuSet.AddItem(pszMenuText, 0);
332 ///////////////////////////////////////////////////////////////////////////////
334 BOOL CreateMenu(const char * pszMenuTag)
336 cMenusInProgress menusInProgress;
338 ParseMenu(NULL, pszMenuTag, g_MenuSet, menusInProgress);
340 return TRUE;
343 ///////////////////////////////////////////////////////////////////////////////
345 void SetMainMenu(const char * pszName)
347 AutoAppIPtr(WinApp);
349 HWND hWnd = pWinApp->GetMainWnd();
351 g_MenuSet.DetachFromWindow();
352 g_MenuSet.DestroyAll();
353 g_MenuCommands.ClearAll();
355 if (pszName)
357 cStr menuNameStr;
359 menuNameStr = "menu_";
360 menuNameStr += pszName;
362 menuNameStr.Trim();
364 CreateMenu(menuNameStr);
366 g_MenuSet.AttachToWindow(hWnd);
370 ///////////////////////////////////////////////////////////////////////////////
372 void MenuCommand(unsigned id)
374 const char * pszMenuCommand = g_MenuCommands.Lookup(id);
376 if (pszMenuCommand)
378 CommandExecute((char *)pszMenuCommand);
382 ///////////////////////////////////////////////////////////////////////////////
384 // Sets an exclusive radio-button style bullet beside a menu item
386 extern "C"
388 void SetRadioCheckmark (int menu, int firstPos, int lastPos, int checkPos)
390 g_MenuSet.GetMenuByNumber(menu)->CheckMenuRadioItem (firstPos, lastPos, checkPos, MF_BYPOSITION);