/*** Copyright 1992 by D.W.Reisig. ***/ unsigned char Version[] = "$VER: ENote 1.0 04-May-92 © 1992 D.W.Reisig\n"; unsigned char PrgTitle[] = "ENote 1.0: "; #include #include #include #include #include #include #include #include #include #include "memory.h" #define COMMENTSIZE 80 #define PUBCLR MEMF_PUBLIC | MEMF_CLEAR #define CHECK_IOERR -1 #define btst(bitnr,var) ((var)&(1<<(bitnr))) #define bset(bitnr,var) ((var)|=(1<<(bitnr))) #define bclr(bitnr,var) ((var)&=~(1<<(bitnr))) #define bchg(bitnr,var) ((var)^=(1<<(bitnr))) extern VOID Quit(LONG ReturnValue, LONG Result2); extern LONG Edit(UBYTE *FileName, struct FileInfoBlock *InfoBlock); extern struct IntuitionBase *IntuitionBase; extern struct WBStartup *WBenchMsg; ULONG StdOut; UBYTE *ErrMsg, *PrgName; /*---------------------------------------------------------------------------*/ VOID main(LONG argc, UBYTE *argv[]) { // static UWORD Pad; // Align FileInfoBlocks if necessary static struct FileInfoBlock WBInfoBlock, InfoBlock; static UBYTE NoAccess[] = "Could not access file\n"; UBYTE *FileName; ULONG FileLock; LONG EditResult; if (argc != 0){ StdOut = Output(); PrgName = argv[0]; } IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0); if (!IntuitionBase){ ErrMsg = "No Intuition\n"; Quit(RETURN_FAIL, 0); } if (argc == 0){ //*** From the Workbench.. ULONG WBLock; if (WBenchMsg->sm_NumArgs < 2){ ErrMsg = "\nSelect the ENote Icon,\nPress shift,\nAnd double-click another Icon..\n"; Quit(RETURN_ERROR, ERROR_REQUIRED_ARG_MISSING); } WBLock = ((struct WBArg *)(WBenchMsg->sm_ArgList)+1)->wa_Lock; CurrentDir(WBLock); FileName = ((struct WBArg *)(WBenchMsg->sm_ArgList)+1)->wa_Name; if (*FileName == '\0'){ //*** Directory selected; one up, so we can find its name.. CurrentDir(ParentDir(WBLock)); if (!Examine(WBLock, &WBInfoBlock)){ ErrMsg = NoAccess; Quit(RETURN_FAIL, CHECK_IOERR); } FileName = WBInfoBlock.fib_FileName; } } else{ //*** From the CLI.. if ((argc<2) || ((argc>1)&&(*argv[1]=='?'))){ // No argument or '?' static UBYTE Usage0[] = "Syntax: "; static UBYTE Usage1[] = " \nFunction: Edit a filenote\n"; Write(StdOut, Usage0, sizeof(Usage0)-1); Write(StdOut, argv[0], strlen(argv[0])); Write(StdOut, Usage1, sizeof(Usage1)-1); Quit(RETURN_ERROR, ERROR_REQUIRED_ARG_MISSING); } FileName = argv[1]; } //*** Get access to file FileLock = Lock(FileName, ACCESS_READ); if (!FileLock){ ErrMsg = NoAccess; Quit(RETURN_FAIL, CHECK_IOERR); } if (!Examine(FileLock, &InfoBlock)){ UnLock(FileLock); ErrMsg = NoAccess; Quit(RETURN_FAIL, CHECK_IOERR); } UnLock(FileLock); //*** Edit filenote and bits EditResult = Edit(FileName, &InfoBlock); if (EditResult < 0) Quit(RETURN_FAIL, 0); if (EditResult > 0){ //*** Store filenote and bits if (!(SetComment(FileName, InfoBlock.fib_Comment) && SetProtection(FileName, InfoBlock.fib_Protection))){ ErrMsg = "Save failed\n"; Quit(RETURN_FAIL, CHECK_IOERR); } } Quit(RETURN_OK, 0); } /*---------------------------------------------------------------------------*/ #define MAXWTITLE 40 VOID Quit(LONG ReturnValue, LONG Result2) { if (Result2 == CHECK_IOERR) Result2 = IoErr(); //*** Print any message if (ErrMsg){ LONG MsgLen = strlen(ErrMsg); if (StdOut){ // CLI Write(StdOut, PrgName, strlen(PrgName)); Write(StdOut, ": ", 2); Write(StdOut, ErrMsg, MsgLen); } else{ // WB UBYTE StrBuf[MAXWTITLE+18], *StrPtr; strcpy(StrBuf, "CON:10/10/630/120/"); strncpy(&StrBuf[18], WBenchMsg->sm_ArgList->wa_Name, MAXWTITLE); StdOut = Open(StrBuf, MODE_OLDFILE); if (StdOut){ Write(StdOut, ErrMsg, MsgLen); if (Result2){ strcpy(StrBuf, "Error "); StrPtr = &StrBuf[6]; StrPtr += stcl_d(StrPtr, Result2); *StrPtr++ = '\n'; *StrPtr = '\0'; Write(StdOut, StrBuf, strlen(StrBuf)); } Delay(100 + 4 * MsgLen); Close(StdOut); } else if (IntuitionBase){ DisplayBeep(0); } } } if (IntuitionBase) CloseLibrary(IntuitionBase); ((struct Process *)FindTask(0))->pr_Result2 = Result2; _exit(ReturnValue); } /*---------------------------------------------------------------------------*/ UBYTE *NoMem(ULONG Size, ULONG Type) { ErrMsg="Not enough memory\n"; return(0); } /*****************************************************************************/ extern struct Gadget *MakeStringGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *TextBuf, ULONG TextLen); extern struct Gadget *MakeBoolGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *Text); extern VOID ToggleGadget(struct Gadget *Gadget, struct Window *Window); #define GADGET_H_DIST 10 #define GADGET_V_DIST 6 #define GADTXT_H_DIST 4 #define GADTXT_V_DIST 2 #define PEN_GREY 0 #define PEN_BLACK 1 #define PEN_WHITE 2 #define PEN_BLUE 3 #define NUMGADGETS 11 #define G_STR 10 #define G_CANCEL 9 #define G_SAVE 8 #define G_H 7 #define G_S 6 #define G_P 5 #define G_A 4 #define G_R 3 #define G_W 2 #define G_E 1 #define G_D 0 UBYTE *GtsText[] = { "D", "E", "W", "R", "A", "P", "S", "H", " Save ", " Cancel ", "" }; struct Screen WBScreen; struct NewWindow NewWin; /*---------------------------------------------------------------------------*/ LONG Edit(UBYTE *FileName, struct FileInfoBlock *InfoBlock) { struct Window *Window; struct Gadget *Gadget[NUMGADGETS]; LONG I; WORD OverShoot, TextHeight; WORD Close = 0, FirstActivate = 1; //*** Get Screen structure for window and font sizes among others if (!GetScreenData(&WBScreen, sizeof(struct Screen), WBENCHSCREEN, NULL)){ ErrMsg="No Screen\n"; Quit(RETURN_FAIL, 0); } //*** Something like Barheight, but Barheight differs between 1.3 and 2.0 TextHeight = WBScreen.RastPort.TxHeight + GADTXT_V_DIST; //*** NewWindow allocation and initialization NewWin.DetailPen = -1; NewWin.BlockPen = -1; NewWin.IDCMPFlags = IDCMP_ACTIVEWINDOW + IDCMP_GADGETUP + IDCMP_VANILLAKEY; NewWin.Flags = WFLG_NOCAREREFRESH + WFLG_SMART_REFRESH + WFLG_ACTIVATE + WFLG_DRAGBAR + WFLG_DEPTHGADGET; NewWin.Type = WBENCHSCREEN; NewWin.TopEdge = WBScreen.MouseY; // Nice for auto-activation.. NewWin.Height = TextHeight * 3 + GADGET_V_DIST * 3 + 2; OverShoot = NewWin.TopEdge + NewWin.Height - WBScreen.Height; if (OverShoot>0){ NewWin.TopEdge -= OverShoot; if (NewWin.TopEdge < 0) NewWin.TopEdge = 0; } NewWin.Width = WBScreen.RastPort.TxWidth * COMMENTSIZE + 2 * GADTXT_H_DIST + 2 * GADGET_H_DIST; if (NewWin.Width > WBScreen.Width) NewWin.Width = WBScreen.Width; OverShoot = WBScreen.MouseX - NewWin.Width + 1; if (OverShoot > 0) NewWin.LeftEdge = OverShoot; NewWin.MinHeight = NewWin.MaxHeight = NewWin.Height; // No fiddling with our sizes! NewWin.MinWidth = NewWin.MaxWidth = NewWin.Width; NewWin.Title = AllocMA(sizeof(PrgTitle) + 1 + strlen(FileName), PUBCLR); if (!NewWin.Title) goto Fail; strcpy(NewWin.Title, PrgTitle); strcpy(&NewWin.Title[sizeof(PrgTitle)-1], FileName); //*** Create string gadget for filenote Gadget[G_STR]=MakeStringGadget(NewWin.Width - 2 * GADGET_H_DIST - 2 * GADTXT_H_DIST, TextHeight, (UBYTE *)&InfoBlock->fib_Comment, COMMENTSIZE); if (!Gadget[G_STR]) goto Fail; Gadget[G_STR]->LeftEdge = GADGET_H_DIST + GADTXT_H_DIST; Gadget[G_STR]->TopEdge = TextHeight + GADGET_V_DIST + 2; // 2 for thick border //*** Create BOOL gadget structures for (I=G_CANCEL; I>=G_D; --I){ Gadget[I]=MakeBoolGadget(strlen(GtsText[I]) * WBScreen.RastPort.TxWidth + 2 * GADTXT_H_DIST, TextHeight, GtsText[I]); if (!Gadget[I]) goto Fail; Gadget[I]->TopEdge = Gadget[G_STR]->TopEdge + TextHeight + GADGET_V_DIST + 1; // 1 for thin border Gadget[I+1]->NextGadget = Gadget[I]; } Gadget[G_SAVE]->GadgetID = 1; // Close gadgets Gadget[G_CANCEL]->GadgetID = 1; //*** Set BOOL gadgets horizontal locations Gadget[G_SAVE]->LeftEdge = GADGET_H_DIST; Gadget[G_CANCEL]->LeftEdge = NewWin.Width - Gadget[G_CANCEL]->Width - GADGET_H_DIST; Gadget[G_H]->LeftEdge = NewWin.Width/2 - 4 * (Gadget[G_H]->Width + GADGET_H_DIST); for (I=G_S; I>=G_D; --I) Gadget[I]->LeftEdge = Gadget[I+1]->LeftEdge + Gadget[I+1]->Width + GADGET_H_DIST; //*** Check gaget overlap if ((Gadget[G_SAVE]->LeftEdge + Gadget[G_SAVE]->Width) > Gadget[G_H]->LeftEdge){ ErrMsg = "Font too wide\n"; goto Fail; } //*** Set Filebit gadgets activation for (I=G_H; I>=G_A; --I) if (btst(I, InfoBlock->fib_Protection)) Gadget[I]->Flags |= GFLG_SELECTED; for (I=G_R; I>=G_D; --I) if (!btst(I, InfoBlock->fib_Protection)) Gadget[I]->Flags |= GFLG_SELECTED; NewWin.FirstGadget = Gadget[G_STR]; //*** Open Window Window = (struct Window *)OpenWindow(&NewWin); if (!Window){ ErrMsg = "No window\n"; goto Fail; } //*** Handle Window messages while(!Close){ struct IntuiMessage IntuMsg, *IM; WaitPort(Window->UserPort); if (IM = (struct IntuiMsg *)GetMsg(Window->UserPort)){ IntuMsg = *IM; ReplyMsg((struct Message *)IM); switch(IntuMsg.Class){ case IDCMP_ACTIVEWINDOW: if (FirstActivate) ActivateGadget(Gadget[G_STR], Window, NULL); FirstActivate=0; break; case IDCMP_VANILLAKEY: switch(IntuMsg.Code){ case 'S': Gadget[G_SAVE]->Flags |= SELECTED; Close = 1; break; case 'C': Close = 1; break; case 'h': ToggleGadget(Gadget[G_H], Window); break; case 's': ToggleGadget(Gadget[G_S], Window); break; case 'p': ToggleGadget(Gadget[G_P], Window); break; case 'a': ToggleGadget(Gadget[G_A], Window); break; case 'r': ToggleGadget(Gadget[G_R], Window); break; case 'w': ToggleGadget(Gadget[G_W], Window); break; case 'e': ToggleGadget(Gadget[G_E], Window); break; case 'd': ToggleGadget(Gadget[G_D], Window); break; case 'f': ActivateGadget(Gadget[G_STR], Window, NULL); break; default: DisplayBeep(0); break; } break; case IDCMP_GADGETUP: /* User perhaps asks to leave */ Close = ((struct Gadget *)IntuMsg.IAddress)->GadgetID; break; } } } //*** Set filebits from gadgets for (I=G_H; I>=G_A; --I) if (Gadget[I]->Flags & GFLG_SELECTED) bset(I, InfoBlock->fib_Protection); else bclr(I, InfoBlock->fib_Protection); for (I=G_R; I>=G_D; --I) if (Gadget[I]->Flags & GFLG_SELECTED) bclr(I, InfoBlock->fib_Protection); else bset(I, InfoBlock->fib_Protection); //*** Close Window and return status CloseWindow(Window); return((Gadget[G_SAVE]->Flags&SELECTED)? 1 : 0); Fail: return(-1); } /*---------------------------------------------------------------------------*/ struct Gadget *MakeStringGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *TextBuf, ULONG TextLen) { //*** Array of coordinates of a border around a gadget with a size of zero. static WORD BasicXY[] = { -4, -3, -4, 0, -3, -1, -3, -3, 2, -3, 1, -3, 1, -1, 0, -1, 0, -1, -1, -1, 3, 0, 3, -3, 2, -2, 2, 0, -3, 0, -2, 0, -2, -3, -1, -2, -1, -2, 0, -2 }; //*** Arrays of coordinate elements to be adapted to real gadget size static WORD VAdapt[] = { 3, 5, 13, 17, 19, 21, 27, 29, 31, 35 }; static WORD HAdapt[] = { 8, 10, 12, 14, 16, 20, 22, 24, 26, 38 }; struct StringInfo *StrInfo; struct Gadget *Gadget; struct Border *BorderLT, *BorderRB; // Border Left Top and Border Right Bottom WORD *XY; LONG I; //*** Allocate and initialize StringInfo structure StrInfo = (struct StringInfo *)AllocMA(sizeof(struct StringInfo), PUBCLR); if (!StrInfo) goto Fail; StrInfo->Buffer = TextBuf; StrInfo->BufferPos = strlen(TextBuf); StrInfo->UndoBuffer = AllocMA(TextLen + 2, PUBCLR); if (!StrInfo->UndoBuffer) goto Fail; StrInfo->MaxChars = TextLen; //*** Allocate and coordinate array's and adapt its contents XY = (WORD *)AllocMA(sizeof(BasicXY), MEMF_PUBLIC); if (!XY) goto Fail; memcpy((UBYTE *)XY, (UBYTE *)BasicXY, sizeof(BasicXY)); for (I=0; I < sizeof(VAdapt)/2; ++I) XY[VAdapt[I]] += TextHeight; for (I=0; I < sizeof(HAdapt)/2; ++I) XY[HAdapt[I]] += TextWidth; //*** Allocate and initialize Border structures BorderLT = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR); if (!BorderLT) goto Fail; BorderLT->XY = XY; BorderLT->Count = (sizeof(BasicXY)/(2 * sizeof(WORD)))/2; BorderLT->FrontPen = PEN_WHITE; BorderLT->DrawMode = JAM2; BorderRB = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR); if (!BorderRB) goto Fail; BorderRB->XY = &XY[20]; BorderRB->Count = (sizeof(BasicXY)/(2 * sizeof(WORD)))/2; BorderRB->FrontPen = PEN_BLACK; BorderRB->DrawMode = JAM2; BorderRB->NextBorder = BorderLT; //*** Allocate and initialize string Gadget structure Gadget = (struct Gadget *)AllocMA(sizeof(struct Gadget), PUBCLR); if (!Gadget) goto Fail; Gadget->SpecialInfo = StrInfo; Gadget->Flags = GFLG_GADGHCOMP + GFLG_SELECTED; Gadget->Activation = GACT_TOGGLESELECT; Gadget->GadgetType = GTYP_STRGADGET; Gadget->Width = TextWidth; Gadget->Height = TextHeight; Gadget->GadgetRender = BorderRB; return(Gadget); Fail: return(0); } /*---------------------------------------------------------------------------*/ struct Gadget *MakeBoolGadget(ULONG TextWidth, ULONG TextHeight, UBYTE *Text) { struct Gadget *Gadget; struct IntuiText *IText; struct Border *BorderLT, *BorderRB; // Border Left Top and Border Right Bottom WORD *XY; //*** Allocate and initialize Border coordinates XY = (WORD *)AllocMA(2 * 5 * 2 * sizeof(WORD), PUBCLR); if (!XY) goto Fail; XY[3] = TextHeight; XY[4] = 1; XY[5] = TextHeight - 1; XY[6] = 1; XY[8] = TextWidth - 1; XY[10] = TextWidth; XY[11] = TextHeight; XY[12] = TextWidth; XY[14] = TextWidth - 1; XY[15] = 1; XY[16] = TextWidth - 1; XY[17] = TextHeight; XY[18] = 1; XY[19] = TextHeight; //*** Allocate and initialize Border structures BorderLT = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR); if (!BorderLT) goto Fail; BorderLT->XY = XY; BorderLT->Count = 5; BorderLT->FrontPen = PEN_WHITE; BorderLT->DrawMode = JAM2; BorderRB = (struct Border *)AllocMA(sizeof(struct Border), PUBCLR); if (!BorderRB) goto Fail; BorderRB->XY = &XY[10]; BorderRB->Count = 5; BorderRB->FrontPen = PEN_BLACK; BorderRB->DrawMode = JAM2; BorderRB->NextBorder = BorderLT; //*** Allocate and initialize IntuiText structures for gadget texts IText = (struct IntuiText *)AllocMA(sizeof(struct IntuiText), PUBCLR); if (!IText) goto Fail; IText->FrontPen = PEN_BLACK; IText->DrawMode = JAM2; IText->LeftEdge = GADTXT_H_DIST; IText->TopEdge = GADTXT_V_DIST; IText->IText = Text; //*** Allocate and initialize BOOL Gadget structure Gadget = (struct Gadget *)AllocMA(sizeof(struct Gadget), PUBCLR); if (!Gadget) goto Fail; Gadget->Width = TextWidth + 1; Gadget->Height = TextHeight + 1; Gadget->Flags = GFLG_GADGHCOMP; Gadget->Activation = GACT_TOGGLESELECT + GACT_RELVERIFY; Gadget->GadgetType = GTYP_BOOLGADGET; Gadget->GadgetRender = BorderRB; Gadget->GadgetText = IText; return(Gadget); Fail: return(0); } /*---------------------------------------------------------------------------*/ /* * It is not the first time I have troubles with gadgets. I have ALWAYS * troubles with gadgets. This time gadgets must toggle by our command. * We must first remove any drawing data from the gadget. No border and * no text. Now you can toggle the drawing just by complementing. You can * let Intuition complement by refreshing a selected gadget. Later the * select flag must be set right. Takes some time to find out. */ VOID ToggleGadget(struct Gadget *Gadget, struct Window *Window) { UWORD Flags; Gadget->GadgetText=NULL; Gadget->GadgetRender=NULL; Flags = Gadget->Flags; Gadget->Flags |= SELECTED; RemoveGadget(Window, Gadget); AddGadget(Window, Gadget, -1); RefreshGadgets(Gadget, Window, NULL); Gadget->Flags = Flags ^ SELECTED; } /*---------------------------------------------------------------------------*/