home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Matrix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  17.8 KB  |  795 lines

  1. /*
  2. **    Matrix.c
  3. **
  4. **    Single character entry
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16. typedef struct MatrixInfo
  17. {
  18.     UWORD             CellWidth,
  19.                      CellHeight;
  20.     UWORD             Width,
  21.                      Height;
  22.     UWORD             PixelWidth,
  23.                      PixelHeight;
  24.     WORD             CurrentX,
  25.                      CurrentY;
  26.     STRPTR            *Labels;
  27.     LONG             NumLabels;
  28.     struct TextFont    *Font;
  29. } MatrixInfo;
  30.  
  31. #define MIA_CellWidth    (TAG_USER+0x70000)
  32. #define MIA_CellHeight    (TAG_USER+0x70001)
  33. #define MIA_Width        (TAG_USER+0x70002)
  34. #define MIA_Height        (TAG_USER+0x70003)
  35. #define MIA_Labels        (TAG_USER+0x70004)
  36. #define MIA_NumLabels    (TAG_USER+0x70005)
  37. #define MIA_Font        (TAG_USER+0x70006)
  38. #define MIA_Index        (TAG_USER+0x70007)
  39.  
  40. STATIC struct IClass    *MatrixClass;
  41. STATIC Object            *MatrixGadget;
  42.  
  43. STATIC UBYTE             TitleBuffer[256];
  44.  
  45. STATIC VOID
  46. DrawCellText(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height,STRPTR Label)
  47. {
  48.     struct TextExtent    Extent;
  49.     LONG                Len = strlen(Label);
  50.  
  51.     if(Len = TextFit(RPort,Label,Len,&Extent,NULL,1,Width,32767))
  52.         PlaceText(RPort,Left + (Width - Extent . te_Width) / 2,Top + (Height - Extent . te_Height) / 2,Label,Len);
  53. }
  54.  
  55. STATIC VOID
  56. DrawCell(struct RastPort *RPort,LONG PixelLeft,LONG PixelTop,UWORD *Pens,MatrixInfo *Info,LONG x,LONG y,BOOL Highlight)
  57. {
  58.     LONG    Left,Top;
  59.     UWORD    Shine,Shadow,Text,Fill;
  60.     LONG    Index;
  61.  
  62.     Left    = PixelLeft    + Info->CellWidth    * x;
  63.     Top        = PixelTop    + Info->CellHeight    * y;
  64.  
  65.     if(Highlight)
  66.     {
  67.         Shine    = SHADOWPEN;
  68.         Shadow    = SHINEPEN;
  69.         Text    = FILLTEXTPEN;
  70.         Fill    = FILLPEN;
  71.     }
  72.     else
  73.     {
  74.         Shine    = SHINEPEN;
  75.         Shadow    = SHADOWPEN;
  76.         Text    = TEXTPEN;
  77.         Fill    = BACKGROUNDPEN;
  78.     }
  79.  
  80.     SetDrMd(RPort,JAM1);
  81.  
  82.     SetAPen(RPort,Pens[Shine]);
  83.     Move(RPort,Left,Top + Info->CellHeight - 1);
  84.     Draw(RPort,Left,Top);
  85.     Draw(RPort,Left + Info->CellWidth - 1,Top);
  86.  
  87.     SetAPen(RPort,Pens[Shadow]);
  88.     Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  89.     Draw(RPort,Left + Info->CellWidth - 1,Top + Info->CellHeight - 1);
  90.     Draw(RPort,Left + Info->CellWidth - 1,Top + 1);
  91.  
  92.     SetAPen(RPort,Pens[Fill]);
  93.     RectFill(RPort,Left + 1,Top + 1,Left + Info->CellWidth - 2,Top + Info->CellHeight - 2);
  94.  
  95.     if((Index = y * Info->Width + x) < Info->NumLabels)
  96.     {
  97.         SetAPen(RPort,Pens[Text]);
  98.         DrawCellText(RPort,Left + 1,Top + 1,Info->CellWidth - 2,Info->CellHeight - 2,Info->Labels[Index]);
  99.     }
  100. }
  101.  
  102. STATIC VOID
  103. DrawGrid(struct RastPort *RPort,LONG PixelLeft,LONG PixelTop,UWORD *Pens,MatrixInfo *Info)
  104. {
  105.     LONG i,j,Left,Top,Bottom,Strange,Charm;
  106.  
  107.     SetDrMd(RPort,JAM1);
  108.  
  109.     Left    = PixelLeft;
  110.     Top        = PixelTop;
  111.     Bottom    = PixelTop + Info->PixelHeight - 1;
  112.  
  113.     Strange    = Pens[SHINEPEN];
  114.     Charm    = Pens[SHADOWPEN];
  115.  
  116.     for(i = 0 ; i < Info->Width ; i++)
  117.     {
  118.         SetAPen(RPort,Strange);
  119.         Move(RPort,Left,Top);
  120.         Draw(RPort,Left,Bottom);
  121.  
  122.         Left += Info->CellWidth;
  123.  
  124.         SetAPen(RPort,Charm);
  125.         Move(RPort,Left - 1,Top);
  126.         Draw(RPort,Left - 1,Bottom);
  127.     }
  128.  
  129.     Top = PixelTop;
  130.  
  131.     for(j = 0 ; j < Info->Height ; j++)
  132.     {
  133.         Left = PixelLeft;
  134.  
  135.         for(i = 0 ; i < Info->Width ; i++)
  136.         {
  137.             SetAPen(RPort,Strange);
  138.             Move(RPort,Left,Top);
  139.             Draw(RPort,Left + Info->CellWidth - 1,Top);
  140.  
  141.             SetAPen(RPort,Charm);
  142.             Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  143.             Draw(RPort,Left + Info->CellWidth - 2,Top + Info->CellHeight - 1);
  144.  
  145.             Left += Info->CellWidth;
  146.         }
  147.  
  148.         Top += Info->CellHeight;
  149.     }
  150. }
  151.  
  152. STATIC VOID
  153. NotifyIndex(struct IClass *class,Object *object,struct GadgetInfo *GInfo,struct opUpdate *msg,LONG Index)
  154. {
  155.     struct TagItem Tags[3];
  156.  
  157.     Tags[0] . ti_Tag    = MIA_Index;
  158.     Tags[0] . ti_Data    = Index;
  159.     Tags[1] . ti_Tag    = GA_ID;
  160.     Tags[1] . ti_Data    = ((struct Gadget *)object)->GadgetID;
  161.     Tags[2] . ti_Tag    = TAG_DONE;
  162.  
  163.     DoSuperMethod(class,object,OM_NOTIFY,Tags,GInfo,((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L));
  164. }
  165.  
  166. STATIC BOOL
  167. SetMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  168. {
  169.     MatrixInfo        *Info = INST_DATA(class,object);
  170.     struct TagItem    *Tag;
  171.  
  172.     if(Tag = FindTagItem(MIA_Index,SetInfo -> ops_AttrList))
  173.     {
  174.         struct RastPort *RPort;
  175.  
  176.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  177.         {
  178.             LONG Index = (LONG)Tag -> ti_Data;
  179.             UWORD *Pens = SetInfo->ops_GInfo->gi_DrInfo->dri_Pens;
  180.  
  181.             SetFont(RPort,Info->Font);
  182.  
  183.             if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  184.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  185.  
  186.             if(Index >= 0 && Index < Info->Width * Info->Height)
  187.             {
  188.                 Info->CurrentX = Index % Info->Width;
  189.                 Info->CurrentY = Index / Info->Width;
  190.  
  191.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  192.  
  193.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,Index);
  194.             }
  195.             else
  196.             {
  197.                 Info->CurrentX = Info->CurrentY = -1;
  198.  
  199.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,-1);
  200.             }
  201.  
  202.             ReleaseGIRPort(RPort);
  203.  
  204.             return(TRUE);
  205.         }
  206.     }
  207.  
  208.     return(FALSE);
  209. }
  210.  
  211. STATIC ULONG
  212. RenderMethod(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  213. {
  214.     MatrixInfo    *Info = INST_DATA(class,object);
  215.     LONG         i;
  216.     LONG         x,y,Left,Top;
  217.     UWORD        *Pens;
  218.  
  219.     Pens = RenderInfo->gpr_GInfo->gi_DrInfo->dri_Pens;
  220.  
  221.     SetFont(RenderInfo->gpr_RPort,Info->Font);
  222.  
  223.     Left    = ((struct Gadget *)object)->LeftEdge;
  224.     Top        = ((struct Gadget *)object)->TopEdge;
  225.  
  226.     SetAPen(RenderInfo->gpr_RPort,Pens[BACKGROUNDPEN]);
  227.     FillBox(RenderInfo->gpr_RPort,Left,Top,((struct Gadget *)object)->Width,((struct Gadget *)object)->Height);
  228.  
  229.     DrawGrid(RenderInfo->gpr_RPort,Left,Top,Pens,Info);
  230.  
  231.     SetAPen(RenderInfo->gpr_RPort,Pens[TEXTPEN]);
  232.  
  233.     for(i = 0 ; i < Info -> NumLabels ; i++)
  234.     {
  235.         x = (i % Info->Width) * Info->CellWidth;
  236.         y = (i / Info->Width) * Info->CellHeight;
  237.  
  238.         DrawCellText(RenderInfo->gpr_RPort,Left + x,Top + y,Info->CellWidth,Info->CellHeight,Info->Labels[i]);
  239.     }
  240.  
  241.     return(TRUE);
  242. }
  243.  
  244. STATIC VOID
  245. DisposeMethod(struct IClass *class,Object *object,Msg msg)
  246. {
  247.     MatrixInfo *Info = INST_DATA(class,object);
  248.  
  249.     if(Info->Font)
  250.         CloseFont(Info->Font);
  251. }
  252.  
  253. STATIC ULONG
  254. NewMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  255. {
  256.     if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
  257.     {
  258.         MatrixInfo        *Info = INST_DATA(class,object);
  259.         struct TagItem    *Tag,*TagList = SetInfo -> ops_AttrList;
  260.         struct TextAttr    *Font;
  261.         LONG             Width,Height;
  262.  
  263.         Width = Height = 0;
  264.         Font = NULL;
  265.  
  266.         memset(Info,0,sizeof(MatrixInfo));
  267.  
  268.         while(Tag = NextTagItem(&TagList))
  269.         {
  270.             switch(Tag->ti_Tag)
  271.             {
  272.                 case MIA_CellWidth:
  273.                     Info->CellWidth = Tag->ti_Data;
  274.                     break;
  275.  
  276.                 case MIA_CellHeight:
  277.                     Info->CellHeight = Tag->ti_Data;
  278.                     break;
  279.  
  280.                 case MIA_Width:
  281.                     Info->Width = Tag->ti_Data;
  282.                     break;
  283.  
  284.                 case MIA_Height:
  285.                     Info->Height = Tag->ti_Data;
  286.                     break;
  287.  
  288.                 case MIA_Labels:
  289.                     Info->Labels = (STRPTR *)Tag->ti_Data;
  290.                     break;
  291.  
  292.                 case MIA_NumLabels:
  293.                     Info->NumLabels = Tag->ti_Data;
  294.                     break;
  295.  
  296.                 case MIA_Font:
  297.                     Font = (struct TextAttr *)Tag->ti_Data;
  298.                     break;
  299.  
  300.                 case GA_Width:
  301.                     Width = Tag->ti_Data;
  302.                     break;
  303.  
  304.                 case GA_Height:
  305.                     Height = Tag->ti_Data;
  306.                     break;
  307.             }
  308.         }
  309.  
  310.         if(Info->Labels && !Info->NumLabels)
  311.         {
  312.             while(Info->Labels[Info->NumLabels])
  313.                 Info->NumLabels++;
  314.         }
  315.  
  316.         if(Font && Info->CellWidth && Info->CellHeight)
  317.         {
  318.             if(!Info->Width)
  319.                 Info->Width = Width / Info->CellWidth;
  320.  
  321.             if(!Info->Height)
  322.                 Info->Height = Height / Info->CellHeight;
  323.  
  324.             if(Info->Width && Info->Height)
  325.             {
  326.                 if(Info->Font = OpenFont(Font))
  327.                 {
  328.                     Info->CurrentX        = -1;
  329.                     Info->CurrentY        = -1;
  330.                     Info->PixelWidth    = Info->Width    * Info->CellWidth;
  331.                     Info->PixelHeight    = Info->Height    * Info->CellHeight;
  332.  
  333.                     return((ULONG)object);
  334.                 }
  335.             }
  336.         }
  337.  
  338.         CoerceMethod(class,object,OM_DISPOSE);
  339.     }
  340.  
  341.     return(0);
  342. }
  343.  
  344. STATIC ULONG
  345. InputMethod(struct IClass *class,Object *object,struct gpInput *InputInfo)
  346. {
  347.     MatrixInfo    *Info    = INST_DATA(class,object);
  348.     ULONG         Result    = GMR_MEACTIVE;
  349.     UWORD        *Pens    = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  350.     LONG         x,y;
  351.     BOOL         Done    = FALSE;
  352.  
  353.     if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
  354.     {
  355.         if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN)
  356.         {
  357.             Result    = GMR_NOREUSE;
  358.             Done    = TRUE;
  359.         }
  360.         else
  361.         {
  362.             if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
  363.             {
  364.                 Done = TRUE;
  365.  
  366.                 if(Info -> CurrentX != -1 && Info -> CurrentY != -1)
  367.                 {
  368.                     Result = GMR_REUSE | GMR_VERIFY;
  369.  
  370.                     *InputInfo -> gpi_Termination = Info -> CurrentY * Info -> Width + Info -> CurrentX;
  371.                 }
  372.                 else
  373.                     Result = GMR_NOREUSE;
  374.             }
  375.         }
  376.  
  377.         if(Done && Info -> CurrentX != -1 && Info -> CurrentY != -1)
  378.         {
  379.             struct RastPort    *RPort;
  380.  
  381.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  382.             {
  383.                 SetFont(RPort,Info->Font);
  384.  
  385.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  386.  
  387.                 Info->CurrentX    = -1;
  388.                 Info->CurrentY    = -1;
  389.  
  390.                 ReleaseGIRPort(RPort);
  391.  
  392.                 NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  393.             }
  394.         }
  395.     }
  396.  
  397.     if(!Done)
  398.     {
  399.         x    = InputInfo->gpi_Mouse . X / Info->CellWidth;
  400.         y    = InputInfo->gpi_Mouse . Y / Info->CellHeight;
  401.  
  402.         if(InputInfo->gpi_Mouse . X < 0 || InputInfo->gpi_Mouse . Y < 0 || x >= Info->Width || y >= Info->Height)
  403.             x = y = -1;
  404.  
  405.         if(x != Info->CurrentX || y != Info->CurrentY)
  406.         {
  407.             struct RastPort    *RPort;
  408.  
  409.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  410.             {
  411.                 SetFont(RPort,Info->Font);
  412.  
  413.                 if(Info->CurrentX != -1 && Info->CurrentY != -1)
  414.                     DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  415.  
  416.                 Info->CurrentX    = x;
  417.                 Info->CurrentY    = y;
  418.  
  419.                 if(x != -1 && y != -1)
  420.                 {
  421.                     DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  422.  
  423.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,y * Info->Width + x);
  424.                 }
  425.                 else
  426.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  427.  
  428.                 ReleaseGIRPort(RPort);
  429.             }
  430.         }
  431.     }
  432.  
  433.     return(Result);
  434. }
  435.  
  436. STATIC ULONG
  437. ActiveMethod(struct IClass *class,Object *object,struct gpInput *InputInfo)
  438. {
  439.     MatrixInfo        *Info    = INST_DATA(class,object);
  440.     UWORD            *Pens    = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  441.     struct RastPort    *RPort;
  442.  
  443.     if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  444.     {
  445.         SetFont(RPort,Info->Font);
  446.  
  447.         if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  448.             DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  449.  
  450.         Info->CurrentX    = InputInfo->gpi_Mouse . X / Info->CellWidth;
  451.         Info->CurrentY    = InputInfo->gpi_Mouse . Y / Info->CellHeight;
  452.  
  453.         if(Info->CurrentX > Info->Width - 1)
  454.             Info->CurrentX = Info->Width - 1;
  455.         else
  456.         {
  457.             if(Info->CurrentX < 0)
  458.                 Info->CurrentX = 0;
  459.         }
  460.  
  461.         if(Info->CurrentY > Info->Height - 1)
  462.             Info->CurrentY = Info->Height - 1;
  463.         else
  464.         {
  465.             if(Info->CurrentY < 0)
  466.                 Info->CurrentY = 0;
  467.         }
  468.  
  469.         DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  470.  
  471.         NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,Info->CurrentY * Info->Width + Info->CurrentX);
  472.  
  473.         ReleaseGIRPort(RPort);
  474.  
  475.         return(GMR_MEACTIVE);
  476.     }
  477.     else
  478.         return(GMR_NOREUSE);
  479. }
  480.  
  481. STATIC ULONG
  482. InactiveMethod(struct IClass *class,Object *object,struct gpGoInactive *InactiveInfo)
  483. {
  484.     MatrixInfo *Info = INST_DATA(class,object);
  485.  
  486.     if(Info -> CurrentX != -1 && Info -> CurrentY != -1)
  487.     {
  488.         struct RastPort    *RPort;
  489.  
  490.         if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  491.         {
  492.             SetFont(RPort,Info->Font);
  493.  
  494.             DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InactiveInfo->gpgi_GInfo->gi_DrInfo->dri_Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  495.  
  496.             ReleaseGIRPort(RPort);
  497.  
  498.             NotifyIndex(class,object,InactiveInfo->gpgi_GInfo,(struct opUpdate *)InactiveInfo,-1);
  499.         }
  500.     }
  501.  
  502.     Info -> CurrentX = -1;
  503.     Info -> CurrentY = -1;
  504.  
  505.     return(0);
  506. }
  507.  
  508. STATIC ULONG
  509. HitTestMethod(struct IClass *class,Object *object,struct gpHitTest *HitInfo)
  510. {
  511.     MatrixInfo *Info = INST_DATA(class,object);
  512.  
  513.     if(HitInfo -> gpht_Mouse . X < Info -> PixelWidth && HitInfo -> gpht_Mouse . Y < Info -> PixelHeight)
  514.         return(GMR_GADGETHIT);
  515.     else
  516.         return(0);
  517. }
  518.  
  519. STATIC ULONG __saveds __asm
  520. Dispatch(REG(a0) struct IClass *class,REG(a2) Object *object,REG(a1) Msg msg)
  521. {
  522.     switch(msg->MethodID)
  523.     {
  524.         case OM_NEW:
  525.             return(NewMethod(class,object,(struct opSet *)msg));
  526.  
  527.         case OM_UPDATE:
  528.         case OM_SET:
  529.             if(SetMethod(class,object,(struct opSet *)msg))
  530.                 return(TRUE);
  531.             else
  532.                 break;
  533.  
  534.         case GM_RENDER:
  535.             return(RenderMethod(class,object,(struct gpRender *)msg));
  536.  
  537.         case GM_HITTEST:
  538.             return(HitTestMethod(class,object,(struct gpHitTest *)msg));
  539.  
  540.         case GM_GOINACTIVE:
  541.             return(InactiveMethod(class,object,(struct gpGoInactive *)msg));
  542.  
  543.         case GM_GOACTIVE:
  544.             return(ActiveMethod(class,object,(struct gpInput *)msg));
  545.  
  546.         case GM_HANDLEINPUT:
  547.             return(InputMethod(class,object,(struct gpInput *)msg));
  548.  
  549.         case OM_DISPOSE:
  550.             DisposeMethod(class,object,msg);
  551.     }
  552.  
  553.     return(DoSuperMethodA(class,object,msg));
  554. }
  555.  
  556. STATIC VOID
  557. DeleteMatrixClass(VOID)
  558. {
  559.     if(MatrixClass)
  560.     {
  561.         FreeClass(MatrixClass);
  562.         MatrixClass = NULL;
  563.     }
  564. }
  565.  
  566. STATIC struct IClass *
  567. CreateMatrixClass(VOID)
  568. {
  569.     if(MatrixClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(MatrixInfo),0))
  570.         MatrixClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
  571.  
  572.     return(MatrixClass);
  573. }
  574.  
  575. VOID
  576. CloseMatrixWindow()
  577. {
  578.     CheckItem(MEN_MATRIX_WINDOW,FALSE);
  579.  
  580.     if(MatrixWindow)
  581.     {
  582.         ClearMenuStrip(MatrixWindow);
  583.  
  584.         CloseWindowSafely(MatrixWindow);
  585.  
  586.         MatrixWindow = NULL;
  587.     }
  588.  
  589.     if(MatrixGadget)
  590.     {
  591.         DisposeObject(MatrixGadget);
  592.  
  593.         MatrixGadget = NULL;
  594.     }
  595.  
  596.     DeleteMatrixClass();
  597. }
  598.  
  599. BOOL
  600. DispatchMatrixWindow(ULONG *MsgClass,UWORD MsgCode,ULONG MsgQualifier,UBYTE Char)
  601. {
  602.     if(MatrixWindow)
  603.     {
  604.         switch(*MsgClass)
  605.         {
  606.             case IDCMP_RAWKEY:
  607.  
  608.                 if(!(MsgCode & IECODE_UP_PREFIX) && !(MsgQualifier & IEQUALIFIER_REPEAT) && !(MsgCode >= CURSOR_UP_CODE && MsgCode <= F10_CODE) && !(MsgCode >= HELP_CODE && MsgCode <= RAMIGA_CODE))
  609.                 {
  610.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  611.                         MIA_Index,    Char,
  612.                     TAG_DONE);
  613.  
  614.                     Delay(TICKS_PER_SECOND / 10);
  615.  
  616.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  617.                         MIA_Index,    -1,
  618.                     TAG_DONE);
  619.                 }
  620.  
  621.                 break;
  622.  
  623.             case IDCMP_CLOSEWINDOW:
  624.  
  625.                 *MsgClass = 0;
  626.  
  627.                 return(TRUE);
  628.  
  629.             case IDCMP_GADGETUP:
  630.  
  631.                 *MsgClass = 0;
  632.  
  633.                 Char = MsgCode;
  634.  
  635.                 SerWrite(&Char,1);
  636.  
  637.                 break;
  638.  
  639.             case IDCMP_IDCMPUPDATE:
  640.  
  641.                 *MsgClass = 0;
  642.  
  643.                 if((WORD)MsgCode < 0)
  644.                     SetWindowTitles(MatrixWindow,LocaleString(MSG_MATRIX_WINDOW_TITLE),(STRPTR)~0);
  645.                 else
  646.                 {
  647.                     UBYTE    OctalBuffer[6],BinBuffer[10];
  648.                     LONG    i,Code;
  649.  
  650.                     OctalBuffer[0] = '0';
  651.  
  652.                     for(Code = MsgCode, i = 0 ; i < 3 ; i++)
  653.                     {
  654.                         OctalBuffer[2 - i + 1] = '0' + (Code & 7);
  655.  
  656.                         Code = Code >> 3;
  657.                     }
  658.  
  659.                     OctalBuffer[4] = 0;
  660.  
  661.                     BinBuffer[0] = '%';
  662.  
  663.                     for(Code = MsgCode, i = 0 ; i < 8 ; i++)
  664.                     {
  665.                         BinBuffer[7 - i + 1] = '0' + (Code & 1);
  666.  
  667.                         Code = Code >> 1;
  668.                     }
  669.  
  670.                     BinBuffer[9] = 0;
  671.  
  672.                     SPrintf(TitleBuffer,"%s [%ld · $%02lx · %s · %s]",LocaleString(MSG_MATRIX_WINDOW_TITLE),MsgCode,MsgCode,OctalBuffer,BinBuffer);
  673.  
  674.                     SetWindowTitles(MatrixWindow,TitleBuffer,(STRPTR)~0);
  675.                 }
  676.  
  677.                 break;
  678.         }
  679.     }
  680.  
  681.     return(FALSE);
  682. }
  683.  
  684. struct Window *
  685. OpenMatrixWindow(struct Window *Parent)
  686. {
  687.     if(MatrixWindow)
  688.     {
  689.         WindowToFront(MatrixWindow);
  690.  
  691.         ActivateWindow(MatrixWindow);
  692.  
  693.         return(MatrixWindow);
  694.     }
  695.     else
  696.     {
  697.         struct RastPort     RastPort;
  698.         struct TextFont    *Font;
  699.         LONG             i,MaxWidth,Width,Height;
  700.  
  701.         InitRastPort(&RastPort);
  702.         Font = OpenFont(&TextAttr);
  703.         SetFont(&RastPort,Font);
  704.  
  705.         for(i = 0, MaxWidth = 0 ; i < 256 ; i++)
  706.         {
  707.             if((Width = TextLength(&RastPort,CharCodes[i],strlen(CharCodes[i]))) > MaxWidth)
  708.                 MaxWidth = Width;
  709.         }
  710.  
  711.         Width    = 2 + MaxWidth + 2;
  712.         Height    = 2 + RastPort . TxHeight + 2;
  713.  
  714.         if(Parent -> WScreen -> WBorTop + Parent -> WScreen -> Font -> ta_YSize + 1 + Parent -> WScreen -> WBorBottom + 16 * Height > Parent -> WScreen -> Height || Parent -> WScreen -> WBorLeft + 16 * Width + Parent -> WScreen -> WBorRight > Parent -> WScreen -> Width)
  715.         {
  716.             DisplayBeep(Parent -> WScreen);
  717.  
  718.             return(NULL);
  719.         }
  720.  
  721.         if(CreateMatrixClass())
  722.         {
  723.             STATIC Tag Map[] = { MIA_Index, ICSPECIAL_CODE, TAG_DONE };
  724.  
  725.             if(MatrixGadget = NewObject(MatrixClass,NULL,
  726.                 GA_Left,            Parent -> WScreen -> WBorLeft + 2,
  727.                 GA_Top,                Parent -> WScreen -> WBorTop + Parent -> WScreen -> Font -> ta_YSize + 1 + 2,
  728.                 GA_Width,            16 * Width,
  729.                 GA_Height,            16 * Height,
  730.                 GA_RelVerify,        TRUE,
  731.  
  732.                 ICA_TARGET,            ICTARGET_IDCMP,
  733.                 ICA_MAP,            Map,
  734.  
  735.                 MIA_Width,            16,
  736.                 MIA_Height,            16,
  737.                 MIA_CellWidth,        Width,
  738.                 MIA_CellHeight,        Height,
  739.                 MIA_Labels,            CharCodes,
  740.                 MIA_NumLabels,        256,
  741.                 MIA_Font,            &TextAttr,
  742.             TAG_DONE))
  743.             {
  744.                 if(MatrixWindow = OpenWindowTags(NULL,
  745.                     WA_Top,                Parent -> TopEdge + Parent -> BorderTop,
  746.                     WA_Left,            Parent -> LeftEdge,
  747.                     WA_Title,            LocaleString(MSG_MATRIX_WINDOW_TITLE),
  748.                     WA_DepthGadget,        TRUE,
  749.                     WA_CloseGadget,        TRUE,
  750.                     WA_DragBar,            TRUE,
  751.                     WA_InnerWidth,        2 + (Width * 16) + 2,
  752.                     WA_InnerHeight,        2 + (Height * 16) + 2,
  753.                     WA_Activate,        TRUE,
  754.                     WA_Gadgets,            MatrixGadget,
  755.                     OpenWindowTag,        Parent -> WScreen,
  756.                     WA_NewLookMenus,    TRUE,
  757.                     BackfillTag,        &BackfillHook,
  758.                     WA_SimpleRefresh,    TRUE,
  759.  
  760.                     AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  761.                     CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  762.                 TAG_DONE))
  763.                 {
  764.                     MatrixWindow -> UserPort = Parent -> UserPort;
  765.  
  766.                     if(ModifyIDCMP(MatrixWindow,Parent -> IDCMPFlags | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | IDCMP_REFRESHWINDOW))
  767.                     {
  768.                         SetMenuStrip(MatrixWindow,Menu);
  769.  
  770.                         CheckItem(MEN_MATRIX_WINDOW,TRUE);
  771.  
  772.                         return(MatrixWindow);
  773.                     }
  774.  
  775.                     MatrixWindow -> UserPort = NULL;
  776.  
  777.                     CloseWindow(MatrixWindow);
  778.  
  779.                     MatrixWindow = NULL;
  780.                 }
  781.  
  782.                 DisposeObject(MatrixGadget);
  783.  
  784.                 MatrixGadget = NULL;
  785.             }
  786.  
  787.             DeleteMatrixClass();
  788.         }
  789.  
  790.         CheckItem(MEN_MATRIX_WINDOW,FALSE);
  791.  
  792.         return(NULL);
  793.     }
  794. }
  795.