Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!uwm.edu!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!cbnewsh!cs From: cs@cbnewsh.att.com (cetin.seren) Newsgroups: comp.windows.x Subject: Re: How to simulate a blocked i/o in an event driven program? Summary: if you MUST do it: and also ^&*^*!! static (this is my 3rd attempt to reply) Message-ID: <1991Feb24.184857.16492@cbnewsh.att.com> Date: 24 Feb 91 18:48:57 GMT References: <1991Feb23.213455.19457@msuinfo.cl.msu.edu> Distribution: usa Organization: AT&T Bell Laboratories Lines: 213 In article <1991Feb23.213455.19457@msuinfo.cl.msu.edu>, veerabad@buster.cps.msu.edu (Vibhu Veerabadrappa) writes: > > Hi, > Here is a question on X window programming: > > I have a program in which I pop up a dialog window from which > I expect the user to input some data which I need, later in the program. > But since X window programs are event driven, the program does not "Block" > ubtil the user types in the required data, but goes on. > > . > . > . > popupwindow (); > /* > some processing > which requires > the user's data ... > */ > . > . > . > I tried to have a loop after the pop up, waiting until the data is > input. But the pop up window was never popped up !! > > Young's book has an example in which the program does not block, > and he also says that it is difficult to simulate "blocked" i/o ... but > does not say it is impossible !! So there must be a way out. > > Can anyone provide me with a hint how it can be done? > > Thank you very much. > > My e_mail address is: veerabad@buster.cps.msu.edu > > ------Vibhu. > Disclaimer: The only half-acceptable argument to doing something like what you want is that you want to port an old, dumb- terminal based application or application support library to a windowed environment. In case you are designing something from scratch, think carefully; you WILL find a BETTER paradigm to do what you want to accomplish. The concurrency involved in multi-window style programming requires that the program designer approaches the problem differently. As a hint, approach your problem with the question: -- What should happen once the user has decided to pick one of the options available in the popupwindow?? as opposed to: -- Now we have to get the users' choice... There has been a lot said and done on the style of multi-window style programming. I can send you a list of references dating back to '85 or even earlier if you want. Having said that, I admit I've had to deal with the problem; it pops up when one tries to port an old, dumb-terminal based user interface support library to a graphical widowing environment like X windows. The programs based on old support libraries count on the popupwindows to be blocking; the popupwindow() call is expected to return the choice. The solution I came up with works fairly well, although if abused, it will come to a point where some stack will overflow and a core dump will follow. Neverthless, it handles one problem fairly well: The event-processing necessary to keep the other windows operating, especially the expose events that have to be dealt with right away. A conventional blocking call would cause all the expose events to be queued, but not be processed; That is why poele NOTE: The code is for example only; you'll have fill in the blanks from the man pages. Also, it is kind of backwards, so you'll have to read all of it before it makes sense: AnyWay, here's how you do it: /* define a global var. to keep reqired action */ int MainLoopContinue = 1; /* write your own equivalent of XtMainLoop() function: */ void MyXtMainLoop(............) { while ( MainLoopContinue ) { /* wait until there's something to read at the X socket */ select ( /* put the fd for the X connection socket in the readfds field, set everything else to NULL for sysV, use poll() instead... */ ); /* since select broke, we have an event: */ XNextEvent(.....&event.....); XtDispactEvent( .....&event......); } MainLoopContinue = 1; } /* now define your own popupwindow's callback. Arrange your ** popupwindow so that this gets called when the user types ** something or select something in the popupwindow: */ void popupwindowcallback(...../* the Xt args */......) { /* ** if you want, you can do some initial processing ** of the user input here */ MainLoopContinue=0; /* next time the while in MyXtMainLoop() is ** encountered, it will return.. */ } /* ** now define your popupwindow() function that actually pops up the ** window: */ int /* or char or ZONK*, or whatever */ popupwindow(.................) { /* set up your pop-up window widget, etc. suppose you call ** your popupwin widget popeye: ** also, the popupwindowcallback() ** function defined above has to be defined as the ** event callback function in your XtCreateManagedWidget() ** call. */ . . . XtRealizeWidget(.......popeye.......); MyXtMainLoop(....); /* defined above */ return /* whatever it is you want your popupwindow call ** to actually return, after seemingly blocking ** until the user types in something */ } /* ** Your MAIN() function would look like this: ** (I guess, since that is dependent on how you really want to use ** the stuff above. Here's one scenario anyway: */ main( int argc, char** argv) /* O.K., so I'm too used to C++ !! */ { /* ** set up your initial widgets, etc... */ . . . MyXtMainLoop(....) /* defined above */ } /* ** and I assume you would actually want to use the blocking ** popupwindow() functionthrough one of the other callbacks: */ void SomeOtherCallBackThatGetsCalled(...........) { /* ** do your other stuff, computation, etc., ** and realize that you actually want to ** use the popupwindow() function */ . . . ZONK* UserResponse = popupwindw(........); . . . some more computation, etc.. . . } That's it. The idea is to call MyXtMainLoop() function recursively and use the the MainLoopContinue global variable as cotrol for breaking out of MyXtMainLoop() at each level. PitFall: If too many blocking popupwindow() calls are made within each other, you will blow away the program stack (eventually, anyway. Never happened to me yet). Good Luck!!! Cetin Seren cs%speedy@att.com