home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / Goodies / CUtility.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-04  |  6.5 KB  |  301 lines  |  [TEXT/KAHL]

  1. /*    General utilities. */
  2.  
  3. #include <TCL>
  4. #include "GLOBAL.h"
  5. #include "CUtility.h"
  6. #include "CDiagnostic.h"
  7. #include "STR.h"
  8. #include "keys.h"
  9. #include "chars.h"
  10. #include <stdio.h>
  11.  
  12. NEW void CUtility::IUtility()
  13. {
  14. }
  15.  
  16. NEW StringPtr CUtility::ApplicationName()
  17. {
  18.     int applRef;
  19.     Handle h;                            /*    I wonder what this is? */
  20.     static Str255 result;
  21.  
  22.     GetAppParms(result, &applRef, &h);
  23.     return result;
  24. }
  25.  
  26. NEW Handle CUtility::MustNewHandle(Size size)
  27. {
  28.     Handle han = NewHandle(size);
  29.     CheckAllocation(han);
  30.     return han;
  31. }
  32.  
  33. NEW Ptr CUtility::MustNewPtr(Size size)
  34. {
  35.     Ptr ptr = NewPtr(size);
  36.     CheckAllocation(ptr);
  37.     return ptr;
  38. }
  39.  
  40. NEW Handle CUtility::MustGetResource(ResType type, int ID)
  41. {
  42.     Handle han = GetResource(type, ID);
  43.  
  44.     CheckResource(han);
  45.     return han;
  46. }
  47.  
  48. /*    BriefGetString() - so called because you'd better only need the string
  49.                        briefly (before the next call to it, in fact). */
  50.  
  51. NEW StringPtr CUtility::BriefGetString(int rsrcID, int index)
  52. {
  53.     static Str255 buffer;
  54.  
  55.     GetIndString(buffer, rsrcID, index);
  56.     return buffer;
  57. }
  58.  
  59. /*    SetField and GetField. We view the patch data (editData handle) as a
  60.     vector of bytes. However, some dialog items just affect a few bits of
  61.     a byte (e.g. a single bit flag). Other dialog items don't start from
  62.     zero (e.g. -50..+50 things). SetField and GetField are our general
  63.     packing/unpacking routines. SetField takes an old byte value,
  64.     a bit shift, min, max, and value [min..max], and sets the correct bits
  65.     of the byte, guessing the bit width. GetField does the inverse. */
  66.  
  67. LOCAL Byte mask(int bitShift, int range)
  68. {
  69.     Byte b = 0;
  70.     while (range != 0)
  71.     {
  72.         b |= (1<<bitShift);
  73.         bitShift++;
  74.         range >>= 1;
  75.     }
  76.     
  77.     return b;
  78. }
  79.  
  80. NEW int CUtility::GetField(Byte byte, int bitShift, int min, int max)
  81. {
  82.     Byte m = mask(bitShift, max - min);
  83.     int result;
  84.     
  85.     result = ((byte&m) >> bitShift) + min;
  86.     
  87.   /*diagnostic("GetField(byte=0x%02x, shift=%d, min=%d, max=%d) -> %d",
  88.                byte, bitShift, min, max, result
  89.               );*/
  90.     return result;
  91. }
  92.  
  93. NEW Byte CUtility::SetField(Byte byte, int bitShift, int min, int max, int value)
  94. {
  95.     Byte m = mask(bitShift, max - min);
  96.     Byte newByte;
  97.     
  98.     newByte = (byte & (~m)) | ((value-min) << bitShift);
  99.     
  100.   /*diagnostic(
  101.         "GetField(byte=0x%02x, shift=%d, min=%d, max=%d, value=%d) -> 0x%02x",
  102.         byte, bitShift, min, max, value, newByte
  103.     );*/
  104.     
  105.     return newByte;
  106. }
  107.  
  108. NEW StringPtr CUtility::FormatNumber(int num, Boolean withPlus)
  109. {
  110.     static Str255 result;
  111.  
  112.     StringPtr p = result;
  113.     Boolean hundreds = FALSE;
  114.  
  115.     if (num < 0) {
  116.         *p++ = '-';
  117.         num = -num;
  118.         withPlus = FALSE;
  119.     }
  120.  
  121.     if (withPlus)
  122.         *p++ = '+';
  123.         
  124.     if (num >= 100) {
  125.         *p++ = '0' + (num / 100);
  126.         num %= 100;
  127.         hundreds = TRUE;
  128.     }
  129.         
  130.     if ((num >= 10) || hundreds) {
  131.         *p++ = '0' + (num / 10);
  132.         num %= 10;
  133.     }
  134.         
  135.     *p++ = '0' + num;
  136.     *p = '\0';
  137.  
  138.     CtoPstr((char *) result);
  139.     return result;
  140. }
  141.  
  142. NEW StringPtr CUtility::FormatNote(int note)
  143. {
  144.     static Str255 result;
  145.     int index = (note % 12) + 1;
  146.  
  147.     GetIndString(result, NOTENAMES_strs, index);
  148.     ConcatPStrings(result, FormatNumber(note / 12 - 2, FALSE));
  149.  
  150.     return result;
  151. }
  152.  
  153. NEW char *CUtility::ShowRoute(RouteRec route)
  154. {
  155.     static char result[4];
  156.  
  157.     sprintf(result, "%c%d",
  158.                     (route.cable == MODEM)
  159.                         ? 'M'
  160.                          : (route.cable == PRINTER) ? 'P' : '-',
  161.                     route.channel
  162.            );
  163.  
  164.     return result;
  165. }
  166.  
  167. LOCAL Boolean keyIsDown(int index, int mask)
  168. {
  169.     KeyMap keys;
  170.     long L;
  171.     
  172.     GetKeys(&keys);
  173.     L = keys.Key[index];
  174.   /*diagnostic("L = %08lx, mask = %08lx", L, mask);*/
  175.     return((L & mask) != 0L);
  176. }
  177.  
  178. NEW Boolean CUtility::OptionKeyDown()
  179. {
  180.     return(keyIsDown(WHICH_KEYWORD, OPTION_KEY));
  181. }
  182.  
  183. NEW Boolean CUtility::CommandKeyDown()
  184. {
  185.     return(keyIsDown(WHICH_KEYWORD, COMMAND_KEY));
  186. }
  187.  
  188. /*    GetFontAndSize() - looks up a string like "Monaco 12" in a STR# resource
  189.                        (with id FONTS_strs), and returns font name and size. */
  190. NEW void CUtility::GetFontAndSize(int index, StringPtr name, int *size)
  191. {
  192.     Str255 buff;
  193.     GetIndString(buff, FONTS_strs, index);
  194.     PtoCstr((char *) buff);
  195.     Assert("GetFontAndSize", sscanf((char *) buff, "%s %d", name, size) == 2);
  196.     CtoPstr((char *) name);
  197. }
  198.  
  199. /*    Sanitise - deal with any characters >127 in a string, ready for putting
  200.                into a MIDI bank. */
  201.  
  202. NEW void CUtility::Sanitise(StringPtr buff)
  203. {
  204.     int len = buff[0], i;
  205.  
  206.     for (i = 1; i <= len; i++)
  207.         if (buff[i] & 0x80)  buff[i] = HUH_char;
  208. }
  209.  
  210. NEW void CUtility::Assert(char *text, Boolean condition)
  211. {
  212.     if (!condition)  g_Die("%s", text);
  213. }
  214.  
  215. NEW void CUtility::HardCheckOSError(OSErr macErr)
  216. {
  217.     if (macErr != noErr)  gError->SevereMacError(macErr);
  218. }
  219.  
  220. NEW void CUtility::HardCheckResError()
  221. {
  222.     HardCheckOSError(ResError());
  223. }
  224.  
  225. /*    Notify() doesn't do anything with objects or the Toolbox, since we want
  226.     to be able to call it from the MIDI Manager interrupt routines. According
  227.     to TN184, we can call NM safely in such circumstances. (WRONG! it has
  228.     bugs. C'est la vie.) g_Notify takes a STR# resource ID and index, and
  229.     notifies the string, by grabbing it into a temporary buffer, putting it
  230.     into a handle, and passing the handle. We therefore have to have a
  231.     completion routine to dispose of the handle (which we pass in the refCon).
  232.  */
  233.  
  234. /*    BE CAREFUL in myCompletion - A5 isn't valid. */
  235.  
  236. static pascal void myCompletion(NMRec *nmReqPtr)
  237. {
  238.     NMRemove(nmReqPtr);
  239.     DisposPtr(nmReqPtr->nmStr);
  240.     DisposPtr(nmReqPtr);
  241. }
  242.  
  243. /*    Note that the use of NewPtr() essentially wipes this out as an
  244.     interrupt-level routine. */
  245.  
  246. NEW void CUtility::Notify(int rsrcID, int index, int extra)
  247. {
  248.     Str255 buffer1, buffer2;
  249.     StringPtr ptr;
  250.     int len;
  251.     NMRec *note;
  252.  
  253.     note = (NMRec *) gUtility->MustNewPtr(sizeof(NMRec));
  254.  
  255.     GetIndString(buffer1, rsrcID, index);
  256.     sprintf((char *) buffer2, "%#s: %#s [%d]",
  257.             ApplicationName(), buffer1, extra
  258.            );
  259.     CtoPstr((char *) buffer2);
  260.     ptr = (StringPtr) gUtility->MustNewPtr(buffer2[0] + 1);
  261.     CopyPString(buffer2, ptr);
  262.  
  263.     note->qType = nmType;
  264.     note->nmMark = 0;
  265.     note->nmSIcon = NULL;
  266.     note->nmSound = (Handle) -1;    /*    System Beep. */
  267.     note->nmStr = ptr;
  268.     note->nmResp = (ProcPtr) myCompletion;
  269.  
  270.     gUtility->HardCheckOSError(NMInstall(note));
  271. }
  272.  
  273. NEW void CUtility::Report(int index)
  274. {
  275.     gError->PostAlert(REPORT_strs, index);
  276. }
  277.  
  278. /*    g_Die - mostly pinched from CError::SevereMacError. It's a vanilla
  279.             routine because methods can't take varargs. */
  280.  
  281. GLOBAL void g_Die(format, a, b, c, d, e, f, g)
  282. char *format;
  283. {
  284.     Str255 buffer;
  285.  
  286.     sprintf((char *) buffer, format, a, b, c, d, e, f, g);
  287.  
  288.     CtoPstr((char *) buffer);
  289.     ParamText(buffer, "\p", "\p", "\p");
  290.     PositionDialog('ALRT', ALRTsevereErr);
  291.     InitCursor();
  292.  
  293.     if (StopAlert(ALRTsevereErr, NULL) == Cancel) {
  294.         gApplication->Exit();
  295.         ExitToShell();
  296.     } else {
  297.         HiliteMenu(NOTHING);
  298.         gApplication->JumpToEventLoop();
  299.     }
  300. }
  301.