WOPR Talk

Rund um die LCL und andere Komponenten
Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

WOPR Talk

Beitrag von theo »

Ich möchte hier einen Thread eröffnen um ein bisschen meine Erfahrungen beim schreiben von WOPR (WOrd (Object Pascal) PRocessor) auszutauschen und gewisse Inputs zu erhalten. Auch etwas inspiriert von user "knight".

Mein momentaner Fokus ist gerade auf dem neuen HTML Reader und Tabellen.
Der HTML Reader kann nun eingeschränktes CSS interpretieren.
Dabei können die Stylesheets in der HTML-Seite drin, extern oder inline sein, es kommt letzlich aufs selbe raus.
Sie werden einfach gewissen Regeln folgend "eingehängt"
Beispiel:

Code: Alles auswählen

<link href="style.css" media="screen" type="text/css" rel="stylesheet"/>
<style>
span.sym {
  color: darkred
}
</style>
</head>
<body>
<span class="sym" style="color:red;">hallo</span>
Also oben ein externes CSS-File, dann eine interne Deklaration dann Inline.

Der CSS Parser ist eingeschränkt, weil es sehr viele Varianten und Regeln gibt, die ich erstens zeitlich nicht alle umsetzen kann und die "in the wild" praktisch nie angetroffen werden. Ich würde auch nie behaupten, dass ich die Geschichte begriffen hätte ;-)

Trotzdem: Was kann der Parser:

- Selektoren
- Klassen
- IDs
- Pseudos
- Sub-Selektoren

Also ein CSS Auszug wie folgender

Code: Alles auswählen

body, td, a {
  font-family: Helvetica, Arial, Geneva, SunSans-Regular, sans-serif;
  font-size: 12px;
  text-decoration: none;
  color: #000000;
}
 
div a{
 color:red;
}
 
td {
  vertical-align: top;
}
 
.spacer {
  margin-top: 10px;
  margin-bottom: 10px;
  height: 1px;
}
 
a:hover, #navigation a:hover {
  color: #72A436;
}
Wird vollständig auf WOPR angewandt.

Hier sieht man praktisch alle interpretierten Regeln:
z.B. "a" hat Grundsätzlich die Eigenschaften von body, td, a {..} ebenso ein td
dieses wir aber überschrieben von td {vertical-align: top;}
Während die meisten Styles statisch zugewiesen werden können, muss man bei der Deklaration des Subselektors von div a{color:red;} den Parse-Tree hochkraxeln und sehen, ob für eines der Elternelemente einen anderen Style für den a-tag vorgesehen ist.
Dazu kommen noch die Pseudos wie a:hover, also den Style für ein a Tag auf dem der Cursor steht.
Das gleiche geht mit den Klassen und ID's wie #navigation a:hover, Also ein a-Tag in einem Elternelement mit der ID "navigation" kann wieder anders dargestellt werden beim hovern.

Confusing isn't it? ;-)

Mehr kann und will ich im Augenblick nicht umsetzen zumal das ca 95% aller Stylesheets die man "so antrifft" abdeckt.
------------

Eine grundsätzliche Entscheidung war es, den DOM-Tree abzuflachen für WOPR.
Während es für handgeschriebenes HTML sinnvoll sein kann, auf Hierarchie zu setzen, macht das für eine Wysiwyg Editor keinen Sinn.
Wie und warum sollte ich dem User verklickern, dass der Absatz den er gerade bearbeitet, das X-te Kind eines Elternabsatzes ist und beispielsweise dessen
Einzugseigenschaften erbt? Der User kann einfach einen Teil markieren und dessen Einzug bestimmen.
Das zeigt natürlich ein Grund-Dilemma von WOPR für HTML, weshalb es auch nicht als HTML Editor zu interpretieren ist.

Also das:
test
test
test
wandle ich um in
para [margin-left 20px] test
para [margin-left 40px] test
para [margin-left 20px] test



------------

Dann kommt das herausfinden der defaults für das darstellen des HTML (ohne CSS).
Interessanterweise regelt das W3Consortium oft das rendering nicht.
Man kann dann nur versuchen herauszufinden wie die Browser das machen.
Beispiel:
Ein hat keinen vordefinierten Abstand (margin), ein aber schon. Der Abstand oben und unten an einem scheint jeweils
nochmal die font-size in pt zu sein. Also die Font.Size * PPI / 72.

Ein Tag hat einen margin-top und margin-bottom. Wenn aber direkt ein weiteres Block-element mit einem margin-top folgt, wird dieser nicht angewandt.
Lustig wa?

------------

Noch lustiger ist es mit Tabellen. Dort gibt es explizit keine Regeln des W3C.
Eine HTML Tabelle ohne Eigenschaften passt sich der Grösse des Inhalts an.
Dazu musste ich ein 2-Pass verfahren anwenden.
Also erstmal schauen wie die Minimalbreite einer Tabellenspalte (ein Wort, ein Bild), und die Maximalbreite des nicht umgebrochenen
Textes ist. Anhand dieser Daten kann man dann die Spaltenweiten verteilen und im zweiten Pass die Zellen befüllen und die Umbrüche machen.
So weit bin ich schon. Auch fixe bzw. prozentuale Tabellenbreiten habe ich schon.
Was ich noch machen muss ist der Mix also z.B. Erste Spalte 200px, Zweite Spalte 70%, dritte Spalte undefiniert.
Dazu kommen colspan rowspan etc.

Und für alle die jetzt immer noch lesen:

Wie sollte eine Markierung auf mehreren Zellen einer Tabelle kopiert werden?
Ob ich eure Vorschläge umsezten kann weiss ich nicht.
Aber was wäre ideal?
Beispiel: Ich selektiere zwei Zellen einer vierspaltigen Tabelle.
Wenn ich diese Selektion nun einfüge, soll diese dann innerhalb der Tabelle als zwei neue Zellen eingefügt werden oder nur als Text?
Soll ausserhalb der Tabelle eine neue, zweispaltige Tabelle erstellt werden, oder nur der Text gepastet werden?

Ich hoffe ich habe euch nicht zu sehr gelangweilt.

P.S: Warum frage ich das? Es ist interessant zu sehen wie z.B. OpenOffice und KWord diese Dinge anders lösen.
Von daher ist keine Referenz zu erwarten.
Es tut aber auch ein bisschen gut, zu sehen das WOPR OpenOffice Text in Positionsrahmen wenigstens anzeigt (wenn auch an falscher Position) während KWord (in 3.5.5) diese einfach verschluckt und dem User vorenthält.
Aber das Positionsrahmen Konzept ist momentan für WOPR noch nicht zu bewältigen.
Anzeigen wäre nicht so schwerig, der Text-Umlauf aber schon eher.
Das was komplett aus dem System fallen würde ist die Navigation. Während der WOPR Cursor eigentlich immer den Document-Tree rauf und runter kraxelt,
ist dies bei Positonsrahmen nicht möglich. Diese fänden ja quasi ausserhalb des Document-Trees statt und wären and die Seite oder einen Absatz gebunden.
Also müsste man einen zweite Liste halten mit allen fix-positionierten Elementen. Ich weiss nicht ob ich das umsetzen werde.

Gerne nehme ich eure Ideen entgegen, aber den Source-Code veröffentliche ich nicht, solange ich das Ganze nicht für einigermassen brauchbar halte.
Ich mache es ja nur als Hobby aber möchte etwas vernünftiges abliefern.
Also wer in den nächsten zwei Wochen sowas braucht, muss sich nach anderen Lösungen umsehen.
Ich glaube auch nicht, dass mir jemand dabei helfen kann.
Nicht dass ich denke, dass ihr zu doof seid, aber ich verstehe ja schon manchmal selber meinen Code nicht mehr und ich kann mir nicht
vorstellen, dass sich jemand auf die Schnelle in die Problematik und meinen Ansatz eindenken kann.

Hier mal ein paar Dateigrössen:
woprdocument.pas 130.4 KB
woprcontrol.pas 74.5 KB
woprrendering.pas 33.9 KB
woprkeycmds.pas 33 KB
woprstreamerhtml.pas 27.1 KB
woprdoctree.pas 26.0 KB
woprstreamerod.pas 25.3 KB
woprcss.pas 22.9 KB
etc. pp

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Könnte ich jetzt aus der intuition heraus gar nicht beantworten.
Ich find beide Varianten OK.
Praktisch kann ich mir eigentlich nur vorstellen das das reine Text einfügen praktikabel ist. Was ist z.b. wenn du 2 Spalten nebeneinander und eine darunter markirt hast, den Quatsch kopierst und dann einfügen willst...

An saubersten und am besten nachvollziehbar wärs sicher eine neue Tabelle anzulegen. Alternative wäre nur den Text zu kopieren.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Christian hat geschrieben:Könnte ich jetzt aus der intuition heraus gar nicht beantworten.
Ich find beide Varianten OK.
Praktisch kann ich mir eigentlich nur vorstellen das das reine Text einfügen praktikabel ist. Was ist z.b. wenn du 2 Spalten nebeneinander und eine darunter markirt hast, den Quatsch kopierst und dann einfügen willst...

An saubersten und am besten nachvollziehbar wärs sicher eine neue Tabelle anzulegen. Alternative wäre nur den Text zu kopieren.
Gar nicht so einfach zu entscheiden was?
Für den Anfang werde ich wahrsch. mal nur den Text kopieren.
Ganze Zeilen könnte man schon einfügen. Aber auch da stellt sich die Frage, ob die
Zeile nun in die Zelle der Einfügeposition als neue Tabelle einkopiert, oder an der bestehenden Tabelle eine Zeile unterhalb der Einfügeposition eingefügt werden soll.
WOPR kann ja verschachtelte Tabellen.
Was OO da macht leuchtet mir nicht ein. OK, Ausserhalb der Tabelle wird eine neue erstellt. Aber innerhalb wird die Zeile einfach überschrieben !?!

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Also intuitiv würd ich in der Tabelle eine neue einfügen auch wenn eine ganze Zeile markiert wurde. Sobald es Eine zeile und Einzelne zellen werden oder mehrere Zeilen ist das der Logischste Weg.
Und bei einer einzelnen zeile anders zu reagieren als bei mehreren oder einer ganzen Tabelle ist quatsch denk ich.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Im Screenshot ein kleines Update bezüglich des Standes von WOPR.
Links WOPR, Rechts Firefox.

Es geht im Moment um den neuen CSS Reader und Tabellen.
Als "real life" - Beispiel habe ich mal versucht, das ganze soweit zu bringen, dass es die Lazarus Help darstellen kann.

Die Seite sieht zwar prinzipiell nicht sehr aufregend aus, aber sie besteht praktisch nur aus Tabellen und CSS-Definitionen. Also ideal um mein Vorhaben zu testen.

Es sind zwar kleine Dimensionsunterschiede zu sehen, aber funktional wird die Seite identisch gerenderet. Sie ist also absolut ohne Einschränkungen in WOPR lesbar.

Die Tabellen sind alle Dimensionslos, also weder die Gesamtbreite noch die Breite einzelner Spalten ist vorgegeben. Alle Breiten werden aufgrund des Inhalts verteilt.
Dabei kann es leichte Unterschiede geben.
Zu sehen ist das im Umbruch bei "type TButton = class". Das ist nicht unbedingt falsch.
WOPR entscheidet da einfach früher umzubrechen um der dritten Spalte mehr Platz zu lassen. Ebenso ist die Minimalbreite der unsichtbaren zweiten Spalte bei FF anders. Kann ich aber evtl. noch anpassen.

Was man bei grösseren Projekten wie diesem lernen kann, ist dass es sich lohnt "APIs" zu bauen. Also Probleme immer möglichst allgemein zu lösen.
Wenn man dann mal für alles nötige eine Funktion hat, kann man Teilweise nur noch "Steinchen auf Steinchen" legen und die Sache funzt. Das macht dann ziemlich viel Spass.
Dateianhänge
woprhtml.png

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Nicht schlecht ! Ich freue mich schon darauf wenn die Komponente deiner Meinung nach soweit ist sie zu veröffentlichen. Sieht sehr Vielversprechend aus.

Die seiten sind bis auf drei Unterschiede fast gleich.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben: Die seiten sind bis auf drei Unterschiede fast gleich.
Die Unterschiede die du siehst, haben nur mit der Fensterbreite zu tun.
FF ist im Screenshot breiter als WOPR, deshalb bricht dort der Text nicht um.
WOPR macht ja auch (wie FF) automatischen Zeilenumbruch, auch in Tabellen-Zellen.
Das was du im WOPR Screenshot siehst, beweist ja leztlich, das die Tabellen-Zellen als solche dargestelt werden.

Es bleiben kleine Unterschiede in den Font Grössen. Diese sind aber nicht dramatisch und nur in direkter Gegenüberstellung erkennbar.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ach so, ich habe angenommen, das beide Fenster gleich groß sind.

Aber ich bin mal auf dein End Ergebnis gespannt.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Rackere mich gerade mit dem RTF-Streamer ab.
RTF schreiben ist noch machbar, aber RTF lesen ist wirklich nicht einfach.
Warum? Es gibt viele Wege RTF zu schreiben. Einer reicht. Aber auslesen sollte man alles können, was mir schier unmöglich scheint.
Deshalb zeige ich heute auch einen Screenshot, welcher das von WOPR gespeicherte RTF (Habe den Save-Streamer heute programmiert) in KWord geladen darstellt.
Im Screenshot: Oben WOPR unten KWord.
WOPR kann zwar den eigenen "Dogfood" mittlerweile auch lesen, aber nicht unbedingt alles was "in the wild" vorkommt (Styles, Groups, Mac-Charset etc).
Auch Unicode habe ich hier nicht angedacht. Das geht aber mit dem ODT und dem HTML Streamer.

Die Entwicklung von WOPR geht im Moment eher schleppend.
Bin bei den Tabellen bei "Rowspan" steckengeblieben.
Muss mir noch überlegen, wie das mit dynamischen (HTML) Tabellen am besten zu implementieren ist. Die Spaltenbreite wird hierbei aufgrund des gerenderten Inhalts einzelner Zellen berechnet. Das auf mehrere Zeilen (nicht Spalten!!) zu verteilen gibt mir im Moment noch etwas Denkstoff.

Vielleicht versuche ich mal eine erste Alpha version zum Testen bereitzustelen ohne diese Komplikationen.

Ansonsten muss ich sagen, dass das ODT (OpenOffice OASIS) Format eigentlich das beste ist, welches ich bisher angetroffen haben.
Es gibt zwar einige Anlaufschwierigkeiten, weil die Datei ein JAR-Archiv ist und man das erstmal Aus- und Einpacken muss.
Als ich aber den Aufbau der darin enthaltenen XML-Dateien einmal halbwegs begriffen hatte, habe ich bemerkt, dass die interne Logik am Besten mit
der WOPR-Logik harmoniert (ohne dass ich vorher das ODT studiert hätte).
Das Meiste geht dann wie von selbst.
Kann gut sein, dass ODT das Haupt-Dateiformat von WOPR wird, neben dem internen Stream-Format *.wop;

P.S: Die Entwicklung und die Screenshots sind mit dem angeblich noch nicht brauchbaren GTK2 gemacht, mit der GTK2 IDE. ;-)
GTK1 eignet sich für WOPR überhaupt nicht. Bei einem Word-Processor sollte man doch Anti-Aliased-Fonts und Unicode haben.
Beides wird mit GTK1 nicht klappen, obwohl WOPR prinzipiell auch auf GTK1 läuft (Übrigens auch mit Delphi)
Dateianhänge
woprbeitrag2.png

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Sieht doch schon ganz gut aus. Ich dachte immer RTF sei leicht zu parsen. Aber da Lage ich wohl falsch.

Evlt. könntest du ja noch einen einfachen BB-Code-Parser einbauen so wie wir in aus den vielen Foren kennen.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben: Evlt. könntest du ja noch einen einfachen BB-Code-Parser einbauen so wie wir in aus den vielen Foren kennen.
Zu welchem Zweck?

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Um z.b. Beiträge für ein Forum Offline zu speichern. Sowas was Monta mal gemacht hat.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Achso, ja. Das wäre nicht besonders schwierig.
Kann man dann immer noch machen.

knight
Beiträge: 802
Registriert: Mi 13. Sep 2006, 22:30

Beitrag von knight »

Zum Stichwort RTF: Offenbar wird auch im FPC Team daran gearbeitet (siehe Revision 11268). Vielleicht lohnt sich ja ein Blick darauf.

knight

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

knight hat geschrieben:Zum Stichwort RTF: Offenbar wird auch im FPC Team daran gearbeitet (siehe Revision 11268). Vielleicht lohnt sich ja ein Blick darauf.
knight
Das hat Michael Van Canneyt freundlicherweise auf meine Anregung hin repariert.

Antworten