Viele Textverarbeitungen haben ein Feature namens Autosave: In gewissen Zeitabständen wird der eingegebene Text automatisch gesichert, um bei Systemabstürzen möglichst wenig Verlust zu haben. Wordplus fehlt, wie so vieles mehr, diese Möglichkeit, das kleine Accessory AUTOSAVE setzt auf Wordplus auf und übernimmt diese Funktion.
Wenn Sie in Wordplus arbeiten und einen Text geöffnet haben, können Sie durch Aufruf des Accessories und Auswahl von “AN” den Autosave aktivieren (Bild 1). Alle fünf Minuten (Voreinstellung) wird Wordplus zur Durchführung von “Speichern & weiter” veranlaßt. Der gerade bearbeitete Text wird dann auf Platte oder Diskette geschrieben und ist somit bei Abstürzen gerettet. Während des Sicherns wird die Texteingabe unterbrochen und die “busy bee” erscheint. Zeichen gehen dabei nicht verloren; sie werden gepuffert.
Ein erneuter Aufruf von AUTOSAVE ergibt eine etwas andere Alertbox (Bild 2). Sie zeigt den Zeitabstand zwischen den Sicherungsvorgängen an, der in Minutenschritten erhöht bzw. erniedrigt werden kann. Der kürzeste Abstand ist eine Minute. Mit “AUS” wird AUTOSAVE abgeschaltet.
Ist AUTOSAVE aktiviert, wenn Wordplus nicht geladen ist, erscheint beim Versuch, Wordplus zum Sichern zu veranlassen, eine Alertbox (Bild 3), und AUTOSAVE wird automatisch abgeschaltet, um das System nicht unnötig zu belasten.
Leider gibt es einige Fehler im GEM und eine schlecht programmierte Stelle in Wordplus, die Einschränkungen im Umgang mit AUTOSAVE erfordern. Der GEM-Fehler besteht darin, daß das System dem Accessory auch dann meldet, Wordplus wäre geladen, wenn dies garnicht der Fall ist. Dieser Bug tritt immer dann auf, wenn das letzte gelaufene Programm die Textverarbeitung war, und kein anderes in der Zwischenzeit gestartet wurde. Wordplus reagiert leider auch dann auf den “Speichern & weiter”- Aufruf, wenn kein Dokument geöffnet ist (Der entsprechende Menüeintrag wird dann deaktiviert; anscheinend kamen die Programmierer nicht auf die Idee, daß eines Tages ein anderes Programm Funktionen aufrufen würde, und fangen dies nicht ab). Wordplus versucht dann einen nicht vorhandenen Text zu sichern, kommt mit der Speicherverwaltung durcheinander und erzeugt einen Busfehler, der wiederum einen Systemabsturz mit Neubooten auslöst.
Da sich diese Fehler nicht von AUTOSAVE aus verhindern lassen, dürfen Sie das Accessory nur dann benutzen, wenn Wordplus geladen und mindestens ein Dokument geöffnet ist. Ärgerlich, aber nicht zu ändern.
Das in Modula-2 geschriebene Programm ist im Listing abgedruckt. Beim Link-Vorgang muß, da es sich um ein Accessory handelt, die Option “QUERY” eingeschaltet und für “GEMX.LNK” das Linkmodul -GEMACCX.LNK” ausgewählt werden. Die Option "OPT” sollte auch eingesetzt werden, damit das Accessory nur ca. 3,5 KByte belegt.
Die Autosave-Funktion wird ermöglicht, indem an Wordplus eine Mitteilung geschickt wird, laut der der Eintrag "Speichern & weiter” im "File”-Menü ausgewählt wurde. Normalerweise verschickt nur GEM solche Mitteilungen, mit der “Appl-Write”-Funktion kann das aber jede Applikation. Dazu muß zunächst mit “ApplFind " die Applikations-Kennzahl von Wordplus ermittelt werden, damit der Empfänger der Nachricht benannt werden kann. “ApplFind” hat den oben beschriebenen Fehler, nicht immer -1 zu liefern, wenn das gesuchte Programm nicht im Speicher steht. Die Mitteilung wird wie eine Standardmessage zusammengestellt und im Gerten und fünften Wert die Indizes des ausgewählten Menütitels und -eintrags abgelegt. Diese Werte sind in dem Programm für die Version 2.02 von Wordplus enthalten (Prozedur “Init”). Wenn Sie eine andere Version benutzen, müssen Sie mit einem Resource-Construction-Set an den Titel “File” und den Eintrag “Sichern & weiter” einen Namen vergeben und die Resource speichern. Aus dem dann erzeugten Headerfile lassen sich die Indizes auslesen. Wenn Sie den Umgang mit einem RCS nicht gewohnt sind, sollten Sie sich von einem “Experten” helfen lassen.
Durch einen “EventMultiple” wird bei eingeschaltetem AUTOSAVE auch auf ein Timer-Ereignis gewartet, das dann den Sicherungsvorgang auslöst. Auch hier soll es einen GEM-Bug geben, durch den der Timerevent bei Accessories nicht immer funktioniert. Allerdings konnte ich dies noch nicht beobachten. Bei einem Mitteilungs-Ereignis werden die Alerts ausgeführt, durch die AUTOSAVE ein-und ausgeschaltet sowie das Sicherungsintervall verändert wird.
Aufbauend auf das gleiche Schema kann : man z.B. ein Autosave für andere Programme schreiben oder andere Funktionen “fernsteuern". Die Möglichkeiten sind dabei praktisch unbegrenzt.
MODULE AutoSave ;
(*$A+*) (* optimieren *)
FROM M2Conversions IMPORT ConvertCardinal ;
FROM Strings IMPORT String, Concat ;
FROM SYSTEM IMPORT ADR ;
FROM GEMAESbase IMPORT AccessoryOpen, MenuSelected, MesageEvent, TimerEvent ;
FROM AESApplications IMPORT ApplInitialise, ApplFind, ApplWrite ;
FROM AESEvents IMPORT EventMultiple ;
FROM AESForms IMPORT FormAlert ;
FROM AESMenus IMPORT MenuRegister ;
CONST
WORDPLUSVERSION = 2.02 ;
OnAlert = '[2][Autosave für Wordplus! by Robert Tolksdorf][AN|ABBRUCH]';
OffAlert1 = ' [2] [Autosave für Wordplus| by Robert Tolksdorf|Intervall:' ;
OffAlert2 = ' Min] [+1 Min|-1 Min|AUS]';
SetOff1 = '[3][Autosave für Wordplus! by Robert Tolksdorf!';
SetOff2 = 'Autosave ausgeschaltet,|da nicht mehr in WORDPLUS][OK]';
AMinute = 60000 ; (* eine Minute = 60000 ms *)
VAR ApplID, AccID, WordPlusID : INTEGER;
MessBuffer : ARRAY [0..7] OF CARDINAL ;
SichernUndWeiterlndex, Fileindex ; CARDINAL ;
Saveinterval : LONGCARD;
dummy, AwaitedEvents, Event : INTEGER;
Alert : ARRAY [0..132] OF CHAR;
Interval : String;
PROCEDURE Init;
BEGIN
IF WORDPLUSVERSION = 2.02 THEN
SichernUndWeiterIndex:=28;
Fileindex:=4;
END;
(* hier andere Versionen einsetzen: IF WORDPLUSVERSION = ... *)
AwaitedEvents:=MesageEvent; (* ausgeschaltet *)
Saveinterval :=5*AMinute; (* auf 5 Min voreinstellen *)
END Init;
BEGIN
Init ; (* Initialisieren *)
ApplID:=ApplInitialis (* Applikation anmelden *)
AccID:=MenuRegister(ApplID,' AutoSave'); (* ACC anmelden *)
LOOP
Event:=EventMultiple(AwaitedEvents,0,0,0,0,0,0,0,0,0,0,0,0,0,
ADR(MessBuffer),
INTEGER(Saveinterval MOD 10000H),
INTEGER(Saveinterval DIV 10000H),
dummy,dummy,dummy,dummy,dummy,dummy);
IF (4 IN BITSET(Event)) AND (MessBuffer[0]=AccessoryOpen)
THEN
IF AwaitedEvents=MesageEvent THEN (* Messageevent *)
IF FormAlert(1,OnAlert)=1 THEN (* ist ausgeschaltet *)
AwaitedEvents:=MesageEvent+TimerEvent; (* einschalten *)
END;
ELSE
ConvertCardinal(CARDINAL(Saveinterval DIV
AMinute),3,Interval);
Concat(OffAlert1,Interval,Alert); (* Intervall einfügen *)
Concat(Alert,OffAlert2,Alert);
CASE FormAlert(3,Alert) OF
1: Saveinterval:=SaveInterval+AMinute; (* + 1 Min *)
| 2: IF SaveInterval>AMinute THEN
SaveInterval:=SaveInterval-AMinute; (* -1 Min *)
END;
| 3: AwaitedEvents:=MesageEvent; (* ausschalten *)
END;
END;
END;
IF 5 IN BITSET(Event) THEN (* Timerevent *)
WordPlusID:=ApplFind('WORDPLUS'); (* ID holen *)
IF WordPlusID#-l THEN
MessBuffer[0]:=MenuSelected; (* Message zusammenbauen *)
MessBuffer[1]:=ApplID;
MessBuffer[2]:=0;
MessBuffer[3]:=FileIndex;
MessBuffer[4]:=SichernUndWeiterIndex;
MessBuffer[5]:=0; MessBuffer[6] :=0; MessBuffer[7]:=0;
ApplWrite(WordPlusID,16,ADR(MessBuffer)); (* Message schicken *)
ELSE
AwaitedEvents:=MesageEvent; (* nicht geladen *)
Concat(SetOff1,SetOff2,Alert); dummy:=FormAlert(1,Alert);
END;
END;
END; (* und von vorne ... *)
END AutoSave.