labc-1ic@e260-1c.berkeley.edu (Willy S. Liao) (05/08/91)
OK dokee, I have a problem that's driving me nuts. I'm sure I'm doing something wrong, but I don't know what it is...I'm using THINK C 4.04 with System 7.0f4 and the Think Class Library. The following function is invoked by my document initialization method (it gets an integer for the size of the game board). Whenever this function gets run with NO other windows on the screen, it works fine. However, if there is another window open in the application layer (i.e. another instance of a document is in memory), this function chokes with a syserr 28 (stack has moved into heap) error on the call to ModalDialog(). Can anyone suggest anything? Boosting the memory partition up to larger sizes doesn't help (although the crash sometimes turns into an error 25, out of memory). My function: static short GetBoardsize(void) { Str255 req, answer; DialogPtr dptr; short temp; long size; Rect rect; Handle ihandle; DialogRecord dRec; GetIndString(req, GAME_MSGS, GET_SIZE_STR); ParamText(req, "\p","\p","\p"); dptr = GetNewDialog(GENERAL_REQ_DIALOG, &dRec, NULL); GetDItem(dptr, GENERAL_ETEXT_NUM, &temp, &ihandle, &rect); do { NumToString((long) DEFAULT_BSIZE, answer); SetIText(ihandle, answer); SelIText(dptr, GENERAL_ETEXT_NUM, 0, (short) answer[0]); ShowWindow(dptr); ModalDialog(NULL, &temp); GetDItem(dptr, GENERAL_ETEXT_NUM, &temp, &ihandle, &rect); GetIText(ihandle, answer); StringToNum(answer, &size); } while (size < MIN_BOARDSIZE || size > MAX_BOARDSIZE); CloseDialog(dptr); DisposHandle(dRec.items); return (short) size; } All of the all-caps identifiers are #define's. Willy Liao labc-1ic@web.berkeley.edu
REEKES@applelink.apple.com (Jim Reekes) (05/09/91)
In article <1991May7.234354.26431@agate.berkeley.edu>, labc-1ic@e260-1c.berkeley.edu (Willy S. Liao) writes: > > OK dokee, I have a problem that's driving me nuts. I'm sure I'm doing > something wrong, but I don't know what it is...I'm using THINK C 4.04 with > System 7.0f4 and the Think Class Library. The following function is invoked > by my document initialization method (it gets an integer for the size of the > game board). Whenever this function gets run with NO other windows on the > screen, it works fine. However, if there is another window open in the > application layer (i.e. another instance of a document is in memory), this > function chokes with a syserr 28 (stack has moved into heap) error on the > call to ModalDialog(). Can anyone suggest anything? Boosting the memory > partition up to larger sizes doesn't help (although the crash sometimes > turns into an error 25, out of memory). > > My function: > > static short > GetBoardsize(void) > { > Str255 req, answer; > DialogPtr dptr; > short temp; > long size; > Rect rect; > Handle ihandle; > DialogRecord dRec; > > GetIndString(req, GAME_MSGS, GET_SIZE_STR); > ParamText(req, "\p","\p","\p"); > dptr = GetNewDialog(GENERAL_REQ_DIALOG, &dRec, NULL); > GetDItem(dptr, GENERAL_ETEXT_NUM, &temp, &ihandle, &rect); > do { > NumToString((long) DEFAULT_BSIZE, answer); > SetIText(ihandle, answer); > SelIText(dptr, GENERAL_ETEXT_NUM, 0, (short) answer[0]); > ShowWindow(dptr); > ModalDialog(NULL, &temp); > GetDItem(dptr, GENERAL_ETEXT_NUM, &temp, &ihandle, &rect); > GetIText(ihandle, answer); > StringToNum(answer, &size); > } while (size < MIN_BOARDSIZE || size > MAX_BOARDSIZE); > CloseDialog(dptr); > DisposHandle(dRec.items); > return (short) size; > } This line is bad: dptr = GetNewDialog(GENERAL_REQ_DIALOG, &dRec, NULL); You never allocated any memory for dRec. You have an uninitialized pointer, and passed it to the Dialog Manager for storage. This is going to cause random results. Either allocate some storage with NewPtr(sizeof(DialogRecord)) or pass nil. Refer to Inside Mac "The Dialog Manager" chapter pages 413-414. Also, you don't need to call ShowWindow every time through the loop. Are you resetting GENERAL_ETEXT_NUM to DEFAULT_BSIZE everytime through the loop? Finally, you should do some reality checking on the text of GENERAL_ETEXT_NUM before calling StringToNum. If some non-numeric data was entered, random results will be returned by StringToNum Jim Reekes E.O., Macintosh Toolbox Engineering
Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (05/09/91)
Willy S. Liao writes in a message to All WSL> OK dokee, I have a problem that's driving me nuts. I'm sure WSL> I'm doing something wrong, but I don't know what it is...I'm WSL> using THINK C 4.04 with System 7.0f4 and the Think Class Library The Think Class Libraries don't support dialogs directly (gDeskTop gets confused and tries to send messages to the dialog window after it is gone). The following class is based on the information supplied by Symantec Tech Support. The key procedures are: DeactivateTCLDeskAndShowDialog; and ActivateTCLDeskAfterHideDialog; which will prevent gDeskTop from getting an update while the dialog is around. One does "myDialog.IResModalDialog (aDLOGid, aFilter, aDefaultItem);" followed by "myDialog.Go" (for generics) or "Run" (for more complicated dialogs) and overrides the "DoModalDialogStuff" method to do the inner workings. Caveat: only one ModalDialog should be "GO"-ing at a time...otherwise gDeskTop might get confused. Never tried it with multiple dialogs, maybe it will work... Hope it helps, source code released for public use by Lawson D. English. ****************************************************************************** {*****************************************************************************} {** CModalDialog implements a generic Modal Dialog Class **} {** Copyright 1991 Lawson D. English (use at will but remember me as well) **} {** From Symantec Tech Support suggestions. **} {**} {*****************************************************************************} unit CModalDialog; interface uses TCL, DialogIntf; implementation {**} { * IModalDialog} { *} { *Initialize a ModalDialog object.} { *} { **} procedure CModalDialog.IModalDialog (aFilter: procPtr; aDefaultItem: Integer); begin itsDefaultItem := aDefaultItem; itsFilterProc := aFilter; { you would have to override here to create dialogs on-the-fly } end; { * IResModalDialog * } { *} { *Initialize a ModalDialog object using a resource * } { * } { ** } procedure CModalDialog.IResModalDialog (aDLOGid: Integer; aFilter: procPtr; aDefaultItem: Integer); begin itsDLOGid := aDLOGid; IModalDialog (aFilter, aDefaultItem); end; procedure CModalDialog.free; begin DisposDialog(itsDialogPtr); inherited Free; end; procedure CModalDialog.ProcureDialogPtr; var theDLOGid: Integer; begin theDLOGid := itsDLOGid; { a dialog must always be invisible when gotten } { to avoid sending updates to gDeskTop, hence "WindowPtr(0)"} itsDialogPtr := GetNewDialog(theDLOGid, nil, WindowPtr(0)); end; procedure CModalDialog.DeactivateTCLDeskAndShowDialog; var theDialogPtr: DialogPtr; begin theDialogPtr := itsDialogPtr; gDeskTop.Deactivate; { we can't have gDeskTop active when } BringToFront(theDialogPtr); { the dialog comes to the front } ShowHide(theDialogPtr, TRUE); end; procedure CModalDialog.ActivateTCLDeskAfterHideDialog; var theDialogPtr: DialogPtr; begin theDialogPtr := itsDialogPtr; ShowHide(theDialogPtr, FALSE); SendBehind(theDialogPtr, WindowPtr(0)); { Hide the dialog before gDeskTop } gDeskTop.Activate; { is activated } end; {**} { * SetDialogID} { *} { *For those times when you need to have a generic dialog with various IDs} { * and just say "Go"} { **} procedure CModalDialog.SetDialogID (aDLOGid: integer); begin itsDLOGid := aDLOGid; end; {**} { * Go * } { *} { *Generic RUN using defaults of no procPtr and itemHit of 1 for RETURN * } { * } { ** } procedure CModalDialog.Go; begin itsDefaultItem := 1; { implements the generic "RETURN" default dialog} itsFilterProc := nil; { with no filterProc } RunModalDialog; free; end; {**} { * RunModalDialog} { *} { *Run ModalDialog object... NO! REally?} { *} { **} procedure CModalDialog.RunModalDialog; var theDialogItem: Integer; theFilterProc: ProcPtr; theDLOGid: Integer; begin theFilterProc := itsFilterProc; ProcureDialogPtr; DeactivateTCLDeskAndShowDialog; repeat ModalDialog(theFilterProc, theDialogItem); DoModalDialogStuff(theDialogItem); until (theDialogItem = itsDefaultItem); ActivateTCLDeskAfterHideDialog; end; procedure CModalDialog.DoModalDialogStuff(theDialogItem:Integer); begin { needs to be overriden in your own dialog classe } end; end. end. ******************************************************************************* -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English Internet: Lawson.English@p88.f15.n300.z1.fidonet.org
wdh@well.sf.ca.us (Bill Hofmann) (05/11/91)
For the second time this week, if you create a window, you must call SetPort before you use it. Jim Reekes is wrong here, the original poster *does* pass the address of a block of memory big enough to hold a DialogRecord, and does all the right things to get rid of memory. He is right to point out the silliness of calling ShowWindow more than once (or even once, if the DLOG indicates the window should be visible). Some things to keep in mind: -ShowWindow, NewWindow, GetNewWindow, NewDialog, GetNewDialog, and every other window and dialog manager routine *does not*, repeat, *NOT* ever call SetPort to make anything the current port, at least as you should know. -You *must* call SetPort yourself, no one will do it for you. -Bill Hofmann Not a ToolBox Engineer
Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (05/13/91)
Bill Hofmann writes in a message to All BH> For the second time this week, if you create a window, you must BH> call SetPort before you use it. Jim Reekes is wrong here, the BH> original poster *does* pass the address of a block of memory BH> big enough to hold a DialogRecord, and does all the right things BH> to get rid of memory. He is right to point out the silliness BH> of calling ShowWindow more than once (or even once, if the DLOG BH> indicates the window should be visible). A not-so-well know bug in the Think Class Libraries requires one to send gDeskTop a Deactivate message before creating and showing a dialog (it must be hidden before it is shown). Otherwise, gDeskTop gets an update event message when the dialog goes away and somehow tries to send its window a deactivate message. As the dialog is NOT part of gDeskTop's window list, and no longer even exists, this causes mucho problemas. I posted a dialog manager class that gets around the problem. Did anyone actually see it, or should I repost? Lawson -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English Internet: Lawson.English@p88.f15.n300.z1.fidonet.org