﻿#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
binmode STDOUT, ':utf8';
use integer;


# Euclid_1607.pl
#
# author: Wolfgang Schmidle
# (c) Max Planck Institute for the History of Science, Berlin, Germany
# version 1.5, 2009-04-07
#
# This script processes the raw text of Euclid (1607), i.e. it turns (a local copy of)
# http://pythia.mpiwg-berlin.mpg.de/department1/mpdl/raw-texts/WO1_Euclid_1607.txt/WO1_Euclid_1607_V1.txt
# into a valid XML file.
#
# For Euclid (1607) see also
# https://itgroup.mpiwg-berlin.mpg.de:8080/tracs/mpdl-project-content/wiki/WO1_Euclid_1607
#
# Usage:  perl Euclid_1607.txt > Euclid_1607.xml


my $rawtext = shift @ARGV;


# text-specific preparations 


# global variables

my @text;

# counters
my $line;
my $doNotCheckBeforeLine = 0;
my $pb = 0;
my $def = 0;
my $post = 0;
my $comm = 0;
my $propos = 0;

my %divTypeCount;

# booleans
my $inH = 0;
my $inP = 0;
my $inMath = 0;
my $inMg = 0;
my $italicsH = 0;
my $italicsP = 0;
my $italicsTb = 0;
my $italicsMg = 0;
my $lineStartsWithS = 0;
my $inTb = 0;
my $mgInItalics = 0;

my $inDiv3 = 0;
my $inDef = 0;
my $defOnHold = 0;
my $inPost = 0;
my $inComm = 0;
my $inPropos = 0;

my $checkForDiv4 = 0;

# pointers
my $inMgSince = 0;

# others
my $pbTag = "";
my $div4 = "";


# read in the raw text
# and immediate emendations (things that break the processing, and changes of the line structure)

$line = 0;

open (RAWTEXT, "<:utf8", $rawtext) or die "Can't open the raw text file \"$rawtext\"!\n";
while (<RAWTEXT>) {

	$line++;
	
	s!\r\n!!;  # remove Windows line ends
		
	next if $line == 73677; # the last line contains the forbidden character SUBSTITUTE (U+001A)
	
	# <pb> and <h> on separate lines (line 7, 303)
	# (note that this emendation changes the line numbering!)
	if (m!<pb><h!) {
			push @text, "<pb>";
			s!<pb>!!;
	}
	
	# resolve ten occurrences of </mg[lr]></p>
	# (this code would fail if <mgr>...</mgr><p> is in one line)
	if (m!</mg[lr]></p>!) {
		s!</p>!!;
		my $beginningOfNote = $line-2 + 2; # +2 because of lines 7 and 303, and it doesn't happen in one-line notes
		while (!($text[$beginningOfNote] =~ m!<mg[lr]!)) { $beginningOfNote--; }
		$text[$beginningOfNote-1] .= '</p>';
	}

	# remove library stamp
	if (($line >= 26) && ($line <= 31)) { $_ = ""; } 

	push @text, $_;
}
close (RAWTEXT);


# emendations of the raw text before XMLifying

$line = 0;

for (@text) {

	$line++;
	
	# $ --> ſ (long s)
	s!\$!ſ!g;
	
	# & is a reserved character in XML
	s!&!&amp;!g;
	
	# provisional treatment of a table which fills a whole page
	# The problem is that one sentence starts on p.501 and continues on p.503, and p.502 is a table with caption.
	# The first "solution" (<cap> --> <h>) was problematic because it meant that <head> could be inside <s>.
	# Now we provisionally solve the problem by inserting a period, i.e. by artificially splitting up one sentence into two.
	# An alternative would be to accept <cap> and <tb> within <s>, but there is only this single table within any <s>.
	# Another alternative would be to move the last two lines of the paragraph from p.503 to p.501 (all other tables are between two <p>).
	s!Al<007>as proportiones eiuſdem!Al<007>as proportiones eiuſdem.!; # line 23791
	s!<cap>TABVLA PYTHA GORICA.</cap>!<cap>TABVLA PYTHAGORICA.</cap>!; # line 23792: remove a space
	
	# mid dot after fractions should be normal period
	s!·!.!g;

	# centered formulas that look like tables or headings, and similar cases
	s!<tb>16. # 24. # 36. # 54. # 81.</tb>!<math><seq>16, 24, 36, 54, 81</seq></math>!; # line 25489
	s!<tb>3. # 4. # 12. # 16. # 48. # 64. # 192. # 256.</tb>!<math><seq>3, 4, 12, 16, 48, 64, 192, 256</seq></math>!; # line 25510
	if (s!<h>([\d\@{/}]+\.( [\d\@{/}]+\.)*( &amp;c\.)?)</h>!<math><seq>$1</seq></math>!) { 
		s!\.!,!g; 
		s!,</seq>!</seq>!g; 
	}
	s!<tb it>7 # R. q. 63. # 9.</tb>!<math>7 # _R. q._ 63. # 9.</math>!; # line 25749

	# typos that are a problem for the script
	s!<scG</sc>!<sc>G</sc>!; # line 57290; must be before "obviously missing spaces between words"
	s!R Q\. Q T,!R Q, Q T,!; # line 61676: would produce an artifact sentence 
	
	# old-style numerals typed as letters
	# (must be before "obviously missing spaces between words")
	s!PROPOS !PROPOS. !; # normalize the period
	s!PROPOS\. I!PROPOS. 1!;
	s!PROPOS\. II!PROPOS. 11!;
	s!<mgl aI>5\.!<mgl a>15.!; # line 38201
	s!<mgl bI>I\.!<mgl b>11.!; # line 38206
	s!<mgl dI>5\.!<mgl d>15.!; # line 38226
	# s!(<mg[lr].*?)>II\.!$1>11.!; # this may be wrong!

	# obviously missing spaces between words
	# (part 1: remove the exceptions)
	s!peZ!pez!g;  # z in italics has often been typed as capital Z (trapeZ...)
	s!pe Z!pez!;  # (by the way: remove some superfluous spaces)
	s!ClaZomenius!Clazomenius!; # line 4741
	s!θaμaIoIIoιηπnὴ!θαυματοποιητικὴ!; # line 4673: a single Greek word going very wrong (corrected version without ligature braces)
	s!oſtend<007>mW!oſtendimus!; # line 20009: badly printed
	s!lxIx!lxix!; # line 54383: dotless i typed as capital I in roman number
	s!lxIv!lxiv!; # line 54416: dotless i typed as capital I in roman number
	s!X CIV!xciv!; # (line 55865: superfluous space in roman number)
	s!lXXXIX!lxxxix!; # line 55866: small and capital letters in roman number
	s!paraHelæ!parallelæ!; # line 61171: ll --> H
	s!kL M!K L M!; # line 63775: typesetter's fault
	s!eCùm!<n e> Cùm!; # line 64564: the anchor is difficult to identify
	s!AbCD!ABCD!; # line 68929: typesetter's fault
	s!CBkHAE!CBKHAE!; # line 71905: typesetter's fault
	# (part 2: apply the rule)
	s!([a-zæ])([A-Z])!$1 $2!; # insert space between small letter and capital letter
	
	s! exdefin\.! ex defin.!g;
	
	# long s --> f
	s!  deſin\.!  defin.!g;
	s! fint! ſint!g;  # I didn't check whether the typesetter or the typists got it wrong; likely the latter
	
	# running heads
	# (all 1451 running heads have the form <rh>[A-Z. Æ´:_]+</rh>)
	s!LIBER I\.´!LIBER I.!;
	s!LIBER Y!LIBER I!;
	s!LIBER XII:!LIBER XII.!;
	s!<rh>_(.+?)_(\.?</rh>)!<rh>$1$2!; # remove italics in the running head (rather pointless information in the running head)
	
	# italics
	s!<h>_(.+?)_</h>!<h it>$1</h>!; # replace _ _ by it in one-line headings
	s!_K_!K!g; # 264 occurrences of K in italics: typesetter's fault
	
	# notes in italics: _ _ --> it (problem of the Specs 1.1.2)
	if (m!<mg[lr]!) { 
		$inMgSince = $line; 
		$mgInItalics = 1; 
	}
	if ($inMgSince) {
		# examples of lines that count as italics: <mgl>_text_<mgl>;   <mgl>_text_.<mgl>;   <mgl>12.;   <mgl>12. _pri_.</mgl>
		# does not catch:  2 2.  and a few other cases
		unless (m!(<mg[lr].*?>)?(\d+\. )?_.+?_[.-]?(</mg[lr])?! || m!<mg[lr].*?>[\d\@]+\.?!) { $mgInItalics = 0; }
		if (m!</mg[lr]>!) { 
			if ($mgInItalics) {
				$text[$inMgSince-1] =~ s!<(mg[lr])(.*?)>!<$1 it$2>!;
				for my $i ($inMgSince-1 .. $line-1) { $text[$i] =~ s!_!!g; } # remove ALL italics markers in these notes
			}
			$inMgSince = 0; 
		}
	}
	
	# incorrect periods, which would produce artifact sentence tags
	# (a regex such as "\. [a-z]" would not work well)
	# line ends
	s!3 DVABVS datis rectis lineis inæqualibus\.!3 DVABVS datis rectis lineis inæqualibus,!; # badly printed comma
	s!reliquis trianguli lateribus deſcribuntur\.!reliquis trianguli lateribus deſcribuntur,!; # line 516: badly printed comma
	s!ex denominatori\.!ex denominatori-!; # line 24587
	s! Et\.! Et!; # line 2179
	s! Non\.! Non!; # line 3671
	s!pun\.!pun-!; # line 16033
	# others
	s!4c\.!40.!; # line 33222
	s!duo\. us!duobus!; # line 33949
	s!commenſura\.!commenſura-!; # line 54153
	
	# resolve punctuation clusters (which would cause artifact sentences)
	# (be careful with &amp; !)
	s!\.\.!.!;
		
	# emendations of headings
	s!<h>SCHOL!<h it>SCHOL!; # lines 6820, 12246, 59058, 66953: I haven't checked the originals; call it normalization
	s!<h>_SCHOLIVM_!<h it>SCHOLIVM!; # 5 times; not checked
	s!EXCAMPANO!EX CAMPANO!;
	s!<h>EX CAMPANO!<h it>EX CAMPANO!; # not checked
	s!EXPROCLO!EX PROCLO!;
	s!<h>EX PROCLO!<h it>EX PROCLO!; # not checked
	s!EXORONTIO!EX ORONTIO.!;
	s!<h>EX CARDANO!<h it>EX CARDANO!; # not checked
	s!EX PELET ARIO!EX PELETARIO!;
	s!<h>EX PELETARIO!<h it>EX PELETARIO!; # not checked
	s!<h>PRAXIS!<h it>PRAXIS!; # not checked
	s!<h>EX FEDERICO COMMANDINO!<h it>EX FEDERICO COMMANDINO!; # not checked
	
	s!PROBLEMA I\.!PROBLEMA 1.!;
	s!PROPOSITIO I\.!PROPOSITIO 1.!;
	s!PROPOS\. 1I\.!PROPOS. 11.!;
	s!PROPOS\. I\.!PROPOS. 1.!;

	s!CONVERSV M!CONVERSVM!;
	s!COROLLARIVMI!COROLLARIVM I!;
	
	s!<h>THEOR\. 13\. PROPOS\. 19</h>!<h>THEOR. 13. PROPOS. 19.</h>!; # line 34061
	
	if ($line == 13631 + 2) { s!SECVNDVM\.!SECVNDVM.</h>!; }
	if ($line == 13632 + 2) { s!_DEFINITIONES_\.!<h it>DEFINITIONES.</h>!; }
	if ($line == 13633 + 2) { s!I\.</h>!<h>I.</h>!; }

	if ($line == 16232 + 2) { s!TERTIVM\.!TERTIVM.</h>!; }
	if ($line == 16233 + 2) { s!_DEFINITIONES\._</h>!<h it>DEFINITIONES.</h>!; }

	if ($line == 21217 + 2) { s!QVARTVM\.!QVARTVM.</h>!; }
	if ($line == 21218 + 2) { s!_DEFINITIONES_\.!<h it>DEFINITIONES.</h>!; }
	if ($line == 21219 + 2) { s!I\.</h>!<h>I.</h>!; }

	if ($line == 38501 + 2) { s!SEPTIMVM\.!SEPTIMVM.</h>!; }
	if ($line == 38502 + 2) { s!_DEFINITIONES\._</h>!<h it>DEFINITIONES.</h>!; }
	# these changes are tedious in a script; better emend it directly in the txt file!

	s!<h it>_DEFINITIONES_\.</h>!<h it>DEFINITIONES.</h>!;
	s!<h it>_DEFINITIONES\._</h>!<h it>DEFINITIONES.</h>!;
	
	if ($line == 63713) { s!<h>THEOR. 16. PROPOS. 16.</h>!<h>THEOR. 16. PROPOS. 18.</h>!; }  # silent correction of obvious typo!
	if ($line == 66659) { s!PROOPS!PROPOS!; }  # silent correction of obvious typo in the book
	
	s!<h>INVENIRE quintam Apotomen\.</h>!<p>INVENIRE quintam Apotomen.</p>!; # line 55545: would create artifact div4
	
	# superscript marked as subscript (there is no <^> in Clavius)
	s!<_>e</_>x E\.!ex E!; # line 11142 (p.0250): typesetter's mistake: remove superscript and dot
	s!2<_>a</_>!<reg orig="2a" type="abbrev">secunda</reg>!; # line 20594 (p.0435)

	# misc. typos I stumbled upon 
	s!I hilo!Philo!; # badly printed P
	s!Mænum!Mœnum!; # æ --> œ
	s!mθnſtratione!monſtratione!;  # θ --> o
	s!IV M!IVM!; # superfluous space as in SCHOLIV M, COROLLARIV M
	s!SCHOLI M!SCHOLIVM!; # missing V
	s!ZVART!QVART!; # ZV --> QV
	s!7. quind. Septima libri quindecimi.!7. quind. # Septima libri quindecimi.!; # line 6769: missing # in table

}

# raw text --> XML

	# metadata: 30 additional lines
    print <<'METADATA';
<?xml version="1.0" encoding="UTF-8"?>
<echo xmlns="http://www.mpiwg-berlin.mpg.de/ns/echo/1.0/"
      xmlns:dc="http://purl.org/dc/elements/1.1/"
      xmlns:dcq="http://purl.org/dc/qualifiers/1.0/"
      xmlns:dct="http://purl.org/dc/terms/1.0/"
      xmlns:echo="http://www.mpiwg-berlin.mpg.de/ns/echo/1.0/"
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:xhtml="http://www.w3.org/1999/xhtml"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      xmlns:xml="http://www.w3.org/XML/1998/namespace">
  <metadata>
    <dc:creator>Clavius</dc:creator>
    <dc:title xml:lang="la">Elementorum Libri XV</dc:title>
    <dc:date>
      <rdf:Description>
        <dcq:dateScheme>ISO 8601</dcq:dateScheme>
        <rdf:value>1607</rdf:value>
      </rdf:Description>
    </dc:date>
    <dc:language>
      <rdf:Description>
        <dcq:languageScheme>ISO 639-2</dcq:languageScheme>
        <rdf:value>lat</rdf:value>
      </rdf:Description>
    </dc:language>
    <dc:identifier>test.xml</dc:identifier>
    <dc:rights>open access</dc:rights>
    <dct:license>http://echo.mpiwg-berlin.mpg.de/policy/oa_basics/declaration</dct:license>
  </metadata>
    <text xml:lang="la">
METADATA

$line = 0;

for (@text) {

	$line++;
	
	
	# ad hoc tagging of the higher-level div structure
	# including some additional lowest-level closing div's
	# note that single lines have been inserted before lines 7 and 303 !

	# frontmatter
	if ($line == 1) { print '<front><div level="1" type="title" n="1">'; }  
	if ($line == 33) { print '</div><div level="1" type="dedication" n="1">'; } # from here on: offset 1
	if ($line == 223) { print '</div><div level="1" type="preface" n="1">'; }
	if ($line == 304) { print '</div><div level="1" type="index" n="1">'; }
	if ($line == 386) { print '</div><div level="1" type="index" n="2">'; }  # from here on: offset 2
	if ($line == 2087) { print '</div><div level="1" type="index" n="3">'; }
	if ($line == 4377) { print '</div><div level="1" type="preface" n="2">'; }
	if ($line == 4505) { print '</div><div level="1" type="dedication" n="2">'; }
	if ($line == 4563) { print '</div><div level="1" type="introduction" n="1">'; }

	# book 1
	if ($line == 5225) { print '</div></front><body><div level="1" type="book" n="1"><div level="2" type="booktitle" n="1">';  } 
	if ($line == 5230) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 6226) { print '</div></div>'; $inDiv3 = 0; $inDef = 0; $inPost = 1; $post = 0; }
	if ($line == 6283) { print '</div></div>'; $inDiv3 = 0; $inPost = 0; $inComm = 1; $comm = 0; }
	if ($line == 6777) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inComm = 0; $inPropos = 1; $propos = 0; } 

	# book 2
	if ($line == 13629) { print '</div></div></div></div><div level="1" type="book" n="2"><div level="2" type="booktitle" n="1">'; }
	if ($line == 13634) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 13806) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 3
	if ($line == 16230) { print '</div></div></div></div><div level="1" type="book" n="3"><div level="2" type="booktitle" n="1">'; }
	if ($line == 16235) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 16481) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 4
	if ($line == 21215) { print '</div></div></div></div><div level="1" type="book" n="4"><div level="2" type="booktitle" n="1">'; }
	if ($line == 21220) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 21301) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 5
	if ($line == 23058) { print '</div></div></div></div><div level="1" type="book" n="5"><div level="2" type="booktitle" n="1">'; }
	if ($line == 23063) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 23194) { print '</div><div level="3" type="addendum" n="1">'; $defOnHold = 1; }
	if ($line == 27240) { $defOnHold = 0; }
	if ($line == 27611) { print '</div><div level="3" type="addendum" n="2">'; $defOnHold = 1; }
	if ($line == 28186) { $defOnHold = 0; }
	if ($line == 28707) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 6
	if ($line == 31048) { print '</div></div></div></div><div level="1" type="book" n="6"><div level="2" type="booktitle" n="1">'; }
	if ($line == 31053) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 31640) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# second book title
	if ($line == 38391) { print '</div></div></div></div><div level="1" type="index" n="1">'; $inPropos = 0; $inDiv3 = 0; } # quick'n'dirty !!!
	if ($line == 38480) { print '</div><div level="1" type="title" n="1">'; }  

	# book 7
	if ($line == 38499) { print '</div><div level="1" type="book" n="7"><div level="2" type="booktitle" n="1">'; }
	if ($line == 38504) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 39239) { print '</div></div>'; $inDiv3 = 0; $inDef = 0; $inPost = 1; $post = 0; }
	if ($line == 39250) { print '</div></div>'; $inDiv3 = 0; $inPost = 0; $inComm = 1; $comm = 0; }
	if ($line == 39355) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inComm = 0; $inPropos = 1; $propos = 0; }

	# book 8
	if ($line == 42003) { print '</div></div></div></div><div level="1" type="book" n="8"><div level="2" type="booktitle" n="1">'; }
	if ($line == 42008) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	# book 9
	if ($line == 44322) { print '</div></div></div></div><div level="1" type="book" n="9"><div level="2" type="booktitle" n="1">'; }
	if ($line == 44327) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	# book 10
	if ($line == 48379) { print '</div></div></div></div><div level="1" type="book" n="10"><div level="2" type="booktitle" n="1">'; }
	if ($line == 48384) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 48638) { print '</div>'; $inDef = 0; }
	if ($line == 48639) { print '<div type="postulatum" level="3" n="1">'; }  # a single postulate, without number "I."
	if ($line == 48650) { print '</div></div>'; $inDiv3 = 0; $inComm = 1; $comm = 0; }
	if ($line == 48677) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inComm = 0; $inPropos = 1; $propos = 0; }

	if ($line == 52978) { print '</div></div></div><div level="2" type="bookhead" n="2">'; $inDiv3 = 0; $inPropos = 0; $inDef = 1; $def = 0; } 
	if ($line == 53045) { print '</div></div></div><div level="2" type="bookmain" n="2">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; } 
	if ($line == 55353) { print '</div></div></div><div level="2" type="bookhead" n="3">'; $inDiv3 = 0; $inPropos = 0; $inDef = 1; $def = 0; } 
	if ($line == 55386) { print '</div></div></div><div level="2" type="bookmain" n="3">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; } 

	# book 11
	if ($line == 57419) { print '</div></div></div></div><div level="1" type="book" n="11"><div level="2" type="booktitle" n="1">'; }
	if ($line == 57425) { print '</div><div level="2" type="bookhead" n="1">'; $inDiv3 = 0; $inDef = 1; $def = 0; } 
	if ($line == 58209) { print '</div></div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 12
	if ($line == 61352) { print '</div></div></div></div><div level="1" type="book" n="12"><div level="2" type="booktitle" n="1">'; }
	if ($line == 61358) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	# book 13
	if ($line == 63790) { print '</div></div></div></div><div level="1" type="book" n="13"><div level="2" type="booktitle" n="1">'; }
	if ($line == 63796) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	# book 14
	if ($line == 66389) { print '</div></div></div></div><div level="1" type="book" n="14"><div level="2" type="booktitle" n="1">'; }
	if ($line == 66398) { print '<div level="2" type="prooemium" n="1">'; } 
	if ($line == 66461) { print '</div></div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inDef = 0; $inPropos = 1; $propos = 0; }

	# book 15
	if ($line == 68896) { print '</div></div></div></div><div level="1" type="book" n="15"><div level="2" type="booktitle" n="1">'; $inDiv3 = 0; } # $inDiv3 = 0: quick'n'dirty solution !!!
	if ($line == 68905) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	# book 16
	if ($line == 70684) { print '</div></div></div></div><div level="1" type="book" n="16"><div level="2" type="booktitle" n="1">'; } 
	if ($line == 70705) { print '</div><div level="2" type="bookmain" n="1">'; $inDiv3 = 0; $inPropos = 1; $propos = 0; }

	if ($line == 72170) { print '</div></div></div><div level="2" type="addendum" n="1">'; $inPropos = 0; $inDiv3 = 0; } # $inDiv3 = 0: ignore the three addenda
	if ($line == 73209) { print '</div><div level="2" type="addendum" n="2">'; }
	if ($line == 73378) { print '</div><div level="2" type="addendum" n="3">'; }

	
	# resolve common abbreviations
	# (problem of &c.: The period may or may not mark the end of a sentence. Heuristics will be: etc. plus capital letter --> <s>)
	
	s!([a-z])propoſ\.!$1 propoſ.!g; # 24 occurrences of propo$. without preceding space, all checked (all other: space, _, beginning of line)
	s!([Aa]d) (propoſ)\.!$1 <reg orig="MURP" type="abbrev">$2itionem</reg>!g; # ad propo$itionem
	s!([Pp]ropoſ)\.!<reg orig="$1." type="abbrev">$1itio</reg>!g; # propo$itio (may be the wrong casus in some cases, e.g. ex propo$.)
	s!MURP!propoſ.!g;
	# does not catch e.g. pro-_ // poſ.

	s!([a-z])coroll\.!$1 coroll.!g; # 15 occurrences of coroll. without preceding space, all checked
	s!([Cc]oroll)\.!<reg orig="$1." type="abbrev">$1arium</reg>!g; # (may sometimes be the wrong casus, e.g. ex coroll.)

	s!lib\.!<reg orig="lib." type="abbrev">liber</reg>!g; # liber (does that make sense? It may be e.g. "libro".)
	# missing: defin. def. cap. and others (see below)

	# resolve ligatures
	s!\\’q;!{que}!g;  # -que ligature with preceding \’
	s!q;!{que}!g;  # -que ligature without preceding \’
	s!{(.+?)}!$1<\!-- {$1} -->!g;
		
	# unknown characters	
	s!<007>!i<\!-- 007 -->!g;  # <007> (dotless i) is resolved as i<!-- 007 -->
	s!<(\d\d\d)>!<unknown code=\"$1\"/>!g;
	s!<\?>!<unsure/>!g;
	s!<gap>!<gap/>!g;
	
	# figures
	# (must be before the tagging of div's to avoid </div></fig>)
	# (the internal ordering is important for successive figures)
	s!<fig>!<figure/>!g;

#	# more elaborate version for texts which have been sent with DESpecs 2 or higher	
# 	if ($inFig) {
# 		if (m!<cap>! || m!<desc>! || m!<var>!) { 
# 			print "$_\n";
# 			next;
# 		}
# 		print "</figure>";
# 		$inFig = 0;
# 	}
# 	if (s!<fig>!<figure>!) { 
# 		$inFig = 1; 
# 		print "$_\n";
# 		next;
# 	}

	
	# handwritten material
	s!<hd>!<hd/>!;


	# tables
	# (must be before paragraphs)
	# many tables are preceded by <cap> </cap>, which can be one or two lines long; we ignore <cap> for the moment
	
	if (m!</?cap>!) { # all captions are one or two lines long; this code would break with a longer caption!
		print "$_\n";
		next;
	}
	
	if (s!<tb it>!<tb>!) { $italicsTb = 1; }
	if (m!<tb>!) { $inTb = 1; }

	if ($inTb) {
		unless (s!<(/?)tb>!<$1xhtml:table>!) {
			$_ = "<xhtml:tr><xhtml:td>$_</xhtml:td></xhtml:tr>";  # this breaks if the table consists of only one line!
			s!#!</xhtml:td><xhtml:td>!g;
		}
		if ($italicsTb) { s!<xhtml:table>!<xhtml:table style="italics">!; }
		print "$_\n";
		if (m!</xhtml:table>!) { $inTb = 0; $italicsTb = 0; }
		next;
	}
	
	
	# mathematical formulas

	if (m!<math>!) { $inMath = 1; }
	
	if ($inMath) {
		print "$_\n";
		if (m!</math>!) { $inMath = 0; }
		next;
	}


	# page breaks

	if (m!<pb!) {
		$pb++;
		
		my $pagenumber = (m!<pb (.+?)>! ? " o=\"$1\"" : "" );
		my $rhead = (m!<rh>(.+?)</rh>! ? " rhead=\"$1\"" : "" );
		my $link = 'http://echo.mpiwg-berlin.mpg.de/ECHOdocuView/ECHOzogiLib?'.
			'url=/mpiwg/online/permanent/library/2QTVUHDT/pageimg&amp;mode=imagepath&amp;pn='.$pb;

		$_ = "<pb$pagenumber$rhead n=\"$pb\" xlink:href='$link'/>";
		
		$pbTag = "";
		if (($inDef) && (!$defOnHold)) { if ( $text[$line] =~ m!<h>[XVI]+\.</h>!) { $pbTag = $_; }}
		if ($inPost) { if ( $text[$line] =~ m!<h>[XVI]+\.</h>!) { $pbTag = $_; }}
		if ($inComm) { if ( $text[$line] =~ m!<h>[XVI]+\.</h>!) { $pbTag = $_; }}
		if ($inPropos) { if ( $text[$line] =~ m!<h>.+? PROPOS\. \d+\.</h>!) { $pbTag = $_; }}

		print "$_" unless $pbTag ne "";
		print "\n";
		next;
	}


	# anchors
	s!<n (.+?)>!<anchor symbol="$1" anchorLocation="given"/>!g;  # <n> never occours without anchor


	# marginal notes
	# (must be before paragraphs)
	if (s!(<mg[lr]) it!$1!) { $italicsMg = 1; }
	if (s!<mgl>!<note place="left">!) { $inMg = 1; }
	if (s!<mgr>!<note place="right">!) { $inMg = 1; }
	if (s!<mgl (.+?)>!<note place="left" anchor="$1">!) { $inMg = 1; }
	if (s!<mgr (.+?)>!<note place="right" anchor="$1">!) { $inMg = 1; }
	if ($italicsMg) { 
		s!(<note.*?)>!$1 style="italics">!;
		$italicsMg = 0;
	}
	if ($inMg) {
		if (s!</mg[lr]>!</note>!) { $inMg = 0; } else { $_ .= "<lb/>"; }
		print "$_\n";
		next;
	}


	sub resetDiv4 {
		$div4 = "";
		$divTypeCount{"comment"} = 0;
		$divTypeCount{"euclid"} = 0;
		$divTypeCount{"euclidComment"} = 0;
		$divTypeCount{"pseudoEuclid"} = 0;
		$divTypeCount{"pseudoEuclidComment"} = 0;
		$divTypeCount{"corollarium"} = 0;
		$divTypeCount{"corollariumComment"} = 0;
	}
	
	sub addDiv4 {
		if ($div4) { print '</div>'; }
		$div4 = shift;
		$divTypeCount{$div4}++;
		print '<div type="'.$div4.'" level="4" n="'.$divTypeCount{$div4}.'">'; 		
	}	
	
	sub checkForNewDiv4 {

		return unless $inDiv3;
		return unless $line >= $doNotCheckBeforeLine;
		return unless (m!<head>! || m!<p>!);
				
		# corollarium
		if (m!<head>COR!) { # <head>COR always triggers a new div4 
			addDiv4("corollarium");
			return;
		} 
		
		# headings: Always start a new div4, but ignore upright/italics in the heading and take upright/italics from the next paragraph instead
		if (m!<head>!) {
			my $nextP = $line;
			while (!($text[$nextP] =~ m!<p[ >]!)) {
					return if m!<pb!;  # do not look further than the next page break: don't start a new div4 in this (hopefully rare) case
					$nextP++;					
			}
			$doNotCheckBeforeLine = $nextP;
			
			# upright: always pseudo-Euclid
			if ($text[$nextP] =~ m!<p>!) {			
				addDiv4("pseudoEuclid");
				return;
			}
			# italics: either a comment div on the preceding upright div, or the same comment div type as before
			if ($div4 =~ m![cC]omment!) {
				addDiv4($div4);
				return;		
			}
			addDiv4($div4."Comment"); # we assume that there is no "comment", i.e. a comment without preceding upright p		
			return;			
		}
		
		# paragraph in italics
		if ($italicsP) {
			if ($div4 eq "") { 
				addDiv4("comment"); # this does not exist in Clavius
				return;
			}
			return if $div4 =~ m![cC]omment!; # return if we are already in a comment div
			
			addDiv4($div4."Comment");
			return;
		}
		
		# euclid and pseudo-euclid
		return if $div4 =~ m![eE]uclid$!; # return if we are already in a euclid or pseudoEuclid div
		return if $div4 =~ m!corollarium$!; # return if we are already in a corollarium div

		# the first euclid part
		if ($div4 eq "") { 
			addDiv4("euclid");
			return;
		}

		# every euclid part apart from the first is called pseudo-euclid
		addDiv4("pseudoEuclid");
		return;		
	}


	# headings

	if (s!<h it>!<h>!) { $italicsH = 1; }
	if (s!<h>!<head>!) { $inH = 1; }
	
	if ($inH) {

 		s!</h>!</head>!;

		# headings at level 3
		if (($inDef) && (!$defOnHold)) {
			if (m!<head>[XVI]+\.</head>!) {
				$def++;
				if ($inDiv3) { print '</div></div>'; }
				print '<div type="definitio" level="3" n="'.$def.'">';
				if ($pbTag) { print $pbTag; $pbTag = ""; }
				$inDiv3 = 1;
				resetDiv4;
				$doNotCheckBeforeLine = $line + 1;
			}
		}
		if ($inPost) {
			if (m!<head>[XVI]+\.</head>!) {
				$post++;
				if ($inDiv3) { print '</div></div>'; }
				print '<div type="postulatum" level="3" n="'.$post.'">';
				if ($pbTag) { print $pbTag; $pbTag = ""; }
				$inDiv3 = 1;
				resetDiv4;
				$doNotCheckBeforeLine = $line + 1;
			}
		}
		if ($inComm) {
			if (m!<head>[XVI]+\.</head>!) {
				$comm++;
				if ($inDiv3) { print '</div></div>'; }
				print '<div type="axioma" level="3" n="'.$comm.'">';
				if ($pbTag) { print $pbTag; $pbTag = ""; }
				$inDiv3 = 1;
				resetDiv4;
				$doNotCheckBeforeLine = $line + 1;
			}
		}
		if ($inPropos) {
			if ((m!<head>PROBLEMA 1\.</head>!) || (m!<head>.+? PROPOS\. \d+\.</head>!)) {
				$propos++;
				if ($inDiv3) { print '</div></div>'; }
				print '<div type="propositio" level="3" n="'.$propos.'">';
				if ($pbTag) { print $pbTag; $pbTag = ""; }
				$inDiv3 = 1;
				resetDiv4;
				$doNotCheckBeforeLine = $line + 1;
				if (m!<head>PROBLEMA 1\.</head>!) { $doNotCheckBeforeLine++; } # allow for the following PROPOSITIO 1. line
			}
		}

		checkForNewDiv4;

		# end each line with <lb/>
		$_ .= "<lb/>";
		s!</head><lb/>!</head>!;
		
		# italics
		if ($italicsH) { s!<head>!<head style="italics">! }
		
		# print all headings
		print "$_\n";

		if (m!</head>!) { $inH = 0; $italicsH = 0; }
		next;
	}
	

	# paragraphs

	if (s!<p it>!<p>!) { $italicsP = 1; }
	if (m!<p>!) { $inP = 1; }
	
	if ($inP) {

		checkForNewDiv4;

		# normalize the periods: there should always be a period before </p>
		s!([^.])</p>!$1\.</p>!g;


		# tagging sentences
		# (A period . may or may not indicate a new sentence; see "handle exceptions".) 
		# (A colon : always indicates a new sentence.)
		# (A semicolon ; indicates a new sentence, probably unless there seems to be a variable before it.)
		
		# -  handle exceptions
		#    period
		s!\."!MURP"!g;  # avoid artifact sentences in xml attributes, especially resolved abbreviations
		s!(\d+)\.!$1MURP!g; # assumption: no new sentence after an arabic number
		s!([a-zA-Z])\. (\d+)!$1MURP $2!g; # assumption: no new sentence before an arabic number
		s!}\.!}MURP!g; # no new sentence after fractions
		s!<p>([IVXLC]+)\.!<p>$1MURP!; # roman number at the beginning of the paragraph
		
		s! defin\.! definMURP!g; # some ad hoc MURPing;  better properly resolve these abbreviations?
		s! def\.! defMURP!g;
		s! cap\.! capMURP!g;
		s! Rep\.! RepMURP!g;
		s! quib\.! quibMURP!g;
		s! duob\.! duobMURP!g;
		s! proportionib.! proportionibMURP!g; 
		s! verticib.! verticibMURP!g;
		s! ſchol\.! ſcholMURP!g;
		s! Regiom\.! RegiomMURP!g; # Regiomontanus
		
		s!li<\!-- 007 -->b\.!li<\!-- 007 -->bMURP!g;
		s! ([A-Z])\. ([^A-Z])! $1MURP $2!g; # catches, among others, " R. q."
		if (m! [A-Z]\.$!) { 
			if ($text[$line] =~ m!^[^A-Z]!) { s!( [A-Z])\.$!$1MURP!; } # same rule at line end
		}

		#    semicolon
		s!&amp; c\.!&amp;c.!g; # normalize &c.
		s!&amp;c\. ([^A-Z])!&amp;cMURP $1!g; # problem of &c., see above. 
		if (m!&amp;c\.$!) { # &c. at line end
			if ($text[$line] =~ m!^[^A-Z]!) { s!&amp;c\.$!&amp;cMURP!; }
		}
		# (This rule will inevitably produce some incorrect tags, e.g. "&c. _Ad" in lines 2802, 3414.)

		s!q;!qHUBA!g;  # -que ligature
#		s!( [a-zA-Z]);!$1HUBA!g; # variables before the ;
		s!( [a-zA-Z]); ([a-zA-Z] )!$1HUBA $2!g; # semicolon between two apparent variables
		if (m! [a-zA-Z];$!) { 
			if ($text[$line] =~ m!^[a-zA-Z] !) { s!( [a-zA-Z]);!$1HUBA!; } # same rule at line end
		}
		s!&amp;!&ampHUBA!g; # &amp;
		

		# -  other preparations
		s!([.:;])</sc>!</sc>$1!g;


		# -  main
		s!<p>!<p><s>!;
		if ($lineStartsWithS) { $_ = "<s>$_"; $lineStartsWithS = 0; } 
		s![.:;]!$&</s><s>!g;
		if (s!<s>$!!) { $lineStartsWithS = 1; }

		# -  corrections
		s!([.:;])</s><s>_!$1_</s><s>!g;  # (the underscore _ should be made into italics!)

		# -  change back non-sentence-ending punctuation marks
		s!MURP!.!g; # period
		s!HUBA!;!g; # semicolon

		# -  final corrections
		s!([.:;])</p>!$1</s></p>!;
		s!<s></p>!</p>!;
#		s!<s> !<s>!g;

		# mark italics
		# (must be after the sentence tagging)		
		if ($italicsP) { s!<p([ >])!<p style="italics"$1!; } # however, in Clavius there are no attributes other than it
		
		# end each line with <lb/>
		$_ .= "<lb/>" unless (($line < $#text) && (($text[$line] =~ m!<tb>!) || ($text[$line] =~ m!<pb!)));
		s!</p><lb/>!</p>!;
		s!<s><lb/>!<lb/><s>!g;

		# corrections after a first discussion
		s!</s><s>\)!)</s><s>!g;
		s!</s><s> ! </s><s>!g;  # beachte Zeilenumbruch??
		
		print "$_\n";

		if (m!</p>!) { $inP = 0; $italicsP = 0; }
		next;
	}
	

	# everything else
	
	print "$_\n";	
}


print "</div></div></body></text></echo>\n";
