home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / csmpdigest / csmp-digest-v3-055 < prev    next >
Text File  |  2010-09-21  |  82KB  |  2,076 lines

  1. Received-Date: Thu, 8 Sep 1994 18:50:22 +0200
  2. From: pottier@clipper.ens.fr (Francois Pottier)
  3. Subject: csmp-digest-v3-055
  4. To: csmp-digest@ens.fr
  5. Date: Thu, 8 Sep 1994 18:50:13 +0200 (MET DST)
  6. X-Mailer: ELM [version 2.4 PL23]
  7. Mime-Version: 1.0
  8. Content-Type: text/plain; charset=ISO-8859-1
  9. Content-Transfer-Encoding: 8bit
  10. Errors-To: listman@ens.fr
  11. Reply-To: pottier@clipper.ens.fr
  12. X-Sequence: 60
  13.  
  14. C.S.M.P. Digest             Thu, 08 Sep 94       Volume 3 : Issue 55
  15.  
  16. Today's Topics:
  17.  
  18.         Clover+. interrupt?~
  19.         Standard C Libraries: use them?
  20.         Summary of 'Safe Save' problem - IM:Files flawed!
  21.         What Happens in the Resource Fork
  22.         Why does NewGWorld do this?
  23.         Won't strange windows come in my layer?
  24.  
  25.  
  26.  
  27. The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
  28. (pottier@clipper.ens.fr).
  29.  
  30. The digest is a collection of article threads from the internet newsgroup
  31. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  32. regularly and want an archive of the discussions.  If you don't know what a
  33. newsgroup is, you probably don't have access to it.  Ask your systems
  34. administrator(s) for details.  If you don't have access to news, you may
  35. still be able to post messages to the group by using a mail server like
  36. anon.penet.fi (mail help@anon.penet.fi for more information).
  37.  
  38. Each issue of the digest contains one or more sets of articles (called
  39. threads), with each set corresponding to a 'discussion' of a particular
  40. subject.  The articles are not edited; all articles included in this digest
  41. are in their original posted form (as received by our news server at
  42. nef.ens.fr).  Article threads are not added to the digest until the last
  43. article added to the thread is at least two weeks old (this is to ensure that
  44. the thread is dead before adding it to the digest).  Article threads that
  45. consist of only one message are generally not included in the digest.
  46.  
  47. The digest is officially distributed by two means, by email and ftp.
  48.  
  49. If you want to receive the digest by mail, send email to listserv@ens.fr
  50. with no subject and one of the following commands as body:
  51.     help                        Sends you a summary of commands
  52.     subscribe csmp-digest Your Name    Adds you to the mailing list
  53.     signoff csmp-digest            Removes you from the list
  54. Once you have subscribed, you will automatically receive each new
  55. issue as it is created.
  56.  
  57. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
  58. Questions related to the ftp site should be directed to
  59. scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
  60. digest are available there.
  61.  
  62. Also, the digests are available to WAIS users.  To search back issues
  63. with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
  64. http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
  65.  
  66.  
  67. -------------------------------------------------------
  68.  
  69. >From arthur_babitz@mentorg.com (Arthur Babitz)
  70. Subject: Clover+. interrupt?
  71. Date: Tue, 23 Aug 1994 13:51:08 -0800
  72. Organization: Mentor Graphics Corp., Wilsonville, OR., USA
  73.  
  74. I've been trying unsuccessfully to implement a "clover+." interrupt for a
  75. compute intensive part of an application.  I won't bore you with a list of
  76. things I've tried which don't work, but can someone point me in the right
  77. direction?  Seems like there must be a standard, simple solution to this
  78. problem.
  79.  
  80. Thanks!
  81.  
  82. +++++++++++++++++++++++++++
  83.  
  84. >From timothys@hood.uucp (Timothy Sherburne)
  85. Date: 24 Aug 94 16:19:46 GMT
  86. Organization: University of Portland
  87.  
  88. arthur_babitz@mentorg.com (Arthur Babitz) writes:
  89.  
  90. >I've been trying unsuccessfully to implement a "clover+." interrupt for a
  91. >compute intensive part of an application.  I won't bore you with a list of
  92. >things I've tried which don't work, but can someone point me in the right
  93. >direction?  Seems like there must be a standard, simple solution to this
  94. >problem.
  95.  
  96. >Thanks!
  97.  
  98. The trick is to check for a cmd-. (the "clover" key is usually called the command key) in your event loop.  Or you could implement a GetKeys filter.
  99.  
  100. Here's a snippet using WaitNextEvent that returns a "true" if cmd-. is detected:
  101.  
  102. Boolean CheckForCmdPeriod (void)
  103. {
  104.     EventRecord    theEvent;
  105.     char        key;
  106.     Boolean        result = false;
  107.     
  108.     // Wait for an event...
  109.     
  110.     if (WaitNextEvent (keyDownMask, &theEvent, kMaxSleep, nil))
  111.     {
  112.         // Get the ASCII value of the key from the event record... 
  113.         
  114.         key = theEvent.message & charCodeMask;
  115.         
  116.         // If the key value is equal to that of the period key and
  117.         // the command modifier key is also being held down, then
  118.         // set result to true...
  119.     
  120.         if ((theEvent.modifiers & cmdKey) && key == '.')   // cmd-. 
  121.             result = true;
  122.     }
  123.     
  124.     return result;
  125. }
  126.  
  127. Here's a snippet using the "GetKeys" toolbox call:
  128.  
  129. Boolean CheckForCmdPeriod (void)
  130. {
  131.     KeyMap        keys;
  132.  
  133.     // Check to see if the user has pressed command-period keys...
  134.         
  135.     GetKeys (keys);
  136.     if(keys [1] & 0x00800000)    // command
  137.     {
  138.         GetKeys (keys);
  139.         if(keys[1] & 0x00008000)    // . (period)
  140.         {
  141.             FlushEvents (mDownMask + mUpMask, 0);
  142.             return true;
  143.         }
  144.     }
  145.     else
  146.         return false;
  147. }
  148.  
  149. The GetKeys call will catch cmd-. that is intended for anyone, so use it sparingly.  It will also not filter the cmd-.
  150.  
  151.  
  152.  
  153. Don't Panic,
  154.  
  155.  
  156. t
  157. -- 
  158.   | Timothy Sherburne                    |               Software Engineer |
  159.   | Internet:  timothys@uofport.edu      |       Prometheus Products, Inc. |
  160.   | AppleLink: D6164@applelink.apple.com |                  1-800-477-3473 |
  161. *All comments are my own and in no way represent those of Prometheus Products*
  162.  
  163. +++++++++++++++++++++++++++
  164.  
  165. >From dshayer@netcom.com (David Shayer)
  166. Date: Wed, 24 Aug 1994 18:04:50 GMT
  167. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  168.  
  169. Arthur Babitz (arthur_babitz@mentorg.com) wrote:
  170. : I've been trying unsuccessfully to implement a "clover+." interrupt for a
  171. : compute intensive part of an application.  I won't bore you with a list of
  172. : things I've tried which don't work, but can someone point me in the right
  173. : direction?  Seems like there must be a standard, simple solution to this
  174. : problem.
  175.  
  176. The simplest solution is to simply call WaitNextEvent every so often, 
  177. checking for keydown events of cmd-period.  This is polling, not 
  178. interrupt based.  But that's the correct way to do it on a Mac.
  179.  
  180. David
  181.  
  182.  
  183. +++++++++++++++++++++++++++
  184.  
  185. >From rhn@waltz.engr.sgi.com (Ron Nicholson)
  186. Date: Thu, 25 Aug 1994 02:02:12 GMT
  187. Organization: Silicon Graphics, Inc., Mountain View, CA
  188.  
  189. In article <timothys.777745186@hood>,
  190. Timothy Sherburne <timothys@hood.uucp> wrote:
  191. >arthur_babitz@mentorg.com (Arthur Babitz) writes:
  192. >
  193. >>I've been trying unsuccessfully to implement a "clover+." interrupt for a
  194. >>compute intensive part of an application.  I won't bore you with a list of
  195. >>things I've tried which don't work, but can someone point me in the right
  196. >>direction?  Seems like there must be a standard, simple solution to this
  197. >>problem.
  198. (snip)
  199. >Here's a snippet using WaitNextEvent that returns a "true" if cmd-. ...
  200. >
  201. (snip)
  202.  
  203. A program has to call WaitNextEvent to cleanly check for a keyboard
  204. abort (command-period).  I tried this in an inner loop of a compute
  205. intensive application and it slowed down the computation noticeably.
  206. I had to figure out a way to poll often enough to not make the user
  207. interface seem sluggish, while slowing calculation down minimally.
  208.  
  209. What I now do is to is this:
  210.  
  211. First I install a VBL task whose only function is to increment a global
  212. variable.  That gives me a tickcount variable that can be read without
  213. a function call.  You can also use the TickCount() access function.
  214. (Or you can just use the lowmem global Ticks at $016A if you aren't
  215. strictly following Apple's guidelines.  Would I do that? :-)
  216.  
  217. In my inner loop I have code similar to:    /* in pseudo code */
  218.  
  219. int ComputeIntensiveFunction(parameters ...)
  220. {
  221.   ...
  222.   volatile long int    *myTickCountPtr;
  223.   long int        CheckNow;
  224.   int            LocalCounter;        /* a local variable */
  225.  
  226.   myTickCountPtr = &some_tickcount_global;     /* point at tickcount */
  227.   CheckNow = *myTickCountPtr + 6;        /* every 10th of a second */
  228.   LocalCounter = 25;
  229.   ...
  230.  
  231.   for (i=1,i<1000000000;i++) {
  232.  
  233.     ...  /* compute intensive inner loop stuff that goes on forever */
  234.  
  235.     if (--LocalCounter <= 0) {
  236.       if (*myTickCountPtr >= CheckNow) {
  237.     flag = CheckForAbortEvent();    /* wrapper for WaitNextEvent */
  238.     if (flag)
  239.         return(kSomeErrorCode);    /* abort calculation    */
  240.                     /* or alternatively just break */
  241.     else
  242.       CheckNow = *myTickCountPtr + 6;
  243.       }
  244.       LocalCounter = 25;        /* or some such value    */
  245.     }
  246.   }
  247.   ...
  248.   return(kFinishedCalculating);
  249. }
  250.  
  251. Every time through the loop, the code does one local variable decrement
  252. and compare.  Every 25th time, the code does one global variable
  253. (probably uncached and thus slower) load and compare.  Every 10th of a
  254. second, the code polls the event queue for abort, application switches, etc.
  255.  
  256. The "6" and "25" are just example values.  You might want to choose the
  257. initial loop counter value based on application tuning and the processor
  258. speed of the Mac on which the application is running.
  259.  
  260. - -
  261. Ronald H. Nicholson, Jr.    rhn@engr.sgi.com, rhn@netcom.com, N6YWU
  262. #include <canonical.disclaimer>     // I speak only for myself, etc.
  263.  
  264. +++++++++++++++++++++++++++
  265.  
  266. >From radixinc@aol.com (RadixInc)
  267. Date: 25 Aug 1994 01:11:10 -0400
  268. Organization: America Online, Inc. (1-800-827-6364)
  269.  
  270. In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com (Ron
  271. Nicholson) writes:
  272.  
  273. <<
  274. A program has to call WaitNextEvent to cleanly check for a keyboard
  275. abort (command-period).  I tried this in an inner loop of a compute
  276. intensive application and it slowed down the computation noticeably.
  277. I had to figure out a way to poll often enough to not make the user
  278. interface seem sluggish, while slowing calculation down minimally.
  279. >>
  280.  
  281. A program has to call WaitNextEvent to cleanly do a lot of things. If you
  282. aren't checking events you are hogging the machine and not letting other
  283. apps have time. And what do you mean "not make the user interface seem
  284. sluggish?" What user interface do you have when you aren't checking for
  285. events?
  286.  
  287. <<
  288. First I install a VBL task whose only function is to increment a global
  289. variable.  That gives me a tickcount variable that can be read without
  290. a function call.  You can also use the TickCount() access function.
  291. (Or you can just use the lowmem global Ticks at $016A if you aren't
  292. strictly following Apple's guidelines.  Would I do that? :-)
  293. >>
  294.  
  295. This is silly. Just call TickCount(), or if you have to, just look at
  296. Ticks. You are overly worried about performance, yet you install a VBL
  297. task that does the same thing as an existing VBL task (how do you think
  298. Ticks gets updated in the first place?). You can use any DOCUMENTED
  299. low-memory globals, like Ticks, without getting in trouble. Certainly
  300. given the choice between that and installing a VBL, DTS would advise the
  301. former.
  302.  
  303. As for the code sample, why not call EventAvail periodically with an event
  304. mask that ignores events you don't care about? That way you won't end up
  305. with an event loop inside your compute-intensive loop and (presumably)
  306. another one in your main program. (DTS will certainly frown on calling
  307. WaitNextEvent from more than one place in your program). And rather than
  308. using Ticks and the local counter, use a modulo calculation on your loop
  309. variable; e.g. check for an event every 10,000 iterations or so.
  310.  
  311. Make it work first, optimize the slow parts later [after identifying the
  312. slow parts].
  313.  
  314. Gregory Jorgensen
  315. Radix Consulting Inc.
  316.  
  317. +++++++++++++++++++++++++++
  318.  
  319. >From rhn@waltz.engr.sgi.com (Ron Nicholson)
  320. Date: Thu, 25 Aug 1994 17:31:16 GMT
  321. Organization: Silicon Graphics, Inc., Mountain View, CA
  322.  
  323. In article <33h95e$ekn@search01.news.aol.com>,
  324. RadixInc <radixinc@aol.com> wrote:
  325. >
  326. >As for the code sample, why not call EventAvail periodically with an event
  327. >mask that ignores events you don't care about? That way you won't end up
  328. >with an event loop inside your compute-intensive loop and (presumably)
  329. >another one in your main program. (DTS will certainly frown on calling
  330. >WaitNextEvent from more than one place in your program). And rather than
  331. >using Ticks and the local counter, use a modulo calculation on your loop
  332. >variable; e.g. check for an event every 10,000 iterations or so.
  333. >
  334.  
  335. You're right, EventAvail is a better choice for polling.  But what's
  336. wrong with calling WNE from more than one place?  WNE has an eventmask
  337. also.  I just get the events that I want to abort my loop, allow WNE to
  338. put the program in the background, etc.
  339.  
  340. Using a modula on the loop count is very bad.  The difference in speed
  341. between a Plus and a 8100/80 is enormous, especially on FP stuff.
  342. Either you will poll much to seldom on slow machines.  Or waste a lot
  343. of time in WNE on fast machines.  That's assuming that the time through
  344. the loop is deterministic.  If it isn't, the Mac GUI could get jerky
  345. suddenly if the modulo is set wrong on any machine.
  346.  
  347. My goal was to poll WNE at the same rate on slow and fast machines so
  348. that the Mac GUI never feels jerky (menus drop promptly, etc.).  Around
  349. the neighborhood of 15 times a second feels about right.  This works
  350. for me and doesn't slow down a program that spends a lot of time doing
  351. FFT's more than 1%.
  352.  
  353. - -
  354. Ronald H. Nicholson, Jr.    rhn@engr.sgi.com, rhn@netcom.com, N6YWU
  355. #include <canonical.disclaimer>     // I speak only for myself, etc.
  356.  
  357. +++++++++++++++++++++++++++
  358.  
  359. >From radixinc@aol.com (RadixInc)
  360. Date: 25 Aug 1994 15:29:10 -0400
  361. Organization: America Online, Inc. (1-800-827-6364)
  362.  
  363. I understand that the overhead of making the WNE toolbox call and polling
  364. for events is time consuming, especially if you are trying to squeeze the
  365. most performance out of a loop. Lots of programs just put up the "watch"
  366. cursor and ignore all events while they do their computation. This is
  367. considered bad etiquette, because WNE does more than just feed events to
  368. your app. It is the only way to let other processes have time. Those other
  369. processes may just be apps sitting there waiting for user input, in which
  370. case it doesn't matter, but they may be important background processes,
  371. such as network software or background printing.
  372.  
  373. Because so many programs are rude about giving up time with WNE, some
  374. developers have gone the route of installing VBL or Time Manager tasks to
  375. make sure they get time, and this is even worse.
  376.  
  377. If your method of calling WNE every 10 ticks works, and you can live with
  378. the potential problems of having two WNE calls in your program, great. I
  379. still think you'd be better off calling EventAvail with an event mask, so
  380. if an event does show up you can exit your loop and let your "main" even
  381. loop handle the event (EventAvail doesn't dequeue the event). You can use
  382. a mask to just look for keyboard events, so mouse events and so on are
  383. ignored (but remain in the even queue).
  384.  
  385. Also keep in mind that, depending on the speed of the Mac you are running
  386. on, events don't live all that long. The event queue only holds 20 events,
  387. and if you aren't removing them with WNE the old events will be lost. That
  388. means you have to poll for events fast enough to catch them before they
  389. are lost. User-interface events will happen much less frequently than
  390. every 10 ticks, but network events may happen very fast on certain Macs.
  391.  
  392.  
  393. Gregory Jorgensen
  394. Radix Consulting Inc.
  395.  
  396. +++++++++++++++++++++++++++
  397.  
  398. >From wilkins@jarthur.cs.hmc.edu (Mark Wilkins)
  399. Date: 25 Aug 1994 21:03:07 GMT
  400. Organization: Harvey Mudd College, Claremont CA
  401.  
  402. In article <33ire6$s4i@search01.news.aol.com>,
  403. RadixInc <radixinc@aol.com> wrote:
  404. >If your method of calling WNE every 10 ticks works, and you can live with
  405. >the potential problems of having two WNE calls in your program, great. I
  406. >still think you'd be better off calling EventAvail with an event mask...
  407.  
  408.  
  409.   What possible problems could be caused by having multiple calls to
  410. WaitNextEvent in an application, especially if the purpose is to check for
  411. interruption of a time-consuming process?
  412.  
  413.   An application which doesn't try to do nifty things like threading will
  414. usually limit user input during a time-consuming processing task to that
  415. which could interrupt the task or that which needs to be passed on to the OS
  416. such as a click in another app's window.
  417.  
  418.   In other words, why should I care if I'm throwing away events which don't
  419. consist of a command period or mouse click when those are the only two forms
  420. of interaction my application will entertain when it's chugging away?  That
  421. is, assuming I'm only throwing away events directed at my application...
  422.  
  423.   I'm just not sure I see the issue.
  424.  
  425. -- Mark Wilkins
  426.  
  427. +++++++++++++++++++++++++++
  428.  
  429. >From radixinc@aol.com (RadixInc)
  430. Date: 26 Aug 1994 00:11:08 -0400
  431. Organization: America Online, Inc. (1-800-827-6364)
  432.  
  433. In article <33j0ub$eip@jaws.cs.hmc.edu>, wilkins@jarthur.cs.hmc.edu (Mark
  434. Wilkins) writes:
  435.  
  436. <<What possible problems could be caused by having multiple calls to
  437. WaitNextEvent in an application, especially if the purpose is to check for
  438. interruption of a time-consuming process? ... In other words, why should I
  439. care if I'm throwing away events which don't consist of a command period
  440. or mouse click when those are the only two forms of interaction my
  441. application will entertain when it's chugging away?  That is, assuming I'm
  442. only throwing away events directed at my application...>>
  443.  
  444. It's mostly a matter of style, and of course it is generic Mac programming
  445. advice to have only one place in your code call WNE. It sounds like you
  446. know what you are doing, and perhaps this is the best way to handle it.
  447. The complication of calling WNE from more than one place is that you have
  448. to (or at least should) handle ALL events you get. In your case you are
  449. going to ignore all events except the ones that can terminate your loop.
  450. It's most important that you call WNE periodically (and often), for the
  451. reasons mentioned in my previous post, even if you don't handle all of the
  452. events.
  453.  
  454. Besides the key and mouse events, there are other events you may get. You
  455. can't really get switched out if you ignore mouse clicks outside of your
  456. window, but another process could do something that causes an update event
  457. in one of your windows. Or a high-level event could get passed to you (if
  458. your program accepts them). If you call WNE but can't respond to these
  459. events in your computation loop, your window won't be updated and you
  460. won't be able to process Apple Events. In your case maybe this is not a
  461. big deal.
  462.  
  463. There is no "hard" reason to have only one WNE call in your program, as
  464. long as you know that you may lose events.
  465.  
  466. Gregory Jorgensen
  467. Radix Consulting Inc.
  468.  
  469. +++++++++++++++++++++++++++
  470.  
  471. >From kluev@jonathan.srcc.msu.su (Kluev)
  472. Date: Sun, 28 Aug 94 18:13:09 +0400
  473. Organization: (none)
  474.  
  475. In article <33h95e$ekn@search01.news.aol.com>
  476. radixinc@aol.com (RadixInc) wrote:
  477.  
  478. > In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com
  479. (Ron
  480. > Nicholson) writes:
  481. > <<
  482. > First I install a VBL task whose only function is to increment a
  483. global
  484. > variable.  That gives me a tickcount variable that can be read
  485. without
  486. > a function call.  You can also use the TickCount() access function.
  487. > (Or you can just use the lowmem global Ticks at $016A if you aren't
  488. > strictly following Apple's guidelines.  Would I do that? :-)
  489. > >>
  490. > This is silly. Just call TickCount(), or if you have to, just look at
  491. > Ticks. You are overly worried about performance, yet you install a
  492. VBL
  493. > task that does the same thing as an existing VBL task (how do you
  494. think
  495. > Ticks gets updated in the first place?).
  496.  
  497. First: There is no special VBL task that increments Ticks.
  498. Second: Installing VBLTask that increments global variable gives you
  499. much less accuracy than looking into Ticks (TickCount). This inaccuracy
  500. will heavily depend on machine load and may rise up to several "real"
  501. ticks against one "your" tick. Ticks is guaranteed to be incremented
  502. every tick, but your VBLTask (which contains 1 in vblCount) is not
  503. guaranteed to be called every tick.
  504.  
  505. > WaitNextEvent from more than one place in your program). And rather
  506. than
  507. > using Ticks and the local counter, use a modulo calculation on your
  508. loop
  509. > variable; e.g. check for an event every 10,000 iterations or so.
  510.  
  511. This is bad practice. If "10,000" is hard-coded you will get different
  512. response time on different machines. It may be computed at start-time.
  513. But think: machine load (VBLs for example) may vary during program
  514. execution. Processor cache may be turned on/off. All this and more
  515. will invalidate this "10,000" estimate. Ticks is better.
  516.  
  517. Michael Kluev.
  518.  
  519. +++++++++++++++++++++++++++
  520.  
  521. >From radixinc@aol.com (RadixInc)
  522. Date: 29 Aug 1994 02:13:04 -0400
  523. Organization: America Online, Inc. (1-800-827-6364)
  524.  
  525. In article <584486046668@jonathan.srcc.msu.su>, kluev@jonathan.srcc.msu.su
  526. (Kluev) writes:
  527.  
  528. <<First: There is no special VBL task that increments Ticks.>>
  529.  
  530. Not on newer Macs, no. Ticks used to get updated by a VBL task, but now it
  531. is synthesized. It doesn't matter how it gets updated; the point is that
  532. it is better to get the value of Ticks, either by function call or reading
  533. the global directly. If you use the Universal Headers you can read the
  534. Ticks global and stay compatible by using LMGetTicks(). For historical
  535. reasons it's easier to pretend that Ticks is incremented at VBL time, even
  536. though on most Macs it isn't actually done that way. I apologize if anyone
  537. was confused or misled by my statement, but it really makes no difference
  538. how Ticks gets incremented, and by design it appears that it is done at
  539. VBL time.
  540.  
  541. <<This is bad practice. If "10,000" is hard-coded you will get different
  542. response time on different machines.>>
  543.  
  544. Obviously, but you are misreading my message. I wasn't suggesting
  545. hard-coding the number 10,000, or any other number--I was suggesting a
  546. modulo calculation based on SOME modulus. The actual number used could be
  547. any value, and could be calculated in advance to account for differences
  548. among machines. 10,000 was simply an illustrative example, and that's why
  549. I wrote "e.g. check for an event every 10,000 iterations or so."  "e.g."
  550. is an abbrevation for "exempli gratia," meaning "for example," not to be
  551. confused with "i.e.," (id est), meaning "that is." This should be
  552. self-evident to anyone capable of writing a VBL task in the first place,
  553. and therefore I didn't see any reason to exhaustively explain what I was
  554. suggesting. Quod erat demonstrandum.
  555.  
  556. <<But think: machine load (VBLs for example) may vary during program
  557. execution. Processor cache may be turned on/off. All this and more
  558. will invalidate this "10,000" estimate. Ticks is better.>>
  559.  
  560. I agree, but the original post, and my response, were discussing other
  561. approaches. My suggestion, which was followed up by email, was to simply
  562. read the value of Ticks and be done with it. Done correctly the modulus
  563. method is a legitimate way to handle the problem, if for some reason the
  564. programmer doesn't want to use Ticks.
  565.  
  566. Gregory Jorgensen
  567. Radix Consulting Inc.
  568.  
  569. +++++++++++++++++++++++++++
  570.  
  571. >From besbris@jeeves.ucsd.edu (David Besbris)
  572. Date: 29 Aug 1994 10:25:39 GMT
  573. Organization: The Avant-Garde of the Now, Ltd.
  574.  
  575. Kluev (kluev@jonathan.srcc.msu.su) wrote:
  576. (snip)
  577.  
  578. : First: There is no special VBL task that increments Ticks.
  579. : Second: Installing VBLTask that increments global variable gives you
  580. : much less accuracy than looking into Ticks (TickCount). This inaccuracy
  581. : will heavily depend on machine load and may rise up to several "real"
  582. : ticks against one "your" tick. Ticks is guaranteed to be incremented
  583. : every tick, but your VBLTask (which contains 1 in vblCount) is not
  584. : guaranteed to be called every tick.
  585.  
  586. (snip)
  587.  
  588. : This is bad practice. If "10,000" is hard-coded you will get different
  589. : response time on different machines. It may be computed at start-time.
  590. : But think: machine load (VBLs for example) may vary during program
  591. : execution. Processor cache may be turned on/off. All this and more
  592. : will invalidate this "10,000" estimate. Ticks is better.
  593.  
  594. : Michael Kluev.
  595.  
  596. Ticks is INDEED incremented by a system-installed VBL task, and is NOT
  597. guaranteed to be inceremented exactly  once evey tick. (for the reasons that
  598. you mention about the inaccuracy of using a VBL task.) I'm curious, why do you
  599. say otherwise? 
  600.  
  601.  
  602. -Dave 
  603.  
  604. One of the last Mac Pascal programmers...
  605.  
  606. besbris@jeeves.ucsd.edu
  607.  
  608.  
  609. +++++++++++++++++++++++++++
  610.  
  611. >From kluev@jonathan.srcc.msu.su (Kluev)
  612. Date: Tue, 30 Aug 94 16:42:18 +0400
  613. Organization: (none)
  614.  
  615. In article <33sd33$4lh@network.ucsd.edu>
  616. besbris@jeeves.ucsd.edu (David Besbris) wrote:
  617.  
  618. > Kluev (kluev@jonathan.srcc.msu.su) wrote:
  619. > (snip)
  620. > : First: There is no special VBL task that increments Ticks.
  621. > : Second: Installing VBLTask that increments global variable gives
  622. you
  623. > : much less accuracy than looking into Ticks (TickCount). This
  624. inaccuracy
  625. > : will heavily depend on machine load and may rise up to several
  626. "real"
  627. > : ticks against one "your" tick. Ticks is guaranteed to be
  628. incremented
  629. > : every tick, but your VBLTask (which contains 1 in vblCount) is not
  630. > : guaranteed to be called every tick.
  631. > : Michael Kluev.
  632. > Ticks is INDEED incremented by a system-installed VBL task, and is
  633. NOT
  634. > guaranteed to be inceremented exactly  once evey tick. (for the
  635. reasons that
  636. > you mention about the inaccuracy of using a VBL task.) I'm curious,
  637. why do
  638. > you say otherwise? 
  639. > -Dave 
  640.  
  641. Here's the story on how VBL mechanism work, at least as I understand
  642. it. Ticks is updated by "VBL mechanism", *not* by system-installed
  643. VBL task. The first thing that is done by VBL mechanism is incrementing
  644. Ticks variable. Then it gets sure that it is not already running
  645. (by looking in VBLQueue). If it is already running, there is nothing
  646. to do, just return. If it is not running, mechanism decrements
  647. vblCounts of VBL tasks, and calls those, which have zero in vblCount.
  648. While VBL task is getting called, VBL mechanism may be entered again.
  649. (This is another story, how is it getting called: is it real video card
  650. interrupt, or is it triggered VIA interrupt. For now it is important
  651. only, that mechanism is getting called every 1/60 sec or so.) In this
  652. case the only thing it does is incrementing Ticks variable. So Ticks
  653. *is guaranteed* (if we aren't talking about situations when interrupts
  654. are disabled for a long time, e. g. diskette formatting) to be
  655. incremented every tick, but VBL task that has 1 in vblCount
  656. *is not guaranteed* to be called every tick. As far as I know all
  657. Macs since 1984 share this scheme.
  658.  
  659. If you don't believe me, disassemble a few bytes of ROM above the
  660. code that calls your VBL task (on my machine it starts at
  661. "_VRemove+16".
  662. You will see:
  663.  
  664. +0014 RTS
  665. ; Starting point of "VBL mechanics"
  666. +0016 ADDQ.L #$1, Ticks;     increments Ticks global
  667. +001A .....
  668. +0020 BSET #$06, VBLQueue;   test if it is already running
  669. +0026 BNE _VRemove+0014;     nothing can do - return.
  670.  
  671. If you still don't believe me, write a small test. Install VBL task
  672. that does the following:
  673.   ...
  674.   Task-> vblCount = 1;            // reinstalls itself
  675.   MyTicks++;                      // increments global
  676.   Delay(10, &L);                  // degrades machine performance,
  677.                                   // (emulates Mac Plus or so)
  678. // You may try to use this "for" loop instead of Delay
  679. //  for (i = 0; i < 1000000L; i++);
  680.   ...
  681.  
  682. In your main write:
  683.    ...
  684.    VInstall(...);            // installs VBL task with 1 in vblCount
  685.    MyOldTicks = MyTicks;     // saves old timers
  686.    OldTicks = TickCount();
  687.    Delay(60*10);             // waits 10 seconds
  688.    MyNewTicks = MyTicks;
  689.    NewTicks = TickCount();   // gets new timers
  690.  
  691.    NumToString(MyNewTicks - MyOldTicks, String);
  692.    DebugStr(String);
  693.    NumToString(NewTicks - OldTicks, String);
  694.    DebugStr(String);              // makes things obvious
  695.  
  696. ...You will notice a big difference.
  697.  
  698. As someone else pointed, for more exact and/or long-term measurements
  699. it is better to use other mechanisms instead of Ticks (e. g. Time
  700. Manager or GetDateTime).
  701.  
  702. Michael Kluev.
  703.  
  704. +++++++++++++++++++++++++++
  705.  
  706. >From kluev@jonathan.srcc.msu.su (Kluev)
  707. Date: Fri, 2 Sep 94 21:33:30 +0400
  708. Organization: (none)
  709.  
  710. In article <33ire6$s4i@search01.news.aol.com>
  711. radixinc@aol.com (RadixInc) wrote:
  712.  
  713. > I understand that the overhead of making the WNE toolbox call and
  714. polling
  715. > for events is time consuming, especially if you are trying to squeeze
  716. the
  717. > most performance out of a loop. Lots of programs just put up the
  718. "watch"
  719. > cursor and ignore all events while they do their computation. This is
  720. > considered bad etiquette, because WNE does more than just feed events
  721. to
  722. > your app. It is the only way to let other processes have time.
  723.  
  724. EventAvail and GetNextEvent also allow other processes to work. Their
  725. "time consuming" is approximately the same as of WaitNextEvent.
  726.  
  727. > Also keep in mind that, depending on the speed of the Mac you are
  728. running
  729. > on, events don't live all that long. The event queue only holds 20
  730. events,
  731. > and if you aren't removing them with WNE the old events will be lost.
  732. That
  733. > means you have to poll for events fast enough to catch them before
  734. they
  735. > are lost. User-interface events will happen much less frequently than
  736. > every 10 ticks, but network events may happen very fast on certain
  737. Macs.
  738.  
  739. Do you use those cool "network" events? This is not recommended
  740. practice.
  741.  
  742. Michael Kluev.
  743.  
  744. +++++++++++++++++++++++++++
  745.  
  746. >From radixinc@aol.com (RadixInc)
  747. Date: 25 Aug 1994 01:11:10 -0400
  748. Organization: America Online, Inc. (1-800-827-6364)
  749.  
  750. In article <Cv2Izo.Ao1@odin.corp.sgi.com>, rhn@waltz.engr.sgi.com (Ron
  751. Nicholson) writes:
  752.  
  753. <<
  754. A program has to call WaitNextEvent to cleanly check for a keyboard
  755. abort (command-period).  I tried this in an inner loop of a compute
  756. intensive application and it slowed down the computation noticeably.
  757. I had to figure out a way to poll often enough to not make the user
  758. interface seem sluggish, while slowing calculation down minimally.
  759. >>
  760.  
  761. A program has to call WaitNextEvent to cleanly do a lot of things. If you
  762. aren't checking events you are hogging the machine and not letting other
  763. apps have time. And what do you mean "not make the user interface seem
  764. sluggish?" What user interface do you have when you aren't checking for
  765. events?
  766.  
  767. <<
  768. First I install a VBL task whose only function is to increment a global
  769. variable.  That gives me a tickcount variable that can be read without
  770. a function call.  You can also use the TickCount() access function.
  771. (Or you can just use the lowmem global Ticks at $016A if you aren't
  772. strictly following Apple's guidelines.  Would I do that? :-)
  773. >>
  774.  
  775. This is silly. Just call TickCount(), or if you have to, just look at
  776. Ticks. You are overly worried about performance, yet you install a VBL
  777. task that does the same thing as an existing VBL task (how do you think
  778. Ticks gets updated in the first place?). You can use any DOCUMENTED
  779. low-memory globals, like Ticks, without getting in trouble. Certainly
  780. given the choice between that and installing a VBL, DTS would advise the
  781. former.
  782.  
  783. As for the code sample, why not call EventAvail periodically with an event
  784. mask that ignores events you don't care about? That way you won't end up
  785. with an event loop inside your compute-intensive loop and (presumably)
  786. another one in your main program. (DTS will certainly frown on calling
  787. WaitNextEvent from more than one place in your program). And rather than
  788. using Ticks and the local counter, use a modulo calculation on your loop
  789. variable; e.g. check for an event every 10,000 iterations or so.
  790.  
  791. Make it work first, optimize the slow parts later [after identifying the
  792. slow parts].
  793.  
  794. Gregory Jorgensen
  795. Radix Consulting Inc.
  796.  
  797. ---------------------------
  798.  
  799. >From dlopez@sailsun (Dean Lopez)
  800. Subject: Standard C Libraries: use them?
  801. Date: 12 Aug 1994 18:46:29 GMT
  802. Organization: NASA Johnson Space Center, Houston, TX, USA
  803.  
  804. I am wondering about the 'legitimacy' of using the Standard C Libraries
  805. in my Mac applications.  As a C programmer on other systems, I've become
  806. quite fond of the Standard C libraries - stdio.h in particular.  The
  807. problem with using them on the Mac, as I'm sure you all know, is the way
  808. files are reference via FILE* 'ers compared with the File Manager's 
  809. file reference numbers.  If I use the File Manager, I don't see how I
  810. can use the stdio.h functions which require a FILE*.  And if I use the
  811. stdio.h functions, I can't use some of the File Manager's goodies.
  812.  
  813. Has anybody figured out how to convert the FILE structure info into the
  814. FSSpec structure? (I mean written the routines already, I really don't
  815. have the time right now to attempt it myself).
  816. I'd just like to be able to interchange how I reference a file right
  817. now, in the same way on say, a Data General system using AOS will let
  818. me reference a file either with the stdio or Unix calls.
  819.  
  820. Is there a reason NOT to try to use either/or?
  821.  
  822. Any and all advice welcome. NOTE: if you e-mail me, see my email addresses
  823. below, don't use what's in my reply-to field.  Its messed up somehow.
  824. --
  825. +---------------------------------------+-----------------------------+
  826. | Dean Lopez                            |                             |
  827. | SAIL DPS Engineer                     | dlopez@sailsun.jsc.nasa.gov |
  828. | Rockwell Space Operations Co.         | deanlopez@aol.com           |
  829. | JSC Shuttle Avionics Integration Lab  | dean_lopez@maclair.cld9.com |
  830. +---------------------------------------+-----------------------------+
  831. #include <standard_disclaimer.h>
  832. /* The opinions expressed are all mine.
  833.    RSOC doesn't speak for me and I don't speak for RSOC
  834.    After all, I'm only an engineer - what do I know?     */
  835.  
  836. +++++++++++++++++++++++++++
  837.  
  838. >From rollin@newton.apple.com (Keith Rollin)
  839. Date: Thu, 18 Aug 1994 04:26:36 -0800
  840. Organization: Apple ][ -> Mac -> Taligent -> Newton -> Windows?
  841.  
  842. In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
  843. Lopez) wrote:
  844.  
  845. >I am wondering about the 'legitimacy' of using the Standard C Libraries
  846. >in my Mac applications.  As a C programmer on other systems, I've become
  847. >quite fond of the Standard C libraries - stdio.h in particular.  The
  848. >problem with using them on the Mac, as I'm sure you all know, is the way
  849. >files are reference via FILE* 'ers compared with the File Manager's 
  850. >file reference numbers.  If I use the File Manager, I don't see how I
  851. >can use the stdio.h functions which require a FILE*.  And if I use the
  852. >stdio.h functions, I can't use some of the File Manager's goodies.
  853. >
  854. >Has anybody figured out how to convert the FILE structure info into the
  855. >FSSpec structure? (I mean written the routines already, I really don't
  856. >have the time right now to attempt it myself).
  857. >I'd just like to be able to interchange how I reference a file right
  858. >now, in the same way on say, a Data General system using AOS will let
  859. >me reference a file either with the stdio or Unix calls.
  860. >
  861. >Is there a reason NOT to try to use either/or?
  862.  
  863. Check the Mac Technotes:
  864.  
  865. "Frequently, developers want to use both Macintosh file I/O and C file
  866. I/O.  Developers who do this must keep in mind that they are combining two
  867. distinct file representations (the Macintosh and ANSI C).  The only
  868. limitation on mixing HFS and C I/O functions is that they cannot be mixed
  869. on the same open file.  There are three reasons why this cannot be done.
  870.  
  871. "First, there is no routine that maps between a C FILE struct (returned by
  872. fopen()) to an HFS fRefNum (needed to call HFS functions).  Similarly,
  873. there is no call to create a FILE struct given an fRefNum returned by
  874. FSOpen().  Thus, there is no way that the information from an fopen() call
  875. could be used to do a FSRead().
  876.  
  877. "Second, even if the first problem were solved, the C libraries eventually
  878. call the HFS file system, but keep some internal state information.  So,
  879. if you call HFS directly (say, SetFPos()), the C file system has no way of
  880. knowing a call was made and, therefore, doesnπt update its state
  881. information. 
  882.  
  883. "Similarly, there is no mechanism for synchronizing the C libraryπs
  884. buffers.  For example, you perform an fwrite() with some number of
  885. characters which get put into a buffer without flushing it.  Then you
  886. perform an FSWrite() with something else.  Neither the C library nor HFS
  887. are aware that the other has written to the file.
  888.  
  889. "Simply put, you cannot make HFS calls on a file opened with fopen() or
  890. fdopen(); you cannot use C library I/O on a file opened under HFS."
  891.  
  892. - --------------------------------------------------------------------------
  893. Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton
  894.  
  895. +++++++++++++++++++++++++++
  896.  
  897. >From cjsmith@nwu.edu (Jeremy Smith)
  898. Date: 18 Aug 1994 15:37:49 GMT
  899. Organization: Northwestern University, Evanston, IL  USA
  900.  
  901.    I'm not sure, what exactly you're trying to do, but if you have a copy
  902. of Think Reference, go to misc. topics/Code Example Orphans/Printing a
  903. Text File and look at the GotATextFile procedure.  This uses a medly of
  904. toolbox and ANSI file routines.  Good luck,
  905.  
  906.    Jeremy Smith   
  907.    cjsmith@nwu.edu
  908.  
  909. +++++++++++++++++++++++++++
  910.  
  911. >From phils@bedford.symantec.com (Phil Shapiro)
  912. Date: Mon, 22 Aug 1994 14:37:27 -0400
  913. Organization: Symantec Corp.
  914.  
  915. In article <rollin-1808940426360001@mac691.kip.apple.com>,
  916. rollin@newton.apple.com (Keith Rollin) wrote:
  917.  
  918. | In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
  919. | Lopez) wrote:
  920. | >I am wondering about the 'legitimacy' of using the Standard C Libraries
  921. | >in my Mac applications.  As a C programmer on other systems, I've become
  922. | >quite fond of the Standard C libraries - stdio.h in particular.  The
  923. | >problem with using them on the Mac, as I'm sure you all know, is the way
  924. | >files are reference via FILE* 'ers compared with the File Manager's 
  925. | >file reference numbers.  If I use the File Manager, I don't see how I
  926. | >can use the stdio.h functions which require a FILE*.  And if I use the
  927. | >stdio.h functions, I can't use some of the File Manager's goodies.
  928. | >
  929. | >Is there a reason NOT to try to use either/or?
  930. | Check the Mac Technotes:
  931. | "First, there is no routine that maps between a C FILE struct (returned by
  932. | fopen()) to an HFS fRefNum (needed to call HFS functions).  Similarly,
  933. | there is no call to create a FILE struct given an fRefNum returned by
  934. | FSOpen().  Thus, there is no way that the information from an fopen() call
  935. | could be used to do a FSRead().
  936.  
  937. The Mac Technotes have always assumed that everyone is using the MPW
  938. development system. If you're using THINK, you *can* get the refnum for an
  939. open FILE. It's stored in the field called "refnum". You could also write
  940. a stdio routine that builds a FILE* from an open file, since the THINK
  941. libraries ship with full source. But that's a fair amount of work just
  942. because you happen to like ANSI I/O. You will only be able to use the code
  943. in THINK, too.
  944.  
  945. Unless you're porting a lot of code that already uses ANSI I/O, you're
  946. much better off going with straight Mac I/O.
  947.  
  948.    -phil
  949.  
  950. +++++++++++++++++++++++++++
  951.  
  952. >From nagle@netcom.com (John Nagle)
  953. Date: Tue, 23 Aug 1994 02:02:25 GMT
  954. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  955.  
  956. phils@bedford.symantec.com (Phil Shapiro) writes:
  957. >In article <rollin-1808940426360001@mac691.kip.apple.com>,
  958. >rollin@newton.apple.com (Keith Rollin) wrote:
  959. >| In article <32gg25$of9@pendragon.jsc.nasa.gov>, dlopez@sailsun (Dean
  960. >| Lopez) wrote:
  961. >| >I am wondering about the 'legitimacy' of using the Standard C Libraries
  962. >| >in my Mac applications.  As a C programmer on other systems, I've become
  963. >| >quite fond of the Standard C libraries - stdio.h in particular.  
  964.  
  965. >The Mac Technotes have always assumed that everyone is using the MPW
  966. >development system. If you're using THINK, you *can* get the refnum for an
  967. >open FILE.
  968.  
  969. >Unless you're porting a lot of code that already uses ANSI I/O, you're
  970. >much better off going with straight Mac I/O.
  971.  
  972.         Of course, then you have to try to read a text file with the
  973. Toolbox calls, a difficult, slow, and badly documented operation.
  974. Anybody have the obscure tech note reference on doing that?
  975.  
  976.                     John Nagle
  977.  
  978. +++++++++++++++++++++++++++
  979.  
  980. >From zstern@adobe.com (Zalman Stern)
  981. Date: Tue, 23 Aug 1994 05:51:49 GMT
  982. Organization: Adobe Systems Incorporated
  983.  
  984. That the Mac API prevents the use of stdio in many cases is just a bug. Any  
  985. reasonable UNIX system provides functions to map a FILE * to a file  
  986. descriptor (the moral equivalent of a Mac file reference number) and to open  
  987. a FILE * from a file descriptor. (They're called fileno and fdopen  
  988. respectively.) The conventions for switching between system call level I/O  
  989. and stdio are a bit arcane but workable for most uses of this functionality.  
  990. (The fdopen call is necessary because UNIX has a unified model of stream I/O  
  991. which a large number of things obey. There are many ways to get a file  
  992. descriptor, but once you have one it behaves according to this model and  
  993. turning it into a stdio stream is very useful.)
  994.  
  995. I've seen a number of posts recently that express the attitude that there is  
  996. no point in using portable API's for Macintosh programming because Mac  
  997. applications are inherently non-portable. (Or perhaps these posters feel a  
  998. program isn't a good Macintosh application unless its non-portable.) People  
  999. who feel this way are quickly becoming economic roadkill, and deservedly so.  
  1000. One writes non-portable code because less than ideal circumstances forces  
  1001. one to, not because it is desirable.
  1002. --
  1003. Zalman Stern           zalman@adobe.com            (415) 962 3824
  1004. Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
  1005.  Please do not change color while I am talking to you -- MC 900 Ft Jesus.
  1006.  
  1007. +++++++++++++++++++++++++++
  1008.  
  1009. >From tree@bedford.symantec.com (Tom Emerson)
  1010. Date: Tue, 23 Aug 1994 06:33:54 -0500
  1011. Organization: Symantec Development Tools Group
  1012.  
  1013. > >Unless you're porting a lot of code that already uses ANSI I/O, you're
  1014. > >much better off going with straight Mac I/O.
  1015. >         Of course, then you have to try to read a text file with the
  1016. > Toolbox calls, a difficult, slow, and badly documented operation.
  1017. > Anybody have the obscure tech note reference on doing that?
  1018.  
  1019. IM: Files, p. 2-90 & 2-122.
  1020.  
  1021.    -tre
  1022.  
  1023. -- 
  1024. Tom Emerson                                              Software Engineer
  1025. Development Tools Group                               Symantec Corporation
  1026.                           tree@bedford.symantec.com
  1027.   "I dreamed I had to take a test, in a Dairy Queen, on another planet."
  1028.  
  1029. +++++++++++++++++++++++++++
  1030.  
  1031. >From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
  1032. Date: Thu, 25 Aug 1994 11:40:13 +0800
  1033. Organization: Department of Computer Science, The University of Western Australia
  1034.  
  1035. In article <1994Aug23.055149.5764@adobe.com>, zstern@adobe.com (Zalman
  1036. Stern) wrote:
  1037.  
  1038. >That the Mac API prevents the use of stdio in many cases is just a bug.
  1039.  
  1040. I disagree with this.  Any API that promotes the use of full paths to
  1041. denote files is fundamentally broken for use on a Mac, mainly because
  1042. multiple volumes can have the same name.  Of course you can work around
  1043. this problem but there comes a point where you've got to decide whether
  1044. your workaround is worth the effort.
  1045. -- 
  1046. Quinn "The Eskimo!"        "Scout in a can. Simple, cheap, easy
  1047.                             to use and it's expendable!"
  1048.  
  1049. +++++++++++++++++++++++++++
  1050.  
  1051. >From zstern@adobe.com (Zalman Stern)
  1052. Date: Thu, 25 Aug 1994 07:10:14 GMT
  1053. Organization: Adobe Systems Incorporated
  1054.  
  1055. Quinn "The Eskimo!" writes
  1056. > In article <1994Aug23.055149.5764@adobe.com>, zstern@adobe.com (Zalman
  1057. > Stern) wrote:
  1058. > >That the Mac API prevents the use of stdio in many cases is just a bug.
  1059. > I disagree with this.  Any API that promotes the use of full paths to
  1060. > denote files is fundamentally broken for use on a Mac, mainly because
  1061. > multiple volumes can have the same name.  Of course you can work around
  1062. > this problem but there comes a point where you've got to decide whether
  1063. > your workaround is worth the effort.
  1064.  
  1065. Fine write a function like so:
  1066.  
  1067.     FILE * FSfopen(FSSpec *fileSpec, char *mode);
  1068.  
  1069. or perhaps a function that pops up a standard file dialog and opens a file  
  1070. that way. Then you can write the file processing routines in a portable  
  1071. fashion. The other alternative is to write your own stream library and  
  1072. ensure that it is portable, but that is fraught with problems. (E.g. the  
  1073. MacApp stream implementation which does no buffering.) I prefer not to  
  1074. re-invent the wheel unless I have to.
  1075.  
  1076. My original point is that with a little work in the stdio implementation one  
  1077. can go back and forth easily. My use of "The Mac API" is wrong. I meant the  
  1078. standard C library implementation combined with the toolbox requirements.  
  1079. Obviously the C library implementation is a better choice to change.
  1080. --
  1081. Zalman Stern           zalman@adobe.com            (415) 962 3824
  1082. Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
  1083.  Please do not change color while I am talking to you -- MC 900 Ft Jesus.
  1084.  
  1085. ---------------------------
  1086.  
  1087. >From redial <redial@netcom.com>
  1088. Subject: Summary of 'Safe Save' problem - IM:Files flawed!
  1089. Date: Thu, 25 Aug 1994 04:29:12 GMT
  1090. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  1091.  
  1092. Netters -
  1093.  
  1094. Awhile ago I posted a request for help with a problem I was having
  1095. implementing the 'Safe Save' routine outlined in Inside Macintosh:Files, pp.
  1096. 1-25,26.  A 'safe save' is a save routine which creates a temporary file on
  1097. disk, saves the data to it, and - if no error occurs - swaps the the
  1098. directory information for the two files, and then deletes the temporary file.
  1099.  The advantage over a 'direct save' to the existing file is that if an error
  1100. were to occur, the existing file could be damaged and its data erased or
  1101. corrupted.  The IM example code is in Pascal (naturally), but since I am
  1102. working in C I attempted to translate it to that language.  The problem I ran
  1103. into was that after the directory swap between the files, I would get a 'file
  1104. busy' error when I attempted to delete the temporary file.  This was quite
  1105. puzzling since the code clearly executes a command to close the temporary
  1106. file immediately before the delete command.
  1107.  
  1108. Scott Bronson pointed out that the swap command, FSpExchangeFiles, swaps
  1109. the FCBs too, and recommended closing both files before swapping.  However, a
  1110. comment line in the original pascal example directed that the data fork of
  1111. the existing file be opened and left open!  I wondered why, but Scott thought
  1112. this was just another example of how inaccurate the code examples in IM can
  1113. be.  The bugginess of the 'Safe Save' routine certainly attests to this fact!
  1114.  
  1115. Further snooping led to several bits of info about the two files which
  1116. enabled Troy Gaul to correctly diagnose that the IM example code called for a
  1117. resource to be written to the original file BEFORE the swap.  Thus, it
  1118. contained the resource and the old data, while the temporary file contained
  1119. only the new data.  AFTER the swap, the original file then contained only the
  1120. new data while the temporary file contained the resource and the old data. 
  1121. Troy also pointed out that since FSpExchangeFiles also swaps the FCBs if
  1122. either or both files are open, the FSClose routine needs to use the path
  1123. reference number of the _original_ file in order to actually close the
  1124. temporary file!  This means that future references to the original file will
  1125. require the use of the temporary file's path refnum, so it must be saved.
  1126.  
  1127. Yet another error was discovered by Jens-Uwe Mager.  The IM:Files example
  1128. used the FSClose routine to close the resource fork of the original file, but
  1129. this did not cause the resource data to actually be flushed to the disk.  He
  1130. correctly suggested the use of CloseResFile, which (contrary to my initial
  1131. response to him) does work exactly like it should.
  1132.  
  1133. The first part of the fix is to move the resource creating code from the
  1134. DoSaveAsCmd routine to the DoWriteFile routine.  However, you must continue
  1135. to allow the DoSaveAsCmd routine to open the original file's data fork and
  1136. leave it open.  This is important because of the interplay between the 'Save'
  1137. and the 'Save As...' file menu commands.  The first time the user saves his
  1138. file, the DoSaveAsCmd routine is going to be executed regardless of which
  1139. command was chosen.  Thereafter, each time the user selects the 'Save'
  1140. command, the DoSaveAsCmd routine is bypassed and flow goes directly to
  1141. DoWriteData.  You could allow DoWriteData to open the original file's data
  1142. fork, but then you'd also have to close it again before leaving the routine. 
  1143. Putting just one call to open the data fork in the DoSaveAsCmd is more
  1144. efficient.
  1145.  
  1146. The second part of the fix is to make the DoWriteFile routine create the
  1147. temporary file, copy the resource to its resource fork, and close the
  1148. resource fork with CloseResFile.  Then the routine should open the temp
  1149. file's data fork, write the current data to it, and leave it open also.  Do
  1150. the swap using FSpExchangeFiles. NOW the path reference numbers of the two
  1151. files, which locate their data in memory, are reversed, but their FSSpecs are
  1152. not.  Close the temp file by calling FSClose with the _original_ file's path
  1153. reference number.  Save the _temporary_ file's path reference number for
  1154. future use with the file, and then delete the temp file by calling FSpDelete
  1155. with the temporary file's FSSpec.
  1156.  
  1157. Sorry to be so long winded.  If anyone wishes to see the final code, drop me
  1158. an email.  And sincere thanks to all who helped.
  1159.  
  1160.  ===============================================================
  1161. |  Ron Goebel                  |                                |
  1162. |  G & V Systems               | Whatdya mean 'I don't get it?' |
  1163. |  Internet: redial@netcom.com |                                |
  1164.  ===============================================================
  1165.  
  1166. ---------------------------
  1167.  
  1168. >From redcon@xmission.com (Dan Eldridge)
  1169. Subject: What Happens in the Resource Fork
  1170. Date: 18 Aug 1994 14:23:26 GMT
  1171. Organization: Redcon
  1172.  
  1173. Hi
  1174.  
  1175. Here's A general question, that I'm sure someone can answer,
  1176. What happens in the Resource Fork if a program significantly and often
  1177. changes the size of one of the resources, does the fork get fragmented, or
  1178. does the whole file get rewritten so that the forks are all contiguous?
  1179.  
  1180.  
  1181.  
  1182. Just Wondering
  1183.  
  1184. -- 
  1185.   Dan
  1186. Redcon
  1187.  
  1188. ***
  1189. insert favorite corn dog joke here
  1190. ***
  1191.  
  1192. +++++++++++++++++++++++++++
  1193.  
  1194. >From mclow@san_marcos.csusm.edu (Marshall Clow)
  1195. Date: Thu, 18 Aug 1994 09:26:20 -0800
  1196. Organization: Aladdin Systems
  1197.  
  1198. In article <redcon-1808940824560001@slc17.xmission.com>,
  1199. redcon@xmission.com (Dan Eldridge) wrote:
  1200.  
  1201. > Hi
  1202. > Here's A general question, that I'm sure someone can answer,
  1203. > What happens in the Resource Fork if a program significantly and often
  1204. > changes the size of one of the resources, does the fork get fragmented, or
  1205. > does the whole file get rewritten so that the forks are all contiguous?
  1206.    My experience has been that if you make resources smaller (or possibly
  1207. delete them), the extra space in the file is left unused, but if you add a
  1208. resource or make one larger, then it is added at the end and the file is
  1209. compacted in UpdateResFile. (which is called from CloseResFile)
  1210.  
  1211. -- Marshall
  1212.  
  1213. -- 
  1214. Marshall Clow
  1215. Aladdin Systems
  1216. mclow@san_marcos.csusm.edu
  1217.  
  1218. +++++++++++++++++++++++++++
  1219.  
  1220. >From Jens Alfke <jens_alfke@powertalk.apple.com>
  1221. Date: Wed, 24 Aug 1994 17:53:54 GMT
  1222. Organization: Apple Computer
  1223.  
  1224. Dan Eldridge, redcon@xmission.com writes:
  1225. > What happens in the Resource Fork if a program significantly and often
  1226. > changes the size of one of the resources, does the fork get fragmented, or
  1227. > does the whole file get rewritten so that the forks are all contiguous?
  1228.  
  1229. When you call UpdateResFile or CloseResFile, all the data gets shuffled
  1230. around on disk until it's contiguous. Needless to say this can be very slow.
  1231. Remember those long delays you sometimes get when you close the Monitors
  1232. control panel or use some utility to update the desktop pattern? That's the
  1233. cause; the System file is rather large, esp. pre-7.1 systems that had all the
  1234. fonts in the System file itself. And the best part is, if you decide your
  1235. system's hung and reboot, you've just destroyed your system file! That's the
  1236. major reason we made Wallpaper not store its desktop pattern in the System
  1237. file.
  1238.  
  1239. All the more reason why (let's all chant it together) "The Resource Manager
  1240. is not a database!"
  1241.  
  1242. --Jens Alfke                           jens_alfke@powertalk.apple.com
  1243.                    "A man, a plan, a yam, a can of Spam ... Bananama!"
  1244.  
  1245. +++++++++++++++++++++++++++
  1246.  
  1247. >From kluev@jonathan.srcc.msu.su (Kluev)
  1248. Date: Thu, 25 Aug 94 20:58:39 +0400
  1249. Organization: (none)
  1250.  
  1251. In article <1994Aug24.175354.27836@gallant.apple.com>
  1252. Jens Alfke <jens_alfke@powertalk.apple.com> wrote:
  1253.  
  1254. > Dan Eldridge, redcon@xmission.com writes:
  1255. > > What happens in the Resource Fork if a program significantly and
  1256. often
  1257. > > changes the size of one of the resources, does the fork get
  1258. fragmented, or
  1259. > > does the whole file get rewritten so that the forks are all
  1260. contiguous?
  1261. > When you call UpdateResFile or CloseResFile, all the data gets
  1262. shuffled
  1263. > around on disk until it's contiguous. Needless to say this can be
  1264. very slow.
  1265.  
  1266. This data compacting occurred in "logical" space of fork instead of
  1267. "physical". Compacting removes empty space in fork (not on disk)
  1268. created when a resource was removed, made smaller, or larger.
  1269. "Physically", file can be shuffled around all the disk.
  1270. So the answer is: Yes, the fork get fragmented.
  1271.  
  1272. Michael Kluev.
  1273.  
  1274. ---------------------------
  1275.  
  1276. >From schwarz@kodak.com (Doug Schwarz)
  1277. Subject: Why does NewGWorld do this?
  1278. Date: Tue, 23 Aug 1994 20:07:42 GMT
  1279. Organization: Eastman Kodak Company, Rochester, NY
  1280.  
  1281. I am trying to create multiple offscreen graphics worlds.
  1282.  
  1283.     QDErr           err1, err2;
  1284.     PixMapHandle    pixBase1, pixBase2;
  1285.     GWorldPtr       theGWorld1, theGWorld2;
  1286.     CGrafPtr        currentPort;
  1287.     GDHandle        currentDevice;
  1288.     Rect            boundsRect;
  1289.  
  1290.     GetGWorld(¤tPort, ¤tDevice);
  1291.     err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
  1292.     pixBase1 = GetGWorldPixMap(theGWorld1);
  1293.     SetGWorld(currentPort, currentDevice);
  1294.  
  1295.     GetGWorld(¤tPort, ¤tDevice);
  1296.     err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
  1297.     pixBase2 = GetGWorldPixMap(theGWorld2);
  1298.     SetGWorld(currentPort, currentDevice);
  1299.  
  1300.  
  1301. In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
  1302. looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
  1303. and err2 are zero.  What is going on/what am I doing wrong?  There is no
  1304. mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
  1305. mean that there wasn't enough memory to allocate the pixel maps, but the pixel
  1306. maps aren't very large and I have the memory partition for the app set plenty
  1307. large.  Thanks for any help you can give me.
  1308.  
  1309. Doug Schwarz
  1310. Eastman Kodak Company
  1311. schwarz@kodak.com
  1312.  
  1313. +++++++++++++++++++++++++++
  1314.  
  1315. >From python@world.std.com (Steven J. Bushell)
  1316. Date: Wed, 24 Aug 1994 11:48:59 -0500
  1317. Organization: Kodak Electronic Printing Systems, Inc.
  1318.  
  1319. In article <schwarz-2308941607420001@150.220.61.78>, schwarz@kodak.com
  1320. (Doug Schwarz) wrote:
  1321. [ code deleted ]
  1322. > In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
  1323. > looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
  1324. > and err2 are zero.  What is going on/what am I doing wrong?  There is no
  1325. > mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
  1326. > mean that there wasn't enough memory to allocate the pixel maps, but the pixel
  1327. > maps aren't very large and I have the memory partition for the app set plenty
  1328. > large.  Thanks for any help you can give me.
  1329. > Doug Schwarz
  1330. > Eastman Kodak Company
  1331. > schwarz@kodak.com
  1332.  
  1333. It's an undocumented feature of NewGWorld that it returns no error when it
  1334. has insufficient memory to allocate the GWorld.  You should ALWAYS check
  1335. the GWorldPtr to determine if the call was successful.  The only time you
  1336. get errors back from NewGWorld is when you pass ridiculous parameters to
  1337. it.  I've never seen any other errors come back from it.
  1338.  
  1339. Considering this, plus the fact that the first call to NewGWorld was
  1340. successful, you can pretty safely assume that you are short on memory. 
  1341. Double-check your boundsRect, and make sure your heap isn't fragmented
  1342. too.  A quick way to confirm that it is a memory problem would be to cut
  1343. the boundsRect in half and see if both calls succeed.  If they don't,
  1344. check to make sure your heap's okay.
  1345.  
  1346. - Steve
  1347.  
  1348. //////////
  1349. //
  1350. //   Steve Bushell
  1351. //   python@world.std.com
  1352. //
  1353. //   "It's always the quiet ones."
  1354. //
  1355. //////////
  1356.  
  1357. +++++++++++++++++++++++++++
  1358.  
  1359. >From dab@zork.tiac.net (Dana Basken)
  1360. Date: 24 Aug 1994 16:41:23 GMT
  1361. Organization: Rockland Software
  1362.  
  1363. In article <python-2408941148590001@155.50.26.175>
  1364. python@world.std.com (Steven J. Bushell) writes:
  1365.  
  1366. > It's an undocumented feature of NewGWorld that it returns no error when it
  1367. > has insufficient memory to allocate the GWorld.  You should ALWAYS check
  1368. > the GWorldPtr to determine if the call was successful.  The only time you
  1369. > get errors back from NewGWorld is when you pass ridiculous parameters to
  1370. > it.  I've never seen any other errors come back from it.
  1371.  
  1372. It's odd that you have never seen any other errors return from
  1373. NewGWorld.  If and when I try to create a GWorld using NewGWorld that
  1374. is too large to fit into memory, I get a result code of -108
  1375. (memFullErr) every time.  In my experience, I've never seen NewGWorld
  1376. not create a GWorld and pass back noErr.
  1377.  
  1378. I would look for some other reason in the failure of the allocation of
  1379. your GWorld.
  1380.  
  1381. - Dana
  1382.  
  1383. - -
  1384. Dana Basken              dab@mote.tiac.net
  1385. Rockland Software
  1386.  
  1387. +++++++++++++++++++++++++++
  1388.  
  1389. >From tg3@u.washington.edu (Thurman Gillespy III)
  1390. Date: Wed, 24 Aug 1994 11:55:51 -0800
  1391. Organization: Dept of Radiology, Univ of Washington
  1392.  
  1393. In article <schwarz-2308941607420001@150.220.61.78>, schwarz@kodak.com
  1394. (Doug Schwarz) wrote:
  1395.  
  1396. > I am trying to create multiple offscreen graphics worlds.
  1397. >     QDErr           err1, err2;
  1398. >     PixMapHandle    pixBase1, pixBase2;
  1399. >     GWorldPtr       theGWorld1, theGWorld2;
  1400. >     CGrafPtr        currentPort;
  1401. >     GDHandle        currentDevice;
  1402. >     Rect            boundsRect;
  1403. >     GetGWorld(¤tPort, ¤tDevice);
  1404. >     err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
  1405. >     pixBase1 = GetGWorldPixMap(theGWorld1);
  1406. >     SetGWorld(currentPort, currentDevice);
  1407. >     GetGWorld(¤tPort, ¤tDevice);
  1408. >     err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
  1409. >     pixBase2 = GetGWorldPixMap(theGWorld2);
  1410. >     SetGWorld(currentPort, currentDevice);
  1411. >
  1412. Err, you HAVE defined boundsRect further, havn't you?
  1413. -- 
  1414. Thurman Gillespy III             |  tg3@u.washington.edu
  1415. Department of Radiology, SB-05   |  voice (206)543-3320
  1416. University of Washington         |  fax   (206)543-6317
  1417. Seattle, WA 98195                |
  1418.  
  1419. +++++++++++++++++++++++++++
  1420.  
  1421. >From snozer@cats.ucsc.edu (Daniel Craig Jalkut)
  1422. Date: 24 Aug 1994 21:21:31 GMT
  1423. Organization: University of California, Santa Cruz
  1424.  
  1425.  
  1426. In <schwarz-2308941607420001@150.220.61.78> schwarz@kodak.com (Doug Schwarz) writes:
  1427.  
  1428. >I am trying to create multiple offscreen graphics worlds.
  1429.  
  1430. >    QDErr           err1, err2;
  1431. >    PixMapHandle    pixBase1, pixBase2;
  1432. >    GWorldPtr       theGWorld1, theGWorld2;
  1433. >    CGrafPtr        currentPort;
  1434. >    GDHandle        currentDevice;
  1435. >    Rect            boundsRect;
  1436.  
  1437. >    GetGWorld(¤tPort, ¤tDevice);
  1438. >    err1 = NewGWorld(&theGWorld1, 32, &boundsRect, NULL, NULL, 0);
  1439. >    pixBase1 = GetGWorldPixMap(theGWorld1);
  1440. >    SetGWorld(currentPort, currentDevice);
  1441.  
  1442. >    GetGWorld(¤tPort, ¤tDevice);
  1443. >    err2 = NewGWorld(&theGWorld2, 32, &boundsRect, NULL, NULL, 0);
  1444. >    pixBase2 = GetGWorldPixMap(theGWorld2);
  1445. >    SetGWorld(currentPort, currentDevice);
  1446.  
  1447.  
  1448. >In the code fragment above, theGWorld1 gets allocated just fine (and pixBase1
  1449. >looks ok), but theGWorld2 is NULL (and pixBase2 is not valid).  Both err1
  1450. >and err2 are zero.  What is going on/what am I doing wrong?  There is no
  1451. >mention in IM VI what a zero GWorldPtr means.  I had assumed that it would
  1452. >mean that there wasn't enough memory to allocate the pixel maps, but the pixel
  1453. >maps aren't very large and I have the memory partition for the app set plenty
  1454. >large.  Thanks for any help you can give me.
  1455.  
  1456. >Doug Schwarz
  1457. >Eastman Kodak Company
  1458. >schwarz@kodak.com
  1459.  
  1460. Any GWorld references I've read have always insisted that you check
  1461. both the return value being noErr, *and* the GworldPtr being != NULL.  
  1462. Probably you are somehow passing NewGWorld parameters that seem ok, 
  1463. and it does it's job ok, but doesn't put the results where you expect
  1464. it to. I can't see from your example code anything that looks wrong in
  1465. the NewGWorld calls.  It is weird that you call GetGWorld and SetGWorld
  1466. before and after your NewGWorld calls, though.  I may be wrong, but  I 
  1467. don't think NewGWorld does any modification to the active GrafPort or
  1468. GDevice.  You only need to Get/SaveGworld before and after you do 
  1469. any drawing to the GWorld(just like a GrafPort, in fact I've seen it 
  1470. recommended that if you use GWorlds at all your just use Get/SaveGWorld
  1471. in *lieu* of Get/SavePort.
  1472.  
  1473. The main problem I ran into when learning GWorlds was running out of memory,
  1474. and it did return the proper error code.  I concur with the other person
  1475. who said that they have never had NewGWorld return noErr in  reaction 
  1476. to an out of memory error.  If you use GWorlds or anything else that is 
  1477. memory intensive, you will probably have to change the default heap size 
  1478. of your application from whatever compiler you use. 
  1479.  
  1480. -- 
  1481.  ____
  1482. / /\ \    Daniel Craig Jalkut       "All I know is that I don't know nothing,
  1483. -/--\-  snozer@cats.ucsc.edu    and that's FINE" -- Operation Ivy
  1484. X____X  UNIX, coffee, politics, punk-rock, Mac, women, food, and more. 
  1485.  
  1486.  
  1487. +++++++++++++++++++++++++++
  1488.  
  1489. >From Darrin Cardani <Darrin.Cardani@AtlantaGA.NCR.COM>
  1490. Date: Wed, 24 Aug 1994 19:34:38 GMT
  1491. Organization: AT&T Global Information Solutions, Atlanta
  1492.  
  1493. >In article <33ft7j$llk@sundog.tiac.net> Dana Basken writes: 
  1494. >In article <python-2408941148590001@155.50.26.175>
  1495. >python@world.std.com (Steven J. Bushell) writes:
  1496. >
  1497. >> It's an undocumented feature of NewGWorld that it returns no error when it
  1498. >> has insufficient memory to allocate the GWorld.  You should ALWAYS check
  1499. >> the GWorldPtr to determine if the call was successful.  The only time you
  1500. >> get errors back from NewGWorld is when you pass ridiculous parameters to
  1501. >> it.  I've never seen any other errors come back from it.
  1502. >
  1503. >It's odd that you have never seen any other errors return from
  1504. >NewGWorld.  If and when I try to create a GWorld using NewGWorld that
  1505. >is too large to fit into memory, I get a result code of -108
  1506. >(memFullErr) every time.  In my experience, I've never seen NewGWorld
  1507. >not create a GWorld and pass back noErr.
  1508.  
  1509. I too have seen the noErr, but no memory problem. Is there maybe more to
  1510. it than those 2 factors? (Maybe, there's enough mem., but it's too fragmented
  1511. or something wacko like that?)
  1512.  
  1513. Darrin
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521. +++++++++++++++++++++++++++
  1522.  
  1523. >From schwarz@kodak.com (Doug Schwarz)
  1524. Date: Wed, 24 Aug 1994 20:26:47 GMT
  1525. Organization: Eastman Kodak Company, Rochester, NY
  1526.  
  1527. In article <33ft7j$llk@sundog.tiac.net>, dab@zork.tiac.net (Dana Basken) wrote:
  1528.  
  1529. > It's odd that you have never seen any other errors return from
  1530. > NewGWorld.  If and when I try to create a GWorld using NewGWorld that
  1531. > is too large to fit into memory, I get a result code of -108
  1532. > (memFullErr) every time.  In my experience, I've never seen NewGWorld
  1533. > not create a GWorld and pass back noErr.
  1534. > I would look for some other reason in the failure of the allocation of
  1535. > your GWorld.
  1536. > - Dana
  1537.  
  1538. I wrote a small application containing little more than my original code
  1539. fragment and I also get a result of -108 when there is not enough memory. 
  1540. It never returns a null GWorld and a zero error.  So, it seems that I need
  1541. to give a more complete description of my original problem.
  1542.  
  1543. I am using THINK C 7.0.3 and the TCL 1.1.3.  The allocation of the GWorlds
  1544. is done in the initialization method for a class.  I create two instances
  1545. of my class and initialize them like so:
  1546.  
  1547.     SetRect(&bounds, ...);
  1548.     instance1 = new(COffscreenPixMap);
  1549.     instance1->IOffscreenPixMap(bounds);
  1550.     instance2 = new(COffscreenPixMap);
  1551.     instance2->IOffscreenPixMap(bounds);
  1552.  
  1553. where, IOffscreenPixMap() is something like:
  1554.  
  1555.  
  1556. class COffscreenPixMap : CObject
  1557. {
  1558. private:
  1559.     CGrafPtr    currentPort;
  1560.     GDHandle    currentDevice;
  1561.     GWorldPtr   theGWorld;
  1562.  
  1563. public:
  1564.     void        IOffscreenPixMap(Rect);
  1565. };
  1566.  
  1567. void COffscreenPixMap::IOffscreenPixMap(Rect boundsRect)
  1568. {
  1569.     QDErr           err, qderr;
  1570.     PixMapHandle    pixBase;
  1571.     
  1572.     GetGWorld(¤tPort, ¤tDevice);
  1573.     err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);
  1574.     qderr = QDError();
  1575.     pixBase = GetGWorldPixMap(theGWorld);
  1576.     SetGWorld(currentPort, currentDevice);
  1577.     return;
  1578. }
  1579.  
  1580.  
  1581. When I step through the program using the source level debugger,
  1582. everything works fine with instance1.  When I get to NewGWorld for
  1583. instance2, I get
  1584. err = 0, theGWorld = NULL and qderr = 0.  If I purposely set the memory
  1585. partition for the app too low, I never return from NewGWorld, but I get a
  1586. dialog from the TCL telling me that there is not enough memory.  (This I
  1587. also do not understand).  The app never really recovers from this and I
  1588. have to enter MacsBug and do an ES.  I don't really care about that right
  1589. now, I just want to be able to allocate my second GWorld.
  1590.  
  1591. Please note: I definitely have enough memory to allocate these two
  1592. GWorlds.  They each take a little over 1 MB and I have the memory
  1593. partition for the app set to 23 MB (the machine has 32M).  All of this
  1594. stuff is right at the beginning of IApplication() so no other large
  1595. objects have been created.
  1596.  
  1597. Thanks for all the help so far!  Does anybody know what is going on?
  1598.  
  1599. Doug Schwarz
  1600. Eastman Kodak Company
  1601. schwarz@kodak.com
  1602.  
  1603. +++++++++++++++++++++++++++
  1604.  
  1605. >From Jaeger@fquest.com (Brian Stern)
  1606. Date: 25 Aug 1994 05:25:14 GMT
  1607. Organization: The University of Texas at Austin, Austin, Texas
  1608.  
  1609. In article <schwarz-2408941626470001@150.220.61.78>, schwarz@kodak.com
  1610. (Doug Schwarz) wrote:
  1611.  
  1612. > I wrote a small application containing little more than my original code
  1613. > fragment and I also get a result of -108 when there is not enough memory. 
  1614. > It never returns a null GWorld and a zero error.  So, it seems that I need
  1615. > to give a more complete description of my original problem.
  1616. > When I step through the program using the source level debugger,
  1617. > everything works fine with instance1.  When I get to NewGWorld for
  1618. > instance2, I get
  1619. > err = 0, theGWorld = NULL and qderr = 0.  If I purposely set the memory
  1620. > partition for the app too low, I never return from NewGWorld, but I get a
  1621. > dialog from the TCL telling me that there is not enough memory.  (This I
  1622. > also do not understand).  The app never really recovers from this and I
  1623. > have to enter MacsBug and do an ES.  I don't really care about that right
  1624. > now, I just want to be able to allocate my second GWorld.
  1625. > Please note: I definitely have enough memory to allocate these two
  1626. > GWorlds.  They each take a little over 1 MB and I have the memory
  1627. > partition for the app set to 23 MB (the machine has 32M).  All of this
  1628. > stuff is right at the beginning of IApplication() so no other large
  1629. > objects have been created.
  1630. > Thanks for all the help so far!  Does anybody know what is going on?
  1631. > Doug Schwarz
  1632. > Eastman Kodak Company
  1633. > schwarz@kodak.com
  1634.  
  1635. Hi Doug,
  1636.  
  1637. Guess what.  You are successfully creating two GWorlds.  That's why your
  1638. return values are err = 0, and qderr = 0.  The problem is that the
  1639. GWorldPtr isn't going where you think it is.  In TCL 1.1.3 objects are
  1640. handles and your instance variables can move when you call a toolbox
  1641. routine that can move memory, like NewGWorld.  You have two choices.  Use
  1642. local variables when you need to pass by reference and copy the result to
  1643. your instance variables or else lock the object using the utility routine
  1644. 'Lock'.
  1645.  
  1646. The problem you mention with the TCL not enough mem error msg is because
  1647. TCL has a GrowZone proc.  If it can't free up enough mem to satisfy the
  1648. request it throws an exception.  This includes a longjump out of the trap
  1649. that was requesting memory.  I think that this can screw up everything, as
  1650. you discovered.
  1651.  
  1652. -- 
  1653. Brian  Stern  :-{)}
  1654. Jaeger@fquest.com
  1655.  
  1656. +++++++++++++++++++++++++++
  1657.  
  1658. >From python@world.std.com (Steven J. Bushell)
  1659. Date: Thu, 25 Aug 1994 11:44:02 -0500
  1660. Organization: Kodak Electronic Printing Systems, Inc.
  1661.  
  1662. In article <schwarz-2408941626470001@150.220.61.78>, schwarz@kodak.com
  1663. (Doug Schwarz) wrote:
  1664.  
  1665. > void COffscreenPixMap::IOffscreenPixMap(Rect boundsRect)
  1666. > {
  1667. >     QDErr           err, qderr;
  1668. >     PixMapHandle    pixBase;
  1669. >     
  1670. >     GetGWorld(¤tPort, ¤tDevice);
  1671. >     err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);
  1672. >     qderr = QDError();
  1673. >     pixBase = GetGWorldPixMap(theGWorld);
  1674. >     SetGWorld(currentPort, currentDevice);
  1675. >     return;
  1676. > }
  1677. > Thanks for all the help so far!  Does anybody know what is going on?
  1678.  
  1679. Have you tried locking your object before creating the GWorld?  If you
  1680. don't, the address of 'theGWorld' can become invalid if memory moves
  1681. around (i.e., when creating a new GWorld), and the pointer to the GWorld
  1682. will be stored in some random place in memory.  Remember, TCL 1.1.3 is
  1683. still handle-based so you have to watch out when using addresses of
  1684. instance vars; TCL 2.0 is pointer based so you can avoid these problems if
  1685. you use a newer TCL.
  1686.  
  1687. - Steve
  1688.  
  1689. //////////
  1690. //
  1691. //   Steve Bushell
  1692. //   python@world.std.com
  1693. //
  1694. //   "It's always the quiet ones."
  1695. //
  1696. //////////
  1697.  
  1698. +++++++++++++++++++++++++++
  1699.  
  1700. >From schwarz@kodak.com (Doug Schwarz)
  1701. Date: Thu, 25 Aug 1994 17:26:03 GMT
  1702. Organization: Eastman Kodak Company, Rochester, NY
  1703.  
  1704. In article <Jaeger-2508940027100001@slip-11-9.ots.utexas.edu>,
  1705. Jaeger@fquest.com (Brian Stern) wrote:
  1706.  
  1707. > Guess what.  You are successfully creating two GWorlds.  That's why your
  1708. > return values are err = 0, and qderr = 0.  The problem is that the
  1709. > GWorldPtr isn't going where you think it is.  In TCL 1.1.3 objects are
  1710. > handles and your instance variables can move when you call a toolbox
  1711. > routine that can move memory, like NewGWorld.  You have two choices.  Use
  1712. > local variables when you need to pass by reference and copy the result to
  1713. > your instance variables or else lock the object using the utility routine
  1714. > 'Lock'.
  1715. > The problem you mention with the TCL not enough mem error msg is because
  1716. > TCL has a GrowZone proc.  If it can't free up enough mem to satisfy the
  1717. > request it throws an exception.  This includes a longjump out of the trap
  1718. > that was requesting memory.  I think that this can screw up everything, as
  1719. > you discovered.
  1720. > -- 
  1721. > Brian  Stern  :-{)}
  1722. > Jaeger@fquest.com
  1723.  
  1724.  
  1725. In article <python-2508941144020001@155.50.26.175>, python@world.std.com
  1726. (Steven J. Bushell) wrote:
  1727.  
  1728. > Have you tried locking your object before creating the GWorld?  If you
  1729. > don't, the address of 'theGWorld' can become invalid if memory moves
  1730. > around (i.e., when creating a new GWorld), and the pointer to the GWorld
  1731. > will be stored in some random place in memory.  Remember, TCL 1.1.3 is
  1732. > still handle-based so you have to watch out when using addresses of
  1733. > instance vars; TCL 2.0 is pointer based so you can avoid these problems if
  1734. > you use a newer TCL.
  1735. > - Steve
  1736. > //   Steve Bushell
  1737. > //   python@world.std.com
  1738.  
  1739.  
  1740.  
  1741. Yes!  Brian and Steve are correct.  I replaced
  1742.  
  1743.     err = NewGWorld(&theGWorld, 32, &boundsRect, NULL, NULL, 0);
  1744.  
  1745. where theGWorld is an instance variable, with
  1746.  
  1747.     GWorldPtr    tempGWorld;
  1748.     err = NewGWorld(&tempGWorld, 32, &boundsRect, NULL, NULL, 0);
  1749.     theGWorld = tempGWorld;
  1750.  
  1751. where tempGWorld is a local variable and it works just fine.  I was also able to
  1752. make some other simplifications once *that* was working (thanks to some other
  1753. helpful suggestions).
  1754.  
  1755. So, THANK YOU EVERYBODY and especially Brian and Steve!
  1756.  
  1757. Doug Schwarz
  1758. Eastman Kodak Company
  1759. schwarz@kodak.com
  1760.  
  1761. ---------------------------
  1762.  
  1763. >From partingt@fwi.uva.nl (Vincent Partington)
  1764. Subject: Won't strange windows come in my layer?
  1765. Date: 23 Aug 1994 11:09:43 GMT
  1766. Organization: FWI, University of Amsterdam
  1767.  
  1768. Hi everyone,
  1769.  
  1770. I'm investigating putting a pointer to an object in the refCon of a windowPtr
  1771. to call a virtual function (C++) through it. I was wondering:
  1772. Can I be sure I'll only get events for my own windows? Can I be sure the
  1773. refCon value doesn't contain garbage?
  1774. I know under System 6 DA's would invade your window list but they can be
  1775. recognized by looking at the windowKind (or something). It's it ok for my
  1776. app to break if somebody makes an INIT that puts windows in my layer?
  1777.  
  1778. Thanks, Vincent
  1779. -- 
  1780. appel peer banaan baksteen           ||| The Fingerware Project:
  1781. schelp zon zand rolstoel             ||| Put your code snippets in your .plan!
  1782. groen wit geel flatgebouw            ||| If you want to know more
  1783. boer postbode bouwvakker roos        ||| finger partingt@gene.fwi.uva.nl
  1784.  
  1785. +++++++++++++++++++++++++++
  1786.  
  1787. >From Jaeger@fquest.com (Brian Stern)
  1788. Date: 23 Aug 1994 16:44:50 GMT
  1789. Organization: The University of Texas at Austin, Austin, Texas
  1790.  
  1791. In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
  1792. Partington) wrote:
  1793.  
  1794. > Hi everyone,
  1795. > I'm investigating putting a pointer to an object in the refCon of a windowPtr
  1796. > to call a virtual function (C++) through it. I was wondering:
  1797. > Can I be sure I'll only get events for my own windows? Can I be sure the
  1798. > refCon value doesn't contain garbage?
  1799. > I know under System 6 DA's would invade your window list but they can be
  1800. > recognized by looking at the windowKind (or something). It's it ok for my
  1801. > app to break if somebody makes an INIT that puts windows in my layer?
  1802. > Thanks, Vincent
  1803. > -- 
  1804. > appel peer banaan baksteen           ||| The Fingerware Project:
  1805. > schelp zon zand rolstoel             ||| Put your code snippets in your .plan!
  1806. > groen wit geel flatgebouw            ||| If you want to know more
  1807. > boer postbode bouwvakker roos        ||| finger partingt@gene.fwi.uva.nl
  1808.  
  1809. Vincent,
  1810.  
  1811. You should set the WindowKind of any window when you create it; choose
  1812. values that are not among the already defined values (> 8 I think).  Then
  1813. when you receive window events you check the windowkind first and then act
  1814. accordingly.  You can put anything you like in the refcon, including
  1815. object references.  If you do this then presumably you wouldn't do
  1816. anything for a windowkind that your app doesn't know about.
  1817.  
  1818. I wouldn't worry about an INIT putting windows in your layer.  If I was
  1819. writing an INIT to do such a thing I'd be sure to steal any window events
  1820. related to that window before your app ever saw them.
  1821.  
  1822. -- 
  1823. Brian  Stern  :-{)}
  1824. Jaeger@fquest.com
  1825.  
  1826. +++++++++++++++++++++++++++
  1827.  
  1828. >From jonasw@lysator.liu.se (Jonas Wallden)
  1829. Date: 23 Aug 1994 21:02:05 GMT
  1830. Organization: (none)
  1831.  
  1832. Jaeger@fquest.com (Brian Stern) writes:
  1833.  
  1834. >In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
  1835. >Partington) wrote:
  1836.  
  1837. >> Hi everyone,
  1838. >> 
  1839. >> I'm investigating putting a pointer to an object in the refCon of a windowPtr
  1840. >> to call a virtual function (C++) through it. I was wondering:
  1841. >> Can I be sure I'll only get events for my own windows? Can I be sure the
  1842. >> refCon value doesn't contain garbage?
  1843. >> I know under System 6 DA's would invade your window list but they can be
  1844. >> recognized by looking at the windowKind (or something). It's it ok for my
  1845. >> app to break if somebody makes an INIT that puts windows in my layer?
  1846. >> 
  1847. >> Thanks, Vincent
  1848. >> -- 
  1849. >> appel peer banaan baksteen         ||| The Fingerware Project:
  1850. >> schelp zon zand rolstoel           ||| Put your code snippets in your .plan!
  1851. >> groen wit geel flatgebouw          ||| If you want to know more
  1852. >> boer postbode bouwvakker roos      ||| finger partingt@gene.fwi.uva.nl
  1853. >
  1854. >Vincent,
  1855. >
  1856. >You should set the WindowKind of any window when you create it; choose
  1857. >values that are not among the already defined values (> 8 I think).  Then
  1858. >when you receive window events you check the windowkind first and then act
  1859. >accordingly.  You can put anything you like in the refcon, including
  1860. >object references.  If you do this then presumably you wouldn't do
  1861. >anything for a windowkind that your app doesn't know about.
  1862. >
  1863. >I wouldn't worry about an INIT putting windows in your layer.  If I was
  1864. >writing an INIT to do such a thing I'd be sure to steal any window events
  1865. >related to that window before your app ever saw them.
  1866. >
  1867. >Brian  Stern  :-{)}
  1868.  
  1869. A great way to extend WindowRecords is to declare your own data type with
  1870. a WindowRecord as the first item.
  1871.  
  1872. E.g.,
  1873.  
  1874. struct tMyWinData {
  1875.    //  This must come first!
  1876.    WindowRecord   winRec;
  1877.  
  1878.    //  Additional window-specific data here...
  1879.    Handle         aHandle;
  1880.    Ptr            aPtr;
  1881. };
  1882. typedef struct tMyWinData tMyWinData;
  1883. typedef tMyWinData *tMyWinPtr;
  1884.  
  1885. The trick now is that you can typecast any window pointer to tMyWinPtr (and
  1886. back) and access your window-specific data fields. You might want to place
  1887. your application's unique creator code in the WindowRecord refCon field and
  1888. check it first to be sure you have a window that belongs to your program.
  1889.  
  1890. I use this all the time and it is useful in many other places where the
  1891. system gives you a pointer to an object (VBL tasks, ParamBlocks, ...) and
  1892. you need to store extra data. No need to use any globals for this stuff!
  1893.  
  1894. --
  1895. `.`.   Jonas Wallden                    `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
  1896. `.`.`.   Internet: jonasw@lysator.liu.se  `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
  1897. `.`.`.`.   AppleLink: sw1369                `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
  1898.  
  1899. +++++++++++++++++++++++++++
  1900.  
  1901. >From benh@fdn.org (Benjamin Herrenschmidt)
  1902. Date: Tue, 23 Aug 94 17:24:09 +0100
  1903. Organization: (none)
  1904.  
  1905.  
  1906. In article <33cldn$ncd@hermes.fwi.uva.nl> (comp.sys.mac.programmer), partingt@fwi.uva.nl (Vincent Partington) writes:
  1907.  
  1908. >I'm investigating putting a pointer to an object in the refCon of a windowPtr
  1909. >to call a virtual function (C++) through it. I was wondering:
  1910. >Can I be sure I'll only get events for my own windows? Can I be sure the
  1911. >refCon value doesn't contain garbage?
  1912. >I know under System 6 DA's would invade your window list but they can be
  1913. >recognized by looking at the windowKind (or something). It's it ok for my
  1914. >app to break if somebody makes an INIT that puts windows in my layer?
  1915.  
  1916. I think you should have somewhere a list of YOUR windows, so you can
  1917. check it's one of yours before using it's refcon. Another way to do
  1918. so is to use a custom windowKind and check for it (that's what PowerPlant
  1919. does) but you are not protected against someone using the same windowKind
  1920. (there is no way to register them).
  1921.  
  1922. BenH.
  1923.  
  1924. +++++++++++++++++++++++++++
  1925.  
  1926. >From lsr@taligent.com (Larry Rosenstein)
  1927. Date: Tue, 23 Aug 1994 23:04:25 GMT
  1928. Organization: Taligent, Inc.
  1929.  
  1930. In article <33cldn$ncd@hermes.fwi.uva.nl>, partingt@fwi.uva.nl (Vincent
  1931. Partington) wrote:
  1932.  
  1933. > Can I be sure I'll only get events for my own windows? Can I be sure the
  1934. > refCon value doesn't contain garbage?
  1935.  
  1936. No.  For example, there's a program called PacerForum (a BBS app) that can
  1937. pop up notification windows inside your application's space.  It makes the
  1938. windows look like DAs (negative windowKind) so if you handle those
  1939. properly you should be OK.
  1940.  
  1941. -- 
  1942. Larry Rosenstein
  1943. Taligent, Inc.
  1944.  
  1945. lsr@taligent.com
  1946.  
  1947. +++++++++++++++++++++++++++
  1948.  
  1949. >From h+@nada.kth.se (Jon W{tte)
  1950. Date: Wed, 24 Aug 1994 10:23:51 +0200
  1951. Organization: Royal Institute of Something or other
  1952.  
  1953. In article <33cldn$ncd@hermes.fwi.uva.nl>,
  1954. partingt@fwi.uva.nl (Vincent Partington) wrote:
  1955.  
  1956. >It's it ok for my
  1957. >app to break if somebody makes an INIT that puts windows in my layer?
  1958.  
  1959. Yes; PowerPlant, TCL and MacApp all put object pointers in the 
  1960. refCon. To be really safe, set the windowKind of windows you 
  1961. create to something >8, like 11147, and test for that first. 
  1962. Also test that the object pointer is not 0 (and if you're 
  1963. paranoid; not odd and above your heap start and below your 
  1964. stack base)
  1965.  
  1966. Cheers,
  1967.  
  1968.                 / h+
  1969.  
  1970.  
  1971. --
  1972.   Jon W‰tte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
  1973.  "Don't use the Layer Manager"
  1974.  
  1975.  
  1976. +++++++++++++++++++++++++++
  1977.  
  1978. >From h+@nada.kth.se (Jon W{tte)
  1979. Date: Wed, 24 Aug 1994 23:10:45 +0200
  1980. Organization: Royal Institute of Something or other
  1981.  
  1982. In article <01050105.7vo9pz@tatooine.fdn.org>,
  1983. benh@fdn.org (Benjamin Herrenschmidt) wrote:
  1984.  
  1985. >I think you should have somewhere a list of YOUR windows, so you can
  1986. >check it's one of yours before using it's refcon. Another way to do
  1987. >so is to use a custom windowKind and check for it (that's what PowerPlant
  1988. >does) but you are not protected against someone using the same windowKind
  1989. >(there is no way to register them).
  1990.  
  1991. No, but there is simply NO WAY that someone elses window gets 
  1992. into your window list, unless that's a DA/system window, in 
  1993. which case the windowKind will be negative. Using a separate 
  1994. list is just a lot of trouble to avoid something which won't 
  1995. happen; sort of lugging around a portable bomb shelter in case 
  1996. a meteorite would hit you...
  1997.  
  1998. Cheers,
  1999.  
  2000.  
  2001.                 / h+
  2002.  
  2003.  
  2004. --
  2005.   Jon W‰tte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
  2006.  "Don't use the Layer Manager"
  2007.  
  2008.  
  2009. +++++++++++++++++++++++++++
  2010.  
  2011. >From sigurasg@plusplus.is (Sigurdur Asgeirsson)
  2012. Date: 25 Aug 1994 09:03:27 GMT
  2013. Organization: Plusplus Inc.
  2014.  
  2015. h+@nada.kth.se (Jon W{tte) writes:
  2016.  
  2017. >In article <01050105.7vo9pz@tatooine.fdn.org>,
  2018. >benh@fdn.org (Benjamin Herrenschmidt) wrote:
  2019.  
  2020. >>I think you should have somewhere a list of YOUR windows, so you can
  2021.  
  2022. [snip]
  2023.  
  2024. >No, but there is simply NO WAY that someone elses window gets 
  2025. >into your window list, unless that's a DA/system window, in 
  2026. >which case the windowKind will be negative. Using a separate 
  2027. >list is just a lot of trouble to avoid something which won't 
  2028. >happen; sort of lugging around a portable bomb shelter in case 
  2029. >a meteorite would hit you...
  2030.  
  2031.   Uhm, hate to rain on your parade, but what about CTB windows? CTB
  2032. tools are allowed to put up windows (just about anytime if I remember
  2033. correctly), AND they use the RefCon for their own purposes, so if
  2034. you're using the CTB beware...
  2035.  
  2036. --
  2037. Sigurdur Asgeirsson    | "Well you know, C isn't that hard, void (*(*f[])())()
  2038. Kambasel 26            | for instance declares f as an array of unspecified 
  2039. 109 Reykjavik, Iceland | size, of pointers to functions that return pointers to
  2040. sigurasg@plusplus.is   | functions that return void... I think"
  2041.  
  2042. ---------------------------
  2043.  
  2044. End of C.S.M.P. Digest
  2045. **********************
  2046.  
  2047.  
  2048.