home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 72 / af072sub.adf / bindt / bindt.lha / binarydt / source / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-19  |  29.7 KB  |  1,045 lines

  1. /*
  2. ** $PROJECT: binary.datatype
  3. **
  4. ** $VER: dispatch.c 39.10 (19.02.95)
  5. **
  6. ** by
  7. **
  8. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  9. **
  10. ** (C) Copyright 1994,1995
  11. ** All Rights Reserved !
  12. **
  13. ** $HISTORY:
  14. **
  15. ** 19.02.95 : 039.010 : fixed bug,which caused a crash ,if the display width was
  16. **                      less than the required width for the offsets.
  17. **                      prefs file parsing now via ReadArgs().
  18. **                      new prefs directory : 'Env:DataTypes' .
  19. ** 28.01.95 : 039.009 : fixed down scrolling bug, which skipped one line
  20. ** 22.01.95 : 039.008 : now supports DTM_PRINT method and searchs for PROGDIR:binary.prefs
  21. ** 21.01.95 : 039.007 : bug fixed. Rendering address higher than the file length (small files)
  22. ** 28.12.94 : 039.006 : now it's a base datatype and no async layout is needed
  23. ** 24.11.94 : 039.005 : memory handling improved, layout only performed if needed
  24. ** 18.11.94 : 039.004 : added PREFS file
  25. ** 16.11.94 : 039.003 : BDTDH_NONE now works
  26. ** 15.11.94 : 039.002 : added BDTA_BytesPerLine,BDTA_DisplayHex and BDTA_ShowASCII attrs
  27. ** 13.11.94 : 039.001 : initial
  28. */
  29.  
  30. /* ------------------------------- include -------------------------------- */
  31.  
  32. #include "classbase.h"
  33.  
  34. /* ------------------------------- autodoc -------------------------------- */
  35.  
  36. /*FS*/ /*"AutoDoc"*/
  37. /*GB*** binary.datatype/binary.datatype **************************************
  38. *
  39. *    NAME
  40. *        binary.datatype -- data type for any binary file
  41. *
  42. *    FUNCTION
  43. *        The binary data type, a base-class of all binary data, is used to
  44. *        load any binary file and displays the contents of the file in hex
  45. *        format.
  46. *
  47. *    PREFS
  48. *        The data type tries to load the prefs file first from
  49. *        "PROGDIR:Prefs/binary.prefs","PROGDIR:binary.prefs" and then
  50. *        "ENV:DataTypes/binary.prefs" on each OM_NEW method to set up the
  51. *        attributes !
  52. *        Up from version 39.10 it uses the ReadArgs() function to parse the
  53. *        prefs file. The template is :
  54. *
  55. *        NOASCII/S,NOWRAP/S,NONE/S,BYTE/S,WORD/S,LONG/S,BPL=BYTESPERLINE/N/K
  56. *
  57. *        NOASCII   - sets BDTA_ShowASCII to FALSE
  58. *        NOWRAP    - sets BDTA_DisplayWrap to FALSE
  59. *        NONE      - sets BDTA_DisplayHex to BDTDH_NONE
  60. *        BYTE      - sets BDTA_DisplayHex to BDTDH_BYTE
  61. *        WORD      - sets BDTA_DisplayHex to BDTDH_WORD
  62. *        LONG      - sets BDTA_DisplayHex to BDTDH_LONG
  63. *        BYTESPERLINE <bpl> or
  64. *        BPL <bpl> - sets BDTA_BytesPerLine to <bpl> bytes
  65. *
  66. *        The options can be on several lines !
  67. *
  68. *    METHODS
  69. *        OM_NEW -- Create a new text object from a binary file in hex mode.
  70. *
  71. *        OM_DISPOSE -- dispose a object
  72. *
  73. *        OM_GET -- get a attribute of the object
  74. *
  75. *        OM_SET -- set attributes of the object
  76. *
  77. *        OM_UPDATE -- update some attributes of the object
  78. *
  79. *        GM_LAYOUT -- Method to layout the hex text
  80. *
  81. *        GM_RENDER -- draw the object
  82. *
  83. *        DTM_WRITE -- DTWM_RAW mode is supported
  84. *
  85. *        DTM_PRINT -- prints the hex text
  86. *
  87. *    TAGS
  88. *        BDTA_Buffer -- (UBYTE *) pointer to the buffer, which should be
  89. *            displayed.
  90. *            Applicability is (ISG).
  91. *
  92. *        BDTA_BufferLen -- (ULONG) length of the buffer supplied with
  93. *            BDTA_Buffer tag. This must be given if the buffer tag is
  94. *            specified.
  95. *            Applicability is (ISG).
  96. *
  97. *        BDTA_BytesPerLine -- (UWORD) number of bytes per line.
  98. *            If BDTA_DisplayHex is BDTDH_WORD it must be a multiply of 2,
  99. *            if it is BDTDH_LONG it must be a multiply of 4 !
  100. *            Default is 32.
  101. *            Applicability is (ISGNU).
  102. *
  103. *        BDTA_DisplayHex -- (UWORD) type of the display. The following types
  104. *            are supported : BDTDH_NONE  - displays no hex values
  105. *                            BDTDH_BYTE  - displays each byte in hex ( 8 bit)
  106. *                            BDTDH_WORD  - displays each word in hex (16 bit)
  107. *                            BDTDH_LONG  - displays each long in hex (32 bit)
  108. *            Default is BDTDH_LONG.
  109. *            Applicability is (ISGNU).
  110. *
  111. *        BDTA_ShowASCII -- (BOOL) display at the end of the line the
  112. *            appropriate ASCII string !
  113. *            Default is TRUE.
  114. *            Applicability is (ISGNU).
  115. *
  116. *        BDTA_DisplayWrap -- (BOOL) the BDTA_BytesPerLine are ignored and the
  117. *            byte number is retrieved from the object width !
  118. *            Default is TRUE.
  119. *            Applicability is (ISGNU).
  120. *
  121. *    BUGS
  122. *        At the moment proportional fonts can't be handled.
  123. *
  124. *    SEE ALSO
  125. *        datatypesclass (where ?)
  126. *
  127. ******************************************************************************
  128. *
  129. */
  130. /*FE*/
  131.  
  132. /* ------------------------------- defines -------------------------------- */
  133.  
  134. #define G(o)               ((struct Gadget *) (o))
  135. #define GPR(msg)           ((struct gpRender *) (msg))
  136. #define SET(msg)           ((struct opSet *) (msg))
  137. #define WRMSG(msg)         ((struct dtWrite *) (msg))
  138.  
  139. #define prefstemplate      "NOASCII/S,NOWRAP/S,NONE/S,BYTE/S,WORD/S,LONG/S,BPL=BYTESPERLINE/N/K"
  140.  
  141. enum
  142. {
  143.    PREFSARG_NOASCII,
  144.    PREFSARG_NOWRAP,
  145.    PREFSARG_NONE,
  146.    PREFSARG_BYTE,
  147.    PREFSARG_WORD,
  148.    PREFSARG_LONG,
  149.    PREFSARG_BYTESPERLINE,
  150.    PREFSARG_MAX
  151. };
  152.  
  153. /* ---------------------------- instance data ----------------------------- */
  154.  
  155. struct BinaryData
  156. {
  157.    UBYTE *bd_Buffer;
  158.    UBYTE *bd_BufferEnd;
  159.    ULONG bd_BufferLen;
  160.  
  161.    UWORD bd_Flags;
  162.    UWORD bd_DisplayHex;
  163.    UWORD bd_BytesPerLine;
  164.  
  165.    UWORD bd_NumGroups;
  166.    UWORD bd_LineBytes;
  167.  
  168.    UWORD bd_LineBufferLen;
  169.    UBYTE *bd_LineBuffer;
  170.  
  171.    ULONG bd_OldX;
  172.    ULONG bd_OldY;
  173.  
  174.    /* font support */
  175.    struct TextFont *bd_Font;
  176.    struct TextAttr bd_TextAttr;
  177.    UBYTE bd_FontName[MAXFONTNAME];
  178.  
  179.    UBYTE bd_Name[256];
  180. };
  181.  
  182. #define BDF_SHOWASCII         (1<<0)
  183. #define BDF_ALLOCATED         (1<<1)
  184. #define BDF_DISPLAYWRAP       (1<<2)
  185.  
  186. /* ---------------------------- constant data ----------------------------- */
  187.  
  188. const ULONG methods[] = {
  189.    OM_NEW,
  190.    OM_DISPOSE,
  191.    OM_GET,
  192.    OM_SET,
  193.    OM_UPDATE,
  194.    GM_LAYOUT,
  195.    GM_RENDER,
  196.    DTM_WRITE,
  197.    DTM_PRINT,
  198.    ~0};
  199.  
  200. /* ------------------------------ init class ------------------------------ */
  201.  
  202. /*FS*/ LibCall Class *initClass(REGA6 struct ClassBase *cb)
  203. {
  204.    Class *cl;
  205.  
  206.    D(bug("init binary.datatype !\n"));
  207.  
  208.    if((cl = MakeClass("binary.datatype","datatypesclass",NULL,sizeof(struct BinaryData),0)))
  209.    {
  210.       cl->cl_Dispatcher.h_Entry = (HOOKFUNC) dispatch;
  211.       cl->cl_UserData = (ULONG) cb;
  212.  
  213.       AddClass(cl);
  214.    }
  215.  
  216.    return(cl);
  217. }
  218. /*FE*/
  219.  
  220. /* -------------------------- support functions --------------------------- */
  221.  
  222. /*FS*/ ULONG notifyAttrChanges(Object * obj, void * ginfo, ULONG flags, ULONG tag1,...)
  223. {
  224.     return(DoMethod(obj, OM_NOTIFY, &tag1, ginfo, flags));
  225. }
  226. /*FE*/
  227.  
  228. /*FS*/ ULONG setSuperAttrs(Class *cl,Object * obj, void *ginfo,ULONG tag1,...)
  229. {
  230.     return(DoSuperMethod(cl,obj, OM_SET, &tag1, ginfo));
  231. }
  232. /*FE*/
  233.  
  234. /*FS*/ BOOL readPrefs(struct ClassBase *cb,struct BinaryData *bd,STRPTR file)
  235. {
  236.    struct RDArgs *rdargs;
  237.    struct RDArgs *args;
  238.    BPTR fh;
  239.  
  240.    ENTERING;
  241.  
  242.    if((fh = Open(file,MODE_OLDFILE)))
  243.    {
  244.       UBYTE buf[256];
  245.       ULONG para[PREFSARG_MAX];
  246.       LONG i;
  247.  
  248.       DB(("def file %s opened\n",file));
  249.  
  250.       while(FGets(fh,buf,sizeof(buf)))
  251.       {
  252.          DB(("line : %s",buf));
  253.  
  254.          if((rdargs = (struct RDArgs *) AllocDosObject(DOS_RDARGS,NULL)))
  255.          {
  256.             rdargs->RDA_Source.CS_Buffer   = buf;
  257.             rdargs->RDA_Source.CS_Length   = strlen(buf);
  258.  
  259.             for(i=0 ; i < (sizeof(para)/sizeof(LONG)) ; i++)
  260.                para[i]=0;
  261.  
  262.             DB(("rdargs at : %lx\n",rdargs));
  263.             
  264.             if(args = ReadArgs(prefstemplate,(LONG *) para,rdargs))
  265.             {
  266.                DB(("args at %lx\n",args));
  267.  
  268.                if(para[PREFSARG_NOASCII])
  269.                   bd->bd_Flags &= ~BDF_SHOWASCII;
  270.  
  271.                if(para[PREFSARG_NOWRAP])
  272.                   bd->bd_Flags &= ~BDF_DISPLAYWRAP;
  273.  
  274.                if(para[PREFSARG_NONE])
  275.                   bd->bd_DisplayHex = BDTDH_NONE;
  276.  
  277.                if(para[PREFSARG_BYTE])
  278.                   bd->bd_DisplayHex = BDTDH_BYTE;
  279.  
  280.                if(para[PREFSARG_WORD])
  281.                   bd->bd_DisplayHex = BDTDH_WORD;
  282.  
  283.                if(para[PREFSARG_LONG])
  284.                   bd->bd_DisplayHex = BDTDH_LONG;
  285.  
  286.                if(para[PREFSARG_BYTESPERLINE])
  287.                {
  288.                   bd->bd_BytesPerLine = (UWORD) *((LONG *) para[PREFSARG_BYTESPERLINE]);
  289.  
  290.                   if(bd->bd_BytesPerLine < 4)
  291.                      bd->bd_BytesPerLine = 4;
  292.                   if(bd->bd_BytesPerLine > (1<<16))
  293.                      bd->bd_BytesPerLine = 32;
  294.                }
  295.             }
  296.             FreeDosObject(DOS_RDARGS , rdargs);
  297.          }
  298.       }
  299.       Close(fh);
  300.    }
  301.  
  302.    LEAVING;
  303.  
  304.    return((BOOL) (fh == NULL));
  305. }
  306. /*FE*/
  307.  
  308. /*FS*/ void useDefaultFont(struct ClassBase *cb,struct BinaryData *bd)
  309. {
  310.    struct TextFont *deffont;
  311.  
  312.    D(bug("using default font !\n"));
  313.  
  314.    #undef GfxBase
  315.    deffont = ((struct GfxBase *) cb->cb_GfxBase)->DefaultFont;
  316.    #define GfxBase cb->cb_GfxBase
  317.  
  318.    bd->bd_TextAttr.ta_YSize = deffont->tf_YSize;
  319.    bd->bd_TextAttr.ta_Style = FS_NORMAL;
  320.    bd->bd_TextAttr.ta_Flags = deffont->tf_Flags;
  321.    bd->bd_TextAttr.ta_Name  = bd->bd_FontName;
  322.    strcpy(bd->bd_TextAttr.ta_Name,deffont->tf_Message.mn_Node.ln_Name);
  323.  
  324.    bd->bd_Font = OpenFont(&bd->bd_TextAttr);
  325. }
  326. /*FE*/
  327.  
  328. /* --------------------------- class dispatcher --------------------------- */
  329.  
  330. /*FS*/ ClassCall ULONG dispatch(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg)
  331. {
  332.    struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  333.    struct BinaryData *bd = INST_DATA(cl,obj);
  334.    ULONG retval = 0;
  335.  
  336.    switch(msg->MethodID)
  337.    {
  338.    case OM_NEW:
  339.       {
  340.          Object *newobj;
  341.          if((newobj = (Object *) DoSuperMethodA(cl,obj,msg)))
  342.          {
  343.             bd = INST_DATA(cl,newobj);
  344.  
  345.             /* set default setting */
  346.             bd->bd_BytesPerLine = 32;
  347.             bd->bd_DisplayHex   = BDTDH_LONG;
  348.             bd->bd_Flags        = BDF_SHOWASCII | BDF_DISPLAYWRAP;
  349.  
  350.             /* read default user settings */
  351.             if(readPrefs(cb,bd,"PROGDIR:Prefs/binary.prefs"))
  352.                if(readPrefs(cb,bd,"PROGDIR:binary.prefs"))
  353.                   readPrefs(cb,bd,"ENV:DataTypes/binary.prefs");
  354.  
  355.             setattrs(cl,newobj,(struct opSet *) msg);
  356.  
  357.             /* use default textfont */
  358.             if(!bd->bd_Font)
  359.                useDefaultFont(cb,bd);
  360.  
  361.             /* if no buffer is provided , get the handle from the superclass
  362.                and load the file in the buffer */
  363.             if(!bd->bd_Buffer)
  364.             {
  365.                BPTR fh;
  366.                ULONG type;
  367.                LONG num;
  368.  
  369.                if(((num = GetDTAttrs((Object *) newobj,DTA_Handle     ,&fh,
  370.                                                        DTA_SourceType ,&type,
  371.                                                        TAG_DONE)) == 2) && fh)
  372.                {
  373.                   struct FileInfoBlock *fib;
  374.  
  375.                   D(bug("type : %ld\n",type));
  376.  
  377.                   switch(type)
  378.                   {
  379.                   case DTST_FILE:
  380.                      if((fib = AllocDosObject(DOS_FIB,NULL)))
  381.                      {
  382.                         if(ExamineFH(fh,fib) && fib->fib_Size > 0)
  383.                         {
  384.                            if((bd->bd_Buffer = AllocMem(fib->fib_Size,MEMF_ANY)))
  385.                            {
  386.                               bd->bd_Flags |= BDF_ALLOCATED;
  387.                               bd->bd_BufferLen = fib->fib_Size;
  388.                               bd->bd_BufferEnd = &bd->bd_Buffer[fib->fib_Size];
  389.                               Seek(fh,0,OFFSET_BEGINNING);
  390.                               Read(fh,bd->bd_Buffer,bd->bd_BufferLen);
  391.                            }
  392.                         }
  393.                      }
  394.                      FreeDosObject(DOS_FIB,fib);
  395.                      if(!NameFromFH(fh,bd->bd_Name,sizeof(bd->bd_Name)))
  396.                         strcpy(bd->bd_Name,"unknown");
  397.                      break;
  398.                   case DTST_RAM:
  399.                      strcpy(bd->bd_Name,"RAM");
  400.                      break;
  401.                   default:
  402.                      D(bug("not supported SourceType : %ld\n",type));
  403.                   }
  404.  
  405.                }
  406.             }
  407.  
  408.             if(bd->bd_Buffer)
  409.             {
  410.                retval = (ULONG) newobj;
  411.                setSuperAttrs(cl,newobj,NULL,GA_RelSpecial,TRUE,TAG_DONE);
  412.                ((struct ExtGadget *) newobj)->MoreFlags = GMORE_SCROLLRASTER;
  413.             } else  /* something was going wrong, thus dispose myself */
  414.             {
  415.                D(bug("binary.datatype error : %ld\n",IoErr()));
  416.                CoerceMethod(cl,(Object *) retval,OM_DISPOSE);
  417.             }
  418.          }
  419.       }
  420.       break;
  421.    case OM_DISPOSE:
  422.       if(bd->bd_Buffer && (bd->bd_Flags & BDF_ALLOCATED))
  423.          FreeMem(bd->bd_Buffer,bd->bd_BufferLen);
  424.  
  425.       if(bd->bd_LineBuffer && bd->bd_LineBufferLen)
  426.          FreeMem(bd->bd_LineBuffer,bd->bd_LineBufferLen);
  427.  
  428.       if(bd->bd_Font)
  429.          CloseFont(bd->bd_Font);
  430.  
  431.       retval = DoSuperMethodA(cl,obj,msg);
  432.       break;
  433.    case OM_UPDATE:
  434.    case OM_SET:
  435.       if((retval = setattrs(cl,obj,(struct opSet *) msg)))
  436.          DoMethod(obj,GM_LAYOUT,((struct opSet *) msg)->ops_GInfo,TRUE);
  437.  
  438.       /* Pass the attributes to the super class and force a refresh
  439.        * if we need it */
  440.       if((retval += DoSuperMethodA (cl, obj, msg)) && (OCLASS (obj) == cl))
  441.       {
  442.          struct RastPort *rp;
  443.  
  444.          /* Get a pointer to the rastport */
  445.          if((rp = ObtainGIRPort (((struct opSet *) msg)->ops_GInfo)))
  446.          {
  447.             struct gpRender gpr;
  448.  
  449.             /* Force a redraw */
  450.             gpr.MethodID   = GM_RENDER;
  451.             gpr.gpr_GInfo  = ((struct opSet *) msg)->ops_GInfo;
  452.             gpr.gpr_RPort  = rp;
  453.             gpr.gpr_Redraw = GREDRAW_UPDATE;
  454.             DoMethodA (obj, (Msg) &gpr);
  455.  
  456.             /* Release the temporary rastport */
  457.             ReleaseGIRPort (rp);
  458.          }
  459.  
  460.          retval = 0;
  461.       }
  462.       break;
  463.    case OM_GET:
  464.       if(!(retval = getattr(cl,obj,(struct opGet *) msg)))
  465.          retval = DoSuperMethodA(cl,obj,msg);
  466.       break;
  467.    case GM_LAYOUT:
  468.       /* Tell everyone that we are busy doing things */
  469.       notifyAttrChanges (obj, ((struct gpLayout *) msg)->gpl_GInfo, NULL,
  470.                          GA_ID,       G(obj)->GadgetID,
  471.                          DTA_Busy,    TRUE,
  472.                          TAG_DONE);
  473.  
  474.       /* Let the super-class partake */
  475.       retval = DoSuperMethodA (cl, obj, msg);
  476.  
  477.       retval += layout(cb, cl, obj, (struct gpLayout *) msg);
  478.  
  479.       break;
  480.  
  481.    case GM_RENDER:
  482.       {
  483.          struct RastPort *rp = GPR(msg)->gpr_RPort;
  484.          struct DrawInfo *dri = GPR(msg)->gpr_GInfo->gi_DrInfo;
  485.          struct Rectangle rect;
  486.          struct IBox *domain;
  487.          ULONG x,y;
  488.          ULONG ux,uy;
  489.          ULONG py,px;
  490.          LONG topy,topx,num;
  491.          LONG w,h;
  492.          LONG dx,dy,height;
  493.          LONG chrs;
  494.  
  495.          STRPTR ptr;
  496.  
  497.          UBYTE fgpen = (dri) ? dri->dri_Pens[TEXTPEN]       : 1;
  498.          UBYTE bgpen = (dri) ? dri->dri_Pens[BACKGROUNDPEN] : 0;
  499.  
  500.          D(bug("draw mode : %lx\n",GPR(msg)->gpr_Redraw));
  501.  
  502.          if(GetDTAttrs(obj,DTA_TopVert     ,&y,
  503.                            DTA_TopHoriz    ,&x,
  504.                            DTA_VisibleVert ,&h,
  505.                            DTA_VisibleHoriz,&w,
  506.                            DTA_VertUnit    ,&uy,
  507.                            DTA_HorizUnit   ,&ux,
  508.                            DTA_Domain      ,&domain,
  509.                            TAG_DONE) == 7)
  510.          {
  511.  
  512.             topy = y;
  513.             topx = x;
  514.  
  515.             height = (h-1) * uy;
  516.  
  517.             rect.MinX = domain->Left;
  518.             rect.MinY = domain->Top;
  519.             rect.MaxX = domain->Left + w * ux - 1;
  520.             rect.MaxY = domain->Top  + h * uy - 1;
  521.  
  522.             SetFont(GPR(msg)->gpr_RPort,bd->bd_Font);
  523.             SetABPenDrMd(rp,fgpen,bgpen,JAM2);
  524.  
  525.             y *= uy;
  526.             x *= ux;
  527.  
  528.             dx = (x - bd->bd_OldX);
  529.             dy = (y - bd->bd_OldY);
  530.  
  531.             bd->bd_OldX = x;
  532.             bd->bd_OldY = y;
  533.  
  534.             if(dx > domain->Width/2 || dx <-domain->Width/2)
  535.                dx = 0;
  536.  
  537.             if(dy > height/2 || dy < -height/2)
  538.                dy = 0;
  539.  
  540.             py = 0;
  541.             px = 0;
  542.  
  543.             if(dx || dy)
  544.                ScrollRasterBF(rp,dx,dy,
  545.                               rect.MinX,rect.MinY,rect.MaxX,rect.MaxY);
  546.  
  547.             D(bug("dx : %ld , dy : %ld\n",dx,dy));
  548.  
  549.             if(dx == 0)
  550.             {
  551.                if(dy < 0)
  552.                   height = -dy;
  553.                else if(dy > 0)
  554.                {
  555.                   py = height - dy;
  556.                   topy += ((domain->Height / uy) - dy/uy) - 1;
  557.                }
  558.             } else if(dx > 0)
  559.             {
  560.                px = w * ux - dx;
  561.                topx += (w - (dx/ux));
  562.                w = dx/ux;
  563.             } else
  564.             {
  565.                w = (-dx/ux);
  566.             }
  567.  
  568.             num = topy * bd->bd_BytesPerLine;
  569.             ptr = &bd->bd_Buffer[num];
  570.  
  571.             D(bug("py : %ld , height : %ld , topy : %ld\n",py,height,topy));
  572.  
  573.             for(; py <= height && ptr < bd->bd_BufferEnd ; py += rp->TxHeight)
  574.             {
  575.                if((chrs = formatline(bd,&ptr,bd->bd_LineBuffer,num) - topx) > w)
  576.                   chrs = w;
  577.  
  578.                if(chrs > 0)
  579.                {
  580.                   Move(rp,domain->Left + px,domain->Top + py + rp->TxBaseline);
  581.                   Text(rp,&bd->bd_LineBuffer[topx],chrs);
  582.                }
  583.  
  584.                num += bd->bd_BytesPerLine;
  585.             }
  586.          }
  587.       }
  588.       retval = DoSuperMethodA(cl,obj,msg);
  589.       break;
  590.    case DTM_WRITE:
  591.       switch(WRMSG(msg)->dtw_Mode)
  592.       {
  593.       case DTWM_RAW:
  594.          D(bug("dtWrite Rawmode : filehandle %lx !\n",WRMSG(msg)->dtw_FileHandle));
  595.          D(bug("attrs at : %lx\n",WRMSG(msg)->dtw_AttrList));
  596.          D({
  597.                struct TagItem *tstate = WRMSG(msg)->dtw_AttrList;
  598.                struct TagItem *tag;
  599.  
  600.                while((tag = NextTagItem(&tstate)))
  601.                   bug("{%08lx,%ld}\n",tag->ti_Tag,tag->ti_Data);
  602.            });
  603.  
  604.          Write(WRMSG(msg)->dtw_FileHandle,bd->bd_Buffer,bd->bd_BufferLen);
  605.          retval = 1;
  606.          break;
  607.       default:
  608.          retval = DoSuperMethodA(cl,obj,msg);
  609.       }
  610.       break;
  611.    case DTM_PRINT:
  612.       {
  613.          union printerIO *pio = ((struct dtPrint *) msg)->dtp_PIO;
  614.          STRPTR ptr;
  615.          STRPTR buf;
  616.          LONG len;
  617.          ULONG num = 0;
  618.  
  619.          ptr = &bd->bd_Buffer[0];
  620.  
  621.          if((buf = AllocVec(bd->bd_LineBufferLen,MEMF_ANY)))
  622.          {
  623.             pio->ios.io_Command = CMD_WRITE;
  624.             pio->ios.io_Data    = buf;
  625.  
  626.             while(ptr < bd->bd_BufferEnd && pio->ios.io_Error  == 0)
  627.             {
  628.                len = formatline(bd,&ptr,buf,num);
  629.  
  630.                if(len > 0)
  631.                {
  632.                   buf[len] = '\n';
  633.                   pio->ios.io_Length = len + 1;
  634.                   DoIO((struct IORequest *) &pio->ios);
  635.                }
  636.                num += bd->bd_BytesPerLine;
  637.             }
  638.             FreeVec(buf);
  639.          }
  640.       }
  641.       break;
  642.    default:
  643.       retval = DoSuperMethodA(cl,obj,msg);
  644.    }
  645.  
  646.    return(retval);
  647. }
  648. /*FE*/
  649.  
  650. /*FS*/ ULONG getattr(Class *cl,Object *obj,struct opGet *msg)
  651. {
  652.    struct BinaryData *bd = INST_DATA(cl,obj);
  653.    ULONG *storage = msg->opg_Storage;
  654.  
  655.    switch(msg->opg_AttrID)
  656.    {
  657.    case DTA_TextFont:
  658.       *storage = (ULONG) bd->bd_Font;
  659.       break;
  660.    case DTA_TextAttr:
  661.       *storage = (ULONG) &bd->bd_TextAttr;
  662.       break;
  663.    case DTA_Methods:
  664.       *storage = (ULONG) methods;
  665.       break;
  666.    case BDTA_Buffer:
  667.       *storage = (ULONG) bd->bd_Buffer;
  668.       break;
  669.    case BDTA_BufferLen:
  670.       *storage = (ULONG) bd->bd_BufferLen;
  671.       break;
  672.    case BDTA_BytesPerLine:
  673.       *storage = (ULONG) bd->bd_BytesPerLine;
  674.       break;
  675.    case BDTA_DisplayHex:
  676.       *storage = (ULONG) bd->bd_DisplayHex;
  677.       break;
  678.    case BDTA_ShowASCII:
  679.       *storage = (ULONG) ((bd->bd_Flags & BDF_SHOWASCII) == BDF_SHOWASCII);
  680.       break;
  681.    case BDTA_DisplayWrap:
  682.       *storage = (ULONG) ((bd->bd_Flags & BDF_DISPLAYWRAP) == BDF_DISPLAYWRAP);
  683.       break;
  684.    default:
  685.       return(0);
  686.    }
  687.    return(1);
  688. }
  689. /*FE*/
  690.  
  691. /*FS*/ ULONG setattrs(Class *cl,Object *obj,struct opSet *msg)
  692. {
  693.    struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  694.    struct BinaryData *bd = INST_DATA(cl,obj);
  695.  
  696.    struct TagItem *tstate = msg->ops_AttrList;
  697.    struct TagItem *tag;
  698.  
  699.    ULONG retval = 0;
  700.    ULONG tidata;
  701.  
  702.    while((tag = NextTagItem(&tstate)))
  703.    {
  704.       tidata = tag->ti_Data;
  705.  
  706.       retval++;
  707.       switch(tag->ti_Tag)
  708.       {
  709.       case DTA_TextAttr:
  710.          {
  711.             struct TextFont *font;
  712.  
  713.             if((font = OpenFont((struct TextAttr *) tidata)))
  714.             {
  715.                /* only use fixed width fonts */
  716.                if(font->tf_Flags & FPF_PROPORTIONAL)
  717.                {
  718.                   CloseFont(font);
  719.                   useDefaultFont(cb,bd);
  720.                } else
  721.                {
  722.                   bd->bd_TextAttr = *((struct TextAttr *) tidata);
  723.                   bd->bd_TextAttr.ta_Name = bd->bd_FontName;
  724.                   strcpy(bd->bd_FontName,((struct TextAttr *) tidata)->ta_Name);
  725.  
  726.                   if(bd->bd_Font)
  727.                      CloseFont(bd->bd_Font);
  728.  
  729.                   bd->bd_Font = font;
  730.                }
  731.             } else
  732.                retval--;
  733.          }
  734.          break;
  735.       case BDTA_Buffer:
  736.          {
  737.             ULONG len = GetTagData(BDTA_BufferLen,0,msg->ops_AttrList);
  738.  
  739.             if(tidata && len)
  740.             {
  741.                if((bd->bd_Buffer) && (bd->bd_Flags & BDF_ALLOCATED))
  742.                   FreeMem(bd->bd_Buffer,bd->bd_BufferLen);
  743.  
  744.                bd->bd_Flags &= ~BDF_ALLOCATED;
  745.  
  746.                bd->bd_Buffer    = (UBYTE *) tidata;
  747.                bd->bd_BufferLen = len;
  748.                bd->bd_BufferEnd = &bd->bd_Buffer[len];
  749.  
  750.                retval++;
  751.             } else
  752.                retval--;
  753.          }
  754.          break;
  755.       case BDTA_BytesPerLine:
  756.          if(tag->ti_Data != bd->bd_BytesPerLine)
  757.             bd->bd_BytesPerLine = (UWORD) tag->ti_Data;
  758.          else
  759.             retval--;
  760.          break;
  761.       case BDTA_DisplayHex:
  762.          if(tag->ti_Data != bd->bd_DisplayHex)
  763.             bd->bd_DisplayHex   = (UWORD) tag->ti_Data;
  764.          else
  765.             retval--;
  766.          break;
  767.       case BDTA_ShowASCII:
  768.          if(tag->ti_Data)
  769.             bd->bd_Flags |= BDF_SHOWASCII;
  770.          else
  771.             bd->bd_Flags &= ~BDF_SHOWASCII;
  772.          break;
  773.       case BDTA_DisplayWrap:
  774.          if(tag->ti_Data)
  775.             bd->bd_Flags |= BDF_DISPLAYWRAP;
  776.          else
  777.             bd->bd_Flags &= ~BDF_DISPLAYWRAP;
  778.          break;
  779.       default:
  780.          retval--;
  781.       }
  782.    }
  783.  
  784.    return(retval);
  785. }
  786. /*FE*/
  787.  
  788. /*FS*/ GetA4 ULONG layout(struct ClassBase *cb, Class * cl, Object * obj, struct gpLayout * gpl)
  789. {
  790.    struct DTSpecialInfo *si = (struct DTSpecialInfo *) G(obj)->SpecialInfo;
  791.    struct BinaryData *bd = INST_DATA(cl,obj);
  792.  
  793.    struct TextFont *font = bd->bd_Font;
  794.  
  795.    /* Attributes obtained from super-class */
  796.    struct IBox *domain;
  797.  
  798.    ULONG retval = 0;
  799.  
  800.    ENTERING;
  801.  
  802.    /* Get all the attributes that we are going to need for a successful layout */
  803.    if((GetDTAttrs(obj,DTA_Domain,      (ULONG) &domain,
  804.                       TAG_DONE) == 1))
  805.    {
  806.       /* Lock the global object data so that nobody else can manipulate it */
  807.       ObtainSemaphore (&(si->si_Lock));
  808.  
  809.       retval = si->si_TotVert;
  810.  
  811.       /* We only need to perform layout if we are doing word wrap, or this
  812.        * is the initial layout call */
  813.       if(gpl->gpl_Initial || (bd->bd_Flags & BDF_DISPLAYWRAP))
  814.       {
  815.          const UBYTE displayhexbytes[]   = {0,3,5,9};
  816.          const UBYTE displayasciibytes[] = {1,1,2,4};
  817.  
  818.          WORD displayaddr = (bd->bd_BufferLen >= (1<<16)) ? 10 : 6;
  819.          WORD numgroups;
  820.          WORD bytesperline;
  821.          WORD showascii = 0;
  822.          LONG lines;
  823.  
  824.          D(bug("calc new layout values !\n"));
  825.  
  826.          if((bd->bd_Flags & BDF_SHOWASCII) || bd->bd_DisplayHex == BDTDH_NONE)
  827.             showascii = 1;
  828.  
  829.          numgroups    =
  830.          bytesperline = bd->bd_BytesPerLine;
  831.  
  832.          if(bd->bd_DisplayHex > 0)
  833.             numgroups >>= (bd->bd_DisplayHex - 1);
  834.  
  835.          /* Note this wrap function doesn't work right with proportional fonts ! */
  836.          if(bd->bd_Flags & BDF_DISPLAYWRAP)
  837.          {
  838.             ULONG chars = domain->Width / bd->bd_Font->tf_XSize;
  839.  
  840.             D(bug("object width : %ld\n",domain->Width));
  841.             D(bug("font width   : %ld\n",font->tf_XSize));
  842.             D(bug("chars        : %ld\n",chars));
  843.  
  844.             if(chars > displayaddr + showascii)
  845.             {
  846.                bytesperline =
  847.                numgroups    = (chars - displayaddr - showascii) / (displayhexbytes[bd->bd_DisplayHex] +
  848.                                                                    ((showascii) ? displayasciibytes[bd->bd_DisplayHex] : 0));
  849.  
  850.                if(numgroups < 1)
  851.                   numgroups = 1;
  852.             } else
  853.                numgroups = 1;
  854.  
  855.             if(bd->bd_DisplayHex > 0)
  856.                bytesperline = (numgroups) << (bd->bd_DisplayHex - 1);
  857.          }
  858.  
  859.          if(bytesperline < 4)
  860.          {
  861.             bytesperline  = 4;
  862.             numgroups     = 4 / displayasciibytes[bd->bd_DisplayHex];
  863.          }
  864.  
  865.          lines = (bd->bd_BufferLen / bytesperline) + ((bd->bd_BufferLen % bytesperline) ? 1 : 0) - 1;
  866.  
  867.          bd->bd_LineBytes = displayaddr + numgroups * displayhexbytes[bd->bd_DisplayHex] +
  868.                             ((showascii) ? bytesperline : 0) + 1;
  869.          bd->bd_NumGroups    = numgroups;
  870.          bd->bd_BytesPerLine = bytesperline;
  871.  
  872.          if(bd->bd_LineBuffer && bd->bd_LineBytes > bd->bd_LineBufferLen)
  873.          {
  874.             FreeMem(bd->bd_LineBuffer,bd->bd_LineBufferLen);
  875.             bd->bd_LineBuffer = NULL;
  876.          }
  877.  
  878.          if(!bd->bd_LineBuffer)
  879.          {
  880.             bd->bd_LineBufferLen = bd->bd_LineBytes;
  881.             bd->bd_LineBuffer    = AllocMem(bd->bd_LineBufferLen,MEMF_ANY);
  882.          }
  883.  
  884.          /* Compute the lines and columns type information */
  885.          si->si_VertUnit  = font->tf_YSize;
  886.          si->si_VisVert   = domain->Height / si->si_VertUnit;
  887.          si->si_TotVert   = lines;
  888.  
  889.          si->si_HorizUnit = font->tf_XSize;
  890.          si->si_VisHoriz  = domain->Width / font->tf_XSize;
  891.          si->si_TotHoriz  = bd->bd_LineBytes;
  892.  
  893.          /* Release the global data lock */
  894.          ReleaseSemaphore(&si->si_Lock);
  895.  
  896.          retval = lines;
  897.  
  898.          D(bug("after releasesem !\n"));
  899.  
  900.          if(gpl->gpl_Initial)
  901.          {
  902.             struct RastPort *rp;
  903.  
  904.             /* Get a pointer to the rastport */
  905.             if((rp = ObtainGIRPort (gpl->gpl_GInfo)))
  906.             {
  907.                struct gpRender gpr;
  908.  
  909.                /* Force a redraw */
  910.                gpr.MethodID   = GM_RENDER;
  911.                gpr.gpr_GInfo  = gpl->gpl_GInfo;
  912.                gpr.gpr_RPort  = rp;
  913.                gpr.gpr_Redraw = GREDRAW_REDRAW;
  914.                DoMethodA (obj, (Msg) &gpr);
  915.  
  916.                /* Release the temporary rastport */
  917.                ReleaseGIRPort (rp);
  918.             }
  919.          }
  920.       } else
  921.          ReleaseSemaphore(&si->si_Lock);
  922.  
  923.       /* Not aborted, so tell the world of our newest attributes */
  924.       notifyAttrChanges (obj, gpl->gpl_GInfo, NULL,
  925.                          GA_ID,                   G(obj)->GadgetID,
  926.  
  927.                          DTA_VisibleVert,         domain->Height / font->tf_YSize,
  928.                          DTA_TotalVert,           retval,
  929.                          DTA_NominalVert,         font->tf_YSize * 25,
  930.                          DTA_VertUnit,            font->tf_YSize,
  931.  
  932.                          DTA_VisibleHoriz,        domain->Width / font->tf_XSize,
  933.                          DTA_TotalHoriz,          bd->bd_LineBytes,
  934.                          DTA_NominalHoriz,        font->tf_XSize * 80,
  935.                          DTA_HorizUnit,           font->tf_XSize,
  936.  
  937.                          DTA_Title,               bd->bd_Name,
  938.                          DTA_Busy,                FALSE,
  939.                          DTA_Sync,                TRUE,
  940.                          TAG_DONE);
  941.  
  942.    }
  943.  
  944.    LEAVING;
  945.  
  946.    return(retval);
  947. }
  948. /*FE*/
  949.  
  950. /*FS*/ LONG formatline(struct BinaryData *bd,STRPTR *start,STRPTR buf,ULONG num)
  951. {
  952.    STRPTR bptr = *start;
  953.    STRPTR ptr  = bptr;
  954.    STRPTR ptr1 = buf;
  955.    UWORD numadd = (bd->bd_BufferLen > ((1<<16) - 1)) ? 10 : 6;
  956.    UWORD grp;
  957.  
  958.    if(numadd == 10)
  959.       sprintf(ptr1,"%08lx: ",num);
  960.    else
  961.       sprintf(ptr1,"%04lx: ",num);
  962.    ptr1 += numadd;
  963.  
  964.    switch(bd->bd_DisplayHex)
  965.    {
  966.    case BDTDH_BYTE:
  967.       for(grp = 0 ; grp < bd->bd_NumGroups && ptr < bd->bd_BufferEnd ; grp++)
  968.       {
  969.          sprintf(ptr1,"%02lx ",*ptr);
  970.          ptr++;
  971.          ptr1 += 3;
  972.       }
  973.  
  974.       while(grp < bd->bd_NumGroups)
  975.       {
  976.          strcpy(ptr1,"   ");
  977.          ptr1 += 3;
  978.          ptr++;
  979.          grp++;
  980.       }
  981.       break;
  982.    case BDTDH_WORD:
  983.       for(grp = 0 ; grp < bd->bd_NumGroups && ptr < bd->bd_BufferEnd ; grp++)
  984.       {
  985.          sprintf(ptr1,"%04lx ",*((UWORD *) ptr));
  986.          ptr += sizeof(UWORD);
  987.          ptr1 += 5;
  988.       }
  989.  
  990.       while(grp < bd->bd_NumGroups)
  991.       {
  992.          strcpy(ptr1,"     ");
  993.          ptr1 += 5;
  994.          ptr += sizeof(UWORD);
  995.          grp++;
  996.       }
  997.       break;
  998.    case BDTDH_LONG:
  999.       for(grp = 0 ; grp < bd->bd_NumGroups && ptr < bd->bd_BufferEnd ; grp++)
  1000.       {
  1001.          sprintf(ptr1,"%08lx ",*((ULONG *) ptr));
  1002.          ptr += sizeof(ULONG);
  1003.          ptr1 += 9;
  1004.       }
  1005.  
  1006.       while(grp < bd->bd_NumGroups)
  1007.       {
  1008.          strcpy(ptr1,"         ");
  1009.          ptr1 += 9;
  1010.          ptr += sizeof(ULONG);
  1011.          grp++;
  1012.       }
  1013.       break;
  1014.    default:
  1015.       ptr += bd->bd_BytesPerLine;
  1016.    }
  1017.  
  1018.    /* write ASCII string */
  1019.    if((bd->bd_Flags & BDF_SHOWASCII) ||
  1020.       (bd->bd_DisplayHex == BDTDH_NONE))
  1021.    {
  1022.       while(bptr < ptr && bptr < bd->bd_BufferEnd)
  1023.       {
  1024.          if(*bptr < 32)
  1025.             *ptr1 = '.';
  1026.          else
  1027.             *ptr1 = *bptr;
  1028.          ptr1++;
  1029.          bptr++;
  1030.       }
  1031.  
  1032.       while(bptr < ptr)
  1033.       {
  1034.          *ptr1++ = ' ';
  1035.          bptr++;
  1036.       }
  1037.    }
  1038.  
  1039.    *start = ptr;
  1040.  
  1041.    return((LONG) (ptr1 - buf));
  1042. }
  1043. /*FE*/
  1044.  
  1045.