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

  1. Received-Date: Wed, 18 May 1994 14:13:23 +0200
  2. From: pottier@clipper.ens.fr (Francois Pottier)
  3. Subject: csmp-digest-v3-028
  4. To: csmp-digest@ens.fr
  5. Date: Wed, 18 May 94 14:13:10 MET DST
  6. X-Mailer: ELM [version 2.3 PL11]
  7. Errors-To: listman@ens.fr
  8. Reply-To: pottier@clipper.ens.fr
  9. X-Sequence: 31
  10.  
  11. C.S.M.P. Digest             Wed, 18 May 94       Volume 3 : Issue 28
  12.  
  13. Today's Topics:
  14.  
  15.         CRC-16 routine in C for native code
  16.         CodeWarrior Gold Education Price
  17.         How to write a bullet-proof lib?
  18.         PixMap to mask
  19.         Posting an event to another application?
  20.         Shared memory...
  21.         Unmounting all volumes?
  22.  
  23.  
  24.  
  25. The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
  26. (pottier@clipper.ens.fr).
  27.  
  28. The digest is a collection of article threads from the internet newsgroup
  29. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  30. regularly and want an archive of the discussions.  If you don't know what a
  31. newsgroup is, you probably don't have access to it.  Ask your systems
  32. administrator(s) for details.  If you don't have access to news, you may
  33. still be able to post messages to the group by using a mail server like
  34. anon.penet.fi (mail help@anon.penet.fi for more information).
  35.  
  36. Each issue of the digest contains one or more sets of articles (called
  37. threads), with each set corresponding to a 'discussion' of a particular
  38. subject.  The articles are not edited; all articles included in this digest
  39. are in their original posted form (as received by our news server at
  40. nef.ens.fr).  Article threads are not added to the digest until the last
  41. article added to the thread is at least two weeks old (this is to ensure that
  42. the thread is dead before adding it to the digest).  Article threads that
  43. consist of only one message are generally not included in the digest.
  44.  
  45. The digest is officially distributed by two means, by email and ftp.
  46.  
  47. If you want to receive the digest by mail, send email to listserv@ens.fr
  48. with no subject and one of the following commands as body:
  49.     help                        Sends you a summary of commands
  50.     subscribe csmp-digest Your Name    Adds you to the mailing list
  51.     signoff csmp-digest            Removes you from the list
  52. Once you have subscribed, you will automatically receive each new
  53. issue as it is created.
  54.  
  55. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
  56. Questions related to the ftp site should be directed to
  57. scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
  58. digest are available there.
  59.  
  60. Also, the digests are available to WAIS users as comp.sys.mac.programmer.src.
  61.  
  62.  
  63. -------------------------------------------------------
  64.  
  65. >From satcomm@aol.com (SatComm)
  66. Subject: CRC-16 routine in C for native code
  67. Date: 30 Apr 1994 14:40:08 -0400
  68. Organization: America Online, Inc. (1-800-827-6364)
  69.  
  70. I'm looking to replace some old code in assembly that calculated the standard
  71. Xmodem/MacBinary CRC-16 stuff.  Unfortunately, I think I threw away all
  72. remnants of my CRC stuff when I discovered the assembly routine.  Does anyone
  73. have a CRC routine for this in C?
  74.  
  75. Thanks.
  76.  
  77. satcomm@aol.com
  78.  
  79. +++++++++++++++++++++++++++
  80.  
  81. >From david@oahu.cs.ucla.edu (David Dantowitz)
  82. Date: Sun, 01 May 94 16:36:57 GMT
  83. Organization: UCLA, Computer Science Department
  84.  
  85. Here's some code and information on CRCs I put together some years
  86. back.  It is in the public domain.
  87.  
  88. David
  89.  
  90. - --------- cut here --------------
  91. /*
  92.  
  93.    Computing CRCs
  94.  
  95.    This set of implementations was written by David M. Dantowitz, and
  96.    has been placed in the public domain, to be used at the user's
  97.    discretion.  The original code was implemented in Turbo Pascal 3.0
  98.    this submission is a version written in C.
  99.  
  100.    This program demonstrates various ways by which Cyclic
  101.    Redundancy Checks (CRC) may be computed and their relative speeds.
  102.  
  103.  
  104.    CRC polynomials in this program are represented by replacing
  105.    each term that is non-zero with a 1 and each zero term with a 0.
  106.    Note that the highest order bits represent the low order terms 
  107.    of the polynomial.
  108.  
  109.    Thus X^3+X^1+1 becomes 1101 and X^4+X^1+1 becomes 11001.
  110.  
  111.    Now, since all polynomials have a highest term (X^a) we drop the
  112.    highest term during computation (shift right one bit, dropping
  113.    the low bit).
  114.  
  115.  
  116.    Here are some examples of conversion from symbolic to binary
  117.    representation (but not necessarily polynomials with desirable
  118.    CRC properties):
  119.  
  120.  
  121.            Polynomial                Representation     Hex
  122.  
  123.           X^5 + X^2 + 1                  10100          $14
  124.  
  125.             X^7 + 1                     1000000         $40
  126.  
  127.           X^3+X^2+X^1+1                   111           $7
  128.  
  129.           X^6+X^5+X^3+1                 100101          $25
  130.  
  131.  
  132.    For a good discussion of polynomial selection see "Cyclic
  133.    Codes for Error Detection", by W. W. Peterson and
  134.    D. T. Brown, Proceedings of the IEEE, volume 49, pp 228-235,
  135.    January 1961.
  136.  
  137.    A reference on table driven CRC computation is "A Cyclic
  138.    Redundancy Checking (CRC) Algorithm" by A. B. Marton and
  139.    T. K. Frambs, The Honeywell Computer Journal, volume 5,
  140.    number 3, 1971.
  141.  
  142.    Also used to prepare these examples was "Computer Networks",
  143.    by Andrew S. Tanenbaum, Prentice Hall, Inc.  Englewood Cliffs,
  144.    New Jersey, 1981.
  145.  
  146.    The following four polynomials are international standards:
  147.  
  148.  
  149.         CRC-12 = X^12 + X^11 + X^3 + X^2 + X^1 + 1
  150.         CRC-16 = X^16 + X^15 + X^2 + 1
  151.         CRC-CCITT = X^16 + X^12 + X^5 + 1
  152.         CCITT-32 = X^32 + X^26 + X^23 + X^22 + X^16 + X^12 + X^11 + X^10 +
  153.                    X^8 + X^7 + X^5 + X^4 + X^2 + X^1 + 1
  154.  
  155.    In Binary and hexadecimal :
  156.  
  157.                    Binary                     Hex
  158.  
  159.         CRC-12    = 1111 0000 0001           $0F01
  160.         CRC-16    = 1010 0000 0000 0001      $A001
  161.         CRC-CCITT = 1000 0100 0000 1000      $8404    (Used below)
  162.         CCITT-32  = 1110 1101 1011 1000 
  163.                     1000 0011 0010 0000      $EDB88320
  164.  
  165.    The first is used with 6-bit characters and the second two
  166.    with 8-bit characters.  All of the above will detect any
  167.    odd number of errors.  The second two will catch all 16-bit
  168.    bursts, a high percentage of 17-bit bursts (~99.997%) and
  169.    also a large percentage of 18-bit or larger bursts (~99.998%).
  170.    The paper mentioned above (Peterson and Brown) discusses how 
  171.    to compute the statistics presented which have been quoted 
  172.    from Tanenbaum.
  173.  
  174.    (A burst of length N is defined a sequence of N bits, where
  175.    the first and last bits are incorrect and the bits in the
  176.    middle are any possible combination of correct and incorrect.
  177.    See the paper by Peterson and Brown for more information)
  178.  
  179.    Note that when using a polynomial of degree N, the CRC is the
  180.    first N bits of the value returned by the routines below.
  181.    (e.g. with CRC-12, the CRC is bits 0 to 11 of the CRC value,
  182.    with the other two mentioned above, the CRC is all 16 bits.)
  183.  
  184.  
  185.    Here is a quick idea of what is being calculated ...
  186.  
  187.    The CRC is the residual from division of the data stream by
  188.    the CRC polynomial.  The data stream is also thought of as a
  189.    polynomial, with the highest order term being the lowest bit
  190.    of the first byte of the data stream and the lowest order term
  191.    of the polynomial being the high bit of the last byte of data.
  192.    The actual division is performed on the data stream polynomial
  193.    multiplied by X^y where y is the degree of the CRC polynomial.
  194.  
  195.  
  196.    All math used to compute CRCs is done modulo 2.  This means the
  197.    following relationships are used:
  198.  
  199.  
  200.                 0+0=0    0+1=1    1+0=1    1+1=0   (XOR)
  201.                 0-0=0    0-1=1    1-0=1    1-1=0   (XOR)
  202.                 0*0=0    0*1=0    1*0=0    1*1=1   (AND)
  203.  
  204.    Thus addition and subtraction have NO carries or borrows.
  205.  
  206.                                              
  207.    Here is a sample computation showing the actual division.
  208.  
  209.  
  210.    Polynomial = X^4+X^3+1; Data = $94.
  211.  
  212.    The division performed is 1001 into 0010 1001.  Notice that
  213.    the highest order terms of the data polynomial are the lowest
  214.    order bits of the data stream.  We will also multiply the
  215.    dividend by X^4 as noted above:
  216.  
  217.              1011011  - The quotient is not important and is discarded.
  218.    1001/001010010000
  219.          -1001  ----    The extra 0s result from multiplying the data by X^4
  220.           ----
  221.             1101 <--    The code below calculates this value
  222.            -1001
  223.             ----
  224.              1000
  225.             -1001
  226.              ----
  227.                 1000
  228.                -1001
  229.                 ----
  230.                 0001  This is the CRC (the residual from the division)!
  231.  
  232.  
  233.    The code below does not shift the data by the number of bits
  234.    equal to the degree of the CRC polynomial.  There is no ill effect
  235.    caused by not doing this multiply.  Now, the result of the CRC computation
  236.    is just the residue from the division of the data by the CRC.  
  237.  
  238.  
  239.    None of the routines below appear to compute a division.  In the example
  240.    above the subtractions are really XORs (pronounced exclusive OR).  XOR
  241.    has the same behavior as +/- in modulo two arithmetic, so it is used
  242.    in the computations.  The first CRC routine below (Simple_CRC) models
  243.    the computation lucidly.  The other routines use various optimization
  244.    techniques to speed the computation.
  245.  
  246.  
  247.    CRC use ...
  248.  
  249.    The CRC is appended to the end of the original data stream (or stored
  250.    separetely).  When the receiver gets the data stream, the CRC is again
  251.    computed and matched against the received CRC, if the two do not match
  252.    then an error has most likely occurred.  
  253.  
  254.  
  255.    My address is
  256.  
  257.    David Dantowitz
  258.    Dantowitz Consulting and Research
  259.    P.O. Box 8105
  260.    Englewood, NJ  07631
  261.  
  262.    (201) Low-Bug-C
  263.    AppleLink: Dantowitz
  264. */
  265.  
  266. #include <stdio.h>
  267. #include <string.h>
  268.  
  269.  
  270. #define INITIAL_CRC 0xFFFFFFFF
  271.  
  272.  
  273. /*
  274.    This result was obtained by calling make_crc_table(0xedb88320).
  275. */
  276.  
  277.  
  278. int             crc_table[16] =
  279. {
  280.   0x00000000,
  281.   0xfdb71064,
  282.   0xfb6e20c8,
  283.   0x06d930ac,
  284.   0xf6dc4190,
  285.   0x0b6b51f4,
  286.   0x0db26158,
  287.   0xf005713c,
  288.   0xedb88320,
  289.   0x100f9344,
  290.   0x16d6a3e8,
  291.   0xeb61b38c,
  292.   0x1b64c2b0,
  293.   0xe6d3d2d4,
  294.   0xe00ae278,
  295.   0x1dbdf21c
  296. };
  297.  
  298.  
  299.  
  300. make_crc_table(crc_poly)
  301.   int             crc_poly;
  302. {
  303.   int             i, val, result;
  304.  
  305.   for (val = 0; val < 16; val++)
  306.   {
  307.     result = val;
  308.  
  309.     for (i = 0; i < 4; i++)
  310.       if (result & 1)
  311.     result = (result >> 1) ^ crc_poly;
  312.       else
  313.     result >>= 1;
  314.  
  315.     crc_table[val] = result;
  316.  
  317.     printf("0x%08lx\n", result);
  318.   }
  319.  
  320. }
  321.  
  322. int
  323. compute_crc(old_crc, s, len)
  324.   int             old_crc;
  325.   char           *s;
  326.   int             len;
  327. {
  328.   int             i;
  329.  
  330.   for (i = 0; i < len; i++)
  331.  
  332.   {
  333. /*
  334.    XOR in the data.
  335. */
  336.  
  337.     old_crc ^= s[i];
  338. /*
  339.    Perform the XORing for each nybble
  340. */
  341.     old_crc = (old_crc >> 4) ^ crc_table[old_crc & 0x0f];
  342.     old_crc = (old_crc >> 4) ^ crc_table[old_crc & 0x0f];
  343.   }
  344.  
  345.   return (old_crc);
  346. }
  347.  
  348. main()
  349. {
  350.   char            line[100];
  351.   int             crc_val;
  352.   int             len;
  353.  
  354. /*   make_crc_table(0xedb88320); done at compile time... */
  355.  
  356. /*
  357.    initialize the crc -- start with this value each time you start
  358.    a session.
  359. */
  360.   crc_val = INITIAL_CRC;
  361.  
  362.   strcpy(line, "This will test the crc function");
  363.  
  364.   len = strlen(line);
  365.  
  366.  
  367.   crc_val = compute_crc(crc_val, line, len);
  368.  
  369. /* 
  370.    let's add MORE text to the CRC -- they can be cumulative across many
  371.    blocks of data.
  372. */
  373.  
  374.   strcpy(line, "More text to add");
  375.  
  376.   len = strlen(line);
  377.  
  378.   crc_val = compute_crc(crc_val, line, len);
  379.  
  380. }
  381.  
  382. -- 
  383. David Dantowitz
  384. david@cs.ucla.edu
  385.  
  386. Singing Barbershop when I'm not doing parallel simulation
  387.  
  388. +++++++++++++++++++++++++++
  389.  
  390. >From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
  391. Date: Mon, 2 May 1994 18:51:22 +1200 (NZST)
  392. Organization: (none)
  393.  
  394. satcomm@aol.com (SatComm) writes:
  395. > I'm looking to replace some old code in assembly that calculated the standard
  396. > Xmodem/MacBinary CRC-16 stuff.  Unfortunately, I think I threw away all
  397. > remnants of my CRC stuff when I discovered the assembly routine.  Does anyone
  398. > have a CRC routine for this in C?
  399.  
  400. Here's a routine for checking the Macbinary header CRC.  I'm not sure what
  401. XModem uses:
  402.  
  403. - --------------
  404. #define CCITT_CRC_GEN    0x1021
  405.  
  406. short CalcCRC(register unsigned char *dataBuf, register long size)
  407. {
  408.     register unsigned short    crc = 0;
  409.     register unsigned short    dataByte;
  410.     register long i;
  411.     
  412.     while (size--)
  413.     {
  414.         dataByte = *dataBuf++ << 8;
  415.         for (i = 8; i > 0; i--)
  416.         {
  417.             if ((dataByte ^ crc) & 0x8000)
  418.                 crc = (crc << 1) ^ CCITT_CRC_GEN;
  419.             else
  420.                 crc <<= 1 ;
  421.             dataByte <<= 1;
  422.         }
  423.     }
  424.     return(crc);
  425. }
  426. - --------------
  427.  
  428.  
  429. For my own use, I've recoded it slightly in a way that gives much better code
  430. on unsophisticated compilers such as MPW C.  I was able to alternate operations
  431. on different data, which should probably help a little on pipelined CPUs (I
  432. don't know how much), and spelling things out a little more explicitely stopped
  433. a lot of data moves etc that weren't needed.
  434.  
  435. Treating C as a two-address assembly language seems to help many compilers a
  436. lot...  :-)
  437.  
  438. - --------------
  439. #define CCITT_CRC_GEN    0x1021
  440.  
  441. short CalcCRC(register unsigned char *dataBuf, register long size)
  442. {
  443.     register unsigned long crc = 0;
  444.     register unsigned long dataByte;
  445.     register long i;
  446.     
  447.     while (--size >= 0)
  448.     {
  449.         dataByte = *dataBuf++;
  450.         dataByte <<= 8;
  451.         i = 8;
  452.         do {    
  453.             register long bit = dataByte;
  454.             dataByte += dataByte;
  455.             bit ^= crc;
  456.             crc += crc;
  457.             if (bit &= 0x8000)
  458.                 crc ^= CCITT_CRC_GEN;
  459.         } while (--i);
  460.     }
  461.     return crc;
  462. }
  463. - --------------
  464.  
  465. +++++++++++++++++++++++++++
  466.  
  467. >From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
  468. Date: Mon, 2 May 1994 19:15:41 +1200 (NZST)
  469. Organization: (none)
  470.  
  471. satcomm@aol.com (SatComm) writes:
  472. > I'm looking to replace some old code in assembly that calculated the standard
  473. > Xmodem/MacBinary CRC-16 stuff.  Unfortunately, I think I threw away all
  474. > remnants of my CRC stuff when I discovered the assembly routine.  Does anyone
  475. > have a CRC routine for this in C?
  476.  
  477. Further to my last post, and to (hopefully) forstall email, yes I am aware
  478. that a bit-by-bit algorithm for CRC isn't the fastest way to do it, no
  479. matter how efficiently coded.
  480.  
  481. It was good enough for my purpose (which was checking a smallish Macbinary
  482. header), and I was more interested in code size than in speed (for reasons
  483. I won't go into...).
  484.  
  485. -- Bruce
  486.  
  487. ---------------------------
  488.  
  489. >From cvafy002@csupomona.edu
  490. Subject: CodeWarrior Gold Education Price
  491. Date: 25 Apr 94 14:32:09 PST
  492. Organization: California State Polytechnic University, Pomona
  493.  
  494. I have a friend who'd like to get CodeWarrior Gold at the education price (I
  495. read it was $99). How would he go about getting it? He doesn't have internet
  496. access. How can he find out if his College and/or he qualifies?
  497.  
  498.  
  499. +++++++++++++++++++++++++++
  500.  
  501. >From mwron@aol.com (MW Ron)
  502. Date: 27 Apr 1994 21:16:03 -0400
  503. Organization: America Online, Inc. (1-800-827-6364)
  504.  
  505. In article <1994Apr25.143209.1@clstac>, cvafy002@csupomona.edu writes:
  506. >>I have a friend who'd like to get CodeWarrior Gold at the education price (I
  507. read it was $99). How would he go about getting it? He doesn't have internet
  508. access. How can he find out if his College and/or he qualifies?
  509.  
  510. I think this will be helpful to all of you strugling students.
  511.  
  512. For educational prices, BookMasters is our distributor and their phone number
  513. is 1-800-247-6553 in the US. Educational pricing is as such:
  514.  
  515.                 Gold    $99.00 US
  516.                 Silver  $79.00 US
  517.                 Bronze  $59.00 US
  518.  
  519. $15.00 shipping and handling US orders.
  520.  
  521. You must fax BookMasters proof that you are either a student or officially
  522. affilliated with a University.  Their fax number is(419) 281-6883.
  523.  
  524. Ron Liechty
  525. mwron@aol.com
  526. Metrowerks Inc.
  527.  
  528. +++++++++++++++++++++++++++
  529.  
  530. >From cs2ev@herts.ac.uk (Mas)
  531. Date: 28 Apr 1994 17:29:59 +0100
  532. Organization: University of Hertfordshire
  533.  
  534.   Dear all
  535.  
  536.     Please do tell me the difference between gold, silver & bronze
  537. versions of codewarrior.  Thanks
  538.  
  539. Andre-John MAS
  540.  
  541.  
  542. +++++++++++++++++++++++++++
  543.  
  544. >From mwron@aol.com (MW Ron)
  545. Date: 28 Apr 1994 20:46:02 -0400
  546. Organization: America Online, Inc. (1-800-827-6364)
  547.  
  548. In article <2pooa7$dej@altair.herts.ac.uk>, cs2ev@herts.ac.uk (Mas) writes:
  549.  
  550. Please do tell me the difference between gold, silver & bronze versions of
  551. codewarrior.  
  552.  
  553. >>GOLD    Includes all for 68K Macintosh and Power Macintosh as well
  554. as 68K-hosted PowerPC compilers.  
  555.  
  556. SILVER   Includes all for PowerPC Only (no 68K Macintosh  compilers or
  557. linkers)
  558.  
  559. BRONZE  Includes all for 68K Macintosh (no PowerPC compilers or
  560. linkers) 
  561.  
  562. Ron Liechty
  563. mwron@aol.com
  564. Metrowerks Inc.
  565.  
  566. +++++++++++++++++++++++++++
  567.  
  568. >From zee@fwi.uva.nl (Daniel vd Zee)
  569. Date: 3 May 1994 14:15:03 GMT
  570. Organization: FWI, University of Amsterdam
  571.  
  572. mwron@aol.com (MW Ron) writes:
  573. >For educational prices, BookMasters is our distributor and their phone number
  574. >is 1-800-247-6553 in the US. Educational pricing is as such:
  575. >                Gold    $99.00 US
  576. >                Silver  $79.00 US
  577. >                Bronze  $59.00 US
  578. >$15.00 shipping and handling US orders.
  579. How about non-US students, are the pricing and the distributor the same and
  580. do i have to get some kind of internalional student card to order?
  581.  
  582. Thanx,
  583. Daniel (zee@fwi.uva.nl)
  584.  
  585.  
  586.  
  587. +++++++++++++++++++++++++++
  588.  
  589. >From mwron@aol.com (MW Ron)
  590. Date: 4 May 1994 17:10:03 -0400
  591. Organization: America Online, Inc. (1-800-827-6364)
  592.  
  593. In article <2q5m97$4dv@hermes.fwi.uva.nl>, zee@fwi.uva.nl (Daniel vd Zee)
  594. writes:
  595. >> How about non-US students, are the pricing and the distributor the same and
  596. do i have to get some kind of internalional student card to order?
  597.  
  598. I do not know if we have  or do not have any  international educational
  599. discounts you would have to contact one of the following to find out what the
  600. item is in your particular country.
  601.  
  602. Japan       -  B.U.G. in Sapporo,  Applelink = BUGPLAN.DVJ
  603.  
  604. Australia   -  Techflow in Australia, Applelink = TECHFLOW
  605.  
  606. Germay      -  pandasoft in Berlin, Germany, telephone= (49) 3031 5913 16
  607.  
  608. All others,   BookMasters
  609.  
  610.                        U.S./Canada:   1-800-247-6553
  611.                        International:   1-419-281-1802
  612.                        Fax No.:   1-419-281-6883
  613. Everywhere else in the world, including Europe out of Germany should be taken
  614. direct through our distributor BookMasters.
  615.  
  616. Ron Liechty
  617. mwron@aol.com
  618. Metrowerks Inc.
  619.  
  620. +++++++++++++++++++++++++++
  621.  
  622. >From neeri@iis.ee.ethz.ch (Matthias Neeracher)
  623. Date: 4 May 1994 22:34:08 GMT
  624. Organization: Swiss Federal Institute of Technology (ETHZ)
  625.  
  626. mwron@aol.com (MW Ron) writes:
  627. >In article <2q5m97$4dv@hermes.fwi.uva.nl>, zee@fwi.uva.nl (Daniel vd Zee)
  628. >writes:
  629. >>> How about non-US students, are the pricing and the distributor the same and
  630. >do i have to get some kind of internalional student card to order?
  631.  
  632. >I do not know if we have  or do not have any  international educational
  633. >discounts 
  634.  
  635. Yes you do. It was no problem getting the Ed. Discount from Switzerland.
  636.  
  637. >All others,   BookMasters
  638.  
  639. >                       Fax No.:   1-419-281-6883
  640.  
  641. I got my copy of CodeWarrior from BookMasters. All I had to do was to fax
  642. them a copy of my Student ID and my credit card number. They messed up
  643. the reply to my first fax, but once I had sent the order, I got CW within
  644. 4 or 5 working days... well done, BookMasters!
  645.  
  646. Matthias
  647.  
  648. - ---
  649. Matthias Neeracher                                      neeri@iis.ee.ethz.ch
  650.   "Do not mess with any jumper you do not know about even if it is labeled
  651.    SEX and FREE BEER" -- Dave Haynie
  652.  
  653. ---------------------------
  654.  
  655. >From mpcline@cats.ucsc.edu (Matthew Paul Cline)
  656. Subject: How to write a bullet-proof lib?
  657. Date: 1 May 1994 23:35:06 GMT
  658. Organization: University of California, Santa Cruz
  659.  
  660.  
  661.     I am writing a library for the Mac, and would like it to be
  662. bullet-proof.  When I say bullet proof, I'm using the term in a paranoid
  663. way: if a customer calls up and complains that he/she can't use it to
  664. make a desktop accessory, I can't say "Well, Apple recommends against
  665. making a desktop accessory"; thus, I am not using any global variables
  666. in the library (the only thing I know programming a desktop accessory).
  667. Given my level of paranoia, is it possible to make a bullet-proof
  668. library?  Or can I just get cloose to bullet-proof?  Any help would be
  669. appreciated.
  670.  
  671. P.S.: Am I being paranoid, or is this the way you should go about
  672. making a library?
  673. -- 
  674. X-phile, GATB               Have you hugged your shoggoth today?
  675. GE d? p c++(+++) l++ u++ e+ m+ s/- n+(-) h+ f !g w+ t+ r y+
  676.  
  677. +++++++++++++++++++++++++++
  678.  
  679. >From Matt Slot <fprefect@engin.umich.edu>
  680. Date: 2 May 1994 07:15:30 GMT
  681. Organization: University of Michigan
  682.  
  683. Matthew Paul Cline, mpcline@cats.ucsc.edu writes:
  684.  
  685. >P.S.: Am I being paranoid, or is this the way you should go about
  686. >making a library?
  687.  
  688. I dont think its paranoid to put something out that you feel is stable
  689. enough for others to want to use. If I get a library that I think
  690. isn't of good quality or has some bugs in it, I dont feel comfortable
  691. putting it into my own software.
  692.  
  693. When I wrote my Gamma Libs, I tried to test it on as many computers
  694. as I could and make it work for the widest audience possible. These
  695. are the things I learned:
  696.  
  697.     * Use simple interfaces and explain them well enough that others
  698.       can use them easily. Calling a function with wrong information
  699.       is an easy way to make anything barf.
  700.       
  701.     * Comment the rest of your code (if provided) so users can see
  702.       what you are trying to do and can make improvments/changes as
  703.       fits their needs. (And bug feedback is much easier too)
  704.       
  705.     * Use the best programming styles and follow the books, technotes
  706.       and advice you can find to make the software as compatible for
  707.       future versions.
  708.       
  709.     * Use Gestalt and other calls make sure you are able to run in
  710.       a given environment and that your memory calls succeed. 
  711.       Returning error codes is very important.
  712.       
  713.     * Try it out in a test app (making a demo program with source is
  714.       really nice), and run it with various system configurations
  715.       and extensions. Clearly define a minimum system that you require,
  716.       such as Mac Plus, System 6 or 7, or Color QD.
  717.       
  718.     * Run it with heap scrambling and Even Better Bus Error. A user
  719.       trying to use software with my library complained that EBBE
  720.       flagged it... and it helped me to clean up some skanky pointer
  721.       arithmetic.
  722.       
  723.     * Look for testers who will give you feedback before you make
  724.       the libs public... so you dont get your lib branded before it
  725.       gets popular. 
  726.       
  727.     * Beg for programmer and user feedback, and try to work with others
  728.       who come to you with odd problems.
  729.       
  730. Hope this helps... good luck with your library. 
  731.  
  732. Matt
  733.  
  734. +++++++++++++++++++++++++++
  735.  
  736. >From gurgle@netcom.com (Pete Gontier)
  737. Date: Mon, 2 May 1994 07:01:34 GMT
  738. Organization: cellular
  739.  
  740. mpcline@cats.ucsc.edu (Matthew Paul Cline) writes:
  741.  
  742. >I am writing a library for the Mac, and would like it to be
  743. >bullet-proof. ...thus, I am not using any global variables in the
  744. >library (the only thing I know programming a desktop accessory).
  745.  
  746. It depends on what your library does, of course; I hope you're allowed
  747. to post that so we can consider it. But, in general, you'll have to be
  748. careful about some other things as well as global variables. If your
  749. library is bigger than 32K, that's as bad as having globals, because any
  750. number of segments greater than one causes many of the same problems as
  751. global variables. Also be careful about calls which assume a valid A5
  752. world. Many QuickDraw calls, for example, assume they own the A5 world.
  753.  
  754. One alternative which takes care of many problems is to provide two
  755. copies of the library, one for A5-based projects (apps) and the other
  756. for A4-based projects (everything else). Of course, under MPW, there is
  757. no such thing as a code resource which has global variables, so even a
  758. separate A4-based lib will not help you there, so it is better to avoid
  759. globals altogether.
  760.  
  761. >P.S.: Am I being paranoid, or is this the way you should go about
  762. >making a library?
  763.  
  764. Be paranoid. Be very very paranoid. :-)
  765.  
  766. As long as you understand low-level Mac programming, and as long as your
  767. boss is happy with the notion of a reasonable beta period, you should be
  768. OK. Your testers may not find bugs in your code, but they can probably
  769. be counted on to have problems linking your library into their projects,
  770. even if you do everything right! :-) Resolving any linking problems they
  771. have which are actually your fault won't be half as nasty as any one bug
  772. hunt.
  773. -- 
  774.  Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
  775.  
  776.  "Reality is 50 million polygons per second." -- Alvy Ray Smith
  777.  
  778. +++++++++++++++++++++++++++
  779.  
  780. >From d88-jwa@dront.nada.kth.se (Jon Wdtte)
  781. Date: 2 May 1994 08:50:58 GMT
  782. Organization: The Royal Institute of Technology
  783.  
  784. In <2q29ai$hcl@lastactionhero.rs.itd.umich.edu> Matt Slot <fprefect@engin.umich.edu> writes:
  785.  
  786. >    * Use simple interfaces and explain them well enough that others
  787. >      can use them easily. Calling a function with wrong information
  788. >      is an easy way to make anything barf.
  789.  
  790. Have a debugging version of your library, which calls
  791. Debugger() when it detects inconsistent data, parameters
  792. out of range or unexpected return values BEFORE returning
  793. them. A simple ASSERT() macro will do this!
  794.  
  795. >    * Use Gestalt and other calls make sure you are able to run in
  796. >      a given environment and that your memory calls succeed. 
  797. >      Returning error codes is very important.
  798.  
  799. Actually, the library probably shouldn't call Gestalt. Maybe a
  800. separate little utility rouinte, in source, which just made
  801. sure that everything's OK and returned a Boolean. Let the user's
  802. code do the checking, for instance by calling your separate
  803. utility routine.
  804.  
  805. >    * Beg for programmer and user feedback, and try to work with others
  806. >      who come to you with odd problems.
  807.  
  808. Especially: be responsive, and take every complaint seriously.
  809. -- 
  810.  -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe (on a Swedish scale) --
  811.  
  812.    There's no problem that can't be solved using brute-force algorithms
  813.    and a sufficiently fast computer. Ergo, buy more hardware.    (NOT!)
  814.  
  815. +++++++++++++++++++++++++++
  816.  
  817. >From mpcline@cats.ucsc.edu (Matthew Paul Cline)
  818. Date: 2 May 1994 17:56:24 GMT
  819. Organization: University of California, Santa Cruz
  820.  
  821.  
  822. In <gurgleCp5y6M.4KL@netcom.com> gurgle@netcom.com (Pete Gontier) writes:
  823.  
  824. >mpcline@cats.ucsc.edu (Matthew Paul Cline) writes:
  825.  
  826. >>I am writing a library for the Mac, and would like it to be
  827. >>bullet-proof. ...thus, I am not using any global variables in the
  828. >>library (the only thing I know programming a desktop accessory).
  829.  
  830. >It depends on what your library does, of course; I hope you're allowed
  831. >to post that so we can consider it.
  832.  
  833. It uses the Novell socket library on top of MacTCP.
  834.  
  835. >                                     But, in general, you'll have to be
  836. >careful about some other things as well as global variables.
  837.  
  838. Since this is a port of an already existing library, I'm replacing all
  839. global variables with static variables local to one file, and then
  840. using get_GLOBAL() and set_GLOBAL() type function calls.  Does that
  841. still have the problem of globals variables?  What about staic variables
  842. within a procedure?
  843.  
  844. >                                                              If your
  845. >library is bigger than 32K, that's as bad as having globals, because any
  846. >number of segments greater than one causes many of the same problems as
  847. >global variables.
  848.  
  849. I was planning on either using pluged-in code resources or using ASLM.
  850. Would this also be bad for a library?
  851.  
  852. [snip]
  853.  
  854. >As long as you understand low-level Mac programming.
  855.  
  856. Hmmm, might have a problem here: I'm very new to the Mac.  My boss
  857. basically hired me and said: "Here, go and learn everything you need to
  858. know about the Mac and port our library to it."  Do you have any advice
  859. on taking a crash course on low-level Mac programming?  Thanks in
  860. advance.
  861. -- 
  862. X-phile, GATB               Have you hugged your shoggoth today?
  863. GE d? p c++(+++) l++ u++ e+ m+ s/- n+(-) h+ f !g w+ t+ r y+
  864.  
  865. +++++++++++++++++++++++++++
  866.  
  867. >From rmah@panix.com (Robert S. Mah)
  868. Date: Mon, 02 May 1994 19:25:06 -0500
  869. Organization: One Step Beyond
  870.  
  871. mpcline@cats.ucsc.edu (Matthew Paul Cline) wrote:
  872.  
  873. > Since this is a port of an already existing library, I'm replacing all
  874. > global variables with static variables local to one file, and then
  875. > using get_GLOBAL() and set_GLOBAL() type function calls.  Does that
  876. > still have the problem of globals variables?  What about staic variables
  877. > within a procedure?
  878.  
  879. Using statics will prevent name space pollution but the variables 
  880. themselves are still referenced like globals.  That is they are accessed 
  881. via offsets from register a5.  This will fall down if the code is being 
  882. used in drivers, extensions or anything without a proper a5 world.
  883.  
  884. One option is to build two sets of libraries, one compiled using a5 
  885. offsets and another using a4 offsets.  This is the technique used by
  886. Symantec for their ANSI libraries, for example.
  887.  
  888. Cheers,
  889. Rob
  890. ___________________________________________________________________________
  891. Robert S. Mah  -=-  One Step Beyond  -=-  212-947-6507  -=-  rmah@panix.com
  892.  
  893. +++++++++++++++++++++++++++
  894.  
  895. >From gurgle@netcom.com (Pete Gontier)
  896. Date: Tue, 3 May 1994 18:40:42 GMT
  897. Organization: cellular
  898.  
  899. mpcline@cats.ucsc.edu (Matthew Paul Cline) writes:
  900.  
  901. >It uses the Novell socket library on top of MacTCP.
  902.  
  903. OK, if you are porting, then you do need to be careful the code you are
  904. porting doesn't use any global variables or use the 'static' modifier
  905. for variables declared inside functions. It's possible to let the code
  906. do these things, depending on the compiler in use, but you do need to be
  907. aware of it so you can make sure it works -- or document how to make it
  908. work, if it needs to be the caller's responsibility.
  909.  
  910. >Since this is a port of an already existing library, I'm replacing all
  911. >global variables with static variables local to one file, and then
  912. >using get_GLOBAL() and set_GLOBAL() type function calls. Does that
  913. >still have the problem of globals variables?
  914.  
  915. Yes. What your routines are doing is hiding the globals, to a certain
  916. extent, and that's marginally good in terms of maintainability. But
  917. the machine doesn't care how maintainable your code is. :-) The hidden
  918. globals are still globals in terms of where they are stored in memory
  919. at run-time, that is at offsets from register A5 (apps) or register A4
  920. (everything else).
  921.  
  922. >What about staic variables within a procedure?
  923.  
  924. Same problem, as I said above.
  925.  
  926. >>If your library is bigger than 32K, that's as bad as having globals,
  927. >>because any number of segments greater than one causes many of the
  928. >>same problems as global variables.
  929.  
  930. >I was planning on either using pluged-in code resources or using ASLM.
  931. >Would this also be bad for a library?
  932.  
  933. I don't know much about ASLM except that it's not available in a fairly
  934. large subset of installed Systems. And last I heard, it required MPW
  935. C++, but that restriction has probably gone away by now.
  936.  
  937. But, if you are stuffing this code into a code resource, I can tell you
  938. you won't have to concern yourself with two different versions of a
  939. linkable library file any more. Your project will be A4-based, and you
  940. can look up and understand the use of <SetUpA4.h> and be done with it.
  941. You can also have code larger than 32K without much difficulty.
  942.  
  943. There are a couple of drawbacks to a code resource, though.
  944.  
  945. First, there's the fact that if you want more than one entry point,
  946. you must create them yourself. In other words, the calling program
  947. should probably call the code resource's main entry point with the
  948. understanding that all that will result is a list of other entry points
  949. into the code resource. I'm basically talking about a structure full of
  950. function pointers here.
  951.  
  952. You will also have to write *another* library to be linked into programs
  953. in order to avoid the chore of documenting for others how to call your
  954. external code resource. (Believe me, writing this extra library is much
  955. better than writing a document about code resources, because people will
  956. call you for tech support no matter how good your doc is.) Fortunately,
  957. this extra library will probably be simple enough that you can include
  958. source code instead of a library file without revealing any trade
  959. secrets.
  960.  
  961. TAKE-HOME MESSAGE:
  962.  
  963. I think your best bet is to do linkable libraries. They involve the
  964. fewest technical headaches. You'll actually have to do three of them
  965. (one for A5, one for A4, and one for PowerPC), but once you have done
  966. one, the rest will follow pretty easily. You'll also have a 32K limit on
  967. each library file, but you can always do more than one library file for
  968. each kind of project.
  969.  
  970. >>As long as you understand low-level Mac programming...
  971.  
  972. >Hmmm, might have a problem here: I'm very new to the Mac. My boss
  973. >basically hired me and said: "Here, go and learn everything you need to
  974. >know about the Mac and port our library to it."
  975.  
  976. Tell your boss right away that aspects of this project are beyond your
  977. field of expertise. The Macintosh issues are fairly simple for a very
  978. experienced Mac programmer, but for someone new to the Mac, they can
  979. be really ugly and take a lot more time than you would like. It will
  980. be especially frustrating if you know all there is to know about the
  981. networking aspects of the job and are constrained only by the Mac
  982. aspects, because your boss may not understand that. If you tell her now,
  983. you'll be able to plan ahead.
  984.  
  985. >Do you have any advice on taking a crash course on low-level Mac
  986. >programming?
  987.  
  988. Of course, if there is no way to tell your boss, then you have just
  989. embarked on the best low-level Mac programming course there is!
  990. Experience: 12 units. Unfortunately, it's also the *only* course. Good
  991. luck, and the net will be here when you need it. :-)
  992. -- 
  993.  Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
  994.  
  995.  You thought Obfuscated C was confusing? Wait for Obfuscated C++!
  996.  
  997. ---------------------------
  998.  
  999. >From adamnash@Xenon.Stanford.EDU (Adam Nash)
  1000. Subject: PixMap to mask
  1001. Date: 2 May 1994 06:28:05 GMT
  1002. Organization: Computer Science Department, Stanford University.
  1003.  
  1004.  
  1005. This may be really simple, but I wanted to check with the net first
  1006. in case this has been done a better way.  I'm converting a PixMap
  1007. (from a Pict) into a Mask for that item.  Now, if you call BitMapToRegion
  1008. you get a nasty speckle because, it translates anything more than "half
  1009. white" to white, when I want every non-white pixel to be black.
  1010. So, I was going to roll my own PixMapToMask, which went through the
  1011. pixel data and every time it hit a value > 0, it would put a black pixel in
  1012. a temporary BitMap, then call BitMapToRgn.
  1013.  
  1014. What do you think, all you sprite and offscreen gurus out there?
  1015.  
  1016. -Adam
  1017.  
  1018. +++++++++++++++++++++++++++
  1019.  
  1020. >From daniel@unx.al.alcoa.com (David L. Daniel)
  1021. Date: 2 May 1994 13:51:41 GMT
  1022. Organization: Alcoa
  1023.  
  1024. In article <2q26hl$f72@Times.Stanford.EDU>, adamnash@Xenon.Stanford.EDU
  1025. (Adam Nash) wrote:
  1026. > So, I was going to roll my own PixMapToMask, which went through the
  1027. > pixel data and every time it hit a value > 0, it would put a black pixel in
  1028. > a temporary BitMap, then call BitMapToRgn.
  1029.  
  1030. You could try using SeedCFill and CalcCMask, but I have had lots of trouble
  1031. using these - not just understanding them (which can be difficult), but
  1032. also with inconsistent results.  Others have expressed similar problems.
  1033. Here is some code that I use to do what you want.  No guarantees, but it
  1034. seems to work for me.  The argument "ignoreColor" is the pixel value
  1035. that you want to be ignored in creating a mask.  Good luck.
  1036.  
  1037.  
  1038. /* ######################################################################
  1039. */
  1040. /* Make a mask for a PixMap (put it into a BitMap). */
  1041.  
  1042. void MakeMask(unsigned char ignoreColor, PixMapHandle pmHndl, BitMapHandle
  1043. bmHndl)
  1044. {
  1045.     short            i,j,k,bmBytes,pmBytes,bmBit,cols,rows;
  1046.     unsigned char    *bmPtr,*pmPtr;
  1047.     
  1048.  
  1049.     cols = (**pmHndl).bounds.right - (**pmHndl).bounds.left;
  1050.     rows = (**pmHndl).bounds.bottom - (**pmHndl).bounds.top;
  1051.  
  1052.     /*if the image rectangles are not the same dimensions, then return an
  1053. error*/
  1054.     if( ( cols != ((**bmHndl).bounds.right - (**bmHndl).bounds.left))
  1055.         || ( rows != ((**bmHndl).bounds.bottom - (**bmHndl).bounds.top)) )
  1056.         return;
  1057.     
  1058.     /*Get the number of rowBytes for each image*/
  1059.     pmBytes = (0x1fff & (**pmHndl).rowBytes);
  1060.     bmBytes = (**bmHndl).rowBytes;
  1061.  
  1062.     /*Determine the starting address for the rectangles in each image*/
  1063.     pmPtr=(unsigned char*) ((**pmHndl).baseAddr +
  1064. pmBytes*(**pmHndl).bounds.top + (**pmHndl).bounds.left);
  1065.     bmPtr=(unsigned char*) ((**bmHndl).baseAddr +
  1066. bmBytes*(**bmHndl).bounds.top + 
  1067.             (short)((**bmHndl).bounds.left / 8) );
  1068.  
  1069.     /*Get the number of bytes to increment at the end of a row for each
  1070. image*/
  1071.     bmBit = (**bmHndl).bounds.left % 8;        /*the starting bit for the bitmap*/
  1072.     pmBytes -= cols;
  1073.     bmBytes -= (short)( (cols + bmBit - 1) / 8);
  1074.     
  1075.     bmBit = 7 - bmBit;    /*image bits are reversed from the order they are
  1076. counted*/
  1077.     
  1078.     /*Loop through each row of the images*/
  1079.     for(i=0; i<rows; i++, pmPtr+=pmBytes, bmPtr+=bmBytes) {
  1080.     
  1081.         /*Loop through each column of the images*/
  1082.         for(j=0, k=bmBit; j<cols; j++, pmPtr++, k--) {
  1083.  
  1084.             /*check and set the current bitmap bit, and the bitmap pointer*/
  1085.             if(k == -1) {
  1086.                 bmPtr++;
  1087.                 k = 7;
  1088.             }
  1089.  
  1090.             /*Check that the current PixMap pixel doesn't match the ignored color*/
  1091.             if(*pmPtr != ignoreColor) {
  1092.                 *bmPtr |= (1 << k);
  1093.             } else {
  1094.                 *bmPtr &= (0xff ^ (1 << k));
  1095.             }
  1096.         }
  1097.     }
  1098. }/*MakeMask*/
  1099.  
  1100.  
  1101. /* ######################################################################
  1102. */
  1103.  
  1104.  
  1105. -David Daniel
  1106. daniel@unx.al.alcoa.com
  1107. #######################
  1108. This random sign-off was generated by a statistician.
  1109. #######################
  1110.  
  1111. ---------------------------
  1112.  
  1113. >From Dwayne Knowles <dwayne@bagend.nacjack.gen.nz>
  1114. Subject: Posting an event to another application?
  1115. Date: Tue, 03 May 94 01:23:48 +1200
  1116. Organization: Society for the Prevention of Cruelty to Hobbits
  1117.  
  1118.  
  1119. Is there a way to post an event to another application - eg. a keydown 
  1120. event, without writing my own version of postEvent? I realise this is 
  1121. probably going to break with future system releases and is very uncool in 
  1122. general but I would like to be able to control an application remotely that 
  1123. isn't scriptable or anything. Is this possible?
  1124.  
  1125. Thanks.
  1126.  
  1127. --
  1128.  
  1129. +++++++++++++++++++++++++++
  1130.  
  1131. >From mkb@remarque.berkeley.edu (Mike Brodhead)
  1132. Date: 2 May 1994 17:47:02 GMT
  1133. Organization: STEDT Project, Dept. o' Linguistics, UCBerkeley
  1134.  
  1135. In article <94050301234800677@bagend.nacjack.gen.nz>, Dwayne Knowles
  1136. <dwayne@bagend.nacjack.gen.nz> wrote:
  1137.  
  1138. > Is there a way to post an event to another application - eg. a keydown 
  1139. > event, without writing my own version of postEvent? I realise this is 
  1140. > probably going to break with future system releases and is very uncool in 
  1141. > general but I would like to be able to control an application remotely that 
  1142. > isn't scriptable or anything. Is this possible?
  1143. > Thanks.
  1144. > --
  1145.  
  1146. I doubt you could do this easily from an app, but an INIT can surely
  1147. do it.  Witness QuickKeys.  In fact, you would probably be better off
  1148. installing QK on the machine and sending Apple Events to QK than doing
  1149. everything from scratch.  (I'm asuming this is for in-house use.)
  1150.  
  1151. If you want to code it yourself, you'll have to use the process manager
  1152. to check that the apropriate app is in the foreground before calling
  1153. PostEvent().  You could even force the app to the foreground.
  1154.  
  1155. __________________________________________________________________________
  1156. Mike Brodhead   (New! .sig now 33% shorter!)   <mkb@remarque.berkeley.edu> 
  1157.                     
  1158.  
  1159. +++++++++++++++++++++++++++
  1160.  
  1161. >From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
  1162. Date: Tue, 3 May 1994 14:15:05 +1200 (NZST)
  1163. Organization: (none)
  1164.  
  1165. Dwayne Knowles <dwayne@bagend.nacjack.gen.nz> writes:
  1166. > Is there a way to post an event to another application - eg. a keydown 
  1167. > event, without writing my own version of postEvent? I realise this is 
  1168. > probably going to break with future system releases and is very uncool in 
  1169. > general but I would like to be able to control an application remotely that 
  1170. > isn't scriptable or anything. Is this possible?
  1171.  
  1172. There is only one queue for mouse-downs, keydowns etc, and the frontmost
  1173. application always gets them -- if you want to post events for a particular
  1174. application then move it to the front (using the process manager) and then
  1175. use PostEvent in the normal way...
  1176.  
  1177. +++++++++++++++++++++++++++
  1178.  
  1179. >From Dwayne Knowles <dwayne@bagend.nacjack.gen.nz>
  1180. Date: Thu, 05 May 94 01:46:59 +1200
  1181. Organization: Society for the Prevention of Cruelty to Hobbits
  1182.  
  1183.  
  1184. In article <mkb-020594104417@interzone.hip.berkeley.edu>, Mike Brodhead 
  1185. writes:
  1186.  
  1187. > I doubt you could do this easily from an app, but an INIT can surely
  1188. > do it.  Witness QuickKeys.  In fact, you would probably be better off
  1189. > installing QK on the machine and sending Apple Events to QK than doing
  1190. > everything from scratch.  (I'm asuming this is for in-house use.)
  1191. > If you want to code it yourself, you'll have to use the process manager
  1192. > to check that the apropriate app is in the foreground before calling
  1193. > PostEvent().  You could even force the app to the foreground.
  1194.  
  1195. There are several problems with this however. The receiving app has to be 
  1196. forced into the foreground, and more importantly, postEvent doesn't let me 
  1197. post a keyDown event with the command key as a modifier - eg. post a menu 
  1198. key event.
  1199.  
  1200. Unfortunately I don't have Quickeys.
  1201.  
  1202. --
  1203.  
  1204. +++++++++++++++++++++++++++
  1205.  
  1206. >From jeremyr@dcs.qmw.ac.uk (Jeremy Roussak;Guest of Distributed Systems Lab)
  1207. Date: Wed, 4 May 1994 21:04:28 GMT
  1208. Organization: Computer Science Dept, QMW, University of London
  1209.  
  1210. >> If you want to code it yourself, you'll have to use the process manager
  1211. >> to check that the apropriate app is in the foreground before calling
  1212. >> PostEvent().  You could even force the app to the foreground.
  1213.  
  1214. >There are several problems with this however. The receiving app has to be
  1215. >forced into the foreground, and more importantly, postEvent doesn't let me
  1216. >post a keyDown event with the command key as a modifier - eg. post a menu
  1217. >key event.
  1218.  
  1219. There's no way around forcing the app to the front, since, as
  1220. has been pointed out before, there's only one event queue and
  1221. all the events in it go to the frontmost app.
  1222.  
  1223. However, you can easily post an event with a specific set of
  1224. modifiers: use PPostEvent, which returns a pointer to the queue
  1225. element, and then modify the modifiers field.
  1226.  
  1227. Jeremy
  1228.  
  1229. +++++++++++++++++++++++++++
  1230.  
  1231. >From mkb@remarque.berkeley.edu (Mike Brodhead)
  1232. Date: 5 May 1994 01:56:34 GMT
  1233. Organization: STEDT Project, Dept. o' Linguistics, UCBerkeley
  1234.  
  1235. In article <CpAqJJ.Jpz@dcs.qmw.ac.uk>, jeremyr@dcs.qmw.ac.uk (Jeremy
  1236. Roussak;Guest of Distributed Systems Lab) wrote:
  1237.  
  1238. > However, you can easily post an event with a specific set of
  1239. > modifiers: use PPostEvent, which returns a pointer to the queue
  1240. > element, and then modify the modifiers field.
  1241.  
  1242. This is true.  Still, if QuickKeys will do the job it is probably a
  1243. lot more cost effective to use it.  Divide the cost of QK by the number
  1244. of hours you expect to spend coding.  (Don't forget Hofstadter's law :)
  1245.  
  1246. What is your desired end result?  What will your code accomplish?
  1247. Who will use it?
  1248.  
  1249. __________________________________________________________________________
  1250. Mike Brodhead   (New! .sig now 33% shorter!)   <mkb@remarque.berkeley.edu> 
  1251.                     
  1252.  
  1253. +++++++++++++++++++++++++++
  1254.  
  1255. >From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
  1256. Date: Thu, 5 May 1994 18:36:54 +1200 (NZST)
  1257. Organization: (none)
  1258.  
  1259. Dwayne Knowles <dwayne@bagend.nacjack.gen.nz> writes:
  1260. > > If you want to code it yourself, you'll have to use the process manager
  1261. > > to check that the apropriate app is in the foreground before calling
  1262. > > PostEvent().  You could even force the app to the foreground.
  1263. > There are several problems with this however. The receiving app has to be 
  1264. > forced into the foreground, and more importantly, postEvent doesn't let me 
  1265. > post a keyDown event with the command key as a modifier - eg. post a menu 
  1266. > vkey event.
  1267.  
  1268. No, that's no problem -- you use PPostEvent, which returns a pointer to the
  1269. newly posted event queue element , and you can them diddle the modifiers.
  1270. Just don't call WaitNextEvent first :-)
  1271.  
  1272. -- Bruce
  1273.  
  1274. +++++++++++++++++++++++++++
  1275.  
  1276. >From chris-b@cs.aukuni.ac.nz (Christopher David Burns)
  1277. Date: 5 May 1994 11:22:45 GMT
  1278. Organization: University of Auckland
  1279.  
  1280. Bruce@hoult.actrix.gen.nz (Bruce Hoult) writes:
  1281.  
  1282. >No, that's no problem -- you use PPostEvent, which returns a pointer to the
  1283. >newly posted event queue element , and you can them diddle the modifiers.
  1284. >Just don't call WaitNextEvent first :-)
  1285.  
  1286. Why don't you use the jGNEFilter mechanism instead of PPostEvent(). Simply
  1287. write an app that installs a jGNEFilter. This proc gets called just before
  1288. GetNextEvent() or WaitNextEvent() return. It has access to the boolean
  1289. result and the event record about to be returned. You can simply call
  1290. SetFrontProcess() and in your proc check curAppName (or maybe compare
  1291. GetFrontProcess() with the process you're interested in). When you find
  1292. that the right app is switched in, you can change the first null event to
  1293. a mouseDown (or whatever).
  1294.  
  1295. Simple. (I assume that the jGNEFilter is called on null events).
  1296.  
  1297. Give me a call if you want some code.
  1298.  
  1299. Cheers,
  1300.  
  1301. Chris B
  1302. - ---------------------------------------------------------------------
  1303. NewZealand:AucklandUniversity:ComputerScience:HyperMediaUnit:ChrisBurns
  1304. Internet:chris-b@cs.aukuni.ac.nz
  1305. Phone: +64 9 373-7599 x5602  Fax: +64 9 373-7453
  1306.  
  1307.  
  1308. +++++++++++++++++++++++++++
  1309.  
  1310. >From zellers@berksys.com (Steve Zellers)
  1311. Date: 5 May 1994 21:17:01 GMT
  1312. Organization: Berkeley Systems, Inc.
  1313.  
  1314. In article <94050501465900688@bagend.nacjack.gen.nz>, Dwayne Knowles
  1315. <dwayne@bagend.nacjack.gen.nz> wrote:
  1316.  
  1317. > postEvent doesn't let me 
  1318. > post a keyDown event with the command key as a modifier - eg. post a menu 
  1319. > key event.
  1320.  
  1321. Check out PPostEvent.
  1322.  
  1323. Consider an INIT/background app combination.
  1324.  
  1325. -- 
  1326. Sr. Software Engineer
  1327. Berkeley Systems, Inc.
  1328.  
  1329. +++++++++++++++++++++++++++
  1330.  
  1331. >From jedavis@CS.Stanford.EDU (James Edward Davis)
  1332. Date: 6 May 1994 14:20:57 -0500
  1333. Organization: UTexas Mail-to-News Gateway
  1334.  
  1335. References: <94050301234800677@bagend.nacjack.gen.nz>
  1336.  
  1337. Dwayne Knowles <dwayne@bagend.nacjack.gen.nz> writes:
  1338.  
  1339. >Is there a way to post an event to another application - eg. a keydown 
  1340. >event, without writing my own version of postEvent? I realise this is 
  1341. >probably going to break with future system releases and is very uncool in 
  1342. >general but I would like to be able to control an application remotely that 
  1343. >isn't scriptable or anything. Is this possible?
  1344.  
  1345. Well, the simple answer is use AutoType. An OSAX I worte that lets 
  1346. AppleScript send keyDowns with modifiers to other apps, so you can script 
  1347. non-scriptable applications. I use ppostevent essentially like others
  1348. in this thread described. Available at fine ftp sites everywhere.
  1349.  
  1350. -James Davis : jedavis@cs.stanford.edu
  1351.  
  1352.  
  1353.  
  1354. +++++++++++++++++++++++++++
  1355.  
  1356. >From walkerj@math.scarolina.edu (Jim Walker)
  1357. Date: 4 May 1994 18:21:50 GMT
  1358. Organization: University of South Carolina - Columbia - Computer Science
  1359.  
  1360. Dwayne Knowles <dwayne@bagend.nacjack.gen.nz> writes:
  1361.  
  1362. (stuff deleted)
  1363. >There are several problems with this however. The receiving app has to be 
  1364. >forced into the foreground, and more importantly, postEvent doesn't let me 
  1365. >post a keyDown event with the command key as a modifier - eg. post a menu 
  1366. >key event.
  1367.  
  1368. PPostEvent (not a typo!) does allow you to post a keyDown event with
  1369. modifiers.
  1370. --
  1371.  
  1372.  -- Jim Walker  USC Dept. of Math.  walkerj@math.scarolina.edu
  1373.  
  1374. ---------------------------
  1375.  
  1376. >From dnebing@bgsu.edu (  Mr. Neb)
  1377. Subject: Shared memory...
  1378. Date: 28 Apr 1994 02:04:11 GMT
  1379. Organization: Bowling Green State University
  1380.  
  1381.   Here's a good one...
  1382.  
  1383.   I have a component which can be opened multiple times.  I don't want
  1384. the components to have to allocate the same memory each time (they
  1385. all share a common resource (a picture) that I don't want multiple
  1386. copies of floating around in memory).  Anyone have a good solution
  1387. for setting up a shared buffer between the components?
  1388.  
  1389. Thanks in advance,
  1390.  
  1391. Dave Nebinger
  1392.  
  1393. ============================================================
  1394. Dave Nebinger                    dnebing@andy.bgsu.edu
  1395. Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1396. Bowling Green State University   dnebing@bgsuopie (bitnet)
  1397. Bowling Green, OH 43403          #include <std_disclaimer.h>
  1398.  
  1399.              *THE* alt.sources.mac supporter!
  1400.  
  1401. -- 
  1402. ============================================================
  1403. Dave Nebinger                    dnebing@andy.bgsu.edu
  1404. Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1405. Bowling Green State University   dnebing@bgsuopie (bitnet)
  1406.  
  1407. +++++++++++++++++++++++++++
  1408.  
  1409. >From devon_hubbard@taligent.com (Devon Hubbard)
  1410. Date: Thu, 28 Apr 1994 17:35:31 GMT
  1411. Organization: Taligent, Inc.
  1412.  
  1413. In article <2pn5ir$rcm@falcon.bgsu.edu>, dnebing@bgsu.edu (  Mr. Neb)
  1414. wrote:
  1415.  
  1416. >   Here's a good one...
  1417. >   I have a component which can be opened multiple times.  I don't want
  1418. > the components to have to allocate the same memory each time (they
  1419. > all share a common resource (a picture) that I don't want multiple
  1420. > copies of floating around in memory).  Anyone have a good solution
  1421. > for setting up a shared buffer between the components?
  1422. > Thanks in advance,
  1423. > Dave Nebinger
  1424. > ============================================================
  1425. > Dave Nebinger                    dnebing@andy.bgsu.edu
  1426. > Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1427. > Bowling Green State University   dnebing@bgsuopie (bitnet)
  1428. > Bowling Green, OH 43403          #include <std_disclaimer.h>
  1429. >              *THE* alt.sources.mac supporter!
  1430.  
  1431. Install your own _Gestalt selector.  Whichever process is first, it
  1432. installs the selector.  The other checks for it's existance.  If there, the
  1433. selector returns the address of a struct that contains whatever you want
  1434. (i.e. addresses of shared memory blocks).  Any of your processes can get to
  1435. it.  If you're starting and quitting apps, allocate the memory in the
  1436. system heap so it'll stick around.  Just be friendly and clean up the
  1437. memory when everything's done.
  1438.  
  1439. dEVoN
  1440.  
  1441. - ------------------------------------------------------------------------
  1442. Devon Hubbard                                                Silicon Pilot
  1443. devon_hubbard@taligent.com                                   Taligent, Inc
  1444.  
  1445. +++++++++++++++++++++++++++
  1446.  
  1447. >From sblack@us.oracle.com (Steven T. Black)
  1448. Date: 28 Apr 94 22:15:44 GMT
  1449. Organization: Oracle Corporation
  1450.  
  1451. In article <devon_hubbard-280494093531@saucer.taligent.com>
  1452. devon_hubbard@taligent.com (Devon Hubbard) writes:
  1453.  
  1454. > In article <2pn5ir$rcm@falcon.bgsu.edu>, dnebing@bgsu.edu (  Mr. Neb)
  1455. > wrote:
  1456. > >   Here's a good one...
  1457. > > 
  1458. > >   I have a component which can be opened multiple times.  I don't want
  1459. > > the components to have to allocate the same memory each time (they
  1460. > > all share a common resource (a picture) that I don't want multiple
  1461. > > copies of floating around in memory).  Anyone have a good solution
  1462. > > for setting up a shared buffer between the components?
  1463. > > 
  1464. > > Thanks in advance,
  1465. > > 
  1466. > > Dave Nebinger
  1467. > > 
  1468. > > ============================================================
  1469. > > Dave Nebinger                    dnebing@andy.bgsu.edu
  1470. > > Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1471. > > Bowling Green State University   dnebing@bgsuopie (bitnet)
  1472. > > Bowling Green, OH 43403          #include <std_disclaimer.h>
  1473. > > 
  1474. > >              *THE* alt.sources.mac supporter!
  1475. > > 
  1476. > Install your own _Gestalt selector.  Whichever process is first, it
  1477. > installs the selector.  The other checks for it's existance.  If there, the
  1478. > selector returns the address of a struct that contains whatever you want
  1479. > (i.e. addresses of shared memory blocks).  Any of your processes can get to
  1480. > it.  If you're starting and quitting apps, allocate the memory in the
  1481. > system heap so it'll stick around.  Just be friendly and clean up the
  1482. > memory when everything's done.
  1483. > dEVoN
  1484. > --------------------------------------------------------------------------
  1485. > Devon Hubbard                                                Silicon Pilot
  1486. > devon_hubbard@taligent.com                                   Taligent, Inc
  1487.  
  1488. You can also use the ASLM (Shared Library Manager) to store the
  1489. resource in a library, and have a routine that returns the address of
  1490. the PICT.  This has the advantage that the ASLM can monitor how many
  1491. clients are using the PICT, and so won't flush it from memory when the
  1492. original app that called it quits if other apps are still referencing
  1493. it.  It also takes care of flushing it from memory when it is no longer
  1494. needed.
  1495.  
  1496. - ----------------------------------------------------------------------
  1497. --
  1498. Steven T. Black                                     Lead Technical
  1499. Staff
  1500. sblack@us.oracle.com                                Oracle Desktop
  1501. Products
  1502.  
  1503. +++++++++++++++++++++++++++
  1504.  
  1505. >From dnebing@falcon.bgsu.edu.bgsu.edu (  Mr. Neb,217 LSC,3722332,3531532)
  1506. Date: 29 Apr 1994 15:42:56 GMT
  1507. Organization: Bowling Green State University
  1508.  
  1509. sblack@us.oracle.com (Steven T. Black) writes:
  1510. > You can also use the ASLM (Shared Library Manager) to store the
  1511. > resource in a library, and have a routine that returns the address of
  1512. > the PICT.  This has the advantage that the ASLM can monitor how many
  1513. > clients are using the PICT, and so won't flush it from memory when the
  1514. > original app that called it quits if other apps are still referencing
  1515. > it.  It also takes care of flushing it from memory when it is no longer
  1516. > needed.
  1517.  
  1518.   This assumes the following:
  1519.  
  1520.     1.  That somehow you have the ASLM headers and libs necessary to
  1521. do so.
  1522.  
  1523.     2.  That the user has the ASLM or that Apple will give you a
  1524. license to distribute it in your shareware/freeware.
  1525.  
  1526.  
  1527.   I would love to use the ASLM because it would simplify my life
  1528. a great deal.  Currently I am implementing my package as a bunch
  1529. of components because Apple chooses to make me pay for the headers
  1530. and libraries needed to use the ASLM.
  1531.  
  1532.   The way I figure it, if Apple wanted me to use new functionality
  1533. within the system then they would provide the headerws and libs
  1534. necessary to do so.
  1535.  
  1536.   I can't even get the Universal Headers without purchasing a
  1537. major upgrade.
  1538.  
  1539.   Without the necessary headers, my stuff won't use the
  1540. DragMgr, PowerTalk, etc.  So people who use my stuff won't see
  1541. any reason to go buy the components from Apple.  So you tell
  1542. me who is really hurt by charging for these simple development
  1543. products.  Like I was quoted in the latest MacWEEK, I don't
  1544. expect to get the components for free.  But I don't think that
  1545. the headers and libs needed to implement the functionality of
  1546. those components is too much to ask for.
  1547.  
  1548. ============================================================
  1549. Dave Nebinger                    dnebing@andy.bgsu.edu
  1550. Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1551. Bowling Green State University   dnebing@bgsuopie (bitnet)
  1552. Bowling Green, OH 43403          #include <std_disclaimer.h>
  1553.  
  1554.              *THE* alt.sources.mac supporter!
  1555. -- 
  1556. ============================================================
  1557. Dave Nebinger                    dnebing@andy.bgsu.edu
  1558. Network Manager, Biology Dept.   dnebing@opie.bgsu.edu
  1559. Bowling Green State University   dnebing@bgsuopie (bitnet)
  1560.  
  1561. +++++++++++++++++++++++++++
  1562.  
  1563. >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
  1564. Date: 30 Apr 94 15:01:20 +1200
  1565. Organization: University of Waikato, Hamilton, New Zealand
  1566.  
  1567. In article <2pn5ir$rcm@falcon.bgsu.edu>, dnebing@bgsu.edu (  Mr. Neb) writes:
  1568. >
  1569. >   I have a component which can be opened multiple times.  I don't want
  1570. > the components to have to allocate the same memory each time (they
  1571. > all share a common resource (a picture) that I don't want multiple
  1572. > copies of floating around in memory).  Anyone have a good solution
  1573. > for setting up a shared buffer between the components?
  1574.  
  1575. You could use SetComponentRefcon and GetComponentRefcon. The Component Manager
  1576. documentation makes it clear that a component only has a single Refcon value,
  1577. no matter how many instances are open.
  1578.  
  1579. If you want to dispose of the storage when the last instance is closed,
  1580. you can just call CountComponentInstances on yourself in your CloseComponent
  1581. handler. I assume the count isn't decremented until your CloseComponent
  1582. handler returns, in which case the value to check for is 1. If the count
  1583. _is_ decremented before entering your CloseComponent handler, then the value
  1584. to check for is 0.
  1585.  
  1586. Or you could avoid the question and maintain your own reference count...
  1587.  
  1588. Lawrence D'Oliveiro                       fone: +64-7-856-2889
  1589. Info & Tech Services Division              fax: +64-7-838-4066
  1590. University of Waikato            electric mail: ldo@waikato.ac.nz
  1591. Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
  1592.  
  1593. +++++++++++++++++++++++++++
  1594.  
  1595. >From jim_reekes@quickmail.apple.com (Jim Reekes)
  1596. Date: Tue, 3 May 1994 19:56:15 GMT
  1597. Organization: Apple Computer, Inc.
  1598.  
  1599. In article <1994Apr30.150120.28180@waikato.ac.nz>, ldo@waikato.ac.nz
  1600. (Lawrence D'Oliveiro, Waikato University) wrote:
  1601. > In article <2pn5ir$rcm@falcon.bgsu.edu>, dnebing@bgsu.edu (  Mr. Neb) writes:
  1602. > >
  1603. > >   I have a component which can be opened multiple times.  I don't want
  1604. > > the components to have to allocate the same memory each time (they
  1605. > > all share a common resource (a picture) that I don't want multiple
  1606. > > copies of floating around in memory).  Anyone have a good solution
  1607. > > for setting up a shared buffer between the components?
  1608. > You could use SetComponentRefcon and GetComponentRefcon. The Component Manager
  1609. > documentation makes it clear that a component only has a single Refcon value,
  1610. > no matter how many instances are open.
  1611. > If you want to dispose of the storage when the last instance is closed,
  1612. > you can just call CountComponentInstances on yourself in your CloseComponent
  1613. > handler. I assume the count isn't decremented until your CloseComponent
  1614. > handler returns, in which case the value to check for is 1. If the count
  1615. > _is_ decremented before entering your CloseComponent handler, then the value
  1616. > to check for is 0.
  1617. > Or you could avoid the question and maintain your own reference count...
  1618. > Lawrence D'Oliveiro                       fone: +64-7-856-2889
  1619. > Info & Tech Services Division              fax: +64-7-838-4066
  1620. > University of Waikato            electric mail: ldo@waikato.ac.nz
  1621. > Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
  1622.  
  1623. Lawrence is right. For components, the refCon was designed exactly for this
  1624. purpose. Only one thing to consider, if the system heap is tight and cannot
  1625. load your component there, then it will be "cloned" into the current
  1626. application heap (the heap that is responsible for opening it). When a
  1627. component is cloned it will not carry it's refCon from the parent. In this
  1628. case you need to check by calling GetComponentInstanceA5. A nil value means
  1629. you're in the system heap, but any value will mean you're in some
  1630. application's context.
  1631.  
  1632. - ---------------------------------------------------------------------
  1633. Jim Reekes, Polterzeitgeist   |     Macintosh Toolbox Engineering
  1634.                               |          Sound Manager Expert
  1635. Apple Computer, Inc.          | "All opinions expressed are mine, and do
  1636. 20525 Mariani Ave. MS 302-3KS |   not necessarily represent those of my
  1637. Cupertino, CA 95014           |       employer, Apple Computer Inc."
  1638.  
  1639. ---------------------------
  1640.  
  1641. >From Anders.Wahlin@hum.gu.se (Anders Wahlin)
  1642. Subject: Unmounting all volumes?
  1643. Date: Tue, 3 May 1994 08:03:46 GMT
  1644. Organization: Hum Fak:s Dataservice
  1645.  
  1646. I would like to know how I can unmount all volumes (except for the system
  1647. volume). I would like to do this without knowing the names or the reference
  1648. number of them. Should I do this in loop and not care about the errorcodes?
  1649.  
  1650. Thanks!
  1651.  
  1652. -- 
  1653. Anders Wahlin
  1654. Anders.Wahlin@hum.gu.se
  1655.  
  1656. +++++++++++++++++++++++++++
  1657.  
  1658. >From jumplong@aol.com (Jump Long)
  1659. Date: 3 May 1994 16:03:02 -0400
  1660. Organization: America Online, Inc. (1-800-827-6364)
  1661.  
  1662. In article <Anders.Wahlin-030594100014@bigmac.hds.gu.se>,
  1663. Anders.Wahlin@hum.gu.se (Anders Wahlin) writes:
  1664.  
  1665. > I would like to know how I can unmount all volumes (except for the system
  1666. > volume). I would like to do this without knowing the names or the reference
  1667. > number of them. Should I do this in loop and not care about the errorcodes?
  1668.  
  1669. You can get a list of mounted volumes by calling PBHGetVInfo starting with
  1670. ioVolIndex==1 and then incrementing ioVolIndex until you get an error.  Each
  1671. call to PBHGetVInfo will give you a mounted volume's volume reference number in
  1672. ioVRefNum.  With that volume reference number, you'll be able to unmount
  1673. volumes that don't have any non-system files open on them with PBUnmountVol. 
  1674. If any non-system files are open on a volume, PBUnmountVol will return fBsyErr
  1675. (-47) and the volume won't be unmounted.  There's function named
  1676. UnmountAndEject in the DTS sample code MoreFiles that you can use to unmount
  1677. and eject (if needed) a volume correctly.
  1678.  
  1679. IMPORTANT WARNING: Some programmers have found and used the _UnmountVol trap
  1680. with the HFS bit set (PBHUnmountVol which isn't in Files.h) to unconditionally
  1681. unmount volumes that have open files.  DON'T EVER DO THAT!  PBHUnmountVol is
  1682. reserved for system use at shutdown when volumes need to be unmounted no matter
  1683. what because the system is either going to be shut off or restarted.  Use of
  1684. PBHUnmountVol at any other time can, and usually does, cause serious file and
  1685. volume corruption because all open files on the volume unmounted by
  1686. PBHUnmountVol are slammed closed by the file system that owns the volume. If
  1687. one of those "slammed closed" file's File Control Blocks (FCB) is reused to
  1688. open another file and the program that opened the first file writes to it or
  1689. closes it, it will be accessing the wrong file!  For a good explanation of how
  1690. closing files more than once (which is another thing that can happen if
  1691. PBHUnmountVol is used) can really screw things up, see the Technical Note "HFS
  1692. Elucidations" (used to be TN #102).
  1693.  
  1694. -- Jim Luther
  1695.  
  1696.  
  1697. ---------------------------
  1698.  
  1699. End of C.S.M.P. Digest
  1700. **********************
  1701.  
  1702.  
  1703.