/*********************************************************************\ * This file has Intuition-related stuff: menus, fonts, etc (intuit.c) * \*********************************************************************/ #include #include #include #include #include #include /* Library pointers imported from main.c */ extern struct IntuitionBase *IntuitionBase; extern struct GfxBase *GfxBase; extern struct DiskfontBase *DiskfontBase; /* * Initialise an IntuiText structure */ /* constants for pen colors */ #define FORE0 (0 << 2) #define FORE1 (1 << 2) #define FORE2 (2 << 2) #define FORE3 (3 << 2) #define BACK0 0 #define BACK1 1 #define BACK2 2 #define BACK3 3 static InitText(intui, text, pens, left, top) struct IntuiText *intui; char *text; SHORT pens, left, top; { intui->FrontPen = (pens >> 2) & 3; intui->BackPen = pens & 3; intui->DrawMode = JAM2; intui->LeftEdge = left; intui->TopEdge = top; intui->ITextFont = NULL; intui->NextText = NULL; intui->IText = (UBYTE *)text; } /* * Menu Creation */ /* macro to compute size in bytes for menu with n items */ #define MenuBytes(n) (sizeof(struct Menu) + (n)*(sizeof(struct MenuItem) + sizeof(struct IntuiText))) static struct Menu *menuList = NULL; static AddMenu(title, size, names, init, rightify) int size, init, rightify; char *title, *names[]; { struct Menu **menu; struct MenuItem *items = NULL; struct IntuiText *text = NULL; int n, width = 0, itemLeft = 1, menuLeft = 5; USHORT flags = ITEMTEXT | ITEMENABLED | HIGHBOX; if (init >= 0) {flags |= CHECKIT; itemLeft += CHECKWIDTH;} for (menu = &menuList; *menu; menu = &((*menu)->NextMenu)) menuLeft += 90; /* menu now points to where the next menu pointer should go */ *menu = (struct Menu *)AllocMem(MenuBytes(size), MEMF_CHIP); if (*menu == NULL) return(TRUE); /* out of memory */ items = (struct MenuItem *)(sizeof(**menu) + (UBYTE *)*menu); text = (struct IntuiText *)(size*sizeof(*items) + (UBYTE *)items); InitText(text, (*menu)->MenuName = title, 0, 0, 0); /* just to measure it */ (*menu)->Width = 8 + IntuiTextLength(text); for (n=0; n= 0) width += CHECKWIDTH; (*menu)->LeftEdge = rightify ? 630-width : menuLeft; (*menu)->FirstItem = items; (*menu)->NextMenu = NULL; (*menu)->TopEdge = 0; (*menu)->Height = 10; (*menu)->Flags = MENUENABLED; for (n=0; nNextItem = items+1; items->LeftEdge = 0; items->TopEdge = 11 * n; items->Width = width; items->Height = 10; items->Flags = flags; items->MutualExclude = (~(1 << n)); items->ItemFill = (APTR)text++; items->SelectFill = NULL; items->Command = 0; items->SubItem = NULL; items->NextSelect = 0; items++; } (--items)->NextItem = NULL; items -= (size-1); if (init >= 0 && init < size) items[init].Flags |= CHECKED; return(FALSE); /* no problems */ } /* end of AddMenu */ /* Specific menus */ static char *fileStrings[] = {"Start Capture", "Start Send", "End Capture", "Cancel Send"}; static char *baudStrings[] = {" 300", "1200", "2400", "4800", "9600"}; static char *dpyStrings[] = {"Vanilla", "SAIL"}; static char *beepStrings[] = {"Brash", "Clear", "Calm", "Eerie", "Subdued", "Silent"}; static char *wnStrings[] = {"Move to Back", "Move to Front", "Close Window"}; static InitMenus() { /* returns TRUE if unable to create them all */ return(AddMenu("File", 2, fileStrings, -1, FALSE) || AddMenu("Baud", 5, baudStrings, 1, FALSE) || AddMenu("Display", 2, dpyStrings, 1, FALSE) || AddMenu("Beep", 6, beepStrings, 1, FALSE) || AddMenu("Window", 3, wnStrings, -1, TRUE)); } /* * SAIL Font (weird chars in positions 0x80-0x9F) */ static struct TextFont *tf; static InitSAILFont(window) struct Window *window; { struct TextAttr ta; ta.ta_Name = "SAIL.font"; ta.ta_YSize = 8; ta.ta_Style = 0; ta.ta_Flags = FPF_ROMFONT | FPF_DISKFONT | FPF_PROPORTIONAL | FPF_DESIGNED; tf = (struct TextFont *)OpenDiskFont(&ta); if (tf) SetFont(window->RPort, tf); } InitWindowStuff(window) struct Window *window; { if (InitMenus() || MakeRequester()) {FreeMenus(); return(TRUE);} InitSAILFont(window); SetMenuStrip(window, menuList); return(FALSE); /* no problem */ } CleanUpWindow(window) struct Window *window; { if (tf) CloseFont(tf); if (window) ClearMenuStrip(window); FreeMenus(); } static FreeMenus() { struct MenuItem *item; while (menuList) { int size = 0; struct Menu *next = menuList->NextMenu; for (item = menuList->FirstItem; item; item = item->NextItem) size++; FreeMem(menuList, MenuBytes(size)); menuList = next; } } /* * Function to handle file menu commands, usually via a requester */ FileMenu(w, item, r, s, flags) struct Window *w; int item, *flags; FILE **r, **s; { /* called with item<0 to fix up menu item text to match current state */ switch (item) { case 0: /* capture */ if (OpenOrCloseFile(w, r, "Capture to", "w", "Include control chars?")) *flags |= 1; else *flags &= ~1; break; case 1: /* send */ if (OpenOrCloseFile(w, s, "Send", "r", "Convert LFs to CRs?")) *flags |= 2; else *flags &= ~2; break; } ((struct IntuiText *)menuList->FirstItem->ItemFill)->IText = (UBYTE *)fileStrings[*r == NULL ? 0 : 2]; ((struct IntuiText *)menuList->FirstItem->NextItem->ItemFill)->IText = (UBYTE *)fileStrings[*s == NULL ? 1 : 3]; } /* The Requester */ static struct Requester myreq; #define FNAMEBUFSIZE 60 static UBYTE fnamebuf[FNAMEBUFSIZE]; static struct StringInfo fname = { fnamebuf, NULL, 0, FNAMEBUFSIZE, 0, 0, 0, 0, 0, 0, 0, 0, NULL}; /* border for requester */ #define FILREQWIDTH 400 #define FILREQHEIGHT 130 #define TEXTGAP 14 #define TEXTTOP 10+TEXTGAP*2 static SHORT reqPairs[] = { 4, 2, FILREQWIDTH-5, 2, FILREQWIDTH-5, FILREQHEIGHT-3, 4, FILREQHEIGHT-3, 4, 2, 5, 2, 5, FILREQHEIGHT-3, FILREQWIDTH-6, FILREQHEIGHT-3, FILREQWIDTH-6, 2 }; static SHORT textPairs[] = {0, TEXTTOP-TEXTGAP-1, 0, TEXTTOP-TEXTGAP-1}; static SHORT errorPairs[] = {0, TEXTTOP-2*TEXTGAP-1, 0, TEXTTOP-2*TEXTGAP-1}; /* border for activation gadgets */ #define OCTLAP 2 #define OCTWIDTH 100 /* tentative, adjusted based on font width */ #define OCTHEIGHT 27 /* likewise adjusted based on font height */ static SHORT gadPairs[] = { OCTLAP*4, -OCTLAP, OCTWIDTH-OCTLAP*4-1, -OCTLAP, OCTWIDTH+OCTLAP*2-1, OCTLAP*2, OCTWIDTH+OCTLAP*2-1, OCTHEIGHT-OCTLAP*2-1, OCTWIDTH+OCTLAP*2-2, OCTLAP*2, OCTWIDTH+OCTLAP*2-2, OCTHEIGHT-OCTLAP*2-1, OCTWIDTH+OCTLAP*2-1, OCTHEIGHT-OCTLAP*2-1, OCTWIDTH-OCTLAP*4-1, OCTHEIGHT+OCTLAP-1, OCTLAP*4, OCTHEIGHT+OCTLAP-1, -OCTLAP*2, OCTHEIGHT-OCTLAP*2-1, -OCTLAP*2, OCTLAP*2, -OCTLAP*2+1, OCTHEIGHT-OCTLAP*2-1, -OCTLAP*2+1, OCTLAP*2, -OCTLAP*2, OCTLAP*2, OCTLAP*4, -OCTLAP }; /* border and background for yes/no gadget */ static SHORT ynBkgPairs[48]; static SHORT ynBrdPairs[] = {-2,-1, -2,3, 1,3, 1,-1, -1,-1, -1,3, 0,3, 0,-1}; static struct Border reqBorder = {0, 0, 3, 0, JAM1, 9, reqPairs, NULL}; static struct Border textBorder = {0, 0, 3, 2, JAM1, 2, textPairs, &reqBorder}; static struct Border errBorder = {0, 0, 1, 2, JAM1, 2, errorPairs, &textBorder}; static struct Border gadBorder = {0, 0, 3, 2, JAM1, 15, gadPairs, NULL}; static struct Border ynBorder = {0, 0, 1, 0, JAM1, 8, ynBrdPairs, NULL}; static struct Border ynBackground = {0, 0, 0, 2, JAM1, 24, ynBkgPairs, &ynBorder}; static struct IntuiText gadText[4], ynText[2]; static struct IntuiText reqText, errorText, optText; static char reqTextChars[30]; static struct Gadget gadgets[5] = { {&gadgets[1], 20,-20-OCTHEIGHT,OCTWIDTH,OCTHEIGHT, GADGHCOMP | GRELBOTTOM, RELVERIFY | ENDGADGET, REQGADGET | BOOLGADGET, (APTR)&gadBorder, NULL, &gadText[0], NULL, NULL, TRUE, NULL}, {&gadgets[2], -20-OCTWIDTH,-20-OCTHEIGHT,OCTWIDTH,OCTHEIGHT, GADGHCOMP | GRELRIGHT | GRELBOTTOM, RELVERIFY | ENDGADGET, REQGADGET | BOOLGADGET, (APTR)&gadBorder, NULL, &gadText[1], NULL, NULL, FALSE, NULL}, {&gadgets[3], 0,TEXTTOP+TEXTGAP*3/2,0,0, GADGHCOMP, RELVERIFY, REQGADGET | BOOLGADGET, (APTR)&ynBackground, NULL, &ynText[0], NULL, NULL, TRUE, (APTR)&gadgets[3]}, {&gadgets[4], 0,TEXTTOP+TEXTGAP*3/2,0,0, GADGHCOMP, RELVERIFY, REQGADGET | BOOLGADGET, (APTR)&ynBackground, NULL, &ynText[1], NULL, NULL, FALSE, (APTR)&gadgets[2]}, {NULL, FILREQWIDTH/5,TEXTTOP,FILREQWIDTH*3/5,12, GADGHCOMP, STRINGCENTER, REQGADGET | STRGADGET, NULL, NULL, NULL, NULL, (APTR)&fname, NULL, NULL} }; static MakeRequester() { int n, width; BYTE height; SHORT *coord; InitRequester(&myreq); myreq.LeftEdge = (640-FILREQWIDTH)/2; myreq.TopEdge = 8; myreq.Width = FILREQWIDTH; myreq.Height = FILREQHEIGHT; myreq.ReqGadget = gadgets; myreq.ReqBorder = &textBorder; myreq.ReqText = &reqText; myreq.BackFill = 2; GetPrefs(&height, 1); /* get height of default font */ InitText(&ynText[0], "Yes", FORE1|BACK0, 4, 2); InitText(&ynText[1], "No", FORE1|BACK0, 4, 2); width = IntuiTextLength(&ynText[0]); ynText[1].LeftEdge += (width-IntuiTextLength(&ynText[1])) / 2; gadgets[2].Width = gadgets[3].Width = width += 8; gadgets[2].Height = gadgets[3].Height = height+3; coord = ynBkgPairs; for (n=0; n= 0) *coord += width; if (*++coord >= 0) *coord += height; } InitText(&gadText[0], " CONFIRM ", FORE0|BACK1, 2, height+1); InitText(&gadText[1], " FORGET IT ", FORE0|BACK1, 2, height+1); InitText(&gadText[2], " ", FORE0|BACK1, 2, 1); InitText(&gadText[3], " ", FORE0|BACK1, 2, height*2+1); gadText[0].NextText = gadText[1].NextText = &gadText[2]; gadText[2].NextText = &gadText[3]; gadgets[1].Width = gadgets[0].Width = width = IntuiTextLength(gadText) + 4; gadgets[1].Height = gadgets[0].Height = height = height*3 + 2; gadgets[1].LeftEdge = -20-width; coord = gadPairs-1; for (n=0; n OCTWIDTH/2) *coord += width-OCTWIDTH; if (*++coord > OCTHEIGHT/2) *coord += height-OCTHEIGHT; } InitText(&reqText, reqTextChars, FORE2|BACK3, 0, TEXTTOP - TEXTGAP); reqText.NextText = &optText; InitText(&optText, NULL, FORE1|BACK2, 0, gadgets[2].TopEdge + ynText[0].TopEdge); InitText(&errorText, " Can't open file; try again ", FORE0|BACK1, 0, TEXTTOP - 2*TEXTGAP); errorText.NextText = &reqText; width = IntuiTextLength(&errorText); errorPairs[0] = errorText.LeftEdge = (FILREQWIDTH-width) / 2; errorPairs[2] = errorPairs[0] + width - 1; return(FALSE); /* no problems */ } static OpenOrCloseFile(w, file, label, mode, option) struct Window *w; FILE **file; char *label, *mode, *option; { struct IntuiMessage *message; ULONG class; struct Gadget *gadg; int proceed, k, opt; if (*file != NULL) {fclose(*file); *file = NULL; return(NULL);} sprintf(reqTextChars, " %s file: ", label); k = IntuiTextLength(&reqText); textPairs[0] = reqText.LeftEdge = (FILREQWIDTH-k) / 2; textPairs[2] = textPairs[0] + k - 1; optText.IText = (UBYTE *)option; k = IntuiTextLength(&optText); opt = gadgets[2].Width + 2; /* distance between Yes gadget and No gadget */ optText.LeftEdge = (FILREQWIDTH - (k + 3*opt)) / 2; gadgets[2].LeftEdge = optText.LeftEdge + k + opt; gadgets[3].LeftEdge = gadgets[2].LeftEdge + opt; fnamebuf[0] = k = 0; myreq.ReqBorder = &textBorder; myreq.ReqText = &reqText; gadgets[2].Flags &= ~SELECTED; gadgets[3].Flags |= SELECTED; gadgets[2].Activation |= TOGGLESELECT; gadgets[3].Activation &= ~TOGGLESELECT; for (;;) { if (! Request(&myreq, w)) return(NULL); /* couldn't open requester */ for (proceed=TRUE; proceed; ) { while (message = (struct IntuiMessage *)GetMsg(w->UserPort)) { class = message->Class; gadg = (struct Gadget *)message->IAddress; ReplyMsg(message); switch (class) { case GADGETUP: if (gadg->Activation & ENDGADGET) { k = gadg->GadgetID; opt = gadgets[2].Flags & SELECTED; } else if (gadg->Activation & TOGGLESELECT) { gadg->Activation &= ~TOGGLESELECT; gadg = (struct Gadget *)gadg->UserData; gadg->Flags &= ~SELECTED; gadg->Activation |= TOGGLESELECT; RefreshGadgets(&gadgets[2], w, &myreq); } break; case REQCLEAR: proceed = FALSE; break; } } } /* requester came down, now check what we're supposed to do */ if (!k) return(NULL); /* user said to forget it */ if (*file = fopen(fnamebuf, mode)) return(opt); /* no problem */ /* bring requester back, this time with error message added */ myreq.ReqBorder = &errBorder; myreq.ReqText = &errorText; } }