(*-- AutoRev header do NOT edit!
*
*   Program         :   GenIO.mod                                           
*   Copyright       :   © 1993                                              
*   Author          :   Thilo Stöferle                                      
*   Creation Date   :   11-Apr-93 
*   Current version :   1.2
*   Translator      :   M2Amiga V4.107d                                     
*
*   REVISION HISTORY
*
*   Date          Version         Comment
*   ---------     -------         ------------------------------------------
*   03-Aug-93     1.2             GUI support, MSG_ id beg. always lowercase 
*   28-Jun-93     1.1             Added QUIET switch                        
*   20-Jun-93     1.0             Cleaned up the code, no more known bugs   
*   11-Apr-93     0.0             Created module                            
*
*-- REV_END --*)

IMPLEMENTATION MODULE GenIO;



FROM Arts	IMPORT	wbStarted,returnVal,programName,Error,Terminate;
FROM SYSTEM	IMPORT	ADR,ADDRESS,CAST,TAG,ASSEMBLE;
IMPORT	e:ExecD,
	d:DosD,
	D:DosL,
	g:GraphicsD,
	gt:GadToolsD,
	gtx:GadToolsBoxD,
	GTX:GadToolsBoxL,
	nf:NoFragD,
	NF:NoFragL,
	w:WorkbenchD,
	C:IconL,
	u:UtilityD,
	U:UtilityL,
	S:String,
	E:ExecL,
	X:ExecSupport,
	FN:FileNames,
	R;
IMPORT	GUI:GenGuiHandler,
	Y:GenStrs;


CONST
  VersionStrPtr	= ADDRESS{ADR("$VER: "+PrgName+" "+PrgVerStr+" ("+PrgDateStr+")")};

  GUIFileWord	= "GUIFILE";
  OutputModWord	= "OUTPUTNAME";
  LocModuleWord	= "LOCMOD";
  CDFileWord	= "CDFILE";
  LocTextWord	= "LOCTEXTMSG";
  QuietWord	= "QUIET";
  GUIWord	= "GUI";
  ArgLine	= GUIFileWord	+ "," +
  		  OutputModWord	+ "," +
  		  LocModuleWord	+ "/K," +
  		  CDFileWord	+ "/K," +
  		  "MSG="+LocTextWord	+ "/S," +
  		  QuietWord	+ "/S," +
  		  GUIWord	+ "/S";


TYPE
  StringPtr	= POINTER TO ARRAY [0..255] OF CHAR;
  LongPtr	= POINTER TO LONGINT;


VAR
  TagBuffer	: ARRAY [0..11] OF LONGINT;

  DefName,ModName	: ARRAY [0..255] OF CHAR;
  DefFile,ModFile,CDFile	: d.FileHandlePtr;

  ModMark	: LONGINT;

  GuiMem	: nf.MemoryChainPtr;
  GuiValid	: gtx.VlFlagSet;

  ModCfg	: gtx.GenC; (* actually uses the C configuration (yet) ... *)
  UseMsgLoc	: BOOLEAN;


(* misc *)

PROCEDURE CopyChar(Char{R.D0}:CHAR;Buf{R.A3}:ADDRESS);
  (*$ EntryExitCode := FALSE *)
  BEGIN
    ASSEMBLE(
      MOVE.B	Char,(Buf)+
      RTS
    END);
  END CopyChar;
PROCEDURE StringFormat(VAR dest:ARRAY OF CHAR;str:ARRAY OF CHAR;fmt:ADDRESS);
  BEGIN
    E.RawDoFmt(ADR(str),fmt,ADR(CopyChar),ADR(dest));
  END StringFormat;
PROCEDURE StringFormatAdr(dest,str,fmt:ADDRESS);
  BEGIN
    E.RawDoFmt(str,fmt,ADR(CopyChar),dest);
  END StringFormatAdr;


PROCEDURE WriteConsole(str,args:ADDRESS);
  VAR
    Actual	: LONGINT;
  BEGIN
    Actual := D.VPrintf(str,args);
  END WriteConsole;

PROCEDURE WriteString(str,args:ADDRESS);
  BEGIN
    IF UseGui THEN
      GUI.WriteStatus(str,args);
    ELSE
      IF NOT(Quiet) THEN
        WriteConsole(str,args);
        WriteConsole(ADR("\n"),NIL);
      END;
    END;
  END WriteString;


PROCEDURE WriteErrString(str,args:ADDRESS);
  BEGIN
    returnVal := d.warn;
    IF UseGui THEN
      GUI.WriteStatus(str,args);
    ELSE
      WriteConsole(str,args);
      WriteConsole(ADR("\n"),NIL);
    END;
  END WriteErrString;

PROCEDURE ErrorQuit(str,args:ADDRESS;retval:LONGINT);
  VAR
    MyStr	: ARRAY [0..255] OF CHAR;
  BEGIN
    returnVal := retval;
    StringFormatAdr(ADR(MyStr),str,args);
    IF UseGui THEN
      Error(Y.GetStr(Y.errorHeader),ADR(MyStr));
    ELSE
      WriteErrString(Y.GetStr(Y.errorFmt),TAG(TagBuffer,ADR(MyStr)));
      Terminate();
    END;
  END ErrorQuit;


PROCEDURE CountArray(arr:ARRAY OF ADDRESS):LONGINT;
  VAR
    Counter	: LONGINT;
  BEGIN
    Counter := 0;
    WHILE ((arr[Counter] # NIL) AND (Counter <= HIGH(arr))) DO
      INC(Counter);
    END;
    RETURN(Counter);
  END CountArray;


(* argument parsing *)

PROCEDURE GetArgStr(StrPtr:ADDRESS;VAR s:ARRAY OF CHAR);
  BEGIN
    IF (StrPtr # NIL) THEN
      S.Copy(s,CAST(StringPtr,StrPtr)^);
    END;
  END GetArgStr;
PROCEDURE GetArgNum(NumPtr:ADDRESS;VAR n:LONGINT;Min,Max:LONGINT);
  VAR
    Err,Number	: LONGINT;
  BEGIN
    IF (NumPtr # NIL) THEN
      IF wbStarted THEN
        Err := D.StrToLong(NumPtr,Number);
      ELSE
        Number := CAST(LongPtr,NumPtr)^;
        Err := 0;
      END;
      IF ((Err # -1) AND
          ((Number >= LONGINT(Min)) AND (Number <= LONGINT(Max)))) THEN
        n := Number;
      END;
    END;
  END GetArgNum;
PROCEDURE GetArgBool(BoolPtr:ADDRESS;VAR bool:BOOLEAN);
  BEGIN
    bool := (BoolPtr # NIL);
  END GetArgBool;


PROCEDURE SetValues();
  BEGIN
    (* switch on localization if a locale module is given *)
    IF (S.Length(LocaleModule) > 0) THEN
      IF UseMsgLoc THEN
        Localization := textToID;
      ELSE
        Localization := labelToID;
      END;
    END;
    (* switch on CD file generation if a CD file is given *)
    IF (S.Length(CDName) > 0) THEN
      GenCDFile := TRUE;
    END;
  END SetValues;
PROCEDURE ParseArgs();
  BEGIN
    GetArgStr(TagBuffer[0],GuiName);
    GetArgStr(TagBuffer[1],OutputName);
    GetArgStr(TagBuffer[2],LocaleModule);
    GetArgStr(TagBuffer[3],CDName);
    GetArgBool(TagBuffer[4],UseMsgLoc);
    GetArgBool(TagBuffer[5],Quiet);
    GetArgBool(TagBuffer[6],UseGui);
    SetValues();
  END ParseArgs;

PROCEDURE GetArgs():BOOLEAN;
  VAR
    MyDiskObj	: w.DiskObjectPtr ;
    MyArgs	: d.RDArgsPtr ;
    ArgCount	: INTEGER ;
  PROCEDURE GetToolType(TTStr:StringPtr);
    BEGIN
      TagBuffer[ArgCount] := C.FindToolType(MyDiskObj^.toolTypes,TTStr);
      INC(ArgCount);
    END GetToolType;
  BEGIN
    IF wbStarted THEN
      (* Fetch Workbench ToolTypes *)
      MyDiskObj := C.GetDiskObjectNew(programName);
      IF (MyDiskObj = NIL) THEN
        RETURN(FALSE);
      END ;
      ArgCount := 0;
      GetToolType(ADR(GUIFileWord));
      GetToolType(ADR(OutputModWord));
      GetToolType(ADR(LocModuleWord));
      GetToolType(ADR(CDFileWord));
      GetToolType(ADR(LocTextWord));
      GetToolType(ADR(QuietWord));
      GetToolType(ADR(GUIWord));
      ParseArgs();
      C.FreeDiskObject (MyDiskObj);
      MyDiskObj := NIL;
    ELSE
      (* Fetch command line arguments *)
      MyArgs := D.ReadArgs(ADR(ArgLine),ADR(TagBuffer),NIL);
      IF (MyArgs = NIL) THEN
        RETURN(FALSE);
      END ;
      ParseArgs();
      D.FreeArgs(MyArgs);
      MyArgs := NIL;
    END;
    RETURN(TRUE);
  END GetArgs;


PROCEDURE InitDefaults();
  BEGIN
    GuiName := "";
    OutputName := "";
    DefName := "";
    ModName := "";
    LocaleModule := "";
    Localization := none;
    CDName := "";
    GenCDFile := FALSE;
    UseMsgLoc := FALSE;
    ModuleName := "";
    Quiet := FALSE;
    UseGui := FALSE;
  END InitDefaults;


PROCEDURE IsFileName(name:ARRAY OF CHAR):BOOLEAN;
  VAR
    Pos1,Pos2,Len	: INTEGER;
  BEGIN
    Len := S.Length(name);
    IF (Len > 0) THEN
      (* is ':' or '/' in name? -> is a file name *)
      Pos1 := S.FirstPos(name,S.first,":");
      Pos2 := S.FirstPos(name,S.first,"/");
      IF ((Pos1 = S.noOccur) AND (Pos2 = S.noOccur)) THEN
        RETURN(TRUE);
      END;
      (* is neither ':' nor '/' our last character? -> is a filename *)
      IF NOT((Pos1 = Len-1) OR (Pos2 = Len-1)) THEN
        RETURN(TRUE);
      END;
    END;
    RETURN(FALSE);
  END IsFileName;

PROCEDURE MakeFileNames();
  VAR
    Extension	: ARRAY [0..7] OF CHAR;
    MyStrPtr	: POINTER TO ARRAY [0..255] OF CHAR;
    Len	: INTEGER;
  BEGIN

    (* make gui name *)
    IF IsFileName(GuiName) THEN
      MyStrPtr := D.FilePart(ADR(GuiName));
      IF (S.Occurs(MyStrPtr^,S.first,GuiSuffix,FALSE) = S.noOccur) THEN
        S.Concat(GuiName,GuiSuffix);
      END;
    ELSE
      GuiName := "";
    END;

    (* make output names (.def, .mod) and module name *)
    IF IsFileName(OutputName) THEN
      MyStrPtr := D.FilePart(ADR(OutputName));
      IF (S.Occurs(MyStrPtr^,S.first,".",FALSE) # S.noOccur) THEN
        FN.GetExtension(OutputName,Extension,Len);
      END;
      (* make Module name *)
      S.Copy(ModuleName,MyStrPtr^);
      (* make .def name *)
      S.Copy(DefName,OutputName);
      S.Concat(DefName,DefSuffix);
      (* make .mod name *)
      S.Copy(ModName,OutputName);
      S.Concat(ModName,ModSuffix);
    ELSE
      ModuleName := "";
      DefName := "";
      ModName := "";
    END;

    (* make cd name *)
    IF GenCDFile THEN
      IF IsFileName(CDName) THEN
        MyStrPtr := D.FilePart(ADR(CDName));
        IF (S.Occurs(MyStrPtr^,S.first,CDSuffix,FALSE) = S.noOccur) THEN
          S.Concat(CDName,CDSuffix);
        END;
      ELSE
        CDName := "";
      END;
    END;

  END MakeFileNames;


(* file i/o *)

PROCEDURE OpenAllFiles():BOOLEAN;
  BEGIN
    IF (DefFile = NIL) THEN
      IF (S.Length(DefName) = 0) THEN
        WriteErrString(Y.GetStr(Y.errorOutput),NIL);
        RETURN(FALSE);
      END;
      DefFile := D.Open(ADR(DefName),d.newFile);
      IF (DefFile = NIL) THEN
        WriteErrString(Y.GetStr(Y.errorCreate),TAG(TagBuffer,ADR(DefName)));
        RETURN(FALSE);
      END;
      WriteString(Y.GetStr(Y.fileCreated),TAG(TagBuffer,ADR(DefName)));
    END;
    IF (ModFile = NIL) THEN
      IF (S.Length(ModName) = 0) THEN
        WriteErrString(Y.GetStr(Y.errorOutput),NIL);
        RETURN(FALSE);
      END;
      ModFile := D.Open(ADR(ModName),d.newFile);
      IF (ModFile = NIL) THEN
        WriteErrString(Y.GetStr(Y.errorCreate),TAG(TagBuffer,ADR(ModName)));
        RETURN(FALSE);
      END;
      WriteString(Y.GetStr(Y.fileCreated),TAG(TagBuffer,ADR(ModName)));
    END;
    IF ((Localization # none) AND GenCDFile AND (CDFile = NIL)) THEN
      IF (S.Length(CDName) = 0) THEN
        WriteErrString(Y.GetStr(Y.errorCd),NIL);
        RETURN(FALSE);
      END;
      CDFile := D.Open(ADR(CDName),d.newFile);
      IF (CDFile = NIL) THEN
        WriteErrString(Y.GetStr(Y.errorCreate),TAG(TagBuffer,ADR(CDName)));
        RETURN(FALSE);
      END;
      WriteString(Y.GetStr(Y.fileCreated),TAG(TagBuffer,ADR(CDName)));
    END;
    RETURN(TRUE);
  END OpenAllFiles;

PROCEDURE CloseAllFiles();
  BEGIN
    IF (CDFile # NIL) THEN
      D.Close(CDFile);
      CDFile := NIL;
    END;
    IF (ModFile # NIL) THEN
      D.Close(ModFile);
      ModFile := NIL;
    END;
    IF (DefFile # NIL) THEN
      D.Close(DefFile);
      DefFile := NIL;
    END;
  END CloseAllFiles;


PROCEDURE OpenGUI():BOOLEAN;
  VAR
    Err	: LONGINT;
  BEGIN
    IF (S.Length(GuiName) = 0) THEN
      WriteErrString(Y.GetStr(Y.errorGui),NIL);
      RETURN(FALSE);
    END;
    GuiMem := NF.GetMemoryChain(4096);
    IF (GuiMem = NIL) THEN
      WriteErrString(Y.GetStr(Y.errorMemory),NIL);
      RETURN(FALSE);
    END;
    Err := GTX.LoadGUIA(GuiMem,ADR(GuiName),TAG(TagBuffer,
             gtx.rgGUI,ADR(GuiData),
             gtx.rgConfig,ADR(GtxCfg),
             gtx.rgCConfig,ADR(ModCfg),
             gtx.rgWindowList,ADR(WinLst),
             gtx.rgValid,ADR(GuiValid),
             u.tagDone));
    CASE Err OF
    | 0:		WriteString(Y.GetStr(Y.fileOpened),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorNoMem:	WriteErrString(Y.GetStr(Y.errorMemory),NIL);
    | gtx.errorOpen:	WriteErrString(Y.GetStr(Y.errorOpen),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorRead:	WriteErrString(Y.GetStr(Y.errorRead),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorWrite:	WriteErrString(Y.GetStr(Y.errorWrite),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorParse:	WriteErrString(Y.GetStr(Y.errorIff),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorPacker:	WriteErrString(Y.GetStr(Y.errorPacker),TAG(TagBuffer,ADR(GuiName)));
    | gtx.errorPPLib:	WriteErrString(Y.GetStr(Y.errorPplib),NIL);
    | gtx.errorNotGUIFile:WriteErrString(Y.GetStr(Y.errorNogui),TAG(TagBuffer,ADR(GuiName)));
    ELSE                WriteErrString(Y.GetStr(Y.errorUnknown),NIL);
    END;
    IF (Err # 0) THEN
      RETURN(FALSE);
    END;
    IF NOT(gtx.vlGUI IN GuiValid) THEN
      WriteErrString(Y.GetStr(Y.errorGuidata),NIL);
      RETURN(FALSE);
    END;
    IF NOT(gtx.vlConfig IN GuiValid) THEN
      WriteErrString(Y.GetStr(Y.errorConfig),NIL);
      RETURN(FALSE);
    END;
    IF NOT(gtx.vlCConfig IN GuiValid) THEN
      WriteErrString(Y.GetStr(Y.errorGtcc),NIL);
      RETURN(FALSE);
    END;
    IF NOT(gtx.vlWindowList IN GuiValid) THEN
      WriteErrString(Y.GetStr(Y.errorWindows),NIL);
      RETURN(FALSE);
    END;
    RETURN(TRUE);
  END OpenGUI;

PROCEDURE CloseGUI();
  BEGIN
    GTX.FreeWindows(GuiMem,ADR(WinLst));
    IF (GuiMem # NIL) THEN
      NF.FreeMemoryChain(GuiMem,TRUE);
      GuiMem := NIL;
    END;
  END CloseGUI;


(*$ CopyDyn := FALSE *)
PROCEDURE WriteDef(str:ARRAY OF CHAR;args:ADDRESS);
  VAR
    Err	: BOOLEAN;
  BEGIN
    IF (args # NIL) THEN
      Err := (D.VFPrintf(DefFile,ADR(str),args) = -1);
    ELSE
      Err := D.FPuts(DefFile,ADR(str));
    END;
    IF Err THEN
      ErrorQuit(Y.GetStr(Y.errorWrite),TAG(TagBuffer,ADR(DefName)),d.error);
    END;
  END WriteDef;

(*$ CopyDyn := FALSE *)
PROCEDURE WriteMod(str:ARRAY OF CHAR;args:ADDRESS);
  VAR
    Err	: BOOLEAN;
  BEGIN
    IF (args # NIL) THEN
      Err := (D.VFPrintf(ModFile,ADR(str),args) = -1);
    ELSE
      Err := D.FPuts(ModFile,ADR(str));
    END;
    IF Err THEN
      ErrorQuit(Y.GetStr(Y.errorWrite),TAG(TagBuffer,ADR(ModName)),d.error);
    END;
  END WriteMod;

(*$ CopyDyn := FALSE *)
PROCEDURE WriteCD(str:ARRAY OF CHAR;args:ADDRESS);
  VAR
    Err	: BOOLEAN;
  BEGIN
    IF GenCDFile THEN
      IF (args # NIL) THEN
        Err := (D.VFPrintf(CDFile,ADR(str),args) = -1);
      ELSE
        Err := D.FPuts(CDFile,ADR(str));
      END;
      IF Err THEN
        ErrorQuit(Y.GetStr(Y.errorWrite),TAG(TagBuffer,ADR(CDName)),d.error);
      END;
    END;
  END WriteCD;


PROCEDURE UnWriteDef();
  VAR
    OldPos	: LONGINT;
  BEGIN
    OldPos := D.Seek(DefFile,-1,d.current);
  END UnWriteDef;

PROCEDURE UnWriteMod();
  VAR
    OldPos	: LONGINT;
  BEGIN
    OldPos := D.Seek(ModFile,-1,d.current);
  END UnWriteMod;


PROCEDURE MarkMod();
  VAR
    Count	: INTEGER;
  BEGIN
    ModMark := D.Seek(ModFile,0,d.current);
    WriteMod("00000",NIL);
  END MarkMod;

PROCEDURE UnMarkMod(number:LONGINT);
  VAR
    CurrentPos	: LONGINT;
  BEGIN
    CurrentPos := D.Seek(ModFile,ModMark,d.beginning);
    WriteMod("%5ld",TAG(TagBuffer,number));
    CurrentPos := D.Seek(ModFile,CurrentPos,d.beginning);
  END UnMarkMod;


(* localization mechanism *)

PROCEDURE GetLocaleStr(VAR dest:ARRAY OF CHAR;text:TextPtr;
                       label:ARRAY OF CHAR;labelargs:ADDRESS);
  CONST
    LocStrFmt	= "LONGINT(-ORD(L.%s)-2)";
    MsgID	= "MSG_";
    LocStr	=
      ";\n" +
      "%s (//)\n" +
      "%s\n" +
      ";\n";
  VAR
    TmpStr	: ARRAY [0..63] OF CHAR;


  PROCEDURE Msg2Id(msg:ARRAY OF CHAR;VAR id:ARRAY OF CHAR);
    VAR
      Count	: INTEGER;
    BEGIN
      (* copy msg to id string *)
      S.Copy(id,msg);
      (* delete "MSG_" *)
      S.Delete(id,S.first,SIZE(MsgID));
      (* make lower case *)
      FOR Count := 0 TO S.Length(id)-1 BY 1 DO
        id[Count] := U.ToLower(id[Count]);
      END;
      (* remove underscores and make first char upper case *)
      Count := 0;
      REPEAT
        IF (id[Count] = "_") THEN
          S.DeleteChar(id,Count);
          id[Count] := CAP(id[Count]);
        END;
        INC(Count);
      UNTIL (Count >= S.Length(id));
    END Msg2Id;

  PROCEDURE Id2Msg(id:ARRAY OF CHAR;VAR msg:ARRAY OF CHAR);
    VAR
      Count	: INTEGER;
    BEGIN
      (* begin with "MSG_" *)
      S.Copy(msg,MsgID);
      (* copy id to msg and insert underscores *)
      FOR Count := 0 TO S.Length(id)-1 BY 1 DO
        IF ((id[Count] >= "A") AND (id[Count] <= "Z")) THEN (* is upper? *)
          S.ConcatChar(msg,"_");
        END;
        S.ConcatChar(msg,id[Count]);
      END;
      (* capitalize msg *)
      S.CapString(msg);
    END Id2Msg;

  BEGIN
    IF (text # NIL) THEN
      CASE Localization OF

      | none:
        StringFormat(dest,'y.ADR("%s")',ADR(text));

      | textToID:
        IF (S.ComparePart(text^,S.first,SIZE(MsgID),MsgID,TRUE) = 0) THEN
          Msg2Id(text^,TmpStr);
          StringFormat(dest,LocStrFmt,TAG(TagBuffer,ADR(TmpStr)));
          IF GenCDFile THEN
            WriteCD(LocStr,TAG(TagBuffer,
                    text,
                    ADR("<default string>")
                              ));
          END;
        ELSE
          StringFormat(dest,'y.ADR("%s")',ADR(text));
        END;

      | labelToID:
        StringFormat(TmpStr,label,labelargs);
        TmpStr[0] := U.ToLower(TmpStr[0]); (* force first character to lower case for more consistency with textToID *)
        StringFormat(dest,LocStrFmt,TAG(TagBuffer,ADR(TmpStr)));
        IF GenCDFile THEN
          Id2Msg(TmpStr,TmpStr);
          WriteCD(LocStr,TAG(TagBuffer,
                  ADR(TmpStr),
                  text
                            ));
        END;

      END;
    ELSE
      S.Copy(dest,"NIL");
    END;
  END GetLocaleStr;


(* miscellaneous functions for GUI handling *)

PROCEDURE IsGTGadPresent(pw:gtx.ProjectWindowPtr;type:INTEGER):BOOLEAN;
  VAR
    CurrentGad	: gtx.ExtNewGadgetPtr;
  BEGIN
    IF (pw # NIL) THEN
      CurrentGad := pw^.gadgets.head;
      IF (CurrentGad # NIL) THEN (* this should ALWAYS be the case since the list at least has to be initialized!!! *)
        WHILE (CurrentGad^.succ # NIL) DO
          IF (CurrentGad^.kind = type) THEN
            RETURN(TRUE);
          END;
          CurrentGad := CurrentGad^.succ;
        END;
      END;
    END;
    RETURN(FALSE);
  END IsGTGadPresent;

PROCEDURE IsGetFilePresent(pw:gtx.ProjectWindowPtr):BOOLEAN;
  BEGIN
    RETURN(IsGTGadPresent(pw,gt.genericKind));
  END IsGetFilePresent;

PROCEDURE IsJoinedPresent(pw:gtx.ProjectWindowPtr):BOOLEAN;
  VAR
    CurrentGad	: gtx.ExtNewGadgetPtr;
  BEGIN
    IF (pw # NIL) THEN
      CurrentGad := pw^.gadgets.head;
      IF (CurrentGad # NIL) THEN (* this should ALWAYS be the case since the list at least has to be initialized!!! *)
        WHILE (CurrentGad^.succ # NIL) DO
          IF ((CurrentGad^.kind = gt.listviewKind) AND
              (gtx.needLock IN CurrentGad^.flags)) THEN
            RETURN(TRUE);
          END;
          CurrentGad := CurrentGad^.succ;
        END;
      END;
    END;
    RETURN(FALSE);
  END IsJoinedPresent;

PROCEDURE IsLVListPresent(pw:gtx.ProjectWindowPtr):BOOLEAN;
  VAR
    CurrentGad	: gtx.ExtNewGadgetPtr;
    LabelList	: e.ListPtr;
  BEGIN
    IF (pw # NIL) THEN
      CurrentGad := pw^.gadgets.head;
      IF (CurrentGad # NIL) THEN (* this should ALWAYS be the case since the list at least has to be initialized!!! *)
        WHILE (CurrentGad^.succ # NIL) DO
          IF (CurrentGad^.kind = gt.listviewKind) THEN
            LabelList := CAST(ADDRESS,U.GetTagData(LONGCARD(gt.gtlvLabels),0,CurrentGad^.tags));
            IF (LabelList # NIL) THEN
              IF NOT(X.IsListEmpty(LabelList)) THEN
                RETURN(TRUE);
              END;
            END;
          END;
          CurrentGad := CurrentGad^.succ;
        END;
      END;
    END;
    RETURN(FALSE);
  END IsLVListPresent;

PROCEDURE CheckOutAll();
  VAR
    CurrentPW	: gtx.ProjectWindowPtr;
    Pos	: INTEGER;
  BEGIN

    (* get font name: e.g. "topaz.font" -> "topaz" *)
    IF NOT(gtx.fontAdapt IN GtxCfg.configFlags0) THEN
      S.Copy(FontName,GuiData.fontName);
      Pos := S.LastPos(FontName,S.Length(FontName),".");
      IF (Pos # S.noOccur) THEN
        S.Delete(FontName,Pos,S.Length(FontName)-Pos);
      END;
    END;

    (* check for presence of a GetFile gadget *)
    UsesGetFile := FALSE;
    CurrentPW := WinLst.head;
    WHILE (CurrentPW^.succ # NIL) DO
      IF IsGetFilePresent(CurrentPW) THEN
        UsesGetFile := TRUE;
      END;
      CurrentPW := CurrentPW^.succ;
    END;

    (* evalute what font is used *)
    UsesOpenFont := (NOT(gtx.fontAdapt IN GtxCfg.configFlags0) AND
                     (gtx.cs0GenOpenFont IN ModCfg.genCFlags0) AND
                     NOT(g.romFont IN GuiData.font.flags));
    UsesSysFont := (gtx.cs0SysFont IN ModCfg.genCFlags0);

    (* check for listview lists *)
    LVListsPresent := FALSE;
    CurrentPW := WinLst.head;
    WHILE (CurrentPW^.succ # NIL) DO
      IF IsLVListPresent(CurrentPW) THEN
        LVListsPresent := TRUE;
      END;
      CurrentPW := CurrentPW^.succ;
    END;
    
  END CheckOutAll;


BEGIN

  InitDefaults();

CLOSE

  CloseAllFiles();
  CloseGUI();

END GenIO.
