home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 09_10 / tricks / ljdrv.txt < prev    next >
Encoding:
Text File  |  1990-10-08  |  18.3 KB  |  384 lines

  1. Deutsch kompatibel
  2.  
  3. Bei den einfacheren und auch billigeren Laserdruckern heißt es zwar, daß sie 
  4. HP-LaserJet-kompatibel sind, allerdings ist es Ansichtssache, wo die 
  5. Kompatibilität beginnt und wo sie endet. 
  6.  
  7. Bei meinem Laserdrucker ist es jedenfalls so, daß er alles kann, was auch das 
  8. Original verspricht, nur bei den deutschen Sonderzeichen hapert es. Entweder 
  9. muß ich in den nicht IBM-kompatiblen Epson-Modus umschalten - geht auch nur 
  10. manuell - oder in den Diablo-Modus - kann auch keine IBM-Zeichen - oder ich 
  11. besorge mir für ein paar Mark Fünfzig eine FontCard, die dann das liefert, 
  12. was nicht mehr ins EPROM gebrannt worden ist. 
  13.  
  14. Ich bin zwar geneigt, für so etwas Geld auszugeben, wenn ich unbedingt eine 
  15. 3D-Schattenschrift mit Farbausgabeoption brauche, aber nur um die - bis auf 
  16. Amtsschreiben - bei uns üblichen Umlaute und das scharfe "ß" auf den Drucker 
  17. zu bringen wieder ein paar Mark auf den Tisch legen zu müssen - nein Danke. 
  18.  
  19. Glücklicherweise gibt es in DOS die Möglichkeit, Fehler in gewissem Umfang 
  20. ausbügeln zu können. Was liegt also näher, als das obige Manko der Hardware 
  21. durch Software auszugleichen. 
  22.  
  23.  
  24. Und es gibt sie doch
  25.  
  26.  
  27. Wer die Zeichensatztabellen des HP-LaserJet und von DOS vergleicht, stellt 
  28. schnell fest, daß eigentlich alle Zeichen, die benötigt werden vorhanden sind. 
  29. Nur haben die Zeichenjongleure bei IBM alle Zeichen ab dem Wert 80h/128d mit 
  30. entsprechenden Symbolen aufgefüllt, während bei Hewlett-Packard im Zeichensatz 
  31. Roman 8, der hier zur Verfügung steht, der Bereich zwischen 80h/128d und 
  32. 9Fh/159d ausgespart ist. Der im Original von HP verwendete Zeichensatz PC-8 
  33. steht hier nicht zur Verfügung ( siehe oben ). Ab dem Wert A0h/160d sind dann 
  34. auf einmal wieder alle möglichen internationalen Zeichen im HP-Zeichensatz 
  35. vorhanden - auch die benötigten deutschen.
  36.  
  37. Was liegt also näher als eine Routine zu schreiben, die die Zeichensätze 
  38. anpaßt, das heißt das jeweilige IBM-Zeichen in das entsprechende HP-Zeichen 
  39. umwandelt, bevor das Zeichen an den Drucker abgeht. 
  40.  
  41. Zum Glück gibt es im Befehlssatz der 80x86-Familie einen einfachen Befehl, 
  42. der diese Umsetzerei von alleine erledigt ( XLAT ). Die größte Fleißarbeit 
  43. besteht nur darin, die Zeichen in einer Tabelle mit ihrem Equivalenz 
  44. zusammenzustellen - und weil's so schön ist, habe ich gleich alle 256 
  45. Möglichkeiten erfaßt, die in einem Byte unterzubringen sind. Jetzt muß die 
  46. Software nur noch "Hier" rufen, wenn sie gemeint ist. 
  47.  
  48.  
  49. Da der Interrupt 17h/23d für die Ausgabe auf den Drucker via Parallelport 
  50. zuständig ist, muß sich die Software also hier zwischenschalten. Von den 
  51. möglichen Optionen dieses Interrupts interessiert nur die Ausgabe von Zeichen 
  52. an den Drucker ( AH = 0 ). Fordert der Interrupt diese Aufgabe, fühlt sich
  53. die kleine Routine angesprochen und ersetzt das an den Drucker zu sendende 
  54. Byte durch das in der Tabelle. Danach geht es bei der alten Interruptroutine 
  55. weiter als ob nichts geschehen wäre. 
  56.  
  57. Im Prinzip wär's das schon, wenn da nicht in der Praxis wieder ein paar 
  58. Problemchen aufkämen. 
  59.  
  60. Wenn Sie mit dem eingehängten Treiber Grafikbytes oder Fonts an den Drucker 
  61. senden, übersetzt der Treiber natürlich treu-doof genauso wie bei ÄÖÜ. Um 
  62. diesem Übel zu begegnen, habe ich über die Aufrufparameter 
  63. D(isable) = deaktivieren und E(nable) = aktivieren die Möglichkeit eingebaut, 
  64. den Treiber von der DOS-Ebene aus steuern zu können.
  65.  
  66.  
  67. Is' er nu' da oder nich'
  68.  
  69.  
  70. Zwangsläufig verliert man irgendwann den Überblick, ob der Treiber nun aktiv 
  71. ist oder nicht - spätestens, wenn das Telefon geläutet hat. Also gibt es 
  72. einen weiteren Parameter, der einen darüber I(nformiert).
  73.  
  74. Wenn man gar nicht mehr weiß, wie das ganze zu bedienen ist - "?" für die 
  75. Ausgabe eines Hilfetextes eingeben. Und damit sich der Treiber nun selbst 
  76. noch auskennt - S(et) = Treiber laden und resident im Speicher lassen und 
  77. R(eset) = Treiber wieder aus dem Speicher entfernen. 
  78.  
  79. Eigentlich wär's das nun wirklich, und der im Speicher belegte Platz benötigt 
  80. auch nur ca. 300 Bytes - doch da war noch etwas.
  81.  
  82. Wie kann ich aus meinem Applikationsprogramm, das außer ein paar Fonts und 
  83. Makros auch noch lesbare Zeichen an den Drucker senden soll feststellen, in 
  84. welchem Gesundheitszustand sich gerade der Treiber befindet. Deaktiviere ich 
  85. ihn für Fonts und Makros kann ich mit Otto Reuter singen: "schau ich weg von 
  86. dem Fleck, sind die Sonderzeichen weg". Wird der Treiber aber aktiviert, kann 
  87. ich die Fonts und Makros vergessen. Also werden noch ein paar Bytes für eine 
  88. Kennung und ein Flag spendiert und das ganze so plaziert, daß es aus eigenen 
  89. Programmen eingesehen werden kann. 
  90.  
  91. Für die Kennung habe ich den Namen des Programms gewählt, allerdings in einer 
  92. eigenen Schreibweise ( "LjDrV" ), damit sichergestellt ist, daß durch 
  93. irgendwelche DOS-Einträge aus Directory oder Environment nicht der falsche 
  94. Schluß entsteht, der Treiber sei da und dem war doch nicht. Für das Flag 
  95. genügt ein Byte, das den Aktivitätszustand des Treibers wiederspiegelt und bei 
  96. Bedarf verändert werden kann. Für den Wert Null gilt, die Zeichenkonvertierung 
  97. wird nicht ausgeführt. 
  98.  
  99.  
  100. Jetzt glaube ich wirklich alles zu haben, außer, daß bei Ausgabe des 
  101. Hilfetextes "Hänschen klein" ertönt. Doch darauf habe ich verzichtet. 
  102.  
  103.  
  104. Um das Programm zum Leben zu erwecken, brauchen Sie entweder einen Assembler 
  105. oder Sie geben das Programm mit dem Debugger ein. Falls Sie sich beim Abtippen 
  106. der Zeichensatztabelle vertun, werden Sie bald merken, wenn Ihnen Ihr Drucker 
  107. ein Ä für ein Ü vormacht. 
  108.  
  109.  
  110. page      66, 100
  111. title     ljdrv.asm  -  (C) 18.11.1989, Peter F. L. Burger & TOOLBOX
  112. ;==============================================================================
  113. ;         DRUCKZEICHENWANDLER FÜR LJ-DRUCKER
  114. ;==============================================================================
  115. ; LJDRV ist ein Zeichensatzanpassungsprogramm für HPLJ-Drucker und kompatible.
  116. ;
  117. ; Es werden die erweiterten Zeichen des IBM-Zeichensatzes in die des HPLJ-
  118. ; Zeichensatzes umgewandelt.
  119. ;
  120. ; Das Programm kann natürlich auch für ähnlich gelagerte Fälle genutzt werden.
  121. ;==============================================================================
  122. ;         MAKROS ( machen das Leben leichter )
  123. ;==============================================================================
  124. dos_call  macro
  125.           int       21h                 ; MS-DOS Funktion aufrufen
  126.           endm
  127. disp_strg macro string                  ; String darstellen
  128.           mov       dx, offset string
  129.           mov       ah, 09h
  130.           dos_call
  131.           endm
  132. get_ivec  macro     int_vec
  133.           mov       al, &int_vec        ; Originalvektor lesen
  134.           mov       ah, 35h
  135.           dos_call
  136.           endm
  137. set_ivec  macro     int_vec, new_vec
  138.           mov       dx, offset new_vec  ; neuen Vektor setzen
  139.           mov       al, &int_vec
  140.           mov       ah, 25h
  141.           dos_call
  142.           endm
  143. ;==============================================================================
  144. ;         PROGRAMMSTART
  145. ;==============================================================================
  146. cseg      segment   'code'
  147.           assume    cs:cseg, ds:cseg, es:cseg
  148.           org        2Ch
  149. env_seg   label     word
  150.           org        80h
  151. dta_len   db        ?
  152. dta_txt   db        ?
  153.           org       100h
  154. main:     jmp       set_up              ; Sprung zur Installationsroutine
  155. ;==============================================================================
  156. ;         TABELLE FÜR ZEICHENWANDLUNG ( HPLJ-8-Bit-Code )
  157. ;         ( Beim Abtippen gut aufpassen ! )
  158. ;==============================================================================
  159. xlat_table:
  160.           db        000h,001h,002h,003h,004h,005h,006h,007h ; 00h..07h
  161.           db        008h,009h,00Ah,00Bh,00Ch,00Dh,00Eh,00Fh ; 08h..0Fh
  162.           db        010h,011h,012h,013h,014h,0BDh,016h,017h ; 10h..17h
  163.           db        018h,019h,01Ah,01Bh,01Ch,01Dh,01Eh,01Fh ; 18h..1Fh
  164.           db        020h,021h,022h,023h,024h,025h,026h,027h ; 20h..27h
  165.           db        028h,029h,02Ah,02Bh,02Ch,02Dh,02Eh,02Fh ; 28h..2Fh
  166.           db        030h,031h,032h,033h,034h,035h,036h,037h ; 30h..37h
  167.           db        038h,039h,03Ah,03Bh,03Ch,03Dh,03Eh,03Fh ; 38h..3Fh
  168.           db        040h,041h,042h,043h,044h,045h,046h,047h ; 40h..47h
  169.           db        048h,049h,04Ah,04Bh,04Ch,04Dh,04Eh,04Fh ; 48h..4Fh
  170.           db        050h,051h,052h,053h,054h,055h,056h,057h ; 50h..57h
  171.           db        058h,059h,05Ah,05Bh,05Ch,05Dh,05Eh,05Fh ; 58h..5Fh
  172.           db        060h,061h,062h,063h,064h,065h,066h,067h ; 60h..67h
  173.           db        068h,069h,06Ah,06Bh,06Ch,06Dh,06Eh,06Fh ; 68h..6Fh
  174.           db        070h,071h,072h,073h,074h,075h,076h,077h ; 70h..77h
  175.           db        078h,079h,07Ah,07Bh,07Ch,07Dh,07Eh,020h ; 78h..7Fh
  176.           db        0B4h,0CFh,0C5h,0C0h,0CCh,0C8h,0D4h,0B5h ; 80h..87h
  177.           db        0C1h,0CDh,0C9h,0DDh,0D1h,0D9h,0D8h,0D0h ; 88h..8Fh
  178.           db        0DCh,0D7h,0D3h,0C2h,0CEh,0CAh,0C3h,0CBh ; 90h..97h
  179.           db        0EFh,0DAh,0DBh,0BFh,0BBh,0BCh,020h,0BEh ; 98h..9Fh
  180.           db        0C4h,0D5h,0C6h,0C7h,0B7h,0B6h,0F9h,0FAh ; A0h..A7h
  181.           db        0B9h,020h,020h,0F8h,0F7h,0B8h,0FBh,0FDh ; A8h..AFh
  182.           db        020h,07Fh,020h,07Ch,02Bh,02Bh,02Bh,02Bh ; B0h..B7h
  183.           db        02Bh,02Bh,07Ch,02Bh,02Bh,02Bh,02Bh,02Bh ; B8h..BFh
  184.           db        02Bh,02Bh,02Bh,02Bh,02Dh,02Bh,02Bh,02Bh ; C0h..C7h
  185.           db        02Bh,02Bh,02Bh,02Bh,02Bh,02Dh,02Bh,02Bh ; C8h..CFh
  186.           db        02Bh,02Bh,02Bh,02Bh,02Bh,02Bh,02Bh,02Bh ; D0h..D7h
  187.           db        02Bh,02Bh,02Bh,020h,020h,020h,020h,020h ; D8h..DFh
  188.           db        020h,0DEh,020h,020h,020h,020h,075h,020h ; E0h..E7h
  189.           db        020h,020h,020h,020h,020h,0D6h,045h,020h ; E8h..EFh
  190.           db        020h,0FEh,020h,020h,020h,020h,020h,020h ; F0h..F7h
  191.           db        0B3h,020h,020h,020h,020h,020h,0FCh,020h ; F8h..FFh
  192. ;==============================================================================
  193. ;         VARIABLEN ( das Herz des Treibers )
  194. ;
  195. ; Die Variablen kennung und enable_flag sind so plaziert, daß sie über den
  196. ; Pointer vom Int 17h ( -1 bzw. -6 ) von jedem externen Programm abgefragt
  197. ; werden können. 
  198. ;
  199. ; z. B. in Turbo Pascal 4:
  200. ;
  201. ;   VAR kennung              : STRING;
  202. ;       kenn_ptr             : ^BYTE;
  203. ;       treiber_ist_da,
  204. ;       treiber_ist_aktiv    : BOOLEAN;
  205. ;
  206. ;   LONGINT( kenn_ptr ) := MEML[ $0000 : $005C ];   { = @INT_17h }
  207. ;                                           { Pointer^ zeigt auf trb_int }
  208. ;   DEC( LONGINT( kenn_ptr ), 6 );          { SEG Grenzen müssen hier nicht }
  209. ;                                           { beachtet werden }
  210. ;   MOVE( kenn_ptr^, kennung[ 1 ], 5 );     { GetString }
  211. ;   BYTE( kennung[ 0 ] ) := 5;              { Length( kennung ) := 5 }
  212. ;   treiber_ist_da := kennung = 'LjDrV';
  213. ;
  214. ;   INC( LONGINT( kenn_ptr ), 5 );          { SEG Grenzen: siehe oben }
  215. ;   treiber_ist_aktiv := kenn_ptr^ = 1;
  216. ;
  217. ; Ebenso kann der Treiber auf diese Art und Weise von einem externen Programm
  218. ; aktiviert bzw. deaktiviert werden ( kenn_ptr^ := 0 oder 1 ).
  219. ;==============================================================================
  220. save_int_17h  dd    (?)                 ; ursprünglicher INT 17H-Vektor
  221. kennung       label byte
  222.               db    'LjDrV'             ; Kennung und
  223. enable_flag   db    0                   ; Flag
  224.                                         ; für Abfragemöglichkeiten aus
  225.                                         ; anderen Programmen
  226. ;==============================================================================
  227. ;         INTERRUPT-ROUTINE INT 17H ( Beginn des residenten Codes )
  228. ;==============================================================================
  229. trb_int   proc      far
  230.           or        ah, ah              ; ah=0: Funktion "drucke Zeichen"?
  231.           jnz       jmp_int             ; nein
  232.           cli
  233.           cmp       cs:enable_flag, 0   ; Treiber aktiv?
  234.           jz        jmp_int
  235.           push      ds
  236.           push      bx
  237.           push      cs                  ; DS = CS für XLAT
  238.           pop       ds
  239.           mov       bx, offset xlat_table
  240.           xlat
  241.           pop       bx
  242.           pop       ds
  243. jmp_int:  sti                           ; weiter bei ursprüngl. Interrupt
  244.           jmp       dword ptr cs:save_int_17h
  245. trb_int   endp
  246. ;==============================================================================
  247. ;         INSTALLATIONS-ROUTINE ( Beginn des transienten Codes )
  248. ;==============================================================================
  249. set_up    proc      near
  250.           xor       ax, ax              ; Register löschen
  251.           xor       cx, cx
  252.           mov       bx, offset dta_len
  253.           mov       cl, [ bx ]          ; Stringlänge im DTA-Bereich
  254. skip:     jcxz      help_trb            ; DTA-Bereich zu Ende oder nichts drin
  255.           inc       bx
  256.           dec       cx                  ; Stringlänge - 1
  257.           mov       al, [ bx ]          ; BXtes Zeichen im DTA-Bereich
  258.           cmp       al, ' '
  259.           jz        skip                ; noch Leerzeichen
  260.           and       al, 5Fh             ; UpCase( al )
  261.           cmp       al, 'D'             ; disable - inaktiv
  262.           jz        disable_trb
  263.           cmp       al, 'E'             ; enable  - aktiv
  264.           jz        enable_trb
  265.           cmp       al, 'I'             ; info    - Statusinformation
  266.           jz        info_trb
  267.           cmp       al, 'S'             ; setup   - installieren
  268.           jz        setup_trb
  269.           cmp       al, 'R'             ; remove  - deinstallieren
  270.           jnz       help_trb
  271.           jmp       remove_trb
  272. help_trb:                               ; alles andere kommt hier an
  273.           disp_strg help_txt
  274.           jmp       ende
  275. disable_trb:
  276.           call      trb_vorh            ; ist Treiber da?
  277.           jne       err_0
  278.           mov       byte ptr es:[ enable_flag ], 0
  279.           disp_strg msg_4
  280.           jmp       ende
  281. enable_trb:
  282.           call      trb_vorh            ; ist Treiber da?
  283.           jne       err_0
  284.           mov       byte ptr es:[ enable_flag ], 1
  285.           disp_strg msg_3
  286.           jmp       ende
  287. err_0:    disp_strg err_msg_0
  288.           jmp       help_trb
  289. info_trb: call      trb_vorh
  290.           jne       err_0
  291.           cmp       byte ptr es:[ enable_flag ], 1
  292.           jz        trb_aktiv
  293.           disp_strg msg_4
  294.           jmp       ende
  295. trb_aktiv:
  296.           disp_strg msg_3
  297.           jmp       ende
  298. setup_trb:
  299.           call      trb_vorh            ; ist Treiber da?
  300.           jne       setup_weiter
  301. err_1:    disp_strg err_msg_1           ; zweimal geht nicht
  302.           jmp       help_trb
  303. setup_weiter:
  304.           mov       word ptr cs:[ save_int_17h ], bx ; Originalvektor sichern
  305.           mov       word ptr cs:[ save_int_17h+2 ], es
  306.           set_ivec  17h, trb_int                    ; neuen Vektor setzen
  307.           mov       byte ptr [ enable_flag ], 1
  308.           disp_strg msg_1                           ; Erfolgsmeldung
  309.           mov       dx, offset set_up
  310.           int       27h                             ; bleib da
  311. ;==============================================================================
  312. remove_trb:                             ; Installation aufheben
  313.           call      trb_vorh            ; ist Treiber da?
  314.           jne       err_0
  315.           mov       dx, word ptr es:[ save_int_17h ] ; Vektoren rücksetzen
  316.           mov       ax, word ptr es:[ save_int_17h+2 ]
  317.           mov       ds, ax
  318.           mov       al, 17h
  319.           mov       ah, 25h
  320.           dos_call
  321.           push      es                  ; ES sichern
  322.           mov       ax, es:env_seg      ; Environmentsegment freimachen
  323.           mov       es, ax
  324.           mov       ah, 49h
  325.           dos_call
  326.           pop       es                  ; altes ES wieder aktivieren
  327.           mov       ah, 49h             ; Programmsegment freimachen
  328.           dos_call
  329.           push      cs                  ; DS = CS
  330.           pop       ds
  331.           jnc       remove_ok
  332.           push      ax                  ; Fehlermeldung
  333.           disp_strg err_msg_2
  334.           pop       ax
  335.           cmp       al, 9
  336.           je        err_4
  337. err_3:    disp_strg err_msg_3
  338.           jmp       term
  339. err_4:    disp_strg err_msg_4
  340. term:     mov       al, 0ffh
  341.           jmp       ende
  342. remove_ok:
  343.           disp_strg msg_2
  344.           xor       al, al
  345. ende:     mov       ah, 4ch             ; Normales Programmende
  346.           dos_call
  347. set_up    endp
  348. ;==============================================================================
  349. ;         CALLs ( sparen Programmcode )
  350. ;==============================================================================
  351. trb_vorh  proc      near
  352.           get_ivec  17h                 ; Originalvektor lesen
  353.           mov       ax, es              ; Testen, ob bereits installiert
  354.           mov       di, offset kennung
  355.           mov       si, di
  356.           mov       cx, 5
  357.           cld
  358.           repe      cmpsb
  359.           ret
  360. trb_vorh  endp
  361. ;==============================================================================
  362. ;         MELDUNGEN ( des Treibers Sprachrohr )
  363. ;==============================================================================
  364. msg_1         db    'LJDRV ist installiert',13,10,'$'
  365. msg_2         db    'LJDRV ist deinstalliert',13,10,'$'
  366. msg_3         db    'LJDRV ist aktiv',13,10,'$'
  367. msg_4         db    'LJDRV ist inaktiv',13,10,'$'
  368. err_msg_0     db    'LJDRV ist nicht installiert',13,10,'$'
  369. err_msg_1     db    'LJDRV ist bereits installiert',13,10,'$'
  370. err_msg_2     db    'FEHLER: Speicher kann nicht freigemacht werden.',13,10,'$'
  371. err_msg_3     db    'ACHTUNG: Speicherbereich zerstört - '
  372.               db    'bitte System neu booten!',13,10,'$'
  373. err_msg_4     db    'Segment gehört nicht zu LJDRV.',13,10,'$'
  374. help_txt      db    'Aufruf: LJDRV [DEIRS]',13,10
  375.               db    '               D = Treiber deaktivieren',13,10
  376.               db    '               E = Treiber aktivieren',13,10
  377.               db    '               I = Treiber Information',13,10
  378.               db    '               ? = Treiber Hilfetext',13,10
  379.               db    '               R = Treiber deinstallieren',13,10
  380.               db    '               S = Treiber installieren',13,10,'$'
  381. cseg      ends
  382. ;==============================================================================
  383. end       main
  384.