TMprint.c revision 0568f49b
1444c061aSmrg/*********************************************************** 2249c3046SmrgCopyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 31477040fSmrg 41477040fSmrgPermission is hereby granted, free of charge, to any person obtaining a 51477040fSmrgcopy of this software and associated documentation files (the "Software"), 61477040fSmrgto deal in the Software without restriction, including without limitation 71477040fSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense, 81477040fSmrgand/or sell copies of the Software, and to permit persons to whom the 91477040fSmrgSoftware is furnished to do so, subject to the following conditions: 101477040fSmrg 111477040fSmrgThe above copyright notice and this permission notice (including the next 121477040fSmrgparagraph) shall be included in all copies or substantial portions of the 131477040fSmrgSoftware. 141477040fSmrg 151477040fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161477040fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171477040fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 181477040fSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191477040fSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 201477040fSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 211477040fSmrgDEALINGS IN THE SOFTWARE. 221477040fSmrg 231477040fSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24444c061aSmrg 25444c061aSmrg All Rights Reserved 26444c061aSmrg 27444c061aSmrgPermission to use, copy, modify, and distribute this software and its 28444c061aSmrgdocumentation for any purpose and without fee is hereby granted, 29444c061aSmrgprovided that the above copyright notice appear in all copies and that 30444c061aSmrgboth that copyright notice and this permission notice appear in 311477040fSmrgsupporting documentation, and that the name of Digital not be 32444c061aSmrgused in advertising or publicity pertaining to distribution of the 33444c061aSmrgsoftware without specific, written prior permission. 34444c061aSmrg 35444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41444c061aSmrgSOFTWARE. 42444c061aSmrg 43444c061aSmrg******************************************************************/ 44444c061aSmrg 45444c061aSmrg/* 46444c061aSmrg 47444c061aSmrgCopyright 1987, 1988, 1998 The Open Group 48444c061aSmrg 49444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 50444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 51444c061aSmrgthe above copyright notice appear in all copies and that both that 52444c061aSmrgcopyright notice and this permission notice appear in supporting 53444c061aSmrgdocumentation. 54444c061aSmrg 55444c061aSmrgThe above copyright notice and this permission notice shall be included in 56444c061aSmrgall copies or substantial portions of the Software. 57444c061aSmrg 58444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64444c061aSmrg 65444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 66444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 67444c061aSmrgin this Software without prior written authorization from The Open Group. 68444c061aSmrg 69444c061aSmrg*/ 70444c061aSmrg 71444c061aSmrg/*LINTLIBRARY*/ 72444c061aSmrg#ifdef HAVE_CONFIG_H 73444c061aSmrg#include <config.h> 74444c061aSmrg#endif 75444c061aSmrg#include "IntrinsicI.h" 76444c061aSmrg#include <stdio.h> 77444c061aSmrg 78444c061aSmrgtypedef struct _TMStringBufRec{ 790568f49bSmrg _XtString start; 800568f49bSmrg _XtString current; 81444c061aSmrg Cardinal max; 82444c061aSmrg}TMStringBufRec, *TMStringBuf; 83444c061aSmrg 84444c061aSmrg 85444c061aSmrg#define STR_THRESHOLD 25 86444c061aSmrg#define STR_INCAMOUNT 100 87444c061aSmrg#define CHECK_STR_OVERFLOW(sb) \ 88444c061aSmrgif (sb->current - sb->start > (int)sb->max - STR_THRESHOLD) \ 890568f49bSmrg{ _XtString old = sb->start; \ 90444c061aSmrg sb->start = XtRealloc(old, (Cardinal)(sb->max += STR_INCAMOUNT)); \ 91444c061aSmrg sb->current = sb->current - old + sb->start; \ 92444c061aSmrg} 93444c061aSmrg 94444c061aSmrg#define ExpandForChars(sb, nchars ) \ 950568f49bSmrg if ((unsigned)(sb->current - sb->start) > (sb->max - STR_THRESHOLD - (Cardinal) nchars)) { \ 960568f49bSmrg _XtString old = sb->start; \ 97444c061aSmrg sb->start = XtRealloc(old, \ 980568f49bSmrg (Cardinal)(sb->max = (Cardinal)(sb->max + STR_INCAMOUNT + (Cardinal) nchars))); \ 99444c061aSmrg sb->current = sb->current - old + sb->start; \ 100444c061aSmrg } 101444c061aSmrg 102444c061aSmrg#define ExpandToFit(sb, more) \ 103444c061aSmrg{ \ 104444c061aSmrg size_t l = strlen(more); \ 105444c061aSmrg ExpandForChars(sb, l); \ 106444c061aSmrg } 107444c061aSmrg 108444c061aSmrgstatic void PrintModifiers( 109444c061aSmrg TMStringBuf sb, 110444c061aSmrg unsigned long mask, unsigned long mod) 111444c061aSmrg{ 112444c061aSmrg Boolean notfirst = False; 113444c061aSmrg CHECK_STR_OVERFLOW(sb); 114444c061aSmrg 115444c061aSmrg if (mask == ~0UL && mod == 0) { 116444c061aSmrg *sb->current++ = '!'; 117444c061aSmrg *sb->current = '\0'; 118444c061aSmrg return; 119444c061aSmrg } 120444c061aSmrg 121444c061aSmrg#define PRINTMOD(modmask,modstring) \ 122444c061aSmrg if (mask & modmask) { \ 123444c061aSmrg if (! (mod & modmask)) { \ 124444c061aSmrg *sb->current++ = '~'; \ 125444c061aSmrg notfirst = True; \ 126444c061aSmrg } \ 127444c061aSmrg else if (notfirst) \ 128444c061aSmrg *sb->current++ = ' '; \ 129444c061aSmrg else notfirst = True; \ 130444c061aSmrg strcpy(sb->current, modstring); \ 131444c061aSmrg sb->current += strlen(sb->current); \ 132444c061aSmrg } 133444c061aSmrg 134444c061aSmrg PRINTMOD(ShiftMask, "Shift"); 135444c061aSmrg PRINTMOD(ControlMask, "Ctrl"); /* name is not CtrlMask... */ 136444c061aSmrg PRINTMOD(LockMask, "Lock"); 137444c061aSmrg PRINTMOD(Mod1Mask, "Mod1"); 138444c061aSmrg CHECK_STR_OVERFLOW(sb); 139444c061aSmrg PRINTMOD(Mod2Mask, "Mod2"); 140444c061aSmrg PRINTMOD(Mod3Mask, "Mod3"); 141444c061aSmrg PRINTMOD(Mod4Mask, "Mod4"); 142444c061aSmrg PRINTMOD(Mod5Mask, "Mod5"); 143444c061aSmrg CHECK_STR_OVERFLOW(sb); 144444c061aSmrg PRINTMOD(Button1Mask, "Button1"); 145444c061aSmrg PRINTMOD(Button2Mask, "Button2"); 146444c061aSmrg PRINTMOD(Button3Mask, "Button3"); 147444c061aSmrg CHECK_STR_OVERFLOW(sb); 148444c061aSmrg PRINTMOD(Button4Mask, "Button4"); 149444c061aSmrg PRINTMOD(Button5Mask, "Button5"); 1500568f49bSmrg (void) notfirst; 151444c061aSmrg 152444c061aSmrg#undef PRINTMOD 153444c061aSmrg} 154444c061aSmrg 155444c061aSmrgstatic void PrintEventType( 156444c061aSmrg TMStringBuf sb, 157444c061aSmrg unsigned long event) 158444c061aSmrg{ 159444c061aSmrg CHECK_STR_OVERFLOW(sb); 160444c061aSmrg switch (event) { 161444c061aSmrg#define PRINTEVENT(event, name) case event: (void) strcpy(sb->current, name); break; 162444c061aSmrg PRINTEVENT(KeyPress, "<KeyPress>") 163444c061aSmrg PRINTEVENT(KeyRelease, "<KeyRelease>") 164444c061aSmrg PRINTEVENT(ButtonPress, "<ButtonPress>") 165444c061aSmrg PRINTEVENT(ButtonRelease, "<ButtonRelease>") 166444c061aSmrg PRINTEVENT(MotionNotify, "<MotionNotify>") 167444c061aSmrg PRINTEVENT(EnterNotify, "<EnterNotify>") 168444c061aSmrg PRINTEVENT(LeaveNotify, "<LeaveNotify>") 169444c061aSmrg PRINTEVENT(FocusIn, "<FocusIn>") 170444c061aSmrg PRINTEVENT(FocusOut, "<FocusOut>") 171444c061aSmrg PRINTEVENT(KeymapNotify, "<KeymapNotify>") 172444c061aSmrg PRINTEVENT(Expose, "<Expose>") 173444c061aSmrg PRINTEVENT(GraphicsExpose, "<GraphicsExpose>") 174444c061aSmrg PRINTEVENT(NoExpose, "<NoExpose>") 175444c061aSmrg PRINTEVENT(VisibilityNotify, "<VisibilityNotify>") 176444c061aSmrg PRINTEVENT(CreateNotify, "<CreateNotify>") 177444c061aSmrg PRINTEVENT(DestroyNotify, "<DestroyNotify>") 178444c061aSmrg PRINTEVENT(UnmapNotify, "<UnmapNotify>") 179444c061aSmrg PRINTEVENT(MapNotify, "<MapNotify>") 180444c061aSmrg PRINTEVENT(MapRequest, "<MapRequest>") 181444c061aSmrg PRINTEVENT(ReparentNotify, "<ReparentNotify>") 182444c061aSmrg PRINTEVENT(ConfigureNotify, "<ConfigureNotify>") 183444c061aSmrg PRINTEVENT(ConfigureRequest, "<ConfigureRequest>") 184444c061aSmrg PRINTEVENT(GravityNotify, "<GravityNotify>") 185444c061aSmrg PRINTEVENT(ResizeRequest, "<ResizeRequest>") 186444c061aSmrg PRINTEVENT(CirculateNotify, "<CirculateNotify>") 187444c061aSmrg PRINTEVENT(CirculateRequest, "<CirculateRequest>") 188444c061aSmrg PRINTEVENT(PropertyNotify, "<PropertyNotify>") 189444c061aSmrg PRINTEVENT(SelectionClear, "<SelectionClear>") 190444c061aSmrg PRINTEVENT(SelectionRequest, "<SelectionRequest>") 191444c061aSmrg PRINTEVENT(SelectionNotify, "<SelectionNotify>") 192444c061aSmrg PRINTEVENT(ColormapNotify, "<ColormapNotify>") 193444c061aSmrg PRINTEVENT(ClientMessage, "<ClientMessage>") 194444c061aSmrg case _XtEventTimerEventType: 195444c061aSmrg (void) strcpy(sb->current,"<EventTimer>"); 196444c061aSmrg break; 197444c061aSmrg default: 198444c061aSmrg (void) sprintf(sb->current, "<0x%x>", (int) event); 199444c061aSmrg#undef PRINTEVENT 200444c061aSmrg } 201444c061aSmrg sb->current += strlen(sb->current); 202444c061aSmrg} 203444c061aSmrg 204444c061aSmrgstatic void PrintCode( 205444c061aSmrg TMStringBuf sb, 206444c061aSmrg unsigned long mask, unsigned long code) 207444c061aSmrg{ 208444c061aSmrg CHECK_STR_OVERFLOW(sb); 209444c061aSmrg if (mask != 0) { 210444c061aSmrg if (mask != ~0UL) 211444c061aSmrg (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code); 2120568f49bSmrg else (void) sprintf(sb->current, /*"0x%lx"*/ "%u", (unsigned)code); 213444c061aSmrg sb->current += strlen(sb->current); 214444c061aSmrg } 215444c061aSmrg} 216444c061aSmrg 217444c061aSmrgstatic void PrintKeysym( 218444c061aSmrg TMStringBuf sb, 219444c061aSmrg KeySym keysym) 220444c061aSmrg{ 221444c061aSmrg String keysymName; 222444c061aSmrg 223444c061aSmrg if (keysym == 0) return; 224444c061aSmrg 225444c061aSmrg CHECK_STR_OVERFLOW(sb); 226444c061aSmrg keysymName = XKeysymToString(keysym); 227444c061aSmrg if (keysymName == NULL) 228444c061aSmrg PrintCode(sb,~0UL,(unsigned long)keysym); 229444c061aSmrg else { 230444c061aSmrg ExpandToFit(sb, keysymName); 231444c061aSmrg strcpy(sb->current, keysymName); 232444c061aSmrg sb->current += strlen(sb->current); 233444c061aSmrg } 234444c061aSmrg} 235444c061aSmrg 236444c061aSmrgstatic void PrintAtom( 237444c061aSmrg TMStringBuf sb, 238444c061aSmrg Display *dpy, 239444c061aSmrg Atom atom) 240444c061aSmrg{ 2410568f49bSmrg _XtString atomName; 242444c061aSmrg 243444c061aSmrg if (atom == 0) return; 244444c061aSmrg 245444c061aSmrg atomName = (dpy ? XGetAtomName(dpy, atom) : NULL); 246444c061aSmrg 247444c061aSmrg if (! atomName) 248444c061aSmrg PrintCode(sb,~0UL,(unsigned long)atom); 249444c061aSmrg else { 250444c061aSmrg ExpandToFit( sb, atomName ); 251444c061aSmrg strcpy(sb->current, atomName); 252444c061aSmrg sb->current += strlen(sb->current); 253444c061aSmrg XFree(atomName); 254444c061aSmrg } 255444c061aSmrg} 256444c061aSmrg 257444c061aSmrgstatic void PrintLateModifiers( 258444c061aSmrg TMStringBuf sb, 259444c061aSmrg LateBindingsPtr lateModifiers) 260444c061aSmrg{ 261444c061aSmrg for (; lateModifiers->keysym; lateModifiers++) { 262444c061aSmrg CHECK_STR_OVERFLOW(sb); 263444c061aSmrg if (lateModifiers->knot) { 264444c061aSmrg *sb->current++ = '~'; 265444c061aSmrg } else { 266444c061aSmrg *sb->current++ = ' '; 267444c061aSmrg } 268444c061aSmrg strcpy(sb->current, XKeysymToString(lateModifiers->keysym)); 269444c061aSmrg sb->current += strlen(sb->current); 270444c061aSmrg if (lateModifiers->pair) { 271444c061aSmrg *(sb->current -= 2) = '\0'; /* strip "_L" */ 272444c061aSmrg lateModifiers++; /* skip _R keysym */ 273444c061aSmrg } 274444c061aSmrg } 275444c061aSmrg} 276444c061aSmrg 277444c061aSmrgstatic void PrintEvent( 278444c061aSmrg TMStringBuf sb, 279444c061aSmrg register TMTypeMatch typeMatch, 280444c061aSmrg register TMModifierMatch modMatch, 281444c061aSmrg Display *dpy) 282444c061aSmrg{ 283444c061aSmrg if (modMatch->standard) *sb->current++ = ':'; 284444c061aSmrg 285444c061aSmrg PrintModifiers(sb, modMatch->modifierMask, modMatch->modifiers); 286444c061aSmrg if (modMatch->lateModifiers != NULL) 287444c061aSmrg PrintLateModifiers(sb, modMatch->lateModifiers); 288444c061aSmrg PrintEventType(sb, typeMatch->eventType); 289444c061aSmrg switch (typeMatch->eventType) { 290444c061aSmrg case KeyPress: 291444c061aSmrg case KeyRelease: 292444c061aSmrg PrintKeysym(sb, (KeySym)typeMatch->eventCode); 293444c061aSmrg break; 294444c061aSmrg 295444c061aSmrg case PropertyNotify: 296444c061aSmrg case SelectionClear: 297444c061aSmrg case SelectionRequest: 298444c061aSmrg case SelectionNotify: 299444c061aSmrg case ClientMessage: 300444c061aSmrg PrintAtom(sb, dpy, (Atom)typeMatch->eventCode); 301444c061aSmrg break; 302444c061aSmrg 303444c061aSmrg default: 304444c061aSmrg PrintCode(sb, typeMatch->eventCodeMask, typeMatch->eventCode); 305444c061aSmrg } 306444c061aSmrg} 307444c061aSmrg 308444c061aSmrgstatic void PrintParams( 309444c061aSmrg TMStringBuf sb, 310444c061aSmrg String *params, 311444c061aSmrg Cardinal num_params) 312444c061aSmrg{ 313444c061aSmrg register Cardinal i; 314444c061aSmrg for (i = 0; i<num_params; i++) { 315444c061aSmrg ExpandToFit( sb, params[i] ); 316444c061aSmrg if (i != 0) { 317444c061aSmrg *sb->current++ = ','; 318444c061aSmrg *sb->current++ = ' '; 319444c061aSmrg } 320444c061aSmrg *sb->current++ = '"'; 321444c061aSmrg strcpy(sb->current, params[i]); 322444c061aSmrg sb->current += strlen(sb->current); 323444c061aSmrg *sb->current++ = '"'; 324444c061aSmrg } 325444c061aSmrg *sb->current = '\0'; 326444c061aSmrg} 327444c061aSmrg 328444c061aSmrgstatic void PrintActions( 329444c061aSmrg TMStringBuf sb, 330444c061aSmrg register ActionPtr actions, 331444c061aSmrg XrmQuark *quarkTbl, 332444c061aSmrg Widget accelWidget) 333444c061aSmrg{ 334444c061aSmrg while (actions != NULL) { 335444c061aSmrg String proc; 336444c061aSmrg 337444c061aSmrg *sb->current++ = ' '; 338444c061aSmrg 339444c061aSmrg if (accelWidget) { 340444c061aSmrg /* accelerator */ 341444c061aSmrg String name = XtName(accelWidget); 3420568f49bSmrg int nameLen = (int) strlen(name); 343444c061aSmrg ExpandForChars(sb, nameLen ); 344444c061aSmrg XtMemmove(sb->current, name, nameLen ); 345444c061aSmrg sb->current += nameLen; 346444c061aSmrg *sb->current++ = '`'; 347444c061aSmrg } 348444c061aSmrg proc = XrmQuarkToString(quarkTbl[actions->idx]); 349444c061aSmrg ExpandToFit( sb, proc ); 350444c061aSmrg strcpy(sb->current, proc); 351444c061aSmrg sb->current += strlen(proc); 352444c061aSmrg *sb->current++ = '('; 353444c061aSmrg PrintParams(sb, actions->params, actions->num_params); 354444c061aSmrg *sb->current++ = ')'; 355444c061aSmrg actions = actions->next; 356444c061aSmrg } 357444c061aSmrg *sb->current = '\0'; 358444c061aSmrg} 359444c061aSmrg 360444c061aSmrgstatic Boolean LookAheadForCycleOrMulticlick( 361444c061aSmrg register StatePtr state, 362444c061aSmrg StatePtr *state_return, /* state to print, usually startState */ 363444c061aSmrg int *countP, 364444c061aSmrg StatePtr *nextLevelP) 365444c061aSmrg{ 366444c061aSmrg int repeatCount = 0; 367444c061aSmrg StatePtr startState = state; 368444c061aSmrg Boolean isCycle = startState->isCycleEnd; 369444c061aSmrg TMTypeMatch sTypeMatch; 370444c061aSmrg TMModifierMatch sModMatch; 371444c061aSmrg 372444c061aSmrg LOCK_PROCESS; 373444c061aSmrg sTypeMatch = TMGetTypeMatch(startState->typeIndex); 374444c061aSmrg sModMatch = TMGetModifierMatch(startState->modIndex); 375444c061aSmrg 376444c061aSmrg *state_return = startState; 377444c061aSmrg 378444c061aSmrg for (state = state->nextLevel; state != NULL; state = state->nextLevel) { 379444c061aSmrg TMTypeMatch typeMatch = TMGetTypeMatch(state->typeIndex); 380444c061aSmrg TMModifierMatch modMatch = TMGetModifierMatch(state->modIndex); 381444c061aSmrg 382444c061aSmrg /* try to pick up the correct state with actions, to be printed */ 383444c061aSmrg /* This is to accommodate <ButtonUp>(2+), for example */ 384444c061aSmrg if (state->isCycleStart) 385444c061aSmrg *state_return = state; 386444c061aSmrg 387444c061aSmrg if (state->isCycleEnd) { 388444c061aSmrg *countP = repeatCount; 389444c061aSmrg UNLOCK_PROCESS; 390444c061aSmrg return True; 391444c061aSmrg } 392444c061aSmrg if ((startState->typeIndex == state->typeIndex) && 393444c061aSmrg (startState->modIndex == state->modIndex)) { 394444c061aSmrg repeatCount++; 395444c061aSmrg *nextLevelP = state; 396444c061aSmrg } 397444c061aSmrg else if (typeMatch->eventType == _XtEventTimerEventType) 398444c061aSmrg continue; 399444c061aSmrg else /* not same event as starting event and not timer */ { 4000568f49bSmrg unsigned int type = (unsigned) sTypeMatch->eventType; 4010568f49bSmrg unsigned int t = (unsigned) typeMatch->eventType; 402444c061aSmrg if ( (type == ButtonPress && t != ButtonRelease) 403444c061aSmrg || (type == ButtonRelease && t != ButtonPress) 404444c061aSmrg || (type == KeyPress && t != KeyRelease) 405444c061aSmrg || (type == KeyRelease && t != KeyPress) 406444c061aSmrg || typeMatch->eventCode != sTypeMatch->eventCode 407444c061aSmrg || modMatch->modifiers != sModMatch->modifiers 408444c061aSmrg || modMatch->modifierMask != sModMatch->modifierMask 409444c061aSmrg || modMatch->lateModifiers != sModMatch->lateModifiers 410444c061aSmrg || typeMatch->eventCodeMask != sTypeMatch->eventCodeMask 411444c061aSmrg || typeMatch->matchEvent != sTypeMatch->matchEvent 412444c061aSmrg || modMatch->standard != sModMatch->standard) 413444c061aSmrg /* not inverse of starting event, either */ 414444c061aSmrg break; 415444c061aSmrg } 416444c061aSmrg } 417444c061aSmrg *countP = repeatCount; 418444c061aSmrg UNLOCK_PROCESS; 419444c061aSmrg return isCycle; 420444c061aSmrg} 421444c061aSmrg 422444c061aSmrgstatic void PrintComplexState( 423444c061aSmrg TMStringBuf sb, 424444c061aSmrg Boolean includeRHS, 425444c061aSmrg StatePtr state, 426444c061aSmrg TMStateTree stateTree, 427444c061aSmrg Widget accelWidget, 428444c061aSmrg Display *dpy) 429444c061aSmrg{ 430444c061aSmrg int clickCount = 0; 431444c061aSmrg Boolean cycle; 432444c061aSmrg StatePtr nextLevel = NULL; 433444c061aSmrg StatePtr triggerState = NULL; 434444c061aSmrg 435444c061aSmrg /* print the current state */ 436444c061aSmrg if (! state) return; 437444c061aSmrg LOCK_PROCESS; 438444c061aSmrg cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount, 439444c061aSmrg &nextLevel); 440444c061aSmrg 441444c061aSmrg PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex), 442444c061aSmrg TMGetModifierMatch(triggerState->modIndex), dpy); 443444c061aSmrg 444444c061aSmrg if (cycle || clickCount) { 445444c061aSmrg if (clickCount) 446444c061aSmrg sprintf(sb->current, "(%d%s)", clickCount+1, cycle ? "+" : ""); 447444c061aSmrg else 448444c061aSmrg (void) strncpy(sb->current, "(+)", 4); 449444c061aSmrg sb->current += strlen(sb->current); 450444c061aSmrg if (! state->actions && nextLevel) 451444c061aSmrg state = nextLevel; 452444c061aSmrg while (! state->actions && ! state->isCycleEnd) 453444c061aSmrg state = state->nextLevel; /* should be trigger state */ 454444c061aSmrg } 455444c061aSmrg 456444c061aSmrg if (state->actions) { 457444c061aSmrg if (includeRHS) { 458444c061aSmrg CHECK_STR_OVERFLOW(sb); 459444c061aSmrg *sb->current++ = ':'; 460444c061aSmrg PrintActions(sb, 461444c061aSmrg state->actions, 462444c061aSmrg ((TMSimpleStateTree)stateTree)->quarkTbl, 463444c061aSmrg accelWidget); 464444c061aSmrg *sb->current++ = '\n'; 465444c061aSmrg } 466444c061aSmrg } 467444c061aSmrg else { 468444c061aSmrg if (state->nextLevel && !cycle && !clickCount) 469444c061aSmrg *sb->current++ = ','; 470444c061aSmrg else { 471444c061aSmrg /* no actions are attached to this production */ 472444c061aSmrg *sb->current++ = ':'; 473444c061aSmrg *sb->current++ = '\n'; 474444c061aSmrg } 475444c061aSmrg } 476444c061aSmrg *sb->current = '\0'; 477444c061aSmrg 478444c061aSmrg /* print succeeding states */ 479444c061aSmrg if (state->nextLevel && !cycle && !clickCount) 480444c061aSmrg PrintComplexState(sb, includeRHS, state->nextLevel, 481444c061aSmrg stateTree, accelWidget, dpy); 482444c061aSmrg UNLOCK_PROCESS; 483444c061aSmrg} 484444c061aSmrg 485444c061aSmrgtypedef struct{ 486444c061aSmrg TMShortCard tIndex; 487444c061aSmrg TMShortCard bIndex; 488444c061aSmrg}PrintRec, *Print; 489444c061aSmrg 490444c061aSmrgstatic int FindNextMatch( 491444c061aSmrg PrintRec *printData, 492444c061aSmrg TMShortCard numPrints, 493444c061aSmrg XtTranslations xlations, 494444c061aSmrg TMBranchHead branchHead, 495444c061aSmrg StatePtr nextLevel, 496444c061aSmrg TMShortCard startIndex) 497444c061aSmrg{ 498444c061aSmrg TMShortCard i; 499444c061aSmrg StatePtr currState, candState; 500444c061aSmrg Boolean noMatch = True; 501444c061aSmrg 502444c061aSmrg for (i = startIndex; noMatch && i < numPrints; i++) { 5030568f49bSmrg TMBranchHead prBranchHead; 5040568f49bSmrg TMComplexStateTree stateTree; 5050568f49bSmrg 506444c061aSmrg stateTree = (TMComplexStateTree) 507444c061aSmrg xlations->stateTreeTbl[printData[i].tIndex]; 508444c061aSmrg prBranchHead = 509444c061aSmrg &(stateTree->branchHeadTbl[printData[i].bIndex]); 510444c061aSmrg 511444c061aSmrg if ((prBranchHead->typeIndex == branchHead->typeIndex) && 512444c061aSmrg (prBranchHead->modIndex == branchHead->modIndex)) { 513444c061aSmrg if (prBranchHead->isSimple) { 514444c061aSmrg if (!nextLevel) 515444c061aSmrg return i; 516444c061aSmrg } 517444c061aSmrg else { 518444c061aSmrg currState = TMComplexBranchHead(stateTree, prBranchHead); 519444c061aSmrg currState = currState->nextLevel; 520444c061aSmrg candState = nextLevel; 521444c061aSmrg for (; 522444c061aSmrg ((currState && !currState->isCycleEnd) && 523444c061aSmrg (candState && !candState->isCycleEnd)); 524444c061aSmrg currState = currState->nextLevel, 525444c061aSmrg candState = candState->nextLevel) { 526444c061aSmrg if ((currState->typeIndex != candState->typeIndex) || 527444c061aSmrg (currState->modIndex != candState->modIndex)) 528444c061aSmrg break; 529444c061aSmrg } 530444c061aSmrg if (candState == currState) { 531444c061aSmrg return i; 532444c061aSmrg } 533444c061aSmrg } 534444c061aSmrg } 535444c061aSmrg } 536444c061aSmrg return TM_NO_MATCH; 537444c061aSmrg} 538444c061aSmrg 539444c061aSmrgstatic void ProcessLaterMatches( 540444c061aSmrg PrintRec *printData, 541444c061aSmrg XtTranslations xlations, 542444c061aSmrg TMShortCard tIndex, 543444c061aSmrg int bIndex, 544444c061aSmrg TMShortCard *numPrintsRtn) 545444c061aSmrg{ 546444c061aSmrg TMComplexStateTree stateTree; 547444c061aSmrg int i, j; 548444c061aSmrg TMBranchHead branchHead, matchBranch = NULL; 549444c061aSmrg 550444c061aSmrg for (i = tIndex; i < (int)xlations->numStateTrees; i++) { 551444c061aSmrg stateTree = (TMComplexStateTree)xlations->stateTreeTbl[i]; 552444c061aSmrg if (i == tIndex) { 553444c061aSmrg matchBranch = &stateTree->branchHeadTbl[bIndex]; 554444c061aSmrg j = bIndex+1; 555444c061aSmrg } 556444c061aSmrg else j = 0; 557444c061aSmrg for (branchHead = &stateTree->branchHeadTbl[j]; 558444c061aSmrg j < (int)stateTree->numBranchHeads; 559444c061aSmrg j++, branchHead++) { 560444c061aSmrg if ((branchHead->typeIndex == matchBranch->typeIndex) && 561444c061aSmrg (branchHead->modIndex == matchBranch->modIndex)) { 562444c061aSmrg StatePtr state; 563444c061aSmrg if (!branchHead->isSimple) 564444c061aSmrg state = TMComplexBranchHead(stateTree, branchHead); 565444c061aSmrg else 566444c061aSmrg state = NULL; 567444c061aSmrg if ((!branchHead->isSimple || branchHead->hasActions) && 568444c061aSmrg (FindNextMatch(printData, 569444c061aSmrg *numPrintsRtn, 570444c061aSmrg xlations, 571444c061aSmrg branchHead, 572444c061aSmrg (state ? state->nextLevel : NULL), 573444c061aSmrg 0) == TM_NO_MATCH)) { 5740568f49bSmrg printData[*numPrintsRtn].tIndex = (TMShortCard) i; 5750568f49bSmrg printData[*numPrintsRtn].bIndex = (TMShortCard) j; 576444c061aSmrg (*numPrintsRtn)++; 577444c061aSmrg } 578444c061aSmrg } 579444c061aSmrg } 580444c061aSmrg } 581444c061aSmrg} 582444c061aSmrg 583444c061aSmrgstatic void ProcessStateTree( 584444c061aSmrg PrintRec *printData, 585444c061aSmrg XtTranslations xlations, 586444c061aSmrg TMShortCard tIndex, 587444c061aSmrg TMShortCard *numPrintsRtn) 588444c061aSmrg{ 589444c061aSmrg TMComplexStateTree stateTree; 590444c061aSmrg int i; 591444c061aSmrg TMBranchHead branchHead; 592444c061aSmrg 593444c061aSmrg stateTree = (TMComplexStateTree)xlations->stateTreeTbl[tIndex]; 594444c061aSmrg 595444c061aSmrg for (i = 0, branchHead = stateTree->branchHeadTbl; 596444c061aSmrg i < (int)stateTree->numBranchHeads; 597444c061aSmrg i++, branchHead++) { 598444c061aSmrg StatePtr state; 599444c061aSmrg if (!branchHead->isSimple) 600444c061aSmrg state = TMComplexBranchHead(stateTree, branchHead); 601444c061aSmrg else 602444c061aSmrg state = NULL; 603444c061aSmrg if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead, 604444c061aSmrg (state ? state->nextLevel : NULL), 0) 605444c061aSmrg == TM_NO_MATCH) { 606444c061aSmrg if (!branchHead->isSimple || branchHead->hasActions) { 607444c061aSmrg printData[*numPrintsRtn].tIndex = tIndex; 6080568f49bSmrg printData[*numPrintsRtn].bIndex = (TMShortCard) i; 609444c061aSmrg (*numPrintsRtn)++; 610444c061aSmrg } 611444c061aSmrg LOCK_PROCESS; 612444c061aSmrg if (_XtGlobalTM.newMatchSemantics == False) 613444c061aSmrg ProcessLaterMatches(printData, 614444c061aSmrg xlations, 615444c061aSmrg tIndex, 616444c061aSmrg i, 617444c061aSmrg numPrintsRtn); 618444c061aSmrg UNLOCK_PROCESS; 619444c061aSmrg } 620444c061aSmrg } 621444c061aSmrg} 622444c061aSmrg 623444c061aSmrgstatic void PrintState( 624444c061aSmrg TMStringBuf sb, 625444c061aSmrg TMStateTree tree, 626444c061aSmrg TMBranchHead branchHead, 627444c061aSmrg Boolean includeRHS, 628444c061aSmrg Widget accelWidget, 629444c061aSmrg Display *dpy) 630444c061aSmrg{ 631444c061aSmrg TMComplexStateTree stateTree = (TMComplexStateTree)tree; 632444c061aSmrg LOCK_PROCESS; 633444c061aSmrg if (branchHead->isSimple) { 634444c061aSmrg PrintEvent(sb, 635444c061aSmrg TMGetTypeMatch(branchHead->typeIndex), 636444c061aSmrg TMGetModifierMatch(branchHead->modIndex), 637444c061aSmrg dpy); 638444c061aSmrg if (includeRHS) { 639444c061aSmrg ActionRec actRec; 640444c061aSmrg 641444c061aSmrg CHECK_STR_OVERFLOW(sb); 642444c061aSmrg *sb->current++ = ':'; 643444c061aSmrg actRec.idx = TMBranchMore(branchHead); 644444c061aSmrg actRec.num_params = 0; 645444c061aSmrg actRec.params = NULL; 646444c061aSmrg actRec.next = NULL; 647444c061aSmrg PrintActions(sb, 648444c061aSmrg &actRec, 649444c061aSmrg stateTree->quarkTbl, 650444c061aSmrg accelWidget); 651444c061aSmrg *sb->current++ = '\n'; 652444c061aSmrg } 653444c061aSmrg else 654444c061aSmrg *sb->current++ = ','; 655444c061aSmrg#ifdef TRACE_TM 656444c061aSmrg if (!branchHead->hasActions) 657444c061aSmrg printf(" !! no actions !! "); 658444c061aSmrg#endif 659444c061aSmrg } 660444c061aSmrg else { /* it's a complex branchHead */ 661444c061aSmrg StatePtr state = TMComplexBranchHead(stateTree, branchHead); 662444c061aSmrg PrintComplexState(sb, 663444c061aSmrg includeRHS, 664444c061aSmrg state, 665444c061aSmrg tree, 666444c061aSmrg accelWidget, 667444c061aSmrg (Display *)NULL); 668444c061aSmrg } 669444c061aSmrg *sb->current = '\0'; 670444c061aSmrg UNLOCK_PROCESS; 671444c061aSmrg} 672444c061aSmrg 6730568f49bSmrg_XtString _XtPrintXlations( 674444c061aSmrg Widget w, 675444c061aSmrg XtTranslations xlations, 676444c061aSmrg Widget accelWidget, 677444c061aSmrg _XtBoolean includeRHS) 678444c061aSmrg{ 679444c061aSmrg register Cardinal i; 680444c061aSmrg#define STACKPRINTSIZE 250 681444c061aSmrg PrintRec stackPrints[STACKPRINTSIZE]; 682444c061aSmrg PrintRec *prints; 683444c061aSmrg TMStringBufRec sbRec, *sb = &sbRec; 684444c061aSmrg TMShortCard numPrints, maxPrints; 685444c061aSmrg#ifdef TRACE_TM 686444c061aSmrg TMBindData bindData = (TMBindData)w->core.tm.proc_table; 687444c061aSmrg Boolean hasAccel = (accelWidget ? True : False); 688444c061aSmrg#endif /* TRACE_TM */ 689444c061aSmrg if (xlations == NULL) return NULL; 690444c061aSmrg 691444c061aSmrg sb->current = sb->start = __XtMalloc((Cardinal)1000); 692444c061aSmrg sb->max = 1000; 693444c061aSmrg maxPrints = 0; 694444c061aSmrg for (i = 0; i < xlations->numStateTrees; i++) 6950568f49bSmrg maxPrints = (TMShortCard) (maxPrints + 6960568f49bSmrg ((TMSimpleStateTree)(xlations->stateTreeTbl[i]))->numBranchHeads); 697444c061aSmrg prints = (PrintRec *) 698444c061aSmrg XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints); 699444c061aSmrg 700444c061aSmrg numPrints = 0; 701444c061aSmrg for (i = 0; i < xlations->numStateTrees; i++) 7020568f49bSmrg ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints); 703444c061aSmrg 704444c061aSmrg for (i = 0; i < numPrints; i++) { 705444c061aSmrg TMSimpleStateTree stateTree = (TMSimpleStateTree) 706444c061aSmrg xlations->stateTreeTbl[prints[i].tIndex]; 707444c061aSmrg TMBranchHead branchHead = 708444c061aSmrg &stateTree->branchHeadTbl[prints[i].bIndex]; 709444c061aSmrg#ifdef TRACE_TM 710444c061aSmrg TMComplexBindProcs complexBindProcs; 711444c061aSmrg 712444c061aSmrg if (hasAccel == False) { 713444c061aSmrg accelWidget = NULL; 714444c061aSmrg if (bindData->simple.isComplex) { 715444c061aSmrg complexBindProcs = TMGetComplexBindEntry(bindData, 0); 716444c061aSmrg accelWidget = complexBindProcs[prints[i].tIndex].widget; 717444c061aSmrg } 718444c061aSmrg } 719444c061aSmrg#endif /* TRACE_TM */ 720444c061aSmrg PrintState(sb, (TMStateTree)stateTree, branchHead, 7210568f49bSmrg (Boolean) includeRHS, accelWidget, XtDisplay(w)); 722444c061aSmrg } 723444c061aSmrg XtStackFree((XtPointer)prints, (XtPointer)stackPrints); 724444c061aSmrg return (sb->start); 725444c061aSmrg} 726444c061aSmrg 727444c061aSmrg 728444c061aSmrg#ifndef NO_MIT_HACKS 729444c061aSmrg/*ARGSUSED*/ 730444c061aSmrgvoid _XtDisplayTranslations( 731444c061aSmrg Widget widget, 732444c061aSmrg XEvent *event, 733444c061aSmrg String *params, 734444c061aSmrg Cardinal *num_params) 735444c061aSmrg{ 7360568f49bSmrg _XtString xString; 737444c061aSmrg 738444c061aSmrg xString = _XtPrintXlations(widget, 739444c061aSmrg widget->core.tm.translations, 740444c061aSmrg NULL, 741444c061aSmrg True); 7422265a131Smrg if (xString) { 7432265a131Smrg printf("%s\n",xString); 7442265a131Smrg XtFree(xString); 7452265a131Smrg } 746444c061aSmrg} 747444c061aSmrg 748444c061aSmrg/*ARGSUSED*/ 749444c061aSmrgvoid _XtDisplayAccelerators( 750444c061aSmrg Widget widget, 751444c061aSmrg XEvent *event, 752444c061aSmrg String *params, 753444c061aSmrg Cardinal *num_params) 754444c061aSmrg{ 7550568f49bSmrg _XtString xString; 756444c061aSmrg 757444c061aSmrg 758444c061aSmrg xString = _XtPrintXlations(widget, 759444c061aSmrg widget->core.accelerators, 760444c061aSmrg NULL, 761444c061aSmrg True); 7622265a131Smrg if (xString) { 7632265a131Smrg printf("%s\n",xString); 7642265a131Smrg XtFree(xString); 7652265a131Smrg } 766444c061aSmrg} 767444c061aSmrg 768444c061aSmrg/*ARGSUSED*/ 769444c061aSmrgvoid _XtDisplayInstalledAccelerators( 770444c061aSmrg Widget widget, 771444c061aSmrg XEvent *event, 772444c061aSmrg String *params, 773444c061aSmrg Cardinal *num_params) 774444c061aSmrg{ 775444c061aSmrg Widget eventWidget 776444c061aSmrg = XtWindowToWidget(event->xany.display, event->xany.window); 777444c061aSmrg register Cardinal i; 778444c061aSmrg TMStringBufRec sbRec, *sb = &sbRec; 779444c061aSmrg XtTranslations xlations; 780444c061aSmrg#define STACKPRINTSIZE 250 781444c061aSmrg PrintRec stackPrints[STACKPRINTSIZE]; 782444c061aSmrg PrintRec *prints; 783444c061aSmrg TMShortCard numPrints, maxPrints; 784249c3046Smrg TMBindData bindData ; 785444c061aSmrg TMComplexBindProcs complexBindProcs; 786444c061aSmrg 787444c061aSmrg if ((eventWidget == NULL) || 788249c3046Smrg (eventWidget->core.tm.translations == NULL) ) 789249c3046Smrg return; 790249c3046Smrg 791249c3046Smrg xlations = eventWidget->core.tm.translations; 792249c3046Smrg bindData = (TMBindData) eventWidget->core.tm.proc_table; 793249c3046Smrg if (bindData->simple.isComplex == False) 794444c061aSmrg return; 795444c061aSmrg 796444c061aSmrg sb->current = sb->start = __XtMalloc((Cardinal)1000); 797444c061aSmrg sb->start[0] = '\0'; 798444c061aSmrg sb->max = 1000; 799444c061aSmrg maxPrints = 0; 800444c061aSmrg for (i = 0; i < xlations->numStateTrees; i++) 8010568f49bSmrg maxPrints = (TMShortCard) (maxPrints + 8020568f49bSmrg ((TMSimpleStateTree)xlations->stateTreeTbl[i])->numBranchHeads); 803444c061aSmrg prints = (PrintRec *) 804444c061aSmrg XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints); 805444c061aSmrg 806444c061aSmrg numPrints = 0; 807444c061aSmrg 808444c061aSmrg complexBindProcs = TMGetComplexBindEntry(bindData, 0); 809444c061aSmrg for (i = 0; 810444c061aSmrg i < xlations->numStateTrees; 811444c061aSmrg i++, complexBindProcs++) { 812444c061aSmrg if (complexBindProcs->widget) 813444c061aSmrg { 8140568f49bSmrg ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints); 815444c061aSmrg } 816444c061aSmrg } 817444c061aSmrg for (i = 0; i < numPrints; i++) { 818444c061aSmrg TMSimpleStateTree stateTree = (TMSimpleStateTree) 819444c061aSmrg xlations->stateTreeTbl[prints[i].tIndex]; 820444c061aSmrg TMBranchHead branchHead = 821444c061aSmrg &stateTree->branchHeadTbl[prints[i].bIndex]; 822444c061aSmrg 823444c061aSmrg complexBindProcs = TMGetComplexBindEntry(bindData, 0); 824444c061aSmrg 825444c061aSmrg PrintState(sb, (TMStateTree)stateTree, branchHead, True, 826444c061aSmrg complexBindProcs[prints[i].tIndex].widget, 827444c061aSmrg XtDisplay(widget)); 828444c061aSmrg } 829444c061aSmrg XtStackFree((XtPointer)prints, (XtPointer)stackPrints); 830444c061aSmrg printf("%s\n", sb->start); 831444c061aSmrg XtFree(sb->start); 832444c061aSmrg} 833444c061aSmrg#endif /*NO_MIT_HACKS*/ 834444c061aSmrg 835444c061aSmrgString _XtPrintActions( 836444c061aSmrg register ActionRec *actions, 837444c061aSmrg XrmQuark *quarkTbl) 838444c061aSmrg{ 839444c061aSmrg TMStringBufRec sbRec, *sb = &sbRec; 840444c061aSmrg 841444c061aSmrg sb->max = 1000; 842444c061aSmrg sb->current = sb->start = __XtMalloc((Cardinal)1000); 843444c061aSmrg PrintActions(sb, 844444c061aSmrg actions, 845444c061aSmrg quarkTbl, 846444c061aSmrg (Widget)NULL); 847444c061aSmrg return sb->start; 848444c061aSmrg} 849444c061aSmrg 850444c061aSmrgString _XtPrintState( 851444c061aSmrg TMStateTree stateTree, 852444c061aSmrg TMBranchHead branchHead) 853444c061aSmrg{ 854444c061aSmrg TMStringBufRec sbRec, *sb = &sbRec; 855444c061aSmrg 856444c061aSmrg sb->current = sb->start = __XtMalloc((Cardinal)1000); 857444c061aSmrg sb->max = 1000; 858444c061aSmrg PrintState(sb, stateTree, branchHead, 859444c061aSmrg True, (Widget)NULL, (Display *)NULL); 860444c061aSmrg return sb->start; 861444c061aSmrg} 862444c061aSmrg 863444c061aSmrg 864444c061aSmrgString _XtPrintEventSeq( 865444c061aSmrg register EventSeqPtr eventSeq, 866444c061aSmrg Display *dpy) 867444c061aSmrg{ 868444c061aSmrg TMStringBufRec sbRec, *sb = &sbRec; 869444c061aSmrg#define MAXSEQS 100 870444c061aSmrg EventSeqPtr eventSeqs[MAXSEQS]; 871444c061aSmrg TMShortCard i, j; 872444c061aSmrg Boolean cycle = False; 873444c061aSmrg 874444c061aSmrg sb->current = sb->start = __XtMalloc((Cardinal)1000); 875444c061aSmrg sb->max = 1000; 876444c061aSmrg for (i = 0; 877444c061aSmrg i < MAXSEQS && eventSeq != NULL && !cycle; 878444c061aSmrg eventSeq = eventSeq->next, i++) 879444c061aSmrg { 880444c061aSmrg eventSeqs[i] = eventSeq; 881444c061aSmrg for (j = 0; j < i && !cycle; j++) 882444c061aSmrg if (eventSeqs[j] == eventSeq) 883444c061aSmrg cycle = True; 884444c061aSmrg } 885444c061aSmrg LOCK_PROCESS; 886444c061aSmrg for (j = 0; j < i; j++) { 8870568f49bSmrg TMTypeMatch typeMatch; 8880568f49bSmrg TMModifierMatch modMatch; 8890568f49bSmrg 890444c061aSmrg typeMatch = 891444c061aSmrg TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event)); 892444c061aSmrg modMatch = 893444c061aSmrg TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event)); 894444c061aSmrg PrintEvent(sb, typeMatch, modMatch, dpy); 895444c061aSmrg if (j < i) 896444c061aSmrg *sb->current++ = ','; 897444c061aSmrg } 898444c061aSmrg UNLOCK_PROCESS; 899444c061aSmrg return sb->start; 900444c061aSmrg} 901