(*
  .name       ERequests
  .task       Edt requester library
  .release    1.0
  .language   Oberon-2
  .translator Amiga Oberon 3.2
  .system     AmigaOS 2.04/2.1/3.0
  .author     Joachim Barheine
  .address    Hochgrevestraße 3, D-38640 Goslar
  .copyright  (c) 1995 by Joachim Barheine
*)

(* .info: 30/01/95, 19:22:06, version 96 *)

MODULE ERequests;

IMPORT
  SYS:= SYSTEM,

  ASCII,
  ASL,
  Dos,
  EdtOS37,
  Err:= ErrCodes,
  Exec,
  ExecSupport,
  F:= Files,
  GT:= GadTools,
  Gfx:= Graphics,
  GUI,
  I:= Intuition,
  IO:= IOServer,
  K:= Kernel,
  S:= Strings,
  Sett:= Settings,
  Str:= StrPool,
  Util:= Utility;

CONST
  (* search/replace request: *)
  cmdCancel* = 0;
  cmdNext*   = 1;
  cmdPrev*   = 2;

  (* replace request: *)
  cmdStop* = 0;
  cmdYes* = 1;
  cmdNo*    = 2;
  cmdAll*     = 3;

  (* search/replace flags: *)
  ignoreCase* = 0;
  findWord*   = 1;

  (* goto/number/string/choice/options request: *)
  (* cmdCancel* = 0 *)
  cmdOk* = 1;

  (* prefs request: *)
  (* cmdCancel* = 0 *)
  cmdUse*         = 1;

  (* gadget IDs *)
  aCancelID     = 0;
  searchID      = 1;
  replaceID     = 2;
  ignoreCaseID  = 3;
  findWordID    = 4;
  linkChgsID    = 5;
  aNextID       = 6;
  aPrevID       = 7;
  aYesID        = 8;
  aNoID         = 9;
  aAllID        = 10;
  aStopID   = 11;
  numberID      = 12;
  stringID      = 13;
  mxID          = 14;
  aOkID         = 15;
  maxChgsID     = 16;
  tabAlignID= 17;
  marginID      = 18;
  aQueryFontID= 19;
  aQuerySModeID= 20;
  autosaveID= 21;
  autosaveDelayID= 22;
  backupsID = 23;
  sTypeID       = 24;
  leftMarginID= 28;
  rightMarginID= 27;
  linesID   = 28;
  colSpacingID= 29;
  pitchID   = 30;
  spacingID = 31;
  qualityID = 32;
  formattingID= 33;
  lineNumbersID= 34;
  hTimeID   = 35;
  hTitleID  = 36;
  hNumbersID= 37;
  hDateID   = 38;
  convTabsID= 39;
  closeFldsID = 40;
  rmbChgsID = 41;
  sNameID   = 42;
  foldHeaderID = 43;
  scrollerSizeID = 44;
  rmbPosID = 45;

  opt0ID    = 46;

TYPE
  String= ARRAY 256 OF CHAR;

VAR
  fileReq- : ASL.FileRequesterPtr;
  fontReq- : ASL.FontRequesterPtr;
  screenReq- : ASL.ScreenModeRequesterPtr;

  reqMsg: ARRAY 512 OF CHAR;

  backupsLabelArray, autosaveLabelArray, sTypeLabelArray: GUI.LabelArray;
  pitchLabelArray, spacingLabelArray, qualityLabelArray,
  formattingLabelArray, foldHeaderLabelArray, scrollerSizeLabelArray: GUI.LabelArray;

  aCancelWd, aSearchWd, aSearchBackWd, aReplaceWd, aReplaceBackWd,
  findWordWd, ignoreCaseWd, linkChgsWd, searchWd, replaceWd, aStopWd, aYesWd,
  aNoWd, aAllWd, aOkWd, maxChgsWd, tabAlignWd, marginWd, fontNameWd,
  autosaveWd, autosaveLabelArrayWd, autosaveDelayWd, backupsWd,
  backupsLabelArrayWd, sTypeWd, sTypeLabelArrayWd, leftMarginWd,
  rightMarginWd, linesWd, colSpacingWd, pitchWd, pitchLabelArrayWd, spacingWd,
  spacingLabelArrayWd, qualityWd, qualityLabelArrayWd, formattingWd,
  formattingLabelArrayWd, lineNumbersWd, hTimeWd, hTitleWd, hNumbersWd,
  hDateWd, convTabsWd, closeFldsWd, rmbChgsWd, sNameWd, sModeNameWd,
  foldHeaderWd, foldHeaderLabelArrayWd, aQueryWd, scrollerSizeWd,
  scrollerSizeLabelArrayWd: INTEGER;

  backupsLabelArrayLen, autosaveLabelArrayLen, sTypeLabelArrayLen,
  pitchLabelArrayLen, spacingLabelArrayLen, qualityLabelArrayLen,
  formattingLabelArrayLen, foldHeaderLabelArrayLen,
  scrollerSizeLabelArrayLen: SHORTINT;

  winX, winY: INTEGER;

PROCEDURE CreateOkCancelGads(wWidth, wHeight: INTEGER): BOOLEAN;

VAR
  y: INTEGER;

BEGIN
  y:= wHeight - 4 - GUI.buttonHt;
  GUI.NewCol(8, y, -1);
  IF GUI.CreateButtonGad(aOkID, Str.aOk^, aCancelWd, TRUE) = NIL THEN RETURN FALSE END;
  GUI.NewCol(wWidth - 8 - aCancelWd, y, -1);
  IF GUI.CreateButtonGad(aCancelID, Str.aCancel^, aCancelWd, TRUE) = NIL THEN RETURN FALSE END;
  RETURN TRUE;
END CreateOkCancelGads;

PROCEDURE ReqAction* (w: I.WindowPtr; message, gadgets: ARRAY OF CHAR): SHORTINT;

(* message: the message as C-style-formatting-string *)
(* gadgets: the gadgetlabels *)

VAR
  easy: I.EasyStruct;
  i: INTEGER;
  result: SHORTINT;

(* $CopyArrays- *)

BEGIN
  i:= 0;
  WHILE message[i] # 0X DO
    IF message[i]= "|" THEN message[i]:= ASCII.lf END;
    INC(i);
  END;

  easy.structSize  := SIZE(I.EasyStruct);
  easy.flags       := LONGSET{};
  easy.textFormat  := SYS.ADR(message);
  easy.gadgetFormat:= SYS.ADR(gadgets);
  easy.title       := SYS.ADR(Str.edt);

  result:= SHORT(SHORT(I.EasyRequest(w, SYS.ADR(easy), NIL, Util.done)));
  IO.Refresh;
  RETURN result;
END ReqAction;

PROCEDURE ReqMessage* (w: I.WindowPtr; msg, gad: ARRAY OF CHAR);

(* $CopyArrays- *)

BEGIN
  IF ReqAction(w, msg, gad) = 0 THEN END;
END ReqMessage;

PROCEDURE ReqActionArgs* (w: I.WindowPtr; msg, gads: ARRAY OF CHAR; arg0, arg1: LONGINT): SHORTINT;

VAR
  a: ARRAY 2 OF LONGINT;

(* $CopyArrays- *)

BEGIN
  a[0]:= arg0; a[1]:= arg1;
  K.FormatString(reqMsg, msg, a);
  RETURN ReqAction(w, reqMsg, gads);
END ReqActionArgs;

PROCEDURE ReqFont* (w: I.WindowPtr; VAR spec: Gfx.TextAttr): BOOLEAN;

VAR
  result: BOOLEAN;

BEGIN
  result:= ASL.AslRequestTags(fontReq, ASL.window, w, Util.done);
  IF result = TRUE THEN spec:= fontReq.attr END;
  IO.Refresh;
  RETURN result;
END ReqFont;

PROCEDURE ReqFile* (w: I.WindowPtr; VAR filename: ARRAY OF CHAR; save: BOOLEAN): BOOLEAN;

VAR
  hail: Exec.LSTRPTR;
  path: ARRAY F.pathLen OF CHAR;
  name: ARRAY F.nameLen OF CHAR;
  lock: Dos.FileLockPtr;
  result: BOOLEAN;

BEGIN
  F.GetPath(path, filename); F.GetName(name, filename);
  IF save THEN
    hail:= Str.saveHail;
  ELSE
    hail:= Str.loadHail;
  END;
  result:= ASL.AslRequestTags(fileReq, ASL.window, w,
                              ASL.titleText, hail,
                              ASL.doSaveMode, I.BoolToLong(save),
                              ASL.initialDrawer, SYS.ADR(path),
                              ASL.initialFile, SYS.ADR(name),
                              Util.done) & (fileReq.file^ # "");
  IF result = TRUE THEN
    F.GetFilename(filename, fileReq.dir^, fileReq.file^);
    lock:= Dos.Lock(filename, Dos.sharedLock);
    IF lock # NIL THEN
      IF ~Dos.NameFromLock(lock, filename, LEN(filename)) THEN END;
      Dos.UnLock(lock);
    END;
  END;
  IO.Refresh;
  RETURN result;
END ReqFile;

PROCEDURE ReqNumber* (w: I.WindowPtr; title, label: ARRAY OF CHAR;
                      VAR number: LONGINT): SHORTINT;

VAR
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  numberGad: I.GadgetPtr;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  code: INTEGER;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    gw: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    wWidth:= 24 + (2 * aCancelWd);
    wHeight:= 8 + GUI.stringHt + 8 + GUI.buttonHt + 4;

    gw:= GUI.TextWidth(label) + (6 * GUI.zeroWd) + 18;
    GUI.GetMax(wWidth, gw + 16);

    GUI.NewCol((wWidth - gw) DIV 2 + GUI.TextWidth(label) + 6, 8, -1);
    numberGad:= GUI.CreateIntegerGad(numberID, label, (6 * GUI.zeroWd) + 12, number, 10, TRUE);

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

(* $CopyArrays- *)

BEGIN
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(title, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.integerIDCMP, gadList);
    IF win # NIL THEN
      GUI.ActivateGad(numberGad, win);
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
                  I.refreshWindow:
                        GT.BeginRefresh(win);
                        GT.EndRefresh(win, I.LTRUE);
                        GT.ReplyIMsg(iMsg);
                | I.changeWindow:
                        IO.Refresh;
                        GT.ReplyIMsg(iMsg);
                | I.gadgetUp:
                        g:= iMsg.iAddress;
                        code:= iMsg.code;
                        GT.ReplyIMsg(iMsg);
                        CASE g.gadgetID OF
                          numberID:
                                IF (code # GUI.escKey) & (code # GUI.tabKey) THEN
                                  result:= cmdOk;
                                  EXIT;
                                END;
                        | aOkID:
                                result:= cmdOk;
                                EXIT;
                        | aCancelID:
                                result:= cmdCancel;
                                EXIT;
                        END;
                | I.vanillaKey:
                        c:= Util.ToUpper(CHR(iMsg.code));
                        GT.ReplyIMsg(iMsg);
                        IF c= Str.aOkCh THEN
              result:= cmdOk;
              EXIT;
            ELSIF c= Str.aCancelCh THEN
              result:= cmdCancel;
              EXIT;
            ELSE
              GUI.Flash;
            END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result = cmdOk THEN number:= numberGad.specialInfo(I.StringInfo).longInt END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqNumber;

PROCEDURE ReqString* (w: I.WindowPtr; title, label: ARRAY OF CHAR;
                      VAR string: ARRAY OF CHAR): SHORTINT;

VAR
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  stringGad: I.GadgetPtr;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  code: INTEGER;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    gw: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    wWidth:= 24 + (2 * aCancelWd);
    wHeight:= GUI.stringHt + GUI.buttonHt + 20;

    gw:= GUI.TextWidth(label) + 338;
    GUI.GetMax(wWidth, gw + 16);

    GUI.NewCol((wWidth - gw) DIV 2 + (GUI.TextWidth(label) + 6), 8, -1);
    stringGad:= GUI.CreateStringGad(stringID, label, 332, string, TRUE);

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

(* $CopyArrays- *)

BEGIN
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(title, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.stringIDCMP, gadList);
    IF win # NIL THEN
      GUI.ActivateGad(stringGad, win);
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
                  I.refreshWindow:
                        GT.BeginRefresh(win);
                        GT.EndRefresh(win, I.LTRUE);
                        GT.ReplyIMsg(iMsg);
                | I.changeWindow:
                        IO.Refresh;
                        GT.ReplyIMsg(iMsg);
                | I.gadgetUp:
                        g:= iMsg.iAddress;
                        code:= iMsg.code;
                        GT.ReplyIMsg(iMsg);
                        CASE g.gadgetID OF
                          stringID:
                                IF (code # GUI.escKey) & (code # GUI.tabKey) THEN
                                  result:= cmdOk;
                                  EXIT;
                                END;
                        | aOkID:
                                result:= cmdOk;
                                EXIT;
                        | aCancelID:
                                result:= cmdCancel;
                                EXIT;
                        END;
                | I.vanillaKey:
                        c:= Util.ToUpper(CHR(iMsg.code));
                        GT.ReplyIMsg(iMsg);
            IF c= Str.aOkCh THEN
              result:= cmdOk;
              EXIT;
            ELSIF c= Str.aCancelCh THEN
              result:= cmdCancel;
              EXIT;
            ELSE
              GUI.Flash;
            END;
                ELSE
                  GT.ReplyIMsg(iMsg);
                END;
      END;
      IF result = cmdOk THEN COPY(stringGad.specialInfo(I.StringInfo).buffer^, string) END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqString;

PROCEDURE ReqChoice* (w: I.WindowPtr; title, label, mxLabels: ARRAY OF CHAR;
                      VAR choice: SHORTINT): SHORTINT;

VAR
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  mxLabelArray: GUI.LabelArray;
  mxLabelWidth, labelLen, labelWd: INTEGER;
  mxLabelArrayLen: SHORTINT;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  active: SHORTINT;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    wWidth:= 10 + (2 * aCancelWd);
    GUI.GetMax(wWidth, mxLabelWidth + GUI.mxWd + 6);
    GUI.GetMax(wWidth, labelWd);
    INC(wWidth, 32);
    wHeight:= GUI.reqFont.ySize + 20 + mxLabelArrayLen
              * (GUI.reqFont.ySize + GUI.mxSpacing) + GUI.buttonHt;

    GUI.NewCol((wWidth - (mxLabelWidth + GUI.mxWd + 6)) DIV 2, GUI.reqFont.ySize + 8, -1);
    RETURN (GUI.CreateMXGad(mxID, label, mxLabelArray, active) # NIL)
         & CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

  PROCEDURE WriteText;

  BEGIN
    IF K.intVer < 39 THEN
      Gfx.Move(win.rPort, (win.width - labelWd) DIV 2, win.borderTop + 4 + GUI.reqFont.baseline);
      Gfx.Text(win.rPort, label, labelLen);
    END;
  END WriteText;

(* $CopyArrays- *)

BEGIN
  active:= choice;
  result:= cmdCancel;
  gadList:= NIL;
  GUI.CreateLabelArray(mxLabelArray, mxLabelArrayLen, mxLabelWidth, mxLabels);
  labelLen:= SHORT(S.Length(label)); labelWd:= GUI.TextWidth(label);
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(title, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.mxIDCMP, gadList);
    IF win # NIL THEN
      Gfx.SetAPen(win.rPort, IO.highTextPen);
      Gfx.SetFont(win.rPort, GUI.reqFont);
      WriteText;
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow: GT.BeginRefresh(win);
                           WriteText;
                           GT.EndRefresh(win, I.LTRUE);
                           GT.ReplyIMsg(iMsg);
        | I.changeWindow:  IO.Refresh;
                           GT.ReplyIMsg(iMsg);
        | I.gadgetDown:    g:= iMsg.iAddress;
                           IF g.gadgetID = mxID THEN
                             active:= SHORT(iMsg.code);
                           END;
                           GT.ReplyIMsg(iMsg);
        | I.gadgetUp:      g:= iMsg.iAddress;
                           GT.ReplyIMsg(iMsg);
                           CASE g.gadgetID OF
                             mxID:      (* igonore *)
                           | aOkID:     result:= cmdOk;
                                        EXIT;
                           | aCancelID: result:= cmdCancel;
                                        EXIT;
                           END;
        | I.vanillaKey:    c:= Util.ToUpper(CHR(iMsg.code));
                           GT.ReplyIMsg(iMsg);
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result= cmdOk THEN choice:= active END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  GUI.DisposeLabelArray(mxLabelArray);
  IO.Refresh;
  RETURN result;
END ReqChoice;

PROCEDURE ReqOptions* (w: I.WindowPtr; title, label, optLabels: ARRAY OF CHAR;
                       VAR options: LONGSET): SHORTINT;

VAR
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  optLabelArray: GUI.LabelArray;
  opt, optLabelWidth, labelLen, labelWd: INTEGER;
  optLabelArrayLen: SHORTINT;
  iMsg: I.IntuiMessagePtr;
  opts: LONGSET;
  c: CHAR;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    str: UNTRACED POINTER TO String;
    i, cols, lines: SHORTINT;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    cols:= 1;
    IF optLabelArrayLen > 7 THEN cols:= 2 END;
    IF optLabelArrayLen > 21 THEN cols:= 3 END;
    lines:= (optLabelArrayLen + cols - 1) DIV cols;

    wWidth:= 10 + (2 * aCancelWd);
    wHeight:= GUI.reqFont.ySize + 20 + lines * (GUI.checkBoxHt + GUI.cbSpacing) + GUI.buttonHt;
    GUI.GetMax(wWidth, cols * (optLabelWidth + GUI.checkBoxWd + 6 + 10));
    GUI.GetMax(wWidth, labelWd + 10);
    INC(wWidth, 32);

    FOR i:= 0 TO optLabelArrayLen - 1 DO
      IF i MOD lines = 0 THEN
        GUI.NewCol(16 + (i DIV lines) * (optLabelWidth + GUI.checkBoxWd + 6 + 10), GUI.reqFont.ySize + 8, GUI.cbSpacing);
      END;
      str:= optLabelArray[i];
      IF GUI.CreateCheckBoxGad(opt0ID + i, str^, i IN opts, TRUE) = NIL THEN RETURN FALSE END;
    END;

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

  PROCEDURE WriteText;

  BEGIN
    Gfx.Move(win.rPort,
             (win.width - labelWd) DIV 2, win.borderTop + 4 + GUI.reqFont.baseline);
    Gfx.Text(win.rPort, label, labelLen);
  END WriteText;

(* $CopyArrays- *)

BEGIN
  opts:= options;
  result:= cmdCancel;
  gadList:= NIL;
  labelLen:= SHORT(S.Length(label)); labelWd:= GUI.TextWidth(label);
  GUI.CreateLabelArray(optLabelArray, optLabelArrayLen, optLabelWidth, optLabels);
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(title, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.checkBoxIDCMP, gadList);
    IF win # NIL THEN
      Gfx.SetAPen(win.rPort, IO.highTextPen);
      Gfx.SetFont(win.rPort, GUI.reqFont);
      WriteText;
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow:
            GT.BeginRefresh(win);
            WriteText;
            GT.EndRefresh(win, I.LTRUE);
            GT.ReplyIMsg(iMsg);
        | I.changeWindow:
            IO.Refresh;
            GT.ReplyIMsg(iMsg);
        | I.gadgetUp:
            g:= iMsg.iAddress;
            GT.ReplyIMsg(iMsg);
            CASE g.gadgetID OF
              opt0ID..opt0ID+31:
                         opt:= g.gadgetID-opt0ID;
                         IF opt IN opts THEN
                           EXCL(opts, opt);
                         ELSE
                           INCL(opts, opt);
                         END;
            | aOkID:     result:= cmdOk;
                         EXIT;
            | aCancelID: result:= cmdCancel;
                         EXIT;
            END;
        | I.vanillaKey:
            c:= Util.ToUpper(CHR(iMsg.code));
            GT.ReplyIMsg(iMsg);
                   IF c= Str.aOkCh THEN
              result:= cmdOk;
              EXIT;
            ELSIF c= Str.aCancelCh THEN
              result:= cmdCancel;
              EXIT;
            ELSE
              GUI.Flash;
            END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result= cmdOk THEN options:= opts END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  GUI.DisposeLabelArray(optLabelArray);
  IO.Refresh;
  RETURN result;
END ReqOptions;

PROCEDURE ReqEditPrefs* (w: I.WindowPtr; VAR convTabs, closeFlds, rmbPos,
                    rmbChgs: BOOLEAN; VAR undoBufSize, tabAlign, margin,
                    autosaveDelay: INTEGER; VAR backups, autosave: SHORTINT): SHORTINT;

VAR
  result: SHORTINT;
  defConfig: BOOLEAN;  (* running with default configuration *)
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  convTabsGad, closeFldsGad, rmbPosGad, rmbChgsGad, maxChgsGad, tabAlignGad, marginGad,
  autosaveDelayGad, backupsGad, autosaveGad: I.GadgetPtr;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  code: INTEGER;
  convTabsNew, closeFldsNew, rmbPosNew, rmbChgsNew: BOOLEAN;
  backupsNew, autosaveNew: SHORTINT;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    y: INTEGER;
    w0, x1, w1, x2, w2: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    w0:= convTabsWd; GUI.GetMax(w0, closeFldsWd); GUI.GetMax(w0, rmbChgsWd);
    x1:= maxChgsWd; GUI.GetMax(x1, tabAlignWd); GUI.GetMax(x1, marginWd);
    GUI.GetMax(x1, autosaveDelayWd);
    INC(x1, GUI.horizOffs + GUI.checkBoxWd + w0 + GUI.horizSpc);
    w1:= (6 * GUI.zeroWd) + 12;

    x2:= backupsWd; GUI.GetMax(x2, autosaveWd);
    INC(x2, GUI.horizOffs);
    w2:= backupsLabelArrayWd; GUI.GetMax(w2, autosaveLabelArrayWd);

    GUI.NewCol(GUI.horizOffs, GUI.vertOffs, GUI.cbSpacing);
    convTabsGad:= GUI.CreateCheckBoxGad(convTabsID, Str.convTabs^, convTabsNew, TRUE);
    closeFldsGad:= GUI.CreateCheckBoxGad(closeFldsID, Str.closeFlds^, closeFldsNew, TRUE);
    rmbPosGad:= GUI.CreateCheckBoxGad(rmbPosID, Str.rmbPos^, rmbPosNew, TRUE);
    rmbChgsGad:= GUI.CreateCheckBoxGad(rmbChgsID, Str.rmbChgs^, rmbChgsNew, TRUE);

    GUI.NewCol(x1, GUI.vertOffs, 2);
    maxChgsGad:= GUI.CreateIntegerGad(maxChgsID, Str.maxChgs^, w1, undoBufSize, 5, rmbChgsNew);
    tabAlignGad:= GUI.CreateIntegerGad(tabAlignID, Str.tabAlign^, w1, tabAlign, 2, TRUE);
    marginGad:= GUI.CreateIntegerGad(marginID, Str.margin^, w1, margin, 2, TRUE);
    autosaveDelayGad:= GUI.CreateIntegerGad(autosaveDelayID, Str.autosaveDelay^, w1,
                                        autosaveDelay, 2, autosave # Sett.autosaveOff);
    GUI.NewCol(x2, GUI.layoutY + GUI.vertOffs, 2);
    backupsGad:= GUI.CreateCycleGad(backupsID, Str.backups^, w2, backupsLabelArray, backups, TRUE);
    autosaveGad:= GUI.CreateCycleGad(autosaveID, Str.autosave^, w2, autosaveLabelArray, autosave, TRUE);

    wWidth:= x1 + w1 + GUI.horizOffs;
    wHeight:= GUI.layoutY + GUI.vertSpc + GUI.buttonHt + GUI.vertOffs;

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

  (* update autosave-delay gadget *)
  PROCEDURE UpdateASD;

  BEGIN
    GT.SetGadgetAttrs(autosaveDelayGad^, win, NIL, I.gaDisabled,
                      I.BoolToLong(autosaveNew = Sett.autosaveOff), Util.done);
  END UpdateASD;

  (* update undobuffer-size gadget *)
  PROCEDURE UpdateUBS;

  BEGIN
    GT.SetGadgetAttrs(maxChgsGad^, win, NIL, I.gaDisabled, I.BoolToLong(~rmbChgsNew),
                      Util.done);
  END UpdateUBS;

BEGIN
  defConfig:= (Sett.configName = Sett.defConfig);
  convTabsNew:= convTabs;
  closeFldsNew:= closeFlds;
  rmbPosNew:= rmbPos;
  rmbChgsNew:= rmbChgs;
  backupsNew:= backups;
  autosaveNew:= autosave;
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(Str.editPrefsTitle^, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey} + GT.buttonIDCMP
                        + GT.checkBoxIDCMP + GT.integerIDCMP + GT.cycleIDCMP, gadList);
    IF win # NIL THEN
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow:
                        GT.BeginRefresh(win);
                        GT.EndRefresh(win, I.LTRUE);
                        GT.ReplyIMsg(iMsg);
        | I.changeWindow:
                        IO.Refresh;
                        GT.ReplyIMsg(iMsg);
        | I.gadgetUp:
          g:= iMsg.iAddress;
          code:= iMsg.code;
          GT.ReplyIMsg(iMsg);
          CASE g.gadgetID OF
            convTabsID:
            convTabsNew:= ~convTabsNew;
          | closeFldsID:
            closeFldsNew:= ~closeFldsNew;
          | rmbPosID:
            rmbPosNew:= ~rmbPosNew;
          | rmbChgsID:
            rmbChgsNew:= ~rmbChgsNew;
            UpdateUBS;
          | maxChgsID:
            IF maxChgsGad.specialInfo(I.StringInfo).longInt <= 0 THEN
              GUI.ToggleGad(rmbChgsGad, win, rmbChgsNew);
            END;
          | backupsID:
            backupsNew:= SHORT(code);
          | autosaveID:
            autosaveNew:= SHORT(code);
            UpdateASD;
          | aOkID:
            result:= cmdUse;
            EXIT;
          | aCancelID:
            result:= cmdCancel;
            EXIT
          ELSE
            (* ignore *)
          END;
        | I.vanillaKey:
          c:= Util.ToUpper(CHR(iMsg.code));
          GT.ReplyIMsg(iMsg);
          IF c= Str.convTabsCh THEN
            GUI.ToggleGad(convTabsGad, win, convTabsNew);
          ELSIF c= Str.closeFldsCh THEN
            GUI.ToggleGad(closeFldsGad, win, closeFldsNew);
          ELSIF c= Str.rmbPosCh THEN
            GUI.ToggleGad(rmbPosGad, win, rmbPosNew);
          ELSIF c= Str.rmbChgsCh THEN
            GUI.ToggleGad(rmbChgsGad, win, rmbChgsNew);
            UpdateUBS;
          ELSIF c= Str.maxChgsCh THEN
            GUI.ActivateGad(maxChgsGad, win);
          ELSIF c= Str.tabAlignCh THEN
            GUI.ActivateGad(tabAlignGad, win);
          ELSIF c= Str.marginCh THEN
            GUI.ActivateGad(marginGad, win);
          ELSIF c= Str.autosaveDelayCh THEN
            GUI.ActivateGad(autosaveDelayGad, win);
          ELSIF c= Str.backupsCh THEN
            GUI.CycleGad(backupsGad, win, backupsNew, backupsLabelArrayLen);
          ELSIF c= Str.autosaveCh THEN
            GUI.CycleGad(autosaveGad, win, autosaveNew, autosaveLabelArrayLen);
            UpdateASD;
          ELSIF c= Str.aOkCh THEN
            result:= cmdUse;
            EXIT;
          ELSIF c= Str.aCancelCh THEN
            result:= cmdCancel;
            EXIT;
          ELSE
            GUI.Flash;
          END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result = cmdUse THEN
        undoBufSize:= SHORT(maxChgsGad.specialInfo(I.StringInfo).longInt);
        tabAlign:= SHORT(tabAlignGad.specialInfo(I.StringInfo).longInt);
        margin:= SHORT(marginGad.specialInfo(I.StringInfo).longInt);
        autosaveDelay:= SHORT(SHORT(autosaveDelayGad.specialInfo(I.StringInfo).longInt));
        convTabs:= convTabsNew;
        closeFlds:= closeFldsNew;
        rmbPos:= rmbPosNew;
        rmbChgs:= rmbChgsNew;
        backups:= backupsNew;
        autosave:= autosaveNew;
        K.ClipI(undoBufSize, 0, MAX(INTEGER));
        K.ClipI(tabAlign, 1, 32);
        K.ClipI(margin, 1, MAX(INTEGER));
        K.ClipI(autosaveDelay, 1, 60);
      END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqEditPrefs;

PROCEDURE ReqDisplayPrefs* (w: I.WindowPtr; VAR sType: SHORTINT;
                     VAR sName: ARRAY OF CHAR; VAR sMode: LONGINT;
                     VAR sWidth, sHeight: LONGINT; VAR sDepth: INTEGER;
                     VAR foldHeader, scrollerSize: SHORTINT;
                     VAR fontSpec: Gfx.TextAttr): SHORTINT;

VAR
  result: SHORTINT;
  defConfig: BOOLEAN;  (* running with default configuration *)
  win: I.WindowPtr;
  ww, wh: INTEGER;
  g, gadList, context: I.GadgetPtr;
  sTypeGad, sNameGad, sModeNameGad, sPageSizeGad, fontNameGad, foldHeaderGad,
  scrollerSizeGad, aQuerySModeGad, aQueryFontGad: I.GadgetPtr;
  fontName, sPageSize, sModeName: String;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  code: INTEGER;
  fontSpecNew: Gfx.TextAttr;
  sNameNew: String;
  sTypeNew, foldHeaderNew, scrollerSizeNew: SHORTINT;
  sWidthNew, sHeightNew: LONGINT;
  sDepthNew: INTEGER;
  sModeNew: LONGINT;

  PROCEDURE CreateFontName(VAR name: ARRAY OF CHAR; attr: Gfx.TextAttr);

  VAR
    args: ARRAY 2 OF LONGINT;

  BEGIN
    args[0]:= SYS.ADR(attr.name^); args[1]:= attr.ySize;
    K.FormatString(name, "%s %ld", args);
  END CreateFontName;

  PROCEDURE GetModeName(VAR name: ARRAY OF CHAR; id: LONGINT);

  VAR
    nameInfo: Gfx.NameInfo;

  BEGIN
    IF Gfx.GetDisplayInfoData(NIL, nameInfo, SIZE(nameInfo), Gfx.dtagName, id) # 0 THEN
      COPY(nameInfo.name, name);
    ELSE
      name:= "???";
    END;
  END GetModeName;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    x0, w0, x1, y0, y1: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    x0:= sTypeWd; GUI.GetMax(x0, sNameWd); GUI.GetMax(x0, sModeNameWd);
    GUI.GetMax(x0, fontNameWd); GUI.GetMax(x0, foldHeaderWd);
    GUI.GetMax(x0, scrollerSizeWd);
    INC(x0, GUI.horizOffs);
    w0:= sTypeLabelArrayWd; GUI.GetMax(w0, 30 * GUI.xWd + 6);
    GUI.GetMax(w0, foldHeaderLabelArrayWd);
    GUI.GetMax(w0, scrollerSizeLabelArrayWd);

    x1:= x0 + w0 + GUI.horizSpc;

    GUI.NewCol(x0, GUI.vertOffs, 2);
    sTypeGad:= GUI.CreateCycleGad(sTypeID, Str.sType^, w0, sTypeLabelArray, sTypeNew, defConfig);
    sNameGad:= GUI.CreateStringGad(sNameID, Str.sName^, w0, sNameNew, defConfig & (sTypeNew # Sett.screenWb));
    y0:= GUI.layoutY;
    sModeNameGad:= GUI.CreateTextGad(Str.sModeName^, w0, sModeName);

    GUI.NewCol(-1, GUI.layoutY - 2 + GUI.vertSpc, 2);
    y1:= GUI.layoutY;
    fontNameGad:= GUI.CreateTextGad(Str.fontName^, w0, fontName);
    foldHeaderGad:= GUI.CreateCycleGad(foldHeaderID, Str.foldHeader^, w0,
      foldHeaderLabelArray, foldHeaderNew, TRUE);
    scrollerSizeGad:= GUI.CreateCycleGad(scrollerSizeID, Str.scrollerSize^, w0,
      scrollerSizeLabelArray, scrollerSizeNew, TRUE);

    wHeight:= GUI.layoutY - 2 + GUI.vertSpc + GUI.buttonHt + GUI.vertOffs;

    GUI.NewCol(x0 + w0, y0, 0);
    aQuerySModeGad:= GUI.CreateButtonGad(aQuerySModeID, "?", aQueryWd, (sTypeNew = Sett.screenCustom));
    GUI.NewCol(-1, y1, 0);
    aQueryFontGad:= GUI.CreateButtonGad(aQueryFontID, "?", aQueryWd, TRUE);

    wWidth:= GUI.layoutX + aQueryWd + GUI.horizSpc;

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

  PROCEDURE SelectFont;

  BEGIN
    IF ReqFont(win, fontSpecNew) THEN
      CreateFontName(fontName, fontSpecNew);
      GT.SetGadgetAttrs(fontNameGad^, win, NIL, GT.txText, SYS.ADR(fontName), Util.done);
    END;
  END SelectFont;

  PROCEDURE SelectSMode;

 BEGIN
    IF screenReq # NIL THEN
      IF ASL.AslRequestTags(screenReq, ASL.window, win,
                            ASL.initialDisplayID, sModeNew,
                            ASL.initialDisplayWidth, sWidthNew,
                            ASL.initialDisplayHeight, sHeightNew,
                            ASL.initialDisplayDepth, sDepthNew,
                            Util.done) THEN
        sModeNew:= screenReq.displayID;
        sWidthNew:= screenReq.displayWidth;
        sHeightNew:= screenReq.displayHeight;
        sDepthNew:= screenReq.displayDepth;
      END;
    ELSIF EdtOS37.base # NIL THEN
      IF EdtOS37.ReqScreen(win, sModeNew, sDepthNew) THEN
        sWidthNew:= I.stdScreenWidth;
        sHeightNew:= I.stdScreenHeight;
      END;
    ELSE
      GUI.Flash;
    END;
    GetModeName(sModeName, sModeNew);
    GT.SetGadgetAttrs(sModeNameGad^, win, NIL, GT.txText, SYS.ADR(sModeName), Util.done);
  END SelectSMode;

  (* update select-screenType button*)
  PROCEDURE NewSType;

  BEGIN
    GT.SetGadgetAttrs(aQuerySModeGad^, win, NIL, I.gaDisabled,
                      I.BoolToLong(~defConfig OR (sTypeNew # Sett.screenCustom)),
                      Util.done);
    GT.SetGadgetAttrs(sNameGad^, win, NIL, I.gaDisabled,
                      I.BoolToLong(~defConfig OR (sTypeNew = Sett.screenWb)), Util.done);
    IF sTypeNew = Sett.screenWb THEN
      GT.SetGadgetAttrs(sNameGad^, win, NIL, GT.stString, SYS.ADR("Workbench"), Util.done);
    ELSE
      GT.SetGadgetAttrs(sNameGad^, win, NIL, GT.stString, SYS.ADR(sName), Util.done);
    END;
    IF sTypeNew = Sett.screenCustom THEN
      GetModeName(sModeName, sModeNew);
      GT.SetGadgetAttrs(sModeNameGad^, win, NIL, GT.txText, SYS.ADR(sModeName), Util.done);
    ELSE
      GT.SetGadgetAttrs(sModeNameGad^, win, NIL, GT.txText, NIL, Util.done);
    END;
  END NewSType;

BEGIN
  defConfig:= Sett.configName = Sett.defConfig;
  sTypeNew:= sType;
  sWidthNew:= sWidth;
  sHeightNew:= sHeight;
  sDepthNew:= sDepth;
  sModeNew:= sMode;
  IF sTypeNew = Sett.screenCustom THEN
    GetModeName(sModeName, sModeNew);
  ELSE
    sModeName:= "";
  END;
  COPY(sName, sNameNew);
  foldHeaderNew:= foldHeader;
  scrollerSizeNew:= scrollerSize;
  fontSpecNew:= fontSpec;
  CreateFontName(fontName, fontSpecNew);
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(Str.displayPrefsTitle^, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.stringIDCMP + GT.cycleIDCMP
                        + GT.checkBoxIDCMP, gadList);
    IF win # NIL THEN
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow:
          GT.BeginRefresh(win);
          GT.EndRefresh(win, I.LTRUE);
          GT.ReplyIMsg(iMsg);
        | I.changeWindow:
          IO.Refresh;
          GT.ReplyIMsg(iMsg);
        | I.gadgetUp:
          g:= iMsg.iAddress;
          code:= iMsg.code;
          GT.ReplyIMsg(iMsg);
          CASE g.gadgetID OF
             sTypeID:
             sTypeNew:= SHORT(code);
             NewSType;
           | scrollerSizeID:
             scrollerSizeNew:= SHORT(code);
           | foldHeaderID:
             foldHeaderNew:= SHORT(code);
           | aQueryFontID:
             SelectFont;
           | aQuerySModeID:
             SelectSMode;
           | aOkID:
             result:= cmdUse;
             EXIT;
           | aCancelID:
             result:= cmdCancel;
             EXIT
           ELSE
             (* ignore *)
           END;
        | I.vanillaKey:
          c:= Util.ToUpper(CHR(iMsg.code));
          GT.ReplyIMsg(iMsg);
          IF c= Str.sTypeCh THEN
            GUI.CycleGad(sTypeGad, win, sTypeNew, sTypeLabelArrayLen);
            NewSType;
          ELSIF c= Str.foldHeaderCh THEN
            GUI.CycleGad(foldHeaderGad, win, foldHeaderNew, foldHeaderLabelArrayLen);
          ELSIF c= Str.scrollerSizeCh THEN
            GUI.CycleGad(scrollerSizeGad, win, scrollerSizeNew, scrollerSizeLabelArrayLen);
          ELSIF c= Str.sNameCh THEN
            GUI.ActivateGad(sNameGad, win);
          ELSIF c= Str.sModeNameCh THEN
            SelectSMode;
          ELSIF c= Str.fontNameCh THEN
            SelectFont;
          ELSIF c= Str.aOkCh THEN
            result:= cmdUse;
            EXIT;
          ELSIF c= Str.aCancelCh THEN
            result:= cmdCancel;
            EXIT;
          ELSE
            GUI.Flash;
          END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
    END;
    IF result = cmdUse THEN
      sType:= sTypeNew;
      COPY(sNameGad.specialInfo(I.StringInfo).buffer^, sName);
      sMode:= sModeNew;
      sWidth:= sWidthNew;
      sHeight:= sHeightNew;
      sDepth:= sDepthNew;
      foldHeader:= foldHeaderNew;
      scrollerSize:= scrollerSizeNew;
      fontSpec:= fontSpecNew;
    END;
    I.CloseWindow(win);
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqDisplayPrefs;

PROCEDURE ReqPrint* (w: I.WindowPtr; VAR pitch, spacing, quality, formatting: SHORTINT;
                   VAR leftMargin, rightMargin, lines, colSpacing: INTEGER;
                   VAR lineNumbers, hTitle, hNumbers, hDate, hTime: BOOLEAN): SHORTINT;

VAR
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  iMsg: I.IntuiMessagePtr;
  c: CHAR;
  code: INTEGER;
  g, context, gadList: I.GadgetPtr;
  pitchGad, spacingGad, qualityGad, formattingGad, leftMarginGad, rightMarginGad,
  linesGad, colSpacingGad, lineNumbersGad, hTimeGad, hTitleGad, hNumbersGad,
  hDateGad: I.GadgetPtr;
  pitchNew, spacingNew, qualityNew, formattingNew: SHORTINT;
  lineNumbersNew, hTimeNew, hTitleNew, hNumbersNew, hDateNew: BOOLEAN;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    x1, x2, x3, w1, w2, w3, h: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    x1:= leftMarginWd; GUI.GetMax(x1, rightMarginWd);
    GUI.GetMax(x1, linesWd); GUI.GetMax(x1, colSpacingWd);
    INC(x1, 8);
    w1:= (6 * GUI.zeroWd) + 12;

    x2:= pitchWd; GUI.GetMax(x2, spacingWd); GUI.GetMax(x2, qualityWd); GUI.GetMax(x2, formattingWd);
    INC(x2, x1 + w1 + 10);
    w2:= pitchLabelArrayWd; GUI.GetMax(w2, spacingLabelArrayWd);
    GUI.GetMax(w2, qualityLabelArrayWd); GUI.GetMax(w2, formattingLabelArrayWd);

    x3:= x2 + w2 + 10;
    w3:= lineNumbersWd; GUI.GetMax(w3, hTimeWd); GUI.GetMax(w3, hTitleWd);
    GUI.GetMax(w3, hNumbersWd); GUI.GetMax(w3, hDateWd);

    GUI.NewCol(x1, 4, 3);
    leftMarginGad:= GUI.CreateIntegerGad(leftMarginID, Str.leftMargin^, w1,
                                     leftMargin, 2, TRUE);
    rightMarginGad:= GUI.CreateIntegerGad(rightMarginID, Str.rightMargin^, w1,
                                      rightMargin, 3, TRUE);
    linesGad:= GUI.CreateIntegerGad(linesID, Str.lines^, w1, lines, 3, TRUE);
    colSpacingGad:= GUI.CreateIntegerGad(colSpacingID, Str.colSpacing^, w1, colSpacing,
                                     1, formatting # Sett.formattingOff);
    h:= GUI.layoutY;

    GUI.NewCol(x2, 4, 3);
    pitchGad:= GUI.CreateCycleGad(pitchID, Str.pitch^, w2, pitchLabelArray, pitch, TRUE);
    spacingGad:= GUI.CreateCycleGad(spacingID, Str.spacing^, w2, spacingLabelArray, spacing, TRUE);
    qualityGad:= GUI.CreateCycleGad(qualityID, Str.quality^, w2, qualityLabelArray, quality, TRUE);
    formattingGad:= GUI.CreateCycleGad(formattingID, Str.formatting^, w2, formattingLabelArray, formatting, TRUE);
    GUI.GetMax(h, GUI.layoutY);

    GUI.NewCol(x3, 4, 4);
    lineNumbersGad:= GUI.CreateCheckBoxGad(lineNumbersID, Str.lineNumbers^, lineNumbers, TRUE);
    hTitleGad:= GUI.CreateCheckBoxGad(hTitleID, Str.hTitle^, hTitle, TRUE);
    hNumbersGad:= GUI.CreateCheckBoxGad(hNumbersID, Str.hNumbers^, hNumbers, TRUE);
    hDateGad:= GUI.CreateCheckBoxGad(hDateID, Str.hDate^, hDate, TRUE);
    hTimeGad:= GUI.CreateCheckBoxGad(hTimeID, Str.hTime^, hTime, TRUE);

    GUI.GetMax(h, GUI.layoutY);

    wWidth:= x3 + w3 + 8;
    wHeight:= h + 4 + GUI.buttonHt + 4;

    RETURN CreateOkCancelGads(wWidth, wHeight);
  END CreateGadgets;

  PROCEDURE UpdateCS;

  BEGIN
    GT.SetGadgetAttrs(colSpacingGad^, win, NIL,
                      I.gaDisabled, I.BoolToLong(formattingNew = Sett.formattingOff),
                      Util.done);
  END UpdateCS;

BEGIN
  pitchNew:= pitch;
  spacingNew:= spacing;
  qualityNew:= quality;
  formattingNew:= formatting;
  lineNumbersNew:= lineNumbers;
  hTimeNew:= hTime;
  hTitleNew:= hTitle;
  hNumbersNew:= hNumbers;
  hDateNew:= hDate;
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindow(Str.printTitle^, w, ww, wh,
                        LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey} + GT.buttonIDCMP
                        + GT.integerIDCMP + GT.cycleIDCMP + GT.checkBoxIDCMP, gadList);
    IF win # NIL THEN
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
                  I.refreshWindow:
                        GT.BeginRefresh(win);
                        GT.EndRefresh(win, I.LTRUE);
                        GT.ReplyIMsg(iMsg);
        | I.changeWindow:
                        IO.Refresh;
                        GT.ReplyIMsg(iMsg);
        | I.gadgetUp:
                        g:= iMsg.iAddress;
                        code:= iMsg.code;
                        GT.ReplyIMsg(iMsg);
                        CASE g.gadgetID OF
                          pitchID:
                                pitchNew:= SHORT(code);
                        | spacingID:
                                spacingNew:= SHORT(code);
                        | qualityID:
                                qualityNew:= SHORT(code);
                        | formattingID:
                                formattingNew:= SHORT(code);
                                UpdateCS;
                        | lineNumbersID:
                                lineNumbersNew:= ~lineNumbersNew;
                        | hTimeID:
                                hTimeNew:= ~hTimeNew;
                        | hTitleID:
                                hTitleNew:= ~hTitleNew;
                        | hNumbersID:
                                hNumbersNew:= ~hNumbersNew;
                        | hDateID:
                                hDateNew:= ~hDateNew;
                        | aOkID:
                                result:= cmdUse;
                                EXIT;
                        | aCancelID:
                                result:= cmdCancel;
                                EXIT
                        ELSE
              (* ignore *)
                        END;
                | I.vanillaKey:
                        c:= Util.ToUpper(CHR(iMsg.code));
                        GT.ReplyIMsg(iMsg);
                        IF c= Str.leftMarginCh THEN
                          GUI.ActivateGad(leftMarginGad, win);
                        ELSIF c= Str.rightMarginCh THEN
                          GUI.ActivateGad(rightMarginGad, win);
                        ELSIF c= Str.linesCh THEN
                          GUI.ActivateGad(linesGad, win);
                        ELSIF c= Str.colSpacingCh THEN
                          GUI.ActivateGad(colSpacingGad, win);
                        ELSIF c= Str.pitchCh THEN
                          GUI.CycleGad(pitchGad, win, pitchNew, pitchLabelArrayLen);
                        ELSIF c= Str.spacingCh THEN
                          GUI.CycleGad(spacingGad, win, spacingNew, spacingLabelArrayLen);
                        ELSIF c= Str.qualityCh THEN
                          GUI.CycleGad(qualityGad, win, qualityNew, qualityLabelArrayLen);
                        ELSIF c= Str.formattingCh THEN
                          GUI.CycleGad(formattingGad, win, formattingNew, formattingLabelArrayLen);
                          UpdateCS;
                        ELSIF c= Str.lineNumbersCh THEN
                          GUI.ToggleGad(lineNumbersGad, win, lineNumbersNew);
                        ELSIF c= Str.hTimeCh THEN
                          GUI.ToggleGad(hTimeGad, win, hTimeNew);
                        ELSIF c= Str.hTitleCh THEN
                          GUI.ToggleGad(hTitleGad, win, hTitleNew);
                        ELSIF c= Str.hNumbersCh THEN
                          GUI.ToggleGad(hNumbersGad, win, hNumbersNew);
                        ELSIF c= Str.hDateCh THEN
                          GUI.ToggleGad(hDateGad, win, hDateNew);
                        ELSIF c= Str.aOkCh THEN
                          result:= cmdUse;
                          EXIT;
                        ELSIF c= Str.aCancelCh THEN
                          result:= cmdCancel;
                          EXIT;
                        ELSE
              GUI.Flash;
                        END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result = cmdUse THEN
        leftMargin:= SHORT(leftMarginGad.specialInfo(I.StringInfo).longInt);
        rightMargin:= SHORT(rightMarginGad.specialInfo(I.StringInfo).longInt);
        lines:= SHORT(linesGad.specialInfo(I.StringInfo).longInt);
        colSpacing:= SHORT(colSpacingGad.specialInfo(I.StringInfo).longInt);
        pitch:= pitchNew;
        spacing:= spacingNew;
        quality:= qualityNew;
        formatting:= formattingNew;
        lineNumbers:= lineNumbersNew;
        hTime:= hTimeNew;
        hTitle:= hTitleNew;
        hNumbers:= hNumbersNew;
        hDate:= hDateNew;
      END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqPrint;

PROCEDURE ReqGoto* (w: I.WindowPtr; VAR line: LONGINT): SHORTINT;

BEGIN
  RETURN ReqNumber(w, Str.gotoTitle^, Str.line^, line);
END ReqGoto;

PROCEDURE ReqReplace* (w: I.WindowPtr): SHORTINT;

VAR
  gadList, context: I.GadgetPtr;
  g: I.GadgetPtr;
  result: SHORTINT;
  iMsg: I.IntuiMessagePtr;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  c: CHAR;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    y: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    wWidth:= aYesWd + aNoWd + aAllWd + aCancelWd + 46;
    wHeight:= GUI.textHt + GUI.buttonHt + 20;
    y:= GUI.textHt + 16;

    GUI.NewCol(8, y, 0);
    IF GUI.CreateButtonGad(aYesID, Str.aYes^, aYesWd, TRUE) = NIL THEN RETURN FALSE END;
    GUI.NewCol(18 + aYesWd, y, -1);
    IF GUI.CreateButtonGad(aNoID, Str.aNo^, aNoWd, TRUE) = NIL THEN RETURN FALSE END;
    GUI.NewCol(28 + aYesWd + aNoWd, y, -1);
    IF GUI.CreateButtonGad(aAllID, Str.aAll^, aAllWd, TRUE) = NIL THEN RETURN FALSE END;
    GUI.NewCol(38 + aYesWd + aNoWd + aAllWd, y, -1);
    RETURN GUI.CreateButtonGad(aStopID, Str.aStop^, aStopWd, TRUE) # NIL;
  END CreateGadgets;

  PROCEDURE WriteText;

  VAR
    x, y: INTEGER;

  BEGIN
    GT.DrawBevelBox(win.rPort, win.borderLeft + 8, win.borderTop + 4,
                     win.gzzWidth - 16, GUI.textHt + 4, GT.bbRecessed, I.LTRUE,
                     GT.visualInfo, IO.visualInfo, Util.done);
    Gfx.Move(win.rPort, win.borderLeft + 18, win.borderTop + 9 + GUI.reqFont.baseline);
    Gfx.Text(win.rPort, Str.replaceReq^, S.Length(Str.replaceReq^));
  END WriteText;

BEGIN
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    win:= GUI.OpenReqWindowXY(Str.replaceTitle^, w, winX, winY, ww, wh,
                              LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                              + GT.buttonIDCMP, gadList);
    IF win # NIL THEN
      Gfx.SetAPen(win.rPort, IO.textPen);
      Gfx.SetFont(win.rPort, GUI.reqFont);
      WriteText;
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow: GT.BeginRefresh(win);
                           WriteText;
                           GT.EndRefresh(win, I.LTRUE);
                           GT.ReplyIMsg(iMsg);
        | I.changeWindow:  IO.Refresh;
                           GT.ReplyIMsg(iMsg);
        | I.gadgetUp:      g:= iMsg.iAddress;
                           GT.ReplyIMsg(iMsg);
                           CASE g.gadgetID OF
                             aYesID   : result:= cmdYes;
                           | aNoID    : result:= cmdNo;
                           | aAllID   : result:= cmdAll;
                           | aStopID: result:= cmdCancel;
                           END;
                           EXIT;
        | I.vanillaKey:
            c:= Util.ToUpper(CHR(iMsg.code));
            GT.ReplyIMsg(iMsg);
            IF c= Str.aStopCh THEN
              result:= cmdCancel;
              EXIT;
            ELSIF c= Str.aNoCh THEN
              result:= cmdNo;
              EXIT;
            ELSIF c= Str.aYesCh THEN
              result:= cmdYes;
              EXIT;
            ELSIF c= Str.aAllCh THEN
              result:= cmdAll;
              EXIT;
            ELSE
              GUI.Flash;
            END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      winX:= win.leftEdge; winY:= win.topEdge;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqReplace;

PROCEDURE ReqSR(w: I.WindowPtr; VAR searchStr, replaceStr: ARRAY OF CHAR;
                VAR ignoreCase, findWord, linkChgs: BOOLEAN;
                replace: BOOLEAN): SHORTINT;

VAR
  c: CHAR;
  result: SHORTINT;
  win: I.WindowPtr;
  ww, wh: INTEGER;
  iMsg: I.IntuiMessagePtr;
  code: INTEGER;
  g: I.GadgetPtr;
  searchGad, findWordGad, ignoreCaseGad, linkChgsGad, replaceGad: I.GadgetPtr;
  gadList, context: I.GadgetPtr;

  PROCEDURE OpenWindow(title: ARRAY OF CHAR): BOOLEAN;

  (* $CopyArrays- *)

  BEGIN
    win:= GUI.OpenReqWindow(title, w, ww, wh, LONGSET{I.refreshWindow, I.changeWindow, I.vanillaKey}
                        + GT.buttonIDCMP + GT.checkBoxIDCMP + GT.stringIDCMP, gadList);
    RETURN win # NIL;
  END OpenWindow;

  PROCEDURE CreateGadgets(VAR wWidth, wHeight: INTEGER): BOOLEAN;

  VAR
    y, aw, sw, ow, oh, fw, sx, ox: INTEGER;

  BEGIN
    context:= GUI.CreateContextGad(gadList);
    K.Assert(context # NIL, Err.userNoGadgets);

    ow:= ignoreCaseWd; GUI.GetMax(ow, findWordWd);
    fw:= 320 + 12;
    sx:= searchWd;
    wHeight:= GUI.stringHt + GUI.buttonHt + 16;
    IF replace THEN
      aw:= aReplaceWd + aReplaceBackWd;
      GUI.GetMax(ow, linkChgsWd);
      oh:= 3 * GUI.checkBoxHt;
      GUI.GetMax(sx, replaceWd);
      INC(wHeight, GUI.stringHt + 4);
    ELSE
      aw:= aSearchWd + aSearchBackWd;
      oh:= 2 * GUI.checkBoxHt;
    END;
    INC(aw, aCancelWd + 36);
    INC(sx, 8);
    ox:= sx + fw + 10;

    wWidth:= aw; GUI.GetMax(wWidth, sx + fw + ow + 18 + GUI.checkBoxWd);
    GUI.GetMax(wHeight, oh + GUI.buttonHt + 16);

    GUI.NewCol(ox, 4, 0);
    ignoreCaseGad:= GUI.CreateCheckBoxGad(ignoreCaseID, Str.ignoreCase^, ignoreCase, TRUE);
    findWordGad:= GUI.CreateCheckBoxGad(findWordID, Str.findWord^, findWord, TRUE);
    IF replace THEN
      linkChgsGad:= GUI.CreateCheckBoxGad(linkChgsID, Str.linkChgs^, linkChgs, TRUE);
    END;

    GUI.NewCol(sx, 4, 4);
    searchGad:= GUI.CreateStringGad(searchID, Str.search^, fw, searchStr, TRUE);
    IF replace THEN
      y:= wHeight - 4 - GUI.buttonHt;
      replaceGad:= GUI.CreateStringGad(replaceID, Str.replace^, fw, replaceStr, TRUE);

      GUI.NewCol(8, y, -1);
      IF GUI.CreateButtonGad(aNextID, Str.aReplace^, aReplaceWd, TRUE) = NIL THEN RETURN FALSE END;
      GUI.NewCol((wWidth - aReplaceBackWd) DIV 2, y, -1);
      IF GUI.CreateButtonGad(aPrevID, Str.aReplaceBack^, aReplaceBackWd, TRUE) = NIL THEN RETURN FALSE END;
    ELSE
      y:= wHeight - GUI.buttonHt - 4;

      GUI.NewCol(8, y, -1);
      IF GUI.CreateButtonGad(aNextID, Str.aSearch^, aSearchWd, TRUE) = NIL THEN RETURN FALSE END;
      GUI.NewCol((wWidth - aSearchBackWd) DIV 2, y, -1);
      IF GUI.CreateButtonGad(aPrevID, Str.aSearchBack^, aSearchBackWd, TRUE) = NIL THEN RETURN FALSE END;
    END;

    GUI.NewCol(wWidth - aCancelWd - 8, y, -1);
    RETURN GUI.CreateButtonGad(aCancelID, Str.aCancel^, aCancelWd, TRUE) # NIL;
  END CreateGadgets;

BEGIN
  result:= cmdCancel;
  gadList:= NIL;
  IF CreateGadgets(ww, wh) THEN
    IF (replace & OpenWindow(Str.replaceTitle^))
      OR OpenWindow(Str.searchTitle^) THEN
      GUI.ActivateGad(searchGad, win);
      LOOP
        iMsg:= GUI.ObtainIMsg(win);
        CASE GUI.IMsgClass(iMsg.class) OF
          I.refreshWindow: GT.BeginRefresh(win);
                           GT.EndRefresh(win, I.LTRUE);
                           GT.ReplyIMsg(iMsg);
        | I.changeWindow:  IO.Refresh;
                           GT.ReplyIMsg(iMsg);
        | I.vanillaKey:    c:= Util.ToUpper(CHR(iMsg.code));
                           GT.ReplyIMsg(iMsg);
                           IF c= Str.searchCh THEN
                             GUI.ActivateGad(searchGad, win);
                           ELSIF c= Str.replaceCh THEN
                             IF replace THEN
                               GUI.ActivateGad(replaceGad, win)
                             ELSE
                               GUI.Flash;
                             END;
                           ELSIF c= Str.ignoreCaseCh THEN
                               GUI.ToggleGad(ignoreCaseGad, win, ignoreCase);
                           ELSIF c= Str.findWordCh THEN
                               GUI.ToggleGad(findWordGad, win, findWord);
                           ELSIF c= Str.linkChgsCh THEN
                               GUI.ToggleGad(linkChgsGad, win, linkChgs);
                           ELSIF c= Str.aCancelCh THEN
                               result:= cmdCancel;
                               EXIT;
                           ELSE
                             IF replace THEN
                               IF c= Str.aReplaceCh THEN
                                 result:= cmdNext;
                                 EXIT;
                               ELSIF c= Str.aReplaceBackCh THEN
                                 result:= cmdPrev;
                                 EXIT;
                               END;
                             ELSE
                               IF c= Str.aSearchCh THEN
                                 result:= cmdNext;
                                 EXIT;
                               ELSIF c= Str.aSearchBackCh THEN
                                 result:= cmdPrev;
                                 EXIT;
                               END;
                             END;
                             GUI.Flash;
                           END;
        | I.gadgetUp:      g:= iMsg.iAddress;
                           code:= iMsg.code;
                           GT.ReplyIMsg(iMsg);
                           CASE g.gadgetID OF
                             aCancelID    : result:= cmdCancel;
                                            EXIT;
                           | aNextID      : result:= cmdNext;
                                            EXIT;
                           | aPrevID      : result:= cmdPrev;
                                            EXIT;
                           | searchID     : IF (code # GUI.escKey) & (code # GUI.tabKey) THEN
                                              IF ~replace THEN
                                                result:= cmdNext;
                                                EXIT;
                                              END;
                                            END;
                           | replaceID    : IF (code # GUI.escKey) & (code # GUI.tabKey) THEN
                                              result:= cmdNext;
                                              EXIT;
                                            END;
                           | findWordID   : findWord:= ~findWord;
                           | ignoreCaseID : ignoreCase:= ~ignoreCase;
                           | linkChgsID   : linkChgs:= ~linkChgs;
                           END;
        ELSE
          GT.ReplyIMsg(iMsg);
        END;
      END;
      IF result # cmdCancel THEN
        COPY(searchGad.specialInfo(I.StringInfo).buffer^, searchStr);
        IF replace THEN COPY(replaceGad.specialInfo(I.StringInfo).buffer^, replaceStr) END;
      END;
      I.CloseWindow(win);
    END;
    GT.FreeGadgets(gadList);
  END;
  IO.Refresh;
  RETURN result;
END ReqSR;

PROCEDURE ReqSearch* (w: I.WindowPtr; VAR searchStr: ARRAY OF CHAR;
                      VAR ignoreCase, findWord: BOOLEAN): SHORTINT;

VAR
  a: ARRAY 1 OF CHAR;
  b: BOOLEAN;

BEGIN
  RETURN ReqSR(w, searchStr, a, ignoreCase, findWord, b, FALSE);
END ReqSearch;

PROCEDURE ReqSearchRep* (w: I.WindowPtr; VAR searchStr, replaceStr: ARRAY OF CHAR;
                         VAR ignoreCase, findWord, linkChgs: BOOLEAN): SHORTINT;

BEGIN
  RETURN ReqSR(w, searchStr, replaceStr, ignoreCase, findWord, linkChgs, TRUE);
END ReqSearchRep;

PROCEDURE AllocAslReqs;

BEGIN
  fileReq:= ASL.AllocAslRequestTags(ASL.fileRequest,
                                    ASL.doPatterns, I.LTRUE,
                                    ASL.initialPattern, SYS.ADR(Sett.fileReqPattern),
                                    ASL.initialWidth, Sett.fileReqWidth,
                                    ASL.initialHeight, Sett.fileReqHeight,
                                    Util.done);
  fontReq:= ASL.AllocAslRequestTags(ASL.fontRequest,
                                    ASL.titleText, Str.selectFontTitle,
                                    ASL.fixedWidthOnly, I.LTRUE,
                                    ASL.initialName, Sett.fontSpec.name,
                                    ASL.initialSize, Sett.fontSpec.ySize,
                                    Util.done);
  screenReq:= ASL.AllocAslRequestTags(ASL.screenModeRequest,
                                    ASL.titleText, Str.selectCustomScreenTitle,
                                    ASL.doWidth, I.LTRUE,
                                    ASL.doHeight, I.LTRUE,
                                    ASL.doDepth, I.LTRUE,
                                    ASL.smMinWidth, 640,
                                    ASL.smMaxDepth, 8,
                                    Util.done);

  K.Assert((fileReq # NIL) & (fontReq # NIL), Err.userNoReqs);
END AllocAslReqs;

BEGIN
  fileReq:= NIL;
  fontReq:= NIL;
  screenReq:= NIL;
  winX:= IO.screen.width DIV 3; winY:= IO.screen.height DIV 3;

  GUI.CreateLabelArray(backupsLabelArray, backupsLabelArrayLen, backupsLabelArrayWd, Str.backupsLabels^);
  INC(backupsLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(autosaveLabelArray, autosaveLabelArrayLen, autosaveLabelArrayWd, Str.autosaveLabels^);
  INC(autosaveLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(sTypeLabelArray, sTypeLabelArrayLen, sTypeLabelArrayWd, Str.sTypeLabels^);
  INC(sTypeLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(pitchLabelArray, pitchLabelArrayLen, pitchLabelArrayWd, Str.pitchLabels^);
  INC(pitchLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(spacingLabelArray, spacingLabelArrayLen, spacingLabelArrayWd, Str.spacingLabels^);
  INC(spacingLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(qualityLabelArray, qualityLabelArrayLen, qualityLabelArrayWd, Str.qualityLabels^);
  INC(qualityLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(formattingLabelArray, formattingLabelArrayLen, formattingLabelArrayWd, Str.formattingLabels^);
  INC(formattingLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(foldHeaderLabelArray, foldHeaderLabelArrayLen, foldHeaderLabelArrayWd, Str.foldHeaderLabels^);
  INC(foldHeaderLabelArrayWd, GUI.cycleImgWd + 16);
  GUI.CreateLabelArray(scrollerSizeLabelArray, scrollerSizeLabelArrayLen, scrollerSizeLabelArrayWd, Str.scrollerSizeLabels^);
  INC(scrollerSizeLabelArrayWd, GUI.cycleImgWd + 16);

  searchWd:= GUI.TextWidth(Str.search^) + 6;
  replaceWd:= GUI.TextWidth(Str.replace^) + 6;
  ignoreCaseWd:= GUI.TextWidth(Str.ignoreCase^) + 6;
  findWordWd:= GUI.TextWidth(Str.findWord^) + 6;
  linkChgsWd:= GUI.TextWidth(Str.linkChgs^) + 6;
  aSearchWd:= GUI.TextWidth(Str.aSearch^) + 16;
  aSearchBackWd:= GUI.TextWidth(Str.aSearchBack^) + 16;
  aReplaceWd:= GUI.TextWidth(Str.aReplace^) + 16;
  aReplaceBackWd:= GUI.TextWidth(Str.aReplaceBack^) + 16;
  aCancelWd:= GUI.TextWidth(Str.aCancel^) + 16;
  aNoWd:= GUI.TextWidth(Str.aNo^) + 24;
  aYesWd:= GUI.TextWidth(Str.aYes^) + 24;
  aAllWd:= GUI.TextWidth(Str.aAll^) + 24;
  aStopWd:= GUI.TextWidth(Str.aStop^) + 24;
  aOkWd:= GUI.TextWidth(Str.aOk^) + 24;
  convTabsWd:= GUI.TextWidth(Str.convTabs^) + 6;
  closeFldsWd:= GUI.TextWidth(Str.closeFlds^) + 6;
  rmbChgsWd:= GUI.TextWidth(Str.rmbChgs^) + 6;
  maxChgsWd:= GUI.TextWidth(Str.maxChgs^) + 6;
  tabAlignWd:= GUI.TextWidth(Str.tabAlign^) + 6;
  marginWd:= GUI.TextWidth(Str.margin^) + 6;
  autosaveDelayWd:= GUI.TextWidth(Str.autosaveDelay^) + 6;
  fontNameWd:= GUI.TextWidth(Str.fontName^) + 6;
  aQueryWd:= GUI.TextWidth("?") + 16;
  autosaveWd:= GUI.TextWidth(Str.autosave^) + 6;
  backupsWd:= GUI.TextWidth(Str.backups^) + 6;
  sTypeWd:= GUI.TextWidth(Str.sType^) + 6;
  sNameWd:= GUI.TextWidth(Str.sName^) + 6;
  sModeNameWd:= GUI.TextWidth(Str.sModeName^) + 6;
  leftMarginWd:= GUI.TextWidth(Str.leftMargin^) + 6;
  rightMarginWd:= GUI.TextWidth(Str.rightMargin^) + 6;
  linesWd:= GUI.TextWidth(Str.lines^) + 6;
  colSpacingWd:= GUI.TextWidth(Str.colSpacing^) + 6;
  pitchWd:= GUI.TextWidth(Str.pitch^) + 6;
  spacingWd:= GUI.TextWidth(Str.spacing^) + 6;
  qualityWd:= GUI.TextWidth(Str.quality^) + 6;
  formattingWd:= GUI.TextWidth(Str.formatting^) + 6;
  lineNumbersWd:= GUI.TextWidth(Str.lineNumbers^) + GUI.checkBoxWd + 6;
  hTimeWd:= GUI.TextWidth(Str.hTime^) + GUI.checkBoxWd + 6;
  hTitleWd:= GUI.TextWidth(Str.hTitle^) + GUI.checkBoxWd + 6;
  hNumbersWd:= GUI.TextWidth(Str.hNumbers^) + GUI.checkBoxWd + 6;
  hDateWd:= GUI.TextWidth(Str.hDate^) + GUI.checkBoxWd + 6;
  scrollerSizeWd:= GUI.TextWidth(Str.scrollerSize^) + GUI.checkBoxWd + 6;

  AllocAslReqs;

CLOSE
  IF screenReq # NIL THEN
    ASL.FreeAslRequest(screenReq);
  END;
  IF fileReq # NIL THEN
    ASL.FreeAslRequest(fileReq);
  END;
  IF fontReq # NIL THEN
    ASL.FreeAslRequest(fontReq);
  END;
END ERequests.
