/*---------------------------------------------------------*
 | 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 <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <libraries/dos.h>
#include <libraries/reqbase.h>
#include <devices/printer.h>
#include "mlo.h"
#include "pf2.h"
#include "ext.h"
#include "aw.h"

struct IntuiMessage *GetMsg();
struct Window       *OpenWindow();

void SetupWB(void)
{

/**
 | Printer setup, driven with requester windows when called from
 | the Workbench.
**/

  struct GetLongStruct GLS = {
    NULL, 0, 0, 0, 0, NULL, REQVERSION, 0, 0
  };

  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
**/

  GfxBase       = LibOpen("graphics.library",   REVISION);
  ReqBase       = LibOpen("req.library",        0);

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;
  }

  windowOff();
  if (PageMode == LEFT_PAGE)    goto r7;

r6:
  GLS.titlebar = "Leading blanks:";
  GLS.defaultval = 0;
  GLS.minlimit = 0;
  GLS.maxlimit = 40;
  if (GetLong(&GLS)) {
    nBlanks = GLS.result;
    if (nBlanks) {
      Buffer = inBuffer + nBlanks;
      memset(inBuffer, BLANK, nBlanks);
    }
  } else {
    goto r5;
  }

r7:
  GLS.titlebar = "TAB expansion:";
  GLS.defaultval = 8;
  GLS.minlimit = 2;
  GLS.maxlimit = 20;
  if (GetLong(&GLS)) {
    nTabs = GLS.result;
  } else {
    if (PageMode == LEFT_PAGE)    goto r5;
       else                       goto r6;
  }

  if (PageMode == LEFT_PAGE)    SetSpecialMode();
}

void windowOff(void)
{
  struct IntuiMessage *pIM;

  if (Wind != NULL) {
    while ((pIM = GetMsg(Wind->UserPort)) != NULL) ReplyMsg(pIM);
    CloseWindow(Wind);
    Wind = NULL;
  }
}

void *LibOpen(
  char *Name,                     /* Library name */
  long  Rev                       /* Revision level (or 0) */
){

/**
 | Open required library
**/

  void *p;

  p = (void *) OpenLibrary(Name, Rev);
  if (p == NULL) Cleanup(SYS_ABORT_CODE);
  return p;
}

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 */

/**
 | Ask() uses the same window for all our cycle gadgets; the first
 | time, it has to be opened (will be closed calling windowOff()).
**/

  if (Wind == NULL) {
    sprintf(title, "PF2 v%.2f - MLO %d ", VERSION, LAST_CHANGE);
    if ( (Wind = OpenWindow(&NWind)) == NULL) {
      Cleanup(SYS_ABORT_CODE);
    }
    realWidth  = Wind->Width  - Wind->BorderRight;
    realHeight = Wind->Height - Wind->BorderBottom;
  }

/**
 | 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(askGad, Wind, NULL);

  SetAPen(pRP, RED_PEN);
  SetBPen(pRP, BLACK_PEN);
  x = (realWidth - TextLength(pRP, pTitle, (n = strlen(pTitle)))) / 2;
  Move(pRP, x, AW_YTITLE);
  Text(pRP, pTitle, n);

  x = (realWidth - TextLength(pRP, cText[0], (n = strlen(cText[0])))) / 2;
  SetAPen(pRP, WHITE_PEN);
  Move(pRP, x, AW_YCYCLE);
  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 {
    Wait(1 << Wind->UserPort->mp_SigBit);
    while ((pIM = GetMsg(Wind->UserPort)) != NULL) {
      MClass = pIM->Class;
      pG = (struct Gadget *) pIM->IAddress;
      ReplyMsg(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;
              if (newcurrent >= nText) {
                newcurrent = 0;
              }
              newx = (realWidth - TextLength(pRP, cText[newcurrent],
                  (newn = strlen(cText[newcurrent])))) / 2;
              break;
            case AW_BACKWARD:
              newcurrent = --current;
              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);
          Text(pRP, cText[current], n);
          SetAPen(pRP, WHITE_PEN);

          current = newcurrent;
          x = newx;
          n = newn;
          Move(pRP, x, AW_YCYCLE);
          Text(pRP, cText[current], n);
      }
    }
  }
}
