[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

;/* cliptext.c - Execute me to compile me with Lattice 5.10a
LC -cfistq -v -y -j73 cliptext.c
Blink FROM LIB:c.o,cliptext.o TO cliptext LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;
**
** The following example, cliptext.c, renders the contents of a text
** file to a Workbench window.  This example gets the new aspect ratio
** for a font by asking the display database what the aspect ratio of
** the current display mode is.
*/
#include <exec/types.h>
#include <dos/rdargs.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <graphics/displayinfo.h>
#include <graphics/regions.h>
#include <graphics/gfx.h>
#include <libraries/diskfont.h>
#include <libraries/diskfonttag.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/layers_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: cliptext 37.2";

#define BUFSIZE          4096
#define FONT_NAME        0
#define FONT_SIZE        1
#define FILE_NAME        2
#define JAM_MODE         3
#define XASP             4
#define YASP             5
#define NUM_ARGS         6
#define DEFAULTFONTSIZE  11L
#define DEFAULTJAMMODE   0L
#define DEFAULTXASP      0L
#define DEFAULTYASP      0L

void MainLoop(void);

LONG args[NUM_ARGS];
struct TagItem tagitem[2];
UBYTE buffer[BUFSIZE];
BPTR myfile;
struct Library *DiskfontBase, *IntuitionBase, *LayersBase, *GfxBase;
struct IntuiMessage *mymsg;
struct DrawInfo *mydrawinfo;
struct Window *mywin;
struct RastPort *myrp;
struct TTextAttr myta;
struct TextFont *myfont;
struct Rectangle myrectangle;
struct Region *new_region;

void main(int argc, char **argv)
{
  struct RDArgs *myrda;
  struct DisplayInfo mydi;
  ULONG mymodeid;

  LONG mydefaultfontsize = DEFAULTFONTSIZE;
  LONG mydefaultJAMMode = DEFAULTJAMMODE;
  LONG mydefaultXASP = 0L;
  LONG mydefaultYASP = 0L;
  args[FONT_NAME] = (LONG)"topaz.font";
  args[FONT_SIZE] = (LONG)&mydefaultfontsize;
  args[FILE_NAME] = (LONG)"s:startup-sequence";
  args[JAM_MODE]  = (LONG)&mydefaultJAMMode;
  args[XASP]      = (LONG)&mydefaultXASP;
  args[YASP]      = (LONG)&mydefaultYASP;

  /* dos.library standard command line parsing--See the dos.library Autodoc for details */
  if (myrda = ReadArgs("FontName,FontSize/N,FileName,Jam/N,XASP/N,YASP/N\n", args, NULL))
  {
    if (myfile = Open((UBYTE *)args[FILE_NAME], MODE_OLDFILE) )   /* Open the file to display. */
    {
      if (DiskfontBase = OpenLibrary("diskfont.library", 37L))          /* Open the libraries. */
      {
        if (IntuitionBase = OpenLibrary("intuition.library", 37L))
        {
          if (GfxBase = OpenLibrary("graphics.library", 37L))
          {
            if (LayersBase = OpenLibrary("layers.library", 37L))
            {
              if (mywin = OpenWindowTags(NULL,                            /* Open that window. */
                     WA_MinWidth,     100,     /* This application wants to hear about three   */
                     WA_MinHeight,    100,     /* things: 1) When the user clicks the window's */
                     WA_SmartRefresh, TRUE,    /* close gadget, 2) when the user starts to     */
                     WA_SizeGadget,   TRUE,    /* resize the window, 3) and when the user has  */
                     WA_CloseGadget,  TRUE,    /* finished resizing the window.                */
                     WA_IDCMP,       IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY,
                     WA_DragBar,     TRUE,
                     WA_DepthGadget, TRUE,
                     WA_Title,       (ULONG)args[FILE_NAME],
                     TAG_END))
              {
                tagitem[0].ti_Tag = OT_DeviceDPI;

                /* See if there is a non-zero value in the XASP or YASP fields. Diskfont.library */
                /* will get a divide by zero GURU if you give it a zero XDPI or YDPI value.      */

                /* if there is a zero value in one of them... */
                if (  ( (*(ULONG *)args[XASP]) == 0) || ( (*(ULONG *)args[YASP]) == 0)  )
                {
                  /* ...then use the aspect ratio of the current display as a default... */
                  mymodeid = GetVPModeID(&(mywin->WScreen->ViewPort));
                  if (GetDisplayInfoData( NULL, (UBYTE *)&mydi,
                                          sizeof(struct DisplayInfo), DTAG_DISP, mymodeid))
                  {
                    mydefaultXASP = mydi.Resolution.x;
                    mydefaultYASP = mydi.Resolution.y;
                    printf("XAsp = %ld    YAsp = %ld\n", mydefaultXASP, mydefaultYASP);
                    /* Notice that the X and Y get _swapped_ to keep the look of the    */
                    /* font glyphs the same using screens with different aspect ratios. */
                    args[YASP]    = (LONG)&mydefaultXASP;
                    args[XASP]    = (LONG)&mydefaultYASP;
                  }
                  else /* ...unless something is preventing us from getting the screen  */
                       /* screens resolution.  In that case, forget about the DPI tag.  */
                       tagitem[0].ti_Tag = TAG_END;
                }
                /* Here we have to put the X and Y DPI into the OT_DeviceDPI tags data field.  */
                /* THESE ARE NOT REAL X AND Y DPI VALUES FOR THIS FONT OR DISPLAY. They only   */
                /* serve to supply the diskfont.library with values to calculate the aspect    */
                /* ratio.  The X value gets stored in the upper word of the tag value and the Y*/
                /* DPI gets stored in the lower word.  Because ReadArgs() stores the _address_ */
                /* of integers it gets from the command line, you have to dereference the      */
                /* pointer it puts into the argument array, which results in some ugly casting.*/

                tagitem[0].ti_Data = (ULONG)( ( (UWORD) *( (ULONG *)args[XASP] ) << 16) |
                                               ((UWORD) *( (ULONG *)args[YASP]) ) );
                tagitem[1].ti_Tag = TAG_END;

                myta.tta_Name = (STRPTR)args[FONT_NAME];           /* Set up the TTextAttr     */
                myta.tta_YSize = *((LONG *)args[FONT_SIZE]);       /* structure to match the   */
                myta.tta_Style = FSF_TAGGED;                       /* font the user requested. */
                myta.tta_Flags = 0L;
                myta.tta_Tags = tagitem;

                if (myfont = OpenDiskFont(&myta))       /* open that font */
                {
                 /* This is for the layers.library clipping region that gets attached to the   */
                 /* window.  This prevents the application from unnecessarily rendering beyond */
                  myrectangle.MinX = mywin->BorderLeft; /* the bounds of the inner part of     */
                  myrectangle.MinY = mywin->BorderTop;  /* the window.  For now, you can       */
                  myrectangle.MaxX = mywin->Width -     /* ignore the layers stuff if you are  */
                      (mywin->BorderRight + 1);         /* just interested in learning about   */
                  myrectangle.MaxY = mywin->Height -    /* using text.  For more information   */
                      (mywin->BorderBottom + 1);        /* on clipping regions and layers, see */
                                                        /* the Layers chapter of this manual.  */

                  if (new_region = NewRegion())                           /* more layers stuff */
                  {
                    if (OrRectRegion(new_region, &myrectangle));     /* Even more layers stuff */
                    {
                      InstallClipRegion(mywin->WLayer, new_region);
                      /* Obtain a pointer to the window's rastport and set up some of the      */
                      myrp = mywin->RPort;    /* rastport attributes. This example obtains the */
                      SetFont(myrp, myfont);  /* text pen for the window's screen using        */
                      if (mydrawinfo =GetScreenDrawInfo(mywin->WScreen)) /* GetScreenDrawInfo()*/
                      {
                        SetAPen(myrp, mydrawinfo->dri_Pens[TEXTPEN]);
                        FreeScreenDrawInfo(mywin->WScreen, mydrawinfo);
                      }
                      SetDrMd(myrp, (BYTE)(*((LONG *)args[JAM_MODE])));

                      MainLoop();
                    }
                    DisposeRegion(new_region);
                  }
                  CloseFont(myfont);
                }
                CloseWindow(mywin);
              }
              CloseLibrary(LayersBase);
            }
            CloseLibrary(GfxBase);
          }
          CloseLibrary(IntuitionBase);
        }
        CloseLibrary(DiskfontBase);
      }
      Close(myfile);
    }
    FreeArgs(myrda);
  }
  else VPrintf("Error parsing arguments\n", NULL);
}


void MainLoop(void)
{
    LONG count, actual, position;
    BOOL aok = TRUE, waitfornewsize = FALSE;
    struct Task *mytask;

    mytask = FindTask(NULL);
    Move(myrp, mywin->BorderLeft + 1, mywin->BorderTop + myfont->tf_YSize + 1);

    while (((actual = Read(myfile, buffer, BUFSIZE)) > 0) && aok) /* While there's something   */
    {                                                             /* to read, fill the buffer. */
        position = 0;
        count = 0;

        while (position <= actual)
        {
           if (!(waitfornewsize))
           {
               while ( ((buffer[count] >= myfont->tf_LoChar) &&
                       (buffer[count] <= myfont->tf_HiChar)) && (count <= actual) )
                   count++;

               Text(myrp, &(buffer[position]), (count)-position);

               while ( ((buffer[count] < myfont->tf_LoChar) ||
                       (buffer[count] > myfont->tf_HiChar)) && (count <= actual) )
               {
                   if (buffer[count] == 0x0A)
                       Move(myrp, mywin->BorderLeft, myrp->cp_y + myfont->tf_YSize + 1);
                   count++;
               }
               position = count;
           }
           else WaitPort(mywin->UserPort);

           while (mymsg = (struct IntuiMessage *)GetMsg(mywin->UserPort))
           {
               if (mymsg->Class == IDCMP_CLOSEWINDOW)     /* The user clicked the close gadget */
               {
                   aok = FALSE;
                   position = actual + 1;
                   ReplyMsg((struct Message *)mymsg);
               }                                                     /* The user picked up the */
               else if (mymsg->Class == IDCMP_SIZEVERIFY)            /* window's sizing gadget */
               {
                  /* When the user has picked up the window's sizing gadget when the           */
                  /* IDCMP_SIZEVERIFY flag is set, the application has to reply to this message*/
                  /* to tell Intuition to allow the user to move the sizing gadget and resize  */
                  /* the window.  The reason for using this here is because the user can resize*/
                  /* the window while cliptext.c is rendering text to the window. Cliptext.c   */
                  /* has to stop rendering text when it receives an IDCMP_SIZEVERIFY message.  */
                  /*                                                                           */
                  /* if this example had instead asked to hear about IDCMP events that could   */
                  /* take place between SIZEVERIFY and NEWSIZE events (especially INTUITICKS), */
                  /* it should turn off those events here using ModifyIDCMP().                 */
                  /*                                                                           */
                  /* After we allow the user to resize the window, we cannot write into the    */
                  /* window until the user has finished resizing it because we need the        */
                  /* window's new size to adjust the clipping area.  Specifically, we have     */
                  /* to wait for an IDCMP_NEWSIZE message which Intuition will send when the   */
                  /* user lets go of the resize gadget.  For now, we set the waitfornewsize    */
                  /* flag to stop rendering until we get that NEWSIZE message.                 */

                   waitfornewsize = TRUE;
                   WaitBlit();

                   ReplyMsg((struct Message *)mymsg);            /* The blitter is done, let the */
               }                                                 /* user resize the window.      */
               else
               {
                   ReplyMsg((struct Message *)mymsg);
                   waitfornewsize = FALSE;
                          /* The user has resized the window, so get the new window dimensions */
                   myrectangle.MinX = mywin->BorderLeft;      /* and readjust the layers       */
                   myrectangle.MinY = mywin->BorderTop;       /* clipping region accordingly.  */
                   myrectangle.MaxX = mywin->Width - (mywin->BorderRight + 1);
                   myrectangle.MaxY = mywin->Height - (mywin->BorderBottom + 1);
                   InstallClipRegion(mywin->WLayer, NULL);
                   ClearRegion(new_region);
                   if (OrRectRegion(new_region, &myrectangle))
                       InstallClipRegion(mywin->WLayer, new_region);
                   else
                   {
                       aok = FALSE;
                       position = actual + 1;
                   }
               }
           }
           if (mytask->tc_SigRecvd & SIGBREAKF_CTRL_C)              /* Check for user break.   */
           {
               aok = FALSE;
               position = actual + 1;
           }

           if (myrp->cp_y > (mywin->Height - (mywin->BorderBottom + 2))) /* if we reached the  */
           {                                               /* bottom of the page, clear the    */
               Delay(25);                                  /* rastport and move back to the top*/

               SetRast(myrp, 0);      /* Set the entire rastport to color zero.  This will not */
               Move(myrp,             /* the window borders because of the layers clipping.    */
               mywin->BorderLeft + 1,
               mywin->BorderTop + myfont->tf_YSize + 1);
            }
        }
    }
    if (actual < 0) VPrintf("Error while reading\n", NULL);
}


[Back to Amiga Developer Docs]