Das Beispiel: „mycas” |
Ganz zum Anfang eine Vorbemerkung: Wenn es darum geht, Schnittstellen zu einem Fremd-Programm zu entwerfen, ändern Sie den Quellcode des Anwenderprogramms so, dass es mit TeXmacs zusammenarbeitet. Sie müssen den Quellcode des Anwenderprogramms also besitzen.
Ein Beispiel zu analysieren, ist der einfachste Weg, um zu lernen, wie man eine neue Schnittstelle von TeXmacs zu einem Fremd-Programm installiert. In dem Unterverzeichnis Ihres TeXmacs-Verzeichnisses, plugins/mycas, finden Sie ein Beispiel für ein simples „Computer Algebra System” mit dem Namen mycas. Dort finden sie auch die Datei mycas.cpp mit diesem wirklich einfachen Programm. Das Programm finden Sie außerdem am Ende dieses Abschnitts. Um es zu testen, müssen Sie es mit dem Befehl
g++ mycas.cpp -o mycas
kompilieren und die so erzeugte ausführbare Datei in ein
Verzeichnis Ihres Suchpfads übertragen. Wenn Sie dann TeXmacs neu
starten, sollten Sie im Menü
Lassen Sie und den Quellcode von mycas Schritt für Schritt durchgehen. Die Kommunikation geht über die normalen Eingabe- und Ausgabekanäle. Damit TeXmacs aber weiß wann die Ausgabe des Programms beendet ist, muss der Output in Blöcke eingekapselt werden und zwar mit drei speziellen Steuer-Buchstaben, die Sie so definieren:t
#define DATA_BEGIN ((char) 2)
#define DATA_END ((char) 5)
#define DATA_ESCAPE ((char) 27)
Der DATA_ESCAPE-Buchstabe dient zur Maskierung. Ein unmittelbar folgender Buchstabe c bleibt c, auch wenn es einer der Steuerbuchstaben ist. Ein Beispiel, wie DATA_BEGIN und DATA_END gebraucht werden, zeigt der Begrüßungstext beim Start des Programms:
int
main () {
cout << DATA_BEGIN << "verbatim:";
cout << "–––––––––––––––––––––––––––\n";
cout << "Welcome to my test computer algebra system for TeXmacs\n";
cout << "This software comes with no warranty whatsoever\n";
cout << "(c) 2001 by Joris van der Hoeven\n";
cout << "–––––––––––––––––––––––––––\n";
next_input ();
cout << DATA_END;
fflush (stdout);
Die erste Zeile von main sorgt dafür, dass in TeXmacs das Format „wörtlich“ zur Ausgabe benutzt wird. Die Funktion next_input die nach dem Begrüßungstext erscheint, erzeugt eine Eingabe-Aufforderung. Sie wird unten genauer erklärt. DATA_END schließt den Begrüßungsblock und teilt TeXmacs mit, dass mycas auf Eingaben wartet. Vergessen Sie nicht den Puffer mit fflush zu leeren, damit TeXmacs die gesamte Information auch wirklich erhält.
Die Hauptschleife, main loop, beginnt mit der Abfrage, ob im Eingaben im Input-Kanal vorhanden sind:
while (1) {
char buffer[100];
cin >> buffer;
if (strcmp (buffer, "quit") == 0) break;
Haben Sie „quit” eingegeben, wird das Programm beendet.
Die Ausgabe von mycas, die als Reaktion auf eine Ihre Eingabe erfolgt, muss wieder in einen DATA_BEGIN-DATA_END-Block. eingeschlossen werden:
cout << DATA_BEGIN << "verbatim:";
cout << "You typed " << buffer << "\n";
Innerhalb eines solchen Blocks, kann man rekursiv weitere Blöcke senden, die unterschiedliche Formate haben dürfen. Z.B. schickt der folgende Code eine LaTeX-Formel:
cout << "And now a LaTeX formula: ";
cout << DATA_BEGIN << "latex:" << "$x^2+y^2=z^2$" << DATA_END;
cout << "\n";
Manchmal kann es nützlich sein, direkt im TeXmacs-Format zu
schicken, indem die
cout << "And finally a fraction ";
cout << DATA_BEGIN << "scheme:" << "(frac \"a\" \"b\")" << DATA_END;
cout << ".\n";
Zum Schluss muss ein abschließendes DATA_END gesendet und der Puffer geleert werden:
next_input ();
cout << DATA_END;
fflush (stdout);
}
return 0;
}
Es ist zu beachten, dass Sie niemals mehr als einen DATA_BEGIN-DATA_END-Block senden dürfen. Denn TeXmacs unterstellt, wenn es einen solchen Block erhalten hat, dass Ihr Programm auf Eingaben wartet. Wenn Sie mehrere DATA_BEGIN-DATA_END-Blöcke senden müssen, dann müssen Sie diese zusammen in einen gemeinsamen Block einschließen.
Ein spezieller „Kanal“ wird für die Übertragung der Eingabeaufforderung benutzt. Kanäle werden als spezielle DATA_BEGIN-DATA_END-Blöcke definiert:
static int counter= 0;
void
next_input () {
counter++;
cout << DATA_BEGIN << "channel:prompt" << DATA_END;
cout << "Input " << counter << "] ";
}
Innerhalb des „prompt“ -Kanals, dem Eingabeaufforderungs-Kanal, kann man wiederum verschachtelte DATA_BEGIN-DATA_END-Blöcke verwenden. Somit kann man auch Formeln für die Eingabeaufforderung verwenden. Es gibt drei Standardkanäle:
Man kann PostScript-Graphik als Ausgabe schicken. Nehmen wir einmal an, dass Sie in Ihrem Heimat-Verzeichnis ein Bild picture.ps haben. Wenn Sie die Zeilen
cout << "A little picture:\n";
cout << DATA_BEGIN << "ps:";
fflush (stdout);
system ("cat $HOME/picture.ps");
cout << DATA_END;
cout << "\n";
an einer passenden Stelle der Hauptschleife einfügen, wird ihr Bild als Teil der Programm-Ausgabe auf dem Bildschirm erscheinen.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>
#define DATA_BEGIN ((char) 2)
#define DATA_END ((char) 5)
#define DATA_ESCAPE ((char) 27)
static int counter= 0;
void
next_input () {
counter++;
cout << DATA_BEGIN << "channel:prompt" << DATA_END;
cout << "Input " << counter << "] ";
}
int
main () {
cout << DATA_BEGIN << "verbatim:";
cout << "–––––––––––––––––––––––––––\n";
cout << "Welcome to my test computer algebra system for TeXmacs\n";
cout << "This software comes with no warranty whatsoever\n";
cout << "(c) 2001 by Joris van der Hoeven\n";
cout << "–––––––––––––––––––––––––––\n";
next_input ();
cout << DATA_END;
fflush (stdout);
while (1) {
char buffer[100];
cin >> buffer;
if (strcmp (buffer, "quit") == 0) break;
cout << DATA_BEGIN << "verbatim:";
cout << "You typed " << buffer << "\n";
cout << "And now a LaTeX formula: ";
cout << DATA_BEGIN << "latex:" << "$x^2+y^2=z^2$" << DATA_END;
cout << "\n";
cout << "And finally a fraction ";
cout << DATA_BEGIN << "scheme:" << "(frac \"a\" \"b\")" << DATA_END;
cout << ".\n";
next_input ();
cout << DATA_END;
fflush (stdout);
}
return 0;
}