! =====================================================
! German Language Definition File
! Library Routines
! (c) 1997/98/99 by Toni Arnold
! Serial Number 991117
! Added GLK/Glulx-Support
! =====================================================

System_file;

Property dekl;	
Property adj;
Property post;
Property changing_gender;

!Property adj2;
!Property adj3;
!Property adj4;
!Property adj5;
!Property adj6; ! maximum 6 adjectives
!Property post;
! Using individual properties instead of common properties
! preferred because their number is unlimited
! -> Need for a dummy-object for declaring them:
!Object dummy_dekl_adj_post,
!  with dekl 0, adj 0, adj1 0, adj2 0, adj3 0, 
!       adj4 0, adj5 0, adj6 0, post 0;

! Adjectives mechanism changed; thanks to Max Kalus
! to restore old mechanism jump to OldAdjectives and uncomment
!Property adj;	! just one property as an adj-array


Constant ta_LanguageNumberCases = 4;
Constant ta_LanguageNumberGenders = 3;
Constant ta_LanguageNumberNumbers = 2;

Constant ta_LanguageNumberGenderCases = 
   ta_languageNumberCases * ta_LanguageNumberGenders;

Constant ta_LanguageNumberBlock =          ! length of a case-gender-block
   ta_LanguageNumberCases * ta_LanguageNumberGenders 
    * ta_LanguageNumberNumbers;

Constant ta_DefArtOffset = 0;
! Beginning of indefinite Articles:
Constant ta_IndefArtOffset = 1 * ta_LanguageNumberBlock;  
Constant ta_KeinArtOffset = 2 * ta_LanguageNumberBlock;

Constant definit = -1;			! constant for force definite article


! ========== Extension to WriteListFrom with case

Constant Nom 0;      ! Constants for case of the list
Constant Akk 1;
Constant Dat 2;
Constant Gen 3;

Global WriteListCase = 1;		! holds any of above constants
! -> defaults to Accusative (in Inventory); if a verb routine changes
!    WriteListCase, it is expected to restore the default value itself

[WriteListFromCase o style depth case;
  WriteListCase = case;
  WriteListFrom(o,style,depth);		! normal WriteListFrom
  WriteListCase = Akk;
];





! --------------------------
!  printing german articles
! --------------------------

Array ta_LanguageArticles --> 

! Nom   Akk   Dat   Gen       Definite articles singular

  "der" "den" "dem" "des"    ! Mask
  "die" "die" "der" "der"    ! Fem
  "das" "das" "dem" "des"    ! Neutr

! Nom   Akk   Dat   Gen       Definite articles plural

  "die" "die" "den" "der"    ! Mask
  "die" "die" "den" "der"    ! Fem
  "die" "die" "den" "der"    ! Neutr



! Nom    Akk     Dat      Gen        Indefinite articles singular

  "ein"  "einen" "einem" "eines"    ! Mask
  "eine" "eine"  "einer" "einer"    ! Fem
  "ein"  "ein"   "einem" "eines"    ! Neutr


! Nom    Akk     Dat      Gen        Indefinite articles plural = none in
!                                      German, genitive even does not exist
  ""     ""      ""       ""        ! Mask
  ""     ""      ""       ""        ! Fem
  ""     ""      ""       ""        ! Neutr


! Nom     Akk       Dat     Gen      "kein" (= engl "no") articles singular

  "kein"  "keinen" "keinem" "keines"  ! Mask
  "keine" "keine"  "keiner" "keiner"  ! Fem
  "kein"  "kein"   "keinem" "keines"  ! Neutr

! Nom     Akk       Dat     Gen      "kein" (= engl "no") articles singular

  "keine" "keine"  "keinen" "keiner"  ! Mask
  "keine" "keine"  "keinen" "keiner"  ! Fem
  "keine" "keine"  "keinen" "keiner"  ! Neutr
;



Array ta_LanguageUpperArticles --> 

! Nom   Akk   Dat   Gen       Definite articles singular

  "Der" "Den" "Dem" "Des"    ! Mask
  "Die" "Die" "Der" "Der"    ! Fem
  "Das" "Das" "Dem" "Des"    ! Neutr

! Nom   Akk   Dat   Gen       Definite articles plural

  "Die" "Die" "Den" "Der"    ! Mask
  "Die" "Die" "Den" "Der"    ! Fem
  "Die" "Die" "Den" "Der"    ! Neutr



! Nom    Akk     Dat      Gen        Indefinite articles singular

  "Ein"  "Einen" "Einem" "Eines"    ! Mask
  "Eine" "Eine"  "Einer" "Einer"    ! Fem
  "Ein"  "Ein"   "Einem" "Eines"    ! Neutr


! Nom    Akk     Dat      Gen        Indefinite articles plural = none in 
!                                      German, genitive even does not exist
  ""     ""      ""       ""        ! Mask
  ""     ""      ""       ""        ! Fem
  ""     ""      ""       ""        ! Neutr


! Nom     Akk       Dat     Gen      "Kein" (= engl "No") articles singular

  "Kein"  "Keinen" "Keinem" "Keines"  ! Mask
  "Keine" "Keine"  "Keiner" "Keiner"  ! Fem
  "Kein"  "Kein"   "Keinem" "Keines"  ! Neutr

! Nom     Akk       Dat     Gen      "Kein" (= engl "No") articles singular

  "Keine" "Keine"  "Keinen" "Keiner"  ! Mask
  "Keine" "Keine"  "Keinen" "Keiner"  ! Fem
  "Keine" "Keine"  "Keinen" "Keiner"  ! Neutr
;



! two routines for computing offsets
! ----------------------------------

[ta_ArticlesGenderOffset obj;
  if (obj provides changing_gender) obj.changing_gender = 0;
  if (obj has male) return 0; else
  { if (obj has female) return ta_LanguageNumberCases; else
    { if (obj has neuter) 
      {return ta_LanguageNumberCases * 2; 
#ifdef DEBUG;
      } else {
        print "^# TGERMAN Warnung: ", obj, 
             " hat kein Geschlecht (has male/female/neuter)";
#endif;
      }
    }
  }
];

[ta_ArticlesChangingGenderOffset obj x;
  if (~~(obj provides changing_gender && obj.changing_gender ~= 0))
    return ta_ArticlesGenderOffset(obj);
  x = obj.changing_gender;
    
  if (x==male) x=0; else
  { if (x==female) x=ta_LanguageNumberCases; else
    { if (x==neuter) 
	{x=ta_LanguageNumberCases * 2;
     } else {
#ifdef DEBUG;
        print "^# TGERMAN Warnung: ", obj, 
             " hat kein korrektes changing_gender - Interner Fehler?^";
#endif;
     return ta_ArticlesGenderOffset(obj); !sonst default nehmen
      }
    }
  }
  return x;
];

[ta_ArticlesNumberOffset obj;
  if (obj has pluralname) return ta_LanguageNumberGenderCases;
   else return 0;
];



! --------------- printing nouns -----------------



! No Article (after prepositions)

[ta_PrintNoArt obj case; 
  ta_PrintAdjectives(obj,1,case);
];


[_er obj;
  ta_PrintNoArt(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[_en obj;
  ta_PrintNoArt(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[_em obj;
  ta_PrintNoArt(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[_es obj;
  ta_PrintNoArt(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];



! --- printing Articles lowercase ---

! Definite Article

[ta_printdefart obj case;
  if (obj hasnt proper || (ta_ProvidesAdj(obj))) {
    print  (string) (ta_LanguageArticles --> (ta_DefArtOffset + 
       ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + Case));
    print " ";
    ta_PrintAdjectives(obj,2,case);
  };
];

[der obj;
  ta_printdefart(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[den obj;
  ta_printdefart(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[dem obj;
  ta_printdefart(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[des obj;
  ta_printdefart(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];



! Indefinite Article

[ta_printIndefart obj case art a;
  if ((obj provides article) && (obj hasnt proper)) {
 					! --- indefinite article provided by object
    a = obj.article;			! a is a number is a string
    if (a == definit) {			! force definite aricle
      ta_printdefart(obj,case);
    } else {
      if (metaclass(a) == string) {	! could be a routine
        a.print_to_array(art);		! art is a word array
        if (art-->0 == 0) { 		! omit space if it is the null article
          ta_printAdjectives(obj,1,case); ! no article -> AdjDecl-Type 1
        } else {
          print (string) a;  
          print " ";
          ta_printAdjectives(obj,1,case); ! "article" sing -> AdjDecl 1
        }
      } else {				! obj.article is a routine
          a.call();			! call it
          print " ";			! assumes (like English.h) it prints something
          ta_printAdjectives(obj,3,case); ! assumes indef article sing -> AdjDecl 3
      }
    }
  } else {				! --- default indefinite article
    if (obj has proper && ta_ProvidesAdj(obj))
      ta_printdefart(obj, case);
    else {
      if ((obj has pluralname) || (obj has proper))
      { ta_printAdjectives(obj,1,case); ! no article -> AdjDecl-Type 1
      } else {
        print  (string) (ta_LanguageArticles --> (ta_InDefArtOffset + 
          ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + case));
        print " ";
        ta_printAdjectives(obj,3,case); ! indef article sing -> AdjDecl 3
      }
    }
  }
];


[ein obj;
  ta_printindefart(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[einen obj;
  ta_printindefart(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[einem obj;
  ta_printindefart(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[eines obj;
  ta_printindefart(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];



! "kein" (= engl "no") article singular

[ta_PrintKeinArt obj case;
  print  (string) (ta_LanguageArticles --> (ta_KeinArtOffset + 
    ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + case));
  print " ";    ! space between article and adj
  ta_printAdjectives(obj,3,case);        ! after "kein" AdjDecl 3
];


[kein obj;
  ta_PrintKeinArt(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[keinen obj;
  ta_PrintKeinArt(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[keinem obj;
  ta_PrintKeinArt(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[keines obj;
  ta_PrintKeinArt(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];





! --- printing Articles uppercase ---


! Definite Article

[ta_printUpperdefart obj case;
  if (obj hasnt proper || (ta_ProvidesAdj(obj))) {
    print  (string) (ta_LanguageUpperArticles --> (ta_DefArtOffset + 
      ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + case));
    print " ";
    ta_printAdjectives(obj,2,case);
  }
];

[gder obj;
  ta_printUpperdefart(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[gden obj;
  ta_printUpperdefart(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[gdem obj;
  ta_printUpperdefart(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[gdes obj;
  ta_printUpperdefart(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];



! Indefinite Article Uppercase

[ta_printUpperIndefart obj case art a;
  if ((obj provides article) && (obj hasnt proper)) {
 					! --- indefinite article provided by object
    a = obj.article;			! a is a number is a string
    if (a == definit) {			! force definite aricle
      ta_printdefart(obj,case);
    } else {
      if (metaclass(a) == string) {	! could be a routine
        a.print_to_array(art);		! art is a byte array
        if (art-->0 == 0) { 		! omit space if it is the null article
          ta_printAdjectives(obj,1,case,true); ! no article -> AdjDecl-Type 1
        } else {			! it has to be upper_cased
          art->2 = ta_zcod_upper(art->2); ! first char is at pos 2!
          ta_PrintArrayBuf(art);	! print the modified array
          print " ";
          ta_printAdjectives(obj,1,case); ! "article" sing -> AdjDecl 1
        }
      } else {				! obj.article is a routine
          a.call();			! call it
          print " ";			! assumes (like English.h) it prints something
          ta_printAdjectives(obj,3,case); ! assumes indef article sing -> AdjDecl 3
      }
    }
  } else {				! --- default indefinite article
    if (obj has proper && ta_ProvidesAdj(obj))
      ta_printUpperDefart(obj, case);
    else {
      if ((obj has pluralname) || (obj has proper))
      { ta_printAdjectives(obj,1,case,true);      ! no article -> AdjDecl-Type 1
      } else {					! 4th-arg 'true' means upper case
        print  (string) (ta_LanguageUpperArticles --> (ta_InDefArtOffset + 
          ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + case));
        print " ";
        ta_printAdjectives(obj,3,case);
      }
    }
  }
];


[gein obj;
  ta_printUpperindefart(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[geinen obj;
  ta_printUpperindefart(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[geinem obj;
  ta_printUpperindefart(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[geines obj;
  ta_printUpperindefart(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];



! "Kein" (= engl "No") article singular

[ta_PrintUpperKeinArt obj case;
  print  (string) (ta_LanguageUpperArticles --> (ta_KeinArtOffset + 
    ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) + case));
  print " ";
  ta_printAdjectives(obj,3,case);        ! after "kein" AdjDecl 3
];


[Gkein obj;
  ta_PrintUpperKeinArt(obj,0);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,0);
  ta_PrintPostNoun(obj);
];
[Gkeinen obj;
  ta_PrintUpperKeinArt(obj,1);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,1);
  ta_PrintPostNoun(obj);
];
[Gkeinem obj;
  ta_PrintUpperKeinArt(obj,2);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,2);
  ta_PrintPostNoun(obj);
];
[Gkeines obj;
  ta_PrintUpperKeinArt(obj,3);
  print (PSN__) obj;
  ta_PrintNounSuffix(obj,3);
  ta_PrintPostNoun(obj);
];

! german declination suffixes for nouns
! -------------------------------------

! type numbers taken from "DUDEN: Die Grammatik" p.220


! Some genders are excluded from some types; this is represented 
!  by empty suffixes

Array ta_LanguageNounSuffix -->

 ! Nom   Akk   Dat   Gen      declination type 1 singular
 !                                  feminine forms follow later
  ""     ""    ""    "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    "s"      ! Neutr

 ! Nom    Akk   Dat   Gen     declination type 1 plural

  "e"     "e"   "en"  "e"     ! Mask
  ""      ""    ""    ""      ! Fem
  "e"     "e"   "en"  "e"     ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 2 singular

  ""     ""    ""    "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    "s"      ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 2 plural

  ""     ""    "n"    ""      ! Mask
  ""     ""    ""     ""      ! Fem
  ""     ""    "n"    ""      ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 3 singular

  ""     ""    ""    "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    "s"      ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 3 plural

  "en"   "en"  "en"  "en"     ! Mask
  ""     ""    ""    ""       ! Fem
  "n"    "n"   "n"   "n"      ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 4 singular

  ""     ""    ""    "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    "s"      ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 4 plural

  "er"   "er"  "ern" "er"     ! Mask
  ""     ""    ""    ""       ! Fem
  "er"   "er"  "ern" "er"     ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 5 singular

  ""     ""    ""    "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    "s"      ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 5 plural

  "s"    "s"   "s"   "s"      ! Mask
  ""     ""    ""    ""       ! Fem
  "s"    "s"   "s"   "s"      ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 6 singular

  ""     "en"  "en"  "en"     ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 6 plural

  "en"   "en"  "en"  "en"     ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 7 singular
 !                                  from here to end only feminine forms
  ""     ""    ""    ""       ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 7 plural

  ""     ""    ""    ""       ! Mask
  "e"    "e"   "en"  "e"      ! Fem
  ""     ""    ""    ""       ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 8 singular

  ""     ""    ""    ""       ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 8 plural

  ""     ""    ""    ""       ! Mask
  ""     ""    "n"   ""       ! Fem
  ""     ""    ""    ""       ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 9 singular

  ""     ""    ""    ""       ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 9 plural

  ""     ""    ""    ""       ! Mask
  "en"   "en"  "en"  "en"     ! Fem
  ""     ""    ""    ""       ! Neutr


  ! Nom   Akk   Dat   Gen     declination type 10 singular

  ""     ""    ""    ""       ! Mask
  ""     ""    ""    ""       ! Fem
  ""     ""    ""    ""       ! Neutr

 ! Nom   Akk   Dat   Gen       declination type 10 plural

  ""     ""    ""    ""       ! Mask
  "s"    "s"   "s"   "s"      ! Fem
  ""     ""    ""    ""       ! Neutr
;




! german declination suffixes for adjectives
! ------------------------------------------

! type numbers taken from "DUDEN: Die Grammatik" p.278

Array ta_LanguageAdjSuffix -->

 ! Nom   Akk   Dat   Gen      declination type 1 singular
 
  "er"   "en"  "em"  "en"     ! Mask
  "e"    "e"   "er"  "er"     ! Fem
  "es"   "es"  "em"  "en"     ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 1 plural

  "e"     "e"   "en"  "er"    ! Mask
  "e"     "e"   "en"  "er"    ! Fem
  "e"     "e"   "en"  "er"    ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 2 singular

  "e"    "en"  "en"  "en"     ! Mask
  "e"    "e"   "en"  "en"     ! Fem
  "e"    "e"   "en"  "en"     ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 2 plural

  "en"   "en"  "en"  "en"     ! Mask
  "en"   "en"  "en"  "en"     ! Fem
  "en"   "en"  "en"  "en"     ! Neutr


 ! Nom   Akk   Dat   Gen      declination type 3 singular

  "er"   "en"  "en"  "en"     ! Mask
  "e"    "e"   "en"  "en"     ! Fem
  "es"   "es"  "en"  "en"      ! Neutr

 ! Nom   Akk   Dat   Gen      declination type 3 plural

  "en"   "en"  "en"  "en"     ! Mask
  "en"   "en"  "en"  "en"     ! Fem
  "en"   "en"  "en"  "en"     ! Neutr
;




! --------------- declination routines -------------------

! --- Buffer for Working with Strings ---

Constant ta_ArrayBufLen = 254; ! real length of the following
!                                word-headed string arrays:

Array ta_ArrayBufA -> 255;
Array ta_ArrayBufB -> 255;


! ---- Buffer utilities ----


! -----------------------------
! ta_shift_left(ArrayBuf,N)
! This function results in the
! elision of the first N characters in the string
! String is afterwards N chars shorter

[ta_shift_left string n i b;
  b = (string --> 0) - n + 1;   ! number of chars minus shift plus corr
  if (b >= 1)
  { for (i=2 : i <= b : i++)
      (string -> i) = (string -> (i+n));
    (string --> 0) = b - 1;     ! corr string lengtth
    rtrue;
  } else rfalse;
];


! ------------------------------
! ta_PrintArrayBuf(Array)
! prints out an array that has
! been created using print_to_array()

[ta_PrintArrayBuf a i;
  for (i=1: i <= a-->0 : i++)
   print (char) (a -> (i+1));
];



! --------------------------------
! ta_PrintSuffix(obj,suffix)
! Prints the contracted
! (or extended) form
! of a suffix after obj
! obj & suffix are given as 
! string addresses

[ta_PrintSuffix obj suffix Lemma_End eloffset;
   obj.print_to_array(ta_ArrayBufA);      ! copy strings (necessary!)
   Suffix.print_to_array(ta_ArrayBufB);
   Lemma_End = 1 + ta_ArrayBufA --> 0;

#ifdef DEBUG;
   if (Lemma_End > ta_ArrayBufLen)
     print "^# TGERMAN Fehler: short_name zu lang^";
#endif;

   if ((ta_ArrayBufB --> 0) >= 1)         ! skip zero suffix
   {eloffset = 0;                         ! reset elision offset counter

     ! check out the various possibilities of morphological stuff

     switch(ta_arrayBufA -> lemma_End)
     {
      'n': if ((ta_ArrayBufB -> 2) == 'n')       ! 'n' - elision
             eloffset=1;
      'e': if ((ta_ArrayBufB -> 2) == 'e')       ! 'e' - elision
             eloffset=1;
      'l': if ( ((ta_ArrayBufB -> 2) == 'e') && ((ta_ArrayBufB -> 3) == 'n') )
           { if ((ta_arrayBufA -> (lemma_End-1)) == 'e')  !'elen'->'eln'-elision
             eloffset=1;
           }
      's': if (ta_ArrayBufA -> (lemma_End-1) ~= 's')  !  no triple 's'
           {  if ( (ta_ArrayBufB -> 2) == 's') 
                print "se";                         ! 's' - doubling and 'e'
              else print "s";                       ! only 's' - doubling
           }
     }
   }
   ta_shift_left(ta_ArrayBufB, eloffset);       ! delete suffix beginning
   ta_PrintArrayBuf(ta_ArrayBufB);              ! print the short suffix
];  




! -------------- printing routines -----------------



! ----- prints the adjectives to a noun -----
! ----- adjusts suffixes automatically  -----

! ------- this OldAdjectives routine is old now and just provided
!                  for backward compatibility
![ta_PrintAdjectives obj typ case queue;
!  queue = false;   ! first adjective is printed without leading space
!  if (obj provides adj ) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj ,typ,case); queue = true;}
!  if (obj provides adj2) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj2,typ,case); queue = true;}
!  if (obj provides adj3) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj3,typ,case); queue = true;}
!  if (obj provides adj4) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj4,typ,case); queue = true;}
!  if (obj provides adj5) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj5,typ,case); queue = true;}
!  if (obj provides adj6) 
!    {if (queue) print " "; ta_PrintAdj(obj,obj.adj6,typ,case); queue = true;}
!  if (queue) print " ";		! last space after the adjectives
!];


! a routine to compute upper zscii-chars out of lower ones
!	needed for printing uppercased leading adjectives
#ifdef TARGET_ZCODE;
[ta_zcod_upper char x;
  if ((char >= 97) && (char <= 122)) {
    x = char - 32;			! normal ASCII-char
  } else {
    switch(char) {
      155: x = 158;
      156: x = 159;
      157: x = 160;
    }
  }
  return x;
];
#ifnot; ! TARGET_GLULX
[ta_zcod_upper char x;
  x = glk_char_to_upper(char);
  return x;
];
#endif; ! TARGET_



! -- this is the new one originally from Max Kalus 1999 --
! -- added 4th argument for upper case printing
[ta_PrintAdjectives obj typ case upper queue i;
  queue = false;   ! first adjective is printed without leading space
  if (obj provides adj)
  {
   for (i = 0: i < (obj.#adj)/WORDSIZE: i++)	! for Glk
   { if (queue) print " ";
     ta_PrintAdj(obj,obj.&adj-->i ,typ,case,i,upper);
     queue = true;
   }
  }
  if (queue) print " ";		! last space after the adjectives
];

! ProvidesAdj_Routine
[ta_ProvidesAdj obj;  ! for space printing: checks if there are any adjectives
  if (obj provides adj )
  rtrue; else rfalse;
];



[ta_PrintAdj obj adj typ case i upper n adjbuf;
 ! print obj, "*", adj, "*", case, "*", n, "*";
  n = (ta_LanguageNumberBlock * (typ-1) 
       + ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj)
       + case);
  if ((i==0) && (upper == true)) { 	! if first adj has to be upper cased
    adj.print_to_array(adjbuf);		! make string out of it
    adjbuf->2 = ta_zcod_upper(adjbuf->2);
    ta_PrintArrayBuf(adjbuf);
  } else {
    print (string) adj;
  }
  print (string) ta_LanguageAdjSuffix --> n;
];






! ----- prints the suffix of a noun -------
! takes the property-value of declination of the object as input

[ta_PrintNounSuffix obj case n d;
 if (obj provides dekl) {
   d = obj.dekl;
   if (d>0) {			! Nulldeklination
     n = ((d - 1) * ta_LanguageNumberBlock)
            + ta_ArticlesNumberOffset(obj) + ta_ArticlesGenderOffset(obj) 
            + case;
     if ((obj provides short_name) && (metaclass(obj.short_name) == string))   
         {ta_PrintSuffix(obj.short_name,ta_LanguageNounSuffix --> n);}
     else {         !^ eventually elision of double chars
         print (string) (ta_LanguageNounSuffix --> n);  ! no elision possible
     };
     rtrue;
   } else if (obj provides suffixes) {
       n = case + ta_ArticlesNumberOffset(obj);
       if (metaclass(obj.suffixes) == Routine) 
	   obj.suffixes(case);
       else
	   print (string) (obj.&suffixes-->case);
   }
	   
#ifdef DEBUG;
 } else {
   print "^# TGERMAN Warnung: ", obj, " hat keine Deklination (dekl)";
   rfalse;
#endif;
 };
];




! -- Printing unflected Post noun word groups --
!     e.g. (das Buch) "des Zauberers"

[ta_PrintPostNoun obj;
   if(obj provides post)
   {
     if(metaclass(obj.post) == string)
     {
       print " ", (string) obj.post;
     } else {
	!print " ";
     	obj.post();
     }
   }
];





! ------------------
! printing pronomina
! ------------------


! german replacements for ItorThem
! --------------------------------

Array ta_LanguageItPronouns --> 

! Nom   Akk   Dat   Gen          personal pronoun 3rd person singular

  "er"  "ihn" "ihm" "seiner"   ! Mask
  "sie" "sie" "ihr" "ihrer"    ! Fem
  "es"  "es"  "ihm" "seiner"   ! Neutr

! Nom   Akk   Dat     Gen          personal pronoun 3rd person plural

  "sie" "sie" "ihnen" "ihrer"    ! Mask
  "sie" "sie" "ihnen" "ihrer"    ! Fem
  "sie" "sie" "ihnen" "ihrer"    ! Neutr
;

[er obj; 
  print (string) ta_LanguageItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj));
];

[ihn obj;
  print (string) ta_LanguageItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 1);
];
 
[ihm obj;
  print (string) ta_LanguageItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 2);
];

[seiner obj;
  print (string) ta_LanguageItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 3);
];


Array ta_LanguageUpperItPronouns -->

! Nom   Akk   Dat   Gen          personal pronoun 3rd person singular

  "Er"  "Ihn" "Ihm" "Seiner"   ! Mask
  "Sie" "Sie" "Ihr" "Ihrer"    ! Fem
  "Es"  "Es"  "Ihm" "Seiner"   ! Neutr

! Nom   Akk   Dat     Gen          personal pronoun 3rd person plural

  "Sie" "Sie" "Ihnen" "Ihrer"    ! Mask
  "Sie" "Sie" "Ihnen" "Ihrer"    ! Fem
  "Sie" "Sie" "Ihnen" "Ihrer"    ! Neutr
;


[Ger obj; 
  print (string) ta_LanguageUpperItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj));
];

[Gihn obj;
  print (string) ta_LanguageUpperItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 1);
];
 
[Gihm obj;
  print (string) ta_LanguageUpperItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 2);
];

[Gseiner obj;
  print (string) ta_LanguageUpperItPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 3);
];





! german replacements for ThatorThose;
! ------------------------------------

Array ta_LanguageThatPronouns --> 

! Nom       Akk      Dat      Gen      demonstrative pronoun 3rd person sg

  "dieser"  "diesen" "diesem" "dieses"   ! Mask
  "diese"   "diese"  "dieser" "dieser"   ! Fem
  "dieses"  "dieses" "diesem" "dieses"   ! Neutr

! Nom     Akk     Dat      Gen         demonstative pronoun 3rd person pl

  "diese" "diese" "diesen" "dieser"    ! Mask
  "diese" "diese" "diesen" "dieser"    ! Fem
  "diese" "diese" "diesen" "dieser"    ! Neutr
;


[dieser obj; 
  print (string) ta_LanguageThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj));
];

[diesen obj;
  print (string) ta_LanguageThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 1);
];
 
[diesem obj;
  print (string) ta_LanguageThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 2);
];

[dieses obj;
  print (string) ta_LanguageThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 3);
];



Array ta_LanguageUpperThatPronouns --> 

! Nom       Akk      Dat      Gen      demonstrative pronoun 3rd person sg

  "Dieser"  "Diesen" "Diesem" "Dieses"   ! Mask
  "Diese"   "Diese"  "Dieser" "Dieser"   ! Fem
  "Dieses"  "Dieses" "Diesem" "Dieses"   ! Neutr

! Nom     Akk     Dat      Gen         demonstative pronoun 3rd person pl

  "Diese" "Diese" "Diesen" "Dieser"    ! Mask
  "Diese" "Diese" "Diesen" "Dieser"    ! Fem
  "Diese" "Diese" "Diesen" "Dieser"    ! Neutr
;


[Gdieser obj; 
  print (string) ta_LanguageUpperThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj));
];

[Gdiesen obj;
  print (string) ta_LanguageUpperThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 1);
];
 
[Gdiesem obj;
  print (string) ta_LanguageUpperThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 2);
];

[Gdieses obj;
  print (string) ta_LanguageUpperThatPronouns --> 
   (ta_ArticlesNumberOffset(obj) + ta_ArticlesChangingGenderOffset(obj) + 3);
];

! german replacements for CTheyreorThats
! --------------------------------------

[GEristSiesind obj;
  print (Ger) obj, " "; isorare(obj);
];

! Einige Funktionen, um das Leben zu vereinfachen - Dank an Martin Oehm
[ist obj;
  isorare(obj);
];

[hat obj;
  if(obj has pluralname) print "haben";
  else print "hat";
];

[wird obj;
  if(obj has pluralname) print "werden";
  else print "wird";
];

[endT obj;	!"t" oder "en" fuer Endungen schwacher Verben
  if(obj has pluralname) print "en";
  else print "t";
];

[endEt obj;	!"et" oder "en" fuer Endungen schwacher Verben
  if(obj has pluralname) print "en";
  else print "et";
];

!gibt sing oder plur fuer unregelmaessige Verben
!aus: singplur(noun, "kann", "koennen")
[singplur obj sing plur;
  if(obj has pluralname) print (string) plur;
  else print (string) sing;
];

! -------------------- Deklination Debug Verbs ----------------------

#ifdef DEBUG;
[DekliniereSub x;
  x = noun;
  print 
    "^", (der) x,"^", (den) x,"^", (dem) x,"^", (des) x,"^",
    "^", (ein) x,"^", (einen) x,"^", (einem) x,"^", (eines) x,"^";
];

[DekliniereAllSub x;  ! mainly to suppress warnings about articles not used
  x = noun;
  print
     "^", (der) x,"^", (den) x,"^", (dem) x,"^", (des) x,"^",
     "^", (ein) x,"^", (einen) x,"^", (einem) x,"^", (eines) x,"^",     
     "^", (kein) x,"^", (keinen) x,"^", (keinem) x,"^", (keines) x,"^",
     "^", (Gder) x,"^", (Gden) x,"^", (Gdem) x,"^", (Gdes) x,"^",
     "^", (Gein) x,"^", (Geinen) x,"^", (Geinem) x,"^", (Geines) x,"^",     
     "^", (Gkein) x,"^", (Gkeinen) x,"^", (Gkeinem) x,"^", (Gkeines) x,"^",
     "^", (_er) x,"^", (_en) x,"^", (_em) x,"^", (_es) x,"^",
     "^", (dieser) x,"^", (diesen) x,"^", (diesem) x,"^", (dieses) x,"^",
     "^", (Gdieser) x,"^",(Gdiesen) x,"^",(Gdiesem) x,"^",(Gdieses) x,"^",
     "^", (er) x,"^", (ihn) x,"^", (ihm) x,"^", (seiner) x,"^",
     "^", (Ger) x,"^", (Gihn) x,"^", (Gihm) x,"^", (Gseiner) x,"^";
];
#endif;







