home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / fileutil / enote.lha / src / ENote.c < prev    next >
C/C++ Source or Header  |  1992-05-20  |  18KB  |  636 lines

  1.  
  2. /***     Copyright 1992 by D.W.Reisig.   ***/
  3.  
  4. unsigned char Version[] = "$VER: ENote 1.0 04-May-92 © 1992 D.W.Reisig\n";
  5. unsigned char PrgTitle[] = "ENote 1.0: ";
  6.  
  7. #include <exec/types.h>
  8. #include <exec/memory.h>
  9. #include <workbench/startup.h>
  10. #include <libraries/dosextens.h>
  11. #include <intuition/intuition.h>
  12. #include <intuition/screens.h>
  13. #include <proto/exec.h>
  14. #include <proto/dos.h>
  15. #include <proto/intuition.h>
  16. #include "memory.h"
  17.  
  18. #define COMMENTSIZE    80
  19. #define PUBCLR        MEMF_PUBLIC | MEMF_CLEAR
  20. #define CHECK_IOERR    -1
  21.  
  22. #define btst(bitnr,var)    ((var)&(1<<(bitnr)))
  23. #define bset(bitnr,var)    ((var)|=(1<<(bitnr)))
  24. #define bclr(bitnr,var)    ((var)&=~(1<<(bitnr)))
  25. #define bchg(bitnr,var)    ((var)^=(1<<(bitnr)))
  26.  
  27. extern VOID Quit(LONG ReturnValue, LONG Result2);
  28. extern LONG Edit(UBYTE *FileName, struct FileInfoBlock *InfoBlock);
  29. extern struct IntuitionBase *IntuitionBase;
  30. extern struct WBStartup *WBenchMsg;
  31.  
  32. ULONG StdOut;
  33. UBYTE *ErrMsg, *PrgName;
  34.  
  35.  
  36. /*---------------------------------------------------------------------------*/
  37.  
  38. VOID main(LONG argc, UBYTE *argv[])
  39. {
  40.   //  static UWORD Pad;  //  Align FileInfoBlocks if necessary
  41.   static struct FileInfoBlock WBInfoBlock, InfoBlock;
  42.   static UBYTE NoAccess[] = "Could not access file\n";
  43.   UBYTE *FileName;
  44.   ULONG FileLock;
  45.   LONG  EditResult;
  46.  
  47.   if (argc != 0){
  48.     StdOut = Output();
  49.     PrgName = argv[0];
  50.   }
  51.  
  52.   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  53.   if (!IntuitionBase){
  54.     ErrMsg = "No Intuition\n";
  55.     Quit(RETURN_FAIL, 0);
  56.   }
  57.  
  58.   if (argc == 0){
  59.  
  60.     //***  From the Workbench..
  61.   
  62.     ULONG WBLock;
  63.  
  64.     if (WBenchMsg->sm_NumArgs < 2){
  65.       ErrMsg = "\nSelect the ENote Icon,\nPress shift,\nAnd double-click another Icon..\n";
  66.       Quit(RETURN_ERROR, ERROR_REQUIRED_ARG_MISSING);
  67.     }
  68.     WBLock = ((struct WBArg *)(WBenchMsg->sm_ArgList)+1)->wa_Lock;
  69.     CurrentDir(WBLock);
  70.     FileName = ((struct WBArg *)(WBenchMsg->sm_ArgList)+1)->wa_Name;
  71.     if (*FileName == '\0'){
  72.       
  73.       //***  Directory selected; one up, so we can find its name..
  74.       
  75.       CurrentDir(ParentDir(WBLock));
  76.       if (!Examine(WBLock, &WBInfoBlock)){
  77.         ErrMsg = NoAccess;
  78.         Quit(RETURN_FAIL, CHECK_IOERR);
  79.       }
  80.       FileName = WBInfoBlock.fib_FileName;
  81.     }
  82.  
  83.   } else{
  84.  
  85.     //***  From the CLI..
  86.     
  87.     if ((argc<2) || ((argc>1)&&(*argv[1]=='?'))){  //  No argument or '?'
  88.       static UBYTE Usage0[] = "Syntax: ";
  89.       static UBYTE Usage1[] = " <file>\nFunction: Edit a filenote\n";
  90.       Write(StdOut, Usage0, sizeof(Usage0)-1);
  91.       Write(StdOut, argv[0], strlen(argv[0]));
  92.       Write(StdOut, Usage1, sizeof(Usage1)-1);
  93.       Quit(RETURN_ERROR, ERROR_REQUIRED_ARG_MISSING);
  94.     }
  95.     FileName = argv[1];
  96.   }
  97.  
  98.   //***  Get access to file
  99.  
  100.   FileLock = Lock(FileName, ACCESS_READ);
  101.   if (!FileLock){
  102.     ErrMsg = NoAccess;
  103.     Quit(RETURN_FAIL, CHECK_IOERR);
  104.   }
  105.   if (!Examine(FileLock, &InfoBlock)){
  106.     UnLock(FileLock);
  107.     ErrMsg = NoAccess;
  108.     Quit(RETURN_FAIL, CHECK_IOERR);
  109.   }
  110.   UnLock(FileLock);
  111.  
  112.   //***  Edit filenote and bits
  113.   
  114.   EditResult = Edit(FileName, &InfoBlock);
  115.   if (EditResult < 0)
  116.     Quit(RETURN_FAIL, 0);
  117.   if (EditResult > 0){
  118.   
  119.     //***  Store filenote and bits
  120.     
  121.     if (!(SetComment(FileName, InfoBlock.fib_Comment) &&
  122.           SetProtection(FileName, InfoBlock.fib_Protection))){
  123.       ErrMsg = "Save failed\n";
  124.       Quit(RETURN_FAIL, CHECK_IOERR);
  125.     }
  126.   }
  127.  
  128.   Quit(RETURN_OK, 0);
  129. }
  130.  
  131. /*---------------------------------------------------------------------------*/
  132.  
  133. #define MAXWTITLE 40
  134.  
  135. VOID Quit(LONG ReturnValue, LONG Result2)
  136. {
  137.   
  138.   if (Result2 == CHECK_IOERR)
  139.     Result2 = IoErr();
  140.  
  141.   //***  Print any message
  142.  
  143.   if (ErrMsg){
  144.     LONG MsgLen = strlen(ErrMsg);
  145.  
  146.     if (StdOut){  // CLI
  147.  
  148.       Write(StdOut, PrgName, strlen(PrgName));
  149.       Write(StdOut, ": ", 2);
  150.       Write(StdOut, ErrMsg, MsgLen);
  151.  
  152.     } else{       // WB
  153.  
  154.       UBYTE StrBuf[MAXWTITLE+18], *StrPtr;
  155.  
  156.       strcpy(StrBuf, "CON:10/10/630/120/");
  157.       strncpy(&StrBuf[18], WBenchMsg->sm_ArgList->wa_Name, MAXWTITLE);
  158.       StdOut = Open(StrBuf, MODE_OLDFILE);
  159.       if (StdOut){
  160.         Write(StdOut, ErrMsg, MsgLen);
  161.         if (Result2){
  162.           strcpy(StrBuf, "Error ");
  163.           StrPtr = &StrBuf[6];
  164.           StrPtr += stcl_d(StrPtr, Result2);
  165.           *StrPtr++ = '\n';
  166.           *StrPtr = '\0';
  167.           Write(StdOut, StrBuf, strlen(StrBuf));
  168.         }
  169.         Delay(100 + 4 * MsgLen);
  170.         Close(StdOut);
  171.       } else if (IntuitionBase){
  172.         DisplayBeep(0);
  173.       }
  174.     }
  175.   }
  176.   
  177.   if (IntuitionBase)
  178.     CloseLibrary(IntuitionBase);
  179.  
  180.   ((struct Process *)FindTask(0))->pr_Result2 = Result2;
  181.   _exit(ReturnValue);
  182. }
  183.  
  184. /*---------------------------------------------------------------------------*/
  185.  
  186. UBYTE *NoMem(ULONG Size, ULONG Type)
  187. {
  188.   ErrMsg="Not enough memory\n";
  189.   return(0);
  190. }
  191.  
  192. /*****************************************************************************/
  193.  
  194. extern struct Gadget  *MakeStringGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *TextBuf, ULONG TextLen);
  195. extern struct Gadget *MakeBoolGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *Text);
  196. extern VOID ToggleGadget(struct Gadget *Gadget, struct Window *Window);
  197.  
  198. #define GADGET_H_DIST    10
  199. #define GADGET_V_DIST    6
  200. #define GADTXT_H_DIST    4
  201. #define GADTXT_V_DIST    2
  202. #define PEN_GREY    0
  203. #define PEN_BLACK    1
  204. #define PEN_WHITE    2
  205. #define PEN_BLUE    3
  206.  
  207. #define NUMGADGETS    11
  208. #define G_STR        10
  209. #define G_CANCEL    9
  210. #define G_SAVE        8
  211. #define G_H        7
  212. #define G_S        6
  213. #define G_P        5
  214. #define G_A        4
  215. #define G_R        3
  216. #define G_W        2
  217. #define G_E        1
  218. #define G_D        0
  219.  
  220. UBYTE *GtsText[] = {
  221.   "D",
  222.   "E",
  223.   "W",
  224.   "R",
  225.   "A",
  226.   "P",
  227.   "S",
  228.   "H",
  229.   "  Save  ",
  230.   " Cancel ",
  231.   ""
  232. };
  233.  
  234. struct Screen WBScreen;
  235. struct NewWindow NewWin;
  236.  
  237. /*---------------------------------------------------------------------------*/
  238.  
  239.  
  240. LONG Edit(UBYTE *FileName, struct FileInfoBlock *InfoBlock)
  241. {
  242.   struct Window *Window;
  243.   struct Gadget *Gadget[NUMGADGETS];
  244.   LONG I;
  245.   WORD OverShoot, TextHeight;
  246.   WORD Close = 0, FirstActivate = 1;
  247.   
  248.  
  249.   //***  Get Screen structure for window and font sizes among others
  250.  
  251.   if (!GetScreenData(&WBScreen, sizeof(struct Screen), WBENCHSCREEN, NULL)){
  252.     ErrMsg="No Screen\n";
  253.     Quit(RETURN_FAIL, 0);
  254.   }
  255.  
  256.   //***  Something like Barheight, but Barheight differs between 1.3 and 2.0
  257.  
  258.   TextHeight = WBScreen.RastPort.TxHeight + GADTXT_V_DIST;
  259.  
  260.   //***  NewWindow allocation and initialization
  261.  
  262.   NewWin.DetailPen  = -1;
  263.   NewWin.BlockPen   = -1;
  264.   NewWin.IDCMPFlags = IDCMP_ACTIVEWINDOW + IDCMP_GADGETUP + IDCMP_VANILLAKEY;
  265.   NewWin.Flags      = WFLG_NOCAREREFRESH + WFLG_SMART_REFRESH + WFLG_ACTIVATE + WFLG_DRAGBAR + WFLG_DEPTHGADGET;
  266.   NewWin.Type       = WBENCHSCREEN;
  267.   NewWin.TopEdge    = WBScreen.MouseY;    // Nice for auto-activation..
  268.   NewWin.Height     = TextHeight * 3 + GADGET_V_DIST * 3 + 2;
  269.   OverShoot = NewWin.TopEdge + NewWin.Height - WBScreen.Height;
  270.   if (OverShoot>0){
  271.     NewWin.TopEdge -= OverShoot;
  272.     if (NewWin.TopEdge < 0)
  273.       NewWin.TopEdge = 0;
  274.   }
  275.   NewWin.Width      = WBScreen.RastPort.TxWidth * COMMENTSIZE + 2 * GADTXT_H_DIST + 2 * GADGET_H_DIST;
  276.   if (NewWin.Width > WBScreen.Width)
  277.     NewWin.Width    = WBScreen.Width;
  278.   OverShoot = WBScreen.MouseX - NewWin.Width + 1;
  279.   if (OverShoot > 0)
  280.     NewWin.LeftEdge = OverShoot;
  281.   NewWin.MinHeight  = NewWin.MaxHeight = NewWin.Height;   // No fiddling with our sizes!
  282.   NewWin.MinWidth   = NewWin.MaxWidth = NewWin.Width;
  283.   NewWin.Title      = AllocMA(sizeof(PrgTitle) + 1 + strlen(FileName), PUBCLR);
  284.   if (!NewWin.Title)
  285.     goto Fail;
  286.   strcpy(NewWin.Title, PrgTitle);
  287.   strcpy(&NewWin.Title[sizeof(PrgTitle)-1], FileName);
  288.  
  289.   //***  Create string gadget for filenote
  290.  
  291.   Gadget[G_STR]=MakeStringGadget(NewWin.Width - 2 * GADGET_H_DIST - 2 * GADTXT_H_DIST, TextHeight,
  292.                                  (UBYTE *)&InfoBlock->fib_Comment, COMMENTSIZE);
  293.   if (!Gadget[G_STR])
  294.     goto Fail;
  295.   Gadget[G_STR]->LeftEdge = GADGET_H_DIST + GADTXT_H_DIST;
  296.   Gadget[G_STR]->TopEdge  = TextHeight + GADGET_V_DIST + 2;  // 2 for thick border
  297.  
  298.   //***  Create BOOL gadget structures
  299.  
  300.   for (I=G_CANCEL; I>=G_D; --I){
  301.     Gadget[I]=MakeBoolGadget(strlen(GtsText[I]) * WBScreen.RastPort.TxWidth + 2 * GADTXT_H_DIST,
  302.                              TextHeight, GtsText[I]);
  303.     if (!Gadget[I])
  304.       goto Fail;
  305.     Gadget[I]->TopEdge       = Gadget[G_STR]->TopEdge + TextHeight + GADGET_V_DIST + 1;  // 1 for thin border
  306.     Gadget[I+1]->NextGadget  = Gadget[I];
  307.   }
  308.   Gadget[G_SAVE]->GadgetID   = 1;  // Close gadgets
  309.   Gadget[G_CANCEL]->GadgetID = 1;
  310.  
  311.   //***  Set BOOL gadgets horizontal locations
  312.   
  313.   Gadget[G_SAVE]->LeftEdge   = GADGET_H_DIST;
  314.   Gadget[G_CANCEL]->LeftEdge = NewWin.Width - Gadget[G_CANCEL]->Width - GADGET_H_DIST;
  315.   Gadget[G_H]->LeftEdge      = NewWin.Width/2 - 4 * (Gadget[G_H]->Width + GADGET_H_DIST);
  316.   for (I=G_S; I>=G_D; --I)
  317.     Gadget[I]->LeftEdge      = Gadget[I+1]->LeftEdge + Gadget[I+1]->Width + GADGET_H_DIST;
  318.  
  319.   //***  Check gaget overlap
  320.  
  321.   if ((Gadget[G_SAVE]->LeftEdge + Gadget[G_SAVE]->Width) > Gadget[G_H]->LeftEdge){
  322.     ErrMsg = "Font too wide\n";
  323.     goto Fail;
  324.   }
  325.  
  326.   //***  Set Filebit gadgets activation
  327.  
  328.   for (I=G_H; I>=G_A; --I)
  329.     if (btst(I, InfoBlock->fib_Protection))
  330.       Gadget[I]->Flags |= GFLG_SELECTED;
  331.  
  332.   for (I=G_R; I>=G_D; --I)
  333.     if (!btst(I, InfoBlock->fib_Protection))
  334.       Gadget[I]->Flags |= GFLG_SELECTED;
  335.  
  336.   NewWin.FirstGadget = Gadget[G_STR];
  337.  
  338.   //***  Open Window
  339.  
  340.   Window = (struct Window *)OpenWindow(&NewWin);
  341.   if (!Window){
  342.     ErrMsg = "No window\n";
  343.     goto Fail;
  344.   }
  345.   
  346.   //***  Handle Window messages
  347.   
  348.   while(!Close){
  349.   
  350.     struct IntuiMessage IntuMsg, *IM;
  351.  
  352.     WaitPort(Window->UserPort);
  353.     if (IM = (struct IntuiMsg *)GetMsg(Window->UserPort)){
  354.       IntuMsg = *IM;
  355.       ReplyMsg((struct Message *)IM);
  356.       switch(IntuMsg.Class){
  357.  
  358.         case IDCMP_ACTIVEWINDOW:
  359.           if (FirstActivate)
  360.             ActivateGadget(Gadget[G_STR], Window, NULL);
  361.           FirstActivate=0;
  362.           break;
  363.         
  364.         case IDCMP_VANILLAKEY:
  365.           switch(IntuMsg.Code){
  366.             
  367.             case 'S':
  368.               Gadget[G_SAVE]->Flags |= SELECTED;
  369.               Close = 1;
  370.             break;
  371.             
  372.             case 'C':
  373.               Close = 1;
  374.               break;
  375.             
  376.             case 'h':
  377.               ToggleGadget(Gadget[G_H], Window);
  378.               break;
  379.             
  380.             case 's':
  381.               ToggleGadget(Gadget[G_S], Window);
  382.               break;
  383.             
  384.             case 'p':
  385.               ToggleGadget(Gadget[G_P], Window);
  386.               break;
  387.             
  388.             case 'a':
  389.               ToggleGadget(Gadget[G_A], Window);
  390.               break;
  391.             
  392.             case 'r':
  393.               ToggleGadget(Gadget[G_R], Window);
  394.               break;
  395.             
  396.             case 'w':
  397.               ToggleGadget(Gadget[G_W], Window);
  398.               break;
  399.             
  400.             case 'e':
  401.               ToggleGadget(Gadget[G_E], Window);
  402.               break;
  403.             
  404.             case 'd':
  405.               ToggleGadget(Gadget[G_D], Window);
  406.               break;
  407.             
  408.             case 'f':
  409.               ActivateGadget(Gadget[G_STR], Window, NULL);
  410.               break;
  411.  
  412.             default:
  413.               DisplayBeep(0);
  414.               break;
  415.           }
  416.           break;
  417.   
  418.         case IDCMP_GADGETUP:  /*  User perhaps asks to leave  */
  419.           Close = ((struct Gadget *)IntuMsg.IAddress)->GadgetID;
  420.           break;
  421.         
  422.         
  423.       }
  424.     }
  425.   }
  426.  
  427.   //***  Set filebits from gadgets
  428.  
  429.   for (I=G_H; I>=G_A; --I)
  430.     if (Gadget[I]->Flags & GFLG_SELECTED)
  431.       bset(I, InfoBlock->fib_Protection);
  432.     else
  433.       bclr(I, InfoBlock->fib_Protection);
  434.  
  435.   for (I=G_R; I>=G_D; --I)
  436.     if (Gadget[I]->Flags & GFLG_SELECTED)
  437.       bclr(I, InfoBlock->fib_Protection);
  438.     else
  439.       bset(I, InfoBlock->fib_Protection);
  440.   
  441.   //***  Close Window and return status
  442.  
  443.   CloseWindow(Window);
  444.   return((Gadget[G_SAVE]->Flags&SELECTED)? 1 : 0);
  445.  
  446. Fail:
  447.   return(-1);
  448. }
  449.  
  450. /*---------------------------------------------------------------------------*/
  451.  
  452.  
  453. struct Gadget  *MakeStringGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *TextBuf, ULONG TextLen)
  454. {
  455.  
  456.   //***  Array of coordinates of a border around a gadget with a size of zero.
  457.  
  458.   static WORD BasicXY[] = {
  459.     -4, -3, -4,  0, -3, -1, -3, -3,  2, -3,  1, -3,  1, -1,  0, -1,  0, -1, -1, -1,
  460.      3,  0,  3, -3,  2, -2,  2,  0, -3,  0, -2,  0, -2, -3, -1, -2, -1, -2,  0, -2
  461.   };
  462.   //***  Arrays of coordinate elements to be adapted to real gadget size
  463.   
  464.   static WORD VAdapt[]  = {  3,  5, 13, 17, 19, 21, 27, 29, 31, 35 };
  465.   static WORD HAdapt[]  = {  8, 10, 12, 14, 16, 20, 22, 24, 26, 38 };
  466.  
  467.   struct StringInfo *StrInfo;
  468.   struct Gadget *Gadget;
  469.   struct Border *BorderLT, *BorderRB;  // Border Left Top and Border Right Bottom
  470.   WORD   *XY;
  471.   LONG I;
  472.  
  473.  
  474.   //***  Allocate and initialize StringInfo structure
  475.  
  476.   StrInfo = (struct StringInfo *)AllocMA(sizeof(struct StringInfo), PUBCLR);
  477.   if (!StrInfo)
  478.     goto Fail;
  479.   StrInfo->Buffer = TextBuf;
  480.   StrInfo->BufferPos = strlen(TextBuf);
  481.   StrInfo->UndoBuffer = AllocMA(TextLen + 2, PUBCLR);
  482.   if (!StrInfo->UndoBuffer)
  483.     goto Fail;
  484.   StrInfo->MaxChars = TextLen;
  485.   
  486.   //***  Allocate and coordinate array's and adapt its contents
  487.   
  488.   XY = (WORD *)AllocMA(sizeof(BasicXY), MEMF_PUBLIC);
  489.   if (!XY)
  490.     goto Fail;
  491.   memcpy((UBYTE *)XY, (UBYTE *)BasicXY, sizeof(BasicXY));
  492.   for (I=0; I < sizeof(VAdapt)/2; ++I)
  493.     XY[VAdapt[I]] += TextHeight;
  494.   for (I=0; I < sizeof(HAdapt)/2; ++I)
  495.     XY[HAdapt[I]] += TextWidth;
  496.  
  497.   //*** Allocate and initialize Border structures
  498.  
  499.   BorderLT = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR);
  500.   if (!BorderLT)
  501.     goto Fail;
  502.   BorderLT->XY         = XY;
  503.   BorderLT->Count      = (sizeof(BasicXY)/(2 * sizeof(WORD)))/2;
  504.   BorderLT->FrontPen   = PEN_WHITE;
  505.   BorderLT->DrawMode   = JAM2;
  506.  
  507.   BorderRB = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR);
  508.   if (!BorderRB)
  509.     goto Fail;
  510.   BorderRB->XY         = &XY[20];
  511.   BorderRB->Count      = (sizeof(BasicXY)/(2 * sizeof(WORD)))/2;
  512.   BorderRB->FrontPen   = PEN_BLACK;
  513.   BorderRB->DrawMode   = JAM2;
  514.   BorderRB->NextBorder = BorderLT;
  515.  
  516.   //***  Allocate and initialize string Gadget structure
  517.  
  518.   Gadget = (struct Gadget *)AllocMA(sizeof(struct Gadget), PUBCLR);
  519.   if (!Gadget)
  520.     goto Fail;
  521.   Gadget->SpecialInfo  = StrInfo;
  522.   Gadget->Flags        = GFLG_GADGHCOMP + GFLG_SELECTED;
  523.   Gadget->Activation   = GACT_TOGGLESELECT;
  524.   Gadget->GadgetType   = GTYP_STRGADGET;
  525.   Gadget->Width        = TextWidth;
  526.   Gadget->Height       = TextHeight;
  527.   Gadget->GadgetRender = BorderRB;
  528.  
  529.   return(Gadget);
  530. Fail:
  531.   return(0);
  532. }
  533.  
  534. /*---------------------------------------------------------------------------*/
  535.  
  536. struct Gadget *MakeBoolGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *Text)
  537. {
  538.   struct Gadget *Gadget;
  539.   struct IntuiText *IText;
  540.   struct Border *BorderLT, *BorderRB;  // Border Left Top and Border Right Bottom
  541.   WORD   *XY;
  542.  
  543.   //***  Allocate and initialize Border coordinates
  544.  
  545.   XY = (WORD *)AllocMA(2 * 5 * 2 * sizeof(WORD), PUBCLR);
  546.   if (!XY)
  547.     goto Fail;
  548.  
  549.                   XY[3]  = TextHeight;
  550.   XY[4]  = 1;            XY[5]  = TextHeight - 1;
  551.   XY[6]  = 1;
  552.   XY[8]  = TextWidth - 1;
  553.  
  554.   XY[10] = TextWidth;        XY[11] = TextHeight;
  555.   XY[12] = TextWidth;
  556.   XY[14] = TextWidth - 1;    XY[15] = 1;
  557.   XY[16] = TextWidth - 1;    XY[17] = TextHeight;
  558.   XY[18] = 1;            XY[19] = TextHeight;
  559.  
  560.   //***  Allocate and initialize Border structures
  561.  
  562.   BorderLT = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR);
  563.   if (!BorderLT)
  564.     goto Fail;
  565.   BorderLT->XY         = XY;
  566.   BorderLT->Count      = 5;
  567.   BorderLT->FrontPen   = PEN_WHITE;
  568.   BorderLT->DrawMode   = JAM2;
  569.  
  570.   BorderRB = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR);
  571.   if (!BorderRB)
  572.     goto Fail;
  573.   BorderRB->XY         = &XY[10];
  574.   BorderRB->Count      = 5;
  575.   BorderRB->FrontPen   = PEN_BLACK;
  576.   BorderRB->DrawMode   = JAM2;
  577.   BorderRB->NextBorder = BorderLT;
  578.   
  579.   //***  Allocate and initialize IntuiText structures for gadget texts
  580.   
  581.   IText = (struct IntuiText *)AllocMA(sizeof(struct IntuiText), PUBCLR);
  582.   if (!IText)
  583.     goto Fail;
  584.   IText->FrontPen      = PEN_BLACK;
  585.   IText->DrawMode      = JAM2;
  586.   IText->LeftEdge      = GADTXT_H_DIST;
  587.   IText->TopEdge       = GADTXT_V_DIST;
  588.   IText->IText         = Text;
  589.   
  590.   //***  Allocate and initialize BOOL Gadget structure
  591.   
  592.   Gadget = (struct Gadget *)AllocMA(sizeof(struct Gadget), PUBCLR);
  593.   if (!Gadget)
  594.     goto Fail;
  595.   Gadget->Width        = TextWidth + 1;
  596.   Gadget->Height       = TextHeight + 1;
  597.   Gadget->Flags        = GFLG_GADGHCOMP;
  598.   Gadget->Activation   = GACT_TOGGLESELECT + GACT_RELVERIFY;
  599.   Gadget->GadgetType   = GTYP_BOOLGADGET;
  600.   Gadget->GadgetRender = BorderRB;
  601.   Gadget->GadgetText   = IText;
  602.  
  603.   return(Gadget);
  604. Fail:
  605.   return(0);
  606. }
  607.   
  608.  
  609. /*---------------------------------------------------------------------------*/
  610.  
  611. /*
  612.  *  It is not the first time I have troubles with gadgets.  I have ALWAYS
  613.  *  troubles with gadgets.  This time gadgets must toggle by our command.
  614.  *  We must first remove any drawing data from the gadget.  No border and
  615.  *  no text.  Now you can toggle the drawing just by complementing.  You can
  616.  *  let Intuition complement by refreshing a selected gadget.  Later the
  617.  *  select flag must be set right.  Takes some time to find out.
  618.  */
  619.   
  620. VOID ToggleGadget(struct Gadget *Gadget, struct Window *Window)
  621. {
  622.   UWORD Flags;
  623.  
  624.   Gadget->GadgetText=NULL;
  625.   Gadget->GadgetRender=NULL;
  626.   Flags = Gadget->Flags;
  627.   Gadget->Flags |= SELECTED;
  628.   RemoveGadget(Window, Gadget);
  629.   AddGadget(Window, Gadget, -1);
  630.   RefreshGadgets(Gadget, Window, NULL);
  631.   Gadget->Flags = Flags ^ SELECTED;
  632. }
  633.  
  634. /*---------------------------------------------------------------------------*/
  635.  
  636.