home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / TRSICAT.LZX / CATS_CD2_TRSI / Reference_Library / lib_examples / strhooks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-21  |  10.2 KB  |  320 lines

  1. ;/* strhooks.c - Execute me to compile me with SAS C 5.10
  2. LC -b1 -cfistq -v -y -j73 strhooks.c
  3. Blink FROM LIB:c.o,strhooks.o TO strhooks LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. **   strhooks.c - string gadget hooks demo
  6. **
  7. ** WARNING: This file contains "callback" functions.
  8. ** You must disable stack checking (SAS -v flag) for them to work.
  9. */
  10. #define INTUI_V36_NAMES_ONLY
  11.  
  12. #include <exec/types.h>
  13. #include <exec/memory.h>
  14. #include <utility/hooks.h>
  15. #include <devices/inputevent.h>
  16. #include <intuition/intuition.h>
  17. #include <intuition/sghooks.h>
  18. #include <graphics/displayinfo.h>
  19.  
  20. #include <clib/intuition_protos.h>
  21. #include <clib/utility_protos.h>
  22. #include <clib/exec_protos.h>
  23.  
  24. #ifdef LATTICE
  25. int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
  26. int chkabort(void) { return(0); }  /* really */
  27. #endif
  28.  
  29. /* our function prototypes */
  30. BOOL IsHexDigit(UBYTE test_char);
  31. ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg);
  32. void initHook(struct Hook *hook, ULONG (*ccode)());
  33. VOID handleWindow(struct Vars *vars);
  34.  
  35. struct Library    *IntuitionBase;
  36. struct Library    *UtilityBase;
  37.  
  38. #define SG_STRLEN     (44)
  39. #define MYSTRGADWIDTH (200)
  40. #define INIT_LATER    0
  41.  
  42. /* A border for the string gadget */
  43. UWORD strBorderData[] =    /* init elements 5 and 7 later (height adjust) */
  44.     {
  45.     0,0,  MYSTRGADWIDTH + 3,0,  MYSTRGADWIDTH + 3,INIT_LATER,
  46.     0,INIT_LATER,   0,0,
  47.     };
  48. struct Border strBorder =
  49.     {
  50.     -2,-2, 1, 0,JAM1,5,strBorderData,NULL,
  51.     };
  52.  
  53. /* We'll dynamically allocate/clear most structures, buffers */
  54. struct Vars
  55.     {
  56.     struct Window      *sgg_Window;
  57.     struct Gadget       sgg_Gadget;
  58.     struct StringInfo   sgg_StrInfo;
  59.     struct StringExtend sgg_Extend;
  60.     struct Hook         sgg_Hook;
  61.     UBYTE               sgg_Buff[SG_STRLEN];
  62.     UBYTE               sgg_WBuff[SG_STRLEN];
  63.     UBYTE               sgg_UBuff[SG_STRLEN];
  64.     };
  65.  
  66. /*   Main entry point.
  67. **
  68. ** Open all required libraries, set-up the string gadget.
  69. ** Prepare the hook, open the sgg_Window and go...
  70. */
  71. VOID main(int argc, char **argv)
  72. {
  73. struct Vars   *vars;
  74. struct Screen   *screen;
  75. struct DrawInfo *drawinfo;
  76.  
  77. if (IntuitionBase = OpenLibrary("intuition.library", 37L))
  78.     {
  79.     if (UtilityBase = OpenLibrary("utility.library", 37L))
  80.         {
  81.         /* get the correct pens for the screen. */
  82.         if (screen = LockPubScreen(NULL))
  83.             {
  84.             if (drawinfo = GetScreenDrawInfo(screen))
  85.                 {
  86.                 vars = (struct Vars *)AllocMem(sizeof(struct Vars),MEMF_CLEAR);
  87.                 if (vars != NULL)
  88.                     {
  89.                     vars->sgg_Extend.Pens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
  90.                     vars->sgg_Extend.Pens[1] = drawinfo->dri_Pens[FILLPEN];
  91.                     vars->sgg_Extend.ActivePens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
  92.                     vars->sgg_Extend.ActivePens[1] = drawinfo->dri_Pens[FILLPEN];
  93.                     vars->sgg_Extend.EditHook = &(vars->sgg_Hook);
  94.                     vars->sgg_Extend.WorkBuffer = vars->sgg_WBuff;
  95.  
  96.                     vars->sgg_StrInfo.Buffer = vars->sgg_Buff;
  97.                     vars->sgg_StrInfo.UndoBuffer = vars->sgg_UBuff;
  98.                     vars->sgg_StrInfo.MaxChars = SG_STRLEN;
  99.                     vars->sgg_StrInfo.Extension = &(vars->sgg_Extend);
  100.  
  101.                     /* There should probably be a border around the string gadget.
  102.                     ** As is, it is hard to locate when disabled.
  103.                     */
  104.                     vars->sgg_Gadget.LeftEdge = 20;
  105.                     vars->sgg_Gadget.TopEdge = 30;
  106.                     vars->sgg_Gadget.Width = MYSTRGADWIDTH;
  107.                     vars->sgg_Gadget.Height = screen->RastPort.TxHeight;
  108.                     vars->sgg_Gadget.Flags = GFLG_GADGHCOMP | GFLG_STRINGEXTEND;
  109.                     vars->sgg_Gadget.Activation = GACT_RELVERIFY;
  110.                     vars->sgg_Gadget.GadgetType = GTYP_STRGADGET;
  111.                     vars->sgg_Gadget.SpecialInfo = &(vars->sgg_StrInfo);
  112.                     vars->sgg_Gadget.GadgetRender = (APTR)&strBorder;
  113.                     strBorderData[5] = strBorderData[7] =
  114.                           screen->RastPort.TxHeight + 3;
  115.  
  116.                     initHook(&(vars->sgg_Hook), str_hookRoutine);
  117.  
  118.                     if (vars->sgg_Window = OpenWindowTags(NULL,
  119.                             WA_PubScreen,       screen,
  120.                             WA_Left,      21,   WA_Top,       20,
  121.                             WA_Width,    500,   WA_Height,   150,
  122.                             WA_MinWidth,  50,   WA_MaxWidth,  ~0,
  123.                             WA_MinHeight, 30,   WA_MaxHeight, ~0,
  124.                             WA_SimpleRefresh, TRUE,
  125.                             WA_NoCareRefresh, TRUE,
  126.                             WA_RMBTrap,       TRUE,
  127.                             WA_IDCMP,         IDCMP_GADGETUP | IDCMP_CLOSEWINDOW,
  128.                             WA_Flags,         WFLG_CLOSEGADGET | WFLG_NOCAREREFRESH |
  129.                                               WFLG_DRAGBAR | WFLG_DEPTHGADGET |
  130.                                               WFLG_SIMPLE_REFRESH,
  131.                             WA_Title,         "String Hook Accepts HEX Digits Only",
  132.                             WA_Gadgets,       &(vars->sgg_Gadget),
  133.                             TAG_DONE))
  134.                         {
  135.                         handleWindow(vars);
  136.  
  137.                         CloseWindow(vars->sgg_Window);
  138.                         }
  139.                     FreeMem(vars,sizeof(struct Vars));
  140.                     }
  141.                 FreeScreenDrawInfo(screen, drawinfo);
  142.                 }
  143.             UnlockPubScreen(NULL, screen);
  144.             }
  145.         CloseLibrary(UtilityBase);
  146.         }
  147.     CloseLibrary(IntuitionBase);
  148.     }
  149. }
  150.  
  151.  
  152. /*
  153. ** This is an example string editing hook, which shows the basics of
  154. ** creating a string editing function.  This hook restricts entry to
  155. ** hexadecimal digits (0-9, A-F, a-f) and converts them to upper case.
  156. ** To demonstrate processing of mouse-clicks, this hook also detects
  157. ** clicking on a character, and converts it to a zero.
  158. **
  159. ** NOTE: String editing hooks are called on Intuition's task context,
  160. ** so the hook may not use DOS and may not cause Wait() to be called.
  161. */
  162.  
  163. ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg)
  164. {
  165. UBYTE *work_ptr;
  166. ULONG return_code;
  167.  
  168. /* Hook must return non-zero if command is supported.
  169. ** This will be changed to zero if the command is unsupported.
  170. */
  171. return_code = ~0L;
  172.  
  173. if (*msg == SGH_KEY)
  174.     {
  175.     /* key hit -- could be any key (Shift, repeat, character, etc.) */
  176.  
  177.     /* allow only upper case characters to be entered.
  178.     ** act only on modes that add or update characters in the buffer.
  179.     */
  180.     if ((sgw->EditOp == EO_REPLACECHAR) ||
  181.         (sgw->EditOp == EO_INSERTCHAR))
  182.         {
  183.         /* Code contains the ASCII representation of the character
  184.         ** entered, if it maps to a single byte.  We could also look
  185.         ** into the work buffer to find the new character.
  186.         **
  187.         **     sgw->Code == sgw->WorkBuffer[sgw->BufferPos - 1]
  188.         **
  189.         ** If the character is not a legal hex digit, don't use
  190.         ** the work buffer and beep the screen.
  191.         */
  192.         if (!IsHexDigit(sgw->Code))
  193.             {
  194.             sgw->Actions |= SGA_BEEP;
  195.             sgw->Actions &= ~SGA_USE;
  196.             }
  197.         else
  198.             {
  199.             /* And make it upper-case, for nicety */
  200.             sgw->WorkBuffer[sgw->BufferPos - 1] = ToUpper(sgw->Code);
  201.             }
  202.         }
  203.     }
  204. else if (*msg == SGH_CLICK)
  205.     {
  206.     /* mouse click
  207.     ** zero the digit clicked on
  208.     */
  209.     if (sgw->BufferPos < sgw->NumChars)
  210.         {
  211.         work_ptr = sgw->WorkBuffer + sgw->BufferPos;
  212.         *work_ptr = '0';
  213.         }
  214.     }
  215. else
  216.     {
  217.     /* UNKNOWN COMMAND
  218.     ** hook should return zero if the command is not supported.
  219.     */
  220.     return_code = 0;
  221.     }
  222.  
  223. return(return_code);
  224. }
  225.  
  226.  
  227.  
  228. /*
  229. ** This is a function which converts register-parameter
  230. ** hook calling convention into standard C conventions.
  231. ** It only works with SAS C 5.0+
  232. **
  233. ** Without the fancy __asm stuff, you'd probably need to
  234. ** write this in assembler.
  235. **
  236. ** You could conceivably declare all your C hook functions
  237. ** this way, and eliminate the middleman (you'd initialize
  238. ** the h_Entry field to your C function's address, and not
  239. ** bother with the h_SubEntry field).
  240. **
  241. ** This is nice and easy, though, and since we're using the
  242. ** small data model, using a single interface routine like this
  243. ** (which does the necessary __saveds), it might
  244. ** actually turn out to be smaller to use a single entry point
  245. ** like this rather than declaring each of many hooks __saveds.
  246. */
  247. ULONG __saveds __asm hookEntry(register __a0 struct Hook *hookptr,
  248.     register __a2 void  *object,
  249.     register __a1 void  *message)
  250. {
  251. return((*hookptr->h_SubEntry)(hookptr, object, message));
  252. }
  253.  
  254.  
  255. /*
  256. ** Initialize the hook to use the hookEntry() routine above.
  257. */
  258. void initHook(struct Hook *hook, ULONG (*ccode)())
  259. {
  260. hook->h_Entry    = hookEntry;
  261. hook->h_SubEntry = ccode;
  262. hook->h_Data     = 0;   /* this program does not use this */
  263. }
  264.  
  265. /*
  266. ** Process messages received by the sgg_Window.  Quit when the close gadget
  267. ** is selected.
  268. */
  269. VOID handleWindow(struct Vars *vars)
  270. {
  271. struct IntuiMessage *msg;
  272. ULONG  class;
  273. USHORT code;
  274.  
  275. for (;;)
  276.     {
  277.     Wait(1L << vars->sgg_Window->UserPort->mp_SigBit);
  278.     while (msg =
  279.             (struct IntuiMessage *)GetMsg(vars->sgg_Window->UserPort))
  280.         {
  281.         /* Stash message contents and reply, important when message
  282.         ** triggers some lengthy processing
  283.         */
  284.         class = msg->Class;
  285.         code  = msg->Code;
  286.         ReplyMsg((struct Message *)msg);
  287.  
  288.         switch (class)
  289.             {
  290.             case IDCMP_GADGETUP:
  291.                 /* if a code is set in the hook after an SGH_KEY
  292.                 ** command, where SGA_END is set on return from
  293.                 ** the hook, the code will be returned in the Code
  294.                 ** field of the IDCMP_GADGETUP message.
  295.                 */
  296.                 break;
  297.             case IDCMP_CLOSEWINDOW:
  298.                 return;
  299.                 break;
  300.             }
  301.         }
  302.     }
  303. }
  304.  
  305.  
  306. /*
  307. ** IsHexDigit()
  308. **
  309. ** Return TRUE if the character is a hex digit (0-9, A-F, a-f)
  310. */
  311. BOOL IsHexDigit(UBYTE test_char)
  312. {
  313. test_char = ToUpper(test_char);
  314. if (((test_char >= '0') && (test_char <= '9')) ||
  315.     ((test_char >= 'A') && (test_char <= 'F')))
  316.     return(TRUE);
  317. else
  318.     return(FALSE);
  319. }
  320.