(*------------------------------------------

  :Module.      COutput.mod
  :Author.      Albert Weinert  [awn]
  :Address.     Krähenweg 21 , 50829 Köln
  :EMail.       Usenet_> aweinert@darkness.gun.de
  :EMail.       Z-Netz_> A.WEINERT@DARKNESS.ZER
  :Phone.       0221 / 580 29 84
  :Revision.    R.4
  :Date.        03-Sep-1993
  :Copyright.   Albert Weinert
  :Language.    Oberon-2
  :Translator.  Amiga Oberon 3.00d
  :Contents.    Erstellt ein Oberon Modul zu lokaliesrung von Programmen.
  :Imports.     Cd2OberonVersion.mod, C2OData.mod, Cd2OberonLocale.mod [awn]
  :Remarks.     <Was Du willst, evtl. Usage>
  :Bugs.        <Bekannte Fehler>
  :Usage.       <Angaben zur Anwendung>
  :History.     .0     [awn] 02-Jun-1993 : Erstellt
  :History.     .1     [awn] 15-Jun-1993 : C-Quelltext von Jochen Wiedmann eingebaut
  :History.     .2     [awn] 17-Jun-1993 : Bugfixes im C-Quelltext erstellt
  :History.     .3     [awn] 06-Jul-1993 : BAsename wir genutzt.
  :History.     .4     [awn] 03-Sep-1993 : Bei CloseCatalog wird nun geprüft ob ok ist.
  :History.            und bei OpenCatalog() wird noch ein CloseCatalog() gemacht.

--------------------------------------------*)
MODULE  COutput;

IMPORT  c2ov := KitCatVersion,
        Dos,
        ms:=MoreStrings,
        str := Strings,
        SYSTEM,
        BT:=BasicTypes,
        ll := LinkedLists,
        cl:=KitCatLocale,
        sc:=StringConvert,
        pf:=Printf,
        cd:= C2OData;

VAR writeok * : BOOLEAN;
TYPE   strptr = UNTRACED POINTER TO ARRAY 128 OF CHAR;
CONST

  beginH =
           "/****************************************************************\n"
           "   This file was created automatically by `%s'\n"
           "   Do NOT edit by hand!\n"
           "****************************************************************/\n\n"
           "#ifndef %s_H\n"
           "#define %s_H\n"
           "\n"
           "\n"
           "#ifndef EXEC_TYPES_H\n"
           "#include <exec/types.h>\n"
           "#endif  /*  !EXEC_TYPES_H           */\n"
           "#ifndef LIBRARIES_LOCALE_H\n"
           "#include <libraries/locale.h>\n"
           "#endif  /*  !LIBRARIES_LOCALE_H     */\n"
           "\n"
           "\n"
           "/*  Prototypes  */\n\n";

  OpenC = "Open%sCatalog";

  CloseC= "Close%sCatalog";

  protos = "extern void %s(struct Locale *, STRPTR);\n"
           "extern void %s(void);\n"
           "extern STRPTR %s(LONG);";

  defineH = "#define %s %ld\n"
           "#define %s_STR \"%s\"\n\n";
  defineH2 = "#define %s %ld\n"
             "#define %s_STR \"\"\\\n";

  numStr   = "\n#define num%sStrings %ld\n"
             "#define min%sId %ld\n"
             "#define max%sId %ld\n\n";

  endH    = "\n#endif /*   !%s_H  */\n";


  beginC =
           "/****************************************************************\n"
           "   This file was created automatically by `%s'\n"
           "   Do NOT edit by hand!\n"
           "****************************************************************/\n\n"
           "#ifndef %s_H\n"
           "#include \"%s.h\"\n"
           "#endif  /*  !%s_H           */\n\n"

           "#ifndef CLIB_LOCALE_PROTOS_H\n"
           "#include <clib/locale_protos.h>\n"
           "#endif  /*  !CLIB_LOCALE_PROTOS_H   */\n"
           "\n"
           "#ifdef AZTEC_C\n"
           "#ifndef __PRAGMAS_LOCALE_LIB_H\n"
           "#include <pragmas/locale_lib.h>\n"
           "#endif /*   !PRAGMAS_LOCALE_LIB_H   */\n"
           "#endif /*   AZTEC_C                 */\n\n"
           "static LONG %sVersion = %ld;\n"
           "static const STRPTR %sBuiltInLanguage = (STRPTR) \"%s\";\n\n"
           "struct %sType\n"
           "{   LONG    cca_ID;\n"
           "    STRPTR  cca_Str;\n"
           "};\n\n"

           "%s struct %sType %s [] =\n"
           "{\n";
  arrayC = "    {%s, (STRPTR)%s_STR},\n";

  procC  = "};\n\n"
           "static struct Catalog *%sCatalog = NULL;\n"
           "void Open%sCatalog(struct Locale *loc, STRPTR language)\n"
           "{ LONG tag, tagarg;\n"
           "  extern struct Library *LocaleBase;\n"
           "\n"
           "  Close%sCatalog();\n"
           "  if (language == NULL)\n"
           "  { tag = TAG_IGNORE;\n"
           "  }\n"
           "  else\n"
           "  { tag = OC_Language;\n"
           "    tagarg = (LONG) language;\n"
           "  }\n"
           "  if (LocaleBase != NULL  &&  %sCatalog == NULL)\n"
           "  { %sCatalog = OpenCatalog(loc, (STRPTR) \"%s%s.catalog\",\n"
           "                             OC_BuiltInLanguage, %sBuiltInLanguage,\n"
           "                             tag, tagarg,\n"
           "                             OC_Version, %sVersion,\n"
           "                             TAG_DONE);\n"
           "  }\n"
           "}\n\n"
           "void Close%sCatalog(void)\n"
           "{ if (LocaleBase != NULL)\n"
           "    CloseCatalog(%sCatalog);\n"
           "  %sCatalog = NULL;\n"
           "}\n\n"
           "STRPTR %s(LONG strnum)\n"
           "{ STRPTR defaultstr = NULL;\n"
           "  LONG i;\n"
           "\n"
           "  for (i = 0;  i < sizeof(%s)/sizeof(struct %sType);  i++)\n"
           "    { if (%s[i].cca_ID == strnum)\n"
           "      { defaultstr = %s[i].cca_Str;\n"
           "        break;\n"
           "      }\n"
           "    }\n"
           "  if (%sCatalog == NULL)\n"
           "  { return(defaultstr);\n"
           "  }\n"
           "  return(GetCatalogStr(%sCatalog, strnum, defaultstr));\n"
           "}\n";



  PROCEDURE Create*(name,catname:ARRAY OF CHAR;short:BOOLEAN):BOOLEAN;
  (*------------------------------------------
    :Input.     name = Name des Moduls, cdname = Name des CatalogDescriptions
    :Output.    TRUE bei Erfolg;
    :Semantic.  erstellt ein Modul für die Lokalisierung eines Programms.
    :Note.
    :Update.    16-May-1993 [awn] - erstellt.
    :Update.    28-May-1993 [awn] - V39 Switch eingebaut
    :Update.    06-Jul-1993 [awn] - Basename wird jetzt beachtet und benutzt.
  --------------------------------------------*)
    VAR fh: Dos.FileHandlePtr;
        ok: BOOLEAN;
        node : ll.Node;
        rstr : BT.DynString;
        sn : ll.Node;
        name2, name3 : strptr;

        base : strptr;
        header, function, array, cdname, open, close : strptr;
        first : BOOLEAN;
        proto : POINTER TO ARRAY OF CHAR;

    BEGIN
      NEW(name2); NEW(name3);

      NEW(header); NEW(function); NEW(array); NEW(cdname);
      NEW(open); NEW(close);
      IF (name2 = NIL) OR
         (name3 = NIL) OR
         (header = NIL) OR
         (function = NIL) OR
         (cdname = NIL) OR
         (open = NIL) OR
         (close = NIL) OR
         (array = NIL)

         THEN
          cd.error:=cl.errNoMemory;
          cd.para1:=SYSTEM.ADR(name);
          RETURN FALSE
      END;
      ok:=TRUE;
      sc.CutName(catname,FALSE);
      sc.CutName(name,TRUE);
      COPY(name,name2^);
      COPY(name,name3^);
      sc.CutName(name3^,FALSE);
      IF cd.CDList.basename # "" THEN
        str.Append(cd.CDList.basename,"/");
        base:=SYSTEM.ADR(cd.CDList.basename);
      ELSE
        base:=NIL;
      END;
      str.Append(name,".h");
      str.Append(name2^,".c");
      str.Append(name3^,".h");

      fh:=Dos.Open(name,Dos.newFile);
      str.Upper(name);
      sc.CutName(name,FALSE);

      pf.SPrintf1(header^,cd.CDList.header,SYSTEM.ADR(name));
      pf.SPrintf1(cdname^,cd.CDList.cdname,SYSTEM.ADR(catname));
      pf.SPrintf1(array^,cd.CDList.array,cdname);
      pf.SPrintf1(function^,cd.CDList.function,cdname);
      pf.SPrintf1(open^,OpenC,cdname);
      pf.SPrintf1(close^,CloseC,cdname);

      cd.error:=cl.errOpenC;
      IF fh # NIL THEN
        ok:=Dos.FPrintf(fh,beginH,SYSTEM.ADR(c2ov.nameVer),
                                  header,
                                  header)#-1;

        IF ok THEN
          IF cd.CDList.prototypes.converted # NIL THEN
            NEW(proto,str.Length(cd.CDList.prototypes.converted^)+100);
            str.Delete(cd.CDList.prototypes.converted^,0,str.Length("#prototypes")+1);
          ELSE
            NEW(cd.CDList.prototypes.converted,str.Length(protos)+2);
            COPY(protos,cd.CDList.prototypes.converted^);
            NEW(proto,str.Length(protos)+100);
          END;
          IF (proto = NIL) OR (cd.CDList.prototypes.converted = NIL) THEN
            ok:=FALSE;
          ELSE
            pf.SPrintf3(proto^,cd.CDList.prototypes.converted^,
                        open,
                        close,
                        function);
            ok:=Dos.FPrintf(fh,"%s\n\n",SYSTEM.ADR(proto^))#-1;
          END;
        END;


        IF ok THEN
          node:=cd.CDList.head;
          WHILE (node # NIL) AND ok DO
            IF short THEN
              ok:=Dos.FPrintf(fh,defineH2,SYSTEM.ADR(node(cd.Node).idName^),
                                          node(cd.Node).idNumber,
                                          SYSTEM.ADR(node(cd.Node).idName^))#-1;
              IF ok THEN
                sn:=node(cd.Node).strings.head;
                first:=TRUE;
                WHILE (sn # NIL) AND ok DO
                  ok:=sc.Convert(sn(cd.SNode).string^,TRUE,TRUE,rstr);
                  IF first THEN
                    IF ok THEN
                      ok:=sc.SetLengthBytes(rstr^,node(cd.Node), node(cd.CDNode).lengthbytes,TRUE);
                    END;
                    first:=FALSE;
                  END;
                  IF ok THEN
                    ok:=Dos.FPrintf(fh,"\"%s\"",SYSTEM.ADR(rstr^))#-1;
                  END;
                  sn:=sn.next;
                  IF ok THEN
                    IF sn # NIL THEN
                      ok:=Dos.FPrintf(fh,"\\\n")#-1;
                    ELSE
                      ok:=Dos.FPrintf(fh,"\n\n")#-1;
                    END;
                  END;
                END;
              END;
            ELSE
              ok:=sc.Convert(node(cd.CDNode).fullstr^,TRUE,TRUE,rstr);
              IF ok THEN
                ok:=sc.SetLengthBytes(rstr^,node(cd.Node), node(cd.CDNode).lengthbytes,TRUE);
              END;
              IF ok THEN
                ok:=Dos.FPrintf(fh,defineH,SYSTEM.ADR(node(cd.CDNode).idName^),
                                           node(cd.Node).idNumber,
                                           SYSTEM.ADR(node(cd.CDNode).idName^),
                                           SYSTEM.ADR(rstr^))#-1;
              ELSE;
                cd.para1:=SYSTEM.ADR(node(cd.CDNode).fullstr^);
              END;
            END;
            node:=node.next;
          END;
          IF ok THEN
            ok:=Dos.FPrintf(fh,numStr,cdname, cd.CDList.nbElements(),
                                      cdname, cd.CDList.minId,
                                      cdname, cd.CDList.maxId)#-1;
          END;
        END;
        IF ok THEN
          ok:=Dos.FPrintf(fh,endH,header)#-1;
        END;
        Dos.OldClose(fh);

        fh:=Dos.Open(name2^,Dos.newFile);
        IF fh # NIL THEN
          ok:=Dos.FPrintf(fh,beginC,SYSTEM.ADR(c2ov.nameVer),
                                    header,
                                    SYSTEM.ADR(name),
                                    header,
                                    cdname,
                                    cd.CDList.version,
                                    cdname,
                                    SYSTEM.ADR(cd.CDList.language),
                                    array,
                                    SYSTEM.ADR(cd.CDList.arrayopts),
                                    array,
                                    array)#-1;

          IF ok THEN
            node:=cd.CDList.head;
            WHILE (node # NIL) AND ok DO
              ok:=Dos.FPrintf(fh,arrayC,SYSTEM.ADR(node(cd.Node).idName^),
                                        SYSTEM.ADR(node(cd.Node).idName^))#-1;
              node:=node.next;
            END;
          END;
          IF ok THEN
            ok:=Dos.FPrintf(fh,procC, cdname,
                                      cdname,
                                      cdname,
                                      cdname,
                                      cdname,
                                      base,
                                      cdname,
                                      cdname,
                                      cdname,
                                      cdname,
                                      cdname,
                                      cdname,
                                      function,
                                      array,
                                      array,
                                      array,
                                      array,
                                      cdname,
                                      cdname)#-1;
          END;
          IF ok THEN
            cd.error:=0;
          ELSE
            cd.error:=cl.errOberonOutput;
          END;
          Dos.OldClose(fh);
        END;
      END;
      RETURN ok;
    END Create;
END COutput.
