+# reset()
+#
+# Den gesicherten Stand des Template-Textes sichern
+#
+# Parameter: -nichts-
+#
+# Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
+
+sub reset
+{
+ my $self = shift;
+ $self->{'template'} = $self->{'original'};
+}
+
+# save_state()
+#
+# Aktuellen Stand des Template-Textes sichern
+# (alte Sicherung wird ueberschrieben)
+#
+# Parameter: -nichts-
+#
+# Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
+
+sub save_state
+{
+ my $self = shift;
+ $self->{'original'} = $self->{'template'};
+}
+
+# parse_loop()
+#
+# Eine Schleife parsen
+#
+# Parameter: Name der Schleife
+#
+# Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
+
+sub parse_loop($)
+{
+ my ($self,$name) = @_;
+
+ my $template = $self->get_template;
+ return if(index($template,'{LOOP '.$name.'}') == -1);
+
+ my $offset   = 0;
+ my $name_len = length($name);
+
+ while((my $begin = index($template,'{LOOP '.$name.'}',$offset)) != -1)
+ {
+  if((my $end = index($template,'{ENDLOOP}',$begin+6+$name_len)) != -1)
+  {
+   my $block   = substr($template,$begin,$end+9-$begin);
+   my $content = substr($block,$name_len+7,-9);
+
+   my $parsed_block = '';
+
+   for(my $x=0;$x<scalar @{$self->{'loop_vars'}->{$name}};$x++)
+   {
+    my $loop_data = $self->{'loop_vars'}->{$name}->[$x];
+    my @loop_vars = keys(%$loop_data);
+
+    my $ctpl = new Template;
+    $ctpl->set_template($content);
+
+    foreach my $loop_var(@loop_vars)
+    {
+     $ctpl->set_var($name.'.'.$loop_var,$loop_data->{$loop_var});
+    }
+
+    $ctpl->parse;
+    $parsed_block .= $ctpl->get_template;
+
+    undef($ctpl);
+   }
+
+   $template = str_replace($block,$parsed_block,$template);
+   $offset   = $begin+length($parsed_block);
+  }
+  else
+  {
+   last;
+  }
+ }
+
+ $self->set_template($template);
+}
+
+# get_defined_vars()
+#
+# In der Template-Datei definierte Variablen auslesen
+#
+# Parameter: -nichts-
+#
+# Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
+
+sub get_defined_vars
+{
+ my $self = shift;
+
+ my $template = $self->get_template;
+ return if(index($template,'{DEFINE ') == -1);
+
+ my $offset = 0;
+
+ while(index($template,'{DEFINE ',$offset) != -1)
+ {
+  my $begin = index($template,'{DEFINE ',$offset)+8;
+  $offset   = $begin;
+
+  my $name    = '';
+  my $content = '';
+
+  my $var_open     = 0;
+  my $name_found   = 0;
+  my $define_block = 0;
+
+  for(my $x=$begin;$x<length($template);$x++)
+  {
+   if(substr($template,$x,1) eq "\012" || substr($template,$x,1) eq "\015")
+   {
+    # Wenn in einem {DEFINE}-Block ein Zeilenumbruch gefunden wird,
+    # brechen wir mit dem Parsen des Blockes ab
+
+    last;
+   }
+
+   if($var_open == 1)
+   {
+    if(substr($template,$x,1) eq '"')
+    {
+     # Der Inhalt der Variable ist hier zu Ende
+
+     $var_open = 0;
+
+     if(substr($template,$x+1,1) eq '}')
+     {
+      # Hier ist der Block zu Ende
+
+      if(not defined $self->get_var($name))
+      {
+       # Die Variable wird nur gesetzt, wenn sie nicht bereits gesetzt ist
+
+       $self->set_var($name,$content);
+       push(@{$self->{'defined_vars'}},$name);
+      }
+
+      # {DEFINE}-Block entfernen
+
+      my $pre  = substr($template,0,$begin-8);
+      my $post = substr($template,$x+2);
+
+      $template = $pre.$post;
+
+      # Fertig!
+
+      $offset = length($pre);
+      last;
+     }
+    }
+    elsif(substr($template,$x,1) eq '\\')
+    {
+     # Ein Backslash wurde gefunden, er dient zum Escapen von Zeichen
+
+     if(substr($template,$x+1,1) eq 'n')
+     {
+      # "\n" in Zeilenumbrueche umwandeln
+
+      $content .= "\n";
+     }
+     else
+     {
+      $content .= substr($template,$x+1,1);
+     }
+
+     $x++;
+    }
+    else
+    {
+     $content .= substr($template,$x,1);
+    }
+   }
+   else
+   {
+    if($name_found == 1)
+    {
+     if($var_open == 0)
+     {
+      if(substr($template,$x,1) eq '"')
+      {
+       $var_open = 1;
+      }
+      else
+      {
+       last;
+      }
+     }
+    }
+    else
+    {
+     # Variablennamen auslesen
+
+     if(substr($template,$x,1) eq '}' && $name ne '')
+     {
+      # Wir haben einen {DEFINE}-Block
+
+      $name_found   = 1;
+      $define_block = 1;
+
+      # Alles ab hier sollte mit dem Teil verbunden werden, der das
+      # {DEFINE} in einer Zeile verarbeitet
+
+      # Der Parser fuer {DEFINE}-Bloecke ist nicht rekursiv, was auch
+      # nicht noetig sein sollte
+
+      if((my $end = index($template,'{ENDDEFINE}',$x)) != -1)
+      {
+       $x++;
+
+       $content = substr($template,$x,$end-$x);
+
+       if(not defined $self->get_var($name))
+       {
+        # Die Variable wird nur gesetzt, wenn sie nicht bereits gesetzt ist
+
+        $self->set_var($name,$content);
+        push(@{$self->{'defined_vars'}},$name);
+       }
+
+       my $pre  = substr($template,0,$begin-8);
+       my $post = substr($template,$end+11);
+
+       $template = $pre.$post;
+
+       # Fertig!
+
+       $offset = length($pre);
+       last;
+      }
+      else
+      {
+       last;
+      }
+     }
+     elsif(substr($template,$x,1) ne ' ')
+     {
+      $name .= substr($template,$x,1);
+     }
+     elsif(substr($template,$x,1) ne '')
+     {
+      $name_found = 1;
+     }
+     else
+     {
+      last;
+     }
+    }
+   }
+  }
+ }
+
+ $self->set_template($template);
+}
+