/****************************** ITextEd.c ************************************
 *
 *  ITextEd() - IntuiText Editor Requester for the Gadget editor
 *  
 *  By Ray R. Larson
 *
 *  Copyright (C) 1986. All rights reserved.
 *
 *  This program is freely distributable as long as this copyright notice
 *  is retained. It intended for personal, non-commercial use.  
 *
 ***************************************************************************/

 
#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <ctype.h>
#include <stdio.h>
#include <workbench/workbench.h>

/* ========================================================================*/
/* Intuitext requester gadget ids                                          */

#define CLASSBITS 8

#define UPDOWNCLASS 1
#define CHOICECLASS 2
#define CHANGECLASS 3
#define BUTTONCLASS 4

#define GADGETNUM 255

#define LOAD   0
#define CANCEL 1
#define ADDTXT 2

#define UP     0
#define DOWN   1
#define POT    2

#define ITXT0  0
#define ITXT1  1
#define ITXT2  2
#define ITXT3  3
#define ITXT4  4
#define ITXT5  5
#define ITXT6  6
#define ITXT7  7

#define PLAIN    0
#define UNDERLIN 1
#define BOLD     2
#define ITALIC   4
#define BACKGPEN 5
#define FGPEN    6
#define MODJAM1  7
#define MODJAM2  8
#define MODINV   9
#define STRGAD  10

#define LOADGADGET   BUTTONCLASS << CLASSBITS | LOAD
#define CANCELGADGET BUTTONCLASS << CLASSBITS | CANCEL
#define ADDTXTGADGET BUTTONCLASS << CLASSBITS | ADDTXT

#define UPGADGET     UPDOWNCLASS << CLASSBITS | UP
#define DOWNGADGET   UPDOWNCLASS << CLASSBITS | DOWN
#define POTGADGET    UPDOWNCLASS << CLASSBITS | POT

#define ITXT0GADGET  CHOICECLASS << CLASSBITS | ITXT0
#define ITXT1GADGET  CHOICECLASS << CLASSBITS | ITXT1
#define ITXT2GADGET  CHOICECLASS << CLASSBITS | ITXT2
#define ITXT3GADGET  CHOICECLASS << CLASSBITS | ITXT3
#define ITXT4GADGET  CHOICECLASS << CLASSBITS | ITXT4
#define ITXT5GADGET  CHOICECLASS << CLASSBITS | ITXT5
#define ITXT6GADGET  CHOICECLASS << CLASSBITS | ITXT6
#define ITXT7GADGET  CHOICECLASS << CLASSBITS | ITXT7

#define PLAINGAD  CHANGECLASS << CLASSBITS | PLAIN
#define UNDERLGAD  CHANGECLASS << CLASSBITS | UNDERLIN
#define BOLDGAD    CHANGECLASS << CLASSBITS | BOLD
#define ITALICGAD  CHANGECLASS << CLASSBITS | ITALIC
#define BGPENGAD   CHANGECLASS << CLASSBITS | BACKGPEN
#define FGPENGAD   CHANGECLASS << CLASSBITS | FGPEN
#define JAM1GAD    CHANGECLASS << CLASSBITS | MODJAM1
#define JAM2GAD    CHANGECLASS << CLASSBITS | MODJAM2
#define INVGAD    CHANGECLASS << CLASSBITS | MODINV
#define MODITGAD    CHANGECLASS << CLASSBITS | STRGAD


/****************************************************************************
 *  Global Structures 
 ***************************************************************************/

/* the newwindow structure used in GT */
extern struct NewWindow nw;
extern struct Window *w;

/* external definitions for IntuiText from men.c */
extern struct IntuiText *Texts[];
extern int nexttext;

/* the list of gadgets */
extern struct Gadget *gads[];
extern int nextgad;

/* global memory allocation base */
extern struct Remember *rememberBase;

/****************************************************************************
 * External function definitions
 ***************************************************************************/
extern APTR AllocRemember();
extern USHORT RemoveGadget();
extern SHORT AddGadget();
struct IntuiText *WaitChoiceReq();
struct IntuiText *WaitITReq();
extern struct IntuiMessage *GetMsg();
extern BOOL autoreq(); /* in misc.c */

/****************************************************************************
 * Requester structures and local/global buffers and counters
 ***************************************************************************/

struct Requester ITxtRequester;
struct Requester ChoiceRequester;


USHORT ITxtCount;                 /* Number of IntuiTexts for the gad */
struct IntuiText *ITMap[50];      /* Pointers to the Gad's Intuitexts */
USHORT FirstITxt;		  /* Index into ITMap                 */

#define STRINGBUFFSIZ  1000
UBYTE  ITxtStringBuff[STRINGBUFFSIZ];/* storage area for text strings */
USHORT StringBuffPos = 0;	  /* Index into String Buffer         */


/***************************************************************************
 * The ITxt list selection Gadgets from the choice requester
 **************************************************************************/
extern struct IntuiText ITxtList[];
extern struct Gadget ITxtListGadget[];

/**************************************************************************
 * The Scroll Selection list up down Potentiometer 
 **************************************************************************/
extern struct PropInfo KnobInfo;
extern struct Gadget PotGadget;
extern struct Gadget DownGadget;

/***************************************************
*       Other Requester structures                 * 
***************************************************/
extern struct IntuiText HeadingText;
extern struct Border Requester3Border;

/****************************************************************************
 * Structures for the IntuiText Add and Modify Requester
 ***************************************************************************/
extern struct Border ITxtReqBord;
extern struct IntuiText ModTxtText;
extern struct IntuiText ITDispText;
extern struct Gadget DummyGad;
extern struct Gadget ModTxtGad;
extern UBYTE ModBuff[];  /* string buffer used to enter/modify itext */
/* This array's subscripts are the ORed bit values of the text types */
extern struct TextAttr *TxtFonts[];


/****************************************************************************
 *               The Code part of the ITextEd module.
 ***************************************************************************/
ITextEd(Gad,ReqWindow)
  struct Gadget *Gad;
  struct Window *ReqWindow;
{
  UBYTE *StrPtr;
  LONG  iflags;
  struct IntuiText *modtext, *ITxtPtr, *nextptr;
  USHORT savegadpos, rmgadpos;
  SHORT i;
  BOOL cancelchosen = FALSE;
  modtext = NULL;
  
  if (Gad == NULL)  
     { /* use auto requestor to tell user to click on gad to modify */
       autoreq("First click on Gadget to add or modify IntuiTexts",
               " Right ","   OK    ");
       return;
     }  

  /* remove all the gadgets from the window */
  for (i=0; i < nextgad; i++) RemoveGadget(ReqWindow,gads[i]);

  /* fix the IDCMP flags to report requester set and clear */
  iflags = nw.IDCMPFlags;
  iflags |= REQCLEAR;
  ModifyIDCMP(ReqWindow,iflags);
  
 
  if (Gad->GadgetText != NULL) {
      /* initialize the text choice requester */ 
      InitCHReq();
      /* Put the intuitext linked list into a work array */
      MapTexts(Gad);
      
      /* move the texts into the requester */
      AttachList(0); 

      /* Put up the requester  */ 
      Request(&ChoiceRequester,ReqWindow);
  
      /* Add the IntuiTexts associated with the gadget to the requester */
      /* and let the user select one.				        */
      modtext = WaitChoiceReq(&cancelchosen);
      ClearListGads();
   }  

   if (cancelchosen != TRUE) 
     {
       if (modtext != NULL) 
          ClearITexts(modtext,(LONG)Gad->LeftEdge,(LONG)Gad->TopEdge);
  
       /* initialize the text add and modify requester */
       InitTxtReq();
   
       /* let the user add or modify text */
       ITxtPtr = WaitITReq(modtext);
       if (ITxtPtr != NULL) { 
	  if (modtext != ITxtPtr)  /* must be new itext */
             { 
               Texts[nexttext] = ITxtPtr;
               nexttext++;
               /* follow the list of itexts to the end */
               if (Gad->GadgetText == NULL) Gad->GadgetText = ITxtPtr;
               else {
                     for(nextptr = Gad->GadgetText; 
                         nextptr->NextText != NULL;
                         nextptr = nextptr->NextText); 
                     nextptr->NextText = ITxtPtr;    
                    }

              } /*if it is old itext it stays in the list - same spot*/
           
          /* let the user drag and position the text */
          DragText(ITxtPtr,(LONG)Gad->LeftEdge,(LONG)Gad->TopEdge);

          } /* drop to here if ITxtPtr is NULL - user cancelled */
     }
   /* restore the gadgets */
   for (i=0; i < nextgad; i++) AddGadget(ReqWindow,gads[i],(LONG)-1);
   RefreshGadgets(Gad,ReqWindow,NULL);
} /* ITextEd */

/*
 *  Init the Itext choice requester
 */
InitCHReq()
{ 
  InitRequester(&ChoiceRequester);
  ChoiceRequester.LeftEdge  = 100;
  ChoiceRequester.TopEdge   = 20;
  ChoiceRequester.Width     = 264;
  ChoiceRequester.Height    = 146;
  ChoiceRequester.ReqGadget = &PotGadget;
  ChoiceRequester.ReqText   = &HeadingText;
  ChoiceRequester.BackFill  = 0;
  ChoiceRequester.Flags     = 0;
  ChoiceRequester.ReqBorder = &Requester3Border;
} /* InitCHReq */


/*
 *  Init the intuitext input and modification requester
 */
InitTxtReq()
{ 
  InitRequester(&ITxtRequester);
  ITxtRequester.LeftEdge  = 100;
  ITxtRequester.TopEdge   = 20;
  ITxtRequester.Width     = 350;
  ITxtRequester.Height    = 135;
  ITxtRequester.ReqGadget = &ModTxtGad;
  ITxtRequester.ReqText   = &ModTxtText;
  ITxtRequester.BackFill  = 0;
  ITxtRequester.Flags     = 0;
  ITxtRequester.ReqBorder = &ITxtReqBord;
} /* InitTxtReq */

/* Copy pointers of the linked list of IntuiTexts associated with the
 * selected gadget into the ITMap array
 */
MapTexts(gadgetp)
  struct Gadget *gadgetp;
  { 
  ITMap[0] = gadgetp->GadgetText;
  for(ITxtCount = 0; ITxtCount < 50 && ITMap[ITxtCount] != NULL; ITxtCount++)
     ITMap[ITxtCount+1] = ITMap[ITxtCount]->NextText;

  }
  
  
/*
 *  WaitChoiceReq - List dirs, scroll, and set drawer and file strings until
 *                  one of the LOAD(SAVE) or CANCEL buttons pushed.
 */
struct IntuiText *WaitChoiceReq(cancelflag)
    BOOL *cancelflag;
{
  ULONG  class = GADGETDOWN;
  USHORT choice = CANCELGADGET;
  USHORT selected = 0;
  struct IntuiMessage *message;
  struct Gadget *gadget;
  
  *cancelflag = FALSE;

  
  while (class != REQCLEAR)
    {
    if ((message=(struct IntuiMessage *) GetMsg(w->UserPort)) == 0L)
      {
      Wait(1L<<w->UserPort->mp_SigBit);
      continue;
      }
    class  = message->Class;
    gadget = (struct Gadget *) message->IAddress;
    ReplyMsg(message);
    switch (class)
      {
      case GADGETDOWN: 
           switch (gadget->GadgetID >> CLASSBITS)
             {
             case UPDOWNCLASS:
                  ScrollList(gadget);      /* scroll up/down 1 file */
                  break;
             case BUTTONCLASS:             /* LOAD or CANCEL */
                  choice = gadget->GadgetID & GADGETNUM;
                  break;
             }
             
      case GADGETUP: 
           switch (gadget->GadgetID >> CLASSBITS)
             {
             case UPDOWNCLASS:
                  PotScrollList(gadget);
                  break;
                  
             case CHOICECLASS:             /* set the text in string gads */
                    if (ITxtCount == 0) break; 
                    if (gadget->GadgetText != NULL)
                       selected = gadget->GadgetID & GADGETNUM;
                  break;

             }
      }
    }
 /* use selected and ITMap to locate correct intuitext */
 
 /* return pointer to selected intuitext */
 if (choice == ADDTXT) return(NULL); 
 else if (choice == CANCEL) 
         { *cancelflag = TRUE;
           return(NULL); 
         } 
 else return((struct IntuiText *)ITxtListGadget[selected].UserData);
       
} /* WaitChoiceReq */


/*
 *  WaitITReq - Let user set the characteristics of the text, such as
 *               fonts, colors, drawing mode, and enter or modify the
 *               text itself.
 */
struct IntuiText *WaitITReq(itextp)
   struct IntuiText *itextp;
{
  ULONG  class = GADGETDOWN;
  USHORT choice = CANCELGADGET;
  USHORT selected = -1;
  SHORT fontnum = 0;
  USHORT dummypos;
  SHORT Mx,My, OldTextLen, NewTextLen;
  UBYTE drawmode, savefrontp, savebackp;
  BOOL nullinput = FALSE;
  struct IntuiMessage *message;
  struct Gadget *gadget;
  struct RastPort *rp; 
  

  if (itextp == NULL) /* allocate a new text structure and fill it in */
      { itextp = (struct IntuiText *)AllocRemember(
               rememberBase,(long)sizeof(struct IntuiText),
               MEMF_PUBLIC | MEMF_CLEAR);
        if (itextp == NULL) return (NULL);
        itextp->FrontPen = 1;
        itextp->BackPen = 0;
        itextp->DrawMode = JAM1;
        itextp->LeftEdge = 0;
        itextp->TopEdge = 0;
        itextp->ITextFont = NULL;
        ITxtStringBuff[StringBuffPos] = '\0';
        itextp->IText = &ITxtStringBuff[StringBuffPos];        
        itextp->NextText = NULL;
        nullinput = TRUE;
      }
      
  /* set the display text to the values for the selected text */    
  ITDispText.FrontPen = itextp->FrontPen;
  ITDispText.BackPen = itextp->BackPen ;
  ITDispText.ITextFont = itextp->ITextFont;
  if (itextp->ITextFont != NULL)/* set the right font index */
     { for(fontnum=0; itextp->ITextFont != TxtFonts[fontnum]; fontnum++);}
  ITDispText.DrawMode = itextp->DrawMode; 
  strcpy(ModBuff,itextp->IText); /* put text into string buffer */
  
  /* set the requester */
  Request(&ITxtRequester,w);

  rp = ITxtRequester.ReqLayer->rp;

  while (class != REQCLEAR)
    {
    if ((message=(struct IntuiMessage *) GetMsg(w->UserPort)) == 0L)
      {
      Wait(1L<<w->UserPort->mp_SigBit);
      continue;
      }
    class  = message->Class;
    Mx = message->MouseX;
    My = message->MouseY;
    gadget = (struct Gadget *) message->IAddress;
    ReplyMsg(message);
    
    if (class == GADGETUP) { 
           switch (gadget->GadgetID >> CLASSBITS)
             {
             case BUTTONCLASS:             /* LOAD or CANCEL */
                  choice = gadget->GadgetID & GADGETNUM;
		  EndRequest(&ITxtRequester,w);
                  break;
                  
             case CHANGECLASS: 
 		  /* save the current pens */
                  savefrontp = ITDispText.FrontPen;
                  savebackp = ITDispText.BackPen;
                  /* clear the text display area */
		  ITDispText.FrontPen = 0;
		  ITDispText.BackPen = 0;
		  PrintIText(rp,&ITDispText,25L,33L);
     
                  switch (gadget->GadgetID & GADGETNUM)
                     {
		      case PLAIN: 
			   fontnum = 0;
		           break;
		                  
		      case UNDERLIN: 
		           fontnum |= 1;
		           break;
		        
		      case BOLD: 
		           fontnum |= 2;
		           break;
		           
		      case ITALIC: 
		           fontnum |= 4;
		           break;

		      case BACKGPEN:
  			   savebackp = (UBYTE)(Mx - 320)/25;
  			   break;
			   
		      case FGPEN:
  			   savefrontp = (UBYTE)(Mx - 320)/25;
		           break;
		           
		      case MODJAM1: 
		           ITDispText.DrawMode = JAM1;
		           break;
		           
		      case MODJAM2: 
		           ITDispText.DrawMode = JAM2;
		           break;
		           
		      case MODINV: 
		           ITDispText.DrawMode = COMPLEMENT;
		           break;

		     }
                  /* set any new text attributes and display */
		  ITDispText.ITextFont = TxtFonts[fontnum];   
		  ITDispText.FrontPen = savefrontp;
                  ITDispText.BackPen = savebackp;
		  PrintIText(rp,&ITDispText,25L,33L);
                  break;
	       }/* CLASSBITS switch */
 	
             } /* if GADGETDOWN */
    } /* while loop */
 
  /* return pointer to selected intuitext */
  if (choice == CANCEL) 
     { 
       if (nullinput)
            /* FreeMem(itextp,(LONG)sizeof(struct IntuiText));*/
       return(NULL);
     }
  /* User must have chosen OK, so update the real IntuiText */
  OldTextLen = strlen(itextp->IText);
  NewTextLen = strlen(ModBuff);
  if (OldTextLen < NewTextLen)
     { if ((NewTextLen+1) > (STRINGBUFFSIZ - StringBuffPos))
	  { /* no room for new text */
           if (autoreq("Out of string space!                        ",
                         "Add Partial String", "Cancel Text")) 
              /* chop the string */
	      ModBuff[STRINGBUFFSIZ-StringBuffPos] = '\0';
           else return(NULL);
          }
       itextp->IText = &ITxtStringBuff[StringBuffPos];
       StringBuffPos += (NewTextLen + 1);
      }
      
   /* if we got to here, means there is space in the buffer and pointer */
   /* is set to the correct position in the buffer		        */
   strcpy(itextp->IText,ModBuff); /* copy the string */
   
   /*set the attributes*/
   itextp->FrontPen = ITDispText.FrontPen;
   itextp->BackPen = ITDispText.BackPen;
   itextp->ITextFont = ITDispText.ITextFont;
   itextp->DrawMode = ITDispText.DrawMode;
   return(itextp); /* send back the pointer to the IntuiText structure */   

} /* WaitITReq */


/*
 *  AttachList - Attach list of file (directory) names to Selection gadgets
 */
AttachList(Start)
  USHORT Start;
{
  USHORT Gadget;
  USHORT Pos;
  struct IntuiText *itextp;

  for (Gadget = 0; Gadget <= 7 && Gadget+Start < ITxtCount; Gadget++)
    {
    itextp = ITMap[Start + Gadget];
    ITxtList[Gadget].IText = itextp->IText;
      
    /* set the display text to the values for the selected text */    
    ITxtList[Gadget].FrontPen = itextp->FrontPen;
    ITxtList[Gadget].BackPen = itextp->BackPen ;
    ITxtList[Gadget].ITextFont = itextp->ITextFont;
    ITxtList[Gadget].DrawMode = itextp->DrawMode; 
    ITxtListGadget[Gadget].UserData = (APTR)itextp; 
    }
  for (; Gadget <= 7; Gadget++)
    {
    ITxtList[Gadget].IText = (UBYTE *)"                                ";
    ITxtList[Gadget].FrontPen = 1;
    ITxtList[Gadget].BackPen = 0;
    ITxtList[Gadget].DrawMode = JAM1;
    ITxtList[Gadget].ITextFont = NULL;
    ITxtListGadget[Gadget].UserData = NULL;
    }
} /* AttachList */

/* 
 * ClearListGads - clears ITxtList after removing the requester ends
 */
ClearListGads()
{ 
  SHORT Gadget;
  
  for (Gadget = 0; Gadget < 8; Gadget++)
    {
    ITxtList[Gadget].IText = (UBYTE *)"                                ";
    ITxtList[Gadget].FrontPen = 1;
    ITxtList[Gadget].BackPen = 0;
    ITxtList[Gadget].DrawMode = JAM1;
    ITxtList[Gadget].ITextFont = NULL;
    ITxtListGadget[Gadget].UserData = NULL;
    }
}
 
/*
 *  ScrollList - Scroll the list up or down 1 file if possible
 */
ScrollList(gadget)
  struct Gadget *gadget;
{
  ULONG VertPot = 0;

  switch(gadget->GadgetID & GADGETNUM)
    {
    case DOWN:
         if (ITxtCount > FirstITxt + 8)
           ++FirstITxt;
         break;
    case UP:
         if (FirstITxt > 0)
           --FirstITxt;
    }
  if (ITxtCount > 8)
    VertPot  = 0xffff/(ITxtCount-6)*FirstITxt;
  ModifyProp(&PotGadget,w,&ChoiceRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,
             0L,VertPot,0L,(LONG)KnobInfo.VertBody);
  ClearListGads();
  RefreshGadgets(&DownGadget,w,&ChoiceRequester);
  AttachList(FirstITxt);
  RefreshGadgets(&DownGadget,w,&ChoiceRequester);
} /* ScrollList */

/*
 *  PotScrollList - Calculate the file number from Pot value and attach
 *                  names to Selector List gadgets.
 */
PotScrollList(gadget)
  struct Gadget *gadget;
{
  switch (gadget->GadgetID & GADGETNUM)
    {
    case POT:
         FirstITxt = (ITxtCount-6)*KnobInfo.VertPot >> 16;
         ClearListGads();
         RefreshGadgets(&DownGadget,w,&ChoiceRequester);
         AttachList(FirstITxt);
         RefreshGadgets(&DownGadget,w,&ChoiceRequester);

    }
} /* PotScrollList */


/*
 * ClearITexts - this routine clears an IntuiText  
 * from the display by overprinting in color 0.
 */
ClearITexts(text,Loff,Toff)
struct IntuiText *text;
LONG Loff,Toff;
{
   UBYTE tempFpen,tempBpen;
   struct IntuiText *temptext;
   if (text == NULL) return;

   tempFpen = text->FrontPen;
   tempBpen = text->BackPen;
   temptext = text->NextText;
   
   text->NextText = NULL;
   text->FrontPen = 0;
   text->BackPen = 0;
   
   PrintIText(w->RPort,text,Loff,Toff);
   text->FrontPen = tempFpen;
   text->BackPen = tempBpen;
   text->NextText = temptext;
}

/*
 * ClearAllTexts - this routine clears all IntuiTexts   
 * from the display for a particular gadget.
 */
ClearAllTexts(gadget,Loff,Toff)
struct Gadget *gadget;
LONG Loff,Toff;
{
   struct IntuiText *nextptr;
   
   if (gadget == NULL) return;
  
   /* follow the list of itexts to the end */
   if (gadget->GadgetText == NULL) return;
   else { 
          for(nextptr = gadget->GadgetText; nextptr != NULL;
              nextptr = nextptr->NextText)
            ClearITexts(nextptr,Loff,Toff); 
         }
}

/*
 * DragText - this routine recursively clears all of the itexts 
 * from the display for a particular gadget.
 */
DragText(text,GadLeft,GadTop)
struct IntuiText *text;
LONG GadLeft,GadTop;
{
   UBYTE SaveDrawMode;
   struct IntuiText *SaveText;
   struct IntuiMessage *message;
   LONG Mx, My, LastX, LastY;
   ULONG class = 0;
   USHORT btcode;
   SHORT skip;
   BOOL notdone = TRUE;

   if (text == NULL) return;
   
   /* save the current settings */
   SaveDrawMode = text->DrawMode;
   SaveText = text->NextText;
   
   /* set the things needed for dragging text */
   text->NextText = NULL;
   text->DrawMode |= COMPLEMENT;
   text->LeftEdge = 0;
   text->TopEdge = 0;

   /* set the location based on the mouse position */
   Mx = (LONG)w->MouseX + 15;
   My = (LONG)w->MouseY;
   
   /* print the text */
   PrintIText(w->RPort,text,Mx,My);
   
   /* save the position where it was printed */
   LastX = Mx;
   LastY = My;

   /* Start IDCMP loop - go until a mouse button is clicked */
  skip = 0;
  while (notdone)
    {
    if ((message=(struct IntuiMessage *) GetMsg(w->UserPort)) == 0L)
      {
      Wait(1L<<w->UserPort->mp_SigBit);
      continue;
      }
    class  = message->Class;
    btcode = message->Code;
    Mx = (LONG)message->MouseX + 15;
    My = (LONG)message->MouseY;
    ReplyMsg(message);
    
    switch (class) {
        case MOUSEMOVE:
             skip++; 
             if (skip == 2)
                { skip = 0;

                  /* erase the old text */
                  PrintIText(w->RPort,text,LastX,LastY);
         
                  /* print the text  in the new spot */
                  PrintIText(w->RPort,text,Mx,My);
         
                  /* save the position where it was printed */
                  LastX = Mx;
                  LastY = My;
                }
              break;
              
         case GADGETUP:
                notdone = FALSE;
                break;
       
         case MOUSEBUTTONS:
                if (btcode = SELECTUP) notdone = FALSE;
                break;
                
       }/* end of switch */

   }/* end of while loop */  
   
   /* erase the last text */
   PrintIText(w->RPort,text,LastX,LastY);
   
   /* restore the mode and next pointer */
   text->DrawMode = SaveDrawMode;
   text->NextText = SaveText;
   
   /* set the offset from the gadget */
   text->LeftEdge = (SHORT)Mx - GadLeft;
   text->TopEdge = (SHORT)My - GadTop;
   
} /* end of DragText */

