/****************************** 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 #include #include #include #include #include #include #include #include /* ========================================================================*/ /* 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<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<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<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 */