Wir lassen drucken

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
Aus: ST-Computer 04 / 1990, Seite 94

Links

Copyright-Bestimmungen: siehe Über diese Seite