CONTENTS | PREV | NEXT

Workshops / Hintergrundberichte
-------------------------------

1. ARexx-Kurs - Teil 5 (von Heiko Kuschel)

»ARexx-Kurs: Übersicht

1. Einführung in ARexx.
    - Wie funktionierts?
    - Was brauche ich?
    - Installation
    - ein erstes kleines Programm
        - Ein- und Ausgabe
        - do...end

2. Programmstruktur und Ansteuerung von anderen Programmen
    - if
    - do...end
    - address
    - Tracing

3. Ein- und Ausgabe; Funktionen
    - Ein- und Ausgabe
    - Stringfunktionen
    - mathematische Funktionen
    - Konvertierungsfunktionen
    - Bitmanipulation

4. komplexere Programmstrukturen
    - Operatoren
    - Procedure
    - Libraries
    - Systemfunktionen

5. Aufbau von Skripten
    - ein ARexx-Skript konzipieren
    - MUIRexx
    - Libraries
    - Beispiele für die Vernetzung von Programmen«


»5. Beispiele für die Vernetzung von Programmen
5.0. Vorbemerkungen
Hier wiederhole ich für Quereinsteiger noch einmal einen Teil der
Vorbemerkungen, die ich zum ganzen Kurs gemacht habe.

Der Kurs wird als reine Text-Datei angefertigt, da auch Amiga Aktuell u.a. 
in ASCII-Form verschickt wird. Um den Text etwas zu gliedern, habe ich 
daher ein paar "Textmarker" eingefügt.

********** unterteilt einzelne Abschnitte

__________ bezeichnet Beginn und Ende eines ARexx-Programms. Die Striche 
gehören nicht zum Programm!
ARexx-Befehle werden in diesem Kurs immer GROSS geschrieben, obwohl das
eigentlich nicht nötig ist. Auf diese Weise kann man sie aber leichter 
erkennen.

Ich hoffe, daß diese Regelung den Kurs etwas leserlicher macht.

Wenn ihr spezielle Fragen habt, etwas nicht verstanden habt oder Anregungen 
und Ideen für weitere Kursteile habt, könnt ihr euch gerne an mich wenden.
Ich selbst benutze folgende ARexx-fähige Programme und kann daher auf deren
Programmierung kurz eingehen, wenn das gewünscht wird:
Wordworth, GoldEd, Database Professional, YAM, Miami, Voyager, TurboCalc.

Hier meine Kontaktadresse:

Heiko Kuschel
Lehmgrubenweg 13
97280 Remlingen
E-Mail: hk0006@wuerzburg.baynet.de

Und jetzt... viel Spaß mit ARexx!

****************************************************

5.1. Ein ARexx-Skript konzipieren
Mittlerweile haben wir so ziemlich alle ARexx-Befehle durchgemacht, die es
gibt. Aber - wie mache ich daraus nun ein sinnvolles ARexx-Skript? Bei 
vielen Vorhaben ist das gar nicht so einfach, denn manche Programme, die 
über ARexx anzusteuern sind, haben so ihre Eigenheiten. Ein paar 
Grundprobleme möchte ich in diesem Kursteil ansprechen und dann noch 
Skripte vorstellen, die ich selber für den "Hausgebrauch" geschrieben habe.

****************************************************
5.1.1. Wie finde ich die Adresse?
Fast alle ARexx-fähigen Programme bieten die Möglichkeit, ARexx-Skripte 

der Port des startenden Programms als ARexx-Port voreingestellt, an den die 
Befehle geschickt werden sollen. Das sieht dann so aus:
__________________________________
OPTIONS RESULTS
PortName = ADDRESS()
__________________________________

Wenn später ein anderes Programm angesteuert wird und dadurch der Port mit
ADRRESS xxx verändert wird, kannst Du anschließend wieder auf das Programm
zurückkommen, das das Skript gestartet hat. Und zwar ganz einfach mit

ADDRESS VALUE PortName

PortName ist hier die Variable, in der der Portname des Programms abgelegt
wird, das das Skript gestartet hat. Z.B. Wordworth.1 oder YAM etc.

****************************************************
5.1.2. Eigenheiten der einzelnen Programme
Manche Programme haben nicht nur einen einzigen ARexx-Port. Stattdessen 
öffnen sie für jedes Fenster einen eigenen, z.B. Wordworth und, soweit ich 
weiß, auch Final Writer. Die werden dann durchnumeriert: Wordworth.1, 
Wordworth.2 usw.
Dadurch kann man sich nie sicher sein, daß ein bestimmter Port tatsächlich
existiert! Es kann ja sein, daß das Fenster (und damit der Port), dem
Wordworth.1 zugeordnet wurde, geschlossen wurde. Vielleicht existieren 
gerade nur Wordworth.3 und Wordworth.5. Wenn ich Wordworth also von außen 
ansteuern will, ohne daß das Skript aus Wordworth heraus gestartet wurde, 
ist es ziemlich schwierig, einen richtigen Port zu finden. Ich behelfe mir 
immer mit der folgenden kleinen Schleife:
__________________________________
options results
DO Num = 1 to 20
        WwPort = "WORDWORTH." || Num
        IF SHOW(PORTS, WwPort) THEN DO
                Address Value WwPort
                leave Num
        end
end
if num=21 then do
    echo "Wordworth nicht gefunden! Programm endet."
    quit
end
__________________________________

Übrigens gibt es auch andere Programme, die eine Zahl hintendran hängen, 
bei der diese Zahl aber etwas anderes bedeutet. Der normale ARexx-Port von 
GoldEd heißt z.B. GOLDED.1 Hier gibt es nur ein GOLDED.2, wenn GoldEd 
tatsächlich nochmal neu gestartet wird. Alle Fenster mit unterschiedlichen 
Texten innerhalb von GoldEd haben dagegen diesen einen ARexx-Port GOLDED.1.
Bei GoldEd gibt es noch eine weitere Besonderheit: Der Text muß für den
normalen Zugriff gesperrt werden. Dabei muß seit Version 4 von GoldEd auch 
noch angegeben werden, für welche Version dieses Skript geschrieben wurde. 
Sinnvoll, da sich der ARexx-Wortschatz von GoldEd beim Sprung von Version 3 
auf 4 ziemlich geändert hat. Einzelheiten dazu stehen in der Online-Hilfe 
zu GoldEd.

Ein Wort noch zu allgemeinen Problemen mit der Ausführung von Programmen:
Gerade bei Database Professional (DBPro) habe ich festgestellt, daß es oft
genau auf die Schreibweise (groß/klein etc.) ankommt. Oft ist es auch 
nötig, daß Argumente in Anführungszeichen gesetzt werden. Beachte dabei 
folgendes: Aus
FINDBASE "Adressen.db"
wird für Database:
FINDBASE Adressen.db

Du mußt stattdessen das Ganze nochmal in Anführungszeichen setzen, da immer 
die äußersten durch ARexx entfernt werden:
'FINDBASE "Addressen.db"'
Alternativ müßte eigentlich auch gehen:
FINDBASE '"Addressen.db"'
An Database wird dann dieser Text übermittelt:
FINDBASE "Adressen.db"

Kapiert? Ich hoffe es. Das Kapitel mit den Anführungszeichen ist eines der
kompliziertesten in der ganzen ARexx-Programmiererei.

Übrigens: Mir ist es auch schon passiert, daß ich einen Befehl genau so
eingegeben habe, wie er im Handbuch steht, und es hat trotzdem nicht
funktioniert. Das war bei Beckertext III.

****************************************************
5.2. MUIRexx

5.2.1. Kurzeinführung
MUIRexx ist ein ausgesprochen gutes Hilfsmittel, um komplizierteste
Bedienoberflächen zu erstellen. Es ist gewissermaßen die Schnittstelle 
zwischen ARexx und dem "Magic User Interface", kurz: MUI, mit dem 
inzwischen viele Programme programmiert sind (z.B. YAM, Voyager, STFax,...)
MUIRexx ist anders als andere Libraries: Es ist ein eigenes Programm, das 
über ARexx gesteuert wird und, je nach den Befehlen, die es erhält, ein 
Fenster mit Schaltflächen, Listern, Texten oder was auch immer aufbaut. Es 
ist im Aminet erhältlich unter dev/mui und kostet eine Shareware-Gebühr von 
15 US-Dollar.
Nun wird das aber nicht einfach über ADDRESS MUIREXX gemacht, sondern jedes
erstellte Fenster bekommt einen eigenen ARexx-Port. Am einfachsten schaffst 
Du das, indem Du mit MUIRexxBuild ein neues Fenster erstellst und dem einen 
Namen gibst. Ich habe auf diese Weise ein Fenster mit dem Namen "Listen" 
erstellt, das wird dann über ADDRESS Listen angesteuert.
Das Ganze funktioniert so ähnlich wie eine DO... END-Schleife: Erst wird 
ein Fenster definiert, und darin einzelne Gruppen:
WINDOW
    GROUP
        GROUP
        ...
        ENDGROUP
    ENDGROUP
    GROUP
    ....
    ENDGROUP
ENDWINDOW
Das wäre eine typische Grundstruktur für eine Fensterdefinition. Die ganzen
Dinge mit diversen Variablen usw. kannst Du dabei weitgehend MUIRexxBuild
überlassen, das übrigens selbst eine MUIRexx-Anwendung ist!

****************************************************
5.2.2. Ein Beispiel
Bis jetzt habe ich es immerhin geschafft, ein Fenster aufzubauen, das
verschiedene Gruppen enthält. Nur das dazugehörige Programm fehlt noch, das 
die damit verbundenen Aktionen auch ausführt... Da es hier aber um die 
Arbeit mit MUIRexx geht, möchte ich das Ganze trotzdem einmal kurz 
vorstellen. Weitere Beispiele finden sich ja auch im MUIRexx-Ordner.
Mein kleines Skript soll mir eigentlich die Verwaltung von Mailinglisten
vereinfachen. Das sind so eine Art EMail-Rundschreiben-Gruppen. Ich schicke
eine Mail an eine bestimmte Adresse, und diese Mail wird an alle verteilt, 
die sich in der Mailingliste eingetragen haben.
Um in so eine Liste zu kommen, muß man an eine jeweils unterschiedliche 
Adresse eine Mail schicken, etwa "subscribe PAmiga-list meine-Email-
Adresse". Ähnlich mit unsubscribe, wenn man wieder rauswill. Und daneben 
gibt es noch manche Mailinglisten, bei denen man sich auch kurzzeitig 
ausklinken kann, ohne sich vollständig zu verabschieden, indem man die 
Optionen auf NOMAIL setzt, das heißt, ich kriege im Moment keine Mail. Für 
jede Mailingliste existiert also:
- eine Adresse, an die alle Befehle geschickt werden müssen
- ein Befehl, um sich einzuschreiben
- ein Befehl, um sich wieder auszuschreiben
- evtl. ein Befehl, um die Listenoptionen auf NOMAIL zu setzen
- evtl. ein Befehl, um NOMAIL wieder rückgängig zu machen.
Da ich immer wieder mal wechsle, dachte ich mir, es wäre sinnvoll, das über 
ein Programm zu machen. Dabei wollte ich zunächst aus einer großen Liste 
(wer die haben will, kann mich anmailen) ein paar Standard-Mailinglisten 
auswählen können, die dann wiederum einzeln an- und abgeschaltet werden 
können.
Das dazugehörige Fenster stelle ich mir so vor, daß ich eine Liste der
aktuellen (sprich: von mir vorausgewählten) Mailinglisten habe und über 
"Prefs" weitere dazunehmen kann oder welche herausnehmen kann. In einer 
Zeile untendrunter soll, sofern vorhanden, eine kurze Beschreibung der 
Mailingliste stehen, die ich gerade angeklickt habe.
... und so sieht mein Programm dazu aus:
(da einige Programmzeilen sehr lang sind, habe ich die längeren unter ihnen
mit zwei Kommentarzeilen eingerahmt. Für viele von Euch ist sonst 
vermutlich nicht zu erkennen, wo eine Programmzeile unterbrochen ist.
/*Das Folgende ist eine Zeile*/
hier dazwischen steht eine lange Programmzeile
/*bis hier*/

Das folgende Programm wird aus einer Shell heraus wie folgt gestartet:
muirexx:muirexx Listen.rexx PORT Listen
Listen.rexx ist dabei der Name des Skripts.
__________________________________
/* Application created by MUIBuild */

address Listen

MUIA_Listview_DragType = 0x80425cd3
MUIA_List_DragSortable = 0x80426099
MUIV_Listview_DragType_Immediate = 1
TRUE = 1
MUIA_Listview_MultiSelect = 0x80427e08
MUIA_Dropable = 0x8042fbce
MUIV_Listview_MultiSelect_Default = 1
MUIA_List_Quiet = 0x8042d8c7
MUIV_List_Insert_Sorted = -2
line = '%s';

/*Diese Variablen wurden von MUIRexxBuild selbstständig eingefügt*/

window COMMAND """quit""" PORT Listen TITLE """Mailinglisten-Verwaltung"""
 group HORIZ REGISTER LABELS "Aktuelle,Prefs"
  group ID Aktuell
   group HORIZ
    group FRAME
     text LABEL "Liste der aktuellen Mailinglisten"
     list ID List1
    endgroup
    group FRAME
     text LABEL "Status"
     space
     radio LABELS "On,Off,Nomail"
     space
    endgroup
   endgroup
   view ID Help1 STRING "Hilfetext"
  endgroup
  group ID Prefs
   group HORIZ
    group FRAME
/*Das Folgende ist eine Zeile*/
    text LABEL "Liste der bekannten Mailinglisten" list ID List2 ATTRS 
MUIA_Listview_DragType MUIV_Listview_DragType_Immediate 
MUIA_List_DragSortable TRUE
/*bis hier*/
     endgroup
    group FRAME
/*Das Folgende ist eine Zeile*/
     text LABEL "Aktuelle Liste" list ID List3 ATTRS MUIA_Listview_DragType 
MUIV_Listview_DragType_Immediate MUIA_List_DragSortable TRUE MUIA_Dropable 
TRUE
/*bis hier*/
    endgroup
   endgroup
  view ID Help2 STRING "Hilfetext2"
  endgroup
 endgroup
endwindow

/* bis hierher sollte es ziemlich verständlich sein. */
callhook ID List2 PORT INLINE INCLUDE List3 DROP,
    COMMAND """options results;
                address Listen;
                line='%s';
/*Das Folgende ist eine Zeile*/
                'list ID "List2" INSERT POS "MUIV_List_Insert_Sorted" 
STRING' line;
/*bis hier*/
                'list ID "List3" REMOVE STRING' line;
                'list ID "List1" REMOVE STRING' line;"""
callhook ID List3 PORT INLINE INCLUDE List2 DROP,
    COMMAND """options results;
                address Listen;
                line='%s';
/*Das Folgende ist eine Zeile*/
                'list ID "List3" INSERT POS "MUIV_List_Insert_Sorted" 
STRING' line;
/*bis hier*/
/*Das Folgende ist eine Zeile*/
                'list ID "List1" INSERT POS "MUIV_List_Insert_Sorted" 
STRING' line;
/*bis hier*/
                'list ID "List2" REMOVE STRING' line;"""
callhook ID List1 INCLUDE List1
   list ID List1 INSERT STRING "YAM"
   list ID List1 INSERT STRING "PAmiga"
   list ID List1 INSERT STRING "I-Amiga"
   list ID List1 INSERT STRING "TeamAmiga"
   list ID List1 INSERT STRING "STFax"
   list ID List3 INSERT STRING "YAM"
   list ID List3 INSERT STRING "PAmiga"
   list ID List3 INSERT STRING "I-Amiga"
   list ID List3 INSERT STRING "TeamAmiga"
   list ID List2 INSERT STRING "CU-Amiga"
   list ID List2 INSERT STRING "Voyager"
   list ID List3 INSERT STRING "STFax"
__________________________________
Ich hoffe, daß der Aufbau des Fensters auch beim Lesen des Quelltextes 
halbwegs verständlich wird. "REGISTER" sind die Karteikartenreiter am 
oberen Ende des Fensters. Wenn ich eine Gruppe später nocheinmal 
weiterverwenden muß, kann ich ihr mit ID einen Namen zuweisen, also z.B. 
GROUP ID ErsteGruppe.
Schwieriger wird schon die Sache mit Callhook. Hier werden Ereignisse
definiert, nach denen irgendeine Aktion stattfinden soll. Also: Wenn ich in
"Prefs" einen Listennamen aus dem einen Lister in den anderen ziehe, muß 
dieser Name natürlich im alten Lister verschwinden und im neuen auftauchen. 
Da Computer, selbst Amigas, leider nicht intelligent genug sind, muß ich 
ihm das extra sagen. Das sieht dann so aus:
__________________________________
callhook ID List2 PORT INLINE INCLUDE List3 DROP,
    COMMAND """options results;
                address Listen;
                line='%s';
/*Das Folgende ist eine Zeile*/
                'list ID "List2" INSERT POS "MUIV_List_Insert_Sorted" 
STRING' line;
/*bis hier*/
                'list ID "List3" REMOVE STRING' line;
                'list ID "List1" REMOVE STRING' line;"""
__________________________________
Das heißt: Wenn in List2 etwas fallengelassen wird, und zwar aus List3, 
dann starte ein ARexx-Skript, das den MUIRexx-Task Listen addressiert. In 
List2 wird der Name der Mailingliste eingefügt (mit %s), in List3 entfernt 
und ebenso in List1. (Das ist die erste, die man sieht, auf der Seite 
"Aktuelle".)
Um das Programm zu vervollständigen, fehlen jetzt also nur noch weitere 
solche Callhooks, die dann erst einmal den jeweils zur Liste gehörigen 
Hilfetext anzeigen, auf der Seite "Aktuelle" den richtigen Radioknopf für 
die jeweils angeklickte Liste aktivieren (also ob sie an, aus oder auf 
NOMAIL gesetzt ist) - und außerdem noch eine Reihe von Knöpfen, um die 
entsprechenden Befehls-mails loszuschicken, abzubrechen oder eine Übersicht 
über den aktuellen Stand der Dinge auszugeben. Vielleicht hast Du ja Lust, 
so etwas zu machen... :)
Anbei mein einfaches Programm, das vier verschiedene Mailinglisten 
bestellt. So habe ich das bisher gehandhabt:
__________________________________
/* YAM und I-Amiga werden auf MAIL gesetzt, Pamiga und Team Amiga 
bestellt*/
/* $VER: 1.0. 23.2.98 */
options results
if ~show("P",YAM) then address command "run Yam:Yam"

address command
'echo >t:Yamtext "SET YAM MAIL"'
'echo >t:Iamigatext "SET I-AMIGA MAIL"'
'echo >t:PAmigatext "SUBSCRIBE PAMIGA-LIST hk0006@wuerzburg.baynet.de"'
'echo >t:TAmigatext "SUBSCRIBE TeamAmiga hk0006@wuerzburg.baynet.de"'

"sys:rexxc/Waitforport YAM"

address YAM
mailwrite
writemailto "Listserv@tu-clausthal.de"
"writeletter t:Yamtext"
writequeue
mailwrite
writemailto "Majordomo@lists.netlink.co.uk"
"writeletter t:PAMIGATEXT"
writequeue
mailwrite
writemailto "listserv@listserv.acsu.buffalo.edu"
"writeletter t:Iamigatext"
writequeue
mailwrite
writemailto "majordomo@thule.no"
"writeletter t:TAMIGATEXT"
writequeue
address command
"delete >NIL: t:yamtext"
"delete >NIL: t:?amigatext"
__________________________________
Ich denke, dieses Skript solltest Du inzwischen mit Leichtigkeit verstehen.

****************************************************
5.3. andere Libraries
5.3.1. rexxreqtools.library
Die rexxreqtools.library findet sich, soweit ich weiß, im Aminet.

Sie enthält die Funktionen der reqtools.library, also alle Arten von
Requestern. Auch dafür gibt es im Lieferumfang schon ein paar Demos, mit 
denen man ganz gut weiterarbeiten kann. Ich möchte nur eben vorstellen, wie 
ich ein Skript beginne, das zuerst nachsieht, ob Wordworth läuft und dann 
den Requester von Wordworth verwendet, ansonsten aber Rexxreqtools:
__________________________________
options results
DO Num = 1 to 20
        WwPort = "WORDWORTH." || Num
        IF SHOW(PORTS, WwPort) THEN DO
                Address Value WwPort
                leave Num
        end
end
if num=21 then do
  if ~show("L",rexxreqtools.library) then do
  call addlib("rexxreqtools.library", 0, -30, 0)
  end
  gadtxt= "_Holen|E_nde|_To-Do-Liste|_Cancel"
  Anf = upper(rtgetstring(" ","Bitte Textstelle eingeben:","Text 
3.0.",gadtxt))
  buttonresult=rtresult
end
else do
  do i=0 to 5
  viewwindow i
  end    /* wenn Makro nicht von WW aus aufgerufen wird, ist sonst die 
Workbench vorne*/
         /* keine Ahnung, wie man herausfinden kann, welches Fenster 
existiert.*/
/*Das Folgende ist eine Zeile*/
  WizardReq TITLE "Text 3.0." LABEL "Bitte Textstelle eingeben:" TEXTBOX 1 
"_Stelle:" BUTTON 1 "_Holen" BUTTON 2 "E_nde" BUTTON 3 "_To-Do-Liste" 
BUTTON "-1" "_Cancel"
/*bis hier*/
  buttonresult = RESULT
  Wizard_GetTextBox 1
  Anf = UPPER(RESULT)
end
select
  when buttonresult = 2 then do
  when buttonresult = -1 then do
  etc.
end
_________________________________
Hier hast Du nun also zwei verschieden definierte Requester drin: Einen mit
einem Wordworth-Befehl (WizardReq) und einen mit der Rexxreqtools.library
(rtgetstring).
Gleichzeitig natürlich auch die verschiedenen Möglichkeiten, das Ergebnis 
des Requesters abzufragen: Bei reqtools wird der eingegebene Text sofort 
als Variable übergeben. Welcher Knopf gedrückt wurde, kann über die 
Variable rtresult abgefragt werden. Bei Wordworth steht die Nummer des 
Knopfs in RESULT, und der eingegebene Text ebenfalls, nachdem der Befehl 
Wizard_GetTextBox eingegeben wurde. Dabei die Nummer der Textbox nicht 
vergessen! (hier 1) Es sind nämlich mehrere Textboxen in ein und demselben 
Requester möglich.
Der "Abbruch"-Knopf hat die Nummer "-1" erhalten, da RESULT ebenfalls -1
enthält, wenn das Schließgadget in der linken oberen Ecke betätigt wird. So
haben wir zwei Fliegen mit einer Klappe geschlagen.

****************************************************
5.3.2. rexxtricks.library
Die Rexxtricks.library enthält eine Menge nützlicher Funktionen aus den
folgenden Bereichen:

AmigaDOS-Funktionen
SCSI-Funktionen
Clipboard-Funktionen
Listen-Funktionen
Publicscreen-Funktionen
Icon-Funktionen
Sonstige Funktionen

Diese im einzelnen zu erläutern, würde hier zu weit führen. Aber ich wollte
einmal auf diese Library aufmerksam machen, denn sie kann oft wirklich 
nützlich sein. Lies mal die Anleitung, sie ist ziemlich gut!

****************************************************
5.4. Beispiele für die Vernetzung von Programmen
5.4.1. Beckertext und Wordworth
Das Schöne an ARexx ist ja gerade, daß es auch möglich ist, mehrere 
Programme miteinander zu verknüpfen. Ein kleines Beispiel hatten wir 
bereits in einem früheren Kursteil: Ein Skript, das Miami und YAM startet, 
online geht, Post sendet und abholt und wieder offline geht. Das war 
natürlich relativ simpel.
Beim folgenden Skript kommt immerhin dazu, daß ein bestimmter Text 
irgendwie zwischen zwei Anwendungen ausgetauscht werden soll. Ich habe es 
geschrieben, weil ich früher viel mit Beckertext gearbeitet habe, jetzt 
inzwischen aber Wordworth verwende. Da BT und WW leider kein gemeinsames 
Clipboard verwenden, Wordworth außerdem keinen "Dazuladen"-Befehl kennt, 
war es gar nicht so einfach, das zu realisieren. Eigentlich tut dieses 
Skript nichts anderes, als einen bereits markierten Text aus Beckertext in 
das aktuelle Wordworth-Dokument an der aktuellen Stelle einzufügen. Und so 
sieht das Ganze aus:
_________________________________
/*  BT-Text (markierten Block) in WW5 einsetzen - MJ+HK 17.6.96  */
OPTIONS RESULTS
WwPortName = Address()
GetFont
OldFont = Result
GetFontSize
OldFontSize = Result
Address ('bt3')
kopiere
neudok
einsetzen
'asichern "T:BT"'
schliesse
Address Value WwPortName
New
Address Value Result
Open FILENAME "T:BT"
SelectAll
Font NAME OldFont SIZE OldFontSize
Copy
Close FORCE
Address Value WwPortName
Paste
Address Command delete "T:BT"
_________________________________
Also: Das Skript wird aus Wordworth aufgerufen, sonst ist es nicht möglich, 
das aktuelle Fenster in Wordworth zu bestimmen.
Dann wird festgestellt, welche Schriftart an der aktuellen Stelle 
eingestellt ist, damit auch der neue Text gleich in dieser Schriftart 
erscheint.
Anschließend setze ich den aktuellen Port auf Beckertext. Warum da die 
Klammern nötig sind, weiß ich wirklich nicht. So stehts im Handbuch, und 
nur so funktioniert's auch.
Mit Beckertext ist es nicht möglich, einen Block einzeln abzuspeichern. 
Also: Neues Dokument öffnen, Block hineinkopieren, Dokument als reinen Text
abspeichern. Und jetzt das gleiche rückwärts für Wordworth: Neues Dokument
öffnen, mit der richtigen Schrift formatieren, ins "richtige" Dokument
kopieren, fertig.

****************************************************
5.4.2. Typisch Multitasking...
Als nächstes möchte ich euch noch ein Skript vorstellen, an dem eine Menge
Programme beteiligt sind: Wordworth, GoldEd, Database Pro, YAM. Dieses 
Skript habe ich geschrieben, um die Texte, die ich schreibe, archivieren, 
ausdrucken, im Großdruck für meinen Opa ausdrucken, an Freunde in 
verschiedenen Dateiformaten mailen zu können. Und das alles in einem 
Aufwasch. :)
Selbst wenn Du einige der Programme nicht selbst hast, hoffe ich, daß Du 
den einen oder anderen Kniff brauchen kannst. Schau's Dir mal an.
_________________________________
/* $VER: 1.1. 19.8.97 - 23.1.98*/
options results
Wordworthport=Address()
/*Das Folgende ist eine Zeile*/
wizardreq title "Ansprache versenden" label "Bitte Nummer der Ansprache 
eingeben." textbox 1 "_Nummer:" textbox 2 "In _DB übernehmen (J/N):" 
textbox 3 "_Großdruck erstellen (J/N):" textbox 4 "_Mail verschicken (J/N)" 
textbox 5 "Anzahl N_ormaldrucke:" Button 1 "_Ok" Button "-1" "_Abbruch"
/*bis hier*/
 if result = "-1" then do
            exit
       end

       Wizard_Gettextbox (1)
       Nummer=Right(Result,3,"0")
       Wizard_Gettextbox (2)
       DB=Result

       Wizard_Gettextbox (3)
       Grossdruck=Result

       Wizard_Gettextbox (4)
       Mail=Result

       Wizard_Gettextbox (5)
       Normaldruck=Result

/* bis hierher wird überprüft, welche der Aktionen tatsächlich durchgeführt 
werden sollen. */
/*Meine Ansprachen sind durchnumeriert, und zwar nach dem Schema 
002.Beschreibung */
if Normaldruck="J" then Normaldruck=1
if Normaldruck>0 then do
   SAVEAS NAME "Text:Wordworth7/Dokumente/Ansprachen/000.TEMP"
end
/*Wenn ein Ausdruck in der "Normalform" gewünscht ist, muß die Datei 
zwischengespeichert werden.*/
/*Den tatsächlichen Namen des Textes kann man mit Wordworth leider nicht 
herausfinden.*/
 if DB="J" then do
    if ~show("P",DataBase) then address command "run Text:DBProV3.1/db"
 end
if Mail="J" then do
   'SAVEAS RTF Name T:Ansprache.rtf'
   'SAVEAS WORDPERFECT Name T:Ansprache.wpf'
   if ~show("P",YAM) then address command "run Yam:Yam"
end
/*Hier werden die jeweils benötigten Programme gestartet:*/
/*DBPRo, falls eine Aufnahme in die Datei gewünscht ist,*/
/*und YAM, falls die Ansprachen per EMail verschickt werden sollen.*/

address command
   if ~Exists("Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz") 
then do
/*Das Folgende ist eine Zeile*/
   "echo > Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz"  
'"Ansprache Nr. '||Nummer||'"'
/*bis hier*/
   "echo >> Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz" '"Text: 
"'
   "echo >> Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz" 
'"Datum: "'
   "echo >> Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz" '"Ort: 
"'
   "echo >> Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz" 
'"Stichworte: "'
   "echo >> Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz" 
'"Beschreibung: "'
    end
/*Hier gebe ich mir selbst ein kleines Formular für eine Kurzbeschreibung 
vor.*/
/*Der doppelte Pfeil nach echo bewirkt, daß der Text an die bestehende 
Datei*/
/*angehängt wird.*/
/*Ein Teil davon wird in der Datenbank weiterverwendet, die ganze Datei 
auf*/
/*jeden Fall mit der entsprechenden Nummer und dem Anhängsel .kurz 
abgespeichert.*/

"ged Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".kurz sticky"
/*GoldEd wird gestartet, damit ich meine Kurzbeschreibung bearbeiten 
kann.*/
/*Die Option sticky bewirkt, daß das Skript erst dann weiterläuft, wenn 
ich*/
/*GoldEd wieder beendet habe.*/
if Mail="J" then do
   if ~show("P",GOLDED.1) then address command ged
   "sys:rexxc/Waitforport GOLDED.1"
   address GOLDED.1
   Lock current release 4
   'open t:Ansprache.rtf'
   replace string "ä" by "'8a" all quiet
   replace string "ö" by "'9a" all quiet
   replace string "ü" by "'9f" all quiet
   replace string "ß" by "'a7" all quiet
   unlock
   'save all nolf exit'
/* Was soll das nur schon wieder sein? Hier ersetze ich alle ä,ö,ü,ß*/
/* durch die entsprechenden Codierungen, wie sie im RTF-Format eigentlich*/
/* verwendet werden - nur Wordworth macht das leider nicht. Zumindest*/
/* WW6 nicht - ich habe WW7 darauf noch nicht überprüft.*/
   address command
   'echo >t:Ansprachemailtext "Hallo!"'
   'echo >>t:Ansprachemailtext "Anbei eine Ansprache von mir."'
   'echo >>t:Ansprachemailtext "Viele Grüße"'
   'echo >>t:Ansprachemailtext'
   'echo >>t:Ansprachemailtext "Heiko"'
   'echo >>t:Ansprachemailtext "Hier die Kurzfassung:"'
/*Das Folgende ist eine Zeile*/
   'join t:Ansprachemailtext 
Text:Wordworth7/Dokumente/Ansprachen/'||Nummer||'.kurz to 
t:Ansprachemailtext2'
/*bis hier*/
   "sys:rexxc/Waitforport YAM"
   address YAM
   mailwrite
 /*  writemailto "Tscho"
   "writesubject Ansprache_von_Heiko"
   "writeletter t:Ansprachemailtext2"
   writequeue
   mailwrite*/
   writemailto "ThoVo"
   "writesubject Ansprache_von_Heiko"
   "writeletter t:Ansprachemailtext2"
   "writeattach t:Ansprache.rtf"
   writequeue
   mailwrite
   writemailto "Reinhard"
   "writesubject Ansprache_von_Heiko"
   "writeletter t:Ansprachemailtext2"
   "writeattach t:Ansprache.wpf"
   writequeue
end
/*OK, jetzt werden die Dateien verschickt. Einmal nur die 
Kurzbeschreibung,*/
/*einmal als RTF-Datei, einmal als WordPerfect-Datei.*/
if DB="J" then do
   address DataBase
   GETFILENAME
   if Result=0 then do
       SAVE
   end
   'OPEN Text:DBProV3.1/Aufsätze/Aufsätze.db'
   'DEMARKRANGE $F1 "#?"'
   'SHOW ALL'

   'SETSEARCH FIELD PART'

   'SEARCHFIELD $F1'
   'SEARCH eig. Anspr.'
   'SEARCHFIELD $F2'
   'SETSEARCH GREATER'
   'SEARCHNEXT ' Nummer
   if RC=0 then do
     GETDATA $F1
     IF RESULT="EIG. Anspr." THEN DO
       SCHONDA=1
     END
   END
/* Hier wird in DBPro erstmal überprüft, ob nicht schon ein Eintrag für*/
/* diese Ansprache vorhanden ist. Ein neuer wird nur gemacht, wenn diese*/
/* Nummer nicht gefunden wurde. (SCHONDA=0)*/
   IF SCHONDA ~=1 THEN DO
      'ADD'
      'PUTDATA $F1 eig. Anspr.'
      'PUTDATA $F2' NUMMER
      'PUTDATA $F3 Kuschel, H.'
/*Das Folgende ist eine Zeile*/
      
Erfolg=OPEN("Kurzdatei","Text:Wordworth7/Dokumente/Ansprachen/"||Nummer||".
kurz","R")
/*bis hier*/
      If Erfolg then do
         Do while ~EOF("Kurzdatei")
            Zeile=Readln("Kurzdatei")
            Select
               when abbrev(Zeile,"Text")=1 then do
                 'PUTDATA $F4 'substr(Zeile,7)
               end
               when abbrev(Zeile,"Datum")=1 then do
                 DatumOrt=substr(Zeile,8)
               end
               when abbrev(Zeile,"Ort")=1 then do
                 DatumOrt=DatumOrt||", "||substr(Zeile,6)
                 'PUTDATA $F7 'DatumOrt
                 end
               when abbrev(Zeile,"Stichworte")=1 then do
                 'PUTDATA $F12 'substr(Zeile,13)
               end
               Otherwise do
                 NOP
               end
            end
         end
      end
/* Jetzt werden die Daten in die einzelnen Felder meiner Datei 
geschrieben:*/
/* $F1 ist der Oberbegriff, $F2 die Nummer, $F3 der Autor. Alles andere*/
/* lese ich aus der Kurzdatei, die ich vorhin angelegt habe. Das wird 
dann*/
/* automatisch an die richtige Stelle geschrieben.*/

      'SORT $F1 $F2'
      'SAVE'
   end
end
/*Sortieren, speichern, Ende.*/
if Grossdruck = "J" then do
  address value Wordworthport
  SAVEAS NAME "Text:Wordworth7/Dokumente/Ansprachen/000.GROSSDRUCK"
  DOCUMENT A4 "2cm" "2cm" "1.67cm" "2.54cm" 1 "2cm" LANDSCAPEOFF
  CTRLDOWN
  CURSOR UP
  SHIFTDOWN
  CURSOR DOWN
  FONT SIZE "24pt"
  PARAGRAPH 0 0 0 FULL AUTO ONEHALF
  PRINTOPTIONS REVERSE BLACKANDWHITE ODDANDEVENPAGES
  SAVE
  PRINT
end
/*Großdruck, falls gewünscht. Das Dokumentformat muß geändert werden,*/
/*weil ich normalerweise DinA4 quer zweispaltig bevorzuge.*/
/*Durch den ganzen Sermon mit CTRLDOWN etc. wird der gesamte Text*/
/*markiert. Dann stelle ich die Schriftgröße 24pt. ein, ein geeignetes*/
/*Absatzformat, und ab in den Drucker damit. */
If Normaldruck>0 then do
 address value Wordworthport
 OPEN FILENAME "Text:Wordworth7/Dokumente/Ansprachen/000.TEMP" FORCE
 PRINTOPTIONS REVERSE BLACKANDWHITE COLLATE COPIES NORMALDRUCK 
ODDANDEVENPAGES
 PRINT
end
/*Die "normale" Druckvariante kommt nach dem Großdruck, weil sie viel 
länger*/
/*dauert. Querformat ist ziemlich langsam mit Wordworth. :( */
/*Beachte bei PRINTOPTIONS, daß eine initialisierte Variable drin ist!*/
/*An einer Stelle steht NORMALDRUCK. In dieser Variable ist gespeichert,*/
/*wie viele Ausdrucke ich davon haben will.*/
address command
If Mail="J" then do
"delete >NIL: t:Ansprache.rtf"
"delete >NIL: t:Ansprachemailtex#?"
"delete >NIL:  t:Ansprache.wpf"
If Normaldruck>0 then do
"delete >NIL: Text:Wordworth7/Dokumente/Ansprachen/000.TEMP"
END
/*Ein bißchen aufräumen muß sein. :)  */
_________________________________
So, das war ein ziemlich langes Programm. Viele weitere Programme, oft auch
kommentierte, findest Du im Aminet, im Verzeichnis util/rexx. Schau Dich 
ruhig einmal um. Evtl. findest Du dort auch schon das, was Du gerade 
schreiben wolltest... oder auf jeden Fall gute Anregungen fürs eigene 
Programmieren.

****************************************************
5.5. Das Ende
Das war der ARexx-Kurs. Geschafft. Ich hoffe, Du hattest Spaß daran, und 
ich konnte das meiste halbwegs verständlich erklären. Wenn Du Probleme 
haben solltest, wende Dich an meine Adresse.
Ich möchte demnächst den ganzen Kurs ins AmigaGuide-Format umwandeln und 
dann im Aminet veröffentlichen. Er wird voraussichtlich veröffentlicht 
unter docs/help/ARexx-Kurs.lha Da ich dabei ein paar AGuide-Kniffe einbauen 
will, bräuchte ich jemanden, der/die diesen Guide unter AmigaOS 2.x testet. 
Ich weiß nämlich nicht, wie es da funktioniert. Außerdem suche ich Leute, 
die mir ein paar Kurzinformationen zu anderen Texteditoren als GoldEd geben 
können, damit ich auch diese Editoren berücksichtigen kann.
Solltest Du Dich hier irgendwo angesprochen fühlen, melde Dich doch bitte 
mal bei mir. Danke!

Heiko«