← ST-Computer 04 / 1990

Wir lassen drucken

Programmierpraxis

Nicht immer ist der gesamte Bildschirminhalt für eine Hardcopy interessant. Oft würde es genügen, nur den Inhalt der aktuellen Dialogbox auf dem Drucker wiederzugeben. Auf den altbekannten Desktop-Hintergrund kann man ja bei der Ausgabe verzichten. PRINTBOX erweitert die im ATARI ST eingebaute Hardcopy-Routine um diese Möglichkeit.

Eigentlich hatte ich mir die Programmierung einer erweiterten Hardcopy-Routine recht einfach vorgestellt. Das war sie im Prinzip auch, die Tücke steckte jedoch in der vom Betriebssystem zur Verfügung gestellten PRTBLK-Funktion des XBIOS. Mit ihrer Hilfe sollte es möglich sein, einen beliebigen Bildschirmausschnitt auf dem Drucker auszugeben. Dazu muß PRTBLK mit einem Parameterblock versehen werden, der folgenden Aufbau hat:

   
long blkprt Startadresse des auszudruckenden Ausschnitts
int offset Offset relativ zur Startadresse
int width Breite des Ausschnitts in Pixeln
int height Höhe des Ausschnitts in Pixeln
int left linker Rand in Pixeln
int right rechter Rand in Pixeln
int scrrez Bildschirmauflösung
int prrez Druckerauflösung
int colpal Pointer auf Farbpaiette
int type Druckertyp (ATARI/Epson)
int port Drucker-Port (parallel = 0, seriell = 1)
long mask Pointer auf Halbtonmaske

Wie man sieht, bietet die PRTBLK-Funktion vielfältige Möglichkeiten. Wichtig ist, daß die Summe von “width”, “left” und “right” die Anzahl der Pixel pro Rasterzeile in der aktuellen Auflösung ergibt. Andernfalls erinnert der Bildschirmausdruck an gewisse Richtungen moderner Kunst: Was es sein soll, kann niemand so recht sagen. Die Druckerauflösung entspricht der “Qualität”-Einstellung in der Druckeranpassung. Als Farbpalette benutzt PRINTBOX die aktuelle Farbpalette ab SFF8240. So weit gab es mit den Parametern keine Probleme. Allerdings war da noch die sogenannte “Halbtonmaske”..

Welche Aufgabe diese Maske genau erfüllt, konnte ich anhand der mir zur Verfügung stehenden Literatur nicht ermitteln, da die PRTBLK-Funktion stets nur sehr unzureichend beschrieben ist. Vermutlich hat die Halbtonmaske etwas mit der Umsetzung der Bildschirmfarben auf den Druckertyp zu tun. Gibt man hier einen Null-Pointer vor, wählt das XBIOS automatisch eine im System definierte Default-Halbtonmaske aus. Das sollte mir bei der Programmierung gerade recht sein, so daß ich in der ersten Programmversion mit dieser Default-Maske arbeitete. Leider mußte ich feststellen, daß die Ausdrucke zwar die gewünschte Dialogbox darstellten, daß jedoch der rechte Rand der Box oft nur unvollständig vorhanden war (siehe Ausdruck 1). Es hatte den Anschein, als ob die Druckerausgabe innerhalb einer Zeile nach einer gewissen Anzahl nicht gesetzter Pixel einfach abgebrochen wurde. Ob hier ein Fall falsch verstandener Optimierung des Ausdrucks vorliegt? Ein plausibler Grund für einen vorzeitigen Abbruch der Druckzeile war jedenfalls nicht vorhanden. Ein Blick ins ROM-Listing (ATARI ST intern) sollte da eigentlich weiterhelfen. Das einzige, was es dort jedoch zu sehen gab, waren viele überflüssige Assembler-Befehle in undurchsichtigen Befehlssequenzen. Fazit: Ein C-Compiler hatte wieder einmal zugeschlagen. Dennoch war zu erkennen, daß es einen Unterschied bezüglich der Druckbreite macht, wenn man statt der Default-Halbtonmaske eine eigene Komposition verwendet. Deshalb gab ich PRTBLK eine Maske mit auf den Weg, die keinen Unterschied zur Default-Maske aufweist. Halt, fast hätte ich es vergessen: Ein Unterschied kam doch zum Vorschein. Nun war die Hardcopy nämlich fehlerfrei (siehe Ausdruck 2). Welchen Sinn es macht, daß die interne Halbtonmaske anders behandelt wird als eine eigens erstellte, auch wenn beide Masken gleich aufgebaut sind, konnte ich nicht klären. Vielleicht ist hier ein Leser fündig geworden.

Soweit meine Ergüsse zum Thema “Halbtonmaske”. Der eigentliche Programmablauf sieht nun folgendermaßen aus:

Ausdruck 1
Ausdruck 2

Bei jedem form_dial-Aufruf überprüft PRINTBOX, ob Bildschirmspeicher für eine Dialogbox reserviert werden soll. Ist dies der Fall, merkt sich das Programm die Koordinaten sowie Breite und Höhe der Box in ihrer größten Größe. Wird die Tastenkombination SHIFT/ALTERNATE/HELP betätigt, und ist eine Dialogbox auf dem Bildschirm vorhanden, holt sich PRINTBOX die aktuelle Druckereinstellung und ruft anschließend PRTBLK auf, um eine Hardcopy der Box zu machen. Befindet sich keine Box auf dem Bildschirm, geschieht nichts.

Nun noch ein paar Worte zu den vom Programm geänderten Systemvektoren. Die Werte der alten Vektoren merkt sich PRINTBOX innerhalb einer sogenannten XBRA-Struktur. Speziell bei residenten Programmen können sich auf diese Weise installierte Programme leicht wieder aus einer Vektorkette ausklinken oder erkennen, ob sie bereits installiert sind. Voraussetzung ist jedoch, daß jedes Programm für veränderte Systemvektoren eine XBRA-Struktur zur Verfügung stellt. Nähere Informationen hierzu finden sich im ATARI ST Profibuch (SYBEX-Verlag).

Soweit die wichtigsten Erläuterungen zum Programm. Abschließend noch ein Hinweis für die Besitzer von 24-Nadeldruckern. Möglicherweise gibt es bei diesen Druk-kern Schwierigkeiten beim Ausdruck. Da der ST Hardcopies auf 24-Nadeldruckern nicht vernünftig unterstützt, geschieht ein Bildschirmausdruck normalerweise über ein spezielles Druckprogramm. Damit PRINTBOX seine Aufgabe erfüllen kann, muß der geladene 24-Nadeltreiber nicht nur in der Lage sein, eine Hardcopy des gesamten Bildschirms zu machen, sondern er muß zusätzlich die PRTBLK-Funktion des XBIOS unterstützen. Dieses dürfte jedoch nicht bei allen Treibern der Fall sein.

************************** * PRINTBOX V1.00 * * (C) 1988 by Uwe Seimet * * Buchenlochstrasse 29 * * 6750 Kaiserslautern * ************************** GEMDOS = 1 PTERMRES= $31 MSHRINK = $4a XBIOS = 14 SETPRT = 33 PRTBLK = 36 SUPEXEC = 38 sshiftmd = $44c _v_bas_ad= $44e _dumpflg = $4ee _sysbase = $4f2 dump_vec = $502 text move.l sp,a0 move.l 4(a0),a0 ;Pointer auf Basepage move.l 12(a0),a6 ;Länge des TEXT-Segments add.l 28(a0),a6 ;Länge des BSS-Segments lea $100(a6),a6 ;Länge der Basepage pea setvec(pc) move #SUPEXEC,-(sp) trap #XBIOS ;neue Systemvektoren setzen addq.l #6,sp clr -(sp) move.l a6,-(sp) move #PTERMRES,-(sp) trap #GEMDOS ;zurück zum Desktop setvec: move.l _sysbase,a0 ;Pointer auf Systemheader cmp #$0102,2(a0) ;altes TOS? bcs.s oldtos ;ja- move 38(a0),shift ;Adresse der kbshift-Variablen ab TOS 1.2 oldtos: move.l $088,gem-4 move.l #gem,$088 move.l dump_vec,hardcopy-4 move.l #hardcopy,dump_vec rts dc.b "XBRA" dc.b "PBOX" ;Programmkennung für XBRA dc.l 0 gem: cmp #$c8,d0 ;AES-Aufruf? bne.s oldgem ;nein- move.l d1,a0 ;Pointer auf AES-Arrays move.l (a0),a1 ;Pointer auf CONTROL-Array cmp #51,(a1) ;form_dial? bne.s oldgem ;nein— move.l 8(a0),a1 ;Pointer auf INTIN-Array tst (a1) ;Bildschirm reservieren? beq.s reserve ;ja_ cmp #3,(a1) ;Bildschirm freigeben? bne.s oldgem ;nein- clr.l width bra.s oldgem reserve:move.l 10(a1),xy ;Koordinaten der Dialogbox move.l 14(a1),width ;Breite und Höhe oldgem: move.l gem-4(pc),a0 jmp (a0) ;weiter im GEM dc.b "XBRA" dc.b "PBOX" ;Programmkennung für XBRA dc.l 0 hardcopy: move shift(pc),a0 move.b (a0),d0 ;Status der Shift-Tasten and.b #3,d0 ;Shift-Taste gedrückt? bne.s boxcopy ;ja- move.l hardcopy-4(pc),a0 jmp (a0) ;zur alten HC-Routine boxcopy:tst.l width ;Dialogbox vorhanden? beq nocopy ;nein- move #-1,-(sp) move #SETPRT,-(sp) trap #XBIOS ;Druckerkonfiguration holen addq.l #4,sp move d0,d1 lsr #3,d1 and #1,d1 move d1,prrez ;Druckerauflösung move d0,d1 lsr #4,d1 and #1,d1 move d1,port ;Druckerport lea prtypes(pc),a0 and #7,d0 move.b (aO,d0),d0 move d0,type ;Druckertyp move d7,-(sp) clr d7 move.b sshiftmd,d7 move d7,scrrez ;Bildschirmauflösung move xy,d0 move d0,left ;linke Ausschnittsbegrenzung add width,d0 move #320,d1 ;320 Pixel pro Zeile annehmen tst d7 ;niedrige Auflösung? beq *+4 ;ja- add d1,d1 ;sonst 640 Pixel pro Zeile sub d0,d1 move d1,right ;rechte Ausschnittsbegrenzung move xy+2,d0 ;y-Koordinate der Box cmp #2,d7 ;hohe Auflösung7 beq *+4 ;ja- add d0,d0 ;160 Bytes pro Pixelzeile mulu #80,d0 moveq #0,d1 move xy,d1 ;x-Koordinate divu #16,d1 ;Wort für x-Koordinate + 16-Bit-Offset moveq #4,d2 lsr d7,d2 ;ergibt Anzahl der Planes asl d2,d1 ;ergibt Byte für x-Koordinate add d1,d0 clr d1 swap d1 ;16-Bit-Offset divu #8,d1 ;auf 8 Bit umrechnen add d1,d0 swap d1 move d1,offset add.l _v_bas_ad,d0 move.l d0,blkprt ;Startadresse d. Ausschnitts move.l #$ff8240,colpal ;Zeiger auf Farbpalette move.l #pmask,mask ;Zeiger auf Halbtonmaske move (sp)+,d7 pea defptr move #PRTBLK,-(sp) move #1,_dumpflg trap #XBIOS ;Hardcopy starten move #-1,_dumpflg addq.l #6, sp nocopy: rts shift: dc.w $e1b ;Adresse von kbshift f.altes TOS prtypes:dc.b 0,2,1,-1,3,-1,-1,-1 ;Tabelle der Druckertypen *Tabelle der Halbtonmasken pmask: dc.b $0f,$0f,$0d,$06,$09,$06,$08,$06 dc.b $08,$02,$08,$00,$08,$00,$08,$00 dc.b $00,$00 bss defptr: blkprt: ds.l 1 ;Start des auszudruckenden Ausschnitts offset: ds.w 1 ;Offset für bis zu 7 Bits width: ds.w 1 ;Breite des Ausschnitts in Punkten height: ds.w 1 ;Höhe des Ausschnitts in Punkten left: ds.w 1 ;linker Rand in Punkten right: ds.w 1 ;rechter Rand in Punkten scrrez: ds.w 1 ;Bildschirmauflösung prrez: ds.w 1 ;Druckerauflösung colpal: ds.l 1 ;Pointer auf Farbpalette type: ds.w 1 ;Druckertyp port: ds.w 1 ;Druckerport mask: ds.l 1 ;Pointer auf Halbtonmasken xy: ds.w 2 ;x und y Koordinate der Dialogbox
Uwe Seimet