/*---------------------------------------------------------* | Author: Maurizio Loreti, aka MLO or I3NOO. | | Address: University of Padova - Department of Physics | | Via F. Marzolo, 8 - 35131 PADOVA - Italy | | Phone: (39)(49) 844-313 FAX: (39)(49) 844-245 | | E-Mail: LORETI at IPDINFN (BITNET); or VAXFPD::LORETI | | (DECnet) - VAXFPD is node 38.257 i.e. 39169; or | | LORETI@PADOVA.INFN.IT (INTERNET). | | Home: Via G. Donizetti 6 - 35010 CADONEGHE (PD) - Italy | *---------------------------------------------------------*/ #include /* Standard library */ #include #include /* Amiga specific */ #include #include #include #include #include #include #include #if defined(REQ) | defined(BOTH) #include #endif #include "mlo.h" /* Program specific */ #include "pf2.h" #include "ext.h" #include "aw.h" static int aw_ytitle, aw_ycycle; static int Ask(char *pTitle, int nText, char *Text[]); static int AskInt(char *pTitle, short valMin, short valMax, short *pVal); static void MakeWindow(struct Gadget *pG); void SetupWB(void) { /** | Printer setup, driven with requester windows when called from | the Workbench. **/ char cOri[] = "Orientation"; char *tOri[] = { "Portrait", "Landscape", "\"Special\"" }; #define nOri (sizeof(tOri) / sizeof(char *)) char cFon[] = "Font"; char *tFon[] = { "Courier", "Letter-Gothic", "Times" }; #define nFon (sizeof(tFon) / sizeof(char *)) char cPit[] = "Horizontal pitch"; char *tPitC[] = { "10 characters per inch", "16.67 characters per inch", "20 characters per inch" }; char *tPitG[] = { "12 characters per inch", "24 characters per inch" }; #define nPitC (sizeof(tPitC) / sizeof(char *)) #define nPitG (sizeof(tPitG) / sizeof(char *)) char cSty[] = "Style"; char *tSty[] = { "Roman", "Italic" }; #define nSty (sizeof(tSty) / sizeof(char *)) char cHei[] = "Character height"; char *tHei[] = { "12 points", "6 points" }; #define nHei (sizeof(tHei) / sizeof(char *)) char cQua[] = "Quality"; char *tQua[] = { "Draft", "Letter" }; #define nQua (sizeof(tQua) / sizeof(char *)) char cSpa[] = "Vertical spacing"; char *tSpa[] = { "6 lines per inch", "8 lines per inch" }; #define nSpa (sizeof(tSpa) / sizeof(char *)) /** | Open required libraries: try graphics library version 37 (Kickstart | 2.04) at first and, if successfull, use asl.library; if not, try | version 33 (Kickstart 1.2) and use req.library. **/ #ifdef ASL GfxBase = LibOpen("graphics.library", REVISION_2, LO_ABORT | LO_MESSAGE); AslBase = LibOpen("asl.library", REVISION_2, LO_ABORT | LO_MESSAGE); #endif #ifdef REQ GfxBase = LibOpen("graphics.library", REVISION, LO_ABORT | LO_MESSAGE); ReqBase = LibOpen("req.library", 0, LO_ABORT | LO_MESSAGE); #endif #ifdef BOTH GfxBase = LibOpen("graphics.library", REVISION_2, 0); if (GfxBase == NULL) { GfxBase = LibOpen("graphics.library", REVISION, LO_ABORT | LO_MESSAGE); ReqBase = LibOpen("req.library", 0, LO_ABORT | LO_MESSAGE); } else { AslBase = LibOpen("asl.library", REVISION_2, LO_ABORT | LO_MESSAGE); } #endif /** | Open topaz-8 font (in RAM) **/ if ((Topaz8 = (struct TextFont *) OpenFont(&ta)) == NULL) { printf("Can't open Topaz-8 font!\n"); Cleanup(SYS_ABORT_CODE); } r1: switch (Ask(cOri, nOri, tOri)) { case QUIT: case CANCEL: Cleanup(SYS_NORMAL_CODE); case 1: PageMode = SINGLE_PAGE; Orientation = PORTRAIT; r2: switch (Ask(cFon, nFon, tFon)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r1; case 1: Font = COURIER; switch (Ask(cPit, nPitC, tPitC)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r2; case 1: Pitch = P10CPI; break; case 2: Pitch = P16_67CPI; break; case 3: Pitch = P20CPI; break; } break; case 2: Font = GOTHIC; switch (Ask(cPit, nPitG, tPitG)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r2; case 1: Pitch = P12CPI; break; case 2: Pitch = P24CPI; } break; case 3: Font = TIMES; Pitch = PROPORTIONAL; break; } if (Font == COURIER && Pitch == P16_67CPI) { Style = ROMAN; } else { switch (Ask(cSty, nSty, tSty)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r2; case 1: Style = ROMAN; break; case 2: Style = ITALIC; break; } } break; case 2: r2l: Orientation = LANDSCAPE; PageMode = SINGLE_PAGE; Font = COURIER; switch (Ask(cPit, nPitC, tPitC)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r1; case 1: Pitch = P10CPI; break; case 2: Pitch = P16_67CPI; break; case 3: Pitch = P20CPI; break; } break; case 3: PageMode = LEFT_PAGE; goto r5; } r3: switch (Ask(cHei, nHei, tHei)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: if (Orientation == PORTRAIT) goto r2; else goto r2l; case 1: Height = 12; break; case 2: Height = 6; break; } r4: switch (Ask(cSpa, nSpa, tSpa)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r3; case 1: Lpi = 6; break; case 2: Lpi = 8; break; } r5: switch (Ask(cQua, nQua, tQua)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: if (PageMode == LEFT_PAGE) goto r1; else goto r4; case 1: Quality = DRAFT_Q; break; case 2: Quality = LETTER_Q; break; } if (PageMode == LEFT_PAGE) goto r7; r6: switch (AskInt("Leading blanks:", 0, 40, &nBlanks)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: goto r5; case OK_FOLKS: if (nBlanks) { Buffer = inBuffer + nBlanks; memset(inBuffer, BLANK, nBlanks); } } r7: switch (AskInt("TAB expansion:", 2, 20, &nTabs)) { case QUIT: Cleanup(SYS_NORMAL_CODE); case CANCEL: if (PageMode == LEFT_PAGE) { goto r5; } goto r6; case OK_FOLKS: windowOff(); if (PageMode == LEFT_PAGE) SetSpecialMode(); } } void windowOff(void) { /** | Closes the requester window (if opened), saving the current | values for left top edge coordinates. **/ struct Message *pIM; if (Wind != NULL) { while ((pIM = GetMsg(Wind->UserPort)) != NULL) ReplyMsg(pIM); NWind.LeftEdge = Wind->LeftEdge; NWind.TopEdge = Wind->TopEdge; CloseWindow(Wind); Wind = NULL; } } void *LibOpen( char *Name, /* Library name */ long Rev, /* Revision level (or 0) */ USHORT flag /* Abort flag */ ){ /** | Open required library **/ void *p; p = OpenLibrary(Name, Rev); if (p == NULL) { if (flag & LO_MESSAGE) { fprintf(stderr, "This program requires %s", Name); if (Rev) { fprintf(stderr, " Rev. %d.\n", Rev); } else { fputs("", stderr); } } if (flag & LO_ABORT) Cleanup(SYS_ABORT_CODE); } return p; } static int Ask( char *pTitle, /* General title */ int nText, /* Number of choices */ char *cText[] /* Description */ ){ /** | This routine displays a "cycle gadget" (an array of nText choices | described by cText[]): i.e. a window where the general title and the | current choice are displayed, together with a forward- and a backward- | cycling gadget, and the 3 fixed gadgets "OK", "QUIT" and "CANCEL". | The return value is either CANCEL (0), or QUIT (-1), or, if OK was | selected, a number in the range 1..nText identifying the currently | selected cycle-gadget choice. The window size should be enough to | display the pTitle and cText strings. **/ int x; /* X coordinate, current string */ int n; /* Number of characters, cur. string */ int newx, newn, newcurrent; int current = 0; /* Current cycle gadget choice */ struct IntuiMessage *pIM; /* Intuition message */ ULONG MClass; /* Message type */ struct RastPort *pRP; /* Requester window raster port */ struct Gadget *pG; /* Selected gadget */ /** | Make sure that the requester window is opened **/ MakeWindow(&forwGadget); /** | Clear the window, and display the general title and the first | cycle-gadget choice. **/ SetAPen((pRP = Wind->RPort), BLACK_PEN); RectFill(pRP, Wind->BorderLeft, Wind->BorderTop, realWidth, realHeight); RefreshGadgets(Wind->FirstGadget, Wind, NULL); SetAPen(pRP, RED_PEN); SetBPen(pRP, BLACK_PEN); x = (realWidth - TextLength(pRP, pTitle, (n = strlen(pTitle)))) / 2; Move(pRP, x, aw_ytitle); (void) Text(pRP, pTitle, n); x = (realWidth - TextLength(pRP, cText[0], (n = strlen(cText[0])))) / 2; SetAPen(pRP, WHITE_PEN); Move(pRP, x, aw_ycycle); (void) Text(pRP, cText[0], n); /** | Now, wait for gadget hits and perform the appropriate action. | Exit when either OK or CANCEL or QUIT has been hit. **/ FOREVER { (void) Wait(1L << Wind->UserPort->mp_SigBit); while ((pIM = (struct IntuiMessage *) GetMsg(Wind->UserPort)) != NULL) { MClass = pIM->Class; pG = (struct Gadget *) pIM->IAddress; ReplyMsg((struct Message *) pIM); switch (MClass) { case GADGETUP: switch (pG->GadgetID) { case AW_CANCEL: return CANCEL; case AW_QUIT: return QUIT; case AW_OK: return ++current; case AW_FORWARD: newcurrent = current + 1; if (newcurrent >= nText) { newcurrent = 0; } newx = (realWidth - TextLength(pRP, cText[newcurrent], (newn = strlen(cText[newcurrent])))) / 2; break; case AW_BACKWARD: newcurrent = current - 1; if (newcurrent < 0) newcurrent = nText - 1; newx = (realWidth - TextLength(pRP, cText[newcurrent], (newn = strlen(cText[newcurrent])))) / 2; break; } SetAPen(pRP, BLACK_PEN); Move(pRP, x, aw_ycycle); (void) Text(pRP, cText[current], n); SetAPen(pRP, WHITE_PEN); current = newcurrent; x = newx; n = newn; Move(pRP, x, aw_ycycle); (void) Text(pRP, cText[current], n); } } } } static int AskInt( char *pTitle, /* General title */ short int valMin, /* Minimum allowed value */ short int valMax, /* Maximum allowed value */ short int *pVal /* Output */ ){ /** | This procedure displays a requester for an integer value, | to be checked against the [valMin,valMax] range. **/ int x; /* X coordinate, title */ int n; /* Number of characters, title */ struct IntuiMessage *pIM; /* Intuition message */ ULONG MClass; /* Message type */ struct RastPort *pRP; /* Requester window raster port */ struct Gadget *pG; /* Selected gadget */ /** | Make sure that the requester window is opened; then clear | the window, and display the general title. **/ MakeWindow(&intGadget); sprintf(intBuffer, "%d", (intInfo.LongInt = *pVal)); SetAPen((pRP = Wind->RPort), BLACK_PEN); RectFill(pRP, Wind->BorderLeft, Wind->BorderTop, realWidth, realHeight); (void) ActivateGadget(&intGadget, Wind, NULL); RefreshGadgets(Wind->FirstGadget, Wind, NULL); SetAPen(pRP, RED_PEN); SetBPen(pRP, BLACK_PEN); x = (realWidth - TextLength(pRP, pTitle, (n = strlen(pTitle)))) / 2; Move(pRP, x, aw_ytitle); (void) Text(pRP, pTitle, n); sprintf(Limits, "Min = %d, Max = %d.", valMin, valMax); /** | Now, wait for gadget hits and perform the appropriate action. | Exit when either OK or CANCEL or QUIT has been hit, or the integer | string gadget deselected (i.e. the user has hit ). **/ FOREVER { (void) Wait(1L << Wind->UserPort->mp_SigBit); while ((pIM = (struct IntuiMessage *) GetMsg(Wind->UserPort)) != NULL) { MClass = pIM->Class; pG = (struct Gadget *) pIM->IAddress; ReplyMsg((struct Message *) pIM); switch (MClass) { case GADGETUP: switch (pG->GadgetID) { case AW_CANCEL: return CANCEL; case AW_QUIT: return QUIT; case AW_OK: case AW_INT: if (intInfo.LongInt < valMin || intInfo.LongInt > valMax) { (void) AutoRequest(Wind, art0, NULL, &arOkText, 0, 0, AR_WIDTH, AR_HEIGHT); } else { *pVal = intInfo.LongInt; return OK_FOLKS; } } } } } } static void MakeWindow( struct Gadget *pG /* First gadget */ ){ /** | Both Ask() and AskInt() use the same window for their requesters. | This routine first checks if the window exists, and if not opens it; | if the window exists, checks if the appropriate gadget chain for | Ask() or for AskInt() is displayed: if so no action is required, if | not MakeWindow() removes the existing gadgets then inserts the new | ones. RefreshGadgets() is called from Ask()/AskInt() after clearing | the requester window calling RectFill(). **/ if (!title[0]) { sprintf(title, "\"PF2\" v%s - MLO %s ", VERSION, LAST_CHANGE); } if (Wind == NULL) { aw_ytitle = ScreenFontHeight + AW_YTITLE; aw_ycycle = ScreenFontHeight + AW_YCYCLE; NWind.Height = ScreenFontHeight + AW_HEIGHT; askGad[0].TopEdge = ScreenFontHeight + AW_YNGAD; askGad[1].TopEdge = ScreenFontHeight + AW_YNGAD; askGad[2].TopEdge = ScreenFontHeight + AW_YNGAD; intGadget.TopEdge = ScreenFontHeight + AW_YCGAD; backGadget.TopEdge = ScreenFontHeight + AW_YCGAD; forwGadget.TopEdge = ScreenFontHeight + AW_YCGAD; NWind.FirstGadget = pG; if ((Wind = OpenWindow(&NWind)) == NULL) Cleanup(SYS_ABORT_CODE); realWidth = Wind->Width - Wind->BorderRight; realHeight = Wind->Height - Wind->BorderBottom; SetFont(Wind->RPort, Topaz8); } else { if (Wind->FirstGadget != pG) { (void) RemoveGList(Wind, Wind->FirstGadget, -1); (void) AddGList(Wind, pG, 0, -1, NULL); } } }