~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Frontier Kernel
Frontier/Common/source/dockmenu.c

Version: ~ [ 10.0 ] ~

** Warning: Cannot open xref database.

1 2 /* $Id: dockmenu.c,v 1.4 2005/01/11 22:48:05 andreradke Exp $ */ 3 4 /****************************************************************************** 5 6 UserLand Frontier(tm) -- High performance Web content management, 7 object database, system-level and Internet scripting environment, 8 including source code editing and debugging. 9 10 Copyright (C) 1992-2004 UserLand Software, Inc. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 26 ******************************************************************************/ 27 28 /* 29 Implement right-click menus in the system tray icon or dock menu. 30 Broken out from FrontierWinMain.c 31 7.1b22 11/08/01 PBS 32 */ 33 34 #include "frontier.h" 35 #include "standard.h" 36 37 #include "menu.h" 38 #include "strings.h" 39 #include "cancoon.h" 40 #include "launch.h" 41 #include "tablestructure.h" 42 #include "popup.h" 43 #include "meprograms.h" 44 #include "dockmenu.h" 45 #include "opinternal.h" 46 #include "menuverbs.h" 47 48 #define idgetdockmenumenuaddresscallback 43 49 50 #define kmaxcommands 100 51 #define kbasecommandid 3000 52 #define maxsubmenus 40 53 54 55 #if MACVERSION 56 UInt32 menuid; 57 short idsubmenu; 58 hdlmenurecord hcurrmenurecord; 59 boolean flstackneedsdisposing = false; 60 #endif 61 62 63 #if WIN95VERSION 64 short menuid; 65 #endif 66 67 68 #if MACVERSION 69 70 typedef struct typopupinfo { 71 72 hdlmenu hmenu; 73 74 short id; 75 } typopupinfo, *ptrpopupinfo, **hdlpopupinfo; 76 77 typedef struct tydockmenustack { 78 79 typopupinfo popupmenus [maxsubmenus]; 80 81 short currstackitem; 82 } tydockmenustack, *ptrdockmenustack, **hdldockmenustack; 83 84 85 tydockmenustack dockmenustack; 86 87 #endif 88 89 90 static boolean dockmenubuildpopupmenu (hdlheadrecord hnode, hdlmenu hmenu); /*forward*/ 91 92 static void dockmenudisposemenusinstack (void); 93 94 95 static void dockmenuresetmenustack (void) { 96 97 #if MACVERSION 98 99 dockmenudisposemenusinstack (); 100 101 dockmenustack.currstackitem = -1; 102 103 dockmenustack.popupmenus [0].hmenu = nil; 104 105 dockmenustack.popupmenus [0].id = -1; 106 107 #endif 108 } /*dockmenuresetmenustack*/ 109 110 111 static void dockmenudisposemenusinstack (void) { 112 113 /* 114 Dispose and delete all menus in popup menu stack. 115 */ 116 117 #if MACVERSION 118 119 short ix = dockmenustack.currstackitem; 120 short i, id; 121 hdlmenu hmenu; 122 123 if (!flstackneedsdisposing) 124 return; 125 126 if (ix < 0) 127 return; 128 129 for (i = ix; i > -1; i--) { 130 131 id = dockmenustack.popupmenus [i].id; 132 133 if (id > -1) 134 135 DeleteMenu (id); 136 137 if (id != defaultpopupmenuid) { /*already disposed by system*/ 138 139 hmenu = dockmenustack.popupmenus [i].hmenu; 140 141 if (hmenu != nil) 142 143 disposemenu (hmenu); 144 } /*if*/ 145 146 dockmenustack.popupmenus [i].hmenu = nil; 147 148 dockmenustack.popupmenus [i].id = -1; 149 150 } /*for*/ 151 152 flstackneedsdisposing = false; 153 #endif 154 } /*dockmenudisposemenusinstack*/ 155 156 157 static boolean dockmenuaddtomenustack (hdlmenu hmenu, short id) { 158 159 #if MACVERSION 160 161 short ix = dockmenustack.currstackitem + 1; 162 163 if (ix > maxsubmenus) 164 return (false); 165 166 dockmenustack.currstackitem = ix; 167 168 dockmenustack.popupmenus [ix].hmenu = hmenu; 169 170 dockmenustack.popupmenus [ix].id = id; 171 172 #endif 173 174 return (true); 175 } /*dockmenuaddtomenustack*/ 176 177 178 static void dockmenuinsertsubmenu (hdlmenu hmenu, short itemnumber, hdlheadrecord hnode) { 179 180 /* 181 7.1b23 PBS: build a sub-menu and attach it. 182 */ 183 184 hdlmenu hsubmenu; 185 short id = defaultpopupmenuid; 186 187 #if MACVERSION 188 idsubmenu++; 189 190 id = idsubmenu; 191 #endif 192 193 hsubmenu = Newmenu (id, ""); 194 195 #if MACVERSION 196 InsertMenu (hsubmenu, -1); 197 #endif 198 199 dockmenubuildpopupmenu (hnode, hsubmenu); 200 201 dockmenuaddtomenustack (hsubmenu, id); 202 203 sethierarchicalmenuitem (hmenu, itemnumber, hsubmenu, id); 204 } /*dockmenuinsertsubmenu*/ 205 206 207 static boolean dockmenugetaddresscallback (tyvaluerecord *val) { 208 209 /* 210 7.1b22 PBS: Run the callback script that returns the address 211 of a menubar object to use. 212 */ 213 214 Handle htext = 0; 215 boolean fl = false; 216 bigstring bsscript; 217 short idscript = idgetdockmenumenuaddresscallback; 218 219 if (getsystemtablescript (idscript, bsscript)) { 220 221 if (!newtexthandle (bsscript, &htext)) 222 223 return (false); 224 225 grabthreadglobals (); 226 227 oppushoutline (outlinedata); 228 229 fl = langrun (htext, val); 230 231 oppopoutline (); 232 233 releasethreadglobals (); 234 } 235 236 return (fl); 237 } /*dockmenugetaddresscallback*/ 238 239 240 static boolean dockmenuinsertmenuitem (hdlmenu hmenu, short itemnumber, hdlheadrecord hnode) { 241 242 /* 243 Insert one menu item. 244 245 7.1b42 PBS: check menu items that should be checked. 246 */ 247 248 bigstring bsheadstring; 249 boolean flenabled = true; 250 boolean flchecked = false; 251 252 getheadstring (hnode, bsheadstring); 253 254 mereduceformula (bsheadstring); 255 256 mereducemenucodes (bsheadstring, &flenabled, &flchecked); /*7.0b23 PBS: items can be disabled.*/ 257 258 pushpopupitem (hmenu, bsheadstring, flenabled, menuid); 259 260 #if TARGET_API_MAC_CARBON == 1 261 262 SetMenuItemCommandID (hmenu, countmenuitems (hmenu), menuid); 263 264 #endif 265 266 if (flchecked) /*7.1b42 PBS: support for checked menu items.*/ 267 checkmenuitem (hmenu, countmenuitems (hmenu), flchecked); 268 269 if (!opnosubheads (hnode)) /*has subs?*/ 270 dockmenuinsertsubmenu (hmenu, itemnumber, hnode); 271 272 #if MACVERSION 273 flstackneedsdisposing = true; 274 #endif 275 276 return (true); 277 } /*dockmenuinsertmenuitem*/ 278 279 280 static boolean dockmenubuildpopupmenu (hdlheadrecord hnode, hdlmenu hmenu) { 281 282 /* 283 7.1b22 PBS: Build a popup menu from the outline pointed to by hnode. 284 Recurse to handle a menu that has a submenu. 285 286 Based on mebuildmenu, but different enough to need its own routine. 287 */ 288 289 short itemnumber; 290 bigstring bs; 291 292 getheadstring (hnode, bs); /*get the menu title*/ 293 294 if (opnosubheads (hnode)) 295 return (true); 296 297 hnode = (**hnode).headlinkright; /*move to first subhead*/ 298 299 for (itemnumber = 1; ; itemnumber++) { 300 301 menuid++; 302 303 if (!dockmenuinsertmenuitem (hmenu, itemnumber, hnode)) 304 return (false); 305 306 if (opislastsubhead (hnode)) /*done with this menu*/ 307 return (true); 308 309 hnode = (**hnode).headlinkdown; /*advance to next item*/ 310 } /*while*/ 311 } /*dockmenubuildpopupmenu*/ 312 313 314 static boolean dockmenufillpopup (hdlmenu hmenu, hdlmenurecord *hmreturned) { 315 316 /* 317 7.1b44 PBS: call menuverbgetsize to make sure the menu is in memory. 318 */ 319 320 hdlhashtable htable; 321 hdlhashnode hnode; 322 hdlmenurecord hm; 323 tyvaluerecord valaddress, val; 324 hdlexternalhandle h; 325 hdlheadrecord hsummit; 326 bigstring bsaddress; 327 boolean fl = false; 328 long menusize = 0; 329 330 if (roottable == nil) /*9.1b1 JES: If there's no system root, don't crash.*/ 331 return (false); 332 333 if (!dockmenugetaddresscallback (&valaddress)) 334 return (false); 335 336 if (valaddress.valuetype != addressvaluetype) 337 goto exit; 338 339 if (!getaddressvalue (valaddress, &htable, bsaddress)) 340 goto exit; 341 342 if (!langsymbolreference (htable, bsaddress, &val, &hnode)) 343 goto exit; 344 345 if (val.valuetype != externalvaluetype) 346 goto exit; 347 348 h = (hdlexternalhandle) val.data.externalvalue; 349 350 if (!menuverbgetsize (h, &menusize)) /*7.1b43 PBS: We don't care about the size. We just want to read it into memory.*/ 351 goto exit; 352 353 if ((**h).id != idmenuprocessor) /*it must be a menu*/ 354 goto exit; 355 356 hm = (hdlmenurecord) (**h).variabledata; 357 358 hsummit = (**(**hm).menuoutline).hsummit; 359 360 #if TARGET_API_MAC_CARBON == 1 361 menuid = kbasecommandid; 362 idsubmenu = 5; 363 #endif 364 365 dockmenudisposemenusinstack (); 366 367 dockmenubuildpopupmenu (hsummit, hmenu); 368 369 *hmreturned = hm; 370 371 fl = true; 372 373 exit: 374 375 disposevaluerecord (valaddress, false); 376 377 return (fl); 378 } /*dockmenufillpopup*/ 379 380 381 static void dockmenuruncommand (hdlmenurecord hm, short itemhit) { 382 383 hdlheadrecord hsummit; 384 hdlheadrecord hmenuitem; 385 bigstring bs; 386 387 hsummit = (**(**hm).menuoutline).hsummit; /*Top level of the menu*/ 388 389 hmenuitem = oprepeatedbump (flatdown, itemhit, hsummit, false); 390 391 oppushoutline ((**hm).menuoutline); 392 393 getheadstring (hmenuitem, bs); 394 395 meuserselected (hmenuitem); 396 397 dockmenudisposemenusinstack (); 398 399 oppopoutline (); 400 } /*dockmenuruncommand*/ 401 402 403 #if TARGET_API_MAC_CARBON == 1 404 405 pascal OSStatus dockcommandhandler (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) { 406 407 #pragma unused(nextHandler) /*happy compiler*/ 408 #pragma unused(theEvent) 409 #pragma unused(userData) 410 411 HICommand commandstruct; 412 UInt32 commandid; 413 OSErr ec = eventNotHandledErr; 414 415 GetEventParameter (theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof (HICommand), NULL, &commandstruct); 416 417 commandid = commandstruct.commandID; 418 419 if ((commandid >= kbasecommandid) && (commandid <= kbasecommandid + kmaxcommands)) { 420 421 dockmenuruncommand (hcurrmenurecord, commandid - kbasecommandid); 422 423 ec = noErr; /*all's well*/ 424 } /*if*/ 425 426 dockmenudisposemenusinstack (); /*7.1b23 PBS: delete and dispose submenus*/ 427 428 return (ec); 429 } /*dockcommandhandler*/ 430 431 432 static void dockmenuinstallhandler (void) { 433 434 EventTypeSpec myevents = {kEventClassCommand, kEventCommandProcess}; 435 436 InstallApplicationEventHandler (NewEventHandlerUPP (dockcommandhandler), 1, &myevents, 0, NULL); 437 438 } /*dockmenuinstallhandler*/ 439 440 441 pascal OSStatus dockmenuhandler (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) { 442 443 /* 444 7.1b22 PBS: called from the system when the dock icon is right-clicked. 445 Build a contextual menu and return it. 446 */ 447 448 #pragma unused(nextHandler) /*happy compiler*/ 449 #pragma unused(theEvent) 450 #pragma unused(userData) 451 452 hdlmenu hmenu; 453 hdlmenurecord hm; 454 static boolean flinited = false; 455 456 menuid = 0; 457 458 dockmenuresetmenustack (); /*7.1b23 PBS: maintain a stack of submenus*/ 459 460 if (!flinited) { /*install command handler first time*/ 461 462 dockmenuinstallhandler (); 463 464 flinited = true; 465 } /*if*/ 466 467 hmenu = Newmenu (defaultpopupmenuid, ""); 468 469 if (!dockmenufillpopup (hmenu, &hm)) 470 goto exit; 471 472 dockmenuaddtomenustack (hmenu, defaultpopupmenuid); 473 474 hcurrmenurecord = hm; 475 476 SetEventParameter (theEvent, kEventParamMenuRef, typeMenuRef, sizeof (MenuRef), &hmenu); 477 478 exit: 479 480 return (noErr); /*all's well in dock-menu-land*/ 481 } /*dockmenuhandler*/ 482 483 #endif 484 485 #if WIN95VERSION 486 487 void rundockmenu (void) { 488 489 /* 490 The system tray icon or dock icon has been right-clicked. 491 Display a menu and handle the user's choice. 492 */ 493 494 hdlmenu hmenu; 495 hdlmenurecord hm; 496 POINT mousept; 497 UINT flags = 0; 498 499 hmenu = Newmenu (defaultpopupmenuid, ""); 500 501 menuid = 0; 502 503 if (!dockmenufillpopup (hmenu, &hm)) 504 goto exit; 505 506 SetMenuDefaultItem (GetSubMenu (hmenu, 0), 0, true); /*Top item is default*/ 507 508 GetCursorPos (&mousept); 509 510 SetForegroundWindow (shellframewindow); 511 512 if (TrackPopupMenuEx (GetSubMenu (hmenu, 0), flags, mousept.x, mousept.y, shellframewindow, NULL)) { 513 514 MSG msg; 515 short itemhit; 516 hdlheadrecord hsummit; 517 hdlheadrecord hmenuitem; 518 bigstring bs; 519 boolean flopencommand = false; 520 521 if (PeekMessage (&msg, shellframewindow, WM_COMMAND, WM_COMMAND, PM_REMOVE)) { 522 523 itemhit = LOWORD (msg.wParam) % 100; 524 525 hsummit = (**(**hm).menuoutline).hsummit; /*Top level of the menu*/ 526 527 //hmenuitem = opnthsubhead (hsummit, itemhit); 528 529 oppushoutline ((**hm).menuoutline); 530 531 hmenuitem = oprepeatedbump (flatdown, itemhit, hsummit, false); 532 533 getheadstring (hmenuitem, bs); 534 535 if (equalidentifiers (bs, "\x0d" "Open Frontier")) 536 flopencommand = true; 537 538 else if (equalidentifiers (bs, "\x0a" "Open Radio")) 539 flopencommand = true; 540 541 if (flopencommand) { /*Intercept -- there's no script verb for this command.*/ 542 543 ShowWindow (shellframewindow, SW_SHOW); /*Show the window.*/ 544 545 activateapplication (NULL); /*bring to front*/ 546 } /*if*/ 547 548 else /*run the script*/ 549 meuserselected (hmenuitem); 550 551 oppopoutline (); 552 } /*if*/ 553 } /*if*/ 554 555 exit: 556 557 disposemenu (hmenu); 558 } /*rundockmenu*/ 559 560 #endif

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.